mTRFpy
Python package for fitting and evaluating multivariate temporal response function models for continuous stimulus-response data
Our View
Assess whether this fits the group’s research and teaching workflows. mTRFpy brings temporal response function modeling to Python. It supports regularized forward and backward models, cross-validation, prediction, visualization, and integration with MNE-Python, making it well suited to reproducible analyses of continuous neurophysiological data.
Provisional positions are editorial proposals awaiting group review.
Teaching — Recorded in topic offerings; consult the dated event links for availability.
1 topics with recorded teaching · 1 past offerings · 1 upcoming offerings
Related themes: Neural Data Analysis
Related topics: (M)EEG Analysis
Common use cases
- Model EEG or MEG responses to speech and other continuous stimuli
- Estimate temporal and spectrotemporal receptive fields
- Reconstruct continuous stimulus features from neural recordings
- Evaluate regularized models with cross-validation
Getting started
mTRFpy is a Python package for temporal response function (TRF) analysis. TRFs are multivariate regression models that describe the relationship between continuous stimulus features and neural responses across a range of time lags. They are commonly used to study responses to naturalistic stimuli such as continuous speech.
The project is a Python adaptation and extension of the mTRF-Toolbox, an established MATLAB toolbox for modeling multivariate stimulus-response data. The basic training and prediction operations in mTRFpy are designed to reproduce the MATLAB toolbox results within numerical precision while supporting Python and NumPy workflows.
Why mTRFpy?
- Continuous-data modeling: Relate dynamic stimulus features to continuous neural recordings
- Forward and backward models: Predict neural responses or reconstruct stimulus features
- Time-lagged regression: Estimate how relationships change across physiologically meaningful delays
- Regularization: Stabilize model estimates and reduce overfitting
- Cross-validation: Evaluate model performance on held-out data
- Visualization: Plot temporal and spectrotemporal response functions with Matplotlib
- MNE-Python integration: Convert fitted models to MNE evoked objects for visualization
- MATLAB continuity: Apply the mTRF modeling framework in Python while retaining conceptual compatibility with the original toolbox
Forward and Backward Models
A forward model, also called an encoding model, uses stimulus features to predict neural responses. Its weights describe how the response to each feature changes across time lags.
A backward model, also called a decoding model, uses neural responses to reconstruct a stimulus feature. Backward models can combine information across channels, but their weights should not generally be interpreted as physiological response patterns without an appropriate transformation.
Installation
The project is named mTRFpy, but the package is installed and imported as mtrf.
# Add the PyPI package to a Pixi environment
pixi add --pypi mtrf
# Or install it with pip
pip install mtrf
Matplotlib is optional and supports model visualization. MNE-Python is optional and enables conversion to MNE data structures.
pixi add matplotlib mne
Basic Forward Model
mTRFpy includes a small EEG dataset recorded while a participant listened to an audiobook. The stimulus contains speech spectrogram features, and the response contains multichannel EEG data.
from mtrf.model import TRF, load_sample_data
# Load normalized stimulus and EEG segments
stimulus, response, fs = load_sample_data(
n_segments=10,
normalize=True,
)
# Fit an encoding model over lags from 0 to 400 ms
forward_model = TRF(direction=1)
forward_model.train(
stimulus,
response,
fs,
tmin=0,
tmax=0.4,
regularization=1000,
)
# Predict the neural response and evaluate the prediction
prediction, correlation = forward_model.predict(stimulus, response)
The regularization parameter controls the trade-off between fitting the training data and obtaining stable model weights that generalize to new data.
Cross-Validation
Evaluating a model on the data used for training produces an overly optimistic estimate of performance. mTRFpy provides cross-validation for evaluating predictions on held-out segments.
from mtrf.stats import crossval
scores = crossval(
forward_model,
stimulus,
response,
fs,
tmin=0,
tmax=0.4,
regularization=1000,
)
print(f"Mean held-out correlation: {scores.mean():.3f}")
Regularization choices should also be made using held-out data. When comparing several values, use a validation procedure that remains separate from the final model evaluation.
Backward Model
Changing the model direction creates a decoder that reconstructs stimulus features from the neural response. This example reconstructs the speech envelope by averaging across spectrogram bands.
from mtrf.model import TRF
from mtrf.stats import crossval
speech_envelope = [segment.mean(axis=1) for segment in stimulus]
backward_model = TRF(direction=-1)
scores = crossval(
backward_model,
speech_envelope,
response,
fs,
tmin=0,
tmax=0.4,
regularization=1000,
)
print(f"Mean reconstruction correlation: {scores.mean():.3f}")
Visualizing Model Weights
The fitted weight matrix relates input features, time lags, and output channels. mTRFpy can plot selected features or summarize weights across channels.
from matplotlib import pyplot as plt
fig, axes = plt.subplots(2, 1)
forward_model.plot(
feature=6,
axes=axes[0],
show=False,
)
forward_model.plot(
channel="gfp",
kind="image",
axes=axes[1],
show=False,
)
plt.tight_layout()
plt.show()
Forward-model weights can often be interpreted similarly to time-resolved evoked responses. Backward-model weights combine signal amplification and noise suppression, so they should not be interpreted in the same way without first transforming the model into a forward representation.
Integration with MNE-Python
A fitted forward model can be converted to mne.Evoked objects for topographic and joint visualization.
from mne.channels import make_standard_montage
montage = make_standard_montage("biosemi128")
evokeds = forward_model.to_mne_evoked(montage)
evokeds[6].plot_joint(
times=[0.11, 0.185, 0.29],
topomap_args={"scalings": 1},
ts_args={"units": "a.u.", "scalings": {"eeg": 1}},
)
Best Practices
- Keep stimulus and neural-response data synchronized and sampled at compatible rates.
- Define the lag window from the scientific question rather than selecting it after inspecting the results.
- Normalize features when their scales differ substantially.
- Select regularization using held-out data.
- Report the lag window, regularization procedure, number of folds, and performance metric.
- Interpret forward- and backward-model weights differently.
- Compare prediction accuracy against an appropriate null model when making inferential claims.
- Inspect predictions and model weights rather than relying on a single summary score.