LSST Applications  21.0.0+04719a4bac,21.0.0-1-ga51b5d4+f5e6047307,21.0.0-11-g2b59f77+a9c1acf22d,21.0.0-11-ga42c5b2+86977b0b17,21.0.0-12-gf4ce030+76814010d2,21.0.0-13-g1721dae+760e7a6536,21.0.0-13-g3a573fe+768d78a30a,21.0.0-15-g5a7caf0+f21cbc5713,21.0.0-16-g0fb55c1+b60e2d390c,21.0.0-19-g4cded4ca+71a93a33c0,21.0.0-2-g103fe59+bb20972958,21.0.0-2-g45278ab+04719a4bac,21.0.0-2-g5242d73+3ad5d60fb1,21.0.0-2-g7f82c8f+8babb168e8,21.0.0-2-g8f08a60+06509c8b61,21.0.0-2-g8faa9b5+616205b9df,21.0.0-2-ga326454+8babb168e8,21.0.0-2-gde069b7+5e4aea9c2f,21.0.0-2-gecfae73+1d3a86e577,21.0.0-2-gfc62afb+3ad5d60fb1,21.0.0-25-g1d57be3cd+e73869a214,21.0.0-3-g357aad2+ed88757d29,21.0.0-3-g4a4ce7f+3ad5d60fb1,21.0.0-3-g4be5c26+3ad5d60fb1,21.0.0-3-g65f322c+e0b24896a3,21.0.0-3-g7d9da8d+616205b9df,21.0.0-3-ge02ed75+a9c1acf22d,21.0.0-4-g591bb35+a9c1acf22d,21.0.0-4-g65b4814+b60e2d390c,21.0.0-4-gccdca77+0de219a2bc,21.0.0-4-ge8a399c+6c55c39e83,21.0.0-5-gd00fb1e+05fce91b99,21.0.0-6-gc675373+3ad5d60fb1,21.0.0-64-g1122c245+4fb2b8f86e,21.0.0-7-g04766d7+cd19d05db2,21.0.0-7-gdf92d54+04719a4bac,21.0.0-8-g5674e7b+d1bd76f71f,master-gac4afde19b+a9c1acf22d,w.2021.13
LSST Data Management Base Package
Classes | Functions | Variables
lsst.pipe.tasks.assembleCoadd Namespace Reference

Classes

class  AssembleCoaddConnections
 
class  AssembleCoaddDataIdContainer
 
class  SafeClipAssembleCoaddConfig
 
class  SafeClipAssembleCoaddTask
 
class  CompareWarpAssembleCoaddConnections
 
class  CompareWarpAssembleCoaddConfig
 
class  CompareWarpAssembleCoaddTask
 

Functions

def processResults (self, coaddExposure, brightObjectMasks=None, dataId=None)
 
def makeSupplementaryData (self, dataRef, selectDataList=None, warpRefList=None)
 
def makeSupplementaryDataGen3 (self, butlerQC, inputRefs, outputRefs)
 
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, brightObjectMasks, dataId=None)
 
def setInexactPsf (self, mask)
 
def filterWarps (self, inputs, goodVisits)
 
def countMaskFromFootprint (mask, footprint, bitmask, ignoreMask)
 

Variables

 id
 
 KEY
 
 patch
 
 tract
 
 filter
 
 visit
 
 ccd
 
 skyInfo
 
 calExpRefList
 
 warpRefList
 
 inputData
 
 supplementaryData
 
 retStruct
 
 brightObjects
 
 coaddDatasetName
 
 warpType
 

Function Documentation

◆ applyAltMaskPlanes()

def lsst.pipe.tasks.assembleCoadd.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 1003 of file assembleCoadd.py.

