22 from contextlib 
import contextmanager
 
   30 from lsst.utils.timer 
import timeMethod
 
   32 __all__ = [
"InterpImageConfig", 
"InterpImageTask"]
 
   36     """Config for InterpImageTask 
   38     modelPsf = measAlg.GaussianPsfFactory.makeField(doc=
"Model Psf factory")
 
   40     useFallbackValueAtEdge = pexConfig.Field(
 
   42         doc=
"Smoothly taper to the fallback value at the edge of the image?",
 
   45     fallbackValueType = pexConfig.ChoiceField(
 
   47         doc=
"Type of statistic to calculate edge fallbackValue for interpolation",
 
   51             "MEANCLIP": 
"clipped mean",
 
   52             "USER": 
"user value set in fallbackUserValue config",
 
   56     fallbackUserValue = pexConfig.Field(
 
   58         doc=
"If fallbackValueType is 'USER' then use this as the fallbackValue; ignored otherwise",
 
   61     negativeFallbackAllowed = pexConfig.Field(
 
   63         doc=(
"Allow negative values for egde interpolation fallbackValue?  If False, set " 
   64              "fallbackValue to max(fallbackValue, 0.0)"),
 
   67     transpose = pexConfig.Field(dtype=int, default=
False,
 
   68                                 doc=
"Transpose image before interpolating? " 
   69                                     "This allows the interpolation to act over columns instead of rows.")
 
   72         pexConfig.Config.validate(self)
 
   76                 raise ValueError(
"User supplied fallbackValue is negative (%.2f) but " 
   81     """Interpolate over bad image pixels 
   83     ConfigClass = InterpImageConfig
 
   84     _DefaultName = 
