Coverage for tests/qg_test_utils.py: 60%
62 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-26 09:15 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-26 09:15 +0000
1# This file is part of ctrl_bps.
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/>.
21"""QuantumGraph-related utilities to support ctrl_bps testing.
22"""
24# Not actually running Quantum so do not need to override 'run' Method
25# pylint: disable=abstract-method
27# Many dummy classes for testing.
28# pylint: disable=missing-class-docstring
30import lsst.pipe.base.connectionTypes as cT
31from lsst.daf.butler import Config, DataCoordinate, DatasetRef, DatasetType, DimensionUniverse, Quantum
32from lsst.pex.config import Field
33from lsst.pipe.base import PipelineTask, PipelineTaskConfig, PipelineTaskConnections, QuantumGraph, TaskDef
34from lsst.utils.introspection import get_full_type_name
36METADATA = {"D1": [1, 2, 3]}
39# For each dummy task, create a Connections, Config, and PipelineTask
42class Dummy1Connections(PipelineTaskConnections, dimensions=("D1", "D2")):
43 initOutput = cT.InitOutput(name="Dummy1InitOutput", storageClass="ExposureF", doc="n/a")
44 input = cT.Input(name="Dummy1Input", storageClass="ExposureF", doc="n/a", dimensions=("D1", "D2"))
45 output = cT.Output(name="Dummy1Output", storageClass="ExposureF", doc="n/a", dimensions=("D1", "D2"))
48class Dummy1Config(PipelineTaskConfig, pipelineConnections=Dummy1Connections):
49 conf1 = Field(dtype=int, default=1, doc="dummy config")
52class Dummy1PipelineTask(PipelineTask):
53 ConfigClass = Dummy1Config
56class Dummy2Connections(PipelineTaskConnections, dimensions=("D1", "D2")):
57 initInput = cT.InitInput(name="Dummy1InitOutput", storageClass="ExposureF", doc="n/a")
58 initOutput = cT.InitOutput(name="Dummy2InitOutput", storageClass="ExposureF", doc="n/a")
59 input = cT.Input(name="Dummy1Output", storageClass="ExposureF", doc="n/a", dimensions=("D1", "D2"))
60 output = cT.Output(name="Dummy2Output", storageClass="ExposureF", doc="n/a", dimensions=("D1", "D2"))
63class Dummy2Config(PipelineTaskConfig, pipelineConnections=Dummy2Connections):
64 conf1 = Field(dtype=int, default=1, doc="dummy config")
67class Dummy2PipelineTask(PipelineTask):
68 ConfigClass = Dummy2Config
71class Dummy3Connections(PipelineTaskConnections, dimensions=("D1", "D2")):
72 initInput = cT.InitInput(name="Dummy2InitOutput", storageClass="ExposureF", doc="n/a")
73 initOutput = cT.InitOutput(name="Dummy3InitOutput", storageClass="ExposureF", doc="n/a")
74 input = cT.Input(name="Dummy2Output", storageClass="ExposureF", doc="n/a", dimensions=("D1", "D2"))
75 output = cT.Output(name="Dummy3Output", storageClass="ExposureF", doc="n/a", dimensions=("D1", "D2"))
78class Dummy3Config(PipelineTaskConfig, pipelineConnections=Dummy3Connections):
79 conf1 = Field(dtype=int, default=1, doc="dummy config")
82class Dummy3PipelineTask(PipelineTask):
83 ConfigClass = Dummy3Config
86# Test if a Task that does not interact with the other Tasks works fine in
87# the graph.
88class Dummy4Connections(PipelineTaskConnections, dimensions=("D1", "D2")):
89 input = cT.Input(name="Dummy4Input", storageClass="ExposureF", doc="n/a", dimensions=("D1", "D2"))
90 output = cT.Output(name="Dummy4Output", storageClass="ExposureF", doc="n/a", dimensions=("D1", "D2"))
93class Dummy4Config(PipelineTaskConfig, pipelineConnections=Dummy4Connections):
94 conf1 = Field(dtype=int, default=1, doc="dummy config")
97class Dummy4PipelineTask(PipelineTask):
98 ConfigClass = Dummy4Config
101def make_test_quantum_graph():
102 """Create a QuantumGraph for unit tests.
104 Returns
105 -------
106 qgraph : `lsst.pipe.base.QuantumGraph`
107 A test QuantumGraph looking like the following:
108 (DummyTask4 is completely independent.)
110 Numbers in parens are the values for the two dimensions (D1, D2).
112 T1(1,2) T1(3,4) T4(1,2) T4(3,4)
113 | |
114 T2(1,2) T2(3,4)
115 | |
116 T3(1,2) T3(3,4)
117 """
118 config = Config(
119 {
120 "version": 1,
121 "skypix": {
122 "common": "htm7",
123 "htm": {
124 "class": "lsst.sphgeom.HtmPixelization",
125 "max_level": 24,
126 },
127 },
128 "elements": {
129 "D1": {
130 "keys": [
131 {
132 "name": "id",
133 "type": "int",
134 }
135 ],
136 "storage": {
137 "cls": "lsst.daf.butler.registry.dimensions.table.TableDimensionRecordStorage",
138 },
139 },
140 "D2": {
141 "keys": [
142 {
143 "name": "id",
144 "type": "int",
145 }
146 ],
147 "storage": {
148 "cls": "lsst.daf.butler.registry.dimensions.table.TableDimensionRecordStorage",
149 },
150 },
151 },
152 "packers": {},
153 }
154 )
156 universe = DimensionUniverse(config=config)
157 # need to make a mapping of TaskDef to set of quantum
158 quantum_map = {}
159 tasks = []
160 for task, label in (
161 (Dummy1PipelineTask, "T1"),
162 (Dummy2PipelineTask, "T2"),
163 (Dummy3PipelineTask, "T3"),
164 (Dummy4PipelineTask, "T4"),
165 ):
166 task_def = TaskDef(get_full_type_name(task), task.ConfigClass(), task, label)
167 tasks.append(task_def)
168 quantum_set = set()
169 for dim1, dim2 in ((1, 2), (3, 4)):
170 if task_def.connections.initInputs:
171 init_init_ds_type = DatasetType(
172 task_def.connections.initInput.name,
173 tuple(),
174 storageClass=task_def.connections.initInput.storageClass,
175 universe=universe,
176 )
177 init_refs = [DatasetRef(init_init_ds_type, DataCoordinate.makeEmpty(universe))]
178 else:
179 init_refs = None
180 input_ds_type = DatasetType(
181 task_def.connections.input.name,
182 task_def.connections.input.dimensions,
183 storageClass=task_def.connections.input.storageClass,
184 universe=universe,
185 )
186 input_refs = [
187 DatasetRef(
188 input_ds_type, DataCoordinate.standardize({"D1": dim1, "D2": dim2}, universe=universe)
189 )
190 ]
191 output_ds_type = DatasetType(
192 task_def.connections.output.name,
193 task_def.connections.output.dimensions,
194 storageClass=task_def.connections.output.storageClass,
195 universe=universe,
196 )
197 output_refs = [
198 DatasetRef(
199 output_ds_type, DataCoordinate.standardize({"D1": dim1, "D2": dim2}, universe=universe)
200 )
201 ]
202 quantum_set.add(
203 Quantum(
204 taskName=task.__qualname__,
205 dataId=DataCoordinate.standardize({"D1": dim1, "D2": dim2}, universe=universe),
206 taskClass=task,
207 initInputs=init_refs,
208 inputs={input_ds_type: input_refs},
209 outputs={output_ds_type: output_refs},
210 )
211 )
212 quantum_map[task_def] = quantum_set
213 qgraph = QuantumGraph(quantum_map, metadata=METADATA)
215 return qgraph