|
@@ -0,0 +1,179 @@
|
|
|
+clear all;
|
|
|
+close all;
|
|
|
+clc;
|
|
|
+
|
|
|
+%% LFP EXTRACTION SETTINGS
|
|
|
+% Time periods to extract from the data
|
|
|
+LFP_START_TIME = -1100;
|
|
|
+LFP_END_TIME = 1100;
|
|
|
+% Account for delays between NLX events and actual visual presentations.
|
|
|
+%STIM_DELAY = 30.5 * 10^3;
|
|
|
+SelectedChannels=[1:16];
|
|
|
+NumOfChs=length(SelectedChannels);
|
|
|
+
|
|
|
+%% LFP GENERATION SETTINGS
|
|
|
+lfpNumSamples = ceil((LFP_END_TIME - LFP_START_TIME));
|
|
|
+LfpTimestamps = linspace(LFP_START_TIME, LFP_END_TIME, lfpNumSamples);
|
|
|
+
|
|
|
+% Main Peaks
|
|
|
+PeaksLocations=[7 8 3 2 4 11]; % channel number where you expect to find peak
|
|
|
+PeaksAmplitudes=[-13 -11 40 28 32 -8]; % signal peak amplitude (not visible in z-scored plots)
|
|
|
+PeaksDelays=[50 45 65 55 70 59]; % [ms] where you expect to find peaks
|
|
|
+PeaksDurations=[10 4 12 8 4 8];
|
|
|
+% Side Peaks Randomly set
|
|
|
+SidePeaksAmplitudeStDev=2; % Std Dev of integer (positive/negative) non-zero values
|
|
|
+SidePeaksMaxDelays=900; % Support of integer random shift (ranging from 0 to MaxDelays)
|
|
|
+SidePeaksDurations=4*ones(1,NumOfChs); % Duration of side peaks
|
|
|
+% Additive White Gaussian Noise Power set accordingly to
|
|
|
+AverageSNR=10^(25/10); % Average SNR you expect to see
|
|
|
+NumOfTrials=1e2;
|
|
|
+
|
|
|
+%% CSD EXTRACTION SETTINGS
|
|
|
+CSD_START_BASELINE_TIME = -200;
|
|
|
+CSD_END_BASELINE_TIME = 30;
|
|
|
+CSD_START_TIME = 0;
|
|
|
+CSD_END_TIME = 150;
|
|
|
+
|
|
|
+%% CSD GENERATION SETTINGS
|
|
|
+contactSpacing=1.5e-4;
|
|
|
+contactPositions = (1:NumOfChs).*contactSpacing;
|
|
|
+conductance = 0.4; % Taken from Logothetis NK, Kayser C, Oeltermann A. In vivo measurement of cortical impedance spectrum in monkeys: implications for signal propagation. Neuron 55: 809?823, 2007.
|
|
|
+diameter = 10e-4; % Taken from Mountcastle 1957
|
|
|
+filterRange = 5e-4; % Taken from Petterson et al Journal of Neurosci Methods 2006
|
|
|
+gaussSigma = 1e-4; % Taken from Petterson et al Journal of Neurosci Methods 2006
|
|
|
+
|
|
|
+csdStartIndex = find(LfpTimestamps >= CSD_START_TIME, 1, 'first');
|
|
|
+csdEndIndex = find(LfpTimestamps >= CSD_END_TIME, 1, 'first');
|
|
|
+csdZeroIndex = find(LfpTimestamps >= 0, 1, 'first');
|
|
|
+CSDNumTimeSamples = csdEndIndex - csdStartIndex + 1;
|
|
|
+CSDTimestamps = linspace(CSD_START_TIME, CSD_END_TIME, CSDNumTimeSamples);
|
|
|
+
|
|
|
+csdStartBaselineIndex = find(LfpTimestamps >= CSD_START_BASELINE_TIME, 1, 'first');
|
|
|
+csdEndBaselineIndex = find(LfpTimestamps >= CSD_END_BASELINE_TIME, 1, 'first');
|
|
|
+
|
|
|
+
|
|
|
+%% GENERATING SYNTHETIC LFPs
|
|
|
+
|
|
|
+
|
|
|
+LfpMat = zeros(NumOfChs, NumOfTrials, lfpNumSamples);
|
|
|
+
|
|
|
+% Generate Clean Signal
|
|
|
+%KernelSignal=1/sqrt(2*pi*PeakDuration^2)*exp(-(LfpTimestamps-PeakDelay).^2/(2*PeakDuration^2));
|
|
|
+PeaksDurationsVec=SidePeaksDurations;
|
|
|
+PeaksDurationsVec(PeaksLocations)=PeaksDurations;
|
|
|
+CleanSignal=exp(-bsxfun(@rdivide, (LfpTimestamps).^2,(2*PeaksDurationsVec.^2)'));
|
|
|
+
|
|
|
+for tr=1:NumOfTrials
|
|
|
+
|
|
|
+ % Randomly Modulate Side Peaks
|
|
|
+ % PeakAmps=randi(SidePeaksAmplitude,1,NumOfChs);
|
|
|
+ PeakAmps=zeros(1,NumOfChs);
|
|
|
+ while ~isempty(find(PeakAmps==0,1))
|
|
|
+ Ppos=find(PeakAmps==0,1);
|
|
|
+ PeakAmps(Ppos)=ceil(SidePeaksAmplitudeStDev*randn);
|
|
|
+ end
|
|
|
+ PeakAmps(PeaksLocations)=PeaksAmplitudes;
|
|
|
+ ModulatedSignal=diag(PeakAmps)*CleanSignal;
|
|
|
+
|
|
|
+ TimeShiftedSignal=ModulatedSignal;
|
|
|
+ % Delay the peaks
|
|
|
+ for ch=PeaksLocations
|
|
|
+ TimeShiftedSignal(ch,:)=circshift(ModulatedSignal(ch,:),[1 PeaksDelays(PeaksLocations==ch)]);
|
|
|
+ end
|
|
|
+
|
|
|
+ % Randomly Scramble the timing of Side Peaks
|
|
|
+ SidePeaksToRandomlyShift=1:NumOfChs;
|
|
|
+ SidePeaksToRandomlyShift(PeaksLocations)=[];
|
|
|
+ for ch=SidePeaksToRandomlyShift;
|
|
|
+ TimeShiftedSignal(ch,:)=circshift(ModulatedSignal(ch,:),[1 randi(SidePeaksMaxDelays)]);
|
|
|
+ end
|
|
|
+
|
|
|
+ % Add NOISE with same SNR for all channels, wrt their signal power
|
|
|
+ SigPow=sum(abs(TimeShiftedSignal).^2,2);
|
|
|
+ LfpNoise=diag(sqrt(SigPow/AverageSNR*1/lfpNumSamples))*randn(NumOfChs,lfpNumSamples);
|
|
|
+ NoisePow=sum(abs(LfpNoise).^2,2);
|
|
|
+ % Uncomment to check that average SNR is properly set
|
|
|
+ % EmpiricalSNR(:,tr,:)=SigPow./NoisePow;
|
|
|
+ LfpMat(:,tr,:)=TimeShiftedSignal+LfpNoise;
|
|
|
+end
|
|
|
+
|
|
|
+
|
|
|
+%% COMPUTE LFP TRIAL AVERAGE
|
|
|
+
|
|
|
+ LfpTimestampsCsdTimeWindow=LfpTimestamps(csdStartIndex:csdEndIndex);
|
|
|
+
|
|
|
+ TotalBaseline=mean(LfpMat(:,:,csdStartBaselineIndex:csdEndBaselineIndex),3);
|
|
|
+ LfpMinusBaseline=LfpMat(:,:,csdStartBaselineIndex:csdEndBaselineIndex)-repmat(TotalBaseline,1,1,length(csdStartBaselineIndex:csdEndBaselineIndex));
|
|
|
+ TotalStdDev=std(LfpMinusBaseline,0,3);
|
|
|
+ DivStdDevMinusBaseline=(LfpMat(:,:,csdStartIndex:csdEndIndex)-repmat(TotalBaseline,1,1,CSDNumTimeSamples))./repmat(TotalStdDev+eps,1,1,CSDNumTimeSamples);
|
|
|
+ LfpTrialAvgCsdTimeWindow=squeeze(mean(DivStdDevMinusBaseline,2));
|
|
|
+ % Uncomment to see the true trial average signal non z-scored
|
|
|
+ % LfpTrialAvgCsdTimeWindow=squeeze(mean(LfpMat(:,:,csdStartIndex:csdEndIndex),2));
|
|
|
+
|
|
|
+ EnergiesVec=sum(abs(LfpTrialAvgCsdTimeWindow),2);
|
|
|
+ ScaleFactorsVec=max(EnergiesVec)./EnergiesVec;
|
|
|
+
|
|
|
+ LfpTrialAvgCsdTimeWindowNormalized=diag(ScaleFactorsVec)*LfpTrialAvgCsdTimeWindow;
|
|
|
+
|
|
|
+ hFig4=figure('visible','on');
|
|
|
+ set(hFig4, 'Position', [0 0 1000 750]); cmp=jet(16);
|
|
|
+ for chf=1:16; subplot(2,2,1); plot(LfpTimestampsCsdTimeWindow,LfpTrialAvgCsdTimeWindow(chf,:),'Color',cmp(chf,:)); hold on; end;
|
|
|
+ axFig4=gca; axFig4.FontSize=8; axFig4.TickLabelInterpreter='latex'; %axFig4.Color=.3*ones(1,3); axFig4.GridColor=.7*ones(1,3);
|
|
|
+ xlabel('Time aligned to stimulus onset [ms]','Interpreter','latex'); grid on; grid minor;
|
|
|
+ xlim([LfpTimestampsCsdTimeWindow(1) LfpTimestampsCsdTimeWindow(end)]);
|
|
|
+ legend(arrayfun(@(x) num2str(x,'ch %.0f'),1:length(SelectedChannels),'unif',0),'Position',axFig4.Position*[1 0 1 0; 0 1 0 0; 0 0 0 0; 0 0 0 1]'+[0.032 0 0.01 0],'interpreter','latex');
|
|
|
+ title('Baseline z-scored LFPs','Interpreter','latex');
|
|
|
+
|
|
|
+ for chf=1:16; subplot(2,2,2); plot(LfpTimestampsCsdTimeWindow,LfpTrialAvgCsdTimeWindowNormalized(chf,:),'Color',cmp(chf,:)); hold on; end;
|
|
|
+ axFig4=gca; axFig4.FontSize=8; axFig4.TickLabelInterpreter='latex'; %axFig4.Color=.3*ones(1,3); axFig4.GridColor=.7*ones(1,3);
|
|
|
+ xlabel('Time aligned to stimulus onset [ms]','Interpreter','latex'); grid on; grid minor;
|
|
|
+ xlim([LfpTimestampsCsdTimeWindow(1) LfpTimestampsCsdTimeWindow(end)]);
|
|
|
+ legend(arrayfun(@(x) num2str(x,'ch %.0f'),1:length(SelectedChannels),'unif',0),'Position',axFig4.Position*[1 0 1 0; 0 1 0 0; 0 0 0 0; 0 0 0 1]'+[0.032 0 0.01 0],'interpreter','latex');
|
|
|
+ title('Energy Normalized LFPs','Interpreter','latex');
|
|
|
+
|
|
|
+
|
|
|
+%% COMPUTE CSD
|
|
|
+
|
|
|
+ CSDNumSpaceSamples=2e2;
|
|
|
+ [iCSDSamples,iCSDPositions]=computeiCSDCubicSplines(LfpTrialAvgCsdTimeWindow,contactPositions,conductance,diameter,CSDNumSpaceSamples);
|
|
|
+
|
|
|
+ [iCSDSamplesNormalized,iCSDPositions]=computeiCSDCubicSplines(LfpTrialAvgCsdTimeWindowNormalized,contactPositions,conductance,diameter,CSDNumSpaceSamples);
|
|
|
+
|
|
|
+
|
|
|
+ set(0, 'currentfigure', hFig4); subplot(2,2,3);
|
|
|
+ surf(repmat(CSDTimestamps,length(iCSDPositions),1),repmat(iCSDPositions'*1e3,1,CSDNumTimeSamples),iCSDSamples*1e-3,'EdgeColor','none'); view(2);
|
|
|
+ axis([CSDTimestamps(1) CSDTimestamps(end) iCSDPositions(1)*1e3 iCSDPositions(end)*1e3]);
|
|
|
+ xlabel('Time aligned to stimulus onset [ms]','Interpreter','latex'); ylabel('Distance from the tip [mm]','Interpreter','Latex');
|
|
|
+ axFig4=gca; axFig4.YTick=(contactPositions)*1e3;
|
|
|
+ colormap(flipud(jet(256))); colorbar('fontsize',7,'Position',axFig4.Position*[1 0 1 0; 0 1 0 0; 0 0 0 0; 0 0 0 1]'+[0.032 0 0.01 0]);
|
|
|
+ axFig4.YTickLabel=arrayfun(@(x) num2str(x,'%.2f'),contactPositions*1e3,'unif',0);
|
|
|
+ yyaxis right; axFig4r=gca; axFig4r.YColor='k';
|
|
|
+ axFig4r.YLim=[iCSDPositions(1) iCSDPositions(end)]*1e3; axFig4r.YTick=(contactPositions)*1e3;
|
|
|
+ axFig4r.YTickLabel=arrayfun(@(x) num2str(x,'%.0f'),1:length(SelectedChannels),'unif',0);
|
|
|
+ aylp=axFig4r.YLabel.Position; ylabel('Channel Number','Rotation',270,'Interpreter','latex','Position',aylp);
|
|
|
+ axFig4r.TickLabelInterpreter='latex'; axFig4.FontSize=8;
|
|
|
+ yyaxis left;
|
|
|
+ title(['Energy Normalized iCSD [$\mu$A/mm$^3$]'] ,'Interpreter','latex');
|
|
|
+
|
|
|
+
|
|
|
+ set(0, 'currentfigure', hFig4); subplot(2,2,4);
|
|
|
+ surf(repmat(CSDTimestamps,length(iCSDPositions),1),repmat(iCSDPositions'*1e3,1,CSDNumTimeSamples),iCSDSamplesNormalized*1e-3,'EdgeColor','none'); view(2);
|
|
|
+ axis([CSDTimestamps(1) CSDTimestamps(end) iCSDPositions(1)*1e3 iCSDPositions(end)*1e3]);
|
|
|
+ xlabel('Time aligned to stimulus onset [ms]','Interpreter','latex'); ylabel('Distance from the tip [mm]','Interpreter','Latex');
|
|
|
+ axFig4=gca; axFig4.YTick=(contactPositions)*1e3;
|
|
|
+ colormap(flipud(jet(256))); colorbar('fontsize',7,'Position',axFig4.Position*[1 0 1 0; 0 1 0 0; 0 0 0 0; 0 0 0 1]'+[0.032 0 0.01 0]);
|
|
|
+ axFig4.YTickLabel=arrayfun(@(x) num2str(x,'%.2f'),contactPositions*1e3,'unif',0);
|
|
|
+ yyaxis right; axFig4r=gca; axFig4r.YColor='k';
|
|
|
+ axFig4r.YLim=[iCSDPositions(1) iCSDPositions(end)]*1e3; axFig4r.YTick=(contactPositions)*1e3;
|
|
|
+ axFig4r.YTickLabel=arrayfun(@(x) num2str(x,'%.0f'),1:length(SelectedChannels),'unif',0);
|
|
|
+ aylp=axFig4r.YLabel.Position; ylabel('Channel Number','Rotation',270,'Interpreter','latex','Position',aylp);
|
|
|
+ axFig4r.TickLabelInterpreter='latex'; axFig4.FontSize=8;
|
|
|
+ yyaxis left;
|
|
|
+ title(['Energy Normalized iCSD [$\mu$A/mm$^3$]'] ,'Interpreter','latex');
|
|
|
+
|
|
|
+ ha = axes('Position',[0 0 1 1],'Xlim',[0 1],'Ylim',[0 1],'Box','off','Visible','off','Units','normalized', 'clipping' , 'off');
|
|
|
+ text(0.5,.98,['LFP/CSD Cortex Visualization'],'HorizontalAlignment','center','VerticalAlignment','top','Interpreter','latex');
|
|
|
+ editedFF='./V1 Jones/Spline iCSD Monitor/Minus Baseline Divided StDev Energy Norm/Comparison/';
|
|
|
+ hFig4.InvertHardcopy='off';
|
|
|
+ saveas(hFig4, ['PLOT_iCSD.png']);
|
|
|
+ saveas(hFig4, ['PLOT_iCSD.fig']);
|