LSSTApplications  18.0.0+106,18.0.0+50,19.0.0,19.0.0+1,19.0.0+10,19.0.0+11,19.0.0+13,19.0.0+17,19.0.0+2,19.0.0-1-g20d9b18+6,19.0.0-1-g425ff20,19.0.0-1-g5549ca4,19.0.0-1-g580fafe+6,19.0.0-1-g6fe20d0+1,19.0.0-1-g7011481+9,19.0.0-1-g8c57eb9+6,19.0.0-1-gb5175dc+11,19.0.0-1-gdc0e4a7+9,19.0.0-1-ge272bc4+6,19.0.0-1-ge3aa853,19.0.0-10-g448f008b,19.0.0-12-g6990b2c,19.0.0-2-g0d9f9cd+11,19.0.0-2-g3d9e4fb2+11,19.0.0-2-g5037de4,19.0.0-2-gb96a1c4+3,19.0.0-2-gd955cfd+15,19.0.0-3-g2d13df8,19.0.0-3-g6f3c7dc,19.0.0-4-g725f80e+11,19.0.0-4-ga671dab3b+1,19.0.0-4-gad373c5+3,19.0.0-5-ga2acb9c+2,19.0.0-5-gfe96e6c+2,w.2020.01
LSSTDataManagementBasePackage
isrQa.py
Go to the documentation of this file.
1 # This file is part of ip_isr.
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 import os
23 import errno
24 
25 import lsst.afw.display.rgb as afwRGB
26 import lsst.afw.math as afwMath
27 import lsst.pex.config as pexConfig
28 
29 
30 class IsrQaFlatnessConfig(pexConfig.Config):
31  meshX = pexConfig.Field(
32  dtype=int,
33  doc="Mesh size in X for flatness statistics",
34  default=256,
35  )
36  meshY = pexConfig.Field(
37  dtype=int,
38  doc="Mesh size in Y for flatness statistics",
39  default=256,
40  )
41  doClip = pexConfig.Field(
42  dtype=bool,
43  doc="Clip outliers for flatness statistics?",
44  default=True,
45  )
46  clipSigma = pexConfig.Field(
47  dtype=float,
48  doc="Number of sigma deviant a pixel must be to be clipped from flatness statistics.",
49  default=3.0,
50  )
51  nIter = pexConfig.Field(
52  dtype=int,
53  doc="Number of iterations used for outlier clipping in flatness statistics.",
54  default=3,
55  )
56 
57 
58 class IsrQaConfig(pexConfig.Config):
59  saveStats = pexConfig.Field(
60  dtype=bool,
61  doc="Calculate ISR statistics while processing?",
62  default=True,
63  )
64 
65  flatness = pexConfig.ConfigField(
66  dtype=IsrQaFlatnessConfig,
67  doc="Flatness statistics configuration.",
68  )
69 
70  doWriteOss = pexConfig.Field(
71  dtype=bool,
72  doc="Write overscan subtracted image?",
73  default=False,
74  )
75  doThumbnailOss = pexConfig.Field(
76  dtype=bool,
77  doc="Write overscan subtracted thumbnail?",
78  default=False,
79  )
80 
81  doWriteFlattened = pexConfig.Field(
82  dtype=bool,
83  doc="Write image after flat-field correction?",
84  default=False,
85  )
86  doThumbnailFlattened = pexConfig.Field(
87  dtype=bool,
88  doc="Write thumbnail after flat-field correction?",
89  default=False,
90  )
91 
92  thumbnailBinning = pexConfig.Field(
93  dtype=int,
94  doc="Thumbnail binning factor.",
95  default=4,
96  )
97  thumbnailStdev = pexConfig.Field(
98  dtype=float,
99  doc="Number of sigma below the background to set the thumbnail minimum.",
100  default=3.0,
101  )
102  thumbnailRange = pexConfig.Field(
103  dtype=float,
104  doc="Total range in sigma for thumbnail mapping.",
105  default=5.0,
106  )
107  thumbnailQ = pexConfig.Field(
108  dtype=float,
109  doc="Softening parameter for thumbnail mapping.",
110  default=20.0,
111  )
112  thumbnailSatBorder = pexConfig.Field(
113  dtype=int,
114  doc="Width of border around saturated pixels in thumbnail.",
115  default=2,
116  )
117 
118 
119 def makeThumbnail(exposure, isrQaConfig=None):
120  """Create a snapshot thumbnail from input exposure.
121 
122  The output thumbnail image is constructed based on the parameters
123  in the configuration file. Currently, the asinh mapping is the
124  only mapping method used.
125 
126  Parameters
127  ----------
128  exposure : `lsst.afw.image.Exposure`
129  The exposure to be converted into a thumbnail.
130  isrQaConfig : `Config`
131  Configuration object containing all parameters to control the
132  thumbnail generation.
133 
134  Returns
135  -------
136  rgbImage : `numpy.ndarray`
137  Binned and scaled version of the exposure, converted to an
138  integer array to allow it to be written as PNG.
139  """
140  if isrQaConfig is not None:
141  binning = isrQaConfig.thumbnailBinning
142  binnedImage = afwMath.binImage(exposure.getMaskedImage(), binning, binning, afwMath.MEAN)
143 
144  statsCtrl = afwMath.StatisticsControl()
145  statsCtrl.setAndMask(binnedImage.getMask().getPlaneBitMask(["SAT", "BAD", "INTRP"]))
146  stats = afwMath.makeStatistics(binnedImage,
147  afwMath.MEDIAN | afwMath.STDEVCLIP | afwMath.MAX, statsCtrl)
148 
149  low = stats.getValue(afwMath.MEDIAN) - isrQaConfig.thumbnailStdev*stats.getValue(afwMath.STDEVCLIP)
150 
151  if isrQaConfig.thumbnailSatBorder:
152  afwRGB.replaceSaturatedPixels(binnedImage, binnedImage, binnedImage,
153  isrQaConfig.thumbnailSatBorder, stats.getValue(afwMath.MAX))
154 
155  asinhMap = afwRGB.AsinhMapping(low, isrQaConfig.thumbnailRange, Q=isrQaConfig.thumbnailQ)
156  rgbImage = asinhMap.makeRgbImage(binnedImage)
157 
158  return rgbImage
159 
160 
161 def writeThumbnail(dataRef, thumb, dataset):
162  """Write snapshot thumbnail to disk.
163 
164  Parameters
165  ----------
166  dataRef : `daf.persistence.butlerSubset.ButlerDataRef`
167  Butler dataref to use to construct the output filename.
168  thumb : `numpy.ndarray`
169  Binned and scaled image to be written as a PNG.
170  dataset : `str`
171  String containing the dataset for this thumbnail.
172 
173  Raises
174  ------
175  OSError
176  Raised if the output directory cannot be created and does not
177  exist.
178  """
179  filename = dataRef.get(dataset + "_filename")[0]
180  directory = os.path.dirname(filename)
181  if not os.path.exists(directory):
182  try:
183  os.makedirs(directory)
184  except OSError as e:
185  # Don't fail if directory exists due to race condition.
186  if e.errno != errno.EEXIST:
187  raise e
188  afwRGB.writeRGB(filename, thumb)
Statistics makeStatistics(lsst::afw::math::MaskedVector< EntryT > const &mv, std::vector< WeightPixel > const &vweights, int const flags, StatisticsControl const &sctrl=StatisticsControl())
The makeStatistics() overload to handle lsst::afw::math::MaskedVector<>
Definition: Statistics.h:520
Pass parameters to a Statistics object.
Definition: Statistics.h:93
def writeThumbnail(dataRef, thumb, dataset)
Definition: isrQa.py:161
std::shared_ptr< ImageT > binImage(ImageT const &inImage, int const binsize, lsst::afw::math::Property const flags=lsst::afw::math::MEAN)
Definition: binImage.cc:38
def makeThumbnail(exposure, isrQaConfig=None)
Definition: isrQa.py:119