Metadata-Version: 2.4
Name: vcti-datanode
Version: 2.0.0
Summary: Lightweight data-plus-attributes node containers, with an optional lazily-loaded variant for out-of-core data.
Author: Visual Collaboration Technologies Inc.
Requires-Python: <3.15,>=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.26
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Provides-Extra: lint
Requires-Dist: ruff; extra == "lint"
Provides-Extra: typecheck
Requires-Dist: mypy; extra == "typecheck"
Dynamic: license-file

# Data Node

The node value type for a hierarchical data model — a single `DataNode` that
composes optional array data, structural identity, and layered metadata.

## Overview

`vcti-datanode` provides `DataNode`, the payload for a tree whose nodes carry
**heavy array data**, **metadata**, both, or neither. A node composes three
independent, optional parts rather than splitting into a subclass per
combination:

- a **`DataSource`** — how the node's array is obtained and how long it stays
  resident. `EagerDataSource` wraps an array already in hand; `LazyDataSource`
  produces one on demand via a callable (read a file, compute a derived array,
  query a service) and can be released and re-loaded. A node with no data has
  no data source.
- **`intrinsic`** attributes — the node's structural identity (`name`, `shape`,
  `dtype`, …), kept in their own namespace so they never collide with free-form
  metadata.
- **metadata** in two provenance layers — `source_attributes` (immutable, as
  received) and `enriched_attributes` (mutable, added later), merged for
  reading as `attributes`.

It is built for CAE-style models read from a file (or built in memory),
transformed, and exported — but depends on nothing beyond numpy and works
anywhere a data-plus-metadata node is useful. See [docs/design.md](docs/design.md)
for the concepts and rationale.

## Installation

```bash
pip install vcti-datanode
```

### In `requirements.txt`

```
vcti-datanode>=2.0.0
```

### In `pyproject.toml` dependencies

```toml
dependencies = [
    "vcti-datanode>=2.0.0",
]
```

---

## Quick Start

```python
import numpy as np
from vcti.datanode import DataNode, EagerDataSource, LazyDataSource

# A metadata-only node (no data) — e.g. a grouping node.
group = DataNode(name="results", enriched_attributes={"analysis": "modal"})

# An eager node: the array is already in hand.
stress = DataNode(
    name="stress",
    data_source=EagerDataSource(np.array([1.0, 2.0, 3.0])),
    source_attributes={"units": "MPa"},
)
stress.shape            # (3,) — a derived intrinsic, read without touching data
stress.attributes["units"]   # 'MPa'

# A lazy node: the array is fetched on demand and can be released.
disp = DataNode(
    name="displacement",
    data_source=LazyDataSource(lambda: np.load("disp.npy"), shape=(2, 3), dtype="float64"),
    source_attributes={"units": "mm"},
)
disp.is_loaded          # False — but disp.shape is already (2, 3)
arr = disp.load()       # loader runs once; cached thereafter
disp.unload()           # frees the array; metadata and intrinsics remain
```

Comparison is explicit (nodes compare by identity, not value):

```python
from vcti.datanode import metadata_equal, data_equal, node_equal

metadata_equal(a, b)    # intrinsic + metadata; never loads data
data_equal(a, b)        # compares arrays, materialising if needed
node_equal(a, b)        # both
```

Run the example end to end to see the package working:

```bash
python examples/basic_usage.py
```

---

## Documentation

- [Changelog](CHANGELOG.md) — Release history and versioning policy
- [Design](docs/design.md) — Concepts and the rationale behind the model
- [Source Guide](docs/source-guide.md) — File descriptions and execution flows
- [Extension Guide](docs/extending.md) — Writing a custom `DataSource`
- [API Reference](docs/api.md) — Autodoc for all modules
- [`examples/basic_usage.py`](examples/basic_usage.py) — Runnable tour of the API

---

## Dependencies

- `numpy>=1.26` — array data, and structural facts (`shape`/`dtype`).
