openmodalpy puts nine modal decomposition methods for spatiotemporal data
behind one API. Extract coherent structures from simulation or experimental
data — energy-ranked POD modes, frequency-resolved SPOD modes, DMD eigenvalues,
nonlinear BSMD triads — without switching libraries or rewriting your loading
code for each method.
Why this package
Most Python tools here specialise: PyDMD covers DMD variants in depth, PySPOD covers SPOD. That depth is real, and if you only need one method they are excellent choices.
OpenModalPy trades some of that depth for breadth. Nine methods share one analyzer interface, one data contract and one config file, so running POD, SPOD, DMD and BSMD over the same dataset — and comparing them directly — is a single command rather than four integrations. Bispectral mode decomposition (BSMD) in particular has little open-source coverage elsewhere.
It runs on the NumPy/SciPy stack. No compiled solver toolchain (PETSc, SLEPc) to install.
Installation
uv add openmodalpy # library
uv tool install openmodalpy # standalone CLI
Optional extras:
| Extra | Adds |
|---|---|
openmodalpy[viz3d] |
3D slice and isosurface plotting (PyVista) |
openmodalpy[mkl] |
Intel MKL FFT backend |
openmodalpy[gpu] |
CuPy / PyTorch FFT backends |
Quick Start
from openmodalpy import PODAnalyzer, SPODAnalyzer, DMDAnalyzer
pod = PODAnalyzer(file_path="data.mat", n_modes_save=10)
pod.run_analysis()
spod = SPODAnalyzer(file_path="data.mat", nfft=256, overlap=0.5)
spod.run_analysis()
# DMD is driven in two steps, so the fit method can be chosen after loading.
dmd = DMDAnalyzer(file_path="data.mat", n_modes_save=10)
dmd.load_and_preprocess()
dmd.perform_dmd(method="ls")
Configuration-Driven Workflow
One JSONC file runs several methods over the same dataset — the main reason to reach for this package over a single-method library:
{
"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 without computing
openmodalpy methods list # supported methods
openmodalpy examples list # bundled examples
openmodalpy results inspect output.hdf5 # inspect a result file
Three example cases ship with the package and need no external data — double_gyre,
cylinder_wake and taylor_green generate their fields analytically. A fourth config,
run_benchmarks, runs all three as a suite. So openmodalpy examples list gives you
something runnable immediately, with nothing to download.
Methods
These are the names openmodalpy methods list reports and the values the method field
takes in a config file.
method |
Class | What it extracts | Reference |
|---|---|---|---|
pod |
variance-optimal | energy-ranked spatial modes | Lumley (1967); Sirovich (1987) |
mpod |
variance-optimal | scale-separated modes across non-overlapping bands | Mendez et al. (2019) |
psd-pod |
variance-optimal | POD of blockwise Fourier realizations | — |
spod |
variance-optimal | frequency-local modes (Welch blocks) | Towne, Schmidt & Colonius (2018) |
stpod |
variance-optimal | space-time structures via delay embedding | — |
dmd |
evolution-fit | modes with frequency and growth rate | Schmid (2010); Tu et al. (2014) |
hodmd |
evolution-fit | delay-embedded (Hankel) DMD | Le Clainche & Vega (2017) |
tls-hodmd |
evolution-fit | delay-embedded DMD, total-least-squares fit | Hemati et al. (2017) |
bsmd |
triadic interaction | nonlinear triad structures | Schmidt (2020) |
dmd accepts method: "ls" (least squares) or method: "tls" (total least squares,
de-biased for noisy data).
The BSMD implementation follows Schmidt (2020) and was inspired by the reference MATLAB implementation.
Data Format
.mat and .npz files are auto-detected and must provide:
{
"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
}
Anything else can be read with a custom loader returning the same dictionary:
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)
FFT Backend
FFT dispatch comes from fftkit, installed
automatically. It probes the available backends, picks the fastest, and falls back to
SciPy when nothing else is present — so this section is optional reading.
To pin a backend:
export FFTKIT_BACKEND=mkl # or scipy, numpy, cupy, accelerate
from openmodalpy.core import FFT_BACKEND
print(FFT_BACKEND) # the backend actually in use
The legacy PYMODAL_FFT_BACKEND variable still works as a fallback, but
FFTKIT_BACKEND is the supported name.
Contributing
Contributions are welcome, and questions and bug reports count. See CONTRIBUTING.md for setup and the checks CI runs, and the openfluids Code of Conduct for how we work together.
License
Apache-2.0. Originally developed by Ricardo A S Frantz — see LICENSE and NOTICE for terms and attribution.
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.5.0.tar.gz.
File metadata
- Download URL: openmodalpy-0.5.0.tar.gz
- Upload date:
- Size: 351.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
38e304a9588333aa3c3f3398692883e84c8ce908791947a392dffd34adb424ea
|
|
| MD5 |
ae8a22cfbb8f87e095dbec75e7d43f1f
|
|
| BLAKE2b-256 |
7df0955a1beb847962df2025dce0739d75e417f54ff4f2059a6bcd6ec2ab7488
|
Provenance
The following attestation bundles were made for openmodalpy-0.5.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.5.0.tar.gz -
Subject digest:
38e304a9588333aa3c3f3398692883e84c8ce908791947a392dffd34adb424ea - Sigstore transparency entry: 2508254094
- Sigstore integration time:
-
Permalink:
openfluids/openmodalpy@981c3f0cb8a94e41fd54766bc99bb1bd083c3a24 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/openfluids
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@981c3f0cb8a94e41fd54766bc99bb1bd083c3a24 -
Trigger Event:
push
-
Statement type:
File details
Details for the file openmodalpy-0.5.0-py3-none-any.whl.
File metadata
- Download URL: openmodalpy-0.5.0-py3-none-any.whl
- Upload date:
- Size: 160.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
11c3650ba56b1bc0c420b5bb56dffaaecf924ef3b66eb9b0039ff7b3a56c4106
|
|
| MD5 |
8627c3b1977c1611e0db13af4583adab
|
|
| BLAKE2b-256 |
c5024b9218e877485f43efc38cb399e854a730eefb44c9c2aa11467e656146b0
|
Provenance
The following attestation bundles were made for openmodalpy-0.5.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.5.0-py3-none-any.whl -
Subject digest:
11c3650ba56b1bc0c420b5bb56dffaaecf924ef3b66eb9b0039ff7b3a56c4106 - Sigstore transparency entry: 2508254349
- Sigstore integration time:
-
Permalink:
openfluids/openmodalpy@981c3f0cb8a94e41fd54766bc99bb1bd083c3a24 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/openfluids
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@981c3f0cb8a94e41fd54766bc99bb1bd083c3a24 -
Trigger Event:
push
-
Statement type: