LSSTApplications  20.0.0
LSSTDataManagementBasePackage
Public Member Functions | Public Attributes | Static Public Attributes | List of all members
lsst.ip.isr.isrTask.IsrTask Class Reference
Inheritance diagram for lsst.ip.isr.isrTask.IsrTask:

Public Member Functions

def __init__ (self, **kwargs)
 
def runQuantum (self, butlerQC, inputRefs, outputRefs)
 
def readIsrData (self, dataRef, rawExposure)
 Retrieve necessary frames for instrument signature removal. More...
 
def run (self, ccdExposure, camera=None, bias=None, linearizer=None, crosstalkSources=None, dark=None, flat=None, bfKernel=None, bfGains=None, defects=None, fringes=pipeBase.Struct(fringes=None), opticsTransmission=None, filterTransmission=None, sensorTransmission=None, atmosphereTransmission=None, detectorNum=None, strayLightData=None, illumMaskedImage=None, isGen3=False)
 Perform instrument signature removal on an exposure. More...
 
def runDataRef (self, sensorRef)
 
def getIsrExposure (self, dataRef, datasetType, dateObs=None, immediate=True)
 Retrieve a calibration dataset for removing instrument signature. More...
 
def ensureExposure (self, inputExp, camera, detectorNum)
 
def convertIntToFloat (self, exposure)
 
def maskAmplifier (self, ccdExposure, amp, defects)
 
def overscanCorrection (self, ccdExposure, amp)
 
def updateVariance (self, ampExposure, amp, overscanImage=None)
 
def darkCorrection (self, exposure, darkExposure, invert=False)
 Apply dark correction in place. More...
 
def doLinearize (self, detector)
 Check if linearization is needed for the detector cameraGeom. More...
 
def flatCorrection (self, exposure, flatExposure, invert=False)
 Apply flat correction in place. More...
 
def saturationDetection (self, exposure, amp)
 Detect saturated pixels and mask them using mask plane config.saturatedMaskName, in place. More...
 
def saturationInterpolation (self, exposure)
 Interpolate over saturated pixels, in place. More...
 
def suspectDetection (self, exposure, amp)
 Detect suspect pixels and mask them using mask plane config.suspectMaskName, in place. More...
 
def maskDefect (self, exposure, defectBaseList)
 Mask defects using mask plane "BAD", in place. More...
 
def maskEdges (self, exposure, numEdgePixels=0, maskPlane="SUSPECT")
 Mask edge pixels with applicable mask plane. More...
 
def maskAndInterpolateDefects (self, exposure, defectBaseList)
 
def maskNan (self, exposure)
 
def maskAndInterpolateNan (self, exposure)
 
def measureBackground (self, exposure, IsrQaConfig=None)
 
def roughZeroPoint (self, exposure)
 
def setValidPolygonIntersect (self, ccdExposure, fpPolygon)
 Set the valid polygon as the intersection of fpPolygon and the ccd corners. More...
 
def flatContext (self, exp, flat, dark=None)
 
def debugView (self, exposure, stepname)
 

Public Attributes

 vignettePolygon
 

Static Public Attributes

 ConfigClass = IsrTaskConfig
 

Detailed Description

Apply common instrument signature correction algorithms to a raw frame.

The process for correcting imaging data is very similar from
camera to camera.  This task provides a vanilla implementation of
doing these corrections, including the ability to turn certain
corrections off if they are not needed.  The inputs to the primary
method, `run()`, are a raw exposure to be corrected and the
calibration data products. The raw input is a single chip sized
mosaic of all amps including overscans and other non-science
pixels.  The method `runDataRef()` identifies and defines the
calibration data products, and is intended for use by a
`lsst.pipe.base.cmdLineTask.CmdLineTask` and takes as input only a
`daf.persistence.butlerSubset.ButlerDataRef`.  This task may be
subclassed for different camera, although the most camera specific
methods have been split into subtasks that can be redirected
appropriately.

The __init__ method sets up the subtasks for ISR processing, using
the defaults from `lsst.ip.isr`.

Parameters
----------
args : `list`
    Positional arguments passed to the Task constructor. None used at this time.
kwargs : `dict`, optional
    Keyword arguments passed on to the Task constructor. None used at this time.

Definition at line 785 of file isrTask.py.

Constructor & Destructor Documentation

◆ __init__()

def lsst.ip.isr.isrTask.IsrTask.__init__ (   self,
**  kwargs 
)

Definition at line 816 of file isrTask.py.

816  def __init__(self, **kwargs):
817  super().__init__(**kwargs)
818  self.makeSubtask("assembleCcd")
819  self.makeSubtask("crosstalk")
820  self.makeSubtask("strayLight")
821  self.makeSubtask("fringe")
822  self.makeSubtask("masking")
823  self.makeSubtask("overscan")
824  self.makeSubtask("vignette")
825 

Member Function Documentation

◆ convertIntToFloat()

def lsst.ip.isr.isrTask.IsrTask.convertIntToFloat (   self,
  exposure 
)
Convert exposure image from uint16 to float.

If the exposure does not need to be converted, the input is
immediately returned.  For exposures that are converted to use
floating point pixels, the variance is set to unity and the
mask to zero.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
   The raw exposure to be converted.

Returns
-------
newexposure : `lsst.afw.image.Exposure`
   The input ``exposure``, converted to floating point pixels.

Raises
------
RuntimeError
    Raised if the exposure type cannot be converted to float.

Definition at line 1674 of file isrTask.py.

1674  def convertIntToFloat(self, exposure):
1675  """Convert exposure image from uint16 to float.
1676 
1677  If the exposure does not need to be converted, the input is
1678  immediately returned. For exposures that are converted to use
1679  floating point pixels, the variance is set to unity and the
1680  mask to zero.
1681 
1682  Parameters
1683  ----------
1684  exposure : `lsst.afw.image.Exposure`
1685  The raw exposure to be converted.
1686 
1687  Returns
1688  -------
1689  newexposure : `lsst.afw.image.Exposure`
1690  The input ``exposure``, converted to floating point pixels.
1691 
1692  Raises
1693  ------
1694  RuntimeError
1695  Raised if the exposure type cannot be converted to float.
1696 
1697  """
1698  if isinstance(exposure, afwImage.ExposureF):
1699  # Nothing to be done
1700  self.log.debug("Exposure already of type float.")
1701  return exposure
1702  if not hasattr(exposure, "convertF"):
1703  raise RuntimeError("Unable to convert exposure (%s) to float." % type(exposure))
1704 
1705  newexposure = exposure.convertF()
1706  newexposure.variance[:] = 1
1707  newexposure.mask[:] = 0x0
1708 
1709  return newexposure
1710 

◆ darkCorrection()

def lsst.ip.isr.isrTask.IsrTask.darkCorrection (   self,
  exposure,
  darkExposure,
  invert = False 
)

Apply dark correction in place.

Parameters

exposure : lsst.afw.image.Exposure Exposure to process. darkExposure : lsst.afw.image.Exposure Dark exposure of the same size as exposure. invert : Bool, optional If True, re-add the dark to an already corrected image.

Raises

RuntimeError Raised if either exposure or darkExposure do not have their dark time defined.

See Also

lsst.ip.isr.isrFunctions.darkCorrection

Definition at line 1961 of file isrTask.py.

1961  def darkCorrection(self, exposure, darkExposure, invert=False):
1962  """!Apply dark correction in place.
1963 
1964  Parameters
1965  ----------
1966  exposure : `lsst.afw.image.Exposure`
1967  Exposure to process.
1968  darkExposure : `lsst.afw.image.Exposure`
1969  Dark exposure of the same size as ``exposure``.
1970  invert : `Bool`, optional
1971  If True, re-add the dark to an already corrected image.
1972 
1973  Raises
1974  ------
1975  RuntimeError
1976  Raised if either ``exposure`` or ``darkExposure`` do not
1977  have their dark time defined.
1978 
1979  See Also
1980  --------
1981  lsst.ip.isr.isrFunctions.darkCorrection
1982  """
1983  expScale = exposure.getInfo().getVisitInfo().getDarkTime()
1984  if math.isnan(expScale):
1985  raise RuntimeError("Exposure darktime is NAN.")
1986  if darkExposure.getInfo().getVisitInfo() is not None \
1987  and not math.isnan(darkExposure.getInfo().getVisitInfo().getDarkTime()):
1988  darkScale = darkExposure.getInfo().getVisitInfo().getDarkTime()
1989  else:
1990  # DM-17444: darkExposure.getInfo.getVisitInfo() is None
1991  # so getDarkTime() does not exist.
1992  self.log.warn("darkExposure.getInfo().getVisitInfo() does not exist. Using darkScale = 1.0.")
1993  darkScale = 1.0
1994 
1995  isrFunctions.darkCorrection(
1996  maskedImage=exposure.getMaskedImage(),
1997  darkMaskedImage=darkExposure.getMaskedImage(),
1998  expScale=expScale,
1999  darkScale=darkScale,
2000  invert=invert,
2001  trimToFit=self.config.doTrimToMatchCalib
2002  )
2003 

◆ debugView()

def lsst.ip.isr.isrTask.IsrTask.debugView (   self,
  exposure,
  stepname 
)
Utility function to examine ISR exposure at different stages.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure to view.
stepname : `str`
    State of processing to view.

Definition at line 2393 of file isrTask.py.

2393  def debugView(self, exposure, stepname):
2394  """Utility function to examine ISR exposure at different stages.
2395 
2396  Parameters
2397  ----------
2398  exposure : `lsst.afw.image.Exposure`
2399  Exposure to view.
2400  stepname : `str`
2401  State of processing to view.
2402  """
2403  frame = getDebugFrame(self._display, stepname)
2404  if frame:
2405  display = getDisplay(frame)
2406  display.scale('asinh', 'zscale')
2407  display.mtv(exposure)
2408  prompt = "Press Enter to continue [c]... "
2409  while True:
2410  ans = input(prompt).lower()
2411  if ans in ("", "c",):
2412  break
2413 
2414 

◆ doLinearize()

def lsst.ip.isr.isrTask.IsrTask.doLinearize (   self,
  detector 
)

Check if linearization is needed for the detector cameraGeom.

Checks config.doLinearize and the linearity type of the first amplifier.

Parameters

detector : lsst.afw.cameraGeom.Detector Detector to get linearity type from.

Returns

doLinearize : Bool If True, linearization should be performed.

Definition at line 2004 of file isrTask.py.

2004  def doLinearize(self, detector):
2005  """!Check if linearization is needed for the detector cameraGeom.
2006 
2007  Checks config.doLinearize and the linearity type of the first
2008  amplifier.
2009 
2010  Parameters
2011  ----------
2012  detector : `lsst.afw.cameraGeom.Detector`
2013  Detector to get linearity type from.
2014 
2015  Returns
2016  -------
2017  doLinearize : `Bool`
2018  If True, linearization should be performed.
2019  """
2020  return self.config.doLinearize and \
2021  detector.getAmplifiers()[0].getLinearityType() != NullLinearityType
2022 

◆ ensureExposure()

def lsst.ip.isr.isrTask.IsrTask.ensureExposure (   self,
  inputExp,
  camera,
  detectorNum 
)
Ensure that the data returned by Butler is a fully constructed exposure.

ISR requires exposure-level image data for historical reasons, so if we did
not recieve that from Butler, construct it from what we have, modifying the
input in place.

Parameters
----------
inputExp : `lsst.afw.image.Exposure`, `lsst.afw.image.DecoratedImageU`, or
   `lsst.afw.image.ImageF`
    The input data structure obtained from Butler.
camera : `lsst.afw.cameraGeom.camera`
    The camera associated with the image.  Used to find the appropriate
    detector.
detectorNum : `int`
    The detector this exposure should match.

Returns
-------
inputExp : `lsst.afw.image.Exposure`
    The re-constructed exposure, with appropriate detector parameters.

Raises
------
TypeError
    Raised if the input data cannot be used to construct an exposure.

Definition at line 1626 of file isrTask.py.

1626  def ensureExposure(self, inputExp, camera, detectorNum):
1627  """Ensure that the data returned by Butler is a fully constructed exposure.
1628 
1629  ISR requires exposure-level image data for historical reasons, so if we did
1630  not recieve that from Butler, construct it from what we have, modifying the
1631  input in place.
1632 
1633  Parameters
1634  ----------
1635  inputExp : `lsst.afw.image.Exposure`, `lsst.afw.image.DecoratedImageU`, or
1636  `lsst.afw.image.ImageF`
1637  The input data structure obtained from Butler.
1638  camera : `lsst.afw.cameraGeom.camera`
1639  The camera associated with the image. Used to find the appropriate
1640  detector.
1641  detectorNum : `int`
1642  The detector this exposure should match.
1643 
1644  Returns
1645  -------
1646  inputExp : `lsst.afw.image.Exposure`
1647  The re-constructed exposure, with appropriate detector parameters.
1648 
1649  Raises
1650  ------
1651  TypeError
1652  Raised if the input data cannot be used to construct an exposure.
1653  """
1654  if isinstance(inputExp, afwImage.DecoratedImageU):
1655  inputExp = afwImage.makeExposure(afwImage.makeMaskedImage(inputExp))
1656  elif isinstance(inputExp, afwImage.ImageF):
1657  inputExp = afwImage.makeExposure(afwImage.makeMaskedImage(inputExp))
1658  elif isinstance(inputExp, afwImage.MaskedImageF):
1659  inputExp = afwImage.makeExposure(inputExp)
1660  elif isinstance(inputExp, afwImage.Exposure):
1661  pass
1662  elif inputExp is None:
1663  # Assume this will be caught by the setup if it is a problem.
1664  return inputExp
1665  else:
1666  raise TypeError("Input Exposure is not known type in isrTask.ensureExposure: %s." %
1667  (type(inputExp), ))
1668 
1669  if inputExp.getDetector() is None:
1670  inputExp.setDetector(camera[detectorNum])
1671 
1672  return inputExp
1673 

