LSST Applications g06d8191974+de063e15a7,g180d380827+d0b6459378,g2079a07aa2+86d27d4dc4,g2305ad1205+f1ae3263cc,g29320951ab+5752d78b6e,g2bbee38e9b+85cf0a37e7,g337abbeb29+85cf0a37e7,g33d1c0ed96+85cf0a37e7,g3a166c0a6a+85cf0a37e7,g3ddfee87b4+b5254b9343,g48712c4677+9ea88d309d,g487adcacf7+05f7dba17f,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+48904e3942,g64a986408d+de063e15a7,g858d7b2824+de063e15a7,g864b0138d7+33ab2bc355,g8a8a8dda67+585e252eca,g99cad8db69+4508353287,g9c22b2923f+53520f316c,g9ddcbc5298+9a081db1e4,ga1e77700b3+15fc3df1f7,gb0e22166c9+60f28cb32d,gba4ed39666+c2a2e4ac27,gbb8dafda3b+ccb7f83a87,gc120e1dc64+6caf640b9b,gc28159a63d+85cf0a37e7,gc3e9b769f7+548c5e05a3,gcf0d15dbbd+b5254b9343,gdaeeff99f8+f9a426f77a,ge6526c86ff+515b6c9330,ge79ae78c31+85cf0a37e7,gee10cc3b42+585e252eca,gff1a9f87cc+de063e15a7,w.2024.17
LSST Data Management Base Package
Loading...
Searching...
No Matches
_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
24import os
25import lsst.daf.base as dafBase
26import lsst.geom
27import lsst.afw.image as afwImage
28from lsst.afw.fits import MemFileManager, reduceToFits, Fits
29from ._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 = []
47 for a in args:
48 self.append(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):
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[i] = (bkgd, interpStyle, undersampleStyle,
73 approxStyle, approxOrderX, approxOrderY, approxWeighting)
74 #
75 # And return what they wanted
76 #
77 return self._backgrounds.__getitem__(*args)
78
79 def __len__(self, *args):
80 return self._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.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
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.append(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:308
A FITS reader class for regular Images.
A FITS reader class for Masks.
Class for storing ordered metadata with comments.
An integer coordinate rectangle.
Definition Box.h:55