LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
Public Member Functions | Public Attributes | Static Public Attributes | List of all members
lsst.pipe.tasks.makeCoaddTempExp.MakeCoaddTempExpTask Class Reference

Warp and optionally PSF-Match calexps onto an a common projection. More...

Inheritance diagram for lsst.pipe.tasks.makeCoaddTempExp.MakeCoaddTempExpTask:
lsst.pipe.tasks.coaddBase.CoaddBaseTask

Public Member Functions

def __init__ (self, reuse=False, **kwargs)
 
def runDataRef (self, patchRef, selectDataList=[])
 Produce <coaddName>Coadd_<warpType>Warp images by warping and optionally PSF-matching. More...
 
def run (self, calExpList, ccdIdList, skyInfo, visitId=0, dataIdList=None, **kwargs)
 
def getCalibratedExposure (self, dataRef, bgSubtracted)
 
def getWarpTypeList (self)
 
def applySkyCorr (self, dataRef, calexp)
 
def selectExposures (self, patchRef, skyInfo=None, selectDataList=[])
 Select exposures to coadd. More...
 
def getSkyInfo (self, patchRef)
 Use getSkyinfo to return the skyMap, tract and patch information, wcs and the outer bbox of the patch. More...
 
def getCoaddDatasetName (self, warpType="direct")
 
def getTempExpDatasetName (self, warpType="direct")
 
def getBadPixelMask (self)
 Convenience method to provide the bitmask from the mask plane names. More...
 

Public Attributes

 reuse
 
 calexpType
 

Static Public Attributes

 ConfigClass = MakeCoaddTempExpConfig
 
 RunnerClass = CoaddTaskRunner
 

Detailed Description

Warp and optionally PSF-Match calexps onto an a common projection.

@anchor MakeCoaddTempExpTask_

@section pipe_tasks_makeCoaddTempExp_Contents  Contents

 - @ref pipe_tasks_makeCoaddTempExp_Purpose
 - @ref pipe_tasks_makeCoaddTempExp_Initialize
 - @ref pipe_tasks_makeCoaddTempExp_IO
 - @ref pipe_tasks_makeCoaddTempExp_Config
 - @ref pipe_tasks_makeCoaddTempExp_Debug
 - @ref pipe_tasks_makeCoaddTempExp_Example

@section pipe_tasks_makeCoaddTempExp_Purpose  Description

Warp and optionally PSF-Match calexps onto a common projection, by
performing the following operations:
- Group calexps by visit/run
- For each visit, generate a Warp by calling method @ref makeTempExp.
  makeTempExp loops over the visit's calexps calling @ref WarpAndPsfMatch
  on each visit

The result is a `directWarp` (and/or optionally a `psfMatchedWarp`).

@section pipe_tasks_makeCoaddTempExp_Initialize  Task Initialization

@copydoc \_\_init\_\_

This task has one special keyword argument: passing reuse=True will cause
the task to skip the creation of warps that are already present in the
output repositories.

@section pipe_tasks_makeCoaddTempExp_IO  Invoking the Task

This task is primarily designed to be run from the command line.

The main method is `runDataRef`, which takes a single butler data reference for the patch(es)
to process.

@copydoc run

WarpType identifies the types of convolutions applied to Warps (previously CoaddTempExps).
Only two types are available: direct (for regular Warps/Coadds) and psfMatched
(for Warps/Coadds with homogenized PSFs). We expect to add a third type, likelihood,
for generating likelihood Coadds with Warps that have been correlated with their own PSF.

@section pipe_tasks_makeCoaddTempExp_Config  Configuration parameters

See @ref MakeCoaddTempExpConfig and parameters inherited from
@link lsst.pipe.tasks.coaddBase.CoaddBaseConfig CoaddBaseConfig @endlink

@subsection pipe_tasks_MakeCoaddTempExp_psfMatching Guide to PSF-Matching Configs

To make `psfMatchedWarps`, select `config.makePsfMatched=True`. The subtask
@link lsst.ip.diffim.modelPsfMatch.ModelPsfMatchTask ModelPsfMatchTask @endlink
is responsible for the PSF-Matching, and its config is accessed via `config.warpAndPsfMatch.psfMatch`.
The optimal configuration depends on aspects of dataset: the pixel scale, average PSF FWHM and
dimensions of the PSF kernel. These configs include the requested model PSF, the matching kernel size,
padding of the science PSF thumbnail and spatial sampling frequency of the PSF.