◆ flatContext()

def lsst.ip.isr.isrTask.IsrTask.flatContext (   self,
  exp,
  flat,
  dark = None 
)
Context manager that applies and removes flats and darks,
if the task is configured to apply them.

Parameters
----------
exp : `lsst.afw.image.Exposure`
    Exposure to process.
flat : `lsst.afw.image.Exposure`
    Flat exposure the same size as ``exp``.
dark : `lsst.afw.image.Exposure`, optional
    Dark exposure the same size as ``exp``.

Yields
------
exp : `lsst.afw.image.Exposure`
    The flat and dark corrected exposure.

Definition at line 2363 of file isrTask.py.

2363  def flatContext(self, exp, flat, dark=None):
2364  """Context manager that applies and removes flats and darks,
2365  if the task is configured to apply them.
2366 
2367  Parameters
2368  ----------
2369  exp : `lsst.afw.image.Exposure`
2370  Exposure to process.
2371  flat : `lsst.afw.image.Exposure`
2372  Flat exposure the same size as ``exp``.
2373  dark : `lsst.afw.image.Exposure`, optional
2374  Dark exposure the same size as ``exp``.
2375 
2376  Yields
2377  ------
2378  exp : `lsst.afw.image.Exposure`
2379  The flat and dark corrected exposure.
2380  """
2381  if self.config.doDark and dark is not None:
2382  self.darkCorrection(exp, dark)
2383  if self.config.doFlat:
2384  self.flatCorrection(exp, flat)
2385  try:
2386  yield exp
2387  finally:
2388  if self.config.doFlat:
2389  self.flatCorrection(exp, flat, invert=True)
2390  if self.config.doDark and dark is not None:
2391  self.darkCorrection(exp, dark, invert=True)
2392 

◆ flatCorrection()

def lsst.ip.isr.isrTask.IsrTask.flatCorrection (   self,
  exposure,
  flatExposure,
  invert = False 
)

Apply flat correction in place.

Parameters

exposure : lsst.afw.image.Exposure Exposure to process. flatExposure : lsst.afw.image.Exposure Flat exposure of the same size as exposure. invert : Bool, optional If True, unflatten an already flattened image.

See Also

lsst.ip.isr.isrFunctions.flatCorrection

Definition at line 2023 of file isrTask.py.

2023  def flatCorrection(self, exposure, flatExposure, invert=False):
2024  """!Apply flat correction in place.
2025 
2026  Parameters
2027  ----------
2028  exposure : `lsst.afw.image.Exposure`
2029  Exposure to process.
2030  flatExposure : `lsst.afw.image.Exposure`
2031  Flat exposure of the same size as ``exposure``.
2032  invert : `Bool`, optional
2033  If True, unflatten an already flattened image.
2034 
2035  See Also
2036  --------
2037  lsst.ip.isr.isrFunctions.flatCorrection
2038  """
2039  isrFunctions.flatCorrection(
2040  maskedImage=exposure.getMaskedImage(),
2041  flatMaskedImage=flatExposure.getMaskedImage(),
2042  scalingType=self.config.flatScalingType,
2043  userScale=self.config.flatUserScale,
2044  invert=invert,
2045  trimToFit=self.config.doTrimToMatchCalib
2046  )
2047 

◆ getIsrExposure()

def lsst.ip.isr.isrTask.IsrTask.getIsrExposure (   self,
  dataRef,
  datasetType,
  dateObs = None,
  immediate = True 
)

Retrieve a calibration dataset for removing instrument signature.

Parameters

dataRef : daf.persistence.butlerSubset.ButlerDataRef DataRef of the detector data to find calibration datasets for. datasetType : str Type of dataset to retrieve (e.g. 'bias', 'flat', etc). dateObs : str, optional Date of the observation. Used to correct butler failures when using fallback filters. immediate : Bool If True, disable butler proxies to enable error handling within this routine.

Returns

exposure : lsst.afw.image.Exposure Requested calibration frame.

Raises

RuntimeError Raised if no matching calibration frame can be found.

Definition at line 1578 of file isrTask.py.

1578  def getIsrExposure(self, dataRef, datasetType, dateObs=None, immediate=True):
1579  """!Retrieve a calibration dataset for removing instrument signature.
1580 
1581  Parameters
1582  ----------
1583 
1584  dataRef : `daf.persistence.butlerSubset.ButlerDataRef`
1585  DataRef of the detector data to find calibration datasets
1586  for.
1587  datasetType : `str`
1588  Type of dataset to retrieve (e.g. 'bias', 'flat', etc).
1589  dateObs : `str`, optional
1590  Date of the observation. Used to correct butler failures
1591  when using fallback filters.
1592  immediate : `Bool`
1593  If True, disable butler proxies to enable error handling
1594  within this routine.
1595 
1596  Returns
1597  -------
1598  exposure : `lsst.afw.image.Exposure`
1599  Requested calibration frame.
1600 
1601  Raises
1602  ------
1603  RuntimeError
1604  Raised if no matching calibration frame can be found.
1605  """
1606  try:
1607  exp = dataRef.get(datasetType, immediate=immediate)
1608  except Exception as exc1:
1609  if not self.config.fallbackFilterName:
1610  raise RuntimeError("Unable to retrieve %s for %s: %s." % (datasetType, dataRef.dataId, exc1))
1611  try:
1612  if self.config.useFallbackDate and dateObs:
1613  exp = dataRef.get(datasetType, filter=self.config.fallbackFilterName,
1614  dateObs=dateObs, immediate=immediate)
1615  else:
1616  exp = dataRef.get(datasetType, filter=self.config.fallbackFilterName, immediate=immediate)
1617  except Exception as exc2:
1618  raise RuntimeError("Unable to retrieve %s for %s, even with fallback filter %s: %s AND %s." %
1619  (datasetType, dataRef.dataId, self.config.fallbackFilterName, exc1, exc2))
1620  self.log.warn("Using fallback calibration from filter %s.", self.config.fallbackFilterName)
1621 
1622  if self.config.doAssembleIsrExposures:
1623  exp = self.assembleCcd.assembleCcd(exp)
1624  return exp
1625 

◆ maskAmplifier()

def lsst.ip.isr.isrTask.IsrTask.maskAmplifier (   self,
  ccdExposure,
  amp,
  defects 
)
Identify bad amplifiers, saturated and suspect pixels.

Parameters
----------
ccdExposure : `lsst.afw.image.Exposure`
    Input exposure to be masked.
amp : `lsst.afw.table.AmpInfoCatalog`
    Catalog of parameters defining the amplifier on this
    exposure to mask.
defects : `lsst.meas.algorithms.Defects`
    List of defects.  Used to determine if the entire
    amplifier is bad.

Returns
-------
badAmp : `Bool`
    If this is true, the entire amplifier area is covered by
    defects and unusable.

Definition at line 1711 of file isrTask.py.

1711  def maskAmplifier(self, ccdExposure, amp, defects):
1712  """Identify bad amplifiers, saturated and suspect pixels.
1713 
1714  Parameters
1715  ----------
1716  ccdExposure : `lsst.afw.image.Exposure`
1717  Input exposure to be masked.
1718  amp : `lsst.afw.table.AmpInfoCatalog`
1719  Catalog of parameters defining the amplifier on this
1720  exposure to mask.
1721  defects : `lsst.meas.algorithms.Defects`
1722  List of defects. Used to determine if the entire
1723  amplifier is bad.
1724 
1725  Returns
1726  -------
1727  badAmp : `Bool`
1728  If this is true, the entire amplifier area is covered by
1729  defects and unusable.
1730 
1731  """
1732  maskedImage = ccdExposure.getMaskedImage()
1733 
1734  badAmp = False
1735 
1736  # Check if entire amp region is defined as a defect (need to use amp.getBBox() for correct
1737  # comparison with current defects definition.
1738  if defects is not None:
1739  badAmp = bool(sum([v.getBBox().contains(amp.getBBox()) for v in defects]))
1740 
1741  # In the case of a bad amp, we will set mask to "BAD" (here use amp.getRawBBox() for correct
1742  # association with pixels in current ccdExposure).
1743  if badAmp:
1744  dataView = afwImage.MaskedImageF(maskedImage, amp.getRawBBox(),
1745  afwImage.PARENT)
1746  maskView = dataView.getMask()
1747  maskView |= maskView.getPlaneBitMask("BAD")
1748  del maskView
1749  return badAmp
1750 
1751  # Mask remaining defects after assembleCcd() to allow for defects that cross amplifier boundaries.
1752  # Saturation and suspect pixels can be masked now, though.
1753  limits = dict()
1754  if self.config.doSaturation and not badAmp:
1755  limits.update({self.config.saturatedMaskName: amp.getSaturation()})
1756  if self.config.doSuspect and not badAmp:
1757  limits.update({self.config.suspectMaskName: amp.getSuspectLevel()})
1758  if math.isfinite(self.config.saturation):
1759  limits.update({self.config.saturatedMaskName: self.config.saturation})
1760 
1761  for maskName, maskThreshold in limits.items():
1762  if not math.isnan(maskThreshold):
1763  dataView = maskedImage.Factory(maskedImage, amp.getRawBBox())
1764  isrFunctions.makeThresholdMask(
1765  maskedImage=dataView,
1766  threshold=maskThreshold,
1767  growFootprints=0,
1768  maskName=maskName
1769  )
1770 
1771  # Determine if we've fully masked this amplifier with SUSPECT and SAT pixels.
1772  maskView = afwImage.Mask(maskedImage.getMask(), amp.getRawDataBBox(),
1773  afwImage.PARENT)
1774  maskVal = maskView.getPlaneBitMask([self.config.saturatedMaskName,
1775  self.config.suspectMaskName])
1776  if numpy.all(maskView.getArray() & maskVal > 0):
1777  badAmp = True
1778  maskView |= maskView.getPlaneBitMask("BAD")
1779 
1780  return badAmp
1781 

◆ maskAndInterpolateDefects()

def lsst.ip.isr.isrTask.IsrTask.maskAndInterpolateDefects (   self,
  exposure,
  defectBaseList 
)
Mask and interpolate defects using mask plane "BAD", in place.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure to process.
defectBaseList : `lsst.meas.algorithms.Defects` or `list` of
         `lsst.afw.image.DefectBase`.
    List of defects to mask and interpolate.

See Also
--------
lsst.ip.isr.isrTask.maskDefect()

Definition at line 2181 of file isrTask.py.

2181  def maskAndInterpolateDefects(self, exposure, defectBaseList):
2182  """Mask and interpolate defects using mask plane "BAD", in place.
2183 
2184  Parameters
2185  ----------
2186  exposure : `lsst.afw.image.Exposure`
2187  Exposure to process.
2188  defectBaseList : `lsst.meas.algorithms.Defects` or `list` of
2189  `lsst.afw.image.DefectBase`.
2190  List of defects to mask and interpolate.
2191 
2192  See Also
2193  --------
2194  lsst.ip.isr.isrTask.maskDefect()
2195  """
2196  self.maskDefect(exposure, defectBaseList)
2197  self.maskEdges(exposure, numEdgePixels=self.config.numEdgeSuspect,
2198  maskPlane="SUSPECT")
2199  isrFunctions.interpolateFromMask(
2200  maskedImage=exposure.getMaskedImage(),
2201  fwhm=self.config.fwhm,
2202  growSaturatedFootprints=0,
2203  maskNameList=["BAD"],
2204  )
2205 

◆ maskAndInterpolateNan()

def lsst.ip.isr.isrTask.IsrTask.maskAndInterpolateNan (   self,
  exposure 
)
"Mask and interpolate NaNs using mask plane "UNMASKEDNAN", in place.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure to process.

See Also
--------
lsst.ip.isr.isrTask.maskNan()

Definition at line 2232 of file isrTask.py.

2232  def maskAndInterpolateNan(self, exposure):
2233  """"Mask and interpolate NaNs using mask plane "UNMASKEDNAN", in place.
2234 
2235  Parameters
2236  ----------
2237  exposure : `lsst.afw.image.Exposure`
2238  Exposure to process.
2239 
2240  See Also
2241  --------
2242  lsst.ip.isr.isrTask.maskNan()
2243  """
2244  self.maskNan(exposure)
2245  isrFunctions.interpolateFromMask(
2246  maskedImage=exposure.getMaskedImage(),
2247  fwhm=self.config.fwhm,
2248  growSaturatedFootprints=0,
2249  maskNameList=["UNMASKEDNAN"],
2250  )
2251 

