Coverage for tests/test_linearizeSquared.py: 21%
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#
2# LSST Data Management System
3# Copyright 2017 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#
22import unittest
23import pickle
24import logging
26import numpy as np
28import lsst.utils.tests
29import lsst.geom
30import lsst.afw.image as afwImage
31import lsst.afw.cameraGeom as cameraGeom
32from lsst.afw.geom.testUtils import BoxGrid
33from lsst.afw.image.testUtils import makeRampImage
34from lsst.ip.isr import Linearizer
37def refLinearizeSquared(image, detector):
38 """!Basic implementation of squared non-linearization correction
40 corr = uncorr + coeff[0]*uncorr^2
42 @param[in,out] image image to correct in place (an lsst.afw.image.Image of some type)
43 @param[in] detector detector info (an lsst.afw.cameraGeom.Detector)
44 """
45 ampInfoCat = detector.getAmplifiers()
46 for ampInfo in ampInfoCat:
47 bbox = ampInfo.getBBox()
48 sqCoeff = ampInfo.getLinearityCoeffs()[0]
49 viewArr = image.Factory(image, bbox).getArray()
50 viewArr[:] = viewArr + sqCoeff*viewArr**2
53class LinearizeSquaredTestCase(lsst.utils.tests.TestCase):
54 """!Unit tests for LinearizeSquared"""
56 def setUp(self):
57 # the following values are all arbitrary, but sane and varied
58 self.bbox = lsst.geom.Box2I(lsst.geom.Point2I(-31, 22), lsst.geom.Extent2I(100, 85))
59 self.numAmps = (2, 3)
60 self.sqCoeffs = np.array([[0, 5e-6, 2.5e-5], [1e-5, 1.1e-6, 2.1e-5]], dtype=float)
61 self.detector = self.makeDetector()
63 def tearDown(self):
64 # destroy LSST objects so memory test passes
65 self.bbox = None
66 self.detector = None
68 def testBasics(self):
69 """!Test basic functionality of LinearizeSquared
70 """
71 for imageClass in (afwImage.ImageF, afwImage.ImageD):
72 inImage = makeRampImage(bbox=self.bbox, start=-5, stop=2500, imageClass=imageClass)
74 measImage = inImage.Factory(inImage, True)
75 linCorr = Linearizer(detector=self.detector)
76 linRes = linCorr.applyLinearity(image=measImage, detector=self.detector)
77 desNumLinearized = np.sum(self.sqCoeffs.flatten() > 0)
78 self.assertEqual(linRes.numLinearized, desNumLinearized)
79 self.assertEqual(linRes.numAmps, len(self.detector.getAmplifiers()))
81 refImage = inImage.Factory(inImage, True)
82 refLinearizeSquared(image=refImage, detector=self.detector)
84 self.assertImagesAlmostEqual(refImage, measImage)
86 # make sure logging is accepted
87 log = logging.getLogger("lsst.ip.isr.LinearizeSquared")
88 linRes = linCorr.applyLinearity(image=measImage, detector=self.detector, log=log)
90 def testKnown(self):
91 """!Test a few known values
92 """
93 numAmps = (2, 2)
94 bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(4, 4))
95 # make a 4x4 image with 4 identical 2x2 subregions that flatten to -1, 0, 1, 2
96 im = afwImage.ImageF(bbox)
97 imArr = im.getArray()
98 imArr[:, :] = np.array(((-1, 0, -1, 0),
99 (1, 2, 1, 2),
100 (-1, 0, -1, 0),
101 (1, 2, 1, 2)), dtype=imArr.dtype)
103 sqCoeffs = np.array(((0, 0.11), (-0.15, -12)))
104 detector = self.makeDetector(bbox=bbox, numAmps=numAmps, sqCoeffs=sqCoeffs)
105 ampInfoCat = detector.getAmplifiers()
107 linSq = Linearizer(detector=detector)
108 linSq.applyLinearity(im, detector=detector)
110 # amp 0 has 0 squared coefficient and so makes no correction
111 imArr0 = im.Factory(im, ampInfoCat[0].getBBox()).getArray()
112 linCoeff0 = ampInfoCat[0].getLinearityCoeffs()[0]
113 self.assertEqual(0, linCoeff0)
114 self.assertFloatsAlmostEqual(imArr0.flatten(), (-1, 0, 1, 2))
116 # test all amps
117 for ampInfo in ampInfoCat:
118 imArr = im.Factory(im, ampInfo.getBBox()).getArray()
119 linCoeff = ampInfo.getLinearityCoeffs()[0]
120 expect = np.array((-1 + linCoeff, 0, 1 + linCoeff, 2 + 4*linCoeff), dtype=imArr.dtype)
121 self.assertFloatsAlmostEqual(imArr.flatten(), expect)
123 def testPickle(self):
124 """!Test that a LinearizeSquared can be pickled and unpickled
125 """
126 inImage = makeRampImage(bbox=self.bbox, start=-5, stop=2500)
127 linSq = Linearizer(detector=self.detector)
129 refImage = inImage.Factory(inImage, True)
130 refNumOutOfRange = linSq.applyLinearity(refImage, detector=self.detector)
132 pickledStr = pickle.dumps(linSq)
133 restoredLlt = pickle.loads(pickledStr)
135 measImage = inImage.Factory(inImage, True)
136 measNumOutOfRange = restoredLlt.applyLinearity(measImage, detector=self.detector)
138 self.assertEqual(refNumOutOfRange, measNumOutOfRange)
139 self.assertImagesAlmostEqual(refImage, measImage)
141 def makeDetector(self, bbox=None, numAmps=None, sqCoeffs=None, linearityType="Squared"):
142 """!Make a detector
144 @param[in] bbox bounding box for image
145 @param[n] numAmps x,y number of amplifiers (pair of int)
146 @param[in] sqCoeffs square coefficient for each amplifier (2D array of float)
147 @param[in] detName detector name (a str)
148 @param[in] detID detector ID (an int)
149 @param[in] detSerial detector serial numbe (a str)
150 @param[in] linearityType name of linearity type (a str)
152 @return a detector (an lsst.afw.cameraGeom.Detector)
153 """
154 bbox = bbox if bbox is not None else self.bbox
155 numAmps = numAmps if numAmps is not None else self.numAmps
156 sqCoeffs = sqCoeffs if sqCoeffs is not None else self.sqCoeffs
158 detName = "det_a"
159 detId = 1
160 detSerial = "123"
161 orientation = cameraGeom.Orientation()
162 pixelSize = lsst.geom.Extent2D(1, 1)
164 camBuilder = cameraGeom.Camera.Builder("fakeCam")
165 detBuilder = camBuilder.add(detName, detId)
166 detBuilder.setSerial(detSerial)
167 detBuilder.setBBox(bbox)
168 detBuilder.setOrientation(orientation)
169 detBuilder.setPixelSize(pixelSize)
171 boxArr = BoxGrid(box=bbox, numColRow=numAmps)
172 for i in range(numAmps[0]):
173 for j in range(numAmps[1]):
174 ampInfo = cameraGeom.Amplifier.Builder()
175 ampInfo.setName("amp %d_%d" % (i + 1, j + 1))
176 ampInfo.setBBox(boxArr[i, j])
177 ampInfo.setLinearityType(linearityType)
178 ampInfo.setLinearityCoeffs([sqCoeffs[i, j]])
179 detBuilder.append(ampInfo)
181 return detBuilder
184class MemoryTester(lsst.utils.tests.MemoryTestCase):
185 pass
188def setup_module(module):
189 lsst.utils.tests.init()
192if __name__ == "__main__": 192 ↛ 193line 192 didn't jump to line 193, because the condition on line 192 was never true
193 lsst.utils.tests.init()
194 unittest.main()