Skip to main content

Array Tree

A generic hierarchical tree data structure backed by NumPy structured arrays, with typed node payloads.

ArrayTree stores tree topology (parent, child, and sibling pointers) in a compact NumPy structured array for cache-friendly memory layout and efficient bulk operations. Payloads are stored separately in a typed list, so the tree works with any Python object — strings, dicts, dataclasses, or the included DataNode container for data + metadata.

Designed for CAE (Computer-Aided Engineering) workflows where trees represent assembly structures, material hierarchies, and analysis results with thousands of nodes carrying large numerical arrays.

Key features

  • Generic — ArrayTree[T] accepts any payload type
  • NumPy-backed topology — structured array with uint32 IDs, ~29 bytes per node
  • Soft deletion — O(1) delete, explicit repack() for compaction
  • Lazy loading — LazyDataNode loads array data on demand, releases to free memory
  • Frozen mode — prevent mutations after construction
  • Zero hard dependencies beyond NumPy

Installation

pip install vcti-array-tree>=1.4.0

In pyproject.toml dependencies

dependencies = [
    "vcti-array-tree>=1.4.0",
]

Quick Start

from vcti.arraytree import ArrayTree, DataNode

# Create a tree with any payload type
tree: ArrayTree[str] = ArrayTree()

# Add nodes (root is always id=0)
models = tree.add_node(0, data="models")
results = tree.add_node(0, data="results")
stress = tree.add_node(results, data="stress")

# Navigate
children = tree.get_children_ids(0)        # [1, 2]
parent = tree.get_parent_id(stress)         # 2 (results)
all_nodes = tree.iter_nodes(0)              # [1, 2, 3] depth-first

# Access and update payloads
tree.get_node(stress)                       # "stress"
tree.set_node(stress, "von_mises_stress")   # update payload

# Ancestry and depth
tree.get_ancestor_ids(stress)               # [2, 0] (results, root)
tree.get_depth(stress)                      # 2

# Soft-delete and repack
tree.delete_node(models)
mapping = tree.repack()                     # compacts, remaps IDs

# Freeze for read-only access
tree.freeze()

With DataNode payloads

import numpy as np
from vcti.arraytree import ArrayTree, DataNode

tree: ArrayTree[DataNode] = ArrayTree()

tree.add_node(0, DataNode(
    data=np.array([1.0, 2.0, 3.0]),
    attributes={'units': 'mm', 'name': 'displacement'},
))

tree.add_node(0, DataNode(
    attributes={'type': 'group', 'solver': 'NASTRAN'},
))

Error handling

from vcti.arraytree import ArrayTree

tree: ArrayTree[str] = ArrayTree()
node = tree.add_node(0, "data")

# KeyError — node doesn't exist
try:
    tree.get_node(999)
except KeyError:
    pass

# ValueError — node is deleted
tree.delete_node(node)
try:
    tree.get_node(node)
except ValueError:
    pass

# RuntimeError — tree is frozen
tree.freeze()
try:
    tree.add_node(0, "blocked")
except RuntimeError:
    pass

Core API

ArrayTree[T]

Method Description
add_node(parent_id, data) Add child node, returns new ID
set_node(node_id, data) Update payload for existing node
delete_node(node_id, recursive) Soft-delete (marks inactive)
get_node(node_id) Get payload (O(1))
get_parent_id(node_id) Get parent ID
get_children_ids(node_id) List child IDs
get_ancestor_ids(node_id) List ancestor IDs (parent to root)
get_depth(node_id) Depth of node (root = 0)
iter_nodes(root_id, recursive) Depth-first traversal
get_all_node_ids(active_only) All node IDs
repack(new_capacity) Remove deleted nodes, compact arrays
freeze(payloads=False) Freeze structure; optionally freeze payloads too
is_payloads_frozen() True if payloads are also frozen
count_nodes(active_only) Count nodes
get_capacity() Current pre-allocated capacity
len(tree) Number of active nodes
node_id in tree Check if node is active
for nid in tree Iterate active node IDs
get_path(node_id) Path from root to node
tree.topology Read-only numpy view of tree structure
tree.payloads Read-only tuple of payloads

DataNode

Simple container for tree node payloads:

Attribute Type Description
data Any (ndarray, MaskedArray, etc.) or None Data payload
attributes dict[str, Any] Metadata dictionary

LazyDataNode

DataNode subclass with on-demand loading for large arrays:

from vcti.arraytree import ArrayTree, LazyDataNode

tree: ArrayTree[LazyDataNode] = ArrayTree()

node = LazyDataNode(
    loader=lambda: load_stress_data(path, offset),
    attributes={'units': 'MPa', 'name': 'stress'},
)
nid = tree.add_node(0, node)

# Attributes always available
tree.get_node(nid).attributes       # {'units': 'MPa', 'name': 'stress'}

# Array loaded on demand
tree.get_node(nid).is_loaded        # False
tree.get_node(nid).load()           # calls loader, caches result
tree.get_node(nid).is_loaded        # True
tree.get_node(nid).release()        # frees array, can reload later
Method/Property Description
load() Load array via callback (idempotent)
release() Free array data, attributes stay resident
is_loaded True if array is in memory

Configuration

The ID dtype and sentinel value are configurable per tree:

import numpy as np
from vcti.arraytree import ArrayTree

tree = ArrayTree(id_dtype=np.uint64)          # 64-bit node IDs
tree.id_dtype                                  # dtype('uint64')
tree.invalid_id                                # 18446744073709551615
tree.tree_dtype                                # structured dtype for topology

The make_tree_dtype(id_dtype) helper builds the structured dtype for external consumers (e.g., file loaders building topology arrays).

Exceptions

Exception Raised when
KeyError Node ID doesn't exist
ValueError Node is deleted, or invalid operation (e.g., delete root)
RuntimeError Tree structure is frozen, or payloads are frozen

Dependencies

Metadata

Release files for vcti-array-tree 1.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vcti-array-tree 1.4.0
File Size Uploaded
vcti_array_tree-1.4.0.tar.gz 22.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vcti-array-tree 1.4.0
File Interpreter ABI Platform
vcti_array_tree-1.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 37.1 kB

Release files / vcti_array_tree-1.4.0.tar.gz

Download URL vcti_array_tree-1.4.0.tar.gz
Size 22.8 kB
Tags Source
SHA-256 checksum
How to use checksums
0e0e91de0b10dc0b25f57331a2719a717d7661c246bc72aa770b2753f445e1d7
BLAKE2b-256 checksum
How to use checksums
28b7b079437841e07551eab623fdc8937097eb381d790bf2fe59397397ee14de
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 6, 2026.

Transparency log

Release files / vcti_array_tree-1.4.0-py3-none-any.whl

Download URL vcti_array_tree-1.4.0-py3-none-any.whl
Size 14.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e133e4d0a8cf6a2d014e65e866b3664d8862d63231c9fa65ba8a3f658f25f3be
BLAKE2b-256 checksum
How to use checksums
c4a662a636c725798b36bdd7712da471eb51cf4202c2c03679183cb998801423
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.4.0 This release

2 release files

1.3.0

2 release files

1.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page