◆ maskDefect()

def lsst.ip.isr.isrTask.IsrTask.maskDefect (   self,
  exposure,
  defectBaseList 
)

Mask defects using mask plane "BAD", in place.

Parameters

exposure : lsst.afw.image.Exposure Exposure to process. defectBaseList : lsst.meas.algorithms.Defects or list of lsst.afw.image.DefectBase. List of defects to mask.

Notes

Call this after CCD assembly, since defects may cross amplifier boundaries.

Definition at line 2132 of file isrTask.py.

2132  def maskDefect(self, exposure, defectBaseList):
2133  """!Mask defects using mask plane "BAD", in place.
2134 
2135  Parameters
2136  ----------
2137  exposure : `lsst.afw.image.Exposure`
2138  Exposure to process.
2139  defectBaseList : `lsst.meas.algorithms.Defects` or `list` of
2140  `lsst.afw.image.DefectBase`.
2141  List of defects to mask.
2142 
2143  Notes
2144  -----
2145  Call this after CCD assembly, since defects may cross amplifier boundaries.
2146  """
2147  maskedImage = exposure.getMaskedImage()
2148  if not isinstance(defectBaseList, Defects):
2149  # Promotes DefectBase to Defect
2150  defectList = Defects(defectBaseList)
2151  else:
2152  defectList = defectBaseList
2153  defectList.maskPixels(maskedImage, maskName="BAD")
2154 

◆ maskEdges()

def lsst.ip.isr.isrTask.IsrTask.maskEdges (   self,
  exposure,
  numEdgePixels = 0,
  maskPlane = "SUSPECT" 
)

Mask edge pixels with applicable mask plane.

Parameters

exposure : lsst.afw.image.Exposure Exposure to process. numEdgePixels : int, optional Number of edge pixels to mask. maskPlane : str, optional Mask plane name to use.

Definition at line 2155 of file isrTask.py.

2155  def maskEdges(self, exposure, numEdgePixels=0, maskPlane="SUSPECT"):
2156  """!Mask edge pixels with applicable mask plane.
2157 
2158  Parameters
2159  ----------
2160  exposure : `lsst.afw.image.Exposure`
2161  Exposure to process.
2162  numEdgePixels : `int`, optional
2163  Number of edge pixels to mask.
2164  maskPlane : `str`, optional
2165  Mask plane name to use.
2166  """
2167  maskedImage = exposure.getMaskedImage()
2168  maskBitMask = maskedImage.getMask().getPlaneBitMask(maskPlane)
2169 
2170  if numEdgePixels > 0:
2171  goodBBox = maskedImage.getBBox()
2172  # This makes a bbox numEdgeSuspect pixels smaller than the image on each side
2173  goodBBox.grow(-numEdgePixels)
2174  # Mask pixels outside goodBBox
2175  SourceDetectionTask.setEdgeBits(
2176  maskedImage,
2177  goodBBox,
2178  maskBitMask
2179  )
2180 

◆ maskNan()

def lsst.ip.isr.isrTask.IsrTask.maskNan (   self,
  exposure 
)
Mask NaNs using mask plane "UNMASKEDNAN", in place.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure to process.

Notes
-----
We mask over all NaNs, including those that are masked with
other bits (because those may or may not be interpolated over
later, and we want to remove all NaNs).  Despite this
behaviour, the "UNMASKEDNAN" mask plane is used to preserve
the historical name.

Definition at line 2206 of file isrTask.py.

2206  def maskNan(self, exposure):
2207  """Mask NaNs using mask plane "UNMASKEDNAN", in place.
2208 
2209  Parameters
2210  ----------
2211  exposure : `lsst.afw.image.Exposure`
2212  Exposure to process.
2213 
2214  Notes
2215  -----
2216  We mask over all NaNs, including those that are masked with
2217  other bits (because those may or may not be interpolated over
2218  later, and we want to remove all NaNs). Despite this
2219  behaviour, the "UNMASKEDNAN" mask plane is used to preserve
2220  the historical name.
2221  """
2222  maskedImage = exposure.getMaskedImage()
2223 
2224  # Find and mask NaNs
2225  maskedImage.getMask().addMaskPlane("UNMASKEDNAN")
2226  maskVal = maskedImage.getMask().getPlaneBitMask("UNMASKEDNAN")
2227  numNans = maskNans(maskedImage, maskVal)
2228  self.metadata.set("NUMNANS", numNans)
2229  if numNans > 0:
2230  self.log.warn("There were %d unmasked NaNs.", numNans)
2231 

◆ measureBackground()

def lsst.ip.isr.isrTask.IsrTask.measureBackground (   self,
  exposure,
  IsrQaConfig = None 
)
Measure the image background in subgrids, for quality control purposes.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure to process.
IsrQaConfig : `lsst.ip.isr.isrQa.IsrQaConfig`
    Configuration object containing parameters on which background
    statistics and subgrids to use.

Definition at line 2252 of file isrTask.py.

2252  def measureBackground(self, exposure, IsrQaConfig=None):
2253  """Measure the image background in subgrids, for quality control purposes.
2254 
2255  Parameters
2256  ----------
2257  exposure : `lsst.afw.image.Exposure`
2258  Exposure to process.
2259  IsrQaConfig : `lsst.ip.isr.isrQa.IsrQaConfig`
2260  Configuration object containing parameters on which background
2261  statistics and subgrids to use.
2262  """
2263  if IsrQaConfig is not None:
2264  statsControl = afwMath.StatisticsControl(IsrQaConfig.flatness.clipSigma,
2265  IsrQaConfig.flatness.nIter)
2266  maskVal = exposure.getMaskedImage().getMask().getPlaneBitMask(["BAD", "SAT", "DETECTED"])
2267  statsControl.setAndMask(maskVal)
2268  maskedImage = exposure.getMaskedImage()
2269  stats = afwMath.makeStatistics(maskedImage, afwMath.MEDIAN | afwMath.STDEVCLIP, statsControl)
2270  skyLevel = stats.getValue(afwMath.MEDIAN)
2271  skySigma = stats.getValue(afwMath.STDEVCLIP)
2272  self.log.info("Flattened sky level: %f +/- %f.", skyLevel, skySigma)
2273  metadata = exposure.getMetadata()
2274  metadata.set('SKYLEVEL', skyLevel)
2275  metadata.set('SKYSIGMA', skySigma)
2276 
2277  # calcluating flatlevel over the subgrids
2278  stat = afwMath.MEANCLIP if IsrQaConfig.flatness.doClip else afwMath.MEAN
2279  meshXHalf = int(IsrQaConfig.flatness.meshX/2.)
2280  meshYHalf = int(IsrQaConfig.flatness.meshY/2.)
2281  nX = int((exposure.getWidth() + meshXHalf) / IsrQaConfig.flatness.meshX)
2282  nY = int((exposure.getHeight() + meshYHalf) / IsrQaConfig.flatness.meshY)
2283  skyLevels = numpy.zeros((nX, nY))
2284 
2285  for j in range(nY):
2286  yc = meshYHalf + j * IsrQaConfig.flatness.meshY
2287  for i in range(nX):
2288  xc = meshXHalf + i * IsrQaConfig.flatness.meshX
2289 
2290  xLLC = xc - meshXHalf
2291  yLLC = yc - meshYHalf
2292  xURC = xc + meshXHalf - 1
2293  yURC = yc + meshYHalf - 1
2294 
2295  bbox = lsst.geom.Box2I(lsst.geom.Point2I(xLLC, yLLC), lsst.geom.Point2I(xURC, yURC))
2296  miMesh = maskedImage.Factory(exposure.getMaskedImage(), bbox, afwImage.LOCAL)
2297 
2298  skyLevels[i, j] = afwMath.makeStatistics(miMesh, stat, statsControl).getValue()
2299 
2300  good = numpy.where(numpy.isfinite(skyLevels))
2301  skyMedian = numpy.median(skyLevels[good])
2302  flatness = (skyLevels[good] - skyMedian) / skyMedian
2303  flatness_rms = numpy.std(flatness)
2304  flatness_pp = flatness.max() - flatness.min() if len(flatness) > 0 else numpy.nan
2305 
2306  self.log.info("Measuring sky levels in %dx%d grids: %f.", nX, nY, skyMedian)
2307  self.log.info("Sky flatness in %dx%d grids - pp: %f rms: %f.",
2308  nX, nY, flatness_pp, flatness_rms)
2309 
2310  metadata.set('FLATNESS_PP', float(flatness_pp))
2311  metadata.set('FLATNESS_RMS', float(flatness_rms))
2312  metadata.set('FLATNESS_NGRIDS', '%dx%d' % (nX, nY))
2313  metadata.set('FLATNESS_MESHX', IsrQaConfig.flatness.meshX)
2314  metadata.set('FLATNESS_MESHY', IsrQaConfig.flatness.meshY)
2315 

◆ overscanCorrection()

def lsst.ip.isr.isrTask.IsrTask.overscanCorrection (   self,
  ccdExposure,
  amp 
)
Apply overscan correction in place.

This method does initial pixel rejection of the overscan
region.  The overscan can also be optionally segmented to
allow for discontinuous overscan responses to be fit
separately.  The actual overscan subtraction is performed by
the `lsst.ip.isr.isrFunctions.overscanCorrection` function,
which is called here after the amplifier is preprocessed.

Parameters
----------
ccdExposure : `lsst.afw.image.Exposure`
    Exposure to have overscan correction performed.
amp : `lsst.afw.table.AmpInfoCatalog`
    The amplifier to consider while correcting the overscan.

Returns
-------
overscanResults : `lsst.pipe.base.Struct`
    Result struct with components:
    - ``imageFit`` : scalar or `lsst.afw.image.Image`
Value or fit subtracted from the amplifier image data.
    - ``overscanFit`` : scalar or `lsst.afw.image.Image`
Value or fit subtracted from the overscan image data.
    - ``overscanImage`` : `lsst.afw.image.Image`
Image of the overscan region with the overscan
correction applied. This quantity is used to estimate
the amplifier read noise empirically.

Raises
------
RuntimeError
    Raised if the ``amp`` does not contain raw pixel information.

See Also
--------
lsst.ip.isr.isrFunctions.overscanCorrection

Definition at line 1782 of file isrTask.py.

