lsst.meas.algorithms  22.0.1-18-g3db9cf4b+f395498f22
testUtils.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 #
4 # Copyright 2008-2017 AURA/LSST.
5 #
6 # This product includes software developed by the
7 # LSST Project (http://www.lsst.org/).
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 LSST License Statement and
20 # the GNU General Public License along with this program. If not,
21 # see <https://www.lsstcorp.org/LegalNotices/>.
22 #
23 
24 import numpy as np
25 
26 import lsst.geom
27 import lsst.afw.image as afwImage
28 from . import SingleGaussianPsf
29 from . import Defect
30 
31 
32 def plantSources(bbox, kwid, sky, coordList, addPoissonNoise=True):
33  """Make an exposure with stars (modelled as Gaussians)
34 
35  Parameters
36  ----------
37  bbox : `lsst.geom.Box2I`
38  Parent bbox of exposure
39  kwid : `int`
40  Kernal width (and height; kernal is square)
41  sky : `float`
42  Amount of sky background (counts)
43  coordList : `list [tuple]`
44  A list of [x, y, counts, sigma] where:
45  * x,y are relative to exposure origin
46  * counts is the integrated counts for the star
47  * sigma is the Gaussian sigma in pixels
48  addPoissonNoise : `bool`
49  If True: add Poisson noise to the exposure
50  """
51  # make an image with sources
52  img = afwImage.ImageD(bbox)
53  meanSigma = 0.0
54  for coord in coordList:
55  x, y, counts, sigma = coord
56  meanSigma += sigma
57 
58  # make a single gaussian psf
59  psf = SingleGaussianPsf(kwid, kwid, sigma)
60 
61  # make an image of it and scale to the desired number of counts
62  thisPsfImg = psf.computeImage(lsst.geom.PointD(x, y))
63  thisPsfImg *= counts
64 
65  # bbox a window in our image and add the fake star image
66  psfBox = thisPsfImg.getBBox()
67  psfBox.clip(bbox)
68  if psfBox != thisPsfImg.getBBox():
69  thisPsfImg = thisPsfImg[psfBox, afwImage.PARENT]
70  imgSeg = img[psfBox, afwImage.PARENT]
71  imgSeg += thisPsfImg
72  meanSigma /= len(coordList)
73 
74  img += sky
75 
76  # add Poisson noise
77  if (addPoissonNoise):
78  np.random.seed(seed=1) # make results reproducible
79  imgArr = img.getArray()
80  imgArr[:] = np.random.poisson(imgArr)
81 
82  # bundle into a maskedimage and an exposure
83  mask = afwImage.Mask(bbox)
84  var = img.convertFloat()
85  img -= sky
86  mimg = afwImage.MaskedImageF(img.convertFloat(), mask, var)
87  exposure = afwImage.makeExposure(mimg)
88 
89  # insert an approximate psf
90  psf = SingleGaussianPsf(kwid, kwid, meanSigma)
91  exposure.setPsf(psf)
92 
93  return exposure
94 
95 
96 def makeRandomTransmissionCurve(rng, minWavelength=4000.0, maxWavelength=7000.0, nWavelengths=200,
97  maxRadius=80.0, nRadii=30, perturb=0.05):
98  """Create a random TransmissionCurve with nontrivial spatial and
99  wavelength variation.
100 
101  Parameters
102  ----------
103  rng : numpy.random.RandomState
104  Random number generator.
105  minWavelength : float
106  Average minimum wavelength for generated TransmissionCurves (will be
107  randomly perturbed).
108  maxWavelength : float
109  Average maximum wavelength for generated TransmissionCurves (will be
110  randomly perturbed).
111  nWavelengths : int
112  Number of samples in the wavelength dimension.
113  maxRadius : float
114  Average maximum radius for spatial variation (will be perturbed).
115  nRadii : int
116  Number of samples in the radial dimension.
117  perturb: float
118  Fraction by which wavelength and radius bounds should be randomly
119  perturbed.
120  """
121  dWavelength = maxWavelength - minWavelength
122 
123  def perturbed(x, s=perturb*dWavelength):
124  return x + 2.0*s*(rng.rand() - 0.5)
125 
126  wavelengths = np.linspace(perturbed(minWavelength), perturbed(maxWavelength), nWavelengths)
127  radii = np.linspace(0.0, perturbed(maxRadius, perturb*maxRadius), nRadii)
128  throughput = np.zeros(wavelengths.shape + radii.shape, dtype=float)
129  # throughput will be a rectangle in wavelength, shifting to higher wavelengths and shrinking
130  # in height with radius, going to zero at all bounds.
131  peak0 = perturbed(0.9, 0.05)
132  start0 = perturbed(minWavelength + 0.25*dWavelength)
133  stop0 = perturbed(minWavelength + 0.75*dWavelength)
134  for i, r in enumerate(radii):
135  mask = np.logical_and(wavelengths >= start0 + r, wavelengths <= stop0 + r)
136  throughput[mask, i] = peak0*(1.0 - r/1000.0)
137  return afwImage.TransmissionCurve.makeRadial(throughput, wavelengths, radii)
138 
139 
141  """Create a list of defects that can be used for testing.
142 
143  Returns
144  -------
145  defectList = `list` [`lsst.meas.algorithms.Defect`]
146  The list of defects.
147  """
148  defectList = [Defect(lsst.geom.Box2I(lsst.geom.Point2I(962, 0),
149  lsst.geom.Extent2I(2, 4611))),
151  lsst.geom.Extent2I(2, 4611))),
153  lsst.geom.Extent2I(4, 4611))),
155  lsst.geom.Extent2I(2, 4611))),
157  lsst.geom.Extent2I(2, 4359))),
159  lsst.geom.Extent2I(2, 3909))),
161  lsst.geom.Extent2I(2, 3471))),
163  lsst.geom.Extent2I(2, 2311))),
165  lsst.geom.Extent2I(2, 65))),
167  lsst.geom.Extent2I(1, 56))),
169  lsst.geom.Extent2I(4, 1814))),
171  lsst.geom.Extent2I(2, 1806))),
173  lsst.geom.Extent2I(2, 766))),
175  lsst.geom.Extent2I(2, 382))),
176  ]
177 
178  return defectList
Encapsulate information about a bad portion of a detector.
Definition: Interp.h:72
Represent a PSF as a circularly symmetrical Gaussian.
def plantSources(bbox, kwid, sky, coordList, addPoissonNoise=True)
Definition: testUtils.py:32
def makeRandomTransmissionCurve(rng, minWavelength=4000.0, maxWavelength=7000.0, nWavelengths=200, maxRadius=80.0, nRadii=30, perturb=0.05)
Definition: testUtils.py:97