22__all__ = [
"MakeKernelConfig",
"MakeKernelTask"]
36from .makeKernelBasisList
import makeKernelBasisList
37from .psfMatch
import PsfMatchConfig, PsfMatchTask, PsfMatchConfigAL, PsfMatchConfigDF
39from .
import diffimLib
40from .
import diffimTools
41from .utils
import getPsfFwhm
54 target=SourceDetectionTask,
55 doc=
"Initial detections used to feed stars to kernel fitting",
58 target=SingleFrameMeasurementTask,
59 doc=
"Initial measurements used to feed stars to kernel fitting",
69 self.
selectMeasurement.algorithms.names = (
'base_SdssCentroid',
'base_PsfFlux',
'base_PixelFlags',
70 'base_SdssShape',
'base_GaussianFlux',
'base_SkyCoord')
77 """Construct a kernel for PSF matching two exposures.
80 ConfigClass = MakeKernelConfig
81 _DefaultName = "makeALKernel"
84 PsfMatchTask.__init__(self, *args, **kwargs)
92 self.makeSubtask(
"selectDetection", schema=self.
selectSchema)
95 def run(self, template, science, kernelSources, preconvolved=False):
96 """Solve for the kernel and background model that best match two
97 Exposures evaluated at the given source locations.
102 Exposure that will be convolved.
104 The exposure that will be matched.
105 kernelSources : `list` of `dict`
106 A list of dicts having a "source" and "footprint"
107 field
for the Sources deemed to be appropriate
for Psf
108 matching. Can be the output
from ``selectKernelSources``.
109 preconvolved : `bool`, optional
110 Was the science image convolved
with its own PSF?
114 results : `lsst.pipe.base.Struct`
117 Spatially varying Psf-matching kernel.
118 ``backgroundModel`` : `lsst.afw.math.Function2D`
119 Spatially varying background-matching function.
122 templateFwhmPix = getPsfFwhm(template.psf)
123 scienceFwhmPix = getPsfFwhm(science.psf)
125 scienceFwhmPix *= np.sqrt(2)
127 metadata=self.metadata)
128 spatialSolution, psfMatchingKernel, backgroundModel = self.
_solve(kernelCellSet, basisList)
129 return lsst.pipe.base.Struct(
130 psfMatchingKernel=psfMatchingKernel,
131 backgroundModel=backgroundModel,
135 """Select sources from a list of candidates, and extract footprints.
140 Exposure that will be convolved.
142 The exposure that will be matched.
143 candidateList : `list`, optional
144 List of Sources to examine. Elements must be of type afw.table.Source
145 or a type that wraps a Source
and has a getSource() method, such
as
147 preconvolved : `bool`, optional
148 Was the science image convolved
with its own PSF?
152 kernelSources : `list` of `dict`
153 A list of dicts having a
"source" and "footprint"
154 field
for the Sources deemed to be appropriate
for Psf
157 templateFwhmPix = getPsfFwhm(template.psf)
158 scienceFwhmPix = getPsfFwhm(science.psf)
160 scienceFwhmPix *= np.sqrt(2)
163 candidateList=candidateList,
164 preconvolved=preconvolved)
168 """Get sources to use for Psf-matching.
170 This method runs detection and measurement on an exposure.
171 The returned set of sources will be used
as candidates
for
177 Exposure on which to run detection/measurement
178 sigma : `float`, optional
179 PSF sigma,
in pixels, used
for smoothing the image
for detection.
180 If `
None`, the PSF width will be used.
182 Whether
or not to smooth the Exposure
with Psf before detection
184 Factory
for the generation of Source ids
189 source catalog containing candidates
for the Psf-matching
195 mi = exposure.getMaskedImage()
197 imArr = mi.getImage().getArray()
198 maskArr = mi.getMask().getArray()
199 miArr = np.ma.masked_array(imArr, mask=maskArr)
202 bkgd = fitBg.getImageF(self.
background.config.algorithm,
205 self.log.warning(
"Failed to get background model. Falling back to median background estimation")
206 bkgd = np.ma.median(miArr)
212 detRet = self.selectDetection.run(
218 selectSources = detRet.sources
219 self.selectMeasurement.run(measCat=selectSources, exposure=exposure)
227 candidateList=None, preconvolved=False):
228 """Make a list of acceptable KernelCandidates.
230 Accept or generate a list of candidate sources
for
231 Psf-matching,
and examine the Mask planes
in both of the
232 images
for indications of bad pixels
237 Exposure that will be convolved
239 Exposure that will be matched-to
241 Dimensions of the Psf-matching Kernel, used to grow detection footprints
242 candidateList : `list`, optional
243 List of Sources to examine. Elements must be of type afw.table.Source
244 or a type that wraps a Source
and has a getSource() method, such
as
246 preconvolved : `bool`, optional
247 Was the science exposure already convolved
with its PSF?
251 candidateList : `list` of `dict`
252 A list of dicts having a
"source" and "footprint"
253 field
for the Sources deemed to be appropriate
for Psf
259 If ``candidateList``
is empty
or contains incompatible types.
261 if candidateList
is None:
262 candidateList = self.
getSelectSources(scienceExposure, doSmooth=
not preconvolved)
264 if len(candidateList) < 1:
265 raise RuntimeError(
"No candidates in candidateList")
267 listTypes =
set(
type(x)
for x
in candidateList)
268 if len(listTypes) > 1:
269 raise RuntimeError(
"Candidate list contains mixed types: %s" % [t
for t
in listTypes])
273 candidateList[0].getSource()
274 except Exception
as e:
275 raise RuntimeError(f
"Candidate List is of type: {type(candidateList[0])} "
276 "Can only make candidate list from list of afwTable.SourceRecords, "
277 f
"measAlg.PsfCandidateF or other type with a getSource() method: {e}")
278 candidateList = [c.getSource()
for c
in candidateList]
280 candidateList = diffimTools.sourceToFootprintList(candidateList,
281 templateExposure, scienceExposure,
285 if len(candidateList) == 0:
286 raise RuntimeError(
"Cannot find any objects suitable for KernelCandidacy")
290 def makeKernelBasisList(self, targetFwhmPix=None, referenceFwhmPix=None,
291 basisDegGauss=None, basisSigmaGauss=None, metadata=None):
292 """Wrapper to set log messages for
297 targetFwhmPix : `float`, optional
298 Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
299 Not used for delta function basis sets.
300 referenceFwhmPix : `float`, optional
301 Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
302 Not used
for delta function basis sets.
303 basisDegGauss : `list` of `int`, optional
304 Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
305 Not used
for delta function basis sets.
306 basisSigmaGauss : `list` of `int`, optional
307 Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
308 Not used
for delta function basis sets.
310 Passed on to `lsst.ip.diffim.generateAlardLuptonBasisList`.
311 Not used
for delta function basis sets.
315 basisList: `list` of `lsst.afw.math.kernel.FixedKernel`
316 List of basis kernels.
319 targetFwhmPix=targetFwhmPix,
320 referenceFwhmPix=referenceFwhmPix,
321 basisDegGauss=basisDegGauss,
322 basisSigmaGauss=basisSigmaGauss,
324 if targetFwhmPix == referenceFwhmPix:
325 self.log.info(
"Target and reference psf fwhms are equal, falling back to config values")
326 elif referenceFwhmPix > targetFwhmPix:
327 self.log.info(
"Reference psf fwhm is the greater, normal convolution mode")
329 self.log.info(
"Target psf fwhm is the greater, deconvolution mode")
333 def _buildCellSet(self, templateMaskedImage, scienceMaskedImage, candidateList):
334 """Build a SpatialCellSet for use with the solve method.
339 MaskedImage to PSF-matched to scienceMaskedImage
341 Reference MaskedImage
342 candidateList : `list`
343 A list of footprints/maskedImages for kernel candidates;
345 - Currently supported: list of Footprints
or measAlg.PsfCandidateF
350 a SpatialCellSet
for use
with self.
_solve
355 If no `candidateList`
is supplied.
357 if not candidateList:
358 raise RuntimeError(
"Candidate list must be populated by makeCandidateList")
362 imageBBox = templateMaskedImage.getBBox()
363 imageBBox.clip(scienceMaskedImage.getBBox())
369 for cand
in candidateList:
371 bbox = cand.getBBox()
373 bbox = cand[
'footprint'].getBBox()
374 tmi = lsst.afw.image.MaskedImageF(templateMaskedImage, bbox)
375 smi = lsst.afw.image.MaskedImageF(scienceMaskedImage, bbox)
379 cand = cand[
'source']
380 xPos = cand.getCentroid()[0]
381 yPos = cand.getCentroid()[1]
382 cand = diffimLib.makeKernelCandidate(xPos, yPos, tmi, smi, ps)
384 self.log.debug(
"Candidate %d at %f, %f", cand.getId(), cand.getXCenter(), cand.getYCenter())
385 kernelCellSet.insertCandidate(cand)
389 def _adaptCellSize(self, candidateList):
390 """NOT IMPLEMENTED YET.
394 candidateList : `list`
395 A list of footprints/maskedImages for kernel candidates;
399 sizeCellX, sizeCellY : `int`
400 New dimensions to use
for the kernel.
A class to contain the data, WCS, and other information needed to describe an image of the sky.
A class to manipulate images, masks, and variance as a single object.
A kernel that is a linear combination of fixed basis kernels.
A collection of SpatialCells covering an entire image.
A polymorphic functor base class for generating record IDs for a table.
Record class that contains measurements made on a single exposure.
static std::shared_ptr< SourceTable > make(Schema const &schema, std::shared_ptr< IdFactory > const &idFactory)
Construct a new table.
static Schema makeMinimalSchema()
Return a minimal schema for Source tables and records.
Class for storing ordered metadata with comments.
Class for storing generic metadata.
def selectKernelSources(self, template, science, candidateList=None, preconvolved=False)
def makeKernelBasisList(self, targetFwhmPix=None, referenceFwhmPix=None, basisDegGauss=None, basisSigmaGauss=None, metadata=None)
def getSelectSources(self, exposure, sigma=None, doSmooth=True, idFactory=None)
def makeCandidateList(self, templateExposure, scienceExposure, kernelSize, candidateList=None, preconvolved=False)
def _adaptCellSize(self, candidateList)
def _buildCellSet(self, templateMaskedImage, scienceMaskedImage, candidateList)
def __init__(self, *args, **kwargs)
def _buildCellSet(self, *args)
def _solve(self, kernelCellSet, basisList, returnOnExcept=False)
daf::base::PropertySet * set