1782  def overscanCorrection(self, ccdExposure, amp):
1783  """Apply overscan correction in place.
1784 
1785  This method does initial pixel rejection of the overscan
1786  region. The overscan can also be optionally segmented to
1787  allow for discontinuous overscan responses to be fit
1788  separately. The actual overscan subtraction is performed by
1789  the `lsst.ip.isr.isrFunctions.overscanCorrection` function,
1790  which is called here after the amplifier is preprocessed.
1791 
1792  Parameters
1793  ----------
1794  ccdExposure : `lsst.afw.image.Exposure`
1795  Exposure to have overscan correction performed.
1796  amp : `lsst.afw.table.AmpInfoCatalog`
1797  The amplifier to consider while correcting the overscan.
1798 
1799  Returns
1800  -------
1801  overscanResults : `lsst.pipe.base.Struct`
1802  Result struct with components:
1803  - ``imageFit`` : scalar or `lsst.afw.image.Image`
1804  Value or fit subtracted from the amplifier image data.
1805  - ``overscanFit`` : scalar or `lsst.afw.image.Image`
1806  Value or fit subtracted from the overscan image data.
1807  - ``overscanImage`` : `lsst.afw.image.Image`
1808  Image of the overscan region with the overscan
1809  correction applied. This quantity is used to estimate
1810  the amplifier read noise empirically.
1811 
1812  Raises
1813  ------
1814  RuntimeError
1815  Raised if the ``amp`` does not contain raw pixel information.
1816 
1817  See Also
1818  --------
1819  lsst.ip.isr.isrFunctions.overscanCorrection
1820  """
1821  if amp.getRawHorizontalOverscanBBox().isEmpty():
1822  self.log.info("ISR_OSCAN: No overscan region. Not performing overscan correction.")
1823  return None
1824 
1825  statControl = afwMath.StatisticsControl()
1826  statControl.setAndMask(ccdExposure.mask.getPlaneBitMask("SAT"))
1827 
1828  # Determine the bounding boxes
1829  dataBBox = amp.getRawDataBBox()
1830  oscanBBox = amp.getRawHorizontalOverscanBBox()
1831  dx0 = 0
1832  dx1 = 0
1833 
1834  prescanBBox = amp.getRawPrescanBBox()
1835  if (oscanBBox.getBeginX() > prescanBBox.getBeginX()): # amp is at the right
1836  dx0 += self.config.overscanNumLeadingColumnsToSkip
1837  dx1 -= self.config.overscanNumTrailingColumnsToSkip
1838  else:
1839  dx0 += self.config.overscanNumTrailingColumnsToSkip
1840  dx1 -= self.config.overscanNumLeadingColumnsToSkip
1841 
1842  # Determine if we need to work on subregions of the amplifier and overscan.
1843  imageBBoxes = []
1844  overscanBBoxes = []
1845 
1846  if ((self.config.overscanBiasJump and
1847  self.config.overscanBiasJumpLocation) and
1848  (ccdExposure.getMetadata().exists(self.config.overscanBiasJumpKeyword) and
1849  ccdExposure.getMetadata().getScalar(self.config.overscanBiasJumpKeyword) in
1850  self.config.overscanBiasJumpDevices)):
1851  if amp.getReadoutCorner() in (ReadoutCorner.LL, ReadoutCorner.LR):
1852  yLower = self.config.overscanBiasJumpLocation
1853  yUpper = dataBBox.getHeight() - yLower
1854  else:
1855  yUpper = self.config.overscanBiasJumpLocation
1856  yLower = dataBBox.getHeight() - yUpper
1857 
1858  imageBBoxes.append(lsst.geom.Box2I(dataBBox.getBegin(),
1859  lsst.geom.Extent2I(dataBBox.getWidth(), yLower)))
1860  overscanBBoxes.append(lsst.geom.Box2I(oscanBBox.getBegin() +
1861  lsst.geom.Extent2I(dx0, 0),
1862  lsst.geom.Extent2I(oscanBBox.getWidth() - dx0 + dx1,
1863  yLower)))
1864 
1865  imageBBoxes.append(lsst.geom.Box2I(dataBBox.getBegin() + lsst.geom.Extent2I(0, yLower),
1866  lsst.geom.Extent2I(dataBBox.getWidth(), yUpper)))
1867  overscanBBoxes.append(lsst.geom.Box2I(oscanBBox.getBegin() + lsst.geom.Extent2I(dx0, yLower),
1868  lsst.geom.Extent2I(oscanBBox.getWidth() - dx0 + dx1,
1869  yUpper)))
1870  else:
1871  imageBBoxes.append(lsst.geom.Box2I(dataBBox.getBegin(),
1872  lsst.geom.Extent2I(dataBBox.getWidth(), dataBBox.getHeight())))
1873  overscanBBoxes.append(lsst.geom.Box2I(oscanBBox.getBegin() + lsst.geom.Extent2I(dx0, 0),
1874  lsst.geom.Extent2I(oscanBBox.getWidth() - dx0 + dx1,
1875  oscanBBox.getHeight())))
1876 
1877  # Perform overscan correction on subregions, ensuring saturated pixels are masked.
1878  for imageBBox, overscanBBox in zip(imageBBoxes, overscanBBoxes):
1879  ampImage = ccdExposure.maskedImage[imageBBox]
1880  overscanImage = ccdExposure.maskedImage[overscanBBox]
1881 
1882  overscanArray = overscanImage.image.array
1883  median = numpy.ma.median(numpy.ma.masked_where(overscanImage.mask.array, overscanArray))
1884  bad = numpy.where(numpy.abs(overscanArray - median) > self.config.overscanMaxDev)
1885  overscanImage.mask.array[bad] = overscanImage.mask.getPlaneBitMask("SAT")
1886 
1887  statControl = afwMath.StatisticsControl()
1888  statControl.setAndMask(ccdExposure.mask.getPlaneBitMask("SAT"))
1889 
1890  overscanResults = self.overscan.run(ampImage.getImage(), overscanImage)
1891 
1892  # Measure average overscan levels and record them in the metadata.
1893  levelStat = afwMath.MEDIAN
1894  sigmaStat = afwMath.STDEVCLIP
1895 
1896  sctrl = afwMath.StatisticsControl(self.config.qa.flatness.clipSigma,
1897  self.config.qa.flatness.nIter)
1898  metadata = ccdExposure.getMetadata()
1899  ampNum = amp.getName()
1900  # if self.config.overscanFitType in ("MEDIAN", "MEAN", "MEANCLIP"):
1901  if isinstance(overscanResults.overscanFit, float):
1902  metadata.set("ISR_OSCAN_LEVEL%s" % ampNum, overscanResults.overscanFit)
1903  metadata.set("ISR_OSCAN_SIGMA%s" % ampNum, 0.0)
1904  else:
1905  stats = afwMath.makeStatistics(overscanResults.overscanFit, levelStat | sigmaStat, sctrl)
1906  metadata.set("ISR_OSCAN_LEVEL%s" % ampNum, stats.getValue(levelStat))
1907  metadata.set("ISR_OSCAN_SIGMA%s" % ampNum, stats.getValue(sigmaStat))
1908 
1909  return overscanResults
1910 

◆ readIsrData()

def lsst.ip.isr.isrTask.IsrTask.readIsrData (   self,
  dataRef,
  rawExposure 
)

Retrieve necessary frames for instrument signature removal.

Pre-fetching all required ISR data products limits the IO required by the ISR. Any conflict between the calibration data available and that needed for ISR is also detected prior to doing processing, allowing it to fail quickly.

Parameters

dataRef : daf.persistence.butlerSubset.ButlerDataRef Butler reference of the detector data to be processed rawExposure : afw.image.Exposure The raw exposure that will later be corrected with the retrieved calibration data; should not be modified in this method.

Returns

result : lsst.pipe.base.Struct Result struct with components (which may be None):

  • bias: bias calibration frame (afw.image.Exposure)
  • linearizer: functor for linearization (ip.isr.linearize.LinearizeBase)
  • crosstalkSources: list of possible crosstalk sources (list)
  • dark: dark calibration frame (afw.image.Exposure)
  • flat: flat calibration frame (afw.image.Exposure)
  • bfKernel: Brighter-Fatter kernel (numpy.ndarray)
  • defects: list of defects (lsst.meas.algorithms.Defects)
  • fringes: lsst.pipe.base.Struct with components:
    • fringes: fringe calibration frame (afw.image.Exposure)
    • seed: random seed derived from the ccdExposureId for random number generator (uint32).
  • opticsTransmission: lsst.afw.image.TransmissionCurve A TransmissionCurve that represents the throughput of the optics, to be evaluated in focal-plane coordinates.
  • filterTransmission : lsst.afw.image.TransmissionCurve A TransmissionCurve that represents the throughput of the filter itself, to be evaluated in focal-plane coordinates.
  • sensorTransmission : lsst.afw.image.TransmissionCurve A TransmissionCurve that represents the throughput of the sensor itself, to be evaluated in post-assembly trimmed detector coordinates.
  • atmosphereTransmission : lsst.afw.image.TransmissionCurve A TransmissionCurve that represents the throughput of the atmosphere, assumed to be spatially constant.
  • strayLightData : object An opaque object containing calibration information for stray-light correction. If None, no correction will be performed.
  • illumMaskedImage : illumination correction image (lsst.afw.image.MaskedImage)

Raises

NotImplementedError : Raised if a per-amplifier brighter-fatter kernel is requested by the configuration.

Definition at line 900 of file isrTask.py.

900  def readIsrData(self, dataRef, rawExposure):
901  """!Retrieve necessary frames for instrument signature removal.
902 
903  Pre-fetching all required ISR data products limits the IO
904  required by the ISR. Any conflict between the calibration data
905  available and that needed for ISR is also detected prior to
906  doing processing, allowing it to fail quickly.
907 
908  Parameters
909  ----------
910  dataRef : `daf.persistence.butlerSubset.ButlerDataRef`
911  Butler reference of the detector data to be processed
912  rawExposure : `afw.image.Exposure`
913  The raw exposure that will later be corrected with the
914  retrieved calibration data; should not be modified in this
915  method.
916 
917  Returns
918  -------
919  result : `lsst.pipe.base.Struct`
920  Result struct with components (which may be `None`):
921  - ``bias``: bias calibration frame (`afw.image.Exposure`)
922  - ``linearizer``: functor for linearization (`ip.isr.linearize.LinearizeBase`)
923  - ``crosstalkSources``: list of possible crosstalk sources (`list`)
924  - ``dark``: dark calibration frame (`afw.image.Exposure`)
925  - ``flat``: flat calibration frame (`afw.image.Exposure`)
926  - ``bfKernel``: Brighter-Fatter kernel (`numpy.ndarray`)
927  - ``defects``: list of defects (`lsst.meas.algorithms.Defects`)
928  - ``fringes``: `lsst.pipe.base.Struct` with components:
929  - ``fringes``: fringe calibration frame (`afw.image.Exposure`)
930  - ``seed``: random seed derived from the ccdExposureId for random
931  number generator (`uint32`).
932  - ``opticsTransmission``: `lsst.afw.image.TransmissionCurve`
933  A ``TransmissionCurve`` that represents the throughput of the optics,
934  to be evaluated in focal-plane coordinates.
935  - ``filterTransmission`` : `lsst.afw.image.TransmissionCurve`
936  A ``TransmissionCurve`` that represents the throughput of the filter
937  itself, to be evaluated in focal-plane coordinates.
938  - ``sensorTransmission`` : `lsst.afw.image.TransmissionCurve`
939  A ``TransmissionCurve`` that represents the throughput of the sensor
940  itself, to be evaluated in post-assembly trimmed detector coordinates.
941  - ``atmosphereTransmission`` : `lsst.afw.image.TransmissionCurve`
942  A ``TransmissionCurve`` that represents the throughput of the
943  atmosphere, assumed to be spatially constant.
944  - ``strayLightData`` : `object`
945  An opaque object containing calibration information for
946  stray-light correction. If `None`, no correction will be
947  performed.
948  - ``illumMaskedImage`` : illumination correction image (`lsst.afw.image.MaskedImage`)
949 
950  Raises
951  ------
952  NotImplementedError :
953  Raised if a per-amplifier brighter-fatter kernel is requested by the configuration.
954  """
955  try:
956  dateObs = rawExposure.getInfo().getVisitInfo().getDate()
957  dateObs = dateObs.toPython().isoformat()
958  except RuntimeError:
959  self.log.warn("Unable to identify dateObs for rawExposure.")
960  dateObs = None
961 
962  ccd = rawExposure.getDetector()
963  filterName = afwImage.Filter(rawExposure.getFilter().getId()).getName() # Canonical name for filter
964  rawExposure.mask.addMaskPlane("UNMASKEDNAN") # needed to match pre DM-15862 processing.
965  biasExposure = (self.getIsrExposure(dataRef, self.config.biasDataProductName)
966  if self.config.doBias else None)
967  # immediate=True required for functors and linearizers are functors; see ticket DM-6515
968  linearizer = (dataRef.get("linearizer", immediate=True)
969  if self.doLinearize(ccd) else None)
970  if linearizer is not None and not isinstance(linearizer, numpy.ndarray):
971  linearizer.log = self.log
972  if isinstance(linearizer, numpy.ndarray):
973  linearizer = linearize.Linearizer(table=linearizer, detector=ccd)
974  crosstalkSources = (self.crosstalk.prepCrosstalk(dataRef)
975  if self.config.doCrosstalk else None)
976  darkExposure = (self.getIsrExposure(dataRef, self.config.darkDataProductName)
977  if self.config.doDark else None)
978  flatExposure = (self.getIsrExposure(dataRef, self.config.flatDataProductName,
979  dateObs=dateObs)
980  if self.config.doFlat else None)
981 
982  brighterFatterKernel = None
983  brighterFatterGains = None
984  if self.config.doBrighterFatter is True:
985  try:
986  # Use the new-style cp_pipe version of the kernel if it exists
987  # If using a new-style kernel, always use the self-consistent
988  # gains, i.e. the ones inside the kernel object itself
989  brighterFatterKernel = dataRef.get("brighterFatterKernel")
990  brighterFatterGains = brighterFatterKernel.gain
991  self.log.info("New style bright-fatter kernel (brighterFatterKernel) loaded")
992  except NoResults:
993  try: # Fall back to the old-style numpy-ndarray style kernel if necessary.
994  brighterFatterKernel = dataRef.get("bfKernel")
995  self.log.info("Old style bright-fatter kernel (np.array) loaded")
996  except NoResults:
997  brighterFatterKernel = None
998  if brighterFatterKernel is not None and not isinstance(brighterFatterKernel, numpy.ndarray):
999  # If the kernel is not an ndarray, it's the cp_pipe version
1000  # so extract the kernel for this detector, or raise an error
1001  if self.config.brighterFatterLevel == 'DETECTOR':
1002  if brighterFatterKernel.detectorKernel:
1003  brighterFatterKernel = brighterFatterKernel.detectorKernel[ccd.getId()]
1004  elif brighterFatterKernel.detectorKernelFromAmpKernels:
1005  brighterFatterKernel = brighterFatterKernel.detectorKernelFromAmpKernels[ccd.getId()]
1006  else:
1007  raise RuntimeError("Failed to extract kernel from new-style BF kernel.")
1008  else:
1009  # TODO DM-15631 for implementing this
1010  raise NotImplementedError("Per-amplifier brighter-fatter correction not implemented")
1011 
1012  defectList = (dataRef.get("defects")
1013  if self.config.doDefect else None)
1014  fringeStruct = (self.fringe.readFringes(dataRef, assembler=self.assembleCcd
1015  if self.config.doAssembleIsrExposures else None)
1016  if self.config.doFringe and self.fringe.checkFilter(rawExposure)
1017  else pipeBase.Struct(fringes=None))
1018 
1019  if self.config.doAttachTransmissionCurve:
1020  opticsTransmission = (dataRef.get("transmission_optics")
1021  if self.config.doUseOpticsTransmission else None)
1022  filterTransmission = (dataRef.get("transmission_filter")
1023  if self.config.doUseFilterTransmission else None)
1024  sensorTransmission = (dataRef.get("transmission_sensor")
1025  if self.config.doUseSensorTransmission else None)
1026  atmosphereTransmission = (dataRef.get("transmission_atmosphere")
1027  if self.config.doUseAtmosphereTransmission else None)
1028  else:
1029  opticsTransmission = None
1030  filterTransmission = None
1031  sensorTransmission = None
1032  atmosphereTransmission = None
1033 
1034  if self.config.doStrayLight:
1035  strayLightData = self.strayLight.readIsrData(dataRef, rawExposure)
1036  else:
1037  strayLightData = None
1038 
1039  illumMaskedImage = (self.getIsrExposure(dataRef,
1040  self.config.illuminationCorrectionDataProductName).getMaskedImage()
1041  if (self.config.doIlluminationCorrection and
1042  filterName in self.config.illumFilters)
1043  else None)
1044 
1045  # Struct should include only kwargs to run()
1046  return pipeBase.Struct(bias=biasExposure,
1047  linearizer=linearizer,
1048  crosstalkSources=crosstalkSources,
1049  dark=darkExposure,
1050  flat=flatExposure,
1051  bfKernel=brighterFatterKernel,
1052  bfGains=brighterFatterGains,
1053  defects=defectList,
1054  fringes=fringeStruct,
1055  opticsTransmission=opticsTransmission,
1056  filterTransmission=filterTransmission,
1057  sensorTransmission=sensorTransmission,
1058  atmosphereTransmission=atmosphereTransmission,
1059  strayLightData=strayLightData,
1060  illumMaskedImage=illumMaskedImage
1061  )
1062 

