Skip to content

Synchronization Analysis Module

The Synchronization Module quantifies temporal coordination between multiple participants, body segments, or movement components.
It provides methods to assess how well different movement signals align in time and phase.

The module implements validated methods for temporal coordination assessment including: - cross-correlation with lag analysis. - Phase coupling and Phase Locking Values (PLV).

Note

These methods assume stationarity over the analysis window and Gaussian noise.

Algorithms Details

Cross-Correlation Analysis

Cross-correlation quantifies linear similarity between signals as a function of lag:

\[ R_{xy}(\tau) = \frac{\sum_t (x(t)-\bar{x})(y(t+\tau)-\bar{y})}{\sigma_x \sigma_y} \]
  • \( \tau \) is the lag
  • \( R_{xy}(\tau) \in [-1,1] \)

Output:

\[ \rho_{\max} = \max_\tau R_{xy}(\tau), \quad \tau^* = \arg\max_\tau R_{xy}(\tau) \]

Interpretation

Synchronization Strength Lag Interpretation
\( \rho_{\max} > 0.8 \): excellent synchronization Zero lag (\(\tau \approx 0\)): Signals are perfectly in-phase
\( 0.6 < \rho_{\max} \leq 0.8 \): good synchronization Positive lag (\(\tau > 0\)): Signal2 leads Signal1 by \(\tau\) seconds
\( 0.4 < \rho_{\max} \leq 0.6 \): moderate synchronization Negative lag (\(\tau < 0\)): Signal1 leads Signal2 by \(\tau\) seconds
\( \rho_{\max} \leq 0.4 \): poor synchronization Large lag (\(\tau > T_{threshold}\)): Loose coordination or potential artifacts

Phase Coupling Analysis

Phase synchronization measures temporal alignment independent of amplitude:

  1. Hilbert Transform: Compute analytic signals
\[ z_x(t) = x(t) + i H[x(t)], \quad z_y(t) = y(t) + i H[y(t)] \]
  1. Instantaneous Phases:
\[ \phi_x(t) = \arg(z_x(t)), \quad \phi_y(t) = \arg(z_y(t)) \]
  1. Phase Difference:
\[ \Delta \phi(t) = \phi_x(t) - \phi_y(t) \]
  1. Phase Locking Value (PLV):
\[ \text{PLV} = \left| \frac{1}{N} \sum_{t=1}^{N} e^{i \Delta \phi(t)} \right| \]

Output: \( \text{PLV} \in [0,1] \)

Interpretation

  • \( PLV > 0.7 \): strong phase coupling
  • \( 0.4 < PLV \leq 0.7 \): moderate phase coupling
  • \( PLV \leq 0.4 \): weak phase coupling

Usage Examples

Basic Synchronization Analysis

from pyeyesweb.sync import Synchronization
import numpy as np

# Initialize synchronization analyzer
sync_analyzer = Synchronization(sampling_rate=100.0)

# Load two movement signals
person1_velocity = np.load('person1_movement.npy')
person2_velocity = np.load('person2_movement.npy')

# Calculate cross-correlation
correlation_metrics = sync_analyzer.calculate_cross_correlation(
    person1_velocity, person2_velocity
)

print(f"Max correlation: {correlation_metrics['max_correlation']:.3f}")
print(f"Optimal lag: {correlation_metrics['lag_seconds']:.3f} seconds")

# Assess phase coupling
phase_metrics = sync_analyzer.assess_phase_coupling(
    person1_velocity, person2_velocity
)

print(f"Phase locking value: {phase_metrics['phase_locking_value']:.3f}")

Multi-Person Dance Analysis

def analyze_dance_synchronization(dancer_trajectories):
    """Analyze synchronization between multiple dancers."""
    sync_analyzer = Synchronization(sampling_rate=60.0)
    n_dancers = len(dancer_trajectories)

    # Pairwise synchronization analysis
    sync_matrix = np.zeros((n_dancers, n_dancers))

    for i in range(n_dancers):
        for j in range(i+1, n_dancers):
            # Extract velocity signals
            vel_i = compute_velocity(dancer_trajectories[i])
            vel_j = compute_velocity(dancer_trajectories[j])

            # Calculate synchronization
            sync_metrics = sync_analyzer.calculate_cross_correlation(
                vel_i, vel_j
            )

            sync_matrix[i, j] = sync_metrics['max_correlation']
            sync_matrix[j, i] = sync_matrix[i, j]

    return {
        'synchronization_matrix': sync_matrix,
        'average_synchronization': np.mean(sync_matrix[sync_matrix > 0]),
        'most_synchronized_pair': np.unravel_index(
            np.argmax(sync_matrix), sync_matrix.shape
        )
    }

Bilateral Coordination Assessment

def assess_bilateral_coordination(left_limb_data, right_limb_data):
    """Assess left-right limb coordination."""
    sync_analyzer = Synchronization(sampling_rate=100.0)

    # Time-varying synchronization analysis
    window_size = 200  # 2 seconds at 100 Hz

    sync_timeline = sync_analyzer.windowed_synchronization(
        left_limb_data, right_limb_data, 
        window_size=window_size,
        overlap=0.75
    )

    # Identify coordination phases
    high_sync_periods = sync_timeline['correlation'] > 0.7
    low_sync_periods = sync_timeline['correlation'] < 0.3

    return {
        'sync_timeline': sync_timeline,
        'high_coordination_duration': np.sum(high_sync_periods) / 100.0,
        'low_coordination_duration': np.sum(low_sync_periods) / 100.0,
        'average_coordination': np.mean(sync_timeline['correlation'])
    }

Real-Time Synchronization Monitoring

class RealTimeSyncMonitor:
    def __init__(self, buffer_size=500, sampling_rate=50.0):
        self.sync_analyzer = Synchronization(sampling_rate=sampling_rate)
        self.buffer_size = buffer_size
        self.buffer1 = deque(maxlen=buffer_size)
        self.buffer2 = deque(maxlen=buffer_size)

    def update(self, signal1_sample, signal2_sample):
        """Update with new data samples."""
        self.buffer1.append(signal1_sample)
        self.buffer2.append(signal2_sample)

        if len(self.buffer1) == self.buffer_size:
            # Calculate current synchronization
            sync_metrics = self.sync_analyzer.calculate_cross_correlation(
                np.array(self.buffer1),
                np.array(self.buffer2)
            )
            return sync_metrics

        return None

# Usage in real-time system
monitor = RealTimeSyncMonitor(buffer_size=300)

for frame in motion_stream:
    signal1 = extract_feature1(frame)
    signal2 = extract_feature2(frame)

    sync_result = monitor.update(signal1, signal2)

    if sync_result and sync_result['max_correlation'] > 0.8:
        print("High synchronization detected!")

Integration with Other Modules

Combined with Smoothness Analysis

# Assess both synchronization and smoothness
sync_metrics = sync_analyzer.calculate_cross_correlation(signal1, signal2)
smoothness_metrics = smoothness_analyzer([signal1, signal2])

coordination_quality = {
    'synchronization': sync_metrics['max_correlation'],
    'smoothness': smoothness_metrics['sparc'],
    'combined_score': (sync_metrics['max_correlation'] + 
                      abs(smoothness_metrics['sparc'])) / 2
}

Integration with Bilateral Symmetry

# Multi-level coordination analysis
bilateral_metrics = symmetry_analyzer.calculate_symmetry_index(
    left_data, right_data
)
temporal_sync = sync_analyzer.calculate_cross_correlation(
    left_data, right_data
)

comprehensive_coordination = {
    'spatial_symmetry': bilateral_metrics,
    'temporal_synchronization': temporal_sync
}

References

To be added