LSSTApplications  16.0-11-g09ed895+2,16.0-11-g12e47bd,16.0-11-g9bb73b2+6,16.0-12-g5c924a4+6,16.0-14-g9a974b3+1,16.0-15-g1417920+1,16.0-15-gdd5ca33+1,16.0-16-gf0259e2,16.0-17-g31abd91+7,16.0-17-g7d7456e+7,16.0-17-ga3d2e9f+13,16.0-18-ga4d4bcb+1,16.0-18-gd06566c+1,16.0-2-g0febb12+21,16.0-2-g9d5294e+69,16.0-2-ga8830df+6,16.0-20-g21842373+7,16.0-24-g3eae5ec,16.0-28-gfc9ea6c+4,16.0-29-ge8801f9,16.0-3-ge00e371+34,16.0-4-g18f3627+13,16.0-4-g5f3a788+20,16.0-4-ga3eb747+10,16.0-4-gabf74b7+29,16.0-4-gb13d127+6,16.0-49-g42e581f7+6,16.0-5-g27fb78a+7,16.0-5-g6a53317+34,16.0-5-gb3f8a4b+87,16.0-6-g9321be7+4,16.0-6-gcbc7b31+42,16.0-6-gf49912c+29,16.0-7-gd2eeba5+51,16.0-71-ge89f8615e,16.0-8-g21fd5fe+29,16.0-8-g3a9f023+20,16.0-8-g4734f7a+1,16.0-8-g5858431+3,16.0-9-gf5c1f43+8,master-gd73dc1d098+1,w.2019.01
LSSTDataManagementBasePackage
backgroundList.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008, 2009, 2010 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 import os
23 import lsst.daf.base as dafBase
24 import lsst.geom
25 import lsst.afw.image as afwImage
26 from lsst.afw.fits import FitsError, MemFileManager, reduceToFits, Fits, DEFAULT_HDU
27 from . import mathLib as afwMath
28 
29 
31  """A list-like class to contain a list of (afwMath.Background, interpStyle, undersampleStyle) tuples
32 
33 In deference to the deprecated-but-not-yet-removed Background.getImage() API, we also accept a single
34 afwMath.Background and extract the interpStyle and undersampleStyle from the as-used values
35  """
36 
37  def __init__(self, *args):
38  self._backgrounds = []
39  for a in args:
40  self.append(a)
41 
42  def __getitem__(self, *args):
43  """Return an item"""
44  #
45  # Set any previously-unknown Styles (they are set by bkgd.getImage())
46  #
47  for i, val in enumerate(self._backgrounds):
48  bkgd, interpStyle, undersampleStyle, approxStyle, \
49  approxOrderX, approxOrderY, approxWeighting = val
50  if interpStyle is None or undersampleStyle is None:
51  interpStyle = bkgd.getAsUsedInterpStyle()
52  undersampleStyle = bkgd.getAsUsedUndersampleStyle()
53  actrl = bkgd.getBackgroundControl().getApproximateControl()
54  approxStyle = actrl.getStyle()
55  approxOrderX = actrl.getOrderX()
56  approxOrderY = actrl.getOrderY()
57  approxWeighting = actrl.getWeighting()
58  self._backgrounds[i] = (bkgd, interpStyle, undersampleStyle,
59  approxStyle, approxOrderX, approxOrderY, approxWeighting)
60  #
61  # And return what they wanted
62  #
63  return self._backgrounds.__getitem__(*args)
64 
65  def __len__(self, *args):
66  return self._backgrounds.__len__(*args)
67 
68  def append(self, val):
69  try:
70  bkgd, interpStyle, undersampleStyle, approxStyle, \
71  approxOrderX, approxOrderY, approxWeighting = val
72  except TypeError:
73  bkgd = val
74  interpStyle = None
75  undersampleStyle = None
76  approxStyle = None
77  approxOrderX = None
78  approxOrderY = None
79  approxWeighting = None
80 
81  bgInfo = (bkgd, interpStyle, undersampleStyle, approxStyle,
82  approxOrderX, approxOrderY, approxWeighting)
83  self._backgrounds.append(bgInfo)
84 
85  def clone(self):
86  """Return a shallow copy
87 
88  Shallow copies do not share backgrounds that are appended after copying,
89  but do share changes to contained background objects.
90  """
91  return BackgroundList(*self)
92 
93  def writeFits(self, fileName, flags=0):
94  """Save our list of Backgrounds to a file
95  @param fileName FITS file to write
96  @param flags Flags to control details of writing; currently unused,
97  but present for consistency with
98  afw.table.BaseCatalog.writeFits.
99  """
100 
101  for i, bkgd in enumerate(self):
102  (bkgd, interpStyle, undersampleStyle, approxStyle, approxOrderX, approxOrderY,
103  approxWeighting) = bkgd
104 
105  statsImage = bkgd.getStatsImage()
106 
107  md = dafBase.PropertyList()
108  md.set("INTERPSTYLE", int(interpStyle))
109  md.set("UNDERSAMPLESTYLE", int(undersampleStyle))
110  md.set("APPROXSTYLE", int(approxStyle))
111  md.set("APPROXORDERX", approxOrderX)
112  md.set("APPROXORDERY", approxOrderY)
113  md.set("APPROXWEIGHTING", approxWeighting)
114  bbox = bkgd.getImageBBox()
115  md.set("BKGD_X0", bbox.getMinX())
116  md.set("BKGD_Y0", bbox.getMinY())
117  md.set("BKGD_WIDTH", bbox.getWidth())
118  md.set("BKGD_HEIGHT", bbox.getHeight())
119 
120  statsImage.getImage().writeFits(fileName, md, "w" if i == 0 else "a")
121  statsImage.getMask().writeFits(fileName, md, "a")
122  statsImage.getVariance().writeFits(fileName, md, "a")
123 
124  @staticmethod
125  def readFits(fileName, hdu=0, flags=0):
126  """Read a our list of Backgrounds from a file
127  @param fileName FITS file to read
128  @param hdu First Header/Data Unit to attempt to read from
129  @param flags Flags to control details of reading; currently unused,
130  but present for consistency with
131  afw.table.BaseCatalog.readFits.
132 
133  See also getImage()
134  """
135  if not isinstance(fileName, MemFileManager) and not os.path.exists(fileName):
136  raise RuntimeError("File not found: %s" % fileName)
137 
138  self = BackgroundList()
139 
140  if hdu == DEFAULT_HDU:
141  hdu = -1
142  else:
143  # we want to start at 0 (post RFC-304), but are about to increment
144  hdu -= 1
145 
146  fits = Fits(fileName, "r")
147  fits.setHdu(hdu + 1)
148  if fits.checkCompressedImagePhu():
149  hdu += 1
150 
151  while True:
152  hdu += 1
153 
154  md = dafBase.PropertyList()
155  try:
156  img = afwImage.ImageF(fileName, hdu, md)
157  hdu += 1
158  except FitsError:
159  break
160 
161  msk = afwImage.Mask(fileName, hdu)
162  hdu += 1
163  var = afwImage.ImageF(fileName, hdu)
164 
165  statsImage = afwImage.makeMaskedImage(img, msk, var)
166 
167  x0 = md.getScalar("BKGD_X0")
168  y0 = md.getScalar("BKGD_Y0")
169  width = md.getScalar("BKGD_WIDTH")
170  height = md.getScalar("BKGD_HEIGHT")
171  imageBBox = lsst.geom.BoxI(lsst.geom.PointI(
172  x0, y0), lsst.geom.ExtentI(width, height))
173 
174  interpStyle = afwMath.Interpolate.Style(md.getScalar("INTERPSTYLE"))
175  undersampleStyle = afwMath.UndersampleStyle(
176  md.getScalar("UNDERSAMPLESTYLE"))
177 
178  # Older outputs won't have APPROX* settings. Provide alternative defaults.
179  # Note: Currently X- and Y-orders must be equal due to a limitation in
180  # math::Chebyshev1Function2. Setting approxOrderY = -1 is equivalent
181  # to saying approxOrderY = approxOrderX.
182  approxStyle = md.getScalar("APPROXSTYLE") if "APPROXSTYLE" in md.names() \
183  else afwMath.ApproximateControl.UNKNOWN
184  approxStyle = afwMath.ApproximateControl.Style(approxStyle)
185  approxOrderX = md.getScalar(
186  "APPROXORDERX") if "APPROXORDERX" in md.names() else 1
187  approxOrderY = md.getScalar(
188  "APPROXORDERY") if "APPROXORDERY" in md.names() else -1
189  approxWeighting = md.getScalar(
190  "APPROXWEIGHTING") if "APPROXWEIGHTING" in md.names() else True
191 
192  bkgd = afwMath.BackgroundMI(imageBBox, statsImage)
193  bctrl = bkgd.getBackgroundControl()
194  bctrl.setInterpStyle(interpStyle)
195  bctrl.setUndersampleStyle(undersampleStyle)
197  approxStyle, approxOrderX, approxOrderY, approxWeighting)
198  bctrl.setApproximateControl(actrl)
199  bgInfo = (bkgd, interpStyle, undersampleStyle, approxStyle,
200  approxOrderX, approxOrderY, approxWeighting)
201  self.append(bgInfo)
202 
203  return self
204 
205  def getImage(self):
206  """
207  Compute and return a full-resolution image from our list of
208  (Background, interpStyle, undersampleStyle)
209  """
210 
211  bkgdImage = None
212  for (bkgd, interpStyle, undersampleStyle, approxStyle,
213  approxOrderX, approxOrderY, approxWeighting) in self:
214  if not bkgdImage:
215  if approxStyle != afwMath.ApproximateControl.UNKNOWN:
216  bkgdImage = bkgd.getImageF()
217  else:
218  bkgdImage = bkgd.getImageF(interpStyle, undersampleStyle)
219  else:
220  if approxStyle != afwMath.ApproximateControl.UNKNOWN:
221  bkgdImage += bkgd.getImageF()
222  else:
223  bkgdImage += bkgd.getImageF(interpStyle, undersampleStyle)
224 
225  return bkgdImage
226 
227  def __reduce__(self):
228  return reduceToFits(self)
def writeFits(self, fileName, flags=0)
Class for storing ordered metadata with comments.
Definition: PropertyList.h:68
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition: fits.h:296
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:1280
Control how to make an approximation.
Definition: Approximate.h:48
Represent a 2-dimensional array of bitmask pixels.
Definition: Mask.h:78
def readFits(fileName, hdu=0, flags=0)
A class to evaluate image background levels.
Definition: Background.h:444
An integer coordinate rectangle.
Definition: Box.h:54