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 | List of all members
lsst.pipe.drivers.background.FocalPlaneBackground Class Reference

Public Member Functions

def fromCamera (cls, config, camera)
 
def __init__ (self, config, dims, transform, values=None, numbers=None)
 
def __reduce__ (self)
 
def clone (self)
 
def addCcd (self, exposure)
 
def toCcdBackground (self, detector, bbox)
 
def merge (self, other)
 
def __iadd__ (self, other)
 
def getStatsImage (self)
 

Public Attributes

 config
 
 dims
 
 transform
 

Detailed Description

Background model for a focal plane camera

We model the background empirically with the "superpixel" method: we
measure the background in each superpixel and interpolate between
superpixels to yield the model.

The principal difference between this and `lsst.afw.math.BackgroundMI`
is that here the superpixels are defined in the frame of the focal
plane of the camera which removes discontinuities across detectors.

The constructor you probably want to use is the `fromCamera` classmethod.

There are two use patterns for building a background model:

* Serial: create a `FocalPlaneBackground`, then `addCcd` for each of the
  CCDs in an exposure.

* Parallel: create a `FocalPlaneBackground`, then `clone` it for each
  of the CCDs in an exposure and use those to `addCcd` their respective
  CCD image. Finally, `merge` all the clones into the original.

Once you've built the background model, you can apply it to individual
CCDs with the `toCcdBackground` method.

Definition at line 482 of file background.py.

Constructor & Destructor Documentation

◆ __init__()

def lsst.pipe.drivers.background.FocalPlaneBackground.__init__ (   self,
  config,
  dims,
  transform,
  values = None,
  numbers = None 
)
Constructor

Developers should note that changes to the signature of this method
require coordinated changes to the `__reduce__` and `clone` methods.

Parameters
----------
config : `FocalPlaneBackgroundConfig`
    Configuration for measuring backgrounds.
dims : `lsst.geom.Extent2I`
    Dimensions for background samples.
transform : `lsst.afw.geom.TransformPoint2ToPoint2`
    Transformation from focal plane coordinates to sample coordinates.
values : `lsst.afw.image.ImageF`
    Measured background values.
numbers : `lsst.afw.image.ImageF`
    Number of pixels in each background measurement.

Definition at line 536 of file background.py.

536  def __init__(self, config, dims, transform, values=None, numbers=None):
537  """Constructor
538 
539  Developers should note that changes to the signature of this method
540  require coordinated changes to the `__reduce__` and `clone` methods.
541 
542  Parameters
543  ----------
544  config : `FocalPlaneBackgroundConfig`
545  Configuration for measuring backgrounds.
546  dims : `lsst.geom.Extent2I`
547  Dimensions for background samples.
548  transform : `lsst.afw.geom.TransformPoint2ToPoint2`
549  Transformation from focal plane coordinates to sample coordinates.
550  values : `lsst.afw.image.ImageF`
551  Measured background values.
552  numbers : `lsst.afw.image.ImageF`
553  Number of pixels in each background measurement.
554  """
555  self.config = config
556  self.dims = dims
557  self.transform = transform
558 
559  if values is None:
560  values = afwImage.ImageF(self.dims)
561  values.set(0.0)
562  else:
563  values = values.clone()
564  assert(values.getDimensions() == self.dims)
565  self._values = values
566  if numbers is None:
567  numbers = afwImage.ImageF(self.dims) # float for dynamic range and convenience
568  numbers.set(0.0)
569  else:
570  numbers = numbers.clone()
571  assert(numbers.getDimensions() == self.dims)
572  self._numbers = numbers
573 

Member Function Documentation

◆ __iadd__()

def lsst.pipe.drivers.background.FocalPlaneBackground.__iadd__ (   self,
  other 
)
Merge with another FocalPlaneBackground

Parameters
----------
other : `FocalPlaneBackground`
    Another background model to merge.

Returns
-------
self : `FocalPlaneBackground`
    The merged background model.

Definition at line 708 of file background.py.

708  def __iadd__(self, other):
709  """Merge with another FocalPlaneBackground
710 
711  Parameters
712  ----------
713  other : `FocalPlaneBackground`
714  Another background model to merge.
715 
716  Returns
717  -------
718  self : `FocalPlaneBackground`
719  The merged background model.
720  """
721  return self.merge(other)
722 

