Coverage for tests/test_map_ap_data.py : 15%

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 ap_association.
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
25from lsst.ap.association import (
26 MapApDataConfig,
27 MapApDataTask,
28 MapDiaSourceConfig,
29 MapDiaSourceTask,
30 UnpackApdbFlags)
31from lsst.afw.cameraGeom.testUtils import DetectorWrapper
32import lsst.afw.table as afwTable
33import lsst.daf.base as dafBase
34import lsst.afw.image as afwImage
35import lsst.geom as geom
36import lsst.meas.base.tests as measTests
37from lsst.utils import getPackageDir
38import lsst.utils.tests
41def make_input_source_catalog(dataset, add_flags=False):
42 """Create tests objects to map into apData products.
44 Parameters
45 ----------
46 dataset : `lsst.meas.base.tests.TestDataset`
47 Test dataset to create random exposure realizations with inserted
48 sources and detected sources in a catalog.
49 """
50 schema = dataset.makeMinimalSchema()
51 schema.addField("base_NaiveCentroid_x", type="D")
52 schema.addField("base_NaiveCentroid_y", type="D")
53 schema.addField("base_PsfFlux_instFlux", type="D")
54 schema.addField("base_PsfFlux_instFluxErr", type="D")
55 schema.addField("ip_diffim_DipoleFit_separation", type="D")
56 schema.addField("ip_diffim_DipoleFit_orientation", type="D")
57 schema.addField("ip_diffim_DipoleFit_neg_instFlux", type="D")
58 schema.addField("ip_diffim_DipoleFit_neg_instFluxErr", type="D")
59 schema.addField("ip_diffim_DipoleFit_pos_instFlux", type="D")
60 schema.addField("ip_diffim_DipoleFit_pos_instFluxErr", type="D")
61 schema.addField("ip_diffim_forced_PsfFlux_instFlux", type="D")
62 schema.addField("ip_diffim_forced_PsfFlux_instFluxErr", type="D")
63 if add_flags:
64 schema.addField("base_PixelFlags_flag", type="Flag")
65 schema.addField("base_PixelFlags_flag_offimage", type="Flag")
67 exposure, catalog = dataset.realize(10.0, schema, randomSeed=1234)
68 catalog.definePsfFlux("base_PsfFlux")
69 catalog.defineCentroid("base_NaiveCentroid")
71 # Fill in simple values for the test DiaSources. Create specific values
72 # where required such as negative values for the negative lobe of the
73 # dipole flux.
74 for src in catalog:
75 for subSchema in schema:
76 if subSchema.getField().getName() == "ip_diffim_DipoleFit_neg_instFlux":
77 src.set(subSchema.getKey(), -1)
78 elif (subSchema.getField().getName().startswith("ip")
79 or subSchema.getField().getName().startswith("base")):
80 src.set(subSchema.getKey(), 1)
81 src.set("base_NaiveCentroid_x", src["truth_x"])
82 src.set("base_NaiveCentroid_y", src["truth_y"])
83 src.setCoord(exposure.getWcs().pixelToSky(src.getCentroid()))
84 return catalog, exposure
87class TestAPDataMapperTask(unittest.TestCase):
89 def setUp(self):
90 nSources = 10
91 self.bbox = geom.Box2I(geom.Point2I(0, 0),
92 geom.Extent2I(1024, 1153))
93 dataset = measTests.TestDataset(self.bbox)
94 for srcIdx in range(nSources):
95 dataset.addSource(100000.0, geom.Point2D(100, 100))
96 self.inputCatalogNoFlags, _ = make_input_source_catalog(dataset, False)
97 self.inputCatalog, self.exposure = \
98 make_input_source_catalog(dataset, True)
100 detector = DetectorWrapper(id=23, bbox=self.exposure.getBBox()).detector
101 visit = afwImage.VisitInfo(
102 exposureId=4321,
103 exposureTime=200.,
104 date=dafBase.DateTime(nsecs=1400000000 * 10**9))
105 self.exposure.setDetector(detector)
106 self.exposure.getInfo().setVisitInfo(visit)
107 self.exposure.setFilterLabel(afwImage.FilterLabel(band='g', physical='g.MP9401'))
108 scale = 2
109 scaleErr = 1
110 self.photoCalib = afwImage.PhotoCalib(scale, scaleErr)
111 self.exposure.setPhotoCalib(self.photoCalib)
113 def test_run(self):
114 """Test the generic data product mapper.
115 """
116 outSchema = afwTable.SourceTable.makeMinimalSchema()
117 outSchema.addField("psFlux", type="D")
118 outSchema.addField("psFluxErr", type="D")
120 mapApDConfig = MapApDataConfig()
121 mapApDConfig.copyColumns = {
122 "id": "id",
123 "parent": "parent",
124 "coord_ra": "coord_ra",
125 "coord_dec": "coord_dec",
126 "slot_PsfFlux_instFlux": "psFlux",
127 "slot_PsfFlux_instFluxErr": "psFluxErr"
128 }
130 mapApD = MapApDataTask(inputSchema=self.inputCatalog.schema,
131 outputSchema=outSchema,
132 config=mapApDConfig)
133 outputCatalog = mapApD.run(self.inputCatalog)
135 for inObj, outObj in zip(self.inputCatalog, outputCatalog):
136 for inputName, outputName in mapApDConfig.copyColumns.items():
137 self.assertEqual(inObj[inputName], outObj[outputName])
139 def test_run_dia_source(self):
140 """Test the DiaSource specific data product mapper/calibrator.
141 """
142 mapApDConfig = self._create_map_dia_source_config()
143 mapApD = MapDiaSourceTask(inputSchema=self.inputCatalog.schema,
144 config=mapApDConfig)
145 outputCatalog = mapApD.run(self.inputCatalog, self.exposure)
147 expectedMeanDip = 2.
148 expectedDiffFlux = 0.
149 expectedLength = 0.19999994425496748
150 expectedBBox = 18
152 for inObj, outObj in zip(self.inputCatalog, outputCatalog):
153 self.assertEqual(
154 outObj["ccdVisitId"],
155 self.exposure.getInfo().getVisitInfo().getExposureId())
156 self.assertEqual(
157 outObj["midPointTai"],
158 self.exposure.getInfo().getVisitInfo().getDate().get(
159 system=dafBase.DateTime.MJD))
160 self.assertEqual(
161 outObj["flags"],
162 1 * 2 ** 0 + 1 * 2 ** 1)
163 for inputName, outputName in mapApDConfig.copyColumns.items():
164 if inputName.startswith("slot_PsfFlux"):
165 self._test_calibrated_flux(inObj, outObj)
166 else:
167 self.assertEqual(inObj[inputName], outObj[outputName])
168 self.assertEqual(outObj["dipMeanFlux"], expectedMeanDip)
169 self.assertEqual(outObj["dipFluxDiff"], expectedDiffFlux)
170 self.assertAlmostEqual(outObj["dipLength"], expectedLength)
171 self.assertEqual(outObj["bboxSize"], expectedBBox)
172 # Mapper should always emit standardized filters
173 self.assertEqual(outObj["filterName"], 'g')
175 def _create_map_dia_source_config(self):
176 """Create a test config for use in MapDiaSourceTask.
178 Returns
179 -------
180 configurable : `lsst.pex.config.Config`
181 Configurable for use in MapDiaSourceTask.
182 """
183 configurable = MapDiaSourceConfig()
184 configurable.copyColumns = {
185 "id": "id",
186 "parent": "parent",
187 "coord_ra": "coord_ra",
188 "coord_dec": "coord_dec",
189 "slot_PsfFlux_instFlux": "psFlux",
190 "slot_PsfFlux_instFluxErr": "psFluxErr"
191 }
192 configurable.calibrateColumns = ["slot_PsfFlux"]
193 configurable.flagMap = os.path.join(
194 getPackageDir("ap_association"),
195 "tests",
196 "test-flag-map.yaml")
198 return configurable
200 def test_run_dia_source_wrong_flags(self):
201 """Test that the proper errors are thrown when requesting flag columns
202 that are not in the input schema.
203 """
204 mapApDConfig = self._create_map_dia_source_config()
205 with self.assertRaises(KeyError):
206 MapDiaSourceTask(inputSchema=self.inputCatalogNoFlags.schema,
207 config=mapApDConfig)
209 def test_calibrateFluxes(self):
210 """Test that flux calibration works as expected.
211 """
212 outSchema = afwTable.SourceTable.makeMinimalSchema()
213 outSchema.addField("psFlux", type="D")
214 outSchema.addField("psFluxErr", type="D")
216 outputCatalog = afwTable.SourceCatalog(outSchema)
217 outRecord = outputCatalog.addNew()
219 mapApDConfig = self._create_map_dia_source_config()
220 mapApD = MapDiaSourceTask(inputSchema=self.inputCatalog.schema,
221 config=mapApDConfig)
223 mapApD.calibrateFluxes(self.inputCatalog[0],
224 outRecord,
225 self.photoCalib)
226 self._test_calibrated_flux(self.inputCatalog[0], outRecord)
228 def _test_calibrated_flux(self, inputRecord, outputRecord):
229 """Compare calibrated fluxes to expectation from zero point.
231 Parameters
232 ----------
233 inputRecord: `lsst.afw.table.SourceRecord`
234 Input source record with uncalibrated flux values.
235 outputRecord: `lsst.afw.table.SourceRecord`
236 Source record with calibrated fluxes.
237 """
238 expected = self.photoCalib.instFluxToNanojansky(inputRecord["slot_PsfFlux_instFlux"],
239 inputRecord["slot_PsfFlux_instFluxErr"])
240 self.assertAlmostEqual(outputRecord["psFlux"], expected.value)
241 self.assertAlmostEqual(outputRecord["psFluxErr"], expected.error)
243 def test_computeBBoxSize(self):
244 """Test the values created for diaSourceBBox.
245 """
246 outSchema = afwTable.SourceTable.makeMinimalSchema()
247 outSchema.addField("bboxSize", type="I")
248 outputCatalog = afwTable.SourceCatalog(outSchema)
249 outRecord = outputCatalog.addNew()
250 mapApDConfig = self._create_map_dia_source_config()
251 mapApD = MapDiaSourceTask(inputSchema=self.inputCatalog.schema,
252 config=mapApDConfig)
253 mapApD.computeBBoxSize(self.inputCatalog[0], outRecord)
255 self.assertEqual(outRecord["bboxSize"], 18)
257 def test_bit_unpacker(self):
258 """Test that the integer bit packer is functioning correctly.
259 """
260 mapApDConfig = self._create_map_dia_source_config()
261 mapApD = MapDiaSourceTask(inputSchema=self.inputCatalog.schema,
262 config=mapApDConfig)
263 for idx, obj in enumerate(self.inputCatalog):
264 if idx in [1, 3, 5]:
265 obj.set("base_PixelFlags_flag", 0)
266 if idx in [1, 4, 6]:
267 obj.set("base_PixelFlags_flag_offimage", 0)
268 outputCatalog = mapApD.run(self.inputCatalog, self.exposure)
270 unpacker = UnpackApdbFlags(mapApDConfig.flagMap, "DiaSource")
271 flag_values = unpacker.unpack(outputCatalog.get("flags"), "flags")
273 for idx, flag in enumerate(flag_values):
274 if idx in [1, 3, 5]:
275 self.assertFalse(flag['base_PixelFlags_flag'])
276 else:
277 self.assertTrue(flag['base_PixelFlags_flag'])
279 if idx in [1, 4, 6]:
280 self.assertFalse(flag['base_PixelFlags_flag_offimage'])
281 else:
282 self.assertTrue(flag['base_PixelFlags_flag_offimage'])
285class MemoryTester(lsst.utils.tests.MemoryTestCase):
286 pass
289def setup_module(module):
290 lsst.utils.tests.init()
293if __name__ == "__main__": 293 ↛ 294line 293 didn't jump to line 294, because the condition on line 293 was never true
294 lsst.utils.tests.init()
295 unittest.main()