%%% Kenneth Kay %%% NS248 %%% Problem Set 11 (Continuous signals) %%% (1) %% (a) raw LFP plot((1:10000)/1500,lfpdata(1:10000),'k','linewidth',1.2) xlabel('time (s)') ylabel('LFP amplitude (uV)') %% (b) spectrum params = {}; params.Fs = 1500; params.fpass = [0 150]; params.err = 0; params.trialave = 0; [S,f] = mtspectrumc(lfpdata(1:100000),params) semilogy(f,S,'k','linewidth',1.2); xlabel('frequency (Hz)'); ylabel('PSD (uV^2/Hz)'); set(gca,'XTick',0:10:150); %% (c) there is an interesting salient peak in the 5-10 Hz band %%% (2) %% (a) 'raw' spectrogram params.tapers=[3 5] [S t f] = mtspecgramc(lfpdata(1:100000), [.5 .25], params); window imagesc(t, f, log(S')); set(gca,'YDir','normal') xlabel('time (s)') ylabel('frequency (Hz)') %% 50% overlapping %% (b) theta power and velocity %% using 0.25 s moving windows, chronux calculates spectral power in bins of %% 0.29 Hz windows (frequency resolution) %% for theta, the corresponding bins f(2:4) will report power for the band: % 5.8594-11.7188, or approximately 6-12 Hz %% let's use all the data provided, and with non-overlapping windows [S t f] = mtspecgramc(lfpdata, [.25 .25], params); thetapower = S(:,2:4); thetapower = sum(thetapower,2); figure plot(t(1:1000),thetapower(1:1000),'k','linewidth',1.2) figure %% unsmoothed, 250 ms windows % total power in both bins %% plots first 8 minutes plot(t,thetapower,'k','linewidth',1.2) %% plots all 15 minutes %% for velocity, we want to bin postimes the same way as the chronux spectrogram %% does the LFP -- that is, in 250 ms windows %% specifically, we'll take the mean of speed in 250 ms windows windowsize_sec = 0.25 ; postimes_Fs = 1/(postimes(2)-postimes(1)); windowsize_possamples = windowsize_sec*postimes_Fs; firstindex=1; speed_in_windows = nan(1,length(t)-20); %% truncate last 20 windows for i=1:length(speed_in_windows) velocity = mean(abs(speed(floor(firstindex):floor((firstindex+windowsize_possamples))))); speed_in_windows(i)=velocity; firstindex = firstindex+windowsize_possamples; end figure plotyy((1:1000)/4,thetapower(1:1000),(1:1000)/4,speed_in_windows(1:1000)) xlabel('time (s)') ylabel('theta power (uV^2)') scatter(thetapower(1:(end-20)),speed_in_windows,'k','.'); xlabel('theta power (uV^2)') ylabel('mean velocity') figure scatter(thetapower(1:(end-20)),speed_in_windows,'k','.'); xlabel('theta power (uV^2)') ylabel('mean velocity') set(gca,'xscale','log') % linear scale % log scale [R,P,RLO,RUP]=corrcoef(thetapower(1:(end-20)),speed_in_windows); relationship %% assumes linear % yields R=-0.0869, p=1.79e-07 -- there seems to be a highly significant % weak negative correlation %%%% (3) %% (a) You can readily specify the amount of attenuation or amplification %% at the various stopbands and passbands. %% (b) In general, higher levels of attenuation/amplification tend to increase the %% order of the filter. %% (c) Tighter bandpass filters require higher order filters. %%%% (4) %% (a) %% matlab 'filter' filtered_data = []; filtered_data = filter(thetafilter.tf.num,thetafilter.tf.den,lfpdata); plot((1:4500)/1500,filtered_data(1:4500),'r','linewidth',1.2); xlabel('time (s)') ylabel('LFP (uV)') hold on plot((1:4500)/1500,lfpdata(1:4500),'k','linewidth',1); %% poor match -- the filter has shifted the phase of the theta %% frequency component, resulting in huge mismatch from the %% original signal (which has lots of theta) %% the beginning of trace is very noticeably mismatched %% matlab 'filtfilt' figure filtered_data = []; filtered_data = filtfilt(thetafilter.tf.num,thetafilter.tf.den,lfpdata); plot((1:4500)/1500,filtered_data(1:4500),'r','linewidth',1.2); xlabel('time (s)') ylabel('LFP (uV)') hold on plot((1:4500)/1500,lfpdata(1:4500),'k','linewidth',1); %% the phases now appear to match %%%% (5) %% (a) hilbert_data = hilbert(filtered_data); hilbert_envelope = abs(hilbert_data); figure hold on plot((1:4500)/1500,hilbert_envelope(1:4500),'b','linewidth',1.2); plot((1:4500)/1500,-hilbert_envelope(1:4500),'b','linewidth',1.2); plot((1:4500)/1500,filtered_data(1:4500),'k','linewidth',1); xlabel('time (s)') ylabel('LFP (uV)') %% amplitude looks correct %% (b) figure hold on plotyy((3500:4500)/1500,angle(hilbert_data(3500:4500)), ... (3500:4500)/1500,filtered_data(3500:4500)); xlabel('time (s)') ylabel('LFP (uV)') %% phase looks correct %% (c) phase histogram %% preliminary function findindex, since spiketimes values aren't corresponding %% exactly to lfptimes... : % % function output = findindex(v,value); % % % % % this function returns the index of vector v closest to value % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % v is assumed to be sorted in increasing order % rounds upwards by default greater_than = v>=value; less_than = v<=value; test=greater_than.*less_than; if sum(test) == 1 %% value is already in v output=find(test); elseif prod(double(less_than ~= greater_than))==1 %% value is between two elements greaterindex = find(greater_than,1); lessindex = greaterindex-1; if abs(value-v(lessindex)) < abs(v(greaterindex)-value) output = lessindex; else output = greaterindex; end else disp('value not contained within vector'); end end hilbert_phases = angle(hilbert_data); spike_phases = nan(1,length(spiketimes)); %% initialize for s=1:length(spiketimes) spike_phases(s) = hilbert_phases(findindex(lfptimes,spiketimes(s))); end hist(spike_phases,20) xlabel('phase (rads)') ylabel('# spikes') %% (d) spike-triggered LFP averages windowsize = 1; windowsize_samp = 1500; eegwindows = nan(length(spiketimes),windowsize_samp*2+1); for s=1:length(spiketimes) centerindex = findindex(lfptimes,spiketimes(s)); eegwindows(s,:) = lfpdata((centerindexwindowsize_samp):(centerindex+windowsize_samp)); end STA = mean(eegwindows,1); plot((-1500:1500),STA,'k','linewidth',1.5); xlabel('time (s)') ylabel('LFP amplitude (uV)') %% spike-triggered average indicates an increase in theta is %% strongly associated with spikes %% (e) phase precession %% we already have spike_phases, now do the same for position: spike_positions = nan(1,length(spiketimes)); %% initialize for s=10:length(spiketimes) spike_positions(s) = pos(findindex(postimes,spiketimes(s))); end scatter(spike_positions,spike_phases,'.','k') %% there appears to be a weak negative correlation between position and %% phase at several positions (one near 0 position, and one near 110 cm) %% (f) directional effect %% conveniently the speed data is actually velocity, thus we can use the %% sign of the speed data to distinguish trial direction spikes_LR = [] spikes_RL = [] ; ; % let positions occupy 1st column, and phases the 2nd for s=10:length(spiketimes) dir = sign(speed(findindex(postimes,spiketimes(s)))); if dir==1 %% LR spikes_LR = [spikes_LR ; [pos(findindex(postimes,spiketimes(s))) ... hilbert_phases(findindex(lfptimes,spiketimes(s)))] ]; else %% RL spikes_RL = [spikes_RL ; [pos(findindex(postimes,spiketimes(s))) ... hilbert_phases(findindex(lfptimes,spiketimes(s)))] ]; end end figure scatter(spikes_LR(:,1),spikes_LR(:,2),'.','k') title('right to left trials') xlabel('linear position (cm)') ylabel('theta phase (rads)') figure scatter(spikes_RL(:,1),spikes_RL(:,2),'.','k') title('left to left trials') xlabel('linear position (cm)') ylabel('theta phase (rads)')