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.
- mtrl/__init__.py +144 -0
- mtrl/_alignment_report.py +105 -0
- mtrl/_archive_documents.py +73 -0
- mtrl/_archive_integrity.py +539 -0
- mtrl/_archive_loading.py +1070 -0
- mtrl/_archive_serialise.py +696 -0
- mtrl/_candidate_matching.py +216 -0
- mtrl/_cli.py +28 -0
- mtrl/_disclosure.py +735 -0
- mtrl/_ingestion_shortcuts.py +99 -0
- mtrl/_install_targets.py +36 -0
- mtrl/_optional.py +38 -0
- mtrl/_provenance.py +32 -0
- mtrl/_receipts.py +211 -0
- mtrl/_record_resolution.py +60 -0
- mtrl/_replay_plan.py +557 -0
- mtrl/_replay_run.py +734 -0
- mtrl/_run_management.py +400 -0
- mtrl/_source_capture.py +507 -0
- mtrl/_table_plan.py +271 -0
- mtrl/_table_provenance.py +387 -0
- mtrl/_table_values.py +188 -0
- mtrl/_transform_apply.py +223 -0
- mtrl/_transform_validation.py +1367 -0
- mtrl/archive/__init__.py +54 -0
- mtrl/archive/canonical.py +45 -0
- mtrl/archive/codecs.py +88 -0
- mtrl/archive/dtypes.py +39 -0
- mtrl/archive/reader.py +945 -0
- mtrl/archive/validation.py +1872 -0
- mtrl/connectors/__init__.py +1 -0
- mtrl/connectors/protocols.py +84 -0
- mtrl/disclosure.py +273 -0
- mtrl/domain/__init__.py +129 -0
- mtrl/domain/archive_limits.py +46 -0
- mtrl/domain/committed_values.py +539 -0
- mtrl/domain/frozen_containers.py +168 -0
- mtrl/domain/identities.py +174 -0
- mtrl/domain/provenance.py +448 -0
- mtrl/domain/records.py +233 -0
- mtrl/domain/revisions.py +121 -0
- mtrl/domain/source.py +13 -0
- mtrl/domain/verification.py +302 -0
- mtrl/excel.py +139 -0
- mtrl/exceptions.py +215 -0
- mtrl/exports.py +326 -0
- mtrl/features.py +251 -0
- mtrl/frames.py +228 -0
- mtrl/grids.py +1172 -0
- mtrl/integrity/__init__.py +143 -0
- mtrl/integrity/canonical.py +511 -0
- mtrl/integrity/digests.py +363 -0
- mtrl/integrity/manifest.py +631 -0
- mtrl/integrity/receipts.py +771 -0
- mtrl/integrity/verification.py +1303 -0
- mtrl/models.py +952 -0
- mtrl/mtrl.py +1852 -0
- mtrl/operations/__init__.py +36 -0
- mtrl/operations/_identity.py +17 -0
- mtrl/operations/_validation.py +106 -0
- mtrl/operations/arithmetic.py +207 -0
- mtrl/operations/base.py +292 -0
- mtrl/operations/resampling.py +203 -0
- mtrl/operations/resampling_scipy.py +138 -0
- mtrl/operations/spectra.py +58 -0
- mtrl/processing/__init__.py +23 -0
- mtrl/processing/_table_capture.py +341 -0
- mtrl/processing/limits.py +9 -0
- mtrl/processing/registry.py +1533 -0
- mtrl/protocols.py +13 -0
- mtrl/py.typed +0 -0
- mtrl/replay.py +946 -0
- mtrl/tables.py +1365 -0
- mtrl/transformations/__init__.py +22 -0
- mtrl/transformations/base.py +17 -0
- mtrl/units.py +60 -0
- vector_mtrl-0.2.0.dist-info/METADATA +142 -0
- vector_mtrl-0.2.0.dist-info/RECORD +81 -0
- vector_mtrl-0.2.0.dist-info/WHEEL +4 -0
- vector_mtrl-0.2.0.dist-info/licenses/LICENSE +373 -0
- 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
|