OpenModalPy: Python tools for POD, MPOD, DMD, SPOD, PSD-POD, BSMD, and ST-POD on spatiotemporal data
Project description
OpenModalPy
Modal decomposition of spatiotemporal data in Python. Pure NumPy/SciPy — no external solver dependencies.
Methods: POD · mPOD · PSD-POD · SPOD · ST-POD · DMD (LS/TLS) · HODMD (LS/TLS) · BSMD
Installation
uv add openmodalpy
The installed package is imported as openmodalpy.
Or as a standalone CLI:
uv tool install openmodalpy
For modern 3D slice/isosurface plotting:
uv add "openmodalpy[viz3d]"
FFT Backend
FFT dispatch is handled by fftkit, installed
automatically. It probes the available backends and picks the fastest one, falling back
to SciPy when nothing else is present — so no configuration is needed.
To pin a backend explicitly:
export FFTKIT_BACKEND=mkl # or scipy, numpy, cupy, accelerate
from openmodalpy.core.config import FFT_BACKEND
print(FFT_BACKEND) # the backend actually in use
Accelerator support comes from the corresponding extra:
uv add "openmodalpy[mkl]" # Intel MKL
uv add "openmodalpy[gpu]" # CuPy / PyTorch
The legacy
PYMODAL_FFT_BACKENDvariable is still honoured as a fallback, butFFTKIT_BACKENDis the supported name.
Quick Start
from openmodalpy import PODAnalyzer, DMDAnalyzer, SPODAnalyzer
pod = PODAnalyzer(file_path="data.mat", n_modes_save=10)
pod.run_analysis()
dmd = DMDAnalyzer(file_path="data.mat", n_modes_save=10)
dmd.load_and_preprocess()
dmd.perform_dmd(method="ls")
spod = SPODAnalyzer(file_path="data.mat", nfft=256, overlap=0.5)
spod.run_analysis()
Configuration-Driven Workflow
A single JSONC file runs multiple methods on one dataset:
{
"case": {
"name": "my_case",
"data": { "kind": "file", "path": "data.mat" },
"n_modes_save": 10, "nfft": 128, "overlap": 0.5
},
"runs": [
{ "id": "pod", "method": "pod" },
{ "id": "spod", "method": "spod" },
{ "id": "dmd", "method": "dmd", "params": { "method": "ls" } },
{ "id": "hodmd","method": "hodmd", "params": { "delays": 4 } },
{ "id": "bsmd", "method": "bsmd" }
]
}
openmodalpy run --config analysis.jsonc
CLI
openmodalpy analyze pod --config case.jsonc # one method
openmodalpy run --config suite.jsonc # full suite
openmodalpy run --config suite.jsonc --dry-run # preview
openmodalpy methods list # supported methods
openmodalpy examples list # bundled examples
openmodalpy results inspect output.hdf5 # inspect result
Bundled Example Configs
The public package ships only self-contained generator-backed example configs:
double_gyre.jsonccylinder_wake.jsonctaylor_green.jsoncrun_benchmarks.jsonc
These configs do not depend on repository-local benchmark datasets.
Supported Methods
| Method | Class | What it extracts |
|---|---|---|
| POD | variance-optimal | energy-ranked spatial modes |
| mPOD | variance-optimal | scale-separated modes |
| PSD-POD | variance-optimal | broadband spectral modes |
| SPOD | variance-optimal | frequency-local modes |
| ST-POD | variance-optimal | space-time structures (delay embedding) |
| DMD (LS) | evolution-fit | modes with frequency and growth rate |
| DMD (TLS) | evolution-fit | de-biased DMD for noisy data |
| HODMD | evolution-fit | delay-embedded DMD |
| TLS-HODMD | evolution-fit | de-biased delay-embedded DMD |
| BSMD | triadic interaction | nonlinear triad structures |
The BSMD implementation follows Schmidt (2020) and was inspired by the reference MATLAB implementation.
Data Format
OpenModalPy auto-detects .mat and .npz files:
{
"q": np.ndarray, # (Ns, Nspace) — snapshots × spatial points
"dt": float, # time step
"Nx": int, # grid points in x
"Ny": int, # grid points in y
"x": np.ndarray, # x-coordinates
"y": np.ndarray, # y-coordinates
}
Custom loaders:
def my_loader(path):
return {"q": data, "dt": 0.01, "Nx": 100, "Ny": 50, "x": x, "y": y}
pod = PODAnalyzer(file_path="ignored", data_loader=my_loader)
References
| Method | Key reference |
|---|---|
| POD | Lumley (1967); Sirovich (1987) |
| mPOD | Mendez et al. (2019) |
| SPOD | Towne, Schmidt & Colonius (2018) |
| DMD | Schmid (2010); Tu et al. (2014) |
| TLS-DMD | Hemati et al. (2017) |
| HODMD | Le Clainche & Vega (2017) |
| BSMD | Schmidt (2020) |
License
This project is licensed under Apache-2.0.
Originally developed by Ricardo A S Frantz. See LICENSE and NOTICE for license terms and attribution notices.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file openmodalpy-0.3.0.tar.gz.
File metadata
- Download URL: openmodalpy-0.3.0.tar.gz
- Upload date:
- Size: 149.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d7ddcb94d6a2ea4d95f0ff7bfc1876138895ef05e463fb9773c7e488c8b4de1a
|
|
| MD5 |
318476f0d6c6c7ccec0ad2350e0b5cdc
|
|
| BLAKE2b-256 |
d2f88005ffc98004eb92a8e357493e69058b903c89c82f2af295c1b57c056f01
|
Provenance
The following attestation bundles were made for openmodalpy-0.3.0.tar.gz:
Publisher:
release.yml on openfluids/openmodalpy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
openmodalpy-0.3.0.tar.gz -
Subject digest:
d7ddcb94d6a2ea4d95f0ff7bfc1876138895ef05e463fb9773c7e488c8b4de1a - Sigstore transparency entry: 2259661266
- Sigstore integration time:
-
Permalink:
openfluids/openmodalpy@6f29e95f08bc4a5c2126c7da71d35520a0eef832 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/openfluids
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6f29e95f08bc4a5c2126c7da71d35520a0eef832 -
Trigger Event:
push
-
Statement type:
File details
Details for the file openmodalpy-0.3.0-py3-none-any.whl.
File metadata
- Download URL: openmodalpy-0.3.0-py3-none-any.whl
- Upload date:
- Size: 123.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2091c07c8cf271281e5cb4bf9ef0b4d245e3951872eb607f452638d5b068504d
|
|
| MD5 |
eb8b6943ff37f9d72088e89cc933db7d
|
|
| BLAKE2b-256 |
608788eea0d561ba3c50e1aeba9092b6f564d8330fdf5f92c29cfe979cd59a82
|
Provenance
The following attestation bundles were made for openmodalpy-0.3.0-py3-none-any.whl:
Publisher:
release.yml on openfluids/openmodalpy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
openmodalpy-0.3.0-py3-none-any.whl -
Subject digest:
2091c07c8cf271281e5cb4bf9ef0b4d245e3951872eb607f452638d5b068504d - Sigstore transparency entry: 2259661373
- Sigstore integration time:
-
Permalink:
openfluids/openmodalpy@6f29e95f08bc4a5c2126c7da71d35520a0eef832 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/openfluids
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6f29e95f08bc4a5c2126c7da71d35520a0eef832 -
Trigger Event:
push
-
Statement type: