Coverage for python/lsst/obs/base/butler_tests.py : 19%

Hot-keys 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# This file is part of obs_base.
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 abc
23import inspect
24import unittest
25import collections
27__all__ = ["ButlerGetTests"]
30class ButlerGetTests(metaclass=abc.ABCMeta):
31 """Tests of obs_* Butler get() functionality.
33 In the subclasses's setUp():
34 * Call setUp_butler_get() to fill in required parameters.
35 """
37 def setUp_butler_get(self,
38 ccdExposureId_bits=None,
39 exposureIds=None,
40 filters=None,
41 exptimes=None,
42 detectorIds=None,
43 detector_names=None,
44 detector_serials=None,
45 dimensions=None,
46 sky_origin=None,
47 raw_subsets=None,
48 good_detectorIds=None,
49 bad_detectorIds=None,
50 linearizer_type=None,
51 raw_header_wcs=None
52 ):
53 """
54 Set up the necessary variables for butlerGet tests.
56 All "exposure name" entries below should correspond to an entry in
57 self.dataIds.
59 Parameters
60 ----------
62 ccdExposureId_bits : `int`
63 expected value of ccdExposureId_bits
64 exposureIds : `dict`
65 dict of exposure name : ccdExposureId (the number as returned by
66 the butler)
67 filters : `dict`
68 dict of exposure name : filter name
69 exptimes : `dict`
70 dict of exposure name : exposure time
71 detector_names : `dict`
72 dict of exposure name : detector name
73 detectorIds : `dict`
74 dict of exposure name : detectorId
75 detector_serials : `dict`
76 dict of exposure name : detector serial
77 dimensions : `dict`
78 dict of exposure name : dimensions (as a geom.Extent2I)
79 sky_origin : `tuple` of `float`
80 Longitude, Latitude of 'raw' exposure
81 raw_subsets : `tuple` of (kwargs, `int`)
82 keyword args and expected number of subsets for
83 ``butler.subset('raw', **kwargs)``
84 good_detectorIds : `list` of `int`
85 list of valid ccd numbers
86 bad_detectorIds : `list` of `int`
87 list of invalid ccd numbers
88 linearizer_type : `dict`
89 dict of detectorId (usually `int`): LinearizerType
90 (e.g. lsst.ip.isr.LinearizeLookupTable.LinearityType),
91 or unittest.SkipTest to skip all linearizer tests.
92 raw_header_wcs : `lsst.afw.geom.SkyWcs`
93 The SkyWcs object that should be returned by
94 ``butler.get("raw_header_wcs", dataId=self.dataIds["raw"])``
95 """
97 fields = ['ccdExposureId_bits',
98 'exposureIds',
99 'filters',
100 'exptimes',
101 'detector_names',
102 'detectorIds',
103 'detector_serials',
104 'dimensions',
105 'sky_origin',
106 'raw_subsets',
107 'good_detectorIds',
108 'bad_detectorIds',
109 'linearizer_type',
110 'raw_header_wcs'
111 ]
112 ButlerGet = collections.namedtuple("ButlerGetData", fields)
114 self.butler_get_data = ButlerGet(ccdExposureId_bits=ccdExposureId_bits,
115 exposureIds=exposureIds,
116 filters=filters,
117 exptimes=exptimes,
118 detectorIds=detectorIds,
119 detector_names=detector_names,
120 detector_serials=detector_serials,
121 dimensions=dimensions,
122 sky_origin=sky_origin,
123 raw_subsets=raw_subsets,
124 good_detectorIds=good_detectorIds,
125 bad_detectorIds=bad_detectorIds,
126 linearizer_type=linearizer_type,
127 raw_header_wcs=raw_header_wcs
128 )
130 def test_exposureId_bits(self):
131 bits = self.butler.get('ccdExposureId_bits')
132 self.assertEqual(bits, self.butler_get_data.ccdExposureId_bits)
134 def _test_exposure(self, name):
135 if self.dataIds[name] is unittest.SkipTest:
136 self.skipTest('Skipping %s as requested' % (inspect.currentframe().f_code.co_name))
137 exp = self.butler.get(name, self.dataIds[name])
139 exp_md = self.butler.get(name + "_md", self.dataIds[name])
140 self.assertEqual(type(exp_md), type(exp.getMetadata()))
142 self.assertEqual(exp.getDimensions(), self.butler_get_data.dimensions[name])
143 self.assertEqual(exp.getDetector().getId(), self.butler_get_data.detectorIds[name])
144 self.assertEqual(exp.getDetector().getName(), self.butler_get_data.detector_names[name])
145 self.assertEqual(exp.getDetector().getSerial(), self.butler_get_data.detector_serials[name])
146 # obs_test does not have physical filters, so include a fallback
147 exposureFilter = exp.getFilterLabel()
148 if exposureFilter:
149 if exposureFilter.hasPhysicalLabel():
150 filterName = exposureFilter.physicalLabel
151 else:
152 filterName = exposureFilter.bandLabel
153 else:
154 filterName = "_unknown_"
155 self.assertEqual(filterName, self.butler_get_data.filters[name])
156 exposureId = self.butler.get('ccdExposureId', dataId=self.dataIds[name])
157 self.assertEqual(exposureId, self.butler_get_data.exposureIds[name])
158 self.assertEqual(exp.getInfo().getVisitInfo().getExposureTime(), self.butler_get_data.exptimes[name])
159 return exp
161 def test_raw(self):
162 exp = self._test_exposure('raw')
163 # We only test the existence of WCS in the raw files, since it's only
164 # well-defined for raw, and other exposure types could have or not
165 # have a WCS depending on various implementation details.
166 # Even for raw, there are data that do not have a WCS, e.g. teststand
167 # data
168 if self.butler_get_data.sky_origin is not unittest.SkipTest:
169 self.assertEqual(exp.hasWcs(), True)
170 origin = exp.getWcs().getSkyOrigin()
171 self.assertAlmostEqual(origin.getLongitude().asDegrees(), self.butler_get_data.sky_origin[0])
172 self.assertAlmostEqual(origin.getLatitude().asDegrees(), self.butler_get_data.sky_origin[1])
174 def test_bias(self):
175 self._test_exposure('bias')
177 def test_dark(self):
178 self._test_exposure('dark')
180 def test_flat(self):
181 self._test_exposure('flat')
183 def test_raw_header_wcs(self):
184 """Test that `raw_header_wcs` returns the unmodified raw image header.
185 """
186 if self.butler_get_data.raw_header_wcs is not None:
187 wcs = self.butler.get('raw_header_wcs', self.dataIds['raw'])
188 self.assertEqual(wcs, self.butler_get_data.raw_header_wcs)
190 @unittest.skip('Cannot test this, as there is a bug in the butler! DM-8097')
191 def test_raw_sub_bbox(self):
192 exp = self.butler.get('raw', self.dataIds['raw'], immediate=True)
193 bbox = exp.getBBox()
194 bbox.grow(-1)
195 sub = self.butler.get("raw_sub", self.dataIds['raw'], bbox=bbox, immediate=True)
196 self.assertEqual(sub.getImage().getBBox(), bbox)
197 self.assertImagesEqual(sub, exp.Factory(exp, bbox))
199 def test_subset_raw(self):
200 for kwargs, expect in self.butler_get_data.raw_subsets:
201 subset = self.butler.subset("raw", **kwargs)
202 self.assertEqual(len(subset), expect, msg="Failed for kwargs: {}".format(kwargs))
204 def test_get_linearizer(self):
205 """Test that we can get a linearizer for good detectorIds."""
206 if self.butler_get_data.linearizer_type is unittest.SkipTest:
207 self.skipTest('Skipping %s as requested' % (inspect.currentframe().f_code.co_name))
209 camera = self.butler.get("camera")
210 for detectorId in self.butler_get_data.good_detectorIds:
211 detector = camera[detectorId]
212 linearizer = self.butler.get("linearizer", dataId=dict(ccd=detectorId), immediate=True)
213 self.assertEqual(linearizer.LinearityType, self.butler_get_data.linearizer_type[detectorId])
214 linearizer.checkDetector(detector)
216 def test_get_linearizer_bad_detectorIds(self):
217 """Do bad detectorIds raise?"""
218 if self.butler_get_data.linearizer_type is unittest.SkipTest:
219 self.skipTest('Skipping %s as requested' % (inspect.currentframe().f_code.co_name))
221 for badccd in self.butler_get_data.bad_detectorIds:
222 with self.assertRaises(RuntimeError):
223 self.butler.get("linearizer", dataId=dict(ccd=badccd), immediate=True)