*Config Guidelines*: The user must specify the size of the model PSF to which to match by setting
`config.modelPsf.defaultFwhm` in units of pixels. The appropriate values depends on science case.
In general, for a set of input images, this config should equal the FWHM of the visit
with the worst seeing. The smallest it should be set to is the median FWHM. The defaults
of the other config options offer a reasonable starting point.
The following list presents the most common problems that arise from a misconfigured
@link lsst.ip.diffim.modelPsfMatch.ModelPsfMatchTask ModelPsfMatchTask @endlink
and corresponding solutions. All assume the default Alard-Lupton kernel, with configs accessed via
```config.warpAndPsfMatch.psfMatch.kernel['AL']```. Each item in the list is formatted as:
Problem: Explanation. *Solution*

*Troublshooting PSF-Matching Configuration:*
- Matched PSFs look boxy: The matching kernel is too small. _Increase the matching kernel size.
    For example:_

        config.warpAndPsfMatch.psfMatch.kernel['AL'].kernelSize=27  # default 21

    Note that increasing the kernel size also increases runtime.
- Matched PSFs look ugly (dipoles, quadropoles, donuts): unable to find good solution
    for matching kernel. _Provide the matcher with more data by either increasing
    the spatial sampling by decreasing the spatial cell size,_

        config.warpAndPsfMatch.psfMatch.kernel['AL'].sizeCellX = 64  # default 128
        config.warpAndPsfMatch.psfMatch.kernel['AL'].sizeCellY = 64  # default 128

    _or increasing the padding around the Science PSF, for example:_

        config.warpAndPsfMatch.psfMatch.autoPadPsfTo=1.6  # default 1.4

    Increasing `autoPadPsfTo` increases the minimum ratio of input PSF dimensions to the
    matching kernel dimensions, thus increasing the number of pixels available to fit
    after convolving the PSF with the matching kernel.
    Optionally, for debugging the effects of padding, the level of padding may be manually
    controlled by setting turning off the automatic padding and setting the number
    of pixels by which to pad the PSF:

        config.warpAndPsfMatch.psfMatch.doAutoPadPsf = False  # default True
        config.warpAndPsfMatch.psfMatch.padPsfBy = 6  # pixels. default 0

- Deconvolution: Matching a large PSF to a smaller PSF produces
    a telltale noise pattern which looks like ripples or a brain.
    _Increase the size of the requested model PSF. For example:_

        config.modelPsf.defaultFwhm = 11  # Gaussian sigma in units of pixels.

- High frequency (sometimes checkered) noise: The matching basis functions are too small.
    _Increase the width of the Gaussian basis functions. For example:_

        config.warpAndPsfMatch.psfMatch.kernel['AL'].alardSigGauss=[1.5, 3.0, 6.0]
        # from default [0.7, 1.5, 3.0]


@section pipe_tasks_makeCoaddTempExp_Debug  Debug variables

MakeCoaddTempExpTask has no debug output, but its subtasks do.

@section pipe_tasks_makeCoaddTempExp_Example   A complete example of using MakeCoaddTempExpTask

This example uses the package ci_hsc to show how MakeCoaddTempExp fits
into the larger Data Release Processing.
Set up by running:

    setup ci_hsc
    cd $CI_HSC_DIR
    # if not built already:
    python $(which scons)  # this will take a while

The following assumes that `processCcd.py` and `makeSkyMap.py` have previously been run
(e.g. by building `ci_hsc` above) to generate a repository of calexps and an
output respository with the desired SkyMap. The command,

    makeCoaddTempExp.py $CI_HSC_DIR/DATA --rerun ci_hsc \
     --id patch=5,4 tract=0 filter=HSC-I \
     --selectId visit=903988 ccd=16 --selectId visit=903988 ccd=17 \
     --selectId visit=903988 ccd=23 --selectId visit=903988 ccd=24 \
     --config doApplyExternalPhotoCalib=False doApplyExternalSkyWcs=False \
     makePsfMatched=True modelPsf.defaultFwhm=11

writes a direct and PSF-Matched Warp to
- `$CI_HSC_DIR/DATA/rerun/ci_hsc/deepCoadd/HSC-I/0/5,4/warp-HSC-I-0-5,4-903988.fits` and
- `$CI_HSC_DIR/DATA/rerun/ci_hsc/deepCoadd/HSC-I/0/5,4/psfMatchedWarp-HSC-I-0-5,4-903988.fits`
    respectively.