"interpImage" 
   86     def _setFallbackValue(self, mi=None):
 
   87         """Set the edge fallbackValue for interpolation 
   89         @param[in] mi  input maksedImage on which to calculate the statistics 
   90                        Must be provided if fallbackValueType != "USER". 
   92         @return fallbackValue  The value set/computed based on the fallbackValueType 
   93                                and negativeFallbackAllowed config parameters 
   95         if self.config.fallbackValueType != 
'USER':
 
   96             assert mi, 
"No maskedImage provided" 
   97         if self.config.fallbackValueType == 
'MEAN':
 
   99         elif self.config.fallbackValueType == 
'MEDIAN':
 
  101         elif self.config.fallbackValueType == 
'MEANCLIP':
 
  103         elif self.config.fallbackValueType == 
'USER':
 
  104             fallbackValue = self.config.fallbackUserValue
 
  106             raise NotImplementedError(
"%s : %s not implemented" %
 
  107                                       (
"fallbackValueType", self.config.fallbackValueType))
 
  109         if not self.config.negativeFallbackAllowed 
and fallbackValue < 0.0:
 
  110             self.log.
warning(
"Negative interpolation edge fallback value computed but " 
  111                              "negativeFallbackAllowed is False: setting fallbackValue to 0.0")
 
  112             fallbackValue = 
max(fallbackValue, 0.0)
 
  114         self.log.
info(
"fallbackValueType %s has been set to %.4f",
 
  115                       self.config.fallbackValueType, fallbackValue)
 
  120     def run(self, image, planeName=None, fwhmPixels=None, defects=None):
 
  121         """!Interpolate in place over pixels in a maskedImage marked as bad 
  123         Pixels to be interpolated are set by either a mask planeName provided 
  124         by the caller OR a defects list of type `~lsst.meas.algorithms.Defects` 
  125         If both are provided an exception is raised. 
  127         Note that the interpolation code in meas_algorithms currently doesn't 
  128         use the input PSF (though it's a required argument), so it's not 
  129         important to set the input PSF parameters exactly.  This PSF is set 
  130         here as the psf attached to the "image" (i.e if the image passed in 
  131         is an Exposure).  Otherwise, a psf model is created using 
  132         measAlg.GaussianPsfFactory with the value of fwhmPixels (the value 
  133         passed in by the caller, or the default defaultFwhm set in 
  134         measAlg.GaussianPsfFactory if None). 
  136         @param[in,out] image       MaskedImage OR Exposure to be interpolated 
  137         @param[in]     planeName   name of mask plane over which to interpolate 
  138                                    If None, must provide a defects list. 
  139         @param[in]     fwhmPixels  FWHM of core star (pixels) 
  140                                    If None the default is used, where the default 
  141                                    is set to the exposure psf if available 
  142         @param[in]     defects     List of defects of type ipIsr.Defects 
  143                                    over which to interpolate. 
  146             maskedImage = image.getMaskedImage()
 
  147         except AttributeError:
 
  151         if planeName 
is None:
 
  153                 raise ValueError(
"No defects or plane name provided")
 
  155                 if not isinstance(defects, ipIsr.Defects):
 
  156                     defectList = ipIsr.Defects(defects)
 
  159                 planeName = 
"defects" 
  161             if defects 
is not None:
 
  162                 raise ValueError(
"Provide EITHER a planeName OR a list of defects, not both")
 
  163             if planeName 
not in maskedImage.getMask().getMaskPlaneDict():
 
  164                 raise ValueError(
"maskedImage does not contain mask plane %s" % planeName)
 
  165             defectList = ipIsr.Defects.fromMask(maskedImage, planeName)
 
  170             self.log.
info(
"Setting psf for interpolation from image")
 
  171         except AttributeError:
 
  172             self.log.
info(
"Creating psf model for interpolation from fwhm(pixels) = %s",
 
  173                           str(fwhmPixels) 
if fwhmPixels 
is not None else 
  174                           (str(self.config.modelPsf.defaultFwhm)) + 
" [default]")
 
  175             psf = self.config.modelPsf.apply(fwhm=fwhmPixels)
 
  178         if self.config.useFallbackValueAtEdge:
 
  181         self.
interpolateImageinterpolateImage(maskedImage, psf, defectList, fallbackValue)
 
  183         self.log.
info(
"Interpolated over %d %s pixels.", len(defectList), planeName)
 
  187         """Context manager to potentially transpose an image 
  189         This applies the ``transpose`` configuration setting. 
  191         Transposing the image allows us to interpolate along columns instead 
  192         of rows, which is useful when the saturation trails are typically 
  193         oriented along rows on the warped/coadded images, instead of along 
  194         columns as they typically are in raw CCD images. 
  198         maskedImage : `lsst.afw.image.MaskedImage` 
  199             Image on which to perform interpolation. 
  200         defects : `lsst.meas.algorithms.Defects` 
  201             List of defects to interpolate over. 
  205         useImage : `lsst.afw.image.MaskedImage` 
  206             Image to use for interpolation; it may have been transposed. 
  207         useDefects : `lsst.meas.algorithms.Defects` 
  208             List of defects to use for interpolation; they may have been 
  211         def transposeImage(image):
 
  212             """Transpose an image""" 
  213             transposed = image.array.T.copy()  
 
  214             return image.Factory(transposed, 
False, 
lsst.geom.Point2I(*reversed(image.getXY0())))
 
  216         useImage = maskedImage
 
  218         if self.config.transpose:
 
  220                                                 transposeImage(maskedImage.mask),
 
  221                                                 transposeImage(maskedImage.variance))
 
  222             useDefects = defects.transpose()
 
  223         yield useImage, useDefects
 
  224         if self.config.transpose:
 
  225             maskedImage.image.array = useImage.image.array.T
 
  226             maskedImage.mask.array = useImage.mask.array.T
 
  227             maskedImage.variance.array = useImage.variance.array.T
 
  230         """Interpolate over defects in an image 
  234         maskedImage : `lsst.afw.image.MaskedImage` 
  235             Image on which to perform interpolation. 
  236         psf : `lsst.afw.detection.Psf` 
  237             Point-spread function; currently unused. 
  238         defectList : `lsst.meas.algorithms.Defects` 
  239             List of defects to interpolate over. 
  240         fallbackValue : `float` 
  241             Value to set when interpolation fails. 
  245         with self.
transposeContexttransposeContext(maskedImage, defectList) 
as (image, defects):
 
  246             measAlg.interpolateOverDefects(image, psf, defects, fallbackValue,
 
  247                                            self.config.useFallbackValueAtEdge)
 
def interpolateImage(self, maskedImage, psf, defectList, fallbackValue)
def _setFallbackValue(self, mi=None)
def run(self, image, planeName=None, fwhmPixels=None, defects=None)
Interpolate in place over pixels in a maskedImage marked as bad.
def transposeContext(self, maskedImage, defects)
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
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.
Statistics makeStatistics(lsst::afw::image::Image< Pixel > const &img, lsst::afw::image::Mask< image::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl=StatisticsControl())
Handle a watered-down front-end to the constructor (no variance)
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations.