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

Public Member Functions

def __init__ (self, *args, **kwargs)
 
def run (self, scienceExposure, templateExposure, doWarping=True)
 
def subtractExposures (self, templateExposure, scienceExposure, *args)
 
def subtractMaskedImages (self, templateExposure, scienceExposure, *args)
 
def getFwhmPix (self, psf)
 
def matchExposures (self, templateExposure, scienceExposure, templateFwhmPix=None, scienceFwhmPix=None, candidateList=None, doWarping=True, convolveTemplate=True)
 
def matchMaskedImages (self, templateMaskedImage, scienceMaskedImage, candidateList, templateFwhmPix=None, scienceFwhmPix=None)
 
def subtractExposures (self, templateExposure, scienceExposure, templateFwhmPix=None, scienceFwhmPix=None, candidateList=None, doWarping=True, convolveTemplate=True)
 
def subtractMaskedImages (self, templateMaskedImage, scienceMaskedImage, candidateList, templateFwhmPix=None, scienceFwhmPix=None)
 
def getSelectSources (self, exposure, sigma=None, doSmooth=True, idFactory=None)
 
def makeCandidateList (self, templateExposure, scienceExposure, kernelSize, candidateList=None)
 
def makeKernelBasisList (self, targetFwhmPix=None, referenceFwhmPix=None, basisDegGauss=None, basisSigmaGauss=None, metadata=None)
 

Public Attributes

 kConfig
 
 background
 
 selectSchema
 
 selectAlgMetadata
 
 useRegularization
 
 hMat
 

Static Public Attributes

 ConfigClass = ZogyImagePsfMatchConfig
 

Detailed Description

Task to perform Zogy PSF matching and image subtraction.

This class inherits from ImagePsfMatchTask to contain the _warper
subtask and related methods.

Definition at line 1269 of file zogy.py.

Constructor & Destructor Documentation

◆ __init__()

def lsst.ip.diffim.zogy.ZogyImagePsfMatchTask.__init__ (   self,
args,
**  kwargs 
)
Create the ImagePsfMatchTask.

Reimplemented from lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.

Definition at line 1278 of file zogy.py.

1278  def __init__(self, *args, **kwargs):
1279  ImagePsfMatchTask.__init__(self, *args, **kwargs)
1280 

Member Function Documentation

◆ getFwhmPix()

def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.getFwhmPix (   self,
  psf 
)
inherited
Return the FWHM in pixels of a Psf.

Definition at line 334 of file imagePsfMatch.py.

334  def getFwhmPix(self, psf):
335  """Return the FWHM in pixels of a Psf.
336  """
337  sigPix = psf.computeShape().getDeterminantRadius()
338  return sigPix*sigma2fwhm
339 

◆ getSelectSources()

def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.getSelectSources (   self,
  exposure,
  sigma = None,
  doSmooth = True,
  idFactory = None 
)
inherited
Get sources to use for Psf-matching.

This method runs detection and measurement on an exposure.
The returned set of sources will be used as candidates for
Psf-matching.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure on which to run detection/measurement
sigma : `float`
    Detection threshold
doSmooth : `bool`
    Whether or not to smooth the Exposure with Psf before detection
idFactory :
    Factory for the generation of Source ids

Returns
-------
selectSources :
    source catalog containing candidates for the Psf-matching

Definition at line 760 of file imagePsfMatch.py.

760  def getSelectSources(self, exposure, sigma=None, doSmooth=True, idFactory=None):
761  """Get sources to use for Psf-matching.
762 
763  This method runs detection and measurement on an exposure.
764  The returned set of sources will be used as candidates for
765  Psf-matching.
766 
767  Parameters
768  ----------
769  exposure : `lsst.afw.image.Exposure`
770  Exposure on which to run detection/measurement
771  sigma : `float`
772  Detection threshold
773  doSmooth : `bool`
774  Whether or not to smooth the Exposure with Psf before detection
775  idFactory :
776  Factory for the generation of Source ids
777 
778  Returns
779  -------
780  selectSources :
781  source catalog containing candidates for the Psf-matching
782  """
783  if idFactory:
784  table = afwTable.SourceTable.make(self.selectSchema, idFactory)
785  else:
786  table = afwTable.SourceTable.make(self.selectSchema)
787  mi = exposure.getMaskedImage()
788 
789  imArr = mi.getImage().getArray()
790  maskArr = mi.getMask().getArray()
791  miArr = np.ma.masked_array(imArr, mask=maskArr)
792  try:
793  fitBg = self.background.fitBackground(mi)
794  bkgd = fitBg.getImageF(self.background.config.algorithm,
795  self.background.config.undersampleStyle)
796  except Exception:
797  self.log.warning("Failed to get background model. Falling back to median background estimation")
798  bkgd = np.ma.median(miArr)
799 
800  # Take off background for detection
801  mi -= bkgd
802  try:
803  table.setMetadata(self.selectAlgMetadata)
804  detRet = self.selectDetection.run(
805  table=table,
806  exposure=exposure,
807  sigma=sigma,
808  doSmooth=doSmooth
809  )
810  selectSources = detRet.sources
811  self.selectMeasurement.run(measCat=selectSources, exposure=exposure)
812  finally:
813  # Put back on the background in case it is needed down stream
814  mi += bkgd
815  del bkgd
816  return selectSources
817 
def run(self, coaddExposures, bbox, wcs)
Definition: getTemplate.py:603

◆ makeCandidateList()

def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.makeCandidateList (   self,
  templateExposure,
  scienceExposure,
  kernelSize,
  candidateList = None 
)
inherited
Make a list of acceptable KernelCandidates.

