Weakly coupled oscillators tutorial
We demonstrate how to simulate weakly coupled oscillators with and without noise and utilize the toolbox functions to estimate synchronization measure estimates from noisy data. We then compare PLV and coherence estimates with approximation of actual phase locking.
Initialization
snr2 =1000;
trial_num=100;
coupling2 =0.75;
detuning=3;
centerfreq=40;
triallength=1;
scale_noise =0;
snrs=0;
mfr= centerfreq; %main frequency of the first oscillator
snr= snr2;
snrs= snrs+1;
freqlin= mfr-detuning; % frequency of the second oscillator
nn=0;
ffr= freqlin;
nn=nn+1;
trt=0;
Generate data with and without noise (from simulation of osc)
for trial=1:trial_num
number_of_nodes=2; % Two oscillators
initial_phase= [ randn(11)*2 randn(11)*2]; % Randomize initial phases
tim_sec=triallength;
time_steps=tim_sec+2; % The two extra seconds is due to transient dynamics at the beginning
dt=0.001; % step size (here 1ms)
phases = zeros(number_of_nodes,time_steps./dt);
phases(1:2,1)= initial_phase(1:number_of_nodes,1).*1;
clear noiseterm
for ind=1:2
noiseterm(ind,:)=powernoise(1,(time_steps./dt)+1,'normalize').*scale_noise;
end
f2=0;
freqs2= ffr;
f2=f2+1;
cops=0;
coupling= coupling2;
cops=cops+1;
K= [ coupling coupling];%coupling matrix (here symmetric)
W= [ mfr freqs2];
W=W.*(2*pi); %radians per sec
K=K.*(2*pi); %scaling of coupling
for time=2:time_steps./dt %%% SIMULATION of the phase-oscillators
for ind=1:number_of_nodes
phases(ind,time)= phases(ind,time-1) + (dt*(W(ind))+ sum(dt.*K(:,ind).* -(sin((phases(ind,time-1) -phases(:,time-1)))) ) )+ noiseterm(ind,time-1) ;
end
end
ph= (mod(phases',2*pi))';
xx=(exp(1i*(ph(:,1:1:end)))');
% noise
noiseterm=randn(2,time_steps*1000).*((tim_sec*1000)/(2*sqrt(tim_sec*1000))); % white noise properly scaled
trials{trial} = ((real(xx)'))+((noiseterm).* 1./sqrt(snr)); %creating composite signal
true_inst_ph{trial} =ph(:,2001:end);
times{trial}=0.001:0.001:time_steps*1;
trials{trial} = trials{trial}(:,2001:end); % ecluding the first seconds
times{trial}=times{trial}(:,2001:end);
xx2=(exp(1i*( angle(exp(1i*ph(1,2001:1:end))./exp(1i*ph(2,2001:1:end))) ))');
% computation of phase dif on noisefree signal
trialx(:,trial)=((xx2));
disp(num2str(trial))
end
Actual Phase locking (approximation of theoretical value - noise free case)
allcoh2(nn,snrs)=abs(mean(trialx(:))); %% Approx. 'True value', here numerically estimated (but very close to analytically derived ones)
SNR(nn,snrs)=snr;%(1/snr).^2;
Expected_Phase_locking = allcoh2;
Spectral Coherence estimate
X = [];
Y = [];
for trial = 1:trial_num
X = [X; trials{trial}(1,:)];
Y = [Y; trials{trial}(2,:)];
end
[parameters,data] = timeseriesCoherence(X, Y);
Coh = parameters.Coh_estimate;
Phase locking value (PLV) estimation
X1 = trials{1}(1,:);
Y1 = trials{1}(2,:);
[parameters, data]=timeseriesPLV(X1,Y1);
PLV = parameters.PLV_estimate;
Value comparison
>> Expected_Phase_locking, PLV, Coh
Expected_Phase_locking =
0.2978
PLV =
0.2282
Coh =
0.9396
Transfer Entropy (TE) estimation (Rank method - simple binning)
t=2; w=2; % time lag
l=1; k=1; % block lengths
[parameters, data] = timeseriesTE_rank(X1,Y1,l,k,t,w,128);
TE = parameters.TE_estimate;
References:
[1] Lowet, E., Roberts, M. J., Bonizzi, P., Karel, J., & De Weerd, P. (2016). Quantifying neural oscillatory synchronization: a comparison between spectral coherence and phase-locking value approaches. PloS one, 11(1)