import scipy.io as io
import scipy.signal as signal
import numpy as np
import matplotlib.pyplot as plt
Coherence Part 3 (spike-field coherence)
Dependence on rate (Part 1)
# Load the data and plot it.
= io.loadmat('Data/spikes-LFP-1.mat') # Load the multiscale data,
data = data['y'] # ... get the LFP data,
y = data['n'] # ... get the spike data,
n = data['t'].reshape(-1) # ... get the time axis,
t = np.shape(n)[0] # Get the number of trials,
K = np.shape(n)[1] # ... and the number of data points in each trial,
N = t[1]-t[0] # Get the sampling interval.
dt
0,:]);
plt.stem(t,n['Time [s]'); plt.xlabel(
For convenience, make a function to compute the cohernece.
def coherence(n,y,t): #INPUT (spikes, fields, time)
= np.shape(n)[0] #... where spikes and fields are arrays [trials, time]
K = np.shape(n)[1]
N = t[-1]
T = np.zeros(int(N/2+1))
SYY = np.zeros(int(N/2+1))
SNN = np.zeros(int(N/2+1), dtype=complex)
SYN
for k in np.arange(K):
= np.fft.rfft((y[k,:]-np.mean(y[k,:]))) # FT of fields
yf = np.fft.rfft((n[k,:]-np.mean(n[k,:]))) # FT of spikes
nf = SYY + ( np.real( yf*np.conj(yf) ) )/K # Field spectrum
SYY = SNN + ( np.real( nf*np.conj(nf) ) )/K # Spike spectrum
SNN = SYN + ( yf*np.conj(nf) )/K # Cross spectrum
SYN
= np.abs(SYN) / np.sqrt(SYY) / np.sqrt(SNN) # Coherence
cohr = np.fft.rfftfreq(N, dt) # Frequency axis for plotting
f
return (cohr, f, SYY, SNN, SYN)
Let’s try it:
= coherence(n,y,t)
[cohr, f, SYY, SNN, SYN]
plt.plot(f,cohr)0, 100]); plt.xlabel('Frequency [Hz]'); plt.ylabel('Coherence'); plt.xlim([
Make a function to thin a spike train.
def thinned_spike_train(n, thinning_factor): # Thin the spike train (n) by the thinning_factor.
= np.copy(n) # Make a copy of the spike train data.
n_thinned for k in np.arange(K): # For each trial,
= np.where(n[k,:]==1) # ...find the spikes.
spike_times = np.size(spike_times) # ...determine number of spikes.
n_spikes = spike_times[0][np.random.permutation(n_spikes)] # ...permute spikes indices,
spike_times_random =int(np.floor(thinning_factor*n_spikes)) # ... determine number of spikes to remove,
n_remove1:n_remove]]=0 # remove the spikes.
n_thinned[k,spike_times_random[return n_thinned
Let’s try it:
plt.clf()0,:], 'k')
plt.stem(t, n[0.5)[0,:], 'r');
plt.stem(t, thinned_spike_train(n,0.2, 0.3])
plt.xlim(['Original', 'Thinned']); plt.legend([
Compare the spike-field coherence for original and thinned data.
= "SOMETHING" # Coherence for original spike train.
[cohr, f, SYY, SNN, SYN]
plt.clf()'b')
plt.plot(f,cohr, = "SOMETHING" # ... and for the thinned spike train.
[cohr, f, SYY, SNN, SYN] 'r')
plt.plot(f,cohr, 40, 50])
plt.xlim(['Original', 'Thinned'])
plt.legend(['Frequency [Hz]')
plt.xlabel('Coherence'); plt.ylabel(
Repeat for different thinning factors.
;
plt.figure()for thin_factor in "SOMETHING
thinned = "SOMETHING" # Make the thinned spike train
="SOMETHING" # ... and compute the coherence
[cohr, f, SYY, SNN, SYN] =str(thin_factor)) #
plt.plot(f,cohr,label
40, 50])
plt.xlim([
plt.legend()'Frequency [Hz]')
plt.xlabel('Coherence'); plt.ylabel(
Dependence on rate (Part 2)
Simulate two simple spiking neurons, with activity dependent on a field.
def sim_two_neurons(baseline_rate_A, baseline_rate_B, field_coupling_A, field_coupling_B):
= 100 # Number of trials.
K = 1000 # Points per trial.
N = np.zeros([K,N]) # Array to hold spikes A.
A = np.zeros([K,N]) # Array to hold spikes B.
B = np.zeros([K,N]) # Array to hold field.
y for k in np.arange(K): # For each trial,
= np.sin(2*np.pi*t*10) + 0.1*np.random.randn(N) # ... generate a field,
y[k,:] = np.random.binomial(1,0.001*np.exp(baseline_rate_A+field_coupling_A*y[k,:])) # ... generate spikes #A that may depend on the field,
A[k,:] = np.random.binomial(1,0.001*np.exp(baseline_rate_B+field_coupling_B*y[k,:])) # ... generate spikes #B that may depend on the field.
B[k,:] return A,B,y
Visualize example trials.
plt.clf()= 1.0; coupling_A = 1 # Fix the rates and coupling to field for each neuron.
rate_A = 0.5; coupling_B = 1 # Simulate the two neurons.
rate_B = sim_two_neurons(rate_A, rate_B, coupling_A, coupling_B)
A,B,y = 0; # Select a trial to plot.
n_trial
plt.plot(t,A[n_trial,:])
plt.plot(t,B[n_trial,:])
plt.plot(t,y[n_trial,:])"Neuron A", "Neuron B", "Field"]); plt.legend([
Compute the average rate of each neuron
= np.mean(sum(A,1)/t[-1])
rateA = np.mean(sum(B,1)/t[-1])
rateB
print("A(Rate) = ", rateA, ", B(Rate) = ", rateB)
Compute the spike-field coherence.
plt.clf()
= coherence(A,y,t); plt.plot(f,cohr)
[cohr, f, SYY, SNN, SYN]
= coherence(B,y,t); plt.plot(f,cohr)
[cohr, f, SYY, SNN, SYN]
0,20])
plt.xlim([0,1])
plt.ylim(['Neuron A', 'Neuron B'])
plt.legend(['Frequency [Hz]')
plt.xlabel('Coherence'); plt.ylabel(
Repeat coherence calculation for many realizations
= 2.0; coupling_A = 0.5 # Fix the rates and coupling to field for each neuron.
baseline_A = 1.0; coupling_B = 0.5
baseline_B = np.zeros([501,100])
cohr_A = np.zeros([501,100])
cohr_B for k in np.arange(100): # For 100 realizations, simulate the neurons & compute coherence.
= sim_two_neurons(baseline_A, baseline_B, coupling_A, coupling_B)
A,B,y = coherence(A,y,t); cohr_A[:,k] = cohr
[cohr, f, SYY, SNN, SYN] = coherence(B,y,t); cohr_B[:,k] = cohr [cohr, f, SYY, SNN, SYN]
# Plot the coherence results.
plt.clf()= np.mean(cohr_A,1); se = np.std( cohr_A,1)/np.sqrt(np.shape(cohr_A)[1])
mn 'b',label="Neuron A"); plt.plot(f,mn-2*se, 'b:'); plt.plot(f,mn+2*se, 'b:');
plt.plot(f,mn,= np.mean(cohr_B,1); se = np.std( cohr_B,1)/np.sqrt(np.shape(cohr_B)[1])
mn 'r',label="Neuron B"); plt.plot(f,mn-2*se, 'r:'); plt.plot(f,mn+2*se, 'r:');
plt.plot(f,mn,5,15]); plt.ylim([0,1]);
plt.xlim([
plt.legend()'Frequency [Hz]')
plt.xlabel('Coherence');
plt.ylabel('Neuron A Rate: Baseline=' + str(baseline_A) + ', Coupling=' + str(coupling_A) + '\n'
plt.title('Neuron B Rate: Baseline=' + str(baseline_B) + ', Coupling=' + str(coupling_B));