◆ roughZeroPoint()

def lsst.ip.isr.isrTask.IsrTask.roughZeroPoint (   self,
  exposure 
)
Set an approximate magnitude zero point for the exposure.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure to process.

Definition at line 2316 of file isrTask.py.

2316  def roughZeroPoint(self, exposure):
2317  """Set an approximate magnitude zero point for the exposure.
2318 
2319  Parameters
2320  ----------
2321  exposure : `lsst.afw.image.Exposure`
2322  Exposure to process.
2323  """
2324  filterName = afwImage.Filter(exposure.getFilter().getId()).getName() # Canonical name for filter
2325  if filterName in self.config.fluxMag0T1:
2326  fluxMag0 = self.config.fluxMag0T1[filterName]
2327  else:
2328  self.log.warn("No rough magnitude zero point set for filter %s.", filterName)
2329  fluxMag0 = self.config.defaultFluxMag0T1
2330 
2331  expTime = exposure.getInfo().getVisitInfo().getExposureTime()
2332  if not expTime > 0: # handle NaN as well as <= 0
2333  self.log.warn("Non-positive exposure time; skipping rough zero point.")
2334  return
2335 
2336  self.log.info("Setting rough magnitude zero point: %f", 2.5*math.log10(fluxMag0*expTime))
2337  exposure.setPhotoCalib(afwImage.makePhotoCalibFromCalibZeroPoint(fluxMag0*expTime, 0.0))
2338 

◆ run()

def lsst.ip.isr.isrTask.IsrTask.run (   self,
  ccdExposure,
  camera = None,
  bias = None,
  linearizer = None,
  crosstalkSources = None,
  dark = None,
  flat = None,
  bfKernel = None,
  bfGains = None,
  defects = None,
  fringes = pipeBase.Struct(fringes=None),
  opticsTransmission = None,
  filterTransmission = None,
  sensorTransmission = None,
  atmosphereTransmission = None,
  detectorNum = None,
  strayLightData = None,
  illumMaskedImage = None,
  isGen3 = False 
)

Perform instrument signature removal on an exposure.

Steps included in the ISR processing, in order performed, are:

  • saturation and suspect pixel masking
  • overscan subtraction
  • CCD assembly of individual amplifiers
  • bias subtraction
  • variance image construction
  • linearization of non-linear response
  • crosstalk masking
  • brighter-fatter correction
  • dark subtraction
  • fringe correction
  • stray light subtraction
  • flat correction
  • masking of known defects and camera specific features
  • vignette calculation
  • appending transmission curve and distortion model

Parameters

ccdExposure : lsst.afw.image.Exposure The raw exposure that is to be run through ISR. The exposure is modified by this method. camera : lsst.afw.cameraGeom.Camera, optional The camera geometry for this exposure. Required if isGen3 is True and one or more of ccdExposure, bias, dark, or flat does not have an associated detector. bias : lsst.afw.image.Exposure, optional Bias calibration frame. linearizer : lsst.ip.isr.linearize.LinearizeBase, optional Functor for linearization. crosstalkSources : list, optional List of possible crosstalk sources. dark : lsst.afw.image.Exposure, optional Dark calibration frame. flat : lsst.afw.image.Exposure, optional Flat calibration frame. bfKernel : numpy.ndarray, optional Brighter-fatter kernel. bfGains : dict of float, optional Gains used to override the detector's nominal gains for the brighter-fatter correction. A dict keyed by amplifier name for the detector in question. defects : lsst.meas.algorithms.Defects, optional List of defects. fringes : lsst.pipe.base.Struct, optional Struct containing the fringe correction data, with elements:

  • fringes: fringe calibration frame (afw.image.Exposure)
  • seed: random seed derived from the ccdExposureId for random number generator (uint32) opticsTransmission: lsst.afw.image.TransmissionCurve, optional A TransmissionCurve that represents the throughput of the optics, to be evaluated in focal-plane coordinates. filterTransmission : lsst.afw.image.TransmissionCurve A TransmissionCurve that represents the throughput of the filter itself, to be evaluated in focal-plane coordinates. sensorTransmission : lsst.afw.image.TransmissionCurve A TransmissionCurve that represents the throughput of the sensor itself, to be evaluated in post-assembly trimmed detector coordinates. atmosphereTransmission : lsst.afw.image.TransmissionCurve A TransmissionCurve that represents the throughput of the atmosphere, assumed to be spatially constant. detectorNum : int, optional The integer number for the detector to process. isGen3 : bool, optional Flag this call to run() as using the Gen3 butler environment. strayLightData : object, optional Opaque object containing calibration information for stray-light correction. If None, no correction will be performed. illumMaskedImage : lsst.afw.image.MaskedImage, optional Illumination correction image.

Returns

result : lsst.pipe.base.Struct Result struct with component:

  • exposure : afw.image.Exposure The fully ISR corrected exposure.
  • outputExposure : afw.image.Exposure An alias for exposure
  • ossThumb : numpy.ndarray Thumbnail image of the exposure after overscan subtraction.
  • flattenedThumb : numpy.ndarray Thumbnail image of the exposure after flat-field correction.

Raises

RuntimeError Raised if a configuration option is set to True, but the required calibration data has not been specified.

Notes

The current processed exposure can be viewed by setting the appropriate lsstDebug entries in the debug.display dictionary. The names of these entries correspond to some of the IsrTaskConfig Boolean options, with the value denoting the frame to use. The exposure is shown inside the matching option check and after the processing of that step has finished. The steps with debug points are:

doAssembleCcd doBias doCrosstalk doBrighterFatter doDark doFringe doStrayLight doFlat

In addition, setting the "postISRCCD" entry displays the exposure after all ISR processing has finished.

Definition at line 1064 of file isrTask.py.

