Coverage for tests/test_curve.py: 20%
104 statements
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-10 02:04 -0700
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-10 02:04 -0700
1# This file is part of meas_algorithms.
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/>.
22import os
23import unittest
24import numpy as np
25from scipy import signal
26import astropy.units as u
28import lsst.meas.algorithms as algorithms
29import lsst.utils.tests
30from lsst.geom import Point2I, Point2D, Box2I, Extent2I
31import lsst.afw.cameraGeom.utils as cgUtils
33TESTDIR = os.path.abspath(os.path.dirname(__file__))
36class MockAmp:
37 def __init__(self, name, bbox):
38 self.name = name
39 self.box = bbox
41 def getName(self):
42 return self.name
44 def getBBox(self):
45 return self.box
48class CurveTestCase(lsst.utils.tests.TestCase):
49 """Tests for the Curve class"""
51 def setUp(self):
52 self.wavelength = np.linspace(3000, 5000, 150)*u.angstrom
53 self.efficiency = signal.gaussian(len(self.wavelength), std=100)*u.percent
54 self.metadata = dict([('MODE', 'AMP'), ('TYPE', 'QE'), ('CALIBDATE', '1970-01-01T00:00:00'),
55 ('INSTRUME', 'ts8'), ('OBSTYPE', 'qe_curve'), ('DETECTOR', 99),
56 ('DATE', '2019-09-27T22:15:13.518320'), ('CALIB_CREATION_DATE', '2019-09-27'),
57 ('CALIB_CREATION_TIME', '22:15:13')])
59 def tearDown(self):
60 del self.wavelength
61 del self.efficiency
62 del self.metadata
64 def curve_tester(self, curve_class, args):
65 curve = curve_class(*args)
67 # Serialization round trip
68 table = curve.toTable()
69 curve2 = curve_class.fromTable(table)
70 self.assertEqual(curve, curve2)
72 # via FITS
73 with lsst.utils.tests.getTempFilePath(".fits") as tmpFile:
74 curve.writeFits(tmpFile)
75 curve2 = algorithms.Curve.readFits(tmpFile)
77 self.assertEqual(curve2, curve)
79 # via text file
80 with lsst.utils.tests.getTempFilePath(".ecsv") as tmpFile:
81 curve.writeText(tmpFile)
82 curve2 = algorithms.Curve.readText(tmpFile)
84 self.assertEqual(curve2, curve)
86 # Check bad values
87 with self.assertRaises(ValueError):
88 # test that raised when non quantities are passed
89 nargs = []
90 for arg in args:
91 if hasattr(arg, 'unit'):
92 nargs.append(arg.value)
93 else:
94 nargs.append(arg)
95 _ = curve_class(*nargs)
97 # Check bad values
98 with self.assertRaises(ValueError):
99 # test that raised when non-length quantities are passed
100 nargs = []
101 for arg in args:
102 if hasattr(arg, 'unit'):
103 nargs.append(arg.value*u.amp)
104 else:
105 nargs.append(arg)
106 _ = curve_class(*nargs)
108 def interp_tester(self, curve_class, args, detector):
109 curve = curve_class(*args)
110 w = 3500*u.angstrom
111 xs = np.linspace(0, 1023, 33)
112 ys = np.linspace(0, 1023, 33)
113 val_map = {'A': 0.9329662, 'B': 0.7463730}
114 # Does interpolation work
115 for x, y in zip(xs, ys):
116 point = Point2D(x, y)
117 if detector:
118 amp = cgUtils.findAmp(detector, Point2I(point))
119 value = val_map[amp.getName()]
120 else:
121 value = 0.9329662
122 interp_val = curve.evaluate(detector, point, w)
123 self.assertAlmostEqual(interp_val.value, value, places=5)
124 self.assertEqual(interp_val.unit, u.percent)
125 # Does interpolation work with arrays
126 w_arr = np.linspace(320, 430, 70)*u.nm
127 out_arr = curve.evaluate(detector, point, w_arr)
128 self.assertEqual(len(w_arr), len(out_arr))
129 # Does interpolation with different units work as expected
130 point = Point2D(500., 500.)
131 val1 = curve.evaluate(detector, point, w)
132 new_w = w.to(u.mm)
133 val2 = curve.evaluate(detector, point, new_w)
134 self.assertEqual(val1.value, val2.value)
135 # Does out of band interpolation do something reasonable
136 # Default is to clamp to 0 outside the bounds.
137 w = 0.*u.angstrom
138 interp_val = curve.evaluate(detector, point, w)
139 self.assertEqual(interp_val, 0.*u.percent)
140 # interpolation with non-quantity should raise
141 with self.assertRaises(ValueError):
142 interp_val = curve.evaluate(detector, point, w.value)
143 # Does interpolation fail with non-length unit
144 with self.assertRaises(ValueError):
145 w = 0.*u.Kelvin
146 interp_val = curve.evaluate(detector, point, w)
148 def test_detector_curve(self):
149 args = (self.wavelength, self.efficiency, self.metadata)
150 self.curve_tester(algorithms.DetectorCurve, args)
151 self.interp_tester(algorithms.DetectorCurve, args, None)
153 def test_amp_curve(self):
154 # Future versions of astropy will pass unit through concatenation
155 amp_wavelength = np.concatenate([self.wavelength.value, self.wavelength.value])*u.angstrom # Two amps
156 amp_efficiency = np.concatenate([self.efficiency.value,
157 self.efficiency.value*0.8])*u.percent # Two amps
158 amp_name = np.concatenate([['A' for el in self.wavelength], ['B' for el in self.wavelength]])
159 amplist = [MockAmp('A', Box2I(Point2I(0, 0), Extent2I(512, 1025))),
160 MockAmp('B', Box2I(Point2I(512, 10), Extent2I(512, 1024)))]
161 args = (amp_name, amp_wavelength, amp_efficiency, self.metadata)
162 self.curve_tester(algorithms.AmpCurve, args)
163 self.interp_tester(algorithms.AmpCurve, args, amplist)
166class TestMemory(lsst.utils.tests.MemoryTestCase):
167 pass
170def setup_module(module):
171 lsst.utils.tests.init()
174if __name__ == "__main__": 174 ↛ 175line 174 didn't jump to line 175, because the condition on line 174 was never true
175 lsst.utils.tests.init()
176 unittest.main()