Accept or generate a list of candidate sources for
Psf-matching, and examine the Mask planes in both of the
images for indications of bad pixels

Parameters
----------
templateExposure : `lsst.afw.image.Exposure`
    Exposure that will be convolved
scienceExposure : `lsst.afw.image.Exposure`
    Exposure that will be matched-to
kernelSize : `float`
    Dimensions of the Psf-matching Kernel, used to grow detection footprints
candidateList : `list`, optional
    List of Sources to examine. Elements must be of type afw.table.Source
    or a type that wraps a Source and has a getSource() method, such as
    meas.algorithms.PsfCandidateF.

Returns
-------
candidateList : `list` of `dict`
    A list of dicts having a "source" and "footprint"
    field for the Sources deemed to be appropriate for Psf
    matching

Definition at line 818 of file imagePsfMatch.py.

818  def makeCandidateList(self, templateExposure, scienceExposure, kernelSize, candidateList=None):
819  """Make a list of acceptable KernelCandidates.
820 
821  Accept or generate a list of candidate sources for
822  Psf-matching, and examine the Mask planes in both of the
823  images for indications of bad pixels
824 
825  Parameters
826  ----------
827  templateExposure : `lsst.afw.image.Exposure`
828  Exposure that will be convolved
829  scienceExposure : `lsst.afw.image.Exposure`
830  Exposure that will be matched-to
831  kernelSize : `float`
832  Dimensions of the Psf-matching Kernel, used to grow detection footprints
833  candidateList : `list`, optional
834  List of Sources to examine. Elements must be of type afw.table.Source
835  or a type that wraps a Source and has a getSource() method, such as
836  meas.algorithms.PsfCandidateF.
837 
838  Returns
839  -------
840  candidateList : `list` of `dict`
841  A list of dicts having a "source" and "footprint"
842  field for the Sources deemed to be appropriate for Psf
843  matching
844  """
845  if candidateList is None:
846  candidateList = self.getSelectSources(scienceExposure)
847 
848  if len(candidateList) < 1:
849  raise RuntimeError("No candidates in candidateList")
850 
851  listTypes = set(type(x) for x in candidateList)
852  if len(listTypes) > 1:
853  raise RuntimeError("Candidate list contains mixed types: %s" % [t for t in listTypes])
854 
855  if not isinstance(candidateList[0], afwTable.SourceRecord):
856  try:
857  candidateList[0].getSource()
858  except Exception as e:
859  raise RuntimeError(f"Candidate List is of type: {type(candidateList[0])} "
860  "Can only make candidate list from list of afwTable.SourceRecords, "
861  f"measAlg.PsfCandidateF or other type with a getSource() method: {e}")
862  candidateList = [c.getSource() for c in candidateList]
863 
864  candidateList = diffimTools.sourceToFootprintList(candidateList,
865  templateExposure, scienceExposure,
866  kernelSize,
867  self.kConfig.detectionConfig,
868  self.log)
869  if len(candidateList) == 0:
870  raise RuntimeError("Cannot find any objects suitable for KernelCandidacy")
871 
872  return candidateList
873 
table::Key< int > type
Definition: Detector.cc:163
Record class that contains measurements made on a single exposure.
Definition: Source.h:78
daf::base::PropertySet * set
Definition: fits.cc:912

◆ makeKernelBasisList()

def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.makeKernelBasisList (   self,
  targetFwhmPix = None,
  referenceFwhmPix = None,
  basisDegGauss = None,
  basisSigmaGauss = None,
  metadata = None 
)
inherited
Wrapper to set log messages for
`lsst.ip.diffim.makeKernelBasisList`.

Parameters
----------
targetFwhmPix : `float`, optional
    Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
    Not used for delta function basis sets.
referenceFwhmPix : `float`, optional
    Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
    Not used for delta function basis sets.
basisDegGauss : `list` of `int`, optional
    Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
    Not used for delta function basis sets.
basisSigmaGauss : `list` of `int`, optional
    Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
    Not used for delta function basis sets.
metadata : `lsst.daf.base.PropertySet`, optional
    Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
    Not used for delta function basis sets.

Returns
-------
basisList: `list` of `lsst.afw.math.kernel.FixedKernel`
    List of basis kernels.

Definition at line 874 of file imagePsfMatch.py.

875  basisDegGauss=None, basisSigmaGauss=None, metadata=None):
876  """Wrapper to set log messages for
877  `lsst.ip.diffim.makeKernelBasisList`.
878 
879  Parameters
880  ----------
881  targetFwhmPix : `float`, optional
882  Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
883  Not used for delta function basis sets.
884  referenceFwhmPix : `float`, optional
885  Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
886  Not used for delta function basis sets.
887  basisDegGauss : `list` of `int`, optional
888  Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
889  Not used for delta function basis sets.
890  basisSigmaGauss : `list` of `int`, optional
891  Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
892  Not used for delta function basis sets.
893  metadata : `lsst.daf.base.PropertySet`, optional
894  Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
895  Not used for delta function basis sets.
896 
897  Returns
898  -------
899  basisList: `list` of `lsst.afw.math.kernel.FixedKernel`
900  List of basis kernels.
901  """
902  basisList = makeKernelBasisList(self.kConfig,
903  targetFwhmPix=targetFwhmPix,
904  referenceFwhmPix=referenceFwhmPix,
905  basisDegGauss=basisDegGauss,
906  basisSigmaGauss=basisSigmaGauss,
907  metadata=metadata)
908  if targetFwhmPix == referenceFwhmPix:
909  self.log.info("Target and reference psf fwhms are equal, falling back to config values")
910  elif referenceFwhmPix > targetFwhmPix:
911  self.log.info("Reference psf fwhm is the greater, normal convolution mode")
912  else:
913  self.log.info("Target psf fwhm is the greater, deconvolution mode")
914 
915  return basisList
916 
def makeKernelBasisList(config, targetFwhmPix=None, referenceFwhmPix=None, basisDegGauss=None, basisSigmaGauss=None, metadata=None)