1003  def applyAltMaskPlanes(self, mask, altMaskSpans):
1004  """Apply in place alt mask formatted as SpanSets to a mask.
1005 
1006  Parameters
1007  ----------
1008  mask : `lsst.afw.image.Mask`
1009  Original mask.
1010  altMaskSpans : `dict`
1011  SpanSet lists to apply. Each element contains the new mask
1012  plane name (e.g. "CLIPPED and/or "NO_DATA") as the key,
1013  and list of SpanSets to apply to the mask.
1014 
1015  Returns
1016  -------
1017  mask : `lsst.afw.image.Mask`
1018  Updated mask.
1019  """
1020  if self.config.doUsePsfMatchedPolygons:
1021  if ("NO_DATA" in altMaskSpans) and ("NO_DATA" in self.config.badMaskPlanes):
1022  # Clear away any other masks outside the validPolygons. These pixels are no longer
1023  # contributing to inexact PSFs, and will still be rejected because of NO_DATA
1024  # self.config.doUsePsfMatchedPolygons should be True only in CompareWarpAssemble
1025  # This mask-clearing step must only occur *before* applying the new masks below
1026  for spanSet in altMaskSpans['NO_DATA']:
1027  spanSet.clippedTo(mask.getBBox()).clearMask(mask, self.getBadPixelMask())
1028 
1029  for plane, spanSetList in altMaskSpans.items():
1030  maskClipValue = mask.addMaskPlane(plane)
1031  for spanSet in spanSetList:
1032  spanSet.clippedTo(mask.getBBox()).setMask(mask, 2**maskClipValue)
1033  return mask
1034 
def applyAltMaskPlanes(self, mask, altMaskSpans)

◆ assembleMetadata()

def lsst.pipe.tasks.assembleCoadd.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 818 of file assembleCoadd.py.

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

◆ assembleSubregion()

def lsst.pipe.tasks.assembleCoadd.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 881 of file assembleCoadd.py.

882  altMaskList, statsFlags, statsCtrl, nImage=None):
883  """Assemble the coadd for a sub-region.
884 
885  For each coaddTempExp, check for (and swap in) an alternative mask
886  if one is passed. Remove mask planes listed in
887  `config.removeMaskPlanes`. Finally, stack the actual exposures using
888  `lsst.afw.math.statisticsStack` with the statistic specified by
889  statsFlags. Typically, the statsFlag will be one of lsst.afw.math.MEAN for
890  a mean-stack or `lsst.afw.math.MEANCLIP` for outlier rejection using
891  an N-sigma clipped mean where N and iterations are specified by
892  statsCtrl. Assign the stacked subregion back to the coadd.
893 
894  Parameters
895  ----------
896  coaddExposure : `lsst.afw.image.Exposure`
897  The target exposure for the coadd.
898  bbox : `lsst.geom.Box`
899  Sub-region to coadd.
900  tempExpRefList : `list`
901  List of data reference to tempExp.
902  imageScalerList : `list`
903  List of image scalers.
904  weightList : `list`
905  List of weights.
906  altMaskList : `list`
907  List of alternate masks to use rather than those stored with
908  tempExp, or None. Each element is dict with keys = mask plane
909  name to which to add the spans.
910  statsFlags : `lsst.afw.math.Property`
911  Property object for statistic for coadd.
912  statsCtrl : `lsst.afw.math.StatisticsControl`
913  Statistics control object for coadd.
914  nImage : `lsst.afw.image.ImageU`, optional
915  Keeps track of exposure count for each pixel.
916  """
917  self.log.debug("Computing coadd over %s", bbox)
918  tempExpName = self.getTempExpDatasetName(self.warpType)
919  coaddExposure.mask.addMaskPlane("REJECTED")
920  coaddExposure.mask.addMaskPlane("CLIPPED")
921  coaddExposure.mask.addMaskPlane("SENSOR_EDGE")
922  maskMap = self.setRejectedMaskMapping(statsCtrl)
923  clipped = afwImage.Mask.getPlaneBitMask("CLIPPED")
924  maskedImageList = []
925  if nImage is not None:
926  subNImage = afwImage.ImageU(bbox.getWidth(), bbox.getHeight())
927  for tempExpRef, imageScaler, altMask in zip(tempExpRefList, imageScalerList, altMaskList):
928 
929  if isinstance(tempExpRef, DeferredDatasetHandle):
930  # Gen 3 API
931  exposure = tempExpRef.get(parameters={'bbox': bbox})
932  else:
933  # Gen 2 API. Delete this when Gen 2 retired
934  exposure = tempExpRef.get(tempExpName + "_sub", bbox=bbox)
935 
936  maskedImage = exposure.getMaskedImage()
937  mask = maskedImage.getMask()
938  if altMask is not None:
939  self.applyAltMaskPlanes(mask, altMask)
940  imageScaler.scaleMaskedImage(maskedImage)
941 
942  # Add 1 for each pixel which is not excluded by the exclude mask.
943  # In legacyCoadd, pixels may also be excluded by afwMath.statisticsStack.
944  if nImage is not None:
945  subNImage.getArray()[maskedImage.getMask().getArray() & statsCtrl.getAndMask() == 0] += 1
946  if self.config.removeMaskPlanes:
947  self.removeMaskPlanes(maskedImage)
948  maskedImageList.append(maskedImage)
949 
950  with self.timer("stack"):
951  coaddSubregion = afwMath.statisticsStack(maskedImageList, statsFlags, statsCtrl, weightList,
952  clipped, # also set output to CLIPPED if sigma-clipped
953  maskMap)
954  coaddExposure.maskedImage.assign(coaddSubregion, bbox)
955  if nImage is not None:
956  nImage.assign(subNImage, bbox)
957 
std::shared_ptr< lsst::afw::image::Image< PixelT > > statisticsStack(std::vector< std::shared_ptr< lsst::afw::image::Image< PixelT >>> &images, Property flags, StatisticsControl const &sctrl=StatisticsControl(), std::vector< lsst::afw::image::VariancePixel > const &wvector=std::vector< lsst::afw::image::VariancePixel >(0))
A function to compute some statistics of a stack of Images.