◆ __reduce__()

def lsst.pipe.drivers.background.FocalPlaneBackground.__reduce__ (   self)

Definition at line 574 of file background.py.

574  def __reduce__(self):
575  return self.__class__, (self.config, self.dims, self.transform, self._values, self._numbers)
576 

◆ addCcd()

def lsst.pipe.drivers.background.FocalPlaneBackground.addCcd (   self,
  exposure 
)
Add CCD to model

We measure the background on the CCD (clipped mean), and record
the results in the model.  For simplicity, measurements are made
in a box on the CCD corresponding to the warped coordinates of the
superpixel rather than accounting for little rotations, etc.
We also record the number of pixels used in the measurement so we
can have a measure of confidence in each bin's value.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    CCD exposure to measure

Definition at line 580 of file background.py.

580  def addCcd(self, exposure):
581  """Add CCD to model
582 
583  We measure the background on the CCD (clipped mean), and record
584  the results in the model. For simplicity, measurements are made
585  in a box on the CCD corresponding to the warped coordinates of the
586  superpixel rather than accounting for little rotations, etc.
587  We also record the number of pixels used in the measurement so we
588  can have a measure of confidence in each bin's value.
589 
590  Parameters
591  ----------
592  exposure : `lsst.afw.image.Exposure`
593  CCD exposure to measure
594  """
595  detector = exposure.getDetector()
596  transform = detector.getTransformMap().getTransform(detector.makeCameraSys(afwCameraGeom.PIXELS),
597  detector.makeCameraSys(afwCameraGeom.FOCAL_PLANE))
598  image = exposure.getMaskedImage()
599  maskVal = image.getMask().getPlaneBitMask(self.config.mask)
600 
601  # Warp the binned image to the focal plane
602  toSample = transform.then(self.transform) # CCD pixels --> focal plane --> sample
603 
604  warped = afwImage.ImageF(self._values.getBBox())
605  warpedCounts = afwImage.ImageF(self._numbers.getBBox())
606  width, height = warped.getDimensions()
607 
608  stats = afwMath.StatisticsControl()
609  stats.setAndMask(maskVal)
610  stats.setNanSafe(True)
611  # Iterating over individual pixels in python is usually bad because it's slow, but there aren't many.
612  pixels = itertools.product(range(width), range(height))
613  for xx, yy in pixels:
614  llc = toSample.applyInverse(geom.Point2D(xx - 0.5, yy - 0.5))
615  urc = toSample.applyInverse(geom.Point2D(xx + 0.5, yy + 0.5))
616  bbox = geom.Box2I(geom.Point2I(llc), geom.Point2I(urc))
617  bbox.clip(image.getBBox())
618  if bbox.isEmpty():
619  continue
620  subImage = image.Factory(image, bbox)
621  result = afwMath.makeStatistics(subImage, afwMath.MEANCLIP | afwMath.NPOINT, stats)
622  mean = result.getValue(afwMath.MEANCLIP)
623  num = result.getValue(afwMath.NPOINT)
624  if not numpy.isfinite(mean) or not numpy.isfinite(num):
625  continue
626  warped[xx, yy, afwImage.LOCAL] = mean*num
627  warpedCounts[xx, yy, afwImage.LOCAL] = num
628 
629  self._values += warped
630  self._numbers += warpedCounts
631 
Pass parameters to a Statistics object.
Definition: Statistics.h:92
An integer coordinate rectangle.
Definition: Box.h:55
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)
Definition: Statistics.h:359

◆ clone()

def lsst.pipe.drivers.background.FocalPlaneBackground.clone (   self)

Definition at line 577 of file background.py.

577  def clone(self):
578  return self.__class__(self.config, self.dims, self.transform, self._values, self._numbers)
579 

◆ fromCamera()

def lsst.pipe.drivers.background.FocalPlaneBackground.fromCamera (   cls,
  config,
  camera 
)
Construct from a camera object

Parameters
----------
config : `FocalPlaneBackgroundConfig`
    Configuration for measuring backgrounds.
camera : `lsst.afw.cameraGeom.Camera`
    Camera for which to measure backgrounds.

