Vinnicombe nu-gap metric and a pipeline for comparing time-course data across two conditions
Project description
nugap
Detect condition-specific changes in dynamics using the Vinnicombe ν-gap metric.
nugap is a lightweight Python implementation of the Vinnicombe ν-gap — a
bounded (0–1) distance between linear dynamical systems from robust control
theory — together with the model identification and statistics needed to ask a
practical question of two-condition time-course data:
Which variables, or which relationships between them, change their dynamical behaviour between conditions?
(for example wild type vs mutant, or untreated vs treated). Comparisons of expression level answer a different question and are blind to changes in timescale, gain or phase. The ν-gap is defined directly on dynamical models, so it is not: two systems close in ν-gap behave the same way under feedback, and a large ν-gap marks a genuine change in dynamics.
Installation
pip install nugap
Requires Python ≥ 3.10. The core and pipelines depend only on NumPy, SciPy and pandas; the plotting helpers additionally use Matplotlib and NetworkX.
Tutorial
A guided, runnable tutorial covers the metric, model fitting, and the two-condition network comparison end to end:
- Open in Colab: https://colab.research.google.com/github/comparativechrono/nugap/blob/main/tutorial_nugap.ipynb
- View on GitHub:
tutorial_nugap.ipynb
Quick start
The ν-gap between two systems (coefficients in descending powers of s):
from nugap import tf, nu_gap
P1 = tf([1], [1, 1]) # 1/(s+1)
P2 = tf([1], [1, 3]) # 1/(s+3)
nu_gap(P1, P2) # -> 0.447 (0 = identical, 1 = maximally different)
Comparing a whole interaction network between two conditions, with replicate-based significance:
from nugap import compare_network
# data_A, data_B: dict {variable_name: array of shape (replicates, timepoints)}
# t: the common time vector
edges = compare_network(data_A, data_B, t, order=1, min_r2=0.5)
edges.query("q_global < 0.1") # relationships rewired between conditions (FDR < 10%)
What it provides
nu_gap— the Vinnicombe ν-gap for SISO systems in continuous or discrete time, with an optional frequency-band restriction (band=) and a switchable winding-number test (check_winding=) for oscillatory data.- Model identification —
fit_first_order,fit_model,fit_arx,fit_prony, with simulation-based fit quality and an optional DC-gain floor (min_dc_gain=); plus thedc_gainhelper. compare_conditions— per-variable comparison of dynamics between two conditions, with a fit-quality reliability flag.compare_network— pairwise interaction-network comparison: a low-order model is fitted to every ordered pair of variables in each condition, the ν-gap is taken between conditions, and significance comes from a replicate-derived empirical null with Benjamini–Hochberg FDR control.- Plotting —
nugap.viz(volcano plot, hub network, hub bar plot).
How it works
For each variable or pairwise interaction, nugap fits a low-order linear
input–output model under each condition, then measures the ν-gap between the
fitted models. Because models are compared on mean-centred trajectories, the
metric reflects changes in the relationship — timescale, gain or phase — rather
than in absolute level. With biological replicates, the spread of within-condition
ν-gaps provides an empirical null and a per-edge noise floor, against which
between-condition changes are tested and FDR-controlled.
The models are single-input single-output, so an edge captures a pairwise input–output relationship, not proven causation.
Correctness
The ν-gap implementation is verified by several independent routes — exact
closed-form values, an algebraic invariance of the chordal metric, an independent
reference implementation, and the Vinnicombe robust-stability theorem — and is
cross-checked against MATLAB's gapmetric (Robust Control Toolbox), which it
reproduces to within ~10⁻⁶. The scripts are in validation/, with
a fast subset run on every commit.
Citing
If you use nugap in your work, please cite the software and the accompanying
methods paper:
Hearn, T. J. nugap: condition-specific changes in dynamical relationships via the
Vinnicombe ν-gap. Software archive: Zenodo, DOI: 10.5281/zenodo.XXXXXXX.
<methods paper reference — to be added>
License
Released under the MIT License. Copyright © 2026 Tim Hearn. See
LICENSE.
Project details
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 nugap-0.5.0.tar.gz.
File metadata
- Download URL: nugap-0.5.0.tar.gz
- Upload date:
- Size: 26.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00bb213a1674d62e598df6db9fa564a1562b125168ac9242b1d902b17862de18
|
|
| MD5 |
31603ec934004ce709039f3684500b7f
|
|
| BLAKE2b-256 |
b78a5ba70e0f70af9d9aa9116184ad5c7766d38d77c475bef6f09132402ee223
|
File details
Details for the file nugap-0.5.0-py3-none-any.whl.
File metadata
- Download URL: nugap-0.5.0-py3-none-any.whl
- Upload date:
- Size: 25.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ded104e06150c53e5c818ab096191d78b21067b4eb34b0878bcc2dfb5f94e5b6
|
|
| MD5 |
ec34946066cddfae4334c32d7fa52337
|
|
| BLAKE2b-256 |
a94c018fee2200fbc6b890b969cc4178d40a1d280c5631732b07cefb14b7e9e0
|