@note PSF-Matching in this particular dataset would benefit from adding
`--configfile ./matchingConfig.py` to
the command line arguments where `matchingConfig.py` is defined by:

    echo "
    config.warpAndPsfMatch.psfMatch.kernel['AL'].kernelSize=27
    config.warpAndPsfMatch.psfMatch.kernel['AL'].alardSigGauss=[1.5, 3.0, 6.0]" > matchingConfig.py


Add the option `--help` to see more options.

Definition at line 121 of file makeCoaddTempExp.py.

Constructor & Destructor Documentation

◆ __init__()

def lsst.pipe.tasks.makeCoaddTempExp.MakeCoaddTempExpTask.__init__ (   self,
  reuse = False,
**  kwargs 
)

Definition at line 279 of file makeCoaddTempExp.py.

279  def __init__(self, reuse=False, **kwargs):
280  CoaddBaseTask.__init__(self, **kwargs)
281  self.reuse = reuse
282  self.makeSubtask("warpAndPsfMatch")
283  if self.config.hasFakes:
284  self.calexpType = "fakes_calexp"
285  else:
286  self.calexpType = "calexp"
287 

Member Function Documentation

◆ applySkyCorr()

def lsst.pipe.tasks.makeCoaddTempExp.MakeCoaddTempExpTask.applySkyCorr (   self,
  dataRef,
  calexp 
)
Apply correction to the sky background level

Sky corrections can be generated with the 'skyCorrection.py'
executable in pipe_drivers. Because the sky model used by that
code extends over the entire focal plane, this can produce
better sky subtraction.

The calexp is updated in-place.

Parameters
----------
dataRef : `lsst.daf.persistence.ButlerDataRef`
    Data reference for calexp.
calexp : `lsst.afw.image.Exposure` or `lsst.afw.image.MaskedImage`
    Calibrated exposure.

Definition at line 559 of file makeCoaddTempExp.py.

559  def applySkyCorr(self, dataRef, calexp):
560  """Apply correction to the sky background level
561 
562  Sky corrections can be generated with the 'skyCorrection.py'
563  executable in pipe_drivers. Because the sky model used by that
564  code extends over the entire focal plane, this can produce
565  better sky subtraction.
566 
567  The calexp is updated in-place.
568 
569  Parameters
570  ----------
571  dataRef : `lsst.daf.persistence.ButlerDataRef`
572  Data reference for calexp.
573  calexp : `lsst.afw.image.Exposure` or `lsst.afw.image.MaskedImage`
574  Calibrated exposure.
575  """
576  bg = dataRef.get("skyCorr")
577  self.log.debug("Applying sky correction to %s", dataRef.dataId)
578  if isinstance(calexp, afwImage.Exposure):
579  calexp = calexp.getMaskedImage()
580  calexp -= bg.getImage()
581 
582 
A class to contain the data, WCS, and other information needed to describe an image of the sky.
Definition: Exposure.h:72

◆ getBadPixelMask()

def lsst.pipe.tasks.coaddBase.CoaddBaseTask.getBadPixelMask (   self)
inherited

Convenience method to provide the bitmask from the mask plane names.

Definition at line 239 of file coaddBase.py.

239  def getBadPixelMask(self):
240  """!
241  @brief Convenience method to provide the bitmask from the mask plane names
242  """
243  return afwImage.Mask.getPlaneBitMask(self.config.badMaskPlanes)
244 
245 

◆ getCalibratedExposure()

def lsst.pipe.tasks.makeCoaddTempExp.MakeCoaddTempExpTask.getCalibratedExposure (   self,
  dataRef,
  bgSubtracted 
)
Return one calibrated Exposure, possibly with an updated SkyWcs.

@param[in] dataRef        a sensor-level data reference
@param[in] bgSubtracted   return calexp with background subtracted? If False get the
                          calexp's background background model and add it to the calexp.
@return calibrated exposure

@raises MissingExposureError If data for the exposure is not available.

If config.doApplyExternalPhotoCalib is `True`, the photometric calibration
(`photoCalib`) is taken from `config.externalPhotoCalibName` via the
`name_photoCalib` dataset.  Otherwise, the photometric calibration is
retrieved from the processed exposure.  When
`config.doApplyExternalSkyWcs` is `True`, the astrometric calibration
is taken from `config.externalSkyWcsName` with the `name_wcs` dataset.
Otherwise, the astrometric calibration is taken from the processed
exposure.

Definition at line 490 of file makeCoaddTempExp.py.

