vector-mtrl 0.2.0__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 (81) hide show
  1. mtrl/__init__.py +144 -0
  2. mtrl/_alignment_report.py +105 -0
  3. mtrl/_archive_documents.py +73 -0
  4. mtrl/_archive_integrity.py +539 -0
  5. mtrl/_archive_loading.py +1070 -0
  6. mtrl/_archive_serialise.py +696 -0
  7. mtrl/_candidate_matching.py +216 -0
  8. mtrl/_cli.py +28 -0
  9. mtrl/_disclosure.py +735 -0
  10. mtrl/_ingestion_shortcuts.py +99 -0
  11. mtrl/_install_targets.py +36 -0
  12. mtrl/_optional.py +38 -0
  13. mtrl/_provenance.py +32 -0
  14. mtrl/_receipts.py +211 -0
  15. mtrl/_record_resolution.py +60 -0
  16. mtrl/_replay_plan.py +557 -0
  17. mtrl/_replay_run.py +734 -0
  18. mtrl/_run_management.py +400 -0
  19. mtrl/_source_capture.py +507 -0
  20. mtrl/_table_plan.py +271 -0
  21. mtrl/_table_provenance.py +387 -0
  22. mtrl/_table_values.py +188 -0
  23. mtrl/_transform_apply.py +223 -0
  24. mtrl/_transform_validation.py +1367 -0
  25. mtrl/archive/__init__.py +54 -0
  26. mtrl/archive/canonical.py +45 -0
  27. mtrl/archive/codecs.py +88 -0
  28. mtrl/archive/dtypes.py +39 -0
  29. mtrl/archive/reader.py +945 -0
  30. mtrl/archive/validation.py +1872 -0
  31. mtrl/connectors/__init__.py +1 -0
  32. mtrl/connectors/protocols.py +84 -0
  33. mtrl/disclosure.py +273 -0
  34. mtrl/domain/__init__.py +129 -0
  35. mtrl/domain/archive_limits.py +46 -0
  36. mtrl/domain/committed_values.py +539 -0
  37. mtrl/domain/frozen_containers.py +168 -0
  38. mtrl/domain/identities.py +174 -0
  39. mtrl/domain/provenance.py +448 -0
  40. mtrl/domain/records.py +233 -0
  41. mtrl/domain/revisions.py +121 -0
  42. mtrl/domain/source.py +13 -0
  43. mtrl/domain/verification.py +302 -0
  44. mtrl/excel.py +139 -0
  45. mtrl/exceptions.py +215 -0
  46. mtrl/exports.py +326 -0
  47. mtrl/features.py +251 -0
  48. mtrl/frames.py +228 -0
  49. mtrl/grids.py +1172 -0
  50. mtrl/integrity/__init__.py +143 -0
  51. mtrl/integrity/canonical.py +511 -0
  52. mtrl/integrity/digests.py +363 -0
  53. mtrl/integrity/manifest.py +631 -0
  54. mtrl/integrity/receipts.py +771 -0
  55. mtrl/integrity/verification.py +1303 -0
  56. mtrl/models.py +952 -0
  57. mtrl/mtrl.py +1852 -0
  58. mtrl/operations/__init__.py +36 -0
  59. mtrl/operations/_identity.py +17 -0
  60. mtrl/operations/_validation.py +106 -0
  61. mtrl/operations/arithmetic.py +207 -0
  62. mtrl/operations/base.py +292 -0
  63. mtrl/operations/resampling.py +203 -0
  64. mtrl/operations/resampling_scipy.py +138 -0
  65. mtrl/operations/spectra.py +58 -0
  66. mtrl/processing/__init__.py +23 -0
  67. mtrl/processing/_table_capture.py +341 -0
  68. mtrl/processing/limits.py +9 -0
  69. mtrl/processing/registry.py +1533 -0
  70. mtrl/protocols.py +13 -0
  71. mtrl/py.typed +0 -0
  72. mtrl/replay.py +946 -0
  73. mtrl/tables.py +1365 -0
  74. mtrl/transformations/__init__.py +22 -0
  75. mtrl/transformations/base.py +17 -0
  76. mtrl/units.py +60 -0
  77. vector_mtrl-0.2.0.dist-info/METADATA +142 -0
  78. vector_mtrl-0.2.0.dist-info/RECORD +81 -0
  79. vector_mtrl-0.2.0.dist-info/WHEEL +4 -0
  80. vector_mtrl-0.2.0.dist-info/licenses/LICENSE +373 -0
  81. vector_mtrl-0.2.0.dist-info/licenses/NOTICE +30 -0