Definition at line 508 of file background.py.

508  def fromCamera(cls, config, camera):
509  """Construct from a camera object
510 
511  Parameters
512  ----------
513  config : `FocalPlaneBackgroundConfig`
514  Configuration for measuring backgrounds.
515  camera : `lsst.afw.cameraGeom.Camera`
516  Camera for which to measure backgrounds.
517  """
518  cameraBox = geom.Box2D()
519  for ccd in camera:
520  for point in ccd.getCorners(afwCameraGeom.FOCAL_PLANE):
521  cameraBox.include(point)
522 
523  width, height = cameraBox.getDimensions()
524  # Offset so that we run from zero
525  offset = geom.Extent2D(cameraBox.getMin())*-1
526  # Add an extra pixel buffer on either side
527  dims = geom.Extent2I(int(numpy.ceil(width/config.xSize)) + 2,
528  int(numpy.ceil(height/config.ySize)) + 2)
529  # Transform takes us from focal plane coordinates --> sample coordinates
530  transform = (geom.AffineTransform.makeTranslation(geom.Extent2D(1, 1))*
531  geom.AffineTransform.makeScaling(1.0/config.xSize, 1.0/config.ySize)*
532  geom.AffineTransform.makeTranslation(offset))
533 
534  return cls(config, dims, afwGeom.makeTransform(transform))
535 
A floating-point coordinate rectangle geometry.
Definition: Box.h:413
std::shared_ptr< TransformPoint2ToPoint2 > makeTransform(lsst::geom::AffineTransform const &affine)
Wrap an lsst::geom::AffineTransform as a Transform.

◆ getStatsImage()

def lsst.pipe.drivers.background.FocalPlaneBackground.getStatsImage (   self)
Return the background model data

This is the measurement of the background for each of the superpixels.

Definition at line 723 of file background.py.

723  def getStatsImage(self):
724  """Return the background model data
725 
726  This is the measurement of the background for each of the superpixels.
727  """
728  values = self._values.clone()
729  values /= self._numbers
730  thresh = (self.config.minFrac*
731  (self.config.xSize/self.config.pixelSize)*(self.config.ySize/self.config.pixelSize))
732  isBad = self._numbers.getArray() < thresh
733  if self.config.doSmooth:
734  array = values.getArray()
735  array[:] = smoothArray(array, isBad, self.config.smoothScale)
736  isBad = numpy.isnan(values.array)
737  if numpy.any(isBad):
738  interpolateBadPixels(values.getArray(), isBad, self.config.interpolation)
739  return values
740 
741 
def interpolateBadPixels(array, isBad, interpolationStyle)
Definition: background.py:415
def smoothArray(array, bad, sigma)
Definition: background.py:849

◆ merge()

def lsst.pipe.drivers.background.FocalPlaneBackground.merge (   self,
  other 
)
Merge with another FocalPlaneBackground

This allows multiple background models to be constructed from
different CCDs, and then merged to form a single consistent
background model for the entire focal plane.

Parameters
----------
other : `FocalPlaneBackground`
    Another background model to merge.

Returns
-------
self : `FocalPlaneBackground`
    The merged background model.

Definition at line 682 of file background.py.

682  def merge(self, other):
683  """Merge with another FocalPlaneBackground
684 
685  This allows multiple background models to be constructed from
686  different CCDs, and then merged to form a single consistent
687  background model for the entire focal plane.
688 
689  Parameters
690  ----------
691  other : `FocalPlaneBackground`
692  Another background model to merge.
693 
694  Returns
695  -------
696  self : `FocalPlaneBackground`
697  The merged background model.
698  """
699  if (self.config.xSize, self.config.ySize) != (other.config.xSize, other.config.ySize):
700  raise RuntimeError("Size mismatch: %s vs %s" % ((self.config.xSize, self.config.ySize),
701  (other.config.xSize, other.config.ySize)))
702  if self.dims != other.dims:
703  raise RuntimeError("Dimensions mismatch: %s vs %s" % (self.dims, other.dims))
704  self._values += other._values
705  self._numbers += other._numbers
706  return self
707 

◆ toCcdBackground()

def lsst.pipe.drivers.background.FocalPlaneBackground.toCcdBackground (   self,
  detector,
  bbox 
)
Produce a background model for a CCD