1064  def run(self, ccdExposure, camera=None, bias=None, linearizer=None, crosstalkSources=None,
1065  dark=None, flat=None, bfKernel=None, bfGains=None, defects=None,
1066  fringes=pipeBase.Struct(fringes=None), opticsTransmission=None, filterTransmission=None,
1067  sensorTransmission=None, atmosphereTransmission=None,
1068  detectorNum=None, strayLightData=None, illumMaskedImage=None,
1069  isGen3=False,
1070  ):
1071  """!Perform instrument signature removal on an exposure.
1072 
1073  Steps included in the ISR processing, in order performed, are:
1074  - saturation and suspect pixel masking
1075  - overscan subtraction
1076  - CCD assembly of individual amplifiers
1077  - bias subtraction
1078  - variance image construction
1079  - linearization of non-linear response
1080  - crosstalk masking
1081  - brighter-fatter correction
1082  - dark subtraction
1083  - fringe correction
1084  - stray light subtraction
1085  - flat correction
1086  - masking of known defects and camera specific features
1087  - vignette calculation
1088  - appending transmission curve and distortion model
1089 
1090  Parameters
1091  ----------
1092  ccdExposure : `lsst.afw.image.Exposure`
1093  The raw exposure that is to be run through ISR. The
1094  exposure is modified by this method.
1095  camera : `lsst.afw.cameraGeom.Camera`, optional
1096  The camera geometry for this exposure. Required if ``isGen3`` is
1097  `True` and one or more of ``ccdExposure``, ``bias``, ``dark``, or
1098  ``flat`` does not have an associated detector.
1099  bias : `lsst.afw.image.Exposure`, optional
1100  Bias calibration frame.
1101  linearizer : `lsst.ip.isr.linearize.LinearizeBase`, optional
1102  Functor for linearization.
1103  crosstalkSources : `list`, optional
1104  List of possible crosstalk sources.
1105  dark : `lsst.afw.image.Exposure`, optional
1106  Dark calibration frame.
1107  flat : `lsst.afw.image.Exposure`, optional
1108  Flat calibration frame.
1109  bfKernel : `numpy.ndarray`, optional
1110  Brighter-fatter kernel.
1111  bfGains : `dict` of `float`, optional
1112  Gains used to override the detector's nominal gains for the
1113  brighter-fatter correction. A dict keyed by amplifier name for
1114  the detector in question.
1115  defects : `lsst.meas.algorithms.Defects`, optional
1116  List of defects.
1117  fringes : `lsst.pipe.base.Struct`, optional
1118  Struct containing the fringe correction data, with
1119  elements:
1120  - ``fringes``: fringe calibration frame (`afw.image.Exposure`)
1121  - ``seed``: random seed derived from the ccdExposureId for random
1122  number generator (`uint32`)
1123  opticsTransmission: `lsst.afw.image.TransmissionCurve`, optional
1124  A ``TransmissionCurve`` that represents the throughput of the optics,
1125  to be evaluated in focal-plane coordinates.
1126  filterTransmission : `lsst.afw.image.TransmissionCurve`
1127  A ``TransmissionCurve`` that represents the throughput of the filter
1128  itself, to be evaluated in focal-plane coordinates.
1129  sensorTransmission : `lsst.afw.image.TransmissionCurve`
1130  A ``TransmissionCurve`` that represents the throughput of the sensor
1131  itself, to be evaluated in post-assembly trimmed detector coordinates.
1132  atmosphereTransmission : `lsst.afw.image.TransmissionCurve`
1133  A ``TransmissionCurve`` that represents the throughput of the
1134  atmosphere, assumed to be spatially constant.
1135  detectorNum : `int`, optional
1136  The integer number for the detector to process.
1137  isGen3 : bool, optional
1138  Flag this call to run() as using the Gen3 butler environment.
1139  strayLightData : `object`, optional
1140  Opaque object containing calibration information for stray-light
1141  correction. If `None`, no correction will be performed.
1142  illumMaskedImage : `lsst.afw.image.MaskedImage`, optional
1143  Illumination correction image.
1144 
1145  Returns
1146  -------
1147  result : `lsst.pipe.base.Struct`
1148  Result struct with component:
1149  - ``exposure`` : `afw.image.Exposure`
1150  The fully ISR corrected exposure.
1151  - ``outputExposure`` : `afw.image.Exposure`
1152  An alias for `exposure`
1153  - ``ossThumb`` : `numpy.ndarray`
1154  Thumbnail image of the exposure after overscan subtraction.
1155  - ``flattenedThumb`` : `numpy.ndarray`
1156  Thumbnail image of the exposure after flat-field correction.
1157 
1158  Raises
1159  ------
1160  RuntimeError
1161  Raised if a configuration option is set to True, but the
1162  required calibration data has not been specified.
1163 
1164  Notes
1165  -----
1166  The current processed exposure can be viewed by setting the
1167  appropriate lsstDebug entries in the `debug.display`
1168  dictionary. The names of these entries correspond to some of
1169  the IsrTaskConfig Boolean options, with the value denoting the
1170  frame to use. The exposure is shown inside the matching
1171  option check and after the processing of that step has
1172  finished. The steps with debug points are:
1173 
1174  doAssembleCcd
1175  doBias
1176  doCrosstalk
1177  doBrighterFatter
1178  doDark
1179  doFringe
1180  doStrayLight
1181  doFlat
1182 
1183  In addition, setting the "postISRCCD" entry displays the
1184  exposure after all ISR processing has finished.
1185 
1186  """
1187 
1188  if isGen3 is True:
1189  # Gen3 currently cannot automatically do configuration overrides.
1190  # DM-15257 looks to discuss this issue.
1191  # Configure input exposures;
1192  if detectorNum is None:
1193  raise RuntimeError("Must supply the detectorNum if running as Gen3.")
1194 
1195  ccdExposure = self.ensureExposure(ccdExposure, camera, detectorNum)
1196  bias = self.ensureExposure(bias, camera, detectorNum)
1197  dark = self.ensureExposure(dark, camera, detectorNum)
1198  flat = self.ensureExposure(flat, camera, detectorNum)
1199  else:
1200  if isinstance(ccdExposure, ButlerDataRef):
1201  return self.runDataRef(ccdExposure)
1202 
1203  ccd = ccdExposure.getDetector()
1204  filterName = afwImage.Filter(ccdExposure.getFilter().getId()).getName() # Canonical name for filter
1205 
1206  if not ccd:
1207  assert not self.config.doAssembleCcd, "You need a Detector to run assembleCcd."
1208  ccd = [FakeAmp(ccdExposure, self.config)]
1209 
1210  # Validate Input
1211  if self.config.doBias and bias is None:
1212  raise RuntimeError("Must supply a bias exposure if config.doBias=True.")
1213  if self.doLinearize(ccd) and linearizer is None:
1214  raise RuntimeError("Must supply a linearizer if config.doLinearize=True for this detector.")
1215  if self.config.doBrighterFatter and bfKernel is None:
1216  raise RuntimeError("Must supply a kernel if config.doBrighterFatter=True.")
1217  if self.config.doDark and dark is None:
1218  raise RuntimeError("Must supply a dark exposure if config.doDark=True.")
1219  if self.config.doFlat and flat is None:
1220  raise RuntimeError("Must supply a flat exposure if config.doFlat=True.")
1221  if self.config.doDefect and defects is None:
1222  raise RuntimeError("Must supply defects if config.doDefect=True.")
1223  if (self.config.doFringe and filterName in self.fringe.config.filters and
1224  fringes.fringes is None):
1225  # The `fringes` object needs to be a pipeBase.Struct, as
1226  # we use it as a `dict` for the parameters of
1227  # `FringeTask.run()`. The `fringes.fringes` `list` may
1228  # not be `None` if `doFringe=True`. Otherwise, raise.
1229  raise RuntimeError("Must supply fringe exposure as a pipeBase.Struct.")
1230  if (self.config.doIlluminationCorrection and filterName in self.config.illumFilters and
1231  illumMaskedImage is None):
1232  raise RuntimeError("Must supply an illumcor if config.doIlluminationCorrection=True.")
1233 
1234  # Begin ISR processing.
1235  if self.config.doConvertIntToFloat:
1236  self.log.info("Converting exposure to floating point values.")
1237  ccdExposure = self.convertIntToFloat(ccdExposure)
1238 
1239  # Amplifier level processing.
1240  overscans = []
1241  for amp in ccd:
1242  # if ccdExposure is one amp, check for coverage to prevent performing ops multiple times
1243  if ccdExposure.getBBox().contains(amp.getBBox()):
1244  # Check for fully masked bad amplifiers, and generate masks for SUSPECT and SATURATED values.
1245  badAmp = self.maskAmplifier(ccdExposure, amp, defects)
1246 
1247  if self.config.doOverscan and not badAmp:
1248  # Overscan correction on amp-by-amp basis.
1249  overscanResults = self.overscanCorrection(ccdExposure, amp)
1250  self.log.debug("Corrected overscan for amplifier %s.", amp.getName())
1251  if overscanResults is not None and \
1252  self.config.qa is not None and self.config.qa.saveStats is True:
1253  if isinstance(overscanResults.overscanFit, float):
1254  qaMedian = overscanResults.overscanFit
1255  qaStdev = float("NaN")
1256  else:
1257  qaStats = afwMath.makeStatistics(overscanResults.overscanFit,
1258  afwMath.MEDIAN | afwMath.STDEVCLIP)
1259  qaMedian = qaStats.getValue(afwMath.MEDIAN)
1260  qaStdev = qaStats.getValue(afwMath.STDEVCLIP)
1261 
1262  self.metadata.set(f"ISR OSCAN {amp.getName()} MEDIAN", qaMedian)
1263  self.metadata.set(f"ISR OSCAN {amp.getName()} STDEV", qaStdev)
1264  self.log.debug(" Overscan stats for amplifer %s: %f +/- %f",
1265  amp.getName(), qaMedian, qaStdev)
1266  ccdExposure.getMetadata().set('OVERSCAN', "Overscan corrected")
1267  else:
1268  if badAmp:
1269  self.log.warn("Amplifier %s is bad.", amp.getName())
1270  overscanResults = None
1271 
1272  overscans.append(overscanResults if overscanResults is not None else None)
1273  else:
1274  self.log.info("Skipped OSCAN for %s.", amp.getName())
1275 
1276  if self.config.doCrosstalk and self.config.doCrosstalkBeforeAssemble:
1277  self.log.info("Applying crosstalk correction.")
1278  self.crosstalk.run(ccdExposure, crosstalkSources=crosstalkSources)
1279  self.debugView(ccdExposure, "doCrosstalk")
1280 
1281  if self.config.doAssembleCcd:
1282  self.log.info("Assembling CCD from amplifiers.")
1283  ccdExposure = self.assembleCcd.assembleCcd(ccdExposure)
1284 
1285  if self.config.expectWcs and not ccdExposure.getWcs():
1286  self.log.warn("No WCS found in input exposure.")
1287  self.debugView(ccdExposure, "doAssembleCcd")
1288 
1289  ossThumb = None
1290  if self.config.qa.doThumbnailOss:
1291  ossThumb = isrQa.makeThumbnail(ccdExposure, isrQaConfig=self.config.qa)
1292 
1293  if self.config.doBias:
1294  self.log.info("Applying bias correction.")
1295  isrFunctions.biasCorrection(ccdExposure.getMaskedImage(), bias.getMaskedImage(),
1296  trimToFit=self.config.doTrimToMatchCalib)
1297  self.debugView(ccdExposure, "doBias")
1298 
1299  if self.config.doVariance:
1300  for amp, overscanResults in zip(ccd, overscans):
1301  if ccdExposure.getBBox().contains(amp.getBBox()):
1302  self.log.debug("Constructing variance map for amplifer %s.", amp.getName())
1303  ampExposure = ccdExposure.Factory(ccdExposure, amp.getBBox())
1304  if overscanResults is not None:
1305  self.updateVariance(ampExposure, amp,
1306  overscanImage=overscanResults.overscanImage)
1307  else:
1308  self.updateVariance(ampExposure, amp,
1309  overscanImage=None)
1310  if self.config.qa is not None and self.config.qa.saveStats is True:
1311  qaStats = afwMath.makeStatistics(ampExposure.getVariance(),
1312  afwMath.MEDIAN | afwMath.STDEVCLIP)
1313  self.metadata.set(f"ISR VARIANCE {amp.getName()} MEDIAN",
1314  qaStats.getValue(afwMath.MEDIAN))
1315  self.metadata.set(f"ISR VARIANCE {amp.getName()} STDEV",
1316  qaStats.getValue(afwMath.STDEVCLIP))
1317  self.log.debug(" Variance stats for amplifer %s: %f +/- %f.",
1318  amp.getName(), qaStats.getValue(afwMath.MEDIAN),
1319  qaStats.getValue(afwMath.STDEVCLIP))
1320 
1321  if self.doLinearize(ccd):
1322  self.log.info("Applying linearizer.")
1323  linearizer.applyLinearity(image=ccdExposure.getMaskedImage().getImage(),
1324  detector=ccd, log=self.log)
1325 
1326  if self.config.doCrosstalk and not self.config.doCrosstalkBeforeAssemble:
1327  self.log.info("Applying crosstalk correction.")
1328  self.crosstalk.run(ccdExposure, crosstalkSources=crosstalkSources, isTrimmed=True)
1329  self.debugView(ccdExposure, "doCrosstalk")
1330 
1331  # Masking block. Optionally mask known defects, NAN pixels, widen trails, and do
1332  # anything else the camera needs. Saturated and suspect pixels have already been masked.
1333  if self.config.doDefect:
1334  self.log.info("Masking defects.")
1335  self.maskDefect(ccdExposure, defects)
1336 
1337  if self.config.numEdgeSuspect > 0:
1338  self.log.info("Masking edges as SUSPECT.")
1339  self.maskEdges(ccdExposure, numEdgePixels=self.config.numEdgeSuspect,
1340  maskPlane="SUSPECT")
1341 
1342  if self.config.doNanMasking:
1343  self.log.info("Masking NAN value pixels.")
1344  self.maskNan(ccdExposure)
1345 
1346  if self.config.doWidenSaturationTrails:
1347  self.log.info("Widening saturation trails.")
1348  isrFunctions.widenSaturationTrails(ccdExposure.getMaskedImage().getMask())
1349 
1350  if self.config.doCameraSpecificMasking:
1351  self.log.info("Masking regions for camera specific reasons.")
1352  self.masking.run(ccdExposure)
1353 
1354  if self.config.doBrighterFatter:
1355  # We need to apply flats and darks before we can interpolate, and we
1356  # need to interpolate before we do B-F, but we do B-F without the
1357  # flats and darks applied so we can work in units of electrons or holes.
1358  # This context manager applies and then removes the darks and flats.
1359  #
1360  # We also do not want to interpolate values here, so operate on temporary
1361  # images so we can apply only the BF-correction and roll back the
1362  # interpolation.
1363  interpExp = ccdExposure.clone()
1364  with self.flatContext(interpExp, flat, dark):
1365  isrFunctions.interpolateFromMask(
1366  maskedImage=interpExp.getMaskedImage(),
1367  fwhm=self.config.fwhm,
1368  growSaturatedFootprints=self.config.growSaturationFootprintSize,
1369  maskNameList=self.config.maskListToInterpolate
1370  )
1371  bfExp = interpExp.clone()
1372 
1373  self.log.info("Applying brighter fatter correction using kernel type %s / gains %s.",
1374  type(bfKernel), type(bfGains))
1375  bfResults = isrFunctions.brighterFatterCorrection(bfExp, bfKernel,
1376  self.config.brighterFatterMaxIter,
1377  self.config.brighterFatterThreshold,
1378  self.config.brighterFatterApplyGain,
1379  bfGains)
1380  if bfResults[1] == self.config.brighterFatterMaxIter:
1381  self.log.warn("Brighter fatter correction did not converge, final difference %f.",
1382  bfResults[0])
1383  else:
1384  self.log.info("Finished brighter fatter correction in %d iterations.",
1385  bfResults[1])
1386  image = ccdExposure.getMaskedImage().getImage()
1387  bfCorr = bfExp.getMaskedImage().getImage()
1388  bfCorr -= interpExp.getMaskedImage().getImage()
1389  image += bfCorr
1390 
1391  # Applying the brighter-fatter correction applies a
1392  # convolution to the science image. At the edges this
1393  # convolution may not have sufficient valid pixels to
1394  # produce a valid correction. Mark pixels within the size
1395  # of the brighter-fatter kernel as EDGE to warn of this
1396  # fact.
1397  self.log.info("Ensuring image edges are masked as SUSPECT to the brighter-fatter kernel size.")
1398  self.maskEdges(ccdExposure, numEdgePixels=numpy.max(bfKernel.shape) // 2,
1399  maskPlane="EDGE")
1400 
1401  if self.config.brighterFatterMaskGrowSize > 0:
1402  self.log.info("Growing masks to account for brighter-fatter kernel convolution.")
1403  for maskPlane in self.config.maskListToInterpolate:
1404  isrFunctions.growMasks(ccdExposure.getMask(),
1405  radius=self.config.brighterFatterMaskGrowSize,
1406  maskNameList=maskPlane,
1407  maskValue=maskPlane)
1408 
1409  self.debugView(ccdExposure, "doBrighterFatter")
1410 
1411  if self.config.doDark:
1412  self.log.info("Applying dark correction.")
1413  self.darkCorrection(ccdExposure, dark)
1414  self.debugView(ccdExposure, "doDark")
1415 
1416  if self.config.doFringe and not self.config.fringeAfterFlat:
1417  self.log.info("Applying fringe correction before flat.")
1418  self.fringe.run(ccdExposure, **fringes.getDict())
1419  self.debugView(ccdExposure, "doFringe")
1420 
1421  if self.config.doStrayLight and self.strayLight.check(ccdExposure):
1422  self.log.info("Checking strayLight correction.")
1423  self.strayLight.run(ccdExposure, strayLightData)
1424  self.debugView(ccdExposure, "doStrayLight")
1425 
1426  if self.config.doFlat:
1427  self.log.info("Applying flat correction.")
1428  self.flatCorrection(ccdExposure, flat)
1429  self.debugView(ccdExposure, "doFlat")
1430 
1431  if self.config.doApplyGains:
1432  self.log.info("Applying gain correction instead of flat.")
1433  isrFunctions.applyGains(ccdExposure, self.config.normalizeGains)
1434 
1435  if self.config.doFringe and self.config.fringeAfterFlat:
1436  self.log.info("Applying fringe correction after flat.")
1437  self.fringe.run(ccdExposure, **fringes.getDict())
1438 
1439  if self.config.doVignette:
1440  self.log.info("Constructing Vignette polygon.")
1441  self.vignettePolygon = self.vignette.run(ccdExposure)
1442 
1443  if self.config.vignette.doWriteVignettePolygon:
1444  self.setValidPolygonIntersect(ccdExposure, self.vignettePolygon)
1445 
1446  if self.config.doAttachTransmissionCurve:
1447  self.log.info("Adding transmission curves.")
1448  isrFunctions.attachTransmissionCurve(ccdExposure, opticsTransmission=opticsTransmission,
1449  filterTransmission=filterTransmission,
1450  sensorTransmission=sensorTransmission,
1451  atmosphereTransmission=atmosphereTransmission)
1452 
1453  flattenedThumb = None
1454  if self.config.qa.doThumbnailFlattened:
1455  flattenedThumb = isrQa.makeThumbnail(ccdExposure, isrQaConfig=self.config.qa)
1456 
1457  if self.config.doIlluminationCorrection and filterName in self.config.illumFilters:
1458  self.log.info("Performing illumination correction.")
1459  isrFunctions.illuminationCorrection(ccdExposure.getMaskedImage(),
1460  illumMaskedImage, illumScale=self.config.illumScale,
1461  trimToFit=self.config.doTrimToMatchCalib)
1462 
1463  preInterpExp = None
1464  if self.config.doSaveInterpPixels:
1465  preInterpExp = ccdExposure.clone()
1466 
1467  # Reset and interpolate bad pixels.
1468  #
1469  # Large contiguous bad regions (which should have the BAD mask
1470  # bit set) should have their values set to the image median.
1471  # This group should include defects and bad amplifiers. As the
1472  # area covered by these defects are large, there's little
1473  # reason to expect that interpolation would provide a more
1474  # useful value.
1475  #
1476  # Smaller defects can be safely interpolated after the larger
1477  # regions have had their pixel values reset. This ensures
1478  # that the remaining defects adjacent to bad amplifiers (as an
1479  # example) do not attempt to interpolate extreme values.
1480  if self.config.doSetBadRegions:
1481  badPixelCount, badPixelValue = isrFunctions.setBadRegions(ccdExposure)
1482  if badPixelCount > 0:
1483  self.log.info("Set %d BAD pixels to %f.", badPixelCount, badPixelValue)
1484 
1485  if self.config.doInterpolate:
1486  self.log.info("Interpolating masked pixels.")
1487  isrFunctions.interpolateFromMask(
1488  maskedImage=ccdExposure.getMaskedImage(),
1489  fwhm=self.config.fwhm,
1490  growSaturatedFootprints=self.config.growSaturationFootprintSize,
1491  maskNameList=list(self.config.maskListToInterpolate)
1492  )
1493 
1494  self.roughZeroPoint(ccdExposure)
1495 
1496  if self.config.doMeasureBackground:
1497  self.log.info("Measuring background level.")
1498  self.measureBackground(ccdExposure, self.config.qa)
1499 
1500  if self.config.qa is not None and self.config.qa.saveStats is True:
1501  for amp in ccd:
1502  ampExposure = ccdExposure.Factory(ccdExposure, amp.getBBox())
1503  qaStats = afwMath.makeStatistics(ampExposure.getImage(),
1504  afwMath.MEDIAN | afwMath.STDEVCLIP)
1505  self.metadata.set("ISR BACKGROUND {} MEDIAN".format(amp.getName()),
1506  qaStats.getValue(afwMath.MEDIAN))
1507  self.metadata.set("ISR BACKGROUND {} STDEV".format(amp.getName()),
1508  qaStats.getValue(afwMath.STDEVCLIP))
1509  self.log.debug(" Background stats for amplifer %s: %f +/- %f",
1510  amp.getName(), qaStats.getValue(afwMath.MEDIAN),
1511  qaStats.getValue(afwMath.STDEVCLIP))
1512 
1513  self.debugView(ccdExposure, "postISRCCD")
1514 
1515  return pipeBase.Struct(
1516  exposure=ccdExposure,
1517  ossThumb=ossThumb,
1518  flattenedThumb=flattenedThumb,
1519 
1520  preInterpolatedExposure=preInterpExp,
1521  outputExposure=ccdExposure,
1522  outputOssThumbnail=ossThumb,
1523  outputFlattenedThumbnail=flattenedThumb,
1524  )
1525 