490  def getCalibratedExposure(self, dataRef, bgSubtracted):
491  """Return one calibrated Exposure, possibly with an updated SkyWcs.
492 
493  @param[in] dataRef a sensor-level data reference
494  @param[in] bgSubtracted return calexp with background subtracted? If False get the
495  calexp's background background model and add it to the calexp.
496  @return calibrated exposure
497 
498  @raises MissingExposureError If data for the exposure is not available.
499 
500  If config.doApplyExternalPhotoCalib is `True`, the photometric calibration
501  (`photoCalib`) is taken from `config.externalPhotoCalibName` via the
502  `name_photoCalib` dataset. Otherwise, the photometric calibration is
503  retrieved from the processed exposure. When
504  `config.doApplyExternalSkyWcs` is `True`, the astrometric calibration
505  is taken from `config.externalSkyWcsName` with the `name_wcs` dataset.
506  Otherwise, the astrometric calibration is taken from the processed
507  exposure.
508  """
509  try:
510  exposure = dataRef.get(self.calexpType, immediate=True)
511  except dafPersist.NoResults as e:
512  raise MissingExposureError('Exposure not found: %s ' % str(e)) from e
513 
514  if not bgSubtracted:
515  background = dataRef.get("calexpBackground", immediate=True)
516  mi = exposure.getMaskedImage()
517  mi += background.getImage()
518  del mi
519 
520  if self.config.doApplyExternalPhotoCalib:
521  source = f"{self.config.externalPhotoCalibName}_photoCalib"
522  self.log.debug("Applying external photoCalib to %s from %s", dataRef.dataId, source)
523  photoCalib = dataRef.get(source)
524  exposure.setPhotoCalib(photoCalib)
525  else:
526  photoCalib = exposure.getPhotoCalib()
527 
528  if self.config.doApplyExternalSkyWcs:
529  source = f"{self.config.externalSkyWcsName}_wcs"
530  self.log.debug("Applying external skyWcs to %s from %s", dataRef.dataId, source)
531  skyWcs = dataRef.get(source)
532  exposure.setWcs(skyWcs)
533 
534  exposure.maskedImage = photoCalib.calibrateImage(exposure.maskedImage,
535  includeScaleUncertainty=self.config.includeCalibVar)
536  exposure.maskedImage /= photoCalib.getCalibrationMean()
537  # TODO: The images will have a calibration of 1.0 everywhere once RFC-545 is implemented.
538  # exposure.setCalib(afwImage.Calib(1.0))
539  return exposure
540 

◆ getCoaddDatasetName()

def lsst.pipe.tasks.coaddBase.CoaddBaseTask.getCoaddDatasetName (   self,
  warpType = "direct" 
)
inherited
Return coadd name for given warpType and task config

Parameters
----------
warpType : string
    Either 'direct' or 'psfMatched'

Returns
-------
CoaddDatasetName : `string`

Definition at line 190 of file coaddBase.py.

190  def getCoaddDatasetName(self, warpType="direct"):
191  """Return coadd name for given warpType and task config
192 
193  Parameters
194  ----------
195  warpType : string
196  Either 'direct' or 'psfMatched'
197 
198  Returns
199  -------
200  CoaddDatasetName : `string`
201  """
202  return self.config.coaddName + "Coadd" + makeCoaddSuffix(warpType)
203 
def makeCoaddSuffix(warpType="direct")
Definition: coaddBase.py:346

◆ getSkyInfo()

def lsst.pipe.tasks.coaddBase.CoaddBaseTask.getSkyInfo (   self,
  patchRef 
)
inherited

Use getSkyinfo to return the skyMap, tract and patch information, wcs and the outer bbox of the patch.

Parameters
[in]patchRefdata reference for sky map. Must include keys "tract" and "patch"
Returns
pipe_base Struct containing:
  • skyMap: sky map
  • tractInfo: information for chosen tract of sky map
  • patchInfo: information about chosen patch of tract
  • wcs: WCS of tract
  • bbox: outer bbox of patch, as an geom Box2I

Definition at line 174 of file coaddBase.py.

174  def getSkyInfo(self, patchRef):
175  """!
176  @brief Use @ref getSkyinfo to return the skyMap, tract and patch information, wcs and the outer bbox
177  of the patch.
178 
179  @param[in] patchRef data reference for sky map. Must include keys "tract" and "patch"
180 
181  @return pipe_base Struct containing:
182  - skyMap: sky map
183  - tractInfo: information for chosen tract of sky map
184  - patchInfo: information about chosen patch of tract
185  - wcs: WCS of tract
186  - bbox: outer bbox of patch, as an geom Box2I
187  """
188  return getSkyInfo(coaddName=self.config.coaddName, patchRef=patchRef)
189 
def getSkyInfo(coaddName, patchRef)
Return the SkyMap, tract and patch information, wcs, and outer bbox of the patch to be coadded.
Definition: coaddBase.py:271

