Coverage for tests/test_graphBuilder.py: 14%
80 statements
« prev ^ index » next coverage.py v6.4.4, created at 2022-08-23 02:31 -0700
« prev ^ index » next coverage.py v6.4.4, created at 2022-08-23 02:31 -0700
1# This file is part of pipe_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/>.
22"""Tests of things related to the GraphBuilder class."""
24import io
25import logging
26import unittest
28import lsst.utils.tests
29from lsst.daf.butler.registry import UserExpressionError
30from lsst.pipe.base import QuantumGraph
31from lsst.pipe.base.graphBuilder import DatasetQueryConstraintVariant
32from lsst.pipe.base.tests import simpleQGraph
33from lsst.utils.tests import temporaryDirectory
35_LOG = logging.getLogger(__name__)
38class GraphBuilderTestCase(unittest.TestCase):
39 def testDefault(self):
40 """Simple test to verify makeSimpleQGraph can be used to make a Quantum
41 Graph."""
42 with temporaryDirectory() as root:
43 # makeSimpleQGraph calls GraphBuilder.
44 butler, qgraph = simpleQGraph.makeSimpleQGraph(root=root)
45 # by default makeSimpleQGraph makes a graph with 5 nodes
46 self.assertEqual(len(qgraph), 5)
47 constraint = DatasetQueryConstraintVariant.OFF
48 _, qgraph2 = simpleQGraph.makeSimpleQGraph(
49 butler=butler, datasetQueryConstraint=constraint, callPopulateButler=False
50 )
51 self.assertEqual(len(qgraph2), 5)
52 self.assertEqual(qgraph, qgraph2)
53 constraint = DatasetQueryConstraintVariant.fromExpression("add_dataset0")
54 _, qgraph3 = simpleQGraph.makeSimpleQGraph(
55 butler=butler, datasetQueryConstraint=constraint, callPopulateButler=False
56 )
57 self.assertEqual(qgraph2, qgraph3)
59 def testAddInstrumentMismatch(self):
60 """Verify that a RuntimeError is raised if the instrument in the user
61 query does not match the instrument in the pipeline."""
62 with temporaryDirectory() as root:
63 pipeline = simpleQGraph.makeSimplePipeline(
64 nQuanta=5, instrument="lsst.pipe.base.tests.simpleQGraph.SimpleInstrument"
65 )
66 with self.assertRaises(UserExpressionError):
67 simpleQGraph.makeSimpleQGraph(root=root, pipeline=pipeline, userQuery="instrument = 'foo'")
69 def test_datastore_records(self):
70 """Test for generating datastore records."""
71 with temporaryDirectory() as root:
72 # need FileDatastore for this tests
73 butler, qgraph1 = simpleQGraph.makeSimpleQGraph(
74 root=root, inMemory=False, makeDatastoreRecords=True
75 )
77 # save and reload
78 buffer = io.BytesIO()
79 qgraph1.save(buffer)
80 buffer.seek(0)
81 qgraph2 = QuantumGraph.load(buffer, universe=butler.dimensions)
82 del buffer
84 for qgraph in (qgraph1, qgraph2):
85 self.assertEqual(len(qgraph), 5)
86 for i, qnode in enumerate(qgraph):
87 quantum = qnode.quantum
88 self.assertIsNotNone(quantum.datastore_records)
89 # only the first quantum has a pre-existing input
90 if i == 0:
91 datastore_name = "FileDatastore@<butlerRoot>"
92 self.assertEqual(set(quantum.datastore_records.keys()), {datastore_name})
93 records_data = quantum.datastore_records[datastore_name]
94 records = dict(records_data.records)
95 self.assertEqual(len(records), 1)
96 _, records = records.popitem()
97 records = records["file_datastore_records"]
98 self.assertEqual(
99 [record.path for record in records],
100 ["test/add_dataset0/add_dataset0_INSTR_det0_test.pickle"],
101 )
102 else:
103 self.assertEqual(quantum.datastore_records, {})
105 def testResolveRefs(self):
106 """Test for GraphBuilder with resolveRefs=True."""
108 with temporaryDirectory() as root:
109 # Make a regular graph, only inputs are resolved.
110 _, qgraph = simpleQGraph.makeSimpleQGraph(root=root)
111 self.assertEqual(len(qgraph), 5)
112 for node in qgraph:
113 quantum = node.quantum
114 for datasetType, refs in quantum.inputs.items():
115 if datasetType.name == "add_dataset0":
116 self.assertTrue(all(ref.id is not None for ref in refs))
117 else:
118 self.assertTrue(all(ref.id is None for ref in refs))
119 for datasetType, refs in quantum.outputs.items():
120 self.assertTrue(all(ref.id is None for ref in refs))
122 with temporaryDirectory() as root:
123 # Make a resolved graph, all refs should be resolved.
124 _, qgraph = simpleQGraph.makeSimpleQGraph(root=root, resolveRefs=True)
125 self.assertEqual(len(qgraph), 5)
126 for node in qgraph:
127 quantum = node.quantum
128 for datasetType, refs in quantum.inputs.items():
129 self.assertTrue(all(ref.id is not None for ref in refs))
130 for datasetType, refs in quantum.outputs.items():
131 self.assertTrue(all(ref.id is not None for ref in refs))
132 for taskDef in qgraph.iterTaskGraph():
133 if (refs := qgraph.initInputRefs(taskDef)) is not None:
134 self.assertTrue(all(ref.id is not None for ref in refs))
135 if (refs := qgraph.initOutputRefs(taskDef)) is not None:
136 self.assertTrue(all(ref.id is not None for ref in refs))
139if __name__ == "__main__": 139 ↛ 140line 139 didn't jump to line 140, because the condition on line 139 was never true
140 lsst.utils.tests.init()
141 unittest.main()