Coverage for tests/test_id_generator.py: 28%
59 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-03-30 03:03 -0700
« prev ^ index » next coverage.py v7.4.4, created at 2024-03-30 03:03 -0700
1# This file is part of meas_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 unittest
23from typing import Callable
25from lsst.pex.config import Config
26from lsst.afw.table import SourceTable
27from lsst.daf.butler import DimensionUniverse, DataCoordinate
28from lsst.meas.base import (
29 IdGenerator,
30 DetectorVisitIdGeneratorConfig,
31 DetectorExposureIdGeneratorConfig,
32 SkyMapIdGeneratorConfig,
33)
36class _TestConfig(Config):
37 skymap = SkyMapIdGeneratorConfig.make_field()
38 visit = DetectorVisitIdGeneratorConfig.make_field()
39 exposure = DetectorExposureIdGeneratorConfig.make_field()
42class IdGeneratorTestCase(unittest.TestCase):
43 """Tests for the IdGenerator class and its config-based construction
44 pattern.
45 """
47 def setUp(self):
48 self.schema = SourceTable.makeMinimalSchema()
49 self.universe = DimensionUniverse()
51 def test_no_packer(self):
52 """Test a simple IdGenerator that doesn't embed anything."""
53 id_gen = IdGenerator()
54 self.check_invariants(id_gen)
56 def test_visit(self):
57 """Test an IdGenerator that packs {visit, detector} data IDs."""
58 data_id = DataCoordinate.standardize(
59 instrument="I",
60 visit=312,
61 detector=5,
62 universe=self.universe,
63 )
64 config = _TestConfig()
65 config.visit.packer.name = "observation"
66 config.visit.packer["observation"].n_observations = 10000
67 config.visit.packer["observation"].n_detectors = 99
68 config.visit.n_releases = 8
69 config.visit.release_id = 2
70 id_generator = config.visit.apply(data_id)
71 self.check_invariants(
72 id_generator,
73 unpacker=IdGenerator.unpacker_from_config(
74 config.visit, data_id.subset(self.universe.conform(["instrument"]))
75 ),
76 expected_release_id=2,
77 )
79 def test_exposure(self):
80 """Test an IdGenerator that packs {exposure, detector} data IDs."""
81 data_id = DataCoordinate.standardize(
82 instrument="I",
83 exposure=312,
84 detector=5,
85 universe=self.universe,
86 )
87 config = _TestConfig()
88 config.exposure.packer.name = "observation"
89 config.exposure.packer["observation"].n_observations = 10000
90 config.exposure.packer["observation"].n_detectors = 99
91 config.exposure.n_releases = 4
92 config.exposure.release_id = 3
93 id_generator = config.exposure.apply(data_id)
94 self.check_invariants(
95 id_generator,
96 unpacker=IdGenerator.unpacker_from_config(
97 config.exposure, data_id.subset(self.universe.conform(["instrument"]))
98 ),
99 expected_release_id=3,
100 )
102 def test_skymap(self):
103 """Test an IdGenerator that packs {tract, patch, band} data IDs."""
104 config = _TestConfig()
105 config.skymap.packer.n_tracts = 11
106 config.skymap.packer.n_patches = 9
107 data_id = DataCoordinate.standardize(
108 skymap="S", tract=9, patch=5, band="r", universe=self.universe
109 )
110 id_generator = config.skymap.apply(data_id)
111 self.check_invariants(
112 id_generator,
113 unpacker=IdGenerator.unpacker_from_config(
114 config.skymap, data_id.subset(self.universe.conform(["skymap"]))
115 ),
116 )
118 def check_invariants(
119 self,
120 id_gen: IdGenerator,
121 unpacker: Callable[[int], tuple[DataCoordinate, int]] | None = None,
122 expected_release_id: int = 0,
123 ):
124 """Check methods of the `IdGenerator` class for self-consistency and
125 expected values.
126 """
127 catalog = id_gen.make_source_catalog(self.schema)
128 for _ in range(5):
129 catalog.addNew()
130 array = id_gen.arange(1, 6)
131 self.assertEqual(list(catalog["id"]), list(array))
132 if unpacker is not None:
133 expected_data_id = id_gen.data_id
134 for i in range(5):
135 embedded_release_id, embedded_data_id, counter = unpacker(array[i])
136 self.assertEqual(counter, i + 1)
137 self.assertEqual(embedded_data_id, expected_data_id)
138 self.assertEqual(embedded_release_id, expected_release_id)
141if __name__ == "__main__": 141 ↛ 142line 141 didn't jump to line 142, because the condition on line 141 was never true
142 unittest.main()