◆ getTempExpDatasetName()

def lsst.pipe.tasks.coaddBase.CoaddBaseTask.getTempExpDatasetName (   self,
  warpType = "direct" 
)
inherited
Return warp name for given warpType and task config

Parameters
----------
warpType : string
    Either 'direct' or 'psfMatched'

Returns
-------
WarpDatasetName : `string`

Definition at line 204 of file coaddBase.py.

204  def getTempExpDatasetName(self, warpType="direct"):
205  """Return warp name for given warpType and task config
206 
207  Parameters
208  ----------
209  warpType : string
210  Either 'direct' or 'psfMatched'
211 
212  Returns
213  -------
214  WarpDatasetName : `string`
215  """
216  return self.config.coaddName + "Coadd_" + warpType + "Warp"
217 

◆ getWarpTypeList()

def lsst.pipe.tasks.makeCoaddTempExp.MakeCoaddTempExpTask.getWarpTypeList (   self)
Return list of requested warp types per the config.

Definition at line 549 of file makeCoaddTempExp.py.

549  def getWarpTypeList(self):
550  """Return list of requested warp types per the config.
551  """
552  warpTypeList = []
553  if self.config.makeDirect:
554  warpTypeList.append("direct")
555  if self.config.makePsfMatched:
556  warpTypeList.append("psfMatched")
557  return warpTypeList
558 

◆ run()

def lsst.pipe.tasks.makeCoaddTempExp.MakeCoaddTempExpTask.run (   self,
  calExpList,
  ccdIdList,
  skyInfo,
  visitId = 0,
  dataIdList = None,
**  kwargs 
)
Create a Warp from inputs

We iterate over the multiple calexps in a single exposure to construct
the warp (previously called a coaddTempExp) of that exposure to the
supplied tract/patch.

Pixels that receive no pixels are set to NAN; this is not correct
(violates LSST algorithms group policy), but will be fixed up by
interpolating after the coaddition.

@param calexpRefList: List of data references for calexps that (may)
    overlap the patch of interest
@param skyInfo: Struct from CoaddBaseTask.getSkyInfo() with geometric
    information about the patch
@param visitId: integer identifier for visit, for the table that will
    produce the CoaddPsf
@return a pipeBase Struct containing:
  - exposures: a dictionary containing the warps requested:
        "direct": direct warp if config.makeDirect
        "psfMatched": PSF-matched warp if config.makePsfMatched

Definition at line 389 of file makeCoaddTempExp.py.