◆ matchExposures()

def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.matchExposures (   self,
  templateExposure,
  scienceExposure,
  templateFwhmPix = None,
  scienceFwhmPix = None,
  candidateList = None,
  doWarping = True,
  convolveTemplate = True 
)
inherited
Warp and PSF-match an exposure to the reference.

Do the following, in order:

- Warp templateExposure to match scienceExposure,
    if doWarping True and their WCSs do not already match
- Determine a PSF matching kernel and differential background model
    that matches templateExposure to scienceExposure
- Convolve templateExposure by PSF matching kernel

Parameters
----------
templateExposure : `lsst.afw.image.Exposure`
    Exposure to warp and PSF-match to the reference masked image
scienceExposure : `lsst.afw.image.Exposure`
    Exposure whose WCS and PSF are to be matched to
templateFwhmPix :`float`
    FWHM (in pixels) of the Psf in the template image (image to convolve)
scienceFwhmPix : `float`
    FWHM (in pixels) of the Psf in the science image
candidateList : `list`, optional
    a list of footprints/maskedImages for kernel candidates;
    if `None` then source detection is run.

    - Currently supported: list of Footprints or measAlg.PsfCandidateF

doWarping : `bool`
    what to do if ``templateExposure`` and ``scienceExposure`` WCSs do not match:

    - if `True` then warp ``templateExposure`` to match ``scienceExposure``
    - if `False` then raise an Exception

convolveTemplate : `bool`
    Whether to convolve the template image or the science image:

    - if `True`, ``templateExposure`` is warped if doWarping,
      ``templateExposure`` is convolved
    - if `False`, ``templateExposure`` is warped if doWarping,
      ``scienceExposure`` is convolved

Returns
-------
results : `lsst.pipe.base.Struct`
    An `lsst.pipe.base.Struct` containing these fields:

    - ``matchedImage`` : the PSF-matched exposure =
        Warped ``templateExposure`` convolved by psfMatchingKernel. This has:

        - the same parent bbox, Wcs and PhotoCalib as scienceExposure
        - the same filter as templateExposure
        - no Psf (because the PSF-matching process does not compute one)

    - ``psfMatchingKernel`` : the PSF matching kernel
    - ``backgroundModel`` : differential background model
    - ``kernelCellSet`` : SpatialCellSet used to solve for the PSF matching kernel

Raises
------
RuntimeError
   Raised if doWarping is False and ``templateExposure`` and
   ``scienceExposure`` WCSs do not match

Definition at line 341 of file imagePsfMatch.py.

