lsst-pipe-base 30.0.0rc2__py3-none-any.whl → 30.0.1__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.
Files changed (69) hide show
  1. lsst/pipe/base/_instrument.py +31 -20
  2. lsst/pipe/base/_quantumContext.py +3 -3
  3. lsst/pipe/base/_status.py +43 -10
  4. lsst/pipe/base/_task_metadata.py +2 -2
  5. lsst/pipe/base/all_dimensions_quantum_graph_builder.py +8 -3
  6. lsst/pipe/base/automatic_connection_constants.py +20 -1
  7. lsst/pipe/base/cli/cmd/__init__.py +18 -2
  8. lsst/pipe/base/cli/cmd/commands.py +149 -4
  9. lsst/pipe/base/connectionTypes.py +72 -160
  10. lsst/pipe/base/connections.py +6 -9
  11. lsst/pipe/base/execution_reports.py +0 -5
  12. lsst/pipe/base/graph/graph.py +11 -10
  13. lsst/pipe/base/graph/quantumNode.py +4 -4
  14. lsst/pipe/base/graph_walker.py +8 -10
  15. lsst/pipe/base/log_capture.py +40 -80
  16. lsst/pipe/base/log_on_close.py +76 -0
  17. lsst/pipe/base/mp_graph_executor.py +51 -15
  18. lsst/pipe/base/pipeline.py +5 -6
  19. lsst/pipe/base/pipelineIR.py +2 -8
  20. lsst/pipe/base/pipelineTask.py +5 -7
  21. lsst/pipe/base/pipeline_graph/_dataset_types.py +2 -2
  22. lsst/pipe/base/pipeline_graph/_edges.py +32 -22
  23. lsst/pipe/base/pipeline_graph/_mapping_views.py +4 -7
  24. lsst/pipe/base/pipeline_graph/_pipeline_graph.py +14 -7
  25. lsst/pipe/base/pipeline_graph/expressions.py +2 -2
  26. lsst/pipe/base/pipeline_graph/io.py +7 -10
  27. lsst/pipe/base/pipeline_graph/visualization/_dot.py +13 -12
  28. lsst/pipe/base/pipeline_graph/visualization/_layout.py +16 -18
  29. lsst/pipe/base/pipeline_graph/visualization/_merge.py +4 -7
  30. lsst/pipe/base/pipeline_graph/visualization/_printer.py +10 -10
  31. lsst/pipe/base/pipeline_graph/visualization/_status_annotator.py +7 -0
  32. lsst/pipe/base/prerequisite_helpers.py +2 -1
  33. lsst/pipe/base/quantum_graph/_common.py +19 -20
  34. lsst/pipe/base/quantum_graph/_multiblock.py +37 -31
  35. lsst/pipe/base/quantum_graph/_predicted.py +113 -15
  36. lsst/pipe/base/quantum_graph/_provenance.py +1136 -45
  37. lsst/pipe/base/quantum_graph/aggregator/__init__.py +0 -1
  38. lsst/pipe/base/quantum_graph/aggregator/_communicators.py +204 -289
  39. lsst/pipe/base/quantum_graph/aggregator/_config.py +87 -9
  40. lsst/pipe/base/quantum_graph/aggregator/_ingester.py +13 -12
  41. lsst/pipe/base/quantum_graph/aggregator/_scanner.py +49 -235
  42. lsst/pipe/base/quantum_graph/aggregator/_structs.py +6 -116
  43. lsst/pipe/base/quantum_graph/aggregator/_supervisor.py +29 -39
  44. lsst/pipe/base/quantum_graph/aggregator/_workers.py +303 -0
  45. lsst/pipe/base/quantum_graph/aggregator/_writer.py +34 -351
  46. lsst/pipe/base/quantum_graph/formatter.py +171 -0
  47. lsst/pipe/base/quantum_graph/ingest_graph.py +413 -0
  48. lsst/pipe/base/quantum_graph/visualization.py +5 -1
  49. lsst/pipe/base/quantum_graph_builder.py +33 -9
  50. lsst/pipe/base/quantum_graph_executor.py +116 -13
  51. lsst/pipe/base/quantum_graph_skeleton.py +31 -35
  52. lsst/pipe/base/quantum_provenance_graph.py +29 -12
  53. lsst/pipe/base/separable_pipeline_executor.py +19 -3
  54. lsst/pipe/base/single_quantum_executor.py +67 -42
  55. lsst/pipe/base/struct.py +4 -0
  56. lsst/pipe/base/testUtils.py +3 -3
  57. lsst/pipe/base/tests/mocks/_storage_class.py +2 -1
  58. lsst/pipe/base/version.py +1 -1
  59. {lsst_pipe_base-30.0.0rc2.dist-info → lsst_pipe_base-30.0.1.dist-info}/METADATA +3 -3
  60. lsst_pipe_base-30.0.1.dist-info/RECORD +129 -0
  61. {lsst_pipe_base-30.0.0rc2.dist-info → lsst_pipe_base-30.0.1.dist-info}/WHEEL +1 -1
  62. lsst_pipe_base-30.0.0rc2.dist-info/RECORD +0 -125
  63. {lsst_pipe_base-30.0.0rc2.dist-info → lsst_pipe_base-30.0.1.dist-info}/entry_points.txt +0 -0
  64. {lsst_pipe_base-30.0.0rc2.dist-info → lsst_pipe_base-30.0.1.dist-info}/licenses/COPYRIGHT +0 -0
  65. {lsst_pipe_base-30.0.0rc2.dist-info → lsst_pipe_base-30.0.1.dist-info}/licenses/LICENSE +0 -0
  66. {lsst_pipe_base-30.0.0rc2.dist-info → lsst_pipe_base-30.0.1.dist-info}/licenses/bsd_license.txt +0 -0
  67. {lsst_pipe_base-30.0.0rc2.dist-info → lsst_pipe_base-30.0.1.dist-info}/licenses/gpl-v3.0.txt +0 -0
  68. {lsst_pipe_base-30.0.0rc2.dist-info → lsst_pipe_base-30.0.1.dist-info}/top_level.txt +0 -0
  69. {lsst_pipe_base-30.0.0rc2.dist-info → lsst_pipe_base-30.0.1.dist-info}/zip-safe +0 -0
