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
brightStarStamps.py
Go to the documentation of this file.
1 # This file is part of meas_algorithms.
2 #
3 # Developed for the LSST Data Management System.
4 # This product includes software developed by the LSST Project
5 # (https://www.lsst.org).
6 # See the COPYRIGHT file at the top-level directory of this distribution
7 # for details of code ownership.
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <https://www.gnu.org/licenses/>.
21 #
22 """Collection of small images (stamps), each centered on a bright star.
23 """
24 
25 __all__ = ["BrightStarStamp", "BrightStarStamps"]
26 
27 from dataclasses import dataclass
28 from operator import ior
29 from functools import reduce
30 from typing import Optional
31 import numpy as np
32 
33 from lsst.afw.image import MaskedImageF
34 from lsst.afw import geom as afwGeom
35 from lsst.afw import math as afwMath
36 from lsst.afw import table as afwTable
37 from lsst.geom import Point2I
38 from .stamps import Stamps, AbstractStamp, readFitsWithOptions
39 
40 
41 @dataclass
43  """Single stamp centered on a bright star, normalized by its
44  annularFlux.
45 
46  Parameters
47  ----------
48  stamp_im : `lsst.afw.image.MaskedImage`
49  Pixel data for this postage stamp
50  position : `lsst.geom.Point2I`
51  Origin of the stamps in its origin exposure (pixels)
52  gaiaGMag : `float`
53  Gaia G magnitude for the object in this stamp
54  gaiaId : `int`
55  Gaia object identifier
56  annularFlux : `Optional[float]`
57  Flux in an annulus around the object
58  """
59  stamp_im: MaskedImageF
60  gaiaGMag: float
61  gaiaId: int
62  position: Point2I
63  archive_element: Optional[afwTable.io.Persistable] = None
64  annularFlux: Optional[float] = None
65 
66  @classmethod
67  def factory(cls, stamp_im, metadata, idx, archive_element=None):
68  """This method is needed to service the FITS reader.
69  We need a standard interface to construct objects like this.
70  Parameters needed to construct this object are passed in via
71  a metadata dictionary and then passed to the constructor of
72  this class. This particular factory method requires keys:
73  G_MAGS, GAIA_IDS, and ANNULAR_FLUXES. They should each
74  point to lists of values.
75 
76  Parameters
77  ----------
78  stamp_im : `lsst.afw.image.MaskedImage`
79  Pixel data to pass to the constructor
80  metadata : `dict`
81  Dictionary containing the information
82  needed by the constructor.
83  idx : `int`
84  Index into the lists in ``metadata``
85  archive_element : `lsst.afwTable.io.Persistable`, optional
86  Archive element (e.g. Transform or WCS) associated with this stamp.
87 
88  Returns
89  -------
90  brightstarstamp : `BrightStarStamp`
91  An instance of this class
92  """
93  if 'X0S' in metadata and 'Y0S' in metadata:
94  x0 = metadata.getArray('X0S')[idx]
95  y0 = metadata.getArray('Y0S')[idx]
96  position = Point2I(x0, y0)
97  else:
98  position = None
99  return cls(stamp_im=stamp_im,
100  gaiaGMag=metadata.getArray('G_MAGS')[idx],
101  gaiaId=metadata.getArray('GAIA_IDS')[idx],
102  position=position,
103  archive_element=archive_element,
104  annularFlux=metadata.getArray('ANNULAR_FLUXES')[idx])
105 
106  def measureAndNormalize(self, annulus, statsControl=afwMath.StatisticsControl(),
107  statsFlag=afwMath.stringToStatisticsProperty("MEAN"),
108  badMaskPlanes=('BAD', 'SAT', 'NO_DATA')):
109  """Compute "annularFlux", the integrated flux within an annulus
110  around an object's center, and normalize it.
111 
112  Since the center of bright stars are saturated and/or heavily affected
113  by ghosts, we measure their flux in an annulus with a large enough
114  inner radius to avoid the most severe ghosts and contain enough
115  non-saturated pixels.
116 
117  Parameters
118  ----------
119  annulus : `lsst.afw.geom.spanSet.SpanSet`
120  SpanSet containing the annulus to use for normalization.
121  statsControl : `lsst.afw.math.statistics.StatisticsControl`, optional
122  StatisticsControl to be used when computing flux over all pixels
123  within the annulus.
124  statsFlag : `lsst.afw.math.statistics.Property`, optional
125  statsFlag to be passed on to ``afwMath.makeStatistics`` to compute
126  annularFlux. Defaults to a simple MEAN.
127  badMaskPlanes : `collections.abc.Collection` [`str`]
128  Collection of mask planes to ignore when computing annularFlux.
129  """
130  stampSize = self.stamp_im.getDimensions()
131  # create image with the same pixel values within annulus, NO_DATA
132  # elsewhere
133  maskPlaneDict = self.stamp_im.mask.getMaskPlaneDict()
134  annulusImage = MaskedImageF(stampSize, planeDict=maskPlaneDict)
135  annulusMask = annulusImage.mask
136  annulusMask.array[:] = 2**maskPlaneDict['NO_DATA']
137  annulus.copyMaskedImage(self.stamp_im, annulusImage)
138  # set mask planes to be ignored
139  andMask = reduce(ior, (annulusMask.getPlaneBitMask(bm) for bm in badMaskPlanes))
140  statsControl.setAndMask(andMask)
141  # compute annularFlux
142  annulusStat = afwMath.makeStatistics(annulusImage, statsFlag, statsControl)
143  self.annularFluxannularFlux = annulusStat.getValue()
144  if np.isnan(self.annularFluxannularFlux):
145  raise RuntimeError("Annular flux computation failed, likely because no pixels were valid.")
146  # normalize stamps
147  self.stamp_im.image.array /= self.annularFluxannularFlux
148  return None
149 
150 
152  """Collection of bright star stamps and associated metadata.
153 
154  Parameters
155  ----------
156  starStamps : `collections.abc.Sequence` [`BrightStarStamp`]
157  Sequence of star stamps. Cannot contain both normalized and
158  unnormalized stamps.
159  innerRadius : `int`, optional
160  Inner radius value, in pixels. This and ``outerRadius`` define the
161  annulus used to compute the ``"annularFlux"`` values within each
162  ``starStamp``. Must be provided if ``normalize`` is True.
163  outerRadius : `int`, optional
164  Outer radius value, in pixels. This and ``innerRadius`` define the
165  annulus used to compute the ``"annularFlux"`` values within each
166  ``starStamp``. Must be provided if ``normalize`` is True.
167  nb90Rots : `int`, optional
168  Number of 90 degree rotations required to compensate for detector
169  orientation.
170  metadata : `lsst.daf.base.PropertyList`, optional
171  Metadata associated with the bright stars.
172  use_mask : `bool`
173  If `True` read and write mask data. Default `True`.
174  use_variance : `bool`
175  If ``True`` read and write variance data. Default ``False``.
176  use_archive : `bool`
177  If ``True`` read and write an Archive that contains a Persistable
178  associated with each stamp. In the case of bright stars, this is
179  usually a ``TransformPoint2ToPoint2``, used to warp each stamp
180  to the same pixel grid before stacking.
181 
182  Raises
183  ------
184  ValueError
185  Raised if one of the star stamps provided does not contain the
186  required keys.
187  AttributeError
188  Raised if there is a mix-and-match of normalized and unnormalized
189  stamps, stamps normalized with different annulus definitions, or if
190  stamps are to be normalized but annular radii were not provided.
191 
192 
193  Notes
194  -----
195  A butler can be used to read only a part of the stamps, specified by a
196  bbox:
197 
198  >>> starSubregions = butler.get("brightStarStamps", dataId, parameters={'bbox': bbox})
199  """
200 
201  def __init__(self, starStamps, innerRadius=None, outerRadius=None, nb90Rots=None,
202  metadata=None, use_mask=True, use_variance=False, use_archive=False):
203  super().__init__(starStamps, metadata, use_mask, use_variance, use_archive)
204  # Ensure stamps contain a flux measurement if and only if they are
205  # already expected to be normalized
206  self._checkNormalization_checkNormalization(False, innerRadius, outerRadius)
207  self._innerRadius, self._outerRadius_outerRadius = innerRadius, outerRadius
208  if innerRadius is not None and outerRadius is not None:
209  self.normalizednormalized = True
210  else:
211  self.normalizednormalized = False
212  self.nb90Rotsnb90Rots = nb90Rots
213 
214  @classmethod
215  def initAndNormalize(cls, starStamps, innerRadius, outerRadius, nb90Rots=None,
216  metadata=None, use_mask=True, use_variance=False,
217  use_archive=False, imCenter=None,
218  discardNanFluxObjects=True,
219  statsControl=afwMath.StatisticsControl(),
220  statsFlag=afwMath.stringToStatisticsProperty("MEAN"),
221  badMaskPlanes=('BAD', 'SAT', 'NO_DATA')):
222  """Normalize a set of bright star stamps and initialize a
223  BrightStarStamps instance.
224 
225  Since the center of bright stars are saturated and/or heavily affected
226  by ghosts, we measure their flux in an annulus with a large enough
227  inner radius to avoid the most severe ghosts and contain enough
228  non-saturated pixels.
229 
230  Parameters
231  ----------
232  starStamps : `collections.abc.Sequence` [`BrightStarStamp`]
233  Sequence of star stamps. Cannot contain both normalized and
234  unnormalized stamps.
235  innerRadius : `int`
236  Inner radius value, in pixels. This and ``outerRadius`` define the
237  annulus used to compute the ``"annularFlux"`` values within each
238  ``starStamp``.
239  outerRadius : `int`
240  Outer radius value, in pixels. This and ``innerRadius`` define the
241  annulus used to compute the ``"annularFlux"`` values within each
242  ``starStamp``.
243  nb90Rots : `int`, optional
244  Number of 90 degree rotations required to compensate for detector
245  orientation.
246  metadata : `lsst.daf.base.PropertyList`, optional
247  Metadata associated with the bright stars.
248  use_mask : `bool`
249  If `True` read and write mask data. Default `True`.
250  use_variance : `bool`
251  If ``True`` read and write variance data. Default ``False``.
252  use_archive : `bool`
253  If ``True`` read and write an Archive that contains a Persistable
254  associated with each stamp. In the case of bright stars, this is
255  usually a ``TransformPoint2ToPoint2``, used to warp each stamp
256  to the same pixel grid before stacking.
257  imCenter : `collections.abc.Sequence`, optional
258  Center of the object, in pixels. If not provided, the center of the
259  first stamp's pixel grid will be used.
260  discardNanFluxObjects : `bool`
261  Whether objects with NaN annular flux should be discarded.
262  If False, these objects will not be normalized.
263  statsControl : `lsst.afw.math.statistics.StatisticsControl`, optional
264  StatisticsControl to be used when computing flux over all pixels
265  within the annulus.
266  statsFlag : `lsst.afw.math.statistics.Property`, optional
267  statsFlag to be passed on to ``afwMath.makeStatistics`` to compute
268  annularFlux. Defaults to a simple MEAN.
269  badMaskPlanes : `collections.abc.Collection` [`str`]
270  Collection of mask planes to ignore when computing annularFlux.
271 
272  Raises
273  ------
274  ValueError
275  Raised if one of the star stamps provided does not contain the
276  required keys.
277  AttributeError
278  Raised if there is a mix-and-match of normalized and unnormalized
279  stamps, stamps normalized with different annulus definitions, or if
280  stamps are to be normalized but annular radii were not provided.
281  """
282  if imCenter is None:
283  stampSize = starStamps[0].stamp_im.getDimensions()
284  imCenter = stampSize[0]//2, stampSize[1]//2
285  # Create SpanSet of annulus
286  outerCircle = afwGeom.SpanSet.fromShape(outerRadius, afwGeom.Stencil.CIRCLE, offset=imCenter)
287  innerCircle = afwGeom.SpanSet.fromShape(innerRadius, afwGeom.Stencil.CIRCLE, offset=imCenter)
288  annulus = outerCircle.intersectNot(innerCircle)
289  # Initialize (unnormalized) brightStarStamps instance
290  bss = cls(starStamps, innerRadius=None, outerRadius=None, nb90Rots=nb90Rots,
291  metadata=metadata, use_mask=use_mask,
292  use_variance=use_variance, use_archive=use_archive)
293  # Ensure no stamps had already been normalized
294  bss._checkNormalization(True, innerRadius, outerRadius)
295  bss._innerRadius, bss._outerRadius = innerRadius, outerRadius
296  # Apply normalization
297  for j, stamp in enumerate(bss._stamps):
298  try:
299  stamp.measureAndNormalize(annulus, statsControl=statsControl, statsFlag=statsFlag,
300  badMaskPlanes=badMaskPlanes)
301  except RuntimeError:
302  # Optionally keep NaN flux objects, for bookkeeping purposes,
303  # and to avoid having to re-find and redo the preprocessing
304  # steps needed before bright stars can be subtracted.
305  if discardNanFluxObjects:
306  bss._stamps.pop(j)
307  else:
308  stamp.annularFlux = np.nan
309  bss.normalized = True
310  return bss
311 
312  def _refresh_metadata(self):
313  """Refresh the metadata. Should be called before writing this object
314  out.
315  """
316  # add full list of positions, Gaia magnitudes, IDs and annularFlxes to
317  # shared metadata
318  self._metadata_metadata["G_MAGS"] = self.getMagnitudesgetMagnitudes()
319  self._metadata_metadata["GAIA_IDS"] = self.getGaiaIdsgetGaiaIds()
320  positions = self.getPositionsgetPositions()
321  self._metadata_metadata["X0S"] = [xy0[0] for xy0 in positions]
322  self._metadata_metadata["Y0S"] = [xy0[1] for xy0 in positions]
323  self._metadata_metadata["ANNULAR_FLUXES"] = self.getAnnularFluxesgetAnnularFluxes()
324  self._metadata_metadata["NORMALIZED"] = self.normalizednormalized
325  self._metadata_metadata["INNER_RADIUS"] = self._innerRadius
326  self._metadata_metadata["OUTER_RADIUS"] = self._outerRadius_outerRadius
327  if self.nb90Rotsnb90Rots is not None:
328  self._metadata_metadata["NB_90_ROTS"] = self.nb90Rotsnb90Rots
329  return None
330 
331  @classmethod
332  def readFits(cls, filename):
333  """Build an instance of this class from a file.
334 
335  Parameters
336  ----------
337  filename : `str`
338  Name of the file to read
339  """
340  return cls.readFitsWithOptionsreadFitsWithOptionsreadFitsWithOptionsreadFitsWithOptions(filename, None)
341 
342  @classmethod
343  def readFitsWithOptions(cls, filename, options):
344  """Build an instance of this class with options.
345 
346  Parameters
347  ----------
348  filename : `str`
349  Name of the file to read
350  options : `PropertyList`
351  Collection of metadata parameters
352  """
353  stamps, metadata = readFitsWithOptions(filename, BrightStarStamp.factory, options)
354  nb90Rots = metadata["NB_90_ROTS"] if "NB_90_ROTS" in metadata else None
355  if metadata["NORMALIZED"]:
356  return cls(stamps,
357  innerRadius=metadata["INNER_RADIUS"], outerRadius=metadata["OUTER_RADIUS"],
358  nb90Rots=nb90Rots, metadata=metadata, use_mask=metadata['HAS_MASK'],
359  use_variance=metadata['HAS_VARIANCE'], use_archive=metadata['HAS_ARCHIVE'])
360  else:
361  return cls(stamps, nb90Rots=nb90Rots, metadata=metadata, use_mask=metadata['HAS_MASK'],
362  use_variance=metadata['HAS_VARIANCE'], use_archive=metadata['HAS_ARCHIVE'])
363 
364  def append(self, item, innerRadius=None, outerRadius=None):
365  """Add an additional bright star stamp.
366 
367  Parameters
368  ----------
369  item : `BrightStarStamp`
370  Bright star stamp to append.
371  innerRadius : `int`, optional
372  Inner radius value, in pixels. This and ``outerRadius`` define the
373  annulus used to compute the ``"annularFlux"`` values within each
374  ``BrightStarStamp``.
375  outerRadius : `int`, optional
376  Outer radius value, in pixels. This and ``innerRadius`` define the
377  annulus used to compute the ``"annularFlux"`` values within each
378  ``BrightStarStamp``.
379  """
380  if not isinstance(item, BrightStarStamp):
381  raise ValueError(f"Can only add instances of BrightStarStamp, got {type(item)}.")
382  if (item.annularFlux is None) == self.normalizednormalized:
383  raise AttributeError("Trying to append an unnormalized stamp to a normalized BrightStarStamps "
384  "instance, or vice-versa.")
385  else:
386  self._checkRadius_checkRadius(innerRadius, outerRadius)
387  self._stamps_stamps.append(item)
388  return None
389 
390  def extend(self, bss):
391  """Extend BrightStarStamps instance by appending elements from another
392  instance.
393 
394  Parameters
395  ----------
396  bss : `BrightStarStamps`
397  Other instance to concatenate.
398  """
399  if not isinstance(bss, BrightStarStamps):
400  raise ValueError('Can only extend with a BrightStarStamps object. '
401  f'Got {type(bss)}.')
402  self._checkRadius_checkRadius(bss._innerRadius, bss._outerRadius)
403  self._stamps_stamps += bss._stamps
404 
405  def getMagnitudes(self):
406  """Retrieve Gaia G magnitudes for each star.
407 
408  Returns
409  -------
410  gaiaGMags : `list` [`float`]
411  """
412  return [stamp.gaiaGMag for stamp in self._stamps_stamps]
413 
414  def getGaiaIds(self):
415  """Retrieve Gaia IDs for each star.
416 
417  Returns
418  -------
419  gaiaIds : `list` [`int`]
420  """
421  return [stamp.gaiaId for stamp in self._stamps_stamps]
422 
423  def getAnnularFluxes(self):
424  """Retrieve normalization factors for each star.
425 
426  These are computed by integrating the flux in annulus centered on the
427  bright star, far enough from center to be beyond most severe ghosts and
428  saturation. The inner and outer radii that define the annulus can be
429  recovered from the metadata.
430 
431  Returns
432  -------
433  annularFluxes : `list` [`float`]
434  """
435  return [stamp.annularFlux for stamp in self._stamps_stamps]
436 
437  def selectByMag(self, magMin=None, magMax=None):
438  """Return the subset of bright star stamps for objects with specified
439  magnitude cuts (in Gaia G).
440 
441  Parameters
442  ----------
443  magMin : `float`, optional
444  Keep only stars fainter than this value.
445  magMax : `float`, optional
446  Keep only stars brighter than this value.
447  """
448  subset = [stamp for stamp in self._stamps_stamps
449  if (magMin is None or stamp.gaiaGMag > magMin)
450  and (magMax is None or stamp.gaiaGMag < magMax)]
451  # This is an optimization to save looping over the init argument when
452  # it is already guaranteed to be the correct type
453  instance = BrightStarStamps((),
454  innerRadius=self._innerRadius, outerRadius=self._outerRadius_outerRadius,
455  metadata=self._metadata_metadata)
456  instance._stamps = subset
457  return instance
458 
459  def _checkRadius(self, innerRadius, outerRadius):
460  """Ensure provided annulus radius is consistent with that already
461  present in the instance, or with arguments passed on at initialization.
462  """
463  if innerRadius != self._innerRadius or outerRadius != self._outerRadius_outerRadius:
464  raise AttributeError("Trying to mix stamps normalized with annulus radii "
465  f"{innerRadius, outerRadius} with those of BrightStarStamp instance\n"
466  f"(computed with annular radii {self._innerRadius, self._outerRadius}).")
467 
468  def _checkNormalization(self, normalize, innerRadius, outerRadius):
469  """Ensure there is no mixing of normalized and unnormalized stars, and
470  that, if requested, normalization can be performed.
471  """
472  noneFluxCount = self.getAnnularFluxesgetAnnularFluxes().count(None)
473  nStamps = len(self)
474  nFluxVals = nStamps - noneFluxCount
475  if noneFluxCount and noneFluxCount < nStamps:
476  # at least one stamp contains an annularFlux value (i.e. has been
477  # normalized), but not all of them do
478  raise AttributeError(f"Only {nFluxVals} stamps contain an annularFlux value.\nAll stamps in a "
479  "BrightStarStamps instance must either be normalized with the same annulus "
480  "definition, or none of them can contain an annularFlux value.")
481  elif normalize:
482  # stamps are to be normalized; ensure annular radii are specified
483  # and they have no annularFlux
484  if innerRadius is None or outerRadius is None:
485  raise AttributeError("For stamps to be normalized (normalize=True), please provide a valid "
486  "value (in pixels) for both innerRadius and outerRadius.")
487  elif noneFluxCount < nStamps:
488  raise AttributeError(f"{nFluxVals} stamps already contain an annularFlux value. For stamps to"
489  " be normalized, all their annularFlux must be None.")
490  elif innerRadius is not None and outerRadius is not None:
491  # Radii provided, but normalize=False; check that stamps
492  # already contain annularFluxes
493  if noneFluxCount:
494  raise AttributeError(f"{noneFluxCount} stamps contain no annularFlux, but annular radius "
495  "values were provided and normalize=False.\nTo normalize stamps, set "
496  "normalize to True.")
497  else:
498  # At least one radius value is missing; ensure no stamps have
499  # already been normalized
500  if nFluxVals:
501  raise AttributeError(f"{nFluxVals} stamps contain an annularFlux value. If stamps have "
502  "been normalized, the innerRadius and outerRadius values used must "
503  "be provided.")
504  return None
def factory(cls, stamp_im, metadata, idx, archive_element=None)
def measureAndNormalize(self, annulus, statsControl=afwMath.StatisticsControl(), statsFlag=afwMath.stringToStatisticsProperty("MEAN"), badMaskPlanes=('BAD', 'SAT', 'NO_DATA'))
def __init__(self, starStamps, innerRadius=None, outerRadius=None, nb90Rots=None, metadata=None, use_mask=True, use_variance=False, use_archive=False)
def _checkNormalization(self, normalize, innerRadius, outerRadius)
def append(self, item, innerRadius=None, outerRadius=None)
def initAndNormalize(cls, starStamps, innerRadius, outerRadius, nb90Rots=None, metadata=None, use_mask=True, use_variance=False, use_archive=False, imCenter=None, discardNanFluxObjects=True, statsControl=afwMath.StatisticsControl(), statsFlag=afwMath.stringToStatisticsProperty("MEAN"), badMaskPlanes=('BAD', 'SAT', 'NO_DATA'))
def readFitsWithOptions(cls, filename, options)
Definition: stamps.py:325
def readFitsWithOptions(cls, filename, options)
Definition: stamps.py:462
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
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
Property stringToStatisticsProperty(std::string const property)
Conversion function to switch a string to a Property (see Statistics.h)
Definition: Statistics.cc:738
Point< int, 2 > Point2I
Definition: Point.h:321