28import lsst.meas.algorithms
as measAlg
31from lsst.utils.timer
import timeMethod
33from .imageMapReduce
import (ImageMapReduceConfig, ImageMapReduceTask,
36__all__ = (
"DecorrelateALKernelTask",
"DecorrelateALKernelConfig",
37 "DecorrelateALKernelMapper",
"DecorrelateALKernelMapReduceConfig",
38 "DecorrelateALKernelSpatialConfig",
"DecorrelateALKernelSpatialTask")
42 """Configuration parameters for the DecorrelateALKernelTask
45 ignoreMaskPlanes = pexConfig.ListField(
47 doc="""Mask planes to ignore for sigma-clipped statistics""",
48 default=(
"INTRP",
"EDGE",
"DETECTED",
"SAT",
"CR",
"BAD",
"NO_DATA",
"DETECTED_NEGATIVE")
50 completeVarPlanePropagation = pexConfig.Field(
53 doc=
"Compute the full effect of the decorrelated matching kernel on the variance plane."
54 " Otherwise use a model weighed sum of the input variances."
59 """Decorrelate the effect of convolution by Alard-Lupton matching kernel in image difference
62 ConfigClass = DecorrelateALKernelConfig
63 _DefaultName = "ip_diffim_decorrelateALKernel"
66 """Create the image decorrelation Task
71 arguments to be passed to ``lsst.pipe.base.task.Task.__init__``
73 keyword arguments to be passed to ``lsst.pipe.base.task.Task.__init__``
75 pipeBase.Task.__init__(self, *args, **kwargs)
80 self.statsControl.setAndMask(afwImage.Mask.getPlaneBitMask(self.config.ignoreMaskPlanes))
86 var = statObj.getValue(afwMath.MEANCLIP)
90 def run(self, scienceExposure, templateExposure, subtractedExposure, psfMatchingKernel,
91 preConvKernel=None, xcen=None, ycen=None, svar=None, tvar=None,
92 templateMatched=True, preConvMode=False, **kwargs):
93 """Perform decorrelation of an image difference or of a score difference exposure.
95 Corrects the difference or score image due to the convolution of the
96 templateExposure
with the A&L PSF matching kernel.
97 See [DMTN-021, Equation 1](http://dmtn-021.lsst.io/
98 [DMTN-179](http://dmtn-179.lsst.io/)
for details.
103 The original science exposure (before pre-convolution,
if ``preConvMode==
True``).
105 The original template exposure warped, but
not psf-matched, to the science exposure.
107 the subtracted exposure produced by
108 `ip_diffim.ImagePsfMatchTask.subtractExposures()`. The `subtractedExposure` must
109 inherit its PSF
from `exposure`, see notes below.
111 An (optionally spatially-varying) PSF matching kernel produced
112 by `ip_diffim.ImagePsfMatchTask.subtractExposures()`.
114 If
not `
None`, then the `scienceExposure` was pre-convolved
with (the reflection of)
115 this kernel. Must be normalized to sum to 1.
116 Allowed only
if ``templateMatched==
True``
and ``preConvMode==
True``.
117 Defaults to the PSF of the science exposure at the image center.
118 xcen : `float`, optional
119 X-pixel coordinate to use
for computing constant matching kernel to use
120 If `
None` (default), then use the center of the image.
121 ycen : `float`, optional
122 Y-pixel coordinate to use
for computing constant matching kernel to use
123 If `
None` (default), then use the center of the image.
124 svar : `float`, optional
125 Image variance
for science image
126 If `
None` (default) then compute the variance over the entire input science image.
127 tvar : `float`, optional
128 Image variance
for template image
129 If `
None` (default) then compute the variance over the entire input template image.
130 templateMatched : `bool`, optional
131 If
True, the template exposure was matched (convolved) to the science exposure.
132 See also notes below.
133 preConvMode : `bool`, optional
134 If
True, ``subtractedExposure``
is assumed to be a likelihood difference image
135 and will be noise corrected
as a likelihood image.
137 Additional keyword arguments propagated
from DecorrelateALKernelSpatialTask.
141 result : `lsst.pipe.base.Struct`
142 - ``correctedExposure`` : the decorrelated diffim
146 If ``preConvMode==
True``, ``subtractedExposure``
is assumed to be a
147 score image
and the noise correction
for likelihood images
148 is applied. The resulting image
is an optimal detection likelihood image
149 when the templateExposure has noise. (See DMTN-179) If ``preConvKernel``
is
150 not specified, the PSF of ``scienceExposure``
is assumed
as pre-convolution kernel.
152 The ``subtractedExposure``
is NOT updated. The returned ``correctedExposure``
153 has an updated but spatially fixed PSF. It
is calculated
as the center of
154 image PSF corrected by the center of image matching kernel.
156 If ``templateMatched==
True``, the templateExposure was matched (convolved)
157 to the ``scienceExposure`` by ``psfMatchingKernel`` during image differencing.
158 Otherwise the ``scienceExposure`` was matched (convolved) by ``psfMatchingKernel``.
159 In either case, note that the original template
and science images are required,
160 not the psf-matched version.
162 This task discards the variance plane of ``subtractedExposure``
and re-computes
163 it
from the variance planes of ``scienceExposure``
and ``templateExposure``.
164 The image plane of ``subtractedExposure`` must be at the photometric level
165 set by the AL PSF matching
in `ImagePsfMatchTask.subtractExposures`.
166 The assumptions about the photometric level are controlled by the
167 `templateMatched` option
in this task.
169 Here we currently convert a spatially-varying matching kernel into a constant kernel,
170 just by computing it at the center of the image (tickets DM-6243, DM-6244).
172 We are also using a constant accross-the-image measure of sigma (sqrt(variance)) to compute
173 the decorrelation kernel.
175 TODO DM-23857 As part of the spatially varying correction implementation
176 consider whether returning a Struct
is still necessary.
178 if preConvKernel
is not None and not (templateMatched
and preConvMode):
179 raise ValueError(
"Pre-convolution kernel is allowed only if "
180 "preConvMode==True and templateMatched==True.")
182 spatialKernel = psfMatchingKernel
183 kimg = afwImage.ImageD(spatialKernel.getDimensions())
184 bbox = subtractedExposure.getBBox()
186 xcen = (bbox.getBeginX() + bbox.getEndX()) / 2.
188 ycen = (bbox.getBeginY() + bbox.getEndY()) / 2.
189 self.log.info(
"Using matching kernel computed at (%d, %d)", xcen, ycen)
190 spatialKernel.computeImage(kimg,
False, xcen, ycen)
194 if preConvKernel
is None:
195 pos = scienceExposure.getPsf().getAveragePosition()
196 preConvKernel = scienceExposure.getPsf().getLocalKernel(pos)
197 preConvImg = afwImage.ImageD(preConvKernel.getDimensions())
198 preConvKernel.computeImage(preConvImg,
True)
204 self.log.info(
"Original variance plane means. Science:%.5e, warped template:%.5e)",
210 if np.isnan(svar)
or np.isnan(tvar):
212 if (np.all(np.isnan(scienceExposure.image.array))
213 or np.all(np.isnan(templateExposure.image.array))):
214 self.log.warning(
'Template or science image is entirely NaNs: skipping decorrelation.')
215 outExposure = subtractedExposure.clone()
216 return pipeBase.Struct(correctedExposure=outExposure, )
220 self.log.info(
"Decorrelation after template image convolution")
222 targetVarianceMean = tvar
224 variance = scienceExposure.variance.array
226 targetVariance = templateExposure.variance.array
229 self.log.info(
"Decorrelation after science image convolution")
231 targetVarianceMean = svar
233 variance = templateExposure.variance.array
235 targetVariance = scienceExposure.variance.array
239 mOverExpVar = targetVarianceMean/varianceMean
240 if mOverExpVar > 1e8:
241 self.log.warning(
"Diverging correction: matched image variance is "
242 " much larger than the unconvolved one's"
243 ", targetVarianceMean/varianceMean:%.2e", mOverExpVar)
246 self.log.info(
"Variance plane mean of uncorrected diffim: %f", oldVarMean)
249 diffimShape = subtractedExposure.image.array.shape
250 psfImg = subtractedExposure.getPsf().computeKernelImage(
geom.Point2D(xcen, ycen))
251 psfShape = psfImg.array.shape
254 self.log.info(
"Decorrelation of likelihood image")
256 psfShape, diffimShape)
259 self.log.info(
"Decorrelation of difference image")
269 if self.config.completeVarPlanePropagation:
270 self.log.debug(
"Using full variance plane calculation in decorrelation")
272 variance, targetVariance,
273 varianceMean, targetVarianceMean, corr.cnft, corr.crft)
275 self.log.debug(
"Using estimated variance plane calculation in decorrelation")
277 variance, targetVariance,
278 corr.cnft, corr.crft)
283 self.log.debug(
"Matching kernel sum: %.3e", kSum)
284 if not templateMatched:
287 correctedVariance /= kSumSq
288 subtractedExposure.image.array[...] = correctedImage
289 subtractedExposure.variance.array[...] = correctedVariance
290 subtractedExposure.setPsf(correctedPsf)
293 self.log.info(
"Variance plane mean of corrected diffim: %.5e", newVarMean)
297 return pipeBase.Struct(correctedExposure=subtractedExposure, )
300 """Calculate the common shape for FFT operations. Set `self.freqSpaceShape`
305 shapes : one or more `tuple` of `int`
306 Shapes of the arrays. All must have the same dimensionality.
307 At least one shape must be provided.
315 For each dimension, gets the smallest even number greater than
or equal to
316 `N1+N2-1` where `N1`
and `N2` are the two largest values.
317 In case of only one shape given, rounds up to even each dimension value.
319 S = np.array(shapes, dtype=int)
324 commonShape = np.sum(S, axis=0) - 1
327 commonShape[commonShape % 2 != 0] += 1
329 self.log.info(
"Common frequency space shape %s", self.
freqSpaceShape)
333 """Zero pad an image where the origin is at the center and replace the
334 origin to the corner as required by the periodic input of FFT. Implement also
335 the inverse operation, crop the padding
and re-center data.
340 An array to copy
from.
341 newShape : `tuple` of `int`
342 The dimensions of the resulting array. For padding, the resulting array
343 must be larger than A
in each dimension. For the inverse operation this
344 must be the original, before padding size of the array.
345 useInverse : bool, optional
346 Selector of forward, add padding, operation (
False)
347 or its inverse, crop padding, operation (
True).
352 The padded
or unpadded array
with shape of `newShape`
and the same dtype
as A.
356 For odd dimensions, the splitting
is rounded to
357 put the center pixel into the new corner origin (0,0). This
is to be consistent
358 e.g.
for a dirac delta kernel that
is originally located at the center pixel.
365 firstHalves = [x//2
for x
in A.shape]
366 secondHalves = [x-y
for x, y
in zip(A.shape, firstHalves)]
369 secondHalves = [x//2
for x
in newShape]
370 firstHalves = [x-y
for x, y
in zip(newShape, secondHalves)]
372 R = np.zeros_like(A, shape=newShape)
373 R[-firstHalves[0]:, -firstHalves[1]:] = A[:firstHalves[0], :firstHalves[1]]
374 R[:secondHalves[0], -firstHalves[1]:] = A[-secondHalves[0]:, :firstHalves[1]]
375 R[:secondHalves[0], :secondHalves[1]] = A[-secondHalves[0]:, -secondHalves[1]:]
376 R[-firstHalves[0]:, :secondHalves[1]] = A[:firstHalves[0], -secondHalves[1]:]
380 """Compute the Lupton decorrelation post-convolution kernel for decorrelating an
381 image difference, based on the PSF-matching kernel.
385 kappa : `numpy.ndarray` of `float`
386 A matching kernel 2-d numpy.array derived from Alard & Lupton PSF matching.
388 Average variance of science image used
for PSF matching.
390 Average variance of the template (matched) image used
for PSF matching.
394 corrft : `numpy.ndarray` of `float`
395 The frequency space representation of the correction. The array
is real (dtype float).
398 cnft, crft : `numpy.ndarray` of `complex`
399 The overall convolution (pre-conv, PSF matching, noise correction) kernel
400 for the science
and template images, respectively
for the variance plane
401 calculations. These are intermediate results
in frequency space.
405 The maximum correction factor converges to `sqrt(tvar/svar)` towards high frequencies.
406 This should be a plausible value.
410 kft = np.fft.fft2(kappa)
411 kftAbsSq = np.real(np.conj(kft) * kft)
413 denom = svar + tvar * kftAbsSq
414 corrft = np.sqrt((svar + tvar * kSum*kSum) / denom)
417 return pipeBase.Struct(corrft=corrft, cnft=cnft, crft=crft)
420 """Compute the correction kernel for a score image.
424 kappa : `numpy.ndarray`
425 A matching kernel 2-d numpy.array derived from Alard & Lupton PSF matching.
427 Average variance of science image used
for PSF matching (before pre-convolution).
429 Average variance of the template (matched) image used
for PSF matching.
430 preConvArr : `numpy.ndarray`
431 The pre-convolution kernel of the science image. It should be the PSF
432 of the science image
or an approximation of it. It must be normed to sum 1.
436 corrft : `numpy.ndarray` of `float`
437 The frequency space representation of the correction. The array
is real (dtype float).
439 cnft, crft : `numpy.ndarray` of `complex`
440 The overall convolution (pre-conv, PSF matching, noise correction) kernel
441 for the science
and template images, respectively
for the variance plane
442 calculations. These are intermediate results
in frequency space.
446 To be precise, the science image should be _correlated_ by ``preConvArray`` but this
447 does
not matter
for this calculation.
449 ``cnft``, ``crft`` contain the scaling factor
as well.
454 kft = np.fft.fft2(kappa)
456 preFt = np.fft.fft2(preConvArr)
457 preFtAbsSq = np.real(np.conj(preFt) * preFt)
458 kftAbsSq = np.real(np.conj(kft) * kft)
461 tiny = np.finfo(preFtAbsSq.dtype).tiny * 1000.
462 flt = preFtAbsSq < tiny
466 preFtAbsSq[flt] = tiny
467 denom = svar + tvar * kftAbsSq / preFtAbsSq
468 corrft = (svar + tvar * kSum*kSum) / denom
469 cnft = np.conj(preFt)*corrft
471 return pipeBase.Struct(corrft=corrft, cnft=cnft, crft=crft)
475 """Estimate the variance planes.
477 The estimation assumes that around each pixel the surrounding
478 pixels' sigmas within the convolution kernel are the same.
482 vplane1, vplane2 : `numpy.ndarray` of `float`
483 Variance planes of the original (before pre-convolution or matching)
485 c1ft, c2ft : `numpy.ndarray` of `complex`
486 The overall convolution that includes the matching
and the
487 afterburner
in frequency space. The result of either
488 ``computeScoreCorrection``
or ``computeDiffimCorrection``.
492 vplaneD : `numpy.ndarray` of `float`
493 The estimated variance plane of the difference/score image
494 as a weighted sum of the input variances.
498 See DMTN-179 Section 5 about the variance plane calculations.
500 w1 = np.sum(np.real(np.conj(c1ft)*c1ft)) / c1ft.size
501 w2 = np.sum(np.real(np.conj(c2ft)*c2ft)) / c2ft.size
504 return vplane1*w1 + vplane2*w2
507 """Full propagation of the variance planes of the original exposures.
509 The original variance planes of independent pixels are convolved with the
510 image space square of the overall kernels.
514 vplane1, vplane2 : `numpy.ndarray` of `float`
515 Variance planes of the original (before pre-convolution
or matching)
517 varMean1, varMean2 : `float`
518 Replacement average values
for non-finite ``vplane1``
and ``vplane2`` values respectively.
520 c1ft, c2ft : `numpy.ndarray` of `complex`
521 The overall convolution that includes the matching
and the
522 afterburner
in frequency space. The result of either
523 ``computeScoreCorrection``
or ``computeDiffimCorrection``.
527 vplaneD : `numpy.ndarray` of `float`
528 The variance plane of the difference/score images.
532 See DMTN-179 Section 5 about the variance plane calculations.
534 Infs
and NaNs are allowed
and kept
in the returned array.
536 D = np.real(np.fft.ifft2(c1ft))
537 c1SqFt = np.fft.fft2(D*D)
539 v1shape = vplane1.shape
540 filtInf = np.isinf(vplane1)
541 filtNan = np.isnan(vplane1)
543 vplane1 = np.copy(vplane1)
544 vplane1[filtInf | filtNan] = varMean1
546 v1 = np.real(np.fft.ifft2(np.fft.fft2(D) * c1SqFt))
551 D = np.real(np.fft.ifft2(c2ft))
552 c2SqFt = np.fft.fft2(D*D)
554 v2shape = vplane2.shape
555 filtInf = np.isinf(vplane2)
556 filtNan = np.isnan(vplane2)
557 vplane2 = np.copy(vplane2)
558 vplane2[filtInf | filtNan] = varMean2
560 v2 = np.real(np.fft.ifft2(np.fft.fft2(D) * c2SqFt))
568 """Compute the (decorrelated) difference image's new PSF.
572 corrft : `numpy.ndarray`
573 The frequency space representation of the correction calculated by
575 psfOld : `numpy.ndarray`
576 The psf of the difference image to be corrected.
580 correctedPsf : `lsst.meas.algorithms.KernelPsf`
581 The corrected psf, same shape as `psfOld`, sum normed to 1.
585 There
is no algorithmic guarantee that the corrected psf can
586 meaningfully fit to the same size
as the original one.
588 psfShape = psfOld.shape
590 psfNew = np.fft.fft2(psfNew)
592 psfNew = np.fft.ifft2(psfNew)
595 psfNew = psfNew/psfNew.sum()
597 psfcI = afwImage.ImageD(
geom.Extent2I(psfShape[1], psfShape[0]))
600 correctedPsf = measAlg.KernelPsf(psfcK)
604 """Compute the decorrelated difference image.
608 corrft : `numpy.ndarray`
609 The frequency space representation of the correction calculated by
611 imgOld : `numpy.ndarray`
612 The difference image to be corrected.
616 imgNew : `numpy.ndarray`
617 The corrected image, same size as the input.
619 expShape = imgOld.shape
620 imgNew = np.copy(imgOld)
621 filtInf = np.isinf(imgNew)
622 filtNan = np.isnan(imgNew)
623 imgNew[filtInf] = np.nan
624 imgNew[filtInf | filtNan] = np.nanmean(imgNew)
626 imgNew = np.fft.fft2(imgNew)
628 imgNew = np.fft.ifft2(imgNew)
631 imgNew[filtNan] = np.nan
632 imgNew[filtInf] = np.inf
637 """Task to be used as an ImageMapper for performing
638 A&L decorrelation on subimages on a grid across a A&L difference image.
640 This task subclasses DecorrelateALKernelTask in order to implement
641 all of that task
's configuration parameters, as well as its `run` method.
644 ConfigClass = DecorrelateALKernelConfig
645 _DefaultName = 'ip_diffim_decorrelateALKernelMapper'
648 DecorrelateALKernelTask.__init__(self, *args, **kwargs)
650 def run(self, subExposure, expandedSubExposure, fullBBox,
651 template, science, alTaskResult=None, psfMatchingKernel=None,
652 preConvKernel=None, **kwargs):
653 """Perform decorrelation operation on `subExposure`, using
654 `expandedSubExposure` to allow for invalid edge pixels arising
from
657 This method performs A&L decorrelation on `subExposure` using
658 local measures
for image variances
and PSF. `subExposure`
is a
659 sub-exposure of the non-decorrelated A&L diffim. It also
660 requires the corresponding sub-exposures of the template
661 (`template`)
and science (`science`) exposures.
666 the sub-exposure of the diffim
668 the expanded sub-exposure upon which to operate
670 the bounding box of the original exposure
672 the corresponding sub-exposure of the template exposure
674 the corresponding sub-exposure of the science exposure
675 alTaskResult : `lsst.pipe.base.Struct`
676 the result of A&L image differencing on `science`
and
677 `template`, importantly containing the resulting
678 `psfMatchingKernel`. Can be `
None`, only
if
679 `psfMatchingKernel`
is not `
None`.
680 psfMatchingKernel : Alternative parameter
for passing the
681 A&L `psfMatchingKernel` directly.
682 preConvKernel : If
not None, then pre-filtering was applied
683 to science exposure,
and this
is the pre-convolution
686 additional keyword arguments propagated
from
687 `ImageMapReduceTask.run`.
691 A `pipeBase.Struct` containing:
693 - ``subExposure`` : the result of the `subExposure` processing.
694 - ``decorrelationKernel`` : the decorrelation kernel, currently
699 This `run` method accepts parameters identical to those of
700 `ImageMapper.run`, since it
is called
from the
701 `ImageMapperTask`. See that
class for more information.
703 templateExposure = template
704 scienceExposure = science
705 if alTaskResult
is None and psfMatchingKernel
is None:
706 raise RuntimeError(
'Both alTaskResult and psfMatchingKernel cannot be None')
707 psfMatchingKernel = alTaskResult.psfMatchingKernel
if alTaskResult
is not None else psfMatchingKernel
711 subExp2 = scienceExposure.Factory(scienceExposure, expandedSubExposure.getBBox())
712 subExp1 = templateExposure.Factory(templateExposure, expandedSubExposure.getBBox())
715 logLevel = self.log.level
716 self.log.setLevel(self.log.WARNING)
717 res = DecorrelateALKernelTask.run(self, subExp2, subExp1, expandedSubExposure,
718 psfMatchingKernel, preConvKernel, **kwargs)
719 self.log.setLevel(logLevel)
721 diffim = res.correctedExposure.Factory(res.correctedExposure, subExposure.getBBox())
722 out = pipeBase.Struct(subExposure=diffim, )
727 """Configuration parameters for the ImageMapReduceTask to direct it to use
728 DecorrelateALKernelMapper as its mapper
for A&L decorrelation.
730 mapper = pexConfig.ConfigurableField(
731 doc='A&L decorrelation task to run on each sub-image',
732 target=DecorrelateALKernelMapper
737 """Configuration parameters for the DecorrelateALKernelSpatialTask.
739 decorrelateConfig = pexConfig.ConfigField(
740 dtype=DecorrelateALKernelConfig,
741 doc='DecorrelateALKernel config to use when running on complete exposure (non spatially-varying)',
744 decorrelateMapReduceConfig = pexConfig.ConfigField(
745 dtype=DecorrelateALKernelMapReduceConfig,
746 doc=
'DecorrelateALKernelMapReduce config to use when running on each sub-image (spatially-varying)',
749 ignoreMaskPlanes = pexConfig.ListField(
751 doc=
"""Mask planes to ignore for sigma-clipped statistics""",
752 default=(
"INTRP",
"EDGE",
"DETECTED",
"SAT",
"CR",
"BAD",
"NO_DATA",
"DETECTED_NEGATIVE")
763 """Decorrelate the effect of convolution by Alard-Lupton matching kernel in image difference
766 ConfigClass = DecorrelateALKernelSpatialConfig
767 _DefaultName = "ip_diffim_decorrelateALKernelSpatial"
770 """Create the image decorrelation Task
775 arguments to be passed to
776 `lsst.pipe.base.task.Task.__init__`
778 additional keyword arguments to be passed to
779 `lsst.pipe.base.task.Task.__init__`
781 pipeBase.Task.__init__(self, *args, **kwargs)
786 self.statsControl.setAndMask(afwImage.Mask.getPlaneBitMask(self.config.ignoreMaskPlanes))
789 """Compute the mean of the variance plane of `exposure`.
794 var = statObj.getValue(afwMath.MEANCLIP)
797 def run(self, scienceExposure, templateExposure, subtractedExposure, psfMatchingKernel,
798 spatiallyVarying=True, preConvKernel=None, templateMatched=True, preConvMode=False):
799 """Perform decorrelation of an image difference exposure.
801 Decorrelates the diffim due to the convolution of the
802 templateExposure with the A&L psfMatchingKernel. If
803 `spatiallyVarying`
is True, it utilizes the spatially varying
804 matching kernel via the `imageMapReduce` framework to perform
805 spatially-varying decorrelation on a grid of subExposures.
810 the science Exposure used
for PSF matching
812 the template Exposure used
for PSF matching
814 the subtracted Exposure produced by `ip_diffim.ImagePsfMatchTask.subtractExposures()`
815 psfMatchingKernel : an (optionally spatially-varying) PSF matching kernel produced
816 by `ip_diffim.ImagePsfMatchTask.subtractExposures()`
817 spatiallyVarying : `bool`
818 if True, perform the spatially-varying operation
819 preConvKernel : `lsst.meas.algorithms.Psf`
820 if not none, the scienceExposure has been pre-filtered
with this kernel. (Currently
821 this option
is experimental.)
822 templateMatched : `bool`, optional
823 If
True, the template exposure was matched (convolved) to the science exposure.
824 preConvMode : `bool`, optional
825 If
True, ``subtractedExposure``
is assumed to be a likelihood difference image
826 and will be noise corrected
as a likelihood image.
830 results : `lsst.pipe.base.Struct`
831 a structure containing:
832 - ``correctedExposure`` : the decorrelated diffim
834 self.log.info('Running A&L decorrelation: spatiallyVarying=%r', spatiallyVarying)
838 if np.isnan(svar)
or np.isnan(tvar):
840 if (np.all(np.isnan(scienceExposure.image.array))
841 or np.all(np.isnan(templateExposure.image.array))):
842 self.log.warning(
'Template or science image is entirely NaNs: skipping decorrelation.')
851 self.log.info(
"Variance (science, template): (%f, %f)", svar, tvar)
852 self.log.info(
"Variance (uncorrected diffim): %f", var)
853 config = self.config.decorrelateMapReduceConfig
855 results = task.run(subtractedExposure, science=scienceExposure,
856 template=templateExposure, psfMatchingKernel=psfMatchingKernel,
857 preConvKernel=preConvKernel, forceEvenSized=
True,
858 templateMatched=templateMatched, preConvMode=preConvMode)
859 results.correctedExposure = results.exposure
864 gm(results.correctedExposure)[:, :] = gm(subtractedExposure)
867 self.log.info(
"Variance (corrected diffim): %f", var)
870 config = self.config.decorrelateConfig
872 results = task.run(scienceExposure, templateExposure,
873 subtractedExposure, psfMatchingKernel, preConvKernel=preConvKernel,
874 templateMatched=templateMatched, preConvMode=preConvMode)
__init__(self, *args, **kwargs)
run(self, subExposure, expandedSubExposure, fullBBox, template, science, alTaskResult=None, psfMatchingKernel=None, preConvKernel=None, **kwargs)
decorrelateMapReduceConfig
__init__(self, *args, **kwargs)
computeVarianceMean(self, exposure)
run(self, scienceExposure, templateExposure, subtractedExposure, psfMatchingKernel, spatiallyVarying=True, preConvKernel=None, templateMatched=True, preConvMode=False)
computeCommonShape(self, *shapes)
computeScoreCorrection(self, kappa, svar, tvar, preConvArr)
__init__(self, *args, **kwargs)
estimateVariancePlane(vplane1, vplane2, c1ft, c2ft)
computeCorrectedDiffimPsf(self, corrft, psfOld)
run(self, scienceExposure, templateExposure, subtractedExposure, psfMatchingKernel, preConvKernel=None, xcen=None, ycen=None, svar=None, tvar=None, templateMatched=True, preConvMode=False, **kwargs)
padCenterOriginArray(A, tuple newShape, useInverse=False)
computeCorrectedImage(self, corrft, imgOld)
computeDiffimCorrection(self, kappa, svar, tvar)
calculateVariancePlane(self, vplane1, vplane2, varMean1, varMean2, c1ft, c2ft)
computeVarianceMean(self, exposure)
Statistics makeStatistics(lsst::afw::image::Image< Pixel > const &img, lsst::afw::image::Mask< image::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl=StatisticsControl())