@@ -49,7 +49,7 @@ import warnings
49
49
  from collections import defaultdict
50
50
  from collections.abc import Iterable, Iterator, Mapping, Sequence
51
51
  from contextlib import AbstractContextManager, contextmanager
52
- from typing import TYPE_CHECKING, Any, TypeVar, cast
52
+ from typing import TYPE_CHECKING, Any, cast
53
53
 
54
54
  import networkx
55
55
  import networkx.algorithms.bipartite
@@ -66,6 +66,7 @@ from lsst.daf.butler import (
66
66
  DimensionDataExtractor,
67
67
  DimensionGroup,
68
68
  DimensionRecordSetDeserializer,
69
+ DimensionUniverse,
69
70
  LimitedButler,
70
71
  Quantum,
71
72
  QuantumBackedButler,
@@ -109,10 +110,14 @@ if TYPE_CHECKING:
109
110
  from ..config import PipelineTaskConfig
110
111
  from ..graph import QgraphSummary, QuantumGraph
111
112
 
112
- _LOG = logging.getLogger(__name__)
113
+ # Sphinx needs imports for type annotations of base class members.
114
+ if "sphinx" in sys.modules:
115
+ import zipfile # noqa: F401
116
+
117
+ from ._multiblock import AddressReader, Decompressor # noqa: F401
113
118
 
114
119
 
115
- _T = TypeVar("_T", bound=pydantic.BaseModel)
120
+ _LOG = logging.getLogger(__name__)
116
121
 
117
122
 
118
123
  class _PredictedThinQuantumModelV0(pydantic.BaseModel):
@@ -198,10 +203,10 @@ class _PredictedThinGraphModelV0(pydantic.BaseModel):
198
203
  def _upgraded(self, address_rows: Mapping[uuid.UUID, AddressRow]) -> PredictedThinGraphModel:
199
204
  """Convert to the v1+ model."""
200
205
  uuid_by_index = {v.index: k for k, v in address_rows.items()}
201
- return PredictedThinGraphModel(
206
+ return PredictedThinGraphModel.model_construct(
202
207
  quanta={
203
208
  task_label: [
204
- PredictedThinQuantumModel(
209
+ PredictedThinQuantumModel.model_construct(
205
210
  quantum_id=uuid_by_index[q.quantum_index], data_coordinate=q.data_coordinate
206
211
  )
207
212
  for q in quanta
@@ -877,6 +882,49 @@ class PredictedQuantumGraph(BaseQuantumGraph):
877
882
  page_size=page_size,
878
883
  ).assemble()
879
884
 
885
+ @classmethod
886
+ def make_empty(
887
+ cls,
888
+ universe: DimensionUniverse,
889
+ *,
890
+ output_run: str,
891
+ inputs: Iterable[str] = (),
892
+ output: str | None = None,
893
+ add_packages: bool = True,
894
+ ) -> PredictedQuantumGraph:
895
+ """Make an empty quantum graph with no tasks.
896
+
897
+ Parameters
898
+ ----------
899
+ universe : `lsst.daf.butler.DimensionUniverse`
900
+ Definitions for all butler dimensions.
901
+ output_run : `str`
902
+ Output run collection.
903
+ inputs : `~collections.abc.Iterable` [`str`], optional
904
+ Iterable of input collection names.
905
+ output : `str` or `None`, optional
906
+ Output chained collection.
907
+ add_packages : `bool`, optional
908
+ Whether to add the special init quantum that writes the 'packages'
909
+ dataset. The default (`True`) is consistent with
910
+ `~..quantum_graph_builder.QuantumGraphBuilder` behavior when there
911
+ are no regular quanta generated.
912
+
913
+ Returns
914
+ -------
915
+ quantum_graph : `PredictedQuantumGraph`
916
+ An empty quantum graph.
917
+ """
918
+ return cls(
919
+ PredictedQuantumGraphComponents.make_empty(
920
+ universe,
921
+ output_run=output_run,
922
+ inputs=inputs,
923
+ output=output,
924
+ add_packages=add_packages,
925
+ )
926
+ )
927
+
880
928
  @property
881
929
  def quanta_by_task(self) -> Mapping[str, Mapping[DataCoordinate, uuid.UUID]]:
882
930
  """A nested mapping of all quanta, keyed first by task name and then by
@@ -1541,6 +1589,63 @@ class PredictedQuantumGraphComponents:
1541
1589
  This does not include special "init" quanta.
1542
1590
  """
1543
1591
 
1592
+ @classmethod
1593
+ def make_empty(
1594
+ cls,
1595
+ universe: DimensionUniverse,
1596
+ *,
1597
+ output_run: str,
1598
+ inputs: Iterable[str] = (),
1599
+ output: str | None = None,
1600
+ add_packages: bool = True,
1601
+ ) -> PredictedQuantumGraphComponents:
1602
+ """Make components for an empty quantum graph with no tasks.
1603
+
1604
+ Parameters
1605
+ ----------
1606
+ universe : `lsst.daf.butler.DimensionUniverse`
1607
+ Definitions for all butler dimensions.
1608
+ output_run : `str`
1609
+ Output run collection.
1610
+ inputs : `~collections.abc.Iterable` [`str`], optional
1611
+ Iterable of input collection names.
1612
+ output : `str` or `None`, optional
1613
+ Output chained collection.
1614
+ add_packages : `bool`, optional
1615
+ Whether to add the special init quantum that writes the 'packages'
1616
+ dataset. The default (`True`) is consistent with
1617
+ `~..quantum_graph_builder.QuantumGraphBuilder` behavior when there
1618
+ are no regular quanta generated.
1619
+
1620
+ Returns
1621
+ -------
1622
+ components : `PredictedQuantumGraphComponents`
1623
+ Components that can be used to build or write an empty quantum
1624
+ graph.
1625
+ """
1626
+ components = cls(pipeline_graph=PipelineGraph(universe=universe))
1627
+ components.header.inputs = list(inputs)
1628
+ components.header.output_run = output_run
1629
+ components.header.output = output
1630
+ if add_packages:
1631
+ components.init_quanta.root = [
1632
+ PredictedQuantumDatasetsModel.model_construct(
1633
+ quantum_id=generate_uuidv7(),
1634
+ task_label="",
1635
+ outputs={
1636
+ acc.PACKAGES_INIT_OUTPUT_NAME: [
1637
+ PredictedDatasetModel(
1638
+ dataset_id=generate_uuidv7(),
1639
+ dataset_type_name=acc.PACKAGES_INIT_OUTPUT_NAME,
1640
+ data_coordinate=[],
1641
+ run=output_run,
1642
+ )
1643
+ ]
1644
+ },
1645
+ )
1646
+ ]
1647
+ return components
1648
+
1544
1649
  def make_dataset_ref(self, predicted: PredictedDatasetModel) -> DatasetRef:
1545
1650
  """Make a `lsst.daf.butler.DatasetRef` from information in the
1546
1651
  predicted quantum graph.
@@ -1793,7 +1898,6 @@ class PredictedQuantumGraphComponents:
1793
1898
  f"Unsupported extension {ext!r} for quantum graph; "
1794
1899
  "expected '.qg' (or '.qgraph' to force the old format)."
1795
1900
  )
1796
- cdict: zstandard.ZstdCompressionDict | None = None
1797
1901
  cdict_data: bytes | None = None
1798
1902
  quantum_datasets_json: dict[uuid.UUID, bytes] = {}
1799
1903
  if len(self.quantum_datasets) < zstd_dict_n_inputs:
@@ -1807,26 +1911,20 @@ class PredictedQuantumGraphComponents:
1807
1911
  for quantum_model in itertools.islice(self.quantum_datasets.values(), zstd_dict_n_inputs)
1808
1912
  }
1809
1913
  try:
1810
- cdict = zstandard.train_dictionary(
1914
+ cdict_data = zstandard.train_dictionary(
1811
1915
  zstd_dict_size,
1812
1916
  list(quantum_datasets_json.values()),
1813
1917
  level=zstd_level,
1814
- )
1918
+ ).as_bytes()
1815
1919
  except zstandard.ZstdError as err:
1816
1920
  warnings.warn(f"Not using a compression dictionary: {err}.")
1817
- cdict = None
1818
- else:
1819
- cdict_data = cdict.as_bytes()
1820
- compressor = zstandard.ZstdCompressor(level=zstd_level, dict_data=cdict)
1821
- indices = {quantum_id: n for n, quantum_id in enumerate(sorted(self.quantum_datasets.keys()))}
1822
1921
  with BaseQuantumGraphWriter.open(
1823
1922
  uri,
1824
1923
  header=self.header,
1825
1924
  pipeline_graph=self.pipeline_graph,
1826
- indices=indices,
1827
1925
  address_filename="quanta",
1828
- compressor=compressor,
1829
1926
  cdict_data=cdict_data,
1927
+ zstd_level=zstd_level,
1830
1928
  ) as writer:
1831
1929
  writer.write_single_model("thin_graph", self.thin_graph)
1832
1930
  if self.dimension_data is None: