Skip to main content

p4TSA — package for Time Series Analysis

PyPI docs CI DOI

Contact: info@elenacuoco.com — https://www.elenacuoco.com

p4TSA is a spin-off of the C++ Noise Analysis Package (NAP). The core is written in C++ and is exposed to Python through a pybind11 binding. The Python interface is called py4TSA (you can still pronounce it pi'za) and is imported as py4tsa.

The module used to be called pytsa. That name on PyPI belongs to an unrelated project, so change any import pytsa to import py4tsa.

What is this for?

p4TSA is a minimal package of ad-hoc functions to work with time series. It includes:

  • Whitening in the time domain
  • Double whitening (equivalent to dividing by the Power Spectral Density) in the time domain
  • Wavelet decomposition: pyramidal transforms, uniform wavelet-packet levels and orthonormal local cosine bases
  • Cosine packets with the Coifman-Wickerhauser best-basis search
  • Wavelet Detection Filter

The WDF basis competition

WDF2Classify transforms every window in each candidate basis, thresholds the coefficients on the window's own noise scale and keeps the candidate with the largest thresholded energy; the winner's name is the trigger's mWave.

from py4tsa import tsa

fs, n = 2048.0, 1024
wdf = tsa.WDF2Classify(n, 0, 5.0, 1.0, n, tsa.WaveletThreshold.block)
wdf.GetBases()      # 'Haar,DaubC4,DaubC8,Sym4,DaubC16,Sym8,Coif3,DaubC24,Sym12,Coif5'
wdf.SetBases(wdf.GetBases() + ",Sym8P6,LocalCos128")
wdf.SetMinFrequency(16.0, fs)      # coefficients at or below 16 Hz leave the statistic
wdf.SetBlockRemainder("merge")     # how blocks shorter than L are judged
wdf.SetBlock(0, 4.505)             # block length (0: round(ln n)) and lambda
  • Candidate names (SetBases, comma-separated, in the order they compete; a tie goes to the later one):

    • a mother for its pyramidal transform: Haar, DaubC4 to DaubC20, DaubC24, DaubC32, DaubC40, Sym4, Sym8, Sym10, Sym12, Sym16, Sym20, Coif1 to Coif5;
    • a mother followed by P and a depth D, as Sym8P6, for the uniform level D of its wavelet-packet tree: 2^D bands of width fs / 2^(D+1), written in frequency order;
    • LocalCos followed by a segment length M, a power of 2, as LocalCos128, for the orthonormal local cosine basis of segment M (Coifman-Meyer bell of half-width M / 2, periodic window edges), written with the layout of the packet level of depth log2 M.

    Under the block rule a packet band, or a local cosine row, must hold one full block of L = round(ln n) coefficients: n / 2^D >= L.

  • SetMinFrequency(fHz, fs) drops every coefficient whose band lies at or below fHz from sigma, from the threshold and from the statistic; 0 (the default) keeps every coefficient.

  • SetBlockRemainder(mode) sets how the block rule judges a block of n < L coefficients at the end of a run: "legacy" (default) against lambda n sigma^2 as a full block, "merge" joined to the block before it, "scaled" at the false-alarm probability of a full block.

  • SetBlock(length, lambda) sets the block length L (0 for round(ln n)) and lambda (default 4.505) in every candidate.

  • The default list is tsa.DefaultWaveletBases(). SetBases(tsa.LegacyWaveletBases()) restores the competition of releases 3.0.0 to 3.3.0.

WDF2Reconstruct runs the same competition: the same default list, the same default threshold rule (tsa.DefaultWaveletThresholding(), the block rule), the same names through SetBases, and the same winner and coefficients in every window. Reconstruct(ev) returns a trigger's window in the time domain, its coefficients inverted with the transform its mWave names:

rec = tsa.WDF2Reconstruct(n, 0, 5.0, 1.0, n)   # block rule, default list
rec.SetBases(wdf.GetBases())
# ... rec << data; while rec.GetDataNeeded() >= 0: if rec(ev): ...
waveform = rec.Reconstruct(ev)     # numpy array of n samples

The transforms are also available on their own:

import numpy as np

x = np.random.default_rng(1).normal(size=n)

lc = tsa.LocalCosineTransform(n, 128)        # segment 128, bell half-width 64
c = lc.Forward(x)                            # frequency-major coefficients
x_back = lc.Inverse(c)

cp = tsa.CosinePackets(n, 64)                # segments n down to 64
cp.BestBasis(x, tsa.CosinePackets.wdfBlock)  # or l1, entropy, wdfUniversal
seg = cp.GetSegmentation()                   # segment lengths in time order
c = cp.GetCoefficients()
x_back = cp.Inverse(c, seg)                  # Analyse(x, seg) gives c back

The pipeline that uses it

p4TSA is the C++ core. The search pipeline that drives it — trigger generation and the downstream trigger analysis — is wdflow, which imports this library through py4tsa. wdflow supersedes the earlier wdf package.

The two share the top-level module name wdf, so they cannot be installed side by side: whichever wdf sits directly in site-packages shadows the other, including an editable install of wdflow. If import wdf resolves somewhere unexpected, pip uninstall wdf removes the legacy package.

How to cite

Use of this code in published work requires citation of the following.

The Wavelet Detection Filter:

  • E. Cuoco, The Wavelet Detection Filter: A Real Time Unmodeled Pipeline for Gravitational Wave Transients, Ranking Coincidences with a Graph Neural Network, arXiv:2609.12797 (2026). arxiv.org/html/2609.12797v1, 10.48550/arXiv.2609.12797
  • E. Cuoco, M. Razzano, A. Utina, Wavelet-based classification of transient signals for gravitational wave detectors, 26th European Signal Processing Conference (EUSIPCO), 2648–2652 (2018). 10.23919/EUSIPCO.2018.8553393

Time-domain whitening, which this library implements:

  • E. Cuoco et al., On-line power spectra identification and whitening for the noise in interferometric gravitational wave detectors, Class. Quantum Grav. 18, 1727 (2001). 10.1088/0264-9381/18/9/309
  • E. Cuoco et al., Noise parametric identification and whitening for LIGO 40-m interferometer data, Phys. Rev. D 64, 122002 (2001). 10.1103/PhysRevD.64.122002

CITATION.cff in this repository carries the same list in machine-readable form; GitHub's Cite this repository button reads it.

Requirements

p4TSA is not a pure-Python package: building it compiles the C++ core into a single Python extension module. It depends on a few native libraries:

Library Role Needed at
GSL (+ gslcblas) linear algebra / numerics build and run
FFTW3 (double, float, long-double) FFTs build and run
FrameL / libframel LIGO/Virgo frame I/O build and run
Boost (headers only — Boost.uBLAS) matrix/vector templates build only
Cereal (headers only) binary serialization (AR/lattice-filter persistence) build only

The wheels on PyPI carry GSL, FFTW3 and FrameL inside them, so this table matters only when building from source. All of it is on conda-forge.

Installation with pip (Linux)

pip install py4tsa
python -c "import py4tsa; print(py4tsa.__file__)"

The wheels are manylinux_2_28_x86_64, for CPython 3.10 to 3.14.

Elsewhere — macOS, Windows, another architecture — pip falls back to the source distribution, which compiles the C++ core and needs the libraries above; use conda there.

Installation with conda

Option A — install a pre-built package

If a built package has been published to a conda channel, install it directly (replace <channel> with the channel it was uploaded to):

conda install -c conda-forge -c <channel> py4tsa

The importable module is py4tsa:

python -c "import py4tsa; print('py4TSA ready')"

Option B — build from source with conda-build

The repository ships a conda recipe under conda-recipe/. The native dependencies live on conda-forge, which must be enabled with strict channel priority, otherwise conda resolves against defaults (where framel, libframel and libboost-headers do not exist).

The build follows the Python of the environment you activate, so py4tsa always matches the interpreter you use — no fixed pin, no version mismatch at install time.

# 1. install conda-build in the base environment
conda install -n base conda-build

# 2. enable conda-forge with strict priority (once)
conda config --add channels conda-forge
conda config --set channel_priority strict

# 3. activate the environment you want to use py4tsa in (or create it),
#    then build FOR that environment's Python:
conda activate <your-env>
PYVER=$(python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
conda build conda-recipe/ -c conda-forge --python=$PYVER

# 4. install into the same environment
conda install -c conda-forge --use-local py4tsa

--python=$PYVER compiles the package exactly for the active environment's Python. If that environment uses a pre-release Python, conda-forge may not yet provide builds of the dependencies — in that case use an environment with a stable Python.

Build and install the py4tsa Python module

The C++ sources are compiled with CMake into a Python extension module named py4tsa. Build and install it for the currently active Python environment with:

conda install -c conda-forge cmake make compilers pybind11 gsl fftw framel libboost-headers cereal

cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_INSTALL_PREFIX="$CONDA_PREFIX"

cmake --build build -j"$(nproc)"
cmake --install build

CMake may install the compiled extension in the environment prefix. Move it to the active Python site-packages directory if necessary:

PYTHON_SITE=$(python -c "import sysconfig; print(sysconfig.get_paths()['platlib'])")
mv "$CONDA_PREFIX"/py4tsa*.so "$PYTHON_SITE"/

Verify the installation with:

python -c "import py4tsa; print(py4tsa.__file__)"

Reinstalling after changing the C++ sources

A rebuild does not by itself change what import py4tsa loads. Repeat the build and install, and check that the module Python resolves is the one just built:

cmake --build build -j"$(nproc)"
cmake --install build

PYTHON_SITE=$(python -c "import sysconfig; print(sysconfig.get_paths()['platlib'])")
mv "$CONDA_PREFIX"/py4tsa*.so "$PYTHON_SITE"/

md5sum build/py4tsa*.so "$PYTHON_SITE"/py4tsa*.so

The two checksums must match. If they differ, the interpreter is still loading the previous build and any change to the C++ will appear not to have taken effect -- a failure that looks like a bug in the code rather than in the install.

A .so placed in site-packages this way takes precedence over an editable install (pip install -e .), which resolves the module through a .pth file instead. Having both means the copied file wins and rebuilds stop taking effect silently, so pick one: either move the file after each build, as above, or use the editable install and delete the copy in site-packages.

Installation with pip

pip builds the C++ extension from source, so the native libraries and the Boost headers must already be present in the environment. The simplest way to provide them is a conda environment:

conda install -c conda-forge gsl fftw framel libboost-headers cereal
pip install .

To build a wheel instead of installing in place:

pip install build
python -m build --wheel        # -> dist/py4tsa-3.4.1-*.whl

Running the tests

pip install pytest
pytest python-wrapper/tests/ -v

The cross-checks of the long mothers against PyWavelets run when PyWavelets is installed. The real-data regression digests of the block rule run when P4TSA_WHITENED_STREAMS names a directory of whitened strain windows, and are skipped otherwise.

Runs on every push/PR via GitHub Actions (Python 3.10-3.12).

Changelog

2.2.0 (2026-08-03)

  • Contact info updated: elena.cuoco@unibo.it replacing the retired ego-gw.it address everywhere it appeared (source headers, README, docs); Giancarlo Cella dropped as a docs team contact.
  • Missing docs page added for ExtraWaveletFamilies.hpp (Coiflet/Symlet bases below) — it had doxygen comments but no Sphinx page since it was introduced.
  • CI Node.js 20 deprecation cleared: actions/checkout v4→v5, mamba-org/setup-micromamba v1→v3 (both now Node 24-native).
  • test_02_persistence.py no longer depends on wdf: builds its SeqView fixture with py4tsa's own SeqView_double_t/FillPoint instead of wdf.structures.array2SeqView, which isn't installed in this repo's CI.
  • WDF trigger SNR statistic fixed: EventFullFeatured::mSigma now exposes the winning wavelet basis's own per-window sigma across the C++/Python boundary (was previously recomputed downstream from a separate, staler sigma convention). The candidate wavelet-basis list dropped the 3 biorthogonal B-spline bases (not L2-energy-preserving, let them win basis selection spuriously even on pure noise).
  • Candidate wavelet-basis list redesigned and trimmed (WDF2Classify/WDF2Reconstruct, 19 → 10 bases): dropped redundant plain/centered Daubechies duplicates (same filter taps, just phase-shifted), added Coiflet (order 1, 2) and Symlet (order 4, 8) — genuinely new basis shapes, plugged into GSL's own extensible gsl_wavelet_type mechanism (no new external wavelet library, no GSL patching). See include/ExtraWaveletFamilies.hpp.
  • eternity (1999-2003 vendored XML persistence) removed entirely, replaced with Cereal (header-only, actively maintained; new cereal conda-forge dependency). See include/CerealPersistence.hpp.
  • Legacy pre-packaging-build files removed: bind.sh, install_dependencies.sh, install_full_dependencies.sh, python-wrapper/CMakeLists.txt (an orphaned separate build script from before this repo's CMake packaging build, unused by it).
  • CI moved from Travis to GitHub Actions (.github/workflows/ci.yml) — Travis's free tier for open source was retired years ago, and its old config predated the current build system.

Contributing

Changes reach master through pull requests only, and a pull request merges only once CI is green. See CONTRIBUTING.md for how to build and test locally, what CI checks, and the invariants a change to the detection filter must preserve.

Who do I talk to?

License

GPL-3.0-or-later. See LICENSE.

Metadata

Release files for py4tsa 3.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for py4tsa 3.4.1
File Size Uploaded
py4tsa-3.4.1.tar.gz 2.1 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for py4tsa 3.4.1
File
py4tsa-3.4.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.24+ x86-64, Linux glibc 2.28+ x86-64 Details
py4tsa-3.4.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64, Linux glibc 2.24+ x86-64 Details
py4tsa-3.4.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ x86-64, Linux glibc 2.24+ x86-64 Details
py4tsa-3.4.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.28+ x86-64, Linux glibc 2.24+ x86-64 Details
py4tsa-3.4.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.24+ x86-64, Linux glibc 2.28+ x86-64 Details

Total release size: 24.9 MB

Release files / py4tsa-3.4.1.tar.gz

Download URL py4tsa-3.4.1.tar.gz
Size 2.1 MB
Tags Source
SHA-256 checksum
How to use checksums
34265fea9b916fb4bb62378d722439af13279f67559bf1b7f1768e4854cc3ce6
BLAKE2b-256 checksum
How to use checksums
7f7bbc9ff66c2b89b3c400ce2ecab37dcf33136f54d907531fc2c12039aff42d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 9, 2026.

Transparency log

Release files / py4tsa-3.4.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL py4tsa-3.4.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 4.6 MB
Tags CPython 3.14 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
d33aa1cbc85b7ee285bc647993cfaa0312f612b59d446c1d5235273640e2520e
BLAKE2b-256 checksum
How to use checksums
f9edb017180d558a95cfe42e9bb57e18ce041a8e5782f29179468f798092c98e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 9, 2026.

Transparency log

Release files / py4tsa-3.4.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL py4tsa-3.4.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 4.6 MB
Tags CPython 3.13 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
01059d80588fbf8bf1dfb2bbcb60d7f7faa3ea639882f4e780eccd5eaba72d89
BLAKE2b-256 checksum
How to use checksums
5fe47368a37de2e98b3b688ef58d17c4eb7f17177520da312367863239393e1b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 9, 2026.

Transparency log

Release files / py4tsa-3.4.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL py4tsa-3.4.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 4.6 MB
Tags CPython 3.12 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
99a3c3eca41bdf8439a1a6c665890d3a29cf45f6621caa8dd437e135a12ed599
BLAKE2b-256 checksum
How to use checksums
82a13921ffe6ddbb26aa7b30057fd67c1bd48326fac31aa2dcf2c59ab594a496
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 9, 2026.

Transparency log

Release files / py4tsa-3.4.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL py4tsa-3.4.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 4.5 MB
Tags CPython 3.11 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
9b525eac1e67dd446dffa91f8f52fb97502c38133d7407b6554d576ddcee2a41
BLAKE2b-256 checksum
How to use checksums
b4725b92dd7f51537d5e03140435e21ffbec9b45b1e78141ba8953b80237848f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 9, 2026.

Transparency log

Release files / py4tsa-3.4.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL py4tsa-3.4.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 4.5 MB
Tags CPython 3.10 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
b0673519579c674f9fbcb176022938e7de07d2f2c5bedd03146e5bfb91ed257e
BLAKE2b-256 checksum
How to use checksums
28096210d2f382b75951162fd7ff7642474c14c75f6c4ac6e807e241cefcacee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 9, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

3.4.1 This release

6 release files

3.3.0

6 release files

3.2.0

5 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page