LSSTApplications  17.0+10,17.0+52,17.0+91,18.0.0+11,18.0.0+16,18.0.0+38,18.0.0+4,18.0.0-2-ge43143a+8,18.1.0-1-g0001055+4,18.1.0-1-g1349e88+13,18.1.0-1-g2505f39+10,18.1.0-1-g380d4d4+13,18.1.0-1-g5315e5e,18.1.0-1-g5e4b7ea+4,18.1.0-1-g7e8fceb,18.1.0-1-g85f8cd4+10,18.1.0-1-g9a6769a+4,18.1.0-1-ga1a4c1a+9,18.1.0-1-gd55f500+5,18.1.0-1-ge10677a+10,18.1.0-11-gb2589d7b,18.1.0-13-g451e75588+2,18.1.0-13-gbfe7f7f+4,18.1.0-14-g2e73c10+1,18.1.0-2-g31c43f9+10,18.1.0-2-g919ecaf,18.1.0-2-g9c63283+13,18.1.0-2-gdf0b915+13,18.1.0-2-gfefb8b5+2,18.1.0-3-g52aa583+4,18.1.0-3-g8f4a2b1+4,18.1.0-3-g9cb968e+12,18.1.0-3-gab23065,18.1.0-4-g7bbbad0+4,18.1.0-5-g510c42a+12,18.1.0-5-gaeab27e+13,18.1.0-6-gc4bdb98+2,18.1.0-6-gdda7f3e+15,18.1.0-9-g9613d271+1,w.2019.34
LSSTDataManagementBasePackage
Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | List of all members
lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask Class Reference
Inheritance diagram for lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask:
lsst.pipe.tasks.coaddBase.CoaddBaseTask lsst.pipe.tasks.assembleCoadd.CompareWarpAssembleCoaddTask lsst.pipe.tasks.assembleCoadd.SafeClipAssembleCoaddTask lsst.pipe.tasks.dcrAssembleCoadd.DcrAssembleCoaddTask

Public Member Functions

def __init__ (self, args, kwargs)
 
def getOutputDatasetTypes (cls, config)
 
def getInputDatasetTypes (cls, config)
 
def getPrerequisiteDatasetTypes (cls, config)
 
def adaptArgsAndRun (self, inputData, inputDataIds, outputDataIds, butler)
 
def runDataRef (self, dataRef, selectDataList=None, warpRefList=None)
 
def processResults (self, coaddExposure, dataRef)
 
def makeSupplementaryData (self, dataRef, selectDataList=None, warpRefList=None)
 
def makeSupplementaryDataGen3 (self, inputData, inputDataIds, outputDataIds, butler)
 
def getTempExpRefList (self, patchRef, calExpRefList)
 
def prepareInputs (self, refList)
 
def prepareStats (self, mask=None)
 
def run (self, skyInfo, tempExpRefList, imageScalerList, weightList, altMaskList=None, mask=None, supplementaryData=None)
 
def assembleMetadata (self, coaddExposure, tempExpRefList, weightList)
 
def assembleSubregion (self, coaddExposure, bbox, tempExpRefList, imageScalerList, weightList, altMaskList, statsFlags, statsCtrl, nImage=None)
 
def removeMaskPlanes (self, maskedImage)
 
def applyAltMaskPlanes (self, mask, altMaskSpans)
 
def shrinkValidPolygons (self, coaddInputs)
 
def readBrightObjectMasks (self, dataRef)
 
def setBrightObjectMasks (self, exposure, dataId, brightObjectMasks)
 
def setInexactPsf (self, mask)
 
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...
 

Static Public Member Functions

def setRejectedMaskMapping (statsCtrl)
 

Public Attributes

 brightObjectBitmask
 
 warpType
 

Static Public Attributes

 ConfigClass = AssembleCoaddConfig
 
 RunnerClass = CoaddTaskRunner
 

Detailed Description

Assemble a coadded image from a set of warps (coadded temporary exposures).

We want to assemble a coadded image from a set of Warps (also called
coadded temporary exposures or ``coaddTempExps``).
Each input Warp covers a patch on the sky and corresponds to a single
run/visit/exposure of the covered patch. We provide the task with a list
of Warps (``selectDataList``) from which it selects Warps that cover the
specified patch (pointed at by ``dataRef``).
Each Warp that goes into a coadd will typically have an independent
photometric zero-point. Therefore, we must scale each Warp to set it to
a common photometric zeropoint. WarpType may be one of 'direct' or
'psfMatched', and the boolean configs `config.makeDirect` and
`config.makePsfMatched` set which of the warp types will be coadded.
The coadd is computed as a mean with optional outlier rejection.
Criteria for outlier rejection are set in `AssembleCoaddConfig`.
Finally, Warps can have bad 'NaN' pixels which received no input from the
source calExps. We interpolate over these bad (NaN) pixels.

`AssembleCoaddTask` uses several sub-tasks. These are

- `ScaleZeroPointTask`
- create and use an ``imageScaler`` object to scale the photometric zeropoint for each Warp
- `InterpImageTask`
- interpolate across bad pixels (NaN) in the final coadd

You can retarget these subtasks if you wish.

Notes
-----
The `lsst.pipe.base.cmdLineTask.CmdLineTask` interface supports a
flag ``-d`` to import ``debug.py`` from your ``PYTHONPATH``; see
`baseDebug` for more about ``debug.py`` files. `AssembleCoaddTask` has
no debug variables of its own. Some of the subtasks may support debug
variables. See the documentation for the subtasks for further information.

Examples
--------
`AssembleCoaddTask` assembles a set of warped images into a coadded image.
The `AssembleCoaddTask` can be invoked by running ``assembleCoadd.py``
with the flag '--legacyCoadd'. Usage of assembleCoadd.py expects two
inputs: a data reference to the tract patch and filter to be coadded, and
a list of Warps to attempt to coadd. These are specified using ``--id`` and
``--selectId``, respectively:

