lsst-ctrl-mpexec 29.2025.2400__py3-none-any.whl → 29.2025.3200__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lsst/ctrl/mpexec/__init__.py +1 -2
- lsst/ctrl/mpexec/cli/butler_factory.py +464 -0
- lsst/ctrl/mpexec/cli/cmd/commands.py +7 -1
- lsst/ctrl/mpexec/cli/opt/optionGroups.py +0 -13
- lsst/ctrl/mpexec/cli/opt/options.py +0 -46
- lsst/ctrl/mpexec/cli/script/build.py +49 -36
- lsst/ctrl/mpexec/cli/script/pre_exec_init_qbb.py +3 -1
- lsst/ctrl/mpexec/cli/script/qgraph.py +0 -25
- lsst/ctrl/mpexec/cli/script/run.py +2 -1
- lsst/ctrl/mpexec/cli/script/run_qbb.py +2 -1
- lsst/ctrl/mpexec/cmdLineFwk.py +30 -556
- lsst/ctrl/mpexec/execFixupDataId.py +9 -101
- lsst/ctrl/mpexec/executionGraphFixup.py +12 -37
- lsst/ctrl/mpexec/log_capture.py +9 -195
- lsst/ctrl/mpexec/mpGraphExecutor.py +60 -696
- lsst/ctrl/mpexec/quantumGraphExecutor.py +20 -90
- lsst/ctrl/mpexec/reports.py +30 -206
- lsst/ctrl/mpexec/separablePipelineExecutor.py +12 -263
- lsst/ctrl/mpexec/showInfo.py +2 -2
- lsst/ctrl/mpexec/simple_pipeline_executor.py +11 -590
- lsst/ctrl/mpexec/singleQuantumExecutor.py +75 -532
- lsst/ctrl/mpexec/taskFactory.py +12 -38
- lsst/ctrl/mpexec/version.py +1 -1
- {lsst_ctrl_mpexec-29.2025.2400.dist-info → lsst_ctrl_mpexec-29.2025.3200.dist-info}/METADATA +1 -1
- lsst_ctrl_mpexec-29.2025.3200.dist-info/RECORD +51 -0
- lsst/ctrl/mpexec/dotTools.py +0 -100
- lsst_ctrl_mpexec-29.2025.2400.dist-info/RECORD +0 -51
- {lsst_ctrl_mpexec-29.2025.2400.dist-info → lsst_ctrl_mpexec-29.2025.3200.dist-info}/WHEEL +0 -0
- {lsst_ctrl_mpexec-29.2025.2400.dist-info → lsst_ctrl_mpexec-29.2025.3200.dist-info}/entry_points.txt +0 -0
- {lsst_ctrl_mpexec-29.2025.2400.dist-info → lsst_ctrl_mpexec-29.2025.3200.dist-info}/licenses/COPYRIGHT +0 -0
- {lsst_ctrl_mpexec-29.2025.2400.dist-info → lsst_ctrl_mpexec-29.2025.3200.dist-info}/licenses/LICENSE +0 -0
- {lsst_ctrl_mpexec-29.2025.2400.dist-info → lsst_ctrl_mpexec-29.2025.3200.dist-info}/licenses/bsd_license.txt +0 -0
- {lsst_ctrl_mpexec-29.2025.2400.dist-info → lsst_ctrl_mpexec-29.2025.3200.dist-info}/licenses/gpl-v3.0.txt +0 -0
- {lsst_ctrl_mpexec-29.2025.2400.dist-info → lsst_ctrl_mpexec-29.2025.3200.dist-info}/top_level.txt +0 -0
- {lsst_ctrl_mpexec-29.2025.2400.dist-info → lsst_ctrl_mpexec-29.2025.3200.dist-info}/zip-safe +0 -0
|
@@ -25,599 +25,20 @@
|
|
|
25
25
|
# You should have received a copy of the GNU General Public License
|
|
26
26
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
27
27
|
|
|
28
|
-
from __future__ import annotations
|
|
29
|
-
|
|
30
28
|
__all__ = ("SimplePipelineExecutor",)
|
|
31
29
|
|
|
32
|
-
import
|
|
33
|
-
import getpass
|
|
34
|
-
import os
|
|
35
|
-
from collections.abc import Iterable, Iterator, Mapping
|
|
36
|
-
from typing import Any
|
|
37
|
-
|
|
38
|
-
from lsst.daf.butler import Butler, CollectionType, DataCoordinate, DatasetRef, Quantum
|
|
39
|
-
from lsst.pex.config import Config
|
|
40
|
-
from lsst.pipe.base import ExecutionResources, Instrument, Pipeline, PipelineGraph, PipelineTask, QuantumGraph
|
|
41
|
-
from lsst.pipe.base.all_dimensions_quantum_graph_builder import AllDimensionsQuantumGraphBuilder
|
|
42
|
-
|
|
43
|
-
from .preExecInit import PreExecInit
|
|
44
|
-
from .singleQuantumExecutor import SingleQuantumExecutor
|
|
45
|
-
from .taskFactory import TaskFactory
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class SimplePipelineExecutor:
|
|
49
|
-
"""A simple, high-level executor for pipelines.
|
|
50
|
-
|
|
51
|
-
Parameters
|
|
52
|
-
----------
|
|
53
|
-
quantum_graph : `~lsst.pipe.base.QuantumGraph`
|
|
54
|
-
Graph to be executed.
|
|
55
|
-
butler : `~lsst.daf.butler.Butler`
|
|
56
|
-
Object that manages all I/O. Must be initialized with `collections`
|
|
57
|
-
and `run` properties that correspond to the input and output
|
|
58
|
-
collections, which must be consistent with those used to create
|
|
59
|
-
``quantum_graph``.
|
|
60
|
-
resources : `~lsst.pipe.base.ExecutionResources`
|
|
61
|
-
The resources available to each quantum being executed.
|
|
62
|
-
raise_on_partial_outputs : `bool`, optional
|
|
63
|
-
If `True` raise exceptions chained by
|
|
64
|
-
`lsst.pipe.base.AnnotatedPartialOutputError` immediately, instead of
|
|
65
|
-
considering the partial result a success and continuing to run
|
|
66
|
-
downstream tasks.
|
|
67
|
-
|
|
68
|
-
Notes
|
|
69
|
-
-----
|
|
70
|
-
Most callers should use one of the `classmethod` factory functions
|
|
71
|
-
(`from_pipeline_filename`, `from_task_class`, `from_pipeline`) instead of
|
|
72
|
-
invoking the constructor directly; these guarantee that the
|
|
73
|
-
`~lsst.daf.butler.Butler` and `~lsst.pipe.base.QuantumGraph` are created
|
|
74
|
-
consistently.
|
|
75
|
-
|
|
76
|
-
This class is intended primarily to support unit testing and small-scale
|
|
77
|
-
integration testing of `~lsst.pipe.base.PipelineTask` classes. It
|
|
78
|
-
deliberately lacks many features present in the command-line-only
|
|
79
|
-
``pipetask`` tool in order to keep the implementation simple. Python
|
|
80
|
-
callers that need more sophistication should call lower-level tools like
|
|
81
|
-
`~lsst.pipe.base.quantum_graph_builder.QuantumGraphBuilder`, `PreExecInit`,
|
|
82
|
-
and `SingleQuantumExecutor` directly.
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
def __init__(
|
|
86
|
-
self,
|
|
87
|
-
quantum_graph: QuantumGraph,
|
|
88
|
-
butler: Butler,
|
|
89
|
-
resources: ExecutionResources | None = None,
|
|
90
|
-
raise_on_partial_outputs: bool = True,
|
|
91
|
-
):
|
|
92
|
-
self.quantum_graph = quantum_graph
|
|
93
|
-
self.butler = butler
|
|
94
|
-
self.resources = resources
|
|
95
|
-
self.raise_on_partial_outputs = raise_on_partial_outputs
|
|
96
|
-
|
|
97
|
-
@classmethod
|
|
98
|
-
def prep_butler(
|
|
99
|
-
cls,
|
|
100
|
-
root: str,
|
|
101
|
-
inputs: Iterable[str],
|
|
102
|
-
output: str,
|
|
103
|
-
output_run: str | None = None,
|
|
104
|
-
) -> Butler:
|
|
105
|
-
"""Return configured `~lsst.daf.butler.Butler`.
|
|
106
|
-
|
|
107
|
-
Helper method for creating `~lsst.daf.butler.Butler` instances with
|
|
108
|
-
collections appropriate for processing.
|
|
109
|
-
|
|
110
|
-
Parameters
|
|
111
|
-
----------
|
|
112
|
-
root : `str`
|
|
113
|
-
Root of the butler data repository; must already exist, with all
|
|
114
|
-
necessary input data.
|
|
115
|
-
inputs : `~collections.abc.Iterable` [ `str` ]
|
|
116
|
-
Collections to search for all input datasets, in search order.
|
|
117
|
-
output : `str`
|
|
118
|
-
Name of a new output `~lsst.daf.butler.CollectionType.CHAINED`
|
|
119
|
-
collection to create that will combine both inputs and outputs.
|
|
120
|
-
output_run : `str`, optional
|
|
121
|
-
Name of the output `~lsst.daf.butler.CollectionType.RUN` that will
|
|
122
|
-
directly hold all output datasets. If not provided, a name will
|
|
123
|
-
be created from ``output`` and a timestamp.
|
|
124
|
-
|
|
125
|
-
Returns
|
|
126
|
-
-------
|
|
127
|
-
butler : `~lsst.daf.butler.Butler`
|
|
128
|
-
Butler client instance compatible with all `classmethod` factories.
|
|
129
|
-
Always writeable.
|
|
130
|
-
"""
|
|
131
|
-
if output_run is None:
|
|
132
|
-
output_run = f"{output}/{Instrument.makeCollectionTimestamp()}"
|
|
133
|
-
# Make initial butler with no collections, since we haven't created
|
|
134
|
-
# them yet.
|
|
135
|
-
butler = Butler.from_config(root, writeable=True)
|
|
136
|
-
butler.registry.registerCollection(output_run, CollectionType.RUN)
|
|
137
|
-
butler.registry.registerCollection(output, CollectionType.CHAINED)
|
|
138
|
-
collections = [output_run]
|
|
139
|
-
collections.extend(inputs)
|
|
140
|
-
butler.registry.setCollectionChain(output, collections)
|
|
141
|
-
# Remake butler to let it infer default data IDs from collections, now
|
|
142
|
-
# that those collections exist.
|
|
143
|
-
return Butler.from_config(butler=butler, collections=[output], run=output_run)
|
|
144
|
-
|
|
145
|
-
@classmethod
|
|
146
|
-
def from_pipeline_filename(
|
|
147
|
-
cls,
|
|
148
|
-
pipeline_filename: str,
|
|
149
|
-
*,
|
|
150
|
-
where: str = "",
|
|
151
|
-
bind: Mapping[str, Any] | None = None,
|
|
152
|
-
butler: Butler,
|
|
153
|
-
resources: ExecutionResources | None = None,
|
|
154
|
-
raise_on_partial_outputs: bool = True,
|
|
155
|
-
attach_datastore_records: bool = False,
|
|
156
|
-
output: str | None = None,
|
|
157
|
-
output_run: str | None = None,
|
|
158
|
-
) -> SimplePipelineExecutor:
|
|
159
|
-
"""Create an executor by building a QuantumGraph from an on-disk
|
|
160
|
-
pipeline YAML file.
|
|
161
|
-
|
|
162
|
-
Parameters
|
|
163
|
-
----------
|
|
164
|
-
pipeline_filename : `str`
|
|
165
|
-
Name of the YAML file to load the pipeline definition from.
|
|
166
|
-
where : `str`, optional
|
|
167
|
-
Data ID query expression that constraints the quanta generated.
|
|
168
|
-
bind : `~collections.abc.Mapping`, optional
|
|
169
|
-
Mapping containing literal values that should be injected into the
|
|
170
|
-
``where`` expression, keyed by the identifiers they replace.
|
|
171
|
-
butler : `~lsst.daf.butler.Butler`
|
|
172
|
-
Butler that manages all I/O. `prep_butler` can be used to create
|
|
173
|
-
one.
|
|
174
|
-
resources : `~lsst.pipe.base.ExecutionResources`
|
|
175
|
-
The resources available to each quantum being executed.
|
|
176
|
-
raise_on_partial_outputs : `bool`, optional
|
|
177
|
-
If `True` raise exceptions chained by
|
|
178
|
-
`lsst.pipe.base.AnnotatedPartialOutputError` immediately, instead
|
|
179
|
-
of considering the partial result a success and continuing to run
|
|
180
|
-
downstream tasks.
|
|
181
|
-
attach_datastore_records : `bool`, optional
|
|
182
|
-
Whether to attach datastore records to the quantum graph. This is
|
|
183
|
-
usually unnecessary, unless the executor is used to test behavior
|
|
184
|
-
that depends on datastore records.
|
|
185
|
-
output : `str`, optional
|
|
186
|
-
Name of a new output `~lsst.daf.butler.CollectionType.CHAINED`
|
|
187
|
-
collection to create that will combine both inputs and outputs.
|
|
188
|
-
output_run : `str`, optional
|
|
189
|
-
Name of the output `~lsst.daf.butler.CollectionType.RUN` that will
|
|
190
|
-
directly hold all output datasets. If not provided, a name will
|
|
191
|
-
be created from ``output`` and a timestamp.
|
|
192
|
-
|
|
193
|
-
Returns
|
|
194
|
-
-------
|
|
195
|
-
executor : `SimplePipelineExecutor`
|
|
196
|
-
An executor instance containing the constructed
|
|
197
|
-
`~lsst.pipe.base.QuantumGraph` and `~lsst.daf.butler.Butler`, ready
|
|
198
|
-
for `run` to be called.
|
|
199
|
-
"""
|
|
200
|
-
pipeline = Pipeline.fromFile(pipeline_filename)
|
|
201
|
-
return cls.from_pipeline(
|
|
202
|
-
pipeline,
|
|
203
|
-
butler=butler,
|
|
204
|
-
where=where,
|
|
205
|
-
bind=bind,
|
|
206
|
-
resources=resources,
|
|
207
|
-
raise_on_partial_outputs=raise_on_partial_outputs,
|
|
208
|
-
attach_datastore_records=attach_datastore_records,
|
|
209
|
-
output=output,
|
|
210
|
-
output_run=output_run,
|
|
211
|
-
)
|
|
212
|
-
|
|
213
|
-
@classmethod
|
|
214
|
-
def from_task_class(
|
|
215
|
-
cls,
|
|
216
|
-
task_class: type[PipelineTask],
|
|
217
|
-
config: Config | None = None,
|
|
218
|
-
label: str | None = None,
|
|
219
|
-
*,
|
|
220
|
-
where: str = "",
|
|
221
|
-
bind: Mapping[str, Any] | None = None,
|
|
222
|
-
butler: Butler,
|
|
223
|
-
resources: ExecutionResources | None = None,
|
|
224
|
-
raise_on_partial_outputs: bool = True,
|
|
225
|
-
attach_datastore_records: bool = False,
|
|
226
|
-
output: str | None = None,
|
|
227
|
-
output_run: str | None = None,
|
|
228
|
-
) -> SimplePipelineExecutor:
|
|
229
|
-
"""Create an executor by building a QuantumGraph from a pipeline
|
|
230
|
-
containing a single task.
|
|
231
|
-
|
|
232
|
-
Parameters
|
|
233
|
-
----------
|
|
234
|
-
task_class : `type`
|
|
235
|
-
A concrete `~lsst.pipe.base.PipelineTask` subclass.
|
|
236
|
-
config : `~lsst.pex.config.Config`, optional
|
|
237
|
-
Configuration for the task. If not provided, task-level defaults
|
|
238
|
-
will be used (no per-instrument overrides).
|
|
239
|
-
label : `str`, optional
|
|
240
|
-
Label for the task in its pipeline; defaults to
|
|
241
|
-
``task_class._DefaultName``.
|
|
242
|
-
where : `str`, optional
|
|
243
|
-
Data ID query expression that constraints the quanta generated.
|
|
244
|
-
bind : `~collections.abc.Mapping`, optional
|
|
245
|
-
Mapping containing literal values that should be injected into the
|
|
246
|
-
``where`` expression, keyed by the identifiers they replace.
|
|
247
|
-
butler : `~lsst.daf.butler.Butler`
|
|
248
|
-
Butler that manages all I/O. `prep_butler` can be used to create
|
|
249
|
-
one.
|
|
250
|
-
resources : `~lsst.pipe.base.ExecutionResources`
|
|
251
|
-
The resources available to each quantum being executed.
|
|
252
|
-
raise_on_partial_outputs : `bool`, optional
|
|
253
|
-
If `True` raise exceptions chained by
|
|
254
|
-
`lsst.pipe.base.AnnotatedPartialOutputError` immediately, instead
|
|
255
|
-
of considering the partial result a success and continuing to run
|
|
256
|
-
downstream tasks.
|
|
257
|
-
attach_datastore_records : `bool`, optional
|
|
258
|
-
Whether to attach datastore records to the quantum graph. This is
|
|
259
|
-
usually unnecessary, unless the executor is used to test behavior
|
|
260
|
-
that depends on datastore records.
|
|
261
|
-
output : `str`, optional
|
|
262
|
-
Name of a new output `~lsst.daf.butler.CollectionType.CHAINED`
|
|
263
|
-
collection to create that will combine both inputs and outputs.
|
|
264
|
-
output_run : `str`, optional
|
|
265
|
-
Name of the output `~lsst.daf.butler.CollectionType.RUN` that will
|
|
266
|
-
directly hold all output datasets. If not provided, a name will
|
|
267
|
-
be created from ``output`` and a timestamp.
|
|
268
|
-
|
|
269
|
-
Returns
|
|
270
|
-
-------
|
|
271
|
-
executor : `SimplePipelineExecutor`
|
|
272
|
-
An executor instance containing the constructed
|
|
273
|
-
`~lsst.pipe.base.QuantumGraph` and `~lsst.daf.butler.Butler`, ready
|
|
274
|
-
for `run` to be called.
|
|
275
|
-
"""
|
|
276
|
-
if config is None:
|
|
277
|
-
config = task_class.ConfigClass()
|
|
278
|
-
if label is None:
|
|
279
|
-
label = task_class._DefaultName
|
|
280
|
-
if not isinstance(config, task_class.ConfigClass):
|
|
281
|
-
raise TypeError(
|
|
282
|
-
f"Invalid config class type: expected {task_class.ConfigClass.__name__}, "
|
|
283
|
-
f"got {type(config).__name__}."
|
|
284
|
-
)
|
|
285
|
-
pipeline_graph = PipelineGraph()
|
|
286
|
-
pipeline_graph.add_task(label=label, task_class=task_class, config=config)
|
|
287
|
-
return cls.from_pipeline_graph(
|
|
288
|
-
pipeline_graph,
|
|
289
|
-
butler=butler,
|
|
290
|
-
where=where,
|
|
291
|
-
bind=bind,
|
|
292
|
-
resources=resources,
|
|
293
|
-
raise_on_partial_outputs=raise_on_partial_outputs,
|
|
294
|
-
attach_datastore_records=attach_datastore_records,
|
|
295
|
-
output=output,
|
|
296
|
-
output_run=output_run,
|
|
297
|
-
)
|
|
298
|
-
|
|
299
|
-
@classmethod
|
|
300
|
-
def from_pipeline(
|
|
301
|
-
cls,
|
|
302
|
-
pipeline: Pipeline,
|
|
303
|
-
*,
|
|
304
|
-
where: str = "",
|
|
305
|
-
bind: Mapping[str, Any] | None = None,
|
|
306
|
-
butler: Butler,
|
|
307
|
-
resources: ExecutionResources | None = None,
|
|
308
|
-
raise_on_partial_outputs: bool = True,
|
|
309
|
-
attach_datastore_records: bool = False,
|
|
310
|
-
output: str | None = None,
|
|
311
|
-
output_run: str | None = None,
|
|
312
|
-
) -> SimplePipelineExecutor:
|
|
313
|
-
"""Create an executor by building a QuantumGraph from an in-memory
|
|
314
|
-
pipeline.
|
|
315
|
-
|
|
316
|
-
Parameters
|
|
317
|
-
----------
|
|
318
|
-
pipeline : `~lsst.pipe.base.Pipeline` or \
|
|
319
|
-
`~collections.abc.Iterable` [ `~lsst.pipe.base.TaskDef` ]
|
|
320
|
-
A Python object describing the tasks to run, along with their
|
|
321
|
-
labels and configuration.
|
|
322
|
-
where : `str`, optional
|
|
323
|
-
Data ID query expression that constraints the quanta generated.
|
|
324
|
-
bind : `~collections.abc.Mapping`, optional
|
|
325
|
-
Mapping containing literal values that should be injected into the
|
|
326
|
-
``where`` expression, keyed by the identifiers they replace.
|
|
327
|
-
butler : `~lsst.daf.butler.Butler`
|
|
328
|
-
Butler that manages all I/O. `prep_butler` can be used to create
|
|
329
|
-
one.
|
|
330
|
-
resources : `~lsst.pipe.base.ExecutionResources`
|
|
331
|
-
The resources available to each quantum being executed.
|
|
332
|
-
raise_on_partial_outputs : `bool`, optional
|
|
333
|
-
If `True` raise exceptions chained by
|
|
334
|
-
`lsst.pipe.base.AnnotatedPartialOutputError` immediately, instead
|
|
335
|
-
of considering the partial result a success and continuing to run
|
|
336
|
-
downstream tasks.
|
|
337
|
-
attach_datastore_records : `bool`, optional
|
|
338
|
-
Whether to attach datastore records to the quantum graph. This is
|
|
339
|
-
usually unnecessary, unless the executor is used to test behavior
|
|
340
|
-
that depends on datastore records.
|
|
341
|
-
output : `str`, optional
|
|
342
|
-
Name of a new output `~lsst.daf.butler.CollectionType.CHAINED`
|
|
343
|
-
collection to create that will combine both inputs and outputs.
|
|
344
|
-
output_run : `str`, optional
|
|
345
|
-
Name of the output `~lsst.daf.butler.CollectionType.RUN` that will
|
|
346
|
-
directly hold all output datasets. If not provided, a name will
|
|
347
|
-
be created from ``output`` and a timestamp.
|
|
348
|
-
|
|
349
|
-
Returns
|
|
350
|
-
-------
|
|
351
|
-
executor : `SimplePipelineExecutor`
|
|
352
|
-
An executor instance containing the constructed
|
|
353
|
-
`~lsst.pipe.base.QuantumGraph` and `~lsst.daf.butler.Butler`, ready
|
|
354
|
-
for `run` to be called.
|
|
355
|
-
"""
|
|
356
|
-
pipeline_graph = pipeline.to_graph()
|
|
357
|
-
return cls.from_pipeline_graph(
|
|
358
|
-
pipeline_graph,
|
|
359
|
-
where=where,
|
|
360
|
-
bind=bind,
|
|
361
|
-
butler=butler,
|
|
362
|
-
resources=resources,
|
|
363
|
-
raise_on_partial_outputs=raise_on_partial_outputs,
|
|
364
|
-
attach_datastore_records=attach_datastore_records,
|
|
365
|
-
output=output,
|
|
366
|
-
output_run=output_run,
|
|
367
|
-
)
|
|
368
|
-
|
|
369
|
-
@classmethod
|
|
370
|
-
def from_pipeline_graph(
|
|
371
|
-
cls,
|
|
372
|
-
pipeline_graph: PipelineGraph,
|
|
373
|
-
*,
|
|
374
|
-
where: str = "",
|
|
375
|
-
bind: Mapping[str, Any] | None = None,
|
|
376
|
-
butler: Butler,
|
|
377
|
-
resources: ExecutionResources | None = None,
|
|
378
|
-
raise_on_partial_outputs: bool = True,
|
|
379
|
-
attach_datastore_records: bool = False,
|
|
380
|
-
output: str | None = None,
|
|
381
|
-
output_run: str | None = None,
|
|
382
|
-
) -> SimplePipelineExecutor:
|
|
383
|
-
"""Create an executor by building a QuantumGraph from an in-memory
|
|
384
|
-
pipeline graph.
|
|
385
|
-
|
|
386
|
-
Parameters
|
|
387
|
-
----------
|
|
388
|
-
pipeline_graph : `~lsst.pipe.base.PipelineGraph`
|
|
389
|
-
A Python object describing the tasks to run, along with their
|
|
390
|
-
labels and configuration, in graph form. Will be resolved against
|
|
391
|
-
the given ``butler``, with any existing resolutions ignored.
|
|
392
|
-
where : `str`, optional
|
|
393
|
-
Data ID query expression that constraints the quanta generated.
|
|
394
|
-
bind : `~collections.abc.Mapping`, optional
|
|
395
|
-
Mapping containing literal values that should be injected into the
|
|
396
|
-
``where`` expression, keyed by the identifiers they replace.
|
|
397
|
-
butler : `~lsst.daf.butler.Butler`
|
|
398
|
-
Butler that manages all I/O. `prep_butler` can be used to create
|
|
399
|
-
one. Must have its `~Butler.run` and
|
|
400
|
-
`~Butler.collections.defaults` not empty and not `None`.
|
|
401
|
-
resources : `~lsst.pipe.base.ExecutionResources`
|
|
402
|
-
The resources available to each quantum being executed.
|
|
403
|
-
raise_on_partial_outputs : `bool`, optional
|
|
404
|
-
If `True` raise exceptions chained by
|
|
405
|
-
`lsst.pipe.base.AnnotatedPartialOutputError` immediately, instead
|
|
406
|
-
of considering the partial result a success and continuing to run
|
|
407
|
-
downstream tasks.
|
|
408
|
-
attach_datastore_records : `bool`, optional
|
|
409
|
-
Whether to attach datastore records to the quantum graph. This is
|
|
410
|
-
usually unnecessary, unless the executor is used to test behavior
|
|
411
|
-
that depends on datastore records.
|
|
412
|
-
output : `str`, optional
|
|
413
|
-
Name of a new output `~lsst.daf.butler.CollectionType.CHAINED`
|
|
414
|
-
collection to create that will combine both inputs and outputs.
|
|
415
|
-
output_run : `str`, optional
|
|
416
|
-
Name of the output `~lsst.daf.butler.CollectionType.RUN` that will
|
|
417
|
-
directly hold all output datasets. If not provided, a name will
|
|
418
|
-
be created from ``output`` and a timestamp.
|
|
419
|
-
|
|
420
|
-
Returns
|
|
421
|
-
-------
|
|
422
|
-
executor : `SimplePipelineExecutor`
|
|
423
|
-
An executor instance containing the constructed
|
|
424
|
-
`~lsst.pipe.base.QuantumGraph` and `~lsst.daf.butler.Butler`, ready
|
|
425
|
-
for `run` to be called.
|
|
426
|
-
"""
|
|
427
|
-
if output_run is None:
|
|
428
|
-
output_run = butler.run
|
|
429
|
-
if output_run is None:
|
|
430
|
-
if output is None:
|
|
431
|
-
raise TypeError("At least one of output or output_run must be provided.")
|
|
432
|
-
output_run = f"{output}/{Instrument.makeCollectionTimestamp()}"
|
|
433
|
-
|
|
434
|
-
quantum_graph_builder = AllDimensionsQuantumGraphBuilder(
|
|
435
|
-
pipeline_graph, butler, where=where, bind=bind, output_run=output_run
|
|
436
|
-
)
|
|
437
|
-
metadata = {
|
|
438
|
-
"input": list(butler.collections.defaults),
|
|
439
|
-
"output": output,
|
|
440
|
-
"output_run": output_run,
|
|
441
|
-
"skip_existing_in": [],
|
|
442
|
-
"skip_existing": False,
|
|
443
|
-
"data_query": where,
|
|
444
|
-
"user": getpass.getuser(),
|
|
445
|
-
"time": str(datetime.datetime.now()),
|
|
446
|
-
}
|
|
447
|
-
quantum_graph = quantum_graph_builder.build(
|
|
448
|
-
metadata=metadata, attach_datastore_records=attach_datastore_records
|
|
449
|
-
)
|
|
450
|
-
return cls(
|
|
451
|
-
quantum_graph=quantum_graph,
|
|
452
|
-
butler=butler,
|
|
453
|
-
resources=resources,
|
|
454
|
-
raise_on_partial_outputs=raise_on_partial_outputs,
|
|
455
|
-
)
|
|
456
|
-
|
|
457
|
-
def use_local_butler(
|
|
458
|
-
self, root: str, register_dataset_types: bool = True, transfer_dimensions: bool = True
|
|
459
|
-
) -> Butler:
|
|
460
|
-
"""Transfer all inputs to a local data repository. and set the executor
|
|
461
|
-
to write outputs to it.
|
|
462
|
-
|
|
463
|
-
Parameters
|
|
464
|
-
----------
|
|
465
|
-
root : `str`
|
|
466
|
-
Path to the local data repository; created if it does not exist.
|
|
467
|
-
register_dataset_types : `bool`, optional
|
|
468
|
-
Whether to register dataset types in the new repository. If
|
|
469
|
-
`False`, the local data repository must already exist and already
|
|
470
|
-
have all input dataset types registered.
|
|
471
|
-
transfer_dimensions : `bool`, optional
|
|
472
|
-
Whether to transfer dimension records to the new repository. If
|
|
473
|
-
`False`, the local data repository must already exist and already
|
|
474
|
-
have all needed dimension records.
|
|
475
|
-
|
|
476
|
-
Returns
|
|
477
|
-
-------
|
|
478
|
-
butler : `lsst.daf.butler.Butler`
|
|
479
|
-
Writeable butler for local data repository.
|
|
480
|
-
|
|
481
|
-
Notes
|
|
482
|
-
-----
|
|
483
|
-
The input collection structure from the original data repository is not
|
|
484
|
-
preserved by this method (it cannot be reconstructed from the quantum
|
|
485
|
-
graph). Instead, a `~lsst.daf.butler.CollectionType.TAGGED` collection
|
|
486
|
-
is created to gather all inputs, and appended to the output
|
|
487
|
-
`~lsst.daf.butler.CollectionType.CHAINED` collection after the output
|
|
488
|
-
`~lsst.daf.butler.CollectionType.RUN` collection. Calibration inputs
|
|
489
|
-
with the same data ID but multiple validity ranges are *not* included
|
|
490
|
-
in that `~lsst.daf.butler.CollectionType.TAGGED`; they are still
|
|
491
|
-
transferred to the local data repository, but can only be found via the
|
|
492
|
-
quantum graph or their original `~lsst.daf.butler.CollectionType.RUN`
|
|
493
|
-
collections.
|
|
494
|
-
"""
|
|
495
|
-
if not os.path.exists(root):
|
|
496
|
-
Butler.makeRepo(root)
|
|
497
|
-
out_butler = Butler.from_config(root, writeable=True)
|
|
498
|
-
|
|
499
|
-
output_run = self.quantum_graph.metadata["output_run"]
|
|
500
|
-
output = self.quantum_graph.metadata["output"]
|
|
501
|
-
inputs = f"{output}/inputs"
|
|
502
|
-
out_butler.collections.register(output_run, CollectionType.RUN)
|
|
503
|
-
out_butler.collections.register(output, CollectionType.CHAINED)
|
|
504
|
-
out_butler.collections.register(inputs, CollectionType.TAGGED)
|
|
505
|
-
out_butler.collections.redefine_chain(output, [output_run, inputs])
|
|
506
|
-
|
|
507
|
-
refs: set[DatasetRef] = set()
|
|
508
|
-
to_tag_by_type: dict[str, dict[DataCoordinate, DatasetRef | None]] = {}
|
|
509
|
-
pipeline_graph = self.quantum_graph.pipeline_graph
|
|
510
|
-
for name, _ in pipeline_graph.iter_overall_inputs():
|
|
511
|
-
to_tag_for_type = to_tag_by_type.setdefault(name, {})
|
|
512
|
-
for task_node in pipeline_graph.consumers_of(name):
|
|
513
|
-
for quantum in self.quantum_graph.get_task_quanta(task_node.label).values():
|
|
514
|
-
refs.update(quantum.inputs[name])
|
|
515
|
-
for ref in quantum.inputs[name]:
|
|
516
|
-
if to_tag_for_type.setdefault(ref.dataId, ref) != ref:
|
|
517
|
-
# There is already a dataset with the same data ID
|
|
518
|
-
# and dataset type, but a different UUID/run. This
|
|
519
|
-
# can only happen for calibrations found in
|
|
520
|
-
# calibration collections, and for now we have no
|
|
521
|
-
# choice but to leave them out of the TAGGED inputs
|
|
522
|
-
# collection in the local butler.
|
|
523
|
-
to_tag_for_type[ref.dataId] = None
|
|
524
|
-
|
|
525
|
-
out_butler.transfer_from(
|
|
526
|
-
self.butler,
|
|
527
|
-
refs,
|
|
528
|
-
register_dataset_types=register_dataset_types,
|
|
529
|
-
transfer_dimensions=transfer_dimensions,
|
|
530
|
-
)
|
|
531
|
-
|
|
532
|
-
to_tag_flat: list[DatasetRef] = []
|
|
533
|
-
for ref_map in to_tag_by_type.values():
|
|
534
|
-
for tag_ref in ref_map.values():
|
|
535
|
-
if tag_ref is not None:
|
|
536
|
-
to_tag_flat.append(tag_ref)
|
|
537
|
-
out_butler.registry.associate(inputs, to_tag_flat)
|
|
538
|
-
|
|
539
|
-
out_butler.registry.defaults = self.butler.registry.defaults.clone(collections=output, run=output_run)
|
|
540
|
-
self.butler = out_butler
|
|
541
|
-
return self.butler
|
|
542
|
-
|
|
543
|
-
def run(self, register_dataset_types: bool = False, save_versions: bool = True) -> list[Quantum]:
|
|
544
|
-
"""Run all the quanta in the `~lsst.pipe.base.QuantumGraph` in
|
|
545
|
-
topological order.
|
|
546
|
-
|
|
547
|
-
Use this method to run all quanta in the graph. Use
|
|
548
|
-
`as_generator` to get a generator to run the quanta one at
|
|
549
|
-
a time.
|
|
550
|
-
|
|
551
|
-
Parameters
|
|
552
|
-
----------
|
|
553
|
-
register_dataset_types : `bool`, optional
|
|
554
|
-
If `True`, register all output dataset types before executing any
|
|
555
|
-
quanta.
|
|
556
|
-
save_versions : `bool`, optional
|
|
557
|
-
If `True` (default), save a package versions dataset.
|
|
558
|
-
|
|
559
|
-
Returns
|
|
560
|
-
-------
|
|
561
|
-
quanta : `list` [ `~lsst.daf.butler.Quantum` ]
|
|
562
|
-
Executed quanta.
|
|
563
|
-
|
|
564
|
-
Notes
|
|
565
|
-
-----
|
|
566
|
-
A topological ordering is not in general unique, but no other
|
|
567
|
-
guarantees are made about the order in which quanta are processed.
|
|
568
|
-
"""
|
|
569
|
-
return list(
|
|
570
|
-
self.as_generator(register_dataset_types=register_dataset_types, save_versions=save_versions)
|
|
571
|
-
)
|
|
572
|
-
|
|
573
|
-
def as_generator(
|
|
574
|
-
self, register_dataset_types: bool = False, save_versions: bool = True
|
|
575
|
-
) -> Iterator[Quantum]:
|
|
576
|
-
"""Yield quanta in the `~lsst.pipe.base.QuantumGraph` in topological
|
|
577
|
-
order.
|
|
578
|
-
|
|
579
|
-
These quanta will be run as the returned generator is iterated
|
|
580
|
-
over. Use this method to run the quanta one at a time.
|
|
581
|
-
Use `run` to run all quanta in the graph.
|
|
30
|
+
from deprecated.sphinx import deprecated
|
|
582
31
|
|
|
583
|
-
|
|
584
|
-
----------
|
|
585
|
-
register_dataset_types : `bool`, optional
|
|
586
|
-
If `True`, register all output dataset types before executing any
|
|
587
|
-
quanta.
|
|
588
|
-
save_versions : `bool`, optional
|
|
589
|
-
If `True` (default), save a package versions dataset.
|
|
32
|
+
import lsst.pipe.base.simple_pipeline_executor
|
|
590
33
|
|
|
591
|
-
|
|
592
|
-
-------
|
|
593
|
-
quanta : `~collections.abc.Iterator` [ `~lsst.daf.butler.Quantum` ]
|
|
594
|
-
Executed quanta.
|
|
34
|
+
# TODO[DM-51962]: Remove this module.
|
|
595
35
|
|
|
596
|
-
Notes
|
|
597
|
-
-----
|
|
598
|
-
Global initialization steps (see `PreExecInit`) are performed
|
|
599
|
-
immediately when this method is called, but individual quanta are not
|
|
600
|
-
actually executed until the returned iterator is iterated over.
|
|
601
36
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
single_quantum_executor = SingleQuantumExecutor(
|
|
611
|
-
self.butler,
|
|
612
|
-
task_factory,
|
|
613
|
-
resources=self.resources,
|
|
614
|
-
raise_on_partial_outputs=self.raise_on_partial_outputs,
|
|
615
|
-
)
|
|
616
|
-
# Important that this returns a generator expression rather than being
|
|
617
|
-
# a generator itself; that is what makes the PreExecInit stuff above
|
|
618
|
-
# happen immediately instead of when the first quanta is executed,
|
|
619
|
-
# which might be useful for callers who want to check the state of the
|
|
620
|
-
# repo in between.
|
|
621
|
-
return (
|
|
622
|
-
single_quantum_executor.execute(qnode.task_node, qnode.quantum)[0] for qnode in self.quantum_graph
|
|
623
|
-
)
|
|
37
|
+
@deprecated(
|
|
38
|
+
"The SimplePipelineExecutor class has moved to lsst.pipe.base.simple_pipeline_executor. "
|
|
39
|
+
"This forwarding shim will be removed after v30.",
|
|
40
|
+
version="v30",
|
|
41
|
+
category=FutureWarning,
|
|
42
|
+
)
|
|
43
|
+
class SimplePipelineExecutor(lsst.pipe.base.simple_pipeline_executor.SimplePipelineExecutor): # noqa: D101
|
|
44
|
+
pass
|