389  def run(self, calExpList, ccdIdList, skyInfo, visitId=0, dataIdList=None, **kwargs):
390  """Create a Warp from inputs
391 
392  We iterate over the multiple calexps in a single exposure to construct
393  the warp (previously called a coaddTempExp) of that exposure to the
394  supplied tract/patch.
395 
396  Pixels that receive no pixels are set to NAN; this is not correct
397  (violates LSST algorithms group policy), but will be fixed up by
398  interpolating after the coaddition.
399 
400  @param calexpRefList: List of data references for calexps that (may)
401  overlap the patch of interest
402  @param skyInfo: Struct from CoaddBaseTask.getSkyInfo() with geometric
403  information about the patch
404  @param visitId: integer identifier for visit, for the table that will
405  produce the CoaddPsf
406  @return a pipeBase Struct containing:
407  - exposures: a dictionary containing the warps requested:
408  "direct": direct warp if config.makeDirect
409  "psfMatched": PSF-matched warp if config.makePsfMatched
410  """
411  warpTypeList = self.getWarpTypeList()
412 
413  totGoodPix = {warpType: 0 for warpType in warpTypeList}
414  didSetMetadata = {warpType: False for warpType in warpTypeList}
415  coaddTempExps = {warpType: self._prepareEmptyExposure(skyInfo) for warpType in warpTypeList}
416  inputRecorder = {warpType: self.inputRecorder.makeCoaddTempExpRecorder(visitId, len(calExpList))
417  for warpType in warpTypeList}
418 
419  modelPsf = self.config.modelPsf.apply() if self.config.makePsfMatched else None
420  if dataIdList is None:
421  dataIdList = ccdIdList
422 
423  for calExpInd, (calExp, ccdId, dataId) in enumerate(zip(calExpList, ccdIdList, dataIdList)):
424  self.log.info("Processing calexp %d of %d for this Warp: id=%s",
425  calExpInd+1, len(calExpList), dataId)
426 
427  try:
428  warpedAndMatched = self.warpAndPsfMatch.run(calExp, modelPsf=modelPsf,
429  wcs=skyInfo.wcs, maxBBox=skyInfo.bbox,
430  makeDirect=self.config.makeDirect,
431  makePsfMatched=self.config.makePsfMatched)
432  except Exception as e:
433  self.log.warning("WarpAndPsfMatch failed for calexp %s; skipping it: %s", dataId, e)
434  continue
435  try:
436  numGoodPix = {warpType: 0 for warpType in warpTypeList}
437  for warpType in warpTypeList:
438  exposure = warpedAndMatched.getDict()[warpType]
439  if exposure is None:
440  continue
441  coaddTempExp = coaddTempExps[warpType]
442  if didSetMetadata[warpType]:
443  mimg = exposure.getMaskedImage()
444  mimg *= (coaddTempExp.getPhotoCalib().getInstFluxAtZeroMagnitude()
445  / exposure.getPhotoCalib().getInstFluxAtZeroMagnitude())
446  del mimg
447  numGoodPix[warpType] = coaddUtils.copyGoodPixels(
448  coaddTempExp.getMaskedImage(), exposure.getMaskedImage(), self.getBadPixelMask())
449  totGoodPix[warpType] += numGoodPix[warpType]
450  self.log.debug("Calexp %s has %d good pixels in this patch (%.1f%%) for %s",
451  dataId, numGoodPix[warpType],
452  100.0*numGoodPix[warpType]/skyInfo.bbox.getArea(), warpType)
453  if numGoodPix[warpType] > 0 and not didSetMetadata[warpType]:
454  coaddTempExp.info.id = exposure.info.id
455  coaddTempExp.setPhotoCalib(exposure.getPhotoCalib())
456  coaddTempExp.setFilterLabel(exposure.getFilterLabel())
457  coaddTempExp.getInfo().setVisitInfo(exposure.getInfo().getVisitInfo())
458  # PSF replaced with CoaddPsf after loop if and only if creating direct warp
459  coaddTempExp.setPsf(exposure.getPsf())
460  didSetMetadata[warpType] = True
461 
462  # Need inputRecorder for CoaddApCorrMap for both direct and PSF-matched
463  inputRecorder[warpType].addCalExp(calExp, ccdId, numGoodPix[warpType])
464 
465  except Exception as e:
466  self.log.warning("Error processing calexp %s; skipping it: %s", dataId, e)
467  continue
468 
469  for warpType in warpTypeList:
470  self.log.info("%sWarp has %d good pixels (%.1f%%)",
471  warpType, totGoodPix[warpType], 100.0*totGoodPix[warpType]/skyInfo.bbox.getArea())
472 
473  if totGoodPix[warpType] > 0 and didSetMetadata[warpType]:
474  inputRecorder[warpType].finish(coaddTempExps[warpType], totGoodPix[warpType])
475  if warpType == "direct":
476  coaddTempExps[warpType].setPsf(
477  CoaddPsf(inputRecorder[warpType].coaddInputs.ccds, skyInfo.wcs,
478  self.config.coaddPsf.makeControl()))
479  else:
480  if not self.config.doWriteEmptyWarps:
481  # No good pixels. Exposure still empty
482  coaddTempExps[warpType] = None
483  # NoWorkFound is unnecessary as the downstream tasks will
484  # adjust the quantum accordingly, and it prevents gen2
485  # MakeCoaddTempExp from continuing to loop over visits.
486 
487  result = pipeBase.Struct(exposures=coaddTempExps)
488  return result
489 
int copyGoodPixels(lsst::afw::image::Image< ImagePixelT > &destImage, lsst::afw::image::Image< ImagePixelT > const &srcImage)
copy good pixels from one image to another
def run(self, coaddExposures, bbox, wcs)
Definition: getTemplate.py:603

◆ runDataRef()

def lsst.pipe.tasks.makeCoaddTempExp.MakeCoaddTempExpTask.runDataRef (   self,
  patchRef,
  selectDataList = [] 
)

