Skip to content

Recurrence Quantification Analysis (RQA) toolbox for gait dynamics. Validated against PyRQA.

Notifications You must be signed in to change notification settings

Taiyou/gait-dynamics-features

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gait-dynamics-features

Feature extraction toolbox for gait dynamics analysis.

Extracts nonlinear dynamical and gait-specific features from gait time series. Includes Recurrence Quantification Analysis (RQA) validated against PyRQA, plus gait-specific measures not found in standard libraries.

Features

Recurrence Analysis

  • RQA - Recurrence Quantification Analysis (9 measures: RR, DET, L, Lmax, ENTR, LAM, TT, Vmax, TND)
  • CRQA - Cross-Recurrence Quantification Analysis for two coupled time series
  • Embedding - Automatic estimation of embedding parameters (AMI + FNN)
  • Visualization - Recurrence plots, cross-recurrence plots, distance matrices, comparison charts

Gait-Specific Features (not available in nolds/antropy/neurokit2/EntropyHub)

  • Poincare Plot (SD1/SD2) - Short/long-term variability for arbitrary stride interval series
  • Harmonic Ratio - Step-to-step symmetry from trunk acceleration (AP/VT/ML axes)
  • Attractor Complexity Index (ACI) - Long-term divergence exponent (Terrier, 2018)
  • Stride Variability - CV, MAD, IQR, asymmetry index

Unified Analysis Pipeline

  • GaitAnalysisPipeline - Single interface for all features (internal + external)
  • Automatic integration with nolds, antropy, neurokit2 (all optional)
  • Entropy measures: Sample, Permutation, SVD, Approximate, Multiscale
  • Fractal/scaling: DFA, Lyapunov, Hurst, Correlation Dimension, Higuchi FD, Katz FD
  • Produces up to 30 features from a single stride interval series
  • Bilateral analysis via Cross-Recurrence for left/right limb coupling

Integration

  • scikit-learn compatible - fit() / transform() interface for ML pipelines
  • Complements existing libraries: use nolds for DFA/Lyapunov, antropy for entropy measures, and this toolbox for RQA + gait-specific features

Installation

git clone https://github.com/Taiyou/gait-dynamics-features.git
cd gait-dynamics-features
pip install -e .

For development (includes test dependencies):

pip install -e ".[dev]"

Quick Start

import numpy as np
from src import RecurrenceAnalyzer, RecurrencePlotter

# Generate a gait-like signal
t = np.linspace(0, 10 * np.pi, 500)
signal = np.sin(t) + 0.3 * np.sin(2 * t)

# Create analyzer
analyzer = RecurrenceAnalyzer(
    embedding_dim=3,
    time_delay=10,
    theiler_window=1,
)

# Auto-select threshold for 5% recurrence rate
eps = analyzer.auto_threshold(signal, target_rr=0.05)

# Compute RQA measures
measures = analyzer.compute_rqa_measures(signal, threshold=eps)
print(measures)
# {'RR': 0.051, 'DET': 0.89, 'L': 7.1, 'Lmax': 160, ...}

# Visualize
plotter = RecurrencePlotter()
rm = analyzer.recurrence_matrix_
fig = plotter.plot_recurrence(rm, title="Gait Recurrence Plot")
fig.savefig("recurrence_plot.png")

Cross-Recurrence Analysis

from src import CrossRecurrenceAnalyzer

# Left and right leg signals
left = np.sin(t) + 0.2 * np.sin(2 * t)
right = np.sin(t + np.pi) + 0.2 * np.sin(2 * (t + np.pi))

crqa = CrossRecurrenceAnalyzer(
    embedding_dim=3,
    time_delay=10,
    threshold_ratio=0.15,
)
measures = crqa.compute_crqa_measures(left, right)

# Detect time lag via diagonal profile
profile = crqa.compute_diagonal_profile(left, right)

Gait-Specific Features

from src import PoincareAnalyzer, HarmonicRatioAnalyzer, StrideVariability, GaitFeatureExtractor

# Stride interval analysis
stride_intervals = np.array([1.12, 1.08, 1.15, 1.10, ...])  # seconds