343  candidateList=None, doWarping=True, convolveTemplate=True):
344  """Warp and PSF-match an exposure to the reference.
345 
346  Do the following, in order:
347 
348  - Warp templateExposure to match scienceExposure,
349  if doWarping True and their WCSs do not already match
350  - Determine a PSF matching kernel and differential background model
351  that matches templateExposure to scienceExposure
352  - Convolve templateExposure by PSF matching kernel
353 
354  Parameters
355  ----------
356  templateExposure : `lsst.afw.image.Exposure`
357  Exposure to warp and PSF-match to the reference masked image
358  scienceExposure : `lsst.afw.image.Exposure`
359  Exposure whose WCS and PSF are to be matched to
360  templateFwhmPix :`float`
361  FWHM (in pixels) of the Psf in the template image (image to convolve)
362  scienceFwhmPix : `float`
363  FWHM (in pixels) of the Psf in the science image
364  candidateList : `list`, optional
365  a list of footprints/maskedImages for kernel candidates;
366  if `None` then source detection is run.
367 
368  - Currently supported: list of Footprints or measAlg.PsfCandidateF
369 
370  doWarping : `bool`
371  what to do if ``templateExposure`` and ``scienceExposure`` WCSs do not match:
372 
373  - if `True` then warp ``templateExposure`` to match ``scienceExposure``
374  - if `False` then raise an Exception
375 
376  convolveTemplate : `bool`
377  Whether to convolve the template image or the science image:
378 
379  - if `True`, ``templateExposure`` is warped if doWarping,
380  ``templateExposure`` is convolved
381  - if `False`, ``templateExposure`` is warped if doWarping,
382  ``scienceExposure`` is convolved
383 
384  Returns
385  -------
386  results : `lsst.pipe.base.Struct`
387  An `lsst.pipe.base.Struct` containing these fields:
388 
389  - ``matchedImage`` : the PSF-matched exposure =
390  Warped ``templateExposure`` convolved by psfMatchingKernel. This has:
391 
392  - the same parent bbox, Wcs and PhotoCalib as scienceExposure
393  - the same filter as templateExposure
394  - no Psf (because the PSF-matching process does not compute one)
395 
396  - ``psfMatchingKernel`` : the PSF matching kernel
397  - ``backgroundModel`` : differential background model
398  - ``kernelCellSet`` : SpatialCellSet used to solve for the PSF matching kernel
399 
400  Raises
401  ------
402  RuntimeError
403  Raised if doWarping is False and ``templateExposure`` and
404  ``scienceExposure`` WCSs do not match
405  """
406  if not self._validateWcs(templateExposure, scienceExposure):
407  if doWarping:
408  self.log.info("Astrometrically registering template to science image")
409  templatePsf = templateExposure.getPsf()
410  # Warp PSF before overwriting exposure
411  xyTransform = afwGeom.makeWcsPairTransform(templateExposure.getWcs(),
412  scienceExposure.getWcs())
413  psfWarped = WarpedPsf(templatePsf, xyTransform)
414  templateExposure = self._warper.warpExposure(scienceExposure.getWcs(),
415  templateExposure,
416  destBBox=scienceExposure.getBBox())
417  templateExposure.setPsf(psfWarped)
418  else:
419  self.log.error("ERROR: Input images not registered")
420  raise RuntimeError("Input images not registered")
421 
422  if templateFwhmPix is None:
423  if not templateExposure.hasPsf():
424  self.log.warning("No estimate of Psf FWHM for template image")
425  else:
426  templateFwhmPix = self.getFwhmPix(templateExposure.getPsf())
427  self.log.info("templateFwhmPix: %s", templateFwhmPix)
428 
429  if scienceFwhmPix is None:
430  if not scienceExposure.hasPsf():
431  self.log.warning("No estimate of Psf FWHM for science image")
432  else:
433  scienceFwhmPix = self.getFwhmPix(scienceExposure.getPsf())
434  self.log.info("scienceFwhmPix: %s", scienceFwhmPix)
435 
436  if convolveTemplate:
437  kernelSize = self.makeKernelBasisList(templateFwhmPix, scienceFwhmPix)[0].getWidth()
438  candidateList = self.makeCandidateList(
439  templateExposure, scienceExposure, kernelSize, candidateList)
440  results = self.matchMaskedImages(
441  templateExposure.getMaskedImage(), scienceExposure.getMaskedImage(), candidateList,
442  templateFwhmPix=templateFwhmPix, scienceFwhmPix=scienceFwhmPix)
443  else:
444  kernelSize = self.makeKernelBasisList(scienceFwhmPix, templateFwhmPix)[0].getWidth()
445  candidateList = self.makeCandidateList(
446  templateExposure, scienceExposure, kernelSize, candidateList)
447  results = self.matchMaskedImages(
448  scienceExposure.getMaskedImage(), templateExposure.getMaskedImage(), candidateList,
449  templateFwhmPix=scienceFwhmPix, scienceFwhmPix=templateFwhmPix)
450 
451  psfMatchedExposure = afwImage.makeExposure(results.matchedImage, scienceExposure.getWcs())
452  psfMatchedExposure.setFilterLabel(templateExposure.getFilterLabel())
453  psfMatchedExposure.setPhotoCalib(scienceExposure.getPhotoCalib())
454  results.warpedExposure = templateExposure
455  results.matchedExposure = psfMatchedExposure
456  return results
457 
std::shared_ptr< TransformPoint2ToPoint2 > makeWcsPairTransform(SkyWcs const &src, SkyWcs const &dst)
A Transform obtained by putting two SkyWcs objects "back to back".
Definition: SkyWcs.cc:146
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:462
int warpExposure(DestExposureT &destExposure, SrcExposureT const &srcExposure, WarpingControl const &control, typename DestExposureT::MaskedImageT::SinglePixel padValue=lsst::afw::math::edgePixel< typename DestExposureT::MaskedImageT >(typename lsst::afw::image::detail::image_traits< typename DestExposureT::MaskedImageT >::image_category()))
Warp (remap) one exposure to another.

◆ matchMaskedImages()

def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.matchMaskedImages (   self,
  templateMaskedImage,
  scienceMaskedImage,
  candidateList,
  templateFwhmPix = None,
  scienceFwhmPix = None 
)
inherited
PSF-match a MaskedImage (templateMaskedImage) to a reference MaskedImage (scienceMaskedImage).

Do the following, in order:

- Determine a PSF matching kernel and differential background model
    that matches templateMaskedImage to scienceMaskedImage
- Convolve templateMaskedImage by the PSF matching kernel

Parameters
----------
templateMaskedImage : `lsst.afw.image.MaskedImage`
    masked image to PSF-match to the reference masked image;
    must be warped to match the reference masked image
scienceMaskedImage : `lsst.afw.image.MaskedImage`
    maskedImage whose PSF is to be matched to
templateFwhmPix : `float`
    FWHM (in pixels) of the Psf in the template image (image to convolve)
scienceFwhmPix : `float`
    FWHM (in pixels) of the Psf in the science image
candidateList : `list`, optional
    A list of footprints/maskedImages for kernel candidates;
    if `None` then source detection is run.

    - Currently supported: list of Footprints or measAlg.PsfCandidateF

Returns
-------
result : `callable`
An `lsst.pipe.base.Struct` containing these fields:

- psfMatchedMaskedImage: the PSF-matched masked image =
    ``templateMaskedImage`` convolved with psfMatchingKernel.
    This has the same xy0, dimensions and wcs as ``scienceMaskedImage``.
- psfMatchingKernel: the PSF matching kernel
- backgroundModel: differential background model
- kernelCellSet: SpatialCellSet used to solve for the PSF matching kernel

Raises
------
RuntimeError
    Raised if input images have different dimensions

Definition at line 459 of file imagePsfMatch.py.

