lsst-ctrl-mpexec 29.2025.1000__py3-none-any.whl → 29.2025.1200__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.
@@ -382,6 +382,18 @@ def update_graph_run(
382
382
  "even when there is only one qgraph. Otherwise, the `QuantumGraphExecutionReport` "
383
383
  "will run on one graph by default.",
384
384
  )
385
+ @click.option(
386
+ "--read-caveats",
387
+ type=click.Choice(["exhaustive", "lazy", "none"], case_sensitive=False),
388
+ default="lazy",
389
+ )
390
+ @click.option(
391
+ "--use-qbb/--no-use-qbb",
392
+ is_flag=True,
393
+ default=True,
394
+ help="Whether to use a quantum-backed butler for metadata and log reads.",
395
+ )
396
+ @processes_option()
385
397
  def report(
386
398
  repo: str,
387
399
  qgraphs: Sequence[str],
@@ -392,6 +404,9 @@ def report(
392
404
  brief: bool = False,
393
405
  curse_failed_logs: bool = False,
394
406
  force_v2: bool = False,
407
+ read_caveats: str = "lazy",
408
+ use_qbb: bool = True,
409
+ processes: int = 1,
395
410
  ) -> None:
396
411
  """Summarize the state of executed quantum graph(s), with counts of failed,
397
412
  successful and expected quanta, as well as counts of output datasets and
@@ -417,7 +432,17 @@ def report(
417
432
  """
418
433
  if any([force_v2, len(qgraphs) > 1, collections, where, curse_failed_logs]):
419
434
  script.report_v2(
420
- repo, qgraphs, collections, where, full_output_filename, logs, brief, curse_failed_logs
435
+ repo,
436
+ qgraphs,
437
+ collections,
438
+ where,
439
+ full_output_filename,
440
+ logs,
441
+ brief,
442
+ curse_failed_logs,
443
+ read_caveats=(read_caveats if read_caveats != "none" else None), # type: ignore[arg-type]
444
+ use_qbb=use_qbb,
445
+ n_cores=processes,
421
446
  )
422
447
  else:
423
448
  assert len(qgraphs) == 1, "Cannot make a report without a quantum graph."
@@ -129,10 +129,23 @@ def build( # type: ignore
129
129
  )
130
130
 
131
131
  if pipeline_mermaid:
132
- with open(pipeline_mermaid, "w") as stream:
132
+ # Determine output format based on file extension.
133
+ if pipeline_mermaid.endswith(".svg"):
134
+ output_format = "svg"
135
+ file_mode = "wb"
136
+ elif pipeline_mermaid.endswith(".png"):
137
+ output_format = "png"
138
+ file_mode = "wb"
139
+ else: # Default to the text-based mmd format.
140
+ output_format = "mmd"
141
+ file_mode = "w"
142
+
143
+ with open(pipeline_mermaid, file_mode) as stream:
133
144
  visualization.show_mermaid(
134
145
  pipeline.to_graph(butler.registry if butler is not None else None, visualization_only=True),
135
146
  stream,
147
+ output_format=output_format,
148
+ width=4500 if output_format != "mmd" else None,
136
149
  dataset_types=True,
137
150
  task_classes="full",
138
151
  )
@@ -26,6 +26,7 @@
26
26
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
27
27
  import pprint
28
28
  from collections.abc import Sequence
29
+ from typing import Literal
29
30
 
30
31
  from astropy.table import Table
31
32
 
@@ -48,23 +49,22 @@ def report(
48
49
 
49
50
  Parameters
50
51
  ----------
51
- butler_config : `str`
52
- The Butler used for this report. This should match the Butler used
53
- for the run associated with the executed quantum graph.
54
- qgraph_uri : `str`
55
- The uri of the location of said quantum graph.
56
- full_output_filename : `str`
57
- Output the full summary report to a yaml file (named herein).
58
- Each data id and error message is keyed to a quantum graph node id.
59
- A convenient output format for error-matching and cataloguing tools
60
- such as the ones in the Campaign Management database. If this is
61
- not included, quanta and dataset information will be printed to the
62
- command-line instead.
63
- logs : `bool`
64
- Get butler log datasets for extra information (error messages).
65
- brief : `bool`
66
- List only the counts (or data_ids if number of failures < 5). This
67
- option is good for those who just want to see totals.
52
+ butler_config : `str`
53
+ The Butler used for this report. This should match the Butler used for
54
+ the run associated with the executed quantum graph.
55
+ qgraph_uri : `str`
56
+ The uri of the location of said quantum graph.
57
+ full_output_filename : `str`
58
+ Output the full summary report to a yaml file (named herein). Each data
59
+ id and error message is keyed to a quantum graph node id. A convenient
60
+ output format for error-matching and cataloguing tools such as the ones
61
+ in the Campaign Management database. If this is not included, quanta
62
+ and dataset information will be printed to the command-line instead.
63
+ logs : `bool`
64
+ Get butler log datasets for extra information (error messages).
65
+ brief : `bool`
66
+ List only the counts (or data_ids if number of failures < 5). This
67
+ option is good for those who just want to see totals.
68
68
  """
69
69
  butler = Butler.from_config(butler_config, writeable=False)
70
70
  qgraph = QuantumGraph.loadUri(qgraph_uri)
@@ -125,6 +125,9 @@ def report_v2(
125
125
  logs: bool = True,
126
126
  brief: bool = False,
127
127
  curse_failed_logs: bool = False,
128
+ read_caveats: Literal["lazy", "exhaustive"] | None = "lazy",
129
+ use_qbb: bool = True,
130
+ n_cores: int = 1,
128
131
  ) -> None:
129
132
  """Summarize the state of executed quantum graph(s), with counts of failed,
130
133
  successful and expected quanta, as well as counts of output datasets and
@@ -135,62 +138,62 @@ def report_v2(
135
138
  Parameters
136
139
  ----------
137
140
  butler_config : `str`
138
- The Butler used for this report. This should match the Butler used
139
- for the run associated with the executed quantum graph.
141
+ The Butler used for this report. This should match the Butler used for
142
+ the run associated with the executed quantum graph.
140
143
  qgraph_uris : `Sequence` [`str`]
141
- One or more uris to the serialized Quantum Graph(s).
144
+ One or more uris to the serialized Quantum Graph(s).
142
145
  collections : `Sequence` [`str`] | None`
143
- Collection(s) associated with said graphs/processing. For use in
144
- `lsst.daf.butler.registry.queryDatasets` if paring down the query
145
- would be useful.
146
+ Collection(s) associated with said graphs/processing. For use in
147
+ `lsst.daf.butler.registry.queryDatasets` if paring down the query would
148
+ be useful.
146
149
  where : `str`
147
- A "where" string to use to constrain the collections, if passed.
150
+ A "where" string to use to constrain the collections, if passed.
148
151
  full_output_filename : `str`
149
- Output the full pydantic model `QuantumProvenanceGraph.Summary`
150
- object into a JSON file. This is ideal for error-matching and
151
- cataloguing tools such as the ones used by Campaign Management
152
- software and pilots, and for searching and counting specific kinds
153
- or instances of failures. This option will also print a "brief"
154
- (counts-only) summary to stdout.
152
+ Output the full pydantic model `QuantumProvenanceGraph.Summary` object
153
+ into a JSON file. This is ideal for error-matching and cataloguing
154
+ tools such as the ones used by Campaign Management software and pilots,
155
+ and for searching and counting specific kinds or instances of failures.
156
+ This option will also print a "brief" (counts-only) summary to stdout.
155
157
  logs : `bool`
156
- Store error messages from Butler logs associated with failed quanta
157
- if `True`.
158
+ Store error messages from Butler logs associated with failed quanta if
159
+ `True`.
158
160
  brief : `bool`
159
- Only display short (counts-only) summary on stdout. This includes
160
- counts and not error messages or data_ids (similar to BPS report).
161
- This option will still report all `cursed` datasets and `wonky`
162
- quanta.
161
+ Only display short (counts-only) summary on stdout. This includes
162
+ counts and not error messages or data_ids (similar to BPS report). This
163
+ option will still report all `cursed` datasets and `wonky` quanta.
163
164
  curse_failed_logs : `bool`
164
- Mark log datasets as `cursed` if they are published in the final
165
- output collection. Note that a campaign-level collection must be
166
- used here for `collections` if `curse_failed_logs` is `True`; if
167
- `lsst.pipe.base.QuantumProvenanceGraph.__resolve_duplicates`
168
- is run on a list of group-level collections, then each will only
169
- show log datasets from their own failures as visible and datasets
170
- from others will be marked as cursed.
165
+ Mark log datasets as `cursed` if they are published in the final output
166
+ collection. Note that a campaign-level collection must be used here for
167
+ `collections` if `curse_failed_logs` is `True`; if
168
+ `lsst.pipe.base.QuantumProvenanceGraph.__resolve_duplicates` is run on
169
+ a list of group-level collections, then each will only show log
170
+ datasets from their own failures as visible and datasets from others
171
+ will be marked as cursed.
172
+ read_caveats : `str`, optional
173
+ Whether and how to read success caveats from metadata datasets:
174
+
175
+ - "exhaustive": read all metadata datasets;
176
+ - "lazy": read metadata datasets only for quanta that had predicted
177
+ outputs that were not produced (will not pick up exceptions raised
178
+ after all datasets were written);
179
+ - `None`: do not read metadata datasets at all.
180
+ use_qbb : `bool`, optional
181
+ Whether to use a quantum-backed butler for metadata and log reads.
182
+ This should reduce the number of database operations.
183
+ n_cores : `int`, optional
184
+ Number of cores for metadata and log reads.
171
185
  """
172
186
  butler = Butler.from_config(butler_config, writeable=False)
173
- qpg = QuantumProvenanceGraph()
174
- qgraphs = []
175
- for qgraph_uri in qgraph_uris:
176
- qgraph = QuantumGraph.loadUri(qgraph_uri)
177
- assert qgraph.metadata is not None, "Saved QGs always have metadata."
178
- qgraphs.append(qgraph)
179
- # If the most recent graph's timestamp was earlier than any of the
180
- # previous graphs, raise a RuntimeError.
181
- for count, qgraph in enumerate(qgraphs):
182
- if len(qgraphs) > 1:
183
- previous_graph = qgraphs[count - 1]
184
- if count > 0 and qgraph.metadata["time"] < previous_graph.metadata["time"]:
185
- raise RuntimeError(
186
- f"""add_new_graph may only be called on graphs
187
- which are passed in the order they were
188
- created. Please call again, passing your
189
- graphs in order. Time of second graph:
190
- {qgraph.metadata["time"]} >
191
- time of first graph: {previous_graph.metadata["time"]}"""
192
- )
193
- qpg.assemble_quantum_provenance_graph(butler, qgraphs, collections, where, curse_failed_logs)
187
+ qpg = QuantumProvenanceGraph(
188
+ butler,
189
+ qgraph_uris,
190
+ collections=collections,
191
+ where=where,
192
+ curse_failed_logs=curse_failed_logs,
193
+ read_caveats=read_caveats,
194
+ use_qbb=use_qbb,
195
+ n_cores=n_cores,
196
+ )
194
197
  summary = qpg.to_summary(butler, do_store_logs=logs)
195
198
  print_summary(summary, full_output_filename, brief)
196
199
 
@@ -71,6 +71,7 @@ from lsst.pipe.base import (
71
71
  )
72
72
  from lsst.pipe.base.all_dimensions_quantum_graph_builder import AllDimensionsQuantumGraphBuilder
73
73
  from lsst.pipe.base.dot_tools import graph2dot
74
+ from lsst.pipe.base.mermaid_tools import graph2mermaid
74
75
  from lsst.pipe.base.pipeline_graph import NodeType
75
76
  from lsst.utils import doImportType
76
77
  from lsst.utils.logging import getLogger
@@ -704,6 +705,10 @@ class CmdLineFwk:
704
705
  _LOG.verbose("Writing quantum graph DOT visualization to %r.", args.qgraph_dot)
705
706
  graph2dot(qgraph, args.qgraph_dot)
706
707
 
708
+ if args.qgraph_mermaid:
709
+ _LOG.verbose("Writing quantum graph Mermaid visualization to %r.", args.qgraph_mermaid)
710
+ graph2mermaid(qgraph, args.qgraph_mermaid)
711
+
707
712
  if args.execution_butler_location:
708
713
  _LOG.verbose("Writing execution butler to %r.", args.execution_butler_location)
709
714
  butler = Butler.from_config(args.butler_config)
@@ -1,2 +1,2 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "29.2025.1000"
2
+ __version__ = "29.2025.1200"
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: lsst-ctrl-mpexec
3
- Version: 29.2025.1000
3
+ Version: 29.2025.1200
4
4
  Summary: Pipeline execution infrastructure for the Rubin Observatory LSST Science Pipelines.
5
5
  Author-email: Rubin Observatory Data Management <dm-admin@lists.lsst.org>
6
6
  License: BSD 3-Clause License
@@ -33,6 +33,7 @@ Provides-Extra: coverage
33
33
  Requires-Dist: coverage; extra == "coverage"
34
34
  Provides-Extra: test
35
35
  Requires-Dist: pytest>=3.2; extra == "test"
36
+ Dynamic: license-file
36
37
 
37
38
  ################
38
39
  lsst-ctrl-mpexec
@@ -1,7 +1,7 @@
1
1
  lsst/__init__.py,sha256=aXdEOZVrBQISQi6XPS9s1NhBjIJaIwNNxCFRiGchRAw,1369
2
2
  lsst/ctrl/__init__.py,sha256=aXdEOZVrBQISQi6XPS9s1NhBjIJaIwNNxCFRiGchRAw,1369
3
3
  lsst/ctrl/mpexec/__init__.py,sha256=34loiOJc5I_65Npo6zsO1Bf8dB5zV1y1MQid6W65cV8,1699
4
- lsst/ctrl/mpexec/cmdLineFwk.py,sha256=93q-HsMjbItXmmdpgoFR-vCYjFUkbS7YbmWpvXP0FbE,41500
4
+ lsst/ctrl/mpexec/cmdLineFwk.py,sha256=4h3qqzUjYRuI8oJehjwa5_ytrxhf0JlBLdDeQYOTGx4,41743
5
5
  lsst/ctrl/mpexec/dotTools.py,sha256=nx31DC7NkQM766sC97lPQMI22snVaWS7USFMFVLChqk,3421
6
6
  lsst/ctrl/mpexec/execFixupDataId.py,sha256=MUirmuoQiWj7C7wQ23QGkgMqx_5_CP4_UMV6h_gVfxk,5056
7
7
  lsst/ctrl/mpexec/executionGraphFixup.py,sha256=1z4P4YmtLTMPoMxmFiOnzljLcP9B5V1SCG9haqR_TyI,2830
@@ -17,34 +17,34 @@ lsst/ctrl/mpexec/simple_pipeline_executor.py,sha256=scqQ1MDS6FcZvFTwxtCkmTSg0zJm
17
17
  lsst/ctrl/mpexec/singleQuantumExecutor.py,sha256=mlv3nF29N1meiHie3r072Ynz5k6XTpFO8jfhq7BufF8,28036
18
18
  lsst/ctrl/mpexec/taskFactory.py,sha256=c4xj8cR_Ts5uzzGovh87ZKdVeeXy5E3lIjCwJnDuOqg,2720
19
19
  lsst/ctrl/mpexec/util.py,sha256=y2Rw5PL40_EuLtVxiqSVX0JfPV4IrFl1LfOMUWx2u30,4236
20
- lsst/ctrl/mpexec/version.py,sha256=J0EmBUnWW_L_z5vGYTLK_7oa_NUvkGOs1LJlKYkBXtk,55
20
+ lsst/ctrl/mpexec/version.py,sha256=Q55pqojE5GgOP1ODSUiZGmFU6sD87FAaQ-iGrKq2N5Y,55
21
21
  lsst/ctrl/mpexec/cli/__init__.py,sha256=6dpDHNBzyicVpFi1fsaiYVbYEMeoL57IHKkPaej24gs,1301
22
22
  lsst/ctrl/mpexec/cli/pipetask.py,sha256=4HnhX9dCizCihVbpHVJX5WXO9TEli9oL6wA-tPh1_vA,2209
23
23
  lsst/ctrl/mpexec/cli/utils.py,sha256=5iOrlj5jJTWtZS0BMLsuiCGAvxbfrjd1MSyXxBthWcc,6503
24
24
  lsst/ctrl/mpexec/cli/cmd/__init__.py,sha256=nRmwwW5d55gAEkyE7NpSK8mxa56HcfEta2r-Y9I07F8,1661
25
- lsst/ctrl/mpexec/cli/cmd/commands.py,sha256=VKfOoGem15I3JErBY8Iic9dmcuQkzPHwc4MCsbD9nsM,16891
25
+ lsst/ctrl/mpexec/cli/cmd/commands.py,sha256=7ohYuNeUhnnyNvWYWYBdHLkNm5VWsOQiOh6HjzBBYXc,17539
26
26
  lsst/ctrl/mpexec/cli/opt/__init__.py,sha256=IzUInuJj9igiaNcEqMx0adelgJtQC5_XMYnaiizBn0A,1378
27
27
  lsst/ctrl/mpexec/cli/opt/arguments.py,sha256=vjUw0ZN_4HStp-_3ne6AT5S_eH7sly3OVfL07tgrJnY,1572
28
28
  lsst/ctrl/mpexec/cli/opt/optionGroups.py,sha256=z1vrRsNlk11cGulbD9qsBOuPhZgryPrka_IxIeVW9TM,8031
29
29
  lsst/ctrl/mpexec/cli/opt/options.py,sha256=TyTYxDrFqhUqfnLPfjr_2kJLPNlBbQ86nX2SuOlqAts,19911
30
30
  lsst/ctrl/mpexec/cli/script/__init__.py,sha256=eCuF4FAI5D3pl05IMJj7TCkZq-hireua2mA5Ui-mKSI,1624
31
- lsst/ctrl/mpexec/cli/script/build.py,sha256=F8EcD6u4EIb8oUkl4KjddhF_HxsIlkgEOq0ufetlDVE,5348
31
+ lsst/ctrl/mpexec/cli/script/build.py,sha256=fTa4veqSfUR5nONedmS14q4N5Y_E3nDP1Q-chJvC5IA,5860
32
32
  lsst/ctrl/mpexec/cli/script/cleanup.py,sha256=D7W-azf4mNJcIWhbU5uCRCi94mkb8-Q2ksRFblQGrUw,4990
33
33
  lsst/ctrl/mpexec/cli/script/confirmable.py,sha256=Bo1GSTZQn44d_TRj6N3YfpYcZiuHEYoz26WZQwMyb4A,3918
34
34
  lsst/ctrl/mpexec/cli/script/pre_exec_init_qbb.py,sha256=DGNseiavrI1VxR_o6vCelbPvr9kCQZzroZHHSQe-RTE,2479
35
35
  lsst/ctrl/mpexec/cli/script/purge.py,sha256=gYwSsZfTBP6oDcDp_YdqQEKGvAStvsj5hwNw42S8ptE,10637
36
36
  lsst/ctrl/mpexec/cli/script/qgraph.py,sha256=p5z84bmRBbZXIEql76nXYnRQcLau-VNTUVkfOhdqjfU,9805
37
- lsst/ctrl/mpexec/cli/script/report.py,sha256=IazYZT-aOtkYpCpGqslMazjXYVma5GajiEbJP_OTVUU,11656
37
+ lsst/ctrl/mpexec/cli/script/report.py,sha256=AssS4S99LFrPZtATsu7lsXVdxk7mOwfrdM9LXmUxgZ0,11427
38
38
  lsst/ctrl/mpexec/cli/script/run.py,sha256=22g7vBhGDGsFSQq7CtruTf-bivo3t53decBAV0wAg1g,9767
39
39
  lsst/ctrl/mpexec/cli/script/run_qbb.py,sha256=oCEydg13zNAtci8XB0IwXx_D5PPsHbjCPATWoBlhcPk,5294
40
40
  lsst/ctrl/mpexec/cli/script/update_graph_run.py,sha256=v_EdOaD6jR_vSlgm_5-pwUjoNEFMrAuYFM1xIaHVU3Q,2597
41
- lsst_ctrl_mpexec-29.2025.1000.dist-info/COPYRIGHT,sha256=pGCjnRAnyt02a6_9PLzXQikpvYmvMmK9fCdOKlRSV6k,369
42
- lsst_ctrl_mpexec-29.2025.1000.dist-info/LICENSE,sha256=pRExkS03v0MQW-neNfIcaSL6aiAnoLxYgtZoFzQ6zkM,232
43
- lsst_ctrl_mpexec-29.2025.1000.dist-info/METADATA,sha256=5m55RyOiPvT7LbQE4cAT9U_ienv_asYLu6nnT2MfuKk,2280
44
- lsst_ctrl_mpexec-29.2025.1000.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
45
- lsst_ctrl_mpexec-29.2025.1000.dist-info/bsd_license.txt,sha256=7MIcv8QRX9guUtqPSBDMPz2SnZ5swI-xZMqm_VDSfxY,1606
46
- lsst_ctrl_mpexec-29.2025.1000.dist-info/entry_points.txt,sha256=aYE38yqZU8qvpLUUkXzgmUxDJYYknEqPxgxYkowrL4s,64
47
- lsst_ctrl_mpexec-29.2025.1000.dist-info/gpl-v3.0.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
48
- lsst_ctrl_mpexec-29.2025.1000.dist-info/top_level.txt,sha256=eUWiOuVVm9wwTrnAgiJT6tp6HQHXxIhj2QSZ7NYZH80,5
49
- lsst_ctrl_mpexec-29.2025.1000.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
50
- lsst_ctrl_mpexec-29.2025.1000.dist-info/RECORD,,
41
+ lsst_ctrl_mpexec-29.2025.1200.dist-info/licenses/COPYRIGHT,sha256=pGCjnRAnyt02a6_9PLzXQikpvYmvMmK9fCdOKlRSV6k,369
42
+ lsst_ctrl_mpexec-29.2025.1200.dist-info/licenses/LICENSE,sha256=pRExkS03v0MQW-neNfIcaSL6aiAnoLxYgtZoFzQ6zkM,232
43
+ lsst_ctrl_mpexec-29.2025.1200.dist-info/licenses/bsd_license.txt,sha256=7MIcv8QRX9guUtqPSBDMPz2SnZ5swI-xZMqm_VDSfxY,1606
44
+ lsst_ctrl_mpexec-29.2025.1200.dist-info/licenses/gpl-v3.0.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
45
+ lsst_ctrl_mpexec-29.2025.1200.dist-info/METADATA,sha256=Jpvf0NjiVh3olU70ZVmnolX3oS1H3CJuHe1XwIAg3GM,2302
46
+ lsst_ctrl_mpexec-29.2025.1200.dist-info/WHEEL,sha256=tTnHoFhvKQHCh4jz3yCn0WPTYIy7wXx3CJtJ7SJGV7c,91
47
+ lsst_ctrl_mpexec-29.2025.1200.dist-info/entry_points.txt,sha256=aYE38yqZU8qvpLUUkXzgmUxDJYYknEqPxgxYkowrL4s,64
48
+ lsst_ctrl_mpexec-29.2025.1200.dist-info/top_level.txt,sha256=eUWiOuVVm9wwTrnAgiJT6tp6HQHXxIhj2QSZ7NYZH80,5
49
+ lsst_ctrl_mpexec-29.2025.1200.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
50
+ lsst_ctrl_mpexec-29.2025.1200.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.2)
2
+ Generator: setuptools (77.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5