◆ runDataRef()

def lsst.ip.isr.isrTask.IsrTask.runDataRef (   self,
  sensorRef 
)
Perform instrument signature removal on a ButlerDataRef of a Sensor.

This method contains the `CmdLineTask` interface to the ISR
processing.  All IO is handled here, freeing the `run()` method
to manage only pixel-level calculations.  The steps performed
are:
- Read in necessary detrending/isr/calibration data.
- Process raw exposure in `run()`.
- Persist the ISR-corrected exposure as "postISRCCD" if
  config.doWrite=True.

Parameters
----------
sensorRef : `daf.persistence.butlerSubset.ButlerDataRef`
    DataRef of the detector data to be processed

Returns
-------
result : `lsst.pipe.base.Struct`
    Result struct with component:
    - ``exposure`` : `afw.image.Exposure`
The fully ISR corrected exposure.

Raises
------
RuntimeError
    Raised if a configuration option is set to True, but the
    required calibration data does not exist.

Definition at line 1527 of file isrTask.py.

1527  def runDataRef(self, sensorRef):
1528  """Perform instrument signature removal on a ButlerDataRef of a Sensor.
1529 
1530  This method contains the `CmdLineTask` interface to the ISR
1531  processing. All IO is handled here, freeing the `run()` method
1532  to manage only pixel-level calculations. The steps performed
1533  are:
1534  - Read in necessary detrending/isr/calibration data.
1535  - Process raw exposure in `run()`.
1536  - Persist the ISR-corrected exposure as "postISRCCD" if
1537  config.doWrite=True.
1538 
1539  Parameters
1540  ----------
1541  sensorRef : `daf.persistence.butlerSubset.ButlerDataRef`
1542  DataRef of the detector data to be processed
1543 
1544  Returns
1545  -------
1546  result : `lsst.pipe.base.Struct`
1547  Result struct with component:
1548  - ``exposure`` : `afw.image.Exposure`
1549  The fully ISR corrected exposure.
1550 
1551  Raises
1552  ------
1553  RuntimeError
1554  Raised if a configuration option is set to True, but the
1555  required calibration data does not exist.
1556 
1557  """
1558  self.log.info("Performing ISR on sensor %s.", sensorRef.dataId)
1559 
1560  ccdExposure = sensorRef.get(self.config.datasetType)
1561 
1562  camera = sensorRef.get("camera")
1563  isrData = self.readIsrData(sensorRef, ccdExposure)
1564 
1565  result = self.run(ccdExposure, camera=camera, **isrData.getDict())
1566 
1567  if self.config.doWrite:
1568  sensorRef.put(result.exposure, "postISRCCD")
1569  if result.preInterpolatedExposure is not None:
1570  sensorRef.put(result.preInterpolatedExposure, "postISRCCD_uninterpolated")
1571  if result.ossThumb is not None:
1572  isrQa.writeThumbnail(sensorRef, result.ossThumb, "ossThumb")
1573  if result.flattenedThumb is not None:
1574  isrQa.writeThumbnail(sensorRef, result.flattenedThumb, "flattenedThumb")
1575 
1576  return result
1577 

◆ runQuantum()

def lsst.ip.isr.isrTask.IsrTask.runQuantum (   self,
  butlerQC,
  inputRefs,
  outputRefs 
)

Definition at line 826 of file isrTask.py.

826  def runQuantum(self, butlerQC, inputRefs, outputRefs):
827  inputs = butlerQC.get(inputRefs)
828 
829  try:
830  inputs['detectorNum'] = inputRefs.ccdExposure.dataId['detector']
831  except Exception as e:
832  raise ValueError("Failure to find valid detectorNum value for Dataset %s: %s." %
833  (inputRefs, e))
834 
835  inputs['isGen3'] = True
836 
837  detector = inputs['ccdExposure'].getDetector()
838 
839  if self.doLinearize(detector) is True:
840  if 'linearizer' in inputs and isinstance(inputs['linearizer'], dict):
841  linearizer = linearize.Linearizer(detector=detector, log=self.log)
842  linearizer.fromYaml(inputs['linearizer'])
843  else:
844  linearizer = linearize.Linearizer(table=inputs.get('linearizer', None), detector=detector,
845  log=self.log)
846  inputs['linearizer'] = linearizer
847 
848  if self.config.doDefect is True:
849  if "defects" in inputs and inputs['defects'] is not None:
850  # defects is loaded as a BaseCatalog with columns x0, y0, width, height.
851  # masking expects a list of defects defined by their bounding box
852  if not isinstance(inputs["defects"], Defects):
853  inputs["defects"] = Defects.fromTable(inputs["defects"])
854 
855  # Load the correct style of brighter fatter kernel, and repack
856  # the information as a numpy array.
857  if self.config.doBrighterFatter:
858  brighterFatterKernel = inputs.pop('newBFKernel', None)
859  if brighterFatterKernel is None:
860  brighterFatterKernel = inputs.get('bfKernel', None)
861 
862  if brighterFatterKernel is not None and not isinstance(brighterFatterKernel, numpy.ndarray):
863  detId = detector.getId()
864  inputs['bfGains'] = brighterFatterKernel.gain
865  # If the kernel is not an ndarray, it's the cp_pipe version
866  # so extract the kernel for this detector, or raise an error
867  if self.config.brighterFatterLevel == 'DETECTOR':
868  if brighterFatterKernel.detectorKernel:
869  inputs['bfKernel'] = brighterFatterKernel.detectorKernel[detId]
870  elif brighterFatterKernel.detectorKernelFromAmpKernels:
871  inputs['bfKernel'] = brighterFatterKernel.detectorKernelFromAmpKernels[detId]
872  else:
873  raise RuntimeError("Failed to extract kernel from new-style BF kernel.")
874  else:
875  # TODO DM-15631 for implementing this
876  raise NotImplementedError("Per-amplifier brighter-fatter correction not implemented")
877 
878  # Broken: DM-17169
879  # ci_hsc does not use crosstalkSources, as it's intra-CCD CT only. This needs to be
880  # fixed for non-HSC cameras in the future.
881  # inputs['crosstalkSources'] = (self.crosstalk.prepCrosstalk(inputsIds['ccdExposure'])
882  # if self.config.doCrosstalk else None)
883 
884  if self.config.doFringe is True and self.fringe.checkFilter(inputs['ccdExposure']):
885  expId = inputs['ccdExposure'].getInfo().getVisitInfo().getExposureId()
886  inputs['fringes'] = self.fringe.loadFringes(inputs['fringes'],
887  expId=expId,
888  assembler=self.assembleCcd
889  if self.config.doAssembleIsrExposures else None)
890  else:
891  inputs['fringes'] = pipeBase.Struct(fringes=None)
892 
893  if self.config.doStrayLight is True and self.strayLight.checkFilter(inputs['ccdExposure']):
894  if 'strayLightData' not in inputs:
895  inputs['strayLightData'] = None
896 
897  outputs = self.run(**inputs)
898  butlerQC.put(outputs, outputRefs)
899 

◆ saturationDetection()

def lsst.ip.isr.isrTask.IsrTask.saturationDetection (   self,
  exposure,
  amp 
)

Detect saturated pixels and mask them using mask plane config.saturatedMaskName, in place.

Parameters

exposure : lsst.afw.image.Exposure Exposure to process. Only the amplifier DataSec is processed. amp : lsst.afw.table.AmpInfoCatalog Amplifier detector data.

See Also

lsst.ip.isr.isrFunctions.makeThresholdMask

Definition at line 2048 of file isrTask.py.

2048  def saturationDetection(self, exposure, amp):
2049  """!Detect saturated pixels and mask them using mask plane config.saturatedMaskName, in place.
2050 
2051  Parameters
2052  ----------
2053  exposure : `lsst.afw.image.Exposure`
2054  Exposure to process. Only the amplifier DataSec is processed.
2055  amp : `lsst.afw.table.AmpInfoCatalog`
2056  Amplifier detector data.
2057 
2058  See Also
2059  --------
2060  lsst.ip.isr.isrFunctions.makeThresholdMask
2061  """
2062  if not math.isnan(amp.getSaturation()):
2063  maskedImage = exposure.getMaskedImage()
2064  dataView = maskedImage.Factory(maskedImage, amp.getRawBBox())
2065  isrFunctions.makeThresholdMask(
2066  maskedImage=dataView,
2067  threshold=amp.getSaturation(),
2068  growFootprints=0,
2069  maskName=self.config.saturatedMaskName,
2070  )
2071 

