Coverage for tests/test_finalizeCharacterization.py: 20%
97 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-04-04 02:48 -0700
« prev ^ index » next coverage.py v6.5.0, created at 2023-04-04 02:48 -0700
1# This file is part of pipe_tasks.
2#
3# LSST Data Management System
4# This product includes software developed by the
5# LSST Project (http://www.lsst.org/).
6# See COPYRIGHT file at the top of the source tree.
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the LSST License Statement and
19# the GNU General Public License along with this program. If not,
20# see <https://www.lsstcorp.org/LegalNotices/>.
21#
22"""Test FinalizeCharacterizationTask.
23"""
24import unittest
25import numpy as np
26import pandas as pd
28import lsst.utils.tests
29import lsst.daf.butler
30import lsst.pipe.base as pipeBase
32from lsst.pipe.tasks.finalizeCharacterization import (FinalizeCharacterizationConfig,
33 FinalizeCharacterizationTask)
36class MockDataFrameReference(lsst.daf.butler.DeferredDatasetHandle):
37 """Very simple object that looks like a Gen3 data reference to
38 a dataframe.
39 """
40 def __init__(self, df):
41 self.df = df
43 def get(self, parameters={}, **kwargs):
44 """Retrieve the specified dataset using the API of the Gen3 Butler.
46 Parameters
47 ----------
48 parameters : `dict`, optional
49 Parameter dictionary. Supported key is ``columns``.
51 Returns
52 -------
53 dataframe : `pandas.DataFrame`
54 dataframe, cut to the specified columns.
55 """
56 if 'columns' in parameters:
57 _columns = parameters['columns']
59 return self.df[_columns]
60 else:
61 return self.df.copy()
64class TestFinalizeCharacterizationTask(FinalizeCharacterizationTask):
65 """A derived class which skips the initialization routines.
66 """
67 __test__ = False # Stop Pytest from trying to parse as a TestCase
69 def __init__(self, **kwargs):
70 pipeBase.PipelineTask.__init__(self, **kwargs)
72 self.makeSubtask('reserve_selection')
75class FinalizeCharacterizationTestCase(lsst.utils.tests.TestCase):
76 """Tests of some functionality of FinalizeCharacterizationTask.
78 Full testing comes from integration tests such as ci_hsc and ci_imsim.
80 These tests bypass the middleware used for accessing data and
81 managing Task execution.
82 """
83 def setUp(self):
84 config = FinalizeCharacterizationConfig()
86 self.finalizeCharacterizationTask = TestFinalizeCharacterizationTask(
87 config=config,
88 )
90 self.isolated_star_cat_dict, self.isolated_star_source_dict = self._make_isocats()
92 def _make_isocats(self):
93 """Make test isolated star catalogs.
95 Returns
96 -------
97 isolated_star_cat_dict : `dict`
98 Per-"tract" dict of isolated star catalogs.
99 isolate_star_source_dict : `dict`
100 Per-"tract" dict of isolated source catalogs.
101 """
102 dtype_cat = [('isolated_star_id', 'i8'),
103 ('ra', 'f8'),
104 ('decl', 'f8'),
105 ('primary_band', 'U2'),
106 ('source_cat_index', 'i4'),
107 ('nsource', 'i4'),
108 ('source_cat_index_i', 'i4'),
109 ('nsource_i', 'i4'),
110 ('source_cat_index_r', 'i4'),
111 ('nsource_r', 'i4'),
112 ('source_cat_index_z', 'i4'),
113 ('nsource_z', 'i4')]
115 dtype_source = [('sourceId', 'i8'),
116 ('obj_index', 'i4')]
118 isolated_star_cat_dict = {}
119 isolated_star_source_dict = {}
121 np.random.seed(12345)
123 # There are 90 stars in both r, i. 10 individually in each.
124 nstar = 110
125 nsource_per_band_per_star = 2
126 self.nstar_total = nstar
127 self.nstar_per_band = nstar - 10
129 # This is a brute-force assembly of a star catalog and matched sources.
130 for tract in [0, 1, 2]:
131 ra = np.random.uniform(low=tract, high=tract + 1.0, size=nstar)
132 dec = np.random.uniform(low=0.0, high=1.0, size=nstar)
134 cat = np.zeros(nstar, dtype=dtype_cat)
135 cat['isolated_star_id'] = tract*nstar + np.arange(nstar)
136 cat['ra'] = ra
137 cat['decl'] = dec
138 if tract < 2:
139 cat['primary_band'][0: 100] = 'i'
140 cat['primary_band'][100:] = 'r'
141 else:
142 # Tract 2 only has z band.
143 cat['primary_band'][:] = 'z'
145 source_cats = []
146 counter = 0
147 for i in range(cat.size):
148 cat['source_cat_index'][i] = counter
149 if tract < 2:
150 if i < 90:
151 cat['nsource'][i] = 2*nsource_per_band_per_star
152 bands = ['r', 'i']
153 else:
154 cat['nsource'][i] = nsource_per_band_per_star
155 if i < 100:
156 bands = ['i']
157 else:
158 bands = ['r']
159 else:
160 cat['nsource'][i] = nsource_per_band_per_star
161 bands = ['z']
163 for band in bands:
164 cat[f'source_cat_index_{band}'][i] = counter
165 cat[f'nsource_{band}'][i] = nsource_per_band_per_star
166 source_cat = np.zeros(nsource_per_band_per_star, dtype=dtype_source)
167 source_cat['sourceId'] = np.arange(
168 tract*nstar + counter,
169 tract*nstar + counter + nsource_per_band_per_star
170 )
171 source_cat['obj_index'] = i
173 source_cats.append(source_cat)
175 counter += nsource_per_band_per_star
177 source_cat = np.concatenate(source_cats)
179 isolated_star_cat_dict[tract] = MockDataFrameReference(pd.DataFrame(cat))
180 isolated_star_source_dict[tract] = MockDataFrameReference(pd.DataFrame(source_cat))
182 return isolated_star_cat_dict, isolated_star_source_dict
184 def test_concat_isolated_star_cats(self):
185 """Test concatenation and reservation of the isolated star catalogs.
186 """
188 for band in ['r', 'i']:
189 iso, iso_src = self.finalizeCharacterizationTask.concat_isolated_star_cats(
190 band,
191 self.isolated_star_cat_dict,
192 self.isolated_star_source_dict
193 )
195 # There are two tracts, so double everything.
196 self.assertEqual(len(iso), 2*self.nstar_per_band)
198 reserve_fraction = self.finalizeCharacterizationTask.config.reserve_selection.reserve_fraction
199 self.assertEqual(np.sum(iso['reserved']),
200 int(reserve_fraction*len(iso)))
202 # 2 tracts, 4 observations per tract per star, minus 2*10 not in the given band.
203 self.assertEqual(len(iso_src), 2*(4*len(iso)//2 - 20))
205 # Check that every star is properly matched to the sources.
206 for i in range(len(iso)):
207 np.testing.assert_array_equal(
208 iso_src['obj_index'][iso[f'source_cat_index_{band}'][i]:
209 iso[f'source_cat_index_{band}'][i] + iso[f'nsource_{band}'][i]],
210 i
211 )
213 # Check that every reserved star is marked as a reserved source.
214 res_star, = np.where(iso['reserved'])
215 for i in res_star:
216 np.testing.assert_array_equal(
217 iso_src['reserved'][iso[f'source_cat_index_{band}'][i]:
218 iso[f'source_cat_index_{band}'][i] + iso[f'nsource_{band}'][i]],
219 True
220 )
222 # Check that every reserved source is marked as a reserved star.
223 res_src, = np.where(iso_src['reserved'])
224 np.testing.assert_array_equal(
225 iso['reserved'][iso_src['obj_index'][res_src]],
226 True
227 )
229 def test_concat_isolate_star_cats_no_sources(self):
230 """Test concatenation when there are no sources in a tract."""
231 iso, iso_src = self.finalizeCharacterizationTask.concat_isolated_star_cats(
232 'z',
233 self.isolated_star_cat_dict,
234 self.isolated_star_source_dict
235 )
237 self.assertGreater(len(iso), 0)
240class MyMemoryTestCase(lsst.utils.tests.MemoryTestCase):
241 pass
244def setup_module(module):
245 lsst.utils.tests.init()
248if __name__ == "__main__": 248 ↛ 249line 248 didn't jump to line 249, because the condition on line 248 was never true
249 lsst.utils.tests.init()
250 unittest.main()