Produce <coaddName>Coadd_<warpType>Warp images by warping and optionally PSF-matching.

    @param[in] patchRef: data reference for sky map patch. Must include keys "tract", "patch",
        plus the camera-specific filter key (e.g. "filter" or "band")
    @return: dataRefList: a list of data references for the new <coaddName>Coadd_directWarps
        if direct or both warp types are requested and <coaddName>Coadd_psfMatchedWarps if only psfMatched
        warps are requested.

    @warning: this task assumes that all exposures in a warp (coaddTempExp) have the same filter.

    @warning: this task sets the PhotoCalib of the coaddTempExp to the PhotoCalib of the first calexp
    with any good pixels in the patch. For a mosaic camera the resulting PhotoCalib should be ignored
    (assembleCoadd should determine zeropoint scaling without referring to it).

Definition at line 289 of file makeCoaddTempExp.py.

289  def runDataRef(self, patchRef, selectDataList=[]):
290  """!Produce <coaddName>Coadd_<warpType>Warp images by warping and optionally PSF-matching.
291 
292  @param[in] patchRef: data reference for sky map patch. Must include keys "tract", "patch",
293  plus the camera-specific filter key (e.g. "filter" or "band")
294  @return: dataRefList: a list of data references for the new <coaddName>Coadd_directWarps
295  if direct or both warp types are requested and <coaddName>Coadd_psfMatchedWarps if only psfMatched
296  warps are requested.
297 
298  @warning: this task assumes that all exposures in a warp (coaddTempExp) have the same filter.
299 
300  @warning: this task sets the PhotoCalib of the coaddTempExp to the PhotoCalib of the first calexp
301  with any good pixels in the patch. For a mosaic camera the resulting PhotoCalib should be ignored
302  (assembleCoadd should determine zeropoint scaling without referring to it).
303  """
304  skyInfo = self.getSkyInfo(patchRef)
305 
306  # DataRefs to return are of type *_directWarp unless only *_psfMatchedWarp requested
307  if self.config.makePsfMatched and not self.config.makeDirect:
308  primaryWarpDataset = self.getTempExpDatasetName("psfMatched")
309  else:
310  primaryWarpDataset = self.getTempExpDatasetName("direct")
311 
312  calExpRefList = self.selectExposures(patchRef, skyInfo, selectDataList=selectDataList)
313 
314  if len(calExpRefList) == 0:
315  self.log.warning("No exposures to coadd for patch %s", patchRef.dataId)
316  return None
317  self.log.info("Selected %d calexps for patch %s", len(calExpRefList), patchRef.dataId)
318  calExpRefList = [calExpRef for calExpRef in calExpRefList if calExpRef.datasetExists(self.calexpType)]
319  self.log.info("Processing %d existing calexps for patch %s", len(calExpRefList), patchRef.dataId)
320 
321  groupData = groupPatchExposures(patchRef, calExpRefList, self.getCoaddDatasetName(),
322  primaryWarpDataset)
323  self.log.info("Processing %d warp exposures for patch %s", len(groupData.groups), patchRef.dataId)
324 
325  dataRefList = []
326  for i, (tempExpTuple, calexpRefList) in enumerate(groupData.groups.items()):
327  tempExpRef = getGroupDataRef(patchRef.getButler(), primaryWarpDataset,
328  tempExpTuple, groupData.keys)
329  if self.reuse and tempExpRef.datasetExists(datasetType=primaryWarpDataset, write=True):
330  self.log.info("Skipping makeCoaddTempExp for %s; output already exists.", tempExpRef.dataId)
331  dataRefList.append(tempExpRef)
332  continue
333  self.log.info("Processing Warp %d/%d: id=%s", i, len(groupData.groups), tempExpRef.dataId)
334 
335  # TODO: mappers should define a way to go from the "grouping keys" to a numeric ID (#2776).
336  # For now, we try to get a long integer "visit" key, and if we can't, we just use the index
337  # of the visit in the list.
338  try:
339  visitId = int(tempExpRef.dataId["visit"])
340  except (KeyError, ValueError):
341  visitId = i
342 
343  calExpList = []
344  ccdIdList = []
345  dataIdList = []
346 
347  for calExpInd, calExpRef in enumerate(calexpRefList):
348  self.log.info("Reading calexp %s of %s for Warp id=%s", calExpInd+1, len(calexpRefList),
349  calExpRef.dataId)
350  try:
351  ccdId = calExpRef.get("ccdExposureId", immediate=True)
352  except Exception:
353  ccdId = calExpInd
354  try:
355  # We augment the dataRef here with the tract, which is harmless for loading things
356  # like calexps that don't need the tract, and necessary for meas_mosaic outputs,
357  # which do.
358  calExpRef = calExpRef.butlerSubset.butler.dataRef(self.calexpType,
359  dataId=calExpRef.dataId,
360  tract=skyInfo.tractInfo.getId())
361  calExp = self.getCalibratedExposure(calExpRef, bgSubtracted=self.config.bgSubtracted)
362  except Exception as e:
363  self.log.warning("Calexp %s not found; skipping it: %s", calExpRef.dataId, e)
364  continue
365 
366  if self.config.doApplySkyCorr:
367  self.applySkyCorr(calExpRef, calExp)
368 
369  calExpList.append(calExp)
370  ccdIdList.append(ccdId)
371  dataIdList.append(calExpRef.dataId)
372 
373  exps = self.run(calExpList, ccdIdList, skyInfo, visitId, dataIdList).exposures
374 
375  if any(exps.values()):
376  dataRefList.append(tempExpRef)
377  else:
378  self.log.warning("Warp %s could not be created", tempExpRef.dataId)
379 
380  if self.config.doWrite:
381  for (warpType, exposure) in exps.items(): # compatible w/ Py3
382  if exposure is not None:
383  self.log.info("Persisting %s", self.getTempExpDatasetName(warpType))
384  tempExpRef.put(exposure, self.getTempExpDatasetName(warpType))
385 
386  return dataRefList
387 
bool any(CoordinateExpr< N > const &expr) noexcept
Return true if any elements are true.
def getGroupDataRef(butler, datasetType, groupTuple, keys)
Definition: coaddHelpers.py:99
def groupPatchExposures(patchDataRef, calexpDataRefList, coaddDatasetType="deepCoadd", tempExpDatasetType="deepCoadd_directWarp")
Definition: coaddHelpers.py:60

