PyOFDR
PyOFDR simulates optical frequency domain reflectometry (OFDR) in Python. Give it a fiber, a laser sweep and a receiver. It returns the digitized beat signal for each fiber core. You can use these traces to check a strain recovery algorithm against a known input, study receiver noise or try different sweep and sampling settings.
1000 microstrain applied to a 1 m segment of a 10 m fiber, recovered from a single PyOFDR run by sub-spectrum cross-correlation against an unstrained baseline.
Status
PyOFDR runs on the NumPy backend and requires Python 3.10 or later. CI runs on Windows and Ubuntu with Python 3.10, 3.11 and 3.12. The pipeline validation section gives the tested cases and their numerical tolerances.
What's simulated
| Stage | Modelled |
|---|---|
| Source | linear sweep + nonlinearity + ripple, phase noise (Wiener + flicker + RW), RIN, coherence roll-off |
| Interferometer | main Mach-Zehnder, auxiliary MZI for k-clock resampling, optical circulator, weak FBG arrays |
| Fiber | Rayleigh backscatter, attenuation, macrobend loss, discrete reflectors, chromatic dispersion (GVD), stochastic n(z), multiple-scattering ghosts, MCF core-to-core crosstalk |
| Perturbations | static + dynamic strain (harmonic, impulsive, thermal relaxation, random vibration), Cox shear-lag coating coupling, distributed temperature with strain-T cross-sensitivity |
| Detection | single-ended or balanced photodetection, shot, thermal and dark-current noise, photodiode saturation and nonlinearity, Butterworth low-pass filter |
| ADC | clip, quantize, jitter, DNL/INL, ENOB |
| Output | HDF5 streaming, multi-sweep campaigns |
For equations and model limits, see the theory guide. The configuration reference describes the YAML fields and units. The architecture guide follows a sweep through the simulation and describes the output arrays.
Install
To install the published package from PyPI, run python -m pip install pyofdr in a virtual environment.
For the basic YAML configuration, notebooks and tests, clone the repository and create a virtual environment.
git clone https://github.com/ameoli/PyOFDR.git
cd PyOFDR
python -m venv .venv
Activate it with .\.venv\Scripts\Activate.ps1 in PowerShell or source .venv/bin/activate on Linux and macOS. Then install the package from the repository root.
python -m pip install -e .
Quick start
From the repository root, run the basic configuration. It simulates a 10 m fiber and a 40 nm sweep in 10 ms at 200 MS/s. info shows the spatial spacing and Nyquist limit. validate checks the configuration, and run writes the simulated sweep to HDF5.
pyofdr info configs/ofdr_basic.yaml
pyofdr validate configs/ofdr_basic.yaml
pyofdr run configs/ofdr_basic.yaml -o out.h5
In out.h5, sweeps/0000/digital_main holds the ADC counts with shape (1, 2000000) for this configuration. To work in Python, run the same sweep in memory and compute its reflectogram. The helper uses the FFT spacing stored in the acquisition.
from pyofdr.analysis.demodulation import reflectogram_from_acq
from pyofdr.core.campaign import run_campaign
from pyofdr.core.config import load_config
cfg = load_config("configs/ofdr_basic.yaml")
acq = run_campaign(cfg)[0]
H, z = reflectogram_from_acq(acq, core=0)
print(acq.digital_main.shape) # (1, 2000000)
print(z[1] - z[0]) # FFT bin spacing in metres
Examples
From the repository root, install the tutorials and start JupyterLab in the same environment:
python -m pip install -e ".[tutorials]"
python -m jupyterlab examples/
Open a notebook and run all cells from the beginning. The examples load the basic YAML configuration relative to the notebook directory.
- 00: Fiber signature compares Rayleigh statistics with theory.
- 01: Reflectogram basics maps ADC samples to distance and compares repeated sweeps.
- 02: Reflector loss and linewidth measures round-trip attenuation, coherence loss and peak width.
- 03: Strain recovery recovers an imposed strain from two Rayleigh traces.
- 04: Noise budget compares predicted and measured shot, thermal and quantization noise.
Tests
Install the test dependencies in the same environment and run the suite from the repository root.
python -m pip install -e ".[dev]"
python -m pytest tests/ -q
Citing
If you use PyOFDR in published work, please cite it.
@software{pyofdr,
author = {Meoli, Alessandro},
title = {PyOFDR: an end-to-end Python simulator for Optical Frequency Domain Reflectometry},
year = {2026},
url = {https://github.com/ameoli/PyOFDR},
}
References
- Froggatt and Moore, High-spatial-resolution distributed strain measurement in optical fiber with Rayleigh scatter, Appl Opt 1998.
- Soller et al., High resolution OFDR for characterization of components and assemblies, Opt Express 2005.
- Hartog, An Introduction to Distributed Optical Fibre Sensors, CRC 2017.
License
PyOFDR is distributed under the MIT license.
Third-party
The laser noise generator uses colorednoise by Felix Patzelt. Its MIT license is included in the source and wheel distributions.
Issues and contributions
Report bugs and feature requests in GitHub Issues. For simulation bugs, include the YAML configuration and the command that reproduces the problem. Pull requests are welcome.
Maintainers can follow the release instructions to publish a tagged version on PyPI.
Metadata
Release files for pyofdr 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pyofdr-1.0.0.tar.gz | 151.9 kB | With provenance | Details for pyofdr-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pyofdr-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for pyofdr-1.0.0-py3-none-any.whl |
Total release size: 233.3 kB
Release files / pyofdr-1.0.0.tar.gz
| Download URL | pyofdr-1.0.0.tar.gz |
|---|---|
| Size | 151.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7101afe4c5b5caa918f669155c61f4a8bdbde2d0127b81a452be5377c644fac5
|
|
BLAKE2b-256 checksum How to use checksums |
7348a4ca723abaa5df7aff5ec09e31f21c78f43b447682ecf93d8ea363385d79
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.
Transparency logRelease files / pyofdr-1.0.0-py3-none-any.whl
| Download URL | pyofdr-1.0.0-py3-none-any.whl |
|---|---|
| Size | 81.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4d961ac464cd6d0742edf8ade53f9cdf9fd1da1f365614a4e0fe15b0b3c21f97
|
|
BLAKE2b-256 checksum How to use checksums |
02f1df6caaa13cc6a94d6f04634870cf9f8b5a469bdb951b249c7020721e78e8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.
Transparency logSecurity for pyofdr 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for pyofdr-1.0.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.