mtrl/__init__.py ADDED
@@ -0,0 +1,144 @@
1
+ """Top-level package for mtrl."""
2
+
3
+ from mtrl.domain import (
4
+ ArchiveId,
5
+ ArchiveLimits,
6
+ OperationRegistry,
7
+ Receipt,
8
+ RecordId,
9
+ RecordRef,
10
+ RevisionId,
11
+ SourcePolicy,
12
+ VerifyIssue,
13
+ VerifyPolicy,
14
+ VerifyResult,
15
+ )
16
+ from mtrl.exceptions import (
17
+ AnchorMismatchError,
18
+ ArchiveLimitError,
19
+ CheckpointExportWarning,
20
+ CommittedRecordMutationError,
21
+ DuplicateCheckpointError,
22
+ DuplicateRunError,
23
+ EnvironmentRecordError,
24
+ InsufficientCoverageError,
25
+ IntegrityMismatchError,
26
+ IntegrityRequiredError,
27
+ InvalidAggregationError,
28
+ InvalidFeatureError,
29
+ InvalidGridError,
30
+ InvalidMtrlFileError,
31
+ InvalidRecordRevisionError,
32
+ InvalidTransformationError,
33
+ ManifestVersionWarning,
34
+ MissingLoaderError,
35
+ MissingOptionalDependencyError,
36
+ MtrlError,
37
+ MtrlFormatError,
38
+ ReceiptUnavailableError,
39
+ RegistryAmbiguityError,
40
+ RegistryCollisionError,
41
+ ReplayIneligibleError,
42
+ ReplayPlanError,
43
+ SourceBundleError,
44
+ TableDuplicateError,
45
+ TableLimitError,
46
+ TablePlanError,
47
+ TableSelectionError,
48
+ UnexportableCheckpointError,
49
+ UnknownCheckpointError,
50
+ UnknownRunError,
51
+ UnrecognisedFileError,
52
+ UnsupportedCommittedValueError,
53
+ UnsupportedDatasetError,
54
+ UnsupportedExportFormatError,
55
+ )
56
+ from mtrl.features import register_supported_features, validate_feature
57
+ from mtrl.integrity import (
58
+ ReceiptLimits,
59
+ forensic_inspect,
60
+ load_receipt,
61
+ receipt_to_text,
62
+ verify_archive,
63
+ )
64
+ from mtrl.models import (
65
+ AggregatedRun,
66
+ AggregationMethod,
67
+ InstrumentRun,
68
+ Manifest,
69
+ MaterialData,
70
+ MetadataField,
71
+ RunCheckpointPair,
72
+ )
73
+ from mtrl.mtrl import Mtrl
74
+ from mtrl.processing import OperationDescriptor
75
+ from mtrl.units import Unit
76
+
77
+ __all__ = [
78
+ "CheckpointExportWarning",
79
+ "AggregatedRun",
80
+ "AggregationMethod",
81
+ "DuplicateCheckpointError",
82
+ "DuplicateRunError",
83
+ "InvalidAggregationError",
84
+ "InvalidGridError",
85
+ "InstrumentRun",
86
+ "InvalidMtrlFileError",
87
+ "InvalidTransformationError",
88
+ "Manifest",
89
+ "ManifestVersionWarning",
90
+ "MaterialData",
91
+ "MetadataField",
92
+ "Mtrl",
93
+ "Unit",
94
+ "MtrlError",
95
+ "MtrlFormatError",
96
+ "RunCheckpointPair",
97
+ "UnexportableCheckpointError",
98
+ "UnknownCheckpointError",
99
+ "UnknownRunError",
100
+ "UnrecognisedFileError",
101
+ "UnsupportedDatasetError",
102
+ "UnsupportedExportFormatError",
103
+ "ArchiveId",
104
+ "RecordId",
105
+ "RevisionId",
106
+ "RecordRef",
107
+ "SourcePolicy",
108
+ "ArchiveLimits",
109
+ "ReceiptLimits",
110
+ "OperationRegistry",
111
+ "OperationDescriptor",
112
+ "VerifyPolicy",
113
+ "VerifyResult",
114
+ "VerifyIssue",
115
+ "Receipt",
116
+ "verify_archive",
117
+ "forensic_inspect",
118
+ "load_receipt",
119
+ "receipt_to_text",
120
+ "UnsupportedCommittedValueError",
121
+ "CommittedRecordMutationError",
122
+ "InvalidRecordRevisionError",
123
+ "ArchiveLimitError",
124
+ "IntegrityMismatchError",
125
+ "AnchorMismatchError",
126
+ "InsufficientCoverageError",
127
+ "ReceiptUnavailableError",
128
+ "IntegrityRequiredError",
129
+ "RegistryCollisionError",
130
+ "RegistryAmbiguityError",
131
+ "MissingLoaderError",
132
+ "MissingOptionalDependencyError",
133
+ "ReplayIneligibleError",
134
+ "ReplayPlanError",
135
+ "TableSelectionError",
136
+ "TablePlanError",
137
+ "TableDuplicateError",
138
+ "TableLimitError",
139
+ "InvalidFeatureError",
140
+ "validate_feature",
141
+ "register_supported_features",
142
+ "EnvironmentRecordError",
143
+ "SourceBundleError",
144
+ ]
@@ -0,0 +1,105 @@
1
+ """Alignment report construction for committed aggregates."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
6
+
7
+ from mtrl._record_resolution import _resolve_exact_record
8
+ from mtrl.exceptions import InvalidAggregationError, UnknownCheckpointError, UnknownRunError
9
+ from mtrl.grids import (
10
+ AlignmentReport,
11
+ _axis_values,
12
+ _member_alignment,
13
+ _recorded_step_identifier,
14
+ _recorded_x_field,
15
+ )
16
+ from mtrl.models import CheckpointType
17
+
18
+ if TYPE_CHECKING:
19
+ from mtrl.mtrl import Mtrl
20
+
21
+
22
+ def _alignment_report_impl(
23
+ container: Mtrl,
24
+ run_id: str,
25
+ checkpoint_id: str,
26
+ ) -> AlignmentReport:
27
+ """Collect the recorded alignment facts of one committed aggregate.
28
+
29
+ The caller checks committed integrity before it calls this helper. The
30
+ helper reads committed records and stores nothing.
31
+
32
+ Args:
33
+ container: The container that holds the aggregate and its members.
34
+ run_id: The identifier of the run holding the aggregate checkpoint.
35
+ checkpoint_id: The identifier of the aggregated checkpoint.
36
+
37
+ Returns:
38
+ The immutable alignment report for that committed aggregate.
39
+
40
+ Raises:
41
+ UnknownRunError: If the container holds no run with that run_id.
42
+ UnknownCheckpointError: If the run holds no checkpoint with that
43
+ checkpoint_id.
44
+ InvalidAggregationError: If the checkpoint is not at stage
45
+ ``aggregated``, records no member references, a member reference
46
+ does not resolve to the exact committed record it names, the owning
47
+ run of a member record cannot be found, or a member or the
48
+ aggregate holds no readable axis.
49
+ """
50
+ run = container.get_run(run_id)
51
+ if run is None:
52
+ raise UnknownRunError(f"No run {run_id!r} in this Mtrl container")
53
+ checkpoint = run.get_checkpoint(checkpoint_id)
54
+ if checkpoint is None:
55
+ raise UnknownCheckpointError(f"No checkpoint {checkpoint_id!r} in run {run_id!r}")
56
+ if checkpoint.type is not CheckpointType.AGGREGATED:
57
+ raise InvalidAggregationError(
58
+ "alignment_report requires a checkpoint at stage 'aggregated'; "
59
+ f"checkpoint {checkpoint_id!r} of run {run_id!r} is at stage "
60
+ f"{checkpoint.type.value!r}."
61
+ )
62
+ member_refs = tuple(checkpoint.lineage.input_refs)
63
+ if not member_refs:
64
+ raise InvalidAggregationError(
65
+ "alignment_report requires an aggregation that records its "
66
+ f"member references; checkpoint {checkpoint_id!r} of run "
67
+ f"{run_id!r} records none."
68
+ )
69
+ x_field = _recorded_x_field(checkpoint)
70
+ aggregate_axis = _axis_values(
71
+ checkpoint, x_field, "alignment report aggregate", InvalidAggregationError
72
+ )
73
+ members = []
74
+ for member_ref in member_refs:
75
+ member_record = _resolve_exact_record(
76
+ container,
77
+ member_ref,
78
+ caller_name="alignment_report",
79
+ reference_label="member reference",
80
+ error_type=InvalidAggregationError,
81
+ )
82
+ member_run_id = container._record_run_map.get(member_record.record_id)
83
+ if member_run_id is None:
84
+ raise InvalidAggregationError(
85
+ "alignment_report cannot find the run that holds member "
86
+ f"record {member_record.record_id!r}."
87
+ )
88
+ members.append(
89
+ _member_alignment(
90
+ member_record,
91
+ run_id=member_run_id,
92
+ x_field=x_field,
93
+ resolve_record=container.get_record,
94
+ )
95
+ )
96
+ return AlignmentReport(
97
+ run_id=run_id,
98
+ checkpoint_id=checkpoint_id,
99
+ record_id=checkpoint.record_id,
100
+ method=_recorded_step_identifier(checkpoint),
101
+ x_field=x_field,
102
+ aggregate_points=int(aggregate_axis.size),
103
+ aggregate_span=float(aggregate_axis.max()) - float(aggregate_axis.min()),
104
+ members=tuple(members),
105
+ )
@@ -0,0 +1,73 @@
1
+ """Archive document normalisation and metadata decoding."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Mapping
6
+ from typing import Any, cast
7
+
8
+ from mtrl.exceptions import CanonicalisationError, InvalidArchiveStructureError
9
+ from mtrl.integrity.canonical import decode_metadata_from_archive
10
+
11
+ _CANONICAL_OPERATION_PARAMETER_PATHS = (
12
+ ("*", "lineage", "transformation", "parameters"),
13
+ ("*", "lineage", "provenance", "effective_parameters"),
14
+ )
15
+
16
+
17
+ def _normalise_new_object_list(
18
+ document: Any,
19
+ key: str,
20
+ label: str,
21
+ ) -> list[dict[str, Any]]:
22
+ """Read a list of objects from an array or named wrapper."""
23
+ if isinstance(document, Mapping):
24
+ if key in document:
25
+ document = document[key]
26
+ else:
27
+ identity_field = {
28
+ "checkpoints": "checkpoint_id",
29
+ "records": "record_id",
30
+ "revisions": "revision_id",
31
+ "runs": "run_id",
32
+ }.get(key)
33
+ if identity_field is not None and identity_field in document:
34
+ document = [document]
35
+ elif identity_field is not None:
36
+ document = [
37
+ {
38
+ **value,
39
+ identity_field: value.get(identity_field, identity),
40
+ }
41
+ for identity, value in document.items()
42
+ if isinstance(value, Mapping)
43
+ ]
44
+ else:
45
+ document = []
46
+ if not isinstance(document, list):
47
+ raise InvalidArchiveStructureError(f"New archive {label} document is not a list.")
48
+ if not all(isinstance(entry, Mapping) for entry in document):
49
+ raise InvalidArchiveStructureError(f"New archive {label} descriptors must be objects.")
50
+ return [cast(dict[str, Any], entry) for entry in document]
51
+
52
+
53
+ def _deserialise_metadata_field(field_data: Any) -> Any:
54
+ """Decode one canonical metadata field with its typed value wrapper."""
55
+ if not isinstance(field_data, Mapping):
56
+ raise InvalidArchiveStructureError(
57
+ "Canonical metadata fields must be objects with a typed value wrapper."
58
+ )
59
+ serialised = dict(field_data)
60
+ if "value" not in serialised:
61
+ raise InvalidArchiveStructureError(
62
+ "Canonical metadata fields must contain a typed value wrapper."
63
+ )
64
+ try:
65
+ serialised["value"] = decode_metadata_from_archive(
66
+ serialised["value"],
67
+ archive_format="canonical",
68
+ )
69
+ except CanonicalisationError as error:
70
+ raise InvalidArchiveStructureError(
71
+ "Canonical metadata value is not a valid recursive typed wrapper."
72
+ ) from error
73
+ return serialised