◆ saturationInterpolation()

def lsst.ip.isr.isrTask.IsrTask.saturationInterpolation (   self,
  exposure 
)

Interpolate over saturated pixels, in place.

This method should be called after saturationDetection, to ensure that the saturated pixels have been identified in the SAT mask. It should also be called after assembleCcd, since saturated regions may cross amplifier boundaries.

Parameters

exposure : lsst.afw.image.Exposure Exposure to process.

See Also

lsst.ip.isr.isrTask.saturationDetection lsst.ip.isr.isrFunctions.interpolateFromMask

Definition at line 2072 of file isrTask.py.

2072  def saturationInterpolation(self, exposure):
2073  """!Interpolate over saturated pixels, in place.
2074 
2075  This method should be called after `saturationDetection`, to
2076  ensure that the saturated pixels have been identified in the
2077  SAT mask. It should also be called after `assembleCcd`, since
2078  saturated regions may cross amplifier boundaries.
2079 
2080  Parameters
2081  ----------
2082  exposure : `lsst.afw.image.Exposure`
2083  Exposure to process.
2084 
2085  See Also
2086  --------
2087  lsst.ip.isr.isrTask.saturationDetection
2088  lsst.ip.isr.isrFunctions.interpolateFromMask
2089  """
2090  isrFunctions.interpolateFromMask(
2091  maskedImage=exposure.getMaskedImage(),
2092  fwhm=self.config.fwhm,
2093  growSaturatedFootprints=self.config.growSaturationFootprintSize,
2094  maskNameList=list(self.config.saturatedMaskName),
2095  )
2096 

◆ setValidPolygonIntersect()

def lsst.ip.isr.isrTask.IsrTask.setValidPolygonIntersect (   self,
  ccdExposure,
  fpPolygon 
)

Set the valid polygon as the intersection of fpPolygon and the ccd corners.

Parameters

ccdExposure : lsst.afw.image.Exposure Exposure to process. fpPolygon : lsst.afw.geom.Polygon Polygon in focal plane coordinates.

Definition at line 2339 of file isrTask.py.

2339  def setValidPolygonIntersect(self, ccdExposure, fpPolygon):
2340  """!Set the valid polygon as the intersection of fpPolygon and the ccd corners.
2341 
2342  Parameters
2343  ----------
2344  ccdExposure : `lsst.afw.image.Exposure`
2345  Exposure to process.
2346  fpPolygon : `lsst.afw.geom.Polygon`
2347  Polygon in focal plane coordinates.
2348  """
2349  # Get ccd corners in focal plane coordinates
2350  ccd = ccdExposure.getDetector()
2351  fpCorners = ccd.getCorners(FOCAL_PLANE)
2352  ccdPolygon = Polygon(fpCorners)
2353 
2354  # Get intersection of ccd corners with fpPolygon
2355  intersect = ccdPolygon.intersectionSingle(fpPolygon)
2356 
2357  # Transform back to pixel positions and build new polygon
2358  ccdPoints = ccd.transform(intersect, FOCAL_PLANE, PIXELS)
2359  validPolygon = Polygon(ccdPoints)
2360  ccdExposure.getInfo().setValidPolygon(validPolygon)
2361 

◆ suspectDetection()

def lsst.ip.isr.isrTask.IsrTask.suspectDetection (   self,
  exposure,
  amp 
)

Detect suspect pixels and mask them using mask plane config.suspectMaskName, in place.

Parameters

exposure : lsst.afw.image.Exposure Exposure to process. Only the amplifier DataSec is processed. amp : lsst.afw.table.AmpInfoCatalog Amplifier detector data.

See Also

lsst.ip.isr.isrFunctions.makeThresholdMask

Notes

Suspect pixels are pixels whose value is greater than amp.getSuspectLevel(). This is intended to indicate pixels that may be affected by unknown systematics; for example if non-linearity corrections above a certain level are unstable then that would be a useful value for suspectLevel. A value of nan indicates that no such level exists and no pixels are to be masked as suspicious.

Definition at line 2097 of file isrTask.py.

2097  def suspectDetection(self, exposure, amp):
2098  """!Detect suspect pixels and mask them using mask plane config.suspectMaskName, in place.
2099 
2100  Parameters
2101  ----------
2102  exposure : `lsst.afw.image.Exposure`
2103  Exposure to process. Only the amplifier DataSec is processed.
2104  amp : `lsst.afw.table.AmpInfoCatalog`
2105  Amplifier detector data.
2106 
2107  See Also
2108  --------
2109  lsst.ip.isr.isrFunctions.makeThresholdMask
2110 
2111  Notes
2112  -----
2113  Suspect pixels are pixels whose value is greater than amp.getSuspectLevel().
2114  This is intended to indicate pixels that may be affected by unknown systematics;
2115  for example if non-linearity corrections above a certain level are unstable
2116  then that would be a useful value for suspectLevel. A value of `nan` indicates
2117  that no such level exists and no pixels are to be masked as suspicious.
2118  """
2119  suspectLevel = amp.getSuspectLevel()
2120  if math.isnan(suspectLevel):
2121  return
2122 
2123  maskedImage = exposure.getMaskedImage()
2124  dataView = maskedImage.Factory(maskedImage, amp.getRawBBox())
2125  isrFunctions.makeThresholdMask(
2126  maskedImage=dataView,
2127  threshold=suspectLevel,
2128  growFootprints=0,
2129  maskName=self.config.suspectMaskName,
2130  )
2131 

◆ updateVariance()

def lsst.ip.isr.isrTask.IsrTask.updateVariance (   self,
  ampExposure,
  amp,
  overscanImage = None 
)
Set the variance plane using the amplifier gain and read noise

The read noise is calculated from the ``overscanImage`` if the
``doEmpiricalReadNoise`` option is set in the configuration; otherwise
the value from the amplifier data is used.

Parameters
----------
ampExposure : `lsst.afw.image.Exposure`
    Exposure to process.
amp : `lsst.afw.table.AmpInfoRecord` or `FakeAmp`
    Amplifier detector data.
overscanImage : `lsst.afw.image.MaskedImage`, optional.
    Image of overscan, required only for empirical read noise.

See also
--------
lsst.ip.isr.isrFunctions.updateVariance

Definition at line 1911 of file isrTask.py.

1911  def updateVariance(self, ampExposure, amp, overscanImage=None):
1912  """Set the variance plane using the amplifier gain and read noise
1913 
1914  The read noise is calculated from the ``overscanImage`` if the
1915  ``doEmpiricalReadNoise`` option is set in the configuration; otherwise
1916  the value from the amplifier data is used.
1917 
1918  Parameters
1919  ----------
1920  ampExposure : `lsst.afw.image.Exposure`
1921  Exposure to process.
1922  amp : `lsst.afw.table.AmpInfoRecord` or `FakeAmp`
1923  Amplifier detector data.
1924  overscanImage : `lsst.afw.image.MaskedImage`, optional.
1925  Image of overscan, required only for empirical read noise.
1926 
1927  See also
1928  --------
1929  lsst.ip.isr.isrFunctions.updateVariance
1930  """
1931  maskPlanes = [self.config.saturatedMaskName, self.config.suspectMaskName]
1932  gain = amp.getGain()
1933 
1934  if math.isnan(gain):
1935  gain = 1.0
1936  self.log.warn("Gain set to NAN! Updating to 1.0 to generate Poisson variance.")
1937  elif gain <= 0:
1938  patchedGain = 1.0
1939  self.log.warn("Gain for amp %s == %g <= 0; setting to %f.",
1940  amp.getName(), gain, patchedGain)
1941  gain = patchedGain
1942 
1943  if self.config.doEmpiricalReadNoise and overscanImage is None:
1944  self.log.info("Overscan is none for EmpiricalReadNoise.")
1945 
1946  if self.config.doEmpiricalReadNoise and overscanImage is not None:
1947  stats = afwMath.StatisticsControl()
1948  stats.setAndMask(overscanImage.mask.getPlaneBitMask(maskPlanes))
1949  readNoise = afwMath.makeStatistics(overscanImage, afwMath.STDEVCLIP, stats).getValue()
1950  self.log.info("Calculated empirical read noise for amp %s: %f.",
1951  amp.getName(), readNoise)
1952  else:
1953  readNoise = amp.getReadNoise()
1954 
1955  isrFunctions.updateVariance(
1956  maskedImage=ampExposure.getMaskedImage(),
1957  gain=gain,
1958  readNoise=readNoise,
1959  )
1960 

Member Data Documentation

◆ ConfigClass

lsst.ip.isr.isrTask.IsrTask.ConfigClass = IsrTaskConfig
static

Definition at line 813 of file isrTask.py.

◆ vignettePolygon

lsst.ip.isr.isrTask.IsrTask.vignettePolygon

Definition at line 1435 of file isrTask.py.


The documentation for this class was generated from the following file:
lsst::log.log.logContinued.warn
def warn(fmt, *args)
Definition: logContinued.py:202
lsst::log.log.logContinued.info
def info(fmt, *args)
Definition: logContinued.py:198
lsst::afw::image::Mask
Represent a 2-dimensional array of bitmask pixels.
Definition: Mask.h:77
lsst::afw.display.ds9.getDisplay
getDisplay
Definition: ds9.py:34
lsst::afw::image::Exposure
A class to contain the data, WCS, and other information needed to describe an image of the sky.
Definition: Exposure.h:72
lsst::afw::image::Filter
Holds an integer identifier for an LSST filter.
Definition: Filter.h:141
lsst.gdb.afw.printers.debug
bool debug
Definition: printers.py:9
lsst::afw::image::makeExposure
std::shared_ptr< Exposure< ImagePixelT, MaskPixelT, VariancePixelT > > makeExposure(MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > &mimage, std::shared_ptr< geom::SkyWcs const > wcs=std::shared_ptr< geom::SkyWcs const >())
A function to return an Exposure of the correct type (cf.
Definition: Exposure.h:442
lsstDebug.getDebugFrame
def getDebugFrame(debugDisplay, name)
Definition: lsstDebug.py:90
pex.config.history.format
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
lsst::afw::math::makeStatistics
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
lsst::afw::image::makePhotoCalibFromCalibZeroPoint
std::shared_ptr< PhotoCalib > makePhotoCalibFromCalibZeroPoint(double instFluxMag0, double instFluxMag0Err)
Construct a PhotoCalib from the deprecated Calib-style instFluxMag0/instFluxMag0Err values.
Definition: PhotoCalib.cc:614
lsst::ip::isr.isrFunctions.flatCorrection
def flatCorrection(maskedImage, flatMaskedImage, scalingType, userScale=1.0, invert=False, trimToFit=False)
Definition: isrFunctions.py:360
lsst::ip::isr.isrFunctions.darkCorrection
def darkCorrection(maskedImage, darkMaskedImage, expScale, darkScale, invert=False, trimToFit=False)
Definition: isrFunctions.py:298
lsst::ip::isr.isrFunctions.overscanCorrection
def overscanCorrection(ampMaskedImage, overscanImage, fitType='MEDIAN', order=1, collapseRej=3.0, statControl=None, overscanIsInt=True)
Definition: isrFunctions.py:441
lsst.pipe.tasks.assembleCoadd.run
def run(self, skyInfo, tempExpRefList, imageScalerList, weightList, altMaskList=None, mask=None, supplementaryData=None)
Definition: assembleCoadd.py:712
astshim.fitsChanContinued.contains
def contains(self, name)
Definition: fitsChanContinued.py:127
lsst::ip::isr::maskNans
size_t maskNans(afw::image::MaskedImage< PixelT > const &mi, afw::image::MaskPixel maskVal, afw::image::MaskPixel allow=0)
Mask NANs in an image.
Definition: Isr.cc:35
lsstDebug.getInfo
getInfo
Definition: lsstDebug.py:87
lsst::ip::isr.isrFunctions.updateVariance
def updateVariance(maskedImage, gain, readNoise)
Definition: isrFunctions.py:342
lsst::afw::math::StatisticsControl
Pass parameters to a Statistics object.
Definition: Statistics.h:93
list
daf::base::PropertyList * list
Definition: fits.cc:913
type
table::Key< int > type
Definition: Detector.cc:163
lsst::geom::Point< int, 2 >
lsst::geom::Box2I
An integer coordinate rectangle.
Definition: Box.h:55
lsst::afw::image::makeMaskedImage
MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > * makeMaskedImage(typename std::shared_ptr< Image< ImagePixelT >> image, typename std::shared_ptr< Mask< MaskPixelT >> mask=Mask< MaskPixelT >(), typename std::shared_ptr< Image< VariancePixelT >> variance=Image< VariancePixelT >())
A function to return a MaskedImage of the correct type (cf.
Definition: MaskedImage.h:1279
lsst::geom::Extent< int, 2 >
set
daf::base::PropertySet * set
Definition: fits.cc:912