◆ countMaskFromFootprint()

def lsst.pipe.tasks.assembleCoadd.countMaskFromFootprint (   mask,
  footprint,
  bitmask,
  ignoreMask 
)
Function to count the number of pixels with a specific mask in a
footprint.

Find the intersection of mask & footprint. Count all pixels in the mask
that are in the intersection that have bitmask set but do not have
ignoreMask set. Return the count.

Parameters
----------
mask : `lsst.afw.image.Mask`
    Mask to define intersection region by.
footprint : `lsst.afw.detection.Footprint`
    Footprint to define the intersection region by.
bitmask
    Specific mask that we wish to count the number of occurances of.
ignoreMask
    Pixels to not consider.

Returns
-------
result : `int`
    Count of number of pixels in footprint with specified mask.

Definition at line 1238 of file assembleCoadd.py.

1238 def countMaskFromFootprint(mask, footprint, bitmask, ignoreMask):
1239  """Function to count the number of pixels with a specific mask in a
1240  footprint.
1241 
1242  Find the intersection of mask & footprint. Count all pixels in the mask
1243  that are in the intersection that have bitmask set but do not have
1244  ignoreMask set. Return the count.
1245 
1246  Parameters
1247  ----------
1248  mask : `lsst.afw.image.Mask`
1249  Mask to define intersection region by.
1250  footprint : `lsst.afw.detection.Footprint`
1251  Footprint to define the intersection region by.
1252  bitmask
1253  Specific mask that we wish to count the number of occurances of.
1254  ignoreMask
1255  Pixels to not consider.
1256 
1257  Returns
1258  -------
1259  result : `int`
1260  Count of number of pixels in footprint with specified mask.
1261  """
1262  bbox = footprint.getBBox()
1263  bbox.clip(mask.getBBox(afwImage.PARENT))
1264  fp = afwImage.Mask(bbox)
1265  subMask = mask.Factory(mask, bbox, afwImage.PARENT)
1266  footprint.spans.setMask(fp, bitmask)
1267  return numpy.logical_and((subMask.getArray() & fp.getArray()) > 0,
1268  (subMask.getArray() & ignoreMask) == 0).sum()
1269 
1270 
Represent a 2-dimensional array of bitmask pixels.
Definition: Mask.h:77
def countMaskFromFootprint(mask, footprint, bitmask, ignoreMask)

◆ filterWarps()

def lsst.pipe.tasks.assembleCoadd.filterWarps (   self,
  inputs,
  goodVisits 
)
Return list of only inputRefs with visitId in goodVisits ordered by goodVisit

Parameters
----------
inputs : list
    List of `lsst.pipe.base.connections.DeferredDatasetRef` with dataId containing visit
goodVisit : `dict`
    Dictionary with good visitIds as the keys. Value ignored.

Returns:
--------
filteredInputs : `list`
    Filtered and sorted list of `lsst.pipe.base.connections.DeferredDatasetRef`

Definition at line 1188 of file assembleCoadd.py.

