A toolkit for EEG phase estimation
Project description
EEGPhasePy
A toolkit for developing and analyzing real-time and pseudo-real-time EEG phase estimation.
EEGPhasePy includes implementations of various EEG phase estimation algorithms — including Educated Temporal Prediction (ETP) and PHASTIMATE (autoregressive) — alongside offline analysis helpers for evaluating phase estimation experiments. For background on EEG phase estimation and its applications, see Zrenner & Ziemann (2024). More phase estimators will continue to be added in the future.
Features
- ETP — Educated Temporal Prediction (Shirinpour et al., 2020): uses average interpeak-interval to determine time to next target phase. Similar accuracy to AR with the added benefit of working well with amplifiers that have low packet send rates.
- PHASTIMATE — Autoregressive phase estimator (Zrenner et al., 2020): uses an AR model to compensate for filter edge effects and extracts instantaneous phase via the Hilbert transform. Estimates ongoing phase rather than predicting.
- Parameter optimization — Bayesian and genetic optimization (via
bayesian-optimizationandPyGAD) over AR order and window edge for PHASTIMATE. Improve accuracy of the AR model on a participant-by-participant basis. - Visualization — Polar phase histograms and average ± std pre/post-trigger waveforms via
matplotlib. - Supports Python 3.9–3.13.
Documentation
Full documentation including API reference, usage guides, and examples is available at eegphasepy.readthedocs.io.
Table of contents
| Section | Pages |
|---|---|
| Guide | What is EEG phase estimation? · Real-time phase estimation |
| Models | ETP-based phase estimation · Autoregressive phase estimation |
| Optimizing | Bayesian optimization of PHASTIMATE · Genetic optimization of PHASTIMATE |
| Analysis | Waveform plots · Polar histograms · Phase estimation statistics |
| Examples | Gallery |
| Reference | API reference |
Installation
pip install eegphasepy
Quick start
Setting up a model
Select the model you plan to run phase estimation with. Below we use ETP; see the models documentation for all available estimators.
import numpy as np
import scipy.signal as signal
from EEGPhasePy.estimators import ETP
fs = 2000
window_len = 2 * fs # 2 s rolling buffer
packet_size = int(0.06 * fs) # samples per amplifier packet (~60 ms)
rt_filter = signal.firwin(120, [8, 12], fs=fs, pass_zero=False)
gt_filter = signal.firwin(300, [8, 12], fs=fs, pass_zero=False)
etp = ETP(rt_filter, gt_filter, fs)
etp.fit(training_signal, min_ipi=int(fs * 1/12))
Real-time phase estimation
In a live experiment your amplifier sends packets of samples at a fixed rate. On each packet arrival you append the new samples to a rolling buffer, run ETP on that buffer, and schedule a trigger to fire at the sample offset ETP returns. predict returns the number of samples from the end of the current window at which the target phase is expected — converting that to wall-clock time (offset / fs) gives you how far in the future to schedule the stimulus.
import collections, time
buffer = collections.deque(maxlen=window_len) # auto-drops oldest samples
triggers = []
# In a real experiment this would be a while loop reading packets from your amplifier
for packet_start in range(0, len(testing_signal) - packet_size, packet_size):
packet = testing_signal[packet_start:packet_start + packet_size]
buffer.extend(packet)
if len(buffer) < window_len:
continue # wait until the buffer is full
window = np.array(buffer)
try:
offset = etp.predict(window, target_phase=0) # predict next peak
trigger_time = time.time() + offset / fs # absolute wall-clock time
trigger_sample = packet_start + packet_size + offset
triggers.append(trigger_sample)
# schedule_trigger(trigger_time) # call your hardware trigger here
except RuntimeError:
pass # no peaks found in this window
Analysing the output
In raw EEG you would typically have trigger markers stored as annotations in your EEG file. EEGPhasePy just needs the sample number each trigger occurs at to analyze the outcome of your phase estimation experiment.
mean_phase = etp.mean_phase_from_triggers(testing_signal, triggers, degree=True)
std_phase = etp.std_phase_from_triggers(testing_signal, triggers, degree=True)
accuracy = etp.phase_accuracy_from_triggers(testing_signal, triggers, 0)
print(f"Mean phase: {mean_phase:.1f}° | Std: {std_phase:.1f}° | Accuracy: {accuracy * 100:.1f}%")
mean_phase_from_triggers and std_phase_from_triggers return the circular mean and standard deviation of the phase at each trigger (a std of 50°–70° is typical in published studies). phase_accuracy_from_triggers returns a 0–1 score where 0.5 is chance, 0 is anti-phase, and 1 is perfect locking.
Visualization
import EEGPhasePy.viz as viz
# Polar histogram of triggered phases
polar_fig = etp.polar_histogram_from_triggers(testing_signal, triggers)
# Average ± std waveform around trigger events
waveform_fig = etp.plot_mean_std_waveform_from_triggers(
testing_signal, triggers, tmin=0.1, tmax=0.1
)
Both functions return a matplotlib.figure.Figure. See the waveform plots and polar histograms documentation for color and style customization options.
Contributing
Contributions are welcome. Please open an issue or pull request on GitHub.
Citation
If you use EEGPhasePy in your research, please cite the underlying algorithm(s) you end up using:
- ETP: Shirinpour et al. (2020). Experimental Evaluation of Methods for Real-Time EEG Phase-Specific Transcranial Magnetic Stimulation. PMC8293904
- PHASTIMATE: Zrenner et al. (2020). The shaky ground truth of real-time phase estimation. PMID 29191438
Licence
BSD 3-Clause Licence. See LICENCE for details.
Acknowledgements
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 eegphasepy-0.0.7.tar.gz.
File metadata
- Download URL: eegphasepy-0.0.7.tar.gz
- Upload date:
- Size: 17.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
daa75f9b07eaf4ba587ea7d5a7f770a8bce79619d6ce9f09384a5cdba9c3150b
|
|
| MD5 |
6c0b2064b3626bcd84927648301fdf81
|
|
| BLAKE2b-256 |
587e04af68f10e3460c86b47fd738724ea2c9b937a5d53dc01a7cd03aae0f8c4
|
File details
Details for the file eegphasepy-0.0.7-py3-none-any.whl.
File metadata
- Download URL: eegphasepy-0.0.7-py3-none-any.whl
- Upload date:
- Size: 17.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43701522332e9118534e37ed4dba706f28fd4f45554b261e02849d4e960d90a1
|
|
| MD5 |
66baf2a8a2b00b8b18bb6796e40c2aad
|
|
| BLAKE2b-256 |
736f9285d15b3afa8589c83b17ee81c6aa07d44170cbbe73ff7946bbd020934d
|