views-frames 1.2.0__tar.gz → 1.3.0__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.2.0 → views_frames-1.3.0}/PKG-INFO +14 -9
- {views_frames-1.2.0 → views_frames-1.3.0}/README.md +13 -8
- {views_frames-1.2.0 → views_frames-1.3.0}/pyproject.toml +1 -1
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames_summarize/config.py +6 -3
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames_summarize/tower.py +22 -11
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames_summarize/tower_point.py +6 -5
- {views_frames-1.2.0 → views_frames-1.3.0}/.gitignore +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/LICENSE +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/__init__.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/_typing.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/_validation.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/conformance/__init__.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/feature_frame.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/index.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/io/__init__.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/io/arrow.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/io/npz.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/metadata.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/prediction_frame.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/protocols.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/py.typed +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/spatial_level.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames/target_frame.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames_summarize/__init__.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames_summarize/_common.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames_summarize/aggregate.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames_summarize/bimodality.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames_summarize/collapse.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames_summarize/conformance.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames_summarize/interval.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames_summarize/point.py +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames_summarize/py.typed +0 -0
- {views_frames-1.2.0 → views_frames-1.3.0}/src/views_frames_summarize/summarize_tower.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: views-frames
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
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
|
|
@@ -30,9 +30,10 @@ Description-Content-Type: text/markdown
|
|
|
30
30
|
> containers (`FeatureFrame`, `PredictionFrame`, and their anticipated siblings)
|
|
31
31
|
> that every other repo depends on and that depends on nothing internal.
|
|
32
32
|
>
|
|
33
|
-
> **Status:** **v1.
|
|
34
|
-
> purely additive — the coherent posterior summary, ADR-019; v1.2.0
|
|
35
|
-
> `outside-in
|
|
33
|
+
> **Status:** **v1.3.0 — frozen API** (frozen since v1.0.0, ADR-018; the v1.1 surface is
|
|
34
|
+
> purely additive — the coherent posterior summary, ADR-019; v1.2.0 rebuilt the tower
|
|
35
|
+
> `outside-in`, C-44; v1.3.0 makes the tower summary distribution-agnostic — no magnitude
|
|
36
|
+
> zeroing by default, register C-45). This README is the design
|
|
36
37
|
> bible; the contract it specifies is realised in `src/views_frames/` (index, frames,
|
|
37
38
|
> io, conformance suite) plus the `src/views_frames_summarize/` sibling package
|
|
38
39
|
> (sample-axis summarization — `collapse`/MAP/HDI/quantiles, the coherent-tower estimators
|
|
@@ -96,16 +97,20 @@ Both are numpy-only. For the subtler cm↔pgm surface — a time-varying
|
|
|
96
97
|
`aggregate_distributions` (`HDI(sum) ≠ sum(HDI)`) — see
|
|
97
98
|
[`examples/cross_level.py`](examples/cross_level.py).
|
|
98
99
|
|
|
99
|
-
**Which estimator? (two coherent paths, v1.
|
|
100
|
+
**Which estimator? (two coherent paths, v1.3.0).** Each frozen estimator has a
|
|
100
101
|
coherent-tower sibling (ADR-019): `map_estimate` ↔ `tower_point` (an unbinned
|
|
101
102
|
median-of-the-`tip_mass`-floor point — the "shorth", free of `map_estimate`'s histogram
|
|
102
103
|
tie-break bias **and** robust to minority duplicated draws, register C-44), and
|
|
103
104
|
`hdi`/`quantiles` ↔ `hdi_tower(masses=…)` (HDIs built **outside-in**, nested **by
|
|
104
105
|
construction** and reproducible — a mass's interval is identical regardless of which others
|
|
105
|
-
you request), with `summarize_tower` returning all three in one pass. The tower
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
you request), with `summarize_tower` returning all three in one pass. The tower path is
|
|
107
|
+
**distribution-agnostic** — it works for counts, continuous, normal, and `[0,1]`
|
|
108
|
+
(rate/probability) targets, with **no magnitude zeroing by default** (zero-inflation is read
|
|
109
|
+
off the floor's density, register C-45); a count consumer that wants "sub-1 ⇒ 0" opts in via
|
|
110
|
+
`config['zero_cutoff']`. The tower's tunables live in `views_frames_summarize.config`
|
|
111
|
+
(fail-loud, no silent defaults). Use the **frozen** estimators for parity with existing
|
|
112
|
+
pipelines; use the **tower** path when you need coherent, reproducible bands plus a matching,
|
|
113
|
+
duplicate-robust point.
|
|
109
114
|
|
|
110
115
|
**Reading the `bimodality` flag.** It is a *deliberately conservative* heuristic, **not** a
|
|
111
116
|
formal multimodality test — tuned for **zero false positives** at the cost of recall on
|
|
@@ -4,9 +4,10 @@
|
|
|
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.
|
|
8
|
-
> purely additive — the coherent posterior summary, ADR-019; v1.2.0
|
|
9
|
-
> `outside-in
|
|
7
|
+
> **Status:** **v1.3.0 — frozen API** (frozen since v1.0.0, ADR-018; the v1.1 surface is
|
|
8
|
+
> purely additive — the coherent posterior summary, ADR-019; v1.2.0 rebuilt the tower
|
|
9
|
+
> `outside-in`, C-44; v1.3.0 makes the tower summary distribution-agnostic — no magnitude
|
|
10
|
+
> zeroing by default, register C-45). This README is the design
|
|
10
11
|
> bible; the contract it specifies is realised in `src/views_frames/` (index, frames,
|
|
11
12
|
> io, conformance suite) plus the `src/views_frames_summarize/` sibling package
|
|
12
13
|
> (sample-axis summarization — `collapse`/MAP/HDI/quantiles, the coherent-tower estimators
|
|
@@ -70,16 +71,20 @@ Both are numpy-only. For the subtler cm↔pgm surface — a time-varying
|
|
|
70
71
|
`aggregate_distributions` (`HDI(sum) ≠ sum(HDI)`) — see
|
|
71
72
|
[`examples/cross_level.py`](examples/cross_level.py).
|
|
72
73
|
|
|
73
|
-
**Which estimator? (two coherent paths, v1.
|
|
74
|
+
**Which estimator? (two coherent paths, v1.3.0).** Each frozen estimator has a
|
|
74
75
|
coherent-tower sibling (ADR-019): `map_estimate` ↔ `tower_point` (an unbinned
|
|
75
76
|
median-of-the-`tip_mass`-floor point — the "shorth", free of `map_estimate`'s histogram
|
|
76
77
|
tie-break bias **and** robust to minority duplicated draws, register C-44), and
|
|
77
78
|
`hdi`/`quantiles` ↔ `hdi_tower(masses=…)` (HDIs built **outside-in**, nested **by
|
|
78
79
|
construction** and reproducible — a mass's interval is identical regardless of which others
|
|
79
|
-
you request), with `summarize_tower` returning all three in one pass. The tower
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
you request), with `summarize_tower` returning all three in one pass. The tower path is
|
|
81
|
+
**distribution-agnostic** — it works for counts, continuous, normal, and `[0,1]`
|
|
82
|
+
(rate/probability) targets, with **no magnitude zeroing by default** (zero-inflation is read
|
|
83
|
+
off the floor's density, register C-45); a count consumer that wants "sub-1 ⇒ 0" opts in via
|
|
84
|
+
`config['zero_cutoff']`. The tower's tunables live in `views_frames_summarize.config`
|
|
85
|
+
(fail-loud, no silent defaults). Use the **frozen** estimators for parity with existing
|
|
86
|
+
pipelines; use the **tower** path when you need coherent, reproducible bands plus a matching,
|
|
87
|
+
duplicate-robust point.
|
|
83
88
|
|
|
84
89
|
**Reading the `bimodality` flag.** It is a *deliberately conservative* heuristic, **not** a
|
|
85
90
|
formal multimodality test — tuned for **zero false positives** at the cost of recall on
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "views-frames"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.3.0"
|
|
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" },
|
|
@@ -31,9 +31,12 @@ TOWER_CONFIG: Final[dict[str, Any]] = {
|
|
|
31
31
|
# The tower-tip reads the median of the floor at this mass — the "shorth". 0.5 is
|
|
32
32
|
# the maximally-robust choice: a duplicate would need ~half the draws to hijack it.
|
|
33
33
|
"tip_mass": 0.5,
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
|
|
34
|
+
# Optional magnitude zero rule, OFF by default (``None``). When set to a float, a
|
|
35
|
+
# row whose every draw is <= it collapses to 0 — a *count* opt-in (sub-1 ⇒ 0).
|
|
36
|
+
# Left ``None`` for any non-count target: zero-inflation is otherwise handled by the
|
|
37
|
+
# density of the ``tip_mass`` floor, not by magnitude (register C-45). The leaf
|
|
38
|
+
# imposes no magnitude assumption by default; a consumer that wants it sets this.
|
|
39
|
+
"zero_cutoff": None,
|
|
37
40
|
# Bimodality detector (coarse histogram + light smoothing; see bimodality.py).
|
|
38
41
|
"bimodality_bins": 16,
|
|
39
42
|
"bimodality_prominence": 0.40,
|
|
@@ -13,9 +13,10 @@ nearest floor, never inserted — "the 50% HDI" is identical regardless of which
|
|
|
13
13
|
masses a caller asks for (reproducibility).
|
|
14
14
|
|
|
15
15
|
The construction is vectorized over the sample axis and runs in row-blocks (register
|
|
16
|
-
C-22/C-25): one sort per block, never a whole-grid sorted copy.
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
C-22/C-25): one sort per block, never a whole-grid sorted copy. Zero-inflation is read
|
|
17
|
+
off the *density* of the `tip_mass` floor (a zero-majority row reads 0); an
|
|
18
|
+
**optional, off-by-default** magnitude cutoff (`config['zero_cutoff']`, a count-domain
|
|
19
|
+
opt-in) can additionally force `max(row) <= cutoff` rows to 0 (C-45).
|
|
19
20
|
|
|
20
21
|
All tunables (the grid, zero cutoff, row-block size) come from `config` with **no silent
|
|
21
22
|
defaults** (ADR-009). The private engine (`_dense_tower`, `_median_in`, `_pin`,
|
|
@@ -34,11 +35,10 @@ from numpy.typing import NDArray
|
|
|
34
35
|
from views_frames_summarize import config
|
|
35
36
|
from views_frames_summarize._common import AnyFrame, block_apply
|
|
36
37
|
|
|
37
|
-
# The fixed canonical mass grid
|
|
38
|
-
#
|
|
39
|
-
#
|
|
38
|
+
# The fixed canonical mass grid, sourced from the single config (no silent defaults —
|
|
39
|
+
# ADR-009). The grid is reproducibility-fixed by design (ADR-019), so it is snapshotted
|
|
40
|
+
# here; the *tunable* knobs (``zero_cutoff``, ``tip_mass``) are read live at call time.
|
|
40
41
|
_CANONICAL_FLOORS: Final[NDArray[np.float64]] = config.canonical_floors()
|
|
41
|
-
_ZERO_CUTOFF: Final[float] = float(config.get("zero_cutoff"))
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
def _ks(sample_count: int) -> NDArray[np.intp]:
|
|
@@ -65,8 +65,18 @@ def _pin(masses: Sequence[float]) -> NDArray[np.intp]:
|
|
|
65
65
|
|
|
66
66
|
|
|
67
67
|
def _zero_mask(block: NDArray[np.float32]) -> NDArray[np.bool_]:
|
|
68
|
-
"""Rows
|
|
69
|
-
|
|
68
|
+
"""Rows the optional magnitude cutoff zeroes — ``max(draws) <= zero_cutoff``.
|
|
69
|
+
|
|
70
|
+
**Off by default** (``zero_cutoff is None`` ⇒ no row is masked). A consumer that
|
|
71
|
+
wants magnitude zeroing (a count target where a sub-1 posterior should read 0) sets
|
|
72
|
+
``zero_cutoff`` to a float in ``config`` — read **live** here, so the knob takes
|
|
73
|
+
effect at runtime. By default the leaf imposes **no** magnitude assumption; zero-
|
|
74
|
+
inflation is handled by the density of the ``tip_mass`` floor instead (C-45).
|
|
75
|
+
"""
|
|
76
|
+
cutoff = config.get("zero_cutoff")
|
|
77
|
+
if cutoff is None:
|
|
78
|
+
return np.zeros(block.shape[0], dtype=np.bool_)
|
|
79
|
+
return np.asarray(block.max(axis=-1) <= cutoff, dtype=np.bool_)
|
|
70
80
|
|
|
71
81
|
|
|
72
82
|
def _in_range_span(
|
|
@@ -203,8 +213,9 @@ def hdi_tower(
|
|
|
203
213
|
Each requested mass is pinned to the nearest fixed canonical floor; the interval is
|
|
204
214
|
read out of the full canonical tower (built once per block, outside-in). Nested by
|
|
205
215
|
construction, robust to minority duplicates, and reproducible (a mass's interval is
|
|
206
|
-
independent of the other requested masses).
|
|
207
|
-
collapse to ``(0, 0)
|
|
216
|
+
independent of the other requested masses). If the optional ``zero_cutoff`` is set,
|
|
217
|
+
``max <= cutoff`` rows collapse to ``(0, 0)`` (off by default — C-45). Aligned to
|
|
218
|
+
``frame.index``. Tunables come from ``config``.
|
|
208
219
|
"""
|
|
209
220
|
values = frame.values
|
|
210
221
|
lead = values.shape[:-1]
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
`tower_point` is the "most likely single value" we report to a consumer: the median of
|
|
4
4
|
the draws inside the **`tip_mass` floor** of the nested tower (config-driven, default
|
|
5
|
-
0.5 — the "shorth")
|
|
6
|
-
|
|
5
|
+
0.5 — the "shorth"). Zero-inflation is handled by that floor's density (a zero-majority
|
|
6
|
+
row reads 0); the optional, off-by-default magnitude cutoff applies too if set (C-45).
|
|
7
7
|
|
|
8
8
|
It is a *new* estimator, deliberately distinct from the frozen `map_estimate` (ADR-018):
|
|
9
9
|
`map_estimate` is a binned histogram mode with a zero-*mass*-fraction rule and a
|
|
@@ -34,9 +34,10 @@ from views_frames_summarize.tower import (
|
|
|
34
34
|
def tower_point(frame: AnyFrame) -> AnyFrame:
|
|
35
35
|
"""Per-row tower-tip point estimate over the sample axis → a `(N, …, 1)` frame.
|
|
36
36
|
|
|
37
|
-
The median of the ``tip_mass`` floor's samples
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
The median of the ``tip_mass`` floor's samples (``0`` when the zero atom dominates,
|
|
38
|
+
by density); if the optional ``zero_cutoff`` is set, ``max <= cutoff`` rows are
|
|
39
|
+
forced to ``0`` (off by default — C-45). Returns the same frame type as ``frame``.
|
|
40
|
+
Tunables (``tip_mass``, grid, ``zero_cutoff``, row-block) come from ``config``.
|
|
40
41
|
"""
|
|
41
42
|
values = frame.values
|
|
42
43
|
lead = values.shape[:-1]
|
|
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
|