Skip to content

Commit e45177f

Browse files
committed
Merge remote-tracking branch 'origin/master' into joss-paper
2 parents ee2ba4a + a220de1 commit e45177f

File tree

238 files changed

+4209
-4079
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

238 files changed

+4209
-4079
lines changed

.github/workflows/publish_to_pypi.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
build
3232
--user
3333
- name: Install package for testing
34-
run: pip install .
34+
run: pip install ".[full]"
3535
- name: Run tests
3636
run: make tests
3737
- name: Build a binary wheel and a source tarball

.github/workflows/publish_to_test_pypi.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ jobs:
1515
name: Build and publish python distributions to TestPyPI
1616
runs-on: ubuntu-latest
1717
concurrency: release
18+
if: ${{ github.event.workflow_run.head_branch == 'test_release' }} # Only run if the first workflow was on the 'test_release' branch
1819
steps:
1920
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
2021
- uses: actions/checkout@master
@@ -31,7 +32,7 @@ jobs:
3132
build
3233
--user
3334
- name: Install teaspoon for testing
34-
run: pip install .
35+
run: pip install ".[full]"
3536
- name: Run tests
3637
run: make tests
3738
- name: Build a binary wheel and a source tarball

.github/workflows/test_installs.yml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
build
3434
--user
3535
- name: Install teaspoon for testing
36-
run: pip install .
36+
run: pip install ".[full]"
3737
- name: Run tests
3838
run: make tests
3939
build-39-mac:
@@ -55,7 +55,7 @@ jobs:
5555
build
5656
--user
5757
- name: Install teaspoon for testing
58-
run: pip install .
58+
run: pip install ".[full]"
5959
- name: Run tests
6060
run: make tests
6161
build-39-windows:
@@ -77,7 +77,7 @@ jobs:
7777
build
7878
--user
7979
- name: Install teaspoon for testing
80-
run: pip install .
80+
run: pip install ".[full]"
8181
- name: Run tests
8282
run: make tests
8383
build-310-ubuntu:
@@ -99,7 +99,7 @@ jobs:
9999
build
100100
--user
101101
- name: Install teaspoon for testing
102-
run: pip install .
102+
run: pip install ".[full]"
103103
- name: Run tests
104104
run: make tests
105105
build-310-mac:
@@ -121,7 +121,7 @@ jobs:
121121
build
122122
--user
123123
- name: Install teaspoon for testing
124-
run: pip install .
124+
run: pip install ".[full]"
125125
- name: Run tests
126126
run: make tests
127127
build-310-windows:
@@ -143,7 +143,7 @@ jobs:
143143
build
144144
--user
145145
- name: Install teaspoon for testing
146-
run: pip install .
146+
run: pip install ".[full]"
147147
- name: Run tests
148148
run: make tests
149149
build-311-ubuntu:
@@ -165,7 +165,7 @@ jobs:
165165
build
166166
--user
167167
- name: Install teaspoon for testing
168-
run: pip install .
168+
run: pip install ".[full]"
169169
- name: Run tests
170170
run: make tests
171171
build-311-mac:
@@ -187,7 +187,7 @@ jobs:
187187
build
188188
--user
189189
- name: Install teaspoon for testing
190-
run: pip install .
190+
run: pip install ".[full]"
191191
- name: Run tests
192192
run: make tests
193193
build-311-windows:
@@ -209,7 +209,7 @@ jobs:
209209
build
210210
--user
211211
- name: Install teaspoon for testing
212-
run: pip install .
212+
run: pip install ".[full]"
213213
- name: Run tests
214214
run: make tests
215215
build-312-ubuntu:
@@ -231,7 +231,7 @@ jobs:
231231
build
232232
--user
233233
- name: Install teaspoon for testing
234-
run: pip install .
234+
run: pip install ".[full]"
235235
- name: Run tests
236236
run: make tests
237237
build-312-mac:
@@ -253,7 +253,7 @@ jobs:
253253
build
254254
--user
255255
- name: Install teaspoon for testing
256-
run: pip install .
256+
run: pip install ".[full]"
257257
- name: Run tests
258258
run: make tests
259259
build-312-windows:
@@ -275,7 +275,7 @@ jobs:
275275
build
276276
--user
277277
- name: Install teaspoon for testing
278-
run: pip install .
278+
run: pip install ".[full]"
279279
- name: Run tests
280280
run: make tests
281281

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include teaspoon/teaspoon/MakeData/DynSysLib/Data/EEG/*.txt

README.md

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,38 @@ The code is a compilation of work done by [Elizabeth Munch](http://www.elizabeth
2121

2222
We gratefully acknowledge the support of the National Science Foundation, which has helped make this work possible.
2323

24+
About TSP
25+
=========
26+
27+
![The basic pipeline of a TSP project aligned with the modules of teaspoon.](doc_source/figures/tspPipeline.png)
28+
29+
Many topological signal processing projects can be fit into the pipeline shown above; and this pipeline aligns with the five submodules of `teaspoon`.
30+
We start with input time series data. In `teaspoon`, the [`MakeData`](https://teaspoontda.github.io/teaspoon/modules/MakeData/index.html) module provides methods for creating synthetic data sets for testing purposes, including the [`DynSysLib`](https://teaspoontda.github.io/teaspoon/modules/MakeData/DynSysLib/index.html) submodule with an extensive array of dynamical systems.
31+
The [`ParameterSelection`](https://teaspoontda.github.io/teaspoon/modules/ParamSelection/index.html) modules provides tools for determining best parameters for transforming the time series into a delay coordinate (sometimes called Takens') embedding. This includes standard tools such as false nearest neighbors and mutual information function as well as newly developed tools. The [Signal Processing `SP`](https://teaspoontda.github.io/teaspoon/modules/SP/index.html) module does the conversion from a time series to a topological input. This includes the standard delay coordinate embedding, as well as network representations of time series. This topological input can be converted to a topological signature, in most cases a persistence diagram, using the [Topological Data Analysis `TDA` ](https://teaspoontda.github.io/teaspoon/modules/TDA/index.html) module. Finally, these persistence diagrams can be used in a machine learning pipeline using the vectorization tools from the [Machine Learning `ML`](https://teaspoontda.github.io/teaspoon/modules/ML/index.html) module.
32+
33+
2434
Installation
2535
=============
2636
To install this package, both boost and CMake must be installed as system dependencies. For boost see for [unix](https://www.boost.org/doc/libs/1_66_0/more/getting_started/unix-variants.html) and [windows](https://www.boost.org/doc/libs/1_62_0/more/getting_started/windows.html). For mac, you can run ``brew install boost`` if using homebrew as a package manager. For CMake see [here](https://cmake.org/install/).
2737

2838
The teaspoon package is available through pip install with version details found [here](https://pypi.org/project/teaspoon/).
2939
The package can be installed using the following pip installation:
3040

31-
``pip install teaspoon``
41+
```bash
42+
pip install teaspoon
43+
```
3244

33-
To install the most up-to-date version of the code, you can clone the repo and then run::
45+
To install the most up-to-date version of the code, you can clone the repo and then run
3446

35-
``pip install .``
47+
```bash
48+
pip install .
49+
```
3650

3751
from the main directory. Note that the master branch will correspond to the version available in pypi, and the test_release branch may have new features.
3852

3953
Please reference the requirements page in the [documentation](https://teaspoontda.github.io/teaspoon/) for more details on other required installations.
4054

4155
Contacts
4256
=============
43-
* Liz Munch: [[email protected]](mailto:[email protected]).
44-
* Firas Khasawneh: [[email protected]](mailto:[email protected]).
57+
* Liz Munch: [[email protected]](mailto:[email protected])
58+
* Firas Khasawneh: [[email protected]](mailto:[email protected])
98.2 KB
Loading

doc_source/index.rst

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ All code is open source with up to date documentation, making the code easy to u
1414
Table of Contents
1515
*******************
1616

17+
1718
.. toctree::
18-
:maxdepth: 4
19+
:maxdepth: 2
1920
:numbered:
2021

2122
Getting Started <installation/index.rst>
@@ -25,6 +26,24 @@ Table of Contents
2526
License <license.rst>
2627
Citing <citing.rst>
2728

29+
Modules
30+
*******
31+
32+
33+
.. image:: figures/tspPipeline.png
34+
:alt: The basic pipeline of a TSP project aligned with the modules of teaspoon.
35+
36+
Many topological signal processing projects can be fit into the pipeline shown above; and this pipeline aligns with the five submodules of ``teaspoon``.
37+
We start with input time series data. In ``teaspoon``, the `MakeData`_ module provides methods for creating synthetic data sets for testing purposes, including the `DynSysLib`_ submodule with an extensive array of dynamical systems.
38+
The `ParameterSelection`_ modules provides tools for determining best parameters for transforming the time series into a delay coordinate (sometimes called Takens') embedding. This includes standard tools such as false nearest neighbors and mutual information function as well as newly developed tools. The Signal Processing (`SP`_) module does the conversion from a time series to a topological input. This includes the standard delay coordinate embedding, as well as network representations of time series. This topological input can be converted to a topological signature, in most cases a persistence diagram, using the `TDA`_ module. These persistence diagrams can then be used in a machine learning pipeline using the vectorization tools from the `ML`_ module. Our newest module, Data Assimilation and Forecasting (`DAF`_),provides tools for generating data driven models for dynamical systems and optimally updating the models using persistent homology.
39+
40+
.. _MakeData: https://teaspoontda.github.io/teaspoon/modules/MakeData/index.html
41+
.. _DynSysLib: https://teaspoontda.github.io/teaspoon/modules/MakeData/DynSysLib/index.html
42+
.. _ParameterSelection: https://teaspoontda.github.io/teaspoon/modules/ParamSelection/index.html
43+
.. _SP: https://teaspoontda.github.io/teaspoon/modules/SP/index.html
44+
.. _TDA: https://teaspoontda.github.io/teaspoon/modules/TDA/index.html
45+
.. _ML: https://teaspoontda.github.io/teaspoon/modules/ML/index.html
46+
.. _DAF: https://teaspoontda.github.io/teaspoon/modules/DAF/index.html
2847

2948

3049
Collaborators
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
2+
3+
Data Assimilation
4+
=========================================================
5+
6+
This page gives a summary of the functions available in the data assimilation library. Differentiation of persistence diagrams is exploited to optimize data driven model coefficients by minimizing topological differences between model the model forecast and measurements. More information on the details of the TADA algorithm can be found in, "`Topological Approach for Data Assimilation <https://arxiv.org/abs/2411.18627>`_." We plan to implement more data assimilation tools here in the future.
7+
8+
.. warning::
9+
`TADA` requires `tensorflow <https://www.tensorflow.org>`_ for optimization features. Please install teaspoon using the command: `pip install "teaspoon[full]"` to install the necessary packages.
10+
11+
.. automodule:: teaspoon.DAF.data_assimilation
12+
:members:
13+
14+
15+
**Example**::
16+
17+
import numpy as np
18+
from teaspoon.MakeData.DynSysLib.autonomous_dissipative_flows import lorenz
19+
from teaspoon.DAF.data_assimilation import TADA
20+
from teaspoon.DAF.forecasting import forecast_time
21+
from teaspoon.DAF.forecasting import random_feature_map_model
22+
from teaspoon.DAF.forecasting import get_forecast
23+
24+
# Set random seed
25+
r_seed = 48824
26+
np.random.seed(r_seed)
27+
28+
# Set TADA parameters
29+
snr = 60.0
30+
lr = 1e-5
31+
train_len = 4000
32+
forecast_len = 2000
33+
window_size = 50
34+
max_window_number = 10
35+
36+
# Get training and validation data at random initial condition
37+
ICs = list(np.random.normal(size=(3,1)).reshape(-1,))
38+
t, ts = lorenz(L=500, fs=50, SampleSize=6001, parameters=[28,10.0,8.0/3.0],InitialConditions=ICs)
39+
ts = np.array(ts)
40+
41+
# Get signal and noise amplitudes using signal-to-noise ratio
42+
a_sig = np.sqrt(np.mean(np.square(ts),axis=1))
43+
a_noise = a_sig * 10**(-snr/20)
44+
45+
# Add noise to the signal
46+
Gamma = np.diag(a_noise)
47+
noise = np.random.normal(size=np.shape(ts[:,0:train_len+forecast_len]))
48+
u_obs = ts[:,0:train_len+forecast_len] + Gamma@noise
49+
50+
# Train model
51+
W_LR, W_in, b_in = random_feature_map_model(u_obs[:,0:train_len],Dr=300, seed=r_seed)
52+
53+
# Set optimization parameters
54+
d_rate = 0.99
55+
opt_params = [lr, d_rate]
56+
W_opt = W_LR
57+
58+
# TADA optimization loop
59+
for window_number in range(1,max_window_number):
60+
model_parameters = [W_opt, W_LR, W_in, b_in]
61+
W_opt = TADA(u_obs, window_size, model_parameters, train_len=train_len, n_epochs=1, opt_params=opt_params, window_number=window_number)
62+
63+
# Set forecast parameters
64+
window_number = 200
65+
start = train_len
66+
end = train_len + window_number + 1
67+
68+
# Forecast TADA and LR models and get measurements
69+
X_model_tada = get_forecast(u_obs[:,train_len], W_opt, W_in, b_in,forecast_len=end-train_len)
70+
X_model_lr =get_forecast(u_obs[:,train_len], W_LR, W_in, b_in,forecast_len=end-train_len)
71+
X_meas = u_obs[:,start:end]
72+
73+
# Compute and print forecast times
74+
tada_time = forecast_time(X_model_tada, X_meas, dt=0.02, lambda_max=0.91, threshold=0.05)
75+
lr_time = forecast_time(X_model_lr, X_meas, dt=0.02, lambda_max=0.91, threshold=0.05)
76+
77+
print(f"TADA Forecast Time: {tada_time}")
78+
print(f"LR Forecast Time: {lr_time}")
79+
80+
.. note::
81+
Resulting forecast times may vary depending on the operating system.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
2+
3+
Forecasting
4+
=========================================================
5+
6+
This page outlines the available time series forecasting functions.
7+
8+
9+
.. automodule:: teaspoon.DAF.forecasting
10+
:members:
11+
12+
**Example**::
13+
14+
import numpy as np
15+
from matplotlib import rc
16+
import matplotlib.pyplot as plt
17+
from matplotlib.gridspec import GridSpec
18+
from teaspoon.MakeData.DynSysLib.autonomous_dissipative_flows import lorenz
19+
from teaspoon.DAF.forecasting import random_feature_map_model
20+
from teaspoon.DAF.forecasting import get_forecast
21+
22+
# Set font
23+
rc('font', **{'family': 'sans-serif', 'sans-serif': ['Helvetica']})
24+
rc('text', usetex=True)
25+
plt.rc('text', usetex=True)
26+
plt.rc('font', family='serif')
27+
plt.rcParams.update({'font.size': 16})
28+
29+
# Set model parameters
30+
Dr=300
31+
train_len = 4000
32+
forecast_len = 2000
33+
34+
r_seed = 48824
35+
np.random.seed(r_seed)
36+
37+
# Get training and tesing data at random initial condition
38+
ICs = list(np.random.normal(size=(3,1)).reshape(-1,))
39+
t, ts = lorenz(L=500, fs=50, SampleSize=6001, parameters=[28,10.0,8.0/3.0],InitialConditions=ICs)
40+
ts = np.array(ts)
41+
42+
# Add noise to signals
43+
noise = np.random.normal(scale=0.01, size=np.shape(ts[:,0:train_len+forecast_len]))
44+
u_obs = ts[:,0:train_len+forecast_len] + noise
45+
46+
# Train model
47+
W_LR, W_in, b_in = random_feature_map_model(u_obs[:,0:train_len],Dr, seed=r_seed)
48+
49+
# Generate forecast
50+
forecast_len = 500
51+
X_model= get_forecast(u_obs[:,train_len], W_LR, W_in, b_in,forecast_len=forecast_len)
52+
X_meas = u_obs[:,train_len:train_len+forecast_len]
53+
54+
# Plot measurements and forecast
55+
fig = plt.figure(figsize=(15, 5))
56+
gs = GridSpec(1, 3)
57+
ax1 = fig.add_subplot(gs[0, 0])
58+
ax1.plot(X_model[0,:],'r', label="Forecast")
59+
ax1.plot(X_meas[0,:], '.b', label="Measurement")
60+
ax1.plot([],[])
61+
ax1.set_title('x', fontsize='x-large')
62+
ax1.tick_params(axis='both', which='major', labelsize='x-large')
63+
ax1.set_ylim((-30,30))
64+
65+
66+
ax2 = fig.add_subplot(gs[0, 1])
67+
ax2.plot(X_model[1,:],'r', label="Forecast")
68+
ax2.plot(X_meas[1,:], '.b', label="Measurement")
69+
ax2.plot([],[])
70+
ax2.set_title('x', fontsize='x-large')
71+
ax2.tick_params(axis='both', which='major', labelsize='x-large')
72+
ax2.set_ylim((-30,30))
73+
74+
ax3 = fig.add_subplot(gs[0, 2])
75+
ax3.plot(X_model[2,:],'r', label="Forecast")
76+
ax3.plot(X_meas[2,:], '.b', label="Measurement")
77+
ax3.plot([],[])
78+
ax3.legend(fontsize='large', loc='upper left')
79+
ax3.set_title('x', fontsize='x-large')
80+
ax3.tick_params(axis='both', which='major', labelsize='x-large')
81+
ax3.set_ylim((0,60))
82+
83+
plt.tight_layout()
84+
plt.show()
85+
86+
Output of example
87+
88+
.. figure:: ../../figures/LR_forecast_example.png
89+
90+
.. note::
91+
Forecast may vary depending on the operating system.

0 commit comments

Comments
 (0)