◆ selectExposures()

def lsst.pipe.tasks.coaddBase.CoaddBaseTask.selectExposures (   self,
  patchRef,
  skyInfo = None,
  selectDataList = [] 
)
inherited

Select exposures to coadd.

Get the corners of the bbox supplied in skyInfo using geom::Box2D and convert the pixel positions of the bbox corners to sky coordinates using skyInfo.wcs.pixelToSky. Use the WcsSelectImagesTask to select exposures that lie inside the patch indicated by the dataRef.

Parameters
[in]patchRefdata reference for sky map patch. Must include keys "tract", "patch", plus the camera-specific filter key (e.g. "filter" or "band")
[in]skyInfogeometry for the patch; output from getSkyInfo
Returns
a list of science exposures to coadd, as butler data references

Definition at line 154 of file coaddBase.py.

154  def selectExposures(self, patchRef, skyInfo=None, selectDataList=[]):
155  """!
156  @brief Select exposures to coadd
157 
158  Get the corners of the bbox supplied in skyInfo using @ref geom.Box2D and convert the pixel
159  positions of the bbox corners to sky coordinates using @ref skyInfo.wcs.pixelToSky. Use the
160  @ref WcsSelectImagesTask_ "WcsSelectImagesTask" to select exposures that lie inside the patch
161  indicated by the dataRef.
162 
163  @param[in] patchRef data reference for sky map patch. Must include keys "tract", "patch",
164  plus the camera-specific filter key (e.g. "filter" or "band")
165  @param[in] skyInfo geometry for the patch; output from getSkyInfo
166  @return a list of science exposures to coadd, as butler data references
167  """
168  if skyInfo is None:
169  skyInfo = self.getSkyInfo(patchRef)
170  cornerPosList = geom.Box2D(skyInfo.bbox).getCorners()
171  coordList = [skyInfo.wcs.pixelToSky(pos) for pos in cornerPosList]
172  return self.select.runDataRef(patchRef, coordList, selectDataList=selectDataList).dataRefList
173 
A floating-point coordinate rectangle geometry.
Definition: Box.h:413

Member Data Documentation

◆ calexpType

lsst.pipe.tasks.makeCoaddTempExp.MakeCoaddTempExpTask.calexpType

Definition at line 284 of file makeCoaddTempExp.py.

◆ ConfigClass

lsst.pipe.tasks.makeCoaddTempExp.MakeCoaddTempExpTask.ConfigClass = MakeCoaddTempExpConfig
static

Definition at line 276 of file makeCoaddTempExp.py.

◆ reuse

lsst.pipe.tasks.makeCoaddTempExp.MakeCoaddTempExpTask.reuse

Definition at line 281 of file makeCoaddTempExp.py.

◆ RunnerClass

lsst.pipe.tasks.coaddBase.CoaddBaseTask.RunnerClass = CoaddTaskRunner
staticinherited

Definition at line 147 of file coaddBase.py.


The documentation for this class was generated from the following file: