tc-cwi
Lightweight Python toolbox for Environmental and Operational Condition (EoC) compensation in ultrasonic Structural Health Monitoring (SHM), using Coda Wave Interferometry (CWI) and the Time-Stretching method.
Temperature variations change the apparent wave velocity of ultrasonic guided waves, which can mask structural damage. tc-cwi estimates the stretch factor (eps) and/or time shift (dt) that best realign a measured signal with a reference, and reports the remaining decorrelation.
Authors
- Arnaud Deraemaeker (ULB)
- Damiano Gianotti (Zensor)
- Jasmien Hassanin (IZFP)
- Jitendra Kumar Sharma (ULB)
- Luigi Trezza (Airbus)
Developed as part of WP3, Deliverable D3.3. Packaged and maintained by Zensor.
Installation
Requirements: Python ≥ 3.11 (dependencies: numpy, scipy)
pip install tc-cwi
Quickstart
import numpy as np
from tc_cwi import tc_cwi
t = np.linspace(0, 1e-3, 1000)
reference = np.sin(2 * np.pi * 50e3 * t)
current = np.sin(2 * np.pi * 50e3 * t * (1 + 1e-4)) # slightly stretched
# Correlation coefficient without compensation (one value per signal)
baseline = tc_cwi("getccns", reference, current)
print(f"Baseline CC: {baseline.CC[0]:.4f}")
# Optimal stretch factor (Nelder-Mead from eps = 0) and remaining decorrelation
result = tc_cwi("findeps", reference, current, t, 0.0, 2)
print(f"eps: {result.eps:.6e}, decorrelation after stretching: {result.DC:.2e}")
Several signals can be processed at once by passing a 2D array with one signal per column (n_samples × n_signals):
signals = np.column_stack([current, current, current])
batch = tc_cwi("findeps", reference, signals, t, (-1e-2, 1e-2)) # bounded search
print(batch.EPSf, batch.DCsf)
API
The package exposes two layers.
MATLAB-compatible dispatch: tc_cwi(cmd, *args, **kwargs)
Mirrors the original MATLAB toolbox. Results are returned as a Struct (types.SimpleNamespace), so fields are accessed MATLAB-style with out.field.
| Command | Arguments | Output fields (single signal / multiple signals) |
|---|---|---|
getccns |
y0, y1, ind=None |
CC, DC |
getccs |
y0, y1, t, eps, ind=None |
CC, DC |
getccdt |
y0, y1, t, dt, ind=None |
CC, DC |
getccepsdt |
y0, y1, t, eps, dt, ind=None |
CC, DC |
getdcs / getdcdt / getdcepsdt |
same as getcc* |
DC array (returned directly) |
findeps |
y1, y2, t, e0, method=1, ind=None |
eps, DC, y, y0 / EPSf, DCsf, ysf, y0 |
finddt |
y1, y2, t, dt0, method=1, ind=None |
dt, DC, y, y0 / DTf, DCdtf, ydtf, y0 |
findepsdt |
y1, y2, t, e0, dt0, method=2, ind=None |
eps, dt, DC, y, y0 / EPSf, DTf, DCsdtf, ysdtf, y0 |
findeps -ma |
y1, y2, t, e0, method=1, ind=None, ma=5 |
multiple signals only: EPSma, DCma, ysma, y0, yma |
stretch |
y, t, eps |
stretched signal |
shift |
y, t, dt, method="interp" |
shifted signal ("point", "interp" or "fft") |
stretchshift |
y, t, eps, dt |
shifted, then stretched signal |
Conventions:
-
CCis the absolute Pearson correlation coefficient,DC = 1 - CCthe decorrelation. -
indrestricts the correlation to a window (index array or slice). The stretch/shift is always applied to the full signal. -
methodselects the optimizer:1: bounded scalar search, the start value is an interval(lower, upper).2: Nelder-Mead, the start value is a starting point.findepsdtonly supports this method.
When processing several signals, each fit is seeded with the result of the previous one.
-
eps > 0compresses the wave (t → t·(1+eps)),dt > 0moves it forward (t → t−dt). -
findeps -macompares each signal against the mean of the lastmacompensated signals instead of a fixed reference.mais either a window size, or theymareturned by a previous call to continue the same window.
Core functions
For direct use in Python code, without the MATLAB-style dispatch:
| Function | Description |
|---|---|
correlation_coefficient(y0, y1) |
Absolute correlation coefficient between two signals |
stretch(y, t, eps) |
Stretch a signal (not-a-knot cubic spline, zero outside t) |
shift(y, t, dt, method="interp") |
Shift a signal by dt |
stretchshift(y, t, eps, dt) |
Shift, then stretch a signal |
find_optimum(y0, y, t, process, x0, method=1, ind=None, xatol=1e-8) |
Parameters of process(y, t, *x) minimizing the decorrelation with y0; returns (x, decorrelation) |
MovingAverageReference(n, y_init=None) |
Rolling window of the last n signals; .reference is their mean, .update(y) adds a signal |
from tc_cwi import find_optimum, stretch
x, decorrelation = find_optimum(reference, current, t, stretch, (-1e-2, 1e-2))
Development
This project uses uv with the uv_build backend:
git clone https://github.com/aderaema/US-EOC-compensation-toolbox.git tc-cwi
cd tc-cwi
uv sync
├── src/tc_cwi/
│ ├── __init__.py # Public API
│ ├── core.py # Stretching, shifting and optimization
│ └── matlab.py # MATLAB-compatible tc_cwi() dispatch
├── tests/
│ ├── test_core.py # Core functions
│ ├── test_matlab.py # Every tc_cwi command: fields and error paths
│ └── test_package.py # Public API
└── pyproject.toml
Tests, coverage and linting:
uv run pytest
uv run pytest --cov # statements + branches, with the missing lines
uv run ruff check .
Releasing to PyPI: bump version in pyproject.toml, then push a matching tag. The publish workflow lints, builds, tests the built distributions and publishes them.
git tag -a v0.1.0 -m v0.1.0
git push origin v0.1.0
License
Metadata
Release files for tc-cwi 0.1.2
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 |
|---|---|---|---|---|
| tc_cwi-0.1.2.tar.gz | 8.5 kB | With provenance | Details for tc_cwi-0.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| tc_cwi-0.1.2-py3-none-any.whl | Python 3 | none | any | Details for tc_cwi-0.1.2-py3-none-any.whl |
Total release size: 17.4 kB
Release files / tc_cwi-0.1.2.tar.gz
| Download URL | tc_cwi-0.1.2.tar.gz |
|---|---|
| Size | 8.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2f9ea5c9457c8925cad5075416a34459eec4a2602c87bd3a5b225b1bb982493c
|
|
BLAKE2b-256 checksum How to use checksums |
6c8f728d2e100eec5428ba38dfd002784724aaef76f19e3dacbf8ef27fd3bbf0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
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 Oct 26, 2026.
Transparency logRelease files / tc_cwi-0.1.2-py3-none-any.whl
| Download URL | tc_cwi-0.1.2-py3-none-any.whl |
|---|---|
| Size | 9.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3087ff5e5c499dc77ae5fa595d292e61309b1da02ece4cd1afda5be077f5b067
|
|
BLAKE2b-256 checksum How to use checksums |
3fb5016f2ee34dbef2f76ebaa841656cdf8e7f8b6dbe8bfa37b99a1dfe54e04b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
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 Oct 26, 2026.
Transparency logSecurity for tc-cwi 0.1.2
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
All 2 files in this release have been uploaded with provenance metadata.
Attestation for tc_cwi-0.1.2.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 Oct 26, 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.