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
_backgroundList.py
Go to the documentation of this file.
1 # This file is part of afw.
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 __all__ = ["BackgroundList"]
23 
24 import os
25 import lsst.daf.base as dafBase
26 import lsst.geom
27 import lsst.afw.image as afwImage
28 from lsst.afw.fits import MemFileManager, reduceToFits, Fits
29 from ._math import Interpolate, ApproximateControl, BackgroundMI, UndersampleStyle
30 
31 
33  """A list-like class to contain a list of (`lsst.afw.math.Background`,
34  `lsst.afw.math.Interpolate.Style`, `~lsst.afw.math.UndersampleStyle`)
35  tuples.
36 
37  Parameters
38  ----------
39  *args : `tuple` or `~lsst.afw.math.Background`
40  A sequence of arguments, each of which becomes an element of the list.
41  We also accept a single `lsst.afw.math.Background` and extract the
42  ``interpStyle`` and ``undersampleStyle`` from the as-used values.
43  """
44 
45  def __init__(self, *args):
46  self._backgrounds_backgrounds = []
47  for a in args:
48  self.appendappend(a)
49 
50  def __getitem__(self, *args):
51  """Return an item
52 
53  Parameters
54  ----------
55  *args
56  Any valid list index.
57  """
58  #
59  # Set any previously-unknown Styles (they are set by bkgd.getImage())
60  #
61  for i, val in enumerate(self._backgrounds_backgrounds):
62  bkgd, interpStyle, undersampleStyle, approxStyle, \
63  approxOrderX, approxOrderY, approxWeighting = val
64  if interpStyle is None or undersampleStyle is None:
65  interpStyle = bkgd.getAsUsedInterpStyle()
66  undersampleStyle = bkgd.getAsUsedUndersampleStyle()
67  actrl = bkgd.getBackgroundControl().getApproximateControl()
68  approxStyle = actrl.getStyle()
69  approxOrderX = actrl.getOrderX()
70  approxOrderY = actrl.getOrderY()
71  approxWeighting = actrl.getWeighting()
72  self._backgrounds_backgrounds[i] = (bkgd, interpStyle, undersampleStyle,
73  approxStyle, approxOrderX, approxOrderY, approxWeighting)
74  #
75  # And return what they wanted
76  #
77  return self._backgrounds_backgrounds.__getitem__(*args)
78 
79  def __len__(self, *args):
80  return self._backgrounds_backgrounds.__len__(*args)
81 
82  def append(self, val):
83  try:
84  bkgd, interpStyle, undersampleStyle, approxStyle, \
85  approxOrderX, approxOrderY, approxWeighting = val
86  except TypeError:
87  bkgd = val
88  interpStyle = None
89  undersampleStyle = None
90  approxStyle = None
91  approxOrderX = None
92  approxOrderY = None
93  approxWeighting = None
94 
95  bgInfo = (bkgd, interpStyle, undersampleStyle, approxStyle,
96  approxOrderX, approxOrderY, approxWeighting)
97  self._backgrounds_backgrounds.append(bgInfo)
98 
99  def clone(self):
100  """Return a shallow copy
101 
102  Shallow copies do not share backgrounds that are appended after copying,
103  but do share changes to contained background objects.
104  """
105  return BackgroundList(*self)
106 
107  def writeFits(self, fileName, flags=0):
108  """Save our list of Backgrounds to a file.
109 
110  Parameters
111  -----------
112  fileName : `str`
113  FITS file to write
114  flags : `int`
115  Flags to control details of writing; currently unused, but present
116  for consistency with `lsst.afw.table.BaseCatalog.writeFits`.
117  """
118 
119  for i, bkgd in enumerate(self):
120  (bkgd, interpStyle, undersampleStyle, approxStyle, approxOrderX, approxOrderY,
121  approxWeighting) = bkgd
122 
123  statsImage = bkgd.getStatsImage()
124 
125  md = dafBase.PropertyList()
126  md.set("INTERPSTYLE", int(interpStyle))
127  md.set("UNDERSAMPLESTYLE", int(undersampleStyle))
128  md.set("APPROXSTYLE", int(approxStyle))
129  md.set("APPROXORDERX", approxOrderX)
130  md.set("APPROXORDERY", approxOrderY)
131  md.set("APPROXWEIGHTING", approxWeighting)
132  bbox = bkgd.getImageBBox()
133  md.set("BKGD_X0", bbox.getMinX())
134  md.set("BKGD_Y0", bbox.getMinY())
135  md.set("BKGD_WIDTH", bbox.getWidth())
136  md.set("BKGD_HEIGHT", bbox.getHeight())
137 
138  statsImage.getImage().writeFits(fileName, md, "w" if i == 0 else "a")
139  statsImage.getMask().writeFits(fileName, md, "a")
140  statsImage.getVariance().writeFits(fileName, md, "a")
141 
142  @staticmethod
143  def readFits(fileName, hdu=0, flags=0):
144  """Read our list of Backgrounds from a file.
145 
146  Parameters
147  ----------
148  fileName : `str`
149  FITS file to read
150  hdu : `int`
151  First Header/Data Unit to attempt to read from
152  flags : `int`
153  Flags to control details of reading; currently unused, but present
154  for consistency with `lsst.afw.table.BaseCatalog.readFits`.
155 
156  See Also
157  --------
158  getImage
159  """
160  if not isinstance(fileName, MemFileManager) and not os.path.exists(fileName):
161  raise RuntimeError(f"File not found: {fileName}")
162 
163  self = BackgroundList()
164 
165  f = Fits(fileName, 'r')
166  nHdus = f.countHdus()
167  f.closeFile()
168  if nHdus % 3 != 0:
169  raise RuntimeError(f"BackgroundList FITS file {fileName} has {nHdus} HDUs;"
170  f"expected a multiple of 3 (compression is not supported).")
171 
172  for hdu in range(0, nHdus, 3):
173  # It seems like we ought to be able to just use
174  # MaskedImageFitsReader here, but it warns about EXTTYPE and still
175  # doesn't work quite naturally when starting from a nonzero HDU.
176  imageReader = afwImage.ImageFitsReader(fileName, hdu=hdu)
177  maskReader = afwImage.MaskFitsReader(fileName, hdu=hdu + 1)
178  varianceReader = afwImage.ImageFitsReader(fileName, hdu=hdu + 2)
179  statsImage = afwImage.MaskedImageF(imageReader.read(), maskReader.read(), varianceReader.read())
180  md = imageReader.readMetadata()
181 
182  x0 = md["BKGD_X0"]
183  y0 = md["BKGD_Y0"]
184  width = md["BKGD_WIDTH"]
185  height = md["BKGD_HEIGHT"]
186  imageBBox = lsst.geom.BoxI(lsst.geom.PointI(x0, y0), lsst.geom.ExtentI(width, height))
187 
188  interpStyle = Interpolate.Style(md["INTERPSTYLE"])
189  undersampleStyle = UndersampleStyle(md["UNDERSAMPLESTYLE"])
190 
191  # Older outputs won't have APPROX* settings. Provide alternative defaults.
192  # Note: Currently X- and Y-orders must be equal due to a limitation in
193  # math::Chebyshev1Function2. Setting approxOrderY = -1 is equivalent
194  # to saying approxOrderY = approxOrderX.
195  approxStyle = md.get("APPROXSTYLE", ApproximateControl.UNKNOWN)
196  approxStyle = ApproximateControl.Style(approxStyle)
197  approxOrderX = md.get("APPROXORDERX", 1)
198  approxOrderY = md.get("APPROXORDERY", -1)
199  approxWeighting = md.get("APPROXWEIGHTING", True)
200 
201  bkgd = BackgroundMI(imageBBox, statsImage)
202  bctrl = bkgd.getBackgroundControl()
203  bctrl.setInterpStyle(interpStyle)
204  bctrl.setUndersampleStyle(undersampleStyle)
205  actrl = ApproximateControl(approxStyle, approxOrderX, approxOrderY, approxWeighting)
206  bctrl.setApproximateControl(actrl)
207  bgInfo = (bkgd, interpStyle, undersampleStyle, approxStyle,
208  approxOrderX, approxOrderY, approxWeighting)
209  self.appendappend(bgInfo)
210 
211  return self
212 
213  def getImage(self):
214  """Compute and return a full-resolution image from our list of
215  (Background, interpStyle, undersampleStyle).
216  """
217 
218  bkgdImage = None
219  for (bkgd, interpStyle, undersampleStyle, approxStyle,
220  approxOrderX, approxOrderY, approxWeighting) in self:
221  if not bkgdImage:
222  if approxStyle != ApproximateControl.UNKNOWN:
223  bkgdImage = bkgd.getImageF()
224  else:
225  bkgdImage = bkgd.getImageF(interpStyle, undersampleStyle)
226  else:
227  if approxStyle != ApproximateControl.UNKNOWN:
228  bkgdImage += bkgd.getImageF()
229  else:
230  bkgdImage += bkgd.getImageF(interpStyle, undersampleStyle)
231 
232  return bkgdImage
233 
234  def __reduce__(self):
235  return reduceToFits(self)
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition: fits.h:297
A FITS reader class for regular Images.
A FITS reader class for Masks.
Class for storing ordered metadata with comments.
Definition: PropertyList.h:68
An integer coordinate rectangle.
Definition: Box.h:55
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.