Entrainment Analysis
This module provides tools for analyzing the relationship between spike timing and LFP oscillations, including phase-locking and spike-field coherence metrics.
Phase-Locking Analysis
Calculate phase-locking between spikes and LFP:
import numpy as np
from bmtool.analysis.entrainment import (
calculate_spike_lfp_plv,
calculate_signal_signal_plv,
calculate_ppc,
calculate_ppc2
)
from bmtool.analysis.spikes import load_spikes_to_df
from bmtool.analysis.lfp import load_ecp_to_xarray, butter_bandpass_filter
# Load data
spikes_df = load_spikes_to_df('output/spikes.h5', network_name='network')
lfp_data = load_ecp_to_xarray('output/ecp.h5', demean=True)
# Filter LFP to specific frequency band (e.g., theta: 4-8 Hz)
lfp_signal = lfp_data.sel(channel=0).data
fs = 10000 # Hz
filtered_lfp = butter_bandpass_filter(
data=lfp_signal,
lowcut=4,
highcut=8,
fs=fs
)
# Get spike times for a specific population
population_spikes = spikes_df[spikes_df['pop_name'] == 'Pyramidal']
spike_times = population_spikes['timestamps'].values
# Calculate phase-locking value (PLV)
plv = calculate_spike_lfp_plv(
spike_times=spike_times,
lfp_data=filtered_lfp,
spike_fs=1000, # Spike times in milliseconds
lfp_fs=fs,
filter_method='butter',
lowcut=4,
highcut=8
)
print(f"Phase-locking value: {plv}")
# Calculate pairwise phase consistency (PPC)
ppc = calculate_ppc(
spike_times=spike_times,
lfp_data=filtered_lfp,
spike_fs=1000,
lfp_fs=fs,
filter_method='butter',
lowcut=4,
highcut=8
)
print(f"Pairwise phase consistency: {ppc}")
# Calculate PPC2 (alternate method)
ppc2 = calculate_ppc2(
spike_times=spike_times,
lfp_data=filtered_lfp,
spike_fs=1000,
lfp_fs=fs,
filter_method='butter',
lowcut=4,
highcut=8
)
print(f"PPC2 value: {ppc2}")
Population Entrainment Analysis
Analyze entrainment across multiple cells or populations:
from bmtool.analysis.entrainment import calculate_entrainment_per_cell
# Calculate entrainment metrics for all cells
entrainment_dict = calculate_entrainment_per_cell(
spike_df=spikes_df,
lfp_data=lfp_signal,
filter_method='wavelet',
pop_names=['Pyramidal', 'Basket'],
entrainment_method='plv', # or 'ppc', 'ppc2'
spike_fs=1000,
lfp_fs=fs,
freqs=[4, 8, 20, 40, 80] # Frequencies of interest
)
# Print results for each population
for pop, cell_dict in entrainment_dict.items():
print(f"\nPopulation: {pop}")
for cell_id, freq_dict in cell_dict.items():
print(f"Cell {cell_id}:")
for freq, value in freq_dict.items():
print(f" {freq} Hz: {value:.3f}")
Spike-LFP Power Correlation
Analyze correlation between spike rates and LFP power:
from bmtool.analysis.entrainment import calculate_spike_rate_power_correlation
# Calculate correlations across frequency bands
correlation_results, frequencies = calculate_spike_rate_power_correlation(
spike_rate=population_rates,
lfp_data=lfp_signal,
fs=fs,
pop_names=['Pyramidal', 'Basket'],
filter_method='wavelet',
freq_range=(4, 100),
freq_step=4
)
# Plot results
for pop in correlation_results:
corr_values = [correlation_results[pop][f]['correlation'] for f in frequencies]
plt.plot(frequencies, corr_values, label=pop)
plt.xlabel('Frequency (Hz)')
plt.ylabel('Correlation Coefficient')
plt.legend()
plt.title('Spike Rate-LFP Power Correlation')
plt.show()