views-frames 1.10.0__tar.gz → 1.10.2__tar.gz
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.
- {views_frames-1.10.0 → views_frames-1.10.2}/PKG-INFO +3 -3
- {views_frames-1.10.0 → views_frames-1.10.2}/README.md +2 -2
- {views_frames-1.10.0 → views_frames-1.10.2}/pyproject.toml +1 -1
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/feature_frame.py +12 -6
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/io/arrow.py +47 -4
- {views_frames-1.10.0 → views_frames-1.10.2}/.gitignore +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/LICENSE +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/__init__.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/_typing.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/_validation.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/conformance/__init__.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/index.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/io/__init__.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/io/npz.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/metadata.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/prediction_frame.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/protocols.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/py.typed +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/spatial_level.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames/target_frame.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_reconcile/__init__.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_reconcile/conformance.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_reconcile/frames.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_reconcile/grouping.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_reconcile/module.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_reconcile/proportional.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_reconcile/py.typed +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_reconcile/result.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_reconcile/validation.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/__init__.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/_common.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/aggregate.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/bimodality.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/collapse.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/config.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/conformance.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/exceedance.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/expected_shortfall.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/interval.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/point.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/py.typed +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/summarize_tower.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/tower.py +0 -0
- {views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/tower_point.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: views-frames
|
|
3
|
-
Version: 1.10.
|
|
3
|
+
Version: 1.10.2
|
|
4
4
|
Summary: The VIEWS platform data-contract layer: immutable array+identifier frames (numpy only, root of the dependency DAG).
|
|
5
5
|
Project-URL: Homepage, https://github.com/views-platform/views-frames
|
|
6
6
|
Project-URL: Repository, https://github.com/views-platform/views-frames
|
|
@@ -36,7 +36,7 @@ Description-Content-Type: text/markdown
|
|
|
36
36
|
> containers (`FeatureFrame`, `PredictionFrame`, and their anticipated siblings)
|
|
37
37
|
> that every other repo depends on and that depends on nothing internal.
|
|
38
38
|
>
|
|
39
|
-
> **Status:** **v1.10.
|
|
39
|
+
> **Status:** **v1.10.2 — frozen API, published to PyPI** (frozen since v1.0.0, ADR-018; the
|
|
40
40
|
> v1.1 surface is
|
|
41
41
|
> purely additive — the coherent posterior summary, ADR-019; v1.2.0 rebuilt the tower
|
|
42
42
|
> `outside-in`, C-44; v1.3.0 makes the tower summary distribution-agnostic — no magnitude
|
|
@@ -53,7 +53,7 @@ Description-Content-Type: text/markdown
|
|
|
53
53
|
> `research/figures/` tower-figure toolkit; v1.10.0 adds the **dense-grid fill**
|
|
54
54
|
> primitive — `reindex_fill(other, *, fill_value)` on all three frames +
|
|
55
55
|
> `SpatioTemporalIndex.cartesian` + the published `assert_reindex_fill_law`, ADR-026,
|
|
56
|
-
> unblocking pandas-free FAO ingestion). This
|
|
56
|
+
> unblocking pandas-free FAO ingestion; v1.10.1 makes `io.arrow.load` fail loudly on a parquet whose row order breaks the wire contract, #199; v1.10.2 changes no behaviour — it arms the documentation check in CI, turns eleven falsification tests from README-wording checks into behaviour checks, and records ADR-027 declining the construction shortcut). This
|
|
57
57
|
> README is the design
|
|
58
58
|
> bible; the contract it specifies is realised in `src/views_frames/` (index, frames,
|
|
59
59
|
> io, conformance suite) plus the `src/views_frames_summarize/` sibling package
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
> containers (`FeatureFrame`, `PredictionFrame`, and their anticipated siblings)
|
|
5
5
|
> that every other repo depends on and that depends on nothing internal.
|
|
6
6
|
>
|
|
7
|
-
> **Status:** **v1.10.
|
|
7
|
+
> **Status:** **v1.10.2 — frozen API, published to PyPI** (frozen since v1.0.0, ADR-018; the
|
|
8
8
|
> v1.1 surface is
|
|
9
9
|
> purely additive — the coherent posterior summary, ADR-019; v1.2.0 rebuilt the tower
|
|
10
10
|
> `outside-in`, C-44; v1.3.0 makes the tower summary distribution-agnostic — no magnitude
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
> `research/figures/` tower-figure toolkit; v1.10.0 adds the **dense-grid fill**
|
|
22
22
|
> primitive — `reindex_fill(other, *, fill_value)` on all three frames +
|
|
23
23
|
> `SpatioTemporalIndex.cartesian` + the published `assert_reindex_fill_law`, ADR-026,
|
|
24
|
-
> unblocking pandas-free FAO ingestion). This
|
|
24
|
+
> unblocking pandas-free FAO ingestion; v1.10.1 makes `io.arrow.load` fail loudly on a parquet whose row order breaks the wire contract, #199; v1.10.2 changes no behaviour — it arms the documentation check in CI, turns eleven falsification tests from README-wording checks into behaviour checks, and records ADR-027 declining the construction shortcut). This
|
|
25
25
|
> README is the design
|
|
26
26
|
> bible; the contract it specifies is realised in `src/views_frames/` (index, frames,
|
|
27
27
|
> io, conformance suite) plus the `src/views_frames_summarize/` sibling package
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "views-frames"
|
|
7
|
-
version = "1.10.
|
|
7
|
+
version = "1.10.2"
|
|
8
8
|
description = "The VIEWS platform data-contract layer: immutable array+identifier frames (numpy only, root of the dependency DAG)."
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Simon Polichinel von der Maase", email = "simmaa@prio.org" },
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"""`FeatureFrame` — model inputs (X): ``y_features (N, F, S)`` float32.
|
|
2
2
|
|
|
3
3
|
A sibling frame (no shared base; ADR-011 Option C). Relocated from
|
|
4
|
-
views-datafactory. The sample axis is **always explicit** (ADR-012)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
(ADR-013). ``from_grid`` is
|
|
4
|
+
views-datafactory. The sample axis is **always explicit** (ADR-012), so
|
|
5
|
+
unsampled features are stored as ``(N, F, 1)``; :meth:`from_2d` builds such a
|
|
6
|
+
frame from a 2-D ``(N, F)`` array by adding that trailing axis. Carries
|
|
7
|
+
``feature_names`` and a typed metadata header (ADR-013). ``from_grid`` is
|
|
8
|
+
**not** here — it stays in views-datafactory.
|
|
8
9
|
"""
|
|
9
10
|
|
|
10
11
|
from __future__ import annotations
|
|
@@ -38,7 +39,7 @@ class FeatureFrame:
|
|
|
38
39
|
raise ValueError(
|
|
39
40
|
"FeatureFrame y_features must be 3D (N, F, S) with an explicit "
|
|
40
41
|
f"trailing sample axis (ADR-012), got ndim={values.ndim}. "
|
|
41
|
-
"Use FeatureFrame.from_2d to
|
|
42
|
+
"Use FeatureFrame.from_2d to build a frame from a 2-D (N, F) array."
|
|
42
43
|
)
|
|
43
44
|
if values.shape[0] != index.n_rows:
|
|
44
45
|
raise ValueError(
|
|
@@ -62,7 +63,12 @@ class FeatureFrame:
|
|
|
62
63
|
feature_names: list[str],
|
|
63
64
|
metadata: FrameMetadata | None = None,
|
|
64
65
|
) -> FeatureFrame:
|
|
65
|
-
"""
|
|
66
|
+
"""Build a frame from a 2-D ``(N, F)`` array of unsampled features.
|
|
67
|
+
|
|
68
|
+
The sample axis is always explicit (ADR-012), so unsampled features are
|
|
69
|
+
stored as ``(N, F, 1)``. This adds that trailing axis for you. Raises
|
|
70
|
+
``ValueError`` if the input is not 2-D.
|
|
71
|
+
"""
|
|
66
72
|
arr = coerce_values(y_features_2d)
|
|
67
73
|
if arr.ndim != 2:
|
|
68
74
|
raise ValueError(f"from_2d expects a 2D (N, F) array, got ndim={arr.ndim}")
|
|
@@ -71,7 +71,20 @@ def save(
|
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
def load(path: Path | str) -> dict[str, Any]:
|
|
74
|
-
"""Read a flat-columnar parquet frame state written by :func:`save`.
|
|
74
|
+
"""Read a flat-columnar parquet frame state written by :func:`save`.
|
|
75
|
+
|
|
76
|
+
The reconstruction is positional (``reshape(n, s)``), so the table's row
|
|
77
|
+
order **is** the contract: before trusting it, the wire-contract layout is
|
|
78
|
+
validated and any violation **raises** rather than reshaping plausible
|
|
79
|
+
floats into the wrong sample slots (ADR-013 §4.5b wire contract; #199).
|
|
80
|
+
|
|
81
|
+
Raises:
|
|
82
|
+
ValueError: the table is truncated/filtered (row count not a multiple
|
|
83
|
+
of the header's ``n_samples``), the ``sample`` column deviates from
|
|
84
|
+
the written ``tile(arange(S), N)`` order, or ``time``/``unit`` are
|
|
85
|
+
not constant within a row's sample block (rows swapped between
|
|
86
|
+
cells) — a reordered, truncated, or foreign-rewritten table.
|
|
87
|
+
"""
|
|
75
88
|
table = pq.read_table(str(path))
|
|
76
89
|
raw = table.schema.metadata or {}
|
|
77
90
|
header = json.loads(raw[b"views_frames"].decode())
|
|
@@ -80,9 +93,39 @@ def load(path: Path | str) -> dict[str, Any]:
|
|
|
80
93
|
|
|
81
94
|
time_col = table.column("time").to_numpy()
|
|
82
95
|
unit_col = table.column("unit").to_numpy()
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
96
|
+
total = int(time_col.shape[0])
|
|
97
|
+
if s <= 0 or total % s != 0:
|
|
98
|
+
raise ValueError(
|
|
99
|
+
f"corrupt frame parquet: {total} rows is not a positive multiple of "
|
|
100
|
+
f"the header's n_samples={s} — a truncated or filtered table cannot "
|
|
101
|
+
"be reshaped safely (wire contract, #199)"
|
|
102
|
+
)
|
|
103
|
+
n = total // s
|
|
104
|
+
|
|
105
|
+
sample_col = table.column("sample").to_numpy()
|
|
106
|
+
if not np.array_equal(sample_col, np.tile(np.arange(s, dtype=np.int32), n)):
|
|
107
|
+
raise ValueError(
|
|
108
|
+
"corrupt frame parquet: the 'sample' column deviates from the "
|
|
109
|
+
"written tile(arange(S), N) order — the table was reordered or "
|
|
110
|
+
"rewritten, so a positional reshape would silently place draws in "
|
|
111
|
+
"the wrong sample slots (wire contract, #199)"
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
time_blocks = time_col.reshape(n, s)
|
|
115
|
+
unit_blocks = unit_col.reshape(n, s)
|
|
116
|
+
if not (
|
|
117
|
+
bool((time_blocks == time_blocks[:, :1]).all())
|
|
118
|
+
and bool((unit_blocks == unit_blocks[:, :1]).all())
|
|
119
|
+
):
|
|
120
|
+
raise ValueError(
|
|
121
|
+
"corrupt frame parquet: 'time'/'unit' are not constant within a "
|
|
122
|
+
"row's sample block — rows were swapped between cells, so a "
|
|
123
|
+
"positional reshape would silently misattribute draws "
|
|
124
|
+
"(wire contract, #199)"
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
time = time_blocks[:, 0]
|
|
128
|
+
unit = unit_blocks[:, 0]
|
|
86
129
|
|
|
87
130
|
if ndim == 2:
|
|
88
131
|
values = table.column("value").to_numpy().reshape(n, s).astype(np.float32)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{views_frames-1.10.0 → views_frames-1.10.2}/src/views_frames_summarize/expected_shortfall.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|