1- import numpy as np
1+ """Mathematical utility functions for signal analysis.
2+
3+ This module provides mathematical functions used throughout the PyEyesWeb
4+ library for signal processing, phase analysis, and movement metrics.
5+ """
26
7+ import numpy as np
38
49def compute_phase_locking_value (phase1 , phase2 ):
5- """Compute the Phase Locking Value (PLV) from two phase arrays."""
10+ """Compute the Phase Locking Value (PLV) from two phase arrays.
11+
12+ PLV measures the inter-trial variability of the phase difference between
13+ two signals. A value of 1 indicates perfect phase locking, while 0
14+ indicates no phase relationship.
15+
16+ Parameters
17+ ----------
18+ phase1 : ndarray
19+ Phase values of first signal in radians.
20+ phase2 : ndarray
21+ Phase values of second signal in radians.
22+
23+ Returns
24+ -------
25+ float
26+ Phase Locking Value between 0 and 1.
27+
28+ References
29+ ----------
30+ Lachaux et al. (1999). Measuring phase synchrony in brain signals.
31+ """
632 phase_diff = phase1 - phase2
733 phase_diff_exp = np .exp (1j * phase_diff )
834 plv = np .abs (np .mean (phase_diff_exp ))
935 return plv
1036
1137
1238def center_signals (sig ):
13- """Remove the mean from each signal to center the data."""
39+ """Remove the mean from each signal to center the data.
40+
41+ Centers signals by subtracting the mean, removing DC bias.
42+
43+ Parameters
44+ ----------
45+ sig : ndarray
46+ Signal array of shape (n_samples, n_channels).
47+
48+ Returns
49+ -------
50+ ndarray
51+ Centered signal with same shape as input.
52+ """
1453 return sig - np .mean (sig , axis = 0 , keepdims = True )
1554
1655
1756def compute_sparc (signal , rate_hz = 50.0 ):
18- """Compute SPARC (Spectral Arc Length) from a signal."""
57+ """Compute SPARC (Spectral Arc Length) from a signal.
58+
59+ SPARC is a dimensionless smoothness metric that quantifies movement
60+ smoothness independent of movement amplitude and duration. More negative
61+ values indicate smoother movement.
62+
63+ Parameters
64+ ----------
65+ signal : ndarray
66+ 1D movement signal.
67+ rate_hz : float, optional
68+ Sampling rate in Hz (default: 50.0).
69+
70+ Returns
71+ -------
72+ float
73+ SPARC value (negative, more negative = smoother).
74+ Returns NaN if signal has less than 2 samples.
75+
76+ References
77+ ----------
78+ Balasubramanian et al. (2015). On the analysis of movement smoothness from the Journal of NeuroEngineering and Rehabilitation.
79+ """
1980 N = len (signal )
2081 if N < 2 :
2182 return float ("nan" )
@@ -30,7 +91,29 @@ def compute_sparc(signal, rate_hz=50.0):
3091
3192
3293def compute_jerk_rms (signal , rate_hz = 50.0 ):
33- """Compute RMS of jerk (third derivative) from a signal."""
94+ """Compute RMS of jerk (third derivative) from a signal.
95+
96+ Jerk is the rate of change of acceleration. Lower RMS jerk values
97+ indicate smoother movement.
98+
99+ Parameters
100+ ----------
101+ signal : ndarray
102+ 1D movement signal (position or velocity).
103+ rate_hz : float, optional
104+ Sampling rate in Hz (default: 50.0).
105+
106+ Returns
107+ -------
108+ float
109+ Root mean square of jerk.
110+ Returns NaN if signal has less than 2 samples.
111+
112+ Notes
113+ -----
114+ This implementation uses first-order finite differences to approximate
115+ the derivative. For position signals, this computes jerk directly.
116+ """
34117 if len (signal ) < 2 :
35118 return float ("nan" )
36119 dt = 1.0 / rate_hz
@@ -39,6 +122,21 @@ def compute_jerk_rms(signal, rate_hz=50.0):
39122
40123
41124def normalize_signal (signal ):
42- """Normalize signal by its maximum absolute value."""
125+ """Normalize signal by its maximum absolute value.
126+
127+ Scales the signal to the range [-1, 1] by dividing by the maximum
128+ absolute value.
129+
130+ Parameters
131+ ----------
132+ signal : ndarray
133+ Input signal to normalize.
134+
135+ Returns
136+ -------
137+ ndarray
138+ Normalized signal with same shape as input.
139+ Returns original signal if max absolute value is 0.
140+ """
43141 max_val = np .max (np .abs (signal ))
44142 return signal / max_val if max_val != 0 else signal
0 commit comments