Coverage for tests/test_loadReferenceObjects.py: 12%
163 statements
« prev ^ index » next coverage.py v7.1.0, created at 2023-02-05 18:13 -0800
« prev ^ index » next coverage.py v7.1.0, created at 2023-02-05 18:13 -0800
1#
2# LSST Data Management System
3#
4# Copyright 2008-2016 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#
24import itertools
25import unittest
27import lsst.afw.table as afwTable
28import lsst.log
29from lsst.meas.algorithms import LoadReferenceObjectsTask, getRefFluxField, getRefFluxKeys
30from lsst.meas.algorithms.loadReferenceObjects import hasNanojanskyFluxUnits, convertToNanojansky
31import lsst.pex.config
32import lsst.utils.tests
35class TrivialLoader(LoadReferenceObjectsTask):
36 """Minimal subclass of LoadReferenceObjectsTask to allow instantiation
37 """
39 def loadSkyCircle(self, ctrCoord, radius, filterName):
40 pass
43class TestLoadReferenceObjects(lsst.utils.tests.TestCase):
44 """Test case for LoadReferenceObjectsTask abstract base class
46 Only methods with concrete implementations are tested (hence not loadSkyCircle)
47 """
49 def testFilterMapVsAnyFilterMapsToThis(self):
50 config = TrivialLoader.ConfigClass()
51 # check that a filterMap-only config passes validation
52 config.filterMap = {"b": "a"}
53 try:
54 config.validate()
55 except lsst.pex.config.FieldValidationError:
56 self.fail("`filterMap`-only LoadReferenceObjectsConfig should not fail validation.")
58 # anyFilterMapsToThis and filterMap are mutually exclusive
59 config.anyFilterMapsToThis = "c"
60 with self.assertRaises(lsst.pex.config.FieldValidationError):
61 config.validate()
63 # check that a anyFilterMapsToThis-only config passes validation
64 config.filterMap = {}
65 try:
66 config.validate()
67 except lsst.pex.config.FieldValidationError:
68 self.fail("`anyFilterMapsToThis`-only LoadReferenceObjectsConfig should not fail validation.")
70 def testMakeMinimalSchema(self):
71 """Make a schema and check it."""
72 for filterNameList in (["r"], ["foo", "_bar"]):
73 for (addIsPhotometric, addIsResolved, addIsVariable,
74 coordErrDim, addProperMotion, properMotionErrDim,
75 addParallax) in itertools.product(
76 (False, True), (False, True), (False, True),
77 (-1, 0, 1, 2, 3, 4), (False, True), (-1, 0, 1, 2, 3, 4),
78 (False, True)):
79 argDict = dict(
80 filterNameList=filterNameList,
81 addIsPhotometric=addIsPhotometric,
82 addIsResolved=addIsResolved,
83 addIsVariable=addIsVariable,
84 coordErrDim=coordErrDim,
85 addProperMotion=addProperMotion,
86 properMotionErrDim=properMotionErrDim,
87 addParallax=addParallax,
88 )
89 if coordErrDim not in (0, 2, 3) or \
90 (addProperMotion and properMotionErrDim not in (0, 2, 3)):
91 with self.assertRaises(ValueError):
92 LoadReferenceObjectsTask.makeMinimalSchema(**argDict)
93 else:
94 refSchema = LoadReferenceObjectsTask.makeMinimalSchema(**argDict)
95 self.assertTrue("coord_ra" in refSchema)
96 self.assertTrue("coord_dec" in refSchema)
97 for filterName in filterNameList:
98 fluxField = filterName + "_flux"
99 self.assertIn(fluxField, refSchema)
100 self.assertNotIn("x" + fluxField, refSchema)
101 fluxErrField = fluxField + "Err"
102 self.assertIn(fluxErrField, refSchema)
103 self.assertEqual(getRefFluxField(refSchema, filterName), filterName + "_flux")
104 self.assertEqual("resolved" in refSchema, addIsResolved)
105 self.assertEqual("variable" in refSchema, addIsVariable)
106 self.assertEqual("photometric" in refSchema, addIsPhotometric)
107 self.assertEqual("photometric" in refSchema, addIsPhotometric)
108 self.assertEqual("epoch" in refSchema, addProperMotion or addParallax)
109 self.assertEqual("coord_raErr" in refSchema, coordErrDim > 0)
110 self.assertEqual("coord_decErr" in refSchema, coordErrDim > 0)
111 self.assertEqual("coord_ra_dec_Cov" in refSchema, coordErrDim == 3)
112 self.assertEqual("pm_ra" in refSchema, addProperMotion)
113 self.assertEqual("pm_dec" in refSchema, addProperMotion)
114 self.assertEqual("pm_raErr" in refSchema, addProperMotion and properMotionErrDim > 0)
115 self.assertEqual("pm_decErr" in refSchema, addProperMotion and properMotionErrDim > 0)
116 self.assertEqual("pm_flag" in refSchema, addProperMotion)
117 self.assertEqual("pm_ra_dec_Cov" in refSchema,
118 addProperMotion and properMotionErrDim == 3)
119 self.assertEqual("parallax" in refSchema, addParallax)
120 self.assertEqual("parallaxErr" in refSchema, addParallax)
121 self.assertEqual("parallax_flag" in refSchema, addParallax)
123 def testFilterAliasMap(self):
124 """Make a schema with filter aliases."""
125 for defaultFilter in ("", "r", "camr"):
126 for filterMap in ({}, {"camr": "r"}):
127 config = TrivialLoader.ConfigClass()
128 config.defaultFilter = defaultFilter
129 config.filterMap = filterMap
130 loader = TrivialLoader(config=config)
131 refSchema = TrivialLoader.makeMinimalSchema(filterNameList="r")
132 try:
133 loader._addFluxAliases(refSchema)
134 self.assertNotEqual(defaultFilter, "camr")
135 except Exception:
136 # only reference filters are allowed as default filters
137 self.assertEqual(defaultFilter, "camr")
138 continue
140 self.assertIn("r_flux", refSchema)
141 self.assertIn("r_fluxErr", refSchema)
143 # camera filters aliases are named <filter>_camFlux
144 if "camr" in filterMap:
145 self.assertEqual(getRefFluxField(refSchema, "camr"), "camr_camFlux")
146 else:
147 with self.assertRaises(RuntimeError):
148 getRefFluxField(refSchema, "camr")
150 # if a non-empty default filter is specified then camFlux
151 # and camFluxErr should be present
152 hasDefault = bool(defaultFilter)
153 self.assertEqual("camFlux" in refSchema, hasDefault)
154 self.assertEqual("camFluxErr" in refSchema, hasDefault)
156 refCat = afwTable.SimpleCatalog(refSchema)
157 refObj = refCat.addNew()
158 refObj["r_flux"] = 1.23
159 self.assertAlmostEqual(refCat[0].get(getRefFluxField(refSchema, "r")), 1.23)
160 if "camr" in filterMap:
161 self.assertAlmostEqual(refCat[0].get(getRefFluxField(refSchema, "camr")), 1.23)
162 if hasDefault:
163 self.assertEqual(getRefFluxField(refSchema, ""), "camFlux")
164 self.assertAlmostEqual(refCat[0].get(getRefFluxField(refSchema, "")), 1.23)
165 refObj["r_fluxErr"] = 0.111
166 if "camr" in filterMap:
167 self.assertEqual(refCat[0].get("camr_camFluxErr"), 0.111)
168 fluxKey, fluxErrKey = getRefFluxKeys(refSchema, "r")
169 self.assertEqual(refCat[0].get(fluxKey), 1.23)
170 self.assertEqual(refCat[0].get(fluxErrKey), 0.111)
171 if "camr" in filterMap:
172 fluxKey, fluxErrKey = getRefFluxKeys(refSchema, "camr")
173 self.assertEqual(refCat[0].get(fluxErrKey), 0.111)
174 else:
175 with self.assertRaises(RuntimeError):
176 getRefFluxKeys(refSchema, "camr")
178 def testAnyFilterMapsToThisAlias(self):
179 # test anyFilterMapsToThis
180 config = TrivialLoader.ConfigClass()
181 config.anyFilterMapsToThis = "gg"
182 loader = TrivialLoader(config=config)
183 refSchema = TrivialLoader.makeMinimalSchema(filterNameList=["gg"])
184 loader._addFluxAliases(refSchema)
185 self.assertEqual(getRefFluxField(refSchema, "r"), "gg_flux")
186 # raise if "gg" is not in the refcat filter list
187 with self.assertRaises(RuntimeError):
188 refSchema = TrivialLoader.makeMinimalSchema(filterNameList=["rr"])
189 refSchema = loader._addFluxAliases(refSchema)
191 def testCheckFluxUnits(self):
192 """Test that we can identify old style fluxes in a schema."""
193 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z'])
194 # the default schema should pass
195 self.assertTrue(hasNanojanskyFluxUnits(schema))
196 schema.addField('bad_fluxSigma', doc='old flux units', type=float, units='')
197 self.assertFalse(hasNanojanskyFluxUnits(schema))
199 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z'])
200 schema.addField('bad_flux', doc='old flux units', type=float, units='')
201 self.assertFalse(hasNanojanskyFluxUnits(schema))
203 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z'])
204 schema.addField('bad_flux', doc='old flux units', type=float, units='Jy')
205 self.assertFalse(hasNanojanskyFluxUnits(schema))
207 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z'])
208 schema.addField('bad_fluxErr', doc='old flux units', type=float, units='')
209 self.assertFalse(hasNanojanskyFluxUnits(schema))
211 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z'])
212 schema.addField('bad_fluxErr', doc='old flux units', type=float, units='Jy')
213 self.assertFalse(hasNanojanskyFluxUnits(schema))
215 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z'])
216 schema.addField('bad_fluxSigma', doc='old flux units', type=float, units='')
217 self.assertFalse(hasNanojanskyFluxUnits(schema))
219 def testConvertOldFluxes(self):
220 """Check that we can convert old style fluxes in a catalog."""
221 flux = 1.234
222 fluxErr = 5.678
223 log = lsst.log.Log()
225 def make_catalog():
226 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z'])
227 schema.addField('bad_flux', doc='old flux units', type=float, units='')
228 schema.addField('bad_fluxErr', doc='old flux units', type=float, units='Jy')
229 refCat = afwTable.SimpleCatalog(schema)
230 refObj = refCat.addNew()
231 refObj["bad_flux"] = flux
232 refObj["bad_fluxErr"] = fluxErr
233 return refCat
235 oldRefCat = make_catalog()
236 newRefCat = convertToNanojansky(oldRefCat, log)
237 self.assertEqual(newRefCat['bad_flux'], [flux*1e9, ])
238 self.assertEqual(newRefCat['bad_fluxErr'], [fluxErr*1e9, ])
239 self.assertEqual(newRefCat.schema['bad_flux'].asField().getUnits(), 'nJy')
240 self.assertEqual(newRefCat.schema['bad_fluxErr'].asField().getUnits(), 'nJy')
242 # check that doConvert=False returns None (it also logs a summary)
243 oldRefCat = make_catalog()
244 newRefCat = convertToNanojansky(oldRefCat, log, doConvert=False)
245 self.assertIsNone(newRefCat)
248class TestMemory(lsst.utils.tests.MemoryTestCase):
249 pass
252def setup_module(module):
253 lsst.utils.tests.init()
256if __name__ == "__main__": 256 ↛ 257line 256 didn't jump to line 257, because the condition on line 256 was never true
257 lsst.utils.tests.init()
258 unittest.main()