460  templateFwhmPix=None, scienceFwhmPix=None):
461  """PSF-match a MaskedImage (templateMaskedImage) to a reference MaskedImage (scienceMaskedImage).
462 
463  Do the following, in order:
464 
465  - Determine a PSF matching kernel and differential background model
466  that matches templateMaskedImage to scienceMaskedImage
467  - Convolve templateMaskedImage by the PSF matching kernel
468 
469  Parameters
470  ----------
471  templateMaskedImage : `lsst.afw.image.MaskedImage`
472  masked image to PSF-match to the reference masked image;
473  must be warped to match the reference masked image
474  scienceMaskedImage : `lsst.afw.image.MaskedImage`
475  maskedImage whose PSF is to be matched to
476  templateFwhmPix : `float`
477  FWHM (in pixels) of the Psf in the template image (image to convolve)
478  scienceFwhmPix : `float`
479  FWHM (in pixels) of the Psf in the science image
480  candidateList : `list`, optional
481  A list of footprints/maskedImages for kernel candidates;
482  if `None` then source detection is run.
483 
484  - Currently supported: list of Footprints or measAlg.PsfCandidateF
485 
486  Returns
487  -------
488  result : `callable`
489  An `lsst.pipe.base.Struct` containing these fields:
490 
491  - psfMatchedMaskedImage: the PSF-matched masked image =
492  ``templateMaskedImage`` convolved with psfMatchingKernel.
493  This has the same xy0, dimensions and wcs as ``scienceMaskedImage``.
494  - psfMatchingKernel: the PSF matching kernel
495  - backgroundModel: differential background model
496  - kernelCellSet: SpatialCellSet used to solve for the PSF matching kernel
497 
498  Raises
499  ------
500  RuntimeError
501  Raised if input images have different dimensions
502  """
503  import lsstDebug
504  display = lsstDebug.Info(__name__).display
505  displayTemplate = lsstDebug.Info(__name__).displayTemplate
506  displaySciIm = lsstDebug.Info(__name__).displaySciIm
507  displaySpatialCells = lsstDebug.Info(__name__).displaySpatialCells
508  maskTransparency = lsstDebug.Info(__name__).maskTransparency
509  if not maskTransparency:
510  maskTransparency = 0
511  if display:
512  afwDisplay.setDefaultMaskTransparency(maskTransparency)
513 
514  if not candidateList:
515  raise RuntimeError("Candidate list must be populated by makeCandidateList")
516 
517  if not self._validateSize(templateMaskedImage, scienceMaskedImage):
518  self.log.error("ERROR: Input images different size")
519  raise RuntimeError("Input images different size")
520 
521  if display and displayTemplate:
522  disp = afwDisplay.Display(frame=lsstDebug.frame)
523  disp.mtv(templateMaskedImage, title="Image to convolve")
524  lsstDebug.frame += 1
525 
526  if display and displaySciIm:
527  disp = afwDisplay.Display(frame=lsstDebug.frame)
528  disp.mtv(scienceMaskedImage, title="Image to not convolve")
529  lsstDebug.frame += 1
530 
531  kernelCellSet = self._buildCellSet(templateMaskedImage,
532  scienceMaskedImage,
533  candidateList)
534 
535  if display and displaySpatialCells:
536  diffimUtils.showKernelSpatialCells(scienceMaskedImage, kernelCellSet,
537  symb="o", ctype=afwDisplay.CYAN, ctypeUnused=afwDisplay.YELLOW,
538  ctypeBad=afwDisplay.RED, size=4, frame=lsstDebug.frame,
539  title="Image to not convolve")
540  lsstDebug.frame += 1
541 
542  if templateFwhmPix and scienceFwhmPix:
543  self.log.info("Matching Psf FWHM %.2f -> %.2f pix", templateFwhmPix, scienceFwhmPix)
544 
545  if self.kConfig.useBicForKernelBasis:
546  tmpKernelCellSet = self._buildCellSet(templateMaskedImage,
547  scienceMaskedImage,
548  candidateList)
549  nbe = diffimTools.NbasisEvaluator(self.kConfig, templateFwhmPix, scienceFwhmPix)
550  bicDegrees = nbe(tmpKernelCellSet, self.log)
551  basisList = self.makeKernelBasisList(templateFwhmPix, scienceFwhmPix,
552  basisDegGauss=bicDegrees[0], metadata=self.metadata)
553  del tmpKernelCellSet
554  else:
555  basisList = self.makeKernelBasisList(templateFwhmPix, scienceFwhmPix,
556  metadata=self.metadata)
557 
558  spatialSolution, psfMatchingKernel, backgroundModel = self._solve(kernelCellSet, basisList)
559 
560  psfMatchedMaskedImage = afwImage.MaskedImageF(templateMaskedImage.getBBox())
561  convolutionControl = afwMath.ConvolutionControl()
562  convolutionControl.setDoNormalize(False)
563  afwMath.convolve(psfMatchedMaskedImage, templateMaskedImage, psfMatchingKernel, convolutionControl)
564  return pipeBase.Struct(
565  matchedImage=psfMatchedMaskedImage,
566  psfMatchingKernel=psfMatchingKernel,
567  backgroundModel=backgroundModel,
568  kernelCellSet=kernelCellSet,
569  )
570 
Parameters to control convolution.
Definition: ConvolveImage.h:50
void convolve(OutImageT &convolvedImage, InImageT const &inImage, KernelT const &kernel, ConvolutionControl const &convolutionControl=ConvolutionControl())
Convolve an Image or MaskedImage with a Kernel, setting pixels of an existing output image.

◆ run()

def lsst.ip.diffim.zogy.ZogyImagePsfMatchTask.run (   self,
  scienceExposure,
  templateExposure,
  doWarping = True 
)
Register, PSF-match, and subtract two Exposures, ``scienceExposure - templateExposure``
using the ZOGY algorithm.

Parameters
----------
templateExposure : `lsst.afw.image.Exposure`
    exposure to be warped to scienceExposure.
scienceExposure : `lsst.afw.image.Exposure`
    reference Exposure.
doWarping : `bool`
    what to do if templateExposure's and scienceExposure's WCSs do not match:
    - if True then warp templateExposure to match scienceExposure
    - if False then raise an Exception

