Metadata-Version: 2.4
Name: oma-python
Version: 0.1.0
Summary: Operational Modal Analysis (OMA) algorithms for structural dynamics: FDD and Covariance SSI.
Author: 19Alma98
License-Expression: MIT
Project-URL: Homepage, https://github.com/19Alma98/oma_python
Project-URL: Repository, https://github.com/19Alma98/oma_python
Project-URL: Issues, https://github.com/19Alma98/oma_python/issues
Keywords: oma,operational-modal-analysis,structural-dynamics,modal-identification,fdd,ssi,vibration
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=2.0.0
Requires-Dist: pydantic>=2.11.7
Requires-Dist: scipy>=1.15.3
Requires-Dist: torch>=2.0.0
Provides-Extra: dev
Requires-Dist: mypy>=2.3.1; extra == "dev"
Requires-Dist: pytest>=9.1.1; extra == "dev"
Requires-Dist: pytest-mock>=3.14.0; extra == "dev"
Requires-Dist: ruff>=0.12.0; extra == "dev"
Requires-Dist: scipy-stubs>=1.15.3.0; extra == "dev"
Dynamic: license-file

# oma-python

Open-source **Operational Modal Analysis (OMA)** algorithms for Python.
Estimate natural frequencies, damping ratios, and mode shapes from ambient vibration measurements.

Install the distribution as `oma-python`; import the library as `dynoma`.

## Install

```bash
pip install oma-python
```

For local development with [uv](https://docs.astral.sh/uv/):

```bash
uv sync --group dev
```

## Quick start (FDD)

Frequency Domain Decomposition on a synthetic multi-channel signal:

```python
import numpy as np
from dynoma import FDD

rng = np.random.default_rng(0)
fs = 100.0  # Hz
t = np.arange(0, 40, 1 / fs)

# Ambient-like response on 3 channels (modes near 2.5 Hz and 6.0 Hz)
signal = np.column_stack(
    [
        np.sin(2 * np.pi * 2.5 * t) + 0.4 * np.sin(2 * np.pi * 6.0 * t),
        0.8 * np.sin(2 * np.pi * 2.5 * t + 0.2) + np.sin(2 * np.pi * 6.0 * t),
        0.5 * np.sin(2 * np.pi * 2.5 * t) + 0.7 * np.sin(2 * np.pi * 6.0 * t + 0.1),
    ]
)
signal += 0.05 * rng.standard_normal(signal.shape)

fdd = FDD(
    frequency_min=0.0,
    frequency_max=20.0,
    number_of_fft_points=512,
    num_svd_plots=3,
)

# Optional: inspect SVD lines before picking peaks
frequencies, eigenvalues, eigenvectors = fdd.compute_signal_svd(
    signal=signal,
    sampling_frequency=fs,
)

# Results are TypedDict mappings (use bracket access)
results = fdd.apply(
    signal=signal,
    sampling_frequency=fs,
    peaks_range=[[2.0, 3.0], [5.5, 6.5]],
)

print(results["frequencies"])       # ~2.54 Hz, ~6.05 Hz
print(results["complex_mode_shapes"].shape)  # (n_channels, n_modes)
print(results["real_mode_shapes"].shape)
```

## Covariance SSI

```python
from dynoma import CovSSI

cov_ssi = CovSSI(
    frequency_min=0.0,
    frequency_max=20.0,
    order_min=20,
    order_max=40,
    order_steps=2,
    time_lag=1.2,
    number_of_fft_points=256,
    num_svd_plots=3,
    continuous_mode=True,
)

results, dashboard = cov_ssi.apply(
    signal=signal,
    sampling_frequency=fs,
    optimized=True,
    shuffle=False,
)

print(results["frequencies"])
print(results["damping_ratios"])  # percent scale
# dashboard is None when continuous_mode=True
```

## Public API

```python
from dynoma import FDD, CovSSI, OmaAlgorithm, ModalIdentificationError, __version__
```

| Symbol | Role |
|--------|------|
| `FDD` | Frequency Domain Decomposition |
| `CovSSI` | Covariance-driven Stochastic Subspace Identification |
| `OmaAlgorithm` | Shared CSD / SVD base (usually subclassed) |
| `ModalIdentificationError` | Domain errors from validation / identification |

Signal layout is `(n_samples, n_channels)`.

## Requirements

- Python ≥ 3.10
- NumPy, SciPy, Pydantic, PyTorch

CPU-only PyTorch wheels are preferred for development (`uv` is configured for the official CPU index).

## License

MIT — see [LICENSE](LICENSE).
