22__all__ = [
"MakeKernelConfig",
"MakeKernelTask"]
32from lsst.meas.algorithms
import SourceDetectionTask, SubtractBackgroundTask
38from .makeKernelBasisList
import makeKernelBasisList
39from .psfMatch
import PsfMatchConfig, PsfMatchTask, PsfMatchConfigAL, PsfMatchConfigDF
41from .
import diffimLib
42from .utils
import evaluateMeanPsfFwhm, getPsfFwhm
46 kernel = lsst.pex.config.ConfigChoiceField(
54 selectDetection = lsst.pex.config.ConfigurableField(
55 target=SourceDetectionTask,
56 doc=
"Initial detections used to feed stars to kernel fitting",
58 selectMeasurement = lsst.pex.config.ConfigurableField(
59 target=SingleFrameMeasurementTask,
60 doc=
"Initial measurements used to feed stars to kernel fitting",
62 fwhmExposureGrid = lsst.pex.config.Field(
63 doc=
"Grid size to compute the average PSF FWHM in an exposure",
67 fwhmExposureBuffer = lsst.pex.config.Field(
68 doc=
"Fractional buffer margin to be left out of all sides of the image during construction"
69 "of grid to compute average PSF FWHM in an exposure",
82 self.
selectMeasurement.algorithms.names = (
'base_SdssCentroid',
'base_PsfFlux',
'base_PixelFlags',
83 'base_SdssShape',
'base_GaussianFlux',
'base_SkyCoord')
90 """Construct a kernel for PSF matching two exposures.
93 ConfigClass = MakeKernelConfig
94 _DefaultName =
"makeALKernel"
97 PsfMatchTask.__init__(self, *args, **kwargs)
105 self.makeSubtask(
"selectDetection", schema=self.
selectSchema)
108 def run(self, template, science, kernelSources, preconvolved=False):
109 """Solve for the kernel and background model that best match two
110 Exposures evaluated at the given source locations.
114 template : `lsst.afw.image.Exposure`
115 Exposure that will be convolved.
116 science : `lsst.afw.image.Exposure`
117 The exposure that will be matched.
118 kernelSources : `lsst.afw.table.SourceCatalog`
119 Kernel candidate sources with appropriately sized footprints.
120 Typically the output of `MakeKernelTask.selectKernelSources`.
121 preconvolved : `bool`, optional
122 Was the science image convolved with its own PSF?
126 results : `lsst.pipe.base.Struct`
128 ``psfMatchingKernel`` : `lsst.afw.math.LinearCombinationKernel`
129 Spatially varying Psf-matching kernel.
130 ``backgroundModel`` : `lsst.afw.math.Function2D`
131 Spatially varying background-matching function.
141 templateFwhmPix = getPsfFwhm(template.psf)
142 scienceFwhmPix = getPsfFwhm(science.psf)
143 except InvalidParameterError:
144 self.log.debug(
"Unable to evaluate PSF at the average position. "
145 "Evaluting PSF on a grid of points."
147 templateFwhmPix = evaluateMeanPsfFwhm(template,
148 fwhmExposureBuffer=self.config.fwhmExposureBuffer,
149 fwhmExposureGrid=self.config.fwhmExposureGrid
151 scienceFwhmPix = evaluateMeanPsfFwhm(science,
152 fwhmExposureBuffer=self.config.fwhmExposureBuffer,
153 fwhmExposureGrid=self.config.fwhmExposureGrid
157 scienceFwhmPix *= np.sqrt(2)
159 metadata=self.metadata)
160 spatialSolution, psfMatchingKernel, backgroundModel = self.
_solve(kernelCellSet, basisList)
161 return lsst.pipe.base.Struct(
162 psfMatchingKernel=psfMatchingKernel,
163 backgroundModel=backgroundModel,
167 """Select sources from a list of candidates, and extract footprints.
171 template : `lsst.afw.image.Exposure`
172 Exposure that will be convolved.
173 science : `lsst.afw.image.Exposure`
174 The exposure that will be matched.
175 candidateList : `lsst.afw.table.SourceCatalog`
176 Sources to check as possible kernel candidates.
177 preconvolved : `bool`, optional
178 Was the science image convolved with its own PSF?
182 kernelSources : `lsst.afw.table.SourceCatalog`
183 Kernel candidates with appropriate sized footprints.
192 templateFwhmPix = getPsfFwhm(template.psf)
193 scienceFwhmPix = getPsfFwhm(science.psf)
194 except InvalidParameterError:
195 self.log.debug(
"Unable to evaluate PSF at the average position. "
196 "Evaluting PSF on a grid of points."
198 templateFwhmPix = evaluateMeanPsfFwhm(template,
199 fwhmExposureBuffer=self.config.fwhmExposureBuffer,
200 fwhmExposureGrid=self.config.fwhmExposureGrid
202 scienceFwhmPix = evaluateMeanPsfFwhm(science,
203 fwhmExposureBuffer=self.config.fwhmExposureBuffer,
204 fwhmExposureGrid=self.config.fwhmExposureGrid
207 scienceFwhmPix *= np.sqrt(2)
210 candidateList=candidateList,
211 preconvolved=preconvolved)
215 """Get sources to use for Psf-matching.
217 This method runs detection and measurement on an exposure.
218 The returned set of sources will be used as candidates for
223 exposure : `lsst.afw.image.Exposure`
224 Exposure on which to run detection/measurement
225 sigma : `float`, optional
226 PSF sigma, in pixels, used for smoothing the image for detection.
227 If `None`, the PSF width will be used.
229 Whether or not to smooth the Exposure with Psf before detection
230 idFactory : `lsst.afw.table.IdFactory`
231 Factory for the generation of Source ids
236 source catalog containing candidates for the Psf-matching
242 mi = exposure.getMaskedImage()
244 imArr = mi.image.array
245 maskArr = mi.mask.array
246 miArr = np.ma.masked_array(imArr, mask=maskArr)
249 bkgd = fitBg.getImageF(self.
background.config.algorithm,
252 self.log.
warning(
"Failed to get background model. Falling back to median background estimation")
253 bkgd = np.ma.median(miArr)
259 detRet = self.selectDetection.
run(
265 selectSources = detRet.sources
266 self.selectMeasurement.
run(measCat=selectSources, exposure=exposure)
272 self.log.
info(
"Selected %d sources via detection measurement.",
len(selectSources))
276 candidateList, preconvolved=False):
277 """Make a list of acceptable KernelCandidates.
279 Generate a list of candidate sources for Psf-matching, remove sources
280 with bad pixel masks set or that extend off the image.
284 convolved : `lsst.afw.image.Exposure`
285 Exposure that will be convolved. This is typically the template
286 image, and may have a large bbox than the reference exposure.
287 reference : `lsst.afw.image.Exposure`
288 Exposure that will be matched-to. This is typically the science
291 Dimensions of the Psf-matching Kernel, used to set detection
293 candidateList : `lsst.afw.table.SourceCatalog`
294 List of Sources to examine for kernel candidacy.
295 preconvolved : `bool`, optional
296 Was the science exposure already convolved with its PSF?
300 candidates : `lsst.afw.table.SourceCatalog`
301 Candidates with footprints extended to a ``kernelSize`` box.
306 If ``candidateList`` is empty after sub-selection.
308 if candidateList
is None:
310 if len(candidateList) < 1:
311 raise RuntimeError(
"No kernel candidates after detection and measurement.")
313 bitmask = reference.mask.getPlaneBitMask(self.config.badMaskPlanes)
314 good = np.ones(
len(candidateList), dtype=bool)
316 for i, candidate
in enumerate(candidateList):
318 peak = candidate.getFootprint().getPeaks()[0]
319 size = 2*kernelSize + 1
323 boxFootprint.addPeak(peak.getFx(), peak.getFy(), peak.getPeakValue())
324 candidate.setFootprint(boxFootprint)
327 if not reference.getBBox().contains(bbox)
or not convolved.getBBox().contains(bbox):
331 if (reference.subset(bbox).mask.array & bitmask).any():
334 candidates = candidateList[good].copy(deep=
True)
336 self.log.
info(
"Selected %d / %d sources as kernel candidates.", good.sum(),
len(candidateList))
338 if len(candidates) < 1:
339 raise RuntimeError(
"No good kernel candidates available.")
343 def makeKernelBasisList(self, targetFwhmPix=None, referenceFwhmPix=None,
344 basisDegGauss=None, basisSigmaGauss=None, metadata=None):
345 """Wrapper to set log messages for
346 `lsst.ip.diffim.makeKernelBasisList`.
350 targetFwhmPix : `float`, optional
351 Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
352 Not used for delta function basis sets.
353 referenceFwhmPix : `float`, optional
354 Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
355 Not used for delta function basis sets.
356 basisDegGauss : `list` of `int`, optional
357 Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
358 Not used for delta function basis sets.
359 basisSigmaGauss : `list` of `int`, optional
360 Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
361 Not used for delta function basis sets.
362 metadata : `lsst.daf.base.PropertySet`, optional
363 Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
364 Not used for delta function basis sets.
368 basisList: `list` of `lsst.afw.math.kernel.FixedKernel`
369 List of basis kernels.
372 targetFwhmPix=targetFwhmPix,
373 referenceFwhmPix=referenceFwhmPix,
374 basisDegGauss=basisDegGauss,
375 basisSigmaGauss=basisSigmaGauss,
377 if targetFwhmPix == referenceFwhmPix:
378 self.log.
info(
"Target and reference psf fwhms are equal, falling back to config values")
379 elif referenceFwhmPix > targetFwhmPix:
380 self.log.
info(
"Reference psf fwhm is the greater, normal convolution mode")
382 self.log.
info(
"Target psf fwhm is the greater, deconvolution mode")
387 """Build a SpatialCellSet for use with the solve method.
391 convolved : `lsst.afw.image.MaskedImage`
392 MaskedImage to PSF-matched to reference.
393 reference : `lsst.afw.image.MaskedImage`
394 Reference MaskedImage.
395 candidateList : `lsst.afw.table.SourceCatalog`
396 Kernel candidate sources with footprints.
400 kernelCellSet : `lsst.afw.math.SpatialCellSet`
401 A SpatialCellSet for use with self._solve.
405 imageBBox = convolved.getBBox()
406 imageBBox.clip(reference.getBBox())
410 candidateConfig = lsst.pex.config.makePropertySet(self.
kConfigkConfig)
412 for candidate
in candidateList:
413 bbox = candidate.getFootprint().getBBox()
414 templateCutout = lsst.afw.image.MaskedImageF(convolved, bbox)
415 scienceCutout = lsst.afw.image.MaskedImageF(reference, bbox)
417 kernelCandidate = diffimLib.makeKernelCandidate(candidate,
422 self.log.debug(
"Candidate %d at %.2f, %.2f rating=%f",
423 kernelCandidate.getId(),
424 kernelCandidate.getXCenter(),
425 kernelCandidate.getYCenter(),
426 kernelCandidate.getCandidateRating())
427 kernelCellSet.insertCandidate(kernelCandidate)
432 """NOT IMPLEMENTED YET.
436 candidateList : `list`
437 A list of footprints/maskedImages for kernel candidates;
441 sizeCellX, sizeCellY : `int`
442 New dimensions to use for the kernel.
static std::shared_ptr< SourceTable > make(Schema const &schema, std::shared_ptr< IdFactory > const &idFactory)
static Schema makeMinimalSchema()
static Box2I makeCenteredBox(Point2D const ¢er, Extent const &size)
Asseses the quality of a candidate given a spatial kernel and background model.
makeCandidateList(self, convolved, reference, kernelSize, candidateList, preconvolved=False)
__init__(self, *args, **kwargs)
_buildCellSet(self, convolved, reference, candidateList)
_adaptCellSize(self, candidateList)
makeKernelBasisList(self, targetFwhmPix=None, referenceFwhmPix=None, basisDegGauss=None, basisSigmaGauss=None, metadata=None)
selectKernelSources(self, template, science, candidateList=None, preconvolved=False)
run(self, template, science, kernelSources, preconvolved=False)
getSelectSources(self, exposure, sigma=None, doSmooth=True, idFactory=None)
_solve(self, kernelCellSet, basisList, returnOnExcept=False)
_buildCellSet(self, *args)