kews 0.1.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.
- kews-0.1.0/LICENSE.txt +21 -0
- kews-0.1.0/MANIFEST.in +8 -0
- kews-0.1.0/PKG-INFO +173 -0
- kews-0.1.0/README.md +135 -0
- kews-0.1.0/examples/01a_bifur_harvesting.ipynb +415 -0
- kews-0.1.0/examples/01b_bifur_rosenzweig_macarthur_hopf.ipynb +500 -0
- kews-0.1.0/examples/02a_rate_saddle.ipynb +475 -0
- kews-0.1.0/examples/02b_rate_bautin.ipynb +462 -0
- kews-0.1.0/examples/03_amoc_model_ews.ipynb +966 -0
- kews-0.1.0/examples/README.md +13 -0
- kews-0.1.0/experiments/README.md +29 -0
- kews-0.1.0/experiments/__init__.py +1 -0
- kews-0.1.0/experiments/amoc/00_inspect_data.ipynb +228 -0
- kews-0.1.0/experiments/amoc/01a_full_analysis.ipynb +403 -0
- kews-0.1.0/experiments/amoc/01b_ablation_analysis.ipynb +306 -0
- kews-0.1.0/experiments/amoc/02_spectral_analysis.ipynb +554 -0
- kews-0.1.0/experiments/amoc/amoc_utils.py +217 -0
- kews-0.1.0/experiments/amoc/data/amoc_si_mldmax_2Juan.nc +0 -0
- kews-0.1.0/experiments/empirical/01_empirical_ews.ipynb +426 -0
- kews-0.1.0/experiments/empirical/empirical_utils.py +211 -0
- kews-0.1.0/experiments/indicators.py +104 -0
- kews-0.1.0/experiments/metrics.py +286 -0
- kews-0.1.0/experiments/systems/__init__.py +5 -0
- kews-0.1.0/experiments/systems/bifurcation/__init__.py +0 -0
- kews-0.1.0/experiments/systems/bifurcation/amoc.py +340 -0
- kews-0.1.0/experiments/systems/bifurcation/bifurcation_simulator.py +132 -0
- kews-0.1.0/experiments/systems/bifurcation/may_harvesting.py +351 -0
- kews-0.1.0/experiments/systems/bifurcation/rosenzweig_macarthur.py +468 -0
- kews-0.1.0/experiments/systems/generate.py +60 -0
- kews-0.1.0/experiments/systems/rate/__init__.py +0 -0
- kews-0.1.0/experiments/systems/rate/amoc.py +288 -0
- kews-0.1.0/experiments/systems/rate/bautin.py +279 -0
- kews-0.1.0/experiments/systems/rate/rate_simulator.py +139 -0
- kews-0.1.0/experiments/systems/rate/saddle_node.py +197 -0
- kews-0.1.0/experiments/systems/registry.py +128 -0
- kews-0.1.0/experiments/systems/types.py +41 -0
- kews-0.1.0/experiments/systems/utils.py +83 -0
- kews-0.1.0/kews/__init__.py +119 -0
- kews-0.1.0/kews/_core.py +441 -0
- kews-0.1.0/kews/diagnostics.py +116 -0
- kews-0.1.0/kews/observables.py +254 -0
- kews-0.1.0/kews.egg-info/PKG-INFO +173 -0
- kews-0.1.0/kews.egg-info/SOURCES.txt +48 -0
- kews-0.1.0/kews.egg-info/dependency_links.txt +1 -0
- kews-0.1.0/kews.egg-info/requires.txt +23 -0
- kews-0.1.0/kews.egg-info/top_level.txt +1 -0
- kews-0.1.0/pyproject.toml +53 -0
- kews-0.1.0/scripts/download_giss_nccs.py +311 -0
- kews-0.1.0/setup.cfg +4 -0
- kews-0.1.0/setup.py +3 -0
kews-0.1.0/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 KEWS Developer Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
kews-0.1.0/MANIFEST.in
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
include README.md LICENSE.txt
|
|
2
|
+
recursive-include examples *.md *.ipynb
|
|
3
|
+
recursive-include experiments *.py *.md *.ipynb
|
|
4
|
+
prune experiments/empirical/data
|
|
5
|
+
prune experiments/amoc/data
|
|
6
|
+
include experiments/amoc/data/amoc_si_mldmax_2Juan.nc
|
|
7
|
+
recursive-include scripts *.py
|
|
8
|
+
global-exclude __pycache__ *.py[cod]
|
kews-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kews
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Koopman operator early warning signals
|
|
5
|
+
Author-email: Juan Nathaniel <jn2808@columbia.edu>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/juannat7/kews
|
|
8
|
+
Project-URL: Issues, https://github.com/juannat7/kews/issues
|
|
9
|
+
Project-URL: Paper, https://arxiv.org/abs/2608.14716
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE.txt
|
|
16
|
+
Requires-Dist: flax==0.12.4
|
|
17
|
+
Requires-Dist: jax==0.9.0.1
|
|
18
|
+
Requires-Dist: jaxlib==0.9.0.1
|
|
19
|
+
Requires-Dist: optax==0.2.6
|
|
20
|
+
Provides-Extra: paper
|
|
21
|
+
Requires-Dist: numpy==2.3.5; extra == "paper"
|
|
22
|
+
Requires-Dist: scipy==1.16.3; extra == "paper"
|
|
23
|
+
Requires-Dist: matplotlib==3.10.8; extra == "paper"
|
|
24
|
+
Requires-Dist: scikit-learn==1.8.0; extra == "paper"
|
|
25
|
+
Requires-Dist: pandas==3.0.0; extra == "paper"
|
|
26
|
+
Requires-Dist: xarray==2026.1.0; extra == "paper"
|
|
27
|
+
Requires-Dist: netCDF4==1.7.3; extra == "paper"
|
|
28
|
+
Requires-Dist: cmocean==4.0.3; extra == "paper"
|
|
29
|
+
Requires-Dist: requests==2.32.5; extra == "paper"
|
|
30
|
+
Requires-Dist: tqdm==4.67.1; extra == "paper"
|
|
31
|
+
Requires-Dist: jupyterlab==4.5.0; extra == "paper"
|
|
32
|
+
Requires-Dist: nbconvert==7.16.6; extra == "paper"
|
|
33
|
+
Requires-Dist: ipykernel==7.1.0; extra == "paper"
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
36
|
+
Requires-Dist: twine>=6; extra == "dev"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# KEWS: Koopman Early Warning Signals
|
|
40
|
+
|
|
41
|
+
**KEWS** (pronounced “cues,” as in cues to potential tipping) is a JAX package for Koopman-based early warning signals of bifurcation- and rate-induced tipping.
|
|
42
|
+
|
|
43
|
+
<div align="center">
|
|
44
|
+
|
|
45
|
+
[](https://www.python.org/)
|
|
46
|
+
[](https://docs.jax.dev/)
|
|
47
|
+
[](https://github.com/juannat7/kews/blob/main/LICENSE.txt)
|
|
48
|
+
[](https://pypi.org/project/kews/)
|
|
49
|
+
[](https://pypi.org/project/kews/)
|
|
50
|
+
[](https://arxiv.org/abs/2608.14716)
|
|
51
|
+
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
## Abstract
|
|
55
|
+
|
|
56
|
+
Abrupt transitions in complex systems are often preceded by early warning signals. However, most indicators rely on the notion of critical slowing down and do not generally extend to rate-induced tipping where transitions can occur without local loss of stability. This is problematic in stochastic, nonautonomous systems where internal variability and time-varying variables interact to shape tipping onset.
|
|
57
|
+
|
|
58
|
+
We use Koopman operator theory to develop a unified early warning framework for both bifurcation and rate-induced tipping in stochastic systems. Our approach builds on residual Koopman mode decomposition that measures discrepancies between dynamics and their finite-dimensional approximation, and extends it to the control setting by augmenting the observable space with time-varying control variables.
|
|
59
|
+
|
|
60
|
+
In idealized examples, the resulting indicators recover expected signatures near bifurcation points and improve detection in rate-induced regimes where classical indicators fail. We further show that learned embeddings through deep learning outperform prescribed dictionaries, especially in a high-dimensional setting.
|
|
61
|
+
|
|
62
|
+
Applied to simulations of the Atlantic Meridional Overturning Circulation, our Koopman-based indicators distinguish tipping from non-tipping trajectories and reveal interpretable spectral signatures prior to critical transition.
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
Python 3.11 or newer is required. Install the library from PyPI:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install kews
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
To reproduce the paper or develop the code:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
git clone https://github.com/juannat7/kews.git
|
|
76
|
+
cd kews
|
|
77
|
+
pip install -e ".[paper,dev]"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Reproduction instructions are in [examples](https://github.com/juannat7/kews/tree/main/examples) for the model systems and [experiments](https://github.com/juannat7/kews/tree/main/experiments) for the coupled AMOC and empirical cases.
|
|
81
|
+
|
|
82
|
+
## Quickstart
|
|
83
|
+
|
|
84
|
+
Compute rolling ResKMD residuals from a scalar time series:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
import jax.numpy as jnp
|
|
88
|
+
from jax import random
|
|
89
|
+
|
|
90
|
+
import kews
|
|
91
|
+
from kews.observables import time_delay
|
|
92
|
+
|
|
93
|
+
time = jnp.linspace(0, 10 * jnp.pi, 100)
|
|
94
|
+
state = jnp.sin(time) + 0.01 * random.normal(random.key(7), time.shape)
|
|
95
|
+
|
|
96
|
+
signal = kews.resdmd(
|
|
97
|
+
state,
|
|
98
|
+
window=50, # Window length in samples (or a fraction, e.g. 0.5)
|
|
99
|
+
observable=time_delay(n_delay=10), # Time-delay dictionary with 10 coordinates
|
|
100
|
+
rank=0.9, # Retain 90% of the SVD energy
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# One residual per time step; the first 49 entries are NaN.
|
|
104
|
+
print(signal.shape) # (100,)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Control-aware residuals
|
|
108
|
+
|
|
109
|
+
Pass a control time series aligned with the state:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
control = jnp.linspace(-1, 1, state.size)
|
|
113
|
+
controlled_signal = kews.resdmd(
|
|
114
|
+
state,
|
|
115
|
+
window=50,
|
|
116
|
+
observable=time_delay(10),
|
|
117
|
+
control=control,
|
|
118
|
+
)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Observable choices
|
|
122
|
+
|
|
123
|
+
Use fixed random Fourier features instead of delay coordinates:
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from kews.observables import rff
|
|
127
|
+
|
|
128
|
+
random_signal = kews.resdmd(
|
|
129
|
+
state,
|
|
130
|
+
window=50,
|
|
131
|
+
observable=rff(n_features=100, scale=0.2, seed=7),
|
|
132
|
+
)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The random basis stays fixed across windows. An autoencoder can learn the features:
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from kews.observables import mlp
|
|
139
|
+
|
|
140
|
+
learned_signal = kews.resdmd(
|
|
141
|
+
state,
|
|
142
|
+
window=50,
|
|
143
|
+
observable=mlp(hidden_layers=(16, 8), bottleneck_dim=3, seed=7),
|
|
144
|
+
fit_kwargs={"epochs": 200, "batch_size": 32, "lr": 1e-3},
|
|
145
|
+
)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Training uses only the first window; the encoder is then frozen. Create a new observable for each independent fit. Paper notebooks specify their full training settings.
|
|
149
|
+
|
|
150
|
+
## Spectral diagnostics
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
from kews import diagnostics
|
|
154
|
+
|
|
155
|
+
fit = diagnostics.fit_operator(state, observable=time_delay(10), rank=0.9)
|
|
156
|
+
generator = diagnostics.generator_eigenvalues(fit["eigvals"], dt=1.0)
|
|
157
|
+
dominant = diagnostics.dominant_mode(generator, dt=1.0)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`dt` is the sampling interval in the units of the input data. The mode summary includes decay rate, oscillation period, and e-folding time.
|
|
161
|
+
|
|
162
|
+
## Citation
|
|
163
|
+
|
|
164
|
+
```bibtex
|
|
165
|
+
@article{nathaniel2026koopman,
|
|
166
|
+
title={Koopman early warning signals for bifurcation and rate-induced tipping},
|
|
167
|
+
author={Nathaniel, Juan and Roesch, Carla and DeSantis, Derek and Kooloth, Parvathi and Fan, Hang and Lucarini, Valerio and Romanou, Anastasia and Gentine, Pierre},
|
|
168
|
+
journal={arXiv preprint arXiv:2608.14716},
|
|
169
|
+
year={2026}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Code uses the [MIT license](https://github.com/juannat7/kews/blob/main/LICENSE.txt). External datasets retain their original terms.
|
kews-0.1.0/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# KEWS: Koopman Early Warning Signals
|
|
2
|
+
|
|
3
|
+
**KEWS** (pronounced “cues,” as in cues to potential tipping) is a JAX package for Koopman-based early warning signals of bifurcation- and rate-induced tipping.
|
|
4
|
+
|
|
5
|
+
<div align="center">
|
|
6
|
+
|
|
7
|
+
[](https://www.python.org/)
|
|
8
|
+
[](https://docs.jax.dev/)
|
|
9
|
+
[](https://github.com/juannat7/kews/blob/main/LICENSE.txt)
|
|
10
|
+
[](https://pypi.org/project/kews/)
|
|
11
|
+
[](https://pypi.org/project/kews/)
|
|
12
|
+
[](https://arxiv.org/abs/2608.14716)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
## Abstract
|
|
17
|
+
|
|
18
|
+
Abrupt transitions in complex systems are often preceded by early warning signals. However, most indicators rely on the notion of critical slowing down and do not generally extend to rate-induced tipping where transitions can occur without local loss of stability. This is problematic in stochastic, nonautonomous systems where internal variability and time-varying variables interact to shape tipping onset.
|
|
19
|
+
|
|
20
|
+
We use Koopman operator theory to develop a unified early warning framework for both bifurcation and rate-induced tipping in stochastic systems. Our approach builds on residual Koopman mode decomposition that measures discrepancies between dynamics and their finite-dimensional approximation, and extends it to the control setting by augmenting the observable space with time-varying control variables.
|
|
21
|
+
|
|
22
|
+
In idealized examples, the resulting indicators recover expected signatures near bifurcation points and improve detection in rate-induced regimes where classical indicators fail. We further show that learned embeddings through deep learning outperform prescribed dictionaries, especially in a high-dimensional setting.
|
|
23
|
+
|
|
24
|
+
Applied to simulations of the Atlantic Meridional Overturning Circulation, our Koopman-based indicators distinguish tipping from non-tipping trajectories and reveal interpretable spectral signatures prior to critical transition.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
Python 3.11 or newer is required. Install the library from PyPI:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install kews
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
To reproduce the paper or develop the code:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
git clone https://github.com/juannat7/kews.git
|
|
38
|
+
cd kews
|
|
39
|
+
pip install -e ".[paper,dev]"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Reproduction instructions are in [examples](https://github.com/juannat7/kews/tree/main/examples) for the model systems and [experiments](https://github.com/juannat7/kews/tree/main/experiments) for the coupled AMOC and empirical cases.
|
|
43
|
+
|
|
44
|
+
## Quickstart
|
|
45
|
+
|
|
46
|
+
Compute rolling ResKMD residuals from a scalar time series:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import jax.numpy as jnp
|
|
50
|
+
from jax import random
|
|
51
|
+
|
|
52
|
+
import kews
|
|
53
|
+
from kews.observables import time_delay
|
|
54
|
+
|
|
55
|
+
time = jnp.linspace(0, 10 * jnp.pi, 100)
|
|
56
|
+
state = jnp.sin(time) + 0.01 * random.normal(random.key(7), time.shape)
|
|
57
|
+
|
|
58
|
+
signal = kews.resdmd(
|
|
59
|
+
state,
|
|
60
|
+
window=50, # Window length in samples (or a fraction, e.g. 0.5)
|
|
61
|
+
observable=time_delay(n_delay=10), # Time-delay dictionary with 10 coordinates
|
|
62
|
+
rank=0.9, # Retain 90% of the SVD energy
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# One residual per time step; the first 49 entries are NaN.
|
|
66
|
+
print(signal.shape) # (100,)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Control-aware residuals
|
|
70
|
+
|
|
71
|
+
Pass a control time series aligned with the state:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
control = jnp.linspace(-1, 1, state.size)
|
|
75
|
+
controlled_signal = kews.resdmd(
|
|
76
|
+
state,
|
|
77
|
+
window=50,
|
|
78
|
+
observable=time_delay(10),
|
|
79
|
+
control=control,
|
|
80
|
+
)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Observable choices
|
|
84
|
+
|
|
85
|
+
Use fixed random Fourier features instead of delay coordinates:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from kews.observables import rff
|
|
89
|
+
|
|
90
|
+
random_signal = kews.resdmd(
|
|
91
|
+
state,
|
|
92
|
+
window=50,
|
|
93
|
+
observable=rff(n_features=100, scale=0.2, seed=7),
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The random basis stays fixed across windows. An autoencoder can learn the features:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from kews.observables import mlp
|
|
101
|
+
|
|
102
|
+
learned_signal = kews.resdmd(
|
|
103
|
+
state,
|
|
104
|
+
window=50,
|
|
105
|
+
observable=mlp(hidden_layers=(16, 8), bottleneck_dim=3, seed=7),
|
|
106
|
+
fit_kwargs={"epochs": 200, "batch_size": 32, "lr": 1e-3},
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Training uses only the first window; the encoder is then frozen. Create a new observable for each independent fit. Paper notebooks specify their full training settings.
|
|
111
|
+
|
|
112
|
+
## Spectral diagnostics
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from kews import diagnostics
|
|
116
|
+
|
|
117
|
+
fit = diagnostics.fit_operator(state, observable=time_delay(10), rank=0.9)
|
|
118
|
+
generator = diagnostics.generator_eigenvalues(fit["eigvals"], dt=1.0)
|
|
119
|
+
dominant = diagnostics.dominant_mode(generator, dt=1.0)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`dt` is the sampling interval in the units of the input data. The mode summary includes decay rate, oscillation period, and e-folding time.
|
|
123
|
+
|
|
124
|
+
## Citation
|
|
125
|
+
|
|
126
|
+
```bibtex
|
|
127
|
+
@article{nathaniel2026koopman,
|
|
128
|
+
title={Koopman early warning signals for bifurcation and rate-induced tipping},
|
|
129
|
+
author={Nathaniel, Juan and Roesch, Carla and DeSantis, Derek and Kooloth, Parvathi and Fan, Hang and Lucarini, Valerio and Romanou, Anastasia and Gentine, Pierre},
|
|
130
|
+
journal={arXiv preprint arXiv:2608.14716},
|
|
131
|
+
year={2026}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Code uses the [MIT license](https://github.com/juannat7/kews/blob/main/LICENSE.txt). External datasets retain their original terms.
|