Metadata-Version: 2.5
Name: vector-mtrl
Version: 0.2.0
Summary: Materials research tools for spectra and archive workflows.
Author-email: Fuzzy Labs <info@fuzzylabs.ai>
License-Expression: MPL-2.0
License-File: LICENSE
License-File: NOTICE
Requires-Python: <4.0,>=3.14
Requires-Dist: numpy>=2.5.2
Requires-Dist: pydantic>=2.13.4
Requires-Dist: rfc8785==0.1.4
Provides-Extra: excel
Requires-Dist: openpyxl>=3.1.5; extra == 'excel'
Requires-Dist: pandas>=3.0.5; extra == 'excel'
Provides-Extra: interp
Requires-Dist: scipy>=1.16; extra == 'interp'
Provides-Extra: tabular
Requires-Dist: pandas>=3.0.5; extra == 'tabular'
Description-Content-Type: text/markdown

# vector-mtrl

`mtrl` reads, checks, and writes materials data archives. It records each scientific result as an
immutable record with exact lineage.

## What you get

- Immutable committed records with stable identities and complete lineage.
- Bounded `.mtrl` archives with an integrity manifest, external receipts, and forensic inspection.
- NumPy-only operations: identity, scale, offset, peak normalisation, zero-at-point, and linear
  resample, beside mean and median aggregates.
- Explicit analysis grids and a read-only alignment report.
- A read-only replay plan, a capability view, and a detached rerun for committed chains.
- Author disclosure that stays inert: stored environment records and passive source bundles that
  MTRL never imports or executes.
- CSV export without pandas.
- Optional extras add SciPy resampling, pandas conversion, and Excel export.

## Install

`vector-mtrl` requires Python 3.14 or newer, below Python 4. The base install depends only on
NumPy, Pydantic, and RFC 8785 canonical JSON. Create one environment and install the core:

```sh
uv venv --python 3.14
uv pip install --python .venv/bin/python vector-mtrl
```

## Quick start

Commit one synthetic spectrum, normalise it, save an archive, verify it, load it, and export
CSV. The base install alone runs every step.

### Example: Quick start

**Required install:** `vector-mtrl`

```python
from pathlib import Path
from tempfile import TemporaryDirectory

import numpy as np

from mtrl import InstrumentRun, MaterialData, Mtrl, verify_archive

application = Mtrl(sample_id="sample-01")
run = InstrumentRun(run_name="replicate-01")
axis = np.array([2000.0, 2100.0, 2200.0])
content = np.empty(axis.size, dtype=[("wavenumber", "<f8"), ("absorbance", "<f8")])
content["wavenumber"] = axis
content["absorbance"] = [0.1, 0.2, 0.3]
checkpoint = MaterialData(
    content=content,
    type="raw",
    checkpoint_name="spectrum",
)
run.add_checkpoint(checkpoint)
application.add(run)

normalised = application.transform(
    run.run_id,
    checkpoint.checkpoint_id,
    "normalise_peak",
)
print(normalised.lineage.provenance.qualified_identifier)

with TemporaryDirectory() as directory:
    archive_path = application.save(Path(directory) / "sample.mtrl")
    verification = verify_archive(archive_path)
    print(verification.structural_status.value, verification.hash_status.value)

    loaded = Mtrl.load(archive_path)
    print(loaded.sample_id, loaded.get_run(run.run_id) is not None)
    csv_path = loaded.export_checkpoint(
        run.run_id,
        normalised.checkpoint_id,
        Path(directory) / "signal.csv",
    )
    exported = np.genfromtxt(csv_path, delimiter=",", names=True)
    np.testing.assert_allclose(exported["absorbance"], [1 / 3, 2 / 3, 1])
    print(csv_path.is_file())
```

`Mtrl.add()` commits a detached copy, so later changes to your arrays cannot alter the record.
Every mutation, including the transform above, creates one new revision.

## Guides

The expanded guides ship in the source archive under `docs/user/`. Download the archive for a
release from https://pypi.org/project/vector-mtrl/#files, then read:

- `docs/user/getting-started.md` for installation, first records, and the save, load, verify,
  and export loop.
- `docs/user/workflows.md` for corrections, replacements, transforms, resampling, aggregates,
  alignment reports, replay, receipts, forensic inspection, disclosure, exports, and registry
  control.
- `docs/user/reference.md` for every public route, the stable typed imports, the exact
  package-root export list, registry names, format features, and the archive safety contract.

## Archive and provenance limits

MTRL reads `.mtrl` archives inside configured size and member limits, and it validates paths,
entries, JSON, references, payloads, and integrity before it returns data. It does not extract
archive files.

Archive content does not install packages, does not import operation code, does not change a
registry, does not execute stored source, and does not change committed records directly.
Committed records are immutable: use `Mtrl` methods to create a new record version or change the
active view.

New archives require integrity coverage. Keep a receipt outside the archive if you need to
detect a complete rewrite. A receipt has no signature, so send it through a separate trusted
channel. `forensic_inspect()` reports damaged archive facts, but it does not return damaged data
for normal analysis. MTRL verifies digests and never verifies your execution environment:
environment records are author claims, not checked facts.

## Licence

The core is licensed under the MPL-2.0. Read the licence text in `LICENSE` and the inherited
notices in `NOTICE`, both included in this distribution. The upstream licence reference is
https://www.mozilla.org/en-US/MPL/2.0/.