Notes
-----
Do the following, in order:
    - Warp templateExposure to match scienceExposure, if their WCSs do not already match
    - Compute subtracted exposure ZOGY image subtraction algorithm on the two exposures

This is the new entry point of the task as of DM-25115.

Returns
-------
results : `lsst.pipe.base.Struct` containing these fields:
    - subtractedExposure: `lsst.afw.image.Exposure`
        The subtraction result.
    - warpedExposure: `lsst.afw.image.Exposure` or `None`
        templateExposure after warping to match scienceExposure

Definition at line 1281 of file zogy.py.

1281  def run(self, scienceExposure, templateExposure, doWarping=True):
1282  """Register, PSF-match, and subtract two Exposures, ``scienceExposure - templateExposure``
1283  using the ZOGY algorithm.
1284 
1285  Parameters
1286  ----------
1287  templateExposure : `lsst.afw.image.Exposure`
1288  exposure to be warped to scienceExposure.
1289  scienceExposure : `lsst.afw.image.Exposure`
1290  reference Exposure.
1291  doWarping : `bool`
1292  what to do if templateExposure's and scienceExposure's WCSs do not match:
1293  - if True then warp templateExposure to match scienceExposure
1294  - if False then raise an Exception
1295 
1296  Notes
1297  -----
1298  Do the following, in order:
1299  - Warp templateExposure to match scienceExposure, if their WCSs do not already match
1300  - Compute subtracted exposure ZOGY image subtraction algorithm on the two exposures
1301 
1302  This is the new entry point of the task as of DM-25115.
1303 
1304  Returns
1305  -------
1306  results : `lsst.pipe.base.Struct` containing these fields:
1307  - subtractedExposure: `lsst.afw.image.Exposure`
1308  The subtraction result.
1309  - warpedExposure: `lsst.afw.image.Exposure` or `None`
1310  templateExposure after warping to match scienceExposure
1311  """
1312 
1313  if not self._validateWcs(scienceExposure, templateExposure):
1314  if doWarping:
1315  self.log.info("Warping templateExposure to scienceExposure")
1316  xyTransform = afwGeom.makeWcsPairTransform(templateExposure.getWcs(),
1317  scienceExposure.getWcs())
1318  psfWarped = measAlg.WarpedPsf(templateExposure.getPsf(), xyTransform)
1319  templateExposure = self._warper.warpExposure(
1320  scienceExposure.getWcs(), templateExposure, destBBox=scienceExposure.getBBox())
1321  templateExposure.setPsf(psfWarped)
1322  else:
1323  raise RuntimeError("Input images are not registered. Consider setting doWarping=True.")
1324 
1325  config = self.config.zogyConfig
1326  task = ZogyTask(config=config)
1327  results = task.run(scienceExposure, templateExposure)
1328  results.warpedExposure = templateExposure
1329  return results
1330 

◆ subtractExposures() [1/2]

def lsst.ip.diffim.zogy.ZogyImagePsfMatchTask.subtractExposures (   self,
  templateExposure,
  scienceExposure,
args 
)

Definition at line 1331 of file zogy.py.

1331  def subtractExposures(self, templateExposure, scienceExposure, *args):
1332  raise NotImplementedError
1333 

◆ subtractExposures() [2/2]

def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.subtractExposures (   self,
  templateExposure,
  scienceExposure,
  templateFwhmPix = None,
  scienceFwhmPix = None,
  candidateList = None,
  doWarping = True,
  convolveTemplate = True 
)
inherited
Register, Psf-match and subtract two Exposures.

Do the following, in order:

- Warp templateExposure to match scienceExposure, if their WCSs do not already match
- Determine a PSF matching kernel and differential background model
    that matches templateExposure to scienceExposure
- PSF-match templateExposure to scienceExposure
- Compute subtracted exposure (see return values for equation).

Parameters
----------
templateExposure : `lsst.afw.image.ExposureF`
    Exposure to PSF-match to scienceExposure
scienceExposure : `lsst.afw.image.ExposureF`
    Reference Exposure
templateFwhmPix : `float`
    FWHM (in pixels) of the Psf in the template image (image to convolve)
scienceFwhmPix : `float`
    FWHM (in pixels) of the Psf in the science image
candidateList : `list`, optional
    A list of footprints/maskedImages for kernel candidates;
    if `None` then source detection is run.

    - Currently supported: list of Footprints or measAlg.PsfCandidateF

