Coverage for tests / test_loadReferenceCatalog.py: 23%
140 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-15 00:08 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-15 00:08 +0000
1import unittest
2import copy
4import astropy.units as u
6import lsst.utils.tests
7import lsst.afw.geom
8import lsst.pipe.base as pipeBase
9from lsst.meas.algorithms import (convertReferenceCatalog,
10 getRefFluxField,
11 ReferenceObjectLoader)
12from lsst.pipe.tasks.loadReferenceCatalog import LoadReferenceCatalogConfig, LoadReferenceCatalogTask
13from lsst.pipe.tasks.colorterms import Colorterm, ColortermDict, ColortermLibrary
16synthTerms = ColortermLibrary(data={
17 "synth*": ColortermDict(data={
18 "filter1": Colorterm(primary="ref1", secondary="ref2", c0=0.0, c1=0.01),
19 "filter2": Colorterm(primary="ref2", secondary="ref3", c0=0.0, c1=-0.01),
20 })
21})
24_synthFlux = 100.0
25_synthCenter = lsst.geom.SpherePoint(30, -30, lsst.geom.degrees)
28def setup_module(module):
29 lsst.utils.tests.init()
32class TrivialLoader(ReferenceObjectLoader):
33 """Minimal subclass of ReferenceObjectLoader"""
34 def make_synthetic_refcat(self, center, flux):
35 """Make a synthetic reference catalog."""
36 filters = ["ref1", "ref2", "ref3"]
37 schema = convertReferenceCatalog._makeSchema(filters)
38 schema.addField('pm_ra', 'D')
39 schema.addField('pm_dec', 'D')
41 catalog = lsst.afw.table.SimpleCatalog(schema)
42 record = catalog.addNew()
43 record.setCoord(center)
44 record[filters[0] + '_flux'] = flux
45 record[filters[0] + '_fluxErr'] = flux*0.1
46 record[filters[1] + '_flux'] = flux*10
47 record[filters[1] + '_fluxErr'] = flux*10*0.1
48 record[filters[2] + '_flux'] = flux*100
49 record[filters[2] + '_fluxErr'] = flux*100*0.1
50 record['pm_ra'] = 0.0
51 record['pm_dec'] = 0.0
53 return catalog
55 def loadSkyCircle(self, ctrCoord, radius, filterName, **kwargs):
56 refCat = self.make_synthetic_refcat(_synthCenter, _synthFlux)
57 fluxField = getRefFluxField(schema=refCat.schema, filterName=filterName)
58 return pipeBase.Struct(
59 refCat=self.make_synthetic_refcat(_synthCenter, _synthFlux),
60 fluxField=fluxField
61 )
63 def loadPixelBox(self, bbox, wcs, referenceFilter, **kwargs):
64 return self.loadSkyCircle(None, None, referenceFilter)
66 def loadSchema(self, filterName):
67 refCat = self.make_synthetic_refcat(_synthCenter, _synthFlux)
68 fluxField = getRefFluxField(schema=refCat.schema, filterName=filterName)
69 return pipeBase.Struct(
70 schema=refCat.schema,
71 fluxField=fluxField
72 )
75class LoadReferenceCatalogTestCase(lsst.utils.tests.TestCase):
76 @classmethod
77 def setUpClass(cls):
78 cls.config = LoadReferenceCatalogConfig()
79 cls.config.refObjLoader.filterMap = {"filter1": "ref1",
80 "filter2": "ref2"}
81 cls.config.colorterms = synthTerms
82 cls.config.referenceSelector.doSignalToNoise = True
83 cls.config.referenceSelector.signalToNoise.fluxField = 'ref1_flux'
84 cls.config.referenceSelector.signalToNoise.errField = 'ref1_fluxErr'
85 cls.config.referenceSelector.signalToNoise.minimum = 20.0
87 cls.config.doApplyColorTerms = False
88 cls.config.doReferenceSelection = False
90 cls.synthMag1 = (_synthFlux*u.nanojansky).to(u.ABmag).value
91 cls.synthMag2 = ((_synthFlux*10)*u.nanojansky).to(u.ABmag).value
92 cls.synthMag3 = ((_synthFlux*100)*u.nanojansky).to(u.ABmag).value
94 cls.synthMag1Corr = cls.synthMag1 + 0.01*(cls.synthMag1 - cls.synthMag2)
95 cls.synthMag2Corr = cls.synthMag2 - 0.01*(cls.synthMag2 - cls.synthMag3)
97 cls.trivialLoader = TrivialLoader(dataIds=[],
98 refCats=[],
99 name="synthCam",
100 config=cls.config.refObjLoader)
102 def testGetReferenceCatalogCircle(self):
103 """Get a reference catalog skycircle."""
104 config = copy.copy(self.config)
105 config.freeze()
107 loaderTask = LoadReferenceCatalogTask(config=config, dataIds=[], refCats=[], name="synthCam")
108 # Monkey-patch our testing trivial loader to bypass the butler
109 loaderTask.refObjLoader = self.trivialLoader
111 cat = loaderTask.getSkyCircleCatalog(_synthCenter,
112 1.0*lsst.geom.degrees,
113 ['filter1', 'filter2'])
115 self.assertAlmostEqual(cat['ra'], _synthCenter.getRa().asDegrees())
116 self.assertAlmostEqual(cat['dec'], _synthCenter.getDec().asDegrees())
117 self.assertFloatsAlmostEqual(cat['refMag'][0, 0], self.synthMag1, rtol=1e-7)
118 self.assertFloatsAlmostEqual(cat['refMag'][0, 1], self.synthMag2, rtol=1e-7)
120 def testGetReferenceCatalogBox(self):
121 """Get a reference catalog box."""
122 config = copy.copy(self.config)
123 config.freeze()
125 loaderTask = LoadReferenceCatalogTask(config=config, dataIds=[], refCats=[], name="synthCam")
126 # Monkey-patch our testing trivial loader to bypass the butler
127 loaderTask.refObjLoader = self.trivialLoader
129 bbox = lsst.geom.Box2I(corner=lsst.geom.Point2I(0, 0),
130 dimensions=lsst.geom.Extent2I(100, 100))
131 crpix = lsst.geom.Point2D(50, 50)
132 crval = _synthCenter
133 cdMatrix = lsst.afw.geom.makeCdMatrix(scale=1.0*lsst.geom.arcseconds)
134 wcs = lsst.afw.geom.makeSkyWcs(crpix, crval, cdMatrix)
136 cat = loaderTask.getPixelBoxCatalog(bbox,
137 wcs,
138 ['filter1', 'filter2'])
140 self.assertAlmostEqual(cat['ra'], _synthCenter.getRa().asDegrees())
141 self.assertAlmostEqual(cat['dec'], _synthCenter.getDec().asDegrees())
142 self.assertFloatsAlmostEqual(cat['refMag'][0, 0], self.synthMag1, rtol=1e-7)
143 self.assertFloatsAlmostEqual(cat['refMag'][0, 1], self.synthMag2, rtol=1e-7)
145 def testGetReferenceCatalogCircleColorterms(self):
146 """Get a reference catalog circle, with color terms applied."""
147 config = copy.copy(self.config)
148 config.doApplyColorTerms = True
149 config.freeze()
151 loaderTask = LoadReferenceCatalogTask(config=config, dataIds=[], refCats=[], name="synthCam")
152 # Monkey-patch our testing trivial loader to bypass the butler
153 loaderTask.refObjLoader = self.trivialLoader
155 cat = loaderTask.getSkyCircleCatalog(_synthCenter,
156 1.0*lsst.geom.degrees,
157 ['filter1', 'filter2'])
159 self.assertAlmostEqual(cat['ra'], _synthCenter.getRa().asDegrees())
160 self.assertAlmostEqual(cat['dec'], _synthCenter.getDec().asDegrees())
161 self.assertFloatsAlmostEqual(cat['refMag'][0, 0], self.synthMag1Corr, rtol=1e-7)
162 self.assertFloatsAlmostEqual(cat['refMag'][0, 1], self.synthMag2Corr, rtol=1e-7)
164 def testGetReferenceCatalogCircleSelection(self):
165 """Get a reference catalog circle, apply selection."""
166 config = copy.copy(self.config)
167 config.doReferenceSelection = True
168 config.freeze()
170 loaderTask = LoadReferenceCatalogTask(config=config, dataIds=[], refCats=[], name="synthCam")
171 # Monkey-patch our testing trivial loader to bypass the butler
172 loaderTask.refObjLoader = self.trivialLoader
174 cat = loaderTask.getSkyCircleCatalog(_synthCenter,
175 1.0*lsst.geom.degrees,
176 ['filter1', 'filter2'])
178 # The selection removed all the objects.
179 self.assertEqual(len(cat), 0)
181 def testGetReferenceCatalogCircleSingleFilter(self):
182 """Get a reference catalog circle, single filter."""
183 config = copy.copy(self.config)
184 config.freeze()
186 loaderTask = LoadReferenceCatalogTask(config=config, dataIds=[], refCats=[], name="synthCam")
187 # Monkey-patch our testing trivial loader to bypass the butler
188 loaderTask.refObjLoader = self.trivialLoader
190 cat = loaderTask.getSkyCircleCatalog(_synthCenter,
191 1.0*lsst.geom.degrees,
192 ['filter1'])
194 self.assertAlmostEqual(cat['ra'], _synthCenter.getRa().asDegrees())
195 self.assertAlmostEqual(cat['dec'], _synthCenter.getDec().asDegrees())
196 self.assertFloatsAlmostEqual(cat['refMag'][0, 0], self.synthMag1, rtol=1e-7)
198 def testGetReferenceCatalogAnyFilter(self):
199 """Get a reference catalog circle, using anyFilterMapsToThis."""
200 config = LoadReferenceCatalogConfig()
201 config.refObjLoader.anyFilterMapsToThis = 'ref1'
203 config.doApplyColorTerms = False
204 config.doReferenceSelection = False
205 config.freeze()
207 loaderTask = LoadReferenceCatalogTask(config=config, dataIds=[], refCats=[], name="synthCam")
208 # Monkey-patch our testing trivial loader to bypass the butler
209 loaderTask.refObjLoader = self.trivialLoader
211 cat = loaderTask.getSkyCircleCatalog(_synthCenter,
212 1.0*lsst.geom.degrees,
213 ['filter1', 'filter2'])
215 self.assertFloatsAlmostEqual(cat['refMag'][0, 0], self.synthMag1, rtol=1e-7)
216 self.assertFloatsAlmostEqual(cat['refMag'][0, 1], self.synthMag1, rtol=1e-7)
218 def testGetReferenceCatalogRequirePm(self):
219 """Get a reference catalog circle, requiring proper motion."""
220 config = copy.copy(self.config)
221 config.refObjLoader.requireProperMotion = True
222 config.freeze()
224 loaderTask = LoadReferenceCatalogTask(config=config, dataIds=[], refCats=[], name="synthCam")
225 # Monkey-patch our testing trivial loader to bypass the butler
226 trivialLoader2 = TrivialLoader(dataIds=[], refCats=[], name="synthCam", config=config.refObjLoader)
227 loaderTask.refObjLoader = trivialLoader2
229 cat = loaderTask.getSkyCircleCatalog(_synthCenter,
230 1.0*lsst.geom.degrees,
231 ['filter1'])
233 self.assertAlmostEqual(cat['ra'], _synthCenter.getRa().asDegrees())
234 self.assertAlmostEqual(cat['dec'], _synthCenter.getDec().asDegrees())
235 self.assertFloatsAlmostEqual(cat['refMag'][0, 0], self.synthMag1, rtol=1e-7)
238class MemoryTester(lsst.utils.tests.MemoryTestCase):
239 pass
242if __name__ == "__main__": 242 ↛ 243line 242 didn't jump to line 243 because the condition on line 242 was never true
243 lsst.utils.tests.init()
244 unittest.main()