.. code-block:: none

   --id = [KEY=VALUE1[^VALUE2[^VALUE3...] [KEY=VALUE1[^VALUE2[^VALUE3...] ...]]
   --selectId [KEY=VALUE1[^VALUE2[^VALUE3...] [KEY=VALUE1[^VALUE2[^VALUE3...] ...]]

Only the Warps that cover the specified tract and patch will be coadded.
A list of the available optional arguments can be obtained by calling
``assembleCoadd.py`` with the ``--help`` command line argument:

.. code-block:: none

   assembleCoadd.py --help

To demonstrate usage of the `AssembleCoaddTask` in the larger context of
multi-band processing, we will generate the HSC-I & -R band coadds from
HSC engineering test data provided in the ``ci_hsc`` package. To begin,
assuming that the lsst stack has been already set up, we must set up the
obs_subaru and ``ci_hsc`` packages. This defines the environment variable
``$CI_HSC_DIR`` and points at the location of the package. The raw HSC
data live in the ``$CI_HSC_DIR/raw directory``. To begin assembling the
coadds, we must first

- processCcd
- process the individual ccds in $CI_HSC_RAW to produce calibrated exposures
- makeSkyMap
- create a skymap that covers the area of the sky present in the raw exposures
- makeCoaddTempExp
- warp the individual calibrated exposures to the tangent plane of the coadd

We can perform all of these steps by running

.. code-block:: none

   $CI_HSC_DIR scons warp-903986 warp-904014 warp-903990 warp-904010 warp-903988

This will produce warped exposures for each visit. To coadd the warped
data, we call assembleCoadd.py as follows:

.. code-block:: none

   assembleCoadd.py --legacyCoadd $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-I \
   --selectId visit=903986 ccd=16 --selectId visit=903986 ccd=22 --selectId visit=903986 ccd=23 \
   --selectId visit=903986 ccd=100 --selectId visit=904014 ccd=1 --selectId visit=904014 ccd=6 \
   --selectId visit=904014 ccd=12 --selectId visit=903990 ccd=18 --selectId visit=903990 ccd=25 \
   --selectId visit=904010 ccd=4 --selectId visit=904010 ccd=10 --selectId visit=904010 ccd=100 \
   --selectId visit=903988 ccd=16 --selectId visit=903988 ccd=17 --selectId visit=903988 ccd=23 \
   --selectId visit=903988 ccd=24

that will process the HSC-I band data. The results are written in
``$CI_HSC_DIR/DATA/deepCoadd-results/HSC-I``.

You may also choose to run:

.. code-block:: none

   scons warp-903334 warp-903336 warp-903338 warp-903342 warp-903344 warp-903346
   assembleCoadd.py --legacyCoadd $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-R \
   --selectId visit=903334 ccd=16 --selectId visit=903334 ccd=22 --selectId visit=903334 ccd=23 \
   --selectId visit=903334 ccd=100 --selectId visit=903336 ccd=17 --selectId visit=903336 ccd=24 \
   --selectId visit=903338 ccd=18 --selectId visit=903338 ccd=25 --selectId visit=903342 ccd=4 \
   --selectId visit=903342 ccd=10 --selectId visit=903342 ccd=100 --selectId visit=903344 ccd=0 \
   --selectId visit=903344 ccd=5 --selectId visit=903344 ccd=11 --selectId visit=903346 ccd=1 \
   --selectId visit=903346 ccd=6 --selectId visit=903346 ccd=12

to generate the coadd for the HSC-R band if you are interested in
following multiBand Coadd processing as discussed in `pipeTasks_multiBand`
(but note that normally, one would use the `SafeClipAssembleCoaddTask`
rather than `AssembleCoaddTask` to make the coadd.

Definition at line 228 of file assembleCoadd.py.

Constructor & Destructor Documentation

◆ __init__()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.__init__ (   self,
  args,
  kwargs 
)

Definition at line 345 of file assembleCoadd.py.

345  def __init__(self, *args, **kwargs):
346  # TODO: DM-17415 better way to handle previously allowed passed args e.g.`AssembleCoaddTask(config)`
347  if args:
348  argNames = ["config", "name", "parentTask", "log"]
349  kwargs.update({k: v for k, v in zip(argNames, args)})
350  warnings.warn("AssembleCoadd received positional args, and casting them as kwargs: %s. "
351  "PipelineTask will not take positional args" % argNames, FutureWarning)
352 
353  super().__init__(**kwargs)
354  self.makeSubtask("interpImage")
355  self.makeSubtask("scaleZeroPoint")
356 
357  if self.config.doMaskBrightObjects:
358  mask = afwImage.Mask()
359  try:
360  self.brightObjectBitmask = 1 << mask.addMaskPlane(self.config.brightObjectMaskName)
361  except pexExceptions.LsstCppException:
362  raise RuntimeError("Unable to define mask plane for bright objects; planes used are %s" %
363  mask.getMaskPlaneDict().keys())
364  del mask
365 
366  self.warpType = self.config.warpType
367 
Represent a 2-dimensional array of bitmask pixels.
Definition: Mask.h:77
def __init__(self, minimum, dataRange, Q)

Member Function Documentation

◆ adaptArgsAndRun()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.adaptArgsAndRun (   self,
  inputData,
  inputDataIds,
  outputDataIds,
  butler 
)
Assemble a coadd from a set of Warps.

PipelineTask (Gen3) entry point to Coadd a set of Warps.
Analogous to `runDataRef`, it prepares all the data products to be
passed to `run`, and processes the results before returning to struct
of results to be written out. AssembleCoadd cannot fit all Warps in memory.
Therefore, its inputs are accessed subregion by subregion
by the `lsst.daf.butler.ShimButler` that quacks like a Gen2
`lsst.daf.persistence.Butler`. Updates to this method should
correspond to an update in `runDataRef` while both entry points
are used.

Parameters
----------
inputData : `dict`
    Keys are the names of the configs describing input dataset types.
    Values are input Python-domain data objects (or lists of objects)
    retrieved from data butler.
inputDataIds : `dict`
    Keys are the names of the configs describing input dataset types.
    Values are DataIds (or lists of DataIds) that task consumes for
    corresponding dataset type.
outputDataIds : `dict`
    Keys are the names of the configs describing input dataset types.
    Values are DataIds (or lists of DataIds) that task is to produce
    for corresponding dataset type.
butler : `lsst.daf.butler.Butler`
    Gen3 Butler object for fetching additional data products before
    running the Task

Returns
-------
result : `lsst.pipe.base.Struct`
   Result struct with components:

   - ``coaddExposure`` : coadded exposure (``lsst.afw.image.Exposure``)
   - ``nImage``: N Image (``lsst.afw.image.Image``)

Definition at line 394 of file assembleCoadd.py.

394  def adaptArgsAndRun(self, inputData, inputDataIds, outputDataIds, butler):
395  """Assemble a coadd from a set of Warps.
396 
397  PipelineTask (Gen3) entry point to Coadd a set of Warps.
398  Analogous to `runDataRef`, it prepares all the data products to be
399  passed to `run`, and processes the results before returning to struct
400  of results to be written out. AssembleCoadd cannot fit all Warps in memory.
401  Therefore, its inputs are accessed subregion by subregion
402  by the `lsst.daf.butler.ShimButler` that quacks like a Gen2
403  `lsst.daf.persistence.Butler`. Updates to this method should
404  correspond to an update in `runDataRef` while both entry points
405  are used.
406 
407  Parameters
408  ----------
409  inputData : `dict`
410  Keys are the names of the configs describing input dataset types.
411  Values are input Python-domain data objects (or lists of objects)
412  retrieved from data butler.
413  inputDataIds : `dict`
414  Keys are the names of the configs describing input dataset types.
415  Values are DataIds (or lists of DataIds) that task consumes for
416  corresponding dataset type.
417  outputDataIds : `dict`
418  Keys are the names of the configs describing input dataset types.
419  Values are DataIds (or lists of DataIds) that task is to produce
420  for corresponding dataset type.
421  butler : `lsst.daf.butler.Butler`
422  Gen3 Butler object for fetching additional data products before
423  running the Task
424 
425  Returns
426  -------
427  result : `lsst.pipe.base.Struct`
428  Result struct with components:
429 
430  - ``coaddExposure`` : coadded exposure (``lsst.afw.image.Exposure``)
431  - ``nImage``: N Image (``lsst.afw.image.Image``)
432  """
433  # Construct skyInfo expected by run
434  # Do not remove skyMap from inputData in case makeSupplementaryDataGen3 needs it
435  skyMap = inputData["skyMap"]
436  outputDataId = next(iter(outputDataIds.values()))
437  inputData['skyInfo'] = makeSkyInfo(skyMap,
438  tractId=outputDataId['tract'],
439  patchId=outputDataId['patch'])
440 
441  # Construct list of input Shim DataRefs that quack like Gen2 DataRefs
442  butlerShim = ShimButler(butler)
443  warpRefList = [butlerShim.dataRef(self.config.inputWarps.name, dataId=dataId)
444  for dataId in inputDataIds['inputWarps']]
445 
446  # Construct output Shim DataRef
447  patchRef = butlerShim.dataRef(self.config.coaddExposure.name, dataId=outputDataIds['coaddExposure'])
448 
449  # Perform same middle steps as `runDataRef` does
450  inputs = self.prepareInputs(warpRefList)
451  self.log.info("Found %d %s", len(inputs.tempExpRefList),
452  self.getTempExpDatasetName(self.warpType))
453  if len(inputs.tempExpRefList) == 0:
454  self.log.warn("No coadd temporary exposures found")
455  return
456 
457  supplementaryData = self.makeSupplementaryDataGen3(inputData, inputDataIds, outputDataIds, butler)
458 
459  retStruct = self.run(inputData['skyInfo'], inputs.tempExpRefList, inputs.imageScalerList,
460  inputs.weightList, supplementaryData=supplementaryData)
461 
462  self.processResults(retStruct.coaddExposure, patchRef)
463  return retStruct
464 
def makeSkyInfo(skyMap, tractId, patchId)
Definition: coaddBase.py:250

◆ applyAltMaskPlanes()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.applyAltMaskPlanes (   self,
  mask,
  altMaskSpans 
)
Apply in place alt mask formatted as SpanSets to a mask.

Parameters
----------
mask : `lsst.afw.image.Mask`
    Original mask.
altMaskSpans : `dict`
    SpanSet lists to apply. Each element contains the new mask
    plane name (e.g. "CLIPPED and/or "NO_DATA") as the key,
    and list of SpanSets to apply to the mask.

Returns
-------
mask : `lsst.afw.image.Mask`
    Updated mask.

Definition at line 984 of file assembleCoadd.py.

984  def applyAltMaskPlanes(self, mask, altMaskSpans):
985  """Apply in place alt mask formatted as SpanSets to a mask.
986 
987  Parameters
988  ----------
989  mask : `lsst.afw.image.Mask`
990  Original mask.
991  altMaskSpans : `dict`
992  SpanSet lists to apply. Each element contains the new mask
993  plane name (e.g. "CLIPPED and/or "NO_DATA") as the key,
994  and list of SpanSets to apply to the mask.
995 
996  Returns
997  -------
998  mask : `lsst.afw.image.Mask`
999  Updated mask.
1000  """
1001  if self.config.doUsePsfMatchedPolygons:
1002  if ("NO_DATA" in altMaskSpans) and ("NO_DATA" in self.config.badMaskPlanes):
1003  # Clear away any other masks outside the validPolygons. These pixels are no longer
1004  # contributing to inexact PSFs, and will still be rejected because of NO_DATA
1005  # self.config.doUsePsfMatchedPolygons should be True only in CompareWarpAssemble
1006  # This mask-clearing step must only occur *before* applying the new masks below
1007  for spanSet in altMaskSpans['NO_DATA']:
1008  spanSet.clippedTo(mask.getBBox()).clearMask(mask, self.getBadPixelMask())
1009 
1010  for plane, spanSetList in altMaskSpans.items():
1011  maskClipValue = mask.addMaskPlane(plane)
1012  for spanSet in spanSetList:
1013  spanSet.clippedTo(mask.getBBox()).setMask(mask, 2**maskClipValue)
1014  return mask
1015 

◆ assembleMetadata()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.assembleMetadata (   self,
  coaddExposure,
  tempExpRefList,
  weightList 
)
Set the metadata for the coadd.

This basic implementation sets the filter from the first input.

Parameters
----------
coaddExposure : `lsst.afw.image.Exposure`
    The target exposure for the coadd.
tempExpRefList : `list`
    List of data references to tempExp.
weightList : `list`
    List of weights.

Definition at line 813 of file assembleCoadd.py.

813  def assembleMetadata(self, coaddExposure, tempExpRefList, weightList):
814  """Set the metadata for the coadd.
815 
816  This basic implementation sets the filter from the first input.
817 
818  Parameters
819  ----------
820  coaddExposure : `lsst.afw.image.Exposure`
821  The target exposure for the coadd.
822  tempExpRefList : `list`
823  List of data references to tempExp.
824  weightList : `list`
825  List of weights.
826  """
827  assert len(tempExpRefList) == len(weightList), "Length mismatch"
828  tempExpName = self.getTempExpDatasetName(self.warpType)
829  # We load a single pixel of each coaddTempExp, because we just want to get at the metadata
830  # (and we need more than just the PropertySet that contains the header), which is not possible
831  # with the current butler (see #2777).
832  tempExpList = [tempExpRef.get(tempExpName + "_sub",
833  bbox=geom.Box2I(coaddExposure.getBBox().getMin(),
834  geom.Extent2I(1, 1)), immediate=True)
835  for tempExpRef in tempExpRefList]
836  numCcds = sum(len(tempExp.getInfo().getCoaddInputs().ccds) for tempExp in tempExpList)
837 
838  coaddExposure.setFilter(tempExpList[0].getFilter())
839  coaddInputs = coaddExposure.getInfo().getCoaddInputs()
840  coaddInputs.ccds.reserve(numCcds)
841  coaddInputs.visits.reserve(len(tempExpList))
842 
843  for tempExp, weight in zip(tempExpList, weightList):
844  self.inputRecorder.addVisitToCoadd(coaddInputs, tempExp, weight)
845 
846  if self.config.doUsePsfMatchedPolygons:
847  self.shrinkValidPolygons(coaddInputs)
848 
849  coaddInputs.visits.sort()
850  if self.warpType == "psfMatched":
851  # The modelPsf BBox for a psfMatchedWarp/coaddTempExp was dynamically defined by
852  # ModelPsfMatchTask as the square box bounding its spatially-variable, pre-matched WarpedPsf.
853  # Likewise, set the PSF of a PSF-Matched Coadd to the modelPsf
854  # having the maximum width (sufficient because square)
855  modelPsfList = [tempExp.getPsf() for tempExp in tempExpList]
856  modelPsfWidthList = [modelPsf.computeBBox().getWidth() for modelPsf in modelPsfList]
857  psf = modelPsfList[modelPsfWidthList.index(max(modelPsfWidthList))]
858  else:
859  psf = measAlg.CoaddPsf(coaddInputs.ccds, coaddExposure.getWcs(),
860  self.config.coaddPsf.makeControl())
861  coaddExposure.setPsf(psf)
862  apCorrMap = measAlg.makeCoaddApCorrMap(coaddInputs.ccds, coaddExposure.getBBox(afwImage.PARENT),
863  coaddExposure.getWcs())
864  coaddExposure.getInfo().setApCorrMap(apCorrMap)
865  if self.config.doAttachTransmissionCurve:
866  transmissionCurve = measAlg.makeCoaddTransmissionCurve(coaddExposure.getWcs(), coaddInputs.ccds)
867  coaddExposure.getInfo().setTransmissionCurve(transmissionCurve)
868 
int max
An integer coordinate rectangle.
Definition: Box.h:54

◆ assembleSubregion()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.assembleSubregion (   self,
  coaddExposure,
  bbox,
  tempExpRefList,
  imageScalerList,
  weightList,
  altMaskList,
  statsFlags,
  statsCtrl,
  nImage = None 
)
Assemble the coadd for a sub-region.

For each coaddTempExp, check for (and swap in) an alternative mask
if one is passed. Remove mask planes listed in
`config.removeMaskPlanes`. Finally, stack the actual exposures using
`lsst.afw.math.statisticsStack` with the statistic specified by
statsFlags. Typically, the statsFlag will be one of lsst.afw.math.MEAN for
a mean-stack or `lsst.afw.math.MEANCLIP` for outlier rejection using
an N-sigma clipped mean where N and iterations are specified by
statsCtrl.  Assign the stacked subregion back to the coadd.

Parameters
----------
coaddExposure : `lsst.afw.image.Exposure`
    The target exposure for the coadd.
bbox : `lsst.geom.Box`
    Sub-region to coadd.
tempExpRefList : `list`
    List of data reference to tempExp.
imageScalerList : `list`
    List of image scalers.
weightList : `list`
    List of weights.
altMaskList : `list`
    List of alternate masks to use rather than those stored with
    tempExp, or None.  Each element is dict with keys = mask plane
    name to which to add the spans.
statsFlags : `lsst.afw.math.Property`
    Property object for statistic for coadd.
statsCtrl : `lsst.afw.math.StatisticsControl`
    Statistics control object for coadd.
nImage : `lsst.afw.image.ImageU`, optional
    Keeps track of exposure count for each pixel.

Definition at line 870 of file assembleCoadd.py.

870  altMaskList, statsFlags, statsCtrl, nImage=None):
871  """Assemble the coadd for a sub-region.
872 
873  For each coaddTempExp, check for (and swap in) an alternative mask
874  if one is passed. Remove mask planes listed in
875  `config.removeMaskPlanes`. Finally, stack the actual exposures using
876  `lsst.afw.math.statisticsStack` with the statistic specified by
877  statsFlags. Typically, the statsFlag will be one of lsst.afw.math.MEAN for
878  a mean-stack or `lsst.afw.math.MEANCLIP` for outlier rejection using
879  an N-sigma clipped mean where N and iterations are specified by
880  statsCtrl. Assign the stacked subregion back to the coadd.
881 
882  Parameters
883  ----------
884  coaddExposure : `lsst.afw.image.Exposure`
885  The target exposure for the coadd.
886  bbox : `lsst.geom.Box`
887  Sub-region to coadd.
888  tempExpRefList : `list`
889  List of data reference to tempExp.
890  imageScalerList : `list`
891  List of image scalers.
892  weightList : `list`
893  List of weights.
894  altMaskList : `list`
895  List of alternate masks to use rather than those stored with
896  tempExp, or None. Each element is dict with keys = mask plane
897  name to which to add the spans.
898  statsFlags : `lsst.afw.math.Property`
899  Property object for statistic for coadd.
900  statsCtrl : `lsst.afw.math.StatisticsControl`
901  Statistics control object for coadd.
902  nImage : `lsst.afw.image.ImageU`, optional
903  Keeps track of exposure count for each pixel.
904  """
905  self.log.debug("Computing coadd over %s", bbox)
906  tempExpName = self.getTempExpDatasetName(self.warpType)
907  coaddExposure.mask.addMaskPlane("REJECTED")
908  coaddExposure.mask.addMaskPlane("CLIPPED")
909  coaddExposure.mask.addMaskPlane("SENSOR_EDGE")
910  maskMap = self.setRejectedMaskMapping(statsCtrl)
911  clipped = afwImage.Mask.getPlaneBitMask("CLIPPED")
912  maskedImageList = []
913  if nImage is not None:
914  subNImage = afwImage.ImageU(bbox.getWidth(), bbox.getHeight())
915  for tempExpRef, imageScaler, altMask in zip(tempExpRefList, imageScalerList, altMaskList):
916  exposure = tempExpRef.get(tempExpName + "_sub", bbox=bbox)
917  maskedImage = exposure.getMaskedImage()
918  mask = maskedImage.getMask()
919  if altMask is not None:
920  self.applyAltMaskPlanes(mask, altMask)
921  imageScaler.scaleMaskedImage(maskedImage)
922 
923  # Add 1 for each pixel which is not excluded by the exclude mask.
924  # In legacyCoadd, pixels may also be excluded by afwMath.statisticsStack.
925  if nImage is not None:
926  subNImage.getArray()[maskedImage.getMask().getArray() & statsCtrl.getAndMask() == 0] += 1
927  if self.config.removeMaskPlanes:
928  self.removeMaskPlanes(maskedImage)
929  maskedImageList.append(maskedImage)
930 
931  with self.timer("stack"):
932  coaddSubregion = afwMath.statisticsStack(maskedImageList, statsFlags, statsCtrl, weightList,
933  clipped, # also set output to CLIPPED if sigma-clipped
934  maskMap)
935  coaddExposure.maskedImage.assign(coaddSubregion, bbox)
936  if nImage is not None:
937  nImage.assign(subNImage, bbox)
938 
std::shared_ptr< image::MaskedImage< PixelT > > statisticsStack(image::MaskedImage< PixelT > const &image, Property flags, char dimension, StatisticsControl const &sctrl)
A function to compute statistics on the rows or columns of an image.
Definition: Stack.cc:478

◆ getBadPixelMask()

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

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

Definition at line 200 of file coaddBase.py.

200  def getBadPixelMask(self):
201  """!
202  @brief Convenience method to provide the bitmask from the mask plane names
203  """
204  return afwImage.Mask.getPlaneBitMask(self.config.badMaskPlanes)
205 
206 

◆ 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 150 of file coaddBase.py.

150  def getCoaddDatasetName(self, warpType="direct"):
151  """Return coadd name for given warpType and task config
152 
153  Parameters
154  ----------
155  warpType : string
156  Either 'direct' or 'psfMatched'
157 
158  Returns
159  -------
160  CoaddDatasetName : `string`
161  """
162  suffix = "" if warpType == "direct" else warpType[0].upper() + warpType[1:]
163  return self.config.coaddName + "Coadd" + suffix
164 

◆ getInputDatasetTypes()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.getInputDatasetTypes (   cls,
  config 
)
Return input dataset type descriptors

Remove input dataset types not used by the Task

Definition at line 380 of file assembleCoadd.py.

380  def getInputDatasetTypes(cls, config):
381  """Return input dataset type descriptors
382 
383  Remove input dataset types not used by the Task
384  """
385  inputTypeDict = super().getInputDatasetTypes(config)
386  if not config.doMaskBrightObjects:
387  inputTypeDict.pop("brightObjectMask", None)
388  return inputTypeDict
389 

◆ getOutputDatasetTypes()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.getOutputDatasetTypes (   cls,
  config 
)
Return output dataset type descriptors

Remove output dataset types not produced by the Task

Definition at line 369 of file assembleCoadd.py.

369  def getOutputDatasetTypes(cls, config):
370  """Return output dataset type descriptors
371 
372  Remove output dataset types not produced by the Task
373  """
374  outputTypeDict = super().getOutputDatasetTypes(config)
375  if not config.doNImage:
376  outputTypeDict.pop("nImage", None)
377  return outputTypeDict
378 

◆ getPrerequisiteDatasetTypes()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.getPrerequisiteDatasetTypes (   cls,
  config 
)

Definition at line 391 of file assembleCoadd.py.

391  def getPrerequisiteDatasetTypes(cls, config):
392  return frozenset(["brightObjectMask"])
393 

◆ 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 134 of file coaddBase.py.

134  def getSkyInfo(self, patchRef):
135  """!
136  @brief Use @ref getSkyinfo to return the skyMap, tract and patch information, wcs and the outer bbox
137  of the patch.
138 
139  @param[in] patchRef data reference for sky map. Must include keys "tract" and "patch"
140 
141  @return pipe_base Struct containing:
142  - skyMap: sky map
143  - tractInfo: information for chosen tract of sky map
144  - patchInfo: information about chosen patch of tract
145  - wcs: WCS of tract
146  - bbox: outer bbox of patch, as an geom Box2I
147  """
148  return getSkyInfo(coaddName=self.config.coaddName, patchRef=patchRef)
149 
def getSkyInfo(coaddName, patchRef)
Return the SkyMap, tract and patch information, wcs, and outer bbox of the patch to be coadded...
Definition: coaddBase.py:232

◆ 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 165 of file coaddBase.py.

165  def getTempExpDatasetName(self, warpType="direct"):
166  """Return warp name for given warpType and task config
167 
168  Parameters
169  ----------
170  warpType : string
171  Either 'direct' or 'psfMatched'
172 
173  Returns
174  -------
175  WarpDatasetName : `string`
176  """
177  return self.config.coaddName + "Coadd_" + warpType + "Warp"
178 

◆ getTempExpRefList()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.getTempExpRefList (   self,
  patchRef,
  calExpRefList 
)
Generate list data references corresponding to warped exposures
that lie within the patch to be coadded.

Parameters
----------
patchRef : `dataRef`
    Data reference for patch.
calExpRefList : `list`
    List of data references for input calexps.

Returns
-------
tempExpRefList : `list`
    List of Warp/CoaddTempExp data references.

Definition at line 612 of file assembleCoadd.py.

612  def getTempExpRefList(self, patchRef, calExpRefList):
613  """Generate list data references corresponding to warped exposures
614  that lie within the patch to be coadded.
615 
616  Parameters
617  ----------
618  patchRef : `dataRef`
619  Data reference for patch.
620  calExpRefList : `list`
621  List of data references for input calexps.
622 
623  Returns
624  -------
625  tempExpRefList : `list`
626  List of Warp/CoaddTempExp data references.
627  """
628  butler = patchRef.getButler()
629  groupData = groupPatchExposures(patchRef, calExpRefList, self.getCoaddDatasetName(self.warpType),
630  self.getTempExpDatasetName(self.warpType))
631  tempExpRefList = [getGroupDataRef(butler, self.getTempExpDatasetName(self.warpType),
632  g, groupData.keys) for
633  g in groupData.groups.keys()]
634  return tempExpRefList
635 
def getGroupDataRef(butler, datasetType, groupTuple, keys)
Definition: coaddHelpers.py:99
def groupPatchExposures(patchDataRef, calexpDataRefList, coaddDatasetType="deepCoadd", tempExpDatasetType="deepCoadd_directWarp")
Definition: coaddHelpers.py:60

◆ makeSupplementaryData()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.makeSupplementaryData (   self,
  dataRef,
  selectDataList = None,
  warpRefList = None 
)
Make additional inputs to run() specific to subclasses (Gen2)

Duplicates interface of `runDataRef` method
Available to be implemented by subclasses only if they need the
coadd dataRef for performing preliminary processing before
assembling the coadd.

Parameters
----------
dataRef : `lsst.daf.persistence.ButlerDataRef`
    Butler data reference for supplementary data.
selectDataList : `list`
    List of data references to Warps.

Definition at line 561 of file assembleCoadd.py.

561  def makeSupplementaryData(self, dataRef, selectDataList=None, warpRefList=None):
562  """Make additional inputs to run() specific to subclasses (Gen2)
563 
564  Duplicates interface of `runDataRef` method
565  Available to be implemented by subclasses only if they need the
566  coadd dataRef for performing preliminary processing before
567  assembling the coadd.
568 
569  Parameters
570  ----------
571  dataRef : `lsst.daf.persistence.ButlerDataRef`
572  Butler data reference for supplementary data.
573  selectDataList : `list`
574  List of data references to Warps.
575  """
576  pass
577 

◆ makeSupplementaryDataGen3()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.makeSupplementaryDataGen3 (   self,
  inputData,
  inputDataIds,
  outputDataIds,
  butler 
)
Make additional inputs to run() specific to subclasses (Gen3)

Duplicates interface of`adaptArgsAndRun` method.
Available to be implemented by subclasses only if they need the
coadd dataRef for performing preliminary processing before
assembling the coadd.

Parameters
----------
inputData : `dict`
    Keys are the names of the configs describing input dataset types.
    Values are input Python-domain data objects (or lists of objects)
    retrieved from data butler.
inputDataIds : `dict`
    Keys are the names of the configs describing input dataset types.
    Values are DataIds (or lists of DataIds) that task consumes for
    corresponding dataset type.
    DataIds are guaranteed to match data objects in ``inputData``.
outputDataIds : `dict`
    Keys are the names of the configs describing input dataset types.
    Values are DataIds (or lists of DataIds) that task is to produce
    for corresponding dataset type.
butler : `lsst.daf.butler.Butler`
    Gen3 Butler object for fetching additional data products before
    running the Task

Returns
-------
result : `lsst.pipe.base.Struct`
    Contains whatever additional data the subclass's `run` method needs

Definition at line 578 of file assembleCoadd.py.

578  def makeSupplementaryDataGen3(self, inputData, inputDataIds, outputDataIds, butler):
579  """Make additional inputs to run() specific to subclasses (Gen3)
580 
581  Duplicates interface of`adaptArgsAndRun` method.
582  Available to be implemented by subclasses only if they need the
583  coadd dataRef for performing preliminary processing before
584  assembling the coadd.
585 
586  Parameters
587  ----------
588  inputData : `dict`
589  Keys are the names of the configs describing input dataset types.
590  Values are input Python-domain data objects (or lists of objects)
591  retrieved from data butler.
592  inputDataIds : `dict`
593  Keys are the names of the configs describing input dataset types.
594  Values are DataIds (or lists of DataIds) that task consumes for
595  corresponding dataset type.
596  DataIds are guaranteed to match data objects in ``inputData``.
597  outputDataIds : `dict`
598  Keys are the names of the configs describing input dataset types.
599  Values are DataIds (or lists of DataIds) that task is to produce
600  for corresponding dataset type.
601  butler : `lsst.daf.butler.Butler`
602  Gen3 Butler object for fetching additional data products before
603  running the Task
604 
605  Returns
606  -------
607  result : `lsst.pipe.base.Struct`
608  Contains whatever additional data the subclass's `run` method needs
609  """
610  pass
611 

◆ prepareInputs()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.prepareInputs (   self,
  refList 
)
Prepare the input warps for coaddition by measuring the weight for
each warp and the scaling for the photometric zero point.

Each Warp has its own photometric zeropoint and background variance.
Before coadding these Warps together, compute a scale factor to
normalize the photometric zeropoint and compute the weight for each Warp.

Parameters
----------
refList : `list`
    List of data references to tempExp

Returns
-------
result : `lsst.pipe.base.Struct`
   Result struct with components:

   - ``tempExprefList``: `list` of data references to tempExp.
   - ``weightList``: `list` of weightings.
   - ``imageScalerList``: `list` of image scalers.

Definition at line 636 of file assembleCoadd.py.

636  def prepareInputs(self, refList):
637  """Prepare the input warps for coaddition by measuring the weight for
638  each warp and the scaling for the photometric zero point.
639 
640  Each Warp has its own photometric zeropoint and background variance.
641  Before coadding these Warps together, compute a scale factor to
642  normalize the photometric zeropoint and compute the weight for each Warp.
643 
644  Parameters
645  ----------
646  refList : `list`
647  List of data references to tempExp
648 
649  Returns
650  -------
651  result : `lsst.pipe.base.Struct`
652  Result struct with components:
653 
654  - ``tempExprefList``: `list` of data references to tempExp.
655  - ``weightList``: `list` of weightings.
656  - ``imageScalerList``: `list` of image scalers.
657  """
658  statsCtrl = afwMath.StatisticsControl()
659  statsCtrl.setNumSigmaClip(self.config.sigmaClip)
660  statsCtrl.setNumIter(self.config.clipIter)
661  statsCtrl.setAndMask(self.getBadPixelMask())
662  statsCtrl.setNanSafe(True)
663  # compute tempExpRefList: a list of tempExpRef that actually exist
664  # and weightList: a list of the weight of the associated coadd tempExp
665  # and imageScalerList: a list of scale factors for the associated coadd tempExp
666  tempExpRefList = []
667  weightList = []
668  imageScalerList = []
669  tempExpName = self.getTempExpDatasetName(self.warpType)
670  for tempExpRef in refList:
671  if not tempExpRef.datasetExists(tempExpName):
672  self.log.warn("Could not find %s %s; skipping it", tempExpName, tempExpRef.dataId)
673  continue
674 
675  tempExp = tempExpRef.get(tempExpName, immediate=True)
676  # Ignore any input warp that is empty of data
677  if numpy.isnan(tempExp.image.array).all():
678  continue
679  maskedImage = tempExp.getMaskedImage()
680  imageScaler = self.scaleZeroPoint.computeImageScaler(
681  exposure=tempExp,
682  dataRef=tempExpRef,
683  )
684  try:
685  imageScaler.scaleMaskedImage(maskedImage)
686  except Exception as e:
687  self.log.warn("Scaling failed for %s (skipping it): %s", tempExpRef.dataId, e)
688  continue
689  statObj = afwMath.makeStatistics(maskedImage.getVariance(), maskedImage.getMask(),
690  afwMath.MEANCLIP, statsCtrl)
691  meanVar, meanVarErr = statObj.getResult(afwMath.MEANCLIP)
692  weight = 1.0 / float(meanVar)
693  if not numpy.isfinite(weight):
694  self.log.warn("Non-finite weight for %s: skipping", tempExpRef.dataId)
695  continue
696  self.log.info("Weight of %s %s = %0.3f", tempExpName, tempExpRef.dataId, weight)
697 
698  del maskedImage
699  del tempExp
700 
701  tempExpRefList.append(tempExpRef)
702  weightList.append(weight)
703  imageScalerList.append(imageScaler)
704 
705  return pipeBase.Struct(tempExpRefList=tempExpRefList, weightList=weightList,
706  imageScalerList=imageScalerList)
707 
Statistics makeStatistics(lsst::afw::math::MaskedVector< EntryT > const &mv, std::vector< WeightPixel > const &vweights, int const flags, StatisticsControl const &sctrl=StatisticsControl())
The makeStatistics() overload to handle lsst::afw::math::MaskedVector<>
Definition: Statistics.h:520
bool all(CoordinateExpr< N > const &expr) noexcept
Return true if all elements are true.
Pass parameters to a Statistics object.
Definition: Statistics.h:93

◆ prepareStats()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.prepareStats (   self,
  mask = None 
)
Prepare the statistics for coadding images.

Parameters
----------
mask : `int`, optional
    Bit mask value to exclude from coaddition.

Returns
-------
stats : `lsst.pipe.base.Struct`
    Statistics structure with the following fields:

    - ``statsCtrl``: Statistics control object for coadd
(`lsst.afw.math.StatisticsControl`)
    - ``statsFlags``: Statistic for coadd (`lsst.afw.math.Property`)

Definition at line 708 of file assembleCoadd.py.

708  def prepareStats(self, mask=None):
709  """Prepare the statistics for coadding images.
710 
711  Parameters
712  ----------
713  mask : `int`, optional
714  Bit mask value to exclude from coaddition.
715 
716  Returns
717  -------
718  stats : `lsst.pipe.base.Struct`
719  Statistics structure with the following fields:
720 
721  - ``statsCtrl``: Statistics control object for coadd
722  (`lsst.afw.math.StatisticsControl`)
723  - ``statsFlags``: Statistic for coadd (`lsst.afw.math.Property`)
724  """
725  if mask is None:
726  mask = self.getBadPixelMask()
727  statsCtrl = afwMath.StatisticsControl()
728  statsCtrl.setNumSigmaClip(self.config.sigmaClip)
729  statsCtrl.setNumIter(self.config.clipIter)
730  statsCtrl.setAndMask(mask)
731  statsCtrl.setNanSafe(True)
732  statsCtrl.setWeighted(True)
733  statsCtrl.setCalcErrorFromInputVariance(self.config.calcErrorFromInputVariance)
734  for plane, threshold in self.config.maskPropagationThresholds.items():
735  bit = afwImage.Mask.getMaskPlane(plane)
736  statsCtrl.setMaskPropagationThreshold(bit, threshold)
737  statsFlags = afwMath.stringToStatisticsProperty(self.config.statistic)
738  return pipeBase.Struct(ctrl=statsCtrl, flags=statsFlags)
739 
Property stringToStatisticsProperty(std::string const property)
Conversion function to switch a string to a Property (see Statistics.h)
Definition: Statistics.cc:747
Pass parameters to a Statistics object.
Definition: Statistics.h:93

◆ processResults()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.processResults (   self,
  coaddExposure,
  dataRef 
)
Interpolate over missing data and mask bright stars.

Parameters
----------
coaddExposure : `lsst.afw.image.Exposure`
    The coadded exposure to process.
dataRef : `lsst.daf.persistence.ButlerDataRef`
    Butler data reference for supplementary data.

Definition at line 540 of file assembleCoadd.py.

540  def processResults(self, coaddExposure, dataRef):
541  """Interpolate over missing data and mask bright stars.
542 
543  Parameters
544  ----------
545  coaddExposure : `lsst.afw.image.Exposure`
546  The coadded exposure to process.
547  dataRef : `lsst.daf.persistence.ButlerDataRef`
548  Butler data reference for supplementary data.
549  """
550  if self.config.doInterp:
551  self.interpImage.run(coaddExposure.getMaskedImage(), planeName="NO_DATA")
552  # The variance must be positive; work around for DM-3201.
553  varArray = coaddExposure.variance.array
554  with numpy.errstate(invalid="ignore"):
555  varArray[:] = numpy.where(varArray > 0, varArray, numpy.inf)
556 
557  if self.config.doMaskBrightObjects:
558  brightObjectMasks = self.readBrightObjectMasks(dataRef)
559  self.setBrightObjectMasks(coaddExposure, dataRef.dataId, brightObjectMasks)
560 

◆ readBrightObjectMasks()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.readBrightObjectMasks (   self,
  dataRef 
)
Retrieve the bright object masks.

Returns None on failure.

Parameters
----------
dataRef : `lsst.daf.persistence.butlerSubset.ButlerDataRef`
    A Butler dataRef.

Returns
-------
result : `lsst.daf.persistence.butlerSubset.ButlerDataRef`
    Bright object mask from the Butler object, or None if it cannot
    be retrieved.

Definition at line 1038 of file assembleCoadd.py.

1038  def readBrightObjectMasks(self, dataRef):
1039  """Retrieve the bright object masks.
1040 
1041  Returns None on failure.
1042 
1043  Parameters
1044  ----------
1045  dataRef : `lsst.daf.persistence.butlerSubset.ButlerDataRef`
1046  A Butler dataRef.
1047 
1048  Returns
1049  -------
1050  result : `lsst.daf.persistence.butlerSubset.ButlerDataRef`
1051  Bright object mask from the Butler object, or None if it cannot
1052  be retrieved.
1053  """
1054  try:
1055  return dataRef.get("brightObjectMask", immediate=True)
1056  except Exception as e:
1057  self.log.warn("Unable to read brightObjectMask for %s: %s", dataRef.dataId, e)
1058  return None
1059 

◆ removeMaskPlanes()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.removeMaskPlanes (   self,
  maskedImage 
)
Unset the mask of an image for mask planes specified in the config.

Parameters
----------
maskedImage : `lsst.afw.image.MaskedImage`
    The masked image to be modified.

Definition at line 939 of file assembleCoadd.py.

939  def removeMaskPlanes(self, maskedImage):
940  """Unset the mask of an image for mask planes specified in the config.
941 
942  Parameters
943  ----------
944  maskedImage : `lsst.afw.image.MaskedImage`
945  The masked image to be modified.
946  """
947  mask = maskedImage.getMask()
948  for maskPlane in self.config.removeMaskPlanes:
949  try:
950  mask &= ~mask.getPlaneBitMask(maskPlane)
952  self.log.debug("Unable to remove mask plane %s: no mask plane with that name was found.",
953  maskPlane)
954 
Reports invalid arguments.
Definition: Runtime.h:66

◆ run()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.run (   self,
  skyInfo,
  tempExpRefList,
  imageScalerList,
  weightList,
  altMaskList = None,
  mask = None,
  supplementaryData = None 
)
Assemble a coadd from input warps

Assemble the coadd using the provided list of coaddTempExps. Since
the full coadd covers a patch (a large area), the assembly is
performed over small areas on the image at a time in order to
conserve memory usage. Iterate over subregions within the outer
bbox of the patch using `assembleSubregion` to stack the corresponding
subregions from the coaddTempExps with the statistic specified.
Set the edge bits the coadd mask based on the weight map.

Parameters
----------
skyInfo : `lsst.pipe.base.Struct`
    Struct with geometric information about the patch.
tempExpRefList : `list`
    List of data references to Warps (previously called CoaddTempExps).
imageScalerList : `list`
    List of image scalers.
weightList : `list`
    List of weights
altMaskList : `list`, optional
    List of alternate masks to use rather than those stored with
    tempExp.
mask : `int`, optional
    Bit mask value to exclude from coaddition.
supplementaryData : lsst.pipe.base.Struct, optional
    Struct with additional data products needed to assemble coadd.
    Only used by subclasses that implement `makeSupplementaryData`
    and override `run`.

Returns
-------
result : `lsst.pipe.base.Struct`
   Result struct with components:

   - ``coaddExposure``: coadded exposure (``lsst.afw.image.Exposure``).
   - ``nImage``: exposure count image (``lsst.afw.image.Image``).

Definition at line 741 of file assembleCoadd.py.

741  altMaskList=None, mask=None, supplementaryData=None):
742  """Assemble a coadd from input warps
743 
744  Assemble the coadd using the provided list of coaddTempExps. Since
745  the full coadd covers a patch (a large area), the assembly is
746  performed over small areas on the image at a time in order to
747  conserve memory usage. Iterate over subregions within the outer
748  bbox of the patch using `assembleSubregion` to stack the corresponding
749  subregions from the coaddTempExps with the statistic specified.
750  Set the edge bits the coadd mask based on the weight map.
751 
752  Parameters
753  ----------
754  skyInfo : `lsst.pipe.base.Struct`
755  Struct with geometric information about the patch.
756  tempExpRefList : `list`
757  List of data references to Warps (previously called CoaddTempExps).
758  imageScalerList : `list`
759  List of image scalers.
760  weightList : `list`
761  List of weights
762  altMaskList : `list`, optional
763  List of alternate masks to use rather than those stored with
764  tempExp.
765  mask : `int`, optional
766  Bit mask value to exclude from coaddition.
767  supplementaryData : lsst.pipe.base.Struct, optional
768  Struct with additional data products needed to assemble coadd.
769  Only used by subclasses that implement `makeSupplementaryData`
770  and override `run`.
771 
772  Returns
773  -------
774  result : `lsst.pipe.base.Struct`
775  Result struct with components:
776 
777  - ``coaddExposure``: coadded exposure (``lsst.afw.image.Exposure``).
778  - ``nImage``: exposure count image (``lsst.afw.image.Image``).
779  """
780  tempExpName = self.getTempExpDatasetName(self.warpType)
781  self.log.info("Assembling %s %s", len(tempExpRefList), tempExpName)
782  stats = self.prepareStats(mask=mask)
783 
784  if altMaskList is None:
785  altMaskList = [None]*len(tempExpRefList)
786 
787  coaddExposure = afwImage.ExposureF(skyInfo.bbox, skyInfo.wcs)
788  coaddExposure.setPhotoCalib(self.scaleZeroPoint.getPhotoCalib())
789  coaddExposure.getInfo().setCoaddInputs(self.inputRecorder.makeCoaddInputs())
790  self.assembleMetadata(coaddExposure, tempExpRefList, weightList)
791  coaddMaskedImage = coaddExposure.getMaskedImage()
792  subregionSizeArr = self.config.subregionSize
793  subregionSize = geom.Extent2I(subregionSizeArr[0], subregionSizeArr[1])
794  # if nImage is requested, create a zero one which can be passed to assembleSubregion
795  if self.config.doNImage:
796  nImage = afwImage.ImageU(skyInfo.bbox)
797  else:
798  nImage = None
799  for subBBox in self._subBBoxIter(skyInfo.bbox, subregionSize):
800  try:
801  self.assembleSubregion(coaddExposure, subBBox, tempExpRefList, imageScalerList,
802  weightList, altMaskList, stats.flags, stats.ctrl,
803  nImage=nImage)
804  except Exception as e:
805  self.log.fatal("Cannot compute coadd %s: %s", subBBox, e)
806 
807  self.setInexactPsf(coaddMaskedImage.getMask())
808  # Despite the name, the following doesn't really deal with "EDGE" pixels: it identifies
809  # pixels that didn't receive any unmasked inputs (as occurs around the edge of the field).
810  coaddUtils.setCoaddEdgeBits(coaddMaskedImage.getMask(), coaddMaskedImage.getVariance())
811  return pipeBase.Struct(coaddExposure=coaddExposure, nImage=nImage)
812 
void setCoaddEdgeBits(lsst::afw::image::Mask< lsst::afw::image::MaskPixel > &coaddMask, lsst::afw::image::Image< WeightPixelT > const &weightMap)
set edge bits of coadd mask based on weight map

◆ runDataRef()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.runDataRef (   self,
  dataRef,
  selectDataList = None,
  warpRefList = None 
)
Assemble a coadd from a set of Warps.

Pipebase.CmdlineTask entry point to Coadd a set of Warps.
Compute weights to be applied to each Warp and
find scalings to match the photometric zeropoint to a reference Warp.
Assemble the Warps using `run`. Interpolate over NaNs and
optionally write the coadd to disk. Return the coadded exposure.

Parameters
----------
dataRef : `lsst.daf.persistence.butlerSubset.ButlerDataRef`
    Data reference defining the patch for coaddition and the
    reference Warp (if ``config.autoReference=False``).
    Used to access the following data products:
    - ``self.config.coaddName + "Coadd_skyMap"``
    - ``self.config.coaddName + "Coadd_ + <warpType> + "Warp"`` (optionally)
    - ``self.config.coaddName + "Coadd"``
selectDataList : `list`
    List of data references to Calexps. Data to be coadded will be
    selected from this list based on overlap with the patch defined
    by dataRef, grouped by visit, and converted to a list of data
    references to warps.
warpRefList : `list`
    List of data references to Warps to be coadded.
    Note: `warpRefList` is just the new name for `tempExpRefList`.

Returns
-------
retStruct : `lsst.pipe.base.Struct`
   Result struct with components:

   - ``coaddExposure``: coadded exposure (``Exposure``).
   - ``nImage``: exposure count image (``Image``).

Definition at line 466 of file assembleCoadd.py.

466  def runDataRef(self, dataRef, selectDataList=None, warpRefList=None):
467  """Assemble a coadd from a set of Warps.
468 
469  Pipebase.CmdlineTask entry point to Coadd a set of Warps.
470  Compute weights to be applied to each Warp and
471  find scalings to match the photometric zeropoint to a reference Warp.
472  Assemble the Warps using `run`. Interpolate over NaNs and
473  optionally write the coadd to disk. Return the coadded exposure.
474 
475  Parameters
476  ----------
477  dataRef : `lsst.daf.persistence.butlerSubset.ButlerDataRef`
478  Data reference defining the patch for coaddition and the
479  reference Warp (if ``config.autoReference=False``).
480  Used to access the following data products:
481  - ``self.config.coaddName + "Coadd_skyMap"``
482  - ``self.config.coaddName + "Coadd_ + <warpType> + "Warp"`` (optionally)
483  - ``self.config.coaddName + "Coadd"``
484  selectDataList : `list`
485  List of data references to Calexps. Data to be coadded will be
486  selected from this list based on overlap with the patch defined
487  by dataRef, grouped by visit, and converted to a list of data
488  references to warps.
489  warpRefList : `list`
490  List of data references to Warps to be coadded.
491  Note: `warpRefList` is just the new name for `tempExpRefList`.
492 
493  Returns
494  -------
495  retStruct : `lsst.pipe.base.Struct`
496  Result struct with components:
497 
498  - ``coaddExposure``: coadded exposure (``Exposure``).
499  - ``nImage``: exposure count image (``Image``).
500  """
501  if selectDataList and warpRefList:
502  raise RuntimeError("runDataRef received both a selectDataList and warpRefList, "
503  "and which to use is ambiguous. Please pass only one.")
504 
505  skyInfo = self.getSkyInfo(dataRef)
506  if warpRefList is None:
507  calExpRefList = self.selectExposures(dataRef, skyInfo, selectDataList=selectDataList)
508  if len(calExpRefList) == 0:
509  self.log.warn("No exposures to coadd")
510  return
511  self.log.info("Coadding %d exposures", len(calExpRefList))
512 
513  warpRefList = self.getTempExpRefList(dataRef, calExpRefList)
514 
515  inputData = self.prepareInputs(warpRefList)
516  self.log.info("Found %d %s", len(inputData.tempExpRefList),
517  self.getTempExpDatasetName(self.warpType))
518  if len(inputData.tempExpRefList) == 0:
519  self.log.warn("No coadd temporary exposures found")
520  return
521 
522  supplementaryData = self.makeSupplementaryData(dataRef, warpRefList=inputData.tempExpRefList)
523 
524  retStruct = self.run(skyInfo, inputData.tempExpRefList, inputData.imageScalerList,
525  inputData.weightList, supplementaryData=supplementaryData)
526 
527  self.processResults(retStruct.coaddExposure, dataRef)
528  if self.config.doWrite:
529  if self.getCoaddDatasetName(self.warpType) == "deepCoadd" and self.config.hasFakes:
530  coaddDatasetName = "fakes_" + self.getCoaddDatasetName(self.warpType)
531  else:
532  coaddDatasetName = self.getCoaddDatasetName(self.warpType)
533  self.log.info("Persisting %s" % coaddDatasetName)
534  dataRef.put(retStruct.coaddExposure, coaddDatasetName)
535  if self.config.doNImage and retStruct.nImage is not None:
536  dataRef.put(retStruct.nImage, self.getCoaddDatasetName(self.warpType) + '_nImage')
537 
538  return retStruct
539 

◆ 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 114 of file coaddBase.py.

114  def selectExposures(self, patchRef, skyInfo=None, selectDataList=[]):
115  """!
116  @brief Select exposures to coadd
117 
118  Get the corners of the bbox supplied in skyInfo using @ref geom.Box2D and convert the pixel
119  positions of the bbox corners to sky coordinates using @ref skyInfo.wcs.pixelToSky. Use the
120  @ref WcsSelectImagesTask_ "WcsSelectImagesTask" to select exposures that lie inside the patch
121  indicated by the dataRef.
122 
123  @param[in] patchRef data reference for sky map patch. Must include keys "tract", "patch",
124  plus the camera-specific filter key (e.g. "filter" or "band")
125  @param[in] skyInfo geometry for the patch; output from getSkyInfo
126  @return a list of science exposures to coadd, as butler data references
127  """
128  if skyInfo is None:
129  skyInfo = self.getSkyInfo(patchRef)
130  cornerPosList = geom.Box2D(skyInfo.bbox).getCorners()
131  coordList = [skyInfo.wcs.pixelToSky(pos) for pos in cornerPosList]
132  return self.select.runDataRef(patchRef, coordList, selectDataList=selectDataList).dataRefList
133 
A floating-point coordinate rectangle geometry.
Definition: Box.h:305

◆ setBrightObjectMasks()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.setBrightObjectMasks (   self,
  exposure,
  dataId,
  brightObjectMasks 
)
Set the bright object masks.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure under consideration.
dataId : `lsst.daf.persistence.dataId`
    Data identifier dict for patch.
brightObjectMasks : `lsst.afw.table`
    Table of bright objects to mask.

Definition at line 1060 of file assembleCoadd.py.

1060  def setBrightObjectMasks(self, exposure, dataId, brightObjectMasks):
1061  """Set the bright object masks.
1062 
1063  Parameters
1064  ----------
1065  exposure : `lsst.afw.image.Exposure`
1066  Exposure under consideration.
1067  dataId : `lsst.daf.persistence.dataId`
1068  Data identifier dict for patch.
1069  brightObjectMasks : `lsst.afw.table`
1070  Table of bright objects to mask.
1071  """
1072 
1073  if brightObjectMasks is None:
1074  self.log.warn("Unable to apply bright object mask: none supplied")
1075  return
1076  self.log.info("Applying %d bright object masks to %s", len(brightObjectMasks), dataId)
1077  mask = exposure.getMaskedImage().getMask()
1078  wcs = exposure.getWcs()
1079  plateScale = wcs.getPixelScale().asArcseconds()
1080 
1081  for rec in brightObjectMasks:
1082  center = geom.PointI(wcs.skyToPixel(rec.getCoord()))
1083  if rec["type"] == "box":
1084  assert rec["angle"] == 0.0, ("Angle != 0 for mask object %s" % rec["id"])
1085  width = rec["width"].asArcseconds()/plateScale # convert to pixels
1086  height = rec["height"].asArcseconds()/plateScale # convert to pixels
1087 
1088  halfSize = geom.ExtentI(0.5*width, 0.5*height)
1089  bbox = geom.Box2I(center - halfSize, center + halfSize)
1090 
1091  bbox = geom.BoxI(geom.PointI(int(center[0] - 0.5*width), int(center[1] - 0.5*height)),
1092  geom.PointI(int(center[0] + 0.5*width), int(center[1] + 0.5*height)))
1093  spans = afwGeom.SpanSet(bbox)
1094  elif rec["type"] == "circle":
1095  radius = int(rec["radius"].asArcseconds()/plateScale) # convert to pixels
1096  spans = afwGeom.SpanSet.fromShape(radius, offset=center)
1097  else:
1098  self.log.warn("Unexpected region type %s at %s" % rec["type"], center)
1099  continue
1100  spans.clippedTo(mask.getBBox()).setMask(mask, self.brightObjectBitmask)
1101 
A compact representation of a collection of pixels.
Definition: SpanSet.h:77
An integer coordinate rectangle.
Definition: Box.h:54

◆ setInexactPsf()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.setInexactPsf (   self,
  mask 
)
Set INEXACT_PSF mask plane.

If any of the input images isn't represented in the coadd (due to
clipped pixels or chip gaps), the `CoaddPsf` will be inexact. Flag
these pixels.

Parameters
----------
mask : `lsst.afw.image.Mask`
    Coadded exposure's mask, modified in-place.

Definition at line 1102 of file assembleCoadd.py.

1102  def setInexactPsf(self, mask):
1103  """Set INEXACT_PSF mask plane.
1104 
1105  If any of the input images isn't represented in the coadd (due to
1106  clipped pixels or chip gaps), the `CoaddPsf` will be inexact. Flag
1107  these pixels.
1108 
1109  Parameters
1110  ----------
1111  mask : `lsst.afw.image.Mask`
1112  Coadded exposure's mask, modified in-place.
1113  """
1114  mask.addMaskPlane("INEXACT_PSF")
1115  inexactPsf = mask.getPlaneBitMask("INEXACT_PSF")
1116  sensorEdge = mask.getPlaneBitMask("SENSOR_EDGE") # chip edges (so PSF is discontinuous)
1117  clipped = mask.getPlaneBitMask("CLIPPED") # pixels clipped from coadd
1118  rejected = mask.getPlaneBitMask("REJECTED") # pixels rejected from coadd due to masks
1119  array = mask.getArray()
1120  selected = array & (sensorEdge | clipped | rejected) > 0
1121  array[selected] |= inexactPsf
1122 

◆ setRejectedMaskMapping()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.setRejectedMaskMapping (   statsCtrl)
static
Map certain mask planes of the warps to new planes for the coadd.

If a pixel is rejected due to a mask value other than EDGE, NO_DATA,
or CLIPPED, set it to REJECTED on the coadd.
If a pixel is rejected due to EDGE, set the coadd pixel to SENSOR_EDGE.
If a pixel is rejected due to CLIPPED, set the coadd pixel to CLIPPED.

Parameters
----------
statsCtrl : `lsst.afw.math.StatisticsControl`
    Statistics control object for coadd

Returns
-------
maskMap : `list` of `tuple` of `int`
    A list of mappings of mask planes of the warped exposures to
    mask planes of the coadd.

Definition at line 956 of file assembleCoadd.py.

956  def setRejectedMaskMapping(statsCtrl):
957  """Map certain mask planes of the warps to new planes for the coadd.
958 
959  If a pixel is rejected due to a mask value other than EDGE, NO_DATA,
960  or CLIPPED, set it to REJECTED on the coadd.
961  If a pixel is rejected due to EDGE, set the coadd pixel to SENSOR_EDGE.
962  If a pixel is rejected due to CLIPPED, set the coadd pixel to CLIPPED.
963 
964  Parameters
965  ----------
966  statsCtrl : `lsst.afw.math.StatisticsControl`
967  Statistics control object for coadd
968 
969  Returns
970  -------
971  maskMap : `list` of `tuple` of `int`
972  A list of mappings of mask planes of the warped exposures to
973  mask planes of the coadd.
974  """
975  edge = afwImage.Mask.getPlaneBitMask("EDGE")
976  noData = afwImage.Mask.getPlaneBitMask("NO_DATA")
977  clipped = afwImage.Mask.getPlaneBitMask("CLIPPED")
978  toReject = statsCtrl.getAndMask() & (~noData) & (~edge) & (~clipped)
979  maskMap = [(toReject, afwImage.Mask.getPlaneBitMask("REJECTED")),
980  (edge, afwImage.Mask.getPlaneBitMask("SENSOR_EDGE")),
981  (clipped, clipped)]
982  return maskMap
983 

◆ shrinkValidPolygons()

def lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.shrinkValidPolygons (   self,
  coaddInputs 
)
Shrink coaddInputs' ccds' ValidPolygons in place.

Either modify each ccd's validPolygon in place, or if CoaddInputs
does not have a validPolygon, create one from its bbox.

Parameters
----------
coaddInputs : `lsst.afw.image.coaddInputs`
    Original mask.

Definition at line 1016 of file assembleCoadd.py.

1016  def shrinkValidPolygons(self, coaddInputs):
1017  """Shrink coaddInputs' ccds' ValidPolygons in place.
1018 
1019  Either modify each ccd's validPolygon in place, or if CoaddInputs
1020  does not have a validPolygon, create one from its bbox.
1021 
1022  Parameters
1023  ----------
1024  coaddInputs : `lsst.afw.image.coaddInputs`
1025  Original mask.
1026 
1027  """
1028  for ccd in coaddInputs.ccds:
1029  polyOrig = ccd.getValidPolygon()
1030  validPolyBBox = polyOrig.getBBox() if polyOrig else ccd.getBBox()
1031  validPolyBBox.grow(-self.config.matchingKernelSize//2)
1032  if polyOrig:
1033  validPolygon = polyOrig.intersectionSingle(validPolyBBox)
1034  else:
1035  validPolygon = afwGeom.polygon.Polygon(geom.Box2D(validPolyBBox))
1036  ccd.setValidPolygon(validPolygon)
1037 
A floating-point coordinate rectangle geometry.
Definition: Box.h:305

Member Data Documentation

◆ brightObjectBitmask

lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.brightObjectBitmask

Definition at line 360 of file assembleCoadd.py.

◆ ConfigClass

lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.ConfigClass = AssembleCoaddConfig
static

Definition at line 342 of file assembleCoadd.py.

◆ RunnerClass

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

Definition at line 107 of file coaddBase.py.

◆ warpType

lsst.pipe.tasks.assembleCoadd.AssembleCoaddTask.warpType

Definition at line 366 of file assembleCoadd.py.


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