doWarping : `bool`
    What to do if ``templateExposure``` and ``scienceExposure`` WCSs do
    not match:

    - if `True` then warp ``templateExposure`` to match ``scienceExposure``
    - if `False` then raise an Exception

convolveTemplate : `bool`
    Convolve the template image or the science image

    - if `True`, ``templateExposure`` is warped if doWarping,
      ``templateExposure`` is convolved
    - if `False`, ``templateExposure`` is warped if doWarping,
      ``scienceExposure is`` convolved

Returns
-------
result : `lsst.pipe.base.Struct`
    An `lsst.pipe.base.Struct` containing these fields:

    - ``subtractedExposure`` : subtracted Exposure
        scienceExposure - (matchedImage + backgroundModel)
    - ``matchedImage`` : ``templateExposure`` after warping to match
                         ``templateExposure`` (if doWarping true),
                         and convolving with psfMatchingKernel
    - ``psfMatchingKernel`` : PSF matching kernel
    - ``backgroundModel`` : differential background model
    - ``kernelCellSet`` : SpatialCellSet used to determine PSF matching kernel

Definition at line 572 of file imagePsfMatch.py.

574  candidateList=None, doWarping=True, convolveTemplate=True):
575  """Register, Psf-match and subtract two Exposures.
576 
577  Do the following, in order:
578 
579  - Warp templateExposure to match scienceExposure, if their WCSs do not already match
580  - Determine a PSF matching kernel and differential background model
581  that matches templateExposure to scienceExposure
582  - PSF-match templateExposure to scienceExposure
583  - Compute subtracted exposure (see return values for equation).
584 
585  Parameters
586  ----------
587  templateExposure : `lsst.afw.image.ExposureF`
588  Exposure to PSF-match to scienceExposure
589  scienceExposure : `lsst.afw.image.ExposureF`
590  Reference Exposure
591  templateFwhmPix : `float`
592  FWHM (in pixels) of the Psf in the template image (image to convolve)
593  scienceFwhmPix : `float`
594  FWHM (in pixels) of the Psf in the science image
595  candidateList : `list`, optional
596  A list of footprints/maskedImages for kernel candidates;
597  if `None` then source detection is run.
598 
599  - Currently supported: list of Footprints or measAlg.PsfCandidateF
600 
601  doWarping : `bool`
602  What to do if ``templateExposure``` and ``scienceExposure`` WCSs do
603  not match:
604 
605  - if `True` then warp ``templateExposure`` to match ``scienceExposure``
606  - if `False` then raise an Exception
607 
608  convolveTemplate : `bool`
609  Convolve the template image or the science image
610 
611  - if `True`, ``templateExposure`` is warped if doWarping,
612  ``templateExposure`` is convolved
613  - if `False`, ``templateExposure`` is warped if doWarping,
614  ``scienceExposure is`` convolved
615 
616  Returns
617  -------
618  result : `lsst.pipe.base.Struct`
619  An `lsst.pipe.base.Struct` containing these fields:
620 
621  - ``subtractedExposure`` : subtracted Exposure
622  scienceExposure - (matchedImage + backgroundModel)
623  - ``matchedImage`` : ``templateExposure`` after warping to match
624  ``templateExposure`` (if doWarping true),
625  and convolving with psfMatchingKernel
626  - ``psfMatchingKernel`` : PSF matching kernel
627  - ``backgroundModel`` : differential background model
628  - ``kernelCellSet`` : SpatialCellSet used to determine PSF matching kernel
629  """
630  results = self.matchExposures(
631  templateExposure=templateExposure,
632  scienceExposure=scienceExposure,
633  templateFwhmPix=templateFwhmPix,
634  scienceFwhmPix=scienceFwhmPix,
635  candidateList=candidateList,
636  doWarping=doWarping,
637  convolveTemplate=convolveTemplate
638  )
639  # Always inherit WCS and photocalib from science exposure
640  subtractedExposure = afwImage.ExposureF(scienceExposure, deep=True)
641  # Note, the decorrelation afterburner re-calculates the variance plane
642  # from the variance planes of the original exposures.
643  # That recalculation code must be in accordance with the
644  # photometric level set here in ``subtractedMaskedImage``.
645  if convolveTemplate:
646  subtractedMaskedImage = subtractedExposure.maskedImage
647  subtractedMaskedImage -= results.matchedExposure.maskedImage
648  subtractedMaskedImage -= results.backgroundModel
649  else:
650  subtractedMaskedImage = subtractedExposure.maskedImage
651  subtractedMaskedImage[:, :] = results.warpedExposure.maskedImage
652  subtractedMaskedImage -= results.matchedExposure.maskedImage
653  subtractedMaskedImage -= results.backgroundModel
654 
655  # Preserve polarity of differences
656  subtractedMaskedImage *= -1
657 
658  # Place back on native photometric scale
659  subtractedMaskedImage /= results.psfMatchingKernel.computeImage(
660  afwImage.ImageD(results.psfMatchingKernel.getDimensions()), False)
661  # We matched to the warped template
662  subtractedExposure.setPsf(results.warpedExposure.getPsf())
663 
664  import lsstDebug
665  display = lsstDebug.Info(__name__).display
666  displayDiffIm = lsstDebug.Info(__name__).displayDiffIm
667  maskTransparency = lsstDebug.Info(__name__).maskTransparency
668  if not maskTransparency:
669  maskTransparency = 0
670  if display:
671  afwDisplay.setDefaultMaskTransparency(maskTransparency)
672  if display and displayDiffIm:
673  disp = afwDisplay.Display(frame=lsstDebug.frame)
674  disp.mtv(templateExposure, title="Template")
675  lsstDebug.frame += 1
676  disp = afwDisplay.Display(frame=lsstDebug.frame)
677  disp.mtv(results.matchedExposure, title="Matched template")
678  lsstDebug.frame += 1
679  disp = afwDisplay.Display(frame=lsstDebug.frame)
680  disp.mtv(scienceExposure, title="Science Image")
681  lsstDebug.frame += 1
682  disp = afwDisplay.Display(frame=lsstDebug.frame)
683  disp.mtv(subtractedExposure, title="Difference Image")
684  lsstDebug.frame += 1
685 
686  results.subtractedExposure = subtractedExposure
687  return results
688 

◆ subtractMaskedImages() [1/2]

def lsst.ip.diffim.zogy.ZogyImagePsfMatchTask.subtractMaskedImages (   self,
  templateExposure,
  scienceExposure,
args 
)

Definition at line 1334 of file zogy.py.

1334  def subtractMaskedImages(self, templateExposure, scienceExposure, *args):
1335  raise NotImplementedError
1336 
1337 
1338 subtractAlgorithmRegistry.register('zogy', ZogyImagePsfMatchTask)

◆ subtractMaskedImages() [2/2]

def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.subtractMaskedImages (   self,
  templateMaskedImage,
  scienceMaskedImage,
  candidateList,
  templateFwhmPix = None,
  scienceFwhmPix = None 
)
inherited
Psf-match and subtract two MaskedImages.

Do the following, in order:

- PSF-match templateMaskedImage to scienceMaskedImage
- Determine the differential background
- Return the difference: scienceMaskedImage
    ((warped templateMaskedImage convolved with psfMatchingKernel) + backgroundModel)

Parameters
----------
templateMaskedImage : `lsst.afw.image.MaskedImage`
    MaskedImage to PSF-match to ``scienceMaskedImage``
scienceMaskedImage : `lsst.afw.image.MaskedImage`
    Reference MaskedImage
templateFwhmPix : `float`
    FWHM (in pixels) of the Psf in the template image (image to convolve)
scienceFwhmPix : `float`
    FWHM (in pixels) of the Psf in the science image
candidateList : `list`, optional
    A list of footprints/maskedImages for kernel candidates;
    if `None` then source detection is run.

    - Currently supported: list of Footprints or measAlg.PsfCandidateF

Returns
-------
results : `lsst.pipe.base.Struct`
    An `lsst.pipe.base.Struct` containing these fields:

    - ``subtractedMaskedImage`` : ``scienceMaskedImage`` - (matchedImage + backgroundModel)
    - ``matchedImage`` : templateMaskedImage convolved with psfMatchingKernel
    - `psfMatchingKernel`` : PSF matching kernel
    - ``backgroundModel`` : differential background model
    - ``kernelCellSet`` : SpatialCellSet used to determine PSF matching kernel

Definition at line 690 of file imagePsfMatch.py.

691  templateFwhmPix=None, scienceFwhmPix=None):
692  """Psf-match and subtract two MaskedImages.
693 
694  Do the following, in order:
695 
696  - PSF-match templateMaskedImage to scienceMaskedImage
697  - Determine the differential background
698  - Return the difference: scienceMaskedImage
699  ((warped templateMaskedImage convolved with psfMatchingKernel) + backgroundModel)
700 
701  Parameters
702  ----------
703  templateMaskedImage : `lsst.afw.image.MaskedImage`
704  MaskedImage to PSF-match to ``scienceMaskedImage``
705  scienceMaskedImage : `lsst.afw.image.MaskedImage`
706  Reference MaskedImage
707  templateFwhmPix : `float`
708  FWHM (in pixels) of the Psf in the template image (image to convolve)
709  scienceFwhmPix : `float`
710  FWHM (in pixels) of the Psf in the science image
711  candidateList : `list`, optional
712  A list of footprints/maskedImages for kernel candidates;
713  if `None` then source detection is run.
714 
715  - Currently supported: list of Footprints or measAlg.PsfCandidateF
716 
717  Returns
718  -------
719  results : `lsst.pipe.base.Struct`
720  An `lsst.pipe.base.Struct` containing these fields:
721 
722  - ``subtractedMaskedImage`` : ``scienceMaskedImage`` - (matchedImage + backgroundModel)
723  - ``matchedImage`` : templateMaskedImage convolved with psfMatchingKernel
724  - `psfMatchingKernel`` : PSF matching kernel
725  - ``backgroundModel`` : differential background model
726  - ``kernelCellSet`` : SpatialCellSet used to determine PSF matching kernel
727 
728  """
729  if not candidateList:
730  raise RuntimeError("Candidate list must be populated by makeCandidateList")
731 
732  results = self.matchMaskedImages(
733  templateMaskedImage=templateMaskedImage,
734  scienceMaskedImage=scienceMaskedImage,
735  candidateList=candidateList,
736  templateFwhmPix=templateFwhmPix,
737  scienceFwhmPix=scienceFwhmPix,
738  )
739 
740  subtractedMaskedImage = afwImage.MaskedImageF(scienceMaskedImage, True)
741  subtractedMaskedImage -= results.matchedImage
742  subtractedMaskedImage -= results.backgroundModel
743  results.subtractedMaskedImage = subtractedMaskedImage
744 
745  import lsstDebug
746  display = lsstDebug.Info(__name__).display
747  displayDiffIm = lsstDebug.Info(__name__).displayDiffIm
748  maskTransparency = lsstDebug.Info(__name__).maskTransparency
749  if not maskTransparency:
750  maskTransparency = 0
751  if display:
752  afwDisplay.setDefaultMaskTransparency(maskTransparency)
753  if display and displayDiffIm:
754  disp = afwDisplay.Display(frame=lsstDebug.frame)
755  disp.mtv(subtractedMaskedImage, title="Subtracted masked image")
756  lsstDebug.frame += 1
757 
758  return results
759 

Member Data Documentation

◆ background

lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.background
inherited

Definition at line 327 of file imagePsfMatch.py.

◆ ConfigClass

lsst.ip.diffim.zogy.ZogyImagePsfMatchTask.ConfigClass = ZogyImagePsfMatchConfig
static

Definition at line 1276 of file zogy.py.

◆ hMat

lsst.ip.diffim.psfMatch.PsfMatchTask.hMat
inherited

Definition at line 661 of file psfMatch.py.

◆ kConfig

lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.kConfig
inherited

Definition at line 323 of file imagePsfMatch.py.

◆ selectAlgMetadata

lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.selectAlgMetadata
inherited

Definition at line 330 of file imagePsfMatch.py.

◆ selectSchema

lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.selectSchema
inherited

Definition at line 329 of file imagePsfMatch.py.

◆ useRegularization

lsst.ip.diffim.psfMatch.PsfMatchTask.useRegularization
inherited

Definition at line 656 of file psfMatch.py.


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