lsst.meas.algorithms  20.0.0-14-g05f4b37e+5ec167a87d
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  @param bbox: parent bbox of exposure
36  @param kwid: kernel width (and height; kernel is square)
37  @param sky: amount of sky background (counts)
38  @param coordList: a list of [x, y, counts, sigma], where:
39  * x,y are relative to exposure origin
40  * counts is the integrated counts for the star
41  * sigma is the Gaussian sigma in pixels
42  @param addPoissonNoise: add Poisson noise to the exposure?
43  """
44  # make an image with sources
45  img = afwImage.ImageD(bbox)
46  meanSigma = 0.0
47  for coord in coordList:
48  x, y, counts, sigma = coord
49  meanSigma += sigma
50 
51  # make a single gaussian psf
52  psf = SingleGaussianPsf(kwid, kwid, sigma)
53 
54  # make an image of it and scale to the desired number of counts
55  thisPsfImg = psf.computeImage(lsst.geom.PointD(x, y))
56  thisPsfImg *= counts
57 
58  # bbox a window in our image and add the fake star image
59  psfBox = thisPsfImg.getBBox()
60  psfBox.clip(bbox)
61  if psfBox != thisPsfImg.getBBox():
62  thisPsfImg = thisPsfImg[psfBox, afwImage.PARENT]
63  imgSeg = img[psfBox, afwImage.PARENT]
64  imgSeg += thisPsfImg
65  meanSigma /= len(coordList)
66 
67  img += sky
68 
69  # add Poisson noise
70  if (addPoissonNoise):
71  np.random.seed(seed=1) # make results reproducible
72  imgArr = img.getArray()
73  imgArr[:] = np.random.poisson(imgArr)
74 
75  # bundle into a maskedimage and an exposure
76  mask = afwImage.Mask(bbox)
77  var = img.convertFloat()
78  img -= sky
79  mimg = afwImage.MaskedImageF(img.convertFloat(), mask, var)
80  exposure = afwImage.makeExposure(mimg)
81 
82  # insert an approximate psf
83  psf = SingleGaussianPsf(kwid, kwid, meanSigma)
84  exposure.setPsf(psf)
85 
86  return exposure
87 
88 
89 def makeRandomTransmissionCurve(rng, minWavelength=4000.0, maxWavelength=7000.0, nWavelengths=200,
90  maxRadius=80.0, nRadii=30, perturb=0.05):
91  """Create a random TransmissionCurve with nontrivial spatial and
92  wavelength variation.
93 
94  Parameters
95  ----------
96  rng : numpy.random.RandomState
97  Random number generator.
98  minWavelength : float
99  Average minimum wavelength for generated TransmissionCurves (will be
100  randomly perturbed).
101  maxWavelength : float
102  Average maximum wavelength for generated TransmissionCurves (will be
103  randomly perturbed).
104  nWavelengths : int
105  Number of samples in the wavelength dimension.
106  maxRadius : float
107  Average maximum radius for spatial variation (will be perturbed).
108  nRadii : int
109  Number of samples in the radial dimension.
110  perturb: float
111  Fraction by which wavelength and radius bounds should be randomly
112  perturbed.
113  """
114  dWavelength = maxWavelength - minWavelength
115 
116  def perturbed(x, s=perturb*dWavelength):
117  return x + 2.0*s*(rng.rand() - 0.5)
118 
119  wavelengths = np.linspace(perturbed(minWavelength), perturbed(maxWavelength), nWavelengths)
120  radii = np.linspace(0.0, perturbed(maxRadius, perturb*maxRadius), nRadii)
121  throughput = np.zeros(wavelengths.shape + radii.shape, dtype=float)
122  # throughput will be a rectangle in wavelength, shifting to higher wavelengths and shrinking
123  # in height with radius, going to zero at all bounds.
124  peak0 = perturbed(0.9, 0.05)
125  start0 = perturbed(minWavelength + 0.25*dWavelength)
126  stop0 = perturbed(minWavelength + 0.75*dWavelength)
127  for i, r in enumerate(radii):
128  mask = np.logical_and(wavelengths >= start0 + r, wavelengths <= stop0 + r)
129  throughput[mask, i] = peak0*(1.0 - r/1000.0)
130  return afwImage.TransmissionCurve.makeRadial(throughput, wavelengths, radii)
131 
132 
134  """Create a list of defects that can be used for testing.
135 
136  Returns
137  -------
138  defectList = `list` [`lsst.meas.algorithms.Defect`]
139  The list of defects.
140  """
141  defectList = [Defect(lsst.geom.Box2I(lsst.geom.Point2I(962, 0),
142  lsst.geom.Extent2I(2, 4611))),
143  Defect(lsst.geom.Box2I(lsst.geom.Point2I(1316, 0),
144  lsst.geom.Extent2I(2, 4611))),
145  Defect(lsst.geom.Box2I(lsst.geom.Point2I(1576, 0),
146  lsst.geom.Extent2I(4, 4611))),
147  Defect(lsst.geom.Box2I(lsst.geom.Point2I(1626, 0),
148  lsst.geom.Extent2I(2, 4611))),
149  Defect(lsst.geom.Box2I(lsst.geom.Point2I(1994, 252),
150  lsst.geom.Extent2I(2, 4359))),
151  Defect(lsst.geom.Box2I(lsst.geom.Point2I(1426, 702),
152  lsst.geom.Extent2I(2, 3909))),
153  Defect(lsst.geom.Box2I(lsst.geom.Point2I(1526, 1140),
154  lsst.geom.Extent2I(2, 3471))),
155  Defect(lsst.geom.Box2I(lsst.geom.Point2I(856, 2300),
156  lsst.geom.Extent2I(2, 2311))),
157  Defect(lsst.geom.Box2I(lsst.geom.Point2I(858, 2328),
158  lsst.geom.Extent2I(2, 65))),
159  Defect(lsst.geom.Box2I(lsst.geom.Point2I(859, 2328),
160  lsst.geom.Extent2I(1, 56))),
161  Defect(lsst.geom.Box2I(lsst.geom.Point2I(844, 2796),
162  lsst.geom.Extent2I(4, 1814))),
163  Defect(lsst.geom.Box2I(lsst.geom.Point2I(1366, 2804),
164  lsst.geom.Extent2I(2, 1806))),
165  Defect(lsst.geom.Box2I(lsst.geom.Point2I(1766, 3844),
166  lsst.geom.Extent2I(2, 766))),
167  Defect(lsst.geom.Box2I(lsst.geom.Point2I(1872, 4228),
168  lsst.geom.Extent2I(2, 382))),
169  ]
170 
171  return defectList
lsst::afw::image
lsst::meas::algorithms.testUtils.plantSources
def plantSources(bbox, kwid, sky, coordList, addPoissonNoise=True)
Definition: testUtils.py:32
lsst::geom
Point< double, 2 >
lsst::geom::Box2I
lsst::meas::algorithms.testUtils.makeDefectList
def makeDefectList()
Definition: testUtils.py:133
Extent< int, 2 >
lsst::meas::algorithms.testUtils.makeRandomTransmissionCurve
def makeRandomTransmissionCurve(rng, minWavelength=4000.0, maxWavelength=7000.0, nWavelengths=200, maxRadius=80.0, nRadii=30, perturb=0.05)
Definition: testUtils.py:89