# Poincare plot
poincare = PoincareAnalyzer(lag=1)
result = poincare.compute(stride_intervals)
# {'SD1': 0.023, 'SD2': 0.041, 'SD_ratio': 0.56, 'S': 0.003, 'GI': 2.1}

# Stride variability
variability = StrideVariability.compute(stride_intervals)
# {'mean': 1.11, 'std': 0.033, 'cv': 3.0, 'range': 0.12, ...}

# All gait features at once (sklearn-compatible)
extractor = GaitFeatureExtractor(embedding_dim=3, time_delay=10)
features = extractor.fit_transform(stride_intervals)  # 15-element vector

# Harmonic ratio from trunk acceleration
hra = HarmonicRatioAnalyzer(n_harmonics=10)
hr = hra.compute_single(stride_acceleration, axis_type='ap')

Unified Analysis Pipeline

from src import GaitAnalysisPipeline

# Full analysis with a single call
pipeline = GaitAnalysisPipeline(
    embedding_dim=3,
    time_delay=5,
    target_rr=0.05,
)

stride_intervals = 1.1 + 0.03 * np.random.randn(300)
results = pipeline.analyze(stride_intervals)

# Access feature groups
print(results['variability']['cv'])   # Coefficient of variation
print(results['poincare']['SD1'])     # Short-term variability
print(results['rqa']['DET'])          # Determinism
print(results['entropy'])             # Sample/Permutation/SVD entropy (if nolds/antropy installed)
print(results['fractal'])             # DFA/Lyapunov/Hurst (if nolds/antropy installed)

# Human-readable report
print(pipeline.summary())

# Export as flat dict or feature vector for ML
flat = pipeline.to_flat_dict()     # {'VAR_cv': 2.8, 'RQA_DET': 0.95, ...}
vec = pipeline.to_feature_vector() # numpy array (up to 30 features)

# Bilateral coupling analysis
results = pipeline.analyze_bilateral(left_strides, right_strides)
print(results['crqa']['DET'])      # Cross-determinism
print(results['coupling_lag'])     # Estimated coupling lag

Automatic Embedding Parameter Estimation

analyzer = RecurrenceAnalyzer()
dim, delay = analyzer.estimate_embedding_parameters(signal)
print(f"Optimal dimension: {dim}, delay: {delay}")

RQA Measures

Measure Symbol Description
Recurrence Rate RR Density of recurrence points
Determinism DET Fraction of recurrence points forming diagonal lines
Average Diagonal Length L Mean length of diagonal line structures
Max Diagonal Length Lmax Longest diagonal line
Entropy ENTR Shannon entropy of diagonal line length distribution
Laminarity LAM Fraction of recurrence points forming vertical lines
Trapping Time TT Mean length of vertical line structures
Max Vertical Length Vmax Longest vertical line
Trend TND Drift of recurrence rate away from main diagonal

Gait-Specific Measures

Measure Class Description
SD1 PoincareAnalyzer Short-term stride variability
SD2 PoincareAnalyzer Long-term stride variability
GI PoincareAnalyzer Gait irregularity index
HR HarmonicRatioAnalyzer Harmonic ratio (gait symmetry)
ACI AttractorComplexityIndex Attractor complexity index
CV StrideVariability Coefficient of variation
MAD StrideVariability Mean absolute deviation

Project Structure

gait-dynamics-features/
├── src/
│   ├── __init__.py
│   ├── rqa_analysis.py          # Core RQA (RecurrenceAnalyzer)
│   ├── crqa_analysis.py         # Cross-RQA (CrossRecurrenceAnalyzer)
│   ├── rqa_visualization.py     # Plotting (RecurrencePlotter)
│   ├── gait_features.py         # Gait-specific features
│   └── gait_analysis.py         # Unified analysis pipeline
├── tests/
│   ├── conftest.py              # Test fixtures
│   ├── test_rqa_analysis.py     # RQA tests (34 tests)
│   ├── test_crqa_analysis.py    # CRQA tests (13 tests)
│   ├── test_gait_features.py    # Gait feature tests (40 tests)
│   └── test_gait_analysis.py    # Pipeline tests (21 tests)
├── examples/
│   ├── demo_rqa.py              # RQA usage demos
│   ├── demo_gait_analysis.py    # Pipeline usage demos
│   ├── validate_against_pyrqa.py # PyRQA comparison
│   └── validate_gait_features.py # Gait feature validation
├── docs/
│   ├── api_reference.md         # Full API documentation
│   ├── tutorial.md              # Step-by-step tutorial
│   └── pyrqa_comparison.md      # Validation against PyRQA
├── setup.py
└── pytest.ini