1188  def filterWarps(self, inputs, goodVisits):
1189  """Return list of only inputRefs with visitId in goodVisits ordered by goodVisit
1190 
1191  Parameters
1192  ----------
1193  inputs : list
1194  List of `lsst.pipe.base.connections.DeferredDatasetRef` with dataId containing visit
1195  goodVisit : `dict`
1196  Dictionary with good visitIds as the keys. Value ignored.
1197 
1198  Returns:
1199  --------
1200  filteredInputs : `list`
1201  Filtered and sorted list of `lsst.pipe.base.connections.DeferredDatasetRef`
1202  """
1203  inputWarpDict = {inputRef.ref.dataId['visit']: inputRef for inputRef in inputs}
1204  filteredInputs = []
1205  for visit in goodVisits.keys():
1206  filteredInputs.append(inputWarpDict[visit])
1207  return filteredInputs
1208 
1209 
def filterWarps(self, inputs, goodVisits)

◆ getTempExpRefList()

def lsst.pipe.tasks.assembleCoadd.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 605 of file assembleCoadd.py.

605  def getTempExpRefList(self, patchRef, calExpRefList):
606  """Generate list data references corresponding to warped exposures
607  that lie within the patch to be coadded.
608 
609  Parameters
610  ----------
611  patchRef : `dataRef`
612  Data reference for patch.
613  calExpRefList : `list`
614  List of data references for input calexps.
615 
616  Returns
617  -------
618  tempExpRefList : `list`
619  List of Warp/CoaddTempExp data references.
620  """
621  butler = patchRef.getButler()
622  groupData = groupPatchExposures(patchRef, calExpRefList, self.getCoaddDatasetName(self.warpType),
623  self.getTempExpDatasetName(self.warpType))
624  tempExpRefList = [getGroupDataRef(butler, self.getTempExpDatasetName(self.warpType),
625  g, groupData.keys) for
626  g in groupData.groups.keys()]
627  return tempExpRefList
628 
def getTempExpRefList(self, patchRef, calExpRefList)
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.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` (optional)
    Optional List of data references to Calexps.
warpRefList : `list` (optional)
    Optional List of data references to Warps.

Definition at line 562 of file assembleCoadd.py.

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

◆ makeSupplementaryDataGen3()

def lsst.pipe.tasks.assembleCoadd.makeSupplementaryDataGen3 (   self,
  butlerQC,
  inputRefs,
  outputRefs 
)
Make additional inputs to run() specific to subclasses (Gen3)

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

Parameters
----------
butlerQC : `lsst.pipe.base.ButlerQuantumContext`
    Gen3 Butler object for fetching additional data products before
    running the Task specialized for quantum being processed
inputRefs : `lsst.pipe.base.InputQuantizedConnection`
    Attributes are the names of the connections describing input dataset types.
    Values are DatasetRefs that task consumes for corresponding dataset type.
    DataIds are guaranteed to match data objects in ``inputData``.
outputRefs : `lsst.pipe.base.OutputQuantizedConnection`
    Attributes are the names of the connections describing output dataset types.
    Values are DatasetRefs that task is to produce
    for corresponding dataset type.

Definition at line 581 of file assembleCoadd.py.

581  def makeSupplementaryDataGen3(self, butlerQC, inputRefs, outputRefs):
582  """Make additional inputs to run() specific to subclasses (Gen3)
583 
584  Duplicates interface of `runQuantum` method.
585  Available to be implemented by subclasses only if they need the
586  coadd dataRef for performing preliminary processing before
587  assembling the coadd.
588 
589  Parameters
590  ----------
591  butlerQC : `lsst.pipe.base.ButlerQuantumContext`
592  Gen3 Butler object for fetching additional data products before
593  running the Task specialized for quantum being processed
594  inputRefs : `lsst.pipe.base.InputQuantizedConnection`
595  Attributes are the names of the connections describing input dataset types.
596  Values are DatasetRefs that task consumes for corresponding dataset type.
597  DataIds are guaranteed to match data objects in ``inputData``.
598  outputRefs : `lsst.pipe.base.OutputQuantizedConnection`
599  Attributes are the names of the connections describing output dataset types.
600  Values are DatasetRefs that task is to produce
601  for corresponding dataset type.
602  """
603  return pipeBase.Struct()
604 
def makeSupplementaryDataGen3(self, butlerQC, inputRefs, outputRefs)

◆ prepareInputs()

def lsst.pipe.tasks.assembleCoadd.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 629 of file assembleCoadd.py.

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

◆ prepareStats()

def lsst.pipe.tasks.assembleCoadd.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 704 of file assembleCoadd.py.

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

◆ processResults()

def lsst.pipe.tasks.assembleCoadd.processResults (   self,
  coaddExposure,
  brightObjectMasks = None,
  dataId = None 
)
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 542 of file assembleCoadd.py.

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

◆ readBrightObjectMasks()

def lsst.pipe.tasks.assembleCoadd.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 1057 of file assembleCoadd.py.

1057  def readBrightObjectMasks(self, dataRef):
1058  """Retrieve the bright object masks.
1059 
1060  Returns None on failure.
1061 
1062  Parameters
1063  ----------
1064  dataRef : `lsst.daf.persistence.butlerSubset.ButlerDataRef`
1065  A Butler dataRef.
1066 
1067  Returns
1068  -------
1069  result : `lsst.daf.persistence.butlerSubset.ButlerDataRef`
1070  Bright object mask from the Butler object, or None if it cannot
1071  be retrieved.
1072  """
1073  try:
1074  return dataRef.get(datasetType="brightObjectMask", immediate=True)
1075  except Exception as e:
1076  self.log.warn("Unable to read brightObjectMask for %s: %s", dataRef.dataId, e)
1077  return None
1078 
def readBrightObjectMasks(self, dataRef)

◆ removeMaskPlanes()

def lsst.pipe.tasks.assembleCoadd.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 958 of file assembleCoadd.py.

958  def removeMaskPlanes(self, maskedImage):
959  """Unset the mask of an image for mask planes specified in the config.
960 
961  Parameters
962  ----------
963  maskedImage : `lsst.afw.image.MaskedImage`
964  The masked image to be modified.
965  """
966  mask = maskedImage.getMask()
967  for maskPlane in self.config.removeMaskPlanes:
968  try:
969  mask &= ~mask.getPlaneBitMask(maskPlane)
971  self.log.debug("Unable to remove mask plane %s: no mask plane with that name was found.",
972  maskPlane)
973 
Reports invalid arguments.
Definition: Runtime.h:66
def removeMaskPlanes(self, maskedImage)

◆ run()

def lsst.pipe.tasks.assembleCoadd.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``), if requested.
   - ``warpRefList``: input list of refs to the warps (
                      ``lsst.daf.butler.DeferredDatasetHandle`` or
                      ``lsst.daf.persistence.ButlerDataRef``)
                      (unmodified)
   - ``imageScalerList``: input list of image scalers (unmodified)
   - ``weightList``: input list of weights (unmodified)

Definition at line 737 of file assembleCoadd.py.

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

◆ setBrightObjectMasks()

def lsst.pipe.tasks.assembleCoadd.setBrightObjectMasks (   self,
  exposure,
  brightObjectMasks,
  dataId = None 
)
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 1079 of file assembleCoadd.py.

1079  def setBrightObjectMasks(self, exposure, brightObjectMasks, dataId=None):
1080  """Set the bright object masks.
1081 
1082  Parameters
1083  ----------
1084  exposure : `lsst.afw.image.Exposure`
1085  Exposure under consideration.
1086  dataId : `lsst.daf.persistence.dataId`
1087  Data identifier dict for patch.
1088  brightObjectMasks : `lsst.afw.table`
1089  Table of bright objects to mask.
1090  """
1091 
1092  if brightObjectMasks is None:
1093  self.log.warn("Unable to apply bright object mask: none supplied")
1094  return
1095  self.log.info("Applying %d bright object masks to %s", len(brightObjectMasks), dataId)
1096  mask = exposure.getMaskedImage().getMask()
1097  wcs = exposure.getWcs()
1098  plateScale = wcs.getPixelScale().asArcseconds()
1099 
1100  for rec in brightObjectMasks:
1101  center = geom.PointI(wcs.skyToPixel(rec.getCoord()))
1102  if rec["type"] == "box":
1103  assert rec["angle"] == 0.0, ("Angle != 0 for mask object %s" % rec["id"])
1104  width = rec["width"].asArcseconds()/plateScale # convert to pixels
1105  height = rec["height"].asArcseconds()/plateScale # convert to pixels
1106 
1107  halfSize = geom.ExtentI(0.5*width, 0.5*height)
1108  bbox = geom.Box2I(center - halfSize, center + halfSize)
1109 
1110  bbox = geom.BoxI(geom.PointI(int(center[0] - 0.5*width), int(center[1] - 0.5*height)),
1111  geom.PointI(int(center[0] + 0.5*width), int(center[1] + 0.5*height)))
1112  spans = afwGeom.SpanSet(bbox)
1113  elif rec["type"] == "circle":
1114  radius = int(rec["radius"].asArcseconds()/plateScale) # convert to pixels
1115  spans = afwGeom.SpanSet.fromShape(radius, offset=center)
1116  else:
1117  self.log.warn("Unexpected region type %s at %s" % rec["type"], center)
1118  continue
1119  spans.clippedTo(mask.getBBox()).setMask(mask, self.brightObjectBitmask)
1120 
A compact representation of a collection of pixels.
Definition: SpanSet.h:78
def setBrightObjectMasks(self, exposure, brightObjectMasks, dataId=None)

◆ setInexactPsf()

def lsst.pipe.tasks.assembleCoadd.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 1121 of file assembleCoadd.py.

1121  def setInexactPsf(self, mask):
1122  """Set INEXACT_PSF mask plane.
1123 
1124  If any of the input images isn't represented in the coadd (due to
1125  clipped pixels or chip gaps), the `CoaddPsf` will be inexact. Flag
1126  these pixels.
1127 
1128  Parameters
1129  ----------
1130  mask : `lsst.afw.image.Mask`
1131  Coadded exposure's mask, modified in-place.
1132  """
1133  mask.addMaskPlane("INEXACT_PSF")
1134  inexactPsf = mask.getPlaneBitMask("INEXACT_PSF")
1135  sensorEdge = mask.getPlaneBitMask("SENSOR_EDGE") # chip edges (so PSF is discontinuous)
1136  clipped = mask.getPlaneBitMask("CLIPPED") # pixels clipped from coadd
1137  rejected = mask.getPlaneBitMask("REJECTED") # pixels rejected from coadd due to masks
1138  array = mask.getArray()
1139  selected = array & (sensorEdge | clipped | rejected) > 0
1140  array[selected] |= inexactPsf
1141 

◆ shrinkValidPolygons()

def lsst.pipe.tasks.assembleCoadd.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 1035 of file assembleCoadd.py.

1035  def shrinkValidPolygons(self, coaddInputs):
1036  """Shrink coaddInputs' ccds' ValidPolygons in place.
1037 
1038  Either modify each ccd's validPolygon in place, or if CoaddInputs
1039  does not have a validPolygon, create one from its bbox.
1040 
1041  Parameters
1042  ----------
1043  coaddInputs : `lsst.afw.image.coaddInputs`
1044  Original mask.
1045 
1046  """
1047  for ccd in coaddInputs.ccds:
1048  polyOrig = ccd.getValidPolygon()
1049  validPolyBBox = polyOrig.getBBox() if polyOrig else ccd.getBBox()
1050  validPolyBBox.grow(-self.config.matchingKernelSize//2)
1051  if polyOrig:
1052  validPolygon = polyOrig.intersectionSingle(validPolyBBox)
1053  else:
1054  validPolygon = afwGeom.polygon.Polygon(geom.Box2D(validPolyBBox))
1055  ccd.setValidPolygon(validPolygon)
1056 
A floating-point coordinate rectangle geometry.
Definition: Box.h:413
def shrinkValidPolygons(self, coaddInputs)

Variable Documentation

◆ brightObjects

lsst.pipe.tasks.assembleCoadd.brightObjects

Definition at line 527 of file assembleCoadd.py.

◆ calExpRefList

lsst.pipe.tasks.assembleCoadd.calExpRefList

Definition at line 507 of file assembleCoadd.py.

◆ ccd

lsst.pipe.tasks.assembleCoadd.ccd

Definition at line 358 of file assembleCoadd.py.

◆ coaddDatasetName

lsst.pipe.tasks.assembleCoadd.coaddDatasetName

Definition at line 532 of file assembleCoadd.py.

◆ filter

lsst.pipe.tasks.assembleCoadd.filter

Definition at line 357 of file assembleCoadd.py.

◆ id

lsst.pipe.tasks.assembleCoadd.id
warpType = pexConfig.Field(
    doc="Warp name: one of 'direct' or 'psfMatched'",
    dtype=str,
    default="direct",
)
subregionSize = pexConfig.ListField(
    dtype=int,
    doc="Width, height of stack subregion size; "
    "make small enough that a full stack of images will fit into memory at once.",
    length=2,
    default=(2000, 2000),
)
statistic = pexConfig.Field(
    dtype=str,
    doc="Main stacking statistic for aggregating over the epochs.",
    default="MEANCLIP",
)
doSigmaClip = pexConfig.Field(
    dtype=bool,
    doc="Perform sigma clipped outlier rejection with MEANCLIP statistic? (DEPRECATED)",
    default=False,
)
sigmaClip = pexConfig.Field(
    dtype=float,
    doc="Sigma for outlier rejection; ignored if non-clipping statistic selected.",
    default=3.0,
)
clipIter = pexConfig.Field(
    dtype=int,
    doc="Number of iterations of outlier rejection; ignored if non-clipping statistic selected.",
    default=2,
)
calcErrorFromInputVariance = pexConfig.Field(
    dtype=bool,
    doc="Calculate coadd variance from input variance by stacking statistic."
        "Passed to StatisticsControl.setCalcErrorFromInputVariance()",
    default=True,
)
scaleZeroPoint = pexConfig.ConfigurableField(
    target=ScaleZeroPointTask,
    doc="Task to adjust the photometric zero point of the coadd temp exposures",
)
doInterp = pexConfig.Field(
    doc="Interpolate over NaN pixels? Also extrapolate, if necessary, but the results are ugly.",
    dtype=bool,
    default=True,
)
interpImage = pexConfig.ConfigurableField(
    target=InterpImageTask,
    doc="Task to interpolate (and extrapolate) over NaN pixels",
)
doWrite = pexConfig.Field(
    doc="Persist coadd?",
    dtype=bool,
    default=True,
)
doNImage = pexConfig.Field(
    doc="Create image of number of contributing exposures for each pixel",
    dtype=bool,
    default=False,
)
doUsePsfMatchedPolygons = pexConfig.Field(
    doc="Use ValidPolygons from shrunk Psf-Matched Calexps? Should be set to True by CompareWarp only.",
    dtype=bool,
    default=False,
)
maskPropagationThresholds = pexConfig.DictField(
    keytype=str,
    itemtype=float,
    doc=("Threshold (in fractional weight) of rejection at which we propagate a mask plane to "
         "the coadd; that is, we set the mask bit on the coadd if the fraction the rejected frames "
         "would have contributed exceeds this value."),
    default={"SAT": 0.1},
)
removeMaskPlanes = pexConfig.ListField(dtype=str, default=["NOT_DEBLENDED"],
                                       doc="Mask planes to remove before coadding")
doMaskBrightObjects = pexConfig.Field(dtype=bool, default=False,
                                      doc="Set mask and flag bits for bright objects?")
brightObjectMaskName = pexConfig.Field(dtype=str, default="BRIGHT_OBJECT",
                                       doc="Name of mask bit used for bright objects")
coaddPsf = pexConfig.ConfigField(
    doc="Configuration for CoaddPsf",
    dtype=measAlg.CoaddPsfConfig,
)
doAttachTransmissionCurve = pexConfig.Field(
    dtype=bool, default=False, optional=False,
    doc=("Attach a piecewise TransmissionCurve for the coadd? "
         "(requires all input Exposures to have TransmissionCurves).")
)
hasFakes = pexConfig.Field(
    dtype=bool,
    default=False,
    doc="Should be set to True if fake sources have been inserted into the input data."
)
doSelectVisits = pexConfig.Field(
    doc="Coadd only visits selected by a SelectVisitsTask",
    dtype=bool,
    default=False,
)

def setDefaults(self):
    super().setDefaults()
    self.badMaskPlanes = ["NO_DATA", "BAD", "SAT", "EDGE"]

def validate(self):
    super().validate()
    if self.doPsfMatch:
        # Backwards compatibility.
        # Configs do not have loggers
        log.warn("Config doPsfMatch deprecated. Setting warpType='psfMatched'")
        self.warpType = 'psfMatched'
    if self.doSigmaClip and self.statistic != "MEANCLIP":
        log.warn('doSigmaClip deprecated. To replicate behavior, setting statistic to "MEANCLIP"')
        self.statistic = "MEANCLIP"
    if self.doInterp and self.statistic not in ['MEAN', 'MEDIAN', 'MEANCLIP', 'VARIANCE', 'VARIANCECLIP']:
        raise ValueError("Must set doInterp=False for statistic=%s, which does not "
                         "compute and set a non-zero coadd variance estimate." % (self.statistic))

    unstackableStats = ['NOTHING', 'ERROR', 'ORMASK']
    if not hasattr(afwMath.Property, self.statistic) or self.statistic in unstackableStats:
        stackableStats = [str(k) for k in afwMath.Property.__members__.keys()
                          if str(k) not in unstackableStats]
        raise ValueError("statistic %s is not allowed. Please choose one of %s."
                         % (self.statistic, stackableStats))


class AssembleCoaddTask(CoaddBaseTask, pipeBase.PipelineTask):

Definition at line 319 of file assembleCoadd.py.

◆ inputData

lsst.pipe.tasks.assembleCoadd.inputData

Definition at line 515 of file assembleCoadd.py.

◆ KEY

lsst.pipe.tasks.assembleCoadd.KEY

Definition at line 319 of file assembleCoadd.py.

◆ patch

lsst.pipe.tasks.assembleCoadd.patch

Definition at line 357 of file assembleCoadd.py.

◆ retStruct

lsst.pipe.tasks.assembleCoadd.retStruct

Definition at line 524 of file assembleCoadd.py.

◆ skyInfo

lsst.pipe.tasks.assembleCoadd.skyInfo
ConfigClass = AssembleCoaddConfig
_DefaultName = "assembleCoadd"

def __init__(self, *args, **kwargs):
    # TODO: DM-17415 better way to handle previously allowed passed args e.g.`AssembleCoaddTask(config)`
    if args:
        argNames = ["config", "name", "parentTask", "log"]
        kwargs.update({k: v for k, v in zip(argNames, args)})
        warnings.warn("AssembleCoadd received positional args, and casting them as kwargs: %s. "
                      "PipelineTask will not take positional args" % argNames, FutureWarning)

    super().__init__(**kwargs)
    self.makeSubtask("interpImage")
    self.makeSubtask("scaleZeroPoint")

    if self.config.doMaskBrightObjects:
        mask = afwImage.Mask()
        try:
            self.brightObjectBitmask = 1 << mask.addMaskPlane(self.config.brightObjectMaskName)
        except pexExceptions.LsstCppException:
            raise RuntimeError("Unable to define mask plane for bright objects; planes used are %s" %
                               mask.getMaskPlaneDict().keys())
        del mask

    self.warpType = self.config.warpType

@utils.inheritDoc(pipeBase.PipelineTask)
def runQuantum(self, butlerQC, inputRefs, outputRefs):
    # Docstring to be formatted with info from PipelineTask.runQuantum
inputData = butlerQC.get(inputRefs)

# Construct skyInfo expected by run
# Do not remove skyMap from inputData in case makeSupplementaryDataGen3 needs it
skyMap = inputData["skyMap"]
outputDataId = butlerQC.quantum.dataId

inputData['skyInfo'] = makeSkyInfo(skyMap,
                                   tractId=outputDataId['tract'],
                                   patchId=outputDataId['patch'])

if self.config.doSelectVisits:
    warpRefList = self.filterWarps(inputData['inputWarps'], inputData['selectedVisits'])
else:
    warpRefList = inputData['inputWarps']

# Perform same middle steps as `runDataRef` does
inputs = self.prepareInputs(warpRefList)
self.log.info("Found %d %s", len(inputs.tempExpRefList),
              self.getTempExpDatasetName(self.warpType))
if len(inputs.tempExpRefList) == 0:
    self.log.warn("No coadd temporary exposures found")
    return

supplementaryData = self.makeSupplementaryDataGen3(butlerQC, inputRefs, outputRefs)
retStruct = self.run(inputData['skyInfo'], inputs.tempExpRefList, inputs.imageScalerList,
                     inputs.weightList, supplementaryData=supplementaryData)

inputData.setdefault('brightObjectMask', None)
self.processResults(retStruct.coaddExposure, inputData['brightObjectMask'], outputDataId)

if self.config.doWrite:
    butlerQC.put(retStruct, outputRefs)
return retStruct

@pipeBase.timeMethod
def runDataRef(self, dataRef, selectDataList=None, warpRefList=None):

Definition at line 505 of file assembleCoadd.py.

◆ supplementaryData

lsst.pipe.tasks.assembleCoadd.supplementaryData

Definition at line 522 of file assembleCoadd.py.

◆ tract

lsst.pipe.tasks.assembleCoadd.tract

Definition at line 357 of file assembleCoadd.py.

◆ visit

lsst.pipe.tasks.assembleCoadd.visit

Definition at line 358 of file assembleCoadd.py.

◆ warpRefList

lsst.pipe.tasks.assembleCoadd.warpRefList

Definition at line 513 of file assembleCoadd.py.

◆ warpType

lsst.pipe.tasks.assembleCoadd.warpType

Definition at line 862 of file assembleCoadd.py.