Pipeline-style view over NumPy arrays — shape columns, labels, and rows, then render as text, DataFrame, or HTML
Project description
Array View
A configurable view over a NumPy array — inspect, export, and display without writing boilerplate.
Overview
ArrayView wraps a NumPy array (structured, 1-D, or 2-D) without
copying the underlying data and lets you describe how it should look
— which columns, which rows, what labels — then render it as text, a
pandas DataFrame, or HTML. The original array remains directly accessible as
view.array, so numpy-level work isn't locked out.
It's intended for large arrays (CAE-scale, millions of rows) where printing everything isn't useful. Inspection usually needs something transformed:
- Row selection — head/tail windows or boolean filters
- Column selection — drop internal padding or bookkeeping fields
- Column transformation — flatten
position (3,)→position_x / y / z - Value transformation — resolve integer codes to human names
(
element_type=1 → "QUAD")
All of these apply lazily to the rendered rows only — a 10M-row array with a 25-row window does 25 rows of work.
import numpy as np
from vcti.arrayview import ArrayView
arr = np.array(
[(1, 10.5), (2, 20.1), (3, 30.7)],
dtype=[("id", "i4"), ("value", "f8")],
)
view = ArrayView(arr).set_index("id")
# Render as text.
print(view.to_table())
# The view is a live configuration, not a throwaway. Reconfigure and
# render again — each render reads the current state.
view.set_column_labels({"value": "measurement"}).slice(head=2)
df = view.to_dataframe()
Configuration methods (set_column_labels, set_index, slice, etc.)
return self, so if you prefer the one-expression style the same
steps read top-to-bottom:
view = (ArrayView(arr)
.set_column_labels({"value": "measurement"})
.set_index("id")
.slice(head=10))
text = view.to_table()
Installation
pip install vcti-array-view>=1.1.0
With pandas support (optional — enables to_dataframe() and to_html()):
pip install vcti-array-view[pandas]>=1.1.0
Quick Start
import numpy as np
from vcti.arrayview import ArrayView, FILLER_COLUMNS, LENGTH_COLUMNS
dt = np.dtype([
("node_id", "i4"),
("f0", "V4"), # C++ alignment padding
("element_type", "i4"), # enum ID
("label", "U20"),
("label_len", "i4"), # string-length bookkeeping
("position", "f8", (3,)), # vector field
])
arr = np.zeros(1_000_000, dtype=dt) # imagine this is full of real data
view = (ArrayView(arr)
.exclude_patterns([FILLER_COLUMNS, LENGTH_COLUMNS])
.set_component_names("position", ["x", "y", "z"])
.add_enum_columns({
"element_type_name": ("element_type", {1: "QUAD", 2: "HEX"}),
})
.set_index("node_id")
.slice(head=10))
print(view.to_table()) # text table, first 10 rows
df = view.to_dataframe() # pandas DataFrame, node_id as pd.Index
html = view.to_html() # HTML string for dashboards
Input shapes
ArrayView(array) accepts three input shapes. Structured arrays are
used as-is; plain 1-D and 2-D arrays are reinterpreted as structured via
np.ndarray.view() (zero-copy for C-contiguous input).
# Structured array — fields already named
dt = np.dtype([("id", "i4"), ("value", "f8")])
arr = np.array([(1, 10.0), (2, 20.0)], dtype=dt)
view = ArrayView(arr) # view_columns == ["id", "value"]
# Plain 1-D — single column, default name "value"
view = ArrayView(np.array([1.5, 2.0, 3.5]))
# view_columns == ["value"]
# Plain 2-D — auto-named col_0, col_1, ...
view = ArrayView(np.random.rand(1000, 3))
# view_columns == ["col_0", "col_1", "col_2"]
view.set_column_labels({"col_0": "x", "col_1": "y", "col_2": "z"})
Non-contiguous 2-D arrays raise ValueError — call
np.ascontiguousarray() first if you accept the copy cost. ndim > 2
is rejected; reshape first. For structured 1-D or 2-D input with
meaningful field names, construct a structured array with numpy before
passing it in.
The four kinds of operation
Operations fall into four kinds, each shaping one aspect of the
displayed table. All return self and generally compose in any order
— you can call them any number of times and reconfigure freely between
renders.
Column shaping — which columns appear and in what order
All operations refer to columns by their dtype name, not their display label.
| Method | Effect |
|---|---|
exclude_patterns(patterns) |
Drop columns matching any pattern (exact name, regex, or (name, dtype) -> bool). Pre-built: FILLER_COLUMNS, LENGTH_COLUMNS, VOID_COLUMNS. |
set_view_columns(columns=None) |
Replace the visible list with a whitelist (or reset to all dtype columns when called without an argument). For pattern-based filtering, compose with exclude_patterns. |
include_view_columns(columns) |
Append columns to the visible list. |
drop_view_columns(columns) |
Remove columns from the visible list. |
Label / value shaping — how columns and cells are displayed
Labels affect rendering only. The dtype identity of a column never changes, so other operations keep working after you relabel.
| Method | Effect |
|---|---|
set_column_labels(mapping) |
Set display labels for top-level dtype fields. For a scalar field, the label is the column header; for a multi-component field, it's the level-1 group header. |
set_component_names(field, names) |
Set level-2 labels for the flattened components of a multi-component field (e.g. ["x", "y", "z"]). Defaults to "0", "1", ... when unset. |
add_column_group(name, columns) |
Attach a level-1 header label spanning columns. The chosen name is also the displayed label. Usable as an index source. |
remove_column_group(name) |
Remove a group. Clears the index if the group was the current source. |
add_enum_columns({name: (id_col, {int: str})}) |
Attach a virtual string column that maps integer codes in id_col to human names (e.g., {1: "QUAD", 2: "HEX"}). The new column takes id_col's place in the view. Mapping is applied only to rendered rows — a 10M-row array with a 20-row window does 20 lookups. |
Row shaping — which rows appear and how they are identified
| Method | Effect |
|---|---|
set_index(source) |
Designate row identity. Use a str — a dtype field name for a single-column index, or a column-group name for a multi-column index using the group's members. Use an np.ndarray of matching length for an external identifier (useful when several arrays share the same row identity without duplicating the id into each); a structured ndarray's fields each become a separate index level. Becomes the pandas Index / MultiIndex. |
clear_index() |
Remove the row identifier. |
slice(head=..., tail=..., mask=..., indices=...) |
Configure a bounded window. Output methods render only within this window. |
clear_slice() |
Remove the slice configuration — full range. |
compute_slice() |
Return the integer index array for the current slice (ndarray of np.intp). |
Output methods — materialize the configured view
| Method | Returns |
|---|---|
to_table(...) |
Text table as str (pure numpy, no dependencies). |
to_dataframe(...) |
pandas DataFrame. |
to_html() |
HTML string (pandas under the hood). |
Output methods return the rendered result; they do not consume state. Reconfigure and call again as often as you like.
Why laziness matters
ArrayView is built to keep large arrays tractable — cost scales with
what you render, not with what you hold:
- Bounded slicing —
.slice(head=20, tail=5)renders 25 rows regardless of array size.compute_slice()returns a tiny integer array, not a copy of the data. - Lazy enum resolution —
add_enum_columns({...})stores a recipe. The integer → string mapping is applied only to rows actually rendered. A 10M-row array with a 10-row slice performs 10 lookups. - Reference semantics — the underlying NumPy array is never copied.
Multiple
ArrayViewinstances can share the same array. - Zero-copy dtype reinterpretation — vector/matrix field flattening
uses
np.ndarray.view(), an O(1) dtype change, no memory movement. - pandas categorical columns — enum names materialize as
pd.Categorical, ~100× smaller than string columns.
Branching views with copy()
copy() creates an independent ArrayView over the same underlying
array. Configuration is deep-copied so branches don't affect each
other. Use this when passing a view to code that might reconfigure
it, or when you need two renders with different slices side-by-side.
export_view = view.copy().drop_view_columns(["label"])
view.array is export_view.array # True — underlying array is shared
Row index
set_index(source) designates what each row represents. Two ways to
specify the source:
1. A column (or group) already in the array — pass a string. For a single-column index, pass a dtype field name:
view = ArrayView(arr).set_index("node_id")
For a multi-column index, register a group first and pass its name:
view = (ArrayView(arr)
.add_column_group("face_id", ["element_idx", "face_num"])
.set_index("face_id"))
2. An external identifier array — pass an np.ndarray of matching
length. Useful when several arrays share the same row identity and
you don't want to duplicate the id into each:
face_id = np.array(
[(1, 0), (1, 1), (2, 0)],
dtype=[("element_idx", "i4"), ("face_num", "i4")],
)
stress = ArrayView(stress_arr).set_index(face_id)
strain = ArrayView(strain_arr).set_index(face_id)
A structured ndarray produces a pandas MultiIndex; a plain 1-D array
becomes a single "id" level. See docs/patterns.md
for more recipes.
Dependencies
- numpy (>=2.0) — required
- vcti-nputils (>=1.0.0) — required
- pandas (>=2.2) — optional, for
to_dataframe(),to_html(), and Jupyter display
Further reading
- docs/design.md — rationale behind the pipeline
- docs/api.md — full API reference with signatures
- docs/patterns.md — common usage recipes
- docs/performance.md — complexity analysis and large-array behavior
- docs/troubleshooting.md — errors, fixes, and gotchas
- docs/extending.md — extending the library
- examples/full_pipeline.py — end-to-end builder-style walkthrough
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vcti_array_view-1.1.0.tar.gz.
File metadata
- Download URL: vcti_array_view-1.1.0.tar.gz
- Upload date:
- Size: 39.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c32bdc200ca4fbaa25047eaf00595388b9a36501a49339c741462c0a3644851d
|
|
| MD5 |
fc2cccb010a3dc49d8a48f698c8c512a
|
|
| BLAKE2b-256 |
6fccc2429f6628327719b3e01e4038a330747fd7980eec79874c7857962f73d7
|
Provenance
The following attestation bundles were made for vcti_array_view-1.1.0.tar.gz:
Publisher:
release.yml on vcollab/vcti-python-array-view
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vcti_array_view-1.1.0.tar.gz -
Subject digest:
c32bdc200ca4fbaa25047eaf00595388b9a36501a49339c741462c0a3644851d - Sigstore transparency entry: 1340110917
- Sigstore integration time:
-
Permalink:
vcollab/vcti-python-array-view@830995ed0b37a1a7460aa314316a9adcb36217ab -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/vcollab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@830995ed0b37a1a7460aa314316a9adcb36217ab -
Trigger Event:
push
-
Statement type:
File details
Details for the file vcti_array_view-1.1.0-py3-none-any.whl.
File metadata
- Download URL: vcti_array_view-1.1.0-py3-none-any.whl
- Upload date:
- Size: 26.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
72dffef5fa025357b5c21d997dae0f95c29f752a163716110a9fd3d6e59f819b
|
|
| MD5 |
1711eb55eacc4b6d3ad8f912a5f19c81
|
|
| BLAKE2b-256 |
f35eeda89474e0dc3409e9cd4f84d10614b3421b5dead264f80b13e6f6b226ad
|
Provenance
The following attestation bundles were made for vcti_array_view-1.1.0-py3-none-any.whl:
Publisher:
release.yml on vcollab/vcti-python-array-view
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vcti_array_view-1.1.0-py3-none-any.whl -
Subject digest:
72dffef5fa025357b5c21d997dae0f95c29f752a163716110a9fd3d6e59f819b - Sigstore transparency entry: 1340110921
- Sigstore integration time:
-
Permalink:
vcollab/vcti-python-array-view@830995ed0b37a1a7460aa314316a9adcb36217ab -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/vcollab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@830995ed0b37a1a7460aa314316a9adcb36217ab -
Trigger Event:
push
-
Statement type: