Joint recurrence of gaze and pupil dynamics¶
This example combines two synchronized subsystem recurrence plots without forcing the systems into one common state vector.
Create synchronized systems¶
import numpy as np
from eyetrajectoriespy import TrajectorySet
time = np.arange(120) * 0.02
phase = 2.0 * np.pi * time / 0.50
gaze = TrajectorySet(
time=time,
values=np.column_stack([
np.sin(phase),
np.cos(phase),
])[None, :, :],
curve_ids=("trial_01",),
dimension_names=("x", "y"),
coordinate_system="unknown",
time_unit="s",
)
pupil = TrajectorySet(
time=time,
values=(
1.0
+ 0.15 * np.sin(phase)
+ 0.05 * np.sin(2.0 * phase)
)[None, :, None],
curve_ids=("trial_01",),
dimension_names=("pupil",),
coordinate_system="unknown",
time_unit="s",
)
Build separate recurrence contracts¶
from eyetrajectoriespy import recurrence_matrix
gaze_rec = recurrence_matrix(
gaze,
curve=0,
dimensions=("x", "y"),
target_recurrence_rate=0.10,
metric="euclidean",
theiler_window=3,
)
pupil_rec = recurrence_matrix(
pupil,
curve=0,
dimensions=("pupil",),
target_recurrence_rate=0.15,
metric="cityblock",
theiler_window=3,
)
The two systems use different dimensions, metrics, and target recurrence rates, while preserving the same time grid and Theiler exclusion.
Intersect the recurrence events¶
from eyetrajectoriespy import joint_recurrence_matrix
joint = joint_recurrence_matrix(
(gaze_rec, pupil_rec),
labels=("gaze", "pupil"),
)
print(joint.joint_recurrence_rate)
Audit the component definitions¶
from eyetrajectoriespy import joint_recurrence_component_frame
print(joint_recurrence_component_frame(joint))
Compute JRQA¶
from eyetrajectoriespy import joint_rqa_metrics
jrqa = joint_rqa_metrics(joint)
print(jrqa.determinism)
print(jrqa.laminarity)
Visualize¶
from eyetrajectoriespy import plot_joint_recurrence
ax = plot_joint_recurrence(joint)
Reporting helper¶
from eyetrajectoriespy import joint_recurrence_reporting_text
print(joint_recurrence_reporting_text(joint, jrqa))
The result means that the two declared systems recur simultaneously at those time pairs. It does not mean that their state vectors are close to each other, nor does it identify direction or causal coupling.
The executable counterpart is examples/joint_recurrence.py.