The superpixel background model is warped back to the
CCD frame, for application to the individual CCD.

Parameters
----------
detector : `lsst.afw.cameraGeom.Detector`
    CCD for which to produce background model.
bbox : `lsst.geom.Box2I`
    Bounding box of CCD exposure.

Returns
-------
bg : `lsst.afw.math.BackgroundList`
    Background model for CCD.

Definition at line 632 of file background.py.

632  def toCcdBackground(self, detector, bbox):
633  """Produce a background model for a CCD
634 
635  The superpixel background model is warped back to the
636  CCD frame, for application to the individual CCD.
637 
638  Parameters
639  ----------
640  detector : `lsst.afw.cameraGeom.Detector`
641  CCD for which to produce background model.
642  bbox : `lsst.geom.Box2I`
643  Bounding box of CCD exposure.
644 
645  Returns
646  -------
647  bg : `lsst.afw.math.BackgroundList`
648  Background model for CCD.
649  """
650  transform = detector.getTransformMap().getTransform(detector.makeCameraSys(afwCameraGeom.PIXELS),
651  detector.makeCameraSys(afwCameraGeom.FOCAL_PLANE))
652  binTransform = (geom.AffineTransform.makeScaling(self.config.binning)*
653  geom.AffineTransform.makeTranslation(geom.Extent2D(0.5, 0.5)))
654 
655  # Binned image on CCD --> unbinned image on CCD --> focal plane --> binned focal plane
656  toSample = afwGeom.makeTransform(binTransform).then(transform).then(self.transform)
657 
658  focalPlane = self.getStatsImage()
659  fpNorm = afwImage.ImageF(focalPlane.getBBox())
660  fpNorm.set(1.0)
661 
662  image = afwImage.ImageF(bbox.getDimensions()//self.config.binning)
663  norm = afwImage.ImageF(image.getBBox())
664  ctrl = afwMath.WarpingControl("bilinear")
665  afwMath.warpImage(image, focalPlane, toSample.inverted(), ctrl)
666  afwMath.warpImage(norm, fpNorm, toSample.inverted(), ctrl)
667  image /= norm
668 
669  mask = afwImage.Mask(image.getBBox())
670  isBad = numpy.isnan(image.getArray())
671  mask.getArray()[isBad] = mask.getPlaneBitMask("BAD")
672  image.getArray()[isBad] = image.getArray()[~isBad].mean()
673 
674  return afwMath.BackgroundList(
675  (afwMath.BackgroundMI(bbox, afwImage.makeMaskedImage(image, mask)),
676  afwMath.stringToInterpStyle(self.config.interpolation),
677  afwMath.stringToUndersampleStyle("REDUCE_INTERP_ORDER"),
678  afwMath.ApproximateControl.UNKNOWN,
679  0, 0, False)
680  )
681 
Represent a 2-dimensional array of bitmask pixels.
Definition: Mask.h:77
A class to evaluate image background levels.
Definition: Background.h:434
Parameters to control convolution.
Definition: warpExposure.h:276
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.
Definition: MaskedImage.h:1240
Interpolate::Style stringToInterpStyle(std::string const &style)
Conversion function to switch a string to an Interpolate::Style.
Definition: Interpolate.cc:256
int warpImage(DestImageT &destImage, geom::SkyWcs const &destWcs, SrcImageT const &srcImage, geom::SkyWcs const &srcWcs, WarpingControl const &control, typename DestImageT::SinglePixel padValue=lsst::afw::math::edgePixel< DestImageT >(typename lsst::afw::image::detail::image_traits< DestImageT >::image_category()))
Warp an Image or MaskedImage to a new Wcs.
UndersampleStyle stringToUndersampleStyle(std::string const &style)
Conversion function to switch a string to an UndersampleStyle.
Definition: Background.cc:117

Member Data Documentation

◆ config

lsst.pipe.drivers.background.FocalPlaneBackground.config

Definition at line 555 of file background.py.

◆ dims

lsst.pipe.drivers.background.FocalPlaneBackground.dims

Definition at line 556 of file background.py.

◆ transform

lsst.pipe.drivers.background.FocalPlaneBackground.transform

Definition at line 557 of file background.py.


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