nested-recd 0.1.0__tar.gz → 0.2.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.
- {nested_recd-0.1.0/src/nested_recd.egg-info → nested_recd-0.2.0}/PKG-INFO +68 -27
- nested_recd-0.2.0/README.md +162 -0
- {nested_recd-0.1.0 → nested_recd-0.2.0}/pyproject.toml +2 -2
- {nested_recd-0.1.0 → nested_recd-0.2.0}/src/nested_recd/__init__.py +20 -4
- {nested_recd-0.1.0 → nested_recd-0.2.0}/src/nested_recd/ordinal_levels.py +270 -71
- {nested_recd-0.1.0 → nested_recd-0.2.0/src/nested_recd.egg-info}/PKG-INFO +68 -27
- {nested_recd-0.1.0 → nested_recd-0.2.0}/tests/test_smoke.py +69 -3
- nested_recd-0.1.0/README.md +0 -121
- {nested_recd-0.1.0 → nested_recd-0.2.0}/LICENSE +0 -0
- {nested_recd-0.1.0 → nested_recd-0.2.0}/setup.cfg +0 -0
- {nested_recd-0.1.0 → nested_recd-0.2.0}/src/nested_recd/py.typed +0 -0
- {nested_recd-0.1.0 → nested_recd-0.2.0}/src/nested_recd/surrogates.py +0 -0
- {nested_recd-0.1.0 → nested_recd-0.2.0}/src/nested_recd.egg-info/SOURCES.txt +0 -0
- {nested_recd-0.1.0 → nested_recd-0.2.0}/src/nested_recd.egg-info/dependency_links.txt +0 -0
- {nested_recd-0.1.0 → nested_recd-0.2.0}/src/nested_recd.egg-info/requires.txt +0 -0
- {nested_recd-0.1.0 → nested_recd-0.2.0}/src/nested_recd.egg-info/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nested-recd
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Nested ordinal RECD: Φ1–Φ3
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Nested ordinal RECD: Φ1–Φ3, continuous excess³ (primary Level-3), and λ-weighted Discrete Extramental Clock
|
|
5
5
|
Author-email: Johel Padilla-Villanueva <joel.padilla2@upr.edu>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/johelpadilla/nested-recd
|
|
@@ -39,9 +39,9 @@ Dynamic: license-file
|
|
|
39
39
|
[](https://pypi.org/project/nested-recd/)
|
|
40
40
|
[](LICENSE)
|
|
41
41
|
|
|
42
|
-
**Nested ordinal RECD** — pure-NumPy implementation of nested ordinal conjunction levels (Φ₁, Φ₂, Φ₃) and λ-weighted Discrete Extramental Clock (RECD) accumulation.
|
|
42
|
+
**Nested ordinal RECD** — pure-NumPy implementation of nested ordinal conjunction levels (Φ₁, Φ₂, Φ₃), the continuous **excess³** Level-3 proxy, and λ-weighted Discrete Extramental Clock (RECD) accumulation.
|
|
43
43
|
|
|
44
|
-
This is the
|
|
44
|
+
This is the **canonical Level-3 software** for the Systemic Tau / RECD stack (cardiac CCTP/SDDB pilot, excess³ methods preprint, Academy Learning Tau).
|
|
45
45
|
|
|
46
46
|
## Install
|
|
47
47
|
|
|
@@ -49,56 +49,85 @@ This is the standalone library behind the nested-time structure used in the CCTP
|
|
|
49
49
|
pip install nested-recd
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
From source:
|
|
52
|
+
From source (development):
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
pip install
|
|
55
|
+
pip install -e ".[dev]"
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
## excess³ contract (methods)
|
|
59
|
+
|
|
60
|
+
Canonical specification: Padilla-Villanueva (2026), *excess³: A Pre-Specified Continuous Proxy…*
|
|
61
|
+
DOI: [10.5281/zenodo.21385937](https://doi.org/10.5281/zenodo.21385937) · repo: [github.com/johelpadilla/excess3](https://github.com/johelpadilla/excess3)
|
|
62
|
+
|
|
63
|
+
| Rule | Software |
|
|
64
|
+
|------|----------|
|
|
65
|
+
| `excess3 = 0.6·Syn + 0.4·Surp` | `ALPHA_SYN`, `ALPHA_SURP` (fixed a priori) |
|
|
66
|
+
| Continuous primary | `out["excess3"]` / `compute_phi3_excess` |
|
|
67
|
+
| Φ₃ secondary | binary ticks of excess3 vs `theta3` |
|
|
68
|
+
| Null on full contrast | `surrogate_pvalue_delta_excess3` (phase-shuffle / permute on `\|Δ\|`) |
|
|
69
|
+
| Proxy ≠ full PID | documented; no complete Williams–Beer atom claimed |
|
|
70
|
+
| Parallel nesting | Φ₁, Φ₂, excess³ computed without hard Boolean ascent |
|
|
71
|
+
|
|
72
|
+
Defaults: `m=3`, delay `1`, window `13`, `theta3=0.10` (software); cardio-like reference `DEFAULT_THETA3_CARDIO=0.08`.
|
|
73
|
+
|
|
58
74
|
## Quick start
|
|
59
75
|
|
|
60
76
|
```python
|
|
61
77
|
import numpy as np
|
|
62
|
-
from nested_recd import compute_recd_from_conjunctions,
|
|
78
|
+
from nested_recd import compute_recd_from_conjunctions, ALPHA_SYN, ALPHA_SURP
|
|
63
79
|
|
|
64
|
-
# Multivariate series: shape (T, N)
|
|
65
80
|
rng = np.random.default_rng(0)
|
|
66
81
|
X = rng.normal(size=(800, 3)).cumsum(axis=0)
|
|
67
82
|
|
|
68
83
|
out = compute_recd_from_conjunctions(X, m=3, d=4, theta3=0.10)
|
|
69
84
|
|
|
70
|
-
print("mean
|
|
71
|
-
print("mean Φ2:", float(np.nanmean(out["phi2"])))
|
|
85
|
+
print("mean excess³ (primary):", float(np.nanmean(out["excess3"])))
|
|
72
86
|
print("Φ3 active fraction:", float(np.nanmean(out["phi3"] > 0)))
|
|
87
|
+
print("weights:", out["params"]["alpha_syn"], out["params"]["alpha_surp"])
|
|
73
88
|
print("final T_recd:", float(out["T_recd"][-1]))
|
|
89
|
+
```
|
|
74
90
|
|
|
75
|
-
|
|
76
|
-
|
|
91
|
+
### Continuous excess³ only
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from nested_recd import generate_multivariate_symbols, compute_phi3_excess
|
|
95
|
+
|
|
96
|
+
S = generate_multivariate_symbols(X, m=3)
|
|
97
|
+
phi3, excess3 = compute_phi3_excess(S, window=13, theta=0.10, stride=1)
|
|
77
98
|
```
|
|
78
99
|
|
|
79
|
-
|
|
100
|
+
### Surrogate p-value on |Δ excess3|
|
|
80
101
|
|
|
81
102
|
```python
|
|
82
|
-
|
|
103
|
+
from nested_recd import surrogate_pvalue_delta_excess3
|
|
104
|
+
|
|
105
|
+
res = surrogate_pvalue_delta_excess3(X, split=400, n_surr=99, method="phase", seed=0)
|
|
106
|
+
print(res["delta_obs"], res["p_value"])
|
|
83
107
|
```
|
|
84
108
|
|
|
85
|
-
|
|
109
|
+
### Optional τ_s for λ regime weights
|
|
86
110
|
|
|
87
111
|
```python
|
|
112
|
+
out = compute_recd_from_conjunctions(X, tau_s=tau_s)
|
|
113
|
+
# or
|
|
88
114
|
out = compute_recd_from_conjunctions(X, lam_override=0.5)
|
|
89
115
|
```
|
|
90
116
|
|
|
117
|
+
**Note:** `delta_recd` / `T_recd` use **binary Φ₃** in the α-weighted clock (legacy Discrete Extramental Clock). For scientific Level-3 claims, report **continuous excess³** and nulls on `|Δ excess3|`.
|
|
118
|
+
|
|
91
119
|
## What it computes
|
|
92
120
|
|
|
93
121
|
| Symbol | Meaning |
|
|
94
122
|
|--------|---------|
|
|
95
123
|
| **Φ₁** | Co-occurrence of identical ordinal symbols across variable pairs |
|
|
96
124
|
| **Φ₂** | Persistence of pairwise ordinal relations over lag `d` |
|
|
97
|
-
|
|
|
125
|
+
| **excess³** | Continuous hybrid: `0.6·Syn + 0.4·Surp` (**primary** Level-3) |
|
|
126
|
+
| **Φ₃** | Binary ticks of excess³ above `theta3` (**secondary**) |
|
|
98
127
|
| **λ** | Chaos / reorganization intensity (from `τ_s` or `lam_override`) |
|
|
99
128
|
| **α(λ)** | Level weights: α₁ decays with λ; α₂, α₃ grow with λ |
|
|
100
|
-
| **ΔRECD** | `α₁Φ₁ + α₂Φ₂ + α₃Φ₃` |
|
|
101
|
-
| **T_recd** | Cumulative sum of ΔRECD
|
|
129
|
+
| **ΔRECD** | `α₁Φ₁ + α₂Φ₂ + α₃Φ₃` (legacy clock; binary Φ₃) |
|
|
130
|
+
| **T_recd** | Cumulative sum of ΔRECD |
|
|
102
131
|
|
|
103
132
|
Ordinal symbols use Bandt–Pompe patterns (`m=3` by default).
|
|
104
133
|
|
|
@@ -107,7 +136,7 @@ Ordinal symbols use Bandt–Pompe patterns (`m=3` by default).
|
|
|
107
136
|
```python
|
|
108
137
|
from nested_recd import phase_shuffle_independent, random_permutation_independent
|
|
109
138
|
|
|
110
|
-
X_null = phase_shuffle_independent(X, seed=42)
|
|
139
|
+
X_null = phase_shuffle_independent(X, seed=42)
|
|
111
140
|
X_perm = random_permutation_independent(X, seed=42)
|
|
112
141
|
```
|
|
113
142
|
|
|
@@ -115,8 +144,12 @@ X_perm = random_permutation_independent(X, seed=42)
|
|
|
115
144
|
|
|
116
145
|
```python
|
|
117
146
|
from nested_recd import (
|
|
147
|
+
ALPHA_SYN, ALPHA_SURP,
|
|
148
|
+
DEFAULT_THETA3, DEFAULT_THETA3_CARDIO,
|
|
118
149
|
compute_recd_from_conjunctions,
|
|
119
150
|
compute_phi1, compute_phi2, compute_phi3,
|
|
151
|
+
compute_phi3_excess, compute_excess3_window,
|
|
152
|
+
mean_excess_pre_post, surrogate_pvalue_delta_excess3,
|
|
120
153
|
compute_lambda, alpha_weights, regime_lambda_proxy,
|
|
121
154
|
compute_weighted_contributions, high_level3_rate,
|
|
122
155
|
generate_multivariate_symbols,
|
|
@@ -128,25 +161,33 @@ from nested_recd import (
|
|
|
128
161
|
|
|
129
162
|
| Project | Role |
|
|
130
163
|
|---------|------|
|
|
131
|
-
| [`systemictau`](https://pypi.org/project/systemictau/) | Full Systemic Tau library (τ_s,
|
|
132
|
-
| [`
|
|
133
|
-
|
|
|
164
|
+
| [`systemictau`](https://pypi.org/project/systemictau/) | Full Systemic Tau library (τ_s, gate RECD, studio) — optional `[nested]` extra |
|
|
165
|
+
| [`systemictau-web`](https://github.com/johelpadilla/systemictau-web) | Streamlit app; depends on this package |
|
|
166
|
+
| [`excess3`](https://github.com/johelpadilla/excess3) | Methods + intro ES + primer (specification) |
|
|
167
|
+
| [`cctp-sddb-systemic-tau`](https://github.com/johelpadilla/cctp-sddb-systemic-tau) | Cardiac VF pilot |
|
|
168
|
+
| This package | Lightweight, installable nested-time / excess³ core |
|
|
134
169
|
|
|
135
170
|
## Citation
|
|
136
171
|
|
|
137
|
-
If you use this
|
|
172
|
+
If you use excess³ / Level-3 from this package, cite the **methods** preprint (canonical specification):
|
|
138
173
|
|
|
139
|
-
> Padilla-Villanueva, J. (2026). *
|
|
174
|
+
> Padilla-Villanueva, J. (2026). *excess³: A Pre-Specified Continuous Proxy for Order-3 Synergistic Surplus* (methods). Zenodo. https://doi.org/10.5281/zenodo.21385937
|
|
140
175
|
|
|
141
|
-
|
|
176
|
+
Software / related stack:
|
|
177
|
+
|
|
178
|
+
> Padilla-Villanueva, J. (2026). Systemic Tau software archive. Zenodo. https://doi.org/10.5281/zenodo.20576241
|
|
179
|
+
|
|
180
|
+
CCTP/SDDB pilot:
|
|
181
|
+
|
|
182
|
+
> Padilla-Villanueva, J. (2026). *CCTP/SDDB: Systemic Tau and ordinal RECD before spontaneous ventricular fibrillation* (v1.0.1). Zenodo. https://doi.org/10.5281/zenodo.21270699
|
|
142
183
|
|
|
143
184
|
```bibtex
|
|
144
185
|
@software{padilla_nested_recd_2026,
|
|
145
186
|
author = {Padilla-Villanueva, Johel},
|
|
146
|
-
title = {nested-recd: Nested ordinal RECD levels},
|
|
187
|
+
title = {nested-recd: Nested ordinal RECD levels and continuous excess³},
|
|
147
188
|
year = {2026},
|
|
148
189
|
url = {https://github.com/johelpadilla/nested-recd},
|
|
149
|
-
version = {0.
|
|
190
|
+
version = {0.2.0}
|
|
150
191
|
}
|
|
151
192
|
```
|
|
152
193
|
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# nested-recd
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/nested-recd/)
|
|
4
|
+
[](https://pypi.org/project/nested-recd/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
**Nested ordinal RECD** — pure-NumPy implementation of nested ordinal conjunction levels (Φ₁, Φ₂, Φ₃), the continuous **excess³** Level-3 proxy, and λ-weighted Discrete Extramental Clock (RECD) accumulation.
|
|
8
|
+
|
|
9
|
+
This is the **canonical Level-3 software** for the Systemic Tau / RECD stack (cardiac CCTP/SDDB pilot, excess³ methods preprint, Academy Learning Tau).
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install nested-recd
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
From source (development):
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install -e ".[dev]"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## excess³ contract (methods)
|
|
24
|
+
|
|
25
|
+
Canonical specification: Padilla-Villanueva (2026), *excess³: A Pre-Specified Continuous Proxy…*
|
|
26
|
+
DOI: [10.5281/zenodo.21385937](https://doi.org/10.5281/zenodo.21385937) · repo: [github.com/johelpadilla/excess3](https://github.com/johelpadilla/excess3)
|
|
27
|
+
|
|
28
|
+
| Rule | Software |
|
|
29
|
+
|------|----------|
|
|
30
|
+
| `excess3 = 0.6·Syn + 0.4·Surp` | `ALPHA_SYN`, `ALPHA_SURP` (fixed a priori) |
|
|
31
|
+
| Continuous primary | `out["excess3"]` / `compute_phi3_excess` |
|
|
32
|
+
| Φ₃ secondary | binary ticks of excess3 vs `theta3` |
|
|
33
|
+
| Null on full contrast | `surrogate_pvalue_delta_excess3` (phase-shuffle / permute on `\|Δ\|`) |
|
|
34
|
+
| Proxy ≠ full PID | documented; no complete Williams–Beer atom claimed |
|
|
35
|
+
| Parallel nesting | Φ₁, Φ₂, excess³ computed without hard Boolean ascent |
|
|
36
|
+
|
|
37
|
+
Defaults: `m=3`, delay `1`, window `13`, `theta3=0.10` (software); cardio-like reference `DEFAULT_THETA3_CARDIO=0.08`.
|
|
38
|
+
|
|
39
|
+
## Quick start
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
import numpy as np
|
|
43
|
+
from nested_recd import compute_recd_from_conjunctions, ALPHA_SYN, ALPHA_SURP
|
|
44
|
+
|
|
45
|
+
rng = np.random.default_rng(0)
|
|
46
|
+
X = rng.normal(size=(800, 3)).cumsum(axis=0)
|
|
47
|
+
|
|
48
|
+
out = compute_recd_from_conjunctions(X, m=3, d=4, theta3=0.10)
|
|
49
|
+
|
|
50
|
+
print("mean excess³ (primary):", float(np.nanmean(out["excess3"])))
|
|
51
|
+
print("Φ3 active fraction:", float(np.nanmean(out["phi3"] > 0)))
|
|
52
|
+
print("weights:", out["params"]["alpha_syn"], out["params"]["alpha_surp"])
|
|
53
|
+
print("final T_recd:", float(out["T_recd"][-1]))
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Continuous excess³ only
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from nested_recd import generate_multivariate_symbols, compute_phi3_excess
|
|
60
|
+
|
|
61
|
+
S = generate_multivariate_symbols(X, m=3)
|
|
62
|
+
phi3, excess3 = compute_phi3_excess(S, window=13, theta=0.10, stride=1)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Surrogate p-value on |Δ excess3|
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from nested_recd import surrogate_pvalue_delta_excess3
|
|
69
|
+
|
|
70
|
+
res = surrogate_pvalue_delta_excess3(X, split=400, n_surr=99, method="phase", seed=0)
|
|
71
|
+
print(res["delta_obs"], res["p_value"])
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Optional τ_s for λ regime weights
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
out = compute_recd_from_conjunctions(X, tau_s=tau_s)
|
|
78
|
+
# or
|
|
79
|
+
out = compute_recd_from_conjunctions(X, lam_override=0.5)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Note:** `delta_recd` / `T_recd` use **binary Φ₃** in the α-weighted clock (legacy Discrete Extramental Clock). For scientific Level-3 claims, report **continuous excess³** and nulls on `|Δ excess3|`.
|
|
83
|
+
|
|
84
|
+
## What it computes
|
|
85
|
+
|
|
86
|
+
| Symbol | Meaning |
|
|
87
|
+
|--------|---------|
|
|
88
|
+
| **Φ₁** | Co-occurrence of identical ordinal symbols across variable pairs |
|
|
89
|
+
| **Φ₂** | Persistence of pairwise ordinal relations over lag `d` |
|
|
90
|
+
| **excess³** | Continuous hybrid: `0.6·Syn + 0.4·Surp` (**primary** Level-3) |
|
|
91
|
+
| **Φ₃** | Binary ticks of excess³ above `theta3` (**secondary**) |
|
|
92
|
+
| **λ** | Chaos / reorganization intensity (from `τ_s` or `lam_override`) |
|
|
93
|
+
| **α(λ)** | Level weights: α₁ decays with λ; α₂, α₃ grow with λ |
|
|
94
|
+
| **ΔRECD** | `α₁Φ₁ + α₂Φ₂ + α₃Φ₃` (legacy clock; binary Φ₃) |
|
|
95
|
+
| **T_recd** | Cumulative sum of ΔRECD |
|
|
96
|
+
|
|
97
|
+
Ordinal symbols use Bandt–Pompe patterns (`m=3` by default).
|
|
98
|
+
|
|
99
|
+
## Surrogates
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from nested_recd import phase_shuffle_independent, random_permutation_independent
|
|
103
|
+
|
|
104
|
+
X_null = phase_shuffle_independent(X, seed=42)
|
|
105
|
+
X_perm = random_permutation_independent(X, seed=42)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## API surface
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from nested_recd import (
|
|
112
|
+
ALPHA_SYN, ALPHA_SURP,
|
|
113
|
+
DEFAULT_THETA3, DEFAULT_THETA3_CARDIO,
|
|
114
|
+
compute_recd_from_conjunctions,
|
|
115
|
+
compute_phi1, compute_phi2, compute_phi3,
|
|
116
|
+
compute_phi3_excess, compute_excess3_window,
|
|
117
|
+
mean_excess_pre_post, surrogate_pvalue_delta_excess3,
|
|
118
|
+
compute_lambda, alpha_weights, regime_lambda_proxy,
|
|
119
|
+
compute_weighted_contributions, high_level3_rate,
|
|
120
|
+
generate_multivariate_symbols,
|
|
121
|
+
phase_shuffle_independent, generate_surrogate_ensemble,
|
|
122
|
+
)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Relation to other projects
|
|
126
|
+
|
|
127
|
+
| Project | Role |
|
|
128
|
+
|---------|------|
|
|
129
|
+
| [`systemictau`](https://pypi.org/project/systemictau/) | Full Systemic Tau library (τ_s, gate RECD, studio) — optional `[nested]` extra |
|
|
130
|
+
| [`systemictau-web`](https://github.com/johelpadilla/systemictau-web) | Streamlit app; depends on this package |
|
|
131
|
+
| [`excess3`](https://github.com/johelpadilla/excess3) | Methods + intro ES + primer (specification) |
|
|
132
|
+
| [`cctp-sddb-systemic-tau`](https://github.com/johelpadilla/cctp-sddb-systemic-tau) | Cardiac VF pilot |
|
|
133
|
+
| This package | Lightweight, installable nested-time / excess³ core |
|
|
134
|
+
|
|
135
|
+
## Citation
|
|
136
|
+
|
|
137
|
+
If you use excess³ / Level-3 from this package, cite the **methods** preprint (canonical specification):
|
|
138
|
+
|
|
139
|
+
> Padilla-Villanueva, J. (2026). *excess³: A Pre-Specified Continuous Proxy for Order-3 Synergistic Surplus* (methods). Zenodo. https://doi.org/10.5281/zenodo.21385937
|
|
140
|
+
|
|
141
|
+
Software / related stack:
|
|
142
|
+
|
|
143
|
+
> Padilla-Villanueva, J. (2026). Systemic Tau software archive. Zenodo. https://doi.org/10.5281/zenodo.20576241
|
|
144
|
+
|
|
145
|
+
CCTP/SDDB pilot:
|
|
146
|
+
|
|
147
|
+
> Padilla-Villanueva, J. (2026). *CCTP/SDDB: Systemic Tau and ordinal RECD before spontaneous ventricular fibrillation* (v1.0.1). Zenodo. https://doi.org/10.5281/zenodo.21270699
|
|
148
|
+
|
|
149
|
+
```bibtex
|
|
150
|
+
@software{padilla_nested_recd_2026,
|
|
151
|
+
author = {Padilla-Villanueva, Johel},
|
|
152
|
+
title = {nested-recd: Nested ordinal RECD levels and continuous excess³},
|
|
153
|
+
year = {2026},
|
|
154
|
+
url = {https://github.com/johelpadilla/nested-recd},
|
|
155
|
+
version = {0.2.0}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
MIT © 2026 Johel Padilla-Villanueva
|
|
162
|
+
ORCID: [0000-0002-5797-6931](https://orcid.org/0000-0002-5797-6931)
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nested-recd"
|
|
7
|
-
version = "0.
|
|
8
|
-
description = "Nested ordinal RECD: Φ1–Φ3
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Nested ordinal RECD: Φ1–Φ3, continuous excess³ (primary Level-3), and λ-weighted Discrete Extramental Clock"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
11
11
|
license = "MIT"
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
nested-recd
|
|
3
3
|
===========
|
|
4
4
|
|
|
5
|
-
Nested ordinal RECD: Φ₁ / Φ₂ / Φ₃ conjunction levels
|
|
6
|
-
Discrete Extramental Clock
|
|
5
|
+
Nested ordinal RECD: Φ₁ / Φ₂ / Φ₃ conjunction levels, continuous excess³
|
|
6
|
+
(primary Level-3 readout), and λ-weighted Discrete Extramental Clock.
|
|
7
7
|
|
|
8
8
|
Quick start
|
|
9
9
|
-----------
|
|
@@ -11,7 +11,7 @@ Quick start
|
|
|
11
11
|
>>> from nested_recd import compute_recd_from_conjunctions
|
|
12
12
|
>>> X = np.random.randn(500, 3).cumsum(axis=0)
|
|
13
13
|
>>> out = compute_recd_from_conjunctions(X)
|
|
14
|
-
>>> out["
|
|
14
|
+
>>> float(np.nanmean(out["excess3"])) # continuous primary Level-3 score
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
from nested_recd.ordinal_levels import (
|
|
@@ -19,13 +19,21 @@ from nested_recd.ordinal_levels import (
|
|
|
19
19
|
DEFAULT_DELAY,
|
|
20
20
|
DEFAULT_D_PERSIST,
|
|
21
21
|
DEFAULT_WINDOW_TAU,
|
|
22
|
+
DEFAULT_WINDOW,
|
|
22
23
|
DEFAULT_THETA_CHAOS,
|
|
23
24
|
DEFAULT_THETA3,
|
|
25
|
+
DEFAULT_THETA3_CARDIO,
|
|
24
26
|
DELTA_FEIGENBAUM,
|
|
27
|
+
ALPHA_SYN,
|
|
28
|
+
ALPHA_SURP,
|
|
25
29
|
generate_multivariate_symbols,
|
|
26
30
|
compute_phi1,
|
|
27
31
|
compute_phi2,
|
|
28
32
|
compute_phi3,
|
|
33
|
+
compute_phi3_excess,
|
|
34
|
+
compute_excess3_window,
|
|
35
|
+
mean_excess_pre_post,
|
|
36
|
+
surrogate_pvalue_delta_excess3,
|
|
29
37
|
compute_lambda,
|
|
30
38
|
alpha_weights,
|
|
31
39
|
regime_lambda_proxy,
|
|
@@ -43,7 +51,7 @@ from nested_recd.surrogates import (
|
|
|
43
51
|
compute_null_distribution,
|
|
44
52
|
)
|
|
45
53
|
|
|
46
|
-
__version__ = "0.
|
|
54
|
+
__version__ = "0.2.0"
|
|
47
55
|
|
|
48
56
|
__all__ = [
|
|
49
57
|
"__version__",
|
|
@@ -51,13 +59,21 @@ __all__ = [
|
|
|
51
59
|
"DEFAULT_DELAY",
|
|
52
60
|
"DEFAULT_D_PERSIST",
|
|
53
61
|
"DEFAULT_WINDOW_TAU",
|
|
62
|
+
"DEFAULT_WINDOW",
|
|
54
63
|
"DEFAULT_THETA_CHAOS",
|
|
55
64
|
"DEFAULT_THETA3",
|
|
65
|
+
"DEFAULT_THETA3_CARDIO",
|
|
56
66
|
"DELTA_FEIGENBAUM",
|
|
67
|
+
"ALPHA_SYN",
|
|
68
|
+
"ALPHA_SURP",
|
|
57
69
|
"generate_multivariate_symbols",
|
|
58
70
|
"compute_phi1",
|
|
59
71
|
"compute_phi2",
|
|
60
72
|
"compute_phi3",
|
|
73
|
+
"compute_phi3_excess",
|
|
74
|
+
"compute_excess3_window",
|
|
75
|
+
"mean_excess_pre_post",
|
|
76
|
+
"surrogate_pvalue_delta_excess3",
|
|
61
77
|
"compute_lambda",
|
|
62
78
|
"alpha_weights",
|
|
63
79
|
"regime_lambda_proxy",
|
|
@@ -19,14 +19,20 @@ import numpy as np
|
|
|
19
19
|
from typing import Dict, Tuple, Optional
|
|
20
20
|
import warnings
|
|
21
21
|
|
|
22
|
-
# Defaults quirúrgicos (ver diseño)
|
|
22
|
+
# Defaults quirúrgicos (ver diseño + excess³ methods contract)
|
|
23
23
|
DEFAULT_M = 3
|
|
24
24
|
DEFAULT_DELAY = 1
|
|
25
25
|
DEFAULT_D_PERSIST = 4
|
|
26
26
|
DEFAULT_WINDOW_TAU = 13
|
|
27
|
+
DEFAULT_WINDOW = DEFAULT_WINDOW_TAU # alias (methods paper)
|
|
27
28
|
DEFAULT_THETA_CHAOS = 0.41
|
|
28
29
|
DELTA_FEIGENBAUM = 4.6692016091
|
|
29
|
-
DEFAULT_THETA3 = 0.10 #
|
|
30
|
+
DEFAULT_THETA3 = 0.10 # software default
|
|
31
|
+
DEFAULT_THETA3_CARDIO = 0.08 # methods cardio-like reference
|
|
32
|
+
|
|
33
|
+
# excess³ = α_Syn · Syn + α_Surp · Surp (fixed a priori; never fit on target data)
|
|
34
|
+
ALPHA_SYN = 0.6
|
|
35
|
+
ALPHA_SURP = 0.4
|
|
30
36
|
|
|
31
37
|
def _gen_ordinal(x: np.ndarray, m: int = DEFAULT_M, delay: int = DEFAULT_DELAY) -> np.ndarray:
|
|
32
38
|
"""Bandt–Pompe ordinal symbols (pure NumPy, no numba required)."""
|
|
@@ -234,77 +240,248 @@ def _joint_entropy_and_marginals(S_window: np.ndarray) -> Tuple[float, float, fl
|
|
|
234
240
|
return H_joint, H_marg_sum, synergy_proxy
|
|
235
241
|
|
|
236
242
|
|
|
237
|
-
def
|
|
243
|
+
def compute_excess3_window(
|
|
244
|
+
win: np.ndarray,
|
|
245
|
+
use_surprise: bool = True,
|
|
246
|
+
alpha_syn: float = ALPHA_SYN,
|
|
247
|
+
alpha_surp: float = ALPHA_SURP,
|
|
248
|
+
) -> float:
|
|
249
|
+
"""
|
|
250
|
+
excess³ score on a single window of joint ordinal symbols (shape (w, N)).
|
|
251
|
+
|
|
252
|
+
Canonical hybrid proxy (methods contract):
|
|
253
|
+
excess3 = alpha_syn · Syn + alpha_surp · Surp
|
|
254
|
+
with default weights (0.6, 0.4) fixed a priori — never optimised on the
|
|
255
|
+
scientific dataset under test.
|
|
256
|
+
|
|
257
|
+
Syn: synergistic residual multiinformation proxy
|
|
258
|
+
max(0, TC − (N−1)·MĪ_pair).
|
|
259
|
+
Surp: observed-vs-independence joint surprise (frequency-weighted log-ratio).
|
|
260
|
+
|
|
261
|
+
This is a **proxy**, not a complete PID synergy atom.
|
|
262
|
+
"""
|
|
263
|
+
win = np.asarray(win)
|
|
264
|
+
if win.ndim != 2 or win.shape[0] == 0:
|
|
265
|
+
return float("nan")
|
|
266
|
+
if win.shape[1] < 2:
|
|
267
|
+
return 0.0
|
|
268
|
+
|
|
269
|
+
_, _, syn = _joint_entropy_and_marginals(win)
|
|
270
|
+
if not use_surprise:
|
|
271
|
+
return float(syn)
|
|
272
|
+
|
|
273
|
+
from collections import Counter
|
|
274
|
+
|
|
275
|
+
joint_tuples = [tuple(int(v) for v in row) for row in win]
|
|
276
|
+
counter = Counter(joint_tuples)
|
|
277
|
+
T_win = len(joint_tuples)
|
|
278
|
+
surprises = []
|
|
279
|
+
for u, cnt in counter.items():
|
|
280
|
+
p_indep = 1.0
|
|
281
|
+
for k, val in enumerate(u):
|
|
282
|
+
p_indep *= max(float(np.mean(win[:, k] == val)), 1e-9)
|
|
283
|
+
p_obs = cnt / T_win
|
|
284
|
+
ratio = p_obs / max(p_indep, 1e-9)
|
|
285
|
+
excess_log = max(0.0, np.log2(ratio)) if ratio > 1 else 0.0
|
|
286
|
+
surprises.append(excess_log * (cnt / T_win))
|
|
287
|
+
joint_surprise = float(np.sum(surprises)) if surprises else 0.0
|
|
288
|
+
return float(alpha_syn * syn + alpha_surp * joint_surprise)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def compute_phi3_excess(
|
|
238
292
|
S: np.ndarray,
|
|
239
|
-
window: int =
|
|
293
|
+
window: int = DEFAULT_WINDOW_TAU,
|
|
240
294
|
theta: float = DEFAULT_THETA3,
|
|
241
295
|
stride: int = 1,
|
|
242
|
-
use_surprise: bool = True
|
|
296
|
+
use_surprise: bool = True,
|
|
297
|
+
alpha_syn: float = ALPHA_SYN,
|
|
298
|
+
alpha_surp: float = ALPHA_SURP,
|
|
299
|
+
fill: bool = False,
|
|
243
300
|
) -> Tuple[np.ndarray, np.ndarray]:
|
|
244
301
|
"""
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
302
|
+
Continuous excess³ (primary) and binary Φ₃ (secondary) on symbol matrix S.
|
|
303
|
+
|
|
304
|
+
Returns
|
|
305
|
+
-------
|
|
306
|
+
phi3 : ndarray
|
|
307
|
+
Binary ticks: 1 if excess3 > theta else 0 (NaN before first full window).
|
|
308
|
+
excess3 : ndarray
|
|
309
|
+
Continuous hybrid score (primary Level-3 readout).
|
|
310
|
+
|
|
311
|
+
Parameters
|
|
312
|
+
----------
|
|
313
|
+
fill : bool
|
|
314
|
+
If True, forward-fill NaNs after the first finite score (plot convenience).
|
|
315
|
+
Default False preserves sparse stride semantics.
|
|
257
316
|
"""
|
|
317
|
+
S = np.asarray(S)
|
|
258
318
|
T_eff, N = S.shape
|
|
259
319
|
phi3 = np.full(T_eff, np.nan)
|
|
260
320
|
excess = np.full(T_eff, np.nan)
|
|
261
321
|
|
|
262
|
-
if T_eff < window:
|
|
322
|
+
if T_eff < window or N < 2:
|
|
263
323
|
return phi3, excess
|
|
264
324
|
|
|
265
325
|
for t in range(window - 1, T_eff, stride):
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
if
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
surprises = []
|
|
284
|
-
for u, cnt in zip(uniq, counts):
|
|
285
|
-
p_indep = 1.0
|
|
286
|
-
for k, val in enumerate(u):
|
|
287
|
-
pk = np.mean([row[k] == val for row in joint_tuples])
|
|
288
|
-
p_indep *= max(pk, 1e-9)
|
|
289
|
-
p_obs = cnt / T_win
|
|
290
|
-
# log-ratio: >0 cuando ocurre más de lo esperado por independencia
|
|
291
|
-
ratio = p_obs / max(p_indep, 1e-9)
|
|
292
|
-
excess_log = max(0.0, np.log2(ratio)) if ratio > 1 else 0.0
|
|
293
|
-
weight = cnt / T_win
|
|
294
|
-
surprises.append(excess_log * weight)
|
|
295
|
-
|
|
296
|
-
joint_surprise = float(np.sum(surprises)) if surprises else 0.0
|
|
297
|
-
# Combinar (syn ya es en bits-ish, surprise también)
|
|
298
|
-
combined = 0.6 * syn + 0.4 * joint_surprise # pesos heurísticos pero transparentes
|
|
299
|
-
else:
|
|
300
|
-
combined = syn
|
|
301
|
-
|
|
302
|
-
excess[t] = combined
|
|
303
|
-
phi3[t] = 1.0 if combined > theta else 0.0
|
|
326
|
+
score = compute_excess3_window(
|
|
327
|
+
S[t - window + 1 : t + 1],
|
|
328
|
+
use_surprise=use_surprise,
|
|
329
|
+
alpha_syn=alpha_syn,
|
|
330
|
+
alpha_surp=alpha_surp,
|
|
331
|
+
)
|
|
332
|
+
excess[t] = score
|
|
333
|
+
phi3[t] = 1.0 if score > theta else 0.0
|
|
334
|
+
|
|
335
|
+
if fill:
|
|
336
|
+
last = np.nan
|
|
337
|
+
for t in range(T_eff):
|
|
338
|
+
if np.isfinite(excess[t]):
|
|
339
|
+
last = excess[t]
|
|
340
|
+
elif np.isfinite(last):
|
|
341
|
+
excess[t] = last
|
|
342
|
+
phi3[t] = 1.0 if last > theta else 0.0
|
|
304
343
|
|
|
305
344
|
return phi3, excess
|
|
306
345
|
|
|
307
346
|
|
|
347
|
+
def compute_phi3(
|
|
348
|
+
S: np.ndarray,
|
|
349
|
+
window: int = 13,
|
|
350
|
+
theta: float = DEFAULT_THETA3,
|
|
351
|
+
stride: int = 1,
|
|
352
|
+
use_surprise: bool = True,
|
|
353
|
+
alpha_syn: float = ALPHA_SYN,
|
|
354
|
+
alpha_surp: float = ALPHA_SURP,
|
|
355
|
+
) -> Tuple[np.ndarray, np.ndarray]:
|
|
356
|
+
"""
|
|
357
|
+
Φ₃(t) binary + continuous excess³ series.
|
|
358
|
+
|
|
359
|
+
Continuous excess³ is the **primary** Level-3 magnitude (methods contract);
|
|
360
|
+
Φ₃ only counts threshold crossings. Weights default to (ALPHA_SYN, ALPHA_SURP).
|
|
361
|
+
|
|
362
|
+
Returns (phi3_binary, excess3_continuous).
|
|
363
|
+
"""
|
|
364
|
+
return compute_phi3_excess(
|
|
365
|
+
S,
|
|
366
|
+
window=window,
|
|
367
|
+
theta=theta,
|
|
368
|
+
stride=stride,
|
|
369
|
+
use_surprise=use_surprise,
|
|
370
|
+
alpha_syn=alpha_syn,
|
|
371
|
+
alpha_surp=alpha_surp,
|
|
372
|
+
fill=False,
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def mean_excess_pre_post(
|
|
377
|
+
excess3: np.ndarray,
|
|
378
|
+
split: int,
|
|
379
|
+
) -> Tuple[float, float, float]:
|
|
380
|
+
"""
|
|
381
|
+
Mean continuous excess³ before / after a split index, and Δ = post − pre.
|
|
382
|
+
|
|
383
|
+
``split`` is an index into the excess3 array (same time base as returned by
|
|
384
|
+
compute_recd_from_conjunctions / compute_phi3_excess).
|
|
385
|
+
"""
|
|
386
|
+
excess3 = np.asarray(excess3, dtype=float)
|
|
387
|
+
if split <= 0 or split >= len(excess3):
|
|
388
|
+
raise ValueError(f"split={split} out of range for length {len(excess3)}")
|
|
389
|
+
pre = float(np.nanmean(excess3[:split]))
|
|
390
|
+
post = float(np.nanmean(excess3[split:]))
|
|
391
|
+
return pre, post, post - pre
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
def surrogate_pvalue_delta_excess3(
|
|
395
|
+
X: np.ndarray,
|
|
396
|
+
split: int,
|
|
397
|
+
n_surr: int = 199,
|
|
398
|
+
method: str = "phase",
|
|
399
|
+
seed: int = 0,
|
|
400
|
+
m: int = DEFAULT_M,
|
|
401
|
+
window: int = DEFAULT_WINDOW_TAU,
|
|
402
|
+
theta3: float = DEFAULT_THETA3,
|
|
403
|
+
stride: int = 1,
|
|
404
|
+
delay: int = DEFAULT_DELAY,
|
|
405
|
+
alpha_syn: float = ALPHA_SYN,
|
|
406
|
+
alpha_surp: float = ALPHA_SURP,
|
|
407
|
+
) -> Dict[str, float]:
|
|
408
|
+
"""
|
|
409
|
+
Two-sided surrogate p-value for |Δ excess3| under independent phase-shuffle
|
|
410
|
+
(default) or column permutation — methods-paper null protocol.
|
|
411
|
+
|
|
412
|
+
Inference is on the **full contrast** |Δ|, not mean-vs-mean of means alone.
|
|
413
|
+
|
|
414
|
+
Parameters
|
|
415
|
+
----------
|
|
416
|
+
X : (T, N) array
|
|
417
|
+
Multivariate series (raw values; symbols computed inside).
|
|
418
|
+
split : int
|
|
419
|
+
Split index on the **raw** time axis; mapped to symbol time via
|
|
420
|
+
embedding length (m, delay).
|
|
421
|
+
method : {"phase", "permute"}
|
|
422
|
+
"phase" uses per-column IAAFT / phase-shuffle; "permute" shuffles time.
|
|
423
|
+
"""
|
|
424
|
+
from nested_recd.surrogates import (
|
|
425
|
+
phase_shuffle_independent,
|
|
426
|
+
random_permutation_independent,
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
X = np.asarray(X)
|
|
430
|
+
if X.ndim != 2:
|
|
431
|
+
raise ValueError("X must be shape (T, N)")
|
|
432
|
+
|
|
433
|
+
def _delta_on(arr: np.ndarray) -> float:
|
|
434
|
+
S = generate_multivariate_symbols(arr, m=m, delay=delay)
|
|
435
|
+
if len(S) == 0:
|
|
436
|
+
return float("nan")
|
|
437
|
+
# Map split from raw time to symbol index (conservative)
|
|
438
|
+
emb = (m - 1) * delay
|
|
439
|
+
split_s = int(np.clip(split - emb, 1, len(S) - 1))
|
|
440
|
+
_, excess = compute_phi3_excess(
|
|
441
|
+
S,
|
|
442
|
+
window=window,
|
|
443
|
+
theta=theta3,
|
|
444
|
+
stride=stride,
|
|
445
|
+
alpha_syn=alpha_syn,
|
|
446
|
+
alpha_surp=alpha_surp,
|
|
447
|
+
)
|
|
448
|
+
_, _, d = mean_excess_pre_post(excess, split_s)
|
|
449
|
+
return float(d)
|
|
450
|
+
|
|
451
|
+
obs = _delta_on(X)
|
|
452
|
+
null = []
|
|
453
|
+
rng = np.random.default_rng(seed)
|
|
454
|
+
for _ in range(n_surr):
|
|
455
|
+
s = int(rng.integers(0, 2**31 - 1))
|
|
456
|
+
if method == "permute":
|
|
457
|
+
Xs = random_permutation_independent(X, seed=s)
|
|
458
|
+
else:
|
|
459
|
+
Xs = phase_shuffle_independent(X, seed=s)
|
|
460
|
+
null.append(_delta_on(Xs))
|
|
461
|
+
null = np.asarray(null, dtype=float)
|
|
462
|
+
null = null[np.isfinite(null)]
|
|
463
|
+
if not np.isfinite(obs) or len(null) == 0:
|
|
464
|
+
return {
|
|
465
|
+
"delta_obs": float(obs) if np.isfinite(obs) else float("nan"),
|
|
466
|
+
"abs_delta_obs": float("nan"),
|
|
467
|
+
"p_value": float("nan"),
|
|
468
|
+
"n_surr": float(len(null)),
|
|
469
|
+
"method": method,
|
|
470
|
+
}
|
|
471
|
+
abs_obs = abs(obs)
|
|
472
|
+
# Add-one smoothing: (1 + #{|null| >= |obs|}) / (1 + n)
|
|
473
|
+
p = (1.0 + float(np.sum(np.abs(null) >= abs_obs))) / (1.0 + len(null))
|
|
474
|
+
return {
|
|
475
|
+
"delta_obs": float(obs),
|
|
476
|
+
"abs_delta_obs": float(abs_obs),
|
|
477
|
+
"p_value": float(p),
|
|
478
|
+
"n_surr": float(len(null)),
|
|
479
|
+
"method": method,
|
|
480
|
+
"null_mean_abs": float(np.mean(np.abs(null))),
|
|
481
|
+
"null_std_abs": float(np.std(np.abs(null))),
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
|
|
308
485
|
# ============================================================
|
|
309
486
|
# λ(t) y pesos α(λ)
|
|
310
487
|
# ============================================================
|
|
@@ -381,27 +558,40 @@ def compute_recd_from_conjunctions(
|
|
|
381
558
|
theta3: float = DEFAULT_THETA3,
|
|
382
559
|
window_tau: int = DEFAULT_WINDOW_TAU,
|
|
383
560
|
lam_override: Optional[np.ndarray] = None,
|
|
561
|
+
stride: int = 1,
|
|
562
|
+
alpha_syn: float = ALPHA_SYN,
|
|
563
|
+
alpha_surp: float = ALPHA_SURP,
|
|
384
564
|
**alpha_kwargs
|
|
385
565
|
) -> Dict[str, np.ndarray]:
|
|
386
566
|
"""
|
|
387
|
-
|
|
388
|
-
-
|
|
389
|
-
- Φ1, Φ2, Φ3
|
|
390
|
-
- λ
|
|
391
|
-
- Δ
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
567
|
+
Full nested ordinal RECD pipeline:
|
|
568
|
+
- Bandt–Pompe symbols
|
|
569
|
+
- Φ1, Φ2, Φ3 (binary) + continuous excess³ (primary Level-3 readout)
|
|
570
|
+
- λ and α(λ) regime weights
|
|
571
|
+
- ΔRECD and cumulative T_recd
|
|
572
|
+
|
|
573
|
+
Level-3 contract (excess³ methods):
|
|
574
|
+
- Continuous ``excess3`` is the primary magnitude for order-3 claims.
|
|
575
|
+
- ``phi3`` is a secondary threshold discretisation of excess3.
|
|
576
|
+
- ``delta_recd`` keeps the legacy λ-weighted clock using **binary** Φ₃
|
|
577
|
+
(back-compat with CCTP / Discrete Extramental Clock nesting). Do not
|
|
578
|
+
treat ``delta_recd`` alone as the Level-3 scientific readout.
|
|
579
|
+
|
|
580
|
+
If tau_s is omitted, λ=0 (warning). Use ``lam_override`` for regime ground truth.
|
|
398
581
|
"""
|
|
399
582
|
S = generate_multivariate_symbols(X, m=m)
|
|
400
583
|
T_eff = S.shape[0]
|
|
401
584
|
|
|
402
585
|
phi1 = compute_phi1(S)
|
|
403
586
|
phi2 = compute_phi2(S, d=d)
|
|
404
|
-
phi3, excess3 = compute_phi3(
|
|
587
|
+
phi3, excess3 = compute_phi3(
|
|
588
|
+
S,
|
|
589
|
+
window=window_tau,
|
|
590
|
+
theta=theta3,
|
|
591
|
+
stride=stride,
|
|
592
|
+
alpha_syn=alpha_syn,
|
|
593
|
+
alpha_surp=alpha_surp,
|
|
594
|
+
)
|
|
405
595
|
|
|
406
596
|
# Determinar λ: override > tau-derived > zero
|
|
407
597
|
if lam_override is not None:
|
|
@@ -425,6 +615,7 @@ def compute_recd_from_conjunctions(
|
|
|
425
615
|
phi3_safe = np.nan_to_num(phi3, nan=0.0)
|
|
426
616
|
excess3_safe = np.nan_to_num(excess3, nan=0.0)
|
|
427
617
|
|
|
618
|
+
# Legacy RECD clock: binary Φ₃ in the α-weighted sum (back-compat)
|
|
428
619
|
delta_recd = a1 * phi1 + a2 * phi2 + a3 * phi3_safe
|
|
429
620
|
T_recd = np.nancumsum(delta_recd)
|
|
430
621
|
|
|
@@ -441,9 +632,17 @@ def compute_recd_from_conjunctions(
|
|
|
441
632
|
"delta_recd": delta_recd,
|
|
442
633
|
"T_recd": T_recd,
|
|
443
634
|
"params": {
|
|
444
|
-
"m": m,
|
|
445
|
-
"
|
|
446
|
-
|
|
635
|
+
"m": m,
|
|
636
|
+
"d": d,
|
|
637
|
+
"theta3": theta3,
|
|
638
|
+
"window_tau": window_tau,
|
|
639
|
+
"stride": stride,
|
|
640
|
+
"alpha_syn": alpha_syn,
|
|
641
|
+
"alpha_surp": alpha_surp,
|
|
642
|
+
"level3_primary": "excess3",
|
|
643
|
+
"level3_secondary": "phi3",
|
|
644
|
+
**alpha_kwargs,
|
|
645
|
+
},
|
|
447
646
|
}
|
|
448
647
|
|
|
449
648
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nested-recd
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Nested ordinal RECD: Φ1–Φ3
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Nested ordinal RECD: Φ1–Φ3, continuous excess³ (primary Level-3), and λ-weighted Discrete Extramental Clock
|
|
5
5
|
Author-email: Johel Padilla-Villanueva <joel.padilla2@upr.edu>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/johelpadilla/nested-recd
|
|
@@ -39,9 +39,9 @@ Dynamic: license-file
|
|
|
39
39
|
[](https://pypi.org/project/nested-recd/)
|
|
40
40
|
[](LICENSE)
|
|
41
41
|
|
|
42
|
-
**Nested ordinal RECD** — pure-NumPy implementation of nested ordinal conjunction levels (Φ₁, Φ₂, Φ₃) and λ-weighted Discrete Extramental Clock (RECD) accumulation.
|
|
42
|
+
**Nested ordinal RECD** — pure-NumPy implementation of nested ordinal conjunction levels (Φ₁, Φ₂, Φ₃), the continuous **excess³** Level-3 proxy, and λ-weighted Discrete Extramental Clock (RECD) accumulation.
|
|
43
43
|
|
|
44
|
-
This is the
|
|
44
|
+
This is the **canonical Level-3 software** for the Systemic Tau / RECD stack (cardiac CCTP/SDDB pilot, excess³ methods preprint, Academy Learning Tau).
|
|
45
45
|
|
|
46
46
|
## Install
|
|
47
47
|
|
|
@@ -49,56 +49,85 @@ This is the standalone library behind the nested-time structure used in the CCTP
|
|
|
49
49
|
pip install nested-recd
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
From source:
|
|
52
|
+
From source (development):
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
pip install
|
|
55
|
+
pip install -e ".[dev]"
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
## excess³ contract (methods)
|
|
59
|
+
|
|
60
|
+
Canonical specification: Padilla-Villanueva (2026), *excess³: A Pre-Specified Continuous Proxy…*
|
|
61
|
+
DOI: [10.5281/zenodo.21385937](https://doi.org/10.5281/zenodo.21385937) · repo: [github.com/johelpadilla/excess3](https://github.com/johelpadilla/excess3)
|
|
62
|
+
|
|
63
|
+
| Rule | Software |
|
|
64
|
+
|------|----------|
|
|
65
|
+
| `excess3 = 0.6·Syn + 0.4·Surp` | `ALPHA_SYN`, `ALPHA_SURP` (fixed a priori) |
|
|
66
|
+
| Continuous primary | `out["excess3"]` / `compute_phi3_excess` |
|
|
67
|
+
| Φ₃ secondary | binary ticks of excess3 vs `theta3` |
|
|
68
|
+
| Null on full contrast | `surrogate_pvalue_delta_excess3` (phase-shuffle / permute on `\|Δ\|`) |
|
|
69
|
+
| Proxy ≠ full PID | documented; no complete Williams–Beer atom claimed |
|
|
70
|
+
| Parallel nesting | Φ₁, Φ₂, excess³ computed without hard Boolean ascent |
|
|
71
|
+
|
|
72
|
+
Defaults: `m=3`, delay `1`, window `13`, `theta3=0.10` (software); cardio-like reference `DEFAULT_THETA3_CARDIO=0.08`.
|
|
73
|
+
|
|
58
74
|
## Quick start
|
|
59
75
|
|
|
60
76
|
```python
|
|
61
77
|
import numpy as np
|
|
62
|
-
from nested_recd import compute_recd_from_conjunctions,
|
|
78
|
+
from nested_recd import compute_recd_from_conjunctions, ALPHA_SYN, ALPHA_SURP
|
|
63
79
|
|
|
64
|
-
# Multivariate series: shape (T, N)
|
|
65
80
|
rng = np.random.default_rng(0)
|
|
66
81
|
X = rng.normal(size=(800, 3)).cumsum(axis=0)
|
|
67
82
|
|
|
68
83
|
out = compute_recd_from_conjunctions(X, m=3, d=4, theta3=0.10)
|
|
69
84
|
|
|
70
|
-
print("mean
|
|
71
|
-
print("mean Φ2:", float(np.nanmean(out["phi2"])))
|
|
85
|
+
print("mean excess³ (primary):", float(np.nanmean(out["excess3"])))
|
|
72
86
|
print("Φ3 active fraction:", float(np.nanmean(out["phi3"] > 0)))
|
|
87
|
+
print("weights:", out["params"]["alpha_syn"], out["params"]["alpha_surp"])
|
|
73
88
|
print("final T_recd:", float(out["T_recd"][-1]))
|
|
89
|
+
```
|
|
74
90
|
|
|
75
|
-
|
|
76
|
-
|
|
91
|
+
### Continuous excess³ only
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from nested_recd import generate_multivariate_symbols, compute_phi3_excess
|
|
95
|
+
|
|
96
|
+
S = generate_multivariate_symbols(X, m=3)
|
|
97
|
+
phi3, excess3 = compute_phi3_excess(S, window=13, theta=0.10, stride=1)
|
|
77
98
|
```
|
|
78
99
|
|
|
79
|
-
|
|
100
|
+
### Surrogate p-value on |Δ excess3|
|
|
80
101
|
|
|
81
102
|
```python
|
|
82
|
-
|
|
103
|
+
from nested_recd import surrogate_pvalue_delta_excess3
|
|
104
|
+
|
|
105
|
+
res = surrogate_pvalue_delta_excess3(X, split=400, n_surr=99, method="phase", seed=0)
|
|
106
|
+
print(res["delta_obs"], res["p_value"])
|
|
83
107
|
```
|
|
84
108
|
|
|
85
|
-
|
|
109
|
+
### Optional τ_s for λ regime weights
|
|
86
110
|
|
|
87
111
|
```python
|
|
112
|
+
out = compute_recd_from_conjunctions(X, tau_s=tau_s)
|
|
113
|
+
# or
|
|
88
114
|
out = compute_recd_from_conjunctions(X, lam_override=0.5)
|
|
89
115
|
```
|
|
90
116
|
|
|
117
|
+
**Note:** `delta_recd` / `T_recd` use **binary Φ₃** in the α-weighted clock (legacy Discrete Extramental Clock). For scientific Level-3 claims, report **continuous excess³** and nulls on `|Δ excess3|`.
|
|
118
|
+
|
|
91
119
|
## What it computes
|
|
92
120
|
|
|
93
121
|
| Symbol | Meaning |
|
|
94
122
|
|--------|---------|
|
|
95
123
|
| **Φ₁** | Co-occurrence of identical ordinal symbols across variable pairs |
|
|
96
124
|
| **Φ₂** | Persistence of pairwise ordinal relations over lag `d` |
|
|
97
|
-
|
|
|
125
|
+
| **excess³** | Continuous hybrid: `0.6·Syn + 0.4·Surp` (**primary** Level-3) |
|
|
126
|
+
| **Φ₃** | Binary ticks of excess³ above `theta3` (**secondary**) |
|
|
98
127
|
| **λ** | Chaos / reorganization intensity (from `τ_s` or `lam_override`) |
|
|
99
128
|
| **α(λ)** | Level weights: α₁ decays with λ; α₂, α₃ grow with λ |
|
|
100
|
-
| **ΔRECD** | `α₁Φ₁ + α₂Φ₂ + α₃Φ₃` |
|
|
101
|
-
| **T_recd** | Cumulative sum of ΔRECD
|
|
129
|
+
| **ΔRECD** | `α₁Φ₁ + α₂Φ₂ + α₃Φ₃` (legacy clock; binary Φ₃) |
|
|
130
|
+
| **T_recd** | Cumulative sum of ΔRECD |
|
|
102
131
|
|
|
103
132
|
Ordinal symbols use Bandt–Pompe patterns (`m=3` by default).
|
|
104
133
|
|
|
@@ -107,7 +136,7 @@ Ordinal symbols use Bandt–Pompe patterns (`m=3` by default).
|
|
|
107
136
|
```python
|
|
108
137
|
from nested_recd import phase_shuffle_independent, random_permutation_independent
|
|
109
138
|
|
|
110
|
-
X_null = phase_shuffle_independent(X, seed=42)
|
|
139
|
+
X_null = phase_shuffle_independent(X, seed=42)
|
|
111
140
|
X_perm = random_permutation_independent(X, seed=42)
|
|
112
141
|
```
|
|
113
142
|
|
|
@@ -115,8 +144,12 @@ X_perm = random_permutation_independent(X, seed=42)
|
|
|
115
144
|
|
|
116
145
|
```python
|
|
117
146
|
from nested_recd import (
|
|
147
|
+
ALPHA_SYN, ALPHA_SURP,
|
|
148
|
+
DEFAULT_THETA3, DEFAULT_THETA3_CARDIO,
|
|
118
149
|
compute_recd_from_conjunctions,
|
|
119
150
|
compute_phi1, compute_phi2, compute_phi3,
|
|
151
|
+
compute_phi3_excess, compute_excess3_window,
|
|
152
|
+
mean_excess_pre_post, surrogate_pvalue_delta_excess3,
|
|
120
153
|
compute_lambda, alpha_weights, regime_lambda_proxy,
|
|
121
154
|
compute_weighted_contributions, high_level3_rate,
|
|
122
155
|
generate_multivariate_symbols,
|
|
@@ -128,25 +161,33 @@ from nested_recd import (
|
|
|
128
161
|
|
|
129
162
|
| Project | Role |
|
|
130
163
|
|---------|------|
|
|
131
|
-
| [`systemictau`](https://pypi.org/project/systemictau/) | Full Systemic Tau library (τ_s,
|
|
132
|
-
| [`
|
|
133
|
-
|
|
|
164
|
+
| [`systemictau`](https://pypi.org/project/systemictau/) | Full Systemic Tau library (τ_s, gate RECD, studio) — optional `[nested]` extra |
|
|
165
|
+
| [`systemictau-web`](https://github.com/johelpadilla/systemictau-web) | Streamlit app; depends on this package |
|
|
166
|
+
| [`excess3`](https://github.com/johelpadilla/excess3) | Methods + intro ES + primer (specification) |
|
|
167
|
+
| [`cctp-sddb-systemic-tau`](https://github.com/johelpadilla/cctp-sddb-systemic-tau) | Cardiac VF pilot |
|
|
168
|
+
| This package | Lightweight, installable nested-time / excess³ core |
|
|
134
169
|
|
|
135
170
|
## Citation
|
|
136
171
|
|
|
137
|
-
If you use this
|
|
172
|
+
If you use excess³ / Level-3 from this package, cite the **methods** preprint (canonical specification):
|
|
138
173
|
|
|
139
|
-
> Padilla-Villanueva, J. (2026). *
|
|
174
|
+
> Padilla-Villanueva, J. (2026). *excess³: A Pre-Specified Continuous Proxy for Order-3 Synergistic Surplus* (methods). Zenodo. https://doi.org/10.5281/zenodo.21385937
|
|
140
175
|
|
|
141
|
-
|
|
176
|
+
Software / related stack:
|
|
177
|
+
|
|
178
|
+
> Padilla-Villanueva, J. (2026). Systemic Tau software archive. Zenodo. https://doi.org/10.5281/zenodo.20576241
|
|
179
|
+
|
|
180
|
+
CCTP/SDDB pilot:
|
|
181
|
+
|
|
182
|
+
> Padilla-Villanueva, J. (2026). *CCTP/SDDB: Systemic Tau and ordinal RECD before spontaneous ventricular fibrillation* (v1.0.1). Zenodo. https://doi.org/10.5281/zenodo.21270699
|
|
142
183
|
|
|
143
184
|
```bibtex
|
|
144
185
|
@software{padilla_nested_recd_2026,
|
|
145
186
|
author = {Padilla-Villanueva, Johel},
|
|
146
|
-
title = {nested-recd: Nested ordinal RECD levels},
|
|
187
|
+
title = {nested-recd: Nested ordinal RECD levels and continuous excess³},
|
|
147
188
|
year = {2026},
|
|
148
189
|
url = {https://github.com/johelpadilla/nested-recd},
|
|
149
|
-
version = {0.
|
|
190
|
+
version = {0.2.0}
|
|
150
191
|
}
|
|
151
192
|
```
|
|
152
193
|
|
|
@@ -1,21 +1,38 @@
|
|
|
1
|
-
"""Smoke and invariant tests for nested-recd."""
|
|
1
|
+
"""Smoke and invariant tests for nested-recd (excess³ contract)."""
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import pytest
|
|
5
5
|
|
|
6
6
|
from nested_recd import (
|
|
7
7
|
__version__,
|
|
8
|
+
ALPHA_SYN,
|
|
9
|
+
ALPHA_SURP,
|
|
10
|
+
DEFAULT_THETA3,
|
|
11
|
+
DEFAULT_THETA3_CARDIO,
|
|
8
12
|
compute_recd_from_conjunctions,
|
|
9
13
|
compute_phi1,
|
|
14
|
+
compute_phi3,
|
|
15
|
+
compute_phi3_excess,
|
|
16
|
+
compute_excess3_window,
|
|
10
17
|
compute_weighted_contributions,
|
|
11
18
|
generate_multivariate_symbols,
|
|
19
|
+
mean_excess_pre_post,
|
|
12
20
|
phase_shuffle_independent,
|
|
13
21
|
random_permutation_independent,
|
|
22
|
+
surrogate_pvalue_delta_excess3,
|
|
14
23
|
)
|
|
15
24
|
|
|
16
25
|
|
|
17
26
|
def test_version():
|
|
18
|
-
assert __version__ == "0.
|
|
27
|
+
assert __version__ == "0.2.0"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_weights_a_priori():
|
|
31
|
+
assert ALPHA_SYN == 0.6
|
|
32
|
+
assert ALPHA_SURP == 0.4
|
|
33
|
+
assert abs(ALPHA_SYN + ALPHA_SURP - 1.0) < 1e-12
|
|
34
|
+
assert DEFAULT_THETA3 == 0.10
|
|
35
|
+
assert DEFAULT_THETA3_CARDIO == 0.08
|
|
19
36
|
|
|
20
37
|
|
|
21
38
|
def test_pipeline_shapes_and_bounds():
|
|
@@ -26,6 +43,7 @@ def test_pipeline_shapes_and_bounds():
|
|
|
26
43
|
T = out["phi1"].shape[0]
|
|
27
44
|
assert out["phi2"].shape == (T,)
|
|
28
45
|
assert out["phi3"].shape == (T,)
|
|
46
|
+
assert out["excess3"].shape == (T,)
|
|
29
47
|
assert out["delta_recd"].shape == (T,)
|
|
30
48
|
assert out["T_recd"].shape == (T,)
|
|
31
49
|
assert out["S"].shape[1] == 3
|
|
@@ -34,7 +52,12 @@ def test_pipeline_shapes_and_bounds():
|
|
|
34
52
|
assert np.all((out["phi2"] >= 0) & (out["phi2"] <= 1))
|
|
35
53
|
assert np.nanmax(out["phi3"]) <= 1.0
|
|
36
54
|
assert np.nanmin(out["phi3"]) >= 0.0 or np.isnan(np.nanmin(out["phi3"]))
|
|
37
|
-
assert np.all(np.diff(out["T_recd"]) >= -1e-12)
|
|
55
|
+
assert np.all(np.diff(out["T_recd"]) >= -1e-12)
|
|
56
|
+
|
|
57
|
+
# Contract: continuous primary declared in params
|
|
58
|
+
assert out["params"]["level3_primary"] == "excess3"
|
|
59
|
+
assert out["params"]["alpha_syn"] == ALPHA_SYN
|
|
60
|
+
assert out["params"]["alpha_surp"] == ALPHA_SURP
|
|
38
61
|
|
|
39
62
|
|
|
40
63
|
def test_identical_series_high_phi1():
|
|
@@ -85,3 +108,46 @@ def test_phi1_single_variable_zeros():
|
|
|
85
108
|
S = np.zeros((50, 1), dtype=int)
|
|
86
109
|
phi1 = compute_phi1(S)
|
|
87
110
|
assert np.all(phi1 == 0)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def test_phi3_delegates_to_phi3_excess():
|
|
114
|
+
rng = np.random.default_rng(6)
|
|
115
|
+
S = generate_multivariate_symbols(rng.normal(size=(120, 3)).cumsum(0), m=3)
|
|
116
|
+
a = compute_phi3(S, window=13, theta=0.10)
|
|
117
|
+
b = compute_phi3_excess(S, window=13, theta=0.10)
|
|
118
|
+
np.testing.assert_allclose(a[0], b[0], equal_nan=True)
|
|
119
|
+
np.testing.assert_allclose(a[1], b[1], equal_nan=True)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def test_excess3_window_weights():
|
|
123
|
+
rng = np.random.default_rng(7)
|
|
124
|
+
# XOR-like synergistic lock: pairs weak, triple determined
|
|
125
|
+
n = 40
|
|
126
|
+
a = rng.integers(0, 2, size=n)
|
|
127
|
+
b = rng.integers(0, 2, size=n)
|
|
128
|
+
c = a ^ b
|
|
129
|
+
win = np.column_stack([a, b, c]).astype(int)
|
|
130
|
+
score = compute_excess3_window(win)
|
|
131
|
+
assert np.isfinite(score)
|
|
132
|
+
assert score >= 0.0
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def test_mean_excess_pre_post():
|
|
136
|
+
x = np.array([0.0, 0.0, 1.0, 1.0, 1.0])
|
|
137
|
+
pre, post, delta = mean_excess_pre_post(x, split=2)
|
|
138
|
+
assert pre == 0.0
|
|
139
|
+
assert post == 1.0
|
|
140
|
+
assert delta == 1.0
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def test_surrogate_pvalue_smoke():
|
|
144
|
+
rng = np.random.default_rng(8)
|
|
145
|
+
T = 180
|
|
146
|
+
# Independent noise: |Δ| should not be extreme
|
|
147
|
+
X = rng.normal(size=(T, 3))
|
|
148
|
+
res = surrogate_pvalue_delta_excess3(
|
|
149
|
+
X, split=T // 2, n_surr=19, method="permute", seed=1, window=11, stride=2
|
|
150
|
+
)
|
|
151
|
+
assert "p_value" in res
|
|
152
|
+
assert 0.0 <= res["p_value"] <= 1.0
|
|
153
|
+
assert res["n_surr"] >= 1
|
nested_recd-0.1.0/README.md
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
# nested-recd
|
|
2
|
-
|
|
3
|
-
[](https://pypi.org/project/nested-recd/)
|
|
4
|
-
[](https://pypi.org/project/nested-recd/)
|
|
5
|
-
[](LICENSE)
|
|
6
|
-
|
|
7
|
-
**Nested ordinal RECD** — pure-NumPy implementation of nested ordinal conjunction levels (Φ₁, Φ₂, Φ₃) and λ-weighted Discrete Extramental Clock (RECD) accumulation.
|
|
8
|
-
|
|
9
|
-
This is the standalone library behind the nested-time structure used in the CCTP/SDDB cardiac pilot and the experimental design in *Conversación de la naturaleza del tiempo*.
|
|
10
|
-
|
|
11
|
-
## Install
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
pip install nested-recd
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
From source:
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
pip install git+https://github.com/johelpadilla/nested-recd.git
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Quick start
|
|
24
|
-
|
|
25
|
-
```python
|
|
26
|
-
import numpy as np
|
|
27
|
-
from nested_recd import compute_recd_from_conjunctions, compute_weighted_contributions
|
|
28
|
-
|
|
29
|
-
# Multivariate series: shape (T, N)
|
|
30
|
-
rng = np.random.default_rng(0)
|
|
31
|
-
X = rng.normal(size=(800, 3)).cumsum(axis=0)
|
|
32
|
-
|
|
33
|
-
out = compute_recd_from_conjunctions(X, m=3, d=4, theta3=0.10)
|
|
34
|
-
|
|
35
|
-
print("mean Φ1:", float(np.nanmean(out["phi1"])))
|
|
36
|
-
print("mean Φ2:", float(np.nanmean(out["phi2"])))
|
|
37
|
-
print("Φ3 active fraction:", float(np.nanmean(out["phi3"] > 0)))
|
|
38
|
-
print("final T_recd:", float(out["T_recd"][-1]))
|
|
39
|
-
|
|
40
|
-
w = compute_weighted_contributions(out)
|
|
41
|
-
print("frac level-3 contribution:", w["frac_contrib3"])
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Optional: supply a Systemic Tau series `tau_s` (aligned in time) so that λ is derived empirically:
|
|
45
|
-
|
|
46
|
-
```python
|
|
47
|
-
out = compute_recd_from_conjunctions(X, tau_s=tau_s)
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Or fix the regime weight with a scalar / array override:
|
|
51
|
-
|
|
52
|
-
```python
|
|
53
|
-
out = compute_recd_from_conjunctions(X, lam_override=0.5)
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## What it computes
|
|
57
|
-
|
|
58
|
-
| Symbol | Meaning |
|
|
59
|
-
|--------|---------|
|
|
60
|
-
| **Φ₁** | Co-occurrence of identical ordinal symbols across variable pairs |
|
|
61
|
-
| **Φ₂** | Persistence of pairwise ordinal relations over lag `d` |
|
|
62
|
-
| **Φ₃** | Higher-order synergy proxy (total-correlation excess + joint surprise) |
|
|
63
|
-
| **λ** | Chaos / reorganization intensity (from `τ_s` or `lam_override`) |
|
|
64
|
-
| **α(λ)** | Level weights: α₁ decays with λ; α₂, α₃ grow with λ |
|
|
65
|
-
| **ΔRECD** | `α₁Φ₁ + α₂Φ₂ + α₃Φ₃` |
|
|
66
|
-
| **T_recd** | Cumulative sum of ΔRECD (nested-time clock) |
|
|
67
|
-
|
|
68
|
-
Ordinal symbols use Bandt–Pompe patterns (`m=3` by default).
|
|
69
|
-
|
|
70
|
-
## Surrogates
|
|
71
|
-
|
|
72
|
-
```python
|
|
73
|
-
from nested_recd import phase_shuffle_independent, random_permutation_independent
|
|
74
|
-
|
|
75
|
-
X_null = phase_shuffle_independent(X, seed=42) # IAAFT per column
|
|
76
|
-
X_perm = random_permutation_independent(X, seed=42)
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## API surface
|
|
80
|
-
|
|
81
|
-
```python
|
|
82
|
-
from nested_recd import (
|
|
83
|
-
compute_recd_from_conjunctions,
|
|
84
|
-
compute_phi1, compute_phi2, compute_phi3,
|
|
85
|
-
compute_lambda, alpha_weights, regime_lambda_proxy,
|
|
86
|
-
compute_weighted_contributions, high_level3_rate,
|
|
87
|
-
generate_multivariate_symbols,
|
|
88
|
-
phase_shuffle_independent, generate_surrogate_ensemble,
|
|
89
|
-
)
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## Relation to other projects
|
|
93
|
-
|
|
94
|
-
| Project | Role |
|
|
95
|
-
|---------|------|
|
|
96
|
-
| [`systemictau`](https://pypi.org/project/systemictau/) | Full Systemic Tau library (τ_s, platform, studio) |
|
|
97
|
-
| [`cctp-sddb-systemic-tau`](https://github.com/johelpadilla/cctp-sddb-systemic-tau) | Cardiac VF pilot using this nested RECD pipeline |
|
|
98
|
-
| This package | Lightweight, installable nested-time / ordinal RECD core |
|
|
99
|
-
|
|
100
|
-
## Citation
|
|
101
|
-
|
|
102
|
-
If you use this software, please cite the CCTP/SDDB pilot archive:
|
|
103
|
-
|
|
104
|
-
> Padilla-Villanueva, J. (2026). *CCTP/SDDB: Systemic Tau and ordinal RECD before spontaneous ventricular fibrillation* (v1.0.1). Zenodo. https://doi.org/10.5281/zenodo.21270699
|
|
105
|
-
|
|
106
|
-
And the theoretical nested-time / RECD framework as appropriate for your venue.
|
|
107
|
-
|
|
108
|
-
```bibtex
|
|
109
|
-
@software{padilla_nested_recd_2026,
|
|
110
|
-
author = {Padilla-Villanueva, Johel},
|
|
111
|
-
title = {nested-recd: Nested ordinal RECD levels},
|
|
112
|
-
year = {2026},
|
|
113
|
-
url = {https://github.com/johelpadilla/nested-recd},
|
|
114
|
-
version = {0.1.0}
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## License
|
|
119
|
-
|
|
120
|
-
MIT © 2026 Johel Padilla-Villanueva
|
|
121
|
-
ORCID: [0000-0002-5797-6931](https://orcid.org/0000-0002-5797-6931)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|