Validation

All RQA measures have been validated against PyRQA across 4 signal types (sine, harmonics, Lorenz chaotic, white noise). See docs/pyrqa_comparison.md for full results.

Signal RR DET L Lmax ENTR LAM TT Vmax
sine = = = = = = = =
harmonics = = = = = = = =
Lorenz = = = = = = * *
noise = = = = = = = =

= exact match, * edge-case difference (see docs for details)

Performance: 3-14x faster than PyRQA for N=100-1000.

Running Tests

pytest tests/ -v

With coverage:

pytest tests/ -v --cov=src --cov-report=term-missing

Dependencies

Required:

  • Python >= 3.9
  • NumPy >= 1.24
  • SciPy >= 1.10
  • matplotlib >= 3.7
  • scikit-learn >= 1.3

Optional (for additional entropy/fractal features via GaitAnalysisPipeline):

  • nolds - Sample Entropy, DFA, Lyapunov, Hurst, Correlation Dimension
  • antropy - Permutation/SVD/Approximate Entropy, Higuchi/Katz FD, DFA
  • neurokit2 - Multiscale Entropy
pip install nolds antropy neurokit2  # optional, any subset is fine

External Library Integration

GaitAnalysisPipeline automatically detects and uses these libraries when installed:

Measure Library Pipeline Key
Sample Entropy nolds or antropy ENT_sample_entropy
Permutation Entropy antropy ENT_permutation_entropy
SVD Entropy antropy ENT_svd_entropy
Approximate Entropy antropy ENT_approximate_entropy
Multiscale Entropy neurokit2 ENT_multiscale_entropy
DFA nolds or antropy FRC_dfa_alpha
Lyapunov Exponent nolds FRC_lyapunov_r
Hurst Exponent nolds FRC_hurst_exponent
Correlation Dimension nolds FRC_correlation_dim
Higuchi FD antropy FRC_higuchi_fd
Katz FD antropy FRC_katz_fd

These measures are well-implemented in the above libraries and are wrapped (not reimplemented) by the pipeline. If no external libraries are installed, internal features (RQA, Poincare, ACI, Variability) are still computed.

References

  • Marwan, N., Romano, M.C., Thiel, M., & Kurths, J. (2007). Recurrence plots for the analysis of complex systems. Physics Reports, 438(5-6), 237-329.
  • Zbilut, J.P., Giuliani, A., & Webber, C.L. (1998). Detecting deterministic signals in exceptionally noisy environments using cross-recurrence quantification. Physics Letters A, 246(1-2), 122-128.
  • Kennel, M.B., Brown, R., & Abarbanel, H.D.I. (1992). Determining embedding dimension for phase-space reconstruction. Physical Review A, 45(6), 3403.
  • Fraser, A.M. & Swinney, H.L. (1986). Independent coordinates for strange attractors from mutual information. Physical Review A, 33(2), 1134.
  • Brennan, M., Palaniswami, M., & Kamen, P. (2001). Do existing measures of Poincare plot geometry reflect nonlinear features of heart rate variability? IEEE Trans Biomed Eng, 48(11), 1342-1347.
  • Bellanca, J.L., Lowry, K.A., VanSwearingen, J.M., Brach, J.S., & Redfern, M.S. (2013). Harmonic ratios: A quantification of step to step symmetry. J Biomech, 46, 828-834.
  • Terrier, P. (2018). Complexity of human walking: the attractor complexity index. Gait & Posture, 61, 378-384.
  • Rosenstein, M.T., Collins, J.J., & De Luca, C.J. (1993). A practical method for calculating largest Lyapunov exponents from small data sets. Physica D, 65, 117-134.

License

MIT

About

Recurrence Quantification Analysis (RQA) toolbox for gait dynamics. Validated against PyRQA.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages