diff --git a/GraphicsPlotting/BreakPlot.asv b/GraphicsPlotting/BreakPlot.asv deleted file mode 100644 index 9764427..0000000 --- a/GraphicsPlotting/BreakPlot.asv +++ /dev/null @@ -1,198 +0,0 @@ -function h=BreakPlot(y_break_start,y_break_end,break_type,axes_handle) -% BreakPlot(x,y,y_break_start,y_break_end,break_type) -% Produces a plot who's y-axis skips to avoid unecessary blank space -%axis_handle is obtained by get(gca). -% -% INPUT -% axes handle -% y_break_start -% y_break_end -% break_type -% if break_type='RPatch' the plot will look torn -% in the broken space -% if break_type='Patch' the plot will have a more -% regular, zig-zag tear -% if break_plot='Line' the plot will merely have -% some hash marks on the y-axis to denote the -% break - -y_break_mid=(y_break_end-y_break_start)./2+y_break_start; - -%Get data from plot -h=get(axes_handle); -a=h.Children; -b=get(a); -x=b.XData; -y=b.YData; - -% leave room for the y_break_end -[junk,i]=min(y>=y_break_end); -if i>y_break_end - x=[x(1:i-1) NaN x(i:end)]; - y=[y(1:i-1) y_break_mid y(i:end)]; -end; - -% remap -y2=y; -y2(y2>=y_break_end)=y2(y2>=y_break_end)-y_break_mid; - -% plot -h=plot(x,y2,'.'); - -% make break -xlim=get(gca,'xlim'); -ytick=get(gca,'YTick'); -[junk,i]=min(ytick<=y_break_start); -y=(ytick(i)-ytick(i-1))./2+ytick(i-1); -dy=(ytick(2)-ytick(1))./10; -xtick=get(gca,'XTick'); -x=xtick(1); -dx=(xtick(2)-xtick(1))./2; - -xlim=get(gca,'xlim'); -ytick=get(gca,'YTick'); -xtick=get(gca,'XTick'); -yticklabel=get(gca,'YTickLabel'); -xticklabel=get(gca,'XTickLabel'); - - - -switch break_type - case 'Patch', - % this can be vectorized - dx=(xlim(2)-xlim(1))./10; - yy=repmat([y-2.*dy y-dy],1,6); - xx=xlim(1)+dx.*[0:11]; - patch([xx(:);flipud(xx(:))], ... - [yy(:);flipud(yy(:)-2.*dy)], ... - [.8 .8 .8]) - case 'RPatch', - % this can be vectorized - dx=(xlim(2)-xlim(1))./100; - yy=y+rand(101,1).*2.*dy; - xx=xlim(1)+dx.*(0:100); - patch([xx(:);flipud(xx(:))], ... - [yy(:);flipud(yy(:)-2.*dy)], ... - [.8 .8 .8]) - case 'Line', - line([x-dx x ],[y-2.*dy y-dy ]); - line([x x+dx],[y+dy y+2.*dy]); - line([x-dx x ],[y-3.*dy y-2.*dy]); - line([x x+dx],[y+2.*dy y+3.*dy]); -end; -set(gca,'xlim',xlim); - -% map back -ytick(ytick>y_break_start)=ytick(ytick>y_break_start)+y_break_mid; -for i=1:length(ytick) - yticklabel{i}=sprintf('%d',ytick(i)); -end; -set(gca,'yticklabel',yticklabel); - -% function h=BreakPlot(x,y,y_break_start,y_break_end,break_type) -% % BreakPlot(x,y,y_break_start,y_break_end,break_type) -% % Produces a plot who's y-axis skips to avoid unecessary blank space -% % -% % INPUT -% % x -% % y -% % y_break_start -% % y_break_end -% % break_type -% % if break_type='RPatch' the plot will look torn -% % in the broken space -% % if break_type='Patch' the plot will have a more -% % regular, zig-zag tear -% % if break_plot='Line' the plot will merely have -% % some hash marks on the y-axis to denote the -% % break -% % -% % USAGE: -% % figure; -% % BreakPlot(rand(1,21),[1:10,40:50],10,40,'Line'); -% % figure; -% % BreakPlot(rand(1,21),[1:10,40:50],10,40,'Patch'); -% % figure; -% % BreakPlot(rand(1,21),[1:10,40:50],10,40,'RPatch'); -% % figure; -% % x=rand(1,21);y=[1:10,40:50]; -% % subplot(2,1,1);plot(x(y>=40),y(y>=40),'.'); -% % set(gca,'XTickLabel',[]); -% % subplot(2,1,2);plot(x(y<=20),y(y<=20),'.'); -% % -% % IT'S NOT FANCY, BUT IT WORKS. -% -% % Michael Robbins -% % robbins@bloomberg.net -% % michael.robbins@bloomberg.net -% -% % data -% if nargin<5 break_type='RPatch'; end; -% if nargin<4 y_break_end=40; end; -% if nargin<3 y_break_start=10; end; -% if nargin<2 y=[1:10,40:50]; end; -% if nargin<1 x=rand(1,21); end; -% -% -% y_break_mid=(y_break_end-y_break_start)./2+y_break_start; -% -% % erase useless data -% x(y>y_break_start & y y_break_start & y =y_break_end); -% if i>y_break_end -% x=[x(1:i-1) NaN x(i:end)]; -% y=[y(1:i-1) y_break_mid y(i:end)]; -% end; -% -% % remap -% y2=y; -% y2(y2>=y_break_end)=y2(y2>=y_break_end)-y_break_mid; -% -% % plot -% h=plot(x,y2,'.'); -% -% % make break -% xlim=get(gca,'xlim'); -% ytick=get(gca,'YTick'); -% [junk,i]=min(ytick<=y_break_start); -% y=(ytick(i)-ytick(i-1))./2+ytick(i-1); -% dy=(ytick(2)-ytick(1))./10; -% xtick=get(gca,'XTick'); -% x=xtick(1); -% dx=(xtick(2)-xtick(1))./2; -% -% switch break_type -% case 'Patch', -% % this can be vectorized -% dx=(xlim(2)-xlim(1))./10; -% yy=repmat([y-2.*dy y-dy],1,6); -% xx=xlim(1)+dx.*[0:11]; -% patch([xx(:);flipud(xx(:))], ... -% [yy(:);flipud(yy(:)-2.*dy)], ... -% [.8 .8 .8]) -% case 'RPatch', -% % this can be vectorized -% dx=(xlim(2)-xlim(1))./100; -% yy=y+rand(101,1).*2.*dy; -% xx=xlim(1)+dx.*(0:100); -% patch([xx(:);flipud(xx(:))], ... -% [yy(:);flipud(yy(:)-2.*dy)], ... -% [.8 .8 .8]) -% case 'Line', -% line([x-dx x ],[y-2.*dy y-dy ]); -% line([x x+dx],[y+dy y+2.*dy]); -% line([x-dx x ],[y-3.*dy y-2.*dy]); -% line([x x+dx],[y+2.*dy y+3.*dy]); -% end; -% set(gca,'xlim',xlim); -% -% % map back -% ytick(ytick>y_break_start)=ytick(ytick>y_break_start)+y_break_mid; -% for i=1:length(ytick) -% yticklabel{i}=sprintf('%d',ytick(i)); -% end; -% set(gca,'yticklabel',yticklabel); -% diff --git a/GraphicsPlotting/BreakPlot.m b/GraphicsPlotting/BreakPlot.m index 1de0e36..6e10c41 100644 --- a/GraphicsPlotting/BreakPlot.m +++ b/GraphicsPlotting/BreakPlot.m @@ -1,5 +1,5 @@ function h=BreakPlot(y_break_start,y_break_end,break_type,axes_handle) -% BreakPlot(x,y,y_break_start,y_break_end,break_type) +% BreakPlot(y_break_start,y_break_end,break_type) % Produces a plot who's y-axis skips to avoid unecessary blank space %axis_handle is obtained by get(gca). % diff --git a/GraphicsPlotting/DendrogramMatrix.m b/GraphicsPlotting/DendrogramMatrix.m index 8adf82e..aca159d 100644 --- a/GraphicsPlotting/DendrogramMatrix.m +++ b/GraphicsPlotting/DendrogramMatrix.m @@ -14,7 +14,7 @@ % % Recommended usage: [DC,order]=DendrogramMatrix(C); % To show matrix use : imagesc(DC); or pcolor(DC); - to show grid -function [DC,order,clusters,h,Z]=DendrogramMatrix(C,varargin) +function [DC,order,clusters,h,Z,cophenetDist]=DendrogramMatrix(C,varargin) %default options toPlotBinaryTree=0; figureHandle=[]; @@ -76,8 +76,10 @@ %calculate euclidean distance Y=pdist(C,linkMetric); Z=linkage(Y,linkMethod); -%C = cophenet(Z,Y); -%I=inconsistent(Z,4); +if nargout==6 + [~,cophenetDist] = cophenet(Z,Y); +end +%I=inconsistent(Z); if strcmp(Orientation,'right') pO1=[1 3]; diff --git a/GraphicsPlotting/colormap2D.m b/GraphicsPlotting/colormap2D.m new file mode 100644 index 0000000..bcea77d --- /dev/null +++ b/GraphicsPlotting/colormap2D.m @@ -0,0 +1,79 @@ +function [CM,CMP,h]=colormap2D(varargin) +parseObj = inputParser; +addParameter(parseObj,'nIntensities',100,@isnumeric); +addParameter(parseObj,'nColors',256,@isnumeric); +addParameter(parseObj,'blackAddition',0,@isnumeric); %adds black to top color, 0 value gives only white +addParameter(parseObj,'multiplicationFactor',8,@isnumeric);%[0-Inf] - makes rate of change stronger +addParameter(parseObj,'additionFactor',1.8,@isnumeric);%[0 1]- the higher makes changes weaker in total +addParameter(parseObj,'plotCartColorBar',1,@isnumeric);%plot a colorbar in cartesian coordinates +addParameter(parseObj,'plotPolarColorBar',1,@isnumeric);%plot a colorbar in polar coordinates +addParameter(parseObj,'plotPolarExample',0,@isnumeric);%plot a possible implementation of the color map on a polar plot +addParameter(parseObj,'inputParams',0,@isnumeric); %if 1 plots the possible inputs to the function + +parseObj.parse(varargin{:}); +par=parseObj.Results; +if parseObj.Results.inputParams + disp(par); + return; +end + +CMap=hsv(par.nColors); +cmapR_theta=repmat(CMap,[1 1 par.nIntensities]); +M=[];M(1,:,1:par.nIntensities)=(par.additionFactor+(0:(par.nIntensities-1))/par.nIntensities).^par.multiplicationFactor; + +cmapR_theta=bsxfun(@times, cmapR_theta+par.blackAddition*ones(size(cmapR_theta)),M); +cmapR_theta=(cmapR_theta-min(cmapR_theta(:))); +cmapR_theta=cmapR_theta./max((cmapR_theta(:))); +cmapR_theta=1-cmapR_theta; + +CM=permute(cmapR_theta,[1,3,2]); + +if par.plotCartColorBar + h.f=figure('Position',[200 200 100 800]); + h.h=axes; + image(CM);axis tight; + ylabel('Color'); + xlabel('Intensity') +end + +if par.plotPolarColorBar + [X,Y]=meshgrid(0.01:0.01:1,0.01:0.01:1); + X=X-0.5;Y=Y-0.5; + + [theta,rho]=cart2pol(X,Y); + normTheta=floor(1+((theta+pi)/2/pi)*(par.nColors-1)); + normRho=floor(1+(rho/0.5)*(par.nIntensities-1)); + normRho(normRho>par.nIntensities)=1; + CMP=zeros(100,100,3); + p{1}=sub2ind(size(CM),normTheta(:),normRho(:),ones(numel(normRho),1)); + p{2}=sub2ind(size(CM),normTheta(:),normRho(:),2*ones(numel(normRho),1)); + p{3}=sub2ind(size(CM),normTheta(:),normRho(:),3*ones(numel(normRho),1)); + + CMP(:)=cat(3,CM(p{1}),CM(p{2}),CM(p{3})); + + h.fP=figure('Position',[200 200 130 120]); + h.hP=axes; + image(CMP);axis tight equal off; +end + +% +if par.plotPolarExample + [nRC,~,nTC]=size(cmapR_theta); + + fP=figure('Position',[200 200 130 115]); + hP=polaraxes;colormap(hP,'hsv');hold on; + + nR=50; + nT=20; + R=1:nR; + Theta=1:nT; + + for i=1:nR + for j=1:nT + %plot(R(i),Theta(j),'.','MarkerSize',20,'Color', cmapR_theta( ceil(R(i)/nR*nRC), : , ceil(Theta(j)/nT*nTC) ) ) + polarplot(R(i)/nR*2*pi,Theta(j),'.','MarkerSize',5,'Color', cmapR_theta( ceil(R(i)/nR*nRC), : , ceil(Theta(j)/nT*nTC) ) ) + end + end + title(['Mul=' num2str(par.multiplicationFactor) ', Add=' num2str(par.additionFactor)]) + set(hP,'RTick',[]); +end diff --git a/GraphicsPlotting/myErrorBar.m b/GraphicsPlotting/myErrorBar.m index 411d397..db57bfc 100644 --- a/GraphicsPlotting/myErrorBar.m +++ b/GraphicsPlotting/myErrorBar.m @@ -1,4 +1,4 @@ -function [h,hE,hB]=myErrorBar(x,y,dy,width,varargin); +function [h,hE,hB]=myErrorBar(x,y,dy,width,varargin) %[hE,hB]=myErrorBar(x,y,dy,width,varargin) %width [0-1] - the width in normalize units of the relative fraction of the bar (e.g. width=1 -> error bar in size of bar), leave empty [] if needed. %[h,hE,hB]=myErrorBar(1:8,Int,Int+IntStd,0.4,'Bfacecolor',[0.3 0.3 0.3],'BLinewidth',5,'Ecolor','k'); @@ -76,7 +76,7 @@ %update axis arguments set(h,'xtick',x); -set(h,axisVarArgIn{:}); +axes(h,axisVarArgIn{:}); diff --git a/GraphicsPlotting/tmp2.m b/GraphicsPlotting/tmp2.m new file mode 100644 index 0000000..d5a9b10 --- /dev/null +++ b/GraphicsPlotting/tmp2.m @@ -0,0 +1,6 @@ +121.5 35 151.5 65 +left 2 right + +ballCoordinates + +[0 0 143 100] \ No newline at end of file diff --git a/dataAnalysisObjects/@MEAAnalysis/._MEAAnalysis.m b/dataAnalysisObjects/@MEAAnalysis/._MEAAnalysis.m deleted file mode 100644 index c8a8fa8..0000000 Binary files a/dataAnalysisObjects/@MEAAnalysis/._MEAAnalysis.m and /dev/null differ diff --git a/dataAnalysisObjects/@MEAAnalysis/MEAAnalysis.m b/dataAnalysisObjects/@MEAAnalysis/MEAAnalysis.m deleted file mode 100644 index b111971..0000000 --- a/dataAnalysisObjects/@MEAAnalysis/MEAAnalysis.m +++ /dev/null @@ -1,1041 +0,0 @@ -classdef MEAAnalysis < recAnalysis - - properties - currentMEAFiles - currentMEADir - gridSorterFolder - VST %visual stimulation parameters table - end - - properties (Constant) - end - - methods - - [data]=getSpikePositionEstimation(obj,varargin); - [data]=getSpikeInducedFields(obj,varargin); - [data,hand]=getCrossCorr(obj,varargin); - [data,hand]=getSpikeParams(obj,varargin); - - [hand,out]=plotSpikeInducedFields(obj,varargin); - [hand,out]=plotAvgSIFMap(obj,varargin); - [hand,out]=plotSIFPerNeuron(obj,varargin); - - %% MEAAnalysis - class constructor - function [obj]=MEAAnalysis(xlsFile) - if nargin==0 - xlsFile=[]; - end - obj=obj@recAnalysis(xlsFile); - end - - %% populate gridSorter object - function [obj,flag]=populateGridSorterObj(obj,gridSorterObj) - if ~isempty(obj.gridSorterObj) - disp('gridSorter object already exists'); - flag=1; - return; - end - if nargin==1 - obj.gridSorterObj=gridSorter(obj.currentDataObj); - elseif nargin==2 - obj.gridSorterObj=gridSorterObj; - end - [obj.gridSorterObj,flag]=obj.gridSorterObj.loadMetaData; - end - - - %% getVStimParams - still under development - function [obj,VST]=getVStimParams(obj,VSFile) - %extract the visual stimulation parameters from parameter file - nParentFolders2Check=2; - folderFound=false; - if nargin==1 - %find visual stimulation folder - if ~exist([obj.currentExpFolder filesep 'visualStimulation'],'dir') %check if not in the current data folder - %go one folder back and look for visualStimulation folder - fileSepTransitions=regexp(obj.currentExpFolder,filesep); %look for file separation transitions - if fileSepTransitions(end)==numel(obj.currentExpFolder) %if last transition appears in the end of the folder remove this transition - fileSepTransitions(end)=[]; - end - for i=1:nParentFolders2Check - tmpCurrentFolder=obj.currentExpFolder(1:fileSepTransitions(end)); - %check parent folder for visual stimulation folder - if exist([tmpCurrentFolder filesep 'visualStimulation'],'dir') - VSFileLocation=[tmpCurrentFolder filesep 'visualStimulation']; - folderFound=true; - end - fileSepTransitions(end)=[]; - end - if ~folderFound - error('Visual stimulation folder was not found!!! Notice the the name of the folder should be visualStimulation'); - end - else - VSFileLocation=[obj.currentExpFolder filesep 'visualStimulation']; - end - fprintf('Visual stimulation folder set as:\n %s\n',VSFileLocation); - %find visual stimulation file according to recording file name - VSFile=dir([VSFileLocation filesep '*.mat']); - dateNumber=datenum({VSFile.date},'dd-mmm-yyyy HH:MM:SS'); - VSFile={VSFile.name}; %do not switch with line above - - tmpFileParts=strsplit(obj.currentDataFiles{1}(1:end-9),filesep); - validVSFile=[]; - for i=1:numel(VSFile) - if contains(VSFile{i}(1:end-4),tmpFileParts{end},'IgnoreCase',true) || ... - contains(tmpFileParts{end},VSFile{i}(1:end-4),'IgnoreCase',true) || ... - contains(VSFile{i}(1:end-4),tmpFileParts{end-1},'IgnoreCase',true) || ... - contains(tmpFileParts{end-1},VSFile{i}(1:end-4),'IgnoreCase',true) - validVSFile=VSFile{i}; - break; - end - end - if ~isempty(validVSFile) - VSFile=[VSFileLocation filesep validVSFile] ; - else - error(['No file with ' tmpFileParts{end} ' in its name was found , please enter specific VS filename']); - end - - elseif ~exist(VSFile,'file') - error(['Input VS file: ' VSFile ' was not found!']); - end - - % Future implementaion - if finding name strategy does not work try to find the correct file according to its save date which should correspond to recording dates - %find(dateNumber>obj.currentDataObj.startDate & dateNumber1 - VST=obj.VST; - end - end - - function data=getAI(obj,varargin) - %% parameter and settings - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'selectedChannels',obj.currentDataObj.channelNumbers,@isnumeric); - addParameter(parseObj,'stdAbsNoiseConstant',4,@isnumeric); - addParameter(parseObj,'bin_ms',2,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parAI=parseObj.Results; - - %check if analysis was already done done - obj.files.AIfile=[obj.currentAnalysisFolder filesep 'AI_' num2str(bin_ms) 'ms_' num2str(stdAbsNoiseConstant) 'std.mat']; - if exist(obj.files.AIfile,'file') & ~overwrite - if nargout==1 - data=load(obj.files.AIfile); - else - disp('AI file already exists'); - end - return; - end - - [IA,tA,icA]=mcdIntensityExtractorUnfiltered(obj.currentDataObj,'Bin_ms',bin_ms,'SelectedChannels',selectedChannels,'StdAbsNoiseConstant',stdAbsNoiseConstant); - - save(obj.files.AIfile,'IA','tA','icA','parAI','-v7.3'); - end - - function obj=getKiloSorting(obj,varargin) - if ~strcmp(class(obj.currentDataObj),'binaryRecording') - fprintf('\nKilo-sort only runs on binaryData class!!!\nYou can use the dataRecording.export2Binary method to convert to this format\n'); - return; - end - if exist('make_eMouseData_drift', 'file')==0 - fprintf('\nKilo-sort is not on the Matlab path, please add to path and run again!!!'); - return; -% else -% fprintf('\nKilo-sort not on path, trying to find it...'); -% NSKToolboxDir=fileparts(which('identifierOfMainDir4NSKToolBox')); -% -% tmp = strsplit(NSKToolboxDir, filesep); -% matlabFunctionsDir = strjoin(tmp(1:end-1),filesep); -% if exist([matlabFunctionsDir filesep 'spikeSorting'],'dir') -% addpath(genpath([matlabFunctionsDir filesep 'spikeSorting' filesep 'kiloSort2'])); -% fprintf('\nPath added successfully.\n'); -% else -% fprintf('Did not find kilosort path!\nPlease add manually\n'); -% end - end - - nCh=numel(obj.currentDataObj.channelNumbers); - NT=64+2^round(log2(1024*(128/nCh)))*1024; - - % Run the configuration file, it builds the structure of options (ops) - ops=makeConfigKiloSort2(obj.currentDataObj.recordingDir,nCh,... - 'GPU',1,'parfor',1,'NT',NT,'fbinary',[obj.currentDataObj.recordingDir filesep obj.currentDataObj.dataFileNames{1}],... - 'fs',obj.currentDataObj.samplingFrequency); - - layoutName=[obj.currentDataObj.layoutName '_JRC.prb']; - resultsFileName=[obj.currentDataObj.recordingDir filesep obj.currentDataObj.recordingName '_' obj.currentDataObj.layoutName '_JRC_ksort.mat']; - tic; %this is important otherwise fitTemplates crashes since it includes a toc without a tic - [rez, DATA] = preprocessDataSub(ops); - save(resultsFileName,'rez', 'DATA', '-v7.3'); - - rez = clusterSingleBatches(rez); - save(resultsFileName,'rez', 'DATA', '-v7.3'); - - rez = learnAndSolve8b(rez); - rez = find_merges(rez, 1); - rez = splitAllClusters(rez, 1); - rez = splitAllClusters(rez, 0); - rez = set_cutoff(rez); - save(resultsFileName,'rez', '-v7.3'); - - fprintf('Total time used for running kilo-sort was %f hours\n', toc/60/60); - delete(ops.fproc); - end - - %% getJRClust - function data=getJRClust(obj,varargin) - % getJRClust - get JRClust results from kilo sort - data=[]; - parseObj = inputParser; - addParameter(parseObj,'fullFile',[],@isnumeric); - addParameter(parseObj,'manual',0,@isnumeric); - addParameter(parseObj,'exportGS',0,@isnumeric); - addParameter(parseObj,'electrodePadSize',[26.5 26.5],@isnumeric); - - addParameter(parseObj,'saveFileName',[],@isstr); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - %displays parameters if 'inputParams' is set to true - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - par.saveFileName=obj.getFileName(dbstack,par.saveFileName); %extracts file save name - - %save/load data -% if exist(par.saveFileName,'file') & ~par.overwrite & ~par.manual & ~par.exportGS -% if nargout==1 -% data=load(par.saveFileName); -% else -% disp('JRClust sorting already exists, use overwrite=true'); -% end -% return; -% end - - if ~strcmp(class(obj.currentDataObj),'binaryRecording') - disp('JRClust only works on binaryRecording data class!!!'); - return; - end - - par.layoutName=[obj.currentDataObj.layoutName '_JRC.prb']; - recName=obj.currentDataObj.recordingName; - recDir=obj.currentDataObj.recordingDir; - if ~exist([recDir filesep par.layoutName],'file') - obj.currentDataObj.convertLayoutJRClust([sqrt(pi*15^2) sqrt(pi*15^2)]); %electrode side is sqrt(pi*15^2)=26.6; - disp('Layout converted to JRclust format'); - end - - % Build files - if isempty(par.fullFile) - par.fullFile=[recDir filesep obj.currentDataObj.dataFileNames{1}]; - end - fullProbeFile=[recDir filesep par.layoutName]; -% par.fullParamFile=[recDir filesep recName '_' par.layoutName(1:end-4) '.prm']; - par.fullParamFile=[recDir filesep recName '.prm']; - - if ~exist(par.fullParamFile,'file') - %jrc('makeprm',par.fullFile,fullProbeFile); - jrc('bootstrap',par.fullFile,fullProbeFile); - else - disp('Prm file already exist'); - end - - if ~exist([par.fullParamFile(1:end-4) '_ksort.mat'],'file') - C = strsplit(par.fullParamFile,filesep); - paramDir = fullfile(join(C(1:end-1),'/')); - resultsFileName = [obj.currentDataObj.recordingDir filesep obj.currentDataObj.recordingName '_' obj.currentDataObj.layoutName '_JRC_ksort.mat']; - load(resultsFileName, 'rez'); - if contains(paramDir{1}, 'wexac') - paramDir{1} = strrep(paramDir{1},'\','\\'); - end - rezToPhy(rez,paramDir{1}); - jrc('import-ksort',paramDir{1}); - else - disp('Data from ksort already imported'); - end - - if par.manual - disp('Deleting results file since manual mode is run again'); - jrc('manual',par.fullParamFile); - if ~exist([par.fullParamFile(1:end-4) '_gridSorter.mat'],'file') || par.exportGS - resultsFileName = [obj.currentDataObj.recordingDir filesep obj.currentDataObj.recordingName '_' obj.currentDataObj.layoutName '_JRC_ksort.mat']; - export_gridsorter2(resultsFileName); - % S=load([par.fullParamFile(1:end-4) '_gridSorter.mat']); - % save(par.saveFileName,'par','S','-v7.3'); - else - disp('Data already exported to gridSorter format, to reexport use overwrite=1'); - end - return; - end -% if par.exportGS -% export_gridS -% jrc('export-gs',par.fullParamFile); -% S=load([par.fullParamFile(1:end-4) '_gridSorter.mat']); -% save(par.saveFileName,'par','S','-v7.3'); -% end - - end - - %% getSpikeSorting - function obj=getSpikeSorting(obj,varargin) - %default parameters - parseObj = inputParser; - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - obj=obj.populateGridSorterObj; - %obj.gridSorterObj.clusteringMinSpikesTotal = 2; - %obj.gridSorterObj.clusteringMinNSpikesCluster = 1; - - if strcmp(obj.recTable.MEA_Layout,'40_Hexa') - obj.gridSorterObj.localGridSize = 9; - obj.gridSorterObj.localGridExt = 3; - - else - obj.gridSorterObj.localGridSize = 3; - obj.gridSorterObj.localGridExt = 1; - end - - if strcmp(obj.recTable.MEA_Layout,'100_9x4_FlexMEA120') - obj.gridSorterObj.filterLowPassPassCutoff=1000; - obj.gridSorterObj.filterLowPassStopCutoff=1500; - obj.gridSorterObj.detectionSpikeDetectionThresholdStd=7; - end - - if overwrite - obj.gridSorterObj.overwriteAll=1; - obj.gridSorterObj.deleteSortingFiles; - end - - obj.gridSorterFolder=obj.gridSorterObj.sortingDir; - - % Start sorting - obj.gridSorterObj=obj.gridSorterObj.runSorting; - - end %runSpikeSorting - - function data=getCSDMovie(obj,varargin) - data=[]; - - parseObj = inputParser; - addParameter(parseObj,'pot',100,@isnumeric); %the potential matrix [channels,time] - addParameter(parseObj,'electrodePitch',100,@isnumeric); - addParameter(parseObj,'frameRate',30,@isnumeric); - addParameter(parseObj,'videoQuality',90,@isnumeric); - addParameter(parseObj,'positionRealSpace',[],@isnumeric); - addParameter(parseObj,'dataType','CSD',@isnumeric);%'pot'/'CSD' - addParameter(parseObj,'electrodeMarker','.',@isnumeric); - addParameter(parseObj,'saveData',false,@isnumeric); %to only calculate CSD without making movie - addParameter(parseObj,'makeMovie',true,@isnumeric); - addParameter(parseObj,'saveFullMatrices',false,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - - %displays parameters if 'inputParams' is set to true - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - par.saveFileName=obj.getFileName(dbstack,par.saveFileName); %extracts file save name - - %save/load data - if exist(par.saveFileName,'file') & ~par.overwrite - if nargout==1 - data=load(par.saveFileName); - else - disp('CSD already exists, use overwrite=true'); - end - return; - end - - - %% - - - [nNeu,nCh,nSamples]=size(pot); - timeSamples=(1:nSamples)/Fs*1000-preMs; - spikeSample=round(preMs/1000*Fs); - - %calculate electrode positions - elecPos=NaN(nCh,3); - En2=En; - for i=1:nCh - [n,m]=find(En2==ch(i)); - if ~isempty(n) - elecPos(i,:)=[m n ch(i)]; - else - elecPos(i,:)=ch(i); - end - end - elecPos(:,1:2)=elecPos(:,1:2)*electrodePitch; - - if saveData - mkdir(dataFolder); - disp(['Data will be saved in ' dataFolder]); - end - - samplingPosX=min(elecPos(:,1)):10:max(elecPos(:,1)); - samplingPosY=min(elecPos(:,2)):10:max(elecPos(:,2)); - [XuM,YuM]=meshgrid(samplingPosX,samplingPosY); - CSD=zeros(size(WF)); - - for i=1:nNeu - mM=squeeze(WF(i,:,:)); - k = kcsd2d(elecPos(:,1:2), mM(elecPos(:,3),:), 'manage_data', 0, 'X', XuM, 'Y', YuM); - - if strcmp(dataType,'CSD') - dynamics=k.CSD_est; - elseif strcmp(dataType,'pot') - dynamics=k.pots_est; - else - error('The parameter dataType was not chosen correctly'); - end - - for j=1:nCh - [pTmpX,pTmpY]=find(XuM==elecPos(j,1) & YuM==elecPos(j,2)); - CSD(i,j,:)=dynamics(pTmpX,pTmpY,:); - end - - %[hPlot,scaleFac]=activityTracePhysicalSpacePlot([],1:120,squeeze(CSDelec(i,:,:)),En); - %[hPlot,scaleFac]=activityTracePhysicalSpacePlot([],1:120,squeeze(WF(i,:,:)),En); - if saveFullMatrices - save([dataFolder filesep 'CSD_Neuron_' num2str(neuronNames(1,i)) '-' num2str(neuronNames(2,i))],'dynamics','dataType','preMs','Fs','XuM','YuM','elecPos'); - end - - if makeMovie - mn=min(min(min(dynamics(:,:,(spikeSample+40):end),[],1),[],2),[],3); - mx=max(max(max(dynamics(:,:,(spikeSample+40):end),[],1),[],2),[],3); - l=max(abs([mn,mx])); - cLim=[-l l]; - - - writerObj = VideoWriter([dataFolder filesep dataType '_neu' num2str(neuronNames(1,i)) '_' num2str(neuronNames(2,i)) '.mp4'],'MPEG-4'); - writerObj.FrameRate=frameRate; - writerObj.Quality=videoQuality; - open(writerObj); - - F=figure('position',[50 50 550 500],'color','w');h=axes; - imagesc(XuM(1,:),YuM(:,1),squeeze(dynamics(:,:,i)),cLim);set(gca,'YDir','normal');hold on; - plot(elecPos(:,1),elecPos(:,2),'.'); - %text(elecPos(:,1),elecPos(:,2),num2str(elecPos(:,3))); - cb=colorbar; - set(cb,'position',[0.9167 0.7600 0.0117 0.1650],'Ticks',round([-l 0 l])); - cb.Label.Position=[4.2 0 0]; - ylab=ylabel(cb,dataType); - ylab.Position=[4.2 0 0]; - - xlabel('\mum'); - ylabel('\mum'); - - axis equal tight; - set(h,'nextplot','replacechildren'); - set(F,'Renderer','zbuffer'); - - if isempty(positionRealSpace) - [~,pPeak]=min(min(min(dynamics(:,:,(spikeSample-10):(spikeSample+10)),[],1),[],2),[],3); - CSDSpikePeak=squeeze(mean(dynamics(:,:,(spikeSample-10+pPeak-5):(spikeSample-10+pPeak+5)),3)); - [ySpk,xSpk] = find(CSDSpikePeak == min(min(CSDSpikePeak))); - cellBodyPos=[XuM(1,xSpk) YuM(ySpk,1)]; - else - cellBodyPos=positionRealSpace(:,i); - end - - for j=1:nSamples - tmpImg=squeeze(dynamics(:,:,j)); - - h(1)=imagesc(XuM(1,:),YuM(:,1),tmpImg,cLim);hold on; - h(2)=plot(elecPos(:,1),elecPos(:,2),electrodeMarker,'color',[0.8 0.8 0.8]); - h(3)=line([XuM(1,1) XuM(1,end)],[cellBodyPos(2) cellBodyPos(2)],'color','k'); - h(4)=line([cellBodyPos(1) cellBodyPos(1)],[YuM(1,1) YuM(end,1)],'color','k'); - - title([num2str(timeSamples(j),'% 10.1f') ' ms']); - - frame = getframe(F); - writeVideo(writerObj,frame); - delete(h); - end - close(writerObj); - close(F); - end - end - - end - - function [saveFileName,funName]=getFileName(obj,funName,saveFileName) - %Get function name and save file name, if save file name is given in input, - funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - if isempty(saveFileName) - saveFileName=obj.files.(funName); - end - end - - function [data]=getTriggeredLFP(obj,varargin) - % extract LFP from triggered traces - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'preStim',500,@isnumeric); - addParameter(parseObj,'win',5000,@isnumeric); - addParameter(parseObj,'downSamplingFactor',100,@isnumeric); - addParameter(parseObj,'trialTriggerNumber',2,@isnumeric); - addParameter(parseObj,'filterObj',[],@isnumeric); - - addParameter(parseObj,'saveFileName',[],@isstr); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - %displays parameters if 'inputParams' is set to true - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - par.saveFileName=obj.getFileName(dbstack,par.saveFileName); %extracts file save name - - %save/load data - if exist(par.saveFileName,'file') & ~par.overwrite - if nargout==1 - data=load(par.saveFileName); - else - disp('triggered LFP data already exists, use overwrite=true'); - end - return; - end - - %Get trial triggers - try - obj.checkFileRecording(obj.files.getDiodeSync,'Diode transition identification file missing, please run getDiodeSync'); - D=obj.getDiodeSync; - T=D.upCross; - disp('Times extracted from Diode signal'); - catch - obj.checkFileRecording(obj.files.getDigitalTriggers,'Digital triggers file missing, please run getDigitalTriggers'); - D=obj.getDiodeSync; - T=D.tTrig(par.trialTriggerNumber*2-1); - fprintf('Times extracted from digital signal - channel %d\n',par.trialTriggerNumber); - end - - %make decimation filter - par.samplingFrequency=obj.currentDataObj.samplingFrequency; - if isempty(filterObj) - F=filterData; - F.samplingFrequency=obj.currentDataObj.samplingFrequency; - F.downSamplingFactor=par.downSamplingFactor; - F=F.designDownSample; - end - par.FsFiltered=F.filteredSamplingFrequency; - par.downSamplingFactor=obj.currentDataObj.samplingFrequency/F.filteredSamplingFrequency; - - %determine size of filtered data matrix - nTrials=numel(T); - ch=obj.currentDataObj.channelNumbers; - nCh=numel(ch); - nSamples=(par.win)*obj.currentDataObj.samplingFrequency/1000/par.downSamplingFactor; - - %determine which chunks to take in terms of memory - userview = memory; - sizeOfMF=nCh*nTrials*(par.win/1000*obj.currentDataObj.samplingFrequency)*8; %size of the array before downsampling bytes (8 bytes / double) - trialsPerSession=min(nTrials,ceil(nTrials/(sizeOfMF*3/userview.MaxPossibleArrayBytes))); - disp('Calculating downsampled LFP traces...'); - if trialsPerSession==nTrials - %Filter all data in one shot - disp('Loading all trials - there is enough memory'); - MF=F.getFilteredData(obj.currentDataObj.getData(ch,T(1:nTrials)-par.preStim,par.win)); - else - %Filter data in chuncks - MF=zeros(nCh,nTrials,nSamples); - trialsPerSession=min(nTrials,ceil(nTrials/(sizeOfMF*4/userview.MaxPossibleArrayBytes))); %take smaller variables - for j=1:trialsPerSession:nTrials - fprintf('Analyzing trials %d-%d / %d\n',j,j+trialsPerSession-1,nTrials); - tmpTrials=j:min(nTrials,j+trialsPerSession-1); - MFtmp=F.getFilteredData(obj.currentDataObj.getData(ch,T(tmpTrials)-par.preStim,par.win)); - MF(:,tmpTrials,:)=MFtmp; - end - end - save(par.saveFileName,'MF','par','-v7.3'); - end - - %% Add binary to table after export2Binary - function obj=addBinary2Table(obj,varargin) - %After using dataRecording's export2Binary a file is created. This - %function adds the new file to the table of the MEAObject by - %copying the line of the recording file (in multiplefile mode - the - %first one) and changing the relevant fields. - % Possible varagins (given as 'Key',value pairs): - % 'updateExternalExcel' - rewrites the excel from which - % MEAAnalysis table was taken to the new table which contains - % the binary file. Default is 0. - % 'setCurrent2Bin' - after adding the line to the data - % table, also set current recording obj to be the new .bin - % file - - updateExternalExcel=0; - setCurrent2Bin=0; - - for i=1:2:numel(varargin) - eval([varargin{i} '=varargin{' num2str(i+1) '};']); - end - - newBinaryLine=obj.recTable(obj.currentPRec(1),:); - %set binaryRecordingName in the same way export2binary sets the - %name. If something changes there, it should be changed here also - if iscell(obj.currentDataObj.recordingDir) - binaryRecordingName = strjoin(cellfun(@(x) x(1:end-3), obj.currentDataObj.dataFileNames,'UniformOutput',false),'-'); - else - binaryRecordingName = obj.currentDataObj.recordingName; - end -% %Remove current extension and replace with .bin -% newFileName=split(newBinaryLine.MEAfiles,'.'); -% newFileName=join([newFileName(1:(end-1));'bin'],'.'); - newBinaryLine.MEAfiles=[binaryRecordingName '.bin']; - newBinaryLine.recNames=[binaryRecordingName '.bin']; - newBinaryLine.recFormat='binaryRecording'; - obj.recTable=[obj.recTable(1:obj.currentPRec(end),:);newBinaryLine;obj.recTable((obj.currentPRec(end)+1):end,:)]; - - if updateExternalExcel - try - writetable(obj.recTable,obj.excelRecordingDataFileName); - disp('Excel file updated!') - catch - disp('Failed to update excel file. Please update manualy') - end - end - obj.nTotalRecordings=obj.nTotalRecordings+1; - - if setCurrent2Bin - obj.setCurrentRecording(['recNames=' binaryRecordingName '.bin']); - end - - end - - - - - %% getHighSNRNeurons - function [data]=getSpikeSNR(obj,varargin) - - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'avgHPWF',[],@isnumeric); - addParameter(parseObj,'stdHPWF',[],@isnumeric); - addParameter(parseObj,'preSpikeMs',0.5,@isnumeric); - addParameter(parseObj,'postSpikeMs',2.5,@isnumeric); - addParameter(parseObj,'minDist',150,@isnumeric); - - addParameter(parseObj,'fileNameSTWaveform',[],@isstr); - addParameter(parseObj,'saveFileName',[],@isstr); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %obj.checkFileRecording(obj.files.getSpikePositionEstimation,'Single cell position estimation file missing, please run getSpikePositionEstimation'); - - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - if isempty(saveFileName) - saveFileName=obj.files.(funName); - end - - if exist(saveFileName,'file') & ~overwrite - if nargout==1 - data=load(saveFileName); - else - disp('spike SNR file already exists'); - end - return; - end - - if ~isempty(fileNameSTWaveform) - load(fileNameSTWaveform,'avgHPWF','stdHPWF','neuronNames','P'); - detectionPreSpikeWindow=P.preFilteredWindow; - detectionPostSpikeWindow=P.totalFilteredWindow-P.preFilteredWindow; - else - if exist(obj.files.getSpikeTrigWF,'file') - avgRawWF=load(obj.files.getSpikeTrigWF,'avgRawWF','neuronNames','P'); - detectionPreSpikeWindow=P.preFilteredWindow; - detectionPostSpikeWindow=P.totalFilteredWindow-P.preFilteredWindow; - else - obj.populateGridSorterObj; - load(obj.gridSorterObj.sortingFileNames.STWaveformFile,'avgHPWF','stdHPWF','neuronNames'); - detectionPostSpikeWindow=obj.gridSorterObj.detectionPostSpikeWindow; - detectionPreSpikeWindow=obj.gridSorterObj.detectionPreSpikeWindow; - warning('Getting spike triggered data from grid sorter!!!! In the future, run getSpikeTrigWF from MEAAnalysis'); - end - fprintf('done\n'); - end - - [Xc,Yc]=obj.currentDataObj.getElectrodePositions; - - Fs_ms=obj.currentDataObj.samplingFrequency(1)/1000; - tSpk=(-detectionPreSpikeWindow+1/Fs_ms):(1/Fs_ms):detectionPostSpikeWindow; - pSpk=tSpk>-preSpikeMs & tSpkobj.currentDataObj.recordingDuration_ms - startTimes=par.startEnd(1); - endTimes=par.startEnd(2); - else - startTimes=(par.startEnd(1):par.detectionMaxChunkDuration:par.startEnd(2)); - endTimes=[startTimes(2:end) par.startEnd(2)]; - end - nChunks=numel(startTimes); - - nCh=numel(obj.currentDataObj.channelNumbers); - nNeurons=size(par.ss.ic,2); - - nSpkTotal=zeros(1,nNeurons); - - windowSamplesRaw=par.totalRawWindow*obj.currentDataObj.samplingFrequency(1)/1000; - windowSamplesFiltered=par.totalFilteredWindow*obj.currentDataObj.samplingFrequency(1)/1000; - HPstartIdx=((par.preRawWindow-par.preFilteredWindow)*obj.currentDataObj.samplingFrequency(1)/1000+1); - HPIdx=HPstartIdx:(HPstartIdx+windowSamplesFiltered-1); - - if ispc - userview = memory; - doubleBytes=8; - if userview.MemAvailableAllArrays<(nNeurons*nCh*windowSamplesRaw*doubleBytes*4) & par.keepAllInMemory - disp('Arrays too big for memory, moving to saving on disk (for using memory change chunk size'); - par.keepAllInMemory=0; - end - end - - nBinsRaw=ceil(par.totalRawWindow/par.binTRaw); - nBinsHP=ceil(par.totalFilteredWindow/par.binTHP); - nBinsV=2*par.maxV/par.binV; - - if par.keepAllInMemory - avgRawWF=zeros(nNeurons,nCh,windowSamplesRaw); - stdRawWF=zeros(nNeurons,nCh,windowSamplesRaw); - avgHPWF=zeros(nNeurons,nCh,windowSamplesFiltered); - stdHPWF=zeros(nNeurons,nCh,windowSamplesFiltered); - if par.calcSpikeHistogram - histRawWF=zeros(nNeurons,nCh,nBinsRaw,nBinsV,'uint8'); - histHPWF=zeros(nNeurons,nCh,nBinsHP,nBinsV,'uint8'); - else - histRawWF=[];histHPWF=[]; - end - else - matFileObj = matfile([saveFileName(1:end-4) postFix],'Writable',true); - if par.extractFilteredWaveformsFromSpikeTimes - matFileObj.avgRawWF=zeros(nNeurons,nCh,windowSamplesRaw); - matFileObj.stdRawWF=zeros(nNeurons,nCh,windowSamplesRaw); - if par.calcSpikeHistogram - matFileObj.histRawWF=zeros(nNeurons,nCh,nBinsRaw,nBinsV,'uint8'); - end - else - matFileObj.avgRawWF=[];matFileObj.stdRawWF=[];matFileObj.histRawWF=[]; - end - - if par.extractFilteredWaveformsFromSpikeTimes - matFileObj.avgHPWF=zeros(nNeurons,nCh,windowSamplesFiltered); - matFileObj.stdHPWF=zeros(nNeurons,nCh,windowSamplesFiltered); - if calcSpikeHistogram - matFileObj.histHPWF=zeros(nNeurons,nCh,nBinsHP,nBinsV,'uint8'); - end - else - matFileObj.avgHPWF=[];matFileObj.stdHPWF=[];matFileObj.histHPWF=[]; - end - end - - %remove mat ending from file base - if strcmp(par.saveFileName(end-3:end),'.mat') - par.saveFileName=par.saveFileName(1:end-4); - end - - %load files if matlab crashed during analysis - if exist([par.saveFileName postFix '_tmp.mat'],'file') & ~par.overwrite - load([par.saveFileName postFix '_tmp.mat']); - startChunk=max(1,lastGoodChunck+1); - disp('Loading temporary data saved following crash...'); - else - startChunk=1; - end - - tBinRaw=shiftdim(ceil(((1:windowSamplesRaw)/obj.currentDataObj.samplingFrequency(1)*1000)/par.binTRaw),-1); - tBinHP=shiftdim(ceil(((1:windowSamplesFiltered)/obj.currentDataObj.samplingFrequency(1)*1000)/par.binTHP),-1); - %VBins=(-par.maxV+par.binV/2):par.binV:par.maxV; - %pPreBaselineSamples=((obj.currentDataObj.samplingFrequency(1)/1000)*(par.preRawWindow-detectionPreSpikeWindow-1)):((obj.currentDataObj.samplingFrequency(1)/1000)*(par.preRawWindow-detectionPreSpikeWindow)); - %tBinsRaw=par.binTRaw/2:par.binTRaw:par.totalRawWindow; - %tBinsHP=par.binTHP/2:par.binTHP:par.totalFilteredWindow; - - try - tic; - %initiate arrays - fprintf('\nExtracting spikes from chunks (total %d): ',nChunks); - for i=startChunk:nChunks - fprintf('%d',i); - %get data - MAll=obj.currentDataObj.getData([],startTimes(i)-par.preRawWindow,endTimes(i)-startTimes(i)+par.totalRawWindow); %get all channels - MFAll=squeeze(filterObj.getFilteredData(MAll))'; %filter class needs unsqueezed input - MAll=squeeze(MAll)'; - nSamples=size(MAll,1); - %tAll=((1:nSamples)/obj.currentDataObj.samplingFrequency(1)*1000)-preRawWindow+startTimes(i); - nSpkAllTmp=zeros(1,nNeurons); - for j=1:nNeurons - tTmp=par.ss.t(par.ss.ic(3,j):par.ss.ic(4,j)); - tTmp=tTmp(find(tTmp>=startTimes(i) & tTmp< (endTimes(i)-par.totalRawWindow+par.preRawWindow) )); - nSpkTmp=numel(tTmp); - if nSpkTmp>0 %if spike rate is unreasonable, reject window (usually does not happen) - startIdx=1+round((tTmp-startTimes(i))*obj.currentDataObj.samplingFrequency(1)/1000); - idx=bsxfun(@plus,startIdx,(0:windowSamplesRaw-1)'); - WF=MAll(idx,:); - WF=permute(reshape(WF,[size(idx,1) size(idx,2) nCh]),[2 3 1]); - %WF=bsxfun(@minus,WF,mean(WF(:,:,pPreBaselineSamples),3)); - avgRawWF(j,:,:)=avgRawWF(j,:,:)+sum(WF,1); - stdRawWF(j,:,:)=stdRawWF(j,:,:)+sum(WF.^2,1); - - idx=idx(HPIdx,:); - WFH=MFAll(idx,:); - WFH=permute(reshape(WFH,[size(idx,1) size(idx,2) nCh]),[2 3 1]); - avgHPWF(j,:,:)=avgHPWF(j,:,:)+sum(WFH,1); - stdHPWF(j,:,:)=stdHPWF(j,:,:)+sum(WFH.^2,1); - if par.calcSpikeHistogram - for k=1:nCh - hVTmp=round((WF(:,k,:)+par.maxV)/(par.maxV*2/nBinsV)); %the reshape is important since otherwise when nSpkTmp==1 squeeze changes matrix from row to column - p=find(hVTmp>0 & hVTmp1 %if there is only one point to include in the statistics we can reject this trial. - htTmp=repmat(tBinRaw,[numel(tTmp) 1]); - if nSpkTmp>1 - histRawWF(j,k,:,:)=histRawWF(j,k,:,:)+shiftdim(uint8(accumarray([htTmp(p) hVTmp(p)],1,[nBinsRaw nBinsV])),-2); - else - histRawWF(j,k,:,:)=histRawWF(j,k,:,:)+shiftdim(uint8(accumarray(squeeze([htTmp(p) hVTmp(p)])',1,[nBinsRaw nBinsV])),-2); - end - - hVTmp=round((WFH(:,k,:)+par.maxV)/(par.maxV*2/nBinsV)); - p=find(hVTmp>0 & hVTmp1 - histHPWF(j,k,:,:)=histHPWF(j,k,:,:)+shiftdim(uint8(accumarray([htTmp(p) hVTmp(p)],1,[nBinsHP nBinsV])),-2); - else - histHPWF(j,k,:,:)=histHPWF(j,k,:,:)+shiftdim(uint8(accumarray(squeeze([htTmp(p) hVTmp(p)])',1,[nBinsHP nBinsV])),-2); - end - end - end - end - nSpkAllTmp(j)=nSpkAllTmp(j)+nSpkTmp; - elseif nSpkTmp>1000 - disp(['Rejecting neuron ' num2str(par.ss.ic(1:2,j)') ' due to >1000 spike count']); - end - end - nSpkTotal=nSpkTotal+nSpkAllTmp; - tChunk(i)=toc;tic; - lastGoodChunck=i; - fprintf('(%d) ',round(tChunk(i))); - end - - for i=1:nNeurons - if nSpkTotal(i)>0 - stdRawWF(i,:,:)=sqrt((stdRawWF(i,:,:)-avgRawWF(i,:,:))/(nSpkTotal(i)-1)); - stdHPWF(i,:,:)=sqrt((stdHPWF(i,:,:)-avgHPWF(i,:,:))/(nSpkTotal(i)-1)); - - avgRawWF(i,:,:)=avgRawWF(i,:,:)/nSpkTotal(i); - avgHPWF(i,:,:)=avgHPWF(i,:,:)/nSpkTotal(i); - end - end - - %save data - if par.keepAllInMemory - fprintf('Saving data...'); - save([par.saveFileName postFix],'avgRawWF','avgHPWF','stdRawWF','stdHPWF','neuronNames','histRawWF','histHPWF','par','nSpkTotal','-v7.3'); - end - fprintf('Deleting temporary files...'); - delete([par.saveFileName postFix '_tmp.mat']); - - catch errorMsg - disp('Extraction of fields crashed!!! Saving data in a temp file...'); - if i>1 - save([par.saveFileName postFix '_tmp.mat'],'avgRawWF','avgHPWF','stdRawWF','stdHPWF','neuronNames','histRawWF','histHPWF','par','nSpkTotal','lastGoodChunck','-v7.3'); - end - disp('Data saved!'); - rethrow(errorMsg); - end - fprintf('\nTriggered waveform analysis took (%f) hours\n',sum(tChunk)/60/60); - end %getSpikeTrigWF - - function obj=testMet(obj) - end - end %methods - -end %class \ No newline at end of file diff --git a/dataAnalysisObjects/@MEAAnalysis/MEAAnalysis.m.orig b/dataAnalysisObjects/@MEAAnalysis/MEAAnalysis.m.orig deleted file mode 100644 index 0c0bfb0..0000000 --- a/dataAnalysisObjects/@MEAAnalysis/MEAAnalysis.m.orig +++ /dev/null @@ -1,1964 +0,0 @@ -<<<<<<< HEAD -classdef MEAAnalysis < recAnalysis - - properties - currentMEAFiles - currentMEADir - gridSorterFolder - VST %visual stimulation parameters table - end - - properties (Constant) - end - - methods - - [data]=getSpikePositionEstimation(obj,varargin); - [data]=getSpikeInducedFields(obj,varargin); - [data,hand]=getCrossCorr(obj,varargin); - [data,hand]=getSpikeParams(obj,varargin); - - [hand,out]=plotSpikeInducedFields(obj,varargin); - [hand,out]=plotAvgSIFMap(obj,varargin); - [hand,out]=plotSIFPerNeuron(obj,varargin); - - %% MEAAnalysis - class constructor - function [obj]=MEAAnalysis(xlsFile) - if nargin==0 - xlsFile=[]; - end - obj=obj@recAnalysis(xlsFile); - end - - %% populate gridSorter object - function [obj,flag]=populateGridSorterObj(obj,gridSorterObj) - if ~isempty(obj.gridSorterObj) - disp('gridSorter object already exists'); - flag=1; - return; - end - if nargin==1 - obj.gridSorterObj=gridSorter(obj.currentDataObj); - elseif nargin==2 - obj.gridSorterObj=gridSorterObj; - end - [obj.gridSorterObj,flag]=obj.gridSorterObj.loadMetaData; - end - - - %% getVStimParams - still under development - function [obj,VST]=getVStimParams(obj,VSFile) - %extract the visual stimulation parameters from parameter file - nParentFolders2Check=2; - folderFound=false; - if nargin==1 - %find visual stimulation folder - if ~exist([obj.currentExpFolder filesep 'visualStimulation'],'dir') %check if not in the current data folder - %go one folder back and look for visualStimulation folder - fileSepTransitions=regexp(obj.currentExpFolder,filesep); %look for file separation transitions - if fileSepTransitions(end)==numel(obj.currentExpFolder) %if last transition appears in the end of the folder remove this transition - fileSepTransitions(end)=[]; - end - for i=1:nParentFolders2Check - tmpCurrentFolder=obj.currentExpFolder(1:fileSepTransitions(end)); - %check parent folder for visual stimulation folder - if exist([tmpCurrentFolder filesep 'visualStimulation'],'dir') - VSFileLocation=[tmpCurrentFolder filesep 'visualStimulation']; - folderFound=true; - end - fileSepTransitions(end)=[]; - end - if ~folderFound - error('Visual stimulation folder was not found!!! Notice the the name of the folder should be visualStimulation'); - end - else - VSFileLocation=[obj.currentExpFolder filesep 'visualStimulation']; - end - fprintf('Visual stimulation folder set as:\n %s\n',VSFileLocation); - %find visual stimulation file according to recording file name - VSFile=dir([VSFileLocation filesep '*.mat']); - dateNumber=datenum({VSFile.date},'dd-mmm-yyyy HH:MM:SS'); - VSFile={VSFile.name}; %do not switch with line above - - tmpFileParts=strsplit(obj.currentDataFiles{1}(1:end-9),filesep); - validVSFile=[]; - for i=1:numel(VSFile) - if contains(VSFile{i}(1:end-4),tmpFileParts{end},'IgnoreCase',true) || ... - contains(tmpFileParts{end},VSFile{i}(1:end-4),'IgnoreCase',true) || ... - contains(VSFile{i}(1:end-4),tmpFileParts{end-1},'IgnoreCase',true) || ... - contains(tmpFileParts{end-1},VSFile{i}(1:end-4),'IgnoreCase',true) - validVSFile=VSFile{i}; - break; - end - end - if ~isempty(validVSFile) - VSFile=[VSFileLocation filesep validVSFile] ; - else - error(['No file with ' tmpFileParts{end} ' in its name was found , please enter specific VS filename']); - end - - elseif ~exist(VSFile,'file') - error(['Input VS file: ' VSFile ' was not found!']); - end - - % Future implementaion - if finding name strategy does not work try to find the correct file according to its save date which should correspond to recording dates - %find(dateNumber>obj.currentDataObj.startDate & dateNumber1 - VST=obj.VST; - end - end - - function data=getAI(obj,varargin) - %% parameter and settings - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'selectedChannels',obj.currentDataObj.channelNumbers,@isnumeric); - addParameter(parseObj,'stdAbsNoiseConstant',4,@isnumeric); - addParameter(parseObj,'bin_ms',2,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parAI=parseObj.Results; - - %check if analysis was already done done - obj.files.AIfile=[obj.currentAnalysisFolder filesep 'AI_' num2str(bin_ms) 'ms_' num2str(stdAbsNoiseConstant) 'std.mat']; - if exist(obj.files.AIfile,'file') & ~overwrite - if nargout==1 - data=load(obj.files.AIfile); - else - disp('AI file already exists'); - end - return; - end - - [IA,tA,icA]=mcdIntensityExtractorUnfiltered(obj.currentDataObj,'Bin_ms',bin_ms,'SelectedChannels',selectedChannels,'StdAbsNoiseConstant',stdAbsNoiseConstant); - - save(obj.files.AIfile,'IA','tA','icA','parAI','-v7.3'); - end - - function obj=getKiloSorting(obj,varargin) - if ~strcmp(class(obj.currentDataObj),'binaryRecording') - fprintf('\nKilo-sort only runs on binaryData class!!!\nYou can use the dataRecording.export2Binary method to convert to this format\n'); - return; - end - if exist('make_eMouseData_drift', 'file')==0 - fprintf('\nKilo-sort is not on the Matlab path, please add to path and run again!!!'); - return; -% else -% fprintf('\nKilo-sort not on path, trying to find it...'); -% NSKToolboxDir=fileparts(which('identifierOfMainDir4NSKToolBox')); -% -% tmp = strsplit(NSKToolboxDir, filesep); -% matlabFunctionsDir = strjoin(tmp(1:end-1),filesep); -% if exist([matlabFunctionsDir filesep 'spikeSorting'],'dir') -% addpath(genpath([matlabFunctionsDir filesep 'spikeSorting' filesep 'kiloSort2'])); -% fprintf('\nPath added successfully.\n'); -% else -% fprintf('Did not find kilosort path!\nPlease add manually\n'); -% end - end - - nCh=numel(obj.currentDataObj.channelNumbers); -% NT=64+2^round(log2(1024*(128/nCh)))*1024; - NT = 32+2^round(log2(1024*(32/nCh)))*64; - NT = 2*32*128+64; - % Run the configuration file, it builds the structure of options (ops) - ops=makeConfigKiloSort2(obj.currentDataObj.recordingDir,nCh,... - 'GPU',1,'parfor',1,'NT',NT,'fbinary',[obj.currentDataObj.recordingDir filesep obj.currentDataObj.dataFileNames{1}],... - 'fs',obj.currentDataObj.samplingFrequency); - - layoutName=[obj.currentDataObj.layoutName '_JRC.prb']; - resultsFileName=[obj.currentDataObj.recordingDir filesep obj.currentDataObj.recordingName '_' obj.currentDataObj.layoutName(1:end-4) '_JRC_ksort.mat']; - tic; %this is important otherwise fitTemplates crashes since it includes a toc without a tic - [rez, DATA] = preprocessDataSub(ops); - save(resultsFileName,'rez', 'DATA', '-v7.3'); - - rez = clusterSingleBatches(rez); - save(resultsFileName,'rez', 'DATA', '-v7.3'); - - rez = learnAndSolve8b(rez); - rez = find_merges(rez, 1); - rez = splitAllClusters(rez, 1); - rez = splitAllClusters(rez, 0); - rez = set_cutoff(rez); - save(resultsFileName,'rez', '-v7.3'); - - fprintf('Total time used for running kilo-sort was %f hours', toc/60/60); - delete(ops.fproc); - end - - %% getJRClust - function data=getJRClust(obj,varargin) - % getJRClust - get JRClust results from kilo sort - data=[]; - parseObj = inputParser; - addParameter(parseObj,'fullFile',[],@isnumeric); - addParameter(parseObj,'manual',0,@isnumeric); - addParameter(parseObj,'exportGS',0,@isnumeric); - addParameter(parseObj,'electrodePadSize',[26.5 26.5],@isnumeric); - - addParameter(parseObj,'saveFileName',[],@isstr); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - %displays parameters if 'inputParams' is set to true - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - par.saveFileName=obj.getFileName(dbstack,par.saveFileName); %extracts file save name - - %save/load data - if exist(par.saveFileName,'file') & ~par.overwrite & ~par.manual & ~par.exportGS - if nargout==1 - data=load(par.saveFileName); - else - disp('JRClust sorting already exists, use overwrite=true'); - end - return; - end - - if ~strcmp(class(obj.currentDataObj),'binaryRecording') - disp('JRClust only works on binaryRecording data class!!!'); - return; - end - - par.layoutName=[obj.currentDataObj.layoutName '_JRC.prb']; - recName=obj.currentDataObj.recordingName; - recDir=obj.currentDataObj.recordingDir; - if ~exist([recDir filesep filesep par.layoutName],'file') - obj.currentDataObj.convertLayoutJRClust([sqrt(pi*15^2) sqrt(pi*15^2)]); %electrode side is sqrt(pi*15^2)=26.6; - disp('Layout converted to JRclust format'); - end - - % Build files - if isempty(par.fullFile) - par.fullFile=[recDir filesep obj.currentDataObj.dataFileNames{1}]; - end - fullProbeFile=[recDir filesep par.layoutName]; -% par.fullParamFile=[recDir filesep recName '_' par.layoutName(1:end-4) '.prm']; - par.fullParamFile=[recDir filesep recName '.prm']; - - if ~exist(par.fullParamFile,'file') - %jrc('makeprm',par.fullFile,fullProbeFile); - jrc('bootstrap',par.fullFile,fullProbeFile); - else - disp('Prm file already exist'); - end - - if ~exist([par.fullParamFile(1:end-4) '_ksort.mat'],'file') - C = strsplit(par.fullParamFile,filesep); - paramDir = fullfile(join(C(1:end-1),'/')); - resultsFileName = [obj.currentDataObj.recordingDir filesep obj.currentDataObj.recordingName '_' obj.currentDataObj.layoutName(1:end-4) '_JRC_ksort.mat']; - load(resultsFileName, 'rez'); - rezToPhy(rez, paramDir{1}); - jrc('import-ksort',paramDir{1}); - else - disp('Data from ksort already imported'); - end - - if par.manual - disp('Deleting results file since manual mode is run again'); - jrc('manual',par.fullParamFile); - if ~exist([par.fullParamFile(1:end-4) '_gridSorter.mat'],'file') || par.exportGS - resultsFileName = [obj.currentDataObj.recordingDir filesep obj.currentDataObj.recordingName '_' obj.currentDataObj.layoutName(1:end-4) '_JRC_ksort.mat']; - export_gridsorter2(resultsFileName); - % S=load([par.fullParamFile(1:end-4) '_gridSorter.mat']); - % save(par.saveFileName,'par','S','-v7.3'); - else - disp('Data already exported to gridSorter format, to reexport use overwrite=1'); - end - return; - end -% if par.exportGS -% export_gridS -% jrc('export-gs',par.fullParamFile); -% S=load([par.fullParamFile(1:end-4) '_gridSorter.mat']); -% save(par.saveFileName,'par','S','-v7.3'); -% end - - end - - %% getSpikeSorting - function obj=getSpikeSorting(obj,varargin) - %default parameters - parseObj = inputParser; - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - obj=obj.populateGridSorterObj; - %obj.gridSorterObj.clusteringMinSpikesTotal = 2; - %obj.gridSorterObj.clusteringMinNSpikesCluster = 1; - - if strcmp(obj.recTable.MEA_Layout,'40_Hexa') - obj.gridSorterObj.localGridSize = 9; - obj.gridSorterObj.localGridExt = 3; - - else - obj.gridSorterObj.localGridSize = 3; - obj.gridSorterObj.localGridExt = 1; - end - - if strcmp(obj.recTable.MEA_Layout,'100_9x4_FlexMEA120') - obj.gridSorterObj.filterLowPassPassCutoff=1000; - obj.gridSorterObj.filterLowPassStopCutoff=1500; - obj.gridSorterObj.detectionSpikeDetectionThresholdStd=7; - end - - if overwrite - obj.gridSorterObj.overwriteAll=1; - obj.gridSorterObj.deleteSortingFiles; - end - - obj.gridSorterFolder=obj.gridSorterObj.sortingDir; - - % Start sorting - obj.gridSorterObj=obj.gridSorterObj.runSorting; - - end %runSpikeSorting - - function data=getCSDMovie(obj,varargin) - data=[]; - - parseObj = inputParser; - addParameter(parseObj,'pot',100,@isnumeric); %the potential matrix [channels,time] - addParameter(parseObj,'electrodePitch',100,@isnumeric); - addParameter(parseObj,'frameRate',30,@isnumeric); - addParameter(parseObj,'videoQuality',90,@isnumeric); - addParameter(parseObj,'positionRealSpace',[],@isnumeric); - addParameter(parseObj,'dataType','CSD',@isnumeric);%'pot'/'CSD' - addParameter(parseObj,'electrodeMarker','.',@isnumeric); - addParameter(parseObj,'saveData',false,@isnumeric); %to only calculate CSD without making movie - addParameter(parseObj,'makeMovie',true,@isnumeric); - addParameter(parseObj,'saveFullMatrices',false,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - - %displays parameters if 'inputParams' is set to true - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - par.saveFileName=obj.getFileName(dbstack,par.saveFileName); %extracts file save name - - %save/load data - if exist(par.saveFileName,'file') & ~par.overwrite - if nargout==1 - data=load(par.saveFileName); - else - disp('CSD already exists, use overwrite=true'); - end - return; - end - - - %% - - - [nNeu,nCh,nSamples]=size(pot); - timeSamples=(1:nSamples)/Fs*1000-preMs; - spikeSample=round(preMs/1000*Fs); - - %calculate electrode positions - elecPos=NaN(nCh,3); - En2=En; - for i=1:nCh - [n,m]=find(En2==ch(i)); - if ~isempty(n) - elecPos(i,:)=[m n ch(i)]; - else - elecPos(i,:)=ch(i); - end - end - elecPos(:,1:2)=elecPos(:,1:2)*electrodePitch; - - if saveData - mkdir(dataFolder); - disp(['Data will be saved in ' dataFolder]); - end - - samplingPosX=min(elecPos(:,1)):10:max(elecPos(:,1)); - samplingPosY=min(elecPos(:,2)):10:max(elecPos(:,2)); - [XuM,YuM]=meshgrid(samplingPosX,samplingPosY); - CSD=zeros(size(WF)); - - for i=1:nNeu - mM=squeeze(WF(i,:,:)); - k = kcsd2d(elecPos(:,1:2), mM(elecPos(:,3),:), 'manage_data', 0, 'X', XuM, 'Y', YuM); - - if strcmp(dataType,'CSD') - dynamics=k.CSD_est; - elseif strcmp(dataType,'pot') - dynamics=k.pots_est; - else - error('The parameter dataType was not chosen correctly'); - end - - for j=1:nCh - [pTmpX,pTmpY]=find(XuM==elecPos(j,1) & YuM==elecPos(j,2)); - CSD(i,j,:)=dynamics(pTmpX,pTmpY,:); - end - - %[hPlot,scaleFac]=activityTracePhysicalSpacePlot([],1:120,squeeze(CSDelec(i,:,:)),En); - %[hPlot,scaleFac]=activityTracePhysicalSpacePlot([],1:120,squeeze(WF(i,:,:)),En); - if saveFullMatrices - save([dataFolder filesep 'CSD_Neuron_' num2str(neuronNames(1,i)) '-' num2str(neuronNames(2,i))],'dynamics','dataType','preMs','Fs','XuM','YuM','elecPos'); - end - - if makeMovie - mn=min(min(min(dynamics(:,:,(spikeSample+40):end),[],1),[],2),[],3); - mx=max(max(max(dynamics(:,:,(spikeSample+40):end),[],1),[],2),[],3); - l=max(abs([mn,mx])); - cLim=[-l l]; - - - writerObj = VideoWriter([dataFolder filesep dataType '_neu' num2str(neuronNames(1,i)) '_' num2str(neuronNames(2,i)) '.mp4'],'MPEG-4'); - writerObj.FrameRate=frameRate; - writerObj.Quality=videoQuality; - open(writerObj); - - F=figure('position',[50 50 550 500],'color','w');h=axes; - imagesc(XuM(1,:),YuM(:,1),squeeze(dynamics(:,:,i)),cLim);set(gca,'YDir','normal');hold on; - plot(elecPos(:,1),elecPos(:,2),'.'); - %text(elecPos(:,1),elecPos(:,2),num2str(elecPos(:,3))); - cb=colorbar; - set(cb,'position',[0.9167 0.7600 0.0117 0.1650],'Ticks',round([-l 0 l])); - cb.Label.Position=[4.2 0 0]; - ylab=ylabel(cb,dataType); - ylab.Position=[4.2 0 0]; - - xlabel('\mum'); - ylabel('\mum'); - - axis equal tight; - set(h,'nextplot','replacechildren'); - set(F,'Renderer','zbuffer'); - - if isempty(positionRealSpace) - [~,pPeak]=min(min(min(dynamics(:,:,(spikeSample-10):(spikeSample+10)),[],1),[],2),[],3); - CSDSpikePeak=squeeze(mean(dynamics(:,:,(spikeSample-10+pPeak-5):(spikeSample-10+pPeak+5)),3)); - [ySpk,xSpk] = find(CSDSpikePeak == min(min(CSDSpikePeak))); - cellBodyPos=[XuM(1,xSpk) YuM(ySpk,1)]; - else - cellBodyPos=positionRealSpace(:,i); - end - - for j=1:nSamples - tmpImg=squeeze(dynamics(:,:,j)); - - h(1)=imagesc(XuM(1,:),YuM(:,1),tmpImg,cLim);hold on; - h(2)=plot(elecPos(:,1),elecPos(:,2),electrodeMarker,'color',[0.8 0.8 0.8]); - h(3)=line([XuM(1,1) XuM(1,end)],[cellBodyPos(2) cellBodyPos(2)],'color','k'); - h(4)=line([cellBodyPos(1) cellBodyPos(1)],[YuM(1,1) YuM(end,1)],'color','k'); - - title([num2str(timeSamples(j),'% 10.1f') ' ms']); - - frame = getframe(F); - writeVideo(writerObj,frame); - delete(h); - end - close(writerObj); - close(F); - end - end - - end - - function [saveFileName,funName]=getFileName(obj,funName,saveFileName) - %Get function name and save file name, if save file name is given in input, - funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - if isempty(saveFileName) - saveFileName=obj.files.(funName); - end - end - - function [data]=getTriggeredLFP(obj,varargin) - % extract LFP from triggered traces - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'preStim',500,@isnumeric); - addParameter(parseObj,'win',5000,@isnumeric); - addParameter(parseObj,'downSamplingFactor',100,@isnumeric); - addParameter(parseObj,'trialTriggerNumber',2,@isnumeric); - addParameter(parseObj,'filterObj',[],@isnumeric); - - addParameter(parseObj,'saveFileName',[],@isstr); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - %displays parameters if 'inputParams' is set to true - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - par.saveFileName=obj.getFileName(dbstack,par.saveFileName); %extracts file save name - - %save/load data - if exist(par.saveFileName,'file') & ~par.overwrite - if nargout==1 - data=load(par.saveFileName); - else - disp('triggered LFP data already exists, use overwrite=true'); - end - return; - end - - %Get trial triggers - try - obj.checkFileRecording(obj.files.getDiodeSync,'Diode transition identification file missing, please run getDiodeSync'); - D=obj.getDiodeSync; - T=D.upCross; - disp('Times extracted from Diode signal'); - catch - obj.checkFileRecording(obj.files.getDigitalTriggers,'Digital triggers file missing, please run getDigitalTriggers'); - D=obj.getDiodeSync; - T=D.tTrig(par.trialTriggerNumber*2-1); - fprintf('Times extracted from digital signal - channel %d\n',par.trialTriggerNumber); - end - - %make decimation filter - par.samplingFrequency=obj.currentDataObj.samplingFrequency; - if isempty(filterObj) - F=filterData; - F.samplingFrequency=obj.currentDataObj.samplingFrequency; - F.downSamplingFactor=par.downSamplingFactor; - F=F.designDownSample; - end - par.FsFiltered=F.filteredSamplingFrequency; - par.downSamplingFactor=obj.currentDataObj.samplingFrequency/F.filteredSamplingFrequency; - - %determine size of filtered data matrix - nTrials=numel(T); - ch=obj.currentDataObj.channelNumbers; - nCh=numel(ch); - nSamples=(par.win)*obj.currentDataObj.samplingFrequency/1000/par.downSamplingFactor; - - %determine which chunks to take in terms of memory - userview = memory; - sizeOfMF=nCh*nTrials*(par.win/1000*obj.currentDataObj.samplingFrequency)*8; %size of the array before downsampling bytes (8 bytes / double) - trialsPerSession=min(nTrials,ceil(nTrials/(sizeOfMF*3/userview.MaxPossibleArrayBytes))); - disp('Calculating downsampled LFP traces...'); - if trialsPerSession==nTrials - %Filter all data in one shot - disp('Loading all trials - there is enough memory'); - MF=F.getFilteredData(obj.currentDataObj.getData(ch,T(1:nTrials)-par.preStim,par.win)); - else - %Filter data in chuncks - MF=zeros(nCh,nTrials,nSamples); - trialsPerSession=min(nTrials,ceil(nTrials/(sizeOfMF*4/userview.MaxPossibleArrayBytes))); %take smaller variables - for j=1:trialsPerSession:nTrials - fprintf('Analyzing trials %d-%d / %d\n',j,j+trialsPerSession-1,nTrials); - tmpTrials=j:min(nTrials,j+trialsPerSession-1); - MFtmp=F.getFilteredData(obj.currentDataObj.getData(ch,T(tmpTrials)-par.preStim,par.win)); - MF(:,tmpTrials,:)=MFtmp; - end - end - save(par.saveFileName,'MF','par','-v7.3'); - end - - %% getHighSNRNeurons - function [data]=getSpikeSNR(obj,varargin) - - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'avgHPWF',[],@isnumeric); - addParameter(parseObj,'stdHPWF',[],@isnumeric); - addParameter(parseObj,'preSpikeMs',0.5,@isnumeric); - addParameter(parseObj,'postSpikeMs',2.5,@isnumeric); - addParameter(parseObj,'minDist',150,@isnumeric); - - addParameter(parseObj,'fileNameSTWaveform',[],@isstr); - addParameter(parseObj,'saveFileName',[],@isstr); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %obj.checkFileRecording(obj.files.getSpikePositionEstimation,'Single cell position estimation file missing, please run getSpikePositionEstimation'); - - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - if isempty(saveFileName) - saveFileName=obj.files.(funName); - end - - if exist(saveFileName,'file') & ~overwrite - if nargout==1 - data=load(saveFileName); - else - disp('spike SNR file already exists'); - end - return; - end - - if ~isempty(fileNameSTWaveform) - load(fileNameSTWaveform,'avgHPWF','stdHPWF','neuronNames','P'); - detectionPreSpikeWindow=P.preFilteredWindow; - detectionPostSpikeWindow=P.totalFilteredWindow-P.preFilteredWindow; - else - if exist(obj.files.getSpikeTrigWF,'file') - avgRawWF=load(obj.files.getSpikeTrigWF,'avgRawWF','neuronNames','P'); - detectionPreSpikeWindow=P.preFilteredWindow; - detectionPostSpikeWindow=P.totalFilteredWindow-P.preFilteredWindow; - else - obj.populateGridSorterObj; - load(obj.gridSorterObj.sortingFileNames.STWaveformFile,'avgHPWF','stdHPWF','neuronNames'); - detectionPostSpikeWindow=obj.gridSorterObj.detectionPostSpikeWindow; - detectionPreSpikeWindow=obj.gridSorterObj.detectionPreSpikeWindow; - warning('Getting spike triggered data from grid sorter!!!! In the future, run getSpikeTrigWF from MEAAnalysis'); - end - fprintf('done\n'); - end - - [Xc,Yc]=obj.currentDataObj.getElectrodePositions; - - Fs_ms=obj.currentDataObj.samplingFrequency(1)/1000; - tSpk=(-detectionPreSpikeWindow+1/Fs_ms):(1/Fs_ms):detectionPostSpikeWindow; - pSpk=tSpk>-preSpikeMs & tSpkobj.currentDataObj.recordingDuration_ms - startTimes=par.startEnd(1); - endTimes=par.startEnd(2); - else - startTimes=(par.startEnd(1):par.detectionMaxChunkDuration:par.startEnd(2)); - endTimes=[startTimes(2:end) par.startEnd(2)]; - end - nChunks=numel(startTimes); - - nCh=numel(obj.currentDataObj.channelNumbers); - nNeurons=size(par.ss.ic,2); - - nSpkTotal=zeros(1,nNeurons); - - windowSamplesRaw=par.totalRawWindow*obj.currentDataObj.samplingFrequency(1)/1000; - windowSamplesFiltered=par.totalFilteredWindow*obj.currentDataObj.samplingFrequency(1)/1000; - HPstartIdx=((par.preRawWindow-par.preFilteredWindow)*obj.currentDataObj.samplingFrequency(1)/1000+1); - HPIdx=HPstartIdx:(HPstartIdx+windowSamplesFiltered-1); - - if ispc - userview = memory; - doubleBytes=8; - if userview.MemAvailableAllArrays<(nNeurons*nCh*windowSamplesRaw*doubleBytes*4) & par.keepAllInMemory - disp('Arrays too big for memory, moving to saving on disk (for using memory change chunk size'); - par.keepAllInMemory=0; - end - end - - nBinsRaw=ceil(par.totalRawWindow/par.binTRaw); - nBinsHP=ceil(par.totalFilteredWindow/par.binTHP); - nBinsV=2*par.maxV/par.binV; - - if par.keepAllInMemory - avgRawWF=zeros(nNeurons,nCh,windowSamplesRaw); - stdRawWF=zeros(nNeurons,nCh,windowSamplesRaw); - avgHPWF=zeros(nNeurons,nCh,windowSamplesFiltered); - stdHPWF=zeros(nNeurons,nCh,windowSamplesFiltered); - if par.calcSpikeHistogram - histRawWF=zeros(nNeurons,nCh,nBinsRaw,nBinsV,'uint8'); - histHPWF=zeros(nNeurons,nCh,nBinsHP,nBinsV,'uint8'); - else - histRawWF=[];histHPWF=[]; - end - else - matFileObj = matfile([saveFileName(1:end-4) postFix],'Writable',true); - if par.extractFilteredWaveformsFromSpikeTimes - matFileObj.avgRawWF=zeros(nNeurons,nCh,windowSamplesRaw); - matFileObj.stdRawWF=zeros(nNeurons,nCh,windowSamplesRaw); - if par.calcSpikeHistogram - matFileObj.histRawWF=zeros(nNeurons,nCh,nBinsRaw,nBinsV,'uint8'); - end - else - matFileObj.avgRawWF=[];matFileObj.stdRawWF=[];matFileObj.histRawWF=[]; - end - - if par.extractFilteredWaveformsFromSpikeTimes - matFileObj.avgHPWF=zeros(nNeurons,nCh,windowSamplesFiltered); - matFileObj.stdHPWF=zeros(nNeurons,nCh,windowSamplesFiltered); - if calcSpikeHistogram - matFileObj.histHPWF=zeros(nNeurons,nCh,nBinsHP,nBinsV,'uint8'); - end - else - matFileObj.avgHPWF=[];matFileObj.stdHPWF=[];matFileObj.histHPWF=[]; - end - end - - %remove mat ending from file base - if strcmp(par.saveFileName(end-3:end),'.mat') - par.saveFileName=par.saveFileName(1:end-4); - end - - %load files if matlab crashed during analysis - if exist([par.saveFileName postFix '_tmp.mat'],'file') & ~par.overwrite - load([par.saveFileName postFix '_tmp.mat']); - startChunk=max(1,lastGoodChunck+1); - disp('Loading temporary data saved following crash...'); - else - startChunk=1; - end - - tBinRaw=shiftdim(ceil(((1:windowSamplesRaw)/obj.currentDataObj.samplingFrequency(1)*1000)/par.binTRaw),-1); - tBinHP=shiftdim(ceil(((1:windowSamplesFiltered)/obj.currentDataObj.samplingFrequency(1)*1000)/par.binTHP),-1); - %VBins=(-par.maxV+par.binV/2):par.binV:par.maxV; - %pPreBaselineSamples=((obj.currentDataObj.samplingFrequency(1)/1000)*(par.preRawWindow-detectionPreSpikeWindow-1)):((obj.currentDataObj.samplingFrequency(1)/1000)*(par.preRawWindow-detectionPreSpikeWindow)); - %tBinsRaw=par.binTRaw/2:par.binTRaw:par.totalRawWindow; - %tBinsHP=par.binTHP/2:par.binTHP:par.totalFilteredWindow; - - try - tic; - %initiate arrays - fprintf('\nExtracting spikes from chunks (total %d): ',nChunks); - for i=startChunk:nChunks - fprintf('%d',i); - %get data - MAll=obj.currentDataObj.getData([],startTimes(i)-par.preRawWindow,endTimes(i)-startTimes(i)+par.totalRawWindow); %get all channels - MFAll=squeeze(filterObj.getFilteredData(MAll))'; %filter class needs unsqueezed input - MAll=squeeze(MAll)'; - nSamples=size(MAll,1); - %tAll=((1:nSamples)/obj.currentDataObj.samplingFrequency(1)*1000)-preRawWindow+startTimes(i); - nSpkAllTmp=zeros(1,nNeurons); - for j=1:nNeurons - tTmp=par.ss.t(par.ss.ic(3,j):par.ss.ic(4,j)); - tTmp=tTmp(find(tTmp>=startTimes(i) & tTmp< (endTimes(i)-par.totalRawWindow+par.preRawWindow) )); - nSpkTmp=numel(tTmp); - if nSpkTmp>0 %if spike rate is unreasonable, reject window (usually does not happen) - startIdx=1+round((tTmp-startTimes(i))*obj.currentDataObj.samplingFrequency(1)/1000); - idx=bsxfun(@plus,startIdx,(0:windowSamplesRaw-1)'); - WF=MAll(idx,:); - WF=permute(reshape(WF,[size(idx,1) size(idx,2) nCh]),[2 3 1]); - %WF=bsxfun(@minus,WF,mean(WF(:,:,pPreBaselineSamples),3)); - avgRawWF(j,:,:)=avgRawWF(j,:,:)+sum(WF,1); - stdRawWF(j,:,:)=stdRawWF(j,:,:)+sum(WF.^2,1); - - idx=idx(HPIdx,:); - WFH=MFAll(idx,:); - WFH=permute(reshape(WFH,[size(idx,1) size(idx,2) nCh]),[2 3 1]); - avgHPWF(j,:,:)=avgHPWF(j,:,:)+sum(WFH,1); - stdHPWF(j,:,:)=stdHPWF(j,:,:)+sum(WFH.^2,1); - if par.calcSpikeHistogram - for k=1:nCh - hVTmp=round((WF(:,k,:)+par.maxV)/(par.maxV*2/nBinsV)); %the reshape is important since otherwise when nSpkTmp==1 squeeze changes matrix from row to column - p=find(hVTmp>0 & hVTmp1 %if there is only one point to include in the statistics we can reject this trial. - htTmp=repmat(tBinRaw,[numel(tTmp) 1]); - if nSpkTmp>1 - histRawWF(j,k,:,:)=histRawWF(j,k,:,:)+shiftdim(uint8(accumarray([htTmp(p) hVTmp(p)],1,[nBinsRaw nBinsV])),-2); - else - histRawWF(j,k,:,:)=histRawWF(j,k,:,:)+shiftdim(uint8(accumarray(squeeze([htTmp(p) hVTmp(p)])',1,[nBinsRaw nBinsV])),-2); - end - - hVTmp=round((WFH(:,k,:)+par.maxV)/(par.maxV*2/nBinsV)); - p=find(hVTmp>0 & hVTmp1 - histHPWF(j,k,:,:)=histHPWF(j,k,:,:)+shiftdim(uint8(accumarray([htTmp(p) hVTmp(p)],1,[nBinsHP nBinsV])),-2); - else - histHPWF(j,k,:,:)=histHPWF(j,k,:,:)+shiftdim(uint8(accumarray(squeeze([htTmp(p) hVTmp(p)])',1,[nBinsHP nBinsV])),-2); - end - end - end - end - nSpkAllTmp(j)=nSpkAllTmp(j)+nSpkTmp; - elseif nSpkTmp>1000 - disp(['Rejecting neuron ' num2str(par.ss.ic(1:2,j)') ' due to >1000 spike count']); - end - end - nSpkTotal=nSpkTotal+nSpkAllTmp; - tChunk(i)=toc;tic; - lastGoodChunck=i; - fprintf('(%d) ',round(tChunk(i))); - end - - for i=1:nNeurons - if nSpkTotal(i)>0 - stdRawWF(i,:,:)=sqrt((stdRawWF(i,:,:)-avgRawWF(i,:,:))/(nSpkTotal(i)-1)); - stdHPWF(i,:,:)=sqrt((stdHPWF(i,:,:)-avgHPWF(i,:,:))/(nSpkTotal(i)-1)); - - avgRawWF(i,:,:)=avgRawWF(i,:,:)/nSpkTotal(i); - avgHPWF(i,:,:)=avgHPWF(i,:,:)/nSpkTotal(i); - end - end - - %save data - if par.keepAllInMemory - fprintf('Saving data...'); - save([par.saveFileName postFix],'avgRawWF','avgHPWF','stdRawWF','stdHPWF','neuronNames','histRawWF','histHPWF','par','nSpkTotal','-v7.3'); - end - fprintf('Deleting temporary files...'); - delete([par.saveFileName postFix '_tmp.mat']); - - catch errorMsg - disp('Extraction of fields crashed!!! Saving data in a temp file...'); - if i>1 - save([par.saveFileName postFix '_tmp.mat'],'avgRawWF','avgHPWF','stdRawWF','stdHPWF','neuronNames','histRawWF','histHPWF','par','nSpkTotal','lastGoodChunck','-v7.3'); - end - disp('Data saved!'); - rethrow(errorMsg); - end - fprintf('\nTriggered waveform analysis took (%f) hours\n',sum(tChunk)/60/60); - end %getSpikeTrigWF - - function obj=testMet(obj) - end - end %methods - -======= -classdef MEAAnalysis < recAnalysis - - properties - currentMEAFiles - currentMEADir - gridSorterFolder - VST %visual stimulation parameters table - end - - properties (Constant) - end - - methods - - [data]=getSpikePositionEstimation(obj,varargin); - [data]=getSpikeInducedFields(obj,varargin); - [data,hand]=getCrossCorr(obj,varargin); - [data,hand]=getSpikeParams(obj,varargin); - - [hand,out]=plotSpikeInducedFields(obj,varargin); - [hand,out]=plotAvgSIFMap(obj,varargin); - [hand,out]=plotSIFPerNeuron(obj,varargin); - - %% MEAAnalysis - class constructor - function [obj]=MEAAnalysis(xlsFile) - if nargin==0 - xlsFile=[]; - end - obj=obj@recAnalysis(xlsFile); - end - - %% populate gridSorter object - function [obj,flag]=populateGridSorterObj(obj,gridSorterObj) - if ~isempty(obj.gridSorterObj) - disp('gridSorter object already exists'); - flag=1; - return; - end - if nargin==1 - obj.gridSorterObj=gridSorter(obj.currentDataObj); - elseif nargin==2 - obj.gridSorterObj=gridSorterObj; - end - [obj.gridSorterObj,flag]=obj.gridSorterObj.loadMetaData; - end - - - %% getVStimParams - still under development - function [obj,VST]=getVStimParams(obj,VSFile) - %extract the visual stimulation parameters from parameter file - nParentFolders2Check=2; - folderFound=false; - if nargin==1 - %find visual stimulation folder - if ~exist([obj.currentExpFolder filesep 'visualStimulation'],'dir') %check if not in the current data folder - %go one folder back and look for visualStimulation folder - fileSepTransitions=regexp(obj.currentExpFolder,filesep); %look for file separation transitions - if fileSepTransitions(end)==numel(obj.currentExpFolder) %if last transition appears in the end of the folder remove this transition - fileSepTransitions(end)=[]; - end - for i=1:nParentFolders2Check - tmpCurrentFolder=obj.currentExpFolder(1:fileSepTransitions(end)); - %check parent folder for visual stimulation folder - if exist([tmpCurrentFolder filesep 'visualStimulation'],'dir') - VSFileLocation=[tmpCurrentFolder filesep 'visualStimulation']; - folderFound=true; - end - fileSepTransitions(end)=[]; - end - if ~folderFound - error('Visual stimulation folder was not found!!! Notice the the name of the folder should be visualStimulation'); - end - else - VSFileLocation=[obj.currentExpFolder filesep 'visualStimulation']; - end - fprintf('Visual stimulation folder set as:\n %s\n',VSFileLocation); - %find visual stimulation file according to recording file name - VSFile=dir([VSFileLocation filesep '*.mat']); - dateNumber=datenum({VSFile.date},'dd-mmm-yyyy HH:MM:SS'); - VSFile={VSFile.name}; %do not switch with line above - - tmpFileParts=strsplit(obj.currentDataFiles{1}(1:end-9),filesep); - validVSFile=[]; - for i=1:numel(VSFile) - if contains(VSFile{i}(1:end-4),tmpFileParts{end},'IgnoreCase',true) || ... - contains(tmpFileParts{end},VSFile{i}(1:end-4),'IgnoreCase',true) || ... - contains(VSFile{i}(1:end-4),tmpFileParts{end-1},'IgnoreCase',true) || ... - contains(tmpFileParts{end-1},VSFile{i}(1:end-4),'IgnoreCase',true) - validVSFile=VSFile{i}; - break; - end - end - if ~isempty(validVSFile) - VSFile=[VSFileLocation filesep validVSFile] ; - else - error(['No file with ' tmpFileParts{end} ' in its name was found , please enter specific VS filename']); - end - - elseif ~exist(VSFile,'file') - error(['Input VS file: ' VSFile ' was not found!']); - end - - % Future implementaion - if finding name strategy does not work try to find the correct file according to its save date which should correspond to recording dates - %find(dateNumber>obj.currentDataObj.startDate & dateNumber1 - VST=obj.VST; - end - end - - function data=getAI(obj,varargin) - %% parameter and settings - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'selectedChannels',obj.currentDataObj.channelNumbers,@isnumeric); - addParameter(parseObj,'stdAbsNoiseConstant',4,@isnumeric); - addParameter(parseObj,'bin_ms',2,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parAI=parseObj.Results; - - %check if analysis was already done done - obj.files.AIfile=[obj.currentAnalysisFolder filesep 'AI_' num2str(bin_ms) 'ms_' num2str(stdAbsNoiseConstant) 'std.mat']; - if exist(obj.files.AIfile,'file') & ~overwrite - if nargout==1 - data=load(obj.files.AIfile); - else - disp('AI file already exists'); - end - return; - end - - [IA,tA,icA]=mcdIntensityExtractorUnfiltered(obj.currentDataObj,'Bin_ms',bin_ms,'SelectedChannels',selectedChannels,'StdAbsNoiseConstant',stdAbsNoiseConstant); - - save(obj.files.AIfile,'IA','tA','icA','parAI','-v7.3'); - end - - function obj=getKiloSorting(obj,varargin) - if ~strcmp(class(obj.currentDataObj),'binaryRecording') - fprintf('\nKilo-sort only runs on binaryData class!!!\nYou can use the dataRecording.export2Binary method to convert to this format\n'); - return; - end - if isempty('make_eMouseData.m') - fprintf('\nKilo-sort is not on the Matlab path, please add to path and run again!!!'); - return; - else - fprintf('\nKilo-sort not on path, trying to find it...'); - NSKToolboxDir=fileparts(which('identifierOfMainDir4NSKToolBox')); - - tmp = strsplit(NSKToolboxDir, filesep); - matlabFunctionsDir = strjoin(tmp(1:end-1),filesep); - if exist([matlabFunctionsDir filesep 'spikeSorting'],'dir') - addpath(genpath([matlabFunctionsDir filesep 'spikeSorting' filesep 'kiloSort'])); - fprintf('\nPath added successfully.\n'); - else - fprintf('Did not find kilosort path!\nPlease add manually\n'); - end - end - - nCh=numel(obj.currentDataObj.channelNumbers); - NT=64+2^round(log2(1024*(128/nCh)))*1024; - - % Run the configuration file, it builds the structure of options (ops) - ops=makeConfigKiloSort(obj.currentDataObj.recordingDir,nCh,... - 'GPU',1,'parfor',1,'NT',NT,'fbinary',[obj.currentDataObj.recordingDir filesep obj.currentDataObj.dataFileNames{1}]); - - layoutName=[obj.currentDataObj.layoutName '_JRC.prb']; - resultsFileName=[obj.currentDataObj.recordingDir obj.currentDataObj.recordingName '_' obj.currentDataObj.layoutName '_JRC_ksort']; - - tic; %this is important otherwise fitTemplates crashes since it includes a toc without a tic - [rez, DATA, uproj] = preprocessData(ops); % preprocess data and extract spikes for initialization - save(resultsFileName,'rez', 'DATA', 'uproj'); - - rez = fitTemplates(rez, DATA, uproj); % fit templates iteratively - save(resultsFileName,'rez', 'DATA'); - - rez = fullMPMU(rez, DATA);% extract final spike times (overlapping extraction) - save(resultsFileName,'rez'); - - rez = merge_posthoc2(rez); %merge spikes - save(resultsFileName,'rez'); - - fprintf('Total time used for running kilo-sort was %f hours', toc/60/60); - delete(ops.fproc); - end - - %% getJRClust - function data=getJRClust(obj,varargin) - % getJRClust - get JRClust results from kilo sort - data=[]; - parseObj = inputParser; - addParameter(parseObj,'fullFile',[],@isnumeric); - addParameter(parseObj,'manual',0,@isnumeric); - addParameter(parseObj,'exportGS',0,@isnumeric); - addParameter(parseObj,'electrodePadSize',[26.5 26.5],@isnumeric); - - addParameter(parseObj,'saveFileName',[],@isstr); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - %displays parameters if 'inputParams' is set to true - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - par.saveFileName=obj.getFileName(dbstack,par.saveFileName); %extracts file save name - - %save/load data - if exist(par.saveFileName,'file') & ~par.overwrite & ~par.manual & ~par.exportGS - if nargout==1 - data=load(par.saveFileName); - else - disp('JRClust sorting already exists, use overwrite=true'); - end - return; - end - - if ~strcmp(class(obj.currentDataObj),'binaryRecording') - disp('JRClust only works on binaryRecording data class!!!'); - return; - end - - par.layoutName=[obj.currentDataObj.layoutName '_JRC.prb']; - recName=obj.currentDataObj.recordingName; - recDir=obj.currentDataObj.recordingDir; - if ~exist([recDir filesep filesep par.layoutName],'file') - obj.currentDataObj.convertLayouteJRClust(par.electrodePadSize); %electrode side is sqrt(pi*15^2)=26.6; - disp('Layout converted to JRclust format'); - end - - % Build files - if isempty(par.fullFile) - par.fullFile=[recDir filesep obj.currentDataObj.dataFileNames{1}]; - end - fullProbeFile=[recDir filesep par.layoutName]; - par.fullParamFile=[recDir filesep recName '_' par.layoutName(1:end-4) '.prm']; - - if ~exist(par.fullParamFile,'file') - jrc3('makeprm',par.fullFile,fullProbeFile); - else - disp('Prm file already exist'); - end - - if ~exist([par.fullParamFile(1:end-4) '_ksort.mat'],'file') - jrc3('import-kilosort',par.fullParamFile); - else - disp('Data from ksort already imported'); - end - - if par.manual - disp('Deleting results file since manual mode is run again'); - jrc3('manual',par.fullParamFile); - return; - end - - if ~exist([par.fullParamFile(1:end-4) '_gridSorter.mat'],'file') | par.exportGS - jrc3('export-gs',par.fullParamFile); - S=load([par.fullParamFile(1:end-4) '_gridSorter.mat']); - save(par.saveFileName,'par','S','-v7.3'); - else - disp('Data already exported to gridSorter format, to reexport use overwrite=1'); - end - - if par.exportGS - jrc3('export-gs',par.fullParamFile); - S=load([par.fullParamFile(1:end-4) '_gridSorter.mat']); - save(par.saveFileName,'par','S','-v7.3'); - end - - %jrc3('detect',par.fullParamFile); - %jrc3('spikesort',par.fullParamFile); - %jrc3('cluster',par.fullParamFile); - %jrc3('manual',par.fullParamFile); - %jrc3('export-spkwav',par.fullParamFile); - %jrc3('import-gs',par.fullParamFile); - %jrc3('export-gs',par.fullParamFile); - - end - - %% getSpikeSorting - function obj=getSpikeSorting(obj,varargin) - %default parameters - parseObj = inputParser; - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - obj=obj.populateGridSorterObj; - %obj.gridSorterObj.clusteringMinSpikesTotal = 2; - %obj.gridSorterObj.clusteringMinNSpikesCluster = 1; - - if strcmp(obj.recTable.MEA_Layout,'40_Hexa') - obj.gridSorterObj.localGridSize = 9; - obj.gridSorterObj.localGridExt = 3; - - else - obj.gridSorterObj.localGridSize = 3; - obj.gridSorterObj.localGridExt = 1; - end - - if strcmp(obj.recTable.MEA_Layout,'100_9x4_FlexMEA120') - obj.gridSorterObj.filterLowPassPassCutoff=1000; - obj.gridSorterObj.filterLowPassStopCutoff=1500; - obj.gridSorterObj.detectionSpikeDetectionThresholdStd=7; - end - - if overwrite - obj.gridSorterObj.overwriteAll=1; - obj.gridSorterObj.deleteSortingFiles; - end - - obj.gridSorterFolder=obj.gridSorterObj.sortingDir; - - % Start sorting - obj.gridSorterObj=obj.gridSorterObj.runSorting; - - end %runSpikeSorting - - function data=getCSDMovie(obj,varargin) - data=[]; - - parseObj = inputParser; - addParameter(parseObj,'pot',100,@isnumeric); %the potential matrix [channels,time] - addParameter(parseObj,'electrodePitch',100,@isnumeric); - addParameter(parseObj,'frameRate',30,@isnumeric); - addParameter(parseObj,'videoQuality',90,@isnumeric); - addParameter(parseObj,'positionRealSpace',[],@isnumeric); - addParameter(parseObj,'dataType','CSD',@isnumeric);%'pot'/'CSD' - addParameter(parseObj,'electrodeMarker','.',@isnumeric); - addParameter(parseObj,'saveData',false,@isnumeric); %to only calculate CSD without making movie - addParameter(parseObj,'makeMovie',true,@isnumeric); - addParameter(parseObj,'saveFullMatrices',false,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - - %displays parameters if 'inputParams' is set to true - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - par.saveFileName=obj.getFileName(dbstack,par.saveFileName); %extracts file save name - - %save/load data - if exist(par.saveFileName,'file') & ~par.overwrite - if nargout==1 - data=load(par.saveFileName); - else - disp('CSD already exists, use overwrite=true'); - end - return; - end - - - %% - - - [nNeu,nCh,nSamples]=size(pot); - timeSamples=(1:nSamples)/Fs*1000-preMs; - spikeSample=round(preMs/1000*Fs); - - %calculate electrode positions - elecPos=NaN(nCh,3); - En2=En; - for i=1:nCh - [n,m]=find(En2==ch(i)); - if ~isempty(n) - elecPos(i,:)=[m n ch(i)]; - else - elecPos(i,:)=ch(i); - end - end - elecPos(:,1:2)=elecPos(:,1:2)*electrodePitch; - - if saveData - mkdir(dataFolder); - disp(['Data will be saved in ' dataFolder]); - end - - samplingPosX=min(elecPos(:,1)):10:max(elecPos(:,1)); - samplingPosY=min(elecPos(:,2)):10:max(elecPos(:,2)); - [XuM,YuM]=meshgrid(samplingPosX,samplingPosY); - CSD=zeros(size(WF)); - - for i=1:nNeu - mM=squeeze(WF(i,:,:)); - k = kcsd2d(elecPos(:,1:2), mM(elecPos(:,3),:), 'manage_data', 0, 'X', XuM, 'Y', YuM); - - if strcmp(dataType,'CSD') - dynamics=k.CSD_est; - elseif strcmp(dataType,'pot') - dynamics=k.pots_est; - else - error('The parameter dataType was not chosen correctly'); - end - - for j=1:nCh - [pTmpX,pTmpY]=find(XuM==elecPos(j,1) & YuM==elecPos(j,2)); - CSD(i,j,:)=dynamics(pTmpX,pTmpY,:); - end - - %[hPlot,scaleFac]=activityTracePhysicalSpacePlot([],1:120,squeeze(CSDelec(i,:,:)),En); - %[hPlot,scaleFac]=activityTracePhysicalSpacePlot([],1:120,squeeze(WF(i,:,:)),En); - if saveFullMatrices - save([dataFolder filesep 'CSD_Neuron_' num2str(neuronNames(1,i)) '-' num2str(neuronNames(2,i))],'dynamics','dataType','preMs','Fs','XuM','YuM','elecPos'); - end - - if makeMovie - mn=min(min(min(dynamics(:,:,(spikeSample+40):end),[],1),[],2),[],3); - mx=max(max(max(dynamics(:,:,(spikeSample+40):end),[],1),[],2),[],3); - l=max(abs([mn,mx])); - cLim=[-l l]; - - - writerObj = VideoWriter([dataFolder filesep dataType '_neu' num2str(neuronNames(1,i)) '_' num2str(neuronNames(2,i)) '.mp4'],'MPEG-4'); - writerObj.FrameRate=frameRate; - writerObj.Quality=videoQuality; - open(writerObj); - - F=figure('position',[50 50 550 500],'color','w');h=axes; - imagesc(XuM(1,:),YuM(:,1),squeeze(dynamics(:,:,i)),cLim);set(gca,'YDir','normal');hold on; - plot(elecPos(:,1),elecPos(:,2),'.'); - %text(elecPos(:,1),elecPos(:,2),num2str(elecPos(:,3))); - cb=colorbar; - set(cb,'position',[0.9167 0.7600 0.0117 0.1650],'Ticks',round([-l 0 l])); - cb.Label.Position=[4.2 0 0]; - ylab=ylabel(cb,dataType); - ylab.Position=[4.2 0 0]; - - xlabel('\mum'); - ylabel('\mum'); - - axis equal tight; - set(h,'nextplot','replacechildren'); - set(F,'Renderer','zbuffer'); - - if isempty(positionRealSpace) - [~,pPeak]=min(min(min(dynamics(:,:,(spikeSample-10):(spikeSample+10)),[],1),[],2),[],3); - CSDSpikePeak=squeeze(mean(dynamics(:,:,(spikeSample-10+pPeak-5):(spikeSample-10+pPeak+5)),3)); - [ySpk,xSpk] = find(CSDSpikePeak == min(min(CSDSpikePeak))); - cellBodyPos=[XuM(1,xSpk) YuM(ySpk,1)]; - else - cellBodyPos=positionRealSpace(:,i); - end - - for j=1:nSamples - tmpImg=squeeze(dynamics(:,:,j)); - - h(1)=imagesc(XuM(1,:),YuM(:,1),tmpImg,cLim);hold on; - h(2)=plot(elecPos(:,1),elecPos(:,2),electrodeMarker,'color',[0.8 0.8 0.8]); - h(3)=line([XuM(1,1) XuM(1,end)],[cellBodyPos(2) cellBodyPos(2)],'color','k'); - h(4)=line([cellBodyPos(1) cellBodyPos(1)],[YuM(1,1) YuM(end,1)],'color','k'); - - title([num2str(timeSamples(j),'% 10.1f') ' ms']); - - frame = getframe(F); - writeVideo(writerObj,frame); - delete(h); - end - close(writerObj); - close(F); - end - end - - end - - function [saveFileName,funName]=getFileName(obj,funName,saveFileName) - %Get function name and save file name, if save file name is given in input, - funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - if isempty(saveFileName) - saveFileName=obj.files.(funName); - end - end - - function [data]=getTriggeredLFP(obj,varargin) - % extract LFP from triggered traces - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'preStim',500,@isnumeric); - addParameter(parseObj,'win',5000,@isnumeric); - addParameter(parseObj,'downSamplingFactor',100,@isnumeric); - addParameter(parseObj,'trialTriggerNumber',2,@isnumeric); - addParameter(parseObj,'filterObj',[],@isnumeric); - - addParameter(parseObj,'saveFileName',[],@isstr); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - %displays parameters if 'inputParams' is set to true - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - par.saveFileName=obj.getFileName(dbstack,par.saveFileName); %extracts file save name - - %save/load data - if exist(par.saveFileName,'file') & ~par.overwrite - if nargout==1 - data=load(par.saveFileName); - else - disp('triggered LFP data already exists, use overwrite=true'); - end - return; - end - - %Get trial triggers - try - obj.checkFileRecording(obj.files.getDiodeSync,'Diode transition identification file missing, please run getDiodeSync'); - D=obj.getDiodeSync; - T=D.upCross; - disp('Times extracted from Diode signal'); - catch - obj.checkFileRecording(obj.files.getDigitalTriggers,'Digital triggers file missing, please run getDigitalTriggers'); - D=obj.getDiodeSync; - T=D.tTrig(par.trialTriggerNumber*2-1); - fprintf('Times extracted from digital signal - channel %d\n',par.trialTriggerNumber); - end - - %make decimation filter - par.samplingFrequency=obj.currentDataObj.samplingFrequency; - if isempty(filterObj) - F=filterData; - F.samplingFrequency=obj.currentDataObj.samplingFrequency; - F.downSamplingFactor=par.downSamplingFactor; - F=F.designDownSample; - end - par.FsFiltered=F.filteredSamplingFrequency; - par.downSamplingFactor=obj.currentDataObj.samplingFrequency/F.filteredSamplingFrequency; - - %determine size of filtered data matrix - nTrials=numel(T); - ch=obj.currentDataObj.channelNumbers; - nCh=numel(ch); - nSamples=(par.win)*obj.currentDataObj.samplingFrequency/1000/par.downSamplingFactor; - - %determine which chunks to take in terms of memory - userview = memory; - sizeOfMF=nCh*nTrials*(par.win/1000*obj.currentDataObj.samplingFrequency)*8; %size of the array before downsampling bytes (8 bytes / double) - trialsPerSession=min(nTrials,ceil(nTrials/(sizeOfMF*3/userview.MaxPossibleArrayBytes))); - disp('Calculating downsampled LFP traces...'); - if trialsPerSession==nTrials - %Filter all data in one shot - disp('Loading all trials - there is enough memory'); - MF=F.getFilteredData(obj.currentDataObj.getData(ch,T(1:nTrials)-par.preStim,par.win)); - else - %Filter data in chuncks - MF=zeros(nCh,nTrials,nSamples); - trialsPerSession=min(nTrials,ceil(nTrials/(sizeOfMF*4/userview.MaxPossibleArrayBytes))); %take smaller variables - for j=1:trialsPerSession:nTrials - fprintf('Analyzing trials %d-%d / %d\n',j,j+trialsPerSession-1,nTrials); - tmpTrials=j:min(nTrials,j+trialsPerSession-1); - MFtmp=F.getFilteredData(obj.currentDataObj.getData(ch,T(tmpTrials)-par.preStim,par.win)); - MF(:,tmpTrials,:)=MFtmp; - end - end - save(par.saveFileName,'MF','par','-v7.3'); - end - - %% getHighSNRNeurons - function [data]=getSpikeSNR(obj,varargin) - - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'avgHPWF',[],@isnumeric); - addParameter(parseObj,'stdHPWF',[],@isnumeric); - addParameter(parseObj,'preSpikeMs',0.5,@isnumeric); - addParameter(parseObj,'postSpikeMs',2.5,@isnumeric); - addParameter(parseObj,'minDist',150,@isnumeric); - - addParameter(parseObj,'fileNameSTWaveform',[],@isstr); - addParameter(parseObj,'saveFileName',[],@isstr); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %obj.checkFileRecording(obj.files.getSpikePositionEstimation,'Single cell position estimation file missing, please run getSpikePositionEstimation'); - - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - if isempty(saveFileName) - saveFileName=obj.files.(funName); - end - - if exist(saveFileName,'file') & ~overwrite - if nargout==1 - data=load(saveFileName); - else - disp('spike SNR file already exists'); - end - return; - end - - if ~isempty(fileNameSTWaveform) - load(fileNameSTWaveform,'avgHPWF','stdHPWF','neuronNames','P'); - detectionPreSpikeWindow=P.preFilteredWindow; - detectionPostSpikeWindow=P.totalFilteredWindow-P.preFilteredWindow; - else - if exist(obj.files.getSpikeTrigWF,'file') - avgRawWF=load(obj.files.getSpikeTrigWF,'avgRawWF','neuronNames','P'); - detectionPreSpikeWindow=P.preFilteredWindow; - detectionPostSpikeWindow=P.totalFilteredWindow-P.preFilteredWindow; - else - obj.populateGridSorterObj; - load(obj.gridSorterObj.sortingFileNames.STWaveformFile,'avgHPWF','stdHPWF','neuronNames'); - detectionPostSpikeWindow=obj.gridSorterObj.detectionPostSpikeWindow; - detectionPreSpikeWindow=obj.gridSorterObj.detectionPreSpikeWindow; - warning('Getting spike triggered data from grid sorter!!!! In the future, run getSpikeTrigWF from MEAAnalysis'); - end - fprintf('done\n'); - end - - [Xc,Yc]=obj.currentDataObj.getElectrodePositions; - - Fs_ms=obj.currentDataObj.samplingFrequency(1)/1000; - tSpk=(-detectionPreSpikeWindow+1/Fs_ms):(1/Fs_ms):detectionPostSpikeWindow; - pSpk=tSpk>-preSpikeMs & tSpkobj.currentDataObj.recordingDuration_ms - startTimes=par.startEnd(1); - endTimes=par.startEnd(2); - else - startTimes=(par.startEnd(1):par.detectionMaxChunkDuration:par.startEnd(2)); - endTimes=[startTimes(2:end) par.startEnd(2)]; - end - nChunks=numel(startTimes); - - nCh=numel(obj.currentDataObj.channelNumbers); - nNeurons=size(par.ss.ic,2); - - nSpkTotal=zeros(1,nNeurons); - - windowSamplesRaw=par.totalRawWindow*obj.currentDataObj.samplingFrequency(1)/1000; - windowSamplesFiltered=par.totalFilteredWindow*obj.currentDataObj.samplingFrequency(1)/1000; - HPstartIdx=((par.preRawWindow-par.preFilteredWindow)*obj.currentDataObj.samplingFrequency(1)/1000+1); - HPIdx=HPstartIdx:(HPstartIdx+windowSamplesFiltered-1); - - if ispc - userview = memory; - doubleBytes=8; - if userview.MemAvailableAllArrays<(nNeurons*nCh*windowSamplesRaw*doubleBytes*4) & par.keepAllInMemory - disp('Arrays too big for memory, moving to saving on disk (for using memory change chunk size'); - par.keepAllInMemory=0; - end - end - - nBinsRaw=ceil(par.totalRawWindow/par.binTRaw); - nBinsHP=ceil(par.totalFilteredWindow/par.binTHP); - nBinsV=2*par.maxV/par.binV; - - if par.keepAllInMemory - avgRawWF=zeros(nNeurons,nCh,windowSamplesRaw); - stdRawWF=zeros(nNeurons,nCh,windowSamplesRaw); - avgHPWF=zeros(nNeurons,nCh,windowSamplesFiltered); - stdHPWF=zeros(nNeurons,nCh,windowSamplesFiltered); - if par.calcSpikeHistogram - histRawWF=zeros(nNeurons,nCh,nBinsRaw,nBinsV,'uint8'); - histHPWF=zeros(nNeurons,nCh,nBinsHP,nBinsV,'uint8'); - else - histRawWF=[];histHPWF=[]; - end - else - matFileObj = matfile([saveFileName(1:end-4) postFix],'Writable',true); - if par.extractFilteredWaveformsFromSpikeTimes - matFileObj.avgRawWF=zeros(nNeurons,nCh,windowSamplesRaw); - matFileObj.stdRawWF=zeros(nNeurons,nCh,windowSamplesRaw); - if par.calcSpikeHistogram - matFileObj.histRawWF=zeros(nNeurons,nCh,nBinsRaw,nBinsV,'uint8'); - end - else - matFileObj.avgRawWF=[];matFileObj.stdRawWF=[];matFileObj.histRawWF=[]; - end - - if par.extractFilteredWaveformsFromSpikeTimes - matFileObj.avgHPWF=zeros(nNeurons,nCh,windowSamplesFiltered); - matFileObj.stdHPWF=zeros(nNeurons,nCh,windowSamplesFiltered); - if calcSpikeHistogram - matFileObj.histHPWF=zeros(nNeurons,nCh,nBinsHP,nBinsV,'uint8'); - end - else - matFileObj.avgHPWF=[];matFileObj.stdHPWF=[];matFileObj.histHPWF=[]; - end - end - - %remove mat ending from file base - if strcmp(par.saveFileName(end-3:end),'.mat') - par.saveFileName=par.saveFileName(1:end-4); - end - - %load files if matlab crashed during analysis - if exist([par.saveFileName postFix '_tmp.mat'],'file') & ~par.overwrite - load([par.saveFileName postFix '_tmp.mat']); - startChunk=max(1,lastGoodChunck+1); - disp('Loading temporary data saved following crash...'); - else - startChunk=1; - end - - tBinRaw=shiftdim(ceil(((1:windowSamplesRaw)/obj.currentDataObj.samplingFrequency(1)*1000)/par.binTRaw),-1); - tBinHP=shiftdim(ceil(((1:windowSamplesFiltered)/obj.currentDataObj.samplingFrequency(1)*1000)/par.binTHP),-1); - %VBins=(-par.maxV+par.binV/2):par.binV:par.maxV; - %pPreBaselineSamples=((obj.currentDataObj.samplingFrequency(1)/1000)*(par.preRawWindow-detectionPreSpikeWindow-1)):((obj.currentDataObj.samplingFrequency(1)/1000)*(par.preRawWindow-detectionPreSpikeWindow)); - %tBinsRaw=par.binTRaw/2:par.binTRaw:par.totalRawWindow; - %tBinsHP=par.binTHP/2:par.binTHP:par.totalFilteredWindow; - - try - tic; - %initiate arrays - fprintf('\nExtracting spikes from chunks (total %d): ',nChunks); - for i=startChunk:nChunks - fprintf('%d',i); - %get data - MAll=obj.currentDataObj.getData([],startTimes(i)-par.preRawWindow,endTimes(i)-startTimes(i)+par.totalRawWindow); %get all channels - MFAll=squeeze(filterObj.getFilteredData(MAll))'; %filter class needs unsqueezed input - MAll=squeeze(MAll)'; - nSamples=size(MAll,1); - %tAll=((1:nSamples)/obj.currentDataObj.samplingFrequency(1)*1000)-preRawWindow+startTimes(i); - nSpkAllTmp=zeros(1,nNeurons); - for j=1:nNeurons - tTmp=par.ss.t(par.ss.ic(3,j):par.ss.ic(4,j)); - tTmp=tTmp(find(tTmp>=startTimes(i) & tTmp< (endTimes(i)-par.totalRawWindow+par.preRawWindow) )); - nSpkTmp=numel(tTmp); - if nSpkTmp>0 %if spike rate is unreasonable, reject window (usually does not happen) - startIdx=1+round((tTmp-startTimes(i))*obj.currentDataObj.samplingFrequency(1)/1000); - idx=bsxfun(@plus,startIdx,(0:windowSamplesRaw-1)'); - WF=MAll(idx,:); - WF=permute(reshape(WF,[size(idx,1) size(idx,2) nCh]),[2 3 1]); - %WF=bsxfun(@minus,WF,mean(WF(:,:,pPreBaselineSamples),3)); - avgRawWF(j,:,:)=avgRawWF(j,:,:)+sum(WF,1); - stdRawWF(j,:,:)=stdRawWF(j,:,:)+sum(WF.^2,1); - - idx=idx(HPIdx,:); - WFH=MFAll(idx,:); - WFH=permute(reshape(WFH,[size(idx,1) size(idx,2) nCh]),[2 3 1]); - avgHPWF(j,:,:)=avgHPWF(j,:,:)+sum(WFH,1); - stdHPWF(j,:,:)=stdHPWF(j,:,:)+sum(WFH.^2,1); - if par.calcSpikeHistogram - for k=1:nCh - hVTmp=round((WF(:,k,:)+par.maxV)/(par.maxV*2/nBinsV)); %the reshape is important since otherwise when nSpkTmp==1 squeeze changes matrix from row to column - p=find(hVTmp>0 & hVTmp1 %if there is only one point to include in the statistics we can reject this trial. - htTmp=repmat(tBinRaw,[numel(tTmp) 1]); - if nSpkTmp>1 - histRawWF(j,k,:,:)=histRawWF(j,k,:,:)+shiftdim(uint8(accumarray([htTmp(p) hVTmp(p)],1,[nBinsRaw nBinsV])),-2); - else - histRawWF(j,k,:,:)=histRawWF(j,k,:,:)+shiftdim(uint8(accumarray(squeeze([htTmp(p) hVTmp(p)])',1,[nBinsRaw nBinsV])),-2); - end - - hVTmp=round((WFH(:,k,:)+par.maxV)/(par.maxV*2/nBinsV)); - p=find(hVTmp>0 & hVTmp1 - histHPWF(j,k,:,:)=histHPWF(j,k,:,:)+shiftdim(uint8(accumarray([htTmp(p) hVTmp(p)],1,[nBinsHP nBinsV])),-2); - else - histHPWF(j,k,:,:)=histHPWF(j,k,:,:)+shiftdim(uint8(accumarray(squeeze([htTmp(p) hVTmp(p)])',1,[nBinsHP nBinsV])),-2); - end - end - end - end - nSpkAllTmp(j)=nSpkAllTmp(j)+nSpkTmp; - elseif nSpkTmp>1000 - disp(['Rejecting neuron ' num2str(par.ss.ic(1:2,j)') ' due to >1000 spike count']); - end - end - nSpkTotal=nSpkTotal+nSpkAllTmp; - tChunk(i)=toc;tic; - lastGoodChunck=i; - fprintf('(%d) ',round(tChunk(i))); - end - - for i=1:nNeurons - if nSpkTotal(i)>0 - stdRawWF(i,:,:)=sqrt((stdRawWF(i,:,:)-avgRawWF(i,:,:))/(nSpkTotal(i)-1)); - stdHPWF(i,:,:)=sqrt((stdHPWF(i,:,:)-avgHPWF(i,:,:))/(nSpkTotal(i)-1)); - - avgRawWF(i,:,:)=avgRawWF(i,:,:)/nSpkTotal(i); - avgHPWF(i,:,:)=avgHPWF(i,:,:)/nSpkTotal(i); - end - end - - %save data - if par.keepAllInMemory - fprintf('Saving data...'); - save([par.saveFileName postFix],'avgRawWF','avgHPWF','stdRawWF','stdHPWF','neuronNames','histRawWF','histHPWF','par','nSpkTotal','-v7.3'); - end - fprintf('Deleting temporary files...'); - delete([par.saveFileName postFix '_tmp.mat']); - - catch errorMsg - disp('Extraction of fields crashed!!! Saving data in a temp file...'); - if i>1 - save([par.saveFileName postFix '_tmp.mat'],'avgRawWF','avgHPWF','stdRawWF','stdHPWF','neuronNames','histRawWF','histHPWF','par','nSpkTotal','lastGoodChunck','-v7.3'); - end - disp('Data saved!'); - rethrow(errorMsg); - end - fprintf('\nTriggered waveform analysis took (%f) hours\n',sum(tChunk)/60/60); - end %getSpikeTrigWF - - function obj=testMet(obj) - end - end %methods - ->>>>>>> upstream/master -end %class \ No newline at end of file diff --git a/dataAnalysisObjects/@MEAAnalysis/MEAAnalysis_old.m b/dataAnalysisObjects/@MEAAnalysis/MEAAnalysis_old.m deleted file mode 100644 index 3c7cfc5..0000000 --- a/dataAnalysisObjects/@MEAAnalysis/MEAAnalysis_old.m +++ /dev/null @@ -1,730 +0,0 @@ -classdef MEAAnalysis < handle - - properties - par - relevantFieldsXls - excelRecordingDataFileName - nTotalRecordings - gridSorterObj - gridSorterFolder - parPool4Batch = false; - - currentDataObj - currentRecName - currentPRec - currentMEAFiles - currentMEADir - currentAnalysisFolder - currentPlotFolder - currentExpFolder - - files - end - - properties (Constant) - xlsSheet=1; - titleLine=1; - startCol=1; - figResJPG=300; - defaultXlsFile='\\storage.laur.corp.brain.mpg.de\Data_3\Shein-IdelsonMark\DCMEA.xlsx'; - MCRackDir='MCRackData'; - end - - methods - - [data]=getSpikePositionEstimation(obj,varargin); - [data]=getSpikeInducedFields(obj,varargin); - [data,hand]=getCrossCorr(obj,varargin); - [data,hand]=getSpikeParams(obj,varargin); - - [hand,out]=plotSpikeInducedFields(obj,varargin); - [hand,out]=plotAvgSIFMap(obj,varargin); - [hand,out]=plotSIFPerNeuron(obj,varargin); - - %% MEAAnalysis - class constructor - function [obj]=MEAAnalysis(xlsFile) - if nargin==0 - obj=obj.getExcelData; - elseif nargin==1 - obj=obj.getExcelData(xlsFile); - end - end - %% getFileNames - function [obj,fileName]=getFileNames(obj,methodName) - %get the names of mat files associated with every method (or a specific method) - %[obj,fileName]=getFileNames(obj,methodName) - % methodName - the name of the method - % fileName - the mat file name associated with the method and a specific recording - if nargin==1 - methodNames=methods(obj); - handleMethods=methods('handle'); - uniqueMethods=setdiff(methodNames,handleMethods); - for i=1:numel(uniqueMethods) - obj.files.(uniqueMethods{i})=[obj.currentAnalysisFolder filesep uniqueMethods{i} '.mat']; - end - else - fileName=[obj.currentAnalysisFolder filesep methodName '.mat']; - obj.files.(methodName)=[obj.currentAnalysisFolder filesep methodName '.mat']; - end - end - - %% populate gridSorter object - function [obj,flag]=populateGridSorterObj(obj,gridSorterObj) - if ~isempty(obj.gridSorterObj) - disp('gridSorter object already exists'); - flag=1; - return; - end - if nargin==1 - obj.gridSorterObj=gridSorter(obj.currentDataObj); - elseif nargin==2 - obj.gridSorterObj=gridSorterObj; - end - [obj.gridSorterObj,flag]=obj.gridSorterObj.loadMetaData; - end - - %% batchProcessData - - function [outArgAll]=batchProcessData(obj,method,fieldName,fieldValues,varargin) - % run analysis on multiple recordings - % method is a string with the name of the requested method. fieldName and field value are used to select recordings, the latter is a cell array - % varargin can be used to forward input arguments to the method. - - %send e-mails when running long batch analysis - %{ - catch errorMsg - if obj.sendEMailMessages - sendMailViaGmail(obj.email4Messages,['An error occured while running runSpikeSorting on ' getenv('COMPUTERNAME') ' session ' num2str(i) '/' num2str(nExp)],errorMsg.getReport); - end - rethrow(errorMsg); - end - if obj.sendEMailMessages - sendMailViaGmail(obj.email4Messages,['runSpikeSorting completed on ' getenv('COMPUTERNAME') ,' session success: ' num2str(nExp)]); - end - %} - nOut=nargout; - nRec=numel(fieldValues); - - pMultiParam=cellfun(@(x) iscell(x),varargin(2:2:end)); - %check input validity - for i=find(pMultiParam) - if numel(varargin{i*2})~=nRec - disp(['Size of cell array args for arg: ' varargin{i*2-1} ' does not match the number of recordings']); - return; - end - end - - %change arguments with single value to cell arrays to fit the multi value arguments - if any(pMultiParam) - for i=find(~pMultiParam) - tmpCell=cell(1,nRec); - tmpCell=cellfun(@(x) varargin{i*2},tmpCell,'UniformOutput',0); - varargin{i*2}=tmpCell; - end - end - - fprintf(['Performing batch analysis on method ' method '\nAnalyzing recording number:']); - if obj.parPool4Batch & nRec>1 - parfor i=1:nRec - tmpObj=obj.setCurrentRecording([fieldName '=' fieldValues{i}]); - fprintf('Analyzing recording %s...\n',fieldValues{i}); - if any(pMultiParam) - tmpVaragrin=cellfun(@(x) x{i},varargin(2:2:end),'UniformOutput',0); - newVarargin={}; - newVarargin(1:2:numel(varargin))=varargin(1:2:end); - newVarargin(2:2:numel(varargin))=tmpVaragrin; - if nOut>0 - [outArgs]=tmpObj.(method)(newVarargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(newVarargin{:}); - end - else - if nOut>0 - [outArgs]=tmpObj.(method)(varargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(varargin{:}); - end - end - %return all non object variables - end - else - for i=1:nRec - tmpObj=obj.setCurrentRecording([fieldName '=' fieldValues{i}]); - fprintf('Analyzing recording %s...\n',fieldValues{i}); - if any(pMultiParam) - tmpVaragrin=cellfun(@(x) x{i},varargin(2:2:end),'UniformOutput',0); - newVarargin={}; - newVarargin(1:2:numel(varargin))=varargin(1:2:end); - newVarargin(2:2:numel(varargin))=tmpVaragrin; - if nOut>0 - [outArgs]=tmpObj.(method)(newVarargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(newVarargin{:}); - end - else - if nOut>0 - [outArgs]=tmpObj.(method)(varargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(varargin{:}); - end - end - %return all non object variables - end - end - end - - %% getVStimParams - still under development - function obj=getVStimParams(obj,VSFile) - error('During development!!!!!'); - if nargin==1 - VSFileLocation=dir([obj.currentMEAFiles{1}(1:end-7) '*.vs']); - if numel(VSFileLocation)==1 - VSFile = importdata(VSFiles.name); - else %try to use time stamps to evaluate the identitfy of the VSfile - startDate=obj.currentDataObj.startDate; - endDate=obj.currentDataObj.startDate; - d=dir(obj.currentDataObj); - end - end - disp(['Extracting information from: ' VSFile]); - - end - - %% getSpikeSorting - function obj=getSpikeSorting(obj,varargin) - %default parameters - parseObj = inputParser; - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - obj=obj.populateGridSorterObj; - %obj.gridSorterObj.clusteringMinSpikesTotal = 2; - %obj.gridSorterObj.clusteringMinNSpikesCluster = 1; - - if strcmp(obj.par.MEA_Layout,'40_Hexa') - obj.gridSorterObj.localGridSize = 9; - obj.gridSorterObj.localGridExt = 3; - - else - obj.gridSorterObj.localGridSize = 3; - obj.gridSorterObj.localGridExt = 1; - end - - if strcmp(obj.par.MEA_Layout,'100_9x4_FlexMEA120') - obj.gridSorterObj.filterLowPassPassCutoff=1000; - obj.gridSorterObj.filterLowPassStopCutoff=1500; - obj.gridSorterObj.detectionSpikeDetectionThresholdStd=7; - end - - if overwrite - obj.gridSorterObj.overwriteAll=1; - obj.gridSorterObj.deleteSortingFiles; - end - - obj.gridSorterFolder=obj.gridSorterObj.sortingDir; - - % Start sorting - obj.gridSorterObj=obj.gridSorterObj.runSorting; - - end %runSpikeSorting - - function getCSDMovie(obj) - obj.checkFileRecording; - - parseObj = inputParser; - - electrodePitch=100; - frameRate=30; - videoQuality=90; - positionRealSpace=[]; - dataType='CSD';%'pot'/'CSD' - electrodeMarker='.'; - saveData=false; %to only calculate CSD without making movie - dataFolder=[cd filesep 'CSDProfiles']; - makeMovie=true; - saveFullMatrices=false; - - addParameter(parseObj,'avgHPWF',[],@isnumeric); - addParameter(parseObj,'stdHPWF',[],@isnumeric); - addParameter(parseObj,'preSpikeMs',0.5,@isnumeric); - addParameter(parseObj,'postSpikeMs',2.5,@isnumeric); - addParameter(parseObj,'minDist',150,@isnumeric); - - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %obj.checkFileRecording(obj.files.getSpikePositionEstimation,'Single cell position estimation file missing, please run getSpikePositionEstimation'); - - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - saveFileName=obj.files.(funName); - - if exist(saveFileName,'file') & ~overwrite - if nargout==1 - data=load(saveFileName); - else - disp('spike SNR file already exists'); - end - return; - end - - %populate grid sorter object - obj=populateGridSorterObj(obj); - if ~all(obj.gridSorterObj.sortingFileNames.postProcessingAnalysisExist) - disp('Post processing data for spike sorting does not exist, please run spikePostProcessing method in grid sorter'); - return; - else - if isempty(avgLongWF) - disp('loading average spike triggered waveforms...'); - load(obj.gridSorterObj.sortingFileNames.postProcessingAnalysisFile,'avgLongWF'); - fprintf('done\n'); - end - if isempty(neuronNames) - load(obj.gridSorterObj.sortingFileNames.postProcessingAnalysisFile,'neuronNames'); - end - end - - - - - %% - [nNeu,nCh,nSamples]=size(WF); - timeSamples=(1:nSamples)/Fs*1000-preMs; - spikeSample=round(preMs/1000*Fs); - - %calculate electrode positions - elecPos=NaN(nCh,3); - En2=En; - for i=1:nCh - [n,m]=find(En2==ch(i)); - if ~isempty(n) - elecPos(i,:)=[m n ch(i)]; - else - elecPos(i,:)=ch(i); - end - end - elecPos(:,1:2)=elecPos(:,1:2)*electrodePitch; - - if saveData - mkdir(dataFolder); - disp(['Data will be saved in ' dataFolder]); - end - - samplingPosX=min(elecPos(:,1)):10:max(elecPos(:,1)); - samplingPosY=min(elecPos(:,2)):10:max(elecPos(:,2)); - [XuM,YuM]=meshgrid(samplingPosX,samplingPosY); - CSD=zeros(size(WF)); - - for i=1:nNeu - mM=squeeze(WF(i,:,:)); - k = kcsd2d(elecPos(:,1:2), mM(elecPos(:,3),:), 'manage_data', 0, 'X', XuM, 'Y', YuM); - - if strcmp(dataType,'CSD') - dynamics=k.CSD_est; - elseif strcmp(dataType,'pot') - dynamics=k.pots_est; - else - error('The parameter dataType was not chosen correctly'); - end - - for j=1:nCh - [pTmpX,pTmpY]=find(XuM==elecPos(j,1) & YuM==elecPos(j,2)); - CSD(i,j,:)=dynamics(pTmpX,pTmpY,:); - end - - %[hPlot,scaleFac]=activityTracePhysicalSpacePlot([],1:120,squeeze(CSDelec(i,:,:)),En); - %[hPlot,scaleFac]=activityTracePhysicalSpacePlot([],1:120,squeeze(WF(i,:,:)),En); - if saveFullMatrices - save([dataFolder filesep 'CSD_Neuron_' num2str(neuronNames(1,i)) '-' num2str(neuronNames(2,i))],'dynamics','dataType','preMs','Fs','XuM','YuM','elecPos'); - end - - if makeMovie - mn=min(min(min(dynamics(:,:,(spikeSample+40):end),[],1),[],2),[],3); - mx=max(max(max(dynamics(:,:,(spikeSample+40):end),[],1),[],2),[],3); - l=max(abs([mn,mx])); - cLim=[-l l]; - - - writerObj = VideoWriter([dataFolder filesep dataType '_neu' num2str(neuronNames(1,i)) '_' num2str(neuronNames(2,i)) '.mp4'],'MPEG-4'); - writerObj.FrameRate=frameRate; - writerObj.Quality=videoQuality; - open(writerObj); - - F=figure('position',[50 50 550 500],'color','w');h=axes; - imagesc(XuM(1,:),YuM(:,1),squeeze(dynamics(:,:,i)),cLim);set(gca,'YDir','normal');hold on; - plot(elecPos(:,1),elecPos(:,2),'.'); - %text(elecPos(:,1),elecPos(:,2),num2str(elecPos(:,3))); - cb=colorbar; - set(cb,'position',[0.9167 0.7600 0.0117 0.1650],'Ticks',round([-l 0 l])); - cb.Label.Position=[4.2 0 0]; - ylab=ylabel(cb,dataType); - ylab.Position=[4.2 0 0]; - - xlabel('\mum'); - ylabel('\mum'); - - axis equal tight; - set(h,'nextplot','replacechildren'); - set(F,'Renderer','zbuffer'); - - if isempty(positionRealSpace) - [~,pPeak]=min(min(min(dynamics(:,:,(spikeSample-10):(spikeSample+10)),[],1),[],2),[],3); - CSDSpikePeak=squeeze(mean(dynamics(:,:,(spikeSample-10+pPeak-5):(spikeSample-10+pPeak+5)),3)); - [ySpk,xSpk] = find(CSDSpikePeak == min(min(CSDSpikePeak))); - cellBodyPos=[XuM(1,xSpk) YuM(ySpk,1)]; - else - cellBodyPos=positionRealSpace(:,i); - end - - for j=1:nSamples - tmpImg=squeeze(dynamics(:,:,j)); - - h(1)=imagesc(XuM(1,:),YuM(:,1),tmpImg,cLim);hold on; - h(2)=plot(elecPos(:,1),elecPos(:,2),electrodeMarker,'color',[0.8 0.8 0.8]); - h(3)=line([XuM(1,1) XuM(1,end)],[cellBodyPos(2) cellBodyPos(2)],'color','k'); - h(4)=line([cellBodyPos(1) cellBodyPos(1)],[YuM(1,1) YuM(end,1)],'color','k'); - - title([num2str(timeSamples(j),'% 10.1f') ' ms']); - - frame = getframe(F); - writeVideo(writerObj,frame); - delete(h); - end - close(writerObj); - close(F); - end - end - - end - - %% getHighSNRNeurons - function [data]=getSpikeSNR(obj,varargin) - - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'avgHPWF',[],@isnumeric); - addParameter(parseObj,'stdHPWF',[],@isnumeric); - addParameter(parseObj,'preSpikeMs',0.5,@isnumeric); - addParameter(parseObj,'postSpikeMs',2.5,@isnumeric); - addParameter(parseObj,'minDist',150,@isnumeric); - - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %make parameter structure - par=parseObj.Results; - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %obj.checkFileRecording(obj.files.getSpikePositionEstimation,'Single cell position estimation file missing, please run getSpikePositionEstimation'); - - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - saveFileName=obj.files.(funName); - - if exist(saveFileName,'file') & ~overwrite - if nargout==1 - data=load(saveFileName); - else - disp('spike SNR file already exists'); - end - return; - end - - %populate grid sorter object - obj=populateGridSorterObj(obj); - if ~all(obj.gridSorterObj.sortingFileNames.STWaveformExist) - disp('Post processing data for spike sorting does not exist, please run spikePostProcessing method in grid sorter'); - else - if isempty(avgHPWF) || isempty(stdHPWF) - disp('loading average+std spike triggered waveforms...'); - load(obj.gridSorterObj.sortingFileNames.STWaveformFile,'avgHPWF','stdHPWF','neuronNames'); - fprintf('done\n'); - end - end - - [Xc,Yc]=obj.currentDataObj.getElectrodePositions; - - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - saveFileName=obj.files.(funName); - - if exist(saveFileName,'file') & ~overwrite - if nargout==1 - data=load(saveFileName); - else - disp('spike SNR file already exists'); - end - return; - end - - Fs_ms=obj.currentDataObj.samplingFrequency(1)/1000; - tSpk=(-obj.gridSorterObj.detectionPreSpikeWindow+1/Fs_ms):(1/Fs_ms):obj.gridSorterObj.detectionPostSpikeWindow; - pSpk=tSpk>-preSpikeMs & tSpk0 - %collect all files in case multiple files were inserted (comma separated) or group format and couple folder with file name - allFullFiles=[]; - for i=1:nRec, - if ~isempty(regexp(obj.par.MEAfiles{pRec(i)},'*')) %for cases in which the files are give as 'ctrl0*.mcd' - multipleFiles=dir([obj.par.folder{pRec(i)} filesep obj.par.MEAfiles{pRec(i)}]); - multipleFiles={multipleFiles.name}; - else - multipleFiles=regexp(obj.par.MEAfiles{pRec(i)},',','split'); - end - allFullFiles=[allFullFiles cellfun(@(x) [obj.par.folder{pRec(i)} filesep x],multipleFiles,'UniformOutput',0)]; - end - obj.currentMEAFiles=allFullFiles'; - - %check which data acquisition system was used - if strcmp(allFullFiles{1}(end-3:end),'.mcd') %MCRack recording - if ispc - obj.currentDataObj=MCRackRecording(obj.currentMEAFiles'); - elseif isunix - obj.currentDataObj=MCRackRecordingNeuroshare(obj.currentMEAFiles'); - end - elseif strcmp(allFullFiles{1}(end-3:end),'.rhd') %Intan recording - obj.currentDataObj=Intan(obj.currentMEAFiles); - elseif isdir(allFullFiles{1}) %OE recording - obj.currentDataObj=OERecording(obj.currentMEAFiles); - else - error(['dataRecording class could not be determined from the file extension: ' num2str(allFullFiles{1}(end-3:end))]); - end - obj.gridSorterObj=[]; %clear any existing grid sorter object from the past - - %create data object - obj.currentRecName=recName; - obj.currentPRec=pRec; - - %define related folders and construct correspondin file names - obj.currentAnalysisFolder=[obj.par.folder{pRec(1)} filesep 'analysis' filesep recName]; - obj.currentPlotFolder=[obj.par.folder{pRec(1)} filesep 'plots' filesep recName]; - obj.currentExpFolder=obj.par.folder{pRec(1)}; - obj=obj.getFileNames; - - [stat,mess,messid]=mkdir(obj.currentAnalysisFolder); %creates analysis directory if not existing - [stat,mess,messid]=mkdir(obj.currentPlotFolder); %creates analysis directory if not existing - fprintf('Current exp. set to: %s-%s @ %s\n',obj.par.MEAfiles{pRec(1)},obj.par.MEAfiles{pRec(end)},obj.par.folder{pRec(1)}); - elseif numel(pRec)==0 - disp('Selected recording/s were not found in recording list'); - return; - end - - elseif nargin==1 - disp('Not enough inputs, specify a recording name or number'); - return; - end - end - - %% checkFile - check the existance of a data file and a recording object - function isDone=checkFileRecording(obj,fileName,message) - if isempty(obj.currentDataObj) - error('No data recording object selected!!!!'); - end - isDone=0; - if nargin>1 - if ~exist(fileName,'file') - if nargin==2 - if nargout==0 - error('Relevant analysis file missing, please first run relevant function'); - else - isDone=0; - end - else - error(message); - end - else - isDone=1; - end - end - end - - end - -end \ No newline at end of file diff --git a/dataAnalysisObjects/@MEAAnalysis/SIFtemptates.mat b/dataAnalysisObjects/@MEAAnalysis/SIFtemptates.mat deleted file mode 100644 index e8e5d01..0000000 Binary files a/dataAnalysisObjects/@MEAAnalysis/SIFtemptates.mat and /dev/null differ diff --git a/dataAnalysisObjects/@MEAAnalysis/getCrossCorr.m b/dataAnalysisObjects/@MEAAnalysis/getCrossCorr.m deleted file mode 100644 index 33a0874..0000000 --- a/dataAnalysisObjects/@MEAAnalysis/getCrossCorr.m +++ /dev/null @@ -1,103 +0,0 @@ -function [data,hand]=getCrossCorr(obj,varargin) -% [data,hand]=getCrossCorr(obj,varargin) -% Function purpose : Calculate spike train cross-correlation in [ms] -% -% Last updated : 20/10/16 - -obj.checkFileRecording; -parseObj = inputParser; - -addParameter(parseObj,'maxLag',500,@isnumeric); %ms -addParameter(parseObj,'bin',1,@isnumeric); %ms -addParameter(parseObj,'hand',[]); -addParameter(parseObj,'fieldPar',[]); -addParameter(parseObj,'saveFileName',[]); -addParameter(parseObj,'overwrite',false,@isnumeric); -addParameter(parseObj,'inputParams',false,@isnumeric); - -parseObj.parse(varargin{:}); -if parseObj.Results.inputParams - disp(parseObj.Results); - return; -end -%evaluate all input parameters in workspace -for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); -end -%make parameter structure -par=parseObj.Results; -load(obj.files.getSpikeInducedFields,'fieldPar'); - -[funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; -if isempty(saveFileName) - saveFileName=obj.files.(funName); -end - -obj.checkFileRecording(obj.files.getSpikeInducedFields,'Spike induced fields file missing, please run getSpikeInducedFields'); - -%load data if existing or contrinue with analysis -if exist(saveFileName,'file') & ~overwrite - if nargout==1 - data=load(saveFileName); - else - disp('Cross-correlation analysis already exists. use overwrite to run again'); - end - return; -end - -%populate grid sorter object -obj=populateGridSorterObj(obj); -S=obj.gridSorterObj.getSortedData({'t','ic'}); -nNeu=size(S.ic,2); -%% Main code - -%calculate cross correlation -[C]=crossCorrRaster(round(S.t/bin),S.ic,maxLag); - -%shuffled cross correlation -nShuffles=5; -CShuf=zeros(nNeu,nNeu,maxLag,nShuffles); -for i=1:nShuffles - tShuf=S.t(randperm(numel(S.t))); - for j=1:nNeu - tShuf(S.ic(3,j):S.ic(4,j))=sort(tShuf(S.ic(3,j):S.ic(4,j))); - end - CShuf(:,:,:,i)=crossCorrRaster(round(tShuf/bin),S.ic,maxLag); -end - -%save crossCorr CShuf C; - -%shuffled cross correlation within sub-populations -pI=find(fieldPar.classIE==2); -pE=find(fieldPar.classIE==3); - -%shuffled cross correlation - only within sub-population of excitatory and inhibitory neurons -CIEShuf=zeros(nNeu,nNeu,maxLag,nShuffles); -for i=1:nShuffles - tShuf=zeros(1,numel(S.t)); - idx=[]; - for j=pE - idx=[idx S.ic(3,j):S.ic(4,j)]; - end - tShuf(idx)=S.t(idx(randperm(numel(idx)))); - - idx=[]; - for j=pI - idx=[idx S.ic(3,j):S.ic(4,j)]; - end - tShuf(idx)=S.t(idx(randperm(numel(idx)))); - for j=1:nNeu - tShuf(S.ic(3,j):S.ic(4,j))=sort(tShuf(S.ic(3,j):S.ic(4,j))); - end - CIEShuf(:,:,:,i)=crossCorrRaster(round(tShuf/bin),S.ic,maxLag); -end - - -%save all data -fprintf('\nSaving results...'); -save(saveFileName,'pI','pE','CIEShuf','C','CShuf','par'); - -fprintf('Done!\n'); - -%save(saveFileName,'pMaxField','-append'); - diff --git a/dataAnalysisObjects/@MEAAnalysis/getSpikeInducedFields.m b/dataAnalysisObjects/@MEAAnalysis/getSpikeInducedFields.m deleted file mode 100644 index ac86bea..0000000 --- a/dataAnalysisObjects/@MEAAnalysis/getSpikeInducedFields.m +++ /dev/null @@ -1,750 +0,0 @@ -function [data,hand]=getSpikeInducedFields(obj,varargin) -% [data,hand]=getSpikeInducedFields(obj,varargin) -% Function purpose : Calculate distribution of post spike fields (PSF) -% -% Last updated : 20/10/16 - -obj.checkFileRecording; - -parseObj = inputParser; - -addParameter(parseObj,'fieldPar',[]); - -addParameter(parseObj,'electrodePitch',[],@isnumeric); -addParameter(parseObj,'nearestNeighborsDistance',190,@isnumeric); -addParameter(parseObj,'SIFStartMs',5,@isnumeric); -addParameter(parseObj,'SIFEndMs',30,@isnumeric); -addParameter(parseObj,'preSpikePeakMs',2,@isnumeric); %this can be larger since the exact spike time is defined by the algorithm -addParameter(parseObj,'postSpike0CrossLimMs',20,@isnumeric); -addParameter(parseObj,'medianFilterLengthMs',7,@isnumeric); -addParameter(parseObj,'spikePeakWidthMs',1,@isnumeric); -addParameter(parseObj,'badChannels',[]); -addParameter(parseObj,'usePostProcessing',false); %to use the old STAs from the postProcessingMethod - -addParameter(parseObj,'smartInterSmoothness',0.0001,@isnumeric); %smoothing [0 1] - higher values fit is close to data (no low pass), 0.0000005 - more low pass -addParameter(parseObj,'weightFunctionStdMs',7,@isnumeric); -addParameter(parseObj,'maxPostSpikeWidthMs',3,@isnumeric); -addParameter(parseObj,'stdThresholdCrossingSpikeInitiation',4,@isnumeric); -addParameter(parseObj,'preSpikeMinInitiationMs',1.5,@isnumeric); -addParameter(parseObj,'preSpikeMaxInitiationMs',0.5,@isnumeric); -addParameter(parseObj,'postSpikeCorrMs',10,@isnumeric); %5 -addParameter(parseObj,'postSpikeReturn2BaselineMs',50,@isnumeric); % -addParameter(parseObj,'baselineSubstructionMethod','preSpikeAverage',@isstr); % 'spikeOnsetOnLowpass','preSpikeAverage','interpolatedBaseline' -addParameter(parseObj,'useInterpolatedBaseline4StrongShifts',true,@isnumeric); %if true uses interplation only in cases of extreme change in baseline during field -addParameter(parseObj,'saveLowPassBaseline',false,@isnumeric); -addParameter(parseObj,'saveBaselineSubstractedSIF',false,@isnumeric); -addParameter(parseObj,'saveBaselineSubstractedRaw',false,@isnumeric); - -addParameter(parseObj,'IEclassificationMethod','templateCorr',@isstr); %'templateCorr','SIFAmpPolarity'; -addParameter(parseObj,'ECorrTh',0,@isnumeric); -addParameter(parseObj,'ICorrTh',0,@isnumeric); -addParameter(parseObj,'classIE',true,@isnumeric); %[true,false,vec]if false, all assumed inhibitory, can also be a vector with excitatory (3) and inhibitory (2) classifications (or 0 for require classification) - -addParameter(parseObj,'PSFMethod','maxBaselineSubstracted',@isstr);% 'max','maxBaselineSubstracted','oldNormMax','integralBaselineSubstracted', -addParameter(parseObj,'fieldPositionMethod','interpolatedMaximaSpline',@isstr);%'maxima','interpolatedMaxima','COM','interpolatedMaximaSpline' - -addParameter(parseObj,'fieldEdgeBand',10,@isnumeric); %the band arround the electrode array edge (from farthest electrode) to include in stats of field positions (if positive, takes also neurons outside the array) - -addParameter(parseObj,'triangulateCellPosition',true,@isnumeric); - -%variables calculated by the algorithm -addParameter(parseObj,'lowpassWF',[],@isnumeric); -addParameter(parseObj,'lowpassWFBaseline',[],@isnumeric); -addParameter(parseObj,'fileNameSTWaveform',[],@isstr); - -%parameters for running on external data sets -addParameter(parseObj,'cellPosition',[],@isnumeric); % [2 x nNeurons] correction to position based on spike shape [um] -addParameter(parseObj,'avgRawWF',[],@isnumeric); %[nNeurons,nCh,nSamples] to give STA as direct input instead of loading -addParameter(parseObj,'neuronNames',[]); -addParameter(parseObj,'preSpikeMs',[]); -addParameter(parseObj,'saveFileName',[]); - -%debuggin plots -addParameter(parseObj,'hand',[]); %handle for plots -addParameter(parseObj,'plotIEClass',0,@isnumeric); -addParameter(parseObj,'plotMaxWFAll',0,@isnumeric); -addParameter(parseObj,'plotLowPassFilters',false,@isnumeric); -addParameter(parseObj,'plotClassPerNeuron',false,@isnumeric); - -addParameter(parseObj,'overwrite',false,@isnumeric); -addParameter(parseObj,'inputParams',false,@isnumeric); - -parseObj.parse(varargin{:}); -if parseObj.Results.inputParams - disp(parseObj.Results); - return; -end -%evaluate all input parameters in workspace -for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); -end -%make parameter structure -par=parseObj.Results; - -[funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; -if isempty(saveFileName) - saveFileName=obj.files.(funName); -end - -%load data if existing or contrinue with analysis -if exist(saveFileName,'file') & ~overwrite - if nargout==1 - data=load(saveFileName); - else - disp('spike induced fields analysis already exists. use overwrite to run again'); - end - return; -end - -%check that triangulation was already performed -if triangulateCellPosition && isempty(cellPosition) - obj.checkFileRecording(obj.files.getSpikePositionEstimation,'Single cell position estimation file missing, please run getSpikePositionEstimation'); -end - -%populate grid sorter object -obj=populateGridSorterObj(obj); -if isempty(avgRawWF) - disp('loading average spike triggered waveforms...'); - if isempty(fileNameSTWaveform) - if exist(obj.files.getSpikeTrigWF,'file') - load(obj.files.getSpikeTrigWF,'avgRawWF','neuronNames','par'); - preSpikeMs=par.preRawWindow; - else - if ~obj.gridSorterObj.sortingFileNames.STWaveformExist - disp('Post processing data for spike sorting does not exist, please run spikePostProcessing method in grid sorter'); - return; - else - load(obj.gridSorterObj.sortingFileNames.STWaveformFile,'avgRawWF','neuronNames'); - preSpikeMs=obj.gridSorterObj.postPreRawWindow; - warning('Getting spike triggered data from grid sorter!!!! In the future, run getSpikeTrigWF from MEAAnalysis'); - end - end - else - avgRawWF=load(fileNameSTWaveform,'avgRawWF','neuronNames','par'); - preSpikeMs=avgRawWF.par.preRawWindow; - neuronNames=avgRawWF.neuronNames; - avgRawWF=avgRawWF.avgRawWF; - end - fprintf('done\n'); -end -if isempty(neuronNames) %for old cases where neuronNames did not exist in STWaveformFile - Should be removed in the future - load(obj.gridSorterObj.sortingFileNames.postProcessingAnalysisFile,'neuronNames'); -end - -%assign parameters -ch=obj.currentDataObj.channelNumbers; -En=obj.currentDataObj.chLayoutNumbers; -Fs=obj.currentDataObj.samplingFrequency(1); - -%% Main code - general calculations -SIFStartSamples=SIFStartMs*Fs/1000; -SIFEndSamples=SIFEndMs*Fs/1000; -preSpikeSamples=preSpikeMs*Fs/1000; -preSpikePeakSamples=preSpikePeakMs*Fs/1000; -spikePeakWidthSamples=spikePeakWidthMs*Fs/1000; -maxPostSpikeWidthSamples=maxPostSpikeWidthMs*Fs/1000; -postSpikeCorrSamples=postSpikeCorrMs*Fs/1000; -weightFunctionStdSamples=weightFunctionStdMs*Fs/1000; -preSpikeMinInitiationSamples=preSpikeMinInitiationMs*Fs/1000; -preSpikeMaxInitiationSamples=preSpikeMaxInitiationMs*Fs/1000; - -medianFilterSamples=round(medianFilterLengthMs*Fs/1000/2)*2+1; %has to be an odd number -postSpike0CrossLimSamples=postSpike0CrossLimMs*Fs/1000; -return2BaselineSamples=postSpikeReturn2BaselineMs*Fs/1000+preSpikeSamples; - -[nNeurons,nCh,nSamples]=size(avgRawWF); -timeVec=(1:nSamples)/Fs*1000-preSpikeMs; - -%Build inverse map between electrode and location -if ~isempty(electrodePitch) - [Xc,Yc]=obj.currentDataObj.getElectrodePositions(electrodePitch); -else - [Xc,Yc]=obj.currentDataObj.getElectrodePositions; - electrodePitch=obj.currentDataObj.electrodePitch; -end - -% get the channel with max spike for extimating spike remove segment (amplitude calculated relative to the segment just before the spike) -maxSpikeAmp=max( abs( bsxfun(@minus, avgRawWF(:,:,(preSpikeSamples-spikePeakWidthSamples/2):(preSpikeSamples+spikePeakWidthSamples/2)),... - mean(avgRawWF(:,:,(preSpikeSamples-3*spikePeakWidthSamples/2):(preSpikeSamples-spikePeakWidthSamples)),3) )) ,[],3); -[~,pMaxSpikeElec]=max( maxSpikeAmp ,[],2); -for i=1:nCh - pNeighbors{i}=find(sqrt((Xc-Xc(i)).^2+(Yc-Yc(i)).^2)<=nearestNeighborsDistance); -end - -if strcmp(baselineSubstructionMethod,'interpolatedBaseline') || useInterpolatedBaseline4StrongShifts || saveLowPassBaseline - calculateInterplatedBaseline=1; -else - calculateInterplatedBaseline=0; -end - -%% pre-process the input waveforms -if isempty(lowpassWF) || (isempty(lowpassWFBaseline) && calculateInterplatedBaseline) - fprintf('Removing spikes from average WFs: '); - - lowpassWF=zeros(size(avgRawWF)); - if calculateInterplatedBaseline - lowpassWFBaseline=zeros(size(avgRawWF)); - end - - pBaseline=1:(preSpikePeakSamples-preSpikeMinInitiationSamples); - preExtension=round(preSpikePeakSamples); %extend the detection point by a few samples - - for i=1:nNeurons - fprintf('%d,',i); - pNeighborsMaxSpkElec=pNeighbors{pMaxSpikeElec(i)}; - if numel(pNeighborsMaxSpkElec)==1 - warning('There was only one nearest neighbohr used, consider changing ''nearestNeighborsDistance'' parameters!!!'); - end - %extract the initiation segment right before the spike (on nearest neigbohrs) and remove the mean of the initial part of this segment so that all segments start at 0 - spikeInitiationWF=squeeze(avgRawWF(i,pNeighborsMaxSpkElec,(preSpikeSamples-preSpikePeakSamples):preSpikeSamples));% - spikeInitiationWF=bsxfun(@minus,spikeInitiationWF,mean(spikeInitiationWF(:,pBaseline),2) ); - %calculate the spike onset (tr) according to where std increases rapidely over different electrode - stdProfile=std(spikeInitiationWF); - pSpikeOnset=min([preSpikePeakSamples-preSpikeMaxInitiationSamples,find(stdProfile > mean(stdProfile(pBaseline)) + stdThresholdCrossingSpikeInitiation*std(stdProfile(pBaseline)),1,'first')-1]); - - pSpikeStart(i)=(preSpikeSamples-preSpikePeakSamples+pSpikeOnset-preExtension); - pSpikeSoftEnd=(preSpikeSamples+maxPostSpikeWidthSamples); - - %weights for slow synaptic potential extraction - w1=ones(1,nSamples); - w1(pSpikeStart(i) : pSpikeSoftEnd)=0; - w1((pSpikeSoftEnd+1):(pSpikeSoftEnd+weightFunctionStdSamples*3))=1-exp(-( (1:weightFunctionStdSamples*3)/weightFunctionStdSamples).^2); - lowpassWF(i,:,:) = csaps(1:nSamples,squeeze(avgRawWF(i,:,:)),smartInterSmoothness,1:nSamples,w1); - - %weights for baseline extraction - if calculateInterplatedBaseline - w2=ones(1,nSamples); - w2(pSpikeStart(i) : return2BaselineSamples)=0; - w2((return2BaselineSamples+1):end)=1-exp(-( (1:(nSamples-return2BaselineSamples))/weightFunctionStdSamples/2).^2); - w2(1:pSpikeStart(i))=1-exp(-( (pSpikeStart(i):-1:1)/weightFunctionStdSamples/3).^2); - lowpassWFBaseline(i,:,:) = csaps(1:nSamples,squeeze(lowpassWF(i,:,:)),1e-6,1:nSamples,w2); - end - %lowpassWFBaseline(i,:,:) = lowpassWF(i,:,:); - - %lowpassWFBaseline(i,:,(pSpikeStart(i)-50):1200) = interp1([1:(pSpikeStart(i)-50) 1200:2000],squeeze(lowpassWF(i,:,[1:(pSpikeStart(i)-50) 1200:2000]))',(pSpikeStart(i)-50):1200)'; - - %plotting - if plotLowPassFilters - h(1)=subplot(2,3,1); - plot(timeVec,squeeze(avgRawWF(i,pMaxSpikeElec(i),:)),'r');hold on; - if calculateInterplatedBaseline - plot(timeVec,squeeze(lowpassWFBaseline(i,pMaxSpikeElec(i),:)),'color',[0.5 0.5 0.5]); - end - plot(timeVec,squeeze(lowpassWF(i,pMaxSpikeElec(i),:)),'b'); - plot(timeVec,(w1-1)*50); - plot(timeVec,(w2-1)*50); - - xlabel('Time [ms]');axis tight; - title(['Max electrode-neuron: ' num2str(neuronNames(:,i)')]); - legend({'WF','base','LP','W_{SIF}','W_{base}'},'Location','southeast','box','off'); - - spikeZoom=squeeze(avgRawWF(i,pNeighbors{pMaxSpikeElec(i)},(preSpikeSamples-preSpikePeakSamples):(preSpikeSamples+SIFEndSamples)));% - spikeZoom=bsxfun(@minus,spikeZoom,mean(spikeZoom(:,200),2) ); - h(2)=subplot(2,3,4); - plot(timeVec((preSpikeSamples-preSpikePeakSamples):(preSpikeSamples+SIFEndSamples)),spikeZoom'); - xlabel('Time [ms]');axis tight; - title('Spike Zoom- raw baseline sub'); - - h(3)=subplot(2,3,[2 6]); - [hPlot,scaleFac]=activityTracePhysicalSpacePlot(h(3),obj.currentDataObj.channelNumbers,squeeze(avgRawWF(i,:,:)),En,'traceColor','r','DrawElectrodeNumbers',1);hold on; - [hPlot]=activityTracePhysicalSpacePlot(h(3),obj.currentDataObj.channelNumbers,squeeze(lowpassWF(i,:,:)),En,'scaleFac',scaleFac);hold on; - if calculateInterplatedBaseline - [hPlot]=activityTracePhysicalSpacePlot(h(3),obj.currentDataObj.channelNumbers,squeeze(lowpassWFBaseline(i,:,:)),En,'scaleFac',scaleFac,'traceColor',[0.5 0.5 0.5]); - end - - pause; - delete(h); - end - end - fprintf(' done!\n'); -end - -%Remove waveforms of bad channels -if ~isempty(badChannels) - [~,pBadCh]=intersect(ch,badChannels); - [~,pGoodCh]=setdiff(ch,badChannels); - lowpassWF(:,pBadCh,:)=NaN; - lowpassWFBaseline(:,pBadCh,:)=NaN; -end -%% Baseline substruction -if strcmp(baselineSubstructionMethod,'spikeOnsetOnLowpass') - %baselineSubstractedSIF=bsxfun(@minus,lowpassWF,lowpassWF(:,:,preSpikeSamples-preSpikePeakSamples)); %substracting a one point value is ok since it is done on the low-passed waveform - baselineSubstractedSIF=bsxfun(@minus,lowpassWF,lowpassWF(:,:,preSpikeSamples)); %substracting a one point value is ok since it is done on the low-passed waveform - baselineSubstractedRaw=bsxfun(@minus,avgRawWF,lowpassWF(:,:,preSpikeSamples)); %substracting a one point value is ok since it is done on the low-passed waveform -elseif strcmp(baselineSubstructionMethod,'preSpikeAverage') - preBaseline=median(lowpassWF(:,:,(preSpikeSamples-preSpikePeakSamples):(preSpikeSamples-preSpikeMinInitiationSamples)),3); - baselineSubstractedSIF=bsxfun(@minus,lowpassWF,preBaseline); - baselineSubstractedRaw=bsxfun(@minus,avgRawWF,preBaseline); -elseif strcmp(baselineSubstructionMethod,'interpolatedBaseline') - baselineSubstractedSIF=lowpassWF-lowpassWFBaseline; - baselineSubstractedRaw=avgRawWF-lowpassWFBaseline; -end - -%use lowpass interpolation method of baseline estimation for situations in which there is an extreme trend in the field over the duration of the sif -maxBaselineShift=20; -maxBaselineShiftFractionElecs=0.2; -if useInterpolatedBaseline4StrongShifts - preBaseline=median(lowpassWF(:,:,1:200),3); - postBaseline=median(lowpassWF(:,:,(end-200):end),3); - pInterpolatedBaseline=mean(abs(preBaseline-postBaseline)>maxBaselineShift,2)>maxBaselineShiftFractionElecs; %if at least 20% of electrodes have a transition of more than 30uV in baseline - baselineSubstractedSIF(pInterpolatedBaseline,:,:)=lowpassWF(pInterpolatedBaseline,:,:)-lowpassWFBaseline(pInterpolatedBaseline,:,:); - baselineSubstractedRaw(pInterpolatedBaseline,:,:)=avgRawWF(pInterpolatedBaseline,:,:)-lowpassWFBaseline(pInterpolatedBaseline,:,:); -end - -%set the main samples for field estimation based on time creteria -pRelevantSamples=(preSpikeSamples+SIFStartSamples):(preSpikeSamples+SIFEndSamples); -%pRelevantSamples=(preSpikeSamples):(preSpikeSamples+SIFEndSamples); - - -%% Calculate polarity score according to max field for classification - -%build extended grid -nNeighbors=2; -[nRowsTmp,nColsTmp]=size(En); -EnExt=NaN(nRowsTmp+nNeighbors*2,nColsTmp+nNeighbors*2); -EnExt(1+nNeighbors:end-nNeighbors,1+nNeighbors:end-nNeighbors)=En; -pPeakElectrode=ceil((nNeighbors+2)^2/2); - -%remove bad channels -if ~isempty(badChannels) - [~,pBadChEnExt]=intersect(EnExt,badChannels); - EnExt(pBadChEnExt)=NaN; -end - -%find max amp electrode - -%[~,pSpikeElec]=min(avgRawWF(:,:,preSpikeSamples+1),[],2); - -T=load('SIFtemptates.mat'); -%resample template to fit the times of the measured data -T.resTemplate = interp1(T.t_ms,T.templates',timeVec,'spline')'; -%put zeros in resampled template if these times are outside the IESIFTemplate time limits -T.resTemplate(:,timeVec>T.t_ms(end) | timeVec=SIFStartMs & T.t_ms< SIFEndMs); -T.pResSIF=preSpikeSamples+(SIFStartSamples:(SIFEndSamples-1)); -excludeSpikePeakElectrode=1; -polarityThreshold=0.25; -for i=1:nNeurons - %find electrodes arround max spike electrode - [pX,pY]=find(EnExt==pMaxSpikeElec(i)); - pElecs=EnExt(pX-nNeighbors:pX+nNeighbors,pY-nNeighbors:pY+nNeighbors); %get electrodes in extended grid - if excludeSpikePeakElectrode - pElecs(pPeakElectrode)=NaN; - end - pElecs=pElecs(~isnan(pElecs)); %remove NaNs - nElecs=numel(pElecs); - - %for more accurate extraction of field polarity - have to be checked if working - %{ - tmp=squeeze(baselineSubstractedSIF(i,pElecs,(preSpikeSamples+SIFStartSamples):(preSpikeSamples+SIFEndSamples))); - pIntersection=findfirst(tmp(:,2:end)>0 & tmp(:,1:end-1)<0, 2, 1); - pIntersection(pIntersection==0)=SIFEndSamples-SIFStartSamples; - sortedIntersection=sort(pIntersection); - SIFEndSamplesNew(i)=(preSpikeSamples+SIFStartSamples)+sortedIntersection(round(0.2*nElecs)); - tmp=tmp(:,1:(SIFEndSamplesNew(i)-(preSpikeSamples+SIFStartSamples))); - %} - tmp=squeeze(baselineSubstractedSIF(i,pElecs,pRelevantSamples)); - - %plot(squeeze(baselineSubstractedSIF(i,pElecs,:))','b');hold on;plot(pRelevantSamples,squeeze(baselineSubstractedSIF(i,pElecs,pRelevantSamples))','r'); - %plot(squeeze(avgRawWF(i,pElecs,:))','b');hold on;plot(squeeze(baselineSubstractedSIF(i,pElecs,:))','r'); - %activityTracePhysicalSpacePlot([],obj.currentDataObj.channelNumbers,squeeze(avgRawWF(i,:,:)),En,'traceColor','k','DrawElectrodeNumbers',1); - - [absSIFscore,pTmp]=max( abs(tmp) ,[] , 2); - [~,pOrder]=sort(absSIFscore); - - if strcmp(IEclassificationMethod,'templateCorr') - [CTemp,pMax]=max(corr(T.resTemplate(:,T.pResSIF)',squeeze(baselineSubstractedRaw(i,pElecs,T.pResSIF))')); - tmpPol=T.polarity(pMax); - polaritySign(i)=sign(mean(tmpPol)+eps); %check the sign by majority vote relative to threshold - polarityConf(i)=mean([CTemp(tmpPol==polaritySign(i)) -CTemp(tmpPol~=polaritySign(i))]); - elseif strcmp(IEclassificationMethod,'SIFAmpPolarity') - selectedElecs=pOrder(round((nElecs*0.5):end));%take only the high 50% of fields - topPolarities=tmp(sub2ind(size(tmp), selectedElecs, pTmp(selectedElecs))); - polarityConf(i)=mean(sign(topPolarities)); - polaritySign(i)=sign(polarityConf(i)-polarityThreshold); %check the sign at maximum and assign -1 or 1 depending of whether positive or negative - end - - %SIFtemptates - if polaritySign(i)>0 - [~,pTmp]=max(max(tmp,[],2)); - pMaxField(i)=pElecs(pTmp); - polarityScore(i)=max(tmp(pTmp,:)); - else - [~,pTmp]=min(min(tmp,[],2)); - pMaxField(i)=pElecs(pTmp); - polarityScore(i)=min(tmp(pTmp,:)); - end - fields4Classification(i,:)=squeeze(baselineSubstractedSIF(i,pMaxField(i),:)); - fields4ClassificationRaw(i,:)=squeeze(baselineSubstractedRaw(i,pMaxField(i),:)); - - %polarity for verification does not work well - %[polarityValidity(i)]=mean(sign( mean( abs(lowpassWF(i,pElecs,(preSpikeSamples+SIFStartSamples):(preSpikeSamples+SIFEndSamples)))-... - % abs(lowpassWFBaseline(i,pElecs,(preSpikeSamples+SIFStartSamples):(preSpikeSamples+SIFEndSamples))) ,3) )); - - %{ - h(1)=subplot(1,3,1:2); - [hPlot,scaleFac]=activityTracePhysicalSpacePlot(h(1),obj.currentDataObj.channelNumbers,squeeze(avgRawWF(i,:,:)),En,'traceColor','r','DrawElectrodeNumbers',1);hold on; - [hPlot]=activityTracePhysicalSpacePlot(h(1),obj.currentDataObj.channelNumbers,squeeze(lowpassWF(i,:,:)),En,'scaleFac',scaleFac);hold on; - [hPlot]=activityTracePhysicalSpacePlot(h(1),obj.currentDataObj.channelNumbers,squeeze(lowpassWFBaseline(i,:,:)),En,'scaleFac',scaleFac,'traceColor',[0.5 0.5 0.5]); - - h(2)=subplot(1,3,3); - %title(['polarity= ' num2str(polarityScore(i)), ' , Validity= ' num2str(polarityValidity(i))]); - - pause; - delete(h); - %} -end - -fieldPar.fields4Classification=fields4Classification; -fieldPar.fields4ClassificationRaw=fields4ClassificationRaw; - -fieldPar.samples4Classification=pRelevantSamples; - -%% inhibitory excitatory classification -%determine which neurons to classify -%classes: 3 = excitatory, 2 = inhibitory, 1 = unclassified - -if numel(classIE)==1 - if classIE==0 %do not classify, but set all to be inhibitory - classIE=3*ones(1,nNeurons); - elseif classIE==1 %classify all - classIE=ones(1,nNeurons); - end %nothing happens for the case of one neuron in recording that was already clasified in the input - toClassify=(classIE==1); -else - toClassify=false(1,nNeurons); -end - -pNotClassified=[]; -if any(toClassify) - useScore=0; - polarityThresh=[0 2]; - polarityConfThresh=0.8; - if useScore - %pExcit=find(polarityScore<=polarityThresh(1) & polarityConf>=polarityConfThresh); - %pInhib=find(polarityScore>=polarityThresh(2) & polarityConf>=polarityConfThresh); - %pNotClassified=find((polarityScore>polarityThresh(1) & polarityScore=-polarityThresh & polarityScore<=polarityThresh); - end - fieldPar.polarityScore=polarityScore; - fieldPar.polarityConf=polarityConf; - fieldPar.polaritySign=polaritySign; - - fieldPar.classIE=ones(1,nNeurons); - fieldPar.classIE(pExcit)=3; %excitatory - fieldPar.classIE(pInhib)=2; %inhibitory - fieldPar.classIE(~toClassify)=classIE(~toClassify); %give the neurons that should not be classified their original classification - -else - pExcit=find(classIE==3); - pInhib=find(classIE==2); - fieldPar.classIE=classIE; -end - -if plotMaxWFAll - - %define number of subplots - maxFields4Plot=375; - n=ceil(sqrt(min(maxFields4Plot,nNeurons)/3/5));%define images in a 3 x 5 ratio - xPlots=n*5; - yPlots=n*3; - nPlotPerPage=xPlots*yPlots; - cMap=lines(2); - cMap=[cMap;0 0 0;0 0 0]; - - f=figure('Position',[50 50 1800 900],'Visible','off'); - for i=1:nNeurons - h=subaxis(f,yPlots,xPlots,i,'S',0.001,'M',0.001); - plot(timeVec,squeeze(avgRawWF(i,pMaxField(i),:)));hold on; - plot(timeVec,squeeze(lowpassWF(i,pMaxField(i),:)),'r');axis tight; - set(h,'XTickLabel',[],'YTick',[],'XTick',0,'TickLength',h.TickLength*5); - %text(h.XLim(2),h.YLim(2),[num2str(neuronNames(1,i)) '-' num2str(neuronNames(2,i))],'VerticalAlignment','top','HorizontalAlignment','right'); - text(h.XLim(1),h.YLim(1),'*','color',cMap(4-fieldPar.classIE(i),:),'FontSize',18) - text(h.XLim(2),h.YLim(1)+0.2*diff(h.YLim),[num2str(i) ',' num2str(neuronNames(1,i)) '-' num2str(neuronNames(2,i))],'VerticalAlignment','top','HorizontalAlignment','right'); - end - f.Visible='on'; -end -%{ - for i=1:nNeurons - f=figure; - h=axes; - [hPlot,scaleFac]=activityTracePhysicalSpacePlot(h,1:120,squeeze(avgRawWF(i,:,:)),En,'traceColor','r','DrawElectrodeNumbers',1);hold on; - [hPlot]=activityTracePhysicalSpacePlot(h,1:120,squeeze(lowpassWF(i,:,:)),En,'scaleFac',scaleFac); - title(['neuron ' num2str(neuronNames(:,i)') ', class = ' num2str(fieldPar.classIE(i))]); - pause; - delete(f); - end -%} - -%% calculate post spike fields -fprintf('\nCalculating PSDs...'); -% include the fact that each neuron has a different end time for integration -% pRelevantSamples=(preSpikeSamples+SIFStartSamples):SIFEndSamplesNew(i); - -switch PSFMethod - case 'max' %pre value substracted - fieldPar.val(pInhib,:)=max(lowpassWF(pInhib,:,pRelevantSamples),[],3); - fieldPar.val(pExcit,:)=-min(lowpassWF(pExcit,:,pRelevantSamples),[],3); - fieldPar.val(pNotClassified,:)=max(abs(lowpassWF(pNotClassified,:,pRelevantSamples)),[],3); - - case 'oldNormMax' - %peak voltage normalized by pre spike peak - %fieldPar.val(pInhib,:)=max(lowpassWF(pInhib,:,pRelevantSamples),[],3)-mean(lowpassWF(pInhib,:,1:(preSpikeSamples-preSpikePeakSamples)),3); - %fieldPar.val(pExcit,:)=-(min(lowpassWF(pExcit,:,(1+preSpikeSamples):(preSpikeSamples+postSpike0CrossLimSamples)),[],3)-mean(lowpassWF(pExcit,:,1:(preSpikeSamples-preSpikePeakSamples)),3)); - - fieldPar.val(pInhib,:)=max(lowpassWF(pInhib,:,pRelevantSamples),[],3)-mean(lowpassWF(pInhib,:,(preSpikeSamples-spikePeakWidthSamples/2):(preSpikeSamples+spikePeakWidthSamples/2)),3); - fieldPar.val(pExcit,:)=-(min(lowpassWF(pExcit,:,(1+preSpikeSamples):(preSpikeSamples+postSpike0CrossLimSamples)),[],3)-mean(lowpassWF(pExcit,:,(preSpikeSamples-spikePeakWidthSamples/2):(preSpikeSamples+spikePeakWidthSamples/2)),3)); - fieldPar.val(pNotClassified,:)=max(abs(lowpassWF(pNotClassified,:,pRelevantSamples),[],3)-mean(lowpassWF(pNotClassified,:,(preSpikeSamples-spikePeakWidthSamples/2):(preSpikeSamples+spikePeakWidthSamples/2)),3)); - - case 'maxBaselineSubstracted' - - fieldPar.val(pInhib,:)=max(baselineSubstractedSIF(pInhib,:,pRelevantSamples),[],3); - fieldPar.val(pExcit,:)=-min(baselineSubstractedSIF(pExcit,:,pRelevantSamples),[],3); - fieldPar.val(pNotClassified,:)=max(abs(baselineSubstractedSIF(pNotClassified,:,pRelevantSamples)),[],3); - - case 'integralBaselineSubstracted' %!!!! Has to be rewritten to support separation between excitatory and inhibitory - %mean voltage normalized by pre spike mean - fieldPar.val(pInhib,:)=mean(baselineSubstractedSIF(pInhib,:,pRelevantSamples),3); %for inhibitory cells - fieldPar.val(pExcit,:)=-mean(baselineSubstractedSIF(pExcit,:,pRelevantSamples),3); %for inhibitory cells - fieldPar.val(pNotClassified,:)=mean(baselineSubstractedSIF(pNotClassified,:,pRelevantSamples),3); - - otherwise - error('SIF calculation method not valid'); -end - -if plotClassPerNeuron - - IE=['?';'I';'E']; - pTmp=find(timeVec==0); - spikeMarker=ones(numel(obj.currentDataObj.channelNumbers),1)*nan(1,numel(timeVec)); - spikeMarker(:,pTmp)=min(lowpassWF(:)); - spikeMarker(:,pTmp+1)=max(lowpassWF(:)); - - for i=1:nNeurons; - h1=subplot(3,4,[1 11]); - [hPlot,scaleFac]=activityTracePhysicalSpacePlot(h1,obj.currentDataObj.channelNumbers,squeeze(avgRawWF(i,:,:)),En,'traceColor','r','averageSubstruction',1);hold on; - activityTracePhysicalSpacePlot(h1,obj.currentDataObj.channelNumbers,squeeze(baselineSubstractedSIF(i,:,:)),En,'scaleFac',scaleFac,'DrawElectrodeNumbers',1,'averageSubstruction',1); - %activityTracePhysicalSpacePlot(h1,obj.currentDataObj.channelNumbers,squeeze(baselineSubstractedSIF(i,:,pRelevantSamples)),En,'scaleFac',scaleFac,'traceColor','k'); - activityTracePhysicalSpacePlot(h1,obj.currentDataObj.channelNumbers,spikeMarker,En,'scaleFac',scaleFac,'DrawElectrodeNumbers',1,'traceColor',[0.7 0.7 0.7]); - title(['Neuron=' num2str(neuronNames(:,i)') 'index=' num2str(i) ', Max ch=' num2str(pMaxField(i)) ', C=' num2str(fieldPar.polaritySign(i))]); - h2=subplot(3,4,8);hCB=IntensityPhysicalSpacePlot(ch,fieldPar.val(i,:),En,'h',h2,'plotElectrodeNumbers',0,'markerSize',30); - title(IE(fieldPar.classIE(i))); - pause; - delete([h1 h2]); - end - -end - -makeGaussianFit=0; -if makeGaussianFit - gaussFit.mX=zeros(1,nNeurons); - gaussFit.mY=zeros(1,nNeurons); - gaussFit.sX=zeros(1,nNeurons); - gaussFit.sY=zeros(1,nNeurons); - gaussFit.A=zeros(1,nNeurons); - gaussFit.Theta=zeros(1,nNeurons); - for i=1:nNeurons - [fitresult] = fmgaussfit(Xc,Yc,fieldPar.val(i,:)); %[amp, ang, sx, sy, xo, yo, zo] - gaussFit.A(i)=fitresult(1); - gaussFit.Theta(i)=fitresult(2); - gaussFit.sX(i)=fitresult(3); - gaussFit.sY(i)=fitresult(4); - gaussFit.mX(i)=fitresult(5); - gaussFit.mY(i)=fitresult(6); - end -end - -%calculate edge neurons -[~,pMax]=max(fieldPar.val,[],2); -[m,n]=size(En); -fieldPar.edgeNeurons=zeros(1,nNeurons); -for i=1:nNeurons - [pX,pY]=find(En==neuronNames(1,i)); - if isempty(pX) - disp('Warning!!! neuron name not found!'); - end - if pX==1 || pX==n || pY==1 || pY==m - fieldPar.edgeNeurons(i)=1; - else - surroundingSquare=En(pY-1:pY+1,pX-1:pX+1); - if any(any(isnan(surroundingSquare))) - fieldPar.edgeNeurons(i)=2; - end - end -end - -%calculate a band arround electrode area to detect points outside array -%calculate points outside electrode area -[pBound] = boundary(Xc',Yc'); %Calculate bounding points -mX=mean([Xc;Yc],2); -[teta,r]=cart2pol((Xc(pBound)-mX(1)),Yc(pBound)-mX(2)); - -rSIF=r+fieldEdgeBand; -[xB,yB]=pol2cart(teta,rSIF); -confiningPolgon=[xB+mX(1);yB+mX(2)]; - -fprintf('\nCalculating field peak...'); -switch fieldPositionMethod - case 'interpolatedMaximaSpline' %fits a 2D polynomial on a local grid of 9 points surrounding center - dXinterp=10; %um - [m,n]=size(En); - Z=nan([m,n]); - %Z=zeros([m,n]); - fieldCoord=zeros(2,nNeurons); - Zidx=sub2ind([m,n],Xc(ch)/electrodePitch,Yc(ch)/electrodePitch); - [Xmesh,Ymesh]=meshgrid(unique(Yc),unique(Xc)); - intX=min(Xc):dXinterp:max(Xc); - intY=min(Yc):dXinterp:max(Yc); - [fieldPar.XintGrid,fieldPar.YintGrid]=meshgrid(intY,intX); - fieldPar.interpAll=zeros(size(fieldPar.XintGrid,1),size(fieldPar.YintGrid,2),nNeurons); - notInInArray = ~inpolygon(fieldPar.XintGrid,fieldPar.YintGrid,confiningPolgon(1,:),confiningPolgon(2,:)); - - warning('off', 'MATLAB:interp2:NaNstrip'); %suppress warning related to the existance of nan values - for i=1:nNeurons - F = scatteredInterpolant(Xc', Yc',fieldPar.val(i,:)'); - fieldPar.interpAll(:,:,i) = interp2(Xmesh,Ymesh,F(Xmesh,Ymesh),fieldPar.XintGrid,fieldPar.YintGrid,'spline'); - tmp=squeeze(fieldPar.interpAll(:,:,i)'); - tmp(notInInArray)=0; - [~,pMax] = max(tmp(:)); - [fieldCoord(1,i),fieldCoord(2,i)] = ind2sub(size(tmp),pMax); - %p = polyFit2D(Z,XGrid,YGrid,2,2);f = polyVal2D(p,XGrid,YGrid,2,2);imagesc(f) - end - warning('on', 'MATLAB:interp2:NaNstrip'); - fieldPar.Xfield=intX(fieldCoord(1,:)); - fieldPar.Yfield=intY(fieldCoord(2,:)); - - case 'interpolatedMaxima' %fits a 2D polynomial on a local grid of 9 points surrounding center - [m,n]=size(En); - Z=nan([m,n]); - %Z=zeros([m,n]); - fieldCoord=zeros(2,nNeurons); - Zidx=sub2ind([m,n],Xc(ch)/electrodePitch,Yc(ch)/electrodePitch); - [Xmesh,Ymesh]=meshgrid(unique(Yc),unique(Xc)); - for i=1:nNeurons - F = scatteredInterpolant(Xc', Yc',fieldPar.val(i,:)'); - Z = interp2(Xmesh, Ymesh,F(Xmesh,Ymesh),Xmesh,Ymesh,'spline'); - [fieldCoord(:,i)] = peakfit2d(Z'); - %p = polyFit2D(Z,XGrid,YGrid,2,2);f = polyVal2D(p,XGrid,YGrid,2,2);imagesc(f) - end - fieldPar.Xfield=fieldCoord(1,:)*electrodePitch; - fieldPar.Yfield=fieldCoord(2,:)*electrodePitch; - - case 'medianCOM' %biased by array edges - %pTmp=fieldPar.val>median(fieldPar.val,2)*ones(1,nCh); - medSubstractedField=fieldPar.val-(median(fieldPar.val,2)*ones(1,nCh)); - fieldPar.Xfield=(sum(bsxfun(@times,medSubstractedField,Xc),2)./sum(medSubstractedField,2))'; - fieldPar.Yfield=(sum(bsxfun(@times,medSubstractedField,Yc),2)./sum(medSubstractedField,2))'; - - case 'maxima' - [PSF,pChPSF]=max(fieldPar.val,[],2);%location of field integral maxima - fieldPar.Xfield=Xc(ch(pChPSF)); - fieldPar.Yfield=Yc(ch(pChPSF)); - - case 'fitGaussian' - [m,n]=size(En); - Z=nan([m,n]); - %Z=zeros([m,n]); - fieldCoord=zeros(2,nNeurons); - [YGrid,XGrid]=meshgrid(1:size(Z,1),1:size(Z,2)); - for i=1:nNeurons - Z(sub2ind([m,n],Xc(ch)/electrodePitch,Yc(ch)/electrodePitch))=fieldPar.val(i,:); - [fitresult] = fmgaussfit(XGrid,YGrid,Z); - fieldCoord(:,i) = fitresult([5 6]); - end - fieldPar.Xfield=fieldCoord(1,:)*electrodePitch; - fieldPar.Yfield=fieldCoord(2,:)*electrodePitch; - - case 'sumOfRegMax' - [m,n]=size(En); - %Z=min(fieldPar.val(:))*ones([m+2,n+2]); - %Z0=min(fieldPar.val(:))*ones([m,n]); - Z=zeros([m+2,n+2]); - Z0=zeros([m,n]); - fieldCoord=zeros(2,nNeurons); - [YGrid,XGrid]=meshgrid(1:size(Z,1),1:size(Z,2)); - for i=1:nNeurons - %Z0(sub2ind([m,n],Xc(ch)/electrodePitch,Yc(ch)/electrodePitch))=fieldPar.val(i,:); - Z0(sub2ind([m,n],Xc(ch)/electrodePitch,Yc(ch)/electrodePitch))=fieldPar.val(i,:)-min(fieldPar.val(i,:)); - Z(2:end-1,2:end-1)=Z0; - [ind] = find(imregionalmax(Z,8)); - pTmp=find(Z(ind)>(fieldPar.val(i,pMaxField(i))/2)); - nPeaks=numel(pTmp); - ys=zeros(nPeaks,1);xs=zeros(nPeaks,1); - for j=1:nPeaks - K=Z((XGrid(ind(pTmp(j)))-1):(XGrid(ind(pTmp(j)))+1),(YGrid(ind(pTmp(j)))-1):(YGrid(ind(pTmp(j)))+1)); - % approximate polynomial parameter - a = (K(2,1)+K(1,1)-2*K(1,2)+K(1,3)-2*K(3,2)-2*K(2,2)+K(2,3)+K(3,1)+K(3,3)); - b = (K(3,3)+K(1,1)-K(1,3)-K(3,1)); - c = (-K(1,1)+K(1,3)-K(2,1)+K(2,3)-K(3,1)+K(3,3)); - %d = (2*K(2,1)-K(1,1)+2*K(1,2)-K(1,3)+2*K(3,2)+5*K(2,2)+2*K(2,3)-K(3,1)-K(3,3)); - e = (-2*K(2,1)+K(1,1)+K(1,2)+K(1,3)+K(3,2)-2*K(2,2)-2*K(2,3)+K(3,1)+K(3,3)); - f = (-K(1,1)-K(1,2)-K(1,3)+K(3,1)+K(3,2)+K(3,3)); - - % (ys,xs) is subpixel shift of peak location relative to point (2,2) - xs(j) = (6*b*c-8*a*f)/(16*e*a-9*b^2); - ys(j) = (6*b*f-8*e*c)/(16*e*a-9*b^2); - end - fieldCoord(:,i)=[mean(XGrid(ind(pTmp))-1+xs);mean(YGrid(ind(pTmp))-1+ys)]; - testPos{i}=[XGrid(ind(pTmp))-1+xs YGrid(ind(pTmp))-1+ys]'*electrodePitch; - %testPos{i}=[XGrid(ind(pTmp))-1 YGrid(ind(pTmp))-1]'*electrodePitch; - end - fieldPar.Xfield=fieldCoord(1,:)*electrodePitch; - fieldPar.Yfield=fieldCoord(2,:)*electrodePitch; - - %s = regionprops(L, 'Centroid'); -end - -%incorporate cell position -if triangulateCellPosition && isempty(cellPosition) - cellPosEst=load(obj.files.getSpikePositionEstimation,''); - cellPosition(1,:)=cellPosEst.Xrs; - cellPosition(2,:)=cellPosEst.Yrs; - %{ - figure; - for i=1:nNeurons - h=axes; - [hPlot,scaleFac]=activityTracePhysicalSpacePlot(h,1:120,squeeze(avgSpkWF(i,:,:)),En,'traceColor','b','DrawElectrodeNumbers',1);hold on;title(neuronNames(:,i)); - pause; - delete(h); - end - %} -elseif ~triangulateCellPosition && isempty(cellPosition) %use max spike electrode as a cell position estimator - cellPosition(1,:)=Xc(neuronNames(1,:)); - cellPosition(2,:)=Yc(neuronNames(1,:)); -end -%create projection vectors -fieldPar.X=[cellPosition(1,:);fieldPar.Xfield]; -fieldPar.Y=[cellPosition(2,:);fieldPar.Yfield]; - -pTmp=isnan(fieldPar.Xfield); -fieldPar.X(:,pTmp)=NaN; -fieldPar.Y(:,pTmp)=NaN; - -if size(cellPosition,2)==1 && size(cellPosition,1)~=2 - error('cellPosition was not entered in the correct format'); -end - -fieldPar.mag=sqrt((fieldPar.X(2,:)-fieldPar.X(1,:)).^2 + (fieldPar.Y(2,:)-fieldPar.Y(1,:)).^2); -fieldPar.angle=atan2(fieldPar.Y(2,:)-fieldPar.Y(1,:),fieldPar.X(2,:)-fieldPar.X(1,:)); - -%save all data -fprintf('\nSaving results...'); -save(saveFileName,'pMaxField','lowpassWF','fieldPar','timeVec','par','-v7.3'); -if saveLowPassBaseline - save(saveFileName,'lowpassWFBaseline','-append'); -end -if saveBaselineSubstractedSIF - save(saveFileName,'baselineSubstractedSIF','-append'); -end -if saveBaselineSubstractedRaw - save(saveFileName,'baselineSubstractedRaw','-append'); -end -fprintf('Done!\n'); - -%save(saveFileName,'pMaxField','-append'); - diff --git a/dataAnalysisObjects/@MEAAnalysis/getSpikeParams.m b/dataAnalysisObjects/@MEAAnalysis/getSpikeParams.m deleted file mode 100644 index 369fe7d..0000000 --- a/dataAnalysisObjects/@MEAAnalysis/getSpikeParams.m +++ /dev/null @@ -1,157 +0,0 @@ -function [data,hand]=getSpikeParams(obj,varargin) -% [data,hand]=getSpikeParams(obj,varargin) -% Function purpose : Get parameters related to spike shape -% -% Last updated : 20/10/16 - -obj.checkFileRecording; -parseObj = inputParser; - -addParameter(parseObj,'smoothingDuration',0.5,@isnumeric); %[ms] -addParameter(parseObj,'WF',[]); %%WF can be either a string with the location of the data or the average highpass waveforms - -addParameter(parseObj,'plotWidth',false,@isnumeric); -addParameter(parseObj,'plotWidthSpkNumbers',false,@isnumeric); %plot spike numbers for each point -addParameter(parseObj,'plotWidthAddNoise',true,@isnumeric); %add noise a noise with a max shift of the sampling frequency to eliminate quantization effects in plot -addParameter(parseObj,'plotWidthColorBar',true,@isnumeric); %add color bar -addParameter(parseObj,'plotWidthLogColormap',true,@isnumeric); %plot colorbar in log scale - -addParameter(parseObj,'hand',[]); -addParameter(parseObj,'fieldPar',[]); -addParameter(parseObj,'saveFileName',[]); -addParameter(parseObj,'overwrite',false,@isnumeric); -addParameter(parseObj,'inputParams',false,@isnumeric); - -parseObj.parse(varargin{:}); -if parseObj.Results.inputParams - disp(parseObj.Results); - return; -end -%evaluate all input parameters in workspace -for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); -end -%make parameter structure -par=parseObj.Results; - -[funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; -if isempty(saveFileName) - saveFileName=obj.files.(funName); -end - -%load data if existing or contrinue with analysis -if exist(saveFileName,'file') & ~overwrite - if nargout==1 - data=load(saveFileName); - else - disp('Spike parameter analysis already exists. use overwrite to run again'); - end - return; -end - -%populate grid sorter object -obj=populateGridSorterObj(obj); -if isempty(WF) - avgSIF=obj.gridSorterObj.getSTData({'avgHPWF','neuronNames','nSpkTotal'}); - for j=1:size(avgSIF.avgHPWF,1),WF(j,:)=avgSIF.avgHPWF(j,avgSIF.neuronNames(1,j),:);end -else %WF can be either a string with the location of the data or the average highpass waveforms - if isnumeric(WF) - avgSIF=obj.gridSorterObj.getSTData({'neuronNames','nSpkTotal'}); - elseif isstr(WF) - avgSIF=load(WF,'avgHPWF','neuronNames','nSpkTotal'); - WF=[]; - for j=1:size(avgSIF.avgHPWF,1),WF(j,:)=avgSIF.avgHPWF(j,avgSIF.neuronNames(1,j),:);end - elseif isstruct(WF) - avgSIF=WF;WF=[]; - for j=1:size(avgSIF.avgHPWF,1),WF(j,:)=avgSIF.avgHPWF(j,avgSIF.neuronNames(1,j),:);end - end -end -nSpkTotal=avgSIF.nSpkTotal'; -neuronNames=avgSIF.neuronNames; - -preSpkSamples=obj.gridSorterObj.postPreFilteredWindow; -Fs=obj.currentDataObj.samplingFrequency; - -nNeu=size(avgSIF.avgHPWF,1); -%% Main code -[nNeu,nSpikeSamples]=size(WF); - -% calculate pre and post samples and their position in the waveform -preSpkSamples=preSpkSamples*Fs/1000; -postSpkSamples=nSpikeSamples-preSpkSamples; -pPre=1:preSpkSamples; -pPost=(preSpkSamples+1):(preSpkSamples+postSpkSamples); - -%smooth spike shapes with local linear regression -smoothingSamples=round(smoothingDuration*Fs/1000); -spikeShapeSmooth=zeros([nNeu,nSpikeSamples]); -for i=1:nNeu - spikeShapeSmooth(i,:) = smooth(WF(i,:),smoothingSamples,'loess'); -end - -%extract spike maxima -extermalAmp=max(abs(spikeShapeSmooth),[],2); -maxAmp=max(spikeShapeSmooth,[],2); -minAmp=min(spikeShapeSmooth,[],2); - -%extract width from crossing at half amplitude -spkWidthSamples=zeros(nNeu,1); -widthVolt=(maxAmp+minAmp)/2; -for i=1:nNeu - pDown=find(spikeShapeSmooth(i,pPre)>widthVolt(i),1,'last'); - pUp=preSpkSamples+find(spikeShapeSmooth(i,pPost)>widthVolt(i),1,'first'); - if ~(isempty(pDown) || isempty(pUp)) - spkWidthSamples(i)=(pUp-pDown); - else - spkWidthSamples(i)=NaN; - end -end -width=spkWidthSamples/Fs*1000; - -%calculate width from time difference between minimal and maximal derivative -spikeShapeDer=diff(spikeShapeSmooth,[],2); -[~,derMinP]=min(spikeShapeDer(:,pPre),[],2); -[~,derMaxP]=max(spikeShapeDer(:,pPost(1:end-1)),[],2); -widthDer=( (preSpkSamples+derMaxP)-derMinP)/Fs*1000; - -if plotWidth - if plotWidthAddNoise - noiseAdd=(rand(nNeu,2)-0.5)/Fs*1000; - else - noiseAdd=zeros(nNeu,2); - end - - f=figure;h.widthAxes=axes; - if plotWidthLogColormap - h.widthScatter=scatter(widthDer+noiseAdd(:,1),width+noiseAdd(:,2),25,log(extermalAmp)); - else - h.widthScatter=scatter(widthDer+noiseAdd(:,1),width+noiseAdd(:,2),25,extermalAmp); - end - xlabel('Width (derivative)'); - ylabel('Width @ half maxima'); - - if plotWidthSpkNumbers - text(widthDer+noiseAdd(:,1),width+noiseAdd(:,2),num2str((1:nNeu)'),'fontSize',8); - end - - if plotWidthColorBar - h.widthCb=colorbar; - if plotWidthLogColormap - cbTicks=get(h.widthCb,'YTick'); - set(h.widthCb,'YTickLabel',num2str(exp(cbTicks)',3)); - end - set(gca,'position',[0.1300 0.1100 0.7164 0.8150]); - set(h.widthCb,'position',[0.8607 0.1071 0.0179 0.8167]); - ylabel(h.widthCb,'Extermal Amp [\muV]'); - end - -end - -%save all data -fprintf('\nSaving results...'); -save(saveFileName,'extermalAmp','maxAmp','minAmp','width','widthDer','neuronNames','nSpkTotal'); - -fprintf('Done!\n'); - -%save(saveFileName,'pMaxField','-append'); - diff --git a/dataAnalysisObjects/@MEAAnalysis/getSpikePositionEstimation.m b/dataAnalysisObjects/@MEAAnalysis/getSpikePositionEstimation.m deleted file mode 100644 index eb343b6..0000000 --- a/dataAnalysisObjects/@MEAAnalysis/getSpikePositionEstimation.m +++ /dev/null @@ -1,655 +0,0 @@ -function [data,hand]=getSpikePositionEstimation(obj,varargin) -% [data,h]=spikePositionEstimation(obj,varargin) -% Function purpose : Estimates spike position -% Last updated : 26/05/16 -data=[]; -obj.checkFileRecording; - -%default parameters -parseObj = inputParser; -addParameter(parseObj,'smoothingDuration',0.5); %[ms] -addParameter(parseObj,'maxDistForElectrodes',150); %[uM] -addParameter(parseObj,'electrodePitch',[]); %[uM] -addParameter(parseObj,'useSameTimePoint',true); %if true takes the time point of max channel of every neuron and uses this time for all channels, if false checks for the max of each ch seperately -addParameter(parseObj,'dXY',1); %[uM] -addParameter(parseObj,'dZ',1); %[uM] -addParameter(parseObj,'dL',1); %[uM] -addParameter(parseObj,'dV0',1); %[uV] -addParameter(parseObj,'maxZ',200); %[uM] -addParameter(parseObj,'minMaxV0',[15 300]); %[uV] - for global minima -addParameter(parseObj,'minMaxL',[10 100]); %[uM] - for global minima -addParameter(parseObj,'maxPotAtCellBody',250); -addParameter(parseObj,'gridColor',[0.8 0.8 0.8]); -addParameter(parseObj,'cellDiameter',15); %[um] -addParameter(parseObj,'modelType','reducedModelOpt');%,'realModelOpt','globalMinima','reducedModelOpt'; -addParameter(parseObj,'smoothSpikes',false); -addParameter(parseObj,'usePostProcessing',false); -addParameter(parseObj,'L0',0); -addParameter(parseObj,'V0',0); -addParameter(parseObj,'Xc',[]); -addParameter(parseObj,'Yc',[]); -addParameter(parseObj,'decayModel','XYZV'); -addParameter(parseObj,'maxIter',5e6); -addParameter(parseObj,'useSpikeExtremum',false); -addParameter(parseObj,'LGrid',45); %decay constants to use as initial conditions in optimization -addParameter(parseObj,'V0Grid',15:5:250); %Potential at r=0 (from cell) to use as initial conditions in optimization -addParameter(parseObj,'Icell',10.^(-10:0.05:-7)); %current density in initial axon segment -addParameter(parseObj,'neuronIdentity',[]); %the identity of the neuron - 1-not classified, 2- inhibitory, 3-excitatory -addParameter(parseObj,'WF',[]); %the waveform to triangulate [nNeurons,nCh,nSpikeSamples] -addParameter(parseObj,'STWaveformFile',[],@isstr) - -addParameter(parseObj,'plot3D',true); -addParameter(parseObj,'h3D',[]); -addParameter(parseObj,'plot3DGrid',true); -addParameter(parseObj,'plot3DElectrodeNumbers',true); -addParameter(parseObj,'plot3DAddScaleBar',true); -addParameter(parseObj,'plot3DTransparency',0.5); -addParameter(parseObj,'plot3DRemoveNeuronOutSideMEA',false); - -addParameter(parseObj,'elecNumFontSize',5); -addParameter(parseObj,'plotTriangulationOnWaveforms',false); -addParameter(parseObj,'plot1NeuronPerPlotInTriangulation',false); -addParameter(parseObj,'plotFit',false); - -addParameter(parseObj,'overwrite',false,@isnumeric); -addParameter(parseObj,'saveFileName',[],@isstr); -addParameter(parseObj,'onlyPlot',false,@isnumeric); -addParameter(parseObj,'inputParams',false,@isnumeric); - -parseObj.parse(varargin{:}); -if parseObj.Results.inputParams - disp(parseObj.Results); - return; -end -%evaluate all input parameters in workspace -for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); -end - -%make parameter structure -par=parseObj.Results; - -%check if analysis was already done done -outputDataWhenFinished=0; - -if isempty(saveFileName) - saveFileName=obj.files.(mfilename); -end - -if ~overwrite - if exist(saveFileName,'file') - if onlyPlot - load(saveFileName); - electrodePitch=par.electrodePitch; - else - if nargout==1 - data=load(saveFileName); - else - disp('Analysis results already exist for this method, use overwrite if needed'); - end - return; - end - end -else - if nargout==1 - outputDataWhenFinished=1; - end -end - -if isempty(WF) - %populate grid sorter object if does not exist - STfileExist=obj.checkFileRecording(obj.files.getSpikeTrigWF,'Missing spike triggered average data...run getSpikeTrigWF'); - if ~STfileExist & isempty(STWaveformFile) - if isempty(obj.gridSorterObj) - obj=obj.populateGridSorterObj; - end - gridSortFileExist=obj.checkFileRecording(obj.gridSorterObj.sortingFileNames.STWaveformFile,'Missing post processing in spike sorting, rerun sorting'); - if gridSortFileExist - WF=load(obj.gridSorterObj.sortingFileNames.STWaveformFile,'avgHPWF'); %load data - preMs=obj.gridSorterObj.postPreFilteredWindow; - warning('Getting spike triggered data from grid sorter!!!! In the future, run getSpikeTrigWF from MEAAnalysis'); - else - error('No spike triggered data in either file or gridsorter!!!'); - end - else - if isempty(STWaveformFile) - STWaveformFile=obj.files.getSpikeTrigWF; - end - WF=load(STWaveformFile,'avgHPWF','par'); - preMs=WF.par.preFilteredWindow; - end -else %use waveforms from an input WF - preMs=WF.preMs; - if ~isstruct(WF) - WF2=WF;clear WF; - WF.avgHPWF=WF2; - clear WF2; - disp('Taking pre spike duration from grid sorter object!!!'); - obj=obj.populateGridSorterObj; - preMs=obj.gridSorterObj.postPreFilteredWindow; - end - disp('Using highpass waveforms from input!'); -end - -%get recording information -Fs=obj.currentDataObj.samplingFrequency; -ch=obj.currentDataObj.channelNumbers; -En=obj.currentDataObj.chLayoutNumbers; - -%check if ch numbers vector was given and if not, take all channels in array in serial order -if isempty(ch) - ch=unique(En(~isnan(En))); - if numel(ch)~=nCh - error('Number of channels in waveform does not match the channels in En'); - end -else - if size(ch,1)==1 - ch=ch'; - end -end - -%get electrode positions in physical space -if ~isempty(electrodePitch) - [Xc,Yc]=obj.currentDataObj.getElectrodePositions(electrodePitch); -else - [Xc,Yc]=obj.currentDataObj.getElectrodePositions; - electrodePitch=obj.currentDataObj.electrodePitch; -end - -%% Output list of default variables -hand=[];testData=[]; -if isempty(WF.avgHPWF) %run on artificial data - nNeurons=10; - nCh=numel(unique(En(~isnan(En)))); - nSpikeSamples=preMs*2*Fs/1000; - - neuronIdentity=round(rand(1,nNeurons))+2; - tX=rand(1,nNeurons)*100-50; - tY=rand(1,nNeurons)*100-50; - tZ=rand(1,nNeurons)*100; - - %tV0=V0+rand(1,nNeurons)*10; - tV0=rand(1,nNeurons)*(minMaxV0(2)-minMaxV0(1))+minMaxV0(1); - %tL=L0+rand(1,nNeurons)*50-25; - tL=rand(1,nNeurons)*(minMaxL(2)-minMaxL(1))+minMaxL(1); - tCh=ceil(rand(1,nNeurons)*nCh); - tCh(tCh==0)=1; - - smoothingSamples=round(smoothingDuration*Fs/1000); - preSpkSamples=preMs*Fs/1000; - WF.avgHPWF=zeros([nNeurons,nCh,nSpikeSamples]); - for i=1:nNeurons - for j=1:nCh - WF.avgHPWF(i,j,preSpkSamples:(preSpkSamples+3*smoothingSamples))=... - -tV0(i).*exp(-sqrt( (Xc(tCh(i))+tX(i)-Xc(j)).^2 + (Yc(tCh(i))+tY(i)-Yc(j)).^2+(tZ(i)-0).^2 )./tL(i)); - %WF.avgHPWF(i,j,preSpkSamples:(preSpkSamples+3*smoothingSamples))=... - % -tV0(i).*exp(-sqrt( (Xc(tCh(i))+tX(i)-Xc(j)).^2 + (Yc(tCh(i))+tY(i)-Yc(j)).^2 )./tL(i)); - end - %h=axes;activityTracePhysicalSpacePlot(h,1:nCh,squeeze(WF.avgHPWF(i,:,:)),En,'traceColor',[0.2 0.2 0.8],'scaling','none'); - end - - %save parameter for output - testData.neuronIdentity=neuronIdentity; - testData.tX=tX; - testData.tY=tY; - testData.tZ=tZ; - testData.tV0=tV0; - testData.tL=tL; - testData.tCh=tCh; -end - -% Find neuron with reliable spiking -[nNeurons,nCh,nSpikeSamples]=size(WF.avgHPWF); - -% calculate pre and post samples and their position in the waveform -preSpkSamples=preMs*Fs/1000; -postSpkSamples=nSpikeSamples-preSpkSamples; - - -%% model with x,y,z,V -%according to the current grid arrangement positive Y is down on real MEA space and positive X is right on real MEA space - -if useSpikeExtremum % find spike extremum ch and position - [vMaxAll,pMaxAll]=max(abs(WF.avgHPWF),[],3); - [vMax,pChMax]=max(vMaxAll,[],2); -else %find spike minimum - [vMaxAll,pMaxAll]=min(WF.avgHPWF,[],3); - [vMax,pChMax]=min(vMaxAll,[],2); - vMax=abs(vMax); - vMaxAll=abs(vMaxAll); -end -pMaxSampleInMaxCh=pMaxAll( sub2ind(size(pMaxAll), 1:nNeurons, pChMax') ); - -%smooth spike shapes with local linear regression -if smoothSpikes - smoothingSamples=round(smoothingDuration*Fs/1000); - for i=1:nNeurons - for j=1:nCh - WF.avgHPWF(i,j,:) = smooth(WF.avgHPWF(i,j,:),smoothingSamples,'loess'); - end - end -end - -if ~onlyPlot - if strcmp(modelType,'globalMinima') - %define search limits - X=-electrodePitch:dXY:electrodePitch; - Y=-electrodePitch:dXY:electrodePitch; - Z=0:dZ:maxZ; - L=minMaxL(1):dL:minMaxL(2); - V0=minMaxV0(1):dV0:minMaxV0(2); - - %initialize arrays - V0All=ones(numel(X),numel(Y),numel(Z),numel(L),numel(V0)); - XAll=V0All; - YAll=V0All; - ZAll=V0All; - LAll=V0All; - - X5D(:,1,1,1,1)=X; - Y5D(1,:,1,1,1)=Y; - Z5D(1,1,:,1,1)=Z; - L5D(1,1,1,:,1)=L; - V05D(1,1,1,1,:)=V0; - - XAll=bsxfun(@times,XAll,X5D); - YAll=bsxfun(@times,YAll,Y5D); - ZAll=bsxfun(@times,ZAll,Z5D); - LAll=bsxfun(@times,LAll,L5D); - V0All=bsxfun(@times,V0All,V05D); - end - - % main loop - estX=zeros(1,nCh); - estY=zeros(1,nCh); - estV0=zeros(1,nCh); - estZ=zeros(1,nCh); - allVPeak=zeros(nNeurons,nCh); - eValAll=zeros(1,nNeurons); - - hWait=waitbar(0,'Triangulating neurons...'); - for i=1:nNeurons - waitbar(i/nNeurons,hWait); - - pXY=sqrt((Xc-Xc(pChMax(i))).^2+(Yc-Yc(pChMax(i))).^2)0 - V(i)=estTmp(pV); - end - if pL>0 - Lamda(i)=estTmp(pL); - end - - end - - Xrs(i)=Xr(i)+Xc(pChMax(i)); - Yrs(i)=Yr(i)+Yc(pChMax(i)); - Zrs(i)=Zr(i); - electrodeX=Xc; - electrodeY=Yc; - end - close(hWait); - - save(saveFileName,'par','Xrs','Yrs','Zrs','Xr','Yr','Zr','Lamda','V','eValAll','electrodeX','electrodeY','pChMax','allVPeak'); - if outputDataWhenFinished - data=load(saveFileName); - end - %notice that all variables after electrodeX are only required for future plotting -else - load(saveFileName,'Xrs','Yrs','Zrs'); -end - - - - -%{ -figure;subplot(2,3,1);plot(tL-Lamda,'.');title('L');subplot(2,3,2);plot(tX-Xr,'.');title('X');subplot(2,3,3);plot(tY-Yr,'.');title('Y');subplot(2,3,4);plot(tZ-Zr,'.');title('Z');subplot(2,3,5);plot(tV0-V,'.');title('V0'); -%} - -if plotFit - if nNeurons>=40 - nPlotsInRow=10; - nPlotsInCol=6; - else - nPlotsInRow=8; - nPlotsInCol=5; - end - hand.fFit(1)=figure('position',[40 80 1500 900]); - c=1; - for i=1:nNeurons - iFig=mod(i-1,nPlotsInRow*nPlotsInCol)+1; - subaxis(nPlotsInCol,nPlotsInRow,iFig,'S',0.005,'M',0.01); - d=sqrt((Xrs(i)-electrodeX).^2+(Yrs(i)-electrodeY).^2+(Zrs(i)).^2); - plot(d,vMaxAll(i,:),'.');hold on; - if strcmp(par.decayModel,'powerDecay') - plot(sort(d),V(i)./(sort(d)).^Lamda(i),'r'); - else - plot(sort(d),V(i).*exp(-sort(d)/Lamda(i)),'r'); - end - - xlim([0 maxDistForElectrodes+100]); - ylim([0 max(vMaxAll(i,:))+3]); - text(0,0,[num2str(i) ' ,V0=' num2str(V(i),3) ' ,\lambda=' num2str(Lamda(i),3),' ,Z=' num2str(Zrs(i),3)],'HorizontalAlignment','left','verticalAlignment','Bottom'); - set(gca,'XTickLabel',[],'YTickLabel',[]); - if mod(i,nPlotsInRow*nPlotsInCol)==0 - c=c+1; - hand.fFit(c)=figure('position',[40 80 1500 900]); - end - end -end - -if plot3D - - if isempty(neuronIdentity) %if no an empty neuron identity is given - neuronIdentity=ones(1,nNeurons); %set all neuorns with unindentified polarity - else - neuronIdentity(neuronIdentity==0)=1; - end - - %create electrode grid with numbers for plotting - [max_grid_y,max_grid_x]=size(En); - XL=[0.5 max_grid_x+0.5]*electrodePitch; - YL=[0.5 max_grid_y+0.5]*electrodePitch; - xM=(1.5:(max_grid_y-0.5))'*electrodePitch; - yM=(1.5:(max_grid_x-0.5))'*electrodePitch; - - %plot electrode grid with numbers - if isempty(h3D) - hand.f3D=figure; - hand.hPlot3D=axes; - else - hand.hPlot3D=h3D; - hand.f3D=hand.hPlot3D.Parent; - end - hold on; - - if plot3DGrid - hand.hPlot1=line([XL(1) XL(2)],[xM xM],'LineWidth',1,'Color',gridColor,'Parent',hand.hPlot3D); - hand.hPlot2=line([yM yM],[YL(1) YL(2)],'LineWidth',1,'Color',gridColor,'Parent',hand.hPlot3D); - end - - if plot3DElectrodeNumbers - hand.hPlot3=text(Xc,Yc,num2str(ch),'fontsize',elecNumFontSize,'horizontalAlignment','center','Parent',hand.hPlot3D); - end - - if plot3DRemoveNeuronOutSideMEA - neurons2Plot=find(Xrs>=XL(1) & Xrs<=XL(2) & Yrs>=YL(1) & Yrs<=YL(2)); - else - neurons2Plot=1:nNeurons; - end - - %plot cell bodies - [Xsp,Ysp,Zsp] = sphere(6); - Xsp=Xsp*cellDiameter;Ysp=Ysp*cellDiameter;Zsp=Zsp*cellDiameter; - cmap=[0.8 0.8 0.8;1 0 0;0 0 1]; - for i=neurons2Plot - %scatter3(translation(Channels(i),1)+bestY0{i}(j)/100,translation(Channels(i),2)+bestX0{i}(j)/100,bestZ0{i}(j)/100,[],i,'filled'); - surf(Xrs(i)+Xsp,Yrs(i)+Ysp,Zrs(i)+Zsp,'FaceColor', cmap(neuronIdentity(i),:),'EdgeColor','none'); - end - set(gca,'XTickLabel',[],'YTickLabel',[]); - box on; - axis equal; - camlight('right') - set(gcf,'color','w'); - xlim([electrodePitch/2 max(Xc)+electrodePitch/2]); - ylim([electrodePitch/2 max(Yc)+electrodePitch/2]); - zlim([-cellDiameter maxZ]); - - view([-30 20]); - zlabel('Z [\mum]'); - - alpha(plot3DTransparency); - - if plot3DAddScaleBar - [hScaleBar]=addScaleBar(hand.hPlot3D,'scaleFac',2,'scaleBarAxes','x','XUnitStr','[\mum]'); - end - %set(gcf,'PaperPositionMode','auto');print estimatedPositionOfNeurons3DCtr0001 -djpeg -r300; -end - -if plotTriangulationOnWaveforms - - %plot cell bodies - cellDiameter=12; - localGridSize=5; - - plotSpheres=false; - if plotSpheres - [Xsp,Ysp,Zsp] = sphere(6); - Xsp=Xsp*cellDiameter;Ysp=Ysp*cellDiameter;Zsp=Zsp*cellDiameter; - end - normZ=Zrs/max(Zrs); - cMap=jet(64); - - - arrayExt=(localGridSize-1)/2; - [nRowsTmp,nColsTmp]=size(En); - - EnExt=NaN(nRowsTmp+arrayExt*2,nColsTmp+arrayExt*2); - EnExt(1+arrayExt:end-arrayExt,1+arrayExt:end-arrayExt)=En; - - if plot1NeuronPerPlotInTriangulation - nPlotsInRow=1; - nPlotsInCol=1; - else - nPlotsInRow=7; - nPlotsInCol=4; - end - - c=0; - for i=1:nNeurons - nSubAxis=mod(i-1,nPlotsInRow*nPlotsInCol)+1; - if nSubAxis==1 - c=c+1; - if plot1NeuronPerPlotInTriangulation - hand.fSingleNeurons(c)=figure('position',[70 70 750 450]); - else - hand.fSingleNeurons(c)=figure('position',[70 70 1500 900]); - end - end - - h=subaxis(hand.fSingleNeurons(c),nPlotsInCol,nPlotsInRow,nSubAxis,'S',0.01,'M',0.002);hold on; - - if plot1NeuronPerPlotInTriangulation - localGrid=En; - [yLoc,xLoc]=find(localGrid==pChMax(i)); - else - [x,y]=find(EnExt==pChMax(i)); - %find the surrounding channels on which feature extraction will be performed - localGrid=EnExt(x-arrayExt:x+arrayExt,y-arrayExt:y+arrayExt); - [yLoc,xLoc]=find(localGrid==pChMax(i)); - end - - [tmpCh,pInCh]=intersect(ch, localGrid(~isnan(localGrid(:))) ); - - %plot( (Xc(tmpCh)-Xc(pChMax(i)) )/electrodePitch + arrayExt + 1 , (Yc(tmpCh)-Yc(pChMax(i)) )/electrodePitch + arrayExt + 1 ,'o','color',[0.8 0.8 0.8]);hold on; - activityTracePhysicalSpacePlot(h,tmpCh,squeeze(WF.avgHPWF(i,pInCh,:)),localGrid,'lockXYRatio',1,'traceColor',[0.9 0.2 0.2],'DrawGrid',1,... - 'gridLineWidth',1,'drawElectrodeCenters',true,'electrodeColor',[0 0.7 0],'electrodeSize',6,'scaling','noOverlap'); - %plot( (Xrs(i)-Xc(pChMax(i)) )/electrodePitch + arrayExt + 1 , (Yrs(i)-Yc(pChMax(i)) )/electrodePitch + arrayExt + 1 ,'o','color',[0.9 0.2 0.2],'lineWidth',3); - - if plotSpheres - surface((Xrs(i)+Xsp-Xc(pChMax(i)) )/electrodePitch + xLoc,... - (Yrs(i)+Ysp-Yc(pChMax(i)) )/electrodePitch + yLoc,... - (Zrs(i)+Zsp)/electrodePitch,'FaceColor',cMap(round(normZ(i)*63)+1,:,:),'EdgeColor','none','FaceAlpha',0.4); - camlight left; - else - hold on;plot((Xrs(i)-Xc(pChMax(i)) )/electrodePitch + xLoc,(Yrs(i)-Yc(pChMax(i)) )/electrodePitch + yLoc,'o','MarkerSize',8,'Color',[0.3 0.2 0.8]); - text(0.5,0.5,['Z=' num2str(round(Zr(i))) ', L=' num2str(round(Lamda(i))) ', V0/V=' num2str(round(V(i)/vMax(i)))]); - end - - end -end - - - %[estTmpTmp,eValTmp] = fminsearch(@(x) XYZLV_Model(x,xTmp,yTmp,zTmp,V0tmp,vMax(i),maxPotAtCellBody,maxZ),[0,0,0,V0Grid(j),vMax(i)],optimset('MaxFunEvals',1000000,'Display','off')); - %[estTmpTmp,eValTmp] = fminsearch(@(x) XYZV_Model(x,xTmp,yTmp,zTmp,vMax(i),maxZ),[0,0,0,vMax(i)],optimset('MaxFunEvals',1000000,'Display','off')); - %[estTmpTmp,eValTmp] = fminsearch(@(x) XYZL_Model(x,xTmp,yTmp,zTmp,V0tmp,V0Grid(j),maxZ),[0,0,0,L0],optimset('MaxFunEvals',100000,'Display','off')); - - %[estTmpTmp,eValTmp] = fminsearch(@(x) XYZV_Model(x,xTmp,yTmp,zTmp,V0tmp,L0,vMax(i),maxPotAtCellBody,maxZ),[0,0,0,vMax(i)],optimset('MaxFunEvals',1000000,'Display','off')); - %[estTmpTmp,eValTmp] = fminsearch(@(x) XYV_Model(x,xTmp,yTmp,V0tmp,LGrid(i),vMax(i),maxZ),[0,0,vMax(i)],optimset('MaxFunEvals',1000000,'Display','off')); - %[estTmpTmp,eValTmp] = fminsearch(@(x) XYZ_Model(x,xTmp,yTmp,zTmp,V0tmp,V0Grid(j),L0,maxZ),[0,0,0],optimset('MaxFunEvals',1000000,'Display','off')); - - - -function score=powerDecay_Model(X,xTmp,yTmp,zTmp,maxZ,V0tmp,V0,L) -score=mean( ( V0tmp- V0./sqrt((xTmp-X(1)).^2+(yTmp-X(2)).^2+(zTmp-X(3)).^2).^L ).^2 ); -if X(3)<0 || X(3)>maxZ - score=score*2; -end - -function score=XYZ_Model(X,xTmp,yTmp,zTmp,maxZ,V0tmp,V0,L) -score=mean( ( V0tmp-V0.*exp(-sqrt((xTmp-X(1)).^2+(yTmp-X(2)).^2+(zTmp-X(3)).^2)./L) ).^2 ); -if X(3)<0 || X(3)>maxZ - score=score*2; -end - -function score=XYZV_Model(X,xTmp,yTmp,zTmp,maxZ,V0tmp,L,vMax,maxPotAtCellBody) -score=mean( ( V0tmp-X(4).*exp(-sqrt((xTmp-X(1)).^2+(yTmp-X(2)).^2+(zTmp-X(3)).^2)./L) ).^2 ); -if X(3)<=0 || X(3)>maxZ || X(4)<=vMax || X(4)>=maxPotAtCellBody - score=score*2; -end - -function score=XYZL_Model(X,xTmp,yTmp,zTmp,maxZ,V0tmp,V0) -score=mean( ( V0tmp-V0.*exp(-sqrt((xTmp-X(1)).^2+(yTmp-X(2)).^2+(zTmp-X(3)).^2)./X(4)) ).^2 ); -if X(3)<0 || X(3)>maxZ - score=score*2; -end - -function score=XYZLV_Model(X,xTmp,yTmp,zTmp,maxZ,V0tmp,vMax,maxPotAtCellBody) -score=mean( ( V0tmp-X(5).*exp(-sqrt((xTmp-X(1)).^2+(yTmp-X(2)).^2+(zTmp-X(3)).^2)./X(4)) ).^2); -if X(3)<0 || X(3)>maxZ || X(5)maxPotAtCellBody - score=score*2; -end - -function score=LogXYZV_Model(X,xTmp,yTmp,zTmp,maxZ,V0tmp,L,vMax) -score=mean((log(V0tmp./X(4)) + sqrt((xTmp-X(1)).^2+(yTmp-X(2)).^2+(zTmp-X(3)).^2)./L).^2); -if X(3)<0 || X(3)>maxZ || X(4)maxZ - score=score*2; -end - -function score=potEst(X,Xe,Ye,Ve) -%[0,0,0,LGrid(j),mxV0] -%x=[X Y Z I] -%P0=@(Xe,Ye) 2.*Fih(Xe-X,Ye-Y,-Z) +2.*W_TS.*sum( Fih(Xe-X,Ye-Y,-Z+2.*(1:nTerms).*h) + Fih(Xe-X,Ye-Y,-Z-2.*(1:nTerms).*h) ); -nTerms=20; -W_TS=-0.6667; -h=400; -sigmaT=0.3; - -Fih=@(u,v,w) X(4)./( (4*pi*sigmaT) .* sqrt(u.^2+v.^2+w.^2) ); - -for n=1:nTerms - tmp(n,:)=(W_TS.^n) .* ( Fih(Xe-X(1),Ye-X(2),-X(3)+2.*n.*h) + Fih(Xe-X(1),Ye-X(2),-X(3)-2.*n.*h)); -end - -P0=2.*Fih(Xe-X(1),Ye-X(2),-X(3)) +2.*sum(tmp); - -score=sum((P0-Ve).^2); - -if X(3)<0 - score=score*2; -end \ No newline at end of file diff --git a/dataAnalysisObjects/@MEAAnalysis/plotAvgSIFMap.m b/dataAnalysisObjects/@MEAAnalysis/plotAvgSIFMap.m deleted file mode 100644 index f48ad49..0000000 --- a/dataAnalysisObjects/@MEAAnalysis/plotAvgSIFMap.m +++ /dev/null @@ -1,169 +0,0 @@ -function [hand,out]=plotAvgSIFMap(obj,varargin) - -obj.checkFileRecording; - -parseObj = inputParser; - -addParameter(parseObj,'hand',[]); -addParameter(parseObj,'pNeu',[],@isnumeric); %the positions of the neurons to plot -addParameter(parseObj,'gridRes',10,@isnumeric); %um -addParameter(parseObj,'gridRadius',500,@isnumeric); %um -addParameter(parseObj,'equalWeight4EveryNeuron',0,@isnumeric); -addParameter(parseObj,'polarPlotDistanceRange',[0 500],@isnumeric); -addParameter(parseObj,'outArg',{}); - - -addParameter(parseObj,'angle2LateralRight',0,@isnumeric); %The angle in degrees to rotate the axes so that lateral is on the left -addParameter(parseObj,'reverseDirction',0,@isnumeric); %whether flip direction is needed to make anterior to top when lateral is left -addParameter(parseObj,'spikeEdgeBand',0,@isnumeric); %the band arround the electrode array edge (from farthest electrode) to include in stats of neuron positions (if positive, takes also neurons outside the array) -addParameter(parseObj,'fieldEdgeBand',-50,@isnumeric); %the band arround the electrode array edge (from farthest electrode) to include in stats of field positions (if positive, takes also neurons outside the array) - -addParameter(parseObj,'plotAvgField',true,@isnumeric); -addParameter(parseObj,'contoursPos',0.4:0.1:1,@isnumeric); %um -addParameter(parseObj,'EC',[0 0.2 0.8],@isnumeric); -addParameter(parseObj,'IC',[0.95 0.1 0.05],@isnumeric); - -addParameter(parseObj,'fileNameSpikeInducedFields',[],@isstr); -addParameter(parseObj,'fileNameSTWaveform',[],@isstr); -addParameter(parseObj,'overwrite',false,@isnumeric); -addParameter(parseObj,'inputParams',false,@isnumeric); - -parseObj.parse(varargin{:}); -if parseObj.Results.inputParams - disp(parseObj.Results); - return; -end -%evaluate all input parameters in workspace -for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); -end -%make parameter structure -par=parseObj.Results; - -[funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; -saveFileName=obj.files.(funName); - -%populate grid sorter object -%obj=populateGridSorterObj(obj); - -%assign parameters -ch=obj.currentDataObj.channelNumbers; -En=obj.currentDataObj.chLayoutNumbers; -%Fs=obj.currentDataObj.samplingFrequency(1); -%preSpikeMs=obj.gridSorterObj.postPreRawWindow; - -%[Xc,Yc]=obj.currentDataObj.getElectrodePositions; -%load(obj.files.getSpikePositionEstimation,'Xrs','Yrs','Zrs'); - -if isempty(fileNameSpikeInducedFields) - obj.checkFileRecording(obj.files.getSpikeInducedFields,'Spike induced fields file missing, please run getSpikeInducedFields'); - load(obj.files.getSpikeInducedFields,'fieldPar','pMaxField'); -else - load(fileNameSpikeInducedFields,'fieldPar','pMaxField'); -end -nNeu=numel(fieldPar.mag); - -%select sub population -if isempty(pNeu) - pNeuron=true(1,nNeu); -else - pNeuron=false(1,nNeu); - pNeuron(pNeu)=true; -end - -%calculate points outside electrode area -[Xc,Yc]=obj.currentDataObj.getElectrodePositions; -Xrs=fieldPar.X(1,:);Yrs=fieldPar.Y(1,:); - -[pBound] = boundary(Xc',Yc'); %Calculate bounding points -mX=mean([Xc;Yc],2); -[teta,r]=cart2pol((Xc(pBound)-mX(1)),Yc(pBound)-mX(2)); - -rSpike=r+spikeEdgeBand; -[xB,yB]=pol2cart(teta,rSpike); -inSpike = inpolygon(Xrs,Yrs,xB+mX(1),yB+mX(2)); -%plot(xB+mX(1),yB+mX(2));hold on;plot(Xrs,Yrs,'.');plot(Xrs(inSpike),Yrs(inSpike),'o');plot(Xc(pBound),Yc(pBound)); - -rSIF=r+fieldEdgeBand; -[xB,yB]=pol2cart(teta,rSIF); -inSIF = inpolygon(fieldPar.Xfield,fieldPar.Yfield,xB+mX(1),yB+mX(2)); -%plot(xB+mX(1),yB+mX(2));hold on;plot(fieldPar.Xfield,fieldPar.Yfield,'.');plot(fieldPar.Xfield(inSIF),fieldPar.Yfield(inSIF),'o');plot(Xc(pBound),Yc(pBound)); - -fieldPar.edgeNeurons=false(1,nNeu);%initialization -fieldPar.edgeNeurons(~inSIF | ~inSpike)=true; - -if ~isempty(polarPlotDistanceRange) - pDist=fieldPar.mag>=polarPlotDistanceRange(1) & fieldPar.mag<=polarPlotDistanceRange(2); -else - pDist=true(1,nNeu); -end - -pI=pNeuron & fieldPar.classIE==2 & pDist & ~fieldPar.edgeNeurons; -pE=pNeuron & fieldPar.classIE==3 & pDist & ~fieldPar.edgeNeurons; - -xx=-gridRadius:gridRes:gridRadius; -[X,Y]=meshgrid(xx,xx); - -[theta,r]=cart2pol(X,Y); -rotAngRad=-angle2LateralRight/180*pi; %rotate sampling point to the opposite dirction of the angle -if reverseDirction - theta=-theta; -end -theta=theta+rotAngRad; -[Xrot,Yrot]=pol2cart(theta,r); - -%rotMat=[cos(rotAngRad) -sin(rotAngRad);sin(rotAngRad) cos(rotAngRad)]; -%tmpX=rotMat*[mX(:)';mY(:)']; -intAll=nan(size(X,1),size(Y,2),nNeu); -for i=1:nNeu - intAll(:,:,i)=interp2(fieldPar.XintGrid-fieldPar.X(1,i), fieldPar.YintGrid-fieldPar.Y(1,i),squeeze(fieldPar.interpAll(:,:,i)),Xrot,Yrot); - %imagesc(fieldPar.XintGrid(1,:),fieldPar.YintGrid(1,:),squeeze(fieldPar.interpAll(:,:,1))); -end - -if equalWeight4EveryNeuron - mn=min(min(intAll,[],1),[],2); - mx=max(max(intAll,[],1),[],2); - intAll=bsxfun(@rdivide,bsxfun(@minus,intAll,mn),mx-mn); -end - -avgFieldI=squeeze(nanmean(intAll(:,:,pI),3)); -avgFieldE=squeeze(nanmean(intAll(:,:,pE),3)); - -nAvgFieldI=(avgFieldI-min(avgFieldI(:)))/(max(avgFieldI(:))-min(avgFieldI(:))); -nAvgFieldE=(avgFieldE-min(avgFieldE(:)))/(max(avgFieldE(:))-min(avgFieldE(:))); - -if plotAvgField - hand.fig=figure('position',[200 200 1000 400]); - hand.ax(1)=subplot(1,2,1); - imagesc(xx,xx,nAvgFieldE);hold on; - line([0 0],[-gridRadius gridRadius],'color','r'); - line([-gridRadius gridRadius],[0 0],'color','r'); - contour(xx,xx,nAvgFieldE,contoursPos,'k'); - [~,pMax]=max(nAvgFieldE(:)); - [maxY,maxX]=ind2sub(size(nAvgFieldE),pMax); - plot(xx(maxX),xx(maxY),'.k'); - - set(hand.ax(1),'YDir','normal'); - axis equal; - xlabel('\mum');ylabel('\mum'); - title('Excitatory','color',EC); - - hand.ax(2)=subplot(1,2,2); - imagesc(xx,xx,nAvgFieldI);hold on; - line([0 0],[-gridRadius gridRadius],'color','r'); - line([-gridRadius gridRadius],[0 0],'color','r'); - contour(xx,xx,nAvgFieldI,contoursPos,'k'); - [~,pMax]=max(nAvgFieldI(:)); - [maxY,maxX]=ind2sub(size(nAvgFieldI),pMax); - plot(xx(maxX),xx(maxY),'.k'); - - set(hand.ax(2),'YDir','normal'); - axis equal; - xlabel('\mum');ylabel('\mum'); - title('Inhibitory','color',IC); -end - -out=[]; -for i=1:numel(outArg) - eval(['out.(outArg{i})=' outArg{i} ';']); -end diff --git a/dataAnalysisObjects/@MEAAnalysis/plotSIFPerNeuron.m b/dataAnalysisObjects/@MEAAnalysis/plotSIFPerNeuron.m deleted file mode 100644 index 18f7df2..0000000 --- a/dataAnalysisObjects/@MEAAnalysis/plotSIFPerNeuron.m +++ /dev/null @@ -1,174 +0,0 @@ -function [hand,out]=plotSIFPerNeuron(obj,varargin) - -obj.checkFileRecording; - -parseObj = inputParser; - -addParameter(parseObj,'outArg',{}); - -%input large matrices instead of calculating -addParameter(parseObj,'avgRawWF',[],@isnumeric); -addParameter(parseObj,'lowpassWFBaseline',[],@isnumeric); -addParameter(parseObj,'baselineSubstractedSIF',[],@isnumeric); -%addParameter(parseObj,'lowpassWF',[],@isnumeric); -%addParameter(parseObj,'neuronNames',[]); -addParameter(parseObj,'pNeu',[],@isnumeric); %the positions of the neurons to plot -addParameter(parseObj,'preSpikeMs',[]); -addParameter(parseObj,'saveFileName',[]); - -addParameter(parseObj,'hand',[]); -addParameter(parseObj,'EC',[0 0.2 0.8],@isnumeric); -addParameter(parseObj,'IC',[0.95 0.1 0.05],@isnumeric); - -addParameter(parseObj,'fileNameSpikeInducedFields',[],@isstr); -addParameter(parseObj,'fileNameSTWaveform',[],@isstr); - -addParameter(parseObj,'overwrite',false,@isnumeric); -addParameter(parseObj,'inputParams',false,@isnumeric); - -parseObj.parse(varargin{:}); -if parseObj.Results.inputParams - disp(parseObj.Results); - return; -end -%evaluate all input parameters in workspace -for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); -end -%make parameter structure -par=parseObj.Results; - -[funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; -saveFileName=obj.files.(funName); - -obj.checkFileRecording(obj.files.getSpikePositionEstimation,'Spike position estimation file missing, please run getSpikePositionEstimation'); - -%populate grid sorter object -obj=populateGridSorterObj(obj); - -%assign parameters -ch=obj.currentDataObj.channelNumbers; -En=obj.currentDataObj.chLayoutNumbers; -Fs=obj.currentDataObj.samplingFrequency(1); -preSpikeMs=obj.gridSorterObj.postPreRawWindow; - -%load SIF variables -toLoad={'fieldPar','pMaxField'}; -if isempty(baselineSubstractedSIF) - toLoad=[toLoad 'baselineSubstractedSIF']; -end -%if isempty(lowpassWF) -% toLoad=[toLoad 'lowpassWF']; -%end -if isempty(fileNameSpikeInducedFields) - obj.checkFileRecording(obj.files.getSpikeInducedFields,'Spike induced fields file missing, please run getSpikeInducedFields'); - load(obj.files.getSpikeInducedFields,toLoad{:}); -else - load(fileNameSpikeInducedFields,toLoad{:}); -end - -if isempty(avgRawWF) - if isempty(fileNameSTWaveform) - if exist(obj.files.getSpikeTrigWF,'file') - avgRawWF=load(obj.files.getSpikeTrigWF,'avgRawWF','neuronNames','par'); - else - avgRawWF=obj.gridSorterObj.getSTData('avgRawWF','neuronNames'); - avgRawWF.par.preRawWindow=obj.gridSorterObj.postPreFilteredWindow; - warning('Getting spike triggered data from grid sorter!!!! In the future, run getSpikeTrigWF from MEAAnalysis'); - end - else - avgRawWF=load(fileNameSTWaveform,'avgRawWF','neuronNames','P'); - end - preSpikeMs=avgRawWF.par.preRawWindow; - neuronNames=avgRawWF.neuronNames; - avgRawWF=avgRawWF.avgRawWF; -end - - -if isempty(baselineSubstractedSIF) - baselineSubstractedSIF=zeros(size(avgRawWF)); -end - -populateGridSorterObj(obj); -if ~exist('neuronNames','var') - ic=obj.gridSorterObj.getSortedData('ic'); - neuronNames=ic.ic(1:2,:); -end - -[Xc,Yc]=obj.currentDataObj.getElectrodePositions; -Xrs=fieldPar.X(1,:);Yrs=fieldPar.Y(1,:); - -[nNeu,nCh,nSamples]=size(avgRawWF); -timeVec=(1:nSamples)/Fs*1000-preSpikeMs; - -%% Plotting results -%temporary plot for debugging -IE=['?';'I';'E']; -pTmp=find(timeVec==0); -spikeMarker=ones(120,1)*nan(1,numel(timeVec)); -spikeMarker(:,pTmp)=min(baselineSubstractedSIF(:)); -spikeMarker(:,pTmp+1)=max(baselineSubstractedSIF(:)); - -minMaxXPos=[min(Xc) max(Xc)]; -minMaxYPos=[min(Yc) max(Yc)]; - -%calculate max spike amplitude -spikePeakWidthMs=1; -spikePeakWidthSamples=spikePeakWidthMs*Fs/1000; -preSpikeSamples=preSpikeMs*Fs/1000; -maxSpikeAmp=max( abs( bsxfun(@minus, avgRawWF(:,:,(preSpikeSamples-spikePeakWidthSamples/2):(preSpikeSamples+spikePeakWidthSamples/2)),... - mean(avgRawWF(:,:,(preSpikeSamples-3*spikePeakWidthSamples/2):(preSpikeSamples-spikePeakWidthSamples)),3) )) ,[],3); - -%select neurons to plot -if isempty(pNeu) - pNeu=1:nNeu; -end - -cMap=[0.5 0.5 0.5;IC;EC]; -f=figure('position',[10 50 1500 700]); -for i=pNeu - hA(1)=subplot(2,5,[1 7]); - [hPlot,scaleFac]=activityTracePhysicalSpacePlot(hA(1),obj.currentDataObj.channelNumbers,squeeze(avgRawWF(i,:,:)),En,'traceColor',[0.5 0.5 0.5],'gridLineWidth',0.5);hold on; - activityTracePhysicalSpacePlot(hA(1),obj.currentDataObj.channelNumbers,squeeze(baselineSubstractedSIF(i,:,:)),En,'traceColor',[0 0 0],'scaleFac',scaleFac,'DrawElectrodeNumbers',0,'DrawGrid',0); - %activityTracePhysicalSpacePlot(hA(1),obj.currentDataObj.channelNumbers,squeeze(lowpassWF(i,:,:)),En,'scaleFac',scaleFac,'DrawElectrodeNumbers',0,'DrawGrid',0); - %activityTracePhysicalSpacePlot(hA(1),obj.currentDataObj.channelNumbers,spikeMarker,En,'scaleFac',scaleFac,'traceColor',[0.7 0.7 0.7],'gridLineWidth',0.5); - tl=title(['Neu=' num2str(neuronNames(:,i)') ',idx=' num2str(i) ',Cls=' num2str(IE(fieldPar.classIE(i))) ',Mxch=' num2str(pMaxField(i)) ',PS=' num2str(fieldPar.polarityScore(i),2)]); - tl.Color=cMap(fieldPar.classIE(i),:); - hA(1).OuterPosition([1 3])=[-0.04 0.42]; - - hA(2)=subplot(2,5,[3 9]); - hA(2).Clipping='off'; - imagesc(fieldPar.XintGrid(1,:),fieldPar.YintGrid(:,1),squeeze(fieldPar.interpAll(:,:,i)));hold on; - set(hA(2),'YDir','normal'); - hCB=colorbar('position',[ 0.7463 0.5943 0.0064 0.3314]); - xlabel('[\mum]'); - ylabel('[\mum]'); - hA(2).OuterPosition([1 3])=[0.39 0.37]; - - plot(Xc,Yc,'.g') - hTmp=arrow([fieldPar.X(1,i);fieldPar.Y(1,i)]',[fieldPar.X(2,i);fieldPar.Y(2,i)],'Width',4); - if exist('testPos','var') - plot(testPos{i}(1,:),testPos{i}(2,:),'*r'); - end - - hA(3)=subplot(2,5,5); - hA(3).OuterPosition([1 3])=[0.8 0.18]; - hCB2=IntensityPhysicalSpacePlot(ch,fieldPar.val(i,:),En,'h',hA(3),'plotElectrodeNumbers',0,'plotGridLines',0,'markerSize',50,'plotColorBar',0);hold on; - hCB2=IntensityPhysicalSpacePlot(ch,maxSpikeAmp(i,:),En,'h',hA(3),'plotElectrodeNumbers',0,'plotGridLines',0,'markerSize',25); - set(hCB2,'position',[0.97 0.7800 0.0051 0.1457],'YTick',[]); - title('out=SIF , in=spk'); - - hA(4)=subplot(2,5,10); - [hPlot,scaleFac]=activityTracePhysicalSpacePlot(hA(4),obj.currentDataObj.channelNumbers,squeeze(avgRawWF(i,:,(preSpikeSamples-50):(preSpikeSamples+100))),En,'traceColor',[0 0 0],'gridLineWidth',0.5); - hA(4).OuterPosition([3 4])=[0.23 0.5]; - title('Spike WF'); - - drawnow update; - pause; - delete(hA); -end - -out=[]; -for i=1:numel(outArg) - eval(['out.(outArg{i})=' outArg{i} ';']); -end diff --git a/dataAnalysisObjects/@MEAAnalysis/plotSpikeInducedFields.m b/dataAnalysisObjects/@MEAAnalysis/plotSpikeInducedFields.m deleted file mode 100644 index 75eac59..0000000 --- a/dataAnalysisObjects/@MEAAnalysis/plotSpikeInducedFields.m +++ /dev/null @@ -1,311 +0,0 @@ -function [hand,out]=plotSpikeInducedFields(obj,varargin) - -obj.checkFileRecording; - -parseObj = inputParser; - -addParameter(parseObj,'outArg',{}); - -addParameter(parseObj,'pNeu',[],@isnumeric); %the positions of the neurons to plot -addParameter(parseObj,'angle2LateralRight',0,@isnumeric); %The angle in degrees to rotate the axes so that lateral is on the left -addParameter(parseObj,'reverseDirction',0,@isnumeric); %whether flip direction is needed to make anterior to top when lateral is left -addParameter(parseObj,'spikeEdgeBand',0,@isnumeric); %the band arround the electrode array edge (from farthest electrode) to include in stats of neuron positions (if positive, takes also neurons outside the array) -addParameter(parseObj,'fieldEdgeBand',-50,@isnumeric); %the band arround the electrode array edge (from farthest electrode) to include in stats of field positions (if positive, takes also neurons outside the array) - -addParameter(parseObj,'hand',[]); -addParameter(parseObj,'dAngle4Plot',30,@isnumeric); -addParameter(parseObj,'maxFields4Plot',375,@isnumeric); -addParameter(parseObj,'plotElectrodeNames',true,@isnumeric); -addParameter(parseObj,'plotFieldVectors',true,@isnumeric); -addParameter(parseObj,'polarPlot',true,@isnumeric); -addParameter(parseObj,'polarPlotPlotNeuronNumber',false,@isnumeric); -addParameter(parseObj,'plotNeuronNumbersAllFields',false,@isnumeric); -addParameter(parseObj,'polarPlotRemoveOuliers',false,@isnumeric); -addParameter(parseObj,'plotFieldMapAllNeurons',false,@isnumeric); -addParameter(parseObj,'polarPlotDistanceRange',[0 500],@isnumeric); -addParameter(parseObj,'plotFieldVectorsOrientation',true,@isnumeric); -addParameter(parseObj,'deleteAngleText',true,@isnumeric); -addParameter(parseObj,'EC',[0 0.2 0.8],@isnumeric); -addParameter(parseObj,'IC',[0.95 0.1 0.05],@isnumeric); - -addParameter(parseObj,'normalizeColorCode',true,@isnumeric); - -addParameter(parseObj,'extrapolateMaxima',true,@isnumeric); -addParameter(parseObj,'markerSizeAllFields',15,@isnumeric); - -addParameter(parseObj,'fileNameSpikeInducedFields',[],@isstr); -addParameter(parseObj,'overwrite',false,@isnumeric); -addParameter(parseObj,'inputParams',false,@isnumeric); - -parseObj.parse(varargin{:}); -if parseObj.Results.inputParams - disp(parseObj.Results); - return; -end -%evaluate all input parameters in workspace -for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); -end -%make parameter structure -par=parseObj.Results; - -[funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; -saveFileName=obj.files.(funName); - -obj.checkFileRecording(obj.files.getSpikePositionEstimation,'Spike position estimation file missing, please run getSpikePositionEstimation'); - -if isempty(fileNameSpikeInducedFields) - obj.checkFileRecording(obj.files.getSpikeInducedFields,'Spike induced fields file missing, please run getSpikeInducedFields'); - load(obj.files.getSpikeInducedFields,'fieldPar','pMaxField'); -else - load(fileNameSpikeInducedFields,'fieldPar','pMaxField'); -end - -%populate grid sorter object -%obj=populateGridSorterObj(obj); - -%assign parameters -ch=obj.currentDataObj.channelNumbers; -En=obj.currentDataObj.chLayoutNumbers; -%Fs=obj.currentDataObj.samplingFrequency(1); -%preSpikeMs=obj.gridSorterObj.postPreRawWindow; - - -[Xc,Yc]=obj.currentDataObj.getElectrodePositions; -%load(obj.files.getSpikePositionEstimation,'Xrs','Yrs','Zrs'); -Xrs=fieldPar.X(1,:);Yrs=fieldPar.Y(1,:); - - -nNeu=numel(fieldPar.mag); - -%% Plotting results - -rotAngRad=angle2LateralRight/180*pi; -fieldPar.anglePolar=fieldPar.angle+rotAngRad; -if reverseDirction - fieldPar.anglePolar=-fieldPar.anglePolar; -end - -%modify this to include -pExcit=find(fieldPar.classIE==3); %excitatory -pInhib=find(fieldPar.classIE==2); - -%select sub population -if isempty(pNeu) - pNeuron=true(1,nNeu); -else - pNeuron=false(1,nNeu); - pNeuron(pNeu)=true; -end - -%calculate points outside electrode area -[pBound] = boundary(Xc',Yc'); %Calculate bounding points -mX=mean([Xc;Yc],2); -[teta,r]=cart2pol((Xc(pBound)-mX(1)),Yc(pBound)-mX(2)); - -rSpike=r+spikeEdgeBand; -[xB,yB]=pol2cart(teta,rSpike); -inSpike = inpolygon(Xrs,Yrs,xB+mX(1),yB+mX(2)); -%plot(xB+mX(1),yB+mX(2));hold on;plot(Xrs,Yrs,'.');plot(Xrs(inSpike),Yrs(inSpike),'o');plot(Xc(pBound),Yc(pBound)); - -rSIF=r+fieldEdgeBand; -[xB,yB]=pol2cart(teta,rSIF); -inSIF = inpolygon(fieldPar.Xfield,fieldPar.Yfield,xB+mX(1),yB+mX(2)); -%plot(xB+mX(1),yB+mX(2));hold on;plot(fieldPar.Xfield,fieldPar.Yfield,'.');plot(fieldPar.Xfield(inSIF),fieldPar.Yfield(inSIF),'o');plot(Xc(pBound),Yc(pBound)); - -fieldPar.edgeNeurons=false(1,nNeu);%initialization -fieldPar.edgeNeurons(~inSIF | ~inSpike)=true; - -if ~isempty(polarPlotDistanceRange) - pDist=fieldPar.mag>=polarPlotDistanceRange(1) & fieldPar.mag<=polarPlotDistanceRange(2); -else - pDist=true(1,nNeu); -end -pI=intersect(find(pDist & ~fieldPar.edgeNeurons & pNeuron),pInhib); -pE=intersect(find(pDist & ~fieldPar.edgeNeurons & pNeuron),pExcit); - -if polarPlot - %prepare for plotting - f=figure('position',[100 100 500 500]); - P = panel(f); - P.pack(2,2); - P.margin=8; - - angleBins=(dAngle4Plot/360/2*pi):(dAngle4Plot/360*pi):(pi*2); - if polarPlotRemoveOuliers - maximalMag=median(fieldPar.mag([pI pE]))+6*mad(fieldPar.mag([pI pE]),1); - else - maximalMag=max(fieldPar.mag([pI pE])); - end - %inhibitory - hand.polarAx(1,1)=P(1, 1).select(); - hRose=rose(fieldPar.anglePolar(pI),angleBins); - hRose.Color=IC; - XdataRose = get(hRose,'Xdata');XdataRose=reshape(XdataRose,[4,numel(XdataRose)/4]); - YdataRose = get(hRose,'Ydata');YdataRose=reshape(YdataRose,[4,numel(YdataRose)/4]); - hPatch=patch(XdataRose,YdataRose,IC); - set(gca,'color','k'); - xlimRose=xlim; - - %calculate mean angle - mAngleI=angle(mean(exp(1i*fieldPar.anglePolar(pI)))); - %calculate mean magnitude by projecting all vectors on the unity vector in the direction of the average angle - [mU,mV]=pol2cart(mAngleI,1); - [U,V]=pol2cart(fieldPar.anglePolar(pI),fieldPar.mag(pI)); - mMagI=mean([U' V']*[mU;mV]); - - %[UI,VI]=pol2cart(mAngleI,mMagI); - hold on; - [UI,VI]=pol2cart(mAngleI,xlimRose(2)); - hand.hCompI(1)=compass(UI,VI,'r'); - hand.hCompI(1).Color=IC; - - hand.polarAx(1,2)=P(1, 2).select(); - polar(0,maximalMag,'-k');hold on; %set scale for polar plot - hand.PolarI=polar(fieldPar.anglePolar(pI),fieldPar.mag(pI),'.r'); - hand.PolarI.Color=IC; - - xlimPolar=xlim; - [UI,VI]=pol2cart(mAngleI,xlimPolar(2)); - hand.hCompI(2)=compass(UI,VI,'r'); - hand.hCompI(2).Color=IC; - - %excitatory - hand.polarAx(2,1)=P(2, 1).select(); - hRose=rose(fieldPar.anglePolar(pE),angleBins); - XdataRose = get(hRose,'Xdata');XdataRose=reshape(XdataRose,[4,numel(XdataRose)/4]); - YdataRose = get(hRose,'Ydata');YdataRose=reshape(YdataRose,[4,numel(YdataRose)/4]); - hPatch=patch(XdataRose,YdataRose,EC); - set(gca,'color','k'); - - %calculate mean angle - mAngleE=angle(mean(exp(1i*fieldPar.anglePolar(pE)))); - %calculate mean magnitude by projecting all vectors on the unity vector in the direction of the average angle - [mU,mV]=pol2cart(mAngleE,1); - [U,V]=pol2cart(fieldPar.anglePolar(pE),fieldPar.mag(pE)); - mMagE=mean([U' V']*[mU;mV]); - - hold on; - xlimRose=xlim; - [UE,VE]=pol2cart(mAngleE,xlimRose(2)); - hand.hCompE(1)=compass(UE,VE,'b'); - hand.hCompE(1).Color=EC; - - hand.polarAx(2,2)=P(2, 2).select(); - polar(0,maximalMag,'-k');hold on; %set scale for polar plot - hand.PolarE=polar(fieldPar.anglePolar(pE),fieldPar.mag(pE),'.b'); - hand.PolarE.Color=EC; - - - [UE,VE]=pol2cart(mAngleE,xlimPolar(2)); - hand.hCompE(2)=compass(UE,VE,'b'); - hand.hCompE(2).Color=EC; - - %delete angle text - if deleteAngleText - textObj1=findall(hand.polarAx(1,1),'type','text'); - textObj2=findall(hand.polarAx(1,2),'type','text'); - textObj3=findall(hand.polarAx(2,1),'type','text'); - textObj4=findall(hand.polarAx(2,2),'type','text'); - - %txt=get(textObj,'string'); - delete([textObj1(1:12);textObj2(1:12);textObj3(1:12);textObj4(1:12)]); - end - - if polarPlotPlotNeuronNumber - text(hand.polarAx(2,2),hand.PolarE.XData',hand.PolarE.YData',num2str(pE'),'FontSize',8); - text(hand.polarAx(1,2),hand.PolarI.XData',hand.PolarI.YData',num2str(pI'),'FontSize',8); - end -end - -%DSI=(prefered - (prefered+pi))/(prefered + (prefered+pi)) -if plotFieldVectors - f=figure('position',[100 100 700 700]); - hand.hVec=axes; - hand.hVec.WarpToFill='off'; %to avoid error in arrow3 function - - if plotElectrodeNames - hand.electrodeText=text(Xc,Yc,num2str(ch'),'fontsize',8,'Parent',hand.hVec,'horizontalAlignment','center'); - xlim([min(Xc)-obj.currentDataObj.electrodePitch max(Xc)+obj.currentDataObj.electrodePitch]); - ylim([min(Yc)-obj.currentDataObj.electrodePitch max(Yc)+obj.currentDataObj.electrodePitch]); - hold(hand.hVec,'on'); - end - - %hQ=quiver(Xc(neuronNames(1,:)),Yc(neuronNames(1,:)),intdX,intdY,'filled','lineWidth',2,'MaxHeadSize',0.1,'color','k','MarkerSize',2,'MarkerFaceColor','k'); - [tmpX,tmpY]=pol2cart(fieldPar.angle,50); - - nInhib2Display=numel(pI); - cMapR=flipud([ones(1,60);(0:0.01:0.59);(0:0.01:0.59)]'); - normColorI = floor(min(fieldPar.mag(pI)./maximalMag,1).*(size(cMapR,1)-1))+1; - if ~isempty(pI) - hand.hArrowI=arrow3([Xrs(pI);Yrs(pI)]',[Xrs(pI)+tmpX(pI);Yrs(pI)+tmpY(pI)]','^r2',0.7,1);hold on; - for i=1:nInhib2Display - hand.hArrowI(i+1).FaceColor=cMapR(normColorI(i),:,:); - end - end - nExcit2Display=numel(pE); - cMapB=flipud([(0:0.01:0.59);(0:0.01:0.59);ones(1,60)]'); - normColorE = floor(min(fieldPar.mag(pE)./maximalMag,1).*(size(cMapR,1)-1))+1; - if ~isempty(pE) - hand.hArrowE=arrow3([Xrs(pE);Yrs(1,pE)]',[Xrs(pE)+tmpX(pE);Yrs(1,pE)+tmpY(pE)]','^b2',0.7,1); - for i=1:nExcit2Display - hand.hArrowE(i+1).FaceColor=cMapB(normColorE(i) ,:,:); - end - end - xlabel('X [\mum]','FontSize',14); - ylabel('Y [\mum]','FontSize',14); - - if plotFieldVectorsOrientation - scale=100;shift=150; - rotMat=[cos(rotAngRad) -sin(rotAngRad);sin(rotAngRad) cos(rotAngRad)]; - x1=[0 -1;-1 0;0 1;1 0]; - x2=[0 1;1 0;0 -1;-1 0]; - xT(:,1)=[0;-1.2;0;1.2]; - xT(:,2)=[-1.2;0;1.2;0]; - x1=x1*rotMat*scale+shift; - x2=x2*rotMat*scale+shift; - xT=xT*rotMat*scale+shift; - - hand.hOrientation=arrow3(x1,x2,'^k2',0.7,1); - if reverseDirction - text(xT(:,1),xT(:,2),{'A','M','P','L'},'horizontalAlignment','center','verticalAlignment','middle') - else - text(xT(:,1),xT(:,2),{'P','M','A','L'},'horizontalAlignment','center','verticalAlignment','middle') - end - - end -end - -if plotFieldMapAllNeurons - nNeurons=numel(fieldPar.mag); - if normalizeColorCode - Ilim=0; - else - Ilim=[min(fieldPar.val(:)) max(fieldPar.val(:))]; - end - n=ceil(sqrt(min(maxFields4Plot,nNeurons)/3/5));%define images in a 3 x 5 ratio - xPlots=n*5; - yPlots=n*3; - nPlotPerPage=xPlots*yPlots; - - f=figure; - P = panel(f); - P.pack(yPlots,xPlots); - P.margin=0.001; - - for i=1:nNeurons - hand.hAllFieldAxes(i)=P(ceil(i/xPlots),i-(ceil(i/xPlots)-1)*xPlots).select(); - IntensityPhysicalSpacePlot(1:120,fieldPar.val(i,:),obj.currentDataObj.chLayoutNumbers,'plotElectrodeNumbers',0,'plotGridLines',0,'plotColorBar',0,'markerSize',markerSizeAllFields,'h',hand.hAllFieldAxes(i),'Ilim',Ilim); - - text(Xc(pChMax(i))/electrodePitch-0.5,Yc(pChMax(i))/obj.currentDataObj.electrodePitch-0.5,'o','horizontalAlignment','center','fontsize',6); - if plotNeuronNumbersAllFields - text(0,0,num2str(i),'horizontalAlignment','left','verticalAlignment','bottom','fontsize',6); - end - line( [Xc(pChMax(i)) fieldPar.Xfield(i)]/obj.currentDataObj.electrodePitch - 0.5 , [Yc(pChMax(i)) fieldPar.Yfield(i)]/obj.currentDataObj.electrodePitch - 0.5 ,'color','k'); - end -end - -out=[]; -for i=1:numel(outArg) - eval(['out.(outArg{i})=' outArg{i} ';']); -end diff --git a/dataAnalysisObjects/@MEAPAnalysis/MEAPAnalysis.m b/dataAnalysisObjects/@MEAPAnalysis/MEAPAnalysis.m deleted file mode 100644 index 61dafd7..0000000 --- a/dataAnalysisObjects/@MEAPAnalysis/MEAPAnalysis.m +++ /dev/null @@ -1,744 +0,0 @@ -classdef MEAPAnalysis < MEAAnalysis - - properties - - end - - properties (Constant) - - end - - methods - - %% MEAPAnalysis - class constructor - function [obj]=MEAPAnalysis(xlsFile) - if nargin==0 - xlsFile=[]; - end - obj=obj@MEAAnalysis(xlsFile); - end - - function [hand,data]=plotPatchTriggerSpikeOnMEA(obj,varargin) - %default parameters - parseObj = inputParser; - addParameter(parseObj,'DrawElectrodeNumbers',0,@isnumeric); - addParameter(parseObj,'scaling','std',@isstr); - addParameter(parseObj,'scaleFac',[],@isnumeric); - addParameter(parseObj,'DrawGrid',true,@isnumeric); - addParameter(parseObj,'traceColor',[0 0 0.4]); - addParameter(parseObj,'gridColor',[0.8 0.8 0.8],@isnumeric); - addParameter(parseObj,'LineWidth',1,@isnumeric); - addParameter(parseObj,'transparentScale',true,@isnumeric); - addParameter(parseObj,'avgSubstruction',false,@isnumeric); - addParameter(parseObj,'showScaleBar',true,@isnumeric); - addParameter(parseObj,'substractMean',true,@isnumeric); - addParameter(parseObj,'lockXYRatio',true,@isnumeric); - addParameter(parseObj,'medFilterMs',0,@isnumeric); - addParameter(parseObj,'averagingMethod','mean',@isnumeric);%'mean','median' - addParameter(parseObj,'spikeOrder2Include',[],@isnumeric); %Plot only a subset of spikes in each sweep e.g. 3:5 includes the 3rd to 5th spikes if existing - addParameter(parseObj,'ser',[],@isnumeric); %if empty plots the average of all series - addParameter(parseObj,'channels2Remove',[],@isnumeric); - addParameter(parseObj,'timeStartEnd',[],@isnumeric); %the start and end times to show relative to spike time - - addParameter(parseObj,'eventRejection',false,@isnumeric); - addParameter(parseObj,'precentile4EventRejection',80,@isnumeric); - addParameter(parseObj,'substractRandSIF',false,@isnumeric); - addParameter(parseObj,'minPreviousISI',0,@isnumeric); - - addParameter(parseObj,'plotRankAverage',false,@isnumeric); % Add a plot with separate averages for different spike ranks - addParameter(parseObj,'plotTimeAverage',false,@isnumeric); % Add a plot with separate averages for different spike times - addParameter(parseObj,'showColorBar',false,@isnumeric); % show color bar in time and rank plots - addParameter(parseObj,'maxRank4RankAvgPlot',7,@isnumeric); %The maximal rank of the neuron to plot, if vecot takes intervals (eg. [1 3 6 10])1-2,3-5,6-9 - addParameter(parseObj,'intervals4TimeAvgPlot',250,@isnumeric); %The maximal rank of the neuron to plot (if vector takes the range of values - addParameter(parseObj,'figureFileNameTimeAvg',[]); - addParameter(parseObj,'figureFileNameRankAvg',[]); - - addParameter(parseObj,'saveFigures',1,@isnumeric); - addParameter(parseObj,'figureFileName',[]); - addParameter(parseObj,'h',0,@ishandle); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams, disp(parseObj.Results), return, end - P=parseObj.Results; - - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - %saveFileName=obj.files.(funName); - - obj.checkFileRecording(obj.files.getPatchTriggerSpikeOnMEA,'getPatchTriggerSpikeOnMEA file missing, please run getPatchTriggerSpikeOnMEA'); - - if isempty(P.ser) - PM=load(obj.files.getPatchTriggerSpikeOnMEA); - pSeries=find(cellfun(@(x) ~isempty(x),PM.MAll)); - pars=PM.par; - if P.substractRandSIF - PMR=load(obj.files.getPatchTriggerSpikeOnMEARandomized); - end - pSpks=1:numel(PM.spkRankAll); - else - PM = matfile(obj.files.getPatchTriggerSpikeOnMEA); - [~,pSeries]=intersect(obj.recTable.Series(obj.currentPRec),P.ser); - pars=PM.par; - if P.substractRandSIF - PMR=load(obj.files.getPatchTriggerSpikeOnMEARandomized); - end - tmpNSpikes=PM.nSpikes; - pSpks=(sum(cell2mat(tmpNSpikes(1:pSeries-1)))+1):sum(cell2mat(tmpNSpikes(1:pSeries))); - end - spkRankAll=PM.spkRankAll; %this is required since indexing cant be used with matfile - spkTimeAll=PM.spkTimeAll; %this is required since indexing cant be used with matfile - - MAll=[];MAllR=[];spkOnMEAAll=[]; - for i=1:numel(pSeries) - tmp=PM.MAll(1,pSeries(i)); - MAll=cat(2,MAll,tmp{1}); - tmp=cellfun(@(x) cell2mat(x),PM.spikeTimesOnMcd(1,pSeries(i)),'UniformOutput',0); - spkOnMEAAll=[spkOnMEAAll tmp{1}]; - if P.substractRandSIF - tmp=PMR.MAll(1,pSeries(i)); - MAllR=cat(2,MAllR,tmp{1}); - end - %MAll=cat(2,MAll,matObj.MAll(pSeries(i))); - end - nTotSpks=size(MAll,2); - - if isempty(MAll) - disp('No spikes identified intra-cellular data'); - return; - end - - if ~isempty(P.spikeOrder2Include) - pRel=false(1,nTotSpks); - pRel(commonElements(spkRankAll(pSpks),P.spikeOrder2Include,0))=true; - else - pRel=true(1,nTotSpks); - end - pRel=pRel & [Inf diff(spkOnMEAAll)]>P.minPreviousISI; - - if P.substractMean - MAll=bsxfun(@minus,MAll,mean(mean(MAll(:,pRel,:),2),3)); - %MAllR=bsxfun(@minus,MAllR,mean(mean(MAllR,2),3)); - end - - if P.eventRejection - traceMAD=mean(mad(MAll(1:end-1,:,:),1,3),1); - eventThresh=prctile(traceMAD,P.precentile4EventRejection); - pRel=pRel & (traceMAD=intervals(i) & spkTimeAll(pSpks)1 - data.avgSIF=avgMEASIF; - data.pCh=pCh; - data.pT=pT; - end - if nargout>0 - hand=[f1 f2]; - end - - end - %% - function [data]=getSortingInSession(obj,varargin) - %default parameters - parseObj = inputParser; - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - par=parseObj.Results; - - %check if analysis was already done done - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - saveFileName=obj.files.(funName); - if exist(saveFileName,'file') & ~overwrite - if nargout==1 - data=load(saveFileName); - else - disp('Analysis results already exist for this method, use overwrite if needed'); - end - return; - end - - obj.populateGridSorterObj; - S=obj.gridSorterObj.getSortedData; - - - obj.checkFileRecording(obj.files.getSpikeSorting,'Patch resampling file missing, please run getPatchData'); - Pc=load(obj.files.getPatchData); - end - %% getPatchTriggerSpikeOnMEA - function [data]=getPatchTriggerSpikeOnMEA(obj,varargin) - - %default parameters - parseObj = inputParser; - addParameter(parseObj,'minSpike2NoiseAmpDiff',10,@isnumeric); - addParameter(parseObj,'spikePeakDetectionWinMs',5,@isnumeric); - addParameter(parseObj,'minFilterCrossMs',0.2,@isnumeric); - addParameter(parseObj,'minSpikePeakValue',0,@isnumeric); - addParameter(parseObj,'prePatchSpikeOnMEA',20,@isnumeric); - addParameter(parseObj,'postPatchSpikeOnMEA',100,@isnumeric); - addParameter(parseObj,'maxMissingTriggers',5,@isnumeric); - addParameter(parseObj,'medFiltDev',10,@isnumeric); - addParameter(parseObj,'medFiltWin',30,@isnumeric); - addParameter(parseObj,'triggerChannel',1,@isnumeric); - addParameter(parseObj,'substractBaseline',1,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - par=parseObj.Results; - - %check if analysis was already done done - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - saveFileName=obj.files.(funName); - if exist(saveFileName,'file') & ~overwrite - if nargout==1 - data=load(saveFileName); - else - disp('Analysis results already exist for this method, use overwrite if needed'); - end - return; - end - - obj.checkFileRecording(obj.files.getPatchData,'Patch resampling file missing, please run getPatchData'); - Pc=load(obj.files.getPatchData); - - obj.checkFileRecording(obj.files.getDigitalTriggers,'Triggers file missing, please run getDigitalTriggers'); - T=load(obj.files.getDigitalTriggers); - - %get required parameters - if ~ismember('SamplingCorrection', obj.recTable.Properties.VariableNames) - disp('No resampling factor found, sampling is assumed to be correct!'); - resamplingFactor=ones(numel(obj.currentPRec),1); - else - resamplingFactor=obj.recTable.SamplingCorrection(obj.currentPRec); - end - - % get parameters - Fs_ms=obj.currentDataObj.samplingFrequency/1000; - spikePeakDetectionWinSamples=spikePeakDetectionWinMs*Fs_ms; - minFilterCrossSamples=minFilterCrossMs*Fs_ms; - nSamples=(prePatchSpikeOnMEA+postPatchSpikeOnMEA)*Fs_ms; - medFiltWinSamples=medFiltWin*Fs_ms; - - patchSeries=obj.recTable.Series(obj.currentPRec); - clamp=obj.recTable.Clamp(obj.currentPRec); - delay2Trig=obj.recTable.delay2Trig_ms(obj.currentPRec); - protocol=obj.recTable.protocol(obj.currentPRec); - - %check if recordings are in current clamp mode - pNonCurrentClamp=~strcmp(clamp,'CC'); - if any(pNonCurrentClamp) - fprintf('The following series are not in current clamp and were not analyzed: %d\n',patchSeries(pNonCurrentClamp)); - end - pValidPatch=find(~isnan(patchSeries) & ~pNonCurrentClamp )'; - - %check for trigger validity - nTotalSweeps=sum(Pc.nPatchSweeps); - sweepNStart=[1;cumsum(Pc.nPatchSweeps(1:end-1))+1]; - if ~isempty(T.tTrig) - nTotalTrigs=numel(T.tTrig{triggerChannel}); - else - nTotalTrigs=0; - disp('No triggers exists in this recording!!! Could not align patch to MEA'); - return; - end - - if nTotalTrigs==0 - triggerCount=cellfun(@(x) numel(x),T.tTrig); - newTriggerChannel=find(triggerCount>0,1,'first'); - if ~isempty(newTriggerChannel) - fprintf('Selected trigger channel %d is empty, trying with trigger channels %d\n',triggerChannel,newTriggerChannel); - triggerChannel=newTriggerChannel; - nTotalTrigs=numel(T.tTrig{triggerChannel}); - end - end - - nMissingTrigs=nTotalSweeps-nTotalTrigs; - if nTotalSweeps==nTotalTrigs - badRecording=false; - disp([num2str(nTotalSweeps) ' sweeps detected, ' num2str(nTotalTrigs) ' triggers detect - no triggers missing']); - trig=T.tTrig{triggerChannel}; - else - disp([num2str(nTotalSweeps) ' sweeps detected, ' num2str(nTotalTrigs) ' - Trigger mismatch!!!!!!!!!!']); - if nMissingTrigs<=maxMissingTriggers - disp(['Assuming that the first ' num2str(nMissingTrigs) ' sweeps have no triggers - attempting to continue']); - else - error('Trigger mismatch is larger than maxMissingTriggers! Please check recording!!!!!!'); - end - badRecording=true; - trig=[nan(1,nMissingTrigs) T.tTrig{triggerChannel}]; - end - - nSeries=numel(patchSeries); - nSpikes=cell(1,nSeries); - pSpikes=cell(1,nSeries); - startTimesOnMcd=cell(1,nSeries); - MAll=cell(1,nSeries); - for k=pValidPatch %go over series in patch data - disp(['Calculating patch triggered MEA data - ' obj.currentRecName ' , Series ' num2str(patchSeries(k))]); - - cumsumNSpikes=0; - - for m=1:Pc.nPatchSweeps(k) - if badRecording && (m<=nMissingTrigs) - pSpikes{k}{m}=[]; - startTimesOnMcd{k}{m}=[]; - nSpikes{k}(m)=0; - else - %calculate the peak value of a spike - peakValue=max(Pc.Mp{k}(m,:)); - - %identify potential threshold crossings - med = fastmedfilt1d(Pc.Mp{k}(m,:), medFiltWinSamples,-fliplr(Pc.Mp{k}(m,1:(medFiltWinSamples/2))),-fliplr(Pc.Mp{k}(m,end+1-(medFiltWinSamples/2):end)))'; - %absMed=abs(Pc.Mp{k}(m,:)-med);medDev = fastmedfilt1d(absMed,medFiltWinSamples,-fliplr(absMed(1:(medFiltWinSamples/2))),-fliplr(absMed(end+1-(medFiltWinSamples/2):end)))'*1.4826; - patchSpikesLogical=Pc.Mp{k}(m,:)>(med+(peakValue-med)*0.5) & (peakValue-med)>minSpike2NoiseAmpDiff; - pUpCross=find((patchSpikesLogical(2:end)-patchSpikesLogical(1:end-1))==1); - pDnCross=find((patchSpikesLogical(2:end)-patchSpikesLogical(1:end-1))==-1); - - %check that the duration of med filter crossing is not too short - if numel(pDnCross)==(numel(pUpCross)) - pUpCross((pDnCross-pUpCross)0 - spikeLocal=zeros(spikePeakDetectionWinSamples,numel(pUpCross)); - pPeakMp=bsxfun(@plus,pUpCross,(1:spikePeakDetectionWinSamples)'); - pPeakMp(pPeakMp>numel(Pc.tMp{k}))=numel(Pc.tMp{k}); %remove samples outside of recording - spikeLocal(:)=Pc.Mp{k}(m,pPeakMp); - spikeLocalSmooth=csaps(1:spikePeakDetectionWinSamples,spikeLocal',0.02,1:spikePeakDetectionWinSamples,ones(1,spikePeakDetectionWinSamples))'; - [vMax,pMax]=max(spikeLocal); %find spike peak - pSpikes{k}{m}=pUpCross+pMax; %update spike position - pSpikes{k}{m}(pSpikes{k}{m}Pc.nPatchSamples(k))=Pc.nPatchSamples(k); - patchTmp(:)=Pc.Mp{k}(m,p); - M(nCh+1,:,:)=patchTmp; - - startTimes=round(Fs_ms*(trig(sweepNStart(k)+m-1)-delay2Trig(k)*resamplingFactor(k)+pSpikes{k}{m}/Fs_ms-prePatchSpikeOnMEA))/Fs_ms; - %startTimes=round(Fs_ms*(trig(m)-delay2Trig(k)*resamplingFactor(k)+pSpikes{m}/Fs_ms-prePatchSpikeOnMEA))/Fs_ms; - M(1:nCh,:,:)=obj.currentDataObj.getData(obj.currentDataObj.channelNumbers,startTimes,prePatchSpikeOnMEA+postPatchSpikeOnMEA); - MAll{k}(:,cumsumNSpikes+1:cumsumNSpikes+nSpikes{k}(m),:)=M; - cumsumNSpikes=cumsumNSpikes+nSpikes{k}(m); - else - pSpikes{k}{m}=[]; - nSpikes{k}(m)=0; - startTimes=[]; - end - spikeTimesOnMcd{k}{m}=startTimes+prePatchSpikeOnMEA; - - end - end - - if ~isempty(MAll{k}) && substractBaseline - MAll{k}(1:nCh,:,:)=bsxfun(@minus,MAll{k}(1:nCh,:,:),mean(mean(MAll{k}(1:nCh,:,1:(prePatchSpikeOnMEA*Fs_ms)),2),3)); %remove average - end - - end %for loop over series - - spkRankAll=[];spkTimeAll=[]; - nSpk=nSpikes;% has to be done in 2 steps since PM is a matlab io class - for i=pValidPatch - pStart=[1 cumsum( nSpk{i}(1:end-1) )+1]; - pEnd=cumsum( nSpk{i} ); - spkRank=cell(1,numel(pStart)); - for j=1:numel(pStart) - spkRank{j}=1:(pEnd(j)-pStart(j)+1); - end - spkRankAll=[spkRankAll cell2mat(spkRank)]; - spkTimeAll=[spkTimeAll cell2mat(pSpikes{i})]; - end - spkTimeAll=spkTimeAll/Fs_ms; - - STPatch=cellfun(@(x) x(end,:,:),MAll,'UniformOutput',1); - save(saveFileName,'par','MAll','STPatch','nSpikes','pSpikes','spikeTimesOnMcd','badRecording','spkTimeAll','spkRankAll','-v7.3','-mat'); - - end %runMEASTAs - - %% getPatchTriggerSpikeOnMEARandomized - function [data]=getPatchTriggerSpikeOnMEARandomized(obj,varargin) - - %default parameters - parseObj = inputParser; - addParameter(parseObj,'randomization','uniform',@isstr); - addParameter(parseObj,'inputParams',false,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - par=parseObj.Results; - - %check if analysis was already done done - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - saveFileName=obj.files.(funName); - if exist(saveFileName,'file') & ~overwrite - if nargout==1 - disp('Loading previouse analyzed results'); - data=load(saveFileName); - else - disp('Analysis results already exist for this method, use overwrite if needed'); - end - return; - end - - obj.checkFileRecording(obj.files.getPatchTriggerSpikeOnMEA,'getPatchTriggerSpikeOnMEA file missing, please run getPatchTriggerSpikeOnMEA'); - load(obj.files.getPatchTriggerSpikeOnMEA,'par','nSpikes','pSpikes','spikeTimesOnMcd','badRecording','spkTimeAll','spkRankAll'); - - obj.checkFileRecording(obj.files.getDigitalTriggers,'Triggers file missing, please run getDigitalTriggers'); - T=load(obj.files.getDigitalTriggers); - - delay2Trig=obj.recTable.delay2Trig_ms(obj.currentPRec); - Fs_ms=obj.currentDataObj.samplingFrequency/1000; - - c=0; - spkTimeAll=[]; - for i=1:numel(spikeTimesOnMcd) - Ttmp=T.tTrig{1}(c+1:c+numel(spikeTimesOnMcd{i})); - c=numel(Ttmp); - spkTimeAllTmp=cell(1,numel(Ttmp)); - if strcmp(randomization,'uniform') - for j=1:numel(Ttmp) - intervals=diff([Ttmp(j) spikeTimesOnMcd{i}{j}]); - prm=randperm(numel(intervals)); - - spkTimeAllTmp{j}=cumsum(intervals(prm)); - permInt=Ttmp(j)+spkTimeAllTmp{j}; - pSpikes{i}{j}=round((delay2Trig(i)+permInt-Ttmp(j))*Fs_ms); - spikeTimesOnMcd{i}{j}=permInt; - end - spkTimeAll=[spkTimeAll cell2mat(spkTimeAllTmp)]; - elseif strcmp(randomization,'shuffleTrials') - - prm=randperm(numel(Ttmp)); - - pSpikes{i}=pSpikes{i}(prm); - nSpikes{i}=nSpikes{i}(prm); - - for j=1:numel(Ttmp) - spikeTimesOnMcd{i}{j}=Ttmp(j)+pSpikes{i}{j}/Fs_ms-delay2Trig(i); - end - - spkTimeAll=[]; - spkRankAll=[]; - - end - MAll{i}=obj.currentDataObj.getData([],cell2mat(spikeTimesOnMcd{i})-par.prePatchSpikeOnMEA,par.postPatchSpikeOnMEA+par.prePatchSpikeOnMEA); - MAll{i}(end+1,:,:)=0; - end - - save(saveFileName,'par','MAll','nSpikes','pSpikes','spikeTimesOnMcd','badRecording','spkTimeAll','spkRankAll','-v7.3','-mat'); - - end - - - function plotICSpikeIdentification(obj) - - obj.checkFileRecording(obj.files.getPatchData,'Patch resampling file missing, please run getPatchData'); - Pc=load(obj.files.getPatchData,'Mp','tMp'); - - obj.checkFileRecording(obj.files.getPatchTriggerSpikeOnMEA,'Patch resampling file missing, please run getPatchTriggerSpikeOnMEA'); - PM=load(obj.files.getPatchTriggerSpikeOnMEA,'pSpikes'); - - patchSeries=obj.recTable.Series(obj.currentPRec); - pValidPatch=find(~isnan(patchSeries))'; - - for j=pValidPatch - vMax=max(Pc.Mp{j}(:)); - vMin=min(Pc.Mp{j}(:)); - f=figure; - imagesc(Pc.tMp{j},1:size(Pc.Mp{j},1),Pc.Mp{j},[max(vMax-50,vMin) vMax]);hold on; - for i=1:numel(PM.pSpikes{j}) - if ~isempty(PM.pSpikes{j}{i}) - plot(Pc.tMp{j}(PM.pSpikes{j}{i}),i,'.r') - end - end - xlabel('Time [ms]'); - ylabel('Trial #'); - end - end - - %% getPatchData - function dataOut=getPatchData(obj,varargin) - - %default parameters - parseObj = inputParser; - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - par=parseObj.Results; - - %check if analysis was already done done - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - saveFileName=obj.files.(funName); - if exist(saveFileName,'file') & ~overwrite - if nargout==1 - dataOut=load(saveFileName); - else - disp('Analysis results already exist for this method, use overwrite if needed'); - end - return; - end - - %get required parameters - if ~ismember('SamplingCorrection', obj.recTable.Properties.VariableNames) - disp('No resampling factor found, sampling is assumed to be correct!'); - resamplingFactor=ones(numel(obj.currentPRec),1); - else - resamplingFactor=obj.recTable.SamplingCorrection(obj.currentPRec); - end - - % Extract patch data (including upsampling - patchSeries=obj.recTable.Series(obj.currentPRec); - pValidPatch=find(~isnan(patchSeries))'; - clamp=obj.recTable.Clamp(obj.currentPRec); - delay2Trig=obj.recTable.delay2Trig_ms(obj.currentPRec); - fullPatchDataFilename=cellfun(@(x,y) [x filesep num2str(y)],obj.recTable.folder(obj.currentPRec),obj.recTable.PatchFile(obj.currentPRec),'UniformOutput',0); - hekaCh=obj.recTable.HekaCh(obj.currentPRec); - if ~isempty(strmatch('hekaCurrCh',obj.recTable.Properties.VariableNames)) - hekaCurrCh=obj.recTable.hekaCurrCh(obj.currentPRec); - else - hekaCurrCh=nan(size(clamp)); - end - %To add - if more than one series exists, increase the number of series by concatenating - - %check if to only analyze specific series, else analyzes all series with exluded series where patch data is not available - nSeries=numel(patchSeries); - - Mp=cell(nSeries,1);tMp=cell(nSeries,1);units=cell(nSeries,1); - MpIn=cell(nSeries,1);unitsIn=cell(nSeries,1); - nPatchSamples=zeros(nSeries,1);nPatchSweeps=zeros(nSeries,1); - for k=pValidPatch %go over series in patch data - - disp(['Resampling patch data ' obj.currentRecName ' , Series ' num2str(patchSeries(k)) ,' , Channel ' num2str(hekaCh(k))]); - - %load and parse patch data - if k==1 || ~strcmp(fullPatchDataFilename{k},fullPatchDataFilename{k-1}) - load(fullPatchDataFilename{k},'data'); %it is assumned that the same Neuron will always belong to the same patch recording - end - [ch , t]= parseHeka(data,patchSeries(k),hekaCh(k)); - if isnan(hekaCurrCh(k)) - [chI , tI]= parseHeka(data,patchSeries(k),hekaCh(k)+2); - else - [chI , tI]= parseHeka(data,patchSeries(k),hekaCurrCh(k)); - end - - %get parameters - units{k}=ch.units; - unitsIn{k}=chI.units; - nPatchSweeps(k)=size(ch.vm,2); - Fs=obj.currentDataObj.samplingFrequency; - - %clear time vector for interpolation - tMp{k}=(1000/Fs/resamplingFactor(k)):(1000/Fs/resamplingFactor(k)):max(t.ms); - nPatchSamples(k)=numel(tMp{k}); - - Mp{k}=zeros(nPatchSweeps(k),nPatchSamples(k)); %initialize data array - for m=1:nPatchSweeps(k) %upsample data - Mp{k}(m,:) = interp1(t.ms,ch.vm(:,m),tMp{k},'spline'); - MpIn{k}(m,:) = interp1(t.ms,chI.vm(:,m),tMp{k},'spline'); - end - %assume that the input current is equal in all sweeps - if all(clamp{k}=='CC') %check that recording is in current clamp - stimBinary=MpIn{k}(1,:)>max(MpIn{k}(1,:))/2; - stimOnTimes{k}=(ones(nPatchSweeps(k),1)*tMp{k}(stimBinary(2:end)==1 & stimBinary(1:end-1)==0))'; - stimOffTimes{k}=(ones(nPatchSweeps(k),1)*tMp{k}(stimBinary(2:end)==0 & stimBinary(1:end-1)==1))'; - else - stimOnTimes{k}=[]; - stimOffTimes{k}=[]; - end - - end %for loop over series - save(saveFileName,'par','Mp','MpIn','tMp','units','unitsIn','stimOnTimes','stimOffTimes','nPatchSamples','nPatchSweeps','-v7.3','-mat'); - end %getPatchData - - end -end \ No newline at end of file diff --git a/dataAnalysisObjects/@sleepAnalysis/sleepAnalysis.m b/dataAnalysisObjects/@sleepAnalysis/sleepAnalysis.m deleted file mode 100644 index ab3d375..0000000 --- a/dataAnalysisObjects/@sleepAnalysis/sleepAnalysis.m +++ /dev/null @@ -1,4546 +0,0 @@ -classdef sleepAnalysis < recAnalysis - properties - filt - end - - methods - %% class constructor - function obj=sleepAnalysis(xlsFile) - if nargin==0 - xlsFile='Y:\brainStates.xlsx'; - end - obj=obj@recAnalysis(xlsFile); - end - - %% plotLizardMovementDB - function hOut=plotLizardMovementDB(obj,varargin) - %% parameter and settings - obj.checkFileRecording; - - parseObj = inputParser; - parseObj.FunctionName='sleepAnalysis\plotLizardMovementDB'; - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'accCh',obj.recTable.accelerometerCh(obj.currentPRec),@isnumeric); - - addParameter(parseObj,'saveFigures',1,@isnumeric); - addParameter(parseObj,'nBins',18,@isnumeric); - addParameter(parseObj,'rLim4Rose',[],@isnumeric); - addParameter(parseObj,'RoseAlpha',0.9,@isnumeric); - addParameter(parseObj,'noBackground',0,@isnumeric); - addParameter(parseObj,'printLocalCopy',0,@isnumeric); - addParameter(parseObj,'h',0,@ishandle); - addParameter(parseObj,'inputParams',false,@isnumeric); - addParameter(parseObj,'plotRandomDist',1,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parPlotLizardMovementDB=parseObj.Results; - - lizardMovement=[obj.currentAnalysisFolder filesep 'lizMov.mat']; - obj.checkFileRecording(lizardMovement,'Lizard movement analysis missing, please first run getLizardMovements'); - load(lizardMovement); %load data - - dbRatioFile=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbRatioFile,'delta to beta file missing, please first run getDBRatio'); - load(dbRatioFile); %load data - - slowCyclesFile=[obj.currentAnalysisFolder filesep 'slowCycles_ch' num2str(ch) '.mat']; - obj.checkFileRecording(slowCyclesFile,'slow cycles file missing, please first run getSlowCycles'); - load(slowCyclesFile); %load data - - %calculate phase in db - for i=1:numel(TcycleOnset) - cycleDuration=TcycleOffset(i)-TcycleOnset(i); - pTmp=find(t_mov_ms>(TcycleMid(i)-cycleDuration/2) & t_mov_ms<(TcycleMid(i)+cycleDuration/2)); - phaseAll{i}=(t_mov_ms(pTmp)-(TcycleMid(i)-cycleDuration/2))/cycleDuration; - - shufTimes=rand(1,numel(pTmp))*cycleDuration; - phaseAllRand{i}=shufTimes/cycleDuration; - - pTmp=find(t_ms>(TcycleMid(i)-cycleDuration/2) & t_ms<(TcycleMid(i)+cycleDuration/2)); - resampledTemplate(i,:) = interp1((0:(numel(pTmp)-1))./(numel(pTmp)-1),bufferedDelta2BetaRatio(pTmp)',(0:(nBins-1))/(nBins-1),'spline'); - end - mResampledTemplate=mean(resampledTemplate); - - phaseMov=cell2mat(phaseAll); - phaseRand=cell2mat(phaseAllRand); - - mPhaseMov=angle(mean(exp(1i*phaseMov*2*pi))); %Mean of circular quantities - wiki - binCenters=(0:(nBins))/(nBins);binCenters=(binCenters(1:end-1)+binCenters(2:end))/2; - mPhaseDB=angle(mean(mean(resampledTemplate).*exp(1i.*binCenters*2*pi))); %Mean of circular quantities - wiki - - if nargout>0 - hOut.phaseMov=phaseMov; - hOut.phaseRand=phaseRand; - hOut.mPhaseMov=mPhaseMov; - hOut.mPhaseDB = mPhaseDB; - end - - if h==0 - fH=figure; - h=polaraxes;hold on; - else - saveFigures=0; - polaraxes(h);hold on; - end - cMap=lines(8); - - hOut.hRose=polarhistogram(phaseMov*2*pi-mPhaseDB,nBins,'FaceColor',[0.9 0.078 0.184],'FaceAlpha',0.7); - h.ThetaTick=[0:30:330]; - h.ThetaTickLabels([2 3 5 6 8 9 11 12])=cell(size([2 3 5 6 8 9 11 12])); - - if ~isempty(rLim4Rose) - h.RLim=[0 rLim4Rose]; - end - - %set(h,'color','k'); - maxSamplesInBin=h.RLim*0.9; - - hOut.hPolar=polarplot([0 (1:nBins)/nBins]*pi*2-mPhaseDB,[mResampledTemplate(end) mResampledTemplate]/(max(mResampledTemplate/maxSamplesInBin(2)))... - ,'LineWidth',2,'Color',cMap(1,:,:)); - - if plotRandomDist - hOut.hRose2=polarhistogram(phaseRand*2*pi-mPhaseDB,nBins,'FaceColor',[0.5 0.5 0.5],'FaceAlpha',0.2); - hOut.l=legend([hOut.hRose hOut.hPolar hOut.hRose2],'Movement','\delta/\beta','shuffled','mean'); - else - hOut.l=legend([hOut.hRose hOut.hPolar],'Movement','\delta/\beta'); - end - hOut.l.Color=[1 1 1]; - hOut.l.Box='off'; - hOut.l.Location='northoutside'; - - hOut.hPolarAvg=polarplot([0 0],h.RLim,'LineWidth',2,'Color','k'); - %if ~isempty(rLim4Rose) - % set(h_fake,'Visible','off'); - %end - - if saveFigures - set(fH,'PaperPositionMode','auto'); - fileName=[obj.currentPlotFolder filesep 'lizardMovementDB']; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - if printLocalCopy - fileName=[cd filesep obj.recTable.Animal{obj.currentPRec} '_Rec' num2str(obj.currentPRec) '_lizardMovementDB_' videoFileName]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - end - end - - end - - - %% getLizardMovements - function data=getLizardMovements(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'accCh',obj.recTable.accelerometerCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'envelopWindow',15,@isnumeric); %max freq. to examine - addParameter(parseObj,'kurtosisNoiseThreshold',3,@isnumeric); %Spike detection - the threshold on the kurtosis value that differentiates noise samples from data - addParameter(parseObj,'eventDetectionThresholdStd',4,@isnumeric);%Spike detection - number of standard deviations above the noise level for event detection - addParameter(parseObj,'movLongWin',1000*60*30,@isnumeric); %max freq. to examine - - addParameter(parseObj,'movWin',10000,@isnumeric); - addParameter(parseObj,'movOLWin',9000,@isnumeric); - addParameter(parseObj,'tStart',0,@isnumeric); - addParameter(parseObj,'win',0,@isnumeric); %if 0 uses the whole recording duration - addParameter(parseObj,'applyNotch',0,@isnumeric); - addParameter(parseObj,'overwrite',0,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parLizMov=parseObj.Results; - - if isnan(ch) - disp('Error: no reference channel for Delta 2 Beta extraction'); - return; - end - if ~iscell(accCh) - disp('Error: no accelerometer channels provided for movement analysis'); - return; - else - accCh=str2num(cell2mat(split(accCh{1},','))); %get accelerometer channel numbers as numerics - end - - %check if analysis was already done done - obj.files.lizMov=[obj.currentAnalysisFolder filesep 'lizMov.mat']; - if exist(obj.files.lizMov,'file') & ~overwrite - if nargout==1 - data=load(obj.files.lizMov); - else - disp('accelerometer movement analysis already exists for this recording'); - end - return; - end - obj.getFilters; - - %check if accelerometer data is saved in analog channels or in electrode data channels and verify that they exist - if all(ismember(accCh,obj.currentDataObj.channelNumbers)) && ~all(ismember(accCh,obj.currentDataObj.analogChannelNumbers)) %strcmp(class(obj.currentDataObj),'OERecording') - readFromAnalogCh=0; - if any(accCh==1) - error('Accelerometer channel numbers cant be correct since they overlap with regular channel numbers and no analog channels were found in the recording!'); - end - else - readFromAnalogCh=1; - if ~all(ismember(accCh,obj.currentDataObj.analogChannelNumbers)) - error('The specified accelerometer channel numbers do not exist in the recording! Check data table!'); - end - end - - movWinSamples=movWin/1000*obj.filt.FFs;%obj.filt.FFs in Hz, movWin in samples - movOLWinSamples=movOLWin/1000*obj.filt.FFs; - timeBin=(movWin-movOLWin); %ms - - if win==0 - win=obj.currentDataObj.recordingDuration_ms-tStart; - endTime=obj.currentDataObj.recordingDuration_ms; - else - endTime=min(win+tStart,obj.currentDataObj.recordingDuration_ms); - end - startTimes=tStart:(movLongWin-movOLWin):endTime; - - nChunks=numel(startTimes); - t_mov_ms=cell(1,nChunks); - movAll=cell(1,nChunks); - - if applyNotch - obj.filt.FN=filterData(obj.currentDataObj.samplingFrequency(1)); - obj.filt.FN.filterDesign='cheby1'; - obj.filt.FN.padding=true; - obj.filt.FN=obj.filt.FN.designNotch; - end - - fprintf('\nAccelerometer data extraction (%d chunks)-',nChunks); - for i=1:nChunks - fprintf('%d,',i); - if readFromAnalogCh - MLong=obj.currentDataObj.getAnalogData(accCh,startTimes(i),movLongWin); - else - MLong=obj.currentDataObj.getData(accCh,startTimes(i),movLongWin); - end - - %plot(squeeze(bsxfun(@minus,MLong,mean(MLong,3)))') - if applyNotch - MLong=obj.filt.FN.getFilteredData(MLong); %for 50Hz noise - end - [FMLong,t_ms]=obj.filt.F.getFilteredData(MLong); - %plot(squeeze(bsxfun(@minus,FMLong,mean(FMLong,3)))') - %y = hilbert(squeeze(FMLong)'); - - %envelop should be able to work with matrices but for some reasdon upper and lower get the same value when using matrix - [yupper1,ylower1] = envelope(squeeze(FMLong(1,1,:)),envelopWindow,'peak'); - [yupper2,ylower2] = envelope(squeeze(FMLong(2,1,:)),envelopWindow,'peak'); - [yupper3,ylower3] = envelope(squeeze(FMLong(3,1,:)),envelopWindow,'peak'); - %plot(squeeze(FMLong(1,:,:)));hold on;plot(yupper1-ylower1); - - allAxes=yupper1-ylower1+yupper2-ylower2+yupper3-ylower3; - %allAxes2=max([yupper1-ylower1 yupper2-ylower2 yupper3-ylower3],[],2); - - bufferedEnv=buffer(allAxes,500,0,'nodelay'); - - noiseSamples=bufferedEnv(:,kurtosis(bufferedEnv,0)Th); - movAll{i}=allAxes(allAxes>Th)'; - end - - fprintf('\n'); - - t_mov_ms=cell2mat(t_mov_ms); - movAll=cell2mat(movAll); - - save(obj.files.lizMov,'t_mov_ms','movAll','parLizMov'); - end - - - %% getDayTimeInRecTime - function data=getSleepVsLights(obj,varargin) - %% parameter and settings - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'referenceClock','19:00:00'); %reference for lights on/off - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'clockStartTime',[]); %cell array with the format 'HH:MM:SS' - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parDayTimeOnRecTime=parseObj.Results; - - %check if analysis was already done done - obj.files.dayTimeOnRecTime=[obj.currentAnalysisFolder filesep 'dayTimeOnRecTime.mat']; - if exist(obj.files.dayTimeOnRecTime,'file') & ~overwrite - if nargout==1 - data=load(obj.files.dayTimeOnRecTime); - else - disp('dayTimeOnRecTime file already exists'); - end - return; - end - - dbRatioFile=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbRatioFile,'Delta to beta analysis missing, please first run getDBRatio'); - dataDB=load(dbRatioFile,'t_ms'); %load data - - dbAutocorrFile=[obj.currentAnalysisFolder filesep 'dbAutocorr_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbAutocorrFile,'Delta to beta autocorr analysis missing, please first run getDBRatioAC'); - dataAC=load(dbAutocorrFile,'pSleepDBRatio','period'); %load data - - if strcmp(obj.currentDataObj.startDate(1),'(m/d/y):') - obj.currentDataObj=obj.currentDataObj.getStartRecordingTime; - end - recordingStartTimeClock=obj.currentDataObj.startDate; - - pStartSleep=find(dataAC.pSleepDBRatio==1,1,'first'); - pEndSleep=find(dataAC.pSleepDBRatio(pStartSleep:end)==0,1,'first')+pStartSleep; - - if pStartSleep==1 - sleepStartEnd=[0 dataDB.t_ms(pEndSleep)]; - else - sleepStartEnd=dataDB.t_ms([pStartSleep pEndSleep]); - end - - if exist([obj.currentAnalysisFolder filesep 'light.mat'],'file') - l=load([obj.currentAnalysisFolder filesep 'light.mat']); - startSleepFromRef_h=(sleepStartEnd-l.light(1))/1000/60/60; - manualLightAnnotation=true; - else - manualLightAnnotation=false; - tmpDV=datevec(datenum(referenceClock,'HH:MM:SS')-datenum(recordingStartTimeClock,'HH:MM:SS') ); - if tmpDV(1)<0 - startSleepFromRef_h=sleepStartEnd/1000/60/60+(24-tmpDV(:,4)+(60-tmpDV(:,5))/60+(60-tmpDV(:,6))/3600); - disp('Interval between start recording and reference time was too large -> assuming recording started after reference time'); - else - startSleepFromRef_h=sleepStartEnd/1000/60/60-(tmpDV(:,4)+tmpDV(:,5)/60+tmpDV(:,6)/3600); - end - end - - save(obj.files.dayTimeOnRecTime,'sleepStartEnd','recordingStartTimeClock','referenceClock','startSleepFromRef_h','parDayTimeOnRecTime','manualLightAnnotation'); - end - - %% getSpikeSTAs - function data=getSpikeSTAs(obj,varargin) - %% parameter and settings - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'nCycles',10,@isnumeric); - addParameter(parseObj,'cycleSelection','first',@(x) any(strcmp(x,{'first','rand'}))); - addParameter(parseObj,'binSW',10,@isnumeric); - addParameter(parseObj,'preSW',1000,@isnumeric); - addParameter(parseObj,'winSW',2000,@isnumeric); - addParameter(parseObj,'binSO',1000,@isnumeric); - addParameter(parseObj,'preSO',40000,@isnumeric); - addParameter(parseObj,'winSO',80000,@isnumeric); - addParameter(parseObj,'minSpikeRate',0.05,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parSpikeSTA=parseObj.Results; - - %check if analysis was already done done - obj.files.spikeSTA=[obj.currentAnalysisFolder filesep 'spikeSTA.mat']; - if exist(obj.files.spikeSTA,'file') & ~overwrite - if nargout==1 - data=load(obj.files.spikeSTA); - else - disp('Spike STA file already exists'); - end - return; - end - - slowCyclesFile=[obj.currentAnalysisFolder filesep 'slowCycles_ch' num2str(ch) '.mat']; - obj.checkFileRecording(slowCyclesFile,'slow cycles file missing, please first run getSlowCycles'); - load(slowCyclesFile,'TcycleMid','TcycleOffset','TcycleOnset'); %load data - - sharpWavesFile=[obj.currentAnalysisFolder filesep 'sharpWaves_ch' num2str(ch) '.mat']; - obj.checkFileRecording(sharpWavesFile,'Sharp wave file missing, please run getSharpWaves'); - load(sharpWavesFile); - - AIfile=[obj.currentAnalysisFolder filesep 'AI_2ms_4std.mat']; - obj.checkFileRecording(sharpWavesFile,'AI file missing, please run getAI'); - load(AIfile); - - nNeurons=size(icA,2); - if strcmp(cycleSelection,'first') - pCycles=1:nCycles; - elseif strcmp(cycleSelection,'rand') - pCycles=randperm(numel(TcycleMid),nCycles); - end - - %get high freq channel correlation matrix - C=zeros(nCycles,nNeurons,nNeurons); - for i=1:nCycles - MSW=squeeze(BuildBurstMatrixA(icA,round(tA/2),IA,round(TcycleMid(pCycles(i))/2),round(TcycleOffset(pCycles(i))/2)))'; - tmpC=corrcoef(MSW); - C(i,:,:)=tmpC; - end - ch=icA(1,:); - avgCrossChCorr=squeeze(mean(C,1)); - clear IA tA icA; - - %cluster high freq channel correlation matrix - [~,orderCtxDVR,ctxDVRClass]=DendrogramMatrix(avgCrossChCorr,'toPlotBinaryTree',0,'linkMethod','average','linkMetric','spearman','maxClusters',2); - - if mean(find(ctxDVRClass==1))=1 - edges=(0:parSyncDBEye.nBins)/(parSyncDBEye.nBins-0.0000001); - middles=(edges(1:end-1)+edges(2:end))/2; - - axes(h(1)); - hOut.imagesc=imagesc(0:parSyncDBEye.nBins,1:size(resampledTemplate,1),resampledTemplate);hold on; - set(h(1),'XTickLabel',[]); - ylabel('# cycle'); - p=cell2mat(cellfun(@(x) ~isempty(x),phaseAll,'UniformOutput',0)); - for i=find(p) - hOut.hP(i)=plot(phaseAll{i}*parSyncDBEye.nBins,i*ones(size(phaseAll{i})),'.r'); - end - - I=histc(phaseMov,edges); - - if numel(h)==1 - xlabel('Phase'); - set(h,'XTick',[-0.5 parSyncDBEye.nBins+0.5],'XTickLabel',{'0','2\pi'}); - xlim([-0.5 parSyncDBEye.nBins+0.5]) - end - end - - if numel(h)>=2 - axes(h(2)); - hOut.p1=plot(middles,normZeroOne(mean(resampledTemplate)),'lineWidth',2);hold on; - hOut.p2=plot(middles,normZeroOne(I(1:end-1)),'r','lineWidth',2); - xlim([0 1]); - xlabel('Phase'); - set(h(2),'XTick',[0 1],'XTickLabel',{'0','2\pi'}); - hOut.l=legend('norm. \delta/\beta','norm. OF counts'); - hOut.l.Box='off'; - hOut.l.Position=[0.6434 0.9061 0.2596 0.0812]; - end - - if numel(h)>=3 - axes(h(3)); - imagesc(resampledTemplate);hold on; - set(h(3),'YTickLabel',[],'XTickLabel',[]); - p=cell2mat(cellfun(@(x) ~isempty(x),phaseAllRand,'UniformOutput',0)); - for i=find(p) - plot(phaseAllRand{i}*parSyncDBEye.nBins,i*ones(size(phaseAllRand{i})),'*r'); - end - I=histc(phaseRand,edges); - end - - if numel(h)>=4 - axes(h(4)); - hOut.p3=plot(middles,normZeroOne(mean(resampledTemplate)),'lineWidth',2);hold on; - hOut.p4=plot(middles,normZeroOne(I(1:end-1)),'r','lineWidth',2); - xlim([0 1]); - xlabel('Phase'); - set(h(4),'XTick',[0 1],'XTickLabel',{'0','2\pi'},'YTickLabel',[]) - end - - if saveFigures - set(fH,'PaperPositionMode','auto'); - fileName=[obj.currentPlotFolder filesep 'syncEyeDBRaster_' videoFileName]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - if printLocalCopy - fileName=[cd filesep obj.recTable.Animal{obj.currentPRec} '_Rec' num2str(obj.currentPRec) '_syncEyeDBRaster_' videoFileName]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - end - end - - end - - %timeBinDB=(parDBRatio.movWin-parDBRatio.movOLWin); - - %{ - figure; - subplot(1,2,1); - imagesc(resampledTemplate);hold on; - p=cell2mat(cellfun(@(x) ~isempty(x),phaseAll,'UniformOutput',0)); - for i=find(p) - plot(phaseAll{i}*nBins,i*ones(size(phaseAll{i})),'or'); - end - - subplot(1,2,2); - imagesc(resampledTemplate);hold on; - p=cell2mat(cellfun(@(x) ~isempty(x),phaseAllRand,'UniformOutput',0)); - for i=find(p) - plot(phaseAllRand{i}*nBins,i*ones(size(phaseAllRand{i})),'or'); - end - %} - - %% plotEyeVideoOFDB - function obj=plotEyeVideoOFDB(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'winFrame',100,@isnumeric); - addParameter(parseObj,'tStart',[],@isnumeric); - addParameter(parseObj,'tEnd',[],@isnumeric); - addParameter(parseObj,'outputVideo',[]); - addParameter(parseObj,'outputFrameRate',10); - addParameter(parseObj,'opticFlowFile',[]); - addParameter(parseObj,'OFlineColor','black'); - addParameter(parseObj,'ampOFLine',50); - addParameter(parseObj,'showOnlyEye',true); - addParameter(parseObj,'videoCompressor','DV Video Encoder'); - addParameter(parseObj,'saveVideo',false,@isnumeric); - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'videoFile',[obj.recTable.VideoFiles{obj.currentPRec}],@(x) exist(x,'file')); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - dbRatioFile=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbRatioFile,'delta to beta file missing, please first run getDBRatio'); - DB=load(dbRatioFile); %load data - - [~,videoFileName]=fileparts(videoFile); - eyeTrackingFile=[obj.currentAnalysisFolder filesep 'eyeTracking_' videoFileName '.mat']; - obj.checkFileRecording(eyeTrackingFile,'Eye tracking analysis missing, please first run getEyeMovement'); - ET=load(eyeTrackingFile,'parEyeTracking','pFrames','mOF','pbboxUpdate','bboxCenterAll'); %load data - - syncDBEyeFile=[obj.currentAnalysisFolder filesep 'syncDBEye_' videoFileName '.mat']; - obj.checkFileRecording(syncDBEyeFile,'sync eye to beta 2 delta file missing, please first run getSyncedDBEyeMovements'); - sync=load(syncDBEyeFile); %load data - - if ~showOnlyEye - videoReader = VideoReader(videoFile); %initiate video obj since number of frames was already read (not allowed by matlab) - end - %videoPlayer = vision.VideoPlayer('Position',[100 100 [videoReader.Width, videoReader.Height]+30]); - if saveVideo - if isempty(outputVideo) - outputVideo=[obj.currentAnalysisFolder filesep videoFileName 'OFDB.avi']; - end - videoWriter = vision.VideoFileWriter([outputVideo '.avi'],'FrameRate',outputFrameRate); - videoWriter.VideoCompressor=videoCompressor; - end - - cMapLines=lines(8); - dPix=5; - if ~isempty(opticFlowFile) - OF=load(opticFlowFile); - tFramesOF=sync.tVideoFrames(OF.pFrames); - plotFlowField=true; - - rX=round(dPix/2):dPix:size(OF.allOF,2)-round(dPix/2); - rY=round(dPix/2):dPix:size(OF.allOF,1)-round(dPix/2); - [Y, X] = meshgrid(rX,rY); - if ~showOnlyEye - X=X+OF.initialFrameSubregion(2); - Y=Y+OF.initialFrameSubregion(1); - end - - shapes = vision.ShapeInserter; - shapes.Shape = 'Lines'; - shapes.BorderColor = OFlineColor; - else - plotFlowField=false; - end - - - smoothDB=2e-11; - interpDBOF=csaps(DB.t_ms,DB.bufferedDelta2BetaRatio,smoothDB,tFramesOF); - - %plot(tAllFrames(pFrames),interpOF);hold on;plot(tAnalyzedFrames,validmOF); - if isempty(tStart) - tStart=tFramesOF(1); - end - if isempty(tEnd) - tEnd=tFramesOF(end); - end - - pFrames=find(tFramesOF>=tStart & tFramesOF<=tEnd); - tFrames=OF.pFrames(pFrames); - - interpDB=interpDBOF(pFrames); - interpOF=OF.mOF(pFrames); - pFramesOrig=OF.pFrames(pFrames); - %plot(normZeroOne(interpDB));hold on;plot(normZeroOne(interpOF)); - - eInterpDB=[zeros(1,winFrame) interpDB zeros(1,winFrame)]./std([zeros(1,winFrame) interpDB zeros(1,winFrame)]); - eInterpOF=[zeros(1,winFrame) interpOF zeros(1,winFrame)]./2/std([zeros(1,winFrame) interpOF zeros(1,winFrame)]); - %plot(eInterpDB);hold on;plot(eInterpOF) - %plot(tAllFrames(pFrames),interpDB);hold on;plot(t_ms,bufferedDelta2BetaRatio);xlim([16027110.8963877 18570778.2072246]) - %plot(tAllFrames(pFrames),interpOF);hold on;plot(tAnalyzedFrames,validmOF);xlim([16027110.8963877 18570778.2072246]) - - %set scaling parameters for curves - if showOnlyEye - f=figure('position',[100 100 350 600]); - set(gcf,'PaperPositionMode','auto'); - - videoFrame=squeeze(OF.allIm(:,:,1)); - h(1)=subaxis(f,2,1,1,'M',0.03,'S',0.07); - h(2)=subaxis(f,2,1,2,'M',0.03,'S',0.07); - axis(h(1),'off'); - xlim(h(1),[0 2*winFrame]); - yl=[0 4]; - ylim(h(1),yl); - imshow(videoFrame,'Parent',h(2)); - set(h(2),'nextplot','replacechildren'); - hold(h(1),'on'); - pH=[]; - else - f=figure('position',[100 100 500 500]); - videoFrame=rgb2gray(videoReader.read(pFramesOrig(i))); %read will be replaced by readFrame in future versions but it is not possible to skip frames with readframes - - W=videoReader.Width; - H=videoReader.Height; - pX=(1:(2*winFrame+1))/(2*winFrame+1)*W; - yStartPixDB=H*0.4; %from top down - yPixDB=H*0.05; - yStartPixOF=H*0.5; - yPixOF=H*0.05; - ylineLim=H*0.55; - imshow(videoFrame); - set(gca,'nextplot','replacechildren'); - end - set(f,'Renderer','zbuffer'); - - for i=1:numel(pFramesOrig) - tmpDB=eInterpDB(i:i+2*winFrame); - tmpOF=eInterpOF(i:i+2*winFrame); - - if showOnlyEye - videoFrame=squeeze(OF.allIm(:,:,pFrames(i))); - else - videoFrame=rgb2gray(videoReader.read(pFramesOrig(i))); %read will be replaced by readFrame in future versions but it is not possible to skip frames with readframes - end - - if plotFlowField - currentFrame=squeeze(OF.allOF(:,:,pFrames(i))); - currentFrame=currentFrame(rY,rX); - Hor = imag(currentFrame)*ampOFLine; - Ver = real(currentFrame)*ampOFLine; - - OFlines = [Y(:)'; X(:)'; Y(:)'+Ver(:)'; X(:)'+Hor(:)']; - videoFrame = step(shapes, videoFrame, int32(OFlines)'); - % Draw lines on top of image - %pHL=line([X(:) X(:)+Hor(:)]',[Y(:) Y(:)+Ver(:)]','color',OFlineColor); - end - - if showOnlyEye - delete(pH); - imshow(videoFrame,'Parent',h(2)); - pH(1)=plot(h(1),tmpDB,'lineWidth',1,'color',cMapLines(1,:)); - pH(2)=plot(h(1),tmpOF,'lineWidth',1,'color',cMapLines(2,:)); - pH(3)=line([winFrame+1 winFrame+1],yl,'color',cMapLines(5,:),'Parent',h(1)); - %pH(4)=text(170,-0.4,[num2str(i-1) 's'],'Parent',h(1),'FontSize',16,'FontWeight','Bold'); - else - imshow(videoFrame);hold on; - pH(1)=plot(pX,-tmpDB*yPixDB+yStartPixDB,'lineWidth',3,'color',cMapLines(1,:)); - pH(2)=plot(pX,-tmpOF*yPixOF+yStartPixOF,'lineWidth',3,'color',cMapLines(2,:)); - pH(3)=line([pX(winFrame+1) pX(winFrame+1)],[ylineLim 0],'color',cMapLines(5,:)); - end - - if saveVideo %save tracked video - frame=getframe(f); - step(videoWriter, frame.cdata); - end - - end - - if saveVideo - release(videoWriter); - end - if ~showOnlyEye - delete(videoReader); - end - delete(f); - - end - - %% getSyncedDBEyeMovements - function data=getSyncedDBEyeMovements(obj,varargin) - %% parameter and settings - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'videoFile',[obj.recTable.VideoFiles{obj.currentPRec}],@(x) exist(x,'file')); - addParameter(parseObj,'win',180*1000,@isnumeric); %median filter window for extracting optic flow baseline - addParameter(parseObj,'useRobustFloatingAvg',1,@isnumeric); %if true uses floating median and MAD, if false uses a regular moving average. - addParameter(parseObj,'nStd',6,@isnumeric); %MAD (std) threshold for - addParameter(parseObj,'nBins',18,@isnumeric); - addParameter(parseObj,'digitalVideoSyncCh',5,@isnumeric); - addParameter(parseObj,'pixelMoveThresh',10,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'nFramesRemoveAfterROIShift',3,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parSyncDBEye=parseObj.Results; - - [~,videoFileName]=fileparts(videoFile); - %check if analysis was already done done - obj.files.syncDBEye=[obj.currentAnalysisFolder filesep 'syncDBEye_' videoFileName '.mat']; - if exist(obj.files.syncDBEye,'file') & ~overwrite - if nargout==1 - data=load(obj.files.syncDBEye); - else - disp(['Syncing DB with eye tracking file for video: ' videoFileName ' already exists']); - end - return; - end - - eyeTrackingFile=[obj.currentAnalysisFolder filesep 'eyeTracking_' videoFileName '.mat']; - obj.checkFileRecording(eyeTrackingFile,'Eye tracking analysis missing, please first run getEyeMovement'); - load(eyeTrackingFile,'parEyeTracking','pFrames','mOF','pbboxUpdate','bboxCenterAll'); %load data - - digiTrigFile=[obj.currentAnalysisFolder filesep 'getDigitalTriggers.mat']; - obj.checkFileRecording(digiTrigFile,'digital trigger file missing, please first run getDigitalTriggers'); - load(digiTrigFile); %load data - - dbRatioFile=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbRatioFile,'delta to beta file missing, please first run getDBRatio'); - load(dbRatioFile); %load data - - slowCyclesFile=[obj.currentAnalysisFolder filesep 'slowCycles_ch' num2str(ch) '.mat']; - obj.checkFileRecording(slowCyclesFile,'slow cycles file missing, please first run getSlowCycles'); - load(slowCyclesFile); %load data - - %remove frames that are close to a ROI shift and frames with large shifts - p2RemoveShifts=find(sqrt(diff(bboxCenterAll(:,1)).^2+diff(bboxCenterAll(:,2)).^2)>pixelMoveThresh)+1; - pFramesValid=pFrames; - validmOF=mOF; - if ~isempty(pbboxUpdate) || ~isempty(p2RemoveShifts) - p2Remove=union(p2RemoveShifts,pbboxUpdate)'; - if size(p2Remove,1)>1 - p2Remove=p2Remove'; - end - p2Remove=bsxfun(@plus,p2Remove,(0:nFramesRemoveAfterROIShift-1)'); - p2Remove=unique(p2Remove(:)); - - validmOF(p2Remove)=[]; - pFramesValid(p2Remove)=[]; - bboxCenterAll(p2Remove,:)=[]; - end - - nFramesVideo=parEyeTracking.nFramesVideo; - tFrames=tTrig{digitalVideoSyncCh}; - diffFrames=abs(numel(tFrames)-round(nFramesVideo)); - if diffFrames==0 - disp('Number of frames in video and in triggers is equal, proceeding with analysis'); - elseif diffFrames<110 - fprintf('\n\nNumber of frames in video and in triggers differs by %d, \nproceeding with analysis assuming uniform distribution of lost frames in video\n',diffFrames); - tFrames(round((1:diffFrames)/diffFrames*numel(tFrames)))=[]; - else - error(['Number of frames in video and in trigger (' num2str(digitalVideoSyncCh) ') differs by ' num2str(diffFrames) ', check recording!!!']); - end - - tAnalyzedFrames=tFrames(pFramesValid); - - %plot(tAnalyzedFrames/3600000,normZeroOne(validmOF));hold on;plot(tAnalyzedFrames/3600000,normZeroOne(bboxCenterAll)); - winSamples=round(win/1000*(parEyeTracking.frameRate/parEyeTracking.skipFrames)); - if useRobustFloatingAvg - mOFmed=fastmedfilt1d(validmOF,winSamples)'; - mOFMAD=fastmedfilt1d(abs(validmOF-mOFmed),winSamples)'*1.4826; - else - mOFmed=movmean(validmOF,winSamples); - mOFMAD=movstd(validmOF,winSamples); - end - tMovement=tAnalyzedFrames(validmOF>(mOFmed+nStd*mOFMAD)); - %plot(tAnalyzedFrames/3600000,validmOF);hold on;plot(tAnalyzedFrames/3600000,mOFmed+nStd*mOFMAD); - for i=1:numel(TcycleOnset) - cycleDuration=TcycleOffset(i)-TcycleOnset(i); - pTmp=find(tMovement>(TcycleMid(i)-cycleDuration/2) & tMovement<(TcycleMid(i)+cycleDuration/2)); - phaseAll{i}=(tMovement(pTmp)-(TcycleMid(i)-cycleDuration/2))/cycleDuration; - - shufTimes=rand(1,numel(pTmp))*cycleDuration; - phaseAllRand{i}=shufTimes/cycleDuration; - - pTmp=find(t_ms>(TcycleMid(i)-cycleDuration/2) & t_ms<(TcycleMid(i)+cycleDuration/2)); - resampledTemplate(i,:) = interp1((0:(numel(pTmp)-1))./(numel(pTmp)-1),bufferedDelta2BetaRatio(pTmp)',(0:(nBins-1))/(nBins-1),'spline'); - - %{ - cycleDuration=TcycleOffset(i)-TcycleOnset(i); - pTmp=find(tMovement>TcycleOnset(i) & tMovementTcycleOnset(i) & t_ms1 - videoReader = VideoReader(videoFile); %initiate video obj since number of frames was already read (not allowed by matlab) - %videoReader.CurrentTime=(1/videoReader.FrameRate)*(pFrames(1)-1); - nonConsecutiveVideo=true; - else - videoReader = vision.VideoFileReader(videoFile,'ImageColorSpace','Intensity','VideoOutputDataType','uint8'); % create required video objects - nonConsecutiveVideo=false; - end - videoReader.CurrentTime = startTime; - - % optic flow definitions - opticFlow = opticalFlowLK; - if ~isempty('OpticFlowNoiseThreshold') - opticFlow.NoiseThreshold=opticFlowNoiseThreshold; - end - - bboxPoints=[initialFrameSubregion(1) initialFrameSubregion(2);initialFrameSubregion(1) initialFrameSubregion(2)+initialFrameSubregion(4);initialFrameSubregion(1)+initialFrameSubregion(3) initialFrameSubregion(2)+initialFrameSubregion(4);initialFrameSubregion(1)+initialFrameSubregion(3) initialFrameSubregion(2)]; - bboxCenter=[(bboxPoints(3,1)+bboxPoints(1,1))/2 (bboxPoints(3,2)+bboxPoints(1,2))/2]; - bboxCenterOld=[(bboxPoints(3,1)+bboxPoints(1,1))/2 (bboxPoints(3,2)+bboxPoints(1,2))/2]; - bboxPointsOld=bboxPoints; - OFBox=bboxPointsOld; - - bboxShiftDistanceThreshold=round(min(initialFrameSubregion(3)*fractionOfBoxJumpThreshold,initialFrameSubregion(4)*fractionOfBoxJumpThreshold)); - - % Detect feature points in the face region. - points = detectMinEigenFeatures(initFrame, 'ROI', round(initialFrameSubregion)); - - %Display the detected points. - %figure, imshow(videoFrame), hold on, title('Detected features'); - %plot(points); - - % Create a point tracker and enable the bidirectional error constraint to make it more robust in the presence of noise and clutter. - pointTracker = vision.PointTracker('MaxBidirectionalError', 2); - - % Initialize the tracker with the initial point locations and the initial video frame. - points = points.Location; - initialize(pointTracker, points, initFrame); - - if plotTracking - videoPlayer = vision.VideoPlayer('Position',[100 100 [size(initFrame, 2), size(initFrame, 1)]+30]); - end - if saveTrackingVideo - videoWriter = vision.VideoFileWriter(trackingFileName,'FrameRate',30); - end - %savePlottedTracking - - % Make a copy of the points to be used for computing the geometric transformation between the points in the previous and the current frames - oldPoints = points; - - if saveFullOFMatrices %if to save all optic flow data - allOF=zeros(numel(yInd),numel(xInd),nFrames,'like',complex(zeros(1,'single'),zeros(1,'single'))); - allIm=zeros(numel(yInd),numel(xInd),nFrames,'single'); - else - allOF=[]; - allIm=[]; - end - - %% main loop - pbboxUpdate=[]; - bboxCenterAll=zeros(nFrames,2); - mOF=zeros(1,nFrames); - skipBoundingBoxInSkip=round(skipFramesBoundingBox/skipFrames); - parEyeTracking.skipBoundingBoxInSkip=skipBoundingBoxInSkip; - - hWB=waitbar(0,'Calculating optic flow'); - for i=1:nFrames - %frame = step(videoReader); this is faster but cant start from an arbitrary frame or jump frames - if nonConsecutiveVideo - videoFrame = rgb2gray(videoReader.readFrame); - %videoReader.CurrentTime = (pFrames(i)/nFramesVideo)*videoDuration; %92% of the time is spent on this command. - for j=1:(skipFrames-1),videoReader.readFrame;end %skip to the next frame to read. - else - videoFrame = step(videoReader); - for j=1:numel(pFrames(i+1)-pFrames(i)-1) - step(videoReader); - end - end - %{ - figure;imshow(videoFrame);hold on;plot(bboxCenter(1),bboxCenter(2),'or','markersize',20,'linewidth',3);plot(bboxPoints(:,1),bboxPoints(:,2),'.g','markersize',10);plot(points(:,1),points(:,2),'*b') - %} - if mod(i,skipBoundingBoxInSkip)==0 - waitbar(i/nFrames,hWB); - - % Track the points. Note that some points may be lost. - [points, isFound] = step(pointTracker, videoFrame); - visiblePoints = points(isFound, :); - oldInliers = oldPoints(isFound, :); - - if size(visiblePoints, 1) >= 2 % need at least 2 points to ensure we are still reliably tracking the object - - % Estimate the geometric transformation between the old points and the new points and eliminate outliers - [xform, oldInliers, visiblePoints] = estimateGeometricTransform(oldInliers, visiblePoints, 'similarity', 'MaxDistance', 4); - - % Apply the transformation to the bounding box points - bboxPoints = transformPointsForward(xform, bboxPoints); - - % Reset the points - if size(oldInliers,1)videoReader.Width - contourBox(3)=videoReader.Width-contourBox(1); - end - if (contourBox(2)+contourBox(4))>videoReader.Height - contourBox(4)=videoReader.Height-contourBox(2); - end - if contourBox(1) < 1 - contourBox(1)=1; - end - if contourBox(2) < 1 - contourBox(2)=1; - end - - newPoints = detectMinEigenFeatures(videoFrame, 'ROI', contourBox ); %this function can not receive a polygon only a rectangle along the main axes - newPoints = newPoints.Location; - in = inpolygon(newPoints(:,1),newPoints(:,2),bboxPoints(:,1),bboxPoints(:,2)); - points=newPoints(in,:); - setPoints(pointTracker,points); - %initialize(pointTracker, points, initFrame); - oldPoints = points; %all new added points are tracked - visiblePoints = points; %all new added points are tracked - else - oldPoints = visiblePoints; - setPoints(pointTracker, oldPoints); - end - %update Bounding box - check if box position was moved considerably and update accordingly - bboxCenter=[(bboxPoints(3,1)+bboxPoints(1,1))/2 (bboxPoints(3,2)+bboxPoints(1,2))/2]; %calculate center - if sqrt((bboxCenter(1)-bboxCenterOld(1)).^2+(bboxCenter(2)-bboxCenterOld(2)).^2) > bboxShiftDistanceThreshold %check if box moved too much such that its position should be updated - bboxPointsOld=bboxPoints; %update old (current) box to new box - %update the indices to be used for optic flow extraction - bboxCenterOld=bboxCenter; %update old box center - pbboxUpdate=[pbboxUpdate i]; - [xInd,yInd,OFBox]=obj.recalculateSampledImageArea4OpticFlow(xInd,yInd,bboxCenter,frameWidth,frameHeight); - %opticFlow.reset; - end - - if plotTracking - % Insert a bounding box around the object being tracked - bboxPolygon = reshape(bboxPoints', 1, []); - bboxPolygonOld = reshape(bboxPointsOld', 1, []); - OFboxPolygon = reshape(OFBox', 1, []); - - videoFramePlot = insertShape(videoFrame, 'Polygon', bboxPolygon,'LineWidth', 2); - videoFramePlot = insertShape(videoFramePlot, 'Polygon', bboxPolygonOld,'LineWidth', 2,'color','r'); - videoFramePlot = insertShape(videoFramePlot, 'Polygon', OFboxPolygon,'LineWidth', 2,'color','g'); - - % Display tracked points - videoFramePlot = insertMarker(videoFramePlot, visiblePoints, '+','Color', 'white'); - - % Display the annotated video frame using the video player object - step(videoPlayer, videoFramePlot); - - if saveTrackingVideo %save tracked video - step(videoWriter, videoFramePlot); - end - end - else - if manuallyUpdatePoints - f=figure('position',[100 100 1200 600]); - subplot(1,3,1:2);imshow(videoFrame); - [xi, yi] = ginput(1); - - %recalculate the area of the bounding box accroding to the center defined by the user. - bboxCenter=[xi,yi]; %bboxCenter=[bboxCenter(1)-xi,bboxCenter(2)-yi]; - - bboxPointsOld=bboxPoints; - bboxCenterOld=bboxCenter; - pbboxUpdate=[pbboxUpdate i]; - %recalculate position of rectangle - [xInd,yInd,OFBox]=obj.recalculateSampledImageArea4OpticFlow(xInd,yInd,bboxCenter,frameWidth,frameHeight); - %opticFlow.reset; - - contourBox=round([min(bboxPoints(:,1)) min(bboxPoints(:,2)) max(bboxPoints(:,1))-min(bboxPoints(:,1)) max(bboxPoints(:,2))-min(bboxPoints(:,2))]); - newPoints = detectMinEigenFeatures(videoFrame, 'ROI', contourBox ); %this function can not receive a polygon only a rectangle along the main axes - newPoints = newPoints.Location; - in = inpolygon(newPoints(:,1),newPoints(:,2),bboxPoints(:,1),bboxPoints(:,2)); - points=newPoints(in,:); - setPoints(pointTracker,points); - %initialize(pointTracker, points, initFrame); - oldPoints = points; %all new added points are tracked - visiblePoints = points; %all new added points are tracked - - subplot(1,3,3);imshow(videoFrame(yInd,xInd,:)); - title('Points lost. Selected region - press any key'); - pause; - close(f); - - else - disp(['Tracking analysis stopped at ' num2str(i) '/' num2str(nFrames) ' since all tracking points were lost']); - parEyeTracking.pStopDue2LostPoints=i; - mOF(i:end)=[]; - bboxCenterAll(i:end,:)=[]; - pFrames(i:end)=[]; - break; %stop for loop - end - end - - end - im = videoFrame(yInd,xInd); - tmpOF=opticFlow.estimateFlow(im); - tmpOFM=tmpOF.Magnitude; - if removeBorderOF - tmpOFM(pBorder)=0; - end - - if saveFullOFMatrices - allOF(:,:,i) = tmpOFM; - allIm(:,:,i) = im; - end - - mOF(i)=mean(mean(abs(tmpOFM))); %mean velocity for every pixel - bboxCenterAll(i,:)=bboxCenter; - - end - close(hWB); - - save(obj.files.eyeTracking,'mOF','allOF','allIm','pbboxUpdate','parEyeTracking','pFrames','bboxCenterAll','initialFrameSubregion','frameRate','nFramesVideo'); - - % Clean uprelease(videoReader); - release(pointTracker); - if nonConsecutiveVideo - delete(videoReader); - else - release(videoReader); - end - - if saveTrackingVideo %save tracked video - release(videoWriter); - end - if plotTracking - release(videoPlayer); - end - - end - - %% getRespirationMovements - function [data]=getRespirationMovements(obj,varargin) - %% parameter and settings - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'videoFile',regexp(obj.recTable.VideoFiles{obj.currentPRec},',','split'),@(x) all(isfile(x))); - addParameter(parseObj,'nFramesVideo',[],@isnumeric); - addParameter(parseObj,'startTime',0,@isnumeric); %%% in seconds %%% - addParameter(parseObj,'endTime',Inf,@isnumeric); %%% in seconds %%% - addParameter(parseObj,'initialFrameSubregion',[],@isnumeric); - addParameter(parseObj,'frameForChestPosExtraction',[],@isnumeric); - addParameter(parseObj,'fractionOfBoxJumpThreshold',0.25,@isnumeric); - addParameter(parseObj,'manuallyUpdatePoints',true,@isnumeric); - addParameter(parseObj,'loadInitialConditions',true,@isnumeric); - addParameter(parseObj,'onlyDefineInitialConditions',false,@isnumeric); - addParameter(parseObj,'updateBoundingBoxRate',0.05,@isnumeric); - addParameter(parseObj,'updatePointsFrameRate',0.01,@isnumeric); - addParameter(parseObj,'analyzedFrameRateHz',10,@isnumeric); - addParameter(parseObj,'plotTracking',false,@isnumeric); - addParameter(parseObj,'saveTrackingVideo',false,@isnumeric); - addParameter(parseObj,'trackingVideoFrameRate',2,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'savedFileName',[]); - addParameter(parseObj,'minTrackingPoints',40,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parChestTracking=parseObj.Results; - - if numel(videoFile)>1 - videoFile=videoFile{1}; - fprintf('\nMultiple video files identified. Using this one:\n%s\n',videoFile); - else - videoFile=videoFile{1}; - end - - [~,videoFileName]=fileparts(videoFile); - if isempty(savedFileName) - obj.files.chestTracking=[obj.currentAnalysisFolder filesep 'chestTracking_' videoFileName '.mat']; - trackingFileName=[obj.currentAnalysisFolder filesep videoFileName '_ChestTracking.avi']; - else - obj.files.chestTracking=[savedFileName '.mat']; - trackingFileName=[savedFileName '_ChestTracking.avi']; - end - - %check if analysis was already done done - if exist(obj.files.chestTracking,'file') & ~overwrite - if nargout==1 - data=load(obj.files.chestTracking); - else - disp(['Chest tracking file for video: ' videoFileName 'already exists']); - end - return; - end - - if exist(obj.files.chestTracking,'file') & loadInitialConditions - load(obj.files.chestTracking,'parChestTracking'); - startTime=parChestTracking.startTime; - endTime=parChestTracking.endTime; - initialFrameSubregion=parChestTracking.initialFrameSubregion; - parChestTracking.startTime=startTime; - parChestTracking.initialFrameSubregion=initialFrameSubregion; - end - - if saveTrackingVideo - plotTracking=1; - end - %% Pre processing - videoReader = VideoReader(videoFile); %initiate video obj - frameWidth=videoReader.Width; - frameHeight=videoReader.Height; - frameRate=videoReader.FrameRate; - videoDuration=videoReader.Duration; - nFramesVideo=round(videoDuration*frameRate); - - parChestTracking.frameWidth=frameWidth; - parChestTracking.frameHeight=frameHeight; - parChestTracking.frameRate=frameRate; - parChestTracking.nFramesVideo=nFramesVideo; - parChestTracking.videoDuration=videoDuration; - parChestTracking.startFrame=startTime*frameRate; - - %get initial chest location for tacking - if isempty(frameForChestPosExtraction) - frameForChestPosExtraction=parChestTracking.startFrame; - end - - if startTime~=0 % this is much faster!!! - videoReader.CurrentTime = startTime; - end - initFrame = rgb2gray(videoReader.readFrame); - startFrame = videoReader.FrameRate*videoReader.CurrentTime; - - if isempty(initialFrameSubregion) %to manually select region for extracting chest movements - f=figure('position',[100 100 1200 600]); - subplot(1,3,1:2);imshow(initFrame); - h = imrect(gca); - initialFrameSubregion=h.getPosition; - - subplot(1,3,3);imshow(initFrame(initialFrameSubregion(2):(initialFrameSubregion(2)+initialFrameSubregion(4)),initialFrameSubregion(1):(initialFrameSubregion(1)+initialFrameSubregion(3)),:)); - title('Selected region - press any key'); - pause; - initialFrameSubregion=round(h.getPosition); - close(f); - end - - if isinf(endTime) %analyze the complete video - endTime=videoDuration; - end - endFrame=round((endTime/videoDuration)*nFramesVideo); - skipFrames=round(frameRate/analyzedFrameRateHz); - updateBoundingBoxSkip=round(analyzedFrameRateHz/updateBoundingBoxRate); - updateTrackingVideoSkip=round(analyzedFrameRateHz/trackingVideoFrameRate); - updatePointsSkip=round(analyzedFrameRateHz/updatePointsFrameRate); - - pFrames=startFrame:skipFrames:endFrame; - nFrames=numel(pFrames); - delete(videoReader); - parChestTracking.initialFrameSubregion=initialFrameSubregion; - - if onlyDefineInitialConditions - save(obj.files.chestTracking,'parChestTracking','pFrames','initialFrameSubregion','frameRate','nFramesVideo'); - return; - end - - %initialization of video reader/converter objects - videoReader = VideoReader(videoFile); %initiate video obj since number of frames was already read (not allowed by matlab) - videoReader.CurrentTime = startTime; - if skipFrames~=1 - nonConsecutiveVideo=true; - else - nonConsecutiveVideo=false; - end - - bboxPoints=[initialFrameSubregion(1) initialFrameSubregion(2);initialFrameSubregion(1) initialFrameSubregion(2)+initialFrameSubregion(4);initialFrameSubregion(1)+initialFrameSubregion(3) initialFrameSubregion(2)+initialFrameSubregion(4);initialFrameSubregion(1)+initialFrameSubregion(3) initialFrameSubregion(2)]; - bboxCenter=[(bboxPoints(3,1)+bboxPoints(1,1))/2 (bboxPoints(3,2)+bboxPoints(1,2))/2]; - bboxCenterOld=[(bboxPoints(3,1)+bboxPoints(1,1))/2 (bboxPoints(3,2)+bboxPoints(1,2))/2]; - bboxPointsOld=bboxPoints; - - bboxShiftDistanceThreshold=round(min(initialFrameSubregion(3)*fractionOfBoxJumpThreshold,initialFrameSubregion(4)*fractionOfBoxJumpThreshold)); - - % Detect feature points in the face region. - points = detectMinEigenFeatures(initFrame, 'ROI', round(initialFrameSubregion)); - - % Create a point tracker and enable the bidirectional error constraint to make it more robust in the presence of noise and clutter. - pointTracker = vision.PointTracker('MaxBidirectionalError', 2); - - % Initialize the tracker with the initial point locations and the initial video frame. - points = points.Location; - initialize(pointTracker, points, initFrame); - - if plotTracking - videoPlayer = vision.VideoPlayer('Position',[100 100 [size(initFrame, 2), size(initFrame, 1)]+30]); - end - if saveTrackingVideo - videoWriter = vision.VideoFileWriter(trackingFileName,'FrameRate',trackingVideoFrameRate); - end - %savePlottedTracking - - % Make a copy of the points to be used for computing the geometric transformation between the points in the previous and the current frames - oldPoints = points; - - %% main loop - - pointsUpdate=zeros(1,nFrames,'logical'); - pbboxUpdate=zeros(1,nFrames,'logical'); - bboxCenterAll=zeros(nFrames,2); - skipBoundingBoxInSkip=round(frameRate/updateBoundingBoxRate); - parChestTracking.skipBoundingBoxInSkip=skipBoundingBoxInSkip; - %allATrans=zeros(3,3,ceil(nFrames/skipFrames),'single'); - avgPointMovement=zeros(ceil(nFrames/skipFrames),2,'single'); - nFoundPoints=zeros(ceil(nFrames/skipFrames),1); - - hWB=waitbar(0,'Calculating movement using KLT algorithm...'); - for i=1:nFrames - if nonConsecutiveVideo - %videoReader.CurrentTime = (pFrames(i)/nFramesVideo)*videoDuration; - videoFrame = rgb2gray(videoReader.readFrame); - for j=1:(skipFrames-1),videoReader.readFrame;end %skip to the next frame to read. - end - - %{ - figure;imshow(videoFrame);hold on;plot(bboxCenter(1),bboxCenter(2),'or','markersize',20,'linewidth',3);plot(bboxPoints(:,1),bboxPoints(:,2),'.g','markersize',10);plot(points(:,1),points(:,2),'*b') - %} - - % Track the points. Note that some points may be lost. - previousPoints=points; - [points, isFound] = step(pointTracker, videoFrame); - visiblePoints = points(isFound, :); - nFoundPoints(i)=sum(isFound); - avgPointMovement(i,:)=mean(maxk(visiblePoints-previousPoints(isFound,:),round(nFoundPoints(i)*0.2))); - - if mod(i,updateBoundingBoxSkip)==0 || (nFoundPoints(i)<=minTrackingPoints) - waitbar(i/nFrames,hWB); - visiblePointsOld = oldPoints(isFound, :); - % Estimate the geometric transformation between the old points and the new points and eliminate outliers - - - - if nFoundPoints(i) > 10 % need at least 2 points to ensure we are still reliably tracking the object - [xform] = estimateGeometricTransform(visiblePointsOld, visiblePoints, 'similarity', 'MaxDistance', 4); - bboxPoints = transformPointsForward(xform, bboxPoints); - bboxCenter=[(bboxPoints(3,1)+bboxPoints(1,1))/2 (bboxPoints(3,2)+bboxPoints(1,2))/2]; %calculate center - largeDiffInNPoints=(size(points,1)-size(oldPoints,1)*0.9)<0; - oldPoints=points; - - % Apply the transformation to the bounding box points - % Reset the points - if size(visiblePoints,1)videoReader.Width - contourBox(3)=videoReader.Width-contourBox(1); - end - if (contourBox(2)+contourBox(4))>videoReader.Height - contourBox(4)=videoReader.Height-contourBox(2); - end - if contourBox(1) < 1 - contourBox(1)=1; - end - if contourBox(2) < 1 - contourBox(2)=1; - end - - newPoints = detectMinEigenFeatures(videoFrame, 'ROI', contourBox ); %this function can not receive a polygon only a rectangle along the main axes - newPoints = newPoints.Location; - in = inpolygon(newPoints(:,1),newPoints(:,2),bboxPoints(:,1),bboxPoints(:,2)); - points=newPoints(in,:); - setPoints(pointTracker,points); - %initialize(pointTracker, points, initFrame); - oldPoints = points; %all new added points are tracked - visiblePoints = points; %all new added points are tracked - visiblePointsOld = points; %all new added points are tracked - pointsUpdate(i)=true; - end - - %update Bounding box - check if box position was moved considerably and update accordingly - if sqrt((bboxCenter(1)-bboxCenterOld(1)).^2+(bboxCenter(2)-bboxCenterOld(2)).^2) > bboxShiftDistanceThreshold %check if box moved too much such that its position should be updated - bboxPointsOld=bboxPoints; %update old (current) box to new box - %update the indices to be used for optic flow extraction - bboxCenterOld=bboxCenter; %update old box center - pbboxUpdate(i)=true; - end - - else - if manuallyUpdatePoints - f=figure('position',[100 100 1200 600]); - subplot(1,3,1:2);imshow(initFrame); - h = imrect(gca); - frameSubregion=h.getPosition; - - subplot(1,3,3);imshow(initFrame(frameSubregion(2):(frameSubregion(2)+frameSubregion(4)),frameSubregion(1):(frameSubregion(1)+frameSubregion(3)),:)); - title('Selected region - press any key'); - pause; - close(f); - bboxPoints=[frameSubregion(1) frameSubregion(2);frameSubregion(1) frameSubregion(2)+frameSubregion(4);frameSubregion(1)+frameSubregion(3) frameSubregion(2)+frameSubregion(4);frameSubregion(1)+frameSubregion(3) frameSubregion(2)]; - bboxCenter=[(bboxPoints(3,1)+bboxPoints(1,1))/2 (bboxPoints(3,2)+bboxPoints(1,2))/2]; - contourBox=round([min(bboxPoints(:,1)) min(bboxPoints(:,2)) max(bboxPoints(:,1))-min(bboxPoints(:,1)) max(bboxPoints(:,2))-min(bboxPoints(:,2))]); - newPoints = detectMinEigenFeatures(videoFrame, 'ROI', contourBox ); %this function can not receive a polygon only a rectangle along the main axes - newPoints = newPoints.Location; - in = inpolygon(newPoints(:,1),newPoints(:,2),bboxPoints(:,1),bboxPoints(:,2)); - points=newPoints(in,:); - setPoints(pointTracker,points); - %initialize(pointTracker, points, initFrame); - oldPoints = points; %all new added points are tracked - visiblePoints = points; %all new added points are tracked - visiblePointsOld = points; - else - disp(['Tracking analysis stopped at ' num2str(i) '/' num2str(nFrames) ' since all tracking points were lost']); - parChestTracking.pStopDue2LostPoints=i; - bboxCenterAll(i:end,:)=[]; - pFrames(i:end)=[]; - break; %stop for loop - end - end - end - - if plotTracking && mod(i,updateTrackingVideoSkip)==0 - % Insert a bounding box around the object being tracked - bboxPolygon = reshape(bboxPoints', 1, []); - bboxPolygonOld = reshape(bboxPointsOld', 1, []); - - videoFramePlot = insertShape(videoFrame, 'Polygon', bboxPolygon,'LineWidth', 2); - videoFramePlot = insertShape(videoFramePlot, 'Polygon', bboxPolygonOld,'LineWidth', 2,'color','r'); - - % Display tracked points - videoFramePlot = insertMarker(videoFramePlot, visiblePoints, '+','Color', 'white'); - - % Display the annotated video frame using the video player object - step(videoPlayer, videoFramePlot); - - if saveTrackingVideo %save tracked video - step(videoWriter, videoFramePlot); - end - end - - bboxCenterAll(i,:)=bboxCenter; - - end - close(hWB); - - save(obj.files.chestTracking,'avgPointMovement','nFoundPoints','pbboxUpdate','pointsUpdate','parChestTracking','pFrames','bboxCenterAll','initialFrameSubregion','frameRate','nFramesVideo'); - - % Clean uprelease(videoReader); - release(pointTracker); - delete(videoReader); - - if saveTrackingVideo %save tracked video - release(videoWriter); - end - if plotTracking - release(videoPlayer); - end - - end - - %% getDelta2BetaRatio - function data=getDelta2BetaRatio(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'avgOnCh',[],@isnumeric); %uses several averaged channels for d/b extraction - addParameter(parseObj,'movLongWin',1000*60*30,@isnumeric); %max freq. to examine - addParameter(parseObj,'movWin',10000,@isnumeric); - addParameter(parseObj,'movOLWin',9000,@isnumeric); - addParameter(parseObj,'segmentWelch',1000,@isnumeric); - addParameter(parseObj,'dftPointsWelch',2^10,@isnumeric); - addParameter(parseObj,'OLWelch',0.5); - addParameter(parseObj,'tStart',0,@isnumeric); - addParameter(parseObj,'win',0,@isnumeric); %if 0 uses the whole recording duration - addParameter(parseObj,'deltaBandCutoff',4,@isnumeric); - addParameter(parseObj,'betaBandLowCutoff',10,@isnumeric); - addParameter(parseObj,'betaBandHighCutoff',40,@isnumeric); - addParameter(parseObj,'applyNotch',0,@isnumeric); - addParameter(parseObj,'saveSpectralProfiles',0,@isnumeric); - addParameter(parseObj,'maxVoltage',1500,@isnumeric); - addParameter(parseObj,'overwrite',0,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parDBRatio=parseObj.Results; - - if isnan(ch) - disp('Error: no reference channel for Delta 2 Beta extraction'); - return; - end - %check if analysis was already done done - obj.files.dbRatio=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - if exist(obj.files.dbRatio,'file') & ~overwrite - if nargout==1 - data=load(obj.files.dbRatio); - else - disp('DB analysis already exists for this recording'); - end - return; - end - - obj.getFilters; - movWinSamples=movWin/1000*obj.filt.FFs;%obj.filt.FFs in Hz, movWin in samples - movOLWinSamples=movOLWin/1000*obj.filt.FFs; - timeBin=(movWin-movOLWin); %ms - - segmentWelchSamples = round(segmentWelch/1000*obj.filt.FFs); - samplesOLWelch = round(segmentWelchSamples*OLWelch); - - %run welch once to get frequencies for every bin (f) determine frequency bands - [~,f] = pwelch(randn(1,movWinSamples),segmentWelchSamples,samplesOLWelch,dftPointsWelch,obj.filt.FFs); - pfLowBand=find(f<=deltaBandCutoff); - pfHighBand=find(f>=betaBandLowCutoff & fmaxVoltage)=nan; %remove high voltage movement artifacts - - FMLongB = buffer(FMLong,movWinSamples,movOLWinSamples,'nodelay'); - pValid=all(~isnan(FMLongB)); - - deltaBetaRatioAll{i}=nan(1,numel(pValid)); %changes from zeros to nan in these 3 lines (Mark) - deltaRatioAll{i}=nan(1,numel(pValid)); - betaRatioAll{i}=nan(1,numel(pValid)); - if any(pValid) - [pxx,f] = pwelch(FMLongB(:,pValid),segmentWelchSamples,samplesOLWelch,dftPointsWelch,obj.filt.FFs); - deltaBetaRatioAll{i}(pValid)=(mean(pxx(pfLowBand,:))./mean(pxx(pfHighBand,:)))'; - deltaRatioAll{i}(pValid)=mean(pxx(pfLowBand,:))'; - betaRatioAll{i}(pValid)=mean(pxx(pfHighBand,:))'; - else - pxx=zeros(dftPointsWelch/2+1,numel(pValid)); - end - - if saveSpectralProfiles - allFreqProfiles(:,(fftInBuffer*(i-1)+find(pValid)))=pxx; - end - - t_ms{i}=startTimes(i)+((movWin/2):timeBin:(movLongWin-movWin/2)); - end - fprintf('\n'); - deltaBetaRatioAll{end}(t_ms{end}>(endTime-movWin/2))=NaN; - deltaRatioAll{end}(t_ms{end}>(endTime-movWin/2))=NaN; - betaRatioAll{end}(t_ms{end}>(endTime-movWin/2))=NaN; - - bufferedDelta2BetaRatio=cell2mat(deltaBetaRatioAll);bufferedDelta2BetaRatio=bufferedDelta2BetaRatio(:); - bufferedDeltaRatio=cell2mat(deltaRatioAll);bufferedDeltaRatio=bufferedDeltaRatio(:); - bufferedBetaRatio=cell2mat(betaRatioAll);bufferedBetaRatio=bufferedBetaRatio(:); - - t_ms=cell2mat(t_ms); - - save(obj.files.dbRatio,'t_ms','bufferedDelta2BetaRatio','parDBRatio','bufferedBetaRatio','bufferedDeltaRatio','allFreqProfiles'); - end - - %% getPhaseAnalysis - function data=getPhaseAnalysis(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch1',NaN,@isnumeric); - addParameter(parseObj,'ch2',NaN,@isnumeric); - - - addParameter(parseObj,'overwrite',0,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parPhaseAnalysis=parseObj.Results; - - if isnan(ch1) || isnan(ch2) - disp('Error: no reference channel for Delta 2 Beta extraction'); - return; - end - %check if analysis was already done done - obj.files.phaseAnalysis=[obj.currentAnalysisFolder filesep 'phaseAnalysis_ch' num2str(ch1) '-' num2str(ch2) '.mat']; - if exist(obj.files.phaseAnalysis,'file') & ~overwrite - if nargout==1 - data=load(obj.files.phaseAnalysis); - else - disp('Phase analysis already exists for this recording'); - end - return; - end - - slowCyclesFile1=[obj.currentAnalysisFolder filesep 'slowCycles_ch' num2str(ch1) '.mat']; - slowCyclesFile2=[obj.currentAnalysisFolder filesep 'slowCycles_ch' num2str(ch2) '.mat']; - obj.checkFileRecording(slowCyclesFile1,'slow cycle analysis missing, please first run getSlowCycles'); - obj.checkFileRecording(slowCyclesFile2,'slow cycle analysis missing, please first run getSlowCycles'); - SC1=load(slowCyclesFile1); %load data - SC2=load(slowCyclesFile2); %load data - - obj.getFilters; - - %Extract REM / SWS segments that are common to both channels - - %pREM=ones(1,SC1. - - fprintf('\nDelta2Beta extraction (%d chunks)-',nChunks); - - for i=1:nChunks - fprintf('%d,',i); - MLong=obj.currentDataObj.getData(ch,startTimes(i),movLongWin); - if applyNotch - FLong=obj.filt.FN.getFilteredData(MLong); %for 50Hz noise - end - FMLong=obj.filt.F.getFilteredData(MLong); - - FMLong(FMLong<-maxVoltage | FMLong>maxVoltage)=nan; %remove high voltage movement artifacts - - end - - - - movWinSamples=movWin/1000*obj.filt.FFs;%obj.filt.FFs in Hz, movWin in samples - movOLWinSamples=movOLWin/1000*obj.filt.FFs; - timeBin=(movWin-movOLWin); %ms - - segmentWelchSamples = round(segmentWelch/1000*obj.filt.FFs); - samplesOLWelch = round(segmentWelchSamples*OLWelch); - - %run welch once to get frequencies for every bin (f) determine frequency bands - [~,f] = pwelch(randn(1,movWinSamples),segmentWelchSamples,samplesOLWelch,dftPointsWelch,obj.filt.FFs); - pfLowBand=find(f<=deltaBandCutoff); - pfHighBand=find(f>=betaBandLowCutoff & fmaxVoltage)=nan; %remove high voltage movement artifacts - - FMLongB = buffer(FMLong,movWinSamples,movOLWinSamples,'nodelay'); - pValid=all(~isnan(FMLongB)); - - [pxx,f] = pwelch(FMLongB(:,pValid),segmentWelchSamples,samplesOLWelch,dftPointsWelch,obj.filt.FFs); - - if saveSpectralProfiles - allFreqProfiles(:,(fftInBuffer*(i-1)+find(pValid)))=pxx; - end - deltaBetaRatioAll{i}=zeros(1,numel(pValid)); - deltaBetaRatioAll{i}(pValid)=(mean(pxx(pfLowBand,:))./mean(pxx(pfHighBand,:)))'; - - deltaRatioAll{i}=zeros(1,numel(pValid)); - deltaRatioAll{i}(pValid)=mean(pxx(pfLowBand,:))'; - - betaRatioAll{i}=zeros(1,numel(pValid)); - betaRatioAll{i}(pValid)=mean(pxx(pfHighBand,:))'; - - t_ms{i}=startTimes(i)+((movWin/2):timeBin:(movLongWin-movWin/2)); - end - fprintf('\n'); - deltaBetaRatioAll{end}(t_ms{end}>(endTime-movWin/2))=NaN; - deltaRatioAll{end}(t_ms{end}>(endTime-movWin/2))=NaN; - betaRatioAll{end}(t_ms{end}>(endTime-movWin/2))=NaN; - - bufferedDelta2BetaRatio=cell2mat(deltaBetaRatioAll);bufferedDelta2BetaRatio=bufferedDelta2BetaRatio(:); - bufferedDeltaRatio=cell2mat(deltaRatioAll);bufferedDeltaRatio=bufferedDeltaRatio(:); - bufferedBetaRatio=cell2mat(betaRatioAll);bufferedBetaRatio=bufferedBetaRatio(:); - - t_ms=cell2mat(t_ms); - - save(obj.files.dbRatio,'t_ms','bufferedDelta2BetaRatio','parDBRatio','bufferedBetaRatio','bufferedDeltaRatio','allFreqProfiles'); - end - - %% getSlowCycles - function data=getSlowCycles(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'medianFiltWin',1000*20,@isnumeric); - addParameter(parseObj,'longOrdFiltWin',1000*1000,@isnumeric); - addParameter(parseObj,'longOrdFiltOrd',0.6,@isnumeric); - addParameter(parseObj,'estimateFilterValuesFromPeriod',1,@isnumeric); - addParameter(parseObj,'removeNonSignificatACSegments',0,@isnumeric); - addParameter(parseObj,'excludeIrregularCycles',1,@isnumeric); %for excluding cycles which do not have a regular duration - addParameter(parseObj,'overwrite',0,@isnumeric); - - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parSlowCycles=parseObj.Results; - - %check if analysis was already done done - obj.files.slowCycles=[obj.currentAnalysisFolder filesep 'slowCycles_ch' num2str(ch) '.mat']; - if exist(obj.files.slowCycles,'file') & ~overwrite - if nargout==1 - data=load(obj.files.slowCycles); - else - disp('Slow cycle analysis already exists for this recording'); - end - return; - end - - dbRatioFile=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbRatioFile,'Delta to beta analysis missing, please first run getDelta2BetaRatio'); - load(dbRatioFile,'t_ms','bufferedDelta2BetaRatio','parDBRatio'); %load data - - dbAutocorrFile=[obj.currentAnalysisFolder filesep 'dbAutocorr_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbAutocorrFile,'Delta to beta autocorr analysis missing, please first run getDelta2BetaAC'); - load(dbAutocorrFile,'pSleepDBRatio','period','pSleepSlidingAC','pSleepDBRatioAC'); %load data - - timeBin=(parDBRatio.movWin-parDBRatio.movOLWin); - bufferedDelta2BetaRatio(isnan(bufferedDelta2BetaRatio))=0; - - %calculate filter values based on oscillation period - band=1.5; - if estimateFilterValuesFromPeriod - medianFiltWin=round(period*0.25); - maxCycleSamples=round((period*band)/timeBin); - minCycleSamples=round(period/band/timeBin); - else - maxCycleSamples=round(140/timeBin); - minCycleSamples=round(10/timeBin); - end - - %smooth with median filter - medianFiltSamples=medianFiltWin/timeBin; - DBRatioMedFilt = fastmedfilt1d(bufferedDelta2BetaRatio, medianFiltSamples); - - %plot(t_ms/1000/60/60,DBRatioMedFilt);hold on;plot(t_ms/1000/60/60,DBLongOrdFilt); - - HAng=phase(hilbert(DBRatioMedFilt)); - %the peaks in this analysis are the end of the delta period and the troughs are the - [cycleMidPeaks,pTcycleMid]=findpeaks(HAng,'MinPeakProminence',pi/8,'MinPeakDistance',minCycleSamples,'MinPeakHeight',0,'MinPeakWidth',minCycleSamples/4); - cycleMid=t_ms(pTcycleMid); - %{ - h(1)=subplot(2,1,1);plot(t_ms/1000/60/60,DBRatioMedFilt); - h(2)=subplot(2,1,2);plot(t_ms/1000/60/60,HAng);hold on;plot(cycleMid/1000/60/60,cycleMidPeaks,'or'); - linkaxes(h,'x'); - %} - %tSlidingAC - removeNonSleepSegments=1; - if removeNonSleepSegments - %pTcycleOnset is places in t_ms - pTcycleMid=intersect(pTcycleMid,find(pSleepDBRatio)); - end - - if removeNonSignificatACSegments - pTcycleMid=intersect(pTcycleMid,find(pSleepDBRatioAC)); - end - - if excludeIrregularCycles %check if cycles are within the range of band and if not remove them - pTcycleMid(diff(pTcycleMid)maxCycleSamples; - pTcycleOnset(ppRemove)=[]; - pTcycleMid(ppRemove)=[]; - pTcycleOffset(ppRemove)=[]; - - TcycleMid=t_ms(pTcycleMid); - TcycleOnset=t_ms(pTcycleOnset); - TcycleOffset=t_ms(pTcycleOffset); - - %plot(t_ms/1000/60/60,HAng);hold on;plot(TcycleMid/1000/60/60,HAng(pTcycleMid),'or');plot(TcycleOffset/1000/60/60,HAng(pTcycleOffset),'og');plot(TcycleOnset/1000/60/60,HAng(pTcycleOnset),'.m'); - save(obj.files.slowCycles,'parSlowCycles','TcycleOnset','TcycleOffset','TcycleMid','pSleepDBRatio','t_ms','DBRatioMedFilt','HAng'); - end - %{ - function data=getSlowCycles(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'medianFiltWin',1000*20,@isnumeric); - addParameter(parseObj,'longOrdFiltWin',1000*1000,@isnumeric); - addParameter(parseObj,'longOrdFiltOrd',0.6,@isnumeric); - addParameter(parseObj,'estimateFilterValuesFromPeriod',1,@isnumeric); - addParameter(parseObj,'removeNonSignificatACSegments',0,@isnumeric); - addParameter(parseObj,'excludeIrregularCycles',1,@isnumeric); %for excluding cycles which do not have a regular duration - addParameter(parseObj,'overwrite',0,@isnumeric); - - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parSlowCycles=parseObj.Results; - - %check if analysis was already done done - obj.files.slowCycles=[obj.currentAnalysisFolder filesep 'slowCycles_ch' num2str(ch) '.mat']; - if exist(obj.files.slowCycles,'file') & ~overwrite - if nargout==1 - data=load(obj.files.slowCycles); - else - disp('Slow cycle analysis already exists for this recording'); - end - return; - end - - dbRatioFile=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbRatioFile,'Delta to beta analysis missing, please first run getDelta2BetaRatio'); - load(dbRatioFile,'t_ms','bufferedDelta2BetaRatio','parDBRatio'); %load data - - dbAutocorrFile=[obj.currentAnalysisFolder filesep 'dbAutocorr_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbAutocorrFile,'Delta to beta autocorr analysis missing, please first run getDelta2BetaAC'); - load(dbAutocorrFile,'pSleepDBRatio','period','pSleepSlidingAC','pSleepDBRatioAC'); %load data - - timeBin=(parDBRatio.movWin-parDBRatio.movOLWin); - bufferedDelta2BetaRatio(isnan(bufferedDelta2BetaRatio))=0; - - %calculate filter values based on oscillation period - band=1.5; - if estimateFilterValuesFromPeriod - medianFiltWin=round(period*0.25); - maxCycleSamples=round((period*band)/timeBin); - minCycleSamples=round(period/band/timeBin); - else - maxCycleSamples=round(140/timeBin); - minCycleSamples=round(10/timeBin); - end - - %smooth with median filter - medianFiltSamples=medianFiltWin/timeBin; - DBRatioMedFilt = fastmedfilt1d(bufferedDelta2BetaRatio, medianFiltSamples); - - %plot(t_ms/1000/60/60,DBRatioMedFilt);hold on;plot(t_ms/1000/60/60,DBLongOrdFilt); - - Th=[]; - hilbertPhaseCycleAnalysis=1; - if hilbertPhaseCycleAnalysis - HAng=phase(hilbert(DBRatioMedFilt)); - %the peaks in this analysis are the end of the delta period and the troughs are the - [cycleOnsetPeaks,pTcycleOnset]=findpeaks(HAng,'MinPeakProminence',pi/8,'MinPeakDistance',minCycleSamples,'MinPeakHeight',0,'MinPeakWidth',minCycleSamples/4); - cycleOnset=t_ms(pTcycleOnset); - % - %{ - h(1)=subplot(2,1,1);plot(t_ms/1000/60/60,DBRatioMedFilt); - h(2)=subplot(2,1,2);plot(t_ms/1000/60/60,HAng);hold on;plot(cycleOnset/1000/60/60,cycleOnsetPeaks,'or'); - linkaxes(h,'x'); - %} - else - edgeSamples=100; - %long order filter to determine edges of DB fluctuation - longOrdFiltSamples=round(longOrdFiltWin/timeBin); - longOrdFiltOrdSamples=round(longOrdFiltOrd*longOrdFiltSamples); - DBLongOrdFilt = ordfilt2(DBRatioMedFilt, longOrdFiltOrdSamples, ones(longOrdFiltSamples,1)); - sortDBLongOrdFilt=sort(DBLongOrdFilt); - sortDBLongOrdFilt(isnan(sortDBLongOrdFilt))=[]; - Th=mean(sortDBLongOrdFilt(1:edgeSamples))+(mean(sortDBLongOrdFilt((end-edgeSamples):end))-mean(sortDBLongOrdFilt(1:edgeSamples)))/2; - %Th=min(DBLongOrdFilt)+(max(DBLongOrdFilt)-min(DBLongOrdFilt))/2; - pTcycleOnset=find((DBRatioMedFilt(2:end)>=Th & DBRatioMedFilt(1:end-1)maxCycleSamples; - pTcycleOffset(ppRemove)=[]; - pTcycleOnset(ppRemove)=[]; - else - pTcycleOffset=pTcycleOnset(2:end); - pTcycleOnset=pTcycleOnset(1:end-1); - end - - %calculate the middle state transition - - pTcycleMid=zeros(numel(pTcycleOnset),1); - %edgesSamples=10; - for i=1:numel(pTcycleOnset) - [~,pTmp]=min(HAng(pTcycleOnset(i):pTcycleOffset(i))); - pTcycleMid(i)=pTmp+pTcycleOnset(i)-1; - % pTmp=find(DBRatioMedFilt((pTcycleOnset(i)+edgesSamples):(pTcycleOffset(i)-edgesSamples))obj.currentDataObj.recordingDuration_ms, win=obj.currentDataObj.recordingDuration_ms-tStart; end - - pt=find(t_ms>tStart & t_ms<=(tStart+win)); - timeBin=(parDBRatio.movWin-parDBRatio.movOLWin); - nSamples=numel(bufferedDelta2BetaRatio(pt)); - - movWinSamples=round(chunksLength/timeBin); - chunks=buffer(bufferedDelta2BetaRatio(pt),movWinSamples); - tLong=t_ms(round(movWinSamples/2):movWinSamples:nSamples)/1000/60/60; - - sortedBetaRatio=sort(bufferedDelta2BetaRatio(~isnan(bufferedDelta2BetaRatio))); - estimateColorMapMax=round(sortedBetaRatio(round(numel(sortedBetaRatio)*0.95))/100)*100; - if estimateColorMapMax==0 - estimateColorMapMax=max(10,round(sortedBetaRatio(round(numel(sortedBetaRatio)*0.95))/10)*10); - end - if h==0 - fDB=figure('Position',[100 100 900 500]); - h=axes; - else - saveFigures=0; - axes(h); - end - - imagesc((1:size(chunks,1))*timeBin/1000/60,tLong,chunks',[0 estimateColorMapMax]); - xlabel('Time [min]');ylabel('Time [hour]'); - - h(2)=colorbar; - set(h(2),'position',[0.9115 0.7040 0.0129 0.2220]); - ylabel(h(2),'\delta/\beta'); - - if saveFigures - set(fDB,'PaperPositionMode','auto'); - fileName=[obj.currentPlotFolder filesep 'dbRatio_ch' num2str(ch)]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - if printLocalCopy - fileName=[cd filesep obj.recTable.Animal{obj.currentPRec} '_Rec' num2str(obj.currentPRec) '_dbRatio_ch' num2str(ch)]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - end - end - end - - %% plotDelta2BetaAC - function h=plotDelta2BetaAC(obj,varargin) - %sleepAnalysis.getDelta2BetaAC - input parameters: - parseObj = inputParser; - parseObj.FunctionName='sleepAnalysis\plotDelta2BetaAC'; - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'saveFigures',1,@isnumeric); - addParameter(parseObj,'printLocalCopy',0,@isnumeric); - addParameter(parseObj,'h',0,@ishandle); - - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - dbAutocorrFile=[obj.currentAnalysisFolder filesep 'dbAutocorr_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbAutocorrFile,'Autocorr analysis missing, please first run getDelta2BetaAC'); - load(dbAutocorrFile); - - if h==0 - fAC=figure; - h=axes; - else - saveFigures=0; - axes(h); - end - - lineHandles = stem(xcf_lags/1000,real(xcf),'filled','r-o'); - set(lineHandles(1),'MarkerSize',4); - grid('on'); - xlabel('Period [s]'); - ylabel('Auto corr.'); - hold('on'); - - plot(period/1000,real(xcf(pPeriod)),'o','MarkerSize',5,'color','k'); - text(period/1000,0.05+real(xcf(pPeriod)),num2str(period/1000)); - - a = axis; - plot([a(1) a(1); a(2) a(2)],[xcf_bounds([1 1]) xcf_bounds([2 2])],'-b'); - plot([a(1) a(2)],[0 0],'-k'); - hold('off'); - - if saveFigures - set(fAC,'PaperPositionMode','auto'); - fileName=[obj.currentPlotFolder filesep 'dbAC_ch' num2str(parDbAutocorr.ch) '_t' num2str(parDbAutocorr.tStart) '_w' num2str(parDbAutocorr.win)]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - if printLocalCopy - fileName=[cd filesep obj.recTable.Animal{obj.currentPRec} '_Rec' num2str(obj.currentPRec) '_dbAC_ch' num2str(parDbAutocorr.ch) '_t' num2str(parDbAutocorr.tStart) '_w' num2str(parDbAutocorr.win)]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - end - end - - end - - %% plotDelta2BetaSlidingAC - function h=plotDelta2BetaSlidingAC(obj,varargin) - %sleepAnalysis.plotDelta2BetaSlidingAC - input parameters: - parseObj = inputParser; - parseObj.FunctionName='sleepAnalysis\plotDelta2BetaSlidingAC'; - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'tStart',0,@isnumeric); - addParameter(parseObj,'win',obj.currentDataObj.recordingDuration_ms,@isnumeric); - addParameter(parseObj,'saveFigures',1,@isnumeric); - addParameter(parseObj,'printLocalCopy',0,@isnumeric); - addParameter(parseObj,'h',0); - - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - dbAutocorrFile=[obj.currentAnalysisFolder filesep 'dbAutocorr_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbAutocorrFile,'Autocorr analysis missing, please first run getDelta2BetaAC'); - load(dbAutocorrFile); - - if win+tStart>obj.currentDataObj.recordingDuration_ms, win=obj.currentDataObj.recordingDuration_ms-tStart; end - pt=find(tSlidingAC>=tStart & tSlidingAC<=(tStart+win+parDbAutocorr.movingAutoCorrWin/2)); - tSlidingAC=tSlidingAC-tSlidingAC(pt(1)); - - if h(1)==0 - fSAC=figure('position',[200 200 550 600]); - h(1)=subaxis(fSAC,2,1,1,'S',0.05,'M',0.1); - h(2)=subaxis(fSAC,2,1,2,'S',0.05,'M',0.1); - else - saveFigures=0; - end - - axes(h(1)); - h(3)=imagesc(tSlidingAC(pt)/1000/60/60,autocorrTimes/1000,real(acf(:,pt)),[-0.5 0.5]); - ylabel('Autocorr lag [s]'); - ylim(xcf_lags([1 end])/1000);%important for panel plots - yl=ylim; - xlim(tSlidingAC(pt([1 end]))/1000/60/60); %important for panel plots - xl=xlim; - set(h(1),'YDir','normal'); - set(h(1),'XTickLabel',[]); - hold on; - - x=[(tStartSleep-tStart)/1000/60/60 (tEndSleep-tStart)/1000/60/60 (tEndSleep-tStart)/1000/60/60 (tStartSleep-tStart)/1000/60/60]; - W=0.03; - y=yl(2)+W*[diff(yl) diff(yl) diff(yl)*3 diff(yl)*3]; - h(4)=patch(x,y,[0.2 0.2 0.2],'Clipping','off','lineStyle','none','FaceAlpha',0.5); - text((x(1)+x(2))/2,(y(1)+y(3))/2,'E-Sleep','HorizontalAlignment','center','VerticalAlignment','middle'); - h(7)=line(xlim,[period/1000 period/1000],'color',[1 0.8 0.8]); - - axes(h(2)); - - h(5)=scatter(tSlidingAC(pSleepSlidingAC)/1000/60/60,acfPeriodAll(pSleepSlidingAC)/1000,5,[0.8 0.8 1],'filled');hold on; - h(6)=plot((tFilteredSlidingPeriod-tStart)/1000/60/60,filteredSlidingPeriod/1000,'-','lineWidth',3); - ylabel('Period [s]'); - xlabel('Time [h]'); - set(h(2),'Box','on'); - axis tight; - xlim(xl); - yl=ylim; - marg=diff(yl)*0.02; - ylim([yl(1)-marg,yl(2)+marg]); - h(8:9)=line([parDbAutocorr.tStart parDbAutocorr.tStart;parDbAutocorr.tStart+parDbAutocorr.win parDbAutocorr.tStart+parDbAutocorr.win]'/1000/60/60,[yl;yl]','color',[0.8 1 0.8]); - - h(10)=line([bestSleepTime/1000/60/60,bestSleepTime/1000/60/60],yl,'color','k'); - linkaxes(h(1:2),'x'); - - if saveFigures - set(fSAC,'PaperPositionMode','auto'); - fileName=[obj.currentPlotFolder filesep 'dbSAC_ch' num2str(parDbAutocorr.ch) '_t' num2str(parDbAutocorr.tStart) '_w' num2str(parDbAutocorr.win)]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - if printLocalCopy - fileName=[cd filesep obj.recTable.Animal{obj.currentPRec} '_Rec' num2str(obj.currentPRec) '_dbSAC_ch' num2str(parDbAutocorr.ch) '_t' num2str(parDbAutocorr.tStart) '_w' num2str(parDbAutocorr.win)]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - end - end - end - - %% getDelta2BetaAC - function [data]=getDelta2BetaAC(obj,varargin) - %sleepAnalysis.getDelta2BetaAC - input parameters: ch,tStart,win,movOLWin,XCFLag,movingAutoCorrWin,movingAutoCorrOL - parseObj = inputParser; - parseObj.FunctionName='sleepAnalysis\getDelta2BetaAC'; - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'tStart',0,@isnumeric); %ms - addParameter(parseObj,'win',obj.currentDataObj.recordingDuration_ms,@isnumeric);%ms - addParameter(parseObj,'maxPeriodBand',20,@isnumeric); - addParameter(parseObj,'movOLWin',4000,@isnumeric); - addParameter(parseObj,'XCFLag',500000,@isnumeric); - addParameter(parseObj,'movingAutoCorrWin',1000*1000,@isnumeric); - addParameter(parseObj,'movingAutoCorrOL',900*1000,@isnumeric); - addParameter(parseObj,'oscilDurationMovingWin',60*60*1000,@isnumeric); - addParameter(parseObj,'smoothingDuration',1000*60*60,@isnumeric); - addParameter(parseObj,'oscilDurationThresh',0.25,@isnumeric); - addParameter(parseObj,'bestSleepWindow',2*60*60*1000,@isnumeric); - addParameter(parseObj,'overwrite',0,@isnumeric); - - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parDbAutocorr=parseObj.Results; - - %check if analysis was already done done - obj.files.dbAutocorr=[obj.currentAnalysisFolder filesep 'dbAutocorr_ch' num2str(ch) '.mat']; - if exist(obj.files.dbAutocorr,'file') & ~overwrite - if nargout==1 - data=load(obj.files.dbAutocorr); - else - disp('Autocorr analysis already exists for this recording'); - end - return; - end - - dbRatioFile=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbRatioFile,'Delta to beta analysis missing, please first run getDelta2BetaRatio'); - load(dbRatioFile); %load data - - bufferedDelta2BetaRatio(isnan(bufferedDelta2BetaRatio))=0; %for cross-corr analysis nans result in imaginary values - - %cross correlation analysis - pOscillation=find(t_ms>tStart & t_ms<(tStart+win)); - timeBin=(parDBRatio.movWin-parDBRatio.movOLWin); - XCFLagSamples=XCFLag/timeBin; - [xcf,xcf_lags,xcf_bounds]=crosscorr(bufferedDelta2BetaRatio(pOscillation),bufferedDelta2BetaRatio(pOscillation),XCFLagSamples); - - xcf_lags=xcf_lags*1000; - %calculate periodicity - - %find first vally and peak in the autocorrelation function - [~,pPeak] = findpeaks(xcf(XCFLagSamples+1:end),'MinPeakProminence',0.1); - [~,pVally] = findpeaks(-xcf(XCFLagSamples+1:end),'MinPeakProminence',0.1); - if isempty(pPeak) %if peak is weak, try a different value - [~,pPeak] = findpeaks(xcf(XCFLagSamples+1:end),'MinPeakProminence',0.04); - [~,pVally] = findpeaks(-xcf(XCFLagSamples+1:end),'MinPeakProminence',0.04); - disp('Prominance for peak detection was reduced to 0.04 due to low periodicity values!!!'); - end - - if isempty(pPeak) | isempty(pVally) - pPeriod=NaN; - period=NaN; - pVally=NaN; - vallyPeriod=NaN; - peak2VallyDiff=NaN; - fprintf('\nCount not complete the run. No prominent oscillations detected in the data!!!\n'); - return; - else - pPeriod=pPeak(1)+XCFLagSamples; - period=xcf_lags(pPeriod); - pAntiPeriod=pVally(1)+XCFLagSamples; - vallyPeriod=xcf_lags(pAntiPeriod); - peak2VallyDiff=xcf(pPeriod)-xcf(pAntiPeriod); - end - - %sliding autocorr analysis - movingAutoCorrWinSamples=movingAutoCorrWin/timeBin; - movingAutoCorrOLSamples=movingAutoCorrOL/timeBin; - autoCorrTimeBin=(movingAutoCorrWin-movingAutoCorrOL); - BetaRatioForSlidingAutocorr = buffer(bufferedDelta2BetaRatio,movingAutoCorrWinSamples,movingAutoCorrOLSamples,'nodelay'); - tSlidingAC=(movingAutoCorrWin/2):(movingAutoCorrWin-movingAutoCorrOL):(t_ms(end)-movingAutoCorrWin/2+movingAutoCorrWin-movingAutoCorrOL); - - %R=xcorrmat(BetaRatioForSlidingAutocorr,BetaRatioForSlidingAutocorr,autoCorrSamples); - - acfSamples=floor(movingAutoCorrWinSamples/2); - acf=zeros(size(BetaRatioForSlidingAutocorr,1)+1,size(BetaRatioForSlidingAutocorr,2)); - peak2VallyDiffSliding=zeros(1,size(BetaRatioForSlidingAutocorr,2)); - for i=1:size(BetaRatioForSlidingAutocorr,2) - [acf(:,i),autoCorrSamples] = crosscorr(BetaRatioForSlidingAutocorr(:,i),BetaRatioForSlidingAutocorr(:,i),acfSamples); - %calculate peak2VallyDiff for different times - acf(:,i)=smooth(acf(:,i),10,'moving'); - - [acfPeakAll(i),acfPeriodAll(i)]=max(acf((acfSamples+pPeak(1)-maxPeriodBand):(acfSamples+pPeak(1)+maxPeriodBand),i)); - [acfVallyAll(i),acfAntiPeriodAll(i)]=min(acf((acfSamples+pVally(1)-maxPeriodBand):(acfSamples+pVally(1)+maxPeriodBand),i)); - peak2VallyDiffSliding(i)=acfPeakAll(i)-acfVallyAll(i); - - %{ - [~,pPeak] = findpeaks(acf(acfSamples+1:end,i),'MinPeakProminence',0.1); - [~,pVally] = findpeaks(-acf(acfSamples+1:end,i),'MinPeakProminence',0.1); - findpeaks(acf(acfSamples+1:end,i),'MinPeakProminence',0.1); - disp([pPeak(1) pVally(1)]) - pause; - - if ~isempty(pPeak) & ~isempty(pVally) - pPeriodTmp=pPeak(1)+acfSamples; - pVally=pVally(1)+acfSamples; - peak2VallyDiff(i)=acf(pPeriodTmp,i)-acf(pVally,i); - end - %} - end - autocorrTimes=autoCorrSamples*timeBin; - acfPeriodAll=autocorrTimes((acfPeriodAll+acfSamples+pPeak(1)-maxPeriodBand-1)); - - oscilDurationMovingSamples=oscilDurationMovingWin/autoCorrTimeBin; - tmpOscDuration=peak2VallyDiffSliding>oscilDurationThresh; - filtOscilDuration = medfilt1(double(tmpOscDuration),oscilDurationMovingSamples); - if all(filtOscilDuration==0) - disp('Oscillation duration threshold too low, trying to reduce a bit!'); - tmpOscDuration=peak2VallyDiffSliding>(oscilDurationThresh*0.8); - filtOscilDuration = medfilt1(double(tmpOscDuration),oscilDurationMovingSamples); - end - pSleepSlidingAC=filtOscilDuration>=0.5; - - tmpBin=movingAutoCorrWinSamples-movingAutoCorrOLSamples; - pSleepDBRatio=false(numel(bufferedDelta2BetaRatio),1); - for i=1:numel(pSleepSlidingAC) - pSleepDBRatio(((i-1)*tmpBin+1):(i*tmpBin))=pSleepSlidingAC(i); - end - - pStartSleep=find(pSleepDBRatio==1,1,'first'); - tStartSleep=t_ms(pStartSleep); - tEndSleep=t_ms(find(pSleepDBRatio(pStartSleep:end)==1,1,'last')+pStartSleep); - - pSleepSlidingAC=find(tSlidingAC>=tStartSleep & tSlidingAC<=tEndSleep & peak2VallyDiffSliding>oscilDurationThresh); - for i=1:numel(pSleepSlidingAC) - pSleepDBRatioAC(((i-1)*tmpBin+1):(i*tmpBin))=pSleepSlidingAC(i); - end - - pTmp=find(tSlidingAC>=tStartSleep & tSlidingAC<=tEndSleep); - [~,pMax]=max(convn(peak2VallyDiffSliding(pTmp),ones(1,round(bestSleepWindow/((movingAutoCorrWinSamples-movingAutoCorrOLSamples)*timeBin))),'same')); - pMax=pMax+pTmp(1); - bestSleepTime=tSlidingAC(pMax); - - smoothingSamples=round(smoothingDuration/autoCorrTimeBin); - filteredSlidingPeriod=smooth(tSlidingAC(pSleepSlidingAC),acfPeriodAll(pSleepSlidingAC),smoothingSamples,'moving'); - edgeSamples=tSlidingAC(pSleepSlidingAC)<=(tSlidingAC(pSleepSlidingAC(1))+smoothingDuration/2) | tSlidingAC(pSleepSlidingAC)>=(tSlidingAC(pSleepSlidingAC(end))-smoothingDuration/2); - filteredSlidingPeriod(edgeSamples)=[]; - tFilteredSlidingPeriod=tSlidingAC(pSleepSlidingAC(~edgeSamples))'; - - %save data - save(obj.files.dbAutocorr,'parDbAutocorr','xcf','xcf_lags','xcf_bounds','BetaRatioForSlidingAutocorr','autoCorrTimeBin','autocorrTimes','timeBin',... - 'pPeriod','period','acf','vallyPeriod','peak2VallyDiff','pSleepDBRatio','pSleepSlidingAC','acfPeakAll','acfVallyAll','peak2VallyDiffSliding','tSlidingAC','acfPeriodAll',... - 'tStartSleep','tEndSleep','filteredSlidingPeriod','tFilteredSlidingPeriod','pSleepSlidingAC','pSleepDBRatioAC','bestSleepTime'); - end - - - %% plotRespirationSlidingAC - function h=plotRespirationSlidingAC(obj,varargin) - %sleepAnalysis.plotDelta2BetaSlidingAC - input parameters: - parseObj = inputParser; - parseObj.FunctionName='sleepAnalysis\plotRespirationSlidingAC'; - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'videoFile',regexp(obj.recTable.VideoFiles{obj.currentPRec},',','split'),@(x) all(isfile(x))); - addParameter(parseObj,'tStart',0,@isnumeric); - addParameter(parseObj,'win',obj.currentDataObj.recordingDuration_ms,@isnumeric); - addParameter(parseObj,'saveFigures',1,@isnumeric); - addParameter(parseObj,'printLocalCopy',0,@isnumeric); - addParameter(parseObj,'h',0); - - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - dbAutocorrFile=[obj.currentAnalysisFolder filesep 'dbAutocorr_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbAutocorrFile,'Autocorr analysis missing, please first run getDelta2BetaAC'); - load(dbAutocorrFile); - - if win+tStart>obj.currentDataObj.recordingDuration_ms, win=obj.currentDataObj.recordingDuration_ms-tStart; end - pt=find(tSlidingAC>=tStart & tSlidingAC<=(tStart+win+parDbAutocorr.movingAutoCorrWin/2)); - tSlidingAC=tSlidingAC-tSlidingAC(pt(1)); - - [~,videoFileName]=fileparts(videoFile); - respirationAutocorrFile=[obj.currentAnalysisFolder filesep 'respirationAC_' videoFileName '.mat']; - obj.checkFileRecording(respirationAutocorrFile,'Autocorr analysis missing, please first run getRespirationAC'); - RAC=load(respirationAutocorrFile); - - if h(1)==0 - fSAC=figure('position',[200 200 550 600]); - h(1)=subaxis(fSAC,2,1,1,'S',0.05,'M',0.1); - h(2)=subaxis(fSAC,2,1,2,'S',0.05,'M',0.1); - else - saveFigures=0; - end - - axes(h(1)); - h(3)=imagesc(tSlidingAC(pt)/1000/60/60,autocorrTimes/1000,real(acf(:,pt)),[-0.5 0.5]); - ylabel('\delta/\beta Autocorr lag [s]'); - ylim(xcf_lags([1 end])/1000);%important for panel plots - yl=ylim; - xlim(tSlidingAC(pt([1 end]))/1000/60/60); %important for panel plots - xl=xlim; - set(h(1),'YDir','normal'); - set(h(1),'XTickLabel',[]); - hold on; - - x=[(tStartSleep-tStart)/1000/60/60 (tEndSleep-tStart)/1000/60/60 (tEndSleep-tStart)/1000/60/60 (tStartSleep-tStart)/1000/60/60]; - W=0.03; - y=yl(2)+W*[diff(yl) diff(yl) diff(yl)*3 diff(yl)*3]; - h(4)=patch(x,y,[0.2 0.2 0.2],'Clipping','off','lineStyle','none','FaceAlpha',0.5); - text((x(1)+x(2))/2,(y(1)+y(3))/2,'E-Sleep','HorizontalAlignment','center','VerticalAlignment','middle'); - h(7)=line(xlim,[period/1000 period/1000],'color',[1 0.8 0.8]); - - axes(h(2)); - h(5)=scatter(RAC.tSlidingAC/1000/60/60,RAC.acfPeriodAll/1000,10,[0.8 0.8 1],'filled');hold on; - h(6)=plot((RAC.tFilteredSlidingPeriod)/1000/60/60,RAC.filteredSlidingPeriod/1000,'-','lineWidth',3); - ylabel('Respiration period [s]'); - xlabel('Time [h]'); - set(h(2),'Box','on'); - axis tight; - xlim(xl); - yl=ylim; - marg=diff(yl)*0.02; - ylim([yl(1)-marg,yl(2)+marg]); - %h(8:9)=line([parDbAutocorr.tStart parDbAutocorr.tStart;parDbAutocorr.tStart+parDbAutocorr.win parDbAutocorr.tStart+parDbAutocorr.win]'/1000/60/60,[yl;yl]','color',[0.8 1 0.8]); - linkaxes(h(1:2),'x'); - - if saveFigures - set(fSAC,'PaperPositionMode','auto'); - fileName=[obj.currentPlotFolder filesep 'respSAC_ch' num2str(parDbAutocorr.ch) '_t' num2str(parDbAutocorr.tStart) '_w' num2str(parDbAutocorr.win)]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - if printLocalCopy - fileName=[cd filesep obj.recTable.Animal{obj.currentPRec} '_Rec' num2str(obj.currentPRec) '_respSAC_ch' num2str(parDbAutocorr.ch) '_t' num2str(parDbAutocorr.tStart) '_w' num2str(parDbAutocorr.win)]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - end - end - end - - %% getRespirationAC - function [data]=getRespirationAC(obj,varargin) - %sleepAnalysis.getRespirationAC - input parameters: ch,tStart,win,movOLWin,XCFLag,movingAutoCorrWin,movingAutoCorrOL - parseObj = inputParser; - parseObj.FunctionName='sleepAnalysis\getRespirationAC'; - addParameter(parseObj,'videoFile',regexp(obj.recTable.VideoFiles{obj.currentPRec},',','split'),@(x) all(isfile(x))); - addParameter(parseObj,'digitalVideoSyncCh',5,@isnumeric); - addParameter(parseObj,'maxPeriodBand',5000,@isnumeric);%band width arround xcf peak to look for correlations [ms] - addParameter(parseObj,'respResampleRate',5,@isnumeric); % the resampled respiration signal sampling freq for further analysis - addParameter(parseObj,'movOLWin',400,@isnumeric); - addParameter(parseObj,'XCFLag',20000,@isnumeric); - addParameter(parseObj,'movingAutoCorrWin',24*1000,@isnumeric); - addParameter(parseObj,'movingAutoCorrOL',22*1000,@isnumeric); - addParameter(parseObj,'smoothingDuration',5*60*1000,@isnumeric); - addParameter(parseObj,'respirationMedianFilterDuration',2*1000,@isnumeric); - addParameter(parseObj,'pixelMoveThresh',10,@isnumeric); - addParameter(parseObj,'timeRemoveAfterROIShift',3,@isnumeric); %sec - addParameter(parseObj,'overwrite',0,@isnumeric); - - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parRespirationAutocorr=parseObj.Results; - - %select video file - if numel(videoFile)>1 - videoFile=videoFile{1}; - fprintf('\nMultiple video files identified. Using this one:\n%s\n',videoFile); - end - - %check if analysis was already done done - [~,videoFileName]=fileparts(videoFile); - obj.files.respirationAutocorr=[obj.currentAnalysisFolder filesep 'respirationAC_' videoFileName '.mat']; - if exist(obj.files.respirationAutocorr,'file') & ~overwrite - if nargout==1 - data=load(obj.files.respirationAutocorr); - else - disp('Autocorr respiration analysis already exists for this recording'); - end - return; - end - - chestTrackingFile=[obj.currentAnalysisFolder filesep 'chestTracking_' videoFileName '.mat']; - obj.checkFileRecording(chestTrackingFile,'Chest tracking analysis missing, please first run getRespirationMovement'); - load(chestTrackingFile,'parChestTracking','bboxCenterAll','nFramesVideo','pFrames','pbboxUpdate','pointsUpdate','nFoundPoints','avgPointMovement'); %load data - - digiTrigFile=[obj.currentAnalysisFolder filesep 'getDigitalTriggers.mat']; - obj.checkFileRecording(digiTrigFile,'digital trigger file missing, please first run getDigitalTriggers'); - load(digiTrigFile); %load data - - tFrames=tTrig{digitalVideoSyncCh}; - diffFrames=abs(numel(tFrames)-round(nFramesVideo)); - if diffFrames==0 - disp('Number of frames in video and in triggers is equal, proceeding with analysis'); - elseif diffFrames<110 - fprintf('\n\nNumber of frames in video and in triggers differs by %d, \nproceeding with analysis assuming uniform distribution of lost frames in video\n',diffFrames); - tFrames(round((1:diffFrames)/diffFrames*numel(tFrames)))=[]; - else - error(['Number of frames in video and in trigger (' num2str(digitalVideoSyncCh) ') differs by ' num2str(diffFrames) ', check recording!!!']); - end - - %remove frames that are close to a ROI shift and frames with large shifts - nFramesRemoveAfterROIShift=timeRemoveAfterROIShift*parChestTracking.analyzedFrameRateHz; - updatedFrames=find(pbboxUpdate); - - p2RemoveShifts=find(sqrt(diff(bboxCenterAll(:,1)).^2+diff(bboxCenterAll(:,2)).^2)>pixelMoveThresh/4)+1; - p2RemoveShifts=union(p2RemoveShifts,find(pbboxUpdate)); - pFrames2Remove=zeros(1,numel(pFrames)); - pFrames2Remove(p2RemoveShifts)=1; - pFrames2Remove=convn(pFrames2Remove,ones(1,nFramesRemoveAfterROIShift),'same'); - pFrames2Remove=find(pFrames2Remove); - pFramesValid=pFrames; - if ~isempty(updatedFrames) || ~isempty(pFrames2Remove) - pFramesValid(pFrames2Remove)=[]; - bboxCenterAll(pFrames2Remove,:)=[]; - avgPointMovement(pFrames2Remove,:)=[]; - end - - useAffineTrasform=true; - if useAffineTrasform - tRespFrames=tFrames(pFramesValid); - else %use optical flow - tRespFrames=tFrames(pFramesValid(parChestTracking.skipBoundingBoxInSkip:parChestTracking.skipBoundingBoxInSkip:end)); - end - - %Choose best direction for movement - [~,score] = pca(avgPointMovement,'NumComponents',1); - - %cross correlation analysis - %timeBin=mean(diff(tRespFrames)); - respResampleRate=5; %Hz - timeBin=1/respResampleRate*1000; - respirationMedianFilterBin=ceil(respirationMedianFilterDuration/timeBin); - respirationSignal=medfilt1(score,respirationMedianFilterBin)'; - respirationSignal(1)=respirationSignal(2); - - [respirationSignal,tRespFrames]=resample(double(respirationSignal),tRespFrames,respResampleRate/1000); - XCFLagSamples=ceil(XCFLag/timeBin); - [xcf,xcf_lags,xcf_bounds]=crosscorr(respirationSignal,respirationSignal,XCFLagSamples); - xcf_lags_sec=xcf_lags/respResampleRate; - - %calculate periodicity - find first vally and peak in the autocorrelation function - [~,pPeak] = findpeaks(xcf(XCFLagSamples+1:end),'MinPeakProminence',1e-4);pPeak=pPeak(1); - [~,pVally] = findpeaks(-xcf(XCFLagSamples+1:end),'MinPeakProminence',1e-4);pVally=pVally(1); - %figure;plot(xcf_lags_sec,xcf);xlabel('Respiration lag [s]');hold on;plot(xcf_lags_sec(pPeak+XCFLagSamples),xcf(pPeak+XCFLagSamples),'or') - - if isempty(pPeak) | isempty(pVally) - pPeriod=NaN; - period=NaN; - pVally=NaN; - vallyPeriod=NaN; - peak2VallyDiff=NaN; - fprintf('\nCount not complete the run. No prominent respiration oscillations detected in the data!!!\n'); - return; - else - pPeriod=pPeak(1)+XCFLagSamples; - period=xcf_lags_sec(pPeriod); - pAntiPeriod=pVally(1)+XCFLagSamples; - vallyPeriod=xcf_lags_sec(pAntiPeriod); - peak2VallyDiff=xcf(pPeriod)-xcf(pAntiPeriod); - end - - %sliding autocorr analysis - movingAutoCorrWinSamples=ceil(movingAutoCorrWin/timeBin); - movingAutoCorrOLSamples=ceil(movingAutoCorrOL/timeBin); - step=(movingAutoCorrWin-movingAutoCorrOL); - autoCorrTimeBin=(movingAutoCorrWin-movingAutoCorrOL); - respirationForSlidingAutocorr = buffer(respirationSignal,movingAutoCorrWinSamples,movingAutoCorrOLSamples,'nodelay'); - tSlidingAC=tRespFrames(1)+movingAutoCorrWin/2+(1:size(respirationForSlidingAutocorr,2))*step; - - %check if the band to look for peak is not too large (larger than the cross corr window) - maxPeriodBandSamples=min(2*(pPeriod-pAntiPeriod),ceil(maxPeriodBand/timeBin)); %take the minimal band based on the autocorr function and input - maxPeriodBandSamplesInner=min(pPeriod-pAntiPeriod,ceil(maxPeriodBand/timeBin/2)); %the band is asymettric with the short interval half the long one. - - acfSamples=floor(movingAutoCorrWinSamples/2); - if (pPeak(1)+maxPeriodBandSamples)>acfSamples - error('maxPeriodBand can not be longer than acf samples! reduce maxPeriodBand and run again'); - end - - acf=zeros(size(respirationForSlidingAutocorr,1)+1,size(respirationForSlidingAutocorr,2)); - peak2VallyDiffAll=zeros(1,size(respirationForSlidingAutocorr,2)); - acfPeriodAll=zeros(1,size(respirationForSlidingAutocorr,2)); - acfHalfPeriodAll=zeros(1,size(respirationForSlidingAutocorr,2)); - for i=1:size(respirationForSlidingAutocorr,2) - [acf(:,i),autoCorrSamples] = crosscorr(respirationForSlidingAutocorr(:,i),respirationForSlidingAutocorr(:,i),acfSamples); - %calculate peak2VallyDiff for different times - acf(:,i)=smooth(acf(:,i),10,'moving'); - - [acfPeakAll(i),acfPeriodAll(i)]=max(acf((acfSamples+pPeak(1)-maxPeriodBandSamplesInner):(acfSamples+pPeak(1)+maxPeriodBandSamples),i)); - [acfVallyAll(i),acfHalfPeriodAll(i)]=min(acf(acfSamples:(acfSamples+pPeak(1)-maxPeriodBandSamplesInner+acfPeriodAll(i)),i)); - peak2VallyDiffAll(i)=acfPeakAll(i)-acfVallyAll(i); - end - slidingACLags_sec=autoCorrSamples'/respResampleRate; - acfPeriodAll=slidingACLags_sec((acfPeriodAll+acfSamples+pPeak(1)-maxPeriodBandSamplesInner-1)); - acfHalfPeriodAll=slidingACLags_sec((acfHalfPeriodAll+acfSamples-1)); - - %Maximum value can not be determined at the edges and half period must be small than period to be a valid oscillation. - pNonValid=find(~(acfPeriodAll>acfHalfPeriodAll)); - acfPeriodAll(pNonValid)=NaN; - acfHalfPeriodAll(pNonValid)=NaN; - - %figure;imagesc(tSlidingAC/1000/60/60,slidingACLags_sec,acf);xlabel('Time [h]');hold on;plot(tSlidingAC/1000/60/60,acfPeriodAll,'or') - - smoothingSamples=round(smoothingDuration/autoCorrTimeBin); - filteredSlidingPeriod=smooth(tSlidingAC,acfPeriodAll,smoothingSamples,'moving'); - edgeSamples=tSlidingAC<=(tSlidingAC(1)+smoothingDuration/2) | tSlidingAC>=(tSlidingAC(end)-smoothingDuration/2); - filteredSlidingPeriod(edgeSamples)=[]; - tFilteredSlidingPeriod=tSlidingAC(~edgeSamples)'; - %save data - save(obj.files.respirationAutocorr,'parRespirationAutocorr','respirationSignal','pFramesValid','tRespFrames','xcf','xcf_lags_sec','xcf_bounds','respirationForSlidingAutocorr','autoCorrTimeBin','slidingACLags_sec','timeBin',... - 'pPeriod','period','acf','vallyPeriod','peak2VallyDiff','peak2VallyDiffAll','acfPeakAll','acfVallyAll','tSlidingAC','acfPeriodAll','acfHalfPeriodAll','videoFile','diffFrames',... - 'filteredSlidingPeriod','tFilteredSlidingPeriod'); - end - - %% getRespirationDBCycle - function [data]=getRespirationDBCycle(obj,varargin) - %sleepAnalysis.getRespirationAC - input parameters: ch,tStart,win,movOLWin,XCFLag,movingAutoCorrWin,movingAutoCorrOL - parseObj = inputParser; - parseObj.FunctionName='sleepAnalysis\getRespirationDBCycle'; - addParameter(parseObj,'videoFile',regexp(obj.recTable.VideoFiles{obj.currentPRec},',','split'),@(x) all(isfile(x))); - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'padding',1.5,@isnumeric); %padd the data to avoid extrapolation - addParameter(parseObj,'nBins',25,@isnumeric); - addParameter(parseObj,'interpolationMethod','linear'); - addParameter(parseObj,'overwrite',0,@isnumeric); - addParameter(parseObj,'plotSingleCycles',0,@isnumeric); - addParameter(parseObj,'videoOccupancyPlot',0,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parRespirationDBCycle=parseObj.Results; - - %check if analysis was already done done - obj.files.respirationDBCycle=[obj.currentAnalysisFolder filesep 'getRespirationDBCycle.mat']; - if isfile(obj.files.respirationDBCycle) & ~overwrite - if nargout==1 - data=load(obj.files.respirationDBCycle); - else - disp('Respiration delta to beta cycle analysis already exists for this recording'); - end - return; - end - - %select video file - if numel(videoFile)>=1 - videoFile=videoFile{1}; - fprintf('\nMultiple video files identified. Using this one:\n%s\n',videoFile); - else - error('Video file missing! Please check data table or provide name'); - end - [~,videoFileName]=fileparts(videoFile); - obj.files.respirationAutocorr=[obj.currentAnalysisFolder filesep 'respirationAC_' videoFileName '.mat']; - obj.checkFileRecording(obj.files.respirationAutocorr,'RespirationAC analysis missing, please first run getRespirationAC'); - load(obj.files.respirationAutocorr,'parRespirationAutocorr','respirationSignal','tRespFrames','period','peak2VallyDiffAll','tSlidingAC','acfPeakAll','acfPeriodAll'); %load data - - dbRatioFile=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbRatioFile,'delta to beta file missing, please first run getDBRatio'); - load(dbRatioFile,'bufferedDelta2BetaRatio','t_ms'); %load data - -% dbAutocorrFile=[obj.currentAnalysisFolder filesep 'dbAutocorr_ch' num2str(ch) '.mat']; -% obj.checkFileRecording(dbAutocorrFile,'Delta to beta autocorr analysis missing, please first run getDelta2BetaAC'); -% load(dbAutocorrFile,'pSleepDBRatio','pSleepSlidingAC'); %load data - - slowCyclesFile=[obj.currentAnalysisFolder filesep 'slowCycles_ch' num2str(ch) '.mat']; - obj.checkFileRecording(slowCyclesFile,'slow cycles file missing, please first run getSlowCycles'); - load(slowCyclesFile,'TcycleOnset','TcycleOffset','TcycleMid','DBRatioMedFilt'); %load data - - stdResp=mad(respirationSignal); - [pks,locs,pksWidth] =findpeaks(respirationSignal,tRespFrames,'MinPeakDistance',2*1000,'MinPeakProminence',stdResp); - [pksLow,locsLow,pksWidthLow] =findpeaks(-respirationSignal,tRespFrames,'MinPeakDistance',2*1000,'MinPeakProminence',stdResp); - pksLow=-pksLow; - - %determine if the minimas or maximas are sharper and choose the sharper peaks for interval estimation. - if median(pksWidth)cycleStartPadded(i) & tBreathingIntervalsminPoints - if tBreathingIntervals(pTmpB(1))<=cycleStart(i) && tBreathingIntervals(pTmpB(end))>=cycleEnd(i) - resampledTemplateBI(i,:) = interp1((tBreathingIntervals(pTmpB)-cycleStart(i))/cycleDuration(i),breathingIntervals(pTmpB)',(0:(nBins-1))/(nBins-1),interpolationMethod); - - pTmp=find(t_ms>cycleStartPadded(i) & t_mscycleStartPadded(i) & locsFinalcycleStartPadded(i) & tSlidingAC0.2 - resampledTemplateBP(i,:) = interp1((tSlidingAC(pTmpAC)-cycleStart(i))/cycleDuration(i),acfPeriodAll(pTmpAC),(0:(nBins-1))/(nBins-1),interpolationMethod); - end - %phaseAll{i}=(t_mov_ms(pTmp)-(TcycleMid(i)-cycleDuration/2))/cycleDuration; - - %shufTimes=rand(1,numel(pTmp))*cycleDuration; - %phaseAllRand{i}=shufTimes/cycleDuration; - if plotSingleCycles - pTmpR=find(tRespFrames>cycleStart(i) & tRespFrames= 0 %first anotation segment is eye open - openEyeStart=eye.eyeOpenStart(1:tmpEvents); - openEyeEnd=eye.eyeCloseStart(1:tmpEvents); - closedEyeStart=eye.eyeCloseStart(1:tmpEvents-1); - closedEyeEnd=eye.eyeOpenStart(2:tmpEvents); - else %first anotation segment is eyes close - openEyeStart=eye.eyeOpenStart(1:tmpEvents-1); - openEyeEnd=eye.eyeCloseStart(2:tmpEvents); - closedEyeStart=eye.eyeCloseStart(1:tmpEvents); - closedEyeEnd=eye.eyeOpenStart(1:tmpEvents); - end - - pNonSleepOpen=find((openEyeStartdbAC.tEndSleep & openEyeEnd>dbAC.tEndSleep)); - pNonSleepClosed=find((closedEyeStartdbAC.tEndSleep & closedEyeEnd>dbAC.tEndSleep)); - - %remove open closed segments that occur during the main sleep epoch - openEyeStart=openEyeStart(pNonSleepOpen); - openEyeEnd=openEyeEnd(pNonSleepOpen); - closedEyeStart=closedEyeStart(pNonSleepClosed); - closedEyeEnd=closedEyeEnd(pNonSleepClosed); - - allOpenDb={};allClosedDb={}; - for i=1:numel(openEyeStart) - pTmp=find(db.t_ms>openEyeStart(i) & db.t_ms<=openEyeEnd(i)); - allOpenDb{i}=db.bufferedDelta2BetaRatio(pTmp); - end - for i=1:numel(closedEyeStart) - pTmp=find(db.t_ms>closedEyeStart(i) & db.t_ms<=closedEyeEnd(i)); - allClosedDb{i}=db.bufferedDelta2BetaRatio(pTmp); - end - allOpenDb=cell2mat(allOpenDb'); - allClosedDb=cell2mat(allClosedDb'); - - - - f=figure('position',[520 -97 560 895]); - for i=1:nZoomPanels - - h(i)=subaxis(f,nZoomPanels+1,1,i,'s',0.03,'mt',0.01); - plot(db.t_ms/1000/60,db.bufferedDelta2BetaRatio);hold on; - yl=ylim; - patch([openEyeStart;openEyeEnd;openEyeEnd;openEyeStart]/1000/60,(ones(numel(openEyeStart),1)*[yl(1) yl(1) yl(2) yl(2)])',[0 0 1],'FaceAlpha',0.2,'edgeColor','none'); - patch([closedEyeStart;closedEyeEnd;closedEyeEnd;closedEyeStart]/1000/60,(ones(numel(closedEyeStart),1)*[yl(1) yl(1) yl(2) yl(2)])',[1 0 0],'FaceAlpha',0.2,'edgeColor','none'); - axis tight; - - if i==1 - [hl,ho]=legend({'\delta/\beta','open','closed'},'box','off','location','northwest'); - %horizontalLegend(ho); - end - end - - xlabel('Time [min]'); - ylabel('\delta/\beta'); - - - - h(nZoomPanels+1)=subaxis(f,nZoomPanels+1,1,nZoomPanels+1,'s',0.01); - - maxEdge=min(2000,6*std([allOpenDb;allClosedDb])); - - edges=[0:(maxEdge/10):maxEdge]; - [IOpen]=histc(allOpenDb,edges); - [IClosed]=histc(allClosedDb,edges); - bar(edges,[IOpen./sum(IOpen) IClosed/sum(IClosed)],1.1); - xlabel('\delta/\beta'); - ylabel('Prob.'); - l=legend({'Open','Close'},'box','off'); - end - - %% getFreqBandDetectionEMG - function under construction - function [data]=getFreqBandDetectionEMG(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',[],@isnumeric); - addParameter(parseObj,'fMax',500,@isnumeric); %max freq. to examine - addParameter(parseObj,'dftPoints',2^12,@isnumeric); - addParameter(parseObj,'tStart',0,@isnumeric); - addParameter(parseObj,'win',1000*60*60,@isnumeric); - addParameter(parseObj,'maxDendroClusters',2,@isnumeric); - addParameter(parseObj,'saveFile',[]); - addParameter(parseObj,'overwrite',0,@isnumeric); - addParameter(parseObj,'segmentLength',1000); - addParameter(parseObj,'WelchOL',0.5); - addParameter(parseObj,'binDuration',10000); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parFreqBandDetectionEMG=parseObj.Results; - - %check if analysis was already done done - if isempty(saveFile) - obj.files.spectralClusteringEMG=[obj.currentAnalysisFolder filesep 'spectalClusteringEMG_ch' num2str(ch) '.mat']; - else - obj.files.spectralClusteringEMG=[saveFile '.mat']; - end - - if exist(obj.files.spectralClusteringEMG,'file') & ~overwrite - if nargout==1 - data=load(obj.files.spectralClusteringEMG); - else - disp('Spectral clustering EMG analysis already exists for this recording'); - end - return; - end - - obj.filt.EMG1=filterData(obj.currentDataObj.samplingFrequency(1)); - obj.filt.EMG1.downSamplingFactor=32; - obj.filt.EMG1.padding=true; - obj.filt.EMG1=obj.filt.EMG1.designDownSample; - - MLong=obj.currentDataObj.getData(ch,tStart,win); - FMLong=obj.filt.EMG1.getFilteredData(MLong); - - %calculate initial parameters - segmentSamples = round(segmentLength/1000*obj.filt.EMG1.filteredSamplingFrequency); - samplesOL = round(segmentSamples*WelchOL); - samplesBin = binDuration/1000*obj.filt.EMG1.filteredSamplingFrequency; - - nBins=numel(FMLong)/samplesBin; - - FMLongB=reshape(FMLong,[samplesBin,nBins]); - - if (numel(FMLong)/samplesBin)~=round(numel(FMLong)/samplesBin) - nBins=nBins-1; - FMLong=FMLong(1:(samplesBin*nBins)); - disp('Last bin in recording not included due to a missmatch between recording duration and binDuration'); - end - - [pxx,f] = pwelch(FMLongB,segmentSamples,samplesOL,dftPoints,obj.filt.EMG1.filteredSamplingFrequency); - %plot(10*log10(pxx)) - p=find(ftStart & data.t_msmean(S2(1:3)) - crossFreq=freqHz(1+find(S2-S1>=0,1,'last')); - else - crossFreq=freqHz(1+find(S1-S2>=0,1,'last')); - end - else - crossFreq=[];order=[];clusters=[]; - end - - save(obj.files.spectralClustering,'corrMat','sPxx','normsPxx','freqHz','parFreqBandDetectionEMG','order','clusters','crossFreq'); - end - - - %% getFreqBandDetection - function [data]=getFreqBandDetection(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.recTable.defaulLFPCh(obj.currentPRec),@isnumeric); - addParameter(parseObj,'fMax',30,@isnumeric); %max freq. to examine - addParameter(parseObj,'dftPoints',2^10,@isnumeric); - addParameter(parseObj,'tStart',0,@isnumeric); - addParameter(parseObj,'win',1000*60*60,@isnumeric); - addParameter(parseObj,'maxDendroClusters',2,@isnumeric); - addParameter(parseObj,'saveFile',[]); - addParameter(parseObj,'remove50HzArtifcats',false); - addParameter(parseObj,'overwrite',0,@isnumeric); - addParameter(parseObj,'segmentLength',1000); - addParameter(parseObj,'WelchOL',0.5); - addParameter(parseObj,'binDuration',10000); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - if isnan(ch) - error('LFP channel not define, either define in database as ''defaulLFPCh'' or as input to method ,eg ''ch'',''1'''); - end - %make parameter structure - parFreqBandDetection=parseObj.Results; - - %check if analysis was already done done - if isempty(saveFile) - obj.files.spectralClustering=[obj.currentAnalysisFolder filesep 'spectalClustering_ch' num2str(ch) '.mat']; - else - obj.files.spectralClustering=[saveFile '.mat']; - end - - if exist(obj.files.spectralClustering,'file') & ~overwrite - if nargout==1 - data=load(obj.files.spectralClustering); - else - disp('Spectral clustering analysis already exists for this recording'); - end - return; - end - obj.getFilters; - - if win>obj.currentDataObj.recordingDuration_ms-tStart - win=obj.currentDataObj.recordingDuration_ms-tStart; - fprintf('Window larger than recordings length, cutting window to %f [ms]\n',win); - end - win=floor(win/binDuration)*binDuration; %making win an integer number of segment length - MLong=obj.currentDataObj.getData(ch,tStart,win); - - %filter data - FMLong=obj.filt.F.getFilteredData(MLong); - if remove50HzArtifcats - obj.filt.notch=filterData(obj.filt.F.filteredSamplingFrequency); - obj.filt.notch.filterDesign='cheby1'; - obj.filt.notch=obj.filt.notch.designNotch; - obj.filt.notch.padding=true; - FMLong=obj.filt.notch.getFilteredData(FMLong); - end - times=(tStart+binDuration/2):binDuration:(tStart+win); - - %calculate initial parameters - segmentSamples = round(segmentLength/1000*obj.filt.FFs); - samplesOL = round(segmentSamples*WelchOL); - samplesBin = binDuration/1000*obj.filt.FFs; - - nBins=numel(FMLong)/samplesBin; - - FMLongB=reshape(FMLong,[samplesBin,nBins]); - - if (numel(FMLong)/samplesBin)~=round(numel(FMLong)/samplesBin) - nBins=nBins-1; - FMLong=FMLong(1:(samplesBin*nBins)); - disp('Last bin in recording not included due to a missmatch between recording duration and binDuration'); - end - - [pxx,f] = pwelch(FMLongB,segmentSamples,samplesOL,dftPoints,obj.filt.FFs); - %plot(10*log10(pxx)) - p=find(fmean(S2(1:3)) - crossFreq=freqHz(find(S2-S1>=0,1,'first')); - else - crossFreq=freqHz(find(S1-S2>=0,1,'first')); - end - else - [DC,order,clusters]=DendrogramMatrix(corrMat,'linkMetric','euclidean','linkMethod','ward','maxClusters',maxDendroClusters); - - for i=1:maxDendroClusters - S(:,i)=mean(normsPxx(:,clusters==i),2); - end - crossFreq=[]; - end - - save(obj.files.spectralClustering,'times','corrMat','sPxx','normsPxx','freqHz','parFreqBandDetection','order','clusters','crossFreq'); - end - - %% getFilters - function [obj]=getFilters(obj,Fs) - if nargin==1 - if isempty(obj.currentDataObj) - error('Sampling frequency is required as an input'); - else - Fs=obj.currentDataObj.samplingFrequency(1); - disp(['sampling frequency set to that of current recording:' num2str(Fs) '[Hz]']); - end - end - - obj.filt.F=filterData(Fs); - obj.filt.F.downSamplingFactor=Fs/250; - obj.filt.F=obj.filt.F.designDownSample; - obj.filt.F.padding=true; - obj.filt.FFs=obj.filt.F.filteredSamplingFrequency; - - obj.filt.DS4Hz=filterData(Fs); - obj.filt.DS4Hz.downSamplingFactor=Fs/250; - obj.filt.DS4Hz.lowPassCutoff=4; - obj.filt.DS4Hz.padding=true; - obj.filt.DS4Hz=obj.filt.DS4Hz.designDownSample; - - obj.filt.FH=filterData(Fs); - obj.filt.FH.highPassPassCutoff=100; - obj.filt.FH.highPassStopCutoff=80; - obj.filt.FH.lowPassPassCutoff=1800; - obj.filt.FH.lowPassStopCutoff=2000; - obj.filt.FH.attenuationInLowpass=20; - obj.filt.FH.attenuationInHighpass=20; - obj.filt.FH=obj.filt.FH.designBandPass; - obj.filt.FH.padding=true; - - obj.filt.FHR=filterData(Fs); - obj.filt.FHR.highPassPassCutoff=60; - obj.filt.FHR.highPassStopCutoff=50; - obj.filt.FHR.lowPassPassCutoff=900; - obj.filt.FHR.lowPassStopCutoff=1000; - obj.filt.FHR.attenuationInLowpass=20; - obj.filt.FHR.attenuationInHighpass=40; - obj.filt.FHR=obj.filt.FHR.designBandPass; - obj.filt.FHR.padding=true; - - obj.filt.FL=filterData(Fs); - obj.filt.FL.lowPassPassCutoff=4.5; - obj.filt.FL.lowPassStopCutoff=6; - obj.filt.FL.attenuationInLowpass=20; - obj.filt.FL=obj.filt.FL.designLowPass; - obj.filt.FL.padding=true; - - obj.filt.FH2=filterData(Fs); - obj.filt.FH2.highPassCutoff=100; - obj.filt.FH2.lowPassCutoff=2000; - obj.filt.FH2.filterDesign='butter'; - obj.filt.FH2=obj.filt.FH2.designBandPass; - obj.filt.FH2.padding=true; - end - - function [loggerData]=getTemperatureLoggerData(obj,timeCorrectionMs) - if nargin==1 - timeCorrectionMs=0; - end - - filename=obj.recTable.TempLogger_file(obj.currentPRec); - filename=[obj.currentExpFolder filesep filename{1}]; - if isfile(filename) - loggerData0 = readtable(filename,'Range','A1:G2'); - loggerData = readtable(filename); - loggerData.Properties.VariableNames=loggerData0.Properties.VariableNames(1:5); - loggerData = [loggerData0(1,1:5);loggerData]; - - if iscell(obj.currentDataObj.startDate) - loggerData.loggerTimeStampsMs=seconds(loggerData.Timestamp-datetime(obj.currentDataObj.startDate{1}))*1000+timeCorrectionMs; - else - loggerData.loggerTimeStampsMs=seconds(loggerData.Timestamp-datetime(obj.currentDataObj.startDate))*1000+timeCorrectionMs; - end - else - disp('Logger data file not found!!!!!'); - loggerData=[]; - end - end - - end - - methods (Static) - - function [hOut]=polarCyclePlot(histPhaseEdges,histValues,linePhases,lineValues,varargin) - parseObj = inputParser; - parseObj.FunctionName='sleepAnalysis\polarCyclePlot'; - addOptional(parseObj,'linePhases2',[],@isnumeric); - addOptional(parseObj,'lineValues2',[],@isnumeric); - addParameter(parseObj,'plotMeanDirection',0,@isnumeric); - addParameter(parseObj,'graphicsHandle',[],@ishghandle); - addParameter(parseObj,'rLim4Rose',[],@isnumeric); - addParameter(parseObj,'randomHistValues',[],@isnumeric); - addParameter(parseObj,'RoseAlpha',0.9,@isnumeric); - addParameter(parseObj,'noBackground',0,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - addParameter(parseObj,'plotRandomDist',1,@isnumeric); - parseObj.parse(varargin{:}); - - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - if isempty(graphicsHandle) - hOut.fH=figure; - hOut.h=polaraxes; - elseif isa(graphicsHandle,'matlab.ui.Figure') %if input handle is a figure - hOut.h=polaraxes; - elseif isa(graphicsHandle,'matlab.graphics.axis.PolarAxes') - hOut.h=graphicsHandle; - else - error('Incorrent graphics handle input provided in graphicsHandle (if axis it should be polar axis).'); - end - hold(hOut.h,'on'); - - cMap=lines(8); - - if ~isempty(rLim4Rose) - hTmp = polarTight(0, rLim4Rose); - delete(hTmp) - set(h, 'Nextplot','add'); - end - - if ~isempty(histPhaseEdges) - hOut.hRose=polarhistogram('BinEdges',histPhaseEdges,'BinCounts',histValues); - hOut.hRose.Color=[0.9 0.078 0.184]; - XdataRose = get(hOut.hRose,'Xdata');XdataRose=reshape(XdataRose,[4,numel(XdataRose)/4]); - YdataRose = get(hOut.hRose,'Ydata');YdataRose=reshape(YdataRose,[4,numel(YdataRose)/4]); - hOut.hPatch=patch(XdataRose,YdataRose,[0.9 0.078 0.184]); - set(hOut.hPatch,'FaceAlpha',RoseAlpha); - %set(h,'color','k'); - if plotMeanDirection - mPhase=angle(mean(normLineValues.*exp(1i.*linePhases)));%Mean of circular quantities - wiki - hOut.hPolarAvg=polarplot([mPhase,mPhase],[0 1],'--','color',cMap(1,:,:),'linewidth',3) - end - end - - if ~isempty(linePhases) - normLineValues=normZeroOne(lineValues); - hOut.hPolar=polarplot(hOut.h,[linePhases,linePhases(1)],[normLineValues normLineValues(1)]); %the first value is added to close the circle (0-360 deg) - hOut.hPolar.LineWidth=2; - hOut.hPolar.Color=cMap(1,:,:); - if plotMeanDirection - mPhase=angle(mean(normLineValues.*exp(1i.*linePhases)));%Mean of circular quantities - wiki - lineColor=sum([2*cMap(1,:,:);[0,0,0]])/3; - hOut.hPolarAvg=polarplot([mPhase,mPhase],[0 1],':','color',lineColor,'linewidth',3); - end - end - - if ~isempty(linePhases2) - normLineValues2=normZeroOne(lineValues2); - hOut.hPolar2=polarplot([linePhases2,linePhases2(1)],[normLineValues2,normLineValues2(1)]); %the first value is added to close the circle (0-360 deg) - hOut.hPolar2.LineWidth=2; - hOut.hPolar2.Color=cMap(2,:,:); - if plotMeanDirection - mPhase2=angle(mean(normLineValues2.*exp(1i.*linePhases2)));%Mean of circular quantities - wiki - lineColor2=sum([2*cMap(2,:,:);[0,0,0]])/3; - hOut.hPolarAvg2=polarplot([mPhase2,mPhase2],[0 1],':','color',lineColor2,'linewidth',3); - end - end - - if ~isempty(histPhaseEdges) - uistack(hOut.hPatch, 'top'); - end - - h.ThetaTick=[0 90 180 270]; - h.RTick=[0.5 1]; - h.FontSize=16; - if ~isempty(randomHistValues) - hOut.hRose2=polarhistogram('BinEdges',histPhaseEdges,'BinCounts',randomHistValues); - hOut.hRose2.Color=[0.5 0.5 0.5]; - end - - %Plot legend - hands=[];legendNames={}; - if ~isempty(histPhaseEdges) - hands=[hands,hOut.hRose]; - legendNames=[legendNames,'histParam']; - end - if ~isempty(randomHistValues) - hands=[hands,hOut.hRose2]; - legendNames=[legendNames,'shuffled']; - end - if ~isempty(linePhases) - hands=[hands,hOut.hPolar]; - legendNames=[legendNames,'lineParam1']; - end - if ~isempty(linePhases2) - hands=[hands,hOut.hPolar2]; - legendNames=[legendNames,'lineParam2']; - end - hOut.l=legend(hands,legendNames); - hOut.l.Color=[1 1 1]; - hOut.l.Box='off'; - hOut.l.Position=[0.7133 0.8317 0.1786 0.1190]; - end - - %Helper methods for video analysis functions - function [xInd,yInd,OFBox]=recalculateSampledImageArea4OpticFlow(xInd,yInd,bboxCenter,frameWidth,frameHeight) - %set coordinates on image to the new box - xInd=round(xInd-xInd(round(numel(xInd)/2))+bboxCenter(1)); - yInd=round(yInd-yInd(round(numel(yInd)/2))+bboxCenter(2)); - - if any(yInd<1) - yInd=1:numel(yInd); - end - if any(xInd<1) - xInd=1:numel(xInd); - end - if any(yInd>frameHeight) - yInd=(frameHeight-numel(yInd)+1):frameHeight; - end - if any(xInd>frameWidth) - xInd=(frameWidth-numel(xInd)+1):frameWidth; - end - OFBox=[min(xInd),min(yInd);min(xInd),max(yInd);max(xInd),max(yInd);max(xInd),min(yInd)]; - end - end - -end \ No newline at end of file diff --git a/dataAnalysisObjects/recAnalysis.m b/dataAnalysisObjects/recAnalysis.m deleted file mode 100644 index f7178c6..0000000 --- a/dataAnalysisObjects/recAnalysis.m +++ /dev/null @@ -1,570 +0,0 @@ -classdef (Abstract) recAnalysis < handle - - properties - par - recTable - relevantFieldsXls - excelRecordingDataFileName - nTotalRecordings - parPool4Batch = false; - currentRecordingMeta - currentDataObj - currentRecName - currentPRec - currentDataFiles - currentDataDir - currentAnalysisFolder - currentPlotFolder - currentExpFolder - - files - gridSorterObj - end - - properties (Constant) - xlsSheet=1; - startCol=1; - figResJPG=300; - defaultXlsFile='\\storage.laur.corp.brain.mpg.de\Data_3\Shein-IdelsonMark\DCMEA.xlsx'; - end - - methods - - %% recAnalysis - class constructor - function [obj]=recAnalysis(xlsFile) - if nargin==0 || isempty(xlsFile) - obj=obj.getExcelData; - elseif nargin==1 - obj=obj.getExcelData(xlsFile); - end - obj.excelRecordingDataFileName=xlsFile; - end - %% getFileNames - function [obj,fileName]=getFileNames(obj,methodName) - %get the names of mat files associated with every method (or a specific method) - %[obj,fileName]=getFileNames(obj,methodName) - % methodName - the name of the method - % fileName - the mat file name associated with the method and a specific recording - obj.files=[]; - if nargin==1 - methodNames=methods(obj); - handleMethods=methods('handle'); - uniqueMethods=setdiff(methodNames,handleMethods); - for i=1:numel(uniqueMethods) - obj.files.(uniqueMethods{i})=[obj.currentAnalysisFolder filesep uniqueMethods{i} '.mat']; - end - else - fileName=[obj.currentAnalysisFolder filesep methodName '.mat']; - obj.files.(methodName)=[obj.currentAnalysisFolder filesep methodName '.mat']; - end - end - - function [recNames]=getRecordingNames(obj,pRec) - for i=1:numel(pRec) - d=dir([obj.recTable.folder{pRec(i)} filesep 'analysis']); - tmpRec = d([d(:).isdir]); - tmpRec = tmpRec(~ismember({tmpRec(:).name},{'.','..'})); - recNames{i} = {tmpRec(:).name}; - end - - end - - %% batchProcessData - function [varargout]=batchProcessData(obj,method,recNames,varargin) - % Run batch analysis of different recordings over a given method - % [outArgAll]=batchProcessData(method,recNames,varargin) - % method - the method used - % recNames - a cell array with recording names - % 'property','value' pairs for input to the method - % example: obj.batchProcessData('getPatchData',{'Animal=X08,Neuron=6','Animal=AG19,Neuron=1'},'plotData',1); - - - %send e-mails when running long batch analysis - %{ - catch errorMsg - if obj.sendEMailMessages - sendMailViaGmail(obj.email4Messages,['An error occured while running runSpikeSorting on ' getenv('COMPUTERNAME') ' session ' num2str(i) '/' num2str(nExp)],errorMsg.getReport); - end - rethrow(errorMsg); - end - if obj.sendEMailMessages - sendMailViaGmail(obj.email4Messages,['runSpikeSorting completed on ' getenv('COMPUTERNAME') ,' session success: ' num2str(nExp)]); - end - %} - - nOut=nargout; - nRec=numel(recNames); - - pMultiParam=cellfun(@(x) iscell(x),varargin(2:2:end)); - %check input validity - for i=find(pMultiParam) - if numel(varargin{i*2})~=nRec - disp(['Size of cell array args for arg: ' varargin{i*2-1} ' does not match the number of recordings']); - return; - end - end - - %change arguments with single value to cell arrays to fit the multi value arguments - if any(pMultiParam) - for i=find(~pMultiParam) - tmpCell=cell(1,nRec); - tmpCell=cellfun(@(x) varargin{i*2},tmpCell,'UniformOutput',0); - varargin{i*2}=tmpCell; - end - end - - fprintf(['Performing batch analysis on method ' method '\nAnalyzing recording number:']); - if obj.parPool4Batch & nRec>1 - parfor i=1:nRec %only one output argument can work with par for !!!!! - tmpObj=obj.setCurrentRecording(recNames{i}); - fprintf('Analyzing recording %s...\n',recNames{i}); - if any(pMultiParam) - tmpVaragrin=cellfun(@(x) x{i},varargin(2:2:end),'UniformOutput',0); - newVarargin={}; - newVarargin(1:2:numel(varargin))=varargin(1:2:end); - newVarargin(2:2:numel(varargin))=tmpVaragrin; - if nOut>0 - [outArgs]=tmpObj.(method)(newVarargin{:}); %only one output argument can work with par for !!!!! - outArgAll{i}=outArgs; - else - tmpObj.(method)(newVarargin{:}); - end - else - if nOut>0 - [outArgs]=tmpObj.(method)(varargin{:});%only one output argument can work with par for !!!!! - outArgAll{i}=outArgs; - else - tmpObj.(method)(varargin{:}); - end - end - %return all non object variables - end - else - for i=1:nRec - fprintf('Analyzing recording %s...\n',recNames{i}); - tmpObj=obj.setCurrentRecording(recNames{i}); - if any(pMultiParam) - tmpVaragrin=cellfun(@(x) x{i},varargin(2:2:end),'UniformOutput',0); - newVarargin={}; - newVarargin(1:2:numel(varargin))=varargin(1:2:end); - newVarargin(2:2:numel(varargin))=tmpVaragrin; - if nOut>0 - [outArgs]=tmpObj.(method)(varargin{:}); - else - tmpObj.(method)(newVarargin{:}); - end - else - if nOut>0 - %[varargout{1:nargout}]=tmpObj.(method)(varargin{:}); %not working in some cases - [outArgs]=tmpObj.(method)(varargin{:}); - else - tmpObj.(method)(varargin{:}); - end - end - for j=1:nargout - outArgAll{j}{i}=outArgs; - end - %return all non object variables - end - end - if nargout>0 - varargout=outArgAll; - end - end - - - %% getDigitalTriggers - function [data]=getDigitalTriggers(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams, disp(parseObj.Results), return, end - par=parseObj.Results; - - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - saveFileName=join(obj.files.(funName),''); - - if exist(saveFileName,'file') & ~par.overwrite - if nargout==1 - data=load(saveFileName); - else - disp('Trigger file already exists'); - end - return; - end - disp(['Getting triggers for ' obj.currentRecName]); - [tTrig]=obj.currentDataObj.getTrigger; - - %save files - save(saveFileName,'tTrig','par'); - end - - %% plotRecordingData - function plotRecordingData(obj,excelRecordingDataFileName) - if nargin==1 - if isempty(obj.excelRecordingDataFileName) - obj.excelRecordingDataFileName=obj.defaultXlsFile; - disp(['setting excel data file to default: ' obj.defaultXlsFile]); - end - else - obj.excelRecordingDataFileName=excelRecordingDataFileName; - end - T = readtable(obj.excelRecordingDataFileName); - disp(T); - end - - %% convertExcelToNewFormat - function obj=convertTableToNewFormat(obj) - xlsFieldNames=obj.recTable.Properties.VariableNames; - - %find valid rows - pExclude=find(strcmp(xlsFieldNames,'Exclude')); - pAnimal=find(strcmp(xlsFieldNames,'Turtle')); - pDate=find(strcmp(xlsFieldNames,'Date')); - - nonExludedRows=1:size(obj.recTable,1); - if ~isempty(pExclude) - if ~iscell(obj.recTable.Exclude) - p2Remove=obj.recTable.Exclude==1; - else - p2Remove=cell2mat(obj.recTable.Exclude)==1; - end - nonExludedRows(p2Remove)=[]; - end - - obj.recTable.folder=obj.recTable.Turtle; %tmp assignment of values - obj.recTable.MEAfiles=obj.recTable.MEAFile; - - lastAnimal=obj.recTable.Turtle(nonExludedRows(1)); - lastDate=obj.recTable.Date(nonExludedRows(1)); - for i=nonExludedRows - if isnan(obj.recTable.Date(i)) - obj.recTable.Turtle(i)=lastAnimal; - obj.recTable.Date(i)=lastDate; - else - lastAnimal=obj.recTable.Turtle(i); - lastDate=obj.recTable.Date(i); - end - obj.recTable.folder(i)={['\\storage.laur.corp.brain.mpg.de\Data\HembergerMike' filesep obj.recTable.Turtle{i} '_' num2str(obj.recTable.Date(i))]}; - [~,~,ext]=fileparts(obj.recTable.MEAFile{i}); - if isempty(ext) - obj.recTable.MEAfiles{i}=strjoin(cellfun(@(x) [x '.mcd'],regexp(obj.recTable.MEAFile{i},',','split'),'UniformOutput',0),','); - else - obj.recTable.MEAfiles{i}=obj.recTable.MEAFile{i}; - end - - obj.recTable.SamplingCorrection(i)=1; - end - obj.recTable.Animal=obj.recTable.Turtle; - - end - - %% getExcelData - function [obj]=getExcelData(obj,excelRecordingDataFileName,additionalExcelFieldNames) - if nargin==1 - if isempty(obj.excelRecordingDataFileName) - obj.excelRecordingDataFileName=obj.defaultXlsFile; - disp(['setting excel data file to default: ' obj.defaultXlsFile]); - end - else - obj.excelRecordingDataFileName=excelRecordingDataFileName; - end - - %General rules for formatting excel files: - %1) All title names will be extracted as fields, except if they have a 'x_' as a first letters - %2) If an line does not contain data, it has to have 1 in the exclude colomn - %3) If a field has a - - - %get data from excel spread sheet - - if verLessThan('matlab', '9.8') - obj.recTable = readtable(obj.excelRecordingDataFileName); - else - obj.recTable = readtable(obj.excelRecordingDataFileName,'Format','auto'); - end - xlsFieldNames=obj.recTable.Properties.VariableNames; - maxRow=size(obj.recTable,1); - - %get all fields except the ones starting with # - obj.relevantFieldsXls=xlsFieldNames; - pRelevantFields=cellfun(@(x) x(1)~='x' & x(2)~='_',obj.relevantFieldsXls); - obj.relevantFieldsXls=obj.relevantFieldsXls(pRelevantFields); - - %remove rows that have the exclude field true - pExclude=find(strcmp(xlsFieldNames,'Exclude')); - nonExludedRows=1:maxRow; - if ~isempty(pExclude) - if ~iscell(obj.recTable.Exclude) - p2Remove=obj.recTable.Exclude==1; - else - p2Remove=cell2mat(obj.recTable.Exclude)==1; - end - nonExludedRows(p2Remove)=[]; - end - obj.nTotalRecordings=numel(nonExludedRows); - - %check if critical fields for all analysis exist - pFolder=find(strcmp(obj.relevantFieldsXls,'folder')); - pMEAfiles=find(strcmp(obj.relevantFieldsXls,'MEAfiles')); - if isempty(pFolder) || isempty(pMEAfiles) - error('Excel table must at least have the fields: ''folder'' and ''MEAfiles'''); - elseif ~iscell(obj.recTable.MEAfiles) - obj.recTable.MEAfiles=cell(size(obj.recTable.MEAfiles)); - obj.recTable.MEAfiles=cellfun(@(x) char,obj.recTable.MEAfiles,'UniformOutput',0); - %obj.recTable.MEAfiles=cellfun(@(x) isnan(x) - end - %{ - if isunix - for i=1:numel(obj.recTable.folder) - obj.recTable.folder{i}=convertPath2Linux(obj.recTable.folder{i}); - end - end - %} - - disp(['Experiment data retrieved from: ' num2str(obj.excelRecordingDataFileName)]); - end - - - %% saveFigure - function figureFileName=saveFigure(obj,f,figureFileName) - set(f,'PaperPositionMode','auto'); - [funName] = dbstack('-completenames');funName=funName(2).name;funName=strsplit(funName,'.');funName=funName{end}; - if nargin<2 - error('The figure handle is required as an input to saveFigure'); - end - if nargin<3 - figureFileName=[obj.currentPlotFolder filesep funName]; - else - if isempty(figureFileName) - figureFileName=[obj.currentPlotFolder filesep funName]; - end - end - print(figureFileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - print(figureFileName,'-dpdf'); - end - - %% setCurrentRecording - function [obj]=setCurrentRecording(obj,recName) - %Function: select a subset of lines from the excel table for setting the current recording in the object - %recName is a string containing the conditions (e.g. 'recNames=Ctr2,Animal=Lizard43&Lizard44'). - if nargin==2 - selectedFields=regexp(recName,',','split'); - pRec=false(numel(selectedFields),size(obj.recTable,1)); - for i=1:numel(selectedFields) - selectedValues=regexp(selectedFields{i},'=','split'); - selectedSubValues=regexp(selectedValues{2},'&','split'); - for k=1:numel(selectedSubValues) - if iscell(obj.recTable.(selectedValues{1})) - pRec(i,:)=pRec(i,:) | cellfun(@(x) strcmp(num2str(x),selectedSubValues{k}),obj.recTable.(selectedValues{1}))'; - else - pRec(i,:)=pRec(i,:) | (obj.recTable.(selectedValues{1})==str2double(selectedSubValues{k}))'; - end - end - end - pRec=find(all(pRec==1,1)); - nRec=numel(pRec); - - if nRec>0 - %collect all files in case multiple files were inserted (comma separated) or group format and couple folder with file name - allFullFiles=[];multipleFiles={''}; - for i=1:nRec - if ~isempty(obj.recTable.MEAfiles{pRec(i)}) - if ~isempty(regexp(obj.recTable.MEAfiles{pRec(i)},'*')) %for cases in which the files are give as 'ctrl0*.mcd' - multipleFiles=dir([obj.recTable.folder{pRec(i)} filesep obj.recTable.MEAfiles{pRec(i)}]); - multipleFiles={multipleFiles.name}; - else - multipleFiles=regexp(obj.recTable.MEAfiles{pRec(i)},',','split'); - end - end - allFullFiles=[allFullFiles cellfun(@(x) [obj.recTable.folder{pRec(i)} filesep x],multipleFiles,'UniformOutput',0)]; - end - obj.currentDataFiles=allFullFiles'; - %check which data acquisition system was used - pFormat=find(strcmp(obj.recTable.Properties.VariableNames,'recFormat')); - obj.currentExpFolder=obj.recTable.folder{pRec(1)}; - %obj = getCurrentObjectMeta(obj); - %obj.currentDataObj.samplingFrequency = obj.currentDataMeta.fs; - - %Find in which recording class is the data - if ~isempty(pFormat) & iscell(obj.recTable{pRec(1),pFormat}) - recFormat=obj.recTable{pRec(1),pFormat}; - fprintf('Setting %s, pRec=%d, file=%s\n',recFormat{1},pRec(1),obj.currentDataFiles{1}); - eval(['obj.currentDataObj=' recFormat{1} '(obj.currentDataFiles);']); - else - if strcmp(allFullFiles{1}(end-3:end),'.mcd') %MCRack recording - if ispc - obj.currentDataObj=MCRackRecording(obj.currentDataFiles'); - elseif isunix - obj.currentDataObj=MCRackRecordingNeuroshare(obj.currentDataFiles'); - end - elseif strcmp(allFullFiles{1}(end-3:end),'.rhd') %Intan recording - obj.currentDataObj=Intan(obj.currentDataFiles); - elseif strcmp(allFullFiles{1}(end-3:end),'.bin') %Intan recording - obj.currentDataObj=binaryRecording(obj.currentDataFiles); - elseif strcmp(allFullFiles{1}(end-3:end),'.kwd') - obj.currentDataObj=KwikRecording(obj.currentDataFiles); - elseif strcmp(allFullFiles{1}(end-2:end),'.h5') - obj.currentDataObj=MCH5Recording(obj.currentDataFiles); - elseif isdir(allFullFiles{1}) %OE or NeuraLynx recording - if ~isempty(regexp(allFullFiles{1}(end-8:end),'cheetah')) %identifies neuralynx recording by the ending of the folder name with "cheetah" - obj.currentDataObj=NLRecording(obj.currentDataFiles{1}); - else - obj.currentDataObj=OERecording(obj.currentDataFiles{1}); - end - else - error(['dataRecording class could not be determined from the file extension: ' num2str(allFullFiles{1}) ',or directory not found']); - end - end - - %check if no layout metadata exists and if not check if MEA_layout field was provided and use it to define electrode layout - if isempty(obj.currentDataObj.chLayoutPositions) - pLayout=find(strcmp(obj.recTable.Properties.VariableNames,'MEA_Layout')); - if ~isempty(pFormat) & iscell(obj.recTable{pRec(1),pLayout}) - fprintf('Looking for layout in MEA_Layout...'); - recLayout=obj.recTable{pRec(1),pLayout}; - obj.currentDataObj.loadChLayout(recLayout{1}); - end - end - - obj.gridSorterObj=[]; %clear any existing grid sorter object from the past - - %create data object - obj.currentRecName=recName; - obj.currentPRec=pRec; - obj.currentRecordingMeta=obj.recTable(obj.currentPRec,:); - - %define related folders and construct correspondin file names - obj.currentAnalysisFolder=[obj.recTable.folder{pRec(1)} filesep 'analysis' filesep recName]; - obj.currentPlotFolder=[obj.recTable.folder{pRec(1)} filesep 'plots' filesep recName]; - obj=obj.getFileNames; - - [stat,mess,messid]=mkdir(char(join(obj.currentAnalysisFolder,''))); %creates analysis directory if not existing - [stat,mess,messid]=mkdir(char(join(obj.currentPlotFolder,''))); %creates analysis directory if not existing - - fprintf('Current exp. set to: %s-%s @ %s\n',obj.recTable.MEAfiles{pRec(1)},num2str(obj.recTable.MEAfiles{pRec(end)}),obj.recTable.folder{pRec(1)}); - elseif numel(pRec)==0 - disp('Selected recording/s were not found in recording list'); - obj.currentDataObj=[]; - return; - end - - elseif nargin==1 - disp('Not enough inputs, specify a recording name or number'); - return; - end - end - - %% create chMap file based on mEA lookup table (elelctrode spacing and diameter - % read MEA_lookup table and sets electrode spacing and diameter - % based on MEA serial number (this is specified in the filename of - % the recording) - % the path to the lookup table is specified in - % PCspecificFiles/MEA_lookupTable_path.txt - function [obj] = getCurrentObjectMeta(obj) - tbl = obj.getExcelData.recTable; - varNames = tbl.Properties.VariableNames; - MEA_idx = find(strcmp(varNames,'MEA')); - recnames_idx = find(strcmp(varNames,'recNames')); - fs_idx = find(strcmp(varNames,'fs')); - temp = obj.currentDataFiles{1}; % row of experiment in excel (take first file) - temp2 = strsplit(temp,filesep); - exp_idx = find(strcmp(tbl{:,recnames_idx},temp2{end})); - % find MEA, read serial number of lookup table and add - % electrode diameter and spacing to obj.CurrentDataMeta - temp = tbl{exp_idx,MEA_idx}; - try - MEA_serialNr = str2double(regexp(temp{1},'\d*','match')); - NSKToolBoxMainDir = fileparts(which('identifierOfMainDir4NSKToolBox')); - fn = [NSKToolBoxMainDir filesep 'PCspecificFiles' filesep 'MEA_lookupTable_path.txt']; - fileID = fopen(fn,'r'); formatSpec = '%s'; - fn_lookuptable = fscanf(fileID,formatSpec); - T = readtable(fn_lookuptable); - headings = T.Properties.VariableNames; - MEA_idx = find(T{:,find(strcmp(headings,'serialNumber'))} == MEA_serialNr); - electrode_diam = T{MEA_idx,find(strcmp(headings,'electrodeDiameter'))}; - electrode_spacing = T{MEA_idx,find(strcmp(headings,'electrodeSpacing'))}; - nElectrodes = T{MEA_idx,find(strcmp(headings,'nElectrodes'))}; - nElectrodes_x = T{MEA_idx,find(strcmp(headings,'electrodes_x'))}; - nElectrodes_y = T{MEA_idx,find(strcmp(headings,'electrodes_y'))}; - obj.currentDataMeta.electrode_diam = electrode_diam; - obj.currentDataMeta.electrode_spacing = electrode_spacing; - % sampling rate - temp = tbl{exp_idx,fs_idx}; - if isempty(temp{1}) - fs = 20e3; % default of 20kHz if it's empty - elseif (strcmp(temp{1},'20kH') ==1) ||(strcmp(temp{1},'20kHz')==1) - fs = 20e3; - else - fs = temp{1}; % check if this will be a string, char or double; change to double - end - obj.currentDataMeta.fs = fs; - - % create layout.chMap - if exist([obj.currentExpFolder,filesep,'layout.chMap']) == 2 - disp('layout.chMap already exists in the experiment folder. Doing nothing.') - else - str = [num2str(electrode_spacing),'_',num2str(nElectrodes_x),'x',num2str(nElectrodes_y),'_newSetup']; - temp = obj.currentDataFiles{1}; - temp2 = strsplit(temp,filesep); - exp_folder = strjoin({temp2{1:end-1}},filesep); - fileID = fopen([exp_folder,filesep,'layout.chMap'],'w'); - fprintf(fileID,str); - fclose(fileID); - disp('Created layout.chMap in experiment folder based on MEA lookup table.') - end - catch - if exist([obj.currentExpFolder,filesep,'layout.chMap']) == 2 - disp('layout.chMap already exists in the experiment folder. Doing nothing.') - else - disp('No MEA Lookup found, using default layout_100_16x16_newSetup'); - str = '100_16x16_newSetup'; - temp = obj.currentDataFiles{1}; - temp2 = strsplit(temp,filesep); - exp_folder = strjoin({temp2{1:end-1}},filesep); - fileID = fopen([exp_folder,filesep,'layout.chMap'],'w'); - fprintf(fileID,str); - fclose(fileID); - end - end - - end - - %% checkFile - check the existance of a data file and a recording object - function isDone=checkFileRecording(obj,fileName,message) - %isDone=checkFileRecording(obj,fileName,message) - %if output variable entered, does not break program but just returns result - if isempty(obj.currentDataObj) - error('No data recording object selected!!!!'); - end - isDone=false; - if nargin>1 - if ~exist(fileName,'file') - if nargin==2 - if nargout==0 - error('Relevant analysis file missing, please first run relevant function'); - else - isDone=false; - end - else - error(message); - end - else - isDone=true; - end - end - end - - end - -end \ No newline at end of file diff --git a/dataAnalysisObjects/recAnalysis.m.orig b/dataAnalysisObjects/recAnalysis.m.orig deleted file mode 100644 index f7acaf7..0000000 --- a/dataAnalysisObjects/recAnalysis.m.orig +++ /dev/null @@ -1,465 +0,0 @@ -classdef (Abstract) recAnalysis < handle - - properties - par - recTable - relevantFieldsXls - excelRecordingDataFileName - nTotalRecordings - parPool4Batch = false; - - currentDataObj - currentRecName - currentPRec - currentDataFiles - currentDataDir - currentAnalysisFolder - currentPlotFolder - currentExpFolder - - files - gridSorterObj - end - - properties (Constant) - xlsSheet=1; - startCol=1; - figResJPG=300; - defaultXlsFile='\\storage.laur.corp.brain.mpg.de\Data_3\Shein-IdelsonMark\DCMEA.xlsx'; - end - - methods - - %% recAnalysis - class constructor - function [obj]=recAnalysis(xlsFile) - if nargin==0 || isempty(xlsFile) - obj=obj.getExcelData; - elseif nargin==1 - obj=obj.getExcelData(xlsFile); - end - obj.excelRecordingDataFileName=xlsFile; - end - %% getFileNames - function [obj,fileName]=getFileNames(obj,methodName) - %get the names of mat files associated with every method (or a specific method) - %[obj,fileName]=getFileNames(obj,methodName) - % methodName - the name of the method - % fileName - the mat file name associated with the method and a specific recording - if nargin==1 - methodNames=methods(obj); - handleMethods=methods('handle'); - uniqueMethods=setdiff(methodNames,handleMethods); - for i=1:numel(uniqueMethods) - obj.files.(uniqueMethods{i})=[obj.currentAnalysisFolder filesep uniqueMethods{i} '.mat']; - end - else - fileName=[obj.currentAnalysisFolder filesep methodName '.mat']; - obj.files.(methodName)=[obj.currentAnalysisFolder filesep methodName '.mat']; - end - end - - - %% batchProcessData - function [outArgAll]=batchProcessData(obj,method,recNames,varargin) - % Run batch analysis of different recordings over a given method - % [outArgAll]=batchProcessData(method,recNames,varargin) - % method - the method used - % recNames - a cell array with recording names - % 'property','value' pairs for input to the method - % example: obj.batchProcessData('getPatchData',{'Animal=X08,Neuron=6','Animal=AG19,Neuron=1'},'plotData',1); - - - %send e-mails when running long batch analysis - %{ - catch errorMsg - if obj.sendEMailMessages - sendMailViaGmail(obj.email4Messages,['An error occured while running runSpikeSorting on ' getenv('COMPUTERNAME') ' session ' num2str(i) '/' num2str(nExp)],errorMsg.getReport); - end - rethrow(errorMsg); - end - if obj.sendEMailMessages - sendMailViaGmail(obj.email4Messages,['runSpikeSorting completed on ' getenv('COMPUTERNAME') ,' session success: ' num2str(nExp)]); - end - %} - - nOut=nargout; - nRec=numel(recNames); - - pMultiParam=cellfun(@(x) iscell(x),varargin(2:2:end)); - %check input validity - for i=find(pMultiParam) - if numel(varargin{i*2})~=nRec - disp(['Size of cell array args for arg: ' varargin{i*2-1} ' does not match the number of recordings']); - return; - end - end - - %change arguments with single value to cell arrays to fit the multi value arguments - if any(pMultiParam) - for i=find(~pMultiParam) - tmpCell=cell(1,nRec); - tmpCell=cellfun(@(x) varargin{i*2},tmpCell,'UniformOutput',0); - varargin{i*2}=tmpCell; - end - end - - fprintf(['Performing batch analysis on method ' method '\nAnalyzing recording number:']); - if obj.parPool4Batch & nRec>1 - parfor i=1:nRec - tmpObj=obj.setCurrentRecording(recNames{i}); - fprintf('Analyzing recording %s...\n',recNames{i}); - if any(pMultiParam) - tmpVaragrin=cellfun(@(x) x{i},varargin(2:2:end),'UniformOutput',0); - newVarargin={}; - newVarargin(1:2:numel(varargin))=varargin(1:2:end); - newVarargin(2:2:numel(varargin))=tmpVaragrin; - if nOut>0 - [outArgs]=tmpObj.(method)(newVarargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(newVarargin{:}); - end - else - if nOut>0 - [outArgs]=tmpObj.(method)(varargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(varargin{:}); - end - end - %return all non object variables - end - else - for i=1:nRec - fprintf('Analyzing recording %s...\n',recNames{i}); - tmpObj=obj.setCurrentRecording(recNames{i}); - if any(pMultiParam) - tmpVaragrin=cellfun(@(x) x{i},varargin(2:2:end),'UniformOutput',0); - newVarargin={}; - newVarargin(1:2:numel(varargin))=varargin(1:2:end); - newVarargin(2:2:numel(varargin))=tmpVaragrin; - if nOut>0 - [outArgs]=tmpObj.(method)(newVarargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(newVarargin{:}); - end - else - if nOut>0 - [outArgs]=tmpObj.(method)(varargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(varargin{:}); - end - end - %return all non object variables - end - end - end - - - %% getDigitalTriggers - function [data]=getDigitalTriggers(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams, disp(parseObj.Results), return, end - par=parseObj.Results; - - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - saveFileName=obj.files.(funName); - - if exist(saveFileName,'file') & ~par.overwrite - if nargout==1 - data=load(saveFileName); - else - disp('Trigger file already exists'); - end - return; - end - disp(['Getting triggers for ' obj.currentRecName]); - [tTrig]=obj.currentDataObj.getTrigger; - - %save files - save(saveFileName,'tTrig','par'); - end - - %% plotRecordingData - function plotRecordingData(obj,excelRecordingDataFileName) - if nargin==1 - if isempty(obj.excelRecordingDataFileName) - obj.excelRecordingDataFileName=obj.defaultXlsFile; - disp(['setting excel data file to default: ' obj.defaultXlsFile]); - end - else - obj.excelRecordingDataFileName=excelRecordingDataFileName; - end - T = readtable(obj.excelRecordingDataFileName); - disp(T); - end - - %% convertExcelToNewFormat - function obj=convertTableToNewFormat(obj) - xlsFieldNames=obj.recTable.Properties.VariableNames; - - %find valid rows - pExclude=find(strcmp(xlsFieldNames,'Exclude')); - pAnimal=find(strcmp(xlsFieldNames,'Turtle')); - pDate=find(strcmp(xlsFieldNames,'Date')); - - nonExludedRows=1:size(obj.recTable,1); - if ~isempty(pExclude) - if ~iscell(obj.recTable.Exclude) - p2Remove=obj.recTable.Exclude==1; - else - p2Remove=cell2mat(obj.recTable.Exclude)==1; - end - nonExludedRows(p2Remove)=[]; - end - - obj.recTable.folder=obj.recTable.Turtle; %tmp assignment of values - obj.recTable.MEAfiles=obj.recTable.MEAFile; - - lastAnimal=obj.recTable.Turtle(nonExludedRows(1)); - lastDate=obj.recTable.Date(nonExludedRows(1)); - for i=nonExludedRows - if isnan(obj.recTable.Date(i)) - obj.recTable.Turtle(i)=lastAnimal; - obj.recTable.Date(i)=lastDate; - else - lastAnimal=obj.recTable.Turtle(i); - lastDate=obj.recTable.Date(i); - end - obj.recTable.folder(i)={['\\storage.laur.corp.brain.mpg.de\Data\HembergerMike' filesep obj.recTable.Turtle{i} '_' num2str(obj.recTable.Date(i))]}; - [~,~,ext]=fileparts(obj.recTable.MEAFile{i}); - if isempty(ext) - obj.recTable.MEAfiles{i}=strjoin(cellfun(@(x) [x '.mcd'],regexp(obj.recTable.MEAFile{i},',','split'),'UniformOutput',0),','); - else - obj.recTable.MEAfiles{i}=obj.recTable.MEAFile{i}; - end - - obj.recTable.SamplingCorrection(i)=1; - end - obj.recTable.Animal=obj.recTable.Turtle; - - end - - %% getExcelData - function [obj]=getExcelData(obj,excelRecordingDataFileName,additionalExcelFieldNames) - if nargin==1 - if isempty(obj.excelRecordingDataFileName) - obj.excelRecordingDataFileName=obj.defaultXlsFile; - disp(['setting excel data file to default: ' obj.defaultXlsFile]); - end - else - obj.excelRecordingDataFileName=excelRecordingDataFileName; - end - - %General rules for formatting excel files: - %1) All title names will be extracted as fields, except if they have a 'x_' as a first letters - %2) If an line does not contain data, it has to have 1 in the exclude colomn - %3) If a field has a - - - %get data from excel spread sheet - obj.recTable = readtable(obj.excelRecordingDataFileName); - xlsFieldNames=obj.recTable.Properties.VariableNames; - maxRow=size(obj.recTable,1); - - %get all fields except the ones starting with # - obj.relevantFieldsXls=xlsFieldNames; - pRelevantFields=cellfun(@(x) x(1)~='x' & x(2)~='_',obj.relevantFieldsXls); - obj.relevantFieldsXls=obj.relevantFieldsXls(pRelevantFields); - - %remove rows that have the exclude field true - pExclude=find(strcmp(xlsFieldNames,'Exclude')); - nonExludedRows=1:maxRow; - if ~isempty(pExclude) - if ~iscell(obj.recTable.Exclude) - p2Remove=obj.recTable.Exclude==1; - else - p2Remove=cell2mat(obj.recTable.Exclude)==1; - end - nonExludedRows(p2Remove)=[]; - end - obj.nTotalRecordings=numel(nonExludedRows); - - %check if critical fields for all analysis exist - pFolder=find(strcmp(obj.relevantFieldsXls,'folder')); - pMEAfiles=find(strcmp(obj.relevantFieldsXls,'MEAfiles')); - if isempty(pFolder) || isempty(pMEAfiles) - error('Excel table must at least have the fields: ''folder'' and ''MEAfiles'''); - elseif ~iscell(obj.recTable.MEAfiles) - obj.recTable.MEAfiles=cell(size(obj.recTable.MEAfiles)); - obj.recTable.MEAfiles=cellfun(@(x) char,obj.recTable.MEAfiles,'UniformOutput',0); - %obj.recTable.MEAfiles=cellfun(@(x) isnan(x) - end - - if isunix - for i=1:numel(obj.recTable.folder) - obj.recTable.folder{i}=convertPath2LinuxMPIBR(obj.recTable.folder{i}); - end - end - disp(['Experiment data retrieved from: ' num2str(obj.excelRecordingDataFileName)]); - end - - - %% saveFigure - function figureFileName=saveFigure(obj,f,figureFileName) - set(f,'PaperPositionMode','auto'); - [funName] = dbstack('-completenames');funName=funName(2).name;funName=strsplit(funName,'.');funName=funName{end}; - if nargin<2 - error('The figure handle is required as an input to saveFigure'); - end - if nargin<3 - figureFileName=[obj.currentPlotFolder filesep funName]; - else - if isempty(figureFileName) - figureFileName=[obj.currentPlotFolder filesep funName]; - end - end - print(figureFileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - print(figureFileName,'-dpdf'); - end - - %% getRecordingNames - function getRecordingNames(obj) - disp(obj.recTable.recNames); - end - - %% setCurrentRecording - function [obj]=setCurrentRecording(obj,recName) - %Function: select a subset of lines from the excel table for setting the current recording in the object - %recName is a string containing the conditions (e.g. 'recNames=Ctr2,Animal=Lizard43&Lizard44'). - if nargin==2 - selectedFields=regexp(recName,',','split'); - pRec=false(numel(selectedFields),size(obj.recTable,1)); - for i=1:numel(selectedFields) - selectedValues=regexp(selectedFields{i},'=','split'); - selectedSubValues=regexp(selectedValues{2},'&','split'); - for k=1:numel(selectedSubValues) - if iscell(obj.recTable.(selectedValues{1})) - pRec(i,:)=pRec(i,:) | cellfun(@(x) strcmp(num2str(x),selectedSubValues{k}),obj.recTable.(selectedValues{1}))'; - else - pRec(i,:)=pRec(i,:) | (obj.recTable.(selectedValues{1})==str2double(selectedSubValues{k}))'; - end - end - end - pRec=find(all(pRec==1,1)); - nRec=numel(pRec); - - if nRec>0 - %collect all files in case multiple files were inserted (comma separated) or group format and couple folder with file name - allFullFiles=[];multipleFiles={''}; - for i=1:nRec, - if ~isempty(obj.recTable.MEAfiles{pRec(i)}) - if ~isempty(regexp(obj.recTable.MEAfiles{pRec(i)},'*')) %for cases in which the files are give as 'ctrl0*.mcd' - multipleFiles=dir([obj.recTable.folder{pRec(i)} filesep obj.recTable.MEAfiles{pRec(i)}]); - multipleFiles={multipleFiles.name}; - else - multipleFiles=regexp(obj.recTable.MEAfiles{pRec(i)},',','split'); - end - end - allFullFiles=[allFullFiles cellfun(@(x) [obj.recTable.folder{pRec(i)} filesep x],multipleFiles,'UniformOutput',0)]; - end - obj.currentDataFiles=allFullFiles'; - - %check which data acquisition system was used - pFormat=find(strcmp(obj.recTable.Properties.VariableNames,'recFormat')); - if ~isempty(pFormat) & iscell(obj.recTable{pRec(1),pFormat}) - recFormat=obj.recTable{pRec(1),pFormat}; - eval(['obj.currentDataObj=' recFormat{1} '(obj.currentDataFiles);']); - else - if strcmp(allFullFiles{1}(end-3:end),'.mcd') %MCRack recording - if ispc - obj.currentDataObj=MCRackRecording(obj.currentDataFiles'); - elseif isunix - obj.currentDataObj=MCRackRecordingNeuroshare(obj.currentDataFiles'); - end - elseif strcmp(allFullFiles{1}(end-3:end),'.rhd') %Intan recording - obj.currentDataObj=Intan(obj.currentDataFiles); - elseif strcmp(allFullFiles{1}(end-3:end),'.bin') %Intan recording - obj.currentDataObj=Recording(obj.currentDataFiles); - elseif strcmp(allFullFiles{1}(end-3:end),'.kwd') - obj.currentDataObj=KwikRecording(obj.currentDataFiles); -<<<<<<< HEAD -======= - elseif strcmp(allFullFiles{1}(end-2:end),'.h5') - obj.currentDataObj=MCH5Recording(obj.currentDataFiles); ->>>>>>> upstream/master - elseif isdir(allFullFiles{1}) %OE or NeuraLynx recording - if ~isempty(regexp(allFullFiles{1}(end-8:end),'cheetah')) %identifies neuralynx recording by the ending of the folder name with "cheetah" - obj.currentDataObj=NLRecording(obj.currentDataFiles{1}); - else - obj.currentDataObj=OERecording(obj.currentDataFiles{1}); - end - else - error(['dataRecording class could not be determined from the file extension: ' num2str(allFullFiles{1}) ',or directory not found']); - end - end - - obj.gridSorterObj=[]; %clear any existing grid sorter object from the past - - %create data object - obj.currentRecName=recName; - obj.currentPRec=pRec; - - %define related folders and construct correspondin file names - obj.currentAnalysisFolder=[obj.recTable.folder{pRec(1)} filesep 'analysis' filesep recName]; - obj.currentPlotFolder=[obj.recTable.folder{pRec(1)} filesep 'plots' filesep recName]; - obj.currentExpFolder=obj.recTable.folder{pRec(1)}; - obj=obj.getFileNames; - - [stat,mess,messid]=mkdir(obj.currentAnalysisFolder); %creates analysis directory if not existing - [stat,mess,messid]=mkdir(obj.currentPlotFolder); %creates analysis directory if not existing - fprintf('Current exp. set to: %s-%s @ %s\n',obj.recTable.MEAfiles{pRec(1)},num2str(obj.recTable.MEAfiles{pRec(end)}),obj.recTable.folder{pRec(1)}); - elseif numel(pRec)==0 - disp('Selected recording/s were not found in recording list'); - obj.currentDataObj=[]; - return; - end - - elseif nargin==1 - disp('Not enough inputs, specify a recording name or number'); - return; - end - end - - %% checkFile - check the existance of a data file and a recording object - function isDone=checkFileRecording(obj,fileName,message) - %isDone=checkFileRecording(obj,fileName,message) - %if output variable entered, does not break program but just returns result - if isempty(obj.currentDataObj) - error('No data recording object selected!!!!'); - end - isDone=false; - if nargin>1 - if ~exist(fileName,'file') - if nargin==2 - if nargout==0 - error('Relevant analysis file missing, please first run relevant function'); - else - isDone=false; - end - else - error(message); - end - else - isDone=true; - end - end - end - - end - -end \ No newline at end of file diff --git a/dataAnalysisObjects/recAnalysis.m~ b/dataAnalysisObjects/recAnalysis.m~ deleted file mode 100644 index 6ae5ddc..0000000 --- a/dataAnalysisObjects/recAnalysis.m~ +++ /dev/null @@ -1,526 +0,0 @@ -classdef (Abstract) recAnalysis < handle - - properties - par - recTable - relevantFieldsXls - excelRecordingDataFileName - nTotalRecordings - parPool4Batch = false; - currentDataMeta - currentDataObj - currentRecName - currentPRec - currentDataFiles - currentDataDir - currentAnalysisFolder - currentPlotFolder - currentExpFolder - - files - gridSorterObj - end - - properties (Constant) - xlsSheet=1; - startCol=1; - figResJPG=300; - defaultXlsFile='\\storage.laur.corp.brain.mpg.de\Data_3\Shein-IdelsonMark\DCMEA.xlsx'; - end - - methods - - %% recAnalysis - class constructor - function [obj]=recAnalysis(xlsFile) - if nargin==0 || isempty(xlsFile) - obj=obj.getExcelData; - elseif nargin==1 - obj=obj.getExcelData(xlsFile); - end - obj.excelRecordingDataFileName=xlsFile; - end - %% getFileNames - function [obj,fileName]=getFileNames(obj,methodName) - %get the names of mat files associated with every method (or a specific method) - %[obj,fileName]=getFileNames(obj,methodName) - % methodName - the name of the method - % fileName - the mat file name associated with the method and a specific recording - if nargin==1 - methodNames=methods(obj); - handleMethods=methods('handle'); - uniqueMethods=setdiff(methodNames,handleMethods); - for i=1:numel(uniqueMethods) - obj.files.(uniqueMethods{i})=[obj.currentAnalysisFolder filesep uniqueMethods{i} '.mat']; - end - else - fileName=[obj.currentAnalysisFolder filesep methodName '.mat']; - obj.files.(methodName)=[obj.currentAnalysisFolder filesep methodName '.mat']; - end - end - - - %% batchProcessData - function [outArgAll]=batchProcessData(obj,method,recNames,varargin) - % Run batch analysis of different recordings over a given method - % [outArgAll]=batchProcessData(method,recNames,varargin) - % method - the method used - % recNames - a cell array with recording names - % 'property','value' pairs for input to the method - % example: obj.batchProcessData('getPatchData',{'Animal=X08,Neuron=6','Animal=AG19,Neuron=1'},'plotData',1); - - - %send e-mails when running long batch analysis - %{ - catch errorMsg - if obj.sendEMailMessages - sendMailViaGmail(obj.email4Messages,['An error occured while running runSpikeSorting on ' getenv('COMPUTERNAME') ' session ' num2str(i) '/' num2str(nExp)],errorMsg.getReport); - end - rethrow(errorMsg); - end - if obj.sendEMailMessages - sendMailViaGmail(obj.email4Messages,['runSpikeSorting completed on ' getenv('COMPUTERNAME') ,' session success: ' num2str(nExp)]); - end - %} - - nOut=nargout; - nRec=numel(recNames); - - pMultiParam=cellfun(@(x) iscell(x),varargin(2:2:end)); - %check input validity - for i=find(pMultiParam) - if numel(varargin{i*2})~=nRec - disp(['Size of cell array args for arg: ' varargin{i*2-1} ' does not match the number of recordings']); - return; - end - end - - %change arguments with single value to cell arrays to fit the multi value arguments - if any(pMultiParam) - for i=find(~pMultiParam) - tmpCell=cell(1,nRec); - tmpCell=cellfun(@(x) varargin{i*2},tmpCell,'UniformOutput',0); - varargin{i*2}=tmpCell; - end - end - - fprintf(['Performing batch analysis on method ' method '\nAnalyzing recording number:']); - if obj.parPool4Batch & nRec>1 - parfor i=1:nRec - tmpObj=obj.setCurrentRecording(recNames{i}); - fprintf('Analyzing recording %s...\n',recNames{i}); - if any(pMultiParam) - tmpVaragrin=cellfun(@(x) x{i},varargin(2:2:end),'UniformOutput',0); - newVarargin={}; - newVarargin(1:2:numel(varargin))=varargin(1:2:end); - newVarargin(2:2:numel(varargin))=tmpVaragrin; - if nOut>0 - [outArgs]=tmpObj.(method)(newVarargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(newVarargin{:}); - end - else - if nOut>0 - [outArgs]=tmpObj.(method)(varargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(varargin{:}); - end - end - %return all non object variables - end - else - for i=1:nRec - fprintf('Analyzing recording %s...\n',recNames{i}); - tmpObj=obj.setCurrentRecording(recNames{i}); - if any(pMultiParam) - tmpVaragrin=cellfun(@(x) x{i},varargin(2:2:end),'UniformOutput',0); - newVarargin={}; - newVarargin(1:2:numel(varargin))=varargin(1:2:end); - newVarargin(2:2:numel(varargin))=tmpVaragrin; - if nOut>0 - [outArgs]=tmpObj.(method)(newVarargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(newVarargin{:}); - end - else - if nOut>0 - [outArgs]=tmpObj.(method)(varargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(varargin{:}); - end - end - %return all non object variables - end - end - end - - - %% getDigitalTriggers - function [data]=getDigitalTriggers(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams, disp(parseObj.Results), return, end - par=parseObj.Results; - - [funName] = dbstack;funName=funName.name;funName=strsplit(funName,'.');funName=funName{end}; - saveFileName=join(obj.files.(funName),''); - - if exist(saveFileName,'file') & ~par.overwrite - if nargout==1 - data=load(saveFileName); - else - disp('Trigger file already exists'); - end - return; - end - disp(['Getting triggers for ' obj.currentRecName]); - [tTrig]=obj.currentDataObj.getTrigger; - - %save files - save(saveFileName,'tTrig','par'); - end - - %% plotRecordingData - function plotRecordingData(obj,excelRecordingDataFileName) - if nargin==1 - if isempty(obj.excelRecordingDataFileName) - obj.excelRecordingDataFileName=obj.defaultXlsFile; - disp(['setting excel data file to default: ' obj.defaultXlsFile]); - end - else - obj.excelRecordingDataFileName=excelRecordingDataFileName; - end - T = readtable(obj.excelRecordingDataFileName); - disp(T); - end - - %% convertExcelToNewFormat - function obj=convertTableToNewFormat(obj) - xlsFieldNames=obj.recTable.Properties.VariableNames; - - %find valid rows - pExclude=find(strcmp(xlsFieldNames,'Exclude')); - pAnimal=find(strcmp(xlsFieldNames,'Turtle')); - pDate=find(strcmp(xlsFieldNames,'Date')); - - nonExludedRows=1:size(obj.recTable,1); - if ~isempty(pExclude) - if ~iscell(obj.recTable.Exclude) - p2Remove=obj.recTable.Exclude==1; - else - p2Remove=cell2mat(obj.recTable.Exclude)==1; - end - nonExludedRows(p2Remove)=[]; - end - - obj.recTable.folder=obj.recTable.Turtle; %tmp assignment of values - obj.recTable.MEAfiles=obj.recTable.MEAFile; - - lastAnimal=obj.recTable.Turtle(nonExludedRows(1)); - lastDate=obj.recTable.Date(nonExludedRows(1)); - for i=nonExludedRows - if isnan(obj.recTable.Date(i)) - obj.recTable.Turtle(i)=lastAnimal; - obj.recTable.Date(i)=lastDate; - else - lastAnimal=obj.recTable.Turtle(i); - lastDate=obj.recTable.Date(i); - end - obj.recTable.folder(i)={['\\storage.laur.corp.brain.mpg.de\Data\HembergerMike' filesep obj.recTable.Turtle{i} '_' num2str(obj.recTable.Date(i))]}; - [~,~,ext]=fileparts(obj.recTable.MEAFile{i}); - if isempty(ext) - obj.recTable.MEAfiles{i}=strjoin(cellfun(@(x) [x '.mcd'],regexp(obj.recTable.MEAFile{i},',','split'),'UniformOutput',0),','); - else - obj.recTable.MEAfiles{i}=obj.recTable.MEAFile{i}; - end - - obj.recTable.SamplingCorrection(i)=1; - end - obj.recTable.Animal=obj.recTable.Turtle; - - end - - %% getExcelData - function [obj]=getExcelData(obj,excelRecordingDataFileName,additionalExcelFieldNames) - if nargin==1 - if isempty(obj.excelRecordingDataFileName) - obj.excelRecordingDataFileName=obj.defaultXlsFile; - disp(['setting excel data file to default: ' obj.defaultXlsFile]); - end - else - obj.excelRecordingDataFileName=excelRecordingDataFileName; - end - - %General rules for formatting excel files: - %1) All title names will be extracted as fields, except if they have a 'x_' as a first letters - %2) If an line does not contain data, it has to have 1 in the exclude colomn - %3) If a field has a - - - %get data from excel spread sheet - obj.recTable = readtable(obj.excelRecordingDataFileName); - xlsFieldNames=obj.recTable.Properties.VariableNames; - maxRow=size(obj.recTable,1); - - %get all fields except the ones starting with # - obj.relevantFieldsXls=xlsFieldNames; - pRelevantFields=cellfun(@(x) x(1)~='x' & x(2)~='_',obj.relevantFieldsXls); - obj.relevantFieldsXls=obj.relevantFieldsXls(pRelevantFields); - - %remove rows that have the exclude field true - pExclude=find(strcmp(xlsFieldNames,'Exclude')); - nonExludedRows=1:maxRow; - if ~isempty(pExclude) - if ~iscell(obj.recTable.Exclude) - p2Remove=obj.recTable.Exclude==1; - else - p2Remove=cell2mat(obj.recTable.Exclude)==1; - end - nonExludedRows(p2Remove)=[]; - end - obj.nTotalRecordings=numel(nonExludedRows); - - %check if critical fields for all analysis exist - pFolder=find(strcmp(obj.relevantFieldsXls,'folder')); - pMEAfiles=find(strcmp(obj.relevantFieldsXls,'MEAfiles')); - if isempty(pFolder) || isempty(pMEAfiles) - error('Excel table must at least have the fields: ''folder'' and ''MEAfiles'''); - elseif ~iscell(obj.recTable.MEAfiles) - obj.recTable.MEAfiles=cell(size(obj.recTable.MEAfiles)); - obj.recTable.MEAfiles=cellfun(@(x) char,obj.recTable.MEAfiles,'UniformOutput',0); - %obj.recTable.MEAfiles=cellfun(@(x) isnan(x) - end - - if isunix - for i=1:numel(obj.recTable.folder) - obj.recTable.folder{i}=convertPath2LinuxMPIBR(obj.recTable.folder{i}); - end - end - disp(['Experiment data retrieved from: ' num2str(obj.excelRecordingDataFileName)]); - end - - - %% saveFigure - function figureFileName=saveFigure(obj,f,figureFileName) - set(f,'PaperPositionMode','auto'); - [funName] = dbstack('-completenames');funName=funName(2).name;funName=strsplit(funName,'.');funName=funName{end}; - if nargin<2 - error('The figure handle is required as an input to saveFigure'); - end - if nargin<3 - figureFileName=[obj.currentPlotFolder filesep funName]; - else - if isempty(figureFileName) - figureFileName=[obj.currentPlotFolder filesep funName]; - end - end - print(figureFileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - print(figureFileName,'-dpdf'); - end - - %% getRecordingNames - function getRecordingNames(obj) - disp(obj.recTable.recNames); - end - - %% setCurrentRecording - function [obj]=setCurrentRecording(obj,recName) - %Function: select a subset of lines from the excel table for setting the current recording in the object - %recName is a string containing the conditions (e.g. 'recNames=Ctr2,Animal=Lizard43&Lizard44'). - if nargin==2 - selectedFields=regexp(recName,',','split'); - pRec=false(numel(selectedFields),size(obj.recTable,1)); - for i=1:numel(selectedFields) - selectedValues=regexp(selectedFields{i},'=','split'); - selectedSubValues=regexp(selectedValues{2},'&','split'); - for k=1:numel(selectedSubValues) - if iscell(obj.recTable.(selectedValues{1})) - pRec(i,:)=pRec(i,:) | cellfun(@(x) strcmp(num2str(x),selectedSubValues{k}),obj.recTable.(selectedValues{1}))'; - else - pRec(i,:)=pRec(i,:) | (obj.recTable.(selectedValues{1})==str2double(selectedSubValues{k}))'; - end - end - end - pRec=find(all(pRec==1,1)); - nRec=numel(pRec); - - if nRec>0 - %collect all files in case multiple files were inserted (comma separated) or group format and couple folder with file name - allFullFiles=[];multipleFiles={''}; - for i=1:nRec - if ~isempty(obj.recTable.MEAfiles{pRec(i)}) - if ~isempty(regexp(obj.recTable.MEAfiles{pRec(i)},'*')) %for cases in which the files are give as 'ctrl0*.mcd' - multipleFiles=dir([obj.recTable.folder{pRec(i)} filesep obj.recTable.MEAfiles{pRec(i)}]); - multipleFiles={multipleFiles.name}; - else - multipleFiles=regexp(obj.recTable.MEAfiles{pRec(i)},',','split'); - end - end - allFullFiles=[allFullFiles cellfun(@(x) [obj.recTable.folder{pRec(i)} filesep x],multipleFiles,'UniformOutput',0)]; - end - obj.currentDataFiles=allFullFiles'; - %check which data acquisition system was used - pFormat=find(strcmp(obj.recTable.Properties.VariableNames,'recFormat')); - obj = getCurrentObjectMeta(obj); -% obj.currentDataObj.samplingFrequency = obj.currentDataMeta.fs; - if ~isempty(pFormat) & iscell(obj.recTable{pRec(1),pFormat}) - recFormat=obj.recTable{pRec(1),pFormat}; - eval(['obj.currentDataObj=' recFormat{1} '(obj.currentDataFiles);']); - else - if strcmp(allFullFiles{1}(end-3:end),'.mcd') %MCRack recording - if ispc - obj.currentDataObj=MCRackRecording(obj.currentDataFiles'); - elseif isunix - obj.currentDataObj=MCRackRecordingNeuroshare(obj.currentDataFiles'); - end - elseif strcmp(allFullFiles{1}(end-3:end),'.rhd') %Intan recording - obj.currentDataObj=Intan(obj.currentDataFiles); - elseif strcmp(allFullFiles{1}(end-3:end),'.bin') %Intan recording - obj.currentDataObj=Recording(obj.currentDataFiles); - elseif strcmp(allFullFiles{1}(end-3:end),'.kwd') - obj.currentDataObj=KwikRecording(obj.currentDataFiles); - elseif strcmp(allFullFiles{1}(end-2:end),'.h5') - obj.currentDataObj=MCH5Recording(obj.currentDataFiles); - elseif isdir(allFullFiles{1}) %OE or NeuraLynx recording - if ~isempty(regexp(allFullFiles{1}(end-8:end),'cheetah')) %identifies neuralynx recording by the ending of the folder name with "cheetah" - obj.currentDataObj=NLRecording(obj.currentDataFiles{1}); - else - obj.currentDataObj=OERecording(obj.currentDataFiles{1}); - end - else - error(['dataRecording class could not be determined from the file extension: ' num2str(allFullFiles{1}) ',or directory not found']); - end - end - - obj.gridSorterObj=[]; %clear any existing grid sorter object from the past - - %create data object - obj.currentRecName=recName; - obj.currentPRec=pRec; - - %define related folders and construct correspondin file names - obj.currentAnalysisFolder=[obj.recTable.folder{pRec(1)} filesep 'analysis' filesep recName]; - obj.currentPlotFolder=[obj.recTable.folder{pRec(1)} filesep 'plots' filesep recName]; - obj.currentExpFolder=obj.recTable.folder{pRec(1)}; - obj=obj.getFileNames; - - [stat,mess,messid]=mkdir(char(join(obj.currentAnalysisFolder,''))); %creates analysis directory if not existing - [stat,mess,messid]=mkdir(char(join(obj.currentPlotFolder,''))); %creates analysis directory if not existing - - fprintf('Current exp. set to: %s-%s @ %s\n',obj.recTable.MEAfiles{pRec(1)},num2str(obj.recTable.MEAfiles{pRec(end)}),obj.recTable.folder{pRec(1)}); - elseif numel(pRec)==0 - disp('Selected recording/s were not found in recording list'); - obj.currentDataObj=[]; - return; - end - - elseif nargin==1 - disp('Not enough inputs, specify a recording name or number'); - return; - end - end - - %% create chMap file based on mEA lookup table (elelctrode spacing and diameter - % read MEA_lookup table and sets electrode spacing and diameter - % based on MEA serial number (this is specified in the filename of - % the recording) - % the path to the lookup table is specified in - % PCspecificFiles/MEA_lookupTable_path.txt - function [obj] = getCurrentObjectMeta(obj) - tbl = obj.getExcelData.recTable; - varNames = tbl.Properties.VariableNames; - MEA_idx = find(strcmp(varNames,'MEA')); - recnames_idx = find(strcmp(varNames,'recNames')); - fs_idx = find(strcmp(varNames,'fs')); - temp = obj.currentDataFiles{1}; % row of experiment in excel (take first file) - temp2 = strsplit(temp,filesep); - exp_idx = find(strcmp(tbl{:,recnames_idx},temp2{end})); - % find MEA, read serial number of lookup table and add - % electrode diameter and spacing to obj.CurrentDataMeta - temp = tbl{exp_idx,MEA_idx}; - MEA_serialNr = str2double(regexp(temp{1},'\d*','match')); - - NSKToolBoxMainDir = fileparts(which('identifierOfMainDir4NSKToolBox')); - fn = [NSKToolBoxMainDir filesep 'PCspecificFiles' filesep 'MEA_lookupTable_path.txt']; - fileID = fopen(fn,'r'); formatSpec = '%s'; - fn_lookuptable = fscanf(fileID,formatSpec); - T = readtable(fn_lookuptable); - headings = T.Properties.VariableNames; - MEA_idx = find(T{:,find(strcmp(headings,'serialNumber'))} == MEA_serialNr); - electrode_diam = T{MEA_idx,find(strcmp(headings,'electrodeDiameter'))}; - electrode_spacing = T{MEA_idx,find(strcmp(headings,'electrodeSpacing'))}; - nElectrodes = T{MEA_idx,find(strcmp(headings,'nElectrodes'))}; - nElectrodes_x = T{MEA_idx,find(strcmp(headings,'electrodes_x'))}; - nElectrodes_y = T{MEA_idx,find(strcmp(headings,'electrodes_y'))}; - obj.currentDataMeta.electrode_diam = electrode_diam; - obj.currentDataMeta.electrode_spacing = electrode_spacing; - - % sampling rate - temp = tbl{exp_idx,fs_idx}; - if isempty(temp{1}) - fs = 20e3; % default of 20kHz if it's empty - elseif (strcmp(temp{1},'20kH') ==1) ||(strcmp(temp{1},'20kHz')==1) - fs = 20e3; - else - fs = temp{1}; % check if this will be a string, char or double; change to double - end - obj.currentDataMeta.fs = fs; - - % create layout.chMap - if exist([obj.currentExpFolder,filesep,'layout.chMap']) == 2 - disp('layout.chMap already exists in the experiment folder. Doing nothing.') - else - str = [num2str(electrode_spacing),'_',num2str(nElectrodes_x),'x',num2str(nElectrodes_y),'_newSetup']; - temp = obj.currentDataFiles{1}; - temp2 = strsplit(temp,filesep); - exp_folder = strjoin({temp2{1:end-1}},filesep); - fileID = fopen([exp_folder,filesep,'layout.chMap'],'w'); - fprintf(fileID,str); - fclose(fileID); - disp('Created layout.chMap in experiment folder based on MEA lookup table.') - end - - end - - %% checkFile - check the existance of a data file and a recording object - function isDone=checkFileRecording(obj,fileName,message) - %isDone=checkFileRecording(obj,fileName,message) - %if output variable entered, does not break program but just returns result - if isempty(obj.currentDataObj) - error('No data recording object selected!!!!'); - end - isDone=false; - if nargin>1 - if ~exist(fileName,'file') - if nargin==2 - if nargout==0 - error('Relevant analysis file missing, please first run relevant function'); - else - isDone=false; - end - else - error(message); - end - else - isDone=true; - end - end - end - - end - -end \ No newline at end of file diff --git a/dataAnalysisObjects/sleepAnalysis_old.m b/dataAnalysisObjects/sleepAnalysis_old.m deleted file mode 100644 index 3c8380c..0000000 --- a/dataAnalysisObjects/sleepAnalysis_old.m +++ /dev/null @@ -1,3132 +0,0 @@ -classdef sleepAnalysis < handle - properties - par - parFreqBandDetection - parDBRatio - excelRecordingDataFileName - fieldNames - nSessions - filt - currentDataObj - currentPRec - currentAnalysisFolder - currentPlotFolder - currentExpFolder - currentVideosFolder - files - parPool4Batch=false; - relevantFields={'Sleep','Awake','Eye','HR','Num','Animal','CheetahFolder','VideoFiles','MatroxTrigScheme','FrameRange','VideoType','AnimalState','DVRLFPCh','ElecLayout','Sorting','tStartAwake'}; - relevantFieldsXls - nTotalRecordings - currentMEAFiles - gridSorterObj - currentRecName - end - properties (Constant) - xlsSheet=1; - titleLine=1; - startCol=1; - figResJPG=400; - figResEPS=1000; %is not important - defaultDir='\\storage.laur.corp.brain.mpg.de\Data_2\chronicLizardExpp' - defaultXlsFile='\\storage.laur.corp.brain.mpg.de\Data_2\chronicLizardExp\SleepExp.xlsx'; - end - methods - - %% getDayTimeInRecTime - function data=getSleepVsLights(obj,varargin) - %% parameter and settings - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'referenceClock','19:00:00'); %reference for lights on/off - addParameter(parseObj,'ch',obj.par.DVRLFPCh{obj.currentPRec},@isnumeric); - addParameter(parseObj,'clockStartTime',[]); %cell array with the format 'HH:MM:SS' - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parDayTimeOnRecTime=parseObj.Results; - - %check if analysis was already done done - obj.files.dayTimeOnRecTime=[obj.currentAnalysisFolder filesep 'dayTimeOnRecTime.mat']; - if exist(obj.files.dayTimeOnRecTime,'file') & ~overwrite - if nargout==1 - data=load(obj.files.dayTimeOnRecTime); - else - disp('dayTimeOnRecTime file already exists'); - end - return; - end - - dbRatioFile=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbRatioFile,'Delta to beta analysis missing, please first run getDBRatio'); - dataDB=load(dbRatioFile,'t_ms'); %load data - - dbAutocorrFile=[obj.currentAnalysisFolder filesep 'dbAutocorr_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbAutocorrFile,'Delta to beta autocorr analysis missing, please first run getDBRatioAC'); - dataAC=load(dbAutocorrFile,'pSleepDBRatio','period'); %load data - - if strcmp(obj.currentDataObj.startDate(1),'(m/d/y):') - obj.currentDataObj=obj.currentDataObj.getStartRecordingTime; - end - recordingStartTimeClock=obj.currentDataObj.startDate; - - pStartSleep=find(dataAC.pSleepDBRatio==1,1,'first'); - pEndSleep=find(dataAC.pSleepDBRatio(pStartSleep:end)==0,1,'first')+pStartSleep; - - if pStartSleep==1 - sleepStartEnd=[0 dataDB.t_ms(pEndSleep)]; - else - sleepStartEnd=dataDB.t_ms([pStartSleep pEndSleep]); - end - - if exist([obj.currentAnalysisFolder filesep 'light.mat'],'file') - l=load([obj.currentAnalysisFolder filesep 'light.mat']); - startSleepFromRef_h=(sleepStartEnd-l.light(1))/1000/60/60; - manualLightAnnotation=true; - else - manualLightAnnotation=false; - tmpDV=datevec(datenum(referenceClock,'HH:MM:SS')-datenum(recordingStartTimeClock,'HH:MM:SS') ); - if tmpDV(1)<0 - startSleepFromRef_h=sleepStartEnd/1000/60/60+(24-tmpDV(:,4)+(60-tmpDV(:,5))/60+(60-tmpDV(:,6))/3600); - disp('Interval between start recording and reference time was too large -> assuming recording started after reference time'); - else - startSleepFromRef_h=sleepStartEnd/1000/60/60-(tmpDV(:,4)+tmpDV(:,5)/60+tmpDV(:,6)/3600); - end - end - - save(obj.files.dayTimeOnRecTime,'sleepStartEnd','recordingStartTimeClock','referenceClock','startSleepFromRef_h','parDayTimeOnRecTime','manualLightAnnotation'); - end - - %% getSpikeSTAs - function data=getSpikeSTAs(obj,varargin) - %% parameter and settings - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.par.DVRLFPCh{obj.currentPRec},@isnumeric); - addParameter(parseObj,'nCycles',10,@isnumeric); - addParameter(parseObj,'cycleSelection','first',@(x) any(strcmp(x,{'first','rand'}))); - addParameter(parseObj,'binSW',10,@isnumeric); - addParameter(parseObj,'preSW',1000,@isnumeric); - addParameter(parseObj,'winSW',2000,@isnumeric); - addParameter(parseObj,'binSO',1000,@isnumeric); - addParameter(parseObj,'preSO',40000,@isnumeric); - addParameter(parseObj,'winSO',80000,@isnumeric); - addParameter(parseObj,'minSpikeRate',0.05,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parSpikeSTA=parseObj.Results; - - %check if analysis was already done done - obj.files.spikeSTA=[obj.currentAnalysisFolder filesep 'spikeSTA.mat']; - if exist(obj.files.spikeSTA,'file') & ~overwrite - if nargout==1 - data=load(obj.files.spikeSTA); - else - disp('Spike STA file already exists'); - end - return; - end - - slowCyclesFile=[obj.currentAnalysisFolder filesep 'slowCycles_ch' num2str(ch) '.mat']; - obj.checkFileRecording(slowCyclesFile,'slow cycles file missing, please first run getSlowCycles'); - load(slowCyclesFile,'TcycleMid','TcycleOffset','TcycleOnset'); %load data - - sharpWavesFile=[obj.currentAnalysisFolder filesep 'sharpWaves_ch' num2str(ch) '.mat']; - obj.checkFileRecording(sharpWavesFile,'Sharp wave file missing, please run getSharpWaves'); - load(sharpWavesFile); - - AIfile=[obj.currentAnalysisFolder filesep 'AI_2ms_4std.mat']; - obj.checkFileRecording(sharpWavesFile,'AI file missing, please run getAI'); - load(AIfile); - - nNeurons=size(icA,2); - if strcmp(cycleSelection,'first') - pCycles=1:nCycles; - elseif strcmp(cycleSelection,'rand') - pCycles=randperm(numel(TcycleMid),nCycles); - end - - %get high freq channel correlation matrix - C=zeros(nCycles,nNeurons,nNeurons); - for i=1:nCycles - MSW=squeeze(BuildBurstMatrixA(icA,round(tA/2),IA,round(TcycleMid(pCycles(i))/2),round(TcycleOffset(pCycles(i))/2)))'; - tmpC=corrcoef(MSW); - C(i,:,:)=tmpC; - end - ch=icA(1,:); - avgCrossChCorr=squeeze(mean(C,1)); - clear IA tA icA; - - %cluster high freq channel correlation matrix - [~,orderCtxDVR,ctxDVRClass]=DendrogramMatrix(avgCrossChCorr,'toPlotBinaryTree',0,'linkMethod','average','linkMetric','spearman','maxClusters',2); - - if mean(find(ctxDVRClass==1))=1 - edges=(0:parSyncDBEye.nBins)/(parSyncDBEye.nBins-0.0000001); - middles=(edges(1:end-1)+edges(2:end))/2; - - axes(h(1)); - hOut.imagesc=imagesc(0:parSyncDBEye.nBins,1:size(resampledTemplate,1),resampledTemplate);hold on; - set(h(1),'XTickLabel',[]); - ylabel('# cycle'); - p=cell2mat(cellfun(@(x) ~isempty(x),phaseAll,'UniformOutput',0)); - for i=find(p) - hOut.hP(i)=plot(phaseAll{i}*parSyncDBEye.nBins,i*ones(size(phaseAll{i})),'.r'); - end - - I=histc(phaseMov,edges); - - if numel(h)==1 - xlabel('Phase'); - set(h,'XTick',[-0.5 parSyncDBEye.nBins+0.5],'XTickLabel',{'0','2\pi'}); - xlim([-0.5 parSyncDBEye.nBins+0.5]) - end - end - - if numel(h)>=2 - axes(h(2)); - hOut.p1=plot(middles,normZeroOne(mean(resampledTemplate)),'lineWidth',2);hold on; - hOut.p2=plot(middles,normZeroOne(I(1:end-1)),'r','lineWidth',2); - xlim([0 1]); - xlabel('Phase'); - set(h(2),'XTick',[0 1],'XTickLabel',{'0','2\pi'}); - hOut.l=legend('norm. \delta/\beta','norm. OF counts'); - hOut.l.Box='off'; - hOut.l.Position=[0.6434 0.9061 0.2596 0.0812]; - end - - if numel(h)>=3 - axes(h(3)); - imagesc(resampledTemplate);hold on; - set(h(3),'YTickLabel',[],'XTickLabel',[]); - p=cell2mat(cellfun(@(x) ~isempty(x),phaseAllRand,'UniformOutput',0)); - for i=find(p) - plot(phaseAllRand{i}*parSyncDBEye.nBins,i*ones(size(phaseAllRand{i})),'*r'); - end - I=histc(phaseRand,edges); - end - - if numel(h)>=4 - axes(h(4)); - hOut.p3=plot(middles,normZeroOne(mean(resampledTemplate)),'lineWidth',2);hold on; - hOut.p4=plot(middles,normZeroOne(I(1:end-1)),'r','lineWidth',2); - xlim([0 1]); - xlabel('Phase'); - set(h(4),'XTick',[0 1],'XTickLabel',{'0','2\pi'},'YTickLabel',[]) - end - - if saveFigures - set(fH,'PaperPositionMode','auto'); - fileName=[obj.currentPlotFolder filesep 'syncEyeDBRaster_' videoFileName]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - print(fileName,'-depsc',['-r' num2str(obj.figResEPS)]); - if printLocalCopy - fileName=[cd filesep obj.par.Animal{obj.currentPRec} '_Rec' num2str(obj.currentPRec) '_syncEyeDBRaster_' videoFileName]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - print(fileName,'-depsc',['-r' num2str(obj.figResEPS)]); - end - end - - end - - %timeBinDB=(parDBRatio.movWin-parDBRatio.movOLWin); - - %{ - figure; - subplot(1,2,1); - imagesc(resampledTemplate);hold on; - p=cell2mat(cellfun(@(x) ~isempty(x),phaseAll,'UniformOutput',0)); - for i=find(p) - plot(phaseAll{i}*nBins,i*ones(size(phaseAll{i})),'or'); - end - - subplot(1,2,2); - imagesc(resampledTemplate);hold on; - p=cell2mat(cellfun(@(x) ~isempty(x),phaseAllRand,'UniformOutput',0)); - for i=find(p) - plot(phaseAllRand{i}*nBins,i*ones(size(phaseAllRand{i})),'or'); - end - %} - - %% plotEyeVideoOFDB - function obj=plotEyeVideoOFDB(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'winFrame',100,@isnumeric); - addParameter(parseObj,'tStart',[],@isnumeric); - addParameter(parseObj,'tEnd',[],@isnumeric); - addParameter(parseObj,'outputVideo',[]); - addParameter(parseObj,'outputFrameRate',10); - addParameter(parseObj,'opticFlowFile',[]); - addParameter(parseObj,'OFlineColor','black'); - addParameter(parseObj,'ampOFLine',50); - addParameter(parseObj,'showOnlyEye',true); - addParameter(parseObj,'videoCompressor','DV Video Encoder'); - addParameter(parseObj,'saveVideo',false,@isnumeric); - addParameter(parseObj,'ch',obj.par.DVRLFPCh{obj.currentPRec},@isnumeric); - addParameter(parseObj,'videoFile',[obj.currentVideosFolder filesep obj.par.VideoFiles{obj.currentPRec}],@(x) exist(x,'file')); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - dbRatioFile=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbRatioFile,'delta to beta file missing, please first run getDBRatio'); - DB=load(dbRatioFile); %load data - - [~,videoFileName]=fileparts(videoFile); - eyeTrackingFile=[obj.currentAnalysisFolder filesep 'eyeTracking_' videoFileName '.mat']; - obj.checkFileRecording(eyeTrackingFile,'Eye tracking analysis missing, please first run getEyeMovement'); - ET=load(eyeTrackingFile,'parEyeTracking','pFrames','mOF','pbboxUpdate','bboxCenterAll'); %load data - - syncDBEyeFile=[obj.currentAnalysisFolder filesep 'syncDBEye_' videoFileName '.mat']; - obj.checkFileRecording(syncDBEyeFile,'sync eye to beta 2 delta file missing, please first run getSyncedDBEyeMovements'); - sync=load(syncDBEyeFile); %load data - - if ~showOnlyEye - videoReader = VideoReader(videoFile); %initiate video obj since number of frames was already read (not allowed by matlab) - end - %videoPlayer = vision.VideoPlayer('Position',[100 100 [videoReader.Width, videoReader.Height]+30]); - if saveVideo - if isempty(outputVideo) - outputVideo=[obj.currentAnalysisFolder filesep videoFileName 'OFDB.avi']; - end - videoWriter = vision.VideoFileWriter([outputVideo '.avi'],'FrameRate',outputFrameRate); - videoWriter.VideoCompressor=videoCompressor; - end - - cMapLines=lines(8); - dPix=5; - if ~isempty(opticFlowFile) - OF=load(opticFlowFile); - tFramesOF=sync.tVideoFrames(OF.pFrames); - plotFlowField=true; - - rX=round(dPix/2):dPix:size(OF.allOF,2)-round(dPix/2); - rY=round(dPix/2):dPix:size(OF.allOF,1)-round(dPix/2); - [Y, X] = meshgrid(rX,rY); - if ~showOnlyEye - X=X+OF.initialFrameSubregion(2); - Y=Y+OF.initialFrameSubregion(1); - end - - shapes = vision.ShapeInserter; - shapes.Shape = 'Lines'; - shapes.BorderColor = OFlineColor; - else - plotFlowField=false; - end - - - smoothDB=2e-11; - interpDBOF=csaps(DB.t_ms,DB.bufferedBetaRatio,smoothDB,tFramesOF); - - %plot(tAllFrames(pFrames),interpOF);hold on;plot(tAnalyzedFrames,validmOF); - if isempty(tStart) - tStart=tFramesOF(1); - end - if isempty(tEnd) - tEnd=tFramesOF(end); - end - - pFrames=find(tFramesOF>=tStart & tFramesOF<=tEnd); - tFrames=OF.pFrames(pFrames); - - interpDB=interpDBOF(pFrames); - interpOF=OF.mOF(pFrames); - pFramesOrig=OF.pFrames(pFrames); - %plot(normZeroOne(interpDB));hold on;plot(normZeroOne(interpOF)); - - eInterpDB=[zeros(1,winFrame) interpDB zeros(1,winFrame)]./std([zeros(1,winFrame) interpDB zeros(1,winFrame)]); - eInterpOF=[zeros(1,winFrame) interpOF zeros(1,winFrame)]./2/std([zeros(1,winFrame) interpOF zeros(1,winFrame)]); - %plot(eInterpDB);hold on;plot(eInterpOF) - %plot(tAllFrames(pFrames),interpDB);hold on;plot(t_ms,bufferedBetaRatio);xlim([16027110.8963877 18570778.2072246]) - %plot(tAllFrames(pFrames),interpOF);hold on;plot(tAnalyzedFrames,validmOF);xlim([16027110.8963877 18570778.2072246]) - - %set scaling parameters for curves - if showOnlyEye - f=figure('position',[100 100 350 600]); - set(gcf,'PaperPositionMode','auto'); - - videoFrame=squeeze(OF.allIm(:,:,1)); - h(1)=subaxis(f,2,1,1,'M',0.03,'S',0.07); - h(2)=subaxis(f,2,1,2,'M',0.03,'S',0.07); - axis(h(1),'off'); - xlim(h(1),[0 2*winFrame]); - yl=[0 4]; - ylim(h(1),yl); - imshow(videoFrame,'Parent',h(2)); - set(h(2),'nextplot','replacechildren'); - hold(h(1),'on'); - pH=[]; - else - f=figure('position',[100 100 500 500]); - videoFrame=rgb2gray(videoReader.read(pFramesOrig(i))); %read will be replaced by readFrame in future versions but it is not possible to skip frames with readframes - - W=videoReader.Width; - H=videoReader.Height; - pX=(1:(2*winFrame+1))/(2*winFrame+1)*W; - yStartPixDB=H*0.4; %from top down - yPixDB=H*0.05; - yStartPixOF=H*0.5; - yPixOF=H*0.05; - ylineLim=H*0.55; - imshow(videoFrame); - set(gca,'nextplot','replacechildren'); - end - set(f,'Renderer','zbuffer'); - - for i=1:numel(pFramesOrig) - tmpDB=eInterpDB(i:i+2*winFrame); - tmpOF=eInterpOF(i:i+2*winFrame); - - if showOnlyEye - videoFrame=squeeze(OF.allIm(:,:,pFrames(i))); - else - videoFrame=rgb2gray(videoReader.read(pFramesOrig(i))); %read will be replaced by readFrame in future versions but it is not possible to skip frames with readframes - end - - if plotFlowField - currentFrame=squeeze(OF.allOF(:,:,pFrames(i))); - currentFrame=currentFrame(rY,rX); - Hor = imag(currentFrame)*ampOFLine; - Ver = real(currentFrame)*ampOFLine; - - OFlines = [Y(:)'; X(:)'; Y(:)'+Ver(:)'; X(:)'+Hor(:)']; - videoFrame = step(shapes, videoFrame, int32(OFlines)'); - % Draw lines on top of image - %pHL=line([X(:) X(:)+Hor(:)]',[Y(:) Y(:)+Ver(:)]','color',OFlineColor); - end - - if showOnlyEye - delete(pH); - imshow(videoFrame,'Parent',h(2)); - pH(1)=plot(h(1),tmpDB,'lineWidth',1,'color',cMapLines(1,:)); - pH(2)=plot(h(1),tmpOF,'lineWidth',1,'color',cMapLines(2,:)); - pH(3)=line([winFrame+1 winFrame+1],yl,'color',cMapLines(5,:),'Parent',h(1)); - %pH(4)=text(170,-0.4,[num2str(i-1) 's'],'Parent',h(1),'FontSize',16,'FontWeight','Bold'); - else - imshow(videoFrame);hold on; - pH(1)=plot(pX,-tmpDB*yPixDB+yStartPixDB,'lineWidth',3,'color',cMapLines(1,:)); - pH(2)=plot(pX,-tmpOF*yPixOF+yStartPixOF,'lineWidth',3,'color',cMapLines(2,:)); - pH(3)=line([pX(winFrame+1) pX(winFrame+1)],[ylineLim 0],'color',cMapLines(5,:)); - end - - if saveVideo %save tracked video - frame=getframe(f); - step(videoWriter, frame.cdata); - end - - end - - if saveVideo - release(videoWriter); - end - if ~showOnlyEye - delete(videoReader); - end - delete(f); - - end - - %% getSyncedDBEyeMovements - function data=getSyncedDBEyeMovements(obj,varargin) - %% parameter and settings - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.par.DVRLFPCh{obj.currentPRec},@isnumeric); - addParameter(parseObj,'videoFile',[obj.currentVideosFolder filesep obj.par.VideoFiles{obj.currentPRec}],@(x) exist(x,'file')); - addParameter(parseObj,'matroxTrigScheme',obj.par.MatroxTrigScheme{obj.currentPRec}); - addParameter(parseObj,'win',180*1000,@isnumeric); %median filter window for extracting optic flow baseline - addParameter(parseObj,'nStd',6,@isnumeric); %MAD (std) threshold for - addParameter(parseObj,'nBins',18,@isnumeric); - addParameter(parseObj,'pixelMoveThresh',10,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'nFramesRemoveAfterROIShift',3,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parSyncDBEye=parseObj.Results; - - [~,videoFileName]=fileparts(videoFile); - %check if analysis was already done done - obj.files.syncDBEye=[obj.currentAnalysisFolder filesep 'syncDBEye_' videoFileName '.mat']; - if exist(obj.files.syncDBEye,'file') & ~overwrite - if nargout==1 - data=load(obj.files.syncDBEye); - else - disp(['Syncing DB with eye tracking file for video: ' videoFileName ' already exists']); - end - return; - end - - eyeTrackingFile=[obj.currentAnalysisFolder filesep 'eyeTracking_' videoFileName '.mat']; - obj.checkFileRecording(eyeTrackingFile,'Eye tracking analysis missing, please first run getEyeMovement'); - load(eyeTrackingFile,'parEyeTracking','pFrames','mOF','pbboxUpdate','bboxCenterAll'); %load data - - digiTrigFile=[obj.currentAnalysisFolder filesep 'digiTrig.mat']; - obj.checkFileRecording(digiTrigFile,'digital trigger file missing, please first run getDigiData'); - load(digiTrigFile); %load data - - dbRatioFile=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - obj.checkFileRecording(dbRatioFile,'delta to beta file missing, please first run getDBRatio'); - load(dbRatioFile); %load data - - slowCyclesFile=[obj.currentAnalysisFolder filesep 'slowCycles_ch' num2str(ch) '.mat']; - obj.checkFileRecording(slowCyclesFile,'slow cycles file missing, please first run getSlowCycles'); - load(slowCyclesFile); %load data - - %remove frames that are close to a ROI shift and frames with large shifts - p2RemoveShifts=find(sqrt(diff(bboxCenterAll(:,1)).^2+diff(bboxCenterAll(:,2)).^2)>pixelMoveThresh)+1; - pFramesValid=pFrames; - validmOF=mOF; - if ~isempty(pbboxUpdate) || ~isempty(p2RemoveShifts) - p2Remove=union(p2RemoveShifts,pbboxUpdate)'; - p2Remove=bsxfun(@plus,p2Remove,(0:nFramesRemoveAfterROIShift-1)'); - p2Remove=unique(p2Remove(:)); - - validmOF(p2Remove)=[]; - pFramesValid(p2Remove)=[]; - bboxCenterAll(p2Remove,:)=[]; - end - - startFrameInVideo=cellfun(@(x) str2num(x),strsplit(obj.par.FrameRange{obj.currentPRec},'-'),'UniformOutput', 1); - if strcmp(matroxTrigScheme,'startD2FramesD1NoEndNoMissed') %correct start trigger (on digi ch 2), no stop trigger, no missed frames (on digi ch 1) - pMatrox=1; - pStart=2; - tAllFrames=tTrig{pMatrox}(1:2:end); - tAllFrames(tAllFramespCameraStart & tTrig{1}pCameraLast)); - frameShutterTimesAfterLastTrigger(diff(frameShutterTimesAfterLastTrigger)<2)=[]; %remove off trigger - every trigger is 1ms long and is recorded twice (once for on and once for off) - frameShutterTimesAfterLastTrigger=frameShutterTimesAfterLastTrigger(1:(nFrames-frameNumberEnd)); - frameShutterTimes=[frameShutterTimes frameShutterTimesAfterLastTrigger]; - end - %plot(tAnalyzedFrames/3600000,normZeroOne(validmOF));hold on;plot(tAnalyzedFrames/3600000,normZeroOne(bboxCenterAll)); - winSamples=round(win/1000*(parEyeTracking.frameRate/parEyeTracking.skipFrames)); - mOFmed=fastmedfilt1d(validmOF,winSamples)'; - mOFMAD=fastmedfilt1d(abs(validmOF-mOFmed),winSamples)'*1.4826; - tMovement=tAnalyzedFrames(validmOF>(mOFmed+nStd*mOFMAD)); - %plot(tAnalyzedFrames/3600000,validmOF);hold on;plot(tAnalyzedFrames/3600000,mOFmed+nStd*mOFMAD); - for i=1:numel(TcycleOnset) - cycleDuration=TcycleOffset(i)-TcycleOnset(i); - pTmp=find(tMovement>(TcycleMid(i)-cycleDuration/2) & tMovement<(TcycleMid(i)+cycleDuration/2)); - phaseAll{i}=(tMovement(pTmp)-(TcycleMid(i)-cycleDuration/2))/cycleDuration; - - shufTimes=rand(1,numel(pTmp))*cycleDuration; - phaseAllRand{i}=shufTimes/cycleDuration; - - pTmp=find(t_ms>(TcycleMid(i)-cycleDuration/2) & t_ms<(TcycleMid(i)+cycleDuration/2)); - resampledTemplate(i,:) = interp1((0:(numel(pTmp)-1))./(numel(pTmp)-1),bufferedBetaRatio(pTmp)',(0:(nBins-1))/(nBins-1),'spline'); - - %{ - cycleDuration=TcycleOffset(i)-TcycleOnset(i); - pTmp=find(tMovement>TcycleOnset(i) & tMovementTcycleOnset(i) & t_ms1 - videoReader = VideoReader(videoFile); %initiate video obj since number of frames was already read (not allowed by matlab) - %videoReader.CurrentTime=(1/videoReader.FrameRate)*(pFrames(1)-1); - nonConsecutiveVideo=true; - else - videoReader = vision.VideoFileReader(videoFile,'ImageColorSpace','Intensity','VideoOutputDataType','uint8'); % create required video objects - nonConsecutiveVideo=false; - end - - % optic flow definitions - converter = vision.ImageDataTypeConverter; - opticalFlow = vision.OpticalFlow(... - 'Method','Lucas-Kanade',... - 'ReferenceFrameDelay', 1,... - 'OutputValue' ,'Horizontal and vertical components in complex form');% use of the Lucas-Kanade method for optic flow determination - - bboxPoints=[initialFrameSubregion(1) initialFrameSubregion(2);initialFrameSubregion(1) initialFrameSubregion(2)+initialFrameSubregion(4);initialFrameSubregion(1)+initialFrameSubregion(3) initialFrameSubregion(2)+initialFrameSubregion(4);initialFrameSubregion(1)+initialFrameSubregion(3) initialFrameSubregion(2)]; - bboxCenter=[(bboxPoints(3,1)+bboxPoints(1,1))/2 (bboxPoints(3,2)+bboxPoints(1,2))/2]; - bboxCenterOld=[(bboxPoints(3,1)+bboxPoints(1,1))/2 (bboxPoints(3,2)+bboxPoints(1,2))/2]; - bboxPointsOld=bboxPoints; - - bboxShiftDistanceThreshold=round(min(initialFrameSubregion(3)*fractionOfBoxJumpThreshold,initialFrameSubregion(4)*fractionOfBoxJumpThreshold)); - - % Detect feature points in the face region. - points = detectMinEigenFeatures(initFrame, 'ROI', round(initialFrameSubregion)); - - %Display the detected points. - %figure, imshow(videoFrame), hold on, title('Detected features'); - %plot(points); - - % Create a point tracker and enable the bidirectional error constraint to make it more robust in the presence of noise and clutter. - pointTracker = vision.PointTracker('MaxBidirectionalError', 2); - - % Initialize the tracker with the initial point locations and the initial video frame. - points = points.Location; - initialize(pointTracker, points, initFrame); - - if plotTracking - videoPlayer = vision.VideoPlayer('Position',[100 100 [size(initFrame, 2), size(initFrame, 1)]+30]); - end - if saveTrackingVideo - videoWriter = vision.VideoFileWriter(trackingFileName,'FrameRate',30); - end - %savePlottedTracking - - % Make a copy of the points to be used for computing the geometric transformation between the points in the previous and the current frames - oldPoints = points; - - if saveFullOFMatrices %if to save all optic flow data - allOF=zeros(numel(yInd),numel(xInd),nFrames,'like',complex(zeros(1,'single'),zeros(1,'single'))); - allIm=zeros(numel(yInd),numel(xInd),nFrames,'single'); - else - allOF=[]; - allIm=[]; - end - - %% main loop - pbboxUpdate=[]; - bboxCenterAll=zeros(nFrames,2); - mOF=zeros(1,nFrames); - skipBoundingBoxInSkip=round(skipFramesBoundingBox/skipFrames); - parEyeTracking.skipBoundingBoxInSkip=skipBoundingBoxInSkip; - - hWB=waitbar(0,'Calculating optic flow'); - for i=1:nFrames - %frame = step(videoReader); this is faster but cant start from an arbitrary frame or jump frames - if nonConsecutiveVideo - videoFrame=rgb2gray(videoReader.read(pFrames(i))); %read will be replaced by readFrame in future versions but it is not possible to skip frames with readframes - else - videoFrame = step(videoReader); - for j=1:numel(pFrames(i+1)-pFrames(i)-1) - step(videoReader); - end - end - - if mod(i,skipBoundingBoxInSkip)==0 - waitbar(i/nFrames,hWB); - - % Track the points. Note that some points may be lost. - [points, isFound] = step(pointTracker, videoFrame); - visiblePoints = points(isFound, :); - oldInliers = oldPoints(isFound, :); - - if size(visiblePoints, 1) >= 2 % need at least 2 points to ensure we are still reliably tracking the object - - % Estimate the geometric transformation between the old points and the new points and eliminate outliers - [xform, oldInliers, visiblePoints] = estimateGeometricTransform(oldInliers, visiblePoints, 'similarity', 'MaxDistance', 4); - - % Apply the transformation to the bounding box points - bboxPoints = transformPointsForward(xform, bboxPoints); - - % Reset the points - if size(oldInliers,1) bboxShiftDistanceThreshold - %xInd=round(bboxPoints(1,1):bboxPoints(3,1)); - %yInd=round(bboxPoints(1,2):bboxPoints(3,2)); - - xyShift=round(bboxCenter-bboxCenterOld); - yInd=round(yInd-(xyShift(1))); - xInd=xInd-(xyShift(2)); - if any(yInd<1) - yInd=1:numel(yInd); - end - if any(xInd<1) - xInd=1:numel(xInd); - end - if any(yInd>frameHeight) - yInd=(frameHeight-numel(yInd)+1):frameHeight; - end - if any(xInd>frameWidth) - xInd=(frameWidth-numel(xInd)+1):frameWidth; - end - - bboxPointsOld=bboxPoints; - bboxCenterOld=bboxCenter; - pbboxUpdate=[pbboxUpdate i]; - end - - if plotTracking - - % Insert a bounding box around the object being tracked - bboxPolygon = reshape(bboxPoints', 1, []); - bboxPolygonOld = reshape(bboxPointsOld', 1, []); - - videoFramePlot = insertShape(videoFrame, 'Polygon', bboxPolygon,'LineWidth', 2); - videoFramePlot = insertShape(videoFramePlot, 'Polygon', bboxPolygonOld,'LineWidth', 2,'color','r'); - - % Display tracked points - %videoFramePlot = insertMarker(videoFramePlot, visiblePoints, '+','Color', 'white'); - - % Display the annotated video frame using the video player object - step(videoPlayer, videoFramePlot); - - if saveTrackingVideo %save tracked video - step(videoWriter, videoFramePlot); - end - end - else - disp(['Tracking analysis stopped at ' num2str(i) '/' num2str(nFrames) ' since all tracking points were lost']); - parEyeTracking.pStopDue2LostPoints=i; - mOF(i:end)=[]; - bboxCenterAll(i:end,:)=[]; - pFrames(i:end)=[]; - break; %stop for loop - end - - end - im = step(converter, videoFrame(yInd,xInd)); - tmpOF=step(opticalFlow, im); - - if removeBorderOF - tmpOF(pBorder)=0; - end - - if saveFullOFMatrices - allOF(:,:,i) = tmpOF; - allIm(:,:,i) = im; - end - - mOF(i)=mean(mean(abs(tmpOF))); %mean velocity for every pixel - bboxCenterAll(i,:)=bboxCenter; - - end - close(hWB); - - save(obj.files.eyeTracking,'mOF','allOF','allIm','pbboxUpdate','parEyeTracking','pFrames','bboxCenterAll','initialFrameSubregion'); - - % Clean uprelease(videoReader); - release(opticalFlow); - release(converter); - release(pointTracker); - if nonConsecutiveVideo - delete(videoReader); - else - release(videoReader); - end - - if saveTrackingVideo %save tracked video - release(videoWriter); - end - if plotTracking - release(videoPlayer); - end - - end - - %% getDelta2BetaRatio - function data=getDelta2BetaRatio(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.par.DVRLFPCh{obj.currentPRec},@isnumeric); - addParameter(parseObj,'movLongWin',1000*60*30,@isnumeric); %max freq. to examine - addParameter(parseObj,'movWin',10000,@isnumeric); - addParameter(parseObj,'movOLWin',9000,@isnumeric); - addParameter(parseObj,'segmentWelch',1000,@isnumeric); - addParameter(parseObj,'dftPointsWelch',2^10,@isnumeric); - addParameter(parseObj,'OLWelch',0.5); - addParameter(parseObj,'tStart',0,@isnumeric); - addParameter(parseObj,'win',0,@isnumeric); %if 0 uses the whole recording duration - addParameter(parseObj,'deltaBandCutoff',4,@isnumeric); - addParameter(parseObj,'betaBandLowCutoff',10,@isnumeric); - addParameter(parseObj,'betaBandHighCutoff',40,@isnumeric); - addParameter(parseObj,'applyNotch',0,@isnumeric); - addParameter(parseObj,'maxVoltage',1500,@isnumeric); - addParameter(parseObj,'overwrite',0,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parDBRatio=parseObj.Results; - - if isnan(ch) - disp('Error: no reference channel for Delta 2 Beta extraction'); - return; - end - %check if analysis was already done done - obj.files.dbRatio=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - if exist(obj.files.dbRatio,'file') & ~overwrite - if nargout==1 - data=load(obj.files.dbRatio); - else - disp('DB analysis already exists for this recording'); - end - return; - end - - movWinSamples=movWin/1000*obj.filt.FFs;%obj.filt.FFs in Hz, movWin in samples - movOLWinSamples=movOLWin/1000*obj.filt.FFs; - timeBin=(movWin-movOLWin); %ms - - segmentWelchSamples = round(segmentWelch/1000*obj.filt.FFs); - samplesOLWelch = round(segmentWelchSamples*OLWelch); - - %run welch once to get frequencies for every bin (f) determine frequency bands - [~,f] = pwelch(randn(1,movWinSamples),segmentWelchSamples,samplesOLWelch,dftPointsWelch,obj.filt.FFs); - pfLowBand=find(f<=deltaBandCutoff); - pfHighBand=find(f>=betaBandLowCutoff & fmaxVoltage)=nan; %remove high voltage movement artifacts - - FMLongB = buffer(FMLong,movWinSamples,movOLWinSamples,'nodelay'); - pValid=all(~isnan(FMLongB)); - - [pxx,f] = pwelch(FMLongB(:,pValid),segmentWelchSamples,samplesOLWelch,dftPointsWelch,obj.filt.FFs); - - deltaBetaRatioAll{i}=zeros(1,numel(pValid)); - deltaBetaRatioAll{i}(pValid)=(mean(pxx(pfLowBand,:))./mean(pxx(pfHighBand,:)))'; - - deltaRatioAll{i}=zeros(1,numel(pValid)); - deltaRatioAll{i}(pValid)=mean(pxx(pfLowBand,:))'; - - betaRatioAll{i}=zeros(1,numel(pValid)); - betaRatioAll{i}(pValid)=mean(pxx(pfHighBand,:))'; - - t_ms{i}=startTimes(i)+((movWin/2):timeBin:(movLongWin-movWin/2)); - end - fprintf('\n'); - deltaBetaRatioAll{end}(t_ms{end}>(endTime-movWin/2))=NaN; - deltaRatioAll{end}(t_ms{end}>(endTime-movWin/2))=NaN; - betaRatioAll{end}(t_ms{end}>(endTime-movWin/2))=NaN; - - bufferedBetaRatio=cell2mat(deltaBetaRatioAll);bufferedBetaRatio=bufferedBetaRatio(:); - bufferedDeltaRatio=cell2mat(deltaRatioAll);bufferedDeltaRatio=bufferedDeltaRatio(:); - bufferedOnlyBetaRatio=cell2mat(betaRatioAll);bufferedOnlyBetaRatio=bufferedOnlyBetaRatio(:); - - t_ms=cell2mat(t_ms); - - save(obj.files.dbRatio,'t_ms','bufferedBetaRatio','parDBRatio','bufferedOnlyBetaRatio','bufferedDeltaRatio'); - end - - %% getSlowCycles - function data=getSlowCycles(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.par.DVRLFPCh{obj.currentPRec},@isnumeric); - addParameter(parseObj,'medianFiltWin',1000*20,@isnumeric); - addParameter(parseObj,'longOrdFiltWin',1000*1000,@isnumeric); - addParameter(parseObj,'longOrdFiltOrd',0.6,@isnumeric); - addParameter(parseObj,'maxCycle',1000*140,@isnumeric); %for excluding cycles which do not have a regular duration - addParameter(parseObj,'minCycle',1000*5,@isnumeric); %for merging cycles with gaps less than these - addParameter(parseObj,'overwrite',0,@isnumeric); - - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parSlowCycles=parseObj.Results; - - %check if analysis was already done done - obj.files.slowCycles=[obj.currentAnalysisFolder filesep 'slowCycles_ch' num2str(ch) '.mat']; - if exist(obj.files.slowCycles,'file') & ~overwrite - if nargout==1 - data=load(obj.files.slowCycles); - else - disp('Slow cycle analysis already exists for this recording'); - end - return; - end - - dbRatioFile=[obj.currentAnalysisFolder filesep 'dbRatio_ch' num2str(ch) '.mat']; - dbAutocorrFile=[obj.currentAnalysisFolder filesep 'dbAutocorr_ch' num2str(ch) '.mat']; - - obj.checkFileRecording(dbRatioFile,'Delta to beta analysis missing, please first run getDBRatio'); - load(dbRatioFile,'t_ms','bufferedBetaRatio','parDBRatio'); %load data - - obj.checkFileRecording(dbAutocorrFile,'Delta to beta autocorr analysis missing, please first run getDBRatioAC'); - load(dbAutocorrFile,'pSleepDBRatio'); %load data - - timeBin=(parDBRatio.movWin-parDBRatio.movOLWin); - - %smooth with median filter - medianFiltSamples=medianFiltWin/timeBin; - DBRatioMedFilt = fastmedfilt1d(bufferedBetaRatio, medianFiltSamples); - - %long order filter to determine edges of DB fluctuation - longOrdFiltSamples=longOrdFiltWin/timeBin; - longOrdFiltOrdSamples=longOrdFiltOrd*longOrdFiltSamples; - DBLongOrdFilt = ordfilt2(DBRatioMedFilt, longOrdFiltOrdSamples, ones(longOrdFiltSamples,1)); - - %plot(t_ms/1000/60/60,DBRatioMedFilt);hold on;plot(t_ms/1000/60/60,DBLongOrdFilt); - - edgeSamples=100; - sortDBLongOrdFilt=sort(DBLongOrdFilt); - sortDBLongOrdFilt(isnan(sortDBLongOrdFilt))=[]; - Th=mean(sortDBLongOrdFilt(1:edgeSamples))+(mean(sortDBLongOrdFilt((end-edgeSamples):end))-mean(sortDBLongOrdFilt(1:edgeSamples)))/2; - %Th=min(DBLongOrdFilt)+(max(DBLongOrdFilt)-min(DBLongOrdFilt))/2; - - maxCycleSamples=maxCycle/timeBin; - minCycleSamples=minCycle/timeBin; - - pTcycleOnset=find((DBRatioMedFilt(2:end)>=Th & DBRatioMedFilt(1:end-1)maxCycleSamples; - - pTcycleOffset(ppRemove)=[]; - pTcycleOnset(ppRemove)=[]; - - TcycleOnset=t_ms(pTcycleOnset); - TcycleOffset=t_ms(pTcycleOffset); - - edgesSamples=10; - pTcycleMid=zeros(numel(TcycleOnset),1); - for i=1:numel(TcycleOnset) - pTmp=find(DBRatioMedFilt((pTcycleOnset(i)+edgesSamples):(pTcycleOffset(i)-edgesSamples))tStart & t_ms<(tStart+win)); - timeBin=(parDBRatio.movWin-parDBRatio.movOLWin); - XCFLagSamples=XCFLag/timeBin; - [xcf,xcf_lags,xcf_bounds]=crosscorr(bufferedBetaRatio(pOscillation),bufferedBetaRatio(pOscillation),XCFLagSamples); - - xcf_lags=xcf_lags*1000; - %calculate periodicity - - %find first vally and peak in the autocorrelation function - [~,pPeak] = findpeaks(xcf(XCFLagSamples+1:end),'MinPeakProminence',0.1); - [~,pVally] = findpeaks(-xcf(XCFLagSamples+1:end),'MinPeakProminence',0.1); - if isempty(pPeak) %if peak is weak, try a different value - [~,pPeak] = findpeaks(xcf(XCFLagSamples+1:end),'MinPeakProminence',0.05); - [~,pVally] = findpeaks(-xcf(XCFLagSamples+1:end),'MinPeakProminence',0.05); - disp('Prominance for peak detection was reduced to 0.05 due to low periodicity values!!!'); - end - - - - if isempty(pPeak) | isempty(pVally) - pPeriod=NaN; - period=NaN; - pVally=NaN; - vallyPeriod=NaN; - peak2VallyDiff=NaN; - else - pPeriod=pPeak(1)+XCFLagSamples; - period=xcf_lags(pPeriod); - pAntiPeriod=pVally(1)+XCFLagSamples; - vallyPeriod=xcf_lags(pAntiPeriod); - peak2VallyDiff=xcf(pPeriod)-xcf(pAntiPeriod); - end - - - %sliding autocorr analysis - movingAutoCorrWinSamples=movingAutoCorrWin/timeBin; - movingAutoCorrOLSamples=movingAutoCorrOL/timeBin; - autoCorrTimeBin=(movingAutoCorrWin-movingAutoCorrOL); - BetaRatioForSlidingAutocorr = buffer(bufferedBetaRatio,movingAutoCorrWinSamples,movingAutoCorrOLSamples,'nodelay'); - tSlidingAC=(movingAutoCorrWin/2):(movingAutoCorrWin-movingAutoCorrOL):(t_ms(end)-movingAutoCorrWin/2+movingAutoCorrWin-movingAutoCorrOL); - - %R=xcorrmat(BetaRatioForSlidingAutocorr,BetaRatioForSlidingAutocorr,autoCorrSamples); - - acfSamples=floor(movingAutoCorrWinSamples/2); - acf=zeros(size(BetaRatioForSlidingAutocorr,1)+1,size(BetaRatioForSlidingAutocorr,2)); - peak2VallyDiff=zeros(1,size(BetaRatioForSlidingAutocorr,2)); - for i=1:size(BetaRatioForSlidingAutocorr,2) - [acf(:,i),autoCorrSamples] = crosscorr(BetaRatioForSlidingAutocorr(:,i),BetaRatioForSlidingAutocorr(:,i),acfSamples); - %calculate peak2VallyDiff for different times - acf(:,i)=smooth(acf(:,i),10,'moving'); - - [acfPeakAll(i),acfPeriodAll(i)]=max(acf((acfSamples+pPeak(1)-maxPeriodBand):(acfSamples+pPeak(1)+maxPeriodBand),i)); - [acfVallyAll(i),acfAntiPeriodAll(i)]=min(acf((acfSamples+pVally(1)-maxPeriodBand):(acfSamples+pVally(1)+maxPeriodBand),i)); - peak2VallyDiff(i)=acfPeakAll(i)-acfVallyAll(i); - - %{ - [~,pPeak] = findpeaks(acf(acfSamples+1:end,i),'MinPeakProminence',0.1); - [~,pVally] = findpeaks(-acf(acfSamples+1:end,i),'MinPeakProminence',0.1); - findpeaks(acf(acfSamples+1:end,i),'MinPeakProminence',0.1); - disp([pPeak(1) pVally(1)]) - pause; - - if ~isempty(pPeak) & ~isempty(pVally) - pPeriodTmp=pPeak(1)+acfSamples; - pVally=pVally(1)+acfSamples; - peak2VallyDiff(i)=acf(pPeriodTmp,i)-acf(pVally,i); - end - %} - end - autocorrTimes=autoCorrSamples*timeBin; - acfPeriodAll=autocorrTimes((acfPeriodAll+acfSamples+pPeak(1)-maxPeriodBand-1)); - - oscilDurationMovingSamples=oscilDurationMovingWin/autoCorrTimeBin; - tmpOscDuration=peak2VallyDiff>oscilDurationThresh; - filtOscilDuration = medfilt1(double(tmpOscDuration),oscilDurationMovingSamples); - pSleepSlidingAC=filtOscilDuration>=0.5; - - tmpBin=movingAutoCorrWinSamples-movingAutoCorrOLSamples; - pSleepDBRatio=false(numel(bufferedBetaRatio),1); - for i=1:numel(pSleepSlidingAC) - pSleepDBRatio(((i-1)*tmpBin+1):(i*tmpBin))=pSleepSlidingAC(i); - end - - pStartSleep=find(pSleepDBRatio==1,1,'first'); - tStartSleep=t_ms(pStartSleep); - tEndSleep=t_ms(find(pSleepDBRatio(pStartSleep:end)==0,1,'first')+pStartSleep); - - pSleepSlidingAC=find(tSlidingAC>=tStartSleep & tSlidingAC<=tEndSleep & peak2VallyDiff>oscilDurationThresh); - - smoothingSamples=round(smoothingDuration/autoCorrTimeBin); - filteredSlidingPeriod=smooth(tSlidingAC(pSleepSlidingAC),acfPeriodAll(pSleepSlidingAC),smoothingSamples,'moving'); - edgeSamples=tSlidingAC(pSleepSlidingAC)<=(tSlidingAC(pSleepSlidingAC(1))+smoothingDuration/2) | tSlidingAC(pSleepSlidingAC)>=(tSlidingAC(pSleepSlidingAC(end))-smoothingDuration/2); - filteredSlidingPeriod(edgeSamples)=[]; - tFilteredSlidingPeriod=tSlidingAC(pSleepSlidingAC(~edgeSamples))'; - - %save data - save(obj.files.dbAutocorr,'parDbAutocorr','xcf','xcf_lags','xcf_bounds','BetaRatioForSlidingAutocorr','autoCorrTimeBin','autocorrTimes','timeBin',... - 'pPeriod','period','acf','vallyPeriod','peak2VallyDiff','pSleepDBRatio','pSleepSlidingAC','acfPeakAll','acfVallyAll','tSlidingAC','acfPeriodAll',... - 'tStartSleep','tEndSleep','filteredSlidingPeriod','tFilteredSlidingPeriod','pSleepSlidingAC'); - end - - %% plotFreqBandDetection - function [h]=plotFreqBandDetection(obj,varargin) - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.par.DVRLFPCh{obj.currentPRec},@isnumeric); - addParameter(parseObj,'plotDendrogram',true); - addParameter(parseObj,'plotSpectralBands',true); - addParameter(parseObj,'savePlots',true); - addParameter(parseObj,'freqBandFile',[]); - addParameter(parseObj,'cLim',0); - addParameter(parseObj,'printLocalCopy',0,@isnumeric); - addParameter(parseObj,'hDendro',0); - addParameter(parseObj,'hSpectra',0); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - if isempty(freqBandFile) - spectralClusteringFile=[obj.currentAnalysisFolder filesep 'spectalClustering_ch' num2str(ch) '.mat']; - else - spectralClusteringFile=freqBandFile; - end - obj.checkFileRecording(spectralClusteringFile,'Spectral band analysis missing, please first run getDelta2BetaRatio'); - load(spectralClusteringFile); - - if plotDendrogram - maxDendroClusters=2; - - if cLim==0 - cLim=[]; - end - if hDendro==0 - hDendro=[]; - else - savePlots=[]; - end - [DC,order,clusters,h]=DendrogramMatrix(corrMat,'linkMetric','euclidean','linkMethod','ward','maxClusters',maxDendroClusters,... - 'toPlotBinaryTree',1,'cLim',cLim,'hDendro',hDendro,'plotOrderLabels',0); - %h(3).Position=[0.9149 0.7595 0.0137 0.1667]; - ylabel(h(3),'Corr.'); - xlabel(h(2),'Segment'); - xlabel(h(1),'Distance'); - if savePlots - set(gcf,'PaperPositionMode','auto'); - fileName=[obj.currentPlotFolder filesep 'dendrogram_ch' num2str(parFreqBandDetection.ch) '_t' num2str(parFreqBandDetection.tStart) '_w' num2str(parFreqBandDetection.win)]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - print(fileName,'-depsc',['-r' num2str(obj.figResEPS)]); - if printLocalCopy - fileName=[cd filesep obj.par.Animal{obj.currentPRec} '_Rec' num2str(obj.currentPRec) '_dendrogram_ch' num2str(parFreqBandDetection.ch) '_t' num2str(parFreqBandDetection.tStart) '_w' num2str(parFreqBandDetection.win)]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - print(fileName,'-depsc',['-r' num2str(obj.figResEPS)]); - end - end - end - - if plotSpectralBands - if hSpectra==0 - fTmp=figure('position',[680 678 658 420]); - hTmp=axes; - h=[h hTmp]; - else - axes(hSpectra); - h=[h hSpectra]; - savePlots=0; - end - for i=1:maxDendroClusters - PS=mean(normsPxx(:,clusters==i),2); - plot(freqHz,PS,'lineWidth',2);hold on; - end - plot(crossFreq,PS(crossFreq==freqHz),'ok','MarkerSize',8,'LineWidth',2); - text(crossFreq+(diff(xlim))*0.15,PS(crossFreq==freqHz),'F_{trans.}'); - xlabel('Frequency (Hz)'); - ylabel('nPSD'); - xlim([0 parFreqBandDetection.fMax]); - - if savePlots - set(fTmp,'PaperPositionMode','auto'); - fileName=[obj.currentPlotFolder filesep 'spectralBands_ch' num2str(parFreqBandDetection.ch) '_t' num2str(parFreqBandDetection.tStart) '_w' num2str(parFreqBandDetection.win)]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - print(fileName,'-depsc',['-r' num2str(obj.figResEPS)]); - if printLocalCopy - fileName=[cd filesep obj.par.Animal{obj.currentPRec} '_Rec' num2str(obj.currentPRec) '_spectralBands_ch' num2str(parFreqBandDetection.ch) '_t' num2str(parFreqBandDetection.tStart) '_w' num2str(parFreqBandDetection.win)]; - print(fileName,'-djpeg',['-r' num2str(obj.figResJPG)]); - print(fileName,'-depsc',['-r' num2str(obj.figResEPS)]); - end - end - - end - - end - - - %% getHPSegments - function data=getAwakeVsSleepFreq(obj,varargin) - %% parameter and settings - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.par.DVRLFPCh{obj.currentPRec},@isnumeric); - addParameter(parseObj,'sleepFreqBandFile',[]); %median filter window for extracting optic flow baseline - addParameter(parseObj,'binDuration',10000); - addParameter(parseObj,'fMax',30,@isnumeric); %max freq. to examine - addParameter(parseObj,'maxWin',1000*60*60*2,@isnumeric); - addParameter(parseObj,'overwrite',false,@isnumeric); - addParameter(parseObj,'saveFileName',[]); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parAwakeVsSleepFreq=parseObj.Results; - - if isempty(sleepFreqBandFile) - spectralClusteringFile=[obj.currentAnalysisFolder filesep 'spectalClustering_ch' num2str(ch) '.mat']; - else - spectralClusteringFile=[sleepFreqBandFile '.mat']; - end - %obj.checkFileRecording(spectralClusteringFile,'Spectral band analysis missing, please first run getFreqBandDetection'); - %dataSleep=load(spectralClusteringFile,'sPxx','freqHz','normsPxx','clusters'); - - %check if analysis was already done done - if isempty(saveFileName) - obj.files.AwakeVsSleepFreq=[obj.currentAnalysisFolder filesep 'AwakeVsSleepFreq_ch' num2str(ch)]; - else - obj.files.AwakeVsSleepFreq=saveFileName; - end - - if exist(obj.files.AwakeVsSleepFreq,'file') & ~overwrite - if nargout==1 - data=load(obj.files.AwakeVsSleepFreq); - else - disp(['AwakeVsSleepFreq analysis file already exists']); - end - return; - end - - animalStates=strsplit(obj.par.AnimalState{obj.currentPRec},'/'); - awakeStartTimeSec=obj.par.tStartAwake{obj.currentPRec}; - - for i=1:numel(animalStates) - if strcmp(animalStates{i},'Awake') || strcmp(animalStates{i},'Running') || strcmp(animalStates{i},'Resting') - recDuration=obj.currentDataObj.recordingDuration_ms; - if ~isnan(awakeStartTimeSec) - tStart=awakeStartTimeSec*1000; - else - tStart=0; - end - win=min(maxWin,floor((recDuration-tStart)/binDuration)*binDuration); - obj.getFreqBandDetection('tStart',tStart,'win',win,'binDuration',binDuration,'saveFile',obj.files.AwakeVsSleepFreq,'maxDendroClusters',1,'overwrite',overwrite,'fMax',fMax); - dataAwake=obj.getFreqBandDetection('saveFile',obj.files.AwakeVsSleepFreq); - - %{ - for j=unique(dataSleep.clusters)' - PS(j,:)=mean(10*log10(dataSleep.normsPxx(:,dataSleep.clusters==j)),2); - end - PA=mean(bsxfun(@rdivide,dataAwake.sPxx,mean(dataSleep.sPxx,2)),2); - plot(dataSleep.freqHz,PS,'lineWidth',2);hold on; - plot(dataAwake.freqHz,PA,'lineWidth',2); - %} - end - end - - %save(obj.files.AwakeVsSleepFreq,'parAwakeVsSleepFreq'); - end - - %% getActivity4OpenVsClosedEyes - function getActivity4OpenVsClosedEyes(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',[],@isnumeric); - addParameter(parseObj,'saveFile',[]); - addParameter(parseObj,'nZoomPanels',1); - addParameter(parseObj,'overwrite',0,@isnumeric); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parActivity4OpenVsClosedEyes=parseObj.Results; - - %check if analysis was already done done - if isempty(saveFile) - obj.files.Activity4OpenVsClosedEyes=[obj.currentAnalysisFolder filesep 'Activity4OpenVsClosedEyes_ch' num2str(ch) '.mat']; - else - obj.files.Activity4OpenVsClosedEyes=[saveFile '.mat']; - end - - if exist(obj.files.Activity4OpenVsClosedEyes,'file') & ~overwrite - if nargout==1 - data=load(obj.files.Activity4OpenVsClosedEyes); - else - disp('Activity4OpenVsClosedEyes analysis already performed, use ''overwrite'' to recalculate'); - end - return; - end - - obj=obj.getFileNames; - if exist(obj.files.dbRatio,'file') - db=load(obj.files.dbRatio); - end - if exist(obj.files.dbRatio,'file') - dbAC=load(obj.files.dbAutocorr,'tStartSleep','tEndSleep'); - end - - eye=load([obj.currentAnalysisFolder filesep 'eye.mat']); - tmpEvents=min(numel(eye.eyeOpenStart),numel(eye.eyeCloseStart)); - if (eye.eyeCloseStart(1)-eye.eyeOpenStart(1)) >= 0 %first anotation segment is eye open - openEyeStart=eye.eyeOpenStart(1:tmpEvents); - openEyeEnd=eye.eyeCloseStart(1:tmpEvents); - closedEyeStart=eye.eyeCloseStart(1:tmpEvents-1); - closedEyeEnd=eye.eyeOpenStart(2:tmpEvents); - else %first anotation segment is eyes close - openEyeStart=eye.eyeOpenStart(1:tmpEvents-1); - openEyeEnd=eye.eyeCloseStart(2:tmpEvents); - closedEyeStart=eye.eyeCloseStart(1:tmpEvents); - closedEyeEnd=eye.eyeOpenStart(1:tmpEvents); - end - - pNonSleepOpen=find((openEyeStartdbAC.tEndSleep & openEyeEnd>dbAC.tEndSleep)); - pNonSleepClosed=find((closedEyeStartdbAC.tEndSleep & closedEyeEnd>dbAC.tEndSleep)); - - %remove open closed segments that occur during the main sleep epoch - openEyeStart=openEyeStart(pNonSleepOpen); - openEyeEnd=openEyeEnd(pNonSleepOpen); - closedEyeStart=closedEyeStart(pNonSleepClosed); - closedEyeEnd=closedEyeEnd(pNonSleepClosed); - - allOpenDb={};allClosedDb={}; - for i=1:numel(openEyeStart) - pTmp=find(db.t_ms>openEyeStart(i) & db.t_ms<=openEyeEnd(i)); - allOpenDb{i}=db.bufferedBetaRatio(pTmp); - end - for i=1:numel(closedEyeStart) - pTmp=find(db.t_ms>closedEyeStart(i) & db.t_ms<=closedEyeEnd(i)); - allClosedDb{i}=db.bufferedBetaRatio(pTmp); - end - allOpenDb=cell2mat(allOpenDb'); - allClosedDb=cell2mat(allClosedDb'); - - - - f=figure('position',[520 -97 560 895]); - for i=1:nZoomPanels - - h(i)=subaxis(f,nZoomPanels+1,1,i,'s',0.03,'mt',0.01); - plot(db.t_ms/1000/60,db.bufferedBetaRatio);hold on; - yl=ylim; - patch([openEyeStart;openEyeEnd;openEyeEnd;openEyeStart]/1000/60,(ones(numel(openEyeStart),1)*[yl(1) yl(1) yl(2) yl(2)])',[0 0 1],'FaceAlpha',0.2,'edgeColor','none'); - patch([closedEyeStart;closedEyeEnd;closedEyeEnd;closedEyeStart]/1000/60,(ones(numel(closedEyeStart),1)*[yl(1) yl(1) yl(2) yl(2)])',[1 0 0],'FaceAlpha',0.2,'edgeColor','none'); - axis tight; - - if i==1 - [hl,ho]=legend({'\delta/\beta','open','closed'},'box','off','location','northwest'); - %horizontalLegend(ho); - end - end - - xlabel('Time [min]'); - ylabel('\delta/\beta'); - - - - h(nZoomPanels+1)=subaxis(f,nZoomPanels+1,1,nZoomPanels+1,'s',0.01); - - maxEdge=min(2000,6*std([allOpenDb;allClosedDb])); - - edges=[0:(maxEdge/10):maxEdge]; - [IOpen]=histc(allOpenDb,edges); - [IClosed]=histc(allClosedDb,edges); - bar(edges,[IOpen./sum(IOpen) IClosed/sum(IClosed)],1.1); - xlabel('\delta/\beta'); - ylabel('Prob.'); - l=legend({'Open','Close'},'box','off'); - end - - %% getFreqBandDetectionEMG - function under construction - function [data]=getFreqBandDetectionEMG(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',[],@isnumeric); - addParameter(parseObj,'fMax',500,@isnumeric); %max freq. to examine - addParameter(parseObj,'dftPoints',2^12,@isnumeric); - addParameter(parseObj,'tStart',0,@isnumeric); - addParameter(parseObj,'win',1000*60*60,@isnumeric); - addParameter(parseObj,'maxDendroClusters',2,@isnumeric); - addParameter(parseObj,'saveFile',[]); - addParameter(parseObj,'overwrite',0,@isnumeric); - addParameter(parseObj,'segmentLength',1000); - addParameter(parseObj,'WelchOL',0.5); - addParameter(parseObj,'binDuration',10000); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parFreqBandDetectionEMG=parseObj.Results; - - %check if analysis was already done done - if isempty(saveFile) - obj.files.spectralClusteringEMG=[obj.currentAnalysisFolder filesep 'spectalClusteringEMG_ch' num2str(ch) '.mat']; - else - obj.files.spectralClusteringEMG=[saveFile '.mat']; - end - - if exist(obj.files.spectralClusteringEMG,'file') & ~overwrite - if nargout==1 - data=load(obj.files.spectralClusteringEMG); - else - disp('Spectral clustering EMG analysis already exists for this recording'); - end - return; - end - - obj.filt.EMG1=filterData(obj.currentDataObj.samplingFrequency(1)); - obj.filt.EMG1.downSamplingFactor=32; - obj.filt.EMG1.padding=true; - obj.filt.EMG1=obj.filt.EMG1.designDownSample; - - MLong=obj.currentDataObj.getData(ch,tStart,win); - FMLong=obj.filt.EMG1.getFilteredData(MLong); - - %calculate initial parameters - segmentSamples = round(segmentLength/1000*obj.filt.EMG1.filteredSamplingFrequency); - samplesOL = round(segmentSamples*WelchOL); - samplesBin = binDuration/1000*obj.filt.EMG1.filteredSamplingFrequency; - - nBins=numel(FMLong)/samplesBin; - - FMLongB=reshape(FMLong,[samplesBin,nBins]); - - if (numel(FMLong)/samplesBin)~=round(numel(FMLong)/samplesBin) - nBins=nBins-1; - FMLong=FMLong(1:(samplesBin*nBins)); - disp('Last bin in recording not included due to a missmatch between recording duration and binDuration'); - end - - [pxx,f] = pwelch(FMLongB,segmentSamples,samplesOL,dftPoints,obj.filt.EMG1.filteredSamplingFrequency); - %plot(10*log10(pxx)) - p=find(ftStart & data.t_msmean(S2(1:3)) - crossFreq=freqHz(1+find(S2-S1>=0,1,'last')); - else - crossFreq=freqHz(1+find(S1-S2>=0,1,'last')); - end - else - crossFreq=[];order=[];clusters=[]; - end - - save(obj.files.spectralClustering,'corrMat','sPxx','normsPxx','freqHz','parFreqBandDetectionEMG','order','clusters','crossFreq'); - end - - - %% getFreqBandDetection - function [data]=getFreqBandDetection(obj,varargin) - obj.checkFileRecording; - - parseObj = inputParser; - addParameter(parseObj,'ch',obj.par.DVRLFPCh{obj.currentPRec},@isnumeric); - addParameter(parseObj,'fMax',30,@isnumeric); %max freq. to examine - addParameter(parseObj,'dftPoints',2^10,@isnumeric); - addParameter(parseObj,'tStart',0,@isnumeric); - addParameter(parseObj,'win',1000*60*60,@isnumeric); - addParameter(parseObj,'maxDendroClusters',2,@isnumeric); - addParameter(parseObj,'saveFile',[]); - addParameter(parseObj,'overwrite',0,@isnumeric); - addParameter(parseObj,'segmentLength',1000); - addParameter(parseObj,'WelchOL',0.5); - addParameter(parseObj,'binDuration',10000); - addParameter(parseObj,'inputParams',false,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - %make parameter structure - parFreqBandDetection=parseObj.Results; - - %check if analysis was already done done - if isempty(saveFile) - obj.files.spectralClustering=[obj.currentAnalysisFolder filesep 'spectalClustering_ch' num2str(ch) '.mat']; - else - obj.files.spectralClustering=[saveFile '.mat']; - end - - if exist(obj.files.spectralClustering,'file') & ~overwrite - if nargout==1 - data=load(obj.files.spectralClustering); - else - disp('Spectral clustering analysis already exists for this recording'); - end - return; - end - - MLong=obj.currentDataObj.getData(ch,tStart,win); - FMLong=obj.filt.F.getFilteredData(MLong); - - %calculate initial parameters - segmentSamples = round(segmentLength/1000*obj.filt.FFs); - samplesOL = round(segmentSamples*WelchOL); - samplesBin = binDuration/1000*obj.filt.FFs; - - nBins=numel(FMLong)/samplesBin; - - FMLongB=reshape(FMLong,[samplesBin,nBins]); - - if (numel(FMLong)/samplesBin)~=round(numel(FMLong)/samplesBin) - nBins=nBins-1; - FMLong=FMLong(1:(samplesBin*nBins)); - disp('Last bin in recording not included due to a missmatch between recording duration and binDuration'); - end - - [pxx,f] = pwelch(FMLongB,segmentSamples,samplesOL,dftPoints,obj.filt.FFs); - %plot(10*log10(pxx)) - p=find(fmean(S2(1:3)) - crossFreq=freqHz(find(S2-S1>=0,1,'first')); - else - crossFreq=freqHz(find(S1-S2>=0,1,'first')); - end - else - crossFreq=[];order=[];clusters=[]; - end - - save(obj.files.spectralClustering,'corrMat','sPxx','normsPxx','freqHz','parFreqBandDetection','order','clusters','crossFreq'); - end - - %% getFileNames - %% getFileNames - function [obj,fileName]=getFileNames(obj,methodName) - %get the names of mat files associated with every method (or a specific method) - %[obj,fileName]=getFileNames(obj,methodName) - % methodName - the name of the method - % fileName - the mat file name associated with the method and a specific recording - if nargin==1 - methodNames=methods(obj); - handleMethods=methods('handle'); - uniqueMethods=setdiff(methodNames,handleMethods); - for i=1:numel(uniqueMethods) - obj.files.(uniqueMethods{i})=[obj.currentAnalysisFolder filesep uniqueMethods{i} '.mat']; - end - else - fileName=[obj.currentAnalysisFolder filesep methodName '.mat']; - obj.files.(methodName)=[obj.currentAnalysisFolder filesep methodName '.mat']; - end - end - - %% batchProcessData - function [outArgAll]=batchProcessData(obj,method,recNumbers,varargin) - - nOut=nargout; - nRec=numel(recNumbers); - - pMultiParam=cellfun(@(x) iscell(x),varargin(2:2:end)); - %check input validity - for i=find(pMultiParam) - if numel(varargin{i*2})~=nRec - disp(['Size of cell array args for arg: ' varargin{i*2-1} ' does not match the number of recordings']); - return; - end - end - - %change arguments with single value to cell arrays to fit the multi value arguments - if any(pMultiParam) - for i=find(~pMultiParam) - tmpCell=cell(1,nRec); - tmpCell=cellfun(@(x) varargin{i*2},tmpCell,'UniformOutput',0); - varargin{i*2}=tmpCell; - end - end - - fprintf(['Performing batch analysis on method ' method '\nAnalyzing recording number:']); - if obj.parPool4Batch & nRec>1 - parfor i=1:nRec - tmpObj=obj.setCurrentRecording(recNumbers(i)); - fprintf('%d ',recNumbers(i)); - if any(pMultiParam) - tmpVaragrin=cellfun(@(x) x{i},varargin(2:2:end),'UniformOutput',0); - newVarargin={}; - newVarargin(1:2:numel(varargin))=varargin(1:2:end); - newVarargin(2:2:numel(varargin))=tmpVaragrin; - if nOut>0 - [outArgs]=tmpObj.(method)(newVarargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(newVarargin{:}); - end - else - if nOut>0 - [outArgs]=tmpObj.(method)(varargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(varargin{:}); - end - end - %return all non object variables - end - else - for i=1:nRec - tmpObj=obj.setCurrentRecording(recNumbers(i)); - fprintf('%d ',recNumbers(i)); - if any(pMultiParam) - tmpVaragrin=cellfun(@(x) x{i},varargin(2:2:end),'UniformOutput',0); - newVarargin={}; - newVarargin(1:2:numel(varargin))=varargin(1:2:end); - newVarargin(2:2:numel(varargin))=tmpVaragrin; - if nOut>0 - [outArgs]=tmpObj.(method)(newVarargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(newVarargin{:}); - end - else - if nOut>0 - [outArgs]=tmpObj.(method)(varargin{:}); - outArgAll{i}=outArgs; - else - tmpObj.(method)(varargin{:}); - end - end - %return all non object variables - end - end - end - - %% getDigitalTriggers - function data=getDigitalTriggers(obj,varargin) - - parseObj = inputParser; - addParameter(parseObj,'saveFile',[]); - addParameter(parseObj,'inputParams',false,@isnumeric); - addParameter(parseObj,'overwrite',0,@isnumeric); - parseObj.parse(varargin{:}); - if parseObj.Results.inputParams - disp(parseObj.Results); - return; - end - - %evaluate all input parameters in workspace - for i=1:numel(parseObj.Parameters) - eval([parseObj.Parameters{i} '=' 'parseObj.Results.(parseObj.Parameters{i});']); - end - - obj.checkFileRecording; - - %check if analysis was already done done - if isempty(saveFile) - obj.files.digiTrig=[obj.currentAnalysisFolder filesep 'digiTrig.mat']; - else - obj.files.digiTrig=[saveFile '.mat']; - end - - if exist(obj.files.digiTrig,'file') & ~overwrite - if nargout==1 - data=load(obj.files.digiTrig); - else - disp('Triggers already exists for this recording'); - end - return; - end - - [tTrig,~,tTrig_string]=obj.currentDataObj.getTrigger; - save(obj.files.digiTrig,'tTrig','tTrig_string'); - end - - %% getExcelData - function [obj]=getExcelData(obj,excelRecordingDataFileName,additionalExcelFieldNames) - if nargin==1 - obj.excelRecordingDataFileName=obj.defaultXlsFile; - else - obj.excelRecordingDataFileName=excelRecordingDataFileName; - end - - %General rules for formatting excel files: - %1) All title names will be extracted as fields, except if they have a '#' as a first letter - %2) If an line does not contain data, it has to have 1 in the exclude colomn - %3) If a field has a - - - %get data from excel spread sheet - [excelNum,excelTxt,excelRaw] = xlsread(obj.excelRecordingDataFileName,obj.xlsSheet,'','basic'); %basic mode used for computers without installed excel - xlsFieldNames=excelTxt(obj.titleLine,:); - maxRow=size(excelTxt,1); - - %get all fields except the ones starting with # - obj.relevantFieldsXls=excelRaw(obj.titleLine,:); - pRelevantFields=cellfun(@(x) x(1)~='#',obj.relevantFieldsXls); - obj.relevantFieldsXls=obj.relevantFieldsXls(pRelevantFields); - - %remove rows that have the exclude field true - pExclude=find(strcmp(xlsFieldNames,'Exclude')); - nonExludedRows=(1:(maxRow-numel(obj.titleLine))); - if ~isempty(pExclude) - p2Remove=cellfun(@(x) x=='1',excelRaw(obj.titleLine+nonExludedRows,pExclude+obj.startCol-1)); - nonExludedRows(p2Remove)=[]; - end - - for i=1:numel(obj.relevantFieldsXls) - pFieldInExcel=find(strcmp(xlsFieldNames,obj.relevantFieldsXls{i})); - if ~isempty(pFieldInExcel) - obj.par.(obj.relevantFieldsXls{i})=excelRaw(obj.titleLine+nonExludedRows,pFieldInExcel+obj.startCol-1); - else - obj.par.(obj.relevantFieldsXls{i})=[]; - end - end - obj.nTotalRecordings=numel(obj.par.(obj.relevantFieldsXls{1})); - - if isunix - for i=1:numel(obj.par.folder) - obj.par.folder{i}=convertPath2LinuxMPIBR(obj.par.folder{i}); - end - end - disp(['Experiment data retrieved from: ' num2str(obj.excelRecordingDataFileName)]); - end - - %% setCurrentRecording - function [obj]=setCurrentRecording(obj,recName) %if recNumber is negative loads all recording related files but not recording object - if nargin==2 - selectedFields=regexp(recName,',','split'); - for i=1:numel(selectedFields) - selectedValues=regexp(selectedFields{i},'=','split'); - pRec(i,:)=cellfun(@(x) strcmp(num2str(x),selectedValues{2}),obj.par.(selectedValues{1})); - end - pRec=find(all(pRec==1,1)); - nRec=numel(pRec); - - if nRec>0 - %collect all files in case multiple files were inserted (comma separated) or group format and couple folder with file name - allFullFiles=[]; - for i=1:nRec, - if ~isempty(regexp(obj.par.MEAfiles{pRec(i)},'*')) %for cases in which the files are give as 'ctrl0*.mcd' - multipleFiles=dir([obj.par.folder{pRec(i)} filesep obj.par.MEAfiles{pRec(i)}]); - multipleFiles={multipleFiles.name}; - else - multipleFiles=regexp(obj.par.MEAfiles{pRec(i)},',','split'); - end - allFullFiles=[allFullFiles cellfun(@(x) [obj.par.folder{pRec(i)} filesep x],multipleFiles,'UniformOutput',0)]; - end - obj.currentMEAFiles=allFullFiles'; - - %check which data acquisition system was used - if strcmp(allFullFiles{1}(end-3:end),'.mcd') %MCRack recording - if ispc - obj.currentDataObj=MCRackRecording(obj.currentMEAFiles'); - elseif isunix - obj.currentDataObj=MCRackRecordingNeuroshare(obj.currentMEAFiles'); - end - elseif strcmp(allFullFiles{1}(end-3:end),'.rhd') %Intan recording - obj.currentDataObj=Intan(obj.currentMEAFiles); - elseif strcmp(allFullFiles{1}(end-3:end),'.kwd') %Intan recording - obj.currentDataObj=KwikRecording(obj.currentMEAFiles); - elseif isdir(allFullFiles{1}) %OE recording - obj.currentDataObj=OERecording(obj.currentMEAFiles); - else - error(['dataRecording class could not be determined from the file extension: ' num2str(allFullFiles{1}(end-3:end))]); - end - obj.gridSorterObj=[]; %clear any existing grid sorter object from the past - - %create data object - obj.currentRecName=recName; - obj.currentPRec=pRec; - - %define related folders and construct correspondin file names - obj.currentAnalysisFolder=[obj.par.folder{pRec(1)} filesep 'analysis' filesep recName]; - obj.currentPlotFolder=[obj.par.folder{pRec(1)} filesep 'plots' filesep recName]; - obj.currentExpFolder=obj.par.folder{pRec(1)}; - obj=obj.getFileNames; - - [stat,mess,messid]=mkdir(obj.currentAnalysisFolder); %creates analysis directory if not existing - [stat,mess,messid]=mkdir(obj.currentPlotFolder); %creates analysis directory if not existing - fprintf('Current exp. set to: %s-%s @ %s\n',obj.par.MEAfiles{pRec(1)},obj.par.MEAfiles{pRec(end)},obj.par.folder{pRec(1)}); - elseif numel(pRec)==0 - disp('Selected recording/s were not found in recording list'); - return; - end - - elseif nargin==1 - disp('Not enough inputs, specify a recording name or number'); - return; - end - end - - %% getFilters - function [obj]=getFilters(obj,Fs) - if nargin==1 - if isempty(obj.currentDataObj) - error('Sampling frequency is required as an input'); - else - Fs=obj.currentDataObj.samplingFrequency(1); - disp(['sampling frequency set to that of current recording:' num2str(Fs) '[Hz]']); - end - end - - obj.filt.F=filterData(Fs); - obj.filt.F.downSamplingFactor=Fs/250; - obj.filt.F=obj.filt.F.designDownSample; - obj.filt.F.padding=true; - obj.filt.FFs=obj.filt.F.filteredSamplingFrequency; - - obj.filt.DS4Hz=filterData(Fs); - obj.filt.DS4Hz.downSamplingFactor=Fs/250; - obj.filt.DS4Hz.lowPassCutoff=4; - obj.filt.DS4Hz.padding=true; - obj.filt.DS4Hz=obj.filt.DS4Hz.designDownSample; - - obj.filt.FH=filterData(Fs); - obj.filt.FH.highPassPassCutoff=100; - obj.filt.FH.highPassStopCutoff=80; - obj.filt.FH.lowPassPassCutoff=1800; - obj.filt.FH.lowPassStopCutoff=2000; - obj.filt.FH.attenuationInLowpass=20; - obj.filt.FH.attenuationInHighpass=20; - obj.filt.FH=obj.filt.FH.designBandPass; - obj.filt.FH.padding=true; - - obj.filt.FHR=filterData(Fs); - obj.filt.FHR.highPassPassCutoff=60; - obj.filt.FHR.highPassStopCutoff=50; - obj.filt.FHR.lowPassPassCutoff=900; - obj.filt.FHR.lowPassStopCutoff=1000; - obj.filt.FHR.attenuationInLowpass=20; - obj.filt.FHR.attenuationInHighpass=40; - obj.filt.FHR=obj.filt.FHR.designBandPass; - obj.filt.FHR.padding=true; - - obj.filt.FL=filterData(Fs); - obj.filt.FL.lowPassPassCutoff=4.5; - obj.filt.FL.lowPassStopCutoff=6; - obj.filt.FL.attenuationInLowpass=20; - obj.filt.FL=obj.filt.FL.designLowPass; - obj.filt.FL.padding=true; - - obj.filt.FH2=filterData(Fs); - obj.filt.FH2.highPassCutoff=100; - obj.filt.FH2.lowPassCutoff=2000; - obj.filt.FH2.filterDesign='butter'; - obj.filt.FH2=obj.filt.FH2.designBandPass; - obj.filt.FH2.padding=true; - end - - %% checkFile - check the existance of a data file and a recording object - function checkFileRecording(obj,fileName,message) - if isempty(obj.currentDataObj) - error('No data recording object selected!!!!'); - end - if nargin>1 - if ~exist(fileName,'file') - if nargin==2 - error('Relevant analysis file missing, please first run relevant function'); - else - error(message); - end - end - end - end - - end - -end \ No newline at end of file diff --git a/general functions/AverageSBE.m b/general functions/AverageSBE.m deleted file mode 100644 index 5115e6d..0000000 --- a/general functions/AverageSBE.m +++ /dev/null @@ -1,180 +0,0 @@ -function [meanSBE,stdSBE,shift,ShiftedSBEs]=AverageSBE(convM,Method) -%function [meanSBE,stdSBE,shift,ShiftedSBEs]=AverageSBE(convM,Method) -%calculate the average SBE from a given set of bursts (already convoluted) -%convM - the selected bursts convoluted matrix. -%convM(bursts,neurons,data_bins); -%ShiftedSBEs - The shifted bursts for the case of one neurons. -%Method='Plot' for plotting - -%21.2.10 - Mark - -if nargin<2 - Method='Non Plot'; -end - -[BurstNum, NeuronNum, BurstSize]=size(convM); -Bursts=zeros(BurstNum,BurstSize*(2*NeuronNum+1)); - -%build a matrix of 1-dimensional vectors of the bursts: -%put zeros between each neuron recording, and at bagining and ending of 1st and last neurons. -if NeuronNum==1 - Bursts=[zeros(BurstNum,BurstSize) squeeze(convM) zeros(BurstNum,BurstSize)]; -else - % [0 0 0 neuron1 0 0 0 neuron2 0 0 0...neuronN 0 0 0] - Bursts=[zeros(BurstSize,BurstNum);reshape(permute(cat(3,convM,zeros(BurstNum,NeuronNum,BurstSize)),[3 2 1]),NeuronNum*(BurstSize*2),BurstNum)]'; -end - - -%calculate the first approximation: -fprintf('Building initial approximated burst...'); -Burst1=Bursts(1,:); -shift=zeros(1,BurstNum); %vector of shifts of each burst from 1st burst. -Group=Bursts; -step=0; -while size(Group,1)>1, - step=step+1; - for i=1:2:size(Group,1), - if i+1<=size(Group,1), - Burst1=Group(i,:); - Burst2=Group(i+1,:); - nanVals=isnan(Burst1);Burst1(nanVals)=mean(Burst1(~nanVals));nanVals=isnan(Burst2);Burst2(nanVals)=mean(Burst2(~nanVals)); %Verify that there are no NaNs - [XCF, Lags, Bounds] = crosscorr(Burst1, Burst2, BurstSize-1); - %[XCF,Lags]=xcorr(Burst1, Burst2,BurstSize,'coeff') ; - [MaxCrossCorrValue,MaxValueLocation]=max(XCF); - for j=1:2^(step-1), - if (2^(step-1)*i+j)<=BurstNum, - shift(2^(step-1)*i+j)=shift(2^(step-1)*i+j)+Lags(MaxValueLocation); - end - end - %Burst1=Burst1(BurstSize+1:end-BurstSize) + Burst2(BurstSize+Lags(MaxValueLocation)+1:end-BurstSize+Lags(MaxValueLocation)); - if Lags(MaxValueLocation)>0, - Burst1(1:end-Lags(MaxValueLocation))=Burst1(1:end-Lags(MaxValueLocation))+Burst2(Lags(MaxValueLocation)+1:end); - else - Burst1(1-Lags(MaxValueLocation):end)=Burst1(1-Lags(MaxValueLocation):end)+Burst2(1:end+Lags(MaxValueLocation)); - end - %replace burst in summed bursts: - Group(i,:)=Burst1; - end - end - Group(2:2:end,:,:)=[]; -end -Burst1=squeeze(Group(1,:,:)); - - - -%iterate for higher approximations. this is because the first bursts were -%positioned in a more robust manner. -ChangedLocations=ones(1,BurstNum); %when all zeros - then bursts are not changed in relative postion. -iteration=1; -fprintf('\nIterating (percent of correct positioned bursts): '); -while (iteration<=40 & sum(ChangedLocations)>0) - fprintf('%d , ' , 100-round(sum(ChangedLocations)/BurstNum*100)); - for i=1:BurstNum, - Burst2=Bursts(i,:); - %remove the burst that is to be rechecked: - if shift(i)>=0, - Burst1(1:end-shift(i))=Burst1(1:end-shift(i))-Burst2(shift(i)+1:end); - else - Burst1(1-shift(i):end)=Burst1(1-shift(i):end)-Burst2(1:end+shift(i)); - end - nanVals=isnan(Burst1);Burst1(nanVals)=mean(Burst1(~nanVals));nanVals=isnan(Burst2);Burst2(nanVals)=mean(Burst2(~nanVals)); %Verify that there are no NaNs - %cross-correlate the two vectors: - [XCF, Lags, Bounds] = crosscorr(Burst1, Burst2, BurstSize-1); - %[XCF,Lags]=xcorr(Burst1, Burst2,BurstSize,'coeff') ; - %find the location of the max value in burst: - [MaxCrossCorrValue,MaxValueLocation]=max(XCF); - if Lags(MaxValueLocation)==shift(i), - ChangedLocations(i)=0; - else, - ChangedLocations(i)=1; - shift(i)=Lags(MaxValueLocation); - end - %calculate the mean burst from tht two shifted vectors: - if shift(i)>0, - Burst1(1:end-shift(i))=Burst1(1:end-shift(i)) + Burst2(shift(i)+1:end); - else - Burst1(1-shift(i):end)=Burst1(1-shift(i):end) + Burst2(1:end+shift(i)); - end - - %build the new burst for next iteration: - % Burst1=[zeros(1,BurstSize),Burst1,zeros(1,BurstSize)]; - end - iteration=iteration+1; -end -fprintf('\ndone!\n'); - -%plot the mean and std bursts: -[meanSBE,stdSBE,ShiftedSBEs]=StdSBE(convM,shift,Method); - -function [meanSBE,stdSBE,ShiftedSBEs]=StdSBE(convM,shift,Method); -%function [meanSBE,stdSBE]=StdSBE(convM,shift); -%calculates the mean and std of burst according to shift as calculated in -%AverageSBE -%convM - the selected bursts convoluted matrix. -%convM(bursts,neurons,data_bins); -%shift - the shift in bins of each burst relative to the mean -%ShiftedSBEs - The shifted bursts for the case of one neurons. - -%04.5.09 - Mark: based on AverageSBE; - -[BurstNum, NeuronNum, BurstSize]=size(convM); - -%build a matrix of 1-dimensional vectors of the bursts: -%put zeros between each neuron recording, and at bagining and ending of 1st and last neurons. -if NeuronNum==1 - for i=1:BurstNum, - Bursts(i,:)=[zeros(1,BurstSize) squeeze(convM(i,:,:))' zeros(1,BurstSize)]; - end -else - for i=1:BurstNum, - Bursts(i,:)=[zeros(1,BurstSize), reshape([squeeze(convM(i,:,:)) , zeros(NeuronNum,BurstSize)]',1,NeuronNum*(BurstSize*2))]; - end % [0 0 0 neuron1 0 0 0 neuron2 0 0 0...neuronN 0 0 0] -end - -%build a matrix of the shifted bursts: -ShiftedBursts=zeros(size(Bursts)); -for i=1:BurstNum, - ShiftedBursts(i,(BurstSize+2):(end-BurstSize-shift(i)+1))=Bursts(i,(BurstSize+shift(i)+1):(end-BurstSize)); -end -Burst1=mean(ShiftedBursts); -Std1=std(ShiftedBursts); -%Burst1=Burst1/BurstNum; - -if NeuronNum==1 - ShiftedSBEs=ShiftedBursts(:,BurstSize+1:BurstSize+BurstSize); -else - for j=1:NeuronNum - ShiftedSBEs(:,j,:)=ShiftedBursts(:,BurstSize*(j*2-1)+1:BurstSize*(j*2-1)+BurstSize); - end -end - -%reshape the final burst back to matrix format: -for i=1:NeuronNum, - meanSBE(i,:)=Burst1(BurstSize*(2*i-1)+1:BurstSize*(2*i-1)+BurstSize); - stdSBE(i,:)=Std1(BurstSize*(2*i-1)+1:BurstSize*(2*i-1)+BurstSize); -end - -if strcmp(Method,'Plot') - %plot the mean burst: - figure; - for i=1:NeuronNum, - hold on; - plot(meanSBE(NeuronNum-i+1,:)+i-1); - end - hold off; - - %plot mean with (+) and (-) std of burst: - figure; - ZeroVec=zeros(1,length(meanSBE)); - P=2.0; - for i=1:NeuronNum, - hold on; - plot(1:length(meanSBE),ZeroVec+i-1,'k--'); - plot(meanSBE(NeuronNum-i+1,:)/P+stdSBE(NeuronNum-i+1,:)/P+i-1,'r'); - plot(meanSBE(NeuronNum-i+1,:)/P-stdSBE(NeuronNum-i+1,:)/P+i-1,'r'); - plot(meanSBE(NeuronNum-i+1,:)/P+i-1,'b'); - end - hold off; - -end - diff --git a/general functions/AverageSN2.c b/general functions/AverageSN2.c deleted file mode 100644 index c373d74..0000000 --- a/general functions/AverageSN2.c +++ /dev/null @@ -1,187 +0,0 @@ -/*[Avg,Std,IsNoise]=AverageSN(Signal,N,Nb,C) -Calculates a moving average -N must be an odd number -*/ - -#include -#include -#include -#include "mex.h" -#include "matrix.h" - - -/*a function that Calculates the moving average*/ -void CalcMovingAverage(double *Signal, double *N, double *Nb, double *C, double *IsNoise, double *Noise, double *STDNoise, long int length) -{ - //Definition and initiation of variables - int i=0; - int j=0; - int index=0; - int index2=1; - int mBufferSize=(int)N[0]+1; //Mistake in analyzer-For historical reasons N in the analyzer is defined one less than normal - int mExtendedBufferSize=(int)Nb[0]; - int mOutLinesCounter=0; - double avg=0.0; - double mAverage=0.0; - double mPrevStdDev=0.0; - double mStdDiv=0.0; - double mSum=0.0; - double mSqrSum=0.0; - double mLimit=0.0; - double mPrevLimit=0.0; - double num; - double *mBuffer; - bool *mBufferNoise; - bool isCurrentRowNoise; - - //Allocations in memory - mBuffer = mxMalloc(mBufferSize*sizeof(double)); - mBufferNoise = mxMalloc(mBufferSize*sizeof(bool)); - - //Intitiaion of arrays - for (j=0;j=0) - { - Noise[i-(mBufferSize-1)/2]=avg; - STDNoise[i-(mBufferSize-1)/2]=mPrevStdDev; - } - IsNoise[i]=1; - continue; - } - else - { - avg = mAverage; - - index=i%(mBufferSize); - index2=(i+1)%(mBufferSize); - - mStdDiv = mPrevStdDev; - - isCurrentRowNoise = Signal[i]mExtendedBufferSize) - { - //mexPrintf("\nReset in line: %d",i); - mOutLinesCounter=0; - mSqrSum = 0; - mSum = 0; - - mBufferNoise[(i - 0 + 1)%(mBufferSize)]=true; //To compensate the for reset noise raws - - for(j=1;j(length-mBufferSize)) //temporal patch to fix the right boundry of the signal - { - Noise[i]=avg; - STDNoise[i]=mPrevStdDev; - } - continue; - } - } - mxFree(mBuffer); - mxFree(mBufferNoise); -} - - - - -/********************************************************************************************/ -/*This function defines the incoming and outgoing matlab variables - and sets pointers to the begining of each one. Then calls to the - function that makes the new SBEmatrix and to the correlation calculation - (the in comming array must me all in the same unit)*/ - -void mexFunction( int nlhs, mxArray *plhs[], - int nrhs, const mxArray *prhs[] ) -{ - double *N, *Nb, *C, *Signal; - long int length=0; - double *STDNoise=NULL,*Noise=NULL,*IsNoise=NULL; - -/*getting pointers and dimensions of the index matrix and the times - vector*/ - - if (nrhs!=4) - { - mexPrintf("\nThe number of variables entered is: %d\n",nrhs); - mexErrMsgTxt("The correct format is:\n[Avg,Std]=AverageSN(Signal,N,Nb,C)\n"); - } - - Signal = mxGetPr(prhs[0]); //Signal - N = mxGetPr(prhs[1]); //Size of average window - Nb = mxGetPr(prhs[2]); //Number of allowed unnoisy signals in window - C = mxGetPr(prhs[3]); //Bias - length = (long int)mxGetDimensions(prhs[0])[1]; //Signal's length - if (length==1) - length = (long int)mxGetDimensions(prhs[0])[0]; - - /* Set the output pointers :*/ - plhs[0] = mxCreateDoubleMatrix(1, length, mxREAL); - plhs[1] = mxCreateDoubleMatrix(1, length, mxREAL); - plhs[2] = mxCreateDoubleMatrix(1, length, mxREAL); - Noise=mxGetPr(plhs[0]); - STDNoise=mxGetPr(plhs[1]); - IsNoise=mxGetPr(plhs[2]); - - CalcMovingAverage(Signal, N, Nb, C, IsNoise, Noise, STDNoise,length); - //mexPrintf("\nFinished Successfully\n"); -} diff --git a/general functions/AverageSN2.mexa64 b/general functions/AverageSN2.mexa64 deleted file mode 100755 index af29a6e..0000000 Binary files a/general functions/AverageSN2.mexa64 and /dev/null differ diff --git a/general functions/AverageSN2.mexw64 b/general functions/AverageSN2.mexw64 deleted file mode 100644 index 2614669..0000000 Binary files a/general functions/AverageSN2.mexw64 and /dev/null differ diff --git a/general functions/BuildBurstMatrix.c b/general functions/BuildBurstMatrix.c deleted file mode 100644 index fb15553..0000000 --- a/general functions/BuildBurstMatrix.c +++ /dev/null @@ -1,154 +0,0 @@ -/*[M]=BuildBurstMatrix(indexChchannel,t,Bind(first:last),width,class); - * t and Bind must be rounded. - * a function that returns a matrix of selected bursts. - * compile function using: mex -largeArrayDims BuildBurstMatrix.c; - */ - -#include -#include -#include -#include "mex.h" -#include "matrix.h" - -/********************************************************************************************/ -/*This function defines the incoming and outgoing matlab variables - * and sets pointers to the begining of each one. Then calls to the - * function that makes the new SBEmatrix and to the correlation calculation - * (the in comming array must me all in the same unit)*/ - -void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) -{ - double *indexCh, *times, *tTrial; - long int width; - int matClass; - mwSize i, rowIdx, nNeurons, nTrials, nSpikes, trial, neu, t, ndims[3]; - - /*Define pointers to go over array of different classes*/ - uint8_T *Muint8; - double *Mdouble; - mxLogical *Mlogical; - - /*check if format is correct-help*/ - if ((nrhs<4) | (nrhs>5)) - { - mexPrintf("\nThe number of variables entered is: %d\n",nrhs); - mexErrMsgTxt("The correct execution format is:\n[M]=BuildBurstMatrix(indexChchannel,t,startTimes,width,class);\nM is a matrix of size trials x Neurons x width\nBurst window is from [startTimes(i) , startTimes(i)+width]\nWhere all variables are ROUNDED and given in the same units\nClass is the variable class (optional): 1='uint8',2='double',3='logical' (Default 2))"); - } - - /* get input variables and their sizes */ - indexCh = mxGetPr(prhs[0]); /*indexChchannel (4x number of neurons)*/ - times = mxGetPr(prhs[1]); /*t - spikes timings*/ - tTrial = mxGetPr(prhs[2]); /*time of beginnings of trials - same units as times*/ - width = (long int)mxGetScalar(prhs[3]); /* width of burst window - same units as times - totla burst window is [tTrial, tTrial+window]*/ - - rowIdx = (mwSize)mxGetM(prhs[0]); /* =4 - return number of rows in array*/ - nNeurons = (mwSize)mxGetN(prhs[0]); /* number of neurions - return number of columns in array.*/ - nSpikes = (mwSize)mxGetN(prhs[1]); /* total number of spikes*/ - nTrials = (mwSize)mxGetN(prhs[2]); /* total number of bursts*/ - - /*Checks that the window width is positive*/ - if (!(width>0)) - { - mexErrMsgTxt("\nThe chosen window is not a positive integer\n"); - } - - /*check that input variables are integers*/ - for (i=0;i=(tTrial[trial])) ) - Muint8[trial+(neu)*nTrials+(((mwSize)times[t])-((mwSize)tTrial[trial]))*nTrials*nNeurons]++; - } - } - } - } - else if (matClass==2) - { - plhs[0] = mxCreateNumericArray(3,ndims,mxDOUBLE_CLASS,mxREAL); - Mdouble = mxGetPr(plhs[0]); - /*mexPrintf("\nDouble class used for output\n");*/ - - for (neu=0;neu=(tTrial[trial])) ) - Mdouble[trial+(neu)*nTrials+(((mwSize)times[t])-((mwSize)tTrial[trial]))*nTrials*nNeurons]++; - } - } - } - - } - else if (matClass==3) - { - plhs[0] = mxCreateLogicalArray(3,ndims); - Mlogical = mxGetPr(plhs[0]); - - for (neu=0;neu=(tTrial[trial])) ) - Mlogical[trial+(neu)*nTrials+(((mwSize)times[t])-((mwSize)tTrial[trial]))*nTrials*nNeurons]=1; - } - } - } - } - - - /*for (i=0;i<(nTrials-1+(nNeurons-1)*nTrials+(width-1)*nTrials*nNeurons);i++) - * M[i]=0;*/ - -} diff --git a/general functions/BuildBurstMatrix.mexa64 b/general functions/BuildBurstMatrix.mexa64 deleted file mode 100755 index c3fd373..0000000 Binary files a/general functions/BuildBurstMatrix.mexa64 and /dev/null differ diff --git a/general functions/BuildBurstMatrix.mexw64 b/general functions/BuildBurstMatrix.mexw64 deleted file mode 100644 index 61ee974..0000000 Binary files a/general functions/BuildBurstMatrix.mexw64 and /dev/null differ diff --git a/general functions/BuildBurstMatrixA.c b/general functions/BuildBurstMatrixA.c deleted file mode 100644 index e349ba7..0000000 --- a/general functions/BuildBurstMatrixA.c +++ /dev/null @@ -1,99 +0,0 @@ -/*[M]=BuildBurstMatrix(indexChchannel,t,Bind(first:last),width); - * t and Bind must be rounded. - * a function that returns a matrix of selected bursts. - * compile function using: mex -largeArrayDims BuildBurstMatrix.c; - */ - -#include -#include -#include -#include "mex.h" -#include "matrix.h" - -/********************************************************************************************/ -/*This function defines the incoming and outgoing matlab variables - * and sets pointers to the begining of each one. Then calls to the - * function that makes the new SBEmatrix and to the correlation calculation - * (the in comming array must me all in the same unit)*/ - -void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) -{ - double *indexCh, *times, *tTrial, *intensities; - double width; - mwSize i, rowIdx, nNeurons, nTrials, nSpikes, trial, neu, t, ndims[3]; - - /*Define pointers to go over array of different classes*/ - uint8_T *Muint8; - double *Mdouble; - mxLogical *Mlogical; - - /*check if format is correct-help*/ - if (nrhs!=5) - { - mexPrintf("\nThe number of variables entered is: %d\n",nrhs); - mexErrMsgTxt("The correct execution format is:\n[M]=BuildBurstMatrixA(ic,t,I,Bind,width,class);\nM is a matrix of size Bind x Neurons x width\nBurst window is from [Bind(i) , Bind(i)+width]\nWhere all variables are ROUNDED and given in the same units\n"); - } - - /* get input variables and their sizes */ - indexCh = mxGetPr(prhs[0]); /*indexChchannel (4x number of neurons)*/ - times = mxGetPr(prhs[1]); /*t - spikes timings*/ - intensities = mxGetPr(prhs[2]); /* I - the intensities in times t*/ - tTrial = mxGetPr(prhs[3]); /*time of beginnings of trials - same units as times*/ - width = (mwSize)mxGetScalar(prhs[4]); /* width of burst window - same units as times - totla burst window is [tTrial, tTrial+window]*/ - - - rowIdx = (mwSize)mxGetM(prhs[0]); /* =4 - return number of rows in array*/ - nNeurons = (mwSize)mxGetN(prhs[0]); /* number of neurions - return number of columns in array.*/ - nSpikes = (mwSize)mxGetN(prhs[1]); /* total number of spikes*/ - nTrials = (mwSize)mxGetN(prhs[3]); /* total number of bursts*/ - - /*check that input variables are integers*/ - for (i=0;i=(tTrial[trial])) ) - Mdouble[trial+(neu)*nTrials+(((mwSize)times[t])-((mwSize)tTrial[trial]))*nTrials*nNeurons] += intensities[t]; - } - } - } - -} diff --git a/general functions/BuildBurstMatrixA.mexa64 b/general functions/BuildBurstMatrixA.mexa64 deleted file mode 100755 index c259197..0000000 Binary files a/general functions/BuildBurstMatrixA.mexa64 and /dev/null differ diff --git a/general functions/BuildBurstMatrixBak.mexa64 b/general functions/BuildBurstMatrixBak.mexa64 deleted file mode 100644 index 001c89f..0000000 Binary files a/general functions/BuildBurstMatrixBak.mexa64 and /dev/null differ diff --git a/general functions/BuildBurstMatrixBak.mexw64 b/general functions/BuildBurstMatrixBak.mexw64 deleted file mode 100644 index da44a35..0000000 Binary files a/general functions/BuildBurstMatrixBak.mexw64 and /dev/null differ diff --git a/general functions/BuildBurstMatrixFirstSpike.c b/general functions/BuildBurstMatrixFirstSpike.c deleted file mode 100644 index b1240cb..0000000 --- a/general functions/BuildBurstMatrixFirstSpike.c +++ /dev/null @@ -1,162 +0,0 @@ -/*[M]=BuildBurstMatrixFirstSpike(indexChchannel,t,Bind(first:last),width,class); - * t and Bind must be rounded. - * a function that returns a matrix of selected bursts. - * compile function using: mex -largeArrayDims BuildBurstMatrixFirstSpike.c; - */ - -#include -#include -#include -#include "mex.h" -#include "matrix.h" - -/********************************************************************************************/ -/*This function defines the incoming and outgoing matlab variables - * and sets pointers to the begining of each one. Then calls to the - * function that makes the new SBEmatrix and to the correlation calculation - * (the in comming array must me all in the same unit)*/ - -void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) -{ - double *indexCh, *times, *tTrial; - double width; - int matClass; - mwSize i, rowIdx, nNeurons, nTrials, nSpikes, trial, neu, t, ndims[3]; - - /*Define pointers to go over array of different classes*/ - uint8_T *Muint8; - double *Mdouble; - mxLogical *Mlogical; - - /*check if format is correct-help*/ - if ((nrhs<4) | (nrhs>5)) - { - mexPrintf("\nThe number of variables entered is: %d\n",nrhs); - mexErrMsgTxt("The correct execution format is:\n[M]=BuildBurstMatrix(indexChchannel,t,startTimes,width,class);\nM is a matrix of size trials x Neurons x width\nBurst window is from [startTimes(i) , startTimes(i)+width]\nWhere all variables are ROUNDED and given in the same units\nClass is the variable class (optional): 1='uint8',2='double',3='logical' (Default 2))"); - } - - /* get input variables and their sizes */ - indexCh = mxGetPr(prhs[0]); /*indexChchannel (4x number of neurons)*/ - times = mxGetPr(prhs[1]); /*t - spikes timings*/ - tTrial = mxGetPr(prhs[2]); /*time of beginnings of trials - same units as times*/ - width = (mwSize)mxGetScalar(prhs[3]); /* width of burst window - same units as times - totla burst window is [tTrial, tTrial+window]*/ - - /* get input variables and their sizes */ - rowIdx = (mwSize)mxGetM(prhs[0]); /* =4 - return number of rows in array*/ - nNeurons = (mwSize)mxGetN(prhs[0]); /* number of neurions - return number of columns in array.*/ - nSpikes = (mwSize)mxGetN(prhs[1]); /* total number of spikes*/ - nTrials = (mwSize)mxGetN(prhs[2]); /* total number of bursts*/ - - /*check that input variables are integers*/ - for (i=0;i=(tTrial[trial])) ) - { - Muint8[trial+(neu)*nTrials+(((mwSize)times[t])-((mwSize)tTrial[trial]))*nTrials*nNeurons]++; - break; - } - - } - } - } - } - else if (matClass==2) - { - plhs[0] = mxCreateNumericArray(3,ndims,mxDOUBLE_CLASS,mxREAL); - Mdouble = mxGetPr(plhs[0]); - /*mexPrintf("\nDouble class used for output\n");*/ - - for (neu=0;neu=(tTrial[trial])) ) - { - Mdouble[trial+(neu)*nTrials+(((mwSize)times[t])-((mwSize)tTrial[trial]))*nTrials*nNeurons]++; - break; - } - } - } - } - - } - else if (matClass==3) - { - plhs[0] = mxCreateLogicalArray(3,ndims); - Mlogical = mxGetPr(plhs[0]); - - for (neu=0;neu=(tTrial[trial])) ) - { - Mlogical[trial+(neu)*nTrials+(((mwSize)times[t])-((mwSize)tTrial[trial]))*nTrials*nNeurons]=1; - break; - } - } - } - } - } - - - /*for (i=0;i<(nTrials-1+(nNeurons-1)*nTrials+(width-1)*nTrials*nNeurons);i++) - * M[i]=0;*/ - -} diff --git a/general functions/BuildBurstMatrixFirstSpike.mexa64 b/general functions/BuildBurstMatrixFirstSpike.mexa64 deleted file mode 100755 index e562436..0000000 Binary files a/general functions/BuildBurstMatrixFirstSpike.mexa64 and /dev/null differ diff --git a/general functions/BuildBurstMatrixFirstSpike.mexw64 b/general functions/BuildBurstMatrixFirstSpike.mexw64 deleted file mode 100644 index ff927fa..0000000 Binary files a/general functions/BuildBurstMatrixFirstSpike.mexw64 and /dev/null differ diff --git a/general functions/BuildBurstMatrixOld.c b/general functions/BuildBurstMatrixOld.c deleted file mode 100644 index 99e1bf3..0000000 --- a/general functions/BuildBurstMatrixOld.c +++ /dev/null @@ -1,101 +0,0 @@ -/*[M]=BuildBurstMatrix(indexchannel,t,Bind(first:last),width); - t and Bind must be rounded. -a function that returns a matrix of selected bursts. - */ - -#include -#include -#include -#include "mex.h" -#include "matrix.h" - - -/*a function that builds the SBE matrix*/ -void MakeSBE (double *index, double *sbematrix, double *times, double *locaburst, -int neunum, long int ntimes, int nburst, double width) -{ - int t=0,currentburst,neu=0; - for (neu=0;neu=(locaburst[currentburst])) ) - sbematrix[currentburst+(neu)*nburst+(((long int)times[t])-((long int)locaburst[currentburst]))*nburst*neunum]++; - } - } - } -} - - - -/********************************************************************************************/ -/*This function defines the incoming and outgoing matlab variables - and sets pointers to the begining of each one. Then calls to the - function that makes the new SBEmatrix and to the correlation calculation - (the in comming array must me all in the same unit)*/ - -void mexFunction( int nlhs, mxArray *plhs[], -int nrhs, const mxArray *prhs[] ) -{ - double *index, *times, *locaburst, *sbeM; - double width; //burst window is from [time , time+width] - long int ntimes; - - int ndims[3], rowindex, neunum, nburst, i=0; - -/*the width is definded as half of the SBE*/ - -/*getting pointers and dimensions of the index matrix and the times - vector*/ - -//check if format is correct-help - if (nrhs!=4) - { - mexPrintf("\nThe number of variables entered is: %d\n",nrhs); - mexErrMsgTxt("The correct execution format is:\n[M]=BuildBurstMatrix(indexchannel,t,Bind,width);\nM is a matrix of size Bind x Neurons x width\nBurst window is from [Bind(i) , Bind(i)+width]\nWhere all variables are ROUNDED and given in the same units\n"); - } - - index = mxGetPr(prhs[0]); //indexchannel (4x number of neurons) - times = mxGetPr(prhs[1]); // t - spikes timings - locaburst = mxGetPr(prhs[2]); //location of beginning of burst window - same units as times - width = mxGetScalar(prhs[3]); // width of burst window - same units as times - totla burst window is [locaburst, locaburst+window] - - - rowindex = mxGetM(prhs[0]); // =4 - return number of rows in array - neunum = mxGetN(prhs[0]); // number of neurions - return number of columns in array. - ntimes = mxGetN(prhs[1]); // total number of spikes - nburst = mxGetN(prhs[2]); // total number of bursts - - //Checks that the input varibles are not empty matrices - if (neunum==0 | ntimes==0 | nburst==0) - { - mexErrMsgTxt("\nOne of the input variables is empty\n"); - } - -/*After convolution the vector size is bigger by the size of (the - response function(respns))-1)*/ - -/*defenition of a 3D matrix in dynamic memory*/ - - /*dimentions of burst matrixes: sbeM, ConvSbeM:*/ - ndims[0]=nburst; - ndims[1]=neunum; - ndims[2]=(int)width; - - /* Set the output pointers :*/ - plhs[0] = mxCreateNumericArray(3,ndims,mxDOUBLE_CLASS,mxREAL); //return burst matrix (sbeM) - sbeM=mxGetPr(plhs[0]); - for (i=0;i<(nburst-1+(neunum-1)*nburst+(width-1)*nburst*neunum);i++) - sbeM[i]=0; - - /* Error Messages */ - if (locaburst[0]<0) mexWarnMsgTxt("Burst location starts from a negative value\n"); - - //build SBE matrix: - MakeSBE (index, sbeM, times, locaburst, neunum, ntimes, nburst, width); -} diff --git a/general functions/BuildBurstMatrixOld.mexa64 b/general functions/BuildBurstMatrixOld.mexa64 deleted file mode 100755 index e6a772c..0000000 Binary files a/general functions/BuildBurstMatrixOld.mexa64 and /dev/null differ diff --git a/general functions/BuildBurstMatrixOld.mexw64 b/general functions/BuildBurstMatrixOld.mexw64 deleted file mode 100644 index 04c3065..0000000 Binary files a/general functions/BuildBurstMatrixOld.mexw64 and /dev/null differ diff --git a/general functions/BuildBurstMatrixOneSpikePerBin.c b/general functions/BuildBurstMatrixOneSpikePerBin.c deleted file mode 100644 index 76ec014..0000000 --- a/general functions/BuildBurstMatrixOneSpikePerBin.c +++ /dev/null @@ -1,122 +0,0 @@ -/*[M]=BuildBurstMatrix(indexchannel,t,Bind(first:last),width); -a function that returns a matrix of selected bursts. -*/ - -#include -#include -#include -#include "mex.h" -#include "matrix.h" - - -/*a function that builds the SBE matrix*/ -void MakeSBE (double *index, double ***sbematrix, double *times, double *locaberst, - int neunum, long int ntimes, int nberst, double width) -{ - int t=0,currentberst,neu=0; - for (neu=0;neu=(locaberst[currentberst])) ) - //add +1 in SBE matrix: - sbematrix[currentberst][neu][((long int)times[t])-((long int)locaberst[currentberst])]=1; - } - } - } -} - - - -/********************************************************************************************/ -/*This function defines the incoming and outgoing matlab variables - and sets pointers to the begining of each one. Then calls to the - function that makes the new SBEmatrix and to the correlation calculation - (the in comming array must me all in the same unit)*/ - -void mexFunction( int nlhs, mxArray *plhs[], - int nrhs, const mxArray *prhs[] ) -{ - double *index, *times, *locaberst, *sbeM; - double ***sbematrix; - - double *corrmat=NULL; - double width; //burst window is from [time , time+width] - long int ntimes; - - int rowindex, neunum, nberst, i=0, j=0, k=0; - -int ndims[3]; - -/*the width is definded as half of the SBE*/ - -/*getting pointers and dimensions of the index matrix and the times - vector*/ - - index = mxGetPr(prhs[0]); //indexchannel (4x number of neurons) - times = mxGetPr(prhs[1]); // t - spikes timings - locaberst = mxGetPr(prhs[2]); //location of beginning of burst window - same units as times - width = mxGetScalar(prhs[3]); // width of burst window - same units as times - totla burst window is [locaburst, locaburst+window] - - rowindex = mxGetM(prhs[0]); // =4 - return number of rows in array - neunum = mxGetN(prhs[0]); // number of neurions - return number of columns in array. - ntimes = mxGetN(prhs[1]); // total number of spikes - nberst = mxGetN(prhs[2]); // total number of bursts - -/*After convolution the vector size is bigger by the size of (the - response function(respns))-1)*/ - -/*defenition of a 3D matrix in dynamic memory*/ - -//put zeros in SBE matrix: - sbematrix = (double***)mxMalloc(sizeof(double**)*nberst); - for (i=0;itimes[ntimes-1]) printf("Error 1 : berst location exceeds recorded data\n"); - if (locaberst[0]<0) printf("Error 2 : Berst location starts from a negative value\n"); - -//build SBE matrix: - MakeSBE (index, sbematrix, times, locaberst, neunum, ntimes, nberst, width); - // copy burst matrix to returned pointer: - for (i=0;i -#include -#include -#include "mex.h" - - -/* Function calculates the mean value of a string*/ - -double mean(double str[],int n) -{ - int i; - double sum=0; - - for (i=0;i(nrespns-2)&&i<(ndata+nrespns-1)) - { - dataplus[i]=data[i-nrespns+1]; - } - else - { - dataplus[i]=0; - } - } - - /* Calculating convolution*/ - - for (i=0;i<(nrespns+ndata-1);i++) - { - for (j=0;jmax) - { - max=meancorr[i]; - } - } - return max; -} - - - - -/***************************************************************************************************************/ -/*This is the core function. it calculates the time invariat cross corelation function - for each element of the correlation martix (corrmat)*/ - -//void CalcCorr (double ***sbematrix, double *corrmat,double *gaussian, -// int neunum, int nberst,int width, int newidth, int gaussize) -void CalcCorr (double ***sbematrix, double *corrmat, int neunum, int nberst,int width) -{ - int i=0,j=0,sbe1=0,sbe2=0,neu=0,activeneu=0,count=0,k=0; - double maxcorrvalue; - double *meancorr,*tempcorr,*convec; - - meancorr = (double*)mxMalloc(sizeof(double)*(2*width-1)); - tempcorr = (double*)mxMalloc(sizeof(double)*(2*width-1)); - convec = (double*)mxMalloc(sizeof(double)*(width)); - - -/*Makes the correlation matrix by adding the cross correlations of every two neurons in an SBE - and fininding the maximum value, the first loop is for the diagonal elements which are always 1*/ - - for (sbe1=0;sbe11 - error('The input kernel is not one dimensional'); -end -if (nargin < 3) - shape = 'full'; -end - -%Initialize output variable -[NBursts NNeurons Width]=size(M); -NKern=size(kern,2); -if (strcmp(shape,'same')) - MC=zeros(NBursts,NNeurons,Width); -elseif (strcmp(shape,'full')) - MC=zeros(NBursts,NNeurons,Width+NKern-1); -else - error('The only supported shapes are ''full'' and ''same'''); -end - -%Calculate convolution -for i=1:NBursts - MC(i,:,:)=convn(squeeze(M(i,:,:)),kern,shape); -end \ No newline at end of file diff --git a/general functions/StdSBE.m b/general functions/StdSBE.m deleted file mode 100644 index af0d50b..0000000 --- a/general functions/StdSBE.m +++ /dev/null @@ -1,61 +0,0 @@ -function [meanSBE,stdSBE,ShiftedBursts]=StdSBE(convM,shift); -%function [meanSBE,stdSBE]=StdSBE(convM,shift); -%calculates the mean and std of burst according to shift as calculated in -%AverageSBE -%convM - the selected bursts convoluted matrix. -%convM(bursts,neurons,data_bins); -%shift - the shift in bins of each burst relative to the mean -%The shifted bursts for the case of one neurons. - -%04.5.09 - Mark: based on AverageSBE; - -[BurstNum, NeuronNum, BurstSize]=size(convM); - -%build a matrix of 1-dimensional vectors of the bursts: -%put zeros between each neuron recording, and at bagining and ending of 1st and last neurons. -if NeuronNum==1 - for i=1:BurstNum, - Bursts(i,:)=[zeros(1,BurstSize) squeeze(convM(i,:,:))' zeros(1,BurstSize)]; - end -else - for i=1:BurstNum, - Bursts(i,:)=[zeros(1,BurstSize), reshape([squeeze(convM(i,:,:),1) , zeros(NeuronNum,BurstSize)]',1,NeuronNum*(BurstSize*2))]; - end % [0 0 0 neuron1 0 0 0 neuron2 0 0 0...neuronN 0 0 0] -end - -%build a matrix of the shifted bursts: -ShiftedBursts=zeros(size(Bursts)); -for i=1:BurstNum, - ShiftedBursts(i,(BurstSize+2):(end-BurstSize-shift(i)+1))=Bursts(i,(BurstSize+shift(i)+1):(end-BurstSize)); -end -Burst1=mean(ShiftedBursts); -Std1=std(ShiftedBursts); -%Burst1=Burst1/BurstNum; - -%reshape the final burst back to matrix format: -for i=1:NeuronNum, - meanSBE(i,:)=Burst1(BurstSize*(2*i-1)+1:BurstSize*(2*i-1)+BurstSize); - stdSBE(i,:)=Std1(BurstSize*(2*i-1)+1:BurstSize*(2*i-1)+BurstSize); -end - -%plot the mean burst: -figure; -for i=1:NeuronNum, - hold on; - plot(meanSBE(NeuronNum-i+1,:)+i-1); -end -hold off; - -%plot mean with (+) and (-) std of burst: -figure; -ZeroVec=zeros(1,length(meanSBE)); -P=2.0; -for i=1:NeuronNum, - hold on; - plot(1:length(meanSBE),ZeroVec+i-1,'k--'); - plot(meanSBE(NeuronNum-i+1,:)/P+stdSBE(NeuronNum-i+1,:)/P+i-1,'r'); - plot(meanSBE(NeuronNum-i+1,:)/P-stdSBE(NeuronNum-i+1,:)/P+i-1,'r'); - plot(meanSBE(NeuronNum-i+1,:)/P+i-1,'b'); -end -hold off; - diff --git a/general functions/StimCrossCorr.c b/general functions/StimCrossCorr.c deleted file mode 100644 index 87b8cfb..0000000 --- a/general functions/StimCrossCorr.c +++ /dev/null @@ -1,252 +0,0 @@ -/*function to calculate the correlation of a convoluted burst matrix: - *function not working -should be checked! - *compile function using: mex -largeArrayDims StimCrossCorr.c; -[R]=StimCrossCorr(convM);*/ - -#include -#include -#include -#include "mex.h" - - -/* Function calculates the mean value of a string*/ - -double mean(double str[],int n) -{ - int i; - double sum=0; - - for (i=0;imax) - { - max=meancorr[i]; - } - } - return max; -} - - - - -/***************************************************************************************************************/ -/*This is the core function. it calculates the time invariat cross corelation function - for each element of the correlation martix (corrmat)*/ - -//void CalcCorr (double ***sbematrix, double *corrmat,double *gaussian, -// int neunum, int nburst,int width, int newidth, int gaussize) -void CalcCorr (double ***sbematrix, double *corrmat, int neunum, int nburst,int width) -{ - int i=0,j=0,sbe1=0,sbe2=0,neu=0,activeneu=0,count=0,k=0; - double maxcorrvalue; - double *meancorr,*tempcorr,*convec; - - meancorr = (double*)mxMalloc(sizeof(double)*(2*width-1)); - tempcorr = (double*)mxMalloc(sizeof(double)*(2*width-1)); - convec = (double*)mxMalloc(sizeof(double)*(width)); - - -/*Makes the correlation matrix by adding the cross correlations of every two neurons in an SBE - and fininding the maximum value, the first loop is for the diagonal elements which are always 1*/ - - for (sbe1=0;sbe11, - step=step+1; - for i=1:2:size(Group,1), - if i+1<=size(Group,1), - Burst1=Group(i,:); - Burst2=Group(i+1,:); - nanVals=isnan(Burst1);Burst1(nanVals)=mean(Burst1(~nanVals));nanVals=isnan(Burst2);Burst2(nanVals)=mean(Burst2(~nanVals)); %Verify that there are no NaNs - [XCF, Lags, Bounds] = crosscorr2(Burst1, Burst2, BurstSize-1); - %[XCF,Lags]=xcorr(Burst1, Burst2,BurstSize,'coeff') ; - [MaxCrossCorrValue,MaxValueLocation]=max(XCF); - for j=1:2^(step-1), - if (2^(step-1)*i+j)<=BurstNum, - shift(2^(step-1)*i+j)=shift(2^(step-1)*i+j)+Lags(MaxValueLocation); - end - end - %Burst1=Burst1(BurstSize+1:end-BurstSize) + Burst2(BurstSize+Lags(MaxValueLocation)+1:end-BurstSize+Lags(MaxValueLocation)); - if Lags(MaxValueLocation)>0, - Burst1(1:end-Lags(MaxValueLocation))=Burst1(1:end-Lags(MaxValueLocation))+Burst2(Lags(MaxValueLocation)+1:end); - else - Burst1(1-Lags(MaxValueLocation):end)=Burst1(1-Lags(MaxValueLocation):end)+Burst2(1:end+Lags(MaxValueLocation)); - end - %replace burst in summed bursts: - Group(i,:)=Burst1; - end - end - Group(2:2:end,:,:)=[]; -end -Burst1=squeeze(Group(1,:,:)); - - - -%iterate for higher approximations. this is because the first bursts were -%positioned in a more robust manner. -ChangedLocations=ones(1,BurstNum); %when all zeros - then bursts are not changed in relative postion. -iteration=1; -fprintf('\nIterating (percent of correct positioned bursts): '); -while (iteration<=40 & sum(ChangedLocations)>0) - fprintf('%d , ' , 100-round(sum(ChangedLocations)/BurstNum*100)); - for i=1:BurstNum, - Burst2=Bursts(i,:); - %remove the burst that is to be rechecked: - if shift(i)>=0, - Burst1(1:end-shift(i))=Burst1(1:end-shift(i))-Burst2(shift(i)+1:end); - else - Burst1(1-shift(i):end)=Burst1(1-shift(i):end)-Burst2(1:end+shift(i)); - end - nanVals=isnan(Burst1);Burst1(nanVals)=mean(Burst1(~nanVals));nanVals=isnan(Burst2);Burst2(nanVals)=mean(Burst2(~nanVals)); %Verify that there are no NaNs - %cross-correlate the two vectors: - [XCF, Lags, Bounds] = crosscorr2(Burst1, Burst2, BurstSize-1); - %[XCF,Lags]=xcorr(Burst1, Burst2,BurstSize,'coeff') ; - %find the location of the max value in burst: - [MaxCrossCorrValue,MaxValueLocation]=max(XCF); - if Lags(MaxValueLocation)==shift(i), - ChangedLocations(i)=0; - else, - ChangedLocations(i)=1; - shift(i)=Lags(MaxValueLocation); - end - %calculate the mean burst from tht two shifted vectors: - if shift(i)>0, - Burst1(1:end-shift(i))=Burst1(1:end-shift(i)) + Burst2(shift(i)+1:end); - else - Burst1(1-shift(i):end)=Burst1(1-shift(i):end) + Burst2(1:end+shift(i)); - end - - %build the new burst for next iteration: - % Burst1=[zeros(1,BurstSize),Burst1,zeros(1,BurstSize)]; - end - iteration=iteration+1; -end -fprintf('\ndone!\n'); - -%plot the mean and std bursts: -[ShiftedSBEs]=StdSBE(convM,shift,Method); - -function [ShiftedSBEs]=StdSBE(convM,shift,Method) -%function [meanSBE,stdSBE]=StdSBE(convM,shift); -%calculates the mean and std of burst according to shift as calculated in -%AverageSBE -%convM - the selected bursts convoluted matrix. -%convM(bursts,neurons,data_bins); -%shift - the shift in bins of each burst relative to the mean -%ShiftedSBEs - The shifted bursts for the case of one neurons. - -%04.5.09 - Mark: based on AverageSBE; - -[BurstNum, NeuronNum, BurstSize]=size(convM); - -%build a matrix of 1-dimensional vectors of the bursts: -%put zeros between each neuron recording, and at bagining and ending of 1st and last neurons. -if NeuronNum==1 - for i=1:BurstNum, - Bursts(i,:)=[zeros(1,BurstSize) squeeze(convM(i,:,:))' zeros(1,BurstSize)]; - end -else - for i=1:BurstNum, - Bursts(i,:)=[zeros(1,BurstSize), reshape([squeeze(convM(i,:,:)) , zeros(NeuronNum,BurstSize)]',1,NeuronNum*(BurstSize*2))]; - end % [0 0 0 neuron1 0 0 0 neuron2 0 0 0...neuronN 0 0 0] -end - -%build a matrix of the shifted bursts: -ShiftedBursts=zeros(size(Bursts)); -for i=1:BurstNum, - ShiftedBursts(i,(BurstSize+2):(end-BurstSize-shift(i)+1))=Bursts(i,(BurstSize+shift(i)+1):(end-BurstSize)); -end -Burst1=mean(ShiftedBursts); -Std1=std(ShiftedBursts); -%Burst1=Burst1/BurstNum; - -if NeuronNum==1 - ShiftedSBEs=ShiftedBursts(:,BurstSize+1:BurstSize+BurstSize); -else - for j=1:NeuronNum - ShiftedSBEs(:,j,:)=ShiftedBursts(:,BurstSize*(j*2-1)+1:BurstSize*(j*2-1)+BurstSize); - end -end - -%reshape the final burst back to matrix format: -for i=1:NeuronNum, - meanSBE(i,:)=Burst1(BurstSize*(2*i-1)+1:BurstSize*(2*i-1)+BurstSize); - stdSBE(i,:)=Std1(BurstSize*(2*i-1)+1:BurstSize*(2*i-1)+BurstSize); -end - -if strcmp(Method,'Plot') - %plot the mean burst: - figure; - for i=1:NeuronNum, - hold on; - plot(meanSBE(NeuronNum-i+1,:)+i-1); - end - hold off; - - %plot mean with (+) and (-) std of burst: - figure; - ZeroVec=zeros(1,length(meanSBE)); - P=2.0; - for i=1:NeuronNum, - hold on; - plot(1:length(meanSBE),ZeroVec+i-1,'k--'); - plot(meanSBE(NeuronNum-i+1,:)/P+stdSBE(NeuronNum-i+1,:)/P+i-1,'r'); - plot(meanSBE(NeuronNum-i+1,:)/P-stdSBE(NeuronNum-i+1,:)/P+i-1,'r'); - plot(meanSBE(NeuronNum-i+1,:)/P+i-1,'b'); - end - hold off; - -end - diff --git a/general functions/commonElements.m b/general functions/commonElements.m deleted file mode 100644 index fe2dcf8..0000000 --- a/general functions/commonElements.m +++ /dev/null @@ -1,12 +0,0 @@ -function [Common,UnCommon]=commonElements(Vec1,Vec2,MaxDiff) -%[Common,UnCommon]=commonElements(Vec1,Vec2,MaxDiff) -%finds element places in vector 1 which values are common to vector 2 -%different from intersect(A, B) in that the function returns all the indices and not only first appearances -Vec2=sort(Vec2); -Common=[]; -for i=1:length(Vec2) - Common=[Common find(Vec1>=(Vec2(i)-MaxDiff) & Vec1<=(Vec2(i)+MaxDiff))]; -end -Common=unique(Common); -UnCommon=1:length(Vec1); -UnCommon(Common)=[]; \ No newline at end of file diff --git a/general functions/crossCorrRaster.c b/general functions/crossCorrRaster.c deleted file mode 100644 index b2694ed..0000000 --- a/general functions/crossCorrRaster.c +++ /dev/null @@ -1,100 +0,0 @@ -/*[C]=crossCorrRaster(t,ic,maxLag) - * t must be rounded. - * cross correlation of all spike trains. - * To compile: mex -largeArrayDims crossCorrRaster.c - * Format: - * [C]=crossCorrRaster(t,ic,lag); - * t is the time vector - * ic is the index channel - * lag is the desired lag - * and C is the calculated cross correlation matrix - * e.g. C(1,2,:) shows activity in neuron 2 following an event in neuron 1 - * C is [Neurons x N eurons x time] with 0 as the first time lag - * To get the pearson correlation use: squeeze(C(2,1,:)./sqrt(C(1,1,1).*C(2,2,1)))); - */ - -#include -#include -#include -#include "mex.h" -#include "matrix.h" - -/********************************************************************************************/ -/*This function defines the incoming and outgoing matlab variables - * and sets pointers to the begining of each one. Then calls to the - * function that makes the new SBEmatrix and to the correlation calculation - * (the in comming array must me all in the same unit)*/ - -void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) -{ - double *t, *ic, *maxLag, t1, t2; - long int tmp, startIdx, neu1, neu2, spk1, spk2, nSpk1, nSpk2; - long int nSpikes, nRowsIc, nNeurons, nLags, lag; - mwSize dimsOutput[3]; - double *C; - - /*check if format is correct-help*/ - if (nrhs!=3) - { - mexPrintf("\nThe number of variables entered is: %d\n",nrhs); - mexPrintf("The correct execution format is:\n[C]=crossCorrRaster(t,ic,lag);\nt is the time vector\nic is the index channel\nlag is the desired lag\nand C is the calculated cross correlation matrix\ne.g. C(1,2,:) shows activity in neuron 2 following an event in neuron 1\nC is [Neurons x Neurons x time] with 0 as the first time lag\nTo get the pearson correlation use: squeeze(C(2,1,:)./sqrt(C(1,1,1).*C(2,2,1))));\n"); - mexErrMsgTxt("See description above"); - } - - /* get input variables and their sizes */ - t = mxGetPr(prhs[0]); /*t - spikes times*/ - ic = mxGetPr(prhs[1]); /*ic (4x number of neurons)*/ - maxLag = mxGetPr(prhs[2]); /*t - spikes times*/ - lag = (long int)maxLag[0]; - - nSpikes = (long int)mxGetN(prhs[0]); /* total number of spikes*/ - nRowsIc = (long int)mxGetM(prhs[1]); /* =4 - return number of rows in array*/ - nNeurons = (long int)mxGetN(prhs[1]); /* number of neurions - return number of columns in array.*/ - nLags = (long int)mxGetN(prhs[2]); /* number of neurions - return number of columns in array.*/ - - if (nRowsIc!=4) - mexErrMsgTxt("\nThe number of rows in ic (index channel) is not 4\n"); - - /*Checks that the input varibles are not empty matrices*/ - if (nNeurons==0 || nSpikes==0 || nLags!=1) - mexErrMsgTxt("\nOne of the input variables is either empty or has the wrong size\n"); - - /* Create output Matrix and set output pointers :*/ - dimsOutput[0]=(mwSize)nNeurons; - dimsOutput[1]=(mwSize)nNeurons; - dimsOutput[2]=(mwSize)lag; - - plhs[0] = mxCreateNumericArray(3,dimsOutput,mxDOUBLE_CLASS,mxREAL); - C = mxGetPr(plhs[0]); - - mexPrintf("\nSpike train cross-corr neuron:"); - for (neu1=0;neu1=t1) - if (t2<(t1+lag)) - { - startIdx=spk1; - C[(long int)(t2-t1)*nNeurons*nNeurons + neu2*nNeurons + neu1]++; - } - else - break; - - } - } - } - -} /*void mexFunction*/ - - diff --git a/general functions/crossCorrRaster.mexa64 b/general functions/crossCorrRaster.mexa64 deleted file mode 100755 index e53716b..0000000 Binary files a/general functions/crossCorrRaster.mexa64 and /dev/null differ diff --git a/general functions/crossCorrRaster.mexw64 b/general functions/crossCorrRaster.mexw64 deleted file mode 100644 index 614937c..0000000 Binary files a/general functions/crossCorrRaster.mexw64 and /dev/null differ diff --git a/general functions/find1dmex.c b/general functions/find1dmex.c deleted file mode 100644 index 160c5f1..0000000 --- a/general functions/find1dmex.c +++ /dev/null @@ -1,250 +0,0 @@ -/************************************************************************* - * MEX ROUTINE FIND1DMEX.C - * B = find1dmex(A, count) - * - * A is 3-d arrays - * FIND along the second dimension - * COUNT is scacar, >0: find most first COUNT - * <0: find most last -COUNT - * - * Method: there is no copy of array - * - * Compilation: - * >> mex -O -v find1dmex.c % add -largeArrayDims on 64-bit computer - * - * Author Bruno Luong - * Last update: 27/June/2009 - * 19-May-2010: change count to mwSignedIndex - ************************************************************************/ - -#include "mex.h" -#include "matrix.h" - -/* Uncomment this on older Matlab version where size_t has not been - * defined */ -/* - * #define mwSize int - * #define size_t int - */ - -/* Define correct type depending on platform - You might have to modify here depending on your compiler */ -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef __int64 int64; -typedef __int32 int32; -typedef __int16 int16; -typedef __int8 int08; -#else /* LINUX + LCC, CAUTION: not tested by the author */ -typedef long long int int64; -typedef long int int32; -typedef short int16; -typedef char int08; -#endif - -/* Macro use for find engine */ -/* pA is a pointer to a specific type of data, specified by pAtype */ -#define FIRST_ENGINE(pA, pAtype) \ - for (j=0; jm) count = m; - - /* Nothing to do */ - if (count==0) - return; - - /* Call the engine */ - switch (ClassID) { - case mxDOUBLE_CLASS: - if (PiA==NULL) - {FIND_ENGINE(prAdouble, double, islast);} - else - {CMPLX_FIND_ENGINE(prAdouble, piAdouble, double, islast);} - case mxSINGLE_CLASS: - if (PiA==NULL) - {FIND_ENGINE(prAsingle, float, islast);} - else - {CMPLX_FIND_ENGINE(prAsingle, piAsingle, float, islast);} - case mxINT64_CLASS: - case mxUINT64_CLASS: - FIND_ENGINE(pA64, int64, islast); - case mxINT32_CLASS: - case mxUINT32_CLASS: - FIND_ENGINE(pA32, int32, islast); - case mxCHAR_CLASS: - case mxINT16_CLASS: - case mxUINT16_CLASS: - FIND_ENGINE(pA16, int16, islast); - case mxLOGICAL_CLASS: - case mxINT8_CLASS: - case mxUINT8_CLASS: - FIND_ENGINE(pA08, int08, islast); - default: - mexErrMsgTxt("FIND1DMEX: Class not supported."); - } - - return; - -} /* FIND1DMEX */ diff --git a/general functions/find1dmex.mexa64 b/general functions/find1dmex.mexa64 deleted file mode 100755 index cd038ab..0000000 Binary files a/general functions/find1dmex.mexa64 and /dev/null differ diff --git a/general functions/find1dmex.mexw64 b/general functions/find1dmex.mexw64 deleted file mode 100644 index 6268cf1..0000000 Binary files a/general functions/find1dmex.mexw64 and /dev/null differ diff --git a/general functions/findfirst.m b/general functions/findfirst.m deleted file mode 100644 index c1b4060..0000000 --- a/general functions/findfirst.m +++ /dev/null @@ -1,116 +0,0 @@ -function B = findfirst(A, dim, count, firstlast) -% B = FINDFIRST(A) -% -% Look for the row-indices of a first non-zero element(s) for all columns -% in the array. It is equivalent to doing: -% -% B=zeros(1,size(A,1)); -% for j=1:size(A,2) -% Bj = find(A(:,j), 1, 'first'); -% if ~isempty(Bj); B(j)=Bj; end -% end -% -% B = FINDFIRST(A, DIM): operate along the dimension DIM -% B = FINDFIRST(A, DIM, COUNT): look for the most COUNT non-zeros elements -% (by default COUNT is 1) -% B = FINDFIRST(A, DIM, COUNT, 'LAST'): returns most last non-zero indices -% -% INPUTS: -% A: array of dimension (N1 x N2 x ...x Nd x ... Nn) -% A can be any numerical class -% OUTPUT: -% B: same dimension than A, but only Nd is contracted to COUNT -% where d is the dimension specified by the second input (DIM) -% and COUNT is specified by the third input -% B dimension is (N1 x N2 x ... x COUNT x ... Nn) -% B contains indices non-zero elements of A along DIM -% B is filled when it's possible, the rest is filles with zeros if A -% contains less than COUNT non-zero elements. -% -% NOTES: - Sparse matrix is not suuported -% - Inplace engine, i.e., no duplicated temporary array is created -% -% USAGE EXAMPLES: -% -% A = [ 0 1 1 -% 1 0 1 -% 0 0 0 -% 0 0 1 -% 1 1 1 ] -% -% OPERATE ALONG COLUMNS: > B = FINDFIRST(A) % returns [2 1 1] -% -% OPERATE ALONG ROWS: > B=FINDFIRST(A,2) % returns [2 1 0 3 1]' -% -% > B=FINDFIRST(A,1,2) % returns two indexes for each column [2 1 1 -% 5 5 2] -% -% > B=FINDFIRST(A,1,2, 'last') % returns two last indexes [5 5 5 -% 2 1 4] -% -% See also: find, nonzeros -% -% AUTHOR: Bruno Luong -% HISTORY -% Original: 05-Jul-2009 -% - -% Default working dimension -if nargin<2 || isempty(dim) - dim = 1; -end -% Check if it's correct -if ~isscalar(dim) - error('FINDFIRST: dim must be a scalar'); -end -dim = round(dim); -if dim<=0 - error('FINDFIRST: dim must be positive number'); -end - -% Default count -if nargin<3 || isempty(count) - count = 1; -end -% Check if it's correct -if ~isscalar(count) - error('FINDFIRST: count must be a scalar'); -end -count = round(double(count)); - -% Default 'first' 'last flag -if nargin<4 || isempty(firstlast) - firstlast = 'first'; -end -if ~ischar(firstlast) || isempty(strmatch(firstlast,{'first' 'last'})) - error('FINDFIRST: Fourth argument must be ''first'' or ''last'''); -end - -if issparse(A) - error('FINDFIRST: A must be full matrix') -end - -% Extend trailing singleton dimension if needed -szA = size(A); -szA(end+1:dim) = 1; - -% Reshape A in 3D arrays, working dimension is the middle -% That is the form the FIND1DMEX -k = prod(szA(1:dim-1)); % return 1 if empty -m = szA(dim); -n = prod(szA(dim+1:end)); % return 1 if empty -A = reshape(A,[k m n]); - -% Call mex engine -if strcmpi(firstlast, 'first') - B = find1dmex(A, count); -else - B = find1dmex(A, -count); -end - -% Dimension of the output -szB = szA; -szB(dim) = count; -B = reshape(B,szB); - -end diff --git a/general functions/findjobj.m b/general functions/findjobj.m deleted file mode 100644 index 8292a7f..0000000 --- a/general functions/findjobj.m +++ /dev/null @@ -1,3210 +0,0 @@ -function [handles,levels,parentIdx,listing] = findjobj(container,varargin) -%findjobj Find java objects contained within a specified java container or Matlab GUI handle -% -% Syntax: -% [handles, levels, parentIds, listing] = findjobj(container, 'PropName',PropValue(s), ...) -% -% Input parameters: -% container - optional handle to java container uipanel or figure. If unsupplied then current figure will be used -% 'PropName',PropValue - optional list of property pairs (case insensitive). PropName may also be named -PropName -% 'position' - filter results based on those elements that contain the specified X,Y position or a java element -% Note: specify a Matlab position (X,Y = pixels from bottom left corner), not a java one -% 'size' - filter results based on those elements that have the specified W,H (in pixels) -% 'class' - filter results based on those elements that contain the substring (or java class) PropValue -% Note1: filtering is case insensitive and relies on regexp, so you can pass wildcards etc. -% Note2: '-class' is an undocumented findobj PropName, but only works on Matlab (not java) classes -% 'property' - filter results based on those elements that possess the specified case-insensitive property string -% Note1: passing a property value is possible if the argument following 'property' is a cell in the -% format of {'propName','propValue'}. Example: FINDJOBJ(...,'property',{'Text','click me'}) -% Note2: partial property names (e.g. 'Tex') are accepted, as long as they're not ambiguous -% 'depth' - filter results based on specified depth. 0=top-level, Inf=all levels (default=Inf) -% 'flat' - same as specifying: 'depth',0 -% 'not' - negates the following filter: 'not','class','c' returns all elements EXCEPT those with class 'c' -% 'persist' - persist figure components information, allowing much faster results for subsequent invocations -% 'nomenu' - skip menu processing, for "lean" list of handles & much faster processing; -% This option is the default for HG containers but not for figure, Java or no container -% 'print' - display all java elements in a hierarchical list, indented appropriately -% Note1: optional PropValue of element index or handle to java container -% Note2: normally this option would be placed last, after all filtering is complete. Placing this -% option before some filters enables debug print-outs of interim filtering results. -% Note3: output is to the Matlab command window unless the 'listing' (4th) output arg is requested -% 'list' - same as 'print' -% 'debug' - list found component positions in the Command Window -% -% Output parameters: -% handles - list of handles to java elements -% levels - list of corresponding hierarchy level of the java elements (top=0) -% parentIds - list of indexes (in unfiltered handles) of the parent container of the corresponding java element -% listing - results of 'print'/'list' options (empty if these options were not specified) -% -% Note: If no output parameter is specified, then an interactive window will be displayed with a -% ^^^^ tree view of all container components, their properties and callbacks. -% -% Examples: -% findjobj; % display list of all javaelements of currrent figure in an interactive GUI -% handles = findjobj; % get list of all java elements of current figure (inc. menus, toolbars etc.) -% findjobj('print'); % list all java elements in current figure -% findjobj('print',6); % list all java elements in current figure, contained within its 6th element -% handles = findjobj(hButton); % hButton is a matlab button -% handles = findjobj(gcf,'position',getpixelposition(hButton,1)); % same as above but also return hButton's panel -% handles = findjobj(hButton,'persist'); % same as above, persist info for future reuse -% handles = findjobj('class','pushbutton'); % get all pushbuttons in current figure -% handles = findjobj('class','pushbutton','position',123,456); % get all pushbuttons at the specified position -% handles = findjobj(gcf,'class','pushbutton','size',23,15); % get all pushbuttons with the specified size -% handles = findjobj('property','Text','not','class','button'); % get all non-button elements with 'text' property -% handles = findjobj('-property',{'Text','click me'}); % get all elements with 'text' property = 'click me' -% -% Sample usage: -% hButton = uicontrol('string','click me'); -% jButton = findjobj(hButton,'nomenu'); -% % or: jButton = findjobj('property',{'Text','click me'}); -% jButton.setFlyOverAppearance(1); -% jButton.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.HAND_CURSOR)); -% set(jButton,'FocusGainedCallback',@myMatlabFunction); % some 30 callback points available... -% jButton.get; % list all changeable properties... -% -% hEditbox = uicontrol('style','edit'); -% jEditbox = findjobj(hEditbox,'nomenu'); -% jEditbox.setCaretColor(java.awt.Color.red); -% jEditbox.KeyTypedCallback = @myCallbackFunc; % many more callbacks where this came from... -% jEdit.requestFocus; -% -% Technical explanation & details: -% http://undocumentedmatlab.com/blog/findjobj/ -% http://undocumentedmatlab.com/blog/findjobj-gui-display-container-hierarchy/ -% -% Known issues/limitations: -% - Cannot currently process multiple container objects - just one at a time -% - Initial processing is a bit slow when the figure is laden with many UI components (so better use 'persist') -% - Passing a simple container Matlab handle is currently filtered by its position+size: should find a better way to do this -% - Matlab uipanels are not implemented as simple java panels, and so they can't be found using this utility -% - Labels have a write-only text property in java, so they can't be found using the 'property',{'Text','string'} notation -% -% Warning: -% This code heavily relies on undocumented and unsupported Matlab functionality. -% It works on Matlab 7+, but use at your own risk! -% -% Bugs and suggestions: -% Please send to Yair Altman (altmany at gmail dot com) -% -% Change log: -% 2013-06-30: Additional fixes for the upcoming HG2 -% 2013-05-15: Fix for the upcoming HG2 -% 2013-02-21: Fixed HG-Java warnings -% 2013-01-23: Fixed callbacks table grouping & editing bugs; added hidden properties to the properties tooltip; updated help section -% 2013-01-13: Improved callbacks table; fixed tree refresh failure; fixed: tree node-selection didn't update the props pane nor flash the selected component -% 2012-07-25: Fixes for R2012a as well as some older Matlab releases -% 2011-12-07: Fixed 'File is empty' messages in compiled apps -% 2011-11-22: Fix suggested by Ward -% 2011-02-01: Fixes for R2011a -% 2010-06-13: Fixes for R2010b; fixed download (m-file => zip-file) -% 2010-04-21: Minor fix to support combo-boxes (aka drop-down, popup-menu) on Windows -% 2010-03-17: Important release: Fixes for R2010a, debug listing, objects not found, component containers that should be ignored etc. -% 2010-02-04: Forced an EDT redraw before processing; warned if requested handle is invisible -% 2010-01-18: Found a way to display label text next to the relevant node name -% 2009-10-28: Fixed uitreenode warning -% 2009-10-27: Fixed auto-collapse of invisible container nodes; added dynamic tree tooltips & context-menu; minor fix to version-check display -% 2009-09-30: Fix for Matlab 7.0 as suggested by Oliver W; minor GUI fix (classname font) -% 2009-08-07: Fixed edge-case of missing JIDE tables -% 2009-05-24: Added support for future Matlab versions that will not support JavaFrame -% 2009-05-15: Added sanity checks for axes items -% 2009-04-28: Added 'debug' input arg; increased size tolerance 1px => 2px -% 2009-04-23: Fixed location of popupmenus (always 20px high despite what's reported by Matlab...); fixed uiinspect processing issues; added blog link; narrower action buttons -% 2009-04-09: Automatic 'nomenu' for uicontrol inputs; significant performance improvement -% 2009-03-31: Fixed position of some Java components; fixed properties tooltip; fixed node visibility indication -% 2009-02-26: Indicated components visibility (& auto-collapse non-visible containers); auto-highlight selected component; fixes in node icons, figure title & tree refresh; improved error handling; display FindJObj version update description if available -% 2009-02-24: Fixed update check; added dedicated labels icon -% 2009-02-18: Fixed compatibility with old Matlab versions -% 2009-02-08: Callbacks table fixes; use uiinspect if available; fix update check according to new FEX website -% 2008-12-17: R2008b compatibility -% 2008-09-10: Fixed minor bug as per Johnny Smith -% 2007-11-14: Fixed edge case problem with class properties tooltip; used existing object icon if available; added checkbox option to hide standard callbacks -% 2007-08-15: Fixed object naming relative property priorities; added sanity check for illegal container arg; enabled desktop (0) container; cleaned up warnings about special class objects -% 2007-08-03: Fixed minor tagging problems with a few Java sub-classes; displayed UIClassID if text/name/tag is unavailable -% 2007-06-15: Fixed problems finding HG components found by J. Wagberg -% 2007-05-22: Added 'nomenu' option for improved performance; fixed 'export handles' bug; fixed handle-finding/display bugs; "cleaner" error handling -% 2007-04-23: HTMLized classname tooltip; returned top-level figure Frame handle for figure container; fixed callbacks table; auto-checked newer version; fixed Matlab 7.2 compatibility issue; added HG objects tree -% 2007-04-19: Fixed edge case of missing figure; displayed tree hierarchy in interactive GUI if no output args; workaround for figure sub-menus invisible unless clicked -% 2007-04-04: Improved performance; returned full listing results in 4th output arg; enabled partial property names & property values; automatically filtered out container panels if children also returned; fixed finding sub-menu items -% 2007-03-20: First version posted on the MathWorks file exchange: http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=14317 -% -% See also: -% java, handle, findobj, findall, javaGetHandles, uiinspect (on the File Exchange) - -% License to use and modify this code is granted freely to all interested, as long as the original author is -% referenced and attributed as such. The original author maintains the right to be solely associated with this work. - -% Programmed and Copyright by Yair M. Altman: altmany(at)gmail.com -% $Revision: 1.39 $ $Date: 2013/06/30 22:34:52 $ - - % Ensure Java AWT is enabled - error(javachk('awt')); - - persistent pContainer pHandles pLevels pParentIdx pPositions - - try - % Initialize - handles = handle([]); - levels = []; - parentIdx = []; - positions = []; % Java positions start at the top-left corner - %sizes = []; - listing = ''; - hg_levels = []; - hg_handles = handle([]); % HG handles are double - hg_parentIdx = []; - nomenu = false; - menuBarFoundFlag = false; - - % Force an EDT redraw before processing, to ensure all uicontrols etc. are rendered - drawnow; pause(0.02); - - % Default container is the current figure's root panel - if nargin - if isempty(container) % empty container - bail out - return; - elseif ischar(container) % container skipped - this is part of the args list... - varargin = {container, varargin{:}}; - origContainer = getCurrentFigure; - [container,contentSize] = getRootPanel(origContainer); - elseif isequal(container,0) % root - origContainer = handle(container); - container = com.mathworks.mde.desk.MLDesktop.getInstance.getMainFrame; - contentSize = [container.getWidth, container.getHeight]; - elseif ishghandle(container) % && ~isa(container,'java.awt.Container') - container = container(1); % another current limitation... - hFig = ancestor(container,'figure'); - origContainer = handle(container); - if isa(origContainer,'uimenu') - % getpixelposition doesn't work for menus... - damn! - varargin = {'class','MenuPeer', 'property',{'Label',strrep(get(container,'Label'),'&','')}, varargin{:}}; - elseif ~isa(origContainer, 'figure') && ~isempty(hFig) - % See limitations section above: should find a better way to directly refer to the element's java container - try - % Note: 'PixelBounds' is undocumented and unsupported, but much faster than getpixelposition! - % ^^^^ unfortunately, its Y position is inaccurate in some cases - damn! - %size = get(container,'PixelBounds'); - pos = fix(getpixelposition(container,1)); - %varargin = {'position',pos(1:2), 'size',pos(3:4), 'not','class','java.awt.Panel', varargin{:}}; - catch - try - figName = get(hFig,'name'); - if strcmpi(get(hFig,'number'),'on') - figName = regexprep(['Figure ' num2str(hFig) ': ' figName],': $',''); - end - mde = com.mathworks.mde.desk.MLDesktop.getInstance; - jFig = mde.getClient(figName); - if isempty(jFig), error('dummy'); end - catch - warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); % R2008b compatibility - jFig = get(get(hFig,'JavaFrame'),'FigurePanelContainer'); - end - pos = []; - try - pxsize = get(container,'PixelBounds'); - pos = [pxsize(1)+5, jFig.getHeight - (pxsize(4)-5)]; - catch - % never mind... - end - end - if size(pos,2) == 2 - pos(:,3:4) = 0; - end - if ~isempty(pos) - if isa(handle(container),'uicontrol') && strcmp(get(container,'style'),'popupmenu') - % popupmenus (combo-box dropdowns) are always 20px high - pos(2) = pos(2) + pos(4) - 20; - pos(4) = 20; - end - %varargin = {'position',pos(1:2), 'size',size(3:4)-size(1:2)-10, 'not','class','java.awt.Panel', varargin{:}}; - varargin = {'position',pos(1:2)+[0,pos(4)], 'size',pos(3:4), 'not','class','java.awt.Panel', 'nomenu', varargin{:}}; - end - elseif isempty(hFig) - hFig = handle(container); - end - [container,contentSize] = getRootPanel(hFig); - elseif isjava(container) - % Maybe a java container obj (will crash otherwise) - origContainer = container; - contentSize = [container.getWidth, container.getHeight]; - else - error('YMA:findjobj:IllegalContainer','Input arg does not appear to be a valid GUI object'); - end - else - % Default container = current figure - origContainer = getCurrentFigure; - [container,contentSize] = getRootPanel(origContainer); - end - - % Check persistency - if isequal(pContainer,container) - % persistency requested and the same container is reused, so reuse the hierarchy information - [handles,levels,parentIdx,positions] = deal(pHandles, pLevels, pParentIdx, pPositions); - else - % Pre-allocate space of complex data containers for improved performance - handles = repmat(handles,1,1000); - positions = zeros(1000,2); - - % Check whether to skip menu processing - nomenu = paramSupplied(varargin,'nomenu'); - - % Traverse the container hierarchy and extract the elements within - traverseContainer(container,0,1); - - % Remove unnecessary pre-allocated elements - dataLen = length(levels); - handles (dataLen+1:end) = []; - positions(dataLen+1:end,:) = []; - end - - % Process persistency check before any filtering is done - if paramSupplied(varargin,'persist') - [pContainer, pHandles, pLevels, pParentIdx, pPositions] = deal(container,handles,levels,parentIdx,positions); - end - - % Save data for possible future use in presentObjectTree() below - allHandles = handles; - allLevels = levels; - allParents = parentIdx; - selectedIdx = 1:length(handles); - %[positions(:,1)-container.getX, container.getHeight - positions(:,2)] - - % Debug-list all found compponents and their positions - if paramSupplied(varargin,'debug') - for handleIdx = 1 : length(allHandles) - thisObj = handles(handleIdx); - pos = sprintf('%d,%d %dx%d',[positions(handleIdx,:) getWidth(thisObj) getHeight(thisObj)]); - disp([repmat(' ',1,levels(handleIdx)) '[' pos '] ' char(toString(thisObj))]); - end - end - - % Process optional args - % Note: positions is NOT returned since it's based on java coord system (origin = top-left): will confuse Matlab users - processArgs(varargin{:}); - - % De-cell and trim listing, if only one element was found (no use for indented listing in this case) - if iscell(listing) && length(listing)==1 - listing = strtrim(listing{1}); - end - - % If no output args and no listing requested, present the FINDJOBJ interactive GUI - if nargout == 0 && isempty(listing) - - % Get all label positions - hg_labels = []; - labelPositions = getLabelsJavaPos(container); - - % Present the GUI (object tree) - if ~isempty(container) - presentObjectTree(); - else - warnInvisible; - end - - % Display the listing, if this was specifically requested yet no relevant output arg was specified - elseif nargout < 4 && ~isempty(listing) - if ~iscell(listing) - disp(listing); - else - for listingIdx = 1 : length(listing) - disp(listing{listingIdx}); - end - end - end - - % Display a warning if the requested handle was not found because it's invisible - if nargout && isempty(handles) - warnInvisible; - end - - return; %debug point - - catch - % 'Cleaner' error handling - strip the stack info etc. - err = lasterror; %#ok - err.message = regexprep(err.message,'Error using ==> [^\n]+\n',''); - if isempty(findstr(mfilename,err.message)) - % Indicate error origin, if not already stated within the error message - err.message = [mfilename ': ' err.message]; - end - rethrow(err); - end - - %% Display a warning if the requested handle was not found because it's invisible - function warnInvisible - try - stk = dbstack; - stkNames = {stk.name}; - OutputFcnIdx = find(~cellfun(@isempty,regexp(stkNames,'_OutputFcn'))); - if ~isempty(OutputFcnIdx) - OutputFcnName = stkNames{OutputFcnIdx}; - warning('YMA:FindJObj:OutputFcn',['No Java reference was found for the requested handle, because the figure is still invisible in ' OutputFcnName '()']); - elseif ishandle(origContainer) && isprop(origContainer,'Visible') && strcmpi(get(origContainer,'Visible'),'off') - warning('YMA:FindJObj:invisibleHandle','No Java reference was found for the requested handle, probably because it is still invisible'); - end - catch - % Never mind... - end - end - - %% Check existence of a (case-insensitive) optional parameter in the params list - function [flag,idx] = paramSupplied(paramsList,paramName) - %idx = find(~cellfun('isempty',regexpi(paramsList(cellfun(@ischar,paramsList)),['^-?' paramName]))); - idx = find(~cellfun('isempty',regexpi(paramsList(cellfun('isclass',paramsList,'char')),['^-?' paramName]))); % 30/9/2009 fix for ML 7.0 suggested by Oliver W - flag = any(idx); - end - - %% Get current figure (even if its 'HandleVisibility' property is 'off') - function curFig = getCurrentFigure - oldShowHidden = get(0,'ShowHiddenHandles'); - set(0,'ShowHiddenHandles','on'); % minor fix per Johnny Smith - curFig = gcf; - set(0,'ShowHiddenHandles',oldShowHidden); - end - - %% Get Java reference to top-level (root) panel - actually, a reference to the java figure - function [jRootPane,contentSize] = getRootPanel(hFig) - try - contentSize = [0,0]; % initialize - jRootPane = hFig; - figName = get(hFig,'name'); - if strcmpi(get(hFig,'number'),'on') - figName = regexprep(['Figure ' num2str(hFig) ': ' figName],': $',''); - end - mde = com.mathworks.mde.desk.MLDesktop.getInstance; - jFigPanel = mde.getClient(figName); - jRootPane = jFigPanel; - jRootPane = jFigPanel.getRootPane; - catch - try - warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); % R2008b compatibility - jFrame = get(hFig,'JavaFrame'); - jFigPanel = get(jFrame,'FigurePanelContainer'); - jRootPane = jFigPanel; - jRootPane = jFigPanel.getComponent(0).getRootPane; - catch - % Never mind - end - end - try - % If invalid RootPane - try another method... - warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); % R2008b compatibility - jFrame = get(hFig,'JavaFrame'); - jAxisComponent = get(jFrame,'AxisComponent'); - jRootPane = jAxisComponent.getParent.getParent.getRootPane; - catch - % Never mind - end - try - % If invalid RootPane, retry up to N times - tries = 10; - while isempty(jRootPane) && tries>0 % might happen if figure is still undergoing rendering... - drawnow; pause(0.001); - tries = tries - 1; - jRootPane = jFigPanel.getComponent(0).getRootPane; - end - - % If still invalid, use FigurePanelContainer which is good enough in 99% of cases... (menu/tool bars won't be accessible, though) - if isempty(jRootPane) - jRootPane = jFigPanel; - end - contentSize = [jRootPane.getWidth, jRootPane.getHeight]; - - % Try to get the ancestor FigureFrame - jRootPane = jRootPane.getTopLevelAncestor; - catch - % Never mind - FigurePanelContainer is good enough in 99% of cases... (menu/tool bars won't be accessible, though) - end - end - - %% Traverse the container hierarchy and extract the elements within - function traverseContainer(jcontainer,level,parent) - persistent figureComponentFound menuRootFound - - % Record the data for this node - %disp([repmat(' ',1,level) '<= ' char(jcontainer.toString)]) - thisIdx = length(levels) + 1; - levels(thisIdx) = level; - parentIdx(thisIdx) = parent; - handles(thisIdx) = handle(jcontainer,'callbackproperties'); - try - positions(thisIdx,:) = getXY(jcontainer); - %sizes(thisIdx,:) = [jcontainer.getWidth, jcontainer.getHeight]; - catch - positions(thisIdx,:) = [0,0]; - %sizes(thisIdx,:) = [0,0]; - end - if level>0 - positions(thisIdx,:) = positions(thisIdx,:) + positions(parent,:); - if ~figureComponentFound && ... - strcmp(jcontainer.getName,'fComponentContainer') && ... - isa(jcontainer,'com.mathworks.hg.peer.FigureComponentContainer') % there are 2 FigureComponentContainers - only process one... - - % restart coordinate system, to exclude menu & toolbar areas - positions(thisIdx,:) = positions(thisIdx,:) - [jcontainer.getRootPane.getX, jcontainer.getRootPane.getY]; - figureComponentFound = true; - end - elseif level==1 - positions(thisIdx,:) = positions(thisIdx,:) + positions(parent,:); - else - % level 0 - initialize flags used later - figureComponentFound = false; - menuRootFound = false; - end - parentId = length(parentIdx); - - % Traverse Menu items, unless the 'nomenu' option was requested - if ~nomenu - try - for child = 1 : getNumMenuComponents(jcontainer) - traverseContainer(jcontainer.getMenuComponent(child-1),level+1,parentId); - end - catch - % Probably not a Menu container, but maybe a top-level JMenu, so discard duplicates - %if isa(handles(end).java,'javax.swing.JMenuBar') - if ~menuRootFound && strcmp(class(java(handles(end))),'javax.swing.JMenuBar') %faster... - if removeDuplicateNode(thisIdx) - menuRootFound = true; - return; - end - end - end - end - - % Now recursively process all this node's children (if any), except menu items if so requested - %if isa(jcontainer,'java.awt.Container') - try % try-catch is faster than checking isa(jcontainer,'java.awt.Container')... - %if jcontainer.getComponentCount, jcontainer.getComponents, end - if ~nomenu || menuBarFoundFlag || isempty(strfind(class(jcontainer),'FigureMenuBar')) - lastChildComponent = java.lang.Object; - child = 0; - while (child < jcontainer.getComponentCount) - childComponent = jcontainer.getComponent(child); - % Looping over menus sometimes causes jcontainer to get mixed up (probably a JITC bug), so identify & fix - if isequal(childComponent,lastChildComponent) - child = child + 1; - childComponent = jcontainer.getComponent(child); - end - lastChildComponent = childComponent; - %disp([repmat(' ',1,level) '=> ' num2str(child) ': ' char(class(childComponent))]) - traverseContainer(childComponent,level+1,parentId); - child = child + 1; - end - else - menuBarFoundFlag = true; % use this flag to skip further testing for FigureMenuBar - end - catch - % do nothing - probably not a container - %dispError - end - - % ...and yet another type of child traversal... - try - if ~isdeployed % prevent 'File is empty' messages in compiled apps - jc = jcontainer.java; - else - jc = jcontainer; - end - for child = 1 : jc.getChildCount - traverseContainer(jc.getChildAt(child-1),level+1,parentId); - end - catch - % do nothing - probably not a container - %dispError - end - - % TODO: Add axis (plot) component handles - end - - %% Get the XY location of a Java component - function xy = getXY(jcontainer) - % Note: getX/getY are better than get(..,'X') (mem leaks), - % ^^^^ but sometimes they fail and revert to getx.m ... - % Note2: try awtinvoke() catch is faster than checking ismethod()... - % Note3: using AWTUtilities.invokeAndWait() directly is even faster than awtinvoke()... - try %if ismethod(jcontainer,'getX') - %positions(thisIdx,:) = [jcontainer.getX, jcontainer.getY]; - cls = getClass(jcontainer); - location = com.mathworks.jmi.AWTUtilities.invokeAndWait(jcontainer,getMethod(cls,'getLocation',[]),[]); - x = location.getX; - y = location.getY; - catch %else - try - x = com.mathworks.jmi.AWTUtilities.invokeAndWait(jcontainer,getMethod(cls,'getX',[]),[]); - y = com.mathworks.jmi.AWTUtilities.invokeAndWait(jcontainer,getMethod(cls,'getY',[]),[]); - catch - try - x = awtinvoke(jcontainer,'getX()'); - y = awtinvoke(jcontainer,'getY()'); - catch - x = get(jcontainer,'X'); - y = get(jcontainer,'Y'); - end - end - end - %positions(thisIdx,:) = [x, y]; - xy = [x,y]; - end - - %% Get the number of menu sub-elements - function numMenuComponents = getNumMenuComponents(jcontainer) - - % The following line will raise an Exception for anything except menus - numMenuComponents = jcontainer.getMenuComponentCount; - - % No error so far, so this must be a menu container... - % Note: Menu subitems are not visible until the top-level (root) menu gets initial focus... - % Try several alternatives, until we get a non-empty menu (or not...) - % TODO: Improve performance - this takes WAY too long... - if jcontainer.isTopLevelMenu && (numMenuComponents==0) - jcontainer.requestFocus; - numMenuComponents = jcontainer.getMenuComponentCount; - if (numMenuComponents == 0) - drawnow; pause(0.001); - numMenuComponents = jcontainer.getMenuComponentCount; - if (numMenuComponents == 0) - jcontainer.setSelected(true); - numMenuComponents = jcontainer.getMenuComponentCount; - if (numMenuComponents == 0) - drawnow; pause(0.001); - numMenuComponents = jcontainer.getMenuComponentCount; - if (numMenuComponents == 0) - jcontainer.doClick; % needed in order to populate the sub-menu components - numMenuComponents = jcontainer.getMenuComponentCount; - if (numMenuComponents == 0) - drawnow; %pause(0.001); - numMenuComponents = jcontainer.getMenuComponentCount; - jcontainer.doClick; % close menu by re-clicking... - if (numMenuComponents == 0) - drawnow; %pause(0.001); - numMenuComponents = jcontainer.getMenuComponentCount; - end - else - % ok - found sub-items - % Note: no need to close menu since this will be done when focus moves to the FindJObj window - %jcontainer.doClick; % close menu by re-clicking... - end - end - end - jcontainer.setSelected(false); % de-select the menu - end - end - end - end - - %% Remove a specific tree node's data - function nodeRemovedFlag = removeDuplicateNode(thisIdx) - nodeRemovedFlag = false; - for idx = 1 : thisIdx-1 - if isequal(handles(idx),handles(thisIdx)) - levels(thisIdx) = []; - parentIdx(thisIdx) = []; - handles(thisIdx) = []; - positions(thisIdx,:) = []; - %sizes(thisIdx,:) = []; - nodeRemovedFlag = true; - return; - end - end - end - - %% Process optional args - function processArgs(varargin) - - % Initialize - invertFlag = false; - listing = ''; - - % Loop over all optional args - while ~isempty(varargin) && ~isempty(handles) - - % Process the arg (and all its params) - foundIdx = 1 : length(handles); - if iscell(varargin{1}), varargin{1} = varargin{1}{1}; end - if ~isempty(varargin{1}) && varargin{1}(1)=='-' - varargin{1}(1) = []; - end - switch lower(varargin{1}) - case 'not' - invertFlag = true; - case 'position' - [varargin,foundIdx] = processPositionArgs(varargin{:}); - if invertFlag, foundIdx = ~foundIdx; invertFlag = false; end - case 'size' - [varargin,foundIdx] = processSizeArgs(varargin{:}); - if invertFlag, foundIdx = ~foundIdx; invertFlag = false; end - case 'class' - [varargin,foundIdx] = processClassArgs(varargin{:}); - if invertFlag, foundIdx = ~foundIdx; invertFlag = false; end - case 'property' - [varargin,foundIdx] = processPropertyArgs(varargin{:}); - if invertFlag, foundIdx = ~foundIdx; invertFlag = false; end - case 'depth' - [varargin,foundIdx] = processDepthArgs(varargin{:}); - if invertFlag, foundIdx = ~foundIdx; invertFlag = false; end - case 'flat' - varargin = {'depth',0, varargin{min(2:end):end}}; - [varargin,foundIdx] = processDepthArgs(varargin{:}); - if invertFlag, foundIdx = ~foundIdx; invertFlag = false; end - case {'print','list'} - [varargin,listing] = processPrintArgs(varargin{:}); - case {'persist','nomenu','debug'} - % ignore - already handled in main function above - otherwise - error('YMA:findjobj:IllegalOption',['Option ' num2str(varargin{1}) ' is not a valid option. Type ''help ' mfilename ''' for the full options list.']); - end - - % If only parent-child pairs found - foundIdx = find(foundIdx); - if ~isempty(foundIdx) && isequal(parentIdx(foundIdx(2:2:end)),foundIdx(1:2:end)) - % Return just the children (the parent panels are uninteresting) - foundIdx(1:2:end) = []; - end - - % If several possible handles were found and the first is the container of the second - if length(foundIdx) > 1 && isequal(handles(foundIdx(1)).java, handles(foundIdx(2)).getParent) - % Discard the uninteresting component container - foundIdx(1) = []; - end - - % Filter the results - selectedIdx = selectedIdx(foundIdx); - handles = handles(foundIdx); - levels = levels(foundIdx); - parentIdx = parentIdx(foundIdx); - positions = positions(foundIdx,:); - - % Remove this arg and proceed to the next one - varargin(1) = []; - - end % Loop over all args - end - - %% Process 'print' option - function [varargin,listing] = processPrintArgs(varargin) - if length(varargin)<2 || ischar(varargin{2}) - % No second arg given, so use the first available element - listingContainer = handles(1); %#ok - used in evalc below - else - % Get the element to print from the specified second arg - if isnumeric(varargin{2}) && (varargin{2} == fix(varargin{2})) % isinteger doesn't work on doubles... - if (varargin{2} > 0) && (varargin{2} <= length(handles)) - listingContainer = handles(varargin{2}); %#ok - used in evalc below - elseif varargin{2} > 0 - error('YMA:findjobj:IllegalPrintFilter','Print filter index %g > number of available elements (%d)',varargin{2},length(handles)); - else - error('YMA:findjobj:IllegalPrintFilter','Print filter must be a java handle or positive numeric index into handles'); - end - elseif ismethod(varargin{2},'list') - listingContainer = varargin{2}; %#ok - used in evalc below - else - error('YMA:findjobj:IllegalPrintFilter','Print filter must be a java handle or numeric index into handles'); - end - varargin(2) = []; - end - - % use evalc() to capture output into a Matlab variable - %listing = evalc('listingContainer.list'); - - % Better solution: loop over all handles and process them one by one - listing = cell(length(handles),1); - for componentIdx = 1 : length(handles) - listing{componentIdx} = [repmat(' ',1,levels(componentIdx)) char(handles(componentIdx).toString)]; - end - end - - %% Process 'position' option - function [varargin,foundIdx] = processPositionArgs(varargin) - if length(varargin)>1 - positionFilter = varargin{2}; - %if (isjava(positionFilter) || iscom(positionFilter)) && ismethod(positionFilter,'getLocation') - try % try-catch is faster... - % Java/COM object passed - get its position - positionFilter = positionFilter.getLocation; - filterXY = [positionFilter.getX, positionFilter.getY]; - catch - if ~isscalar(positionFilter) - % position vector passed - if (length(positionFilter)>=2) && isnumeric(positionFilter) - % Remember that java coordinates start at top-left corner, Matlab coords start at bottom left... - %positionFilter = java.awt.Point(positionFilter(1), container.getHeight - positionFilter(2)); - filterXY = [container.getX + positionFilter(1), container.getY + contentSize(2) - positionFilter(2)]; - - % Check for full Matlab position vector (x,y,w,h) - %if (length(positionFilter)==4) - % varargin{end+1} = 'size'; - % varargin{end+1} = fix(positionFilter(3:4)); - %end - else - error('YMA:findjobj:IllegalPositionFilter','Position filter must be a java UI component, or X,Y pair'); - end - elseif length(varargin)>2 - % x,y passed as separate arg values - if isnumeric(positionFilter) && isnumeric(varargin{3}) - % Remember that java coordinates start at top-left corner, Matlab coords start at bottom left... - %positionFilter = java.awt.Point(positionFilter, container.getHeight - varargin{3}); - filterXY = [container.getX + positionFilter, container.getY + contentSize(2) - varargin{3}]; - varargin(3) = []; - else - error('YMA:findjobj:IllegalPositionFilter','Position filter must be a java UI component, or X,Y pair'); - end - else - error('YMA:findjobj:IllegalPositionFilter','Position filter must be a java UI component, or X,Y pair'); - end - end - - % Compute the required element positions in order to be eligible for a more detailed examination - % Note: based on the following constraints: 0 <= abs(elementX-filterX) + abs(elementY+elementH-filterY) < 7 - baseDeltas = [positions(:,1)-filterXY(1), positions(:,2)-filterXY(2)]; % faster than repmat()... - %baseHeight = - baseDeltas(:,2);% -abs(baseDeltas(:,1)); - %minHeight = baseHeight - 7; - %maxHeight = baseHeight + 7; - %foundIdx = ~arrayfun(@(b)(invoke(b,'contains',positionFilter)),handles); % ARGH! - disallowed by Matlab! - %foundIdx = repmat(false,1,length(handles)); - %foundIdx(length(handles)) = false; % faster than repmat()... - foundIdx = (abs(baseDeltas(:,1)) < 7) & (abs(baseDeltas(:,2)) < 7); % & (minHeight >= 0); - %fi = find(foundIdx); - %for componentIdx = 1 : length(fi) - %foundIdx(componentIdx) = handles(componentIdx).getBounds.contains(positionFilter); - - % Search for a point no farther than 7 pixels away (prevents rounding errors) - %foundIdx(componentIdx) = handles(componentIdx).getLocationOnScreen.distanceSq(positionFilter) < 50; % fails for invisible components... - - %p = java.awt.Point(positions(componentIdx,1), positions(componentIdx,2) + handles(componentIdx).getHeight); - %foundIdx(componentIdx) = p.distanceSq(positionFilter) < 50; - - %foundIdx(componentIdx) = sum(([baseDeltas(componentIdx,1),baseDeltas(componentIdx,2)+handles(componentIdx).getHeight]).^2) < 50; - - % Following is the fastest method found to date: only eligible elements are checked in detailed - % elementHeight = handles(fi(componentIdx)).getHeight; - % foundIdx(fi(componentIdx)) = elementHeight > minHeight(fi(componentIdx)) && ... - % elementHeight < maxHeight(fi(componentIdx)); - %disp([componentIdx,elementHeight,minHeight(fi(componentIdx)),maxHeight(fi(componentIdx)),foundIdx(fi(componentIdx))]) - %end - - varargin(2) = []; - else - foundIdx = []; - end - end - - %% Process 'size' option - function [varargin,foundIdx] = processSizeArgs(varargin) - if length(varargin)>1 - sizeFilter = lower(varargin{2}); - %if (isjava(sizeFilter) || iscom(sizeFilter)) && ismethod(sizeFilter,'getSize') - try % try-catch is faster... - % Java/COM object passed - get its size - sizeFilter = sizeFilter.getSize; - filterWidth = sizeFilter.getWidth; - filterHeight = sizeFilter.getHeight; - catch - if ~isscalar(sizeFilter) - % size vector passed - if (length(sizeFilter)>=2) && isnumeric(sizeFilter) - %sizeFilter = java.awt.Dimension(sizeFilter(1),sizeFilter(2)); - filterWidth = sizeFilter(1); - filterHeight = sizeFilter(2); - else - error('YMA:findjobj:IllegalSizeFilter','Size filter must be a java UI component, or W,H pair'); - end - elseif length(varargin)>2 - % w,h passed as separate arg values - if isnumeric(sizeFilter) && isnumeric(varargin{3}) - %sizeFilter = java.awt.Dimension(sizeFilter,varargin{3}); - filterWidth = sizeFilter; - filterHeight = varargin{3}; - varargin(3) = []; - else - error('YMA:findjobj:IllegalSizeFilter','Size filter must be a java UI component, or W,H pair'); - end - else - error('YMA:findjobj:IllegalSizeFilter','Size filter must be a java UI component, or W,H pair'); - end - end - %foundIdx = ~arrayfun(@(b)(invoke(b,'contains',sizeFilter)),handles); % ARGH! - disallowed by Matlab! - foundIdx(length(handles)) = false; % faster than repmat()... - for componentIdx = 1 : length(handles) - %foundIdx(componentIdx) = handles(componentIdx).getSize.equals(sizeFilter); - % Allow a 2-pixel tollerance to account for non-integer pixel sizes - foundIdx(componentIdx) = abs(handles(componentIdx).getWidth - filterWidth) <= 3 && ... % faster than getSize.equals() - abs(handles(componentIdx).getHeight - filterHeight) <= 3; - end - varargin(2) = []; - else - foundIdx = []; - end - end - - %% Process 'class' option - function [varargin,foundIdx] = processClassArgs(varargin) - if length(varargin)>1 - classFilter = varargin{2}; - %if ismethod(classFilter,'getClass') - try % try-catch is faster... - classFilter = char(classFilter.getClass); - catch - if ~ischar(classFilter) - error('YMA:findjobj:IllegalClassFilter','Class filter must be a java object, class or string'); - end - end - - % Now convert all java classes to java.lang.Strings and compare to the requested filter string - try - foundIdx(length(handles)) = false; % faster than repmat()... - jClassFilter = java.lang.String(classFilter).toLowerCase; - for componentIdx = 1 : length(handles) - % Note: JVM 1.5's String.contains() appears slightly slower and is available only since Matlab 7.2 - foundIdx(componentIdx) = handles(componentIdx).getClass.toString.toLowerCase.indexOf(jClassFilter) >= 0; - end - catch - % Simple processing: slower since it does extra processing within opaque.char() - for componentIdx = 1 : length(handles) - % Note: using @toChar is faster but returns java String, not a Matlab char - foundIdx(componentIdx) = ~isempty(regexpi(char(handles(componentIdx).getClass),classFilter)); - end - end - - varargin(2) = []; - else - foundIdx = []; - end - end - - %% Process 'property' option - function [varargin,foundIdx] = processPropertyArgs(varargin) - if length(varargin)>1 - propertyName = varargin{2}; - if iscell(propertyName) - if length(propertyName) == 2 - propertyVal = propertyName{2}; - propertyName = propertyName{1}; - elseif length(propertyName) == 1 - propertyName = propertyName{1}; - else - error('YMA:findjobj:IllegalPropertyFilter','Property filter must be a string (case insensitive name of property) or cell array {propName,propValue}'); - end - end - if ~ischar(propertyName) - error('YMA:findjobj:IllegalPropertyFilter','Property filter must be a string (case insensitive name of property) or cell array {propName,propValue}'); - end - propertyName = lower(propertyName); - %foundIdx = arrayfun(@(h)isprop(h,propertyName),handles); % ARGH! - disallowed by Matlab! - foundIdx(length(handles)) = false; % faster than repmat()... - - % Split processing depending on whether a specific property value was requested (ugly but faster...) - if exist('propertyVal','var') - for componentIdx = 1 : length(handles) - try - % Find out whether this element has the specified property - % Note: findprop() and its return value schema.prop are undocumented and unsupported! - prop = findprop(handles(componentIdx),propertyName); % faster than isprop() & enables partial property names - - % If found, compare it to the actual element's property value - foundIdx(componentIdx) = ~isempty(prop) && isequal(get(handles(componentIdx),prop.Name),propertyVal); - catch - % Some Java classes have a write-only property (like LabelPeer with 'Text'), so we end up here - % In these cases, simply assume that the property value doesn't match and continue - foundIdx(componentIdx) = false; - end - end - else - for componentIdx = 1 : length(handles) - try - % Find out whether this element has the specified property - % Note: findprop() and its return value schema.prop are undocumented and unsupported! - foundIdx(componentIdx) = ~isempty(findprop(handles(componentIdx),propertyName)); - catch - foundIdx(componentIdx) = false; - end - end - end - varargin(2) = []; - else - foundIdx = []; - end - end - - %% Process 'depth' option - function [varargin,foundIdx] = processDepthArgs(varargin) - if length(varargin)>1 - level = varargin{2}; - if ~isnumeric(level) - error('YMA:findjobj:IllegalDepthFilter','Depth filter must be a number (=maximal element depth)'); - end - foundIdx = (levels <= level); - varargin(2) = []; - else - foundIdx = []; - end - end - - %% Convert property data into a string - function data = charizeData(data) - if isa(data,'com.mathworks.hg.types.HGCallback') - data = get(data,'Callback'); - end - if ~ischar(data) && ~isa(data,'java.lang.String') - newData = strtrim(evalc('disp(data)')); - try - newData = regexprep(newData,' +',' '); - newData = regexprep(newData,'Columns \d+ through \d+\s',''); - newData = regexprep(newData,'Column \d+\s',''); - catch - %never mind... - end - if iscell(data) - newData = ['{ ' newData ' }']; - elseif isempty(data) - newData = ''; - elseif isnumeric(data) || islogical(data) || any(ishandle(data)) || numel(data) > 1 %&& ~isscalar(data) - newData = ['[' newData ']']; - end - data = newData; - elseif ~isempty(data) - data = ['''' data '''']; - end - end % charizeData - - %% Prepare a hierarchical callbacks table data - function setProp(list,name,value,category) - prop = eval('com.jidesoft.grid.DefaultProperty();'); % prevent JIDE alert by run-time (not load-time) evaluation - prop.setName(name); - prop.setType(java.lang.String('').getClass); - prop.setValue(value); - prop.setEditable(true); - prop.setExpert(true); - %prop.setCategory(['' category ' callbacks']); - prop.setCategory([category ' callbacks']); - list.add(prop); - end % getTreeData - - %% Prepare a hierarchical callbacks table data - function list = getTreeData(data) - list = java.util.ArrayList(); - names = regexprep(data,'([A-Z][a-z]+).*','$1'); - %hash = java.util.Hashtable; - others = {}; - for propIdx = 1 : length(data) - if (propIdx < length(data) && strcmp(names{propIdx},names{propIdx+1})) || ... - (propIdx > 1 && strcmp(names{propIdx},names{propIdx-1})) - % Child callback property - setProp(list,data{propIdx,1},data{propIdx,2},names{propIdx}); - else - % Singular callback property => Add to 'Other' category at bottom of the list - others(end+1,:) = data(propIdx,:); %#ok - end - end - for propIdx = 1 : size(others,1) - setProp(list,others{propIdx,1},others{propIdx,2},'Other'); - end - end % getTreeData - - %% Get callbacks table data - function [cbData, cbHeaders, cbTableEnabled] = getCbsData(obj, stripStdCbsFlag) - % Initialize - cbData = {'(no callbacks)'}; - cbHeaders = {'Callback name'}; - cbTableEnabled = false; - - try - classHdl = classhandle(handle(obj)); - cbNames = get(classHdl.Events,'Name'); - if ~isempty(cbNames) && ~iscom(obj) %only java-based please... - cbNames = strcat(cbNames,'Callback'); - end - propNames = get(classHdl.Properties,'Name'); - propCbIdx = []; - if ischar(propNames), propNames={propNames}; end % handle case of a single callback - if ~isempty(propNames) - propCbIdx = find(~cellfun(@isempty,regexp(propNames,'(Fcn|Callback)$'))); - cbNames = unique([cbNames; propNames(propCbIdx)]); %#ok logical is faster but less debuggable... - end - if ~isempty(cbNames) - if stripStdCbsFlag - cbNames = stripStdCbs(cbNames); - end - if iscell(cbNames) - cbNames = sort(cbNames); - if size(cbNames,1) < size(cbNames,2) - cbNames = cbNames'; - end - end - hgHandleFlag = 0; try hgHandleFlag = ishghandle(obj); catch, end %#ok - try - obj = handle(obj,'CallbackProperties'); - catch - hgHandleFlag = 1; - end - if hgHandleFlag - % HG handles don't allow CallbackProperties - search only for *Fcn - cbNames = propNames(propCbIdx); - end - if iscom(obj) - cbs = obj.eventlisteners; - if ~isempty(cbs) - cbNamesRegistered = cbs(:,1); - cbData = setdiff(cbNames,cbNamesRegistered); - %cbData = charizeData(cbData); - if size(cbData,2) > size(cbData(1)) - cbData = cbData'; - end - cbData = [cbData, cellstr(repmat(' ',length(cbData),1))]; - cbData = [cbData; cbs]; - [sortedNames, sortedIdx] = sort(cbData(:,1)); - sortedCbs = cellfun(@charizeData,cbData(sortedIdx,2),'un',0); - cbData = [sortedNames, sortedCbs]; - else - cbData = [cbNames, cellstr(repmat(' ',length(cbNames),1))]; - end - elseif iscell(cbNames) - cbNames = sort(cbNames); - %cbData = [cbNames, get(obj,cbNames)']; - cbData = cbNames; - oldWarn = warning('off','MATLAB:hg:JavaSetHGProperty'); - warning('off','MATLAB:hg:PossibleDeprecatedJavaSetHGProperty'); - for idx = 1 : length(cbNames) - try - cbData{idx,2} = charizeData(get(obj,cbNames{idx})); - catch - cbData{idx,2} = '(callback value inaccessible)'; - end - end - warning(oldWarn); - else % only one event callback - %cbData = {cbNames, get(obj,cbNames)'}; - %cbData{1,2} = charizeData(cbData{1,2}); - try - cbData = {cbNames, charizeData(get(obj,cbNames))}; - catch - cbData = {cbNames, '(callback value inaccessible)'}; - end - end - cbHeaders = {'Callback name','Callback value'}; - cbTableEnabled = true; - end - catch - % never mind - use default (empty) data - end - end % getCbsData - - %% Get relative (0.0-1.0) divider location - function divLocation = getRalativeDivlocation(jDiv) - divLocation = jDiv.getDividerLocation; - if divLocation > 1 % i.e. [pixels] - visibleRect = jDiv.getVisibleRect; - if jDiv.getOrientation == 0 % vertical - start = visibleRect.getY; - extent = visibleRect.getHeight - start; - else - start = visibleRect.getX; - extent = visibleRect.getWidth - start; - end - divLocation = (divLocation - start) / extent; - end - end % getRalativeDivlocation - - %% Try to set a treenode icon based on a container's icon - function setTreeNodeIcon(treenode,container) - try - iconImage = []; - iconImage = container.getIcon; - if ~isempty(findprop(handle(iconImage),'Image')) % get(iconImage,'Image') is easier but leaks memory... - iconImage = iconImage.getImage; - else - a=b; %#ok cause an error - end - catch - try - iconImage = container.getIconImage; - catch - try - if ~isempty(iconImage) - ge = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment; - gd = ge.getDefaultScreenDevice; - gc = gd.getDefaultConfiguration; - image = gc.createCompatibleImage(iconImage.getIconWidth, iconImage.getIconHeight); % a BufferedImage object - g = image.createGraphics; - iconImage.paintIcon([], g, 0, 0); - g.dispose; - iconImage = image; - end - catch - % never mind... - end - end - end - if ~isempty(iconImage) - iconImage = setIconSize(iconImage); - treenode.setIcon(iconImage); - end - end % setTreeNodeIcon - - %% Present the object hierarchy tree - function presentObjectTree() - import java.awt.* - import javax.swing.* - hTreeFig = findall(0,'tag','findjobjFig'); - iconpath = [matlabroot, '/toolbox/matlab/icons/']; - cbHideStd = 0; % Initial state of the cbHideStdCbs checkbox - if isempty(hTreeFig) - % Prepare the figure - hTreeFig = figure('tag','findjobjFig','menuBar','none','toolBar','none','Name','FindJObj','NumberTitle','off','handleVisibility','off','IntegerHandle','off'); - figIcon = ImageIcon([iconpath 'tool_legend.gif']); - drawnow; - try - mde = com.mathworks.mde.desk.MLDesktop.getInstance; - jTreeFig = mde.getClient('FindJObj').getTopLevelAncestor; - jTreeFig.setIcon(figIcon); - catch - warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); % R2008b compatibility - jTreeFig = get(hTreeFig,'JavaFrame'); - jTreeFig.setFigureIcon(figIcon); - end - vsplitPaneLocation = 0.8; - hsplitPaneLocation = 0.5; - else - % Remember cbHideStdCbs checkbox & dividers state for later - userdata = get(hTreeFig, 'userdata'); - try cbHideStd = userdata.cbHideStdCbs.isSelected; catch, end %#ok - try - vsplitPaneLocation = getRalativeDivlocation(userdata.vsplitPane); - hsplitPaneLocation = getRalativeDivlocation(userdata.hsplitPane); - catch - vsplitPaneLocation = 0.8; - hsplitPaneLocation = 0.5; - end - - % Clear the figure and redraw - clf(hTreeFig); - figure(hTreeFig); % bring to front - end - - % Traverse all HG children, if root container was a HG handle - if ishghandle(origContainer) %&& ~isequal(origContainer,container) - traverseHGContainer(origContainer,0,0); - end - - % Prepare the tree pane - warning('off','MATLAB:uitreenode:MigratingFunction'); % R2008b compatibility - warning('off','MATLAB:uitreenode:DeprecatedFunction'); % R2008a compatibility - tree_h = com.mathworks.hg.peer.UITreePeer; - hasChildren = sum(allParents==1) > 1; - icon = [iconpath 'upfolder.gif']; - [rootName, rootTitle] = getNodeName(container); - try - root = uitreenode('v0', handle(container), rootName, icon, ~hasChildren); - catch % old matlab version don't have the 'v0' option - root = uitreenode(handle(container), rootName, icon, ~hasChildren); - end - setTreeNodeIcon(root,container); % constructor must accept a char icon unfortunately, so need to do this afterwards... - if ~isempty(rootTitle) - set(hTreeFig, 'Name',['FindJObj - ' char(rootTitle)]); - end - nodedata.idx = 1; - nodedata.obj = container; - set(root,'userdata',nodedata); - root.setUserObject(container); - setappdata(root,'childHandle',container); - tree_h.setRoot(root); - treePane = tree_h.getScrollPane; - treePane.setMinimumSize(Dimension(50,50)); - jTreeObj = treePane.getViewport.getComponent(0); - jTreeObj.setShowsRootHandles(true) - jTreeObj.getSelectionModel.setSelectionMode(javax.swing.tree.TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); - %jTreeObj.setVisible(0); - %jTreeObj.getCellRenderer.setLeafIcon([]); - %jTreeObj.getCellRenderer.setOpenIcon(figIcon); - %jTreeObj.getCellRenderer.setClosedIcon([]); - treePanel = JPanel(BorderLayout); - treePanel.add(treePane, BorderLayout.CENTER); - progressBar = JProgressBar(0); - progressBar.setMaximum(length(allHandles) + length(hg_handles)); % = # of all nodes - treePanel.add(progressBar, BorderLayout.SOUTH); - - % Prepare the image pane -%disable for now, until we get it working... -%{ - try - hFig = ancestor(origContainer,'figure'); - [cdata, cm] = getframe(hFig); %#ok cm unused - tempfname = [tempname '.png']; - imwrite(cdata,tempfname); % don't know how to pass directly to BufferedImage, so use disk... - jImg = javax.imageio.ImageIO.read(java.io.File(tempfname)); - try delete(tempfname); catch end - imgPanel = JPanel(); - leftPanel = JSplitPane(JSplitPane.VERTICAL_SPLIT, treePanel, imgPanel); - leftPanel.setOneTouchExpandable(true); - leftPanel.setContinuousLayout(true); - leftPanel.setResizeWeight(0.8); - catch - leftPanel = treePanel; - end -%} - leftPanel = treePanel; - - % Prepare the inspector pane - classNameLabel = JLabel([' ' char(class(container))]); - classNameLabel.setForeground(Color.blue); - updateNodeTooltip(container, classNameLabel); - inspectorPanel = JPanel(BorderLayout); - inspectorPanel.add(classNameLabel, BorderLayout.NORTH); - % TODO: Maybe uncomment the following when we add the HG tree - in the meantime it's unused (java properties are un-groupable) - %objReg = com.mathworks.services.ObjectRegistry.getLayoutRegistry; - %toolBar = awtinvoke('com.mathworks.mlwidgets.inspector.PropertyView$ToolBarStyle','valueOf(Ljava.lang.String;)','GROUPTOOLBAR'); - %inspectorPane = com.mathworks.mlwidgets.inspector.PropertyView(objReg, toolBar); - inspectorPane = com.mathworks.mlwidgets.inspector.PropertyView; - identifiers = disableDbstopError; %#ok "dbstop if error" causes inspect.m to croak due to a bug - so workaround - inspectorPane.setObject(container); - inspectorPane.setAutoUpdate(true); - % TODO: Add property listeners - % TODO: Display additional props - inspectorTable = inspectorPane; - try - while ~isa(inspectorTable,'javax.swing.JTable') - inspectorTable = inspectorTable.getComponent(0); - end - catch - % R2010a - inspectorTable = inspectorPane.getComponent(0).getScrollPane.getViewport.getComponent(0); - end - toolTipText = 'hover mouse over the red classname above to see the full list of properties'; - inspectorTable.setToolTipText(toolTipText); - jideTableUtils = []; - try - % Try JIDE features - see http://www.jidesoft.com/products/JIDE_Grids_Developer_Guide.pdf - com.mathworks.mwswing.MJUtilities.initJIDE; - jideTableUtils = eval('com.jidesoft.grid.TableUtils;'); % prevent JIDE alert by run-time (not load-time) evaluation - jideTableUtils.autoResizeAllColumns(inspectorTable); - inspectorTable.setRowAutoResizes(true); - inspectorTable.getModel.setShowExpert(1); - catch - % JIDE is probably unavailable - never mind... - end - inspectorPanel.add(inspectorPane, BorderLayout.CENTER); - % TODO: Add data update listeners - - % Prepare the callbacks pane - callbacksPanel = JPanel(BorderLayout); - stripStdCbsFlag = true; % initial value - [cbData, cbHeaders, cbTableEnabled] = getCbsData(container, stripStdCbsFlag); - %{ - %classHdl = classhandle(handle(container)); - %eventNames = get(classHdl.Events,'Name'); - %if ~isempty(eventNames) - % cbNames = sort(strcat(eventNames,'Callback')); - % try - % cbData = [cbNames, get(container,cbNames)']; - % catch - % % R2010a - % cbData = cbNames; - % if isempty(cbData) - % cbData = {}; - % elseif ~iscell(cbData) - % cbData = {cbData}; - % end - % for idx = 1 : length(cbNames) - % cbData{idx,2} = get(container,cbNames{idx}); - % end - % end - % cbTableEnabled = true; - %else - % cbData = {'(no callbacks)',''}; - % cbTableEnabled = false; - %end - %cbHeaders = {'Callback name','Callback value'}; - %} - try - % Use JideTable if available on this system - %callbacksTableModel = javax.swing.table.DefaultTableModel(cbData,cbHeaders); %#ok - %callbacksTable = eval('com.jidesoft.grid.PropertyTable(callbacksTableModel);'); % prevent JIDE alert by run-time (not load-time) evaluation - try - list = getTreeData(cbData); %#ok - model = eval('com.jidesoft.grid.PropertyTableModel(list);'); %#ok prevent JIDE alert by run-time (not load-time) evaluation - - % Auto-expand if only one category - if model.getRowCount==1 % length(model.getCategories)==1 fails for some unknown reason... - model.expandFirstLevel; - end - - %callbacksTable = eval('com.jidesoft.grid.TreeTable(model);'); %#ok prevent JIDE alert by run-time (not load-time) evaluation - callbacksTable = eval('com.jidesoft.grid.PropertyTable(model);'); %#ok prevent JIDE alert by run-time (not load-time) evaluation - - %callbacksTable.expandFirstLevel; - callbacksTable.setShowsRootHandles(true); - callbacksTable.setShowTreeLines(false); - %callbacksTable.setShowNonEditable(0); %=SHOW_NONEDITABLE_NEITHER - callbacksPane = eval('com.jidesoft.grid.PropertyPane(callbacksTable);'); % prevent JIDE alert by run-time (not load-time) evaluation - callbacksPane.setShowDescription(false); - catch - callbacksTable = eval('com.jidesoft.grid.TreeTable(cbData,cbHeaders);'); % prevent JIDE alert by run-time (not load-time) evaluation - end - callbacksTable.setRowAutoResizes(true); - callbacksTable.setColumnAutoResizable(true); - callbacksTable.setColumnResizable(true); - jideTableUtils.autoResizeAllColumns(callbacksTable); - callbacksTable.setTableHeader([]); % hide the column headers since now we can resize columns with the gridline - callbacksLabel = JLabel(' Callbacks:'); % The column headers are replaced with a header label - callbacksLabel.setForeground(Color.blue); - %callbacksPanel.add(callbacksLabel, BorderLayout.NORTH); - - % Add checkbox to show/hide standard callbacks - callbacksTopPanel = JPanel; - callbacksTopPanel.setLayout(BoxLayout(callbacksTopPanel, BoxLayout.LINE_AXIS)); - callbacksTopPanel.add(callbacksLabel); - callbacksTopPanel.add(Box.createHorizontalGlue); - jcb = JCheckBox('Hide standard callbacks', cbHideStd); - set(handle(jcb,'CallbackProperties'), 'ActionPerformedCallback',{@cbHideStdCbs_Callback,callbacksTable}); - try - set(jcb, 'userdata',callbacksTable, 'tooltip','Hide standard Swing callbacks - only component-specific callbacks will be displayed'); - catch - jcb.setToolTipText('Hide standard Swing callbacks - only component-specific callbacks will be displayed'); - %setappdata(jcb,'userdata',callbacksTable); - end - callbacksTopPanel.add(jcb); - callbacksPanel.add(callbacksTopPanel, BorderLayout.NORTH); - catch - % Otherwise, use a standard Swing JTable (keep the headers to enable resizing) - callbacksTable = JTable(cbData,cbHeaders); - end - cbToolTipText = 'Callbacks may be ''strings'', @funcHandle or {@funcHandle,arg1,...}'; - callbacksTable.setToolTipText(cbToolTipText); - callbacksTable.setGridColor(inspectorTable.getGridColor); - cbNameTextField = JTextField; - cbNameTextField.setEditable(false); % ensure that the callback names are not modified... - cbNameCellEditor = DefaultCellEditor(cbNameTextField); - cbNameCellEditor.setClickCountToStart(intmax); % i.e, never enter edit mode... - callbacksTable.getColumnModel.getColumn(0).setCellEditor(cbNameCellEditor); - if ~cbTableEnabled - callbacksTable.getColumnModel.getColumn(1).setCellEditor(cbNameCellEditor); - end - hModel = callbacksTable.getModel; - set(handle(hModel,'CallbackProperties'), 'TableChangedCallback',{@tbCallbacksChanged,container,callbacksTable}); - %set(hModel, 'UserData',container); - try - cbScrollPane = callbacksPane; %JScrollPane(callbacksPane); - %cbScrollPane.setHorizontalScrollBarPolicy(cbScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - catch - cbScrollPane = JScrollPane(callbacksTable); - cbScrollPane.setVerticalScrollBarPolicy(cbScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); - end - callbacksPanel.add(cbScrollPane, BorderLayout.CENTER); - callbacksPanel.setToolTipText(cbToolTipText); - - % Prepare the top-bottom JSplitPanes - vsplitPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, inspectorPanel, callbacksPanel); - vsplitPane.setOneTouchExpandable(true); - vsplitPane.setContinuousLayout(true); - vsplitPane.setResizeWeight(0.8); - - % Prepare the left-right JSplitPane - hsplitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, vsplitPane); - hsplitPane.setOneTouchExpandable(true); - hsplitPane.setContinuousLayout(true); - hsplitPane.setResizeWeight(0.6); - pos = getpixelposition(hTreeFig); - - % Prepare the bottom pane with all buttons - lowerPanel = JPanel(FlowLayout); - blogUrlLabel = 'Undocumented
Matlab.com
'; - jWebsite = createJButton(blogUrlLabel, @btWebsite_Callback, 'Visit the UndocumentedMatlab.com blog'); - jWebsite.setContentAreaFilled(0); - lowerPanel.add(jWebsite); - lowerPanel.add(createJButton('Refresh
tree', {@btRefresh_Callback, origContainer, hTreeFig}, 'Rescan the component tree, from the root down')); - lowerPanel.add(createJButton('Export to
workspace', {@btExport_Callback, jTreeObj, classNameLabel}, 'Export the selected component handles to workspace variable findjobj_hdls')); - lowerPanel.add(createJButton('Request
focus', {@btFocus_Callback, jTreeObj, root}, 'Set the focus on the first selected component')); - lowerPanel.add(createJButton('Inspect
object', {@btInspect_Callback, jTreeObj, root}, 'View the signature of all methods supported by the first selected component')); - lowerPanel.add(createJButton('Check for
updates', {@btCheckFex_Callback}, 'Check the MathWorks FileExchange for the latest version of FindJObj')); - - % Display everything on-screen - globalPanel = JPanel(BorderLayout); - globalPanel.add(hsplitPane, BorderLayout.CENTER); - globalPanel.add(lowerPanel, BorderLayout.SOUTH); - [obj, hcontainer] = javacomponent(globalPanel, [0,0,pos(3:4)], hTreeFig); - set(hcontainer,'units','normalized'); - drawnow; - hsplitPane.setDividerLocation(hsplitPaneLocation); % this only works after the JSplitPane is displayed... - vsplitPane.setDividerLocation(vsplitPaneLocation); % this only works after the JSplitPane is displayed... - %restoreDbstopError(identifiers); - - % Refresh & resize the screenshot thumbnail -%disable for now, until we get it working... -%{ - try - hAx = axes('Parent',hTreeFig, 'units','pixels', 'position',[10,10,250,150], 'visible','off'); - axis(hAx,'image'); - image(cdata,'Parent',hAx); - axis(hAx,'off'); - set(hAx,'UserData',cdata); - set(imgPanel, 'ComponentResizedCallback',{@resizeImg, hAx}, 'UserData',lowerPanel); - imgPanel.getGraphics.drawImage(jImg, 0, 0, []); - catch - % Never mind... - end -%} - % If all handles were selected (i.e., none were filtered) then only select the first - if (length(selectedIdx) == length(allHandles)) && ~isempty(selectedIdx) - selectedIdx = 1; - end - - % Store handles for callback use - userdata.handles = allHandles; - userdata.levels = allLevels; - userdata.parents = allParents; - userdata.hg_handles = hg_handles; - userdata.hg_levels = hg_levels; - userdata.hg_parents = hg_parentIdx; - userdata.initialIdx = selectedIdx; - userdata.userSelected = false; % Indicates the user has modified the initial selections - userdata.inInit = true; - userdata.jTree = jTreeObj; - userdata.jTreePeer = tree_h; - userdata.vsplitPane = vsplitPane; - userdata.hsplitPane = hsplitPane; - userdata.classNameLabel = classNameLabel; - userdata.inspectorPane = inspectorPane; - userdata.callbacksTable = callbacksTable; - userdata.jideTableUtils = jideTableUtils; - try - userdata.cbHideStdCbs = jcb; - catch - userdata.cbHideStdCbs = []; - end - - % Update userdata for use in callbacks - try - set(tree_h,'userdata',userdata); - catch - setappdata(tree_h,'userdata',userdata); - end - try - set(callbacksTable,'userdata',userdata); - catch - setappdata(callbacksTable,'userdata',userdata); - end - set(hTreeFig,'userdata',userdata); - - % Select the root node if requested - % Note: we must do so here since all other nodes except the root are processed by expandNode - if any(selectedIdx==1) - tree_h.setSelectedNode(root); - end - - % Set the initial cbHideStdCbs state - try - if jcb.isSelected - drawnow; - evd.getSource.isSelected = jcb.isSelected; - cbHideStdCbs_Callback(jcb,evd,callbacksTable); - end - catch - % never mind... - end - - % Set the callback functions - tree_hh = handle(tree_h,'CallbackProperties'); - set(tree_hh, 'NodeExpandedCallback', {@nodeExpanded, tree_h}); - set(tree_hh, 'NodeSelectedCallback', {@nodeSelected, tree_h}); - - % Set the tree mouse-click callback - % Note: default actions (expand/collapse) will still be performed? - % Note: MousePressedCallback is better than MouseClickedCallback - % since it fires immediately when mouse button is pressed, - % without waiting for its release, as MouseClickedCallback does - handleTree = tree_h.getScrollPane; - jTreeObj = handleTree.getViewport.getComponent(0); - jTreeObjh = handle(jTreeObj,'CallbackProperties'); - set(jTreeObjh, 'MousePressedCallback', {@treeMousePressedCallback,tree_h}); % context (right-click) menu - set(jTreeObjh, 'MouseMovedCallback', @treeMouseMovedCallback); % mouse hover tooltips - - % Update userdata - userdata.inInit = false; - try - set(tree_h,'userdata',userdata); - catch - setappdata(tree_h,'userdata',userdata); - end - set(hTreeFig,'userdata',userdata); - - % Pre-expand all rows - expandNode(progressBar, jTreeObj, tree_h, root, 0); - %jTreeObj.setVisible(1); - - % Hide the progressbar now that we've finished expanding all rows - try - hsplitPane.getLeftComponent.setTopComponent(treePane); - catch - % Probably not a vSplitPane on the left... - hsplitPane.setLeftComponent(treePane); - end - hsplitPane.setDividerLocation(hsplitPaneLocation); % need to do it again... - - % Set keyboard focus on the tree - jTreeObj.requestFocus; - drawnow; - - % Check for a newer version - checkVersion(); - - % Reset the last error - lasterr(''); %#ok - end - - %% Rresize image pane - function resizeImg(varargin) %#ok - unused (TODO: waiting for img placement fix...) - try - hPanel = varargin{1}; - hAx = varargin{3}; - lowerPanel = get(hPanel,'UserData'); - newJPos = cell2mat(get(hPanel,{'X','Y','Width','Height'})); - newMPos = [1,get(lowerPanel,'Height'),newJPos(3:4)]; - set(hAx, 'units','pixels', 'position',newMPos, 'Visible','on'); - uistack(hAx,'top'); % no good... - set(hPanel,'Opaque','off'); % also no good... - catch - % Never mind... - dispError - end - return; - end - - %% "dbstop if error" causes inspect.m to croak due to a bug - so workaround by temporarily disabling this dbstop - function identifiers = disableDbstopError - dbStat = dbstatus; - idx = find(strcmp({dbStat.cond},'error')); - identifiers = [dbStat(idx).identifier]; - if ~isempty(idx) - dbclear if error; - msgbox('''dbstop if error'' had to be disabled due to a Matlab bug that would have caused Matlab to crash.', 'FindJObj', 'warn'); - end - end - - %% Restore any previous "dbstop if error" - function restoreDbstopError(identifiers) %#ok - for itemIdx = 1 : length(identifiers) - eval(['dbstop if error ' identifiers{itemIdx}]); - end - end - - %% Recursively expand all nodes (except toolbar/menubar) in startup - function expandNode(progressBar, tree, tree_h, parentNode, parentRow) - try - if nargin < 5 - parentPath = javax.swing.tree.TreePath(parentNode.getPath); - parentRow = tree.getRowForPath(parentPath); - end - tree.expandRow(parentRow); - progressBar.setValue(progressBar.getValue+1); - numChildren = parentNode.getChildCount; - if (numChildren == 0) - pause(0.0002); % as short as possible... - drawnow; - end - nodesToUnExpand = {'FigureMenuBar','MLMenuBar','MJToolBar','Box','uimenu','uitoolbar','ScrollBar'}; - numChildren = parentNode.getChildCount; - for childIdx = 0 : numChildren-1 - childNode = parentNode.getChildAt(childIdx); - - % Pre-select the node based upon the user's FINDJOBJ filters - try - nodedata = get(childNode, 'userdata'); - try - userdata = get(tree_h, 'userdata'); - catch - userdata = getappdata(tree_h, 'userdata'); - end - %fprintf('%d - %s\n',nodedata.idx,char(nodedata.obj)) - if ~ishghandle(nodedata.obj) && ~userdata.userSelected && any(userdata.initialIdx == nodedata.idx) - pause(0.0002); % as short as possible... - drawnow; - if isempty(tree_h.getSelectedNodes) - tree_h.setSelectedNode(childNode); - else - newSelectedNodes = [tree_h.getSelectedNodes, childNode]; - tree_h.setSelectedNodes(newSelectedNodes); - end - end - catch - % never mind... - dispError - end - - % Expand child node if not leaf & not toolbar/menubar - if childNode.isLeafNode - - % This is a leaf node, so simply update the progress-bar - progressBar.setValue(progressBar.getValue+1); - - else - % Expand all non-leaves - expandNode(progressBar, tree, tree_h, childNode); - - % Re-collapse toolbar/menubar etc., and also invisible containers - % Note: if we simply did nothing, progressbar would not have been updated... - try - childHandle = getappdata(childNode,'childHandle'); %=childNode.getUserObject - visible = childHandle.isVisible; - catch - visible = 1; - end - visible = visible && isempty(findstr(get(childNode,'Name'),'color="gray"')); - %if any(strcmp(childNode.getName,nodesToUnExpand)) - %name = char(childNode.getName); - if any(cellfun(@(s)~isempty(strmatch(s,char(childNode.getName))),nodesToUnExpand)) || ~visible - childPath = javax.swing.tree.TreePath(childNode.getPath); - childRow = tree.getRowForPath(childPath); - tree.collapseRow(childRow); - end - end - end - catch - % never mind... - dispError - end - end - - %% Create utility buttons - function hButton = createJButton(nameStr, handler, toolTipText) - try - jButton = javax.swing.JButton(['
' nameStr]); - jButton.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.HAND_CURSOR)); - jButton.setToolTipText(toolTipText); - try - minSize = jButton.getMinimumSize; - catch - minSize = jButton.getMinimumSize; % for HG2 - strange indeed that this is needed! - end - jButton.setMinimumSize(java.awt.Dimension(minSize.getWidth,35)); - hButton = handle(jButton,'CallbackProperties'); - set(hButton,'ActionPerformedCallback',handler); - catch - % Never mind... - a= 1; - end - end - - %% Flash a component off/on for the specified duration - % note: starts with 'on'; if numTimes is odd then ends with 'on', otherwise with 'off' - function flashComponent(jComps,delaySecs,numTimes) - persistent redBorder redBorderPanels - try - % Handle callback data from right-click (context-menu) - if iscell(numTimes) - [jComps,delaySecs,numTimes] = deal(numTimes{:}); - end - - if isempty(redBorder) % reuse if possible - redBorder = javax.swing.border.LineBorder(java.awt.Color.red,2,0); - end - for compIdx = 1 : length(jComps) - try - oldBorder{compIdx} = jComps(compIdx).getBorder; %#ok grow - catch - oldBorder{compIdx} = []; %#ok grow - end - isSettable(compIdx) = ismethod(jComps(compIdx),'setBorder'); %#ok grow - if isSettable(compIdx) - try - % some components prevent border modification: - oldBorderFlag = jComps(compIdx).isBorderPainted; - if ~oldBorderFlag - jComps(compIdx).setBorderPainted(1); - isSettable(compIdx) = jComps(compIdx).isBorderPainted; %#ok grow - jComps(compIdx).setBorderPainted(oldBorderFlag); - end - catch - % do nothing... - end - end - if compIdx > length(redBorderPanels) - redBorderPanels{compIdx} = javax.swing.JPanel; - redBorderPanels{compIdx}.setBorder(redBorder); - redBorderPanels{compIdx}.setOpaque(0); % transparent interior, red border - end - try - redBorderPanels{compIdx}.setBounds(jComps(compIdx).getBounds); - catch - % never mind - might be an HG handle - end - end - for idx = 1 : 2*numTimes - if idx>1, pause(delaySecs); end % don't pause at start - visible = mod(idx,2); - for compIdx = 1 : length(jComps) - try - jComp = jComps(compIdx); - - % Prevent Matlab crash (java buffer overflow...) - if jComp.isa('com.mathworks.mwswing.desk.DTSplitPane') || ... - jComp.isa('com.mathworks.mwswing.MJSplitPane') - continue; - end - - % HG handles are highlighted by setting their 'Selected' property - if isa(jComp,'uimenu') - if visible - oldColor = get(jComp,'ForegroundColor'); - setappdata(jComp,'findjobj_oldColor',oldColor); - set(jComp,'ForegroundColor','red'); - else - oldColor = getappdata(jComp,'findjobj_oldColor'); - set(jComp,'ForegroundColor',oldColor); - rmappdata(jComp,'ForegroundColor'); - end - - elseif ishghandle(jComp) - if visible - set(jComp,'Selected','on'); - else - set(jComp,'Selected','off'); - end - - else %if isjava(jComp) - - jParent = jComps(compIdx).getParent; - - % Most Java components allow modifying their borders - if isSettable(compIdx) - if visible - jComp.setBorder(redBorder); - try jComp.setBorderPainted(1); catch, end %#ok - else %if ~isempty(oldBorder{compIdx}) - jComp.setBorder(oldBorder{compIdx}); - end - jComp.repaint; - - % The other Java components are highlighted by a transparent red-border - % panel that is placed on top of them in their parent's space - elseif ~isempty(jParent) - if visible - jParent.add(redBorderPanels{compIdx}); - jParent.setComponentZOrder(redBorderPanels{compIdx},0); - else - jParent.remove(redBorderPanels{compIdx}); - end - jParent.repaint - end - end - catch - % never mind - try the next component (if any) - end - end - drawnow; - end - catch - % never mind... - dispError; - end - return; % debug point - end % flashComponent - - %% Select tree node - function nodeSelected(src, evd, tree) %#ok - try - if iscell(tree) - [src,node] = deal(tree{:}); - else - node = evd.getCurrentNode; - end - %nodeHandle = node.getUserObject; - nodedata = get(node,'userdata'); - nodeHandle = nodedata.obj; - try - userdata = get(src,'userdata'); - catch - try - userdata = getappdata(java(src),'userdata'); - catch - userdata = getappdata(src,'userdata'); - end - if isempty(userdata) - try userdata = get(java(src),'userdata'); catch, end - end - end - if ~isempty(nodeHandle) && ~isempty(userdata) - numSelections = userdata.jTree.getSelectionCount; - selectionPaths = userdata.jTree.getSelectionPaths; - if (numSelections == 1) - % Indicate that the user has modified the initial selection (except if this was an initial auto-selected node) - if ~userdata.inInit - userdata.userSelected = true; - try - set(src,'userdata',userdata); - catch - try - setappdata(java(src),'userdata',userdata); - catch - setappdata(src,'userdata',userdata); - end - end - end - - % Update the fully-qualified class name label - numInitialIdx = length(userdata.initialIdx); - thisHandle = nodeHandle; - try - if ~ishghandle(thisHandle) - thisHandle = java(nodeHandle); - end - catch - % never mind... - end - if ~userdata.inInit || (numInitialIdx == 1) - userdata.classNameLabel.setText([' ' char(class(thisHandle))]); - else - userdata.classNameLabel.setText([' ' num2str(numInitialIdx) 'x handles (some handles hidden by unexpanded tree nodes)']); - end - if ishghandle(thisHandle) - userdata.classNameLabel.setText(userdata.classNameLabel.getText.concat(' (HG handle)')); - end - userdata.inspectorPane.dispose; % remove props listeners - doesn't work... - updateNodeTooltip(nodeHandle, userdata.classNameLabel); - - % Update the data properties inspector pane - % Note: we can't simply use the evd nodeHandle, because this node might have been DE-selected with only one other node left selected... - %nodeHandle = selectionPaths(1).getLastPathComponent.getUserObject; - nodedata = get(selectionPaths(1).getLastPathComponent,'userdata'); - nodeHandle = nodedata.obj; - %identifiers = disableDbstopError; % "dbstop if error" causes inspect.m to croak due to a bug - so workaround - userdata.inspectorPane.setObject(thisHandle); - - % Update the callbacks table - try - stripStdCbsFlag = getappdata(userdata.callbacksTable,'hideStdCbs'); - [cbData, cbHeaders, cbTableEnabled] = getCbsData(nodeHandle, stripStdCbsFlag); %#ok cbTableEnabled unused - try - % Use JideTable if available on this system - list = getTreeData(cbData); %#ok - callbacksTableModel = eval('com.jidesoft.grid.PropertyTableModel(list);'); %#ok prevent JIDE alert by run-time (not load-time) evaluation - - % Expand if only one category - if length(callbacksTableModel.getCategories)==1 - callbacksTableModel.expandFirstLevel; - end - catch - callbacksTableModel = javax.swing.table.DefaultTableModel(cbData,cbHeaders); - end - set(handle(callbacksTableModel,'CallbackProperties'), 'TableChangedCallback',{@tbCallbacksChanged,nodeHandle,userdata.callbacksTable}); - %set(callbacksTableModel, 'UserData',nodeHandle); - userdata.callbacksTable.setModel(callbacksTableModel) - userdata.callbacksTable.setRowAutoResizes(true); - userdata.jideTableUtils.autoResizeAllColumns(userdata.callbacksTable); - catch - % never mind... - %dispError - end - pause(0.005); - drawnow; - %restoreDbstopError(identifiers); - - % Highlight the selected object (if visible) - flashComponent(nodeHandle,0.2,3); - - elseif (numSelections > 1) % Multiple selections - - % Get the list of all selected nodes - jArray = javaArray('java.lang.Object', numSelections); - toolTipStr = ''; - sameClassFlag = true; - for idx = 1 : numSelections - %jArray(idx) = selectionPaths(idx).getLastPathComponent.getUserObject; - nodedata = get(selectionPaths(idx).getLastPathComponent,'userdata'); - try - jArray(idx) = java(nodedata.obj); - catch - jArray(idx) = nodedata.obj; - end - toolTipStr = [toolTipStr ' ' class(jArray(idx)) ' ']; %#ok grow - if (idx < numSelections), toolTipStr = [toolTipStr '
']; end %#ok grow - if (idx > 1) && sameClassFlag && ~isequal(jArray(idx).getClass,jArray(1).getClass) - sameClassFlag = false; - end - end - toolTipStr = [toolTipStr '']; - - % Update the fully-qualified class name label - if sameClassFlag - classNameStr = class(jArray(1)); - else - classNameStr = 'handle'; - end - if all(ishghandle(jArray)) - if strcmp(classNameStr,'handle') - classNameStr = 'HG handles'; - else - classNameStr = [classNameStr ' (HG handles)']; - end - end - classNameStr = [' ' num2str(numSelections) 'x ' classNameStr]; - userdata.classNameLabel.setText(classNameStr); - userdata.classNameLabel.setToolTipText(toolTipStr); - - % Update the data properties inspector pane - %identifiers = disableDbstopError; % "dbstop if error" causes inspect.m to croak due to a bug - so workaround - userdata.inspectorPane.getRegistry.setSelected(jArray, true); - - % Update the callbacks table - try - % Get intersecting callback names & values - stripStdCbsFlag = getappdata(userdata.callbacksTable,'hideStdCbs'); - [cbData, cbHeaders, cbTableEnabled] = getCbsData(jArray(1), stripStdCbsFlag); %#ok cbHeaders & cbTableEnabled unused - if ~isempty(cbData) - cbNames = cbData(:,1); - for idx = 2 : length(jArray) - [cbData2, cbHeaders2] = getCbsData(jArray(idx), stripStdCbsFlag); %#ok cbHeaders2 unused - if ~isempty(cbData2) - newCbNames = cbData2(:,1); - [cbNames, cbIdx, cb2Idx] = intersect(cbNames,newCbNames); %#ok cb2Idx unused - cbData = cbData(cbIdx,:); - for cbIdx = 1 : length(cbNames) - newIdx = find(strcmp(cbNames{cbIdx},newCbNames)); - if ~isequal(cbData2{newIdx,2}, cbData{cbIdx,2}) - cbData{cbIdx,2} = ''; - end - end - else - cbData = cbData([],:); %=empty cell array - end - if isempty(cbData) - break; - end - end - end - cbHeaders = {'Callback name','Callback value'}; - try - % Use JideTable if available on this system - list = getTreeData(cbData); %#ok - callbacksTableModel = eval('com.jidesoft.grid.PropertyTableModel(list);'); %#ok prevent JIDE alert by run-time (not load-time) evaluation - - % Expand if only one category - if length(callbacksTableModel.getCategories)==1 - callbacksTableModel.expandFirstLevel; - end - catch - callbacksTableModel = javax.swing.table.DefaultTableModel(cbData,cbHeaders); - end - set(handle(callbacksTableModel,'CallbackProperties'), 'TableChangedCallback',{@tbCallbacksChanged,jArray,userdata.callbacksTable}); - %set(callbacksTableModel, 'UserData',jArray); - userdata.callbacksTable.setModel(callbacksTableModel) - userdata.callbacksTable.setRowAutoResizes(true); - userdata.jideTableUtils.autoResizeAllColumns(userdata.callbacksTable); - catch - % never mind... - dispError - end - - pause(0.005); - drawnow; - %restoreDbstopError(identifiers); - - % Highlight the selected objects (if visible) - flashComponent(jArray,0.2,3); - end - - % TODO: Auto-highlight selected object (?) - %nodeHandle.requestFocus; - end - catch - dispError - end - end - - %% IFF utility function for annonymous cellfun funcs - function result = iff(test,trueVal,falseVal) %#ok - try - if test - result = trueVal; - else - result = falseVal; - end - catch - result = false; - end - end - - %% Get an HTML representation of the object's properties - function dataFieldsStr = getPropsHtml(nodeHandle, dataFields) - try - % Get a text representation of the fieldnames & values - undefinedStr = ''; - hiddenStr = ''; - dataFieldsStr = ''; % just in case the following croaks... - if isempty(dataFields) - return; - end - dataFieldsStr = evalc('disp(dataFields)'); - if dataFieldsStr(end)==char(10), dataFieldsStr=dataFieldsStr(1:end-1); end - - % Strip out callbacks - dataFieldsStr = regexprep(dataFieldsStr,'^\s*\w*Callback(Data)?:[^\n]*$','','lineanchors'); - dataFieldsStr = regexprep(dataFieldsStr,'\n\n','\n'); - - % Convert into a Matlab handle() - %nodeHandle = handle(nodeHandle); - try - % ensure this is a Matlab handle, not a java object - nodeHandle = handle(nodeHandle, 'CallbackProperties'); - catch - try - % HG handles don't allow CallbackProperties... - nodeHandle = handle(nodeHandle); - catch - % Some Matlab class objects simply cannot be converted into a handle() - end - end - - % HTMLize tooltip data - % First, set the fields' font based on its read-write status - fieldNames = fieldnames(dataFields); - for fieldIdx = 1 : length(fieldNames) - thisFieldName = fieldNames{fieldIdx}; - %accessFlags = get(findprop(nodeHandle,thisFieldName),'AccessFlags'); - try - hProp = findprop(nodeHandle,thisFieldName); - accessFlags = get(hProp,'AccessFlags'); - visible = get(hProp,'Visible'); - catch - accessFlags = []; - visible = 'on'; - end - if isfield(accessFlags,'PublicSet') && strcmp(accessFlags.PublicSet,'on') - % Bolden read/write fields - thisFieldFormat = ['' thisFieldName ':$2']; - elseif ~isfield(accessFlags,'PublicSet') - % Undefined - probably a Matlab-defined field of com.mathworks.hg.peer.FigureFrameProxy... - thisFieldFormat = ['' thisFieldName ':$2']; - undefinedStr = ', undefined'; - else % PublicSet=='off' - % Gray-out & italicize any read-only fields - thisFieldFormat = ['' thisFieldName ':$2']; - end - if strcmpi(visible,'off') - %thisFieldFormat = ['' thisFieldFormat '']; %#ok - thisFieldFormat = regexprep(thisFieldFormat, '(.*):(.*)', '$1:$2'); - hiddenStr = ', hidden'; - end - dataFieldsStr = regexprep(dataFieldsStr, ['([\s\n])' thisFieldName ':([^\n]*)'], ['$1' thisFieldFormat]); - end - catch - % never mind... - probably an ambiguous property name - %dispError - end - - % Method 1: simple
list - %dataFieldsStr = strrep(dataFieldsStr,char(10),' 
  '); - - % Method 2: 2-column - dataFieldsStr = regexprep(dataFieldsStr, '^\s*([^:]+:)([^\n]*)\n^\s*([^:]+:)([^\n]*)$', '', 'lineanchors'); - dataFieldsStr = regexprep(dataFieldsStr, '^[^<]\s*([^:]+:)([^\n]*)$', '', 'lineanchors'); - dataFieldsStr = ['(modifiable' undefinedStr hiddenStr ' & read-only fields)

  

 $1 $2    $3 $4 
 $1 $2  
' dataFieldsStr '
']; - end - - %% Update tooltip string with a node's data - function updateNodeTooltip(nodeHandle, uiObject) - try - toolTipStr = class(nodeHandle); - dataFieldsStr = ''; - - % Add HG annotation if relevant - if ishghandle(nodeHandle) - hgStr = ' HG Handle'; - else - hgStr = ''; - end - - % Prevent HG-Java warnings - oldWarn = warning('off','MATLAB:hg:JavaSetHGProperty'); - warning('off','MATLAB:hg:PossibleDeprecatedJavaSetHGProperty'); - - % Note: don't bulk-get because (1) not all properties are returned & (2) some properties cause a Java exception - % Note2: the classhandle approach does not enable access to user-defined schema.props - ch = classhandle(handle(nodeHandle)); - dataFields = []; - [sortedNames, sortedIdx] = sort(get(ch.Properties,'Name')); - for idx = 1 : length(sortedIdx) - sp = ch.Properties(sortedIdx(idx)); - % TODO: some fields (see EOL comment below) generate a Java Exception from: com.mathworks.mlwidgets.inspector.PropertyRootNode$PropertyListener$1$1.run - if strcmp(sp.AccessFlags.PublicGet,'on') % && ~any(strcmp(sp.Name,{'FixedColors','ListboxTop','Extent'})) - try - dataFields.(sp.Name) = get(nodeHandle, sp.Name); - catch - dataFields.(sp.Name) = 'Error!'; - end - else - dataFields.(sp.Name) = '(no public getter method)'; - end - end - dataFieldsStr = getPropsHtml(nodeHandle, dataFields); - catch - % Probably a non-HG java object - try - % Note: the bulk-get approach enables access to user-defined schema-props, but not to some original classhandle Properties... - dataFields = get(nodeHandle); - dataFieldsStr = getPropsHtml(nodeHandle, dataFields); - catch - % Probably a missing property getter implementation - try - % Inform the user - bail out on error - err = lasterror; %#ok - dataFieldsStr = ['

' strrep(err.message, char(10), '
')]; - catch - % forget it... - end - end - end - - % Restore warnings - try warning(oldWarn); catch, end - - % Set the object tooltip - if ~isempty(dataFieldsStr) - toolTipStr = [' ' char(toolTipStr) '' hgStr ': ' dataFieldsStr '']; - end - uiObject.setToolTipText(toolTipStr); - end - - %% Expand tree node - function nodeExpanded(src, evd, tree) %#ok - % tree = handle(src); - % evdsrc = evd.getSource; - evdnode = evd.getCurrentNode; - - if ~tree.isLoaded(evdnode) - - % Get the list of children TreeNodes - childnodes = getChildrenNodes(tree, evdnode); - - % Add the HG sub-tree (unless already included in the first tree) - childHandle = getappdata(evdnode.handle,'childHandle'); %=evdnode.getUserObject - if evdnode.isRoot && ~isempty(hg_handles) && ~isequal(hg_handles(1).java, childHandle) - childnodes = [childnodes, getChildrenNodes(tree, evdnode, true)]; - end - - % If we have a single child handle, wrap it within a javaArray for tree.add() to "swallow" - if (length(childnodes) == 1) - chnodes = childnodes; - childnodes = javaArray('com.mathworks.hg.peer.UITreeNode', 1); - childnodes(1) = java(chnodes); - end - - % Add child nodes to the current node - tree.add(evdnode, childnodes); - tree.setLoaded(evdnode, true); - end - end - - %% Get an icon image no larger than 16x16 pixels - function iconImage = setIconSize(iconImage) - try - iconWidth = iconImage.getWidth; - iconHeight = iconImage.getHeight; - if iconWidth > 16 - newHeight = fix(iconHeight * 16 / iconWidth); - iconImage = iconImage.getScaledInstance(16,newHeight,iconImage.SCALE_SMOOTH); - elseif iconHeight > 16 - newWidth = fix(iconWidth * 16 / iconHeight); - iconImage = iconImage.getScaledInstance(newWidth,16,iconImage.SCALE_SMOOTH); - end - catch - % never mind... - return original icon - end - end % setIconSize - - %% Get list of children nodes - function nodes = getChildrenNodes(tree, parentNode, isRootHGNode) - try - iconpath = [matlabroot, '/toolbox/matlab/icons/']; - nodes = handle([]); - try - userdata = get(tree,'userdata'); - catch - userdata = getappdata(tree,'userdata'); - end - hdls = userdata.handles; - nodedata = get(parentNode,'userdata'); - if nargin < 3 - %isJavaNode = ~ishghandle(parentNode.getUserObject); - isJavaNode = ~ishghandle(nodedata.obj); - isRootHGNode = false; - else - isJavaNode = ~isRootHGNode; - end - - % Search for this parent node in the list of all nodes - parents = userdata.parents; - nodeIdx = nodedata.idx; - - if isJavaNode && isempty(nodeIdx) % Failback, in case userdata doesn't work for some reason... - for hIdx = 1 : length(hdls) - %if isequal(handle(parentNode.getUserObject), hdls(hIdx)) - if isequal(handle(nodedata.obj), hdls(hIdx)) - nodeIdx = hIdx; - break; - end - end - end - if ~isJavaNode - if isRootHGNode % =root HG node - thisChildHandle = userdata.hg_handles(1); - childName = getNodeName(thisChildHandle); - hasGrandChildren = any(parents==1); - icon = []; - if hasGrandChildren && length(hg_handles)>1 - childName = childName.concat(' - HG root container'); - icon = [iconpath 'figureicon.gif']; - end - try - nodes = uitreenode('v0', thisChildHandle, childName, icon, ~hasGrandChildren); - catch % old matlab version don't have the 'v0' option - try - nodes = uitreenode(thisChildHandle, childName, icon, ~hasGrandChildren); - catch - % probably an invalid handle - ignore... - end - end - - % Add the handler to the node's internal data - % Note: could also use 'userdata', but setUserObject() is recommended for TreeNodes - % Note2: however, setUserObject() sets a java *BeenAdapter object for HG handles instead of the required original class, so use setappdata - %nodes.setUserObject(thisChildHandle); - setappdata(nodes,'childHandle',thisChildHandle); - nodedata.idx = 1; - nodedata.obj = thisChildHandle; - set(nodes,'userdata',nodedata); - return; - else % non-root HG node - parents = userdata.hg_parents; - hdls = userdata.hg_handles; - end % if isRootHGNode - end % if ~isJavaNode - - % If this node was found, get the list of its children - if ~isempty(nodeIdx) - %childIdx = setdiff(find(parents==nodeIdx),nodeIdx); - childIdx = find(parents==nodeIdx); - childIdx(childIdx==nodeIdx) = []; % faster... - numChildren = length(childIdx); - for cIdx = 1 : numChildren - thisChildIdx = childIdx(cIdx); - thisChildHandle = hdls(thisChildIdx); - childName = getNodeName(thisChildHandle); - try - visible = thisChildHandle.Visible; - if visible - try visible = thisChildHandle.Width > 0; catch, end %#ok - end - if ~visible - childName = ['' char(childName) '']; %#ok grow - end - catch - % never mind... - end - hasGrandChildren = any(parents==thisChildIdx); - try - isaLabel = isa(thisChildHandle.java,'javax.swing.JLabel'); - catch - isaLabel = 0; - end - if hasGrandChildren && ~any(strcmp(class(thisChildHandle),{'axes'})) - icon = [iconpath 'foldericon.gif']; - elseif isaLabel - icon = [iconpath 'tool_text.gif']; - else - icon = []; - end - try - nodes(cIdx) = uitreenode('v0', thisChildHandle, childName, icon, ~hasGrandChildren); - catch % old matlab version don't have the 'v0' option - try - nodes(cIdx) = uitreenode(thisChildHandle, childName, icon, ~hasGrandChildren); - catch - % probably an invalid handle - ignore... - end - end - - % Use existing object icon, if available - try - setTreeNodeIcon(nodes(cIdx),thisChildHandle); - catch - % probably an invalid handle - ignore... - end - - % Pre-select the node based upon the user's FINDJOBJ filters - try - if isJavaNode && ~userdata.userSelected && any(userdata.initialIdx == thisChildIdx) - pause(0.0002); % as short as possible... - drawnow; - if isempty(tree.getSelectedNodes) - tree.setSelectedNode(nodes(cIdx)); - else - newSelectedNodes = [tree.getSelectedNodes, nodes(cIdx).java]; - tree.setSelectedNodes(newSelectedNodes); - end - end - catch - % never mind... - end - - % Add the handler to the node's internal data - % Note: could also use 'userdata', but setUserObject() is recommended for TreeNodes - % Note2: however, setUserObject() sets a java *BeenAdapter object for HG handles instead of the required original class, so use setappdata - % Note3: the following will error if invalid handle - ignore - try - if isJavaNode - thisChildHandle = thisChildHandle.java; - end - %nodes(cIdx).setUserObject(thisChildHandle); - setappdata(nodes(cIdx),'childHandle',thisChildHandle); - nodedata.idx = thisChildIdx; - nodedata.obj = thisChildHandle; - set(nodes(cIdx),'userdata',nodedata); - catch - % never mind (probably an invalid handle) - leave unchanged (like a leaf) - end - end - end - catch - % Never mind - leave unchanged (like a leaf) - %error('YMA:findjobj:UnknownNodeType', 'Error expanding component tree node'); - dispError - end - end - - %% Get a node's name - function [nodeName, nodeTitle] = getNodeName(hndl,charsLimit) - try - % Initialize (just in case one of the succeding lines croaks) - nodeName = ''; - nodeTitle = ''; - if ~ismethod(hndl,'getClass') - try - nodeName = class(hndl); - catch - nodeName = hndl.type; % last-ditch try... - end - else - nodeName = hndl.getClass.getSimpleName; - end - - % Strip away the package name, leaving only the regular classname - if ~isempty(nodeName) && ischar(nodeName) - nodeName = java.lang.String(nodeName); - nodeName = nodeName.substring(nodeName.lastIndexOf('.')+1); - end - if (nodeName.length == 0) - % fix case of anonymous internal classes, that do not have SimpleNames - try - nodeName = hndl.getClass.getName; - nodeName = nodeName.substring(nodeName.lastIndexOf('.')+1); - catch - % never mind - leave unchanged... - end - end - - % Get any unique identifying string (if available in one of several fields) - labelsToCheck = {'label','title','text','string','displayname','toolTipText','TooltipString','actionCommand','name','Tag','style'}; %,'UIClassID'}; - nodeTitle = ''; - strField = ''; %#ok - used for debugging - while ((~isa(nodeTitle,'java.lang.String') && ~ischar(nodeTitle)) || isempty(nodeTitle)) && ~isempty(labelsToCheck) - try - nodeTitle = get(hndl,labelsToCheck{1}); - strField = labelsToCheck{1}; %#ok - used for debugging - catch - % never mind - probably missing prop, so skip to next one - end - labelsToCheck(1) = []; - end - if length(nodeTitle) ~= numel(nodeTitle) - % Multi-line - convert to a long single line - nodeTitle = nodeTitle'; - nodeTitle = nodeTitle(:)'; - end - if isempty(char(nodeTitle)) - % No title - check whether this is an HG label whose text is gettable - try - location = hndl.getLocationOnScreen; - pos = [location.getX, location.getY, hndl.getWidth, hndl.getHeight]; - dist = sum((labelPositions-repmat(pos,size(labelPositions,1),[1,1,1,1])).^2, 2); - [minVal,minIdx] = min(dist); - % Allow max distance of 8 = 2^2+2^2 (i.e. X&Y off by up to 2 pixels, W&H exact) - if minVal <= 8 % 8=2^2+2^2 - nodeTitle = get(hg_labels(minIdx),'string'); - % Preserve the label handles & position for the tooltip & context-menu - %hg_labels(minIdx) = []; - %labelPositions(minIdx,:) = []; - end - catch - % never mind... - end - end - if nargin<2, charsLimit = 25; end - extraStr = regexprep(nodeTitle,{sprintf('(.{%d,%d}).*',charsLimit,min(charsLimit,length(nodeTitle)-1)),' +'},{'$1...',' '},'once'); - if ~isempty(extraStr) - if ischar(extraStr) - nodeName = nodeName.concat(' (''').concat(extraStr).concat(''')'); - else - nodeName = nodeName.concat(' (').concat(num2str(extraStr)).concat(')'); - end - %nodeName = nodeName.concat(strField); - end - catch - % Never mind - use whatever we have so far - %dispError - end - end - - %% Strip standard Swing callbacks from a list of events - function evNames = stripStdCbs(evNames) - try - stdEvents = {'AncestorAdded', 'AncestorMoved', 'AncestorRemoved', 'AncestorResized', ... - 'CaretPositionChanged', 'ComponentAdded', 'ComponentRemoved', ... - 'ComponentHidden', 'ComponentMoved', 'ComponentResized', 'ComponentShown', ... - 'PropertyChange', 'FocusGained', 'FocusLost', ... - 'HierarchyChanged', 'InputMethodTextChanged', ... - 'KeyPressed', 'KeyReleased', 'KeyTyped', ... - 'MouseClicked', 'MouseDragged', 'MouseEntered', 'MouseExited', ... - 'MouseMoved', 'MousePressed', 'MouseReleased', 'MouseWheelMoved', ... - 'VetoableChange'}; - stdEvents = [stdEvents, strcat(stdEvents,'Callback'), strcat(stdEvents,'Fcn')]; - evNames = setdiff(evNames,stdEvents)'; - catch - % Never mind... - dispError - end - end - - %% Callback function for checkbox - function cbHideStdCbs_Callback(src, evd, callbacksTable, varargin) %#ok - try - % Store the current checkbox value for later use - if nargin < 3 - try - callbacksTable = get(src,'userdata'); - catch - callbacksTable = getappdata(src,'userdata'); - end - end - if evd.getSource.isSelected - setappdata(callbacksTable,'hideStdCbs',1); - else - setappdata(callbacksTable,'hideStdCbs',[]); - end - - % Rescan the current node - try - userdata = get(callbacksTable,'userdata'); - catch - userdata = getappdata(callbacksTable,'userdata'); - end - nodepath = userdata.jTree.getSelectionModel.getSelectionPath; - try - ed.getCurrentNode = nodepath.getLastPathComponent; - nodeSelected(handle(userdata.jTreePeer),ed,[]); - catch - % ignore - probably no node selected - end - catch - % Never mind... - dispError - end - end - - %% Callback function for button - function btWebsite_Callback(src, evd, varargin) %#ok - try - web('http://UndocumentedMatlab.com/'); - catch - % Never mind... - dispError - end - end - - %% Callback function for button - function btRefresh_Callback(src, evd, varargin) %#ok - try - % Set cursor shape to hourglass until we're done - hTreeFig = varargin{2}; - set(hTreeFig,'Pointer','watch'); - drawnow; - object = varargin{1}; - - % Re-invoke this utility to re-scan the container for all children - findjobj(object); - catch - % Never mind... - end - - % Restore default cursor shape - set(hTreeFig,'Pointer','arrow'); - end - - %% Callback function for button - function btExport_Callback(src, evd, varargin) %#ok - try - % Get the list of all selected nodes - if length(varargin) > 1 - jTree = varargin{1}; - numSelections = jTree.getSelectionCount; - selectionPaths = jTree.getSelectionPaths; - hdls = handle([]); - for idx = 1 : numSelections - %hdls(idx) = handle(selectionPaths(idx).getLastPathComponent.getUserObject); - nodedata = get(selectionPaths(idx).getLastPathComponent,'userdata'); - hdls(idx) = handle(nodedata.obj,'CallbackProperties'); - end - - % Assign the handles in the base workspace & inform user - assignin('base','findjobj_hdls',hdls); - classNameLabel = varargin{2}; - msg = ['Exported ' char(classNameLabel.getText.trim) ' to base workspace variable findjobj_hdls']; - else - % Right-click (context-menu) callback - data = varargin{1}; - obj = data{1}; - varName = data{2}; - if isempty(varName) - varName = inputdlg('Enter workspace variable name','FindJObj'); - if isempty(varName), return; end % bail out on - varName = varName{1}; - if isempty(varName) || ~ischar(varName), return; end % bail out on empty/null - varName = genvarname(varName); - end - assignin('base',varName,handle(obj,'CallbackProperties')); - msg = ['Exported object to base workspace variable ' varName]; - end - msgbox(msg,'FindJObj','help'); - catch - % Never mind... - dispError - end - end - - %% Callback function for button - function btFocus_Callback(src, evd, varargin) %#ok - try - % Request focus for the specified object - object = getTopSelectedObject(varargin{:}); - object.requestFocus; - catch - try - object = object.java.getPeer.requestFocus; - object.requestFocus; - catch - % Never mind... - %dispError - end - end - end - - %% Callback function for button - function btInspect_Callback(src, evd, varargin) %#ok - try - % Inspect the specified object - if length(varargin) == 1 - object = varargin{1}; - else - object = getTopSelectedObject(varargin{:}); - end - if isempty(which('uiinspect')) - - % If the user has not indicated NOT to be informed about UIInspect - if ~ispref('FindJObj','dontCheckUIInspect') - - % Ask the user whether to download UIINSPECT (YES, no, no & don't ask again) - answer = questdlg({'The object inspector requires UIINSPECT from the MathWorks File Exchange. UIINSPECT was created by Yair Altman, like this FindJObj utility.','','Download & install UIINSPECT?'},'UIInspect','Yes','No','No & never ask again','Yes'); - switch answer - case 'Yes' % => Yes: download & install - try - % Download UIINSPECT - baseUrl = 'http://www.mathworks.com/matlabcentral/fileexchange/17935'; - fileUrl = [baseUrl '?controller=file_infos&download=true']; - %file = urlread(fileUrl); - %file = regexprep(file,[char(13),char(10)],'\n'); %convert to OS-dependent EOL - - % Install... - %newPath = fullfile(fileparts(which(mfilename)),'uiinspect.m'); - %fid = fopen(newPath,'wt'); - %fprintf(fid,'%s',file); - %fclose(fid); - [fpath,fname,fext] = fileparts(which(mfilename)); - zipFileName = fullfile(fpath,'uiinspect.zip'); - urlwrite(fileUrl,zipFileName); - unzip(zipFileName,fpath); - rehash; - catch - % Error downloading: inform the user - msgbox(['Error in downloading: ' lasterr], 'UIInspect', 'warn'); %#ok - web(baseUrl); - end - - % ...and now run it... - %pause(0.1); - drawnow; - dummy = which('uiinspect'); %#ok used only to load into memory - uiinspect(object); - return; - - case 'No & never ask again' % => No & don't ask again - setpref('FindJObj','dontCheckUIInspect',1); - - otherwise - % forget it... - end - end - drawnow; - - % No UIINSPECT available - run the good-ol' METHODSVIEW()... - methodsview(object); - else - uiinspect(object); - end - catch - try - if isjava(object) - methodsview(object) - else - methodsview(object.java); - end - catch - % Never mind... - dispError - end - end - end - - %% Callback function for button - function btCheckFex_Callback(src, evd, varargin) %#ok - try - % Check the FileExchange for the latest version - web('http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=14317'); - catch - % Never mind... - dispError - end - end - - %% Check for existence of a newer version - function checkVersion() - try - % If the user has not indicated NOT to be informed - if ~ispref('FindJObj','dontCheckNewerVersion') - - % Get the latest version date from the File Exchange webpage - baseUrl = 'http://www.mathworks.com/matlabcentral/fileexchange/'; - webUrl = [baseUrl '14317']; % 'loadFile.do?objectId=14317']; - webPage = urlread(webUrl); - modIdx = strfind(webPage,'>Updates<'); - if ~isempty(modIdx) - webPage = webPage(modIdx:end); - % Note: regexp hangs if substr not found, so use strfind instead... - %latestWebVersion = regexprep(webPage,'.*?>(20[\d-]+).*','$1'); - dateIdx = strfind(webPage,'class="date">'); - if ~isempty(dateIdx) - latestDate = webPage(dateIdx(end)+13 : dateIdx(end)+23); - try - startIdx = dateIdx(end)+27; - descStartIdx = startIdx + strfind(webPage(startIdx:startIdx+999),''); - descEndIdx = startIdx + strfind(webPage(startIdx:startIdx+999),''); - descStr = webPage(descStartIdx(1)+3 : descEndIdx(1)-2); - descStr = regexprep(descStr,'',''); - catch - descStr = ''; - end - - % Get this file's latest date - thisFileName = which(mfilename); %#ok - try - thisFileData = dir(thisFileName); - try - thisFileDatenum = thisFileData.datenum; - catch % old ML versions... - thisFileDatenum = datenum(thisFileData.date); - end - catch - thisFileText = evalc('type(thisFileName)'); - thisFileLatestDate = regexprep(thisFileText,'.*Change log:[\s%]+([\d-]+).*','$1'); - thisFileDatenum = datenum(thisFileLatestDate,'yyyy-mm-dd'); - end - - % If there's a newer version on the File Exchange webpage (allow 2 days grace period) - if (thisFileDatenum < datenum(latestDate,'dd mmm yyyy')-2) - - % Ask the user whether to download the newer version (YES, no, no & don't ask again) - msg = {['A newer version (' latestDate ') of FindJObj is available on the MathWorks File Exchange:'], '', ... - ['\color{blue}' descStr '\color{black}'], '', ... - 'Download & install the new version?'}; - createStruct.Interpreter = 'tex'; - createStruct.Default = 'Yes'; - answer = questdlg(msg,'FindJObj','Yes','No','No & never ask again',createStruct); - switch answer - case 'Yes' % => Yes: download & install newer file - try - %fileUrl = [baseUrl '/download.do?objectId=14317&fn=findjobj&fe=.m']; - fileUrl = [baseUrl '/14317?controller=file_infos&download=true']; - %file = urlread(fileUrl); - %file = regexprep(file,[char(13),char(10)],'\n'); %convert to OS-dependent EOL - %fid = fopen(thisFileName,'wt'); - %fprintf(fid,'%s',file); - %fclose(fid); - [fpath,fname,fext] = fileparts(thisFileName); - zipFileName = fullfile(fpath,[fname '.zip']); - urlwrite(fileUrl,zipFileName); - unzip(zipFileName,fpath); - rehash; - catch - % Error downloading: inform the user - msgbox(['Error in downloading: ' lasterr], 'FindJObj', 'warn'); %#ok - web(webUrl); - end - case 'No & never ask again' % => No & don't ask again - setpref('FindJObj','dontCheckNewerVersion',1); - otherwise - % forget it... - end - end - end - else - % Maybe webpage not fully loaded or changed format - bail out... - end - end - catch - % Never mind... - end - end - - %% Get the first selected object (might not be the top one - depends on selection order) - function object = getTopSelectedObject(jTree, root) - try - object = []; - numSelections = jTree.getSelectionCount; - if numSelections > 0 - % Get the first object specified - %object = jTree.getSelectionPath.getLastPathComponent.getUserObject; - nodedata = get(jTree.getSelectionPath.getLastPathComponent,'userdata'); - else - % Get the root object (container) - %object = root.getUserObject; - nodedata = get(root,'userdata'); - end - object = nodedata.obj; - catch - % Never mind... - dispError - end - end - - %% Update component callback upon callbacksTable data change - function tbCallbacksChanged(src, evd, object, table) - persistent hash - try - % exit if invalid handle or already in Callback - %if ~ishandle(src) || ~isempty(getappdata(src,'inCallback')) % || length(dbstack)>1 %exit also if not called from user action - if isempty(hash), hash = java.util.Hashtable; end - if ~ishandle(src) || ~isempty(hash.get(src)) % || length(dbstack)>1 %exit also if not called from user action - return; - end - %setappdata(src,'inCallback',1); % used to prevent endless recursion % can't use getappdata(src,...) because it fails on R2010b!!! - hash.put(src,1); - - % Update the object's callback with the modified value - modifiedColIdx = evd.getColumn; - modifiedRowIdx = evd.getFirstRow; - if modifiedRowIdx>=0 %&& modifiedColIdx==1 %sanity check - should always be true - %table = evd.getSource; - %object = get(src,'userdata'); - modifiedRowIdx = table.getSelectedRow; % overcome issues with hierarchical table - cbName = strtrim(table.getValueAt(modifiedRowIdx,0)); - try - cbValue = strtrim(char(table.getValueAt(modifiedRowIdx,1))); - if ~isempty(cbValue) && ismember(cbValue(1),'{[@''') - cbValue = eval(cbValue); - end - if (~ischar(cbValue) && ~isa(cbValue, 'function_handle') && (~iscell(cbValue) || iscom(object(1)))) - revertCbTableModification(table, modifiedRowIdx, modifiedColIdx, cbName, object, ''); - else - for objIdx = 1 : length(object) - obj = object(objIdx); - if ~iscom(obj) - try - try - if isjava(obj) - obj = handle(obj,'CallbackProperties'); - end - catch - % never mind... - end - set(obj, cbName, cbValue); - catch - try - set(handle(obj,'CallbackProperties'), cbName, cbValue); - catch - % never mind - probably a callback-group header - end - end - else - cbs = obj.eventlisteners; - if ~isempty(cbs) - cbs = cbs(strcmpi(cbs(:,1),cbName),:); - obj.unregisterevent(cbs); - end - if ~isempty(cbValue) && ~strcmp(cbName,'-') - obj.registerevent({cbName, cbValue}); - end - end - end - end - catch - revertCbTableModification(table, modifiedRowIdx, modifiedColIdx, cbName, object, lasterr) %#ok - end - end - catch - % never mind... - end - %setappdata(src,'inCallback',[]); % used to prevent endless recursion % can't use setappdata(src,...) because it fails on R2010b!!! - hash.remove(src); - end - - %% Revert Callback table modification - function revertCbTableModification(table, modifiedRowIdx, modifiedColIdx, cbName, object, errMsg) %#ok - try - % Display a notification MsgBox - msg = 'Callbacks must be a ''string'', or a @function handle'; - if ~iscom(object(1)), msg = [msg ' or a {@func,args...} construct']; end - if ~isempty(errMsg), msg = {errMsg, '', msg}; end - msgbox(msg, ['Error setting ' cbName ' value'], 'warn'); - - % Revert to the current value - curValue = ''; - try - if ~iscom(object(1)) - curValue = charizeData(get(object(1),cbName)); - else - cbs = object(1).eventlisteners; - if ~isempty(cbs) - cbs = cbs(strcmpi(cbs(:,1),cbName),:); - curValue = charizeData(cbs(1,2)); - end - end - catch - % never mind... - clear the current value - end - table.setValueAt(curValue, modifiedRowIdx, modifiedColIdx); - catch - % never mind... - end - end % revertCbTableModification - - %% Get the Java positions of all HG text labels - function labelPositions = getLabelsJavaPos(container) - try - labelPositions = []; - - % Ensure we have a figure handle - try - h = hFig; %#ok unused - catch - hFig = getCurrentFigure; - end - - % Get the figure's margins from the Matlab properties - hg_labels = findall(hFig, 'Style','text'); - units = get(hFig,'units'); - set(hFig,'units','pixels'); - outerPos = get(hFig,'OuterPosition'); - innerPos = get(hFig,'Position'); - set(hFig,'units',units); - margins = abs(innerPos-outerPos); - - figX = container.getX; % =outerPos(1) - figY = container.getY; % =outerPos(2) - %figW = container.getWidth; % =outerPos(3) - figH = container.getHeight; % =outerPos(4) - - % Get the relevant screen pixel size - %monitorPositions = get(0,'MonitorPositions'); - %for monitorIdx = size(monitorPositions,1) : -1 : 1 - % screenSize = monitorPositions(monitorIdx,:); - % if (outerPos(1) >= screenSize(1)) % && (outerPos(1)+outerPos(3) <= screenSize(3)) - % break; - % end - %end - %monitorBaseY = screenSize(4) - monitorPositions(1,4); - - % Compute the labels' screen pixel position in Java units ([0,0] = top left) - for idx = 1 : length(hg_labels) - matlabPos = getpixelposition(hg_labels(idx),1); - javaX = figX + matlabPos(1) + margins(1); - javaY = figY + figH - matlabPos(2) - matlabPos(4) - margins(2); - labelPositions(idx,:) = [javaX, javaY, matlabPos(3:4)]; %#ok grow - end - catch - % never mind... - err = lasterror; %#ok debug point - end - end - - %% Traverse an HG container hierarchy and extract the HG elements within - function traverseHGContainer(hcontainer,level,parent) - try - % Record the data for this node - thisIdx = length(hg_levels) + 1; - hg_levels(thisIdx) = level; - hg_parentIdx(thisIdx) = parent; - try - hg_handles(thisIdx) = handle(hcontainer); - catch - hg_handles = handle(hcontainer); - end - parentId = length(hg_parentIdx); - - % Now recursively process all this node's children (if any) - %if ishghandle(hcontainer) - try % try-catch is faster than checking ishghandle(hcontainer)... - allChildren = allchild(handle(hcontainer)); - for childIdx = 1 : length(allChildren) - traverseHGContainer(allChildren(childIdx),level+1,parentId); - end - catch - % do nothing - probably not a container - %dispError - end - - % TODO: Add axis (plot) component handles - catch - % forget it... - end - end - - %% Debuggable "quiet" error-handling - function dispError - err = lasterror; %#ok - msg = err.message; - for idx = 1 : length(err.stack) - filename = err.stack(idx).file; - if ~isempty(regexpi(filename,mfilename)) - funcname = err.stack(idx).name; - line = num2str(err.stack(idx).line); - msg = [msg ' at ' funcname ' line #' line '']; %#ok grow - break; - end - end - disp(msg); - return; % debug point - end - - %% ML 7.0 - compatible ischar() function - function flag = ischar(data) - try - flag = builtin('ischar',data); - catch - flag = isa(data,'char'); - end - end - - %% Set up the uitree context (right-click) menu - function jmenu = setTreeContextMenu(obj,node,tree_h) - % Prepare the context menu (note the use of HTML labels) - import javax.swing.* - titleStr = getNodeTitleStr(obj,node); - titleStr = regexprep(titleStr,'


.*',''); - menuItem0 = JMenuItem(titleStr); - menuItem0.setEnabled(false); - menuItem0.setArmed(false); - %menuItem1 = JMenuItem('Export handle to findjobj_hdls'); - if isjava(obj), prefix = 'j'; else, prefix = 'h'; end %#ok - varname = strrep([prefix strtok(char(node.getName))], '$','_'); - varname = genvarname(varname); - varname(2) = upper(varname(2)); % ensure lowerCamelCase - menuItem1 = JMenuItem(['Export handle to ' varname]); - menuItem2 = JMenuItem('Export handle to...'); - menuItem3 = JMenuItem('Request focus (bring to front)'); - menuItem4 = JMenuItem('Flash component borders'); - menuItem5 = JMenuItem('Display properties & callbacks'); - menuItem6 = JMenuItem('Inspect object'); - - % Set the menu items' callbacks - set(handle(menuItem1,'CallbackProperties'), 'ActionPerformedCallback', {@btExport_Callback,{obj,varname}}); - set(handle(menuItem2,'CallbackProperties'), 'ActionPerformedCallback', {@btExport_Callback,{obj,[]}}); - set(handle(menuItem3,'CallbackProperties'), 'ActionPerformedCallback', {@requestFocus,obj}); - set(handle(menuItem4,'CallbackProperties'), 'ActionPerformedCallback', {@flashComponent,{obj,0.2,3}}); - set(handle(menuItem5,'CallbackProperties'), 'ActionPerformedCallback', {@nodeSelected,{tree_h,node}}); - set(handle(menuItem6,'CallbackProperties'), 'ActionPerformedCallback', {@btInspect_Callback,obj}); - - % Add all menu items to the context menu (with internal separator) - jmenu = JPopupMenu; - jmenu.add(menuItem0); - jmenu.addSeparator; - handleValue=[]; try handleValue = double(obj); catch, end; %#ok - if ~isempty(handleValue) - % For valid HG handles only - menuItem0a = JMenuItem('Copy handle value to clipboard'); - set(handle(menuItem0a,'CallbackProperties'), 'ActionPerformedCallback', sprintf('clipboard(''copy'',%.99g)',handleValue)); - jmenu.add(menuItem0a); - end - jmenu.add(menuItem1); - jmenu.add(menuItem2); - jmenu.addSeparator; - jmenu.add(menuItem3); - jmenu.add(menuItem4); - jmenu.add(menuItem5); - jmenu.add(menuItem6); - end % setTreeContextMenu - - %% Set the mouse-press callback - function treeMousePressedCallback(hTree, eventData, tree_h) %#ok hTree is unused - if eventData.isMetaDown % right-click is like a Meta-button - % Get the clicked node - clickX = eventData.getX; - clickY = eventData.getY; - jtree = eventData.getSource; - treePath = jtree.getPathForLocation(clickX, clickY); - try - % Modify the context menu based on the clicked node - node = treePath.getLastPathComponent; - userdata = get(node,'userdata'); - obj = userdata.obj; - jmenu = setTreeContextMenu(obj,node,tree_h); - - % TODO: remember to call jmenu.remove(item) in item callback - % or use the timer hack shown here to remove the item: - % timerFcn = {@menuRemoveItem,jmenu,item}; - % start(timer('TimerFcn',timerFcn,'StartDelay',0.2)); - - % Display the (possibly-modified) context menu - jmenu.show(jtree, clickX, clickY); - jmenu.repaint; - - % This is for debugging: - userdata.tree = jtree; - setappdata(gcf,'findjobj_hgtree',userdata) - catch - % clicked location is NOT on top of any node - % Note: can also be tested by isempty(treePath) - end - end - end % treeMousePressedCallback - - %% Remove the extra context menu item after display - function menuRemoveItem(hObj,eventData,jmenu,item) %#ok unused - jmenu.remove(item); - end % menuRemoveItem - - %% Get the title for the tooltip and context (right-click) menu - function nodeTitleStr = getNodeTitleStr(obj,node) - try - % Display the full classname and object name in the tooltip - %nodeName = char(node.getName); - %nodeName = strrep(nodeName, '',''); - %nodeName = strrep(nodeName, '',''); - nodeName = char(getNodeName(obj,99)); - [objClass,objName] = strtok(nodeName); - objName = objName(3:end-1); % strip leading ( and trailing ) - if isempty(objName), objName = '(none found)'; end - nodeName = char(node.getName); - objClass = char(obj.getClass.getName); - nodeTitleStr = sprintf('Class name: %s
Text/title: %s',objClass,objName); - - % If the component is invisible, state this in the tooltip - if ~isempty(strfind(nodeName,'color="gray"')) - nodeTitleStr = [nodeTitleStr '
*** Invisible ***']; - end - nodeTitleStr = [nodeTitleStr '
Right-click for context-menu']; - catch - % Possible not a Java object - try treating as an HG handle - try - handleValueStr = sprintf('#: %.99g',double(obj)); - try - type = ''; - type = get(obj,'type'); - type(1) = upper(type(1)); - catch - if ~ishandle(obj) - type = ['Invalid ' char(node.getName) '']; - handleValueStr = '!!!
Perhaps this handle was deleted after this UIInspect tree was
already drawn. Try to refresh by selecting any valid node handle'; - end - end - nodeTitleStr = sprintf('%s handle %s',type,handleValueStr); - try - % If the component is invisible, state this in the tooltip - if strcmp(get(obj,'Visible'),'off') - nodeTitleStr = [nodeTitleStr '
Invisible']; - end - catch - % never mind... - end - catch - % never mind... - ignore - end - end - end % getNodeTitleStr - - %% Handle tree mouse movement callback - used to set the tooltip & context-menu - function treeMouseMovedCallback(hTree, eventData) - try - x = eventData.getX; - y = eventData.getY; - jtree = eventData.getSource; - treePath = jtree.getPathForLocation(x, y); - try - % Set the tooltip string based on the hovered node - node = treePath.getLastPathComponent; - userdata = get(node,'userdata'); - obj = userdata.obj; - tooltipStr = getNodeTitleStr(obj,node); - set(hTree,'ToolTipText',tooltipStr) - catch - % clicked location is NOT on top of any node - % Note: can also be tested by isempty(treePath) - end - catch - dispError; - end - return; % denug breakpoint - end % treeMouseMovedCallback - - %% Request focus for a specific object handle - function requestFocus(hTree, eventData, obj) %#ok hTree & eventData are unused - % Ensure the object handle is valid - if isjava(obj) - obj.requestFocus; - return; - elseif ~ishandle(obj) - msgbox('The selected object does not appear to be a valid handle as defined by the ishandle() function. Perhaps this object was deleted after this hierarchy tree was already drawn. Refresh this tree by selecting a valid node handle and then retry.','FindJObj','warn'); - beep; - return; - end - - try - foundFlag = 0; - while ~foundFlag - if isempty(obj), return; end % sanity check - type = get(obj,'type'); - obj = double(obj); - foundFlag = any(strcmp(type,{'figure','axes','uicontrol'})); - if ~foundFlag - obj = get(obj,'Parent'); - end - end - feval(type,obj); - catch - % never mind... - dispError; - end - end % requestFocus - - -end % FINDJOBJ - - -%% TODO TODO TODO -%{ -- Enh: Improve performance - esp. expandNode() (performance solved in non-nteractive mode) -- Enh: Add property listeners - same problem in MathWork's inspect.m -- Enh: Display additional properties - same problem in MathWork's inspect.m -- Enh: Add axis (plot, Graphics) component handles -- Enh: Group callbacks according to the first word (up to 2nd cap letter) -- Enh: Add figure thumbnail image below the java tree (& indicate corresponding jObject when selected) -- Enh: scroll initially-selected node into view (problem because treenode has no pixel location) -- Fix: java exceptions when getting some fields (com.mathworks.mlwidgets.inspector.PropertyRootNode$PropertyListener$1$1.run) -- Fix: use EDT if available (especially in flashComponent) -%} \ No newline at end of file diff --git a/general functions/fmgaussfit.m b/general functions/fmgaussfit.m deleted file mode 100644 index 2466263..0000000 --- a/general functions/fmgaussfit.m +++ /dev/null @@ -1,98 +0,0 @@ -function [fitresult, zfit, fiterr, zerr, resnorm, rr] = fmgaussfit(xx,yy,zz) -% FMGAUSSFIT Create/alter optimization OPTIONS structure. -% [fitresult,..., rr] = fmgaussfit(xx,yy,zz) uses ZZ for the surface -% height. XX and YY are vectors or matrices defining the x and y -% components of a surface. If XX and YY are vectors, length(XX) = n and -% length(YY) = m, where [m,n] = size(Z). In this case, the vertices of the -% surface faces are (XX(j), YY(i), ZZ(i,j)) triples. To create XX and YY -% matrices for arbitrary domains, use the meshgrid function. FMGAUSSFIT -% uses the lsqcurvefit tool, and the OPTIMZATION TOOLBOX. The initial -% guess for the gaussian is places at the maxima in the ZZ plane. The fit -% is restricted to be in the span of XX and YY. -% See: -% http://en.wikipedia.org/wiki/Gaussian_function -% -% Examples: -% To fit a 2D gaussian: -% [fitresult, zfit, fiterr, zerr, resnorm, rr] = -% fmgaussfit(xx,yy,zz); -% See also SURF, OMPTMSET, LSQCURVEFIT, NLPARCI, NLPREDCI. - -% Copyright 2013, Nathan Orloff. - -%% Condition the data -[xData, yData, zData] = prepareSurfaceData( xx, yy, zz ); -xyData = {xData,yData}; - -%% Set up the startpoint -[amp, ind] = max(zData); % amp is the amplitude. -xo = xData(ind); % guess that it is at the maximum -yo = yData(ind); % guess that it is at the maximum -ang = 45; % angle in degrees. -sy = 1; -sx = 1; -zo = median(zData(:))-std(zData(:)); -xmax = max(xData)+2; -ymax = max(yData)+2; -zmax = amp*2; % amp is the amplitude. -xmin = min(xData)-2; -ymin = min(yData)-2; -zmin = min(zData)/2; % amp is the amplitude. - -%% Set up fittype and options. -Lower = [0, eps, 0, 0, xmin, ymin, zmin]; -Upper = [Inf, 180, Inf, Inf, xmax, ymax, zmax]; % angles greater than 90 are redundant -StartPoint = [amp, ang, sx, sy, xo, yo, zo];%[amp, sx, sxy, sy, xo, yo, zo]; - -tols = 1e-16; -options = optimset('Algorithm','levenberg-marquardt',... - 'Display','off',... - 'MaxFunEvals',5e2,... - 'MaxIter',5e2,... - 'TolX',tols,... - 'TolFun',tols,... - 'TolCon',tols ,... - 'UseParallel','always'); - -%% perform the fitting -[fitresult,resnorm,residual] = ... - lsqcurvefit(@gaussian2D,StartPoint,xyData,zData,Lower,Upper,options); -[fiterr, zfit, zerr] = gaussian2Duncert(fitresult,residual,xyData); -rr = rsquared(zData, zfit, zerr); -zfit = reshape(zfit,size(zz)); -zerr = reshape(zerr,size(zz)); - -end - -function rr = rsquared(z,zf,ze) -% reduced chi-squared -dz = z-zf; -rr = 1./(numel(z)-8).*sum(dz.^2./ze.^2); % minus 8 because there are 7 fit parameters +1 (DOF) -end - -function z = gaussian2D(par,xy) -% compute 2D gaussian -z = par(7) + ... - par(1)*exp(-(((xy{1}-par(5)).*cosd(par(2))+(xy{2}-par(6)).*sind(par(2)))./par(3)).^2-... - ((-(xy{1}-par(5)).*sind(par(2))+(xy{2}-par(6)).*cosd(par(2)))./par(4)).^2); -end - -function [dpar,zf,dzf] = gaussian2Duncert(par,resid,xy) -% get the confidence intervals -J = guassian2DJacobian(par,xy); -parci = nlparci(par,resid,'Jacobian',J); -dpar = (diff(parci,[],2)./2)'; -[zf,dzf] = nlpredci(@gaussian2D,xy,par,resid,'Jacobian',J); -end - -function J = guassian2DJacobian(par,xy) -% compute the jacobian -x = xy{1}; y = xy{2}; -J(:,1) = exp(- (cosd(par(2)).*(x - par(5)) + sind(par(2)).*(y - par(6))).^2./par(3).^2 - (cosd(par(2)).*(y - par(6)) - sind(par(2)).*(x - par(5))).^2./par(4).^2); -J(:,2) = -par(1).*exp(- (cosd(par(2)).*(x - par(5)) + sind(par(2)).*(y - par(6))).^2./par(3).^2 - (cosd(par(2)).*(y - par(6)) - sind(par(2)).*(x - par(5))).^2./par(4).^2).*((2.*(cosd(par(2)).*(x - par(5)) + sind(par(2)).*(y - par(6))).*(cosd(par(2)).*(y - par(6)) - sind(par(2)).*(x - par(5))))./par(3).^2 - (2.*(cosd(par(2)).*(x - par(5)) + sind(par(2)).*(y - par(6))).*(cosd(par(2)).*(y - par(6)) - sind(par(2)).*(x - par(5))))./par(4).^2); -J(:,3) = (2.*par(1).*exp(- (cosd(par(2)).*(x - par(5)) + sind(par(2)).*(y - par(6))).^2./par(3).^2 - (cosd(par(2)).*(y - par(6)) - sind(par(2)).*(x - par(5))).^2./par(4).^2).*(cosd(par(2)).*(x - par(5)) + sind(par(2)).*(y - par(6))).^2)./par(3)^3; -J(:,4) = (2.*par(1).*exp(- (cosd(par(2)).*(x - par(5)) + sind(par(2)).*(y - par(6))).^2./par(3).^2 - (cosd(par(2)).*(y - par(6)) - sind(par(2)).*(x - par(5))).^2./par(4).^2).*(cosd(par(2)).*(y - par(6)) - sind(par(2)).*(x - par(5))).^2)./par(4)^3; -J(:,5) = par(1).*exp(- (cosd(par(2)).*(x - par(5)) + sind(par(2)).*(y - par(6))).^2./par(3).^2 - (cosd(par(2)).*(y - par(6)) - sind(par(2)).*(x - par(5))).^2./par(4).^2).*((2.*cosd(par(2)).*(cosd(par(2)).*(x - par(5)) + sind(par(2)).*(y - par(6))))./par(3).^2 - (2.*sind(par(2)).*(cosd(par(2)).*(y - par(6)) - sind(par(2)).*(x - par(5))))./par(4).^2); -J(:,6) = par(1).*exp(- (cosd(par(2)).*(x - par(5)) + sind(par(2)).*(y - par(6))).^2./par(3).^2 - (cosd(par(2)).*(y - par(6)) - sind(par(2)).*(x - par(5))).^2./par(4).^2).*((2.*cosd(par(2)).*(cosd(par(2)).*(y - par(6)) - sind(par(2)).*(x - par(5))))./par(4).^2 + (2.*sind(par(2)).*(cosd(par(2)).*(x - par(5)) + sind(par(2)).*(y - par(6))))./par(3).^2); -J(:,7) = ones(size(x)); -end \ No newline at end of file diff --git a/general functions/getSubclasses.m b/general functions/getSubclasses.m deleted file mode 100644 index ed48017..0000000 --- a/general functions/getSubclasses.m +++ /dev/null @@ -1,269 +0,0 @@ -function tb = getSubclasses(rootclass,rootpath) -% GETSUBCLASSES Display all subclasses -% -% GETSUBCLASSES(ROOTCLASS, [ROOTPATH]) -% Lists all subclasses of ROOTCLASS and their node dependency. -% ROOTCLASS can be a string with the name of the class, an -% object or a meta.class(). -% -% It looks for subclasses in the ROOTPATH folder and in all -% its subfolders (at any depth). If ROOTPATH is not specified, -% it is set to the folder where ROOTCLASS is located. -% ROOTCLASS can also be a negative integer indicating how many -% folders above that of ROOTCLASS to begin the search. -% -% TB = GETSUBCLASSES... -% TB is a table with -% .names - name of the subclass -% .from - current node -% .to - node of the direct subclass -% -% If the function is called with no output, it will plot -% a graph() with the dependencies. -% -% -% Example: -% -% which sde -% C:\Program Files\MATLAB\R2016a\toolbox\finance\finsupport\@sde\sde.m % sde constructor -% -% getSubclasses('sde','C:\Program Files\MATLAB\R2016a\toolbox\finance\finsupport\'); -% -% See also: META.CLASS, GRAPH - -rootclass = validateRootclass(rootclass); -if isempty(rootclass) || ~isa(rootclass, 'meta.class') - error('getSubclasses:unrecognizedClass','Unrecognized class.') -end - -if nargin < 2 - rootpath = 0; -end -rootpath = validateRootpath(rootpath, rootclass); - -garray = addNewTree([],rootclass,{rootclass.Name}); -garray = recurseFolder(rootpath, garray); -tb = getFromToNodes(garray{1}); - -if nargout == 0 - G = graph(tb.from, tb.to, [], unique(tb.names,'stable')); - G.plot() -end -end - -% retrieve files and subfolders recursively -function garray = recurseFolder(folder, garray) - -[files, subfld] = getEligible(folder); -garray = checkFiles(files,garray); - -for ii = 1:numel(subfld) - garray = recurseFolder(subfld{ii}, garray); - % cell2table(garray{1}.values,'VariableNames',garray{1}.keys) -end -end - -% List files and folders to search down for subclasses -function [files,subfolders] = getEligible(folder) -list = dir(folder); -idir = [list.isdir]; - -files = {list(~idir).name}; -files = regexp(files,'.+(?=\.m|\.p)','match','once'); - -subfolders = {list(idir).name}; - -% Drop . and .. (setdiff is slow) -nfld = nnz(idir); -idir = false(nfld,1); -for ii = 1:nfld - idir(ii) = subfolders{ii}(1) == '.'; -end -subfolders(idir) = []; - -subfolders = fullfile(folder, subfolders); -end - -% check if files are classes and build up parent relationship -function garray = checkFiles(files,garray) -for ii = 1:numel(files) - mcls = meta.class.fromName(files{ii}); - if isempty(mcls) || isempty(mcls.SuperclassList) || isInTreeArray(garray, mcls.Name) - % Do something with classes with no parents? - continue - end - garray = addNewTree(garray, mcls); - [garray,trash,hasMerged] = getSuperclassTree(mcls, garray, numel(garray), 1); - if hasMerged - garray(end) = []; - end -end -end - -% recursively travel up through all parents assigning node values -function [garray, current_node, doMerge] = getSuperclassTree(mcls,garray,index, current_node) -disp(mcls.Name) -% Add direct parents -[garray{index}, parent_list, current_node] = addParents(mcls, garray{index}, current_node); - -% Check if any parent is mergeable -doMerge = false; -nparen = numel(parent_list); -iexclude = false(nparen,1); -for ii = 1:nparen - p = parent_list(ii); - [doMerge, into] = isInTreeArray(garray(1:end-1), p.Name); - if doMerge - garray{into} = mergeTrees(garray{into}, garray{index}, p.Name); - iexclude(ii) = true; - end -end - -% Exclude merged parents from recursion -parent_list(iexclude) = []; - -% Recurse each parent up -for p = parent_list(:)' - [garray, current_node, doMerge] = getSuperclassTree(p, garray, index, current_node); -end -end - -function [tree, list, nodenum] = addParents(mcls, tree, nodenum) -[list, parent_names] = getParentList(mcls); -for ii = 1:numel(list) - nodenum = nodenum + 1; - [trash,grandparent_names] = getParentList(list(ii)); - tree(parent_names{ii}) = makeVal(grandparent_names,nodenum); -end -end -% get meta classes and names of parents -function [list,names] = getParentList(mcls) -list = mcls.SuperclassList; -if isempty(list) - list = []; - names = mcls.Name; - return -end - -if nargout == 2 - names = arrayfun(@(x) x.Name,list,'un',0); -end -end - -% merge tree into parent containing the root class of interest -function main = mergeTrees(main, subtree, mergeat) - -num_children = subtree.Count - 1; -shift = getNode(main, mergeat); -for k = main.keys - val = main(k{1}); - if val.Node > shift - val.Node = val.Node + num_children; - main(k{1}) = val; - end -end - -nodenum = getNode(subtree, mergeat); -for k = subtree.keys - val = subtree(k{1}); - if val.Node < nodenum - val.Node = val.Node + shift; - main(k{1}) = val; - end -end -end - -function node = getNode(g, classname) -val = g(classname); -node = val.Node; -end - -% checks if class is already part of any tree -function [bool,into] = isInTreeArray(array,classname) -numtrees = numel(array); -bool = false; -into = 0; -for t = 1:numtrees - bool = bool | array{t}.isKey(classname); - if bool - into = t; - return - end -end -end - -% initialize data structure that builds parent relationships -function array = addNewTree(array, class, parents) -if nargin < 3 - [trash, parents] = getParentList(class); - array = addNewTree(array, class, parents); -else - array = [array, {containers.Map(class.Name, makeVal(parents,1))}]; -end -end - -function val = makeVal(parents, nodenum) -if ischar(parents) - parents = {parents}; -end -val = struct('Parent',{parents},'Node',nodenum); -end - -% create list with from-to nodes for graph() input -function tb = getFromToNodes(g) -keys = g.keys; -n = numel(keys); -c = 0; -[from,to] = deal(zeros(n,1)); -names = cell(n,1); -for k = keys - value = g(k{1}); - for p = value.Parent(:)' - c = c+1; - try - to(c) = getNode(g,p{1}); - catch - to(c) = value.Node; - end - from(c) = value.Node; - names{c} = k{1}; - end -end -tb = table(names, from, to); -tb = unique(tb,'rows'); -tb = sortrows(tb,'from'); - -% remove duplicates -[un,trash,subs] = unique(tb.names); -irepeated = accumarray(subs,1) > 1; -irepeated = ismember(tb.names,un(irepeated)); -icircular = tb.from == tb.to; -tb(irepeated & icircular,:) = []; - -% TODO: avoid re-mapping node -[un,trash,from_new] = unique(tb.from); -[trash,pos] = ismember(tb.to, tb.from); -to_new = from_new(pos); -tb.from = from_new; -tb.to = to_new; -end - -function rclass = validateRootclass(rclass) -if ischar(rclass) - rclass = meta.class.fromName(rclass); -elseif isobject(rclass) && ~isa(rclass, 'meta.class') - rclass = meta.class.fromName(class(rclass)); -end -end - -function rpath = validateRootpath(rpath, rclass) -if isnumeric(rpath) && rpath <= 0 && mod(rpath,1) == 0 - s = what(rclass.Name); - for ii = 1:abs(rpath) - s.path = fileparts(s.path); - end - rpath = s.path; -elseif ~ischar(rpath) - error('getSubclasses:unrecognizedPath','Unrecognized path.') -end -end \ No newline at end of file diff --git a/general functions/hist2.m b/general functions/hist2.m deleted file mode 100644 index 9414b0c..0000000 --- a/general functions/hist2.m +++ /dev/null @@ -1,149 +0,0 @@ -function [D,h,cb]=hist2(X1,X2,varargin) -% [D,h,cb]=hist2(X1,X2,varargin) -% Function purpose : Calculates and plots a 2D histogram -% -% Function recives : X1 - first axis coordinates -% X2 - second axis coordinates -% varargin - arguments in format: 'property',value,... -% logColorScale - [default=true] whether to use a logarithmic color scale -% h - axis handle for plotting -% nBins1 - [1x1] - number of bins for coordinate 1 -% nBins2 - [1x1] - number of bins for coordinate 2 -% dX1 - [1x1] - interval for coordinate 1 -% dX2 - [1x1] - interval for coordinate 2 -% edges1 - [1,M] - bin centers for coordinate 1 -% edges2 - [1,M] - bin centers for coordinate 2 -% plotProb [default=false] - display the count histrogram or the probability -% -% Function give back : D - the count histogram -% h - a handle to the density plot (if not entered only calculates and doesnt plot) -% -% Last updated : 27/06/12 - -%set default variables -nBins1=100; -nBins2=100; -dX1=[]; -dX2=[]; -edges1=[]; -edges2=[]; -h=[]; -plotResults=1; -logColorScale=1; -plotColorBar=1; -plotProb=0; -limits1=[]; -limits2=[]; - - -% Output list of default variables -%print out default arguments and values if no inputs are given -if nargin==0 - defaultArguments=who; - for i=1:numel(defaultArguments) - eval(['defaultArgumentValue=' defaultArguments{i} ';']); - if numel(defaultArgumentValue)==1 - disp([defaultArguments{i} ' = ' num2str(defaultArgumentValue)]); - else - fprintf([defaultArguments{i} ' = ']); - disp(defaultArgumentValue); - end - end - return; -end - -% Collects all input variables -for i=1:2:length(varargin) - eval([varargin{i} '=' 'varargin{i+1};']) -end - -%check if histogram limits were provided as inputs -if isempty(limits1) - limits1(1)=min(X1(:)); - limits1(2)=max(X1(:)); -else %if limits were added as a parameter - reject points outside limits - pReject=X1limits1(2); - X1(pReject)=[]; - X2(pReject)=[]; -end -if isempty(limits2) - limits2(1)=min(X2(:)); - limits2(2)=max(X2(:)); -else %if limits were added as a parameter - reject points outside limits - pReject=X2limits2(2); - X1(pReject)=[]; - X2(pReject)=[]; -end - -if isempty(edges1) %coordinate 1 - if isempty(dX1) %divide hist to n bins - if limits1(1)~=limits1(2) - edges1=linspace(limits1(1),limits1(2),nBins1); - else - edges1=linspace(limits1(1)-1,limits1(2)+1,nBins1); - disp('There is only one value on the X dimension, cant plot a 2D hist'); - end - else %divide hist to sections of length dX - edges1=limits1(1):dX1:(limits1(2)+dX1); - edges1=edges1+dX1/2; - end -end -if isempty(edges2) %coordinate 1 - if isempty(dX2) %divide hist to n bins - if limits2(1)~=limits2(2) - edges2=linspace(limits2(1),limits2(2),nBins2); - else - edges2=linspace(limits2(1)-1,limits2(2)+1,nBins2); - disp('There is only one value on the Y dimension, cant plot a 2D hist'); - end - else %divide hist to sections of length dX - edges2=limits2(1):dX2:(limits2(2)+dX2); - edges2=edges2+dX2/2; - end -end - -nBinBins1=numel(edges1); -nBinBins2=numel(edges2); - -%interpolate to grid -x1r=interp1(edges1,1:numel(edges1),X1(:),'nearest','extrap'); -x2r=interp1(edges2,1:numel(edges2),X2(:),'nearest','extrap'); - -D=accumarray([x1r x2r],1,[nBinBins1 nBinBins2])'; -if plotProb - D=D./sum(D); -end - -if plotResults %plot results - if isempty(h) - h=axes; - else - axes(h); - end - colormap(flipud(gray(256))); - if logColorScale - imagesc(edges1,edges2,log10(1+D)); - else - imagesc(edges1,edges2,D); - end - if plotColorBar - cb=colorbar('location','EastOutside'); - if logColorScale - if plotProb - ylabel(cb,'log_{10}(1+Prob.)'); - else - ylabel(cb,'log_{10}(1+#)'); - end - else - if plotProb - ylabel(cb,'Prob.'); - else - ylabel(cb,'#'); - end - - end - else - cb=[]; - end - set(h,'YDir','normal'); -end \ No newline at end of file diff --git a/general functions/hist3.m b/general functions/hist3.m deleted file mode 100644 index 04d1c0c..0000000 --- a/general functions/hist3.m +++ /dev/null @@ -1,93 +0,0 @@ -function [D,h]=hist3(X1,X2,X3,varargin) -%[D,h]=hist3(X,Y,varargin) -% Function purpose : Calculates and plots a 3D histogram -% -% Function recives : X1 - first axis coordinates -% X2 - second axis coordinates -% X3 - third axis coordinates -% varargin - arguments in format: 'property',value,... -% n1 - [1x1] - number of bins for coordinate 1 -% n2 - [1x1] - number of bins for coordinate 2 -% n3 - [1x1] - number of bins for coordinate 3 -% dX1 - [1x1] - interval for coordinate 1 -% dX2 - [1x1] - interval for coordinate 2 -% dX3 - [1x1] - interval for coordinate 3 -% c1 - [1,M] - bin centers for coordinate 1 -% c2 - [1,M] - bin centers for coordinate 2 -% c3 - [1,M] - bin centers for coordinate 3 -% -% Function give back : D - the count histogram -% h - a handle to the density plot (if not entered only calculates and doesnt plot) -% -% Last updated : 27/06/12 - -%set default variables -n1=100; -n2=100; -n3=100; -dX1=[]; -dX2=[]; -dX3=[]; -c1=[]; -c2=[]; -c3=[]; - -%Collects all arguments -for i=1:2:length(varargin) - eval([varargin{i} '=' 'varargin{i+1};']) -end - -minX1=min(X1(:)); -minX2=min(X2(:)); -minX3=min(X3(:)); -maxX1=max(X1(:)); -maxX2=max(X2(:)); -maxX3=max(X3(:)); - -if isempty(c1) %coordinate 1 - if isempty(dX1) %divide hist to n bins - c1=linspace(minX1,maxX1,n1); - else %divide hist to sections of length dX - c1=minX1:dX1:(maxX1+dX1); - c1=x1i+dX1/2; - end -end -if isempty(c2) %coordinate 1 - if isempty(dX2) %divide hist to n bins - c2=linspace(minX2,maxX2,n2); - else %divide hist to sections of length dX - c2=minX2:dX2:(maxX2+dX2); - c2=x2i+dX2/2; - end -end -if isempty(c3) %coordinate 1 - if isempty(dX3) %divide hist to n bins - c3=linspace(minX3,maxX3,n3); - else %divide hist to sections of length dX - c3=minX3:dX3:(maxX3+dX3); - c3=x3i+dX3/2; - end -end - -nBin1=numel(c1); -nBin2=numel(c2); -nBin3=numel(c3); - -%interpolate to grid -x1r=interp1(c1,1:numel(c1),X1(:),'nearest'); -x2r=interp1(c2,1:numel(c2),X2(:),'nearest'); -x3r=interp1(c3,1:numel(c3),X3(:),'nearest'); - -D=accumarray([x1r x2r x3r],1,[nBin1 nBin2 nBin3]); - -if nargout==2 %plot results - h=axes; - cmap=flipud(colormap(gray(256))); - colormap(cmap); - plot3(c1,c2,c3,log10(D)); - cb=colorbar; - ylabel(cb,'log_{10}#'); -end - - - diff --git a/general functions/histcn.m b/general functions/histcn.m deleted file mode 100644 index 6f693d1..0000000 --- a/general functions/histcn.m +++ /dev/null @@ -1,138 +0,0 @@ -function [count edges mid loc] = histcn(X, varargin) -% function [count edges mid loc] = histcn(X, edge1, edge2, ..., edgeN) -% -% Purpose: compute n-dimensional histogram -% -% INPUT -% - X: is (M x N) array, represents M data points in R^N -% - edgek: are the bin vectors on dimension k, k=1...N. -% If it is a scalar (Nk), the bins will be the linear subdivision of -% the data on the range [min(X(:,k)), max(X(:,k))] into Nk -% sub-intervals -% If it's empty, a default of 32 subdivions will be used -% -% OUTPUT -% - count: n-dimensional array count of X on the bins, i.e., -% count(i1,i2,...,iN) = cardinal of X such that -% edge1(i1) <= X(:,i1) < edge1(i1)+1 and -% ... -% edgeN(iN) <= X(:,iN) < edgeN(iN)+1 -% - edges: (1 x N) cell, each provides the effective edges used in the -% respective dimension -% - mid: (1 x N) cell, provides the mid points of the cellpatch used in -% the respective dimension -% - loc: (M x N) array, index location of X in the bins. Points have out -% of range coordinates will have zero at the corresponding dimension. -% -% DATA ACCUMULATE SYNTAX: -% [ ... ] = histcn(..., 'AccumData', VAL); -% where VAL is M x 1 array. Each VAL(k) corresponds to position X(k,:) -% will be accumulated in the cell containing X. The accumulate result -% is returned in COUNT. -% NOTE: Calling without 'AccumData' is similar to having VAL = ones(M,1) -% -% [ ... ] = histcn(..., 'AccumData', VAL, 'FUN', FUN); -% applies the function FUN to each subset of elements of VAL. FUN is -% a function that accepts a column vector and returns -% a numeric, logical, or char scalar, or a scalar cell. A has the same class -% as the values returned by FUN. FUN is @SUM by default. Specify FUN as [] -% for the default behavior. -% -% Usage examples: -% M = 1e5; -% N = 3; -% X = randn(M,N); -% [N edges mid loc] = histcn(X); -% imagesc(mid{1:2},N(:,:,ceil(end/2))) -% -% % Compute the mean on rectangular patch from scattered data -% DataSize = 1e5; -% Lat = rand(1,DataSize)*180; -% Lon = rand(1,DataSize)*360; -% Data = randn(1,DataSize); -% lat_edge = 0:1:180; -% lon_edge = 0:1:360; -% meanData = histcn([Lat(:) Lon(:)], lat_edge, lon_edge, 'AccumData', Data, 'Fun', @mean); -% -% See also: HIST, ACCUMARRAY -% -% Bruno Luong: -% Last update: 25/August/2011 - -if ndims(X)>2 - error('histcn: X requires to be an (M x N) array of M points in R^N'); -end -DEFAULT_NBINS = 32; - -AccumData = []; -Fun = {}; - -% Looks for where optional parameters start -% For now only 'AccumData' is valid -split = find(cellfun('isclass', varargin, 'char'), 1, 'first'); -if ~isempty(split) - for k = split:2:length(varargin) - if strcmpi(varargin{k},'AccumData') - AccumData = varargin{k+1}(:); - elseif strcmpi(varargin{k},'Fun') - Fun = varargin(k+1); % 1x1 cell - end - end - varargin = varargin(1:split-1); -end - -% Get the dimension -nd = size(X,2); -edges = varargin; -if nd0, 2); -if ~isempty(AccumData) - count = accumarray(loc(hasdata,:), AccumData(hasdata), sz, Fun{:}); -else - count = accumarray(loc(hasdata,:), 1, sz); -end - -return - -end % histcn diff --git a/general functions/license.txt b/general functions/license.txt deleted file mode 100644 index e9a5419..0000000 --- a/general functions/license.txt +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2015, Yair Altman -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/general functions/movingWindowIndices.m b/general functions/movingWindowIndices.m deleted file mode 100644 index a8a9b34..0000000 --- a/general functions/movingWindowIndices.m +++ /dev/null @@ -1,49 +0,0 @@ -function [startIdx,endIdx,allIdx,tWindowCenter_sec]=movingWindowIndices(Nsamples,win_sec,Fs_Hz,OL_sec) -% [startIdx,endIdx,tWindowCenter_sec]=movingWindowIndices(Nsamples,win_sec,Fs_Hz,OL_percent); -% Function purpose : calculate indices for moving window analysis -% -% Recives : Nsamples - the number of samples in the signal -% win_sec - the window duration [sec] -% Fs_Hz - the signal's sampling frequency -% OL_sec - the degree of overlap [sec] -% -% Function give back : startIdx - the start indices of the windows -% endIdx - the end indices of the windows -% allIdx - all the indices of the moving window (each column corresponds to one moving window) -% tWindowCenter_sec - the times of window centers [sec] -% -% Recomended usage : [startIdx,endIdx,allIdx,tWindowCenter_sec]=movingWindowIndices(1e6,2e-6,800e6,400e6) -% Last updated : 13/11/12 - -%translate window size and overlap to samples and check that the window size corresponds to the sampling rate -win_samples=win_sec*Fs_Hz; -OL_samples=OL_sec*Fs_Hz; -if win_samples~=round(win_samples) - win_samples=round(win_samples); - disp(['Due to mismatch between window size and sampling freq., the # of samples in window was rounded to: ' num2str(win_samples)]); -end - -if Nsamples/Fs_Hz length cut to ' num2str(startIdx(end)+win_samples-1) ' samples']); -end - -% allocate segmented matrices -allIdx = zeros(win_samples,nSegments); - -% parse matrix -Idx = (1:win_samples)'; -allIdx(:) = Idx(:,ones(1,nSegments))+startIdx(ones(win_samples,1),:)-1; diff --git a/general functions/mwwtest.m b/general functions/mwwtest.m deleted file mode 100644 index 34e73c3..0000000 --- a/general functions/mwwtest.m +++ /dev/null @@ -1,131 +0,0 @@ -function STATS=mwwtest(x1,x2) -%Mann-Whitney-Wilcoxon non parametric test for two unpaired groups. -%This file execute the non parametric Mann-Whitney-Wilcoxon test to evaluate the -%difference between unpaired samples. If the number of combinations is less than -%20000, the algorithm calculates the exact ranks distribution; else it -%uses a normal distribution approximation. The result is not different from -%RANKSUM MatLab function, but there are more output informations. -%There is an alternative formulation of this test that yields a statistic -%commonly denoted by U. Also the U statistic is computed. -% -% Syntax: STATS=MWWTEST(X1,X2) -% -% Inputs: -% X1 and X2 - data vectors. -% Outputs: -% - T and U values and p-value when exact ranks distribution is used. -% - T and U values, mean, standard deviation, Z value, and p-value when -% normal distribution is used. -% If STATS nargout was specified the results will be stored in the STATS -% struct. -% -% Example: -% -% X1=[181 183 170 173 174 179 172 175 178 176 158 179 180 172 177]; -% -% X2=[168 165 163 175 176 166 163 174 175 173 179 180 176 167 176]; -% -% Calling on Matlab the function: mwwtest(X1,X2) -% -% Answer is: -% -% MANN-WHITNEY-WILCOXON TEST -% --------------------------------------------------------------------------- -% Group 1 Group 2 -% numerosity 15 15 -% Sum of Ranks (W) 270.0 195.0 -% Mean rank 18.0 13.0 -% Test variable (U) 75.0 150.0 -% --------------------------------------------------------------------------- -% Sample size is large enough to use the normal distribution approximation -% Mean 112.5 -% Standard deviation corrected for ties 24.0474 -% Z corrected for continuity 1.5386 1.5386 -% p-value (1-tailed) 0.06195 -% p-value (2-tailed) 0.12389 -% --------------------------------------------------------------------------- -% -% Created by Giuseppe Cardillo -% giuseppe.cardillo-edta@poste.it -% -% To cite this file, this would be an appropriate format: -% Cardillo G. (2009). MWWTEST: Mann-Whitney-Wilcoxon non parametric test for two unpaired samples. -% http://www.mathworks.com/matlabcentral/fileexchange/25830 - -%Input Error handling -if ~isvector(x1) || ~isvector(x2) - error('MWWTEST requires vector rather than matrix data.'); -end -if ~all(isfinite(x1)) || ~all(isnumeric(x1)) || ~all(isfinite(x2)) || ~all(isnumeric(x2)) - error('Warning: all X1 and X2 values must be numeric and finite') -end - -%set the basic parameter -n1=length(x1); n2=length(x2); NP=n1*n2; N=n1+n2; N1=N+1; k=min([n1 n2]); - -[A,B]=tiedrank([x1(:); x2(:)]); %compute the ranks and the ties -R1=A(1:n1); R2=A(n1+1:end); -T1=sum(R1); T2=sum(R2); -U1=NP+(n1*(n1+1))/2-T1; U2=NP-U1; -tr=repmat('-',1,75); %set the divisor -disp('MANN-WHITNEY-WILCOXON TEST') -disp(tr) -fprintf('\t\t\t\tGroup 1\t\tGroup 2\n') -fprintf('numerosity\t\t\t%i\t\t%i\n',n1,n2) -fprintf('Sum of Ranks (W)\t\t%0.1f\t\t%0.1f\n',T1,T2) -fprintf('Mean rank\t\t\t%0.1f\t\t%0.1f\n',T1/n1,T2/n2) -fprintf('Test variable (U)\t\t%0.1f\t\t%0.1f\n',U1,U2) -disp(tr) -if nargout - STATS.n=[n1 n2]; - STATS.W=[T1 T2]; - STATS.mr=[T1/n1 T2/n2]; - STATS.U=[U1 U2]; -end -if round(exp(gammaln(N1)-gammaln(k+1)-gammaln(N1-k))) > 20000 - mU=NP/2; - if B==0 - sU=realsqrt(NP*N1/12); - else - sU=realsqrt((NP/(N^2-N))*((N^3-N-2*B)/12)); - end - Z1=(abs(U1-mU)-0.5)/sU; Z2=(abs(U2-mU)-0.5)/sU; - p=1-normcdf(Z1); %p-value - disp('Sample size is large enough to use the normal distribution approximation') - fprintf('Mean\t\t\t\t\t%0.1f\n',mU) - if B==0 - fprintf('Standard deviation\t\t\t%0.4f\n',sU) - else - fprintf('Standard deviation corrected for ties\t%0.4f\n',sU) - end - fprintf('Z corrected for continuity\t%0.4f\t\t%0.4f\n',Z1,Z2) - fprintf('p-value (1-tailed)\t\t\t%0.5f\n',p) - fprintf('p-value (2-tailed)\t\t\t%0.5f\n',2*p) - if nargout - STATS.method='Normal approximation'; - STATS.mU=mU; - STATS.sU=sU; - STATS.Z=Z1; - STATS.p=[p 2*p]; - end -else - disp('Sample size is small enough to use the exact Mann-Whitney-Wilcoxon distribution') - if n1<=n2 - w=T1; - else - w=T2; - end - pdf=sum(nchoosek(A,k),2); - P = [sum(pdf<=w) sum(pdf>=w)]./length(pdf); - p = min(P); - fprintf('Test variable (W)\t\t\t%0.1f\n',w) - fprintf('p-value (1-tailed)\t\t\t%0.5f\n',p) - fprintf('p-value (2-tailed)\t\t\t%0.5f\n',2*p) - if nargout - STATS.method='Exact distribution'; - STATS.T=w; - STATS.p=[p 2*p]; - end -end -disp(tr) -disp(' ') diff --git a/general functions/normZeroOne.m b/general functions/normZeroOne.m deleted file mode 100644 index 28fcc27..0000000 --- a/general functions/normZeroOne.m +++ /dev/null @@ -1,13 +0,0 @@ -function [M]=normZeroOne(M,scale) -%[M]=normZeroOne(M,scale) -%normalize each column between 0-1 (or scale) separately -if nargin==1 - scale=[0 1]; -end -S=size(M); -if S(1)==1 || S(2)==1 - M=(M-min(M))./(max(M)-min(M)); -elseif numel(S)==2 - M=bsxfun(@rdivide,bsxfun(@minus,M,min(M)),max(M)-min(M)); -end -M=M.*(scale(2)-scale(1))+scale(1); diff --git a/general functions/orderClustering.m b/general functions/orderClustering.m deleted file mode 100644 index 8d85cdb..0000000 --- a/general functions/orderClustering.m +++ /dev/null @@ -1,160 +0,0 @@ -% [R,A]=orderClustering(M,varargin) -% Function purpose : Calculates a similarity matrix between different activity profiles -% -% Function recives : M - The activity matrix [Bind x Neurons x Activity trace length] -% varagin (list of possible options) -% -% Function give back : R -% Recommended usage: [R]=orderClustering(M); -% -% Last updated : 21/09/18 -function [R,TimeOrder,RS,A,AS]=orderClustering(M,varargin) - -input='activity'; %options: 'activity'/'delays' -Threshold=0.1; %threshold for insignificant delays -weights='Binary';%options 'NonBinary'/'Binary' -method='FirstSpike'; -averageOverNeurons=false; %if false, will compare sequences to the average propagation for each neuron -usePenalty=true; -nShuffles=10; -nearestNeigh=10; - - -%Collects all options -for i=1:2:length(varargin) - eval([varargin{i} '=' 'varargin{i+1};']) -end - -if strcmp(input,'activity') - % intialize variables - [NBs NN L]=size(M); %[NB number X Neuron number X Activity window - - if strcmp(method,'FirstSpike') - M2=zeros(size(M)); - for i=1:size(M,1) - tmp=findfirst(M(i,:,:), 3); - p=find(tmp>0); - for j=1:numel(p) - M2(i,p(j),tmp(p(j)))=1; - end - end - M=M2; - end - - TimeOrder=zeros(NBs,NN); - A=zeros(NBs,NN,NN); - AS=zeros(NBs,NN,NN,nShuffles); - - %Build a binary delay matrix of all neuronal pears for every NB (network burst) - Times=(1:L)'; - for i=1:NBs - tmpM=squeeze(M(i,:,:)); - TimeOrder(i,:)=tmpM*Times./sum(tmpM,2); %calculates the average time delay for every neuron - TimeOrderShuff=TimeOrder(i,:); - pNonNaN=find(~isnan(TimeOrder(i,:))); - %Build a delay matrix for the ith NB - - for l=1:nShuffles - TimeOrderShuff(pNonNaN)=TimeOrder(i,pNonNaN(randperm(numel(pNonNaN)))); - for m=1:NN - for n=1:NN - A(i,m,n)=TimeOrder(i,m)-TimeOrder(i,n); - AS(i,m,n,l)=TimeOrderShuff(m)-TimeOrderShuff(n); - end - end - end - end -elseif strcmp(input,'delays') - [NBs NN junk]=size(M); %[NB number X Neuron number X Neuron number - A=M; - M=[]; -else error('!!!input variable not given correctly'); -end -%Conversion to Binary delay matrix (unless exists 'NonBinaryWeights') -if strcmp(weights,'Binary') - A(A>Threshold)=1; - A(A<-Threshold)=-1; - A(A<=Threshold & A>=-Threshold)=0; - %Matices should be anti-symetric - AS(AS>Threshold)=1; - AS(AS<-Threshold)=-1; - AS(AS<=Threshold & AS>=-Threshold)=0; - -elseif strcmp(weights,'NonBinary') -else error('!!!weights variable not given correctly'); -end - -hWB=waitbar(0,'Building similarity matrices...'); -if averageOverNeurons - % intialize variables - R=zeros(NBs,NBs); - RS=zeros(NBs,NBs); - RSstd=zeros(NBs,NBs); - %Build similarity matrix - for i=1:NBs - for j=1:NBs - tmpA=A(i,:,:).*A(j,:,:); - tmpAS=AS(i,:,:,:).*AS(j,:,:,:); - - if ~usePenalty - tmpA(tmpA<0)=0; - tmpAS(tmpAS<0)=0; - end - %this section should be tested first!!! - R(i,j)=nansum(tmpA(:))/sum(tmpA(:)~=0 & ~isnan(tmpA(:))); - RS(i,j)=nansum(tmpAS(:))/sum(tmpAS(:)~=0 & ~isnan(tmpAS(:))); - RSstd(i,j)=nanstd(nansum(sum(tmpAS,2),3)./sum(nansum(tmpAS~=0 & ~isnan(tmpAS),2),3)); - end - waitbar(i/NBs,hWB); - end -else - % intialize variables - R=zeros(NBs,NBs,NN); - RS=zeros(NBs,NBs,NN,nShuffles); - - %determine average time order baseline and sort correlation matrices accordingly - [~,ord]=sort(nanmean(TimeOrder)); - A=A(:,ord,ord); - AS=AS(:,ord,ord,:); - - Mat=~(tril(ones([NN NN]),nearestNeigh) & triu(ones([NN NN]),-nearestNeigh)) & ~eye([NN NN]); - A(permute(repmat(Mat,[1 1 NBs]),[3 1 2]))=0; - AS(permute(repmat(Mat,[1 1 NBs nShuffles]),[3 1 2 4]))=0; - - for i=1:NBs - for j=1:NBs - tmpA=A(i,:,:).*A(j,:,:); - tmpAS=AS(i,:,:,:).*AS(j,:,:,:); - - if ~usePenalty - tmpA(tmpA<0)=0; - tmpAS(tmpAS<0)=0; - end - - R(i,j,:)=nansum(tmpA,2)./sum(tmpA~=0 & ~isnan(tmpA),2); - RS(i,j,:,:)=nansum(tmpAS,2)./sum(tmpAS~=0 & ~isnan(tmpAS),2); - %{ - figure; - h1=subplot(2,4,1);imagesc(conv2(squeeze(M(i,ord,:)),ones(1,5))); - h2=subplot(2,4,2);imagesc(conv2(squeeze(M(j,ord,:)),ones(1,5))); - subplot(2,4,3);pcolor(squeeze(A(i,:,:))); - subplot(2,4,4);pcolor(squeeze(A(j,:,:))); - subplot(2,4,5);pcolor(squeeze(AS(i,:,:,1))); - subplot(2,4,6);pcolor(squeeze(AS(j,:,:,1))); - subplot(2,4,7);pcolor(squeeze(tmpA)); - subplot(2,4,8);pcolor(squeeze(tmpAS(1,:,:,1))); - colormap(h1,flipud(gray(2)));colormap(h2,flipud(gray(2))); - - figure;plot(squeeze(R(i,j,:)),'o-k');hold on;plot(squeeze(RS(i,j,:)),'o-r');plot(squeeze(RSstd(i,j,:)),'o-','color',[0.8 0.5 0.5]); - %} - end - waitbar(i/NBs,hWB); - end -end -%{ -figure; -for i=1:12 - subplot(3,4,i);imagesc(squeeze(M(i,ord,:)));colormap(flipud(gray(2))); -end -%} -close(hWB); \ No newline at end of file diff --git a/general functions/parforSave.m b/general functions/parforSave.m deleted file mode 100644 index d7ce73d..0000000 --- a/general functions/parforSave.m +++ /dev/null @@ -1,7 +0,0 @@ -function parforSave(varargin) -evalExpression='save('; -for i=1:numel(varargin) - evalExpression=[evalExpression '''' varargin{i} '''' ',' '']; -end -evalExpression=[evalExpression(1:end-1) ');']; -evalin('caller',evalExpression); \ No newline at end of file diff --git a/general functions/peakfit2d.m b/general functions/peakfit2d.m deleted file mode 100644 index 075528a..0000000 --- a/general functions/peakfit2d.m +++ /dev/null @@ -1,78 +0,0 @@ -function P = peakfit2d(Z) -% Find sub-sample location of a global peak within 2D-matrix by applying -% two dimensional polynomial fit & extremum detection. -% -% Sample usage: -% >> M = exp(-((1:30) - 19.5).^2/(2*5^2)); % gauss: center=19.5; sigma=5 -% >> P = peakfit2d(M'*M); % find peak in 2D-gauss -% >> disp(P); -% 19.5050 19.5050 -% -% Algebraic solution derived with the following steps: -% -% 0.) Define Approximation-Function: -% -% F(x,y) => z = a*x^2+b*x*y+c*x+d+e*y^2+f*y -% -% 1.) Formulate equation for sum of squared differences with -% -% x=-1:1,y=-1:1,z=Z(x,y) -% -% SSD = [ a*(-1)^2+b*(-1)*(-1)+c*(-1)+d+e*(-1)^2+f*(-1) - Z(-1,-1) ]^2 + ... -% ... -% a*(+1)^2+b*(+1)*(+1)+c*(+1)+d+e*(+1)^2+f*(+1) - Z(-1,-1) ]^2 -% -% 2.) Differentiate SSD towards each parameter -% -% dSSD / da = ... -% ... -% dSSD / df = ... -% -% 3.) Solve linear system to get [a..f] -% -% 4.) Differentiate F towards x and y and solve linear system for x & y -% -% dF(x,y) / dx = a*... = 0 ! -% dF(x,y) / dy = b*... = 0 ! - -%% Check input -sZ = size(Z); -if min(sZ)<2 - disp('Wrong matrix size. Input matrix should be numerical MxN type.'); - P = [0 0]; - return; -end - - -%% peak approximation using 2D polynomial fit within 9 point neighbourship - -% find global maximum and extract 9-point neighbourship -[~,p] = max(Z(:)); -[yp,xp]=ind2sub(sZ,p); -if (yp==1)||(yp==sZ(1))||(xp==1)||(xp==sZ(2)) - disp('Maximum position at matrix border. No subsample approximation possible.'); - P = [yp xp]; - return; -end - -K = Z(yp-1:yp+1,xp-1:xp+1); - -if any(isnan(K)) - disp('There are nans in the 3x3 square surrounding the matrix. No subsample approximation possible.'); - P = [yp xp]; - return; -end - -% approximate polynomial parameter -a = (K(2,1)+K(1,1)-2*K(1,2)+K(1,3)-2*K(3,2)-2*K(2,2)+K(2,3)+K(3,1)+K(3,3)); -b = (K(3,3)+K(1,1)-K(1,3)-K(3,1)); -c = (-K(1,1)+K(1,3)-K(2,1)+K(2,3)-K(3,1)+K(3,3)); -%d = (2*K(2,1)-K(1,1)+2*K(1,2)-K(1,3)+2*K(3,2)+5*K(2,2)+2*K(2,3)-K(3,1)-K(3,3)); -e = (-2*K(2,1)+K(1,1)+K(1,2)+K(1,3)+K(3,2)-2*K(2,2)-2*K(2,3)+K(3,1)+K(3,3)); -f = (-K(1,1)-K(1,2)-K(1,3)+K(3,1)+K(3,2)+K(3,3)); - -% (ys,xs) is subpixel shift of peak location relative to point (2,2) -ys = (6*b*c-8*a*f)/(16*e*a-9*b^2); -xs = (6*b*f-8*e*c)/(16*e*a-9*b^2); - -P = [ys+yp xs+xp]; \ No newline at end of file diff --git a/general functions/plotShifted.m b/general functions/plotShifted.m deleted file mode 100644 index 948e5f6..0000000 --- a/general functions/plotShifted.m +++ /dev/null @@ -1,105 +0,0 @@ -function varargout=plotShifted(varargin) -%plotShifted Linear shifted plot. -% plotShifted(X,Y) plots matrix Y versus vector X, where each column of Y is one linear plot and these plots are shifted (on the y axis) by a constant. -% plot shifted can get the same inputs as Matlab PLOT function -% -% plotShifted(Y) plots the columns of Y versus their index. -% If Y is complex, plotShifted(Y) is equivalent to plotShifted(real(Y),imag(Y)). -% In all other uses of plotShifted, the imaginary part is ignored. -% -% Various line types, plot symbols and colors may be obtained with -% plotShifted(X,Y,S) where S is a character string made from one element -% from any or all the following 3 columns: -% -% b blue . point - solid -% g green o circle : dotted -% r red x x-mark -. dashdot -% c cyan + plus -- dashed -% m magenta * star (none) no line -% y yellow s square -% k black d diamond -% w white v triangle (down) -% ^ triangle (up) -% < triangle (left) -% > triangle (right) -% p pentagram -% h hexagram -% -% For example, plotShifted(X,Y,'c+:') plots a cyan dotted line with a plus -% at each data point; plotShifted(X,Y,'bd') plots blue diamond at each data -% point but does not draw any line. -% -% The plotShifted command, if no color is specified, makes automatic use of -% the colors specified by the axes ColorOrder property. By default, -% plotShifted cycles through the colors in the ColorOrder property. For -% monochrome systems, plotShifted cycles over the axes LineStyleOrder property. -% -% Note that RGB colors in the ColorOrder property may differ from -% similarly-named colors in the (X,Y,S) triples. For example, the -% second axes ColorOrder property is medium green with RGB [0 .5 0], -% while plotShifted(X,Y,'g') plots a green line with RGB [0 1 0]. -% -% If you do not specify a marker type, plotShifted uses no marker. -% If you do not specify a line style, plotShifted uses a solid line. -% -% plotShifted(AX,...) plots into the axes with handle AX. -% -% plotShifted returns a column vector of handles to lineseries objects, one -% handle per plotted line. -% -% The X,Y pairs, or X,Y,S triples, can be followed by -% parameter/value pairs to specify additional properties -% of the lines. For example, plotShifted(X,Y,'LineWidth',2,'Color',[.6 0 0]) -% will create a plot with a dark red line width of 2 points. -% -% Example -% x = 1:100 -% y = randn(100,1000); -% plotShifted(x,y,'--rs','verticalShift',30,... -% 'MarkerEdgeColor','k',... -% 'MarkerFaceColor','g',... -% 'MarkerSize',10) -% -% See also PLOTTOOLS, SEMILOGX, SEMILOGY, LOGLOG, PLOTYY, PLOT3, GRID, -% TITLE, XLABEL, YLABEL, AXIS, AXES, HOLD, LEGEND, SUBPLOT, SCATTER. - -% If the NextPlot axes property is "replace" (HOLD is off), plotShifted resets -% all axes properties, except Position, to their default values, -% deletes all axes children (line, patch, text, surface, and -% image objects), and sets the View property to [0 90]. - -% Up dated by Mark Shein-Idelson -% $Revision: 5.19.4.10 $ $Date: 2014/05/14 $ - -%find the data input variable -pNumeric=cellfun(@(x) isnumeric(x),varargin); -pFirst=find(pNumeric,1,'first'); -if nargin>1 && pNumeric(pFirst+1) %check if format is time,data or data - pData=pFirst+1;%for time,data -else - pData=pFirst;% for data -end - -%look for inputs into varargin which are within the local list, place them into Par and remove them from varargin -localPropertyList={'verticalShift'}; -for i=1:numel(localPropertyList) - pProp=find(strcmp(localPropertyList{i},varargin)); - if ~isempty(pProp) %assign input value from varargin - Par.(localPropertyList{i})=varargin{pProp+1}; - varargin(pProp:pProp+1)=[]; - else %assign empty value - Par.(localPropertyList{i})=[]; - end -end - -%determine the vertical shifts -[nSamples,nCh]=size(varargin{pData}); -if isempty(Par.verticalShift); %automatically detection - Par.verticalShift=cumsum(nanstd(varargin{pData})*3); -elseif numel(Par.verticalShift)==1 %manual detection - Par.verticalShift=0:Par.verticalShift:(Par.verticalShift*(nCh-1)); -end - -varargin{pData}=bsxfun(@plus,varargin{pData},Par.verticalShift); -[varargout]=plot(varargin{:}); -varargout={varargout(1:nargout)}; diff --git a/general functions/polyDer2D.m b/general functions/polyDer2D.m deleted file mode 100644 index 81867fe..0000000 --- a/general functions/polyDer2D.m +++ /dev/null @@ -1,85 +0,0 @@ -function [fx,fy] = polyDer2D(p,x,y,n,m) -%POLYDER2D Evaluate a 2-D polynomial using Horner's method. -% F = POLYDER2D(P,X,Y,N,M) evaluates the 2-D polynomial P at the points -% specified by X and Y, which must have the same dimensions. The output F -% will have the same dimensions as X and Y. N and M specify the order of X -% and Y respectively. Polynomial coefficients are in the following order. -% -% F(X,Y) = P_1 * X^N * Y^M + P_2 * X^{N-1} * Y^M + ... + P_{N+1} * Y^M + ... -% P_{N+2} * X^N * Y^{M-1} + P_{N+3} * X^{N-1} * Y^{M-1} + ... + P_{2*(N+1)} * Y^{M-1} + ... -% ... -% P_{M*(N+1)+1} * X^N + P_{M*(N+1)+2} * X^{N-1} + ... + P_{(N+1)*(M+1)} -% -% See also: POLYFITN by John D'Errico on MathWorks MATLAB Central FEX -% http://www.mathworks.com/matlabcentral/fileexchange/34765-polyfitn -% -% Mark Mikofski, http://poquitopicante.blogspot.com -% Version 1-0, 2013-04-17 - -%% LaTex -% -% $$f\left(x,y\right)=p_1 x^n y^m+p_2 x^{\left(n-1\right)} y^m+\ldots+p_{n+1} y^m+\ldots$$ -% -% $$p_{n+2}x^ny^{\left(m-1\right)}+p_{n+3}x^{\left(n-1\right)}y^{\left(m-1\right)}+\ldots+p_{2\left(n+1\right)}y^{\left(m-1\right)}+\ldots$$ -% -% $$\ldots$$ -% -% $$p_{m\left(n+1\right)+1}*x^n+p_{m\left(n+1\right)+2}*x^{\left(n-1\right)}+\ldots+p_{\left(n+1\right)\left(m+1\right)}$$ - -%% check input args -validateattributes(p,{'numeric'},{'2d','nonempty','real','finite'}, ... - 'polyDer2D','p',1) -validateattributes(x,{'numeric'},{'nonempty','real','finite'}, ... - 'polyDer2D','x',2) -validateattributes(y,{'numeric'},{'nonempty','real','finite'}, ... - 'polyDer2D','y',3) -assert(all(size(x)==size(y)),'polyDer2D:sizeMismatch', ... - 'X and Y must be the same size.') -% use size of p to set n & m -pdims = size(p); -if nargin<4 && all(pdims>1) - n = pdims(1)-1; - m = pdims(2)-1; -end -validateattributes(n,{'numeric'},{'scalar','integer','positive','<',10}, ... - 'polyDer2D','n',4) -validateattributes(m,{'numeric'},{'scalar','integer','positive','<',10}, ... - 'polyDer2D','m',5) -if all(pdims>1) - assert(pdims(1)==n+1,'polyDer2D:xOrderMismatch', ... - 'The number of x coefficients doesn''t match the order n.') - assert(pdims(2)==m+1,'polyDer2D:yOrderMismatch', ... - 'The number of y coefficients doesn''t match the order m.') -end -p = p(:); -Np = numel(p); -assert(Np==(n+1)*(m+1),'OrderMismatch', ... - ['The number of x & y coefficients doesn''t match the orders ', ... - 'n & m.']) -%% fx = df/dx -fx = n*p(1); -for ni = 1:n-1 - fx = fx.*x+(n-ni)*p(1+ni); -end -for mi = 1:m - mj = (n+1)*mi+1; - gx = n*p(mj); - for ni = 1:n-1 - gx = gx.*x+(n-ni)*p(mj+ni); - end - fx = fx.*y+gx; -end -%% fy = df/dy -fy = p(1); -for ni = 1:n - fy = fy.*x+p(1+ni); -end -fy = m*fy; -for mi = 1:m-1 - mj = (n+1)*mi+1; - gy = p(mj); - for ni = 1:n - gy = gy.*x+p(mj+ni); - end - fy = fy.*y+(m-mi)*gy; -end \ No newline at end of file diff --git a/general functions/polyFit2D.m b/general functions/polyFit2D.m deleted file mode 100644 index 3fde790..0000000 --- a/general functions/polyFit2D.m +++ /dev/null @@ -1,61 +0,0 @@ -function p = polyFit2D(f,x,y,n,m) -%POLYFIT2D Fit data with a 2-D polynomial. -% P = POLYFIT2D(F,X,Y,N,M) determines the 2-D polynomial P that best fit the -% data F(X,Y) in the least squares sense. Polynomial coefficients are in the -% following order. -% -% F(X,Y) = P_1 * X^N * Y^M + P_2 * X^{N-1} * Y^M + ... + P_{N+1} * Y^M + ... -% P_{N+2} * X^N * Y^{M-1} + P_{N+3} * X^{N-1} * Y^{M-1} + ... + P_{2*(N+1)} * Y^{M-1} + ... -% ... -% P_{M*(N+1)+1} * X^N + P_{M*(N+1)+2} * X^{N-1} + ... + P_{(N+1)*(M+1)} -% -% See also: POLYFITN by John D'Errico on MathWorks MATLAB Central FEX -% http://www.mathworks.com/matlabcentral/fileexchange/34765-polyfitn -% -% Mark Mikofski, http://poquitopicante.blogspot.com -% Version 1-0, 2013-03-13 - -%% LaTex -% -% $$f\left(x,y\right)=p_1 x^n y^m+p_2 x^{\left(n-1\right)} y^m+\ldots+p_{n+1} y^m+\ldots$$ -% -% $$p_{n+2}x^ny^{\left(m-1\right)}+p_{n+3}x^{\left(n-1\right)}y^{\left(m-1\right)}+\ldots+p_{2\left(n+1\right)}y^{\left(m-1\right)}+\ldots$$ -% -% $$\ldots$$ -% -% $$p_{m\left(n+1\right)+1}*x^n+p_{m\left(n+1\right)+2}*x^{\left(n-1\right)}+\ldots+p_{\left(n+1\right)\left(m+1\right)}$$ - -%% check input args -validateattributes(f,{'numeric'},{'nonempty','real','finite'}, ... - 'polyFit2D','f',1) -validateattributes(x,{'numeric'},{'nonempty','real','finite'}, ... - 'polyFit2D','x',2) -validateattributes(y,{'numeric'},{'nonempty','real','finite'}, ... - 'polyFit2D','y',3) -assert(all(size(x)==size(y)),'polyFit2D:sizeMismatch', ... - 'X and Y must be the same size.') -assert(all(size(x)==size(f)),'polyFit2D:sizeMismatch', ... - 'X and F must be the same size.') -validateattributes(n,{'numeric'},{'scalar','integer','positive','<',10}, ... - 'polyFit2D','n',4) -validateattributes(m,{'numeric'},{'scalar','integer','positive','<',10}, ... - 'polyFit2D','m',5) -Npoints = numel(f); -assert(all((n+1)*(m+1)1) - n = pdims(1)-1; - m = pdims(2)-1; -end -validateattributes(n,{'numeric'},{'scalar','integer','positive','<',10}, ... - 'polyVal2D','n',4) -validateattributes(m,{'numeric'},{'scalar','integer','positive','<',10}, ... - 'polyVal2D','m',5) -if all(pdims>1) - assert(pdims(1)==n+1,'polyVal2D:xOrderMismatch', ... - 'The number of x coefficients doesn''t match the order n.') - assert(pdims(2)==m+1,'polyVal2D:yOrderMismatch', ... - 'The number of y coefficients doesn''t match the order m.') -end -%% evaluate polynomial P -f = p(1); -for ni = 1:n - f = f.*x+p(1+ni); -end -for mi = 1:m - mj = (n+1)*mi+1; - g = p(mj); - for ni = 1:n - g = g.*x+p(mj+ni); - end - f = f.*y+g; -end diff --git a/general functions/propertiesGUI.m b/general functions/propertiesGUI.m deleted file mode 100644 index dc80b79..0000000 --- a/general functions/propertiesGUI.m +++ /dev/null @@ -1,764 +0,0 @@ -function [hPropsPane,parameters] = propertiesGUI(hParent, parameters) -% propertiesGUI displays formatted editable list of properties -% -% Syntax: -% [hPropsPane,parameters] = propertiesGUI(hParent, parameters) -% -% Description: -% propertiesGUI processes a list of data properties and displays -% them in a GUI table, where each parameter value has a unique -% associated editor. -% -% propertiesGUI by itself, with no input parameters, displays a demo -% -% By default, propertiesGUI identifies and processes the following -% field types: signed, unsigned, float, file, folder, text or string, -% color, IPAddress, password, date, boolean, cell-array, numeric array, -% class object. -% -% Inputs: -% hParent - optional handle of a parent GUI container (figure/uipanel -% /uitab) in which the properties table will appear. -% If missing or empty or 0, the table will be shown in a -% new modal dialog window; otherwise it will be embedded -% in the parent container. -% -% parameters - struct or object with data fields. The fields are -% processed separately to determine their corresponding cell -% editor. If parameters is not specified, then the global -% test_data will be used. If test_data is also empty, then -% a demo of several different data types will be used. -% -% Outputs: -% hPropsPane - handle of the properties panel widget, which can be -% customized to display field descriptions, toolbar, etc. -% -% parameters - the resulting (possibly-updated) parameters struct. -% Naturally, this is only relevant in case of a modal dialog. -% -% (global test_data) - this global variable is updated internally when -% the button is clicked. It is meant to enable easy data -% passing between the properties GUI and other application -% component. Using global vars is generally discouraged as -% bad programming, but it simplifies component interaction. -% -% Customization: -% This utility is meant to be used either as stand-alone, or as a -% template for customization. For example, you can attach a unique -% description to each property that will be shown in an internal -% sub-panel: see the customizePropertyPane() and preparePropsList() -% sub-functions. -% -% When passing the properties in an input parameters struct, the -% utility automatically inspects each struct field and assigns a -% corresponding cell-editor with no description and a field label -% that reflects the field name. The properties are automatically -% set as modifiable (editable) and assigned a default callback -% function (propUpdatedCallback() sub-function). -% See the demoParameters() sub-function for some examples. -% -% You can have specific control over each property's description, -% label, editability, cell-editor and callback function. See the -% preparePropsList() sub-functions for some examples. You can add -% additional cell-editors/renderers in the newProperty() sub-function. -% -% You can place specific control over the acceptable property values -% by entering custom code into the checkProp() sub-function. -% -% Future development: -% 1. Fix the renderer/editor for numeric and cell arrays -% 2. Enable more control over appearance and functionality via -% propertiesGUI's input parameters -% 3. Add additional built-in cell editors/renderers: time, slider, -% point, rectangle (=position), font, ... -% -% Example: -% propertiesGUI; % displays the demo -% -% params.name = 'Yair'; -% params.age = uint8(41); -% params.folder = pwd; -% params.date = now; -% params.size.width = 10; -% params.size.height = 20; -% [hPropsPane, params] = propertiesGUI(params); -% -% Bugs and suggestions: -% Please send to Yair Altman (altmany at gmail dot com) -% -% Warning: -% This code heavily relies on undocumented and unsupported Matlab -% functionality. It works on Matlab 7+, but use at your own risk! -% -% A technical description of the implementation can be found at: -% http://undocumentedmatlab.com/blog/propertiesGUI/ -% http://undocumentedmatlab.com/blog/jide-property-grids/ -% http://undocumentedmatlab.com/blog/advanced-jide-property-grids/ -% -% Change log: -% 2013-04-23: Fixed case of empty ([]) data, handled class objects & numeric/cell arrays, fixed error reported by Andrew Ness -% 2013-01-26: Updated help section -% 2012-11-07: Minor fix for file/folder properties -% 2012-11-07: Accept any object having properties/fields as input parameter; support multi-level properties -% 2012-10-31: First version posted on MathWorks File Exchange -% -% See also: -% inspect, uiinspect (#17935 on the MathWorks File Exchange) - -% License to use and modify this code is granted freely to all interested, as long as the original author is -% referenced and attributed as such. The original author maintains the right to be solely associated with this work. - -% Programmed and Copyright by Yair M. Altman: altmany(at)gmail.com -% $Revision: 1.07 $ $Date: 2013/04/23 00:15:42 $ - - % Get the initial data - global test_data - if nargin < 2 - try - isObj = nargin==1; - [hasProps,isHG] = hasProperties(hParent); - isObj = isObj && hasProps && ~isHG; - catch - % ignore - maybe nargin==0, so no hParent is available - end - if isObj - parameters = hParent; - hParent = []; - else - parameters = test_data; % comment this if you do not want persistent parameters - if isempty(parameters) - % demo mode - parameters = demoParameters; - end - end - end - - % Accept any object having data fields/properties - try - parameters = get(parameters); - catch - oldWarn = warning('off','MATLAB:structOnObject'); - parameters = struct(parameters); - warning(oldWarn); - end - - % Init JIDE - com.mathworks.mwswing.MJUtilities.initJIDE; - - % Prepare the list of properties - oldWarn = warning('off','MATLAB:hg:JavaSetHGProperty'); - warning off MATLAB:hg:PossibleDeprecatedJavaSetHGProperty - isEditable = true; %=nargin < 1; - propsList = preparePropsList(parameters, isEditable); - - % Create a mapping propName => prop - propsHash = java.util.Hashtable; - propsArray = propsList.toArray(); - for propsIdx = 1 : length(propsArray) - thisProp = propsArray(propsIdx); - propName = get(thisProp, 'UserData'); - propsHash.put(propName, thisProp); - end - warning(oldWarn); - - % Prepare a properties table that contains the list of properties - model = javaObjectEDT(com.jidesoft.grid.PropertyTableModel(propsList)); - model.expandAll(); - - % Prepare the properties table (grid) - grid = javaObjectEDT(com.jidesoft.grid.PropertyTable(model)); - grid.setShowNonEditable(grid.SHOW_NONEDITABLE_BOTH_NAME_VALUE); - %set(handle(grid.getSelectionModel,'CallbackProperties'), 'ValueChangedCallback', @propSelectedCallback); - com.jidesoft.grid.TableUtils.autoResizeAllColumns(grid); - %com.jidesoft.grid.TableUtils.autoResizeAllRows(grid); - grid.setRowHeight(19); % default=16; autoResizeAllRows=20 - we need something in between - - % Auto-end editing upon focus loss - grid.putClientProperty('terminateEditOnFocusLost',true); - - % If no parent (or the root) was specified - if nargin < 1 || isempty(hParent) || isequal(hParent,0) - % Create a new figure window - delete(findall(0, '-depth',1, 'Tag','fpropertiesGUI')); - hFig = figure('Number','off', 'Name','Application properties', 'Units','pixel', 'Pos',[300,200,500,500], 'Menu','none', 'Toolbar','none', 'Tag','fpropertiesGUI', 'Visible','off'); - hParent = hFig; - setappdata(0,'isParamsGUIApproved',false) - - % Add the bottom action buttons - btOK = uicontrol('String','OK', 'Units','pixel', 'Pos',[ 50,5,60,30], 'Tag','btOK', 'Callback',@btOK_Callback); - btCancel = uicontrol('String','Cancel', 'Units','pixel', 'Pos',[150,5,60,30], 'Tag','btCancel', 'Callback',@(h,e)close(hFig)); %#ok - - % Check the property values to determine whether the button should be enabled or not - checkProps(propsList, btOK, true); - - % Set the figure icon & make visible - jFrame = get(handle(hFig),'JavaFrame'); - icon = javax.swing.ImageIcon(fullfile(matlabroot, '/toolbox/matlab/icons/tool_legend.gif')); - jFrame.setFigureIcon(icon); - set(hFig, 'WindowStyle','modal', 'Visible','on'); - - % Set the component's position - %pos = [5,40,490,440]; - hFigPos = getpixelposition(hFig); - pos = [5,40,hFigPos(3)-10,hFigPos(4)-50]; - else - % Set the component's position - drawnow; - pos = getpixelposition(hParent); - pos(1:2) = 5; - pos = pos - [0,0,10,10]; - hFig = []; - end - - %drawnow; pause(0.05); - pane = javaObjectEDT(com.jidesoft.grid.PropertyPane(grid)); - customizePropertyPane(pane); - [jPropsPane, hPropsPane_] = javacomponent(pane, pos, hParent); - setappdata(hParent, 'jPropsPane',jPropsPane); - setappdata(hParent, 'propsList',propsList); - setappdata(hParent, 'propsHash',propsHash); - setappdata(hParent, 'mirror',parameters); - set(hPropsPane_,'tag','hpropertiesGUI'); - - set(hPropsPane_, 'Units','norm'); - - % Align the background colors - bgcolor = pane.getBackground.getComponents([]); - try set(hParent, 'Color', bgcolor(1:3)); catch, end % this fails in uitabs - never mind (works ok in stand-alone figures) - try pane.setBorderColor(pane.getBackground); catch, end % error reported by Andrew Ness - - % If a new figure was created, make it modal and wait for user to close it - if ~isempty(hFig) - uiwait(hFig); - if getappdata(0,'isParamsGUIApproved') - parameters = test_data; %=getappdata(hFig, 'mirror'); - end - end - - if nargout, hPropsPane = hPropsPane_; end % prevent unintentional printouts to the command window -end % propertiesGUI - -%% Determine whether a specified object should be considered as having fields/properties -% Note: HG handles must be processed seperately for the main logic to work -function [hasProps,isHG] = hasProperties(object) - % A bunch of tests, some of which may croak depending on the Matlab release, platform - try isHG = ishghandle(object); catch, isHG = ishandle(object); end - try isst = isstruct(object); catch, isst = false; end - try isjav = isjava(object); catch, isjav = false; end - try isobj = isobject(object); catch, isobj = false; end - try isco = iscom(object); catch, isco = false; end - hasProps = ~isempty(object) && (isst || isjav || isobj || isco); -end - -%% Customize the property-pane's appearance -function customizePropertyPane(pane) - pane.setShowDescription(false); % YMA: we don't currently have textual descriptions of the parameters, so no use showing an empty box that just takes up GUI space... - pane.setShowToolBar(false); - pane.setOrder(2); % uncategorized, unsorted - see http://undocumentedmatlab.com/blog/advanced-jide-property-grids/#comment-42057 -end - -%% Prepare a list of some parameters for demo mode -function parameters = demoParameters - parameters.floating_point_property = pi; - parameters.signed_integer_property = int16(12); - parameters.unsigned_integer_property = uint16(12); - parameters.flag_property = true; - parameters.file_property = mfilename('fullpath'); - parameters.folder_property = pwd; - parameters.text_property = 'Sample text'; - parameters.fixed_choice_property = {'Yes','No','Maybe'}; - parameters.editable_choice_property = {'Yes','No','Maybe',''}; % editable if the last cell element is '' - parameters.date_property = java.util.Date; % today's date - parameters.another_date_property = now-365; % last year - parameters.time_property = datestr(now,'HH:MM:SS'); - parameters.password_property = '*****'; - parameters.IP_address_property = '10.20.30.40'; - parameters.my_category.width = 4; - parameters.my_category.height = 3; - parameters.my_category.and_a_subcategory.is_OK = true; - parameters.numeric_array_property = [11,12,13,14]; - parameters.cell_array_property = {1,magic(3),'text',-4}; - parameters.color_property = [0.4,0.5,0.6]; - parameters.another_color_property = java.awt.Color.red; - try parameters.class_object_property = matlab.desktop.editor.getActive; catch, end -end % demoParameters - -%% Prepare a list of properties -function propsList = preparePropsList(parameters, isEditable) - propsList = java.util.ArrayList(); - - % Convert a class object into a struct - if isobject(parameters) - parameters = struct(parameters); - end - - % Prepare a dynamic list of properties, based on the struct fields - if isstruct(parameters) && ~isempty(parameters) - % Dynamically (generically) inspect all the fields and assign corresponding props - field_names = fieldnames(parameters); - for field_idx = 1 : length(field_names) - field_name = field_names{field_idx}; - value = parameters.(field_name); - field_label = strrep(field_name,'_',' '); - field_label(1) = upper(field_label(1)); - field_description = ''; % TODO - type = 'string'; - if isempty(value) - type = 'string'; % not really needed, but for consistency - elseif isa(value,'java.awt.Color') - type = 'color'; - elseif isnumeric(value) - try %if length(value)==3 - colorComponents = num2cell(value); - if numel(colorComponents) ~= 3 - error(' '); % bail out if definitely not a color - end - try - value = java.awt.Color(colorComponents{:}); % value between 0-1 - catch - colorComponents = num2cell(value/255); - value = java.awt.Color(colorComponents{:}); % value between 0-255 - end - type = 'color'; - catch %else - if numel(value)==1 - %value = value(1); - if value > now-3650 && value < now+3650 - type = 'date'; - value = java.util.Date(datestr(value)); - elseif isa(value,'uint') || isa(value,'uint8') || isa(value,'uint16') || isa(value,'uint32') || isa(value,'uint64') - type = 'unsigned'; - elseif isinteger(value) - type = 'signed'; - else - type = 'float'; - end - else - value = strtrim(regexprep(num2str(value),' +',' ')); - if length(value) > 50 - value(51:end) = ''; - value = [value '...']; - end - value = ['[ ' value ' ]']; - end - end - elseif islogical(value) - type = 'boolean'; - elseif ischar(value) - if exist(value,'dir') - type = 'folder'; - value = java.io.File(value); - elseif exist(value,'file') - type = 'file'; - value = java.io.File(value); - elseif value(1)=='*' - type = 'password'; - elseif sum(value=='.')==3 - type = 'IPAddress'; - else - type = 'string'; - if length(value) > 50 - value(51:end) = ''; - value = [value '...']; - end - end - elseif iscellstr(value) - type = value; % editable if the last cell element is '' - elseif isa(value,'java.util.Date') - type = 'date'; - elseif isa(value,'java.io.File') - if value.isFile - type = 'file'; - else % value.isDirectory - type = 'folder'; - end - elseif iscell(value) - value = strtrim(regexprep(evalc('disp(value)'),' +',' ')); - value = ['{ ' value ' }']; - elseif isobject(value) - oldWarn = warning('off','MATLAB:structOnObject'); - value = struct(value); - warning(oldWarn); - elseif ~isstruct(value) - value = strtrim(regexprep(evalc('disp(value)'),' +',' ')); - end - parameters.(field_name) = value; % possibly updated above - newProp = newProperty(parameters, field_name, field_label, isEditable, type, field_description, @propUpdatedCallback); - propsList.add(newProp); - end - else - % You can also use direct assignments, instead of the generic code above. For example: - % (Possible property types: signed, unsigned, float, file, folder, text or string, color, IPAddress, password, date, boolean, cell-array of strings) - propsList.add(newProperty(parameters, 'flag_prop_name', 'Flag value:', isEditable, 'boolean', 'Turn this on if you want to make extra plots', @propUpdatedCallback)); - propsList.add(newProperty(parameters, 'float_prop_name', 'Boolean prop', isEditable, 'float', 'description 123...', @propUpdatedCallback)); - propsList.add(newProperty(parameters, 'string_prop_name', 'My text msg:', isEditable, 'string', 'Yaba daba doo', @propUpdatedCallback)); - propsList.add(newProperty(parameters, 'int_prop_name', 'Now an integer', isEditable, 'unsigned', '123 456...', @propUpdatedCallback)); - propsList.add(newProperty(parameters, 'choice_prop_name', 'And a drop-down', isEditable, {'Yes','No','Maybe'}, 'no description here!', @propUpdatedCallback)); - end -end % preparePropsList - -%% Prepare a data property -function prop = newProperty(dataStruct, propName, label, isEditable, dataType, description, propUpdatedCallback) - - % Auto-generate the label from the property name, if the label was not specified - if isempty(label) - label = strrep(propName,'_',' '); - label(1) = upper(label(1)); - end - - % Create a new property with the chosen label - prop = javaObjectEDT(com.jidesoft.grid.DefaultProperty); % UNDOCUMENTED internal MATLAB component - prop.setName(label); - - % Set the property to the current patient's data value - thisProp = dataStruct.(propName); - if isstruct(thisProp) %hasProperties(thisProp) - - % Accept any object having data fields/properties - try - thisProp = get(thisProp); - catch - oldWarn = warning('off','MATLAB:structOnObject'); - thisProp = struct(thisProp); - warning(oldWarn); - end - - % Parse the children props and add them to this property - summary = regexprep(evalc('disp(thisProp)'),' +',' '); - prop.setValue(summary); % TODO: display summary dynamically - prop.setValue(''); - prop.setEditable(false); - children = toArray(preparePropsList(thisProp, isEditable)); - for childIdx = 1 : length(children) - prop.addChild(children(childIdx)); - end - else - prop.setValue(thisProp); - prop.setEditable(isEditable); - end - set(prop,'UserData',propName); - - % Set property editor, renderer and alignment - if iscell(dataType) - % treat this as drop-down values - cbIsEditable = true; - if isempty(dataType{end}) % ends with '' - editable - dataType(end) = []; % remove from the drop-down list - else % standard drop-down, non-editable - cbIsEditable = false; - end - editor = com.jidesoft.grid.ListComboBoxCellEditor(dataType); - try editor.getComboBox.setEditable(cbIsEditable); catch, end %#ok - %set(editor,'EditingStoppedCallback',{@propUpdatedCallback,tagName,propName}); - alignProp(prop, editor); - try prop.setValue(dataStruct.(propName){1}); catch, end - else - switch lower(dataType) - case 'signed', %alignProp(prop, com.jidesoft.grid.IntegerCellEditor, 'int32'); - model = javax.swing.SpinnerNumberModel(prop.getValue, -intmax, intmax, 1); - editor = com.jidesoft.grid.SpinnerCellEditor(model); - alignProp(prop, editor, 'int32'); - case 'unsigned', %alignProp(prop, com.jidesoft.grid.IntegerCellEditor, 'uint32'); - model = javax.swing.SpinnerNumberModel(prop.getValue, 0, intmax, 1); - editor = com.jidesoft.grid.SpinnerCellEditor(model); - alignProp(prop, editor, 'uint32'); - case 'float', alignProp(prop, com.jidesoft.grid.CalculatorCellEditor, 'double'); % DoubleCellEditor - case 'boolean', alignProp(prop, com.jidesoft.grid.BooleanCheckBoxCellEditor, 'logical'); - case 'folder', alignProp(prop, com.jidesoft.grid.FolderCellEditor); - case 'file', alignProp(prop, com.jidesoft.grid.FileCellEditor); - case 'ipaddress', alignProp(prop, com.jidesoft.grid.IPAddressCellEditor); - case 'password', alignProp(prop, com.jidesoft.grid.PasswordCellEditor); - case 'color', alignProp(prop, com.jidesoft.grid.ColorCellEditor); - case 'text', alignProp(prop); - case 'time', alignProp(prop); % maybe use com.jidesoft.grid.FormattedTextFieldCellEditor ? - - case 'date', dateModel = com.jidesoft.combobox.DefaultDateModel; - dateFormat = java.text.SimpleDateFormat('dd/MM/yyyy'); - dateModel.setDateFormat(dateFormat); - editor = com.jidesoft.grid.DateCellEditor(dateModel, 1); - alignProp(prop, editor, 'java.util.Date'); - try - prop.setValue(dateFormat.parse(prop.getValue)); % convert string => Date - catch - % ignore - end - - otherwise, alignProp(prop); % treat as a simple text field - end - end % for all possible data types - - prop.setDescription(description); - if ~isempty(description) - renderer = com.jidesoft.grid.CellRendererManager.getRenderer(prop.getType, prop.getEditorContext); - renderer.setToolTipText(description); - end - - % Set the property's editability state - if prop.isEditable - % Set the property's label to be black - prop.setDisplayName(['' label]); - - % Add callbacks for property-change events - hprop = handle(prop, 'CallbackProperties'); - set(hprop,'PropertyChangeCallback',{propUpdatedCallback,propName}); - else - % Set the property's label to be gray - prop.setDisplayName(['' label]); - end -end % newProperty - -%% Align a text property to right/left -function alignProp(prop, editor, propTypeStr, direction) - if nargin < 2, editor = com.jidesoft.grid.StringCellEditor; end %(javaclass('char',1)); - if nargin < 3, propTypeStr = 'cellstr'; end % => javaclass('char',1) - if nargin < 4, direction = javax.swing.SwingConstants.RIGHT; end - - % Set this property's data type - propType = javaclass(propTypeStr); - prop.setType(propType); - - % Prepare a specific context object for this property - if strcmpi(propTypeStr,'logical') - %TODO - FIXME - context = editor.CONTEXT; - prop.setEditorContext(context); - %renderer = CheckBoxRenderer; - %renderer.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); - %com.jidesoft.grid.CellRendererManager.registerRenderer(propType, renderer, context); - else - context = com.jidesoft.grid.EditorContext(prop.getName); - prop.setEditorContext(context); - - % Register a unique cell renderer so that each property can be modified seperately - %renderer = com.jidesoft.grid.CellRendererManager.getRenderer(propType, prop.getEditorContext); - renderer = com.jidesoft.grid.ContextSensitiveCellRenderer; - com.jidesoft.grid.CellRendererManager.registerRenderer(propType, renderer, context); - renderer.setBackground(java.awt.Color.white); - renderer.setHorizontalAlignment(direction); - %renderer.setHorizontalTextPosition(direction); - end - - % Update the property's cell editor - try editor.setHorizontalAlignment(direction); catch, end - try - editor.getTextField.setHorizontalAlignment(direction); - catch - try - editor.getComboBox.setHorizontalAlignment(direction); - catch - % ignore - end - end - - % Set limits on unsigned int values - try - if strcmpi(propTypeStr,'uint32') - %pause(0.01); - editor.setMinInclusive(java.lang.Integer(0)); - editor.setMinExclusive(java.lang.Integer(-1)); - editor.setMaxExclusive(java.lang.Integer(intmax)); - editor.setMaxInclusive(java.lang.Integer(intmax)); - end - catch - % ignore - end - com.jidesoft.grid.CellEditorManager.registerEditor(propType, editor, context); -end % alignProp - -%% Property updated callback function -function propUpdatedCallback(prop, eventData, propName) - try if strcmpi(char(eventData.getPropertyName),'parent'), return; end; catch, end - hFig = findall(0, '-depth',1, 'Tag','fpropertiesGUI'); - if isempty(hFig) - hPropsPane = findall(0,'Tag','hpropertiesGUI'); - if isempty(hPropsPane), return; end - hFig = get(hPropsPane,'Parent'); - end - if isempty(hFig), return; end - propsList = getappdata(hFig, 'propsList'); - propsPane = getappdata(hFig, 'jPropsPane'); - data = getappdata(hFig, 'mirror'); - - % Get the updated property value - propValue = get(prop,'Value'); %#ok (used in eval() below) - if isjava(propValue) - if isa(propValue,'java.util.Date') - sdf = java.text.SimpleDateFormat('MM-dd-yyyy'); - propValue = datenum(sdf.format(propValue).char); %#ok - elseif isa(propValue,'java.awt.Color') - propValue = propValue.getColorComponents([])'; %#ok - else - propValue = char(propValue); %#ok - end - end - - % Get the actual recursive propName - try - oldWarn = warning('off','MATLAB:hg:JavaSetHGProperty'); - try prop = java(prop); catch, end - while isa(prop,'com.jidesoft.grid.Property') - prop = get(prop,'Parent'); - newName = get(prop,'UserData'); - if isempty(newName), break; end - propName = [newName '.' propName]; %#ok - end - catch - % Reached the top of the property's heirarchy - bail out - warning(oldWarn); - end - - % Update the mirror with the updated field value - %data.(propName) = propValue; % croaks on multiple sub-fields - eval(['data.' propName ' = propValue;']); - - % Update the local mirror - setappdata(hFig, 'mirror',data); - - % Update the display - checkProps(propsList, hFig); - try propsPane.repaint; catch; end -end % propUpdatedCallback - -%% button callback function -function btOK_Callback(btOK, eventData) %#ok - global test_data - - % Store the current data-info struct mirror in the global struct - hFig = ancestor(btOK, 'figure'); - test_data = getappdata(hFig, 'mirror'); - setappdata(0,'isParamsGUIApproved',true); - - % Close the window - try - close(hFig); - catch - delete(hFig); % force-close - end -end % btOK_Callback - -%% Check whether all mandatory fields have been filled, update background color accordingly -function checkProps(propsList, hContainer, isInit) - if nargin < 3, isInit = false; end - okEnabled = 'on'; - try propsArray = propsList.toArray(); catch, return; end - for propsIdx = 1 : length(propsArray) - isOk = checkProp(propsArray(propsIdx)); - if ~isOk || isInit, okEnabled = 'off'; end - end - - % Update the button's editability state accordingly - btOK = findall(hContainer, 'Tag','btOK'); - set(btOK, 'Enable',okEnabled); - drawnow; pause(0.01); -end % checkProps - -function isOk = checkProp(prop) - isOk = true; - oldWarn = warning('off','MATLAB:hg:JavaSetHGProperty'); - warning off MATLAB:hg:PossibleDeprecatedJavaSetHGProperty - propName = get(prop, 'UserData'); - renderer = com.jidesoft.grid.CellRendererManager.getRenderer(get(prop,'Type'), get(prop,'EditorContext')); - warning(oldWarn); - mandatoryFields = {}; % TODO - add the mandatory field-names here - if any(strcmpi(propName, mandatoryFields)) && isempty(get(prop,'Value')) - propColor = java.awt.Color.yellow; - isOk = false; - elseif ~prop.isEditable - %propColor = java.awt.Color.gray; - propColor = renderer.getBackground(); - else - propColor = java.awt.Color.white; - end - renderer.setBackground(propColor); -end % checkProp - -%% Return java.lang.Class instance corresponding to the Matlab type -function jclass = javaclass(mtype, ndims) - % Input arguments: - % mtype: - % the MatLab name of the type for which to return the java.lang.Class - % instance - % ndims: - % the number of dimensions of the MatLab data type - % - % See also: class - - % Copyright 2009-2010 Levente Hunyadi - % Downloaded from: http://www.UndocumentedMatlab.com/files/javaclass.m - - validateattributes(mtype, {'char'}, {'nonempty','row'}); - if nargin < 2 - ndims = 0; - else - validateattributes(ndims, {'numeric'}, {'nonnegative','integer','scalar'}); - end - - if ndims == 1 && strcmp(mtype, 'char'); % a character vector converts into a string - jclassname = 'java.lang.String'; - elseif ndims > 0 - jclassname = javaarrayclass(mtype, ndims); - else - % The static property .class applied to a Java type returns a string in - % MatLab rather than an instance of java.lang.Class. For this reason, - % use a string and java.lang.Class.forName to instantiate a - % java.lang.Class object; the syntax java.lang.Boolean.class will not do so - switch mtype - case 'logical' % logical vaule (true or false) - jclassname = 'java.lang.Boolean'; - case 'char' % a singe character - jclassname = 'java.lang.Character'; - case {'int8','uint8'} % 8-bit signed and unsigned integer - jclassname = 'java.lang.Byte'; - case {'int16','uint16'} % 16-bit signed and unsigned integer - jclassname = 'java.lang.Short'; - case {'int32','uint32'} % 32-bit signed and unsigned integer - jclassname = 'java.lang.Integer'; - case {'int64','uint64'} % 64-bit signed and unsigned integer - jclassname = 'java.lang.Long'; - case 'single' % single-precision floating-point number - jclassname = 'java.lang.Float'; - case 'double' % double-precision floating-point number - jclassname = 'java.lang.Double'; - case 'cellstr' % a single cell or a character array - jclassname = 'java.lang.String'; - otherwise - jclassname = mtype; - %error('java:javaclass:InvalidArgumentValue', ... - % 'MatLab type "%s" is not recognized or supported in Java.', mtype); - end - end - % Note: When querying a java.lang.Class object by name with the method - % jclass = java.lang.Class.forName(jclassname); - % MatLab generates an error. For the Class.forName method to work, MatLab - % requires class loader to be specified explicitly. - jclass = java.lang.Class.forName(jclassname, true, java.lang.Thread.currentThread().getContextClassLoader()); -end % javaclass - -%% Return the type qualifier for a multidimensional Java array -function jclassname = javaarrayclass(mtype, ndims) - switch mtype - case 'logical' % logical array of true and false values - jclassid = 'Z'; - case 'char' % character array - jclassid = 'C'; - case {'int8','uint8'} % 8-bit signed and unsigned integer array - jclassid = 'B'; - case {'int16','uint16'} % 16-bit signed and unsigned integer array - jclassid = 'S'; - case {'int32','uint32'} % 32-bit signed and unsigned integer array - jclassid = 'I'; - case {'int64','uint64'} % 64-bit signed and unsigned integer array - jclassid = 'J'; - case 'single' % single-precision floating-point number array - jclassid = 'F'; - case 'double' % double-precision floating-point number array - jclassid = 'D'; - case 'cellstr' % cell array of strings - jclassid = 'Ljava.lang.String;'; - otherwise - jclassid = ['L' mtype ';']; - %error('java:javaclass:InvalidArgumentValue', ... - % 'MatLab type "%s" is not recognized or supported in Java.', mtype); - end - jclassname = [repmat('[',1,ndims), jclassid]; -end % javaarrayclass diff --git a/general functions/rootFolder.m b/general functions/rootFolder.m deleted file mode 100644 index f1694ee..0000000 --- a/general functions/rootFolder.m +++ /dev/null @@ -1,2 +0,0 @@ -function [folderName]=rootFolder() -folderName='C:\Users\Tulip\Documents\Academic\Post-Doc\'; \ No newline at end of file diff --git a/general functions/sendMailViaGmail.m b/general functions/sendMailViaGmail.m deleted file mode 100644 index 7d860e3..0000000 --- a/general functions/sendMailViaGmail.m +++ /dev/null @@ -1,62 +0,0 @@ -function sendMailViaGmail(recipientMail,subject,message) - -% Modify these two lines to reflect your account and password. -NSKToolBoxMainDir=fileparts(which('identifierOfMainDir4NSKToolBox')); -if exist([NSKToolBoxMainDir filesep 'PCspecificFiles' filesep 'emailsCredentials.txt'],'file') - emailCredentialsFile = fileread([NSKToolBoxMainDir filesep 'PCspecificFiles' filesep 'emailsCredentials.txt']); - emailCredentials = regexp(emailCredentialsFile, '\r\n|\r|\n', 'split'); - myaddress = emailCredentials{1}; - mypassword = emailCredentials{2}; -else - message.server.mark@gmail.com -end - - -setpref('Internet','E_mail',myaddress); -setpref('Internet','SMTP_Server','smtp.gmail.com'); -setpref('Internet','SMTP_Username',myaddress); -setpref('Internet','SMTP_Password',mypassword); - -props = java.lang.System.getProperties; -props.setProperty('mail.smtp.auth','true'); -props.setProperty('mail.smtp.socketFactory.class', ... - 'javax.net.ssl.SSLSocketFactory'); -props.setProperty('mail.smtp.socketFactory.port','465'); - -%{ -NET.addAssembly('System.Net') -import System.Net.Mail.*; - -mySmtpClient = SmtpClient('smtp.gmail.com'); - -mySmtpClient.UseDefaultCredentials = false; -mySmtpClient.Credentials = System.Net.NetworkCredential(myaddress, mypassword); - -from = MailAddress('from.name@address.com'); -to = MailAddress('to.form@address.com'); - -myMail = MailMessage(from, to); - -myMail.Subject = ['Test message: ' datestr(now)]; -myMail.SubjectEncoding = System.Text.Encoding.UTF8; -myMail.Body = 'Test Mail
using HTML'; -myMail.BodyEncoding = System.Text.Encoding.UTF8; -myMail.IsBodyHtml = true; -mySmtpClient.Send(myMail); -%} - -if nargin==3 - try - sendmail(recipientMail,subject,message); - catch errorMsg - disp(['Email was not successfully sent: ' errorMsg.message]); - end -elseif nargin==2 - try - sendmail(recipientMail,subject) - catch errorMsg - disp(['Email was not successfully sent: ' errorMsg.message]); - end -else - error('Either 2 or 3 arguments are required for running sendMailViaGmail function'); -end \ No newline at end of file diff --git a/general functions/sendMailViaGmail.m.orig b/general functions/sendMailViaGmail.m.orig deleted file mode 100644 index 42344ac..0000000 --- a/general functions/sendMailViaGmail.m.orig +++ /dev/null @@ -1,64 +0,0 @@ -function sendMailViaGmail(recipientMail,subject,message) - -% Modify these two lines to reflect -% your account and password. -<<<<<<< HEAD -myaddress = 'message.server.mark@gmail.com'; -mypassword = 'marksheinidelson'; -======= -NSKToolBoxMainDir=fileparts(which('identifierOfMainDir4NSKToolBox')); -emailCredentialsFile = fileread([NSKToolBoxMainDir filesep 'PCspecificFiles' filesep 'VSEmailsCredentials.txt']); -emailCredentials = regexp(emailCredentialsFile, '\r\n|\r|\n', 'split'); - -myaddress = emailCredentials{1}; -mypassword = emailCredentials{2}; ->>>>>>> upstream/master - -setpref('Internet','E_mail',myaddress); -setpref('Internet','SMTP_Server','smtp.gmail.com'); -setpref('Internet','SMTP_Username',myaddress); -setpref('Internet','SMTP_Password',mypassword); - -props = java.lang.System.getProperties; -props.setProperty('mail.smtp.auth','true'); -props.setProperty('mail.smtp.socketFactory.class', ... - 'javax.net.ssl.SSLSocketFactory'); -props.setProperty('mail.smtp.socketFactory.port','465'); - -%{ -NET.addAssembly('System.Net') -import System.Net.Mail.*; - -mySmtpClient = SmtpClient('smtp.gmail.com'); - -mySmtpClient.UseDefaultCredentials = false; -mySmtpClient.Credentials = System.Net.NetworkCredential(myaddress, mypassword); - -from = MailAddress('from.name@address.com'); -to = MailAddress('to.form@address.com'); - -myMail = MailMessage(from, to); - -myMail.Subject = ['Test message: ' datestr(now)]; -myMail.SubjectEncoding = System.Text.Encoding.UTF8; -myMail.Body = 'Test Mail
using HTML'; -myMail.BodyEncoding = System.Text.Encoding.UTF8; -myMail.IsBodyHtml = true; -mySmtpClient.Send(myMail); -%} - -if nargin==3 - try - sendmail(recipientMail,subject,message); - catch errorMsg - disp(['Email was not successfully sent: ' errorMsg.message]); - end -elseif nargin==2 - try - sendmail(recipientMail,subject) - catch errorMsg - disp(['Email was not successfully sent: ' errorMsg.message]); - end -else - error('Either 2 or 3 arguments are required for running sendMailViaGmail function'); -end \ No newline at end of file diff --git a/general functions/uiinspect.m b/general functions/uiinspect.m deleted file mode 100644 index 1803cdc..0000000 --- a/general functions/uiinspect.m +++ /dev/null @@ -1,3002 +0,0 @@ -function hFig = uiinspect(obj, fig) -% uiinspect Inspect an object handle (Java/COM/HG) and display its methods/props/callbacks in a unified window -% -% Syntax: -% hFig = uiinspect(obj, hFig) % hFig input argument is optional -% -% Description: -% UIINSPECT(OBJ) inspects an object handle (e.g., Java, COM, Handle -% Graphics, Matlab class, Dot-Net etc.) and displays inspection results -% in a Matlab figure window with all the relevant object methods (as can -% be displayed via Matlab's methodsview function), properties (as can be -% displayed via Matlab's inspect function), static fields and callbacks. -% UIINSPECT also displays properties that are not normally displayed -% with Matlab's inspect function. Property meta-data such as type, -% accessibility, visibility and default value are also displayed (where -% available). -% -% If the inspected object is an HG handle, then a component tree is -% displayed instead of the methods pane (see attached animated screenshot). -% -% Unlike Matlab's inspect function, multiple UIINSPECT windows can be -% opened simultaneously. -% -% Object properties and callbacks may be modified interactively within -% the UIINSPECT window. -% -% UIINSPECT(OBJ) reuses an already-displayed UIINSPECT window if its -% title is the same (i.e., same object or class); otherwise a new window -% is created. UIINPECT(OBJ,hFIG) forces using the specified hFig window -% handle, even if another window would otherwise have been reused/created. -% -% hFig = UIINSPECT(...) returns a handle to the UIINSPECT figure window. -% UIINSPECT creates a regular Matlab figure window which may be accessed -% via this hFig handle (unlike Matlab's methodsview function which opens -% a Java frame that is not easily accessible from Matlab). -% -% Examples: -% hFig = uiinspect(0); % root (desktop) -% hFig = uiinspect(handle(0)); % root handle -% hFig = uiinspect(gcf); % current figure -% uiinspect(get(gcf,'JavaFrame')); % current figure's Java Frame -% uiinspect(classhandle(handle(gcf))); % a schema.class object -% uiinspect(findprop(handle(gcf),'MenuBar')); % a schema.prop object -% uiinspect('java.lang.String'); % a Java class name -% uiinspect(java.lang.String('yes')); % a Java object -% uiinspect(actxserver('Excel.Application')); % a COM object -% uiinspect(Employee) % a Matlab class object -% uiinspect(?handle) % a Matlab metaclass object -% uiinspect('meta.class') % a Matlab class name -% uiinspect(System.Diagnostics.Process.GetCurrentProcess) % a .Net object -% -% Technical explanation & details: -% http://undocumentedmatlab.com/blog/uiinspect/ -% -% Known issues/limitations: -% - Fix: some fields generate a Java Exception, or a Matlab warning -% - other future enhancements may be found in the TODO list below -% -% Warning: -% This code heavily relies on undocumented and unsupported Matlab functionality. -% It works on Matlab 7+, but use at your own risk! -% -% Bugs and suggestions: -% Please send to Yair Altman (altmany at gmail dot com) -% -% Change log: -% 2015-03-02: Fix for R2014a and older Matlab releases -% 2014-11-21: Additional fixes for R2014b (HG2) -% 2014-10-24: Fixed properties panel for .Net objects -% 2014-10-24: Fixed a reported "invalid object handle" bug -% 2014-10-20: Fixes for multiple edge cases -% 2014-10-13: Fixes for R2014a, R2014b -% 2013-06-30: Fixes for the upcoming HG2 -% 2013-01-25: Added context-menu option to export handle to workspace -% 2013-01-23: Prevented intermittent crash reported for uiinspect(0); auto-expanded callbacks table if only one category; added hidden properties to the properties tooltip; updated FEX link in help; updated javadoc hyperlinks; fixed callbacks table -% 2012-01-16: Fixes for R2012a -% 2011-12-09: Fixed Matlab R2011b crash when inspecting COM object -% 2011-06-14: Fixed problems with the Value field of the "Other properties" table for static fields -% 2011-03-22: Fixed display of non-static Java class fields; fixed display of some cases of Java class names; minor fixes for Matlab class properties -% 2011-03-03: Fixed several issues in the Value field of the "Other properties" table -% 2011-02-28: Removed R2010b warning messages; minor fix for Dot-Net classes -% 2010-11-02: Minor fixes for callbacks table; fixed online docpage for Swing classes -% 2010-11-01: Major fix for pre-R2010 compatibility -% 2010-10-20: Minor fix suggested by Andrew Stamps; added automatic callbacks grouping -% 2010-06-13: Fixed download (m-file => zip-file) -% 2010-06-11: Displayed class modifiers; improved performance; removed empty panels by default; fixed warning msgs when sorting props table; fixes for R2010b -% 2010-03-18: Minor fix in copy-handle-value-to-clipboard (in tree context-menu) -% 2010-03-17: Fixes for R2010a -% 2010-01-16: Fixed a few bugs in properties meta-info of Matlab classes -% 2009-10-23: Added CaretPositionChanged & InputMethodTextChanged to list of standard callbacks; minor fix to requesting focus of Java handles; minor fix to version-check display -% 2009-05-22: Added support for Matlab classes (helped by Darik Gamble); improved display for classname input -% 2009-05-20: Fixed methods info gathering for some handles -% 2009-05-19: Improved information display for HG handles; added HG-handle screenshot to animated gif (added to COM, Java screenshots); enabled reuse of uiinspect window -% 2009-05-04: Fixed setting callbacks on non-handle('CallbackProperties')ed Java objects; fixed input param edge-case; hyperlinked the className to Sun's Javadocs where relevant; auto-checked newer version; removed main menu -% 2009-04-16: Fixed occasional endless loop upon callback update error -% 2009-04-01: Fixed case of no methods (e.g., uimenus); fixed superclass/interfaces of classname input; auto-hide callbacks pane if no CBs are available -% 2009-03-30: Added Extra method details checkbox (default=off); auto-hide inspectable checkbox if irrelevant; auto-sort methods by args list; hyperlinked classes; fixed title for classname inputs -% 2009-03-14: Fixed string property value displayed; fixed display of Java classes added to the dynamic classpath; fixed display of classname static fields value; updated list of standard callbacks -% 2009-03-05: Fixed single property edge-case; fixed prop name case sensitivity problem; fixed properties tooltip; accept class names; added display of class interfaces & static fields -% 2008-01-25: Fixes for many edge-cases -% 2007-12-08: First version posted on MathWorks File Exchange -% -% See also: -% ishandle, iscom, inspect, methodsview, FindJObj (on the File Exchange) - -% License to use and modify this code is granted freely to all interested, as long as the original author is -% referenced and attributed as such. The original author maintains the right to be solely associated with this work. - -% Programmed by Yair M. Altman: altmany(at)gmail.com -% $Revision: 1.32 $ $Date: 2015/03/02 10:12:52 $ - - try - % Arg check - error(nargchk(1,2,nargin)); - try - mc = getMetaClass(obj); - catch - mc = []; - end - if ~ischar(obj) && (isempty(obj) || (~ishandle(obj) && isempty(mc))) - myError('YMA:uiinspect:notAHandle','Input to uiinspect must be a valid object as defined by ISHANDLE'); - elseif ~ischar(obj) && (numel(obj) ~= 1) - myError('YMA:uiinspect:notASingleton','Input to uiinspect must be a single object handle'); - elseif isnumeric(obj) && ishandle(obj) - obj = handle(obj); - end - if nargin < 2 - fig = []; - elseif ~ishandle(fig) || ~ishghandle(fig) || (~isa(handle(fig),'figure') && ~isa(handle(fig),'matlab.ui.Figure')) - myError('YMA:uiinspect:notAFigure','Second input to uiinspect must be a valid figure handle'); - end - - % Get object data - objMethods = getObjMethods(obj); - objProps = getObjProps(obj); - objCallbacks = getObjCallbacks(obj); - objChildren = getObjChildren(obj); - - % Display object data - fig = displayObj(obj, objMethods, objProps, objCallbacks, objChildren, inputname(1), fig); - if nargout, hFig = fig; end -% { - % Error handling - catch - v = version; - if v(1)<='6' - err.message = lasterr; % no lasterror function... - else - err = lasterror; - end - try - err.message = regexprep(err.message,'Error using ==> [^\n]+\n',''); - catch - try - % Another approach, used in Matlab 6 (where regexprep is unavailable) - startIdx = findstr(err.message,'Error using ==> '); - stopIdx = findstr(err.message,char(10)); - for idx = length(startIdx) : -1 : 1 - idx2 = min(find(stopIdx > startIdx(idx))); %#ok ML6 - err.message(startIdx(idx):stopIdx(idx2)) = []; - end - catch - % never mind... - end - end - if isempty(findstr(mfilename,err.message)) - % Indicate error origin, if not already stated within the error message - err.message = [mfilename ': ' err.message]; - end - if v(1)<='6' - while err.message(end)==char(10) - err.message(end) = []; % strip excessive Matlab 6 newlines - end - error(err.message); - else - rethrow(err); - end - end -% } - -%% Internal error processing -function myError(id,msg) - v = version; - if (v(1) >= '7') - error(id,msg); - else - % Old Matlab versions do not have the error(id,msg) syntax... - error(msg); - end -%end % myError %#ok for Matlab 6 compatibility - -%% Get object data - methods -function objMethods = getObjMethods(obj) - - % The following was taken from Matlab's methodsview.m function - if ischar(obj) - qcls = obj; % Yair - else - qcls = builtin('class', obj); - end - [m,d] = methods(qcls,'-full'); - dflag = 1; - ncols = 6; - - if isempty(d) - dflag = 0; - d = cell(size(m,1), ncols); - for i=1:size(m,1) - t = find(m{i}=='%',1,'last'); - if ~isempty(t) - d{i,3} = m{i}(1:t-2); - d{i,6} = m{i}(t+17:end); - else - d{i,3} = m{i}; - end - end - end - - r = size(m,1); - t = d(:,4); - if ~isempty(d) - d(:,4:ncols-1) = d(:,5:ncols); - d(:,ncols) = t; - %[y,x] = sort(d(:,3)); %#ok y is unused - [y,x] = sort(strcat(d(:,3),d(:,4))); %#ok y is unused - secondary sort by argument list - else - %d = {'','','no methods for this object','','',''}; - x = 1; - end - cls = ''; - clss = 0; - - w = num2cell(zeros(1,ncols)); - - for i=1:r - if isempty(cls) && ~isempty(d{i,6}) - t = find(d{i,6}=='.', 1, 'last'); - if ~isempty(t) && strcmp(d{i,3},d{i,6}(t+1:end)) - cls = d{i,6}; - clss = length(cls); - end - end - for j=1:ncols - if isnumeric(d{i,j}) - d{i,j} = ''; - elseif j==4 && strcmp(d{i,j},'()') - d{i,j} = '( )'; - elseif j==6 - d{i,6} = deblank(d{i,6}); - if clss > 0 && ... % If this is the inheritance column & indicates no inheritance - (strncmp(d{i,6},qcls,length(qcls)) || ... %Yair - (strncmp(d{i,6},cls,clss) &&... - (length(d{i,6}) == clss ||... - (length(d{i,6}) > clss && d{i,6}(clss+1) == '.')))) - d{i,6} = ''; % ...then clear this cell (=not inherited) - elseif ~isempty(d{i,6}) - t = find(d{i,6}=='.', 1, 'last'); - if ~isempty(t) - d{i,6} = d{i,6}(1:t-1); - end - end - end - end - end - - if ~dflag - for i=1:r - d{i,6} = d{i,5}; - d{i,5} = ''; - end - end - - datacol = zeros(1, ncols); - for i=1:r - for j=1:ncols - if ~isempty(d{i,j}) - datacol(j) = 1; - w{j} = max(w{j},length(d{i,j})); - end - end - end - - % HTMLize classes - %d = regexprep(d,'([^ ,()\[\]]+\.[^ ,()\[\]]*)','$1'); - d = regexprep(d,'([^ ,()\[\]]+\.[^ ,()\[\]]*)','$1'); - d = regexprep(d,',',' , '); - d = regexprep(d,'(.+)','$1'); - - % Determine the relevant column headers (& widths) - ch = {}; - hdrs = {'Qualifiers', 'Return Type', 'Name', 'Arguments', 'Other', 'Inherited From'}; - for i=ncols:-1:1 - if datacol(i) - datacol(i) = sum(datacol(1:i)); - ch{datacol(i)} = hdrs{i}; %#ok - w{i} = max([length(ch{datacol(i)}),w{i}]); - end - end - - if isempty(ch) - ch = ' '; - d = {'(no methods)'}; - w = {100}; - x = 1; - datacol = 1; - end - - % Return the data - objMethods.headers = ch; - objMethods.methods = d(:,find(datacol)); %#ok for ML6 compatibility - objMethods.widths = [w{find(datacol)}]; %#ok for ML6 compatibility - objMethods.sortIdx = x; -%end % getObjMethods - -%% Get object data - properties -function objProps = getObjProps(obj) - objProps = obj; %TODO - merge with getPropsData() below -%end % getObjProps - -%% Get object data - callbacks -function objCallbacks = getObjCallbacks(obj) - objCallbacks = obj; %TODO - merge with getCbsData() below -%end % getObjCallbacks - -%% Get object data - children -function objChildren = getObjChildren(obj) - objChildren = obj; %TODO - merge with getPropsData() below -%end % getObjChildren - -%% Display object data -function hFig = displayObj(obj, objMethods, objProps, objCallbacks, objChildren, objName, hFig) - - % Set the figure title - if isempty(objName) - objName = 'object of '; - else - objName = [objName ' of ']; - end - if ischar(obj) - className = obj; - objName = ''; - else - className = builtin('class', obj); - end - title = ['uiinspect: ' objName 'class ' className]; - - % If no figure handle for reuse was specified - if isempty(hFig) - % Try to reuse figure with the same title - hFig = findall(0, '-depth',1, 'type','figure', 'name',title); - end - % If no valid figure was found, create a new one - otherwise clear and reuse - if isempty(hFig) - hFig = figure('visible','off'); % existing uiinspector for this object not found - create a new figure (invisible at first) - else - hFig = hFig(1); % just in case there's more than one such figure - clf(hFig); - end - set(hFig, 'Name',title, 'NumberTitle','off', 'units','pixel', 'toolbar','none', 'menubar','none'); - - % Prepare the data panes - [methodsPane, hgFlag] = getMethodsPane(objMethods, obj, hFig); - [callbacksPanel, cbTable] = getCbsPane(objCallbacks, false); - [propsPane, inspectorTable] = getPropsPane(objProps); - [childrenPane, propsNum] = getChildrenPane(objChildren, inspectorTable, propsPane); - - % Prepare the top-bottom JSplitPanes - import java.awt.* - import javax.swing.* - if ~isempty(inspectorTable) - rightPanel = JSplitPane(JSplitPane.VERTICAL_SPLIT, propsPane, childrenPane); - leftPanel = JSplitPane(JSplitPane.VERTICAL_SPLIT, methodsPane, callbacksPanel); - rightPanel.setOneTouchExpandable(1); rightPanel.setContinuousLayout(1); rightPanel.setResizeWeight(0.8); - leftPanel.setOneTouchExpandable(1); leftPanel.setContinuousLayout(1); leftPanel.setResizeWeight(0.7); - else - rightPanel = childrenPane; - leftPanel = methodsPane; - end - - % Prepare the left-right JSplitPane - hsplitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel); - hsplitPane.setOneTouchExpandable(1); - hsplitPane.setContinuousLayout(1); - hsplitPane.setResizeWeight(0.6); - - % blog link at bottom - blogLabel = JLabel('
More undocumented stuff at: UndocumentedMatlab.com
'); - set(handle(blogLabel,'CallbackProperties'), 'MouseClickedCallback', 'web(''http://UndocumentedMatlab.com'',''-browser'')'); - blogLabel.setCursor(java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); - lowerPanel = JPanel(FlowLayout); - lowerPanel.add(blogLabel); - - % Display on-screen - globalPanel = JPanel(BorderLayout); - globalPanel.add(lowerPanel, BorderLayout.SOUTH); - if isempty(inspectorTable) && (propsNum==0) - globalPanel.add(leftPanel, BorderLayout.CENTER); - else - globalPanel.add(hsplitPane, BorderLayout.CENTER); - end - - set(hFig, 'visible','on'); - pos = get(hFig,'position'); - [obj, hcontainer] = javacomponent(globalPanel, [0,0,pos(3:4)], hFig); - set(hcontainer,'units','normalized'); - drawnow; - - % Update the central horizontal divider position based on #methods - % Note: this only works after the JSplitPane is displayed... - hDivPos = 0.6; - if isempty(inspectorTable) && (propsNum==0) - hDivPos = 1.0; - elseif length(objMethods.widths) < 3 - hDivPos = 0.4; - end - hsplitPane.setDividerLocation(hDivPos); - - % Update the right vertical divider position based on #properties - if ~isempty(inspectorTable) - vDivPos = 0.8; - try - vDivPos = max(0.2,min(vDivPos,inspectorTable.getRowCount/10)); - catch - % never mind... - end - rightPanel.setDividerLocation(vDivPos); - end - - % Update the left vertical divider position based on #methods,#callbacks - vDivPos = max(0.7, 1-cbTable.getRowCount/10); - try - % For non-HG handles - if ~hgFlag - % Drag the left horizontal divider upward to leave more space for callbacks if not too many methods - vDivPos = max(0.3,min(vDivPos,length(objMethods.methods)/10)); - end - catch - % never mind... - end - if ~isempty(inspectorTable) - % auto-hide cbTable if no callbacks - if cbTable.getRowCount==1 && cbTable.getColumnCount==1 - vDivPos = 1; - end - leftPanel.setDividerLocation(vDivPos); - end - %restoreDbstopError(identifiers); - - drawnow; - figure(hFig); % focus in front - - % Check for a newer version - checkVersion(); - - return; % debugable point -%end % displayObj - -%% Prepare the property inspector panel -function [propsPane, inspectorTable] = getPropsPane(obj) - % Prepare the properties pane - import java.awt.* - import javax.swing.* - %classNameLabel = JLabel([' ' char(obj.class)]); - classNameLabel = JLabel(' Inspectable object properties'); - classNameLabel.setForeground(Color.blue); - objProps = updateObjTooltip(obj, classNameLabel); %#ok unused - propsPane = JPanel(BorderLayout); - oldWarn = warning('off','MATLAB:hg:JavaSetHGProperty'); - try - set(propsPane, 'userdata',classNameLabel); - catch - setappdata(propsPane, 'userdata',classNameLabel); - end - warning(oldWarn); - propsPane.add(classNameLabel, BorderLayout.NORTH); - % TODO: Maybe uncomment the following - in the meantime it's unused (java properties are un-groupable) - %objReg = com.mathworks.services.ObjectRegistry.getLayoutRegistry; - %toolBar = awtinvoke('com.mathworks.mlwidgets.inspector.PropertyView$ToolBarStyle','valueOf(Ljava.lang.String;)','GROUPTOOLBAR'); - %inspectorPane = com.mathworks.mlwidgets.inspector.PropertyView(objReg, toolBar); - inspectorPane = com.mathworks.mlwidgets.inspector.PropertyView; - identifiers = disableDbstopError; %#ok "dbstop if error" causes inspect.m to croak due to a bug - so workaround - try - if ischar(obj), error(' '); end % bail out on class names... - inspectorPane.setObject(obj); - catch - inspectorTable = []; - return; - end - inspectorPane.setAutoUpdate(true); - % TODO: Add property listeners - inspectorTable = inspectorPane; - try - while ~isa(inspectorTable,'javax.swing.JTable') - inspectorTable = inspectorTable.getComponent(0); - end - catch - % R2010a - inspectorTable = inspectorPane.getComponent(0).getScrollPane.getViewport.getComponent(0); - end - toolTipText = 'hover mouse over the blue label above to see the full list of properties'; - inspectorTable.setToolTipText(toolTipText); - try - % Try JIDE features - see http://www.jidesoft.com/products/JIDE_Grids_Developer_Guide.pdf - com.mathworks.mwswing.MJUtilities.initJIDE; - jideTableUtils = eval('com.jidesoft.grid.TableUtils;'); % prevent JIDE alert by run-time (not load-time) evaluation - jideTableUtils.autoResizeAllColumns(inspectorTable); - inspectorTable.setRowAutoResizes(true); - inspectorTable.getModel.setShowExpert(1); - catch - % JIDE is probably unavailable - never mind... - end - propsPane.add(inspectorPane, BorderLayout.CENTER); - %mainPropsPane = JPanel; - %mainPropsPane.setLayout(BoxLayout(mainPropsPane, BoxLayout.PAGE_AXIS)); - %mainPropsPane.add(inspectorPane); - - % Strip all inspected props from objProps: - pause(0.1); %allow the inspector time to load... - return; - %{ - rows = inspectorTable.getModel.getRows; - numRows = rows.size; - for rowIdx = 0 : numRows-1 - thisRow = rows.get(rowIdx); - objProps = stripProp(objProps, char(thisRow.getDisplayName)); - for childIdx = 0 : thisRow.getChildrenCount-1 - objProps = stripProp(objProps, char(thisRow.getChildAt(childIdx).getDisplayName)); - end - end - %} -%end % getPropsPane - -%% Strip inspected property name from pre-fetched list of object properties -function objProps = stripProp(objProps, inspectedPropName) %#ok unused - try - % search for a case-insensitive match - %objProps = rmfield(objProps,inspectedPropName); - propNames = fieldnames(objProps); - idx = strcmpi(propNames,inspectedPropName); - objProps = rmfield(objProps,propNames(idx)); - catch - % never mind - inspectedProp was probably not in objProps - end -%end % stripPropName - -%% Get callbacks table data -function [cbData, cbHeaders, cbTableEnabled] = getCbsData(obj, stripStdCbsFlag) - % Initialize - cbData = {'(no callbacks)'}; - cbHeaders = {'Callback name'}; - cbTableEnabled = false; - cbNames = {}; - - try - try - classHdl = classhandle(handle(obj)); - cbNames = get(classHdl.Events,'Name'); - if ~isempty(cbNames) && ~iscom(obj) %only java-based please... - cbNames = strcat(cbNames,'Callback'); - end - propNames = get(classHdl.Properties,'Name'); - catch - % Try to interpret as an MCOS class object - try - oldWarn = warning('off','MATLAB:structOnObject'); - warning off MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame - dataFields = struct(obj); - warning(oldWarn); - catch - dataFields = get(obj); - end - propNames = fieldnames(dataFields); - end - propCbIdx = []; - if ischar(propNames), propNames={propNames}; end - if ~isempty(propNames) - propCbIdx = find(~cellfun(@isempty,regexp(propNames,'(Fcn|Callback)$'))); - cbNames = unique([cbNames; propNames(propCbIdx)]); %#ok logical is faster but less debuggable... - end - if ~isempty(cbNames) - if stripStdCbsFlag - cbNames = stripStdCbs(cbNames); - end - if iscell(cbNames) - cbNames = sort(cbNames); - end - hgHandleFlag = 0; try hgHandleFlag = ishghandle(obj); catch, end - try - obj = handle(obj,'CallbackProperties'); - catch - hgHandleFlag = 1; - end - if hgHandleFlag - % HG handles don't allow CallbackProperties - search only for *Fcn - cbNames = propNames(propCbIdx); - end - if iscom(obj) - cbs = obj.eventlisteners; - if ~isempty(cbs) - cbNamesRegistered = cbs(:,1); - cbData = setdiff(cbNames,cbNamesRegistered); - %cbData = charizeData(cbData); - if size(cbData,2) > size(cbData(1)) - cbData = cbData'; - end - cbData = [cbData, cellstr(repmat(' ',length(cbData),1))]; - cbData = [cbData; cbs]; - [sortedNames, sortedIdx] = sort(cbData(:,1)); - sortedCbs = cellfun(@charizeData,cbData(sortedIdx,2),'un',0); - cbData = [sortedNames, sortedCbs]; - else - cbData = [cbNames, cellstr(repmat(' ',length(cbNames),1))]; - end - elseif iscell(cbNames) - %cbData = [cbNames, get(obj,cbNames)']; - cbData = cbNames; - oldWarn = warning('off','MATLAB:hg:JavaSetHGProperty'); - for idx = 1 : length(cbNames) - try - cbData{idx,2} = charizeData(get(obj,cbNames{idx})); - catch - cbData{idx,2} = '(callback value inaccessible)'; - end - end - warning(oldWarn); - else % only one event callback - %cbData = {cbNames, get(obj,cbNames)'}; - %cbData{1,2} = charizeData(cbData{1,2}); - try - cbData = {cbNames, charizeData(get(obj,cbNames))}; - catch - cbData = {cbNames, '(callback value inaccessible)'}; - end - end - cbHeaders = {'Callback name','Callback value'}; - cbTableEnabled = true; - end - catch - % never mind - use default (empty) data - end -%end % getCbsData - -%% Get a Matlab object's meta-class object -function mc = getMetaClass(obj) - try - mc = meta.class.fromName(obj); - catch - mc = metaclass(obj); - end -%end % getMetaClass - -%% Load a Java class name -function loadedClass = loadClass(className) - try - loadedClass = java.lang.Class.forName(className); - catch - try - classLoader = com.mathworks.jmi.ClassLoaderManager.getClassLoaderManager; - loadedClass = classLoader.loadClass(className); - catch - % One more attempt - maybe the last sub-segment is an internal class: - if isempty(strfind(className,'$')) - obj = regexprep(className,'\.([^.]+$)','\$$1'); - loadedClass = loadClass(obj); - else - loadedClass = []; - end - end - end -%end % loadClass - -%% Get properties table data -function [propsData, propsHeaders, propTableEnabled, propsNum] = getPropsData(obj, showMetaData, showInspectedPropsFlag, inspectorTable, cbInspected) - try - propsNum = 0; % ok - just in case of error - propNames = {}; - mc = []; - try - %propNames = fieldnames(handle(obj)); - classHdl = classhandle(handle(obj)); - propNames = get(classHdl.Properties,'Name'); - catch - % maybe a Matlab class... - try - mc = getMetaClass(obj); - propNames = cellfun(@(p) p.Name, mc.Properties, 'un',0); - catch - %never mind... - might be a classname without any handle - end - end - - % Add static class fields, if available - try - if ischar(obj) - objClass = loadClass(obj); - fields = objClass.getFields; - fieldsData = cellfun(@(c)char(toString(c)),cell(fields),'un',0); - fieldNames = cellfun(@(c)char(toString(c.getName)),cell(fields),'un',0); - else - fieldNames = fieldnames(obj); - try fieldsData = fieldnames(obj,'-full'); catch, end %#ok - end - propNames = [propNames; fieldNames]; - fieldsData = strcat(fieldsData,'%'); - catch - % never mind... - end - - % Sort properties alphabetically - % Note: sorting is already a side-effect of setdiff, but setdiff is not called when showInspectedPropsFlag=1 - if iscell(propNames) - propNames = sort(unique(propNames)); - end - - %propsData = cell(0,7); - propsData = {'(no properties)','','','','','',''}; - propsHeaders = {'Name','Type','Value','Get','Set','Visible'}; - if isempty(mc) - propsHeaders{end+1} = 'Default'; % not relevant for Matlab classes - else - propsHeaders{end+1} = 'Extra'; % Sealed/Dependent/Constant/Abstract/Transient - end - propTableEnabled = false; - propsNum = length(propNames); - if ~isempty(propNames) - - if ~showInspectedPropsFlag - oldPropNames = propNames; - % Strip all inspected props - pause(0.01); %allow the inspector time to load... - rows = inspectorTable.getModel.getRows; - numRows = rows.size; - for rowIdx = 0 : numRows-1 - thisRow = rows.get(rowIdx); - [dummy,idx] = setdiff(upper(propNames), upper(char(thisRow.getDisplayName))); - propNames = propNames(idx); - for childIdx = 0 : thisRow.getChildrenCount-1 - [dummy,idx] = setdiff(upper(propNames), upper(char(thisRow.getChildAt(childIdx).getDisplayName))); - propNames = propNames(idx); - end - end - if ~isequal(oldPropNames,propNames) - cbInspected.setVisible(1); - end - end - - % Strip callback properties - if ischar(propNames), propNames = {propNames}; end - propNames(~cellfun(@isempty,regexp(propNames,'(Fcn|Callback)$'))') = []; - try - mcPropNames = cellfun(@(p) p.Name, mc.Properties, 'un',0); - catch - mcPropNames = propNames; - end - - % Add property Type & Value data - errorPrefix = ''; %red - unsettablePrefix = ''; %light gray - staticFinalPrefix = ''; %light blue - for idx = 1 : length(propNames) - propName = propNames{idx}; - try - % Find the property's schema.prop data - sp = findprop(handle(obj),propName); %=obj.classhandle.findprop(propName); - - % Fade non-settable properties (gray italic font) - prefix = ''; - try if strcmpi(sp.AccessFlags.PublicSet,'off'), prefix = unsettablePrefix; end, catch, end - try if ~isequal(sp.SetAccess,'public'), prefix = unsettablePrefix; end, catch, end - - % Get the property's meta-data - propsData{idx,1} = [prefix propName]; - propsData{idx,2} = ''; - if ~isempty(sp) - try - % UDD - dataType = sp.DataType; - publicGet = sp.AccessFlags.PublicGet; - publicSet = sp.AccessFlags.PublicSet; - isVisible = sp.Visible; - try - factoryValue = ''; - factoryValue = charizeData(sp.FactoryValue); - %factoryValue = charizeData(get(sp,'FactoryValue')); % sp.FactoryValue fails... - catch - % Prevent a Matlab crash on R2011b - V = sscanf(version, '%d.', 2); - if V(1) <= 7 && V(2) < 13 - factoryValue = charizeData(get(sp,'FactoryValue')); - end - end - extraStr = factoryValue; - catch - % MCOS/HG2 - publicGet = sp.GetAccess; - publicSet = sp.SetAccess; - isVisible = 'on'; if sp.Hidden, isVisible = 'off'; end - try - factoryValue = charizeData(sp.DefaultValue); - dataType = class(factoryValue); - catch % no default value defined - TODO: how do we get the data type? - factoryValue = ''; - dataType = strrep(sp.Description,' PropInfo',''); - if strcmp(dataType,propName), dataType='?'; end - end - extraStr = strtrim([factoryValue ... - charizeBoolData(sp.Sealed, ' Sealed') ... - charizeBoolData(sp.Dependent,' Dependent') ... - charizeBoolData(sp.Constant, ' Constant') ... - charizeBoolData(sp.Abstract, ' Abstract') ... - charizeBoolData(sp.Transient,' Transient')]); - end - propsData{idx,2} = [prefix charizeData(dataType)]; - propsData{idx,4} = [prefix charizeData(publicGet)]; - propsData{idx,5} = [prefix charizeData(publicSet)]; - propsData{idx,6} = [prefix charizeData(isVisible)]; - if ~isempty(extraStr) % && ~strcmp(propName,'FactoryValue') - propsData{idx,7} = [prefix extraStr]; - else - propsData{idx,7} = ''; % otherwise Matlab crashes... - end - %propsData{idx,8} = [prefix sp.Description]; - end - % TODO: some fields (see EOL comment below) generate a Java Exception from: com.mathworks.mlwidgets.inspector.PropertyRootNode$PropertyListener$1$1.run - try - isGettable = strcmpi(sp.AccessFlags.PublicGet,'on'); % && ~any(strcmpi(sp.Name,{'FixedColors','ListboxTop','Extent'})) - catch - isGettable = isequal(sp.GetAccess,'public'); - end - if isGettable - try - % Trap warning about unused/deprecated properties - s = warning('off','all'); - lastwarn(''); - try - value = javaMethod(['get' sp.Name],obj); % Java object - catch - try - value = get(obj, sp.Name); % standard MCOS object - catch - value = obj.(sp.Name); % .Net object - end - end - strToIgnore1 = 'Possible deprecated use of get on a Java object'; - strToIgnore2 = 'figure JavaFrame property will be obsoleted in a future release.'; - if ~strncmpi(strToIgnore1,lastwarn,length(strToIgnore1)) && ... - ~strncmpi(strToIgnore2,lastwarn,length(strToIgnore2)) - disp(lastwarn); - end - warning(s); - value = regexprep(charizeData(value),']*>',''); % strip hyperlinks - if ~isempty(value) && any(strfind(value,'>')) - propsData{idx,3} = ['' value]; - else - propsData{idx,3} = value; - end - catch - errMsg = regexprep(lasterr, {char(10),'Error using ==> get.Java exception occurred:..','Error using .* Message: ',' Source:.*'}, {' ','','',''}); - propsData{idx,3} = [errorPrefix errMsg]; - propsData{idx,1} = strrep(propsData{idx,1},propName,[errorPrefix propName]); - end - else - propsData{idx,3} = '(no public getter method)'; - end - %disp({idx,propName}) % for debugging... - catch - % Try accessing the meta.property metadata - try - try - mp = findprop(obj,propName); - catch - mp = mc.Properties{strcmpi(mcPropNames,propName)}; - end - - % Fade non-settable properties (gray italic font) - prefix = ''; - if ~strcmpi(mp.SetAccess,'public') - prefix = unsettablePrefix; - end - - % Get the property's meta-data - propsData{idx,1} = [prefix propName]; - propsData{idx,2} = ''; - if ~isempty(mp) - propsData{idx,2} = [prefix mp.Description]; - propsData{idx,4} = [prefix mp.GetAccess]; - propsData{idx,5} = [prefix mp.SetAccess]; - visibleStr = 'true'; if mp.Hidden, visibleStr='false'; end - propsData{idx,6} = [prefix visibleStr]; - propsData{idx,7} = [prefix charizeBoolData(mp.Sealed, 'Sealed') ... - charizeBoolData(mp.Dependent,' Dependent') ... - charizeBoolData(mp.Constant, ' Constant') ... - charizeBoolData(mp.Abstract, ' Abstract') ... - charizeBoolData(mp.Transient,' Transient')]; - propsData{idx,7} = strtrim(propsData{idx,7}); - end - if strcmpi(mp.GetAccess,'public') - try - try - value = obj.(propName); - catch - value = eval([obj '.' propName]); - end - value = regexprep(charizeData(value),']*>',''); % strip hyperlinks - if ~isempty(value) && any(strfind(value,'>')) - propsData{idx,3} = ['' value]; - else - propsData{idx,3} = value; - end - catch - errMsg = regexprep(lasterr, {char(10),'Error using ==> get.Java exception occurred:..'}, {' ',''}); - propsData{idx,3} = [errorPrefix errMsg]; - propsData{idx,1} = strrep(propsData{idx,1},propName,[errorPrefix propName]); - end - else - propsData{idx,3} = '(no public getter method)'; - end - catch - % No schema.prop nor meta.property meta-data... - propsData{idx,1} = propName; - [propsData{idx,2:7}] = deal('???'); - try - try - propsData{idx,3} = charizeData(obj.(propName)); - catch - propsData{idx,3} = charizeData(get(obj,propName)); - end - catch - try - if ~ischar(obj) - propsData{idx,3} = obj.(propName); - else - propsData{idx,3} = eval([obj '.' char(propName)]); - end - propsData{idx,3} = charizeData(propsData{idx,3}); - fieldIdx = find(~cellfun(@isempty,regexp(fieldsData,['[ .]' propName '[ %]']))); - if ~isempty(fieldIdx) - thisFieldData = fieldsData{fieldIdx(1)}; - propsData{idx,2} = regexprep(thisFieldData,[' ' propName '.*'],''); - if ~isempty(regexp(thisFieldData,'final ', 'once')) - propsData{idx,1} = [staticFinalPrefix propsData{idx,1}]; - propsData{idx,2} = [unsettablePrefix propsData{idx,2}]; - propsData{idx,4} = [unsettablePrefix 'on']; - [propsData{idx,5:6}] = deal([unsettablePrefix 'off']); - %propsData{idx,7} = [unsettablePrefix propsData{idx,3}]; - propsData{idx,3} = [staticFinalPrefix propsData{idx,3}]; - end - end - catch - try - % Try using Java reflection - for fieldIdx = 1 : length(fields) % might have been resorted above - if strcmp(fields(fieldIdx).getName.char,propName) - propsData{idx,2} = fields(fieldIdx).toString.char; - propsData{idx,2} = regexprep(propsData{idx,2},[' [^ ]*' propName '$'],''); - isFinal = ~isempty(strfind(propsData{idx,2},'final')); - isPublic = ~isempty(strfind(propsData{idx,2},'public')); - if isPublic - propsData{idx,4} = 'on'; - propsData{idx,6} = 'on'; - else - propsData{idx,4} = 'off'; - propsData{idx,6} = 'off'; - end - if isPublic && ~isFinal - propsData{idx,5} = 'on'; - else - propsData{idx,5} = 'off'; - end - break; - end - end - catch - % never mind.. - end - end - end - end - end - end - propTableEnabled = true; - end - if ~showMetaData - % only show the Name & Value columns - propsData = propsData(:,[1,3]); - propsHeaders = propsHeaders(:,[1,3]); - end - catch - disp(lasterr); rethrow(lasterror) - end -%end % getPropsData - -%% Convert logical data into a string -function str = charizeBoolData(flagValue,flagName) - if islogical(flagValue) - if flagValue - str = flagName; - else - str = ''; - end - else - str = charizeData(flagValue); - end -%end % charizeBoolData - -%% Convert property data into a string -function data = charizeData(data) - if ~ischar(data) && ~isa(data,'java.lang.String') - newData = strtrim(evalc('disp(data)')); - try - newData = regexprep(newData,' +',' '); - newData = regexprep(newData,'Columns \d+ through \d+\s',''); - newData = regexprep(newData,'Column \d+\s',''); - catch - %never mind... - end - if iscell(data) - newData = ['{ ' newData ' }']; - elseif isempty(data) - newData = ''; - elseif isnumeric(data) || islogical(data) || any(ishandle(data)) || numel(data) > 1 %&& ~isscalar(data) - newData = ['[' newData ']']; - end - data = newData; - elseif ~isempty(data) - data = ['''' char(data) '''']; - end -%end % charizeData - -%% Prepare a hierarchical callbacks table data -function setProp(list,name,value,category) - prop = eval('com.jidesoft.grid.DefaultProperty();'); % prevent JIDE alert by run-time (not load-time) evaluation - prop.setName(name); - prop.setType(java.lang.String('').getClass); - prop.setValue(value); - prop.setEditable(true); - prop.setExpert(true); - %prop.setCategory(['' category ' callbacks']); - prop.setCategory([category ' callbacks']); - list.add(prop); -%end % getTreeData - -%% Prepare a hierarchical callbacks table data -function list = getTreeData(data) - list = java.util.ArrayList(); - names = regexprep(data,'([A-Z][a-z]+).*','$1'); - %hash = java.util.Hashtable; - others = {}; - for propIdx = 1 : size(data,1) - if (propIdx < size(data,1) && strcmp(names{propIdx},names{propIdx+1})) || ... - (propIdx > 1 && strcmp(names{propIdx},names{propIdx-1})) - % Child callback property - setProp(list,data{propIdx,1},data{propIdx,2},names{propIdx}); - else - % Singular callback property => Add to 'Other' category at bottom of the list - others(end+1,:) = data(propIdx,:); %#ok - end - end - for propIdx = 1 : size(others,1) - setProp(list,others{propIdx,1},others{propIdx,2},'Other'); - end -%end % getTreeData - -%% Prepare the callbacks pane -function [callbacksPanel, callbacksTable] = getCbsPane(obj, stripStdCbsFlag) - % Prepare the callbacks pane - import java.awt.* - import javax.swing.* - callbacksPanel = JPanel(BorderLayout); - [cbData, cbHeaders, cbTableEnabled] = getCbsData(obj, stripStdCbsFlag); - try - % Use JideTable if available on this system - com.mathworks.mwswing.MJUtilities.initJIDE; - %callbacksTableModel = javax.swing.table.DefaultTableModel(cbData,cbHeaders); %#ok - %callbacksTable = eval('com.jidesoft.grid.PropertyTable(callbacksTableModel);'); % prevent JIDE alert by run-time (not load-time) evaluation - try - list = getTreeData(cbData); %#ok - model = eval('com.jidesoft.grid.PropertyTableModel(list);'); %#ok prevent JIDE alert by run-time (not load-time) evaluation - - % Auto-expand if only one category - if model.getRowCount==1 % length(model.getCategories)==1 fails for some unknown reason... - model.expandFirstLevel; - end - - %callbacksTable = eval('com.jidesoft.grid.TreeTable(model);'); %#ok prevent JIDE alert by run-time (not load-time) evaluation - callbacksTable = eval('com.jidesoft.grid.PropertyTable(model);'); %#ok prevent JIDE alert by run-time (not load-time) evaluation - - %callbacksTable.expandFirstLevel; - callbacksTable.setShowsRootHandles(true); - callbacksTable.setShowTreeLines(false); - %callbacksTable.setShowNonEditable(0); %=SHOW_NONEDITABLE_NEITHER - callbacksPane = eval('com.jidesoft.grid.PropertyPane(callbacksTable);'); % prevent JIDE alert by run-time (not load-time) evaluation - callbacksPane.setShowDescription(false); - catch - callbacksTable = eval('com.jidesoft.grid.TreeTable(cbData,cbHeaders);'); % prevent JIDE alert by run-time (not load-time) evaluation - end - callbacksTable.setRowAutoResizes(true); - callbacksTable.setColumnAutoResizable(true); - callbacksTable.setColumnResizable(true); - jideTableUtils = eval('com.jidesoft.grid.TableUtils;'); % prevent JIDE alert by run-time (not load-time) evaluation - jideTableUtils.autoResizeAllColumns(callbacksTable); - callbacksTable.setTableHeader([]); % hide the column headers since now we can resize columns with the gridline - callbacksLabel = JLabel(' Callbacks:'); % The column headers are replaced with a header label - callbacksLabel.setForeground(Color.blue); - %callbacksPanel.add(callbacksLabel, BorderLayout.NORTH); - - % Add checkbox to show/hide standard callbacks (only if not a HG handle) - callbacksTopPanel = JPanel; - callbacksTopPanel.setLayout(BoxLayout(callbacksTopPanel, BoxLayout.LINE_AXIS)); - callbacksTopPanel.add(callbacksLabel); - hgHandleFlag = 0; try hgHandleFlag = ishghandle(obj); catch, end %#ok - % { - if ~hgHandleFlag && ~iscom(obj) - jcb = JCheckBox('Hide standard callbacks', stripStdCbsFlag); - set(handle(jcb,'CallbackProperties'), 'ActionPerformedCallback',@cbHideStdCbs_Callback); - set(jcb, 'userdata',callbacksTable, 'tooltip','Hide standard Swing callbacks - only component-specific callbacks will be displayed'); - callbacksTopPanel.add(Box.createHorizontalGlue); - callbacksTopPanel.add(jcb); - end - % } - callbacksPanel.add(callbacksTopPanel, BorderLayout.NORTH); - catch - % Otherwise, use a standard Swing JTable (keep the headers to enable resizing) - callbacksTable = JTable(cbData,cbHeaders); - end - try - set(callbacksTable, 'userdata',obj); - catch - setappdata(callbacksTable, 'userdata',obj); - end - if iscom(obj) - cbToolTipText = 'Callbacks may be ''string'' or @funcHandle'; - else - cbToolTipText = 'Callbacks may be ''string'', @funcHandle or {@funcHandle,arg1,...}'; - end - %cbToolTipText = [cbToolTipText '
 {Cell} callbacks are displayed as: [Ljava.lang...']; - callbacksTable.setToolTipText(cbToolTipText); - %callbacksTable.setGridColor(inspectorTable.getGridColor); - cbNameTextField = JTextField; - cbNameTextField.setEditable(false); % ensure that the callback names are not modified... - cbNameCellEditor = DefaultCellEditor(cbNameTextField); - cbNameCellEditor.setClickCountToStart(intmax); % i.e, never enter edit mode... - callbacksTable.getColumnModel.getColumn(0).setCellEditor(cbNameCellEditor); - if ~cbTableEnabled && callbacksTable.getColumnModel.getColumnCount>1 - callbacksTable.getColumnModel.getColumn(1).setCellEditor(cbNameCellEditor); - end - try - pause(0.05); % prevent intermittent crash reported for uiinspect(0) - hModel = handle(callbacksTable.getModel, 'CallbackProperties'); - set(hModel, 'TableChangedCallback',@tbCallbacksChanged); - try - set(callbacksTable.getModel,'userdata',obj); % set(hModel,'userdata',obj) croacks for some unknown reason... - catch - setappdata(hModel,'userdata',obj); - end - catch - % ignore - odd... - end - try - cbScrollPane = callbacksPane; %JScrollPane(callbacksPane); - %cbScrollPane.setHorizontalScrollBarPolicy(cbScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - catch - cbScrollPane = JScrollPane(callbacksTable); - cbScrollPane.setVerticalScrollBarPolicy(cbScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); - end - callbacksPanel.add(cbScrollPane, BorderLayout.CENTER); - callbacksPanel.setToolTipText(cbToolTipText); -%end % getCbsPane - -%% Get the class modifiers -function modifiers = getClassModifiers(thisClass) - try - modifiers = 'class'; - modifiers = char(java.lang.reflect.Modifier.toString(thisClass.getModifiers)); - modifiers = strtrim(strrep(modifiers,'public','')); - if isempty(modifiers), modifiers = 'class'; end - catch - % never mind... - end -%end % getClassModifiers - -%% Prepare the methods pane -function [methodsPane, hgFlag] = getMethodsPane(methodsObj, obj, hFig) - import java.awt.* - import javax.swing.* - methodsPane = JPanel(BorderLayout); - - % Get superclass if possible - superclass = ''; - interfaces = ''; - scSep = ''; - hgFlag = 0; - labelTypeStr = 'Methods of class'; - mc = []; - try - if isjava(obj) - thisClass = obj.getClass; - labelTypeStr = ['Methods of ' getClassModifiers(thisClass)]; - elseif ischar(obj) - try - thisClass = java.lang.Class.forName(obj); - catch - try - classLoader = com.mathworks.jmi.ClassLoaderManager.getClassLoaderManager; - thisClass = classLoader.loadClass(obj); - catch - % one final attempt... - thisClass = java.lang.String(obj); - end - end - labelTypeStr = ['Methods of ' getClassModifiers(thisClass)]; - elseif ~iscom(obj) && ishghandle(obj) - hgFlag = 1; - labelTypeStr = 'Hierarchy of'; - end - try - superclass = char(thisClass.getSuperclass.getCanonicalName); - catch - % try using metaclass - try - mc = getMetaClass(obj); - sc = mc.SuperClasses; - for scIdx = 1 : length(sc) - if scIdx>1, superclass = [superclass ', ']; end - superclass = [superclass, sc{scIdx}.Name]; - end - catch - % never mind... - end - end - interfaces = cellfun(@(c)char(toString(c.getName)),thisClass.getInterfaces.cell,'un',0); - catch - % never mind... - end - try - modifiers = ''; - modifiers = char(java.lang.reflect.Modifier.toString(thisClass.getModifiers)); - modifiers = strtrim(strrep(modifiers,'public','')); - catch - % never mind... - end - if isempty(modifiers), modifiers = 'class'; end - - if ~isempty(superclass) - superclass = [' (superclass: ' superclass ')']; - scSep = ' 
 '; - end - - % Add a label - hyperlink = ''; - if ischar(obj) - className = char(thisClass.toString); - className = regexprep(className,'.* ([^ ]+$)','$1'); - if ~isempty(strfind(className,'java')) - hyperlink = className; - className = ['' className '']; - end - else - className = builtin('class',obj); - if (isjava(obj) && ~isempty(strfind(className,'java'))) || ~isempty(mc) - hyperlink = className; - className = ['' className '']; - end - end - labelStr = ['  ' labelTypeStr ' ' className '']; - methodsLabel = JLabel([labelStr superclass]); - - % Hyperlink the className to Sun's Javadocs, if relevant - if hyperlink - try - if ~isempty(mc) - targetStr = ['help ' hyperlink]; - else - switch com.mathworks.util.PlatformInfo.getVersion % JVM version - case com.mathworks.util.PlatformInfo.VERSION_13 - prefix = 'javase/1.3'; % old: 'j2se/1.3'; - case com.mathworks.util.PlatformInfo.VERSION_14 - prefix = 'javase/1.4.2'; % old: 'j2se/1.4.2'; - case com.mathworks.util.PlatformInfo.VERSION_15 - prefix = 'javase/1.5.0'; % old: 'j2se/1.5.0'; - otherwise %case com.mathworks.util.PlatformInfo.VERSION_16 - prefix = 'javase/6'; - end - domain = 'http://docs.oracle.com'; %download.oracle.com'; % old: java.sun.com - url = [domain '/' prefix '/docs/api/' strrep(hyperlink,'.','/') '.html']; % TODO: treat classNames with internal '.' - targetStr = ['web(''' url ''')']; - end - set(handle(methodsLabel,'CallbackProperties'), 'MouseClickedCallback', targetStr); - methodsLabel.setCursor(java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); - catch - % never mind... - end - end - - % Set extra class info in the title's tooltip - toolTipStr = [' ' labelStr scSep superclass]; - if ~isempty(interfaces) && iscell(interfaces) - scSep = ' 
 '; - toolTipStr = [toolTipStr scSep ' implements: ']; - if length(interfaces) > 1, toolTipStr=[toolTipStr scSep '   ']; end - for intIdx = 1 : length(interfaces) - if intIdx>1, toolTipStr=[toolTipStr scSep '   ']; end %#ok grow - toolTipStr = [toolTipStr interfaces{intIdx}]; %#ok grow - end - end - methodsLabel.setToolTipText(toolTipStr); - methodsLabel.setForeground(Color.blue); - %methodsPane.add(methodsLabel, BorderLayout.NORTH); - methodsPanel = JPanel; - methodsPanel.setLayout(BoxLayout(methodsPanel, BoxLayout.LINE_AXIS)); - methodsPanel.add(methodsLabel); - methodsPanel.add(Box.createHorizontalGlue); - - % If this is an HG handle, display hierarchy tree instead of methods - if hgFlag - paneContents = getHandleTree(obj, hFig); - else - % Otherwise simply display the object's methods - paneContents = getMethodsTable(methodsObj, methodsPanel); - end - - % Attach the title panel and center contents to the methods pane - methodsPane.add(methodsPanel, BorderLayout.NORTH); - methodsPane.add(paneContents, BorderLayout.CENTER); -%end % getMethodsPane - -%% Display HG handle hiererchy in a tree -function handleTree = getHandleTree(obj, hFig) - import java.awt.* - import javax.swing.* - - %handleTree = uitree. - tree_h = com.mathworks.hg.peer.UITreePeer; - tree_hh = handle(tree_h,'CallbackProperties'); - try tree_h = javaObjectEDT(tree_h); catch, end % auto-delegate on EDT - %tree_h = handle(com.mathworks.hg.peer.UITreePeer,'CallbackProperties'); - try setappdata(tree_h, 'userdata',[]); catch, end % required to prevent an "invalid object" error downstream - - % Use the parent handle as root, unless there is none - hRoot = handle(get(obj,'parent')); - if isempty(hRoot) || ~ishandle(hRoot) - hRoot = obj; - end - [icon, iconObj] = getNodeIcon(hRoot); - rootName = getNodeName(hRoot); - isLeaf = isempty(allchild(hRoot)); - try - oldWarn = warning('off','MATLAB:uitreenode:DeprecatedFunction'); - rootNode = uitreenode('v0', handle(hRoot), rootName, icon, isLeaf); - warning(oldWarn); - catch % old matlab version don't have the 'v0' option - rootNode = uitreenode(handle(hRoot), rootName, icon, isLeaf); - end - if ~isempty(iconObj) - rootNode.setIcon(iconObj); - end - nodedata.obj = hRoot; - set(rootNode,'userdata',nodedata); -% root.setUserObject(hRoot); - setappdata(rootNode,'childHandle',obj); - tree_h.setRoot(rootNode); - handleTree = tree_h.getScrollPane; - handleTree.setMinimumSize(Dimension(50,50)); - jTreeObj = handle(handleTree.getViewport.getComponent(0),'CallbackProperties'); - jTreeObj.setShowsRootHandles(true) - jTreeObj.getSelectionModel.setSelectionMode(javax.swing.tree.TreeSelectionModel.SINGLE_TREE_SELECTION); - %jTreeObj.setVisible(0); - %jTreeObj.getCellRenderer.setLeafIcon([]); - %jTreeObj.getCellRenderer.setOpenIcon(figIcon); - %jTreeObj.getCellRenderer.setClosedIcon([]); - - % Select the root node if it's the current obj - % Note: we must do so here since all other nodes except the root are processed by expandNode below - if hRoot == obj - tree_h.setSelectedNode(rootNode); - end - - % Set meta-data for use in node expansion - userdata.initialHandle = obj; - userdata.inInit = true; - userdata.jTree = jTreeObj; - try - set(tree_h, 'userdata',userdata); - catch - try - setappdata(tree_h, 'userdata',userdata); - catch - tree_h = handle(tree_h, 'CallbackProperties'); - setappdata(tree_h, 'userdata',userdata); - end - end - - % Set the callback functions - set(tree_hh, 'NodeExpandedCallback', {@nodeExpanded, tree_h}); - set(tree_hh, 'NodeSelectedCallback', {@nodeSelected, tree_h, hFig}); - - % Set the tree mouse-click callback -% Note: default actions (expand/collapse) will still be performed? - % Note: MousePressedCallback is better than MouseClickedCallback - % since it fires immediately when mouse button is pressed, - % without waiting for its release, as MouseClickedCallback does - set(jTreeObj, 'MousePressedCallback', @treeMousePressedCallback); % context (right-click) menu - set(jTreeObj, 'MouseMovedCallback', @treeMouseMovedCallback); % mouse hover tooltips - - % Pre-expand hierarchy (parent & all grandchildren downward, but not current siblings) - expandNode(jTreeObj, tree_h, rootNode, 0); - jTreeObj.expandRow(0); % To fix intermittent cases of unexpansion - see TODO list below - - % Update userdata - userdata.inInit = false; - try - set(tree_h, 'userdata',userdata); - catch - setappdata(tree_h, 'userdata',userdata); - end -%end % getHandleTree - -%% Set up the uitree context (right-click) menu -function jmenu = setTreeContextMenu(obj,node) - % Prepare the context menu (note the use of HTML labels) - import javax.swing.* - handleValue = double(obj); - titleStr = getNodeTitleStr(obj,node); - menuItem0 = JMenuItem(titleStr); - menuItem0.setEnabled(0); - menuItem0.setArmed(0); - menuItem1 = JMenuItem('Copy handle value to clipboard'); - if isjava(obj), prefix = 'j'; else, prefix = 'h'; end %#ok - varname = char(node.getName); - varname = regexprep(varname,'<[^>]*>',''); % strip HTML - varname = strrep([prefix strtok(varname)], '$','_'); - varname = genvarname(varname); - varname(2) = upper(varname(2)); % ensure lowerCamelCase - menuItem2 = JMenuItem(['Export handle to ' varname]); - menuItem3 = JMenuItem('Export handle to...'); - menuItem4 = JMenuItem('Request focus (bring to front)'); - menuItem5 = JMenuItem('Inspect in this window'); - menuItem6 = JMenuItem('Inspect in a new window'); - menuItem7 = JMenuItem('Inspect underlying Java object'); - menuItem8 = JMenuItem('View object in Java hierarchy'); - - % Set the menu items' callbacks - set(handle(menuItem1,'CallbackProperties'),'ActionPerformedCallback',sprintf('clipboard(''copy'',''%.99g'')',handleValue)); - set(handle(menuItem2,'CallbackProperties'),'ActionPerformedCallback',{@btExport_Callback,{obj,varname}}); - set(handle(menuItem3,'CallbackProperties'),'ActionPerformedCallback',{@btExport_Callback,{obj,[]}}); - set(handle(menuItem4,'CallbackProperties'),'ActionPerformedCallback',{@requestFocus,obj}); - set(handle(menuItem5,'CallbackProperties'),'ActionPerformedCallback',{@inspectHandle,obj,0}); - set(handle(menuItem6,'CallbackProperties'),'ActionPerformedCallback',{@inspectHandle,obj,1}); - set(handle(menuItem7,'CallbackProperties'),'ActionPerformedCallback',{@inspectJavaObj,obj,0}); - set(handle(menuItem8,'CallbackProperties'),'ActionPerformedCallback',{@inspectJavaObj,obj,1}); - - % Add all menu items to the context menu (with internal separator) - jmenu = JPopupMenu; - jmenu.add(menuItem0); - jmenu.addSeparator; - jmenu.add(menuItem1); - jmenu.add(menuItem2); - jmenu.add(menuItem3); - jmenu.addSeparator; - jmenu.add(menuItem4); - jmenu.addSeparator; - jmenu.add(menuItem5); - jmenu.add(menuItem6); - jmenu.addSeparator; - jmenu.add(menuItem7); - jmenu.add(menuItem8); -%end % setTreeContextMenu - -%% Callback function for context-menu item -function btExport_Callback(src, evd, varargin) %#ok - try - data = varargin{1}; - obj = data{1}; - varName = data{2}; - if isempty(varName) - varName = inputdlg('Enter workspace variable name',mfilename); - if isempty(varName), return; end % bail out on - varName = varName{1}; - if isempty(varName) || ~ischar(varName), return; end % bail out on empty/null - varName = genvarname(varName); - end - assignin('base',varName,handle(obj,'CallbackProperties')); - msg = ['Exported object to base workspace variable ' varName]; - msgbox(msg,mfilename,'help'); - catch - % Never mind... - dispError - end -%end % btExport_Callback - -%% Inspect a specified handle -function inspectHandle(hTree, eventData, obj, newFigureFlag) %#ok hTree & eventData are unused - % Ensure the object handle is valid - if ~ishandle(obj) - msgbox('The selected object does not appear to be a valid handle as defined by the ishandle() function. Perhaps this object was deleted after this hierarchy tree was already drawn. Refresh this tree by selecting a valid node handle and then retry.','FindJObj','warn'); - beep; - return; - end - - try - % Run uiinspect on the specified object handle, in the requested window - hFig = gcf; - if newFigureFlag - hFig = figure; - end - uiinspect(obj,hFig); - catch - % never mind... - dispError; - end -%end % inspectHandle - -%% Inspect the underlying Java object of a handle -function inspectJavaObj(hTree, eventData, obj, newFigureFlag) %#ok hTree & eventData are unused - try - % If FINDJOBJ is not installed - if isempty(which('findjobj')) - - % Ask the user whether to download FINDJOBJ (YES, no, no & don't ask again) - answer = questdlg({'The Java inspector requires FINDJOBJ from Matlab Central File Exchange. FINDJOBJ was also created by Yair Altman, like this UIInspect utility.','','Download & install FINDJOBJ?'},'FindJObj','Yes','No','Yes'); - switch answer - case 'Yes' % => Yes: download & install - try - % Download FINDJOBJ - baseUrl = 'http://www.mathworks.com/matlabcentral/fileexchange/14317'; - fileUrl = [baseUrl '?controller=file_infos&download=true']; - file = urlread(fileUrl); - file = regexprep(file,[char(13),char(10)],'\n'); %convert to OS-dependent EOL - - % Install... - newPath = fullfile(fileparts(which(mfilename)),'findjobj.m'); - fid = fopen(newPath,'wt'); - fprintf(fid,'%s',file); - fclose(fid); - catch - % Error downloading: inform the user - msgbox(['Error in downloading: ' lasterr], 'FindJObj', 'warn'); - web(baseUrl); - end - - % ...and now run it... - %pause(0.1); - drawnow; - dummy = which('findjobj'); %#ok used only to load into memory (could also use rehash) - inspectJavaObjInternal(obj,newFigureFlag); - return; - - otherwise - % forget it... - end - else - % FindJobj is installed - run it on the specified handle - inspectJavaObjInternal(obj,newFigureFlag); - end - catch - % Never mind... - dispError - end -%end % inspectJavaObj - -%% Try to find and inspect the underlying Java object of a component handle -function inspectJavaObjInternal(obj,newFigureFlag) - - % Ensure the object handle is valid - if ~ishandle(obj) - msgbox('The selected object does not appear to be a valid handle as defined by the ishandle() function. Perhaps this object was deleted after this hierarchy tree was already drawn. Refresh this tree by selecting a valid node handle and then retry.','FindJObj','warn'); - beep; - return; - end - - try - % Change the mouse pointer to an hourglass until we're done - hFig = gcf; - oldPointer = get(hFig,'pointer'); - set(hFig,'pointer','watch') - drawnow; - - if newFigureFlag - % Interactive (GUI) FindJObj - findjobj(obj); - else - % Non-interactive FindJObj - jObj = findjobj(obj); - if ~isempty(jObj) - % Object found - inspect it in a new figure window - jObj = jObj(1); % several instances may be found - only inspect the first found instance - try - % Try to strip Matlab javahandle wrapper - jObj = jObj.java; - catch - % never mind... - end - uiinspect(jObj); - else - % Object not found - try interactive (GUI) FindJObj - answer = questdlg({['No underlying Java object was found for this ' get(handle(obj),'type') ' handle.'],'','Try to find it using the Java hierarchy tree?'},'FindJObj','Yes','No','Yes'); - switch answer - case 'Yes', findjobj(obj); - otherwise, % Do nothing... - end - end - end - catch - dispError - end - - % Restore the figure pointer to its original value - set(hFig,'pointer',oldPointer) -%end % inspectJavaObjInternal - -%% Request focus for the specified handle -function requestFocus(hTree, eventData, obj) %#ok hTree & eventData are unused - % Ensure the object handle is valid - if isjava(obj) - obj.requestFocus; - elseif ~ishandle(obj) - msgbox('The selected object does not appear to be a valid handle as defined by the ishandle() function. Perhaps this object was deleted after this hierarchy tree was already drawn. Refresh this tree by selecting a valid node handle and then retry.','FindJObj','warn'); - beep; - return; - end - - try - foundFlag = 0; - while ~foundFlag - if isempty(obj), return; end % sanity check - type = get(obj,'type'); - obj = double(obj); - foundFlag = any(strcmp(type,{'figure','axes','uicontrol'})); - if ~foundFlag - obj = get(obj,'Parent'); - end - end - feval(type,obj); - catch - % never mind... - dispError; - end -%end % requestFocus - -%% Set the mouse-press callback -function treeMousePressedCallback(hTree, eventData) - if eventData.isMetaDown % right-click is like a Meta-button - % Get the clicked node - clickX = eventData.getX; - clickY = eventData.getY; - jtree = eventData.getSource; - treePath = jtree.getPathForLocation(clickX, clickY); - try - % Modify the context menu based on the clicked node - node = treePath.getLastPathComponent; - try - userdata = get(node,'userdata'); - catch - userdata = getappdata(node,'userdata'); - end - obj = userdata.obj; - jmenu = setTreeContextMenu(obj,node); - - % TODO: remember to call jmenu.remove(item) in item callback - % or use the timer hack shown here to remove the item: -% timerFcn = {@menuRemoveItem,jmenu,item}; -% start(timer('TimerFcn',timerFcn,'StartDelay',0.2)); - - % Display the (possibly-modified) context menu - jmenu.show(jtree, clickX, clickY); - jmenu.repaint; - - % This is for debugging: - userdata.tree = jtree; - setappdata(gcf,'uiinspect_hgtree',userdata) - catch - % clicked location is NOT on top of any node - % Note: can also be tested by isempty(treePath) - end - end -%end - -%% Remove the extra context menu item after display -function menuRemoveItem(hObj,eventData,jmenu,item) %#ok unused - jmenu.remove(item); -%end % menuRemoveItem - -%% Get the title for the tooltip and context (right-click) menu -function nodeTitleStr = getNodeTitleStr(obj,node) - try - handleValueStr = sprintf('#: %.99g',double(obj)); - try - type = ''; - type = get(obj,'type'); - type(1) = upper(type(1)); - catch - if ~ishandle(obj) - type = ['Invalid ' char(node.getName) '']; - handleValueStr = '!!!
Perhaps this handle was deleted after this UIInspect tree was
already drawn. Try to refresh by selecting any valid node handle'; - end - end - nodeTitleStr = sprintf('%s handle %s',type,handleValueStr); - try - % If the component is invisible, state this in the tooltip - if strcmp(get(obj,'Visible'),'off') - nodeTitleStr = [nodeTitleStr '
Invisible']; - end - catch - % never mind... - end - catch - dispError - end -%end % getNodeTitleStr - -%% Handle tree mouse movement callback - used to set the tooltip & context-menu -function treeMouseMovedCallback(hTree, eventData) - try - x = eventData.getX; - y = eventData.getY; - jtree = eventData.getSource; - treePath = jtree.getPathForLocation(x, y); - try - % Set the tooltip string based on the hovered node - node = treePath.getLastPathComponent; - try - userdata = get(node,'userdata'); - catch - userdata = getappdata(node,'userdata'); - end - obj = userdata.obj; - tooltipStr = getNodeTitleStr(obj,node); - set(hTree,'ToolTipText',tooltipStr) - catch - % clicked location is NOT on top of any node - % Note: can also be tested by isempty(treePath) - end - catch - dispError; - end - return; % denug breakpoint -%end % treeMouseMovedCallback - -%% Find a tree node's type for its name -function [nodeName, nodeTitle] = getNodeName(hndl) - try - if isnumeric(hndl) - hndl = handle(hndl); - end - - % Initialize (just in case one of the succeding lines croaks) - nodeName = ''; - try - nodeName = class(hndl); - catch - if ~ismethod(hndl,'getClass') - try - nodeName = hndl.class; - catch - nodeName = hndl.type; % last-ditch try... - end - else - nodeName = hndl.getClass.getSimpleName; - end - end - nodeType = nodeName; - - % Strip away the package name, leaving only the regular classname - if ~isempty(nodeName) && ischar(nodeName) - nodeName = java.lang.String(nodeName); - nodeName = nodeName.substring(nodeName.lastIndexOf('.')+1); - end - if (nodeName.length == 0) - % fix case of anonymous internal classes, that do not have SimpleNames - try - nodeName = hndl.getClass.getName; - nodeName = nodeName.substring(nodeName.lastIndexOf('.')+1); - catch - % never mind - leave unchanged... - end - end - - % Get any unique identifying string (if available in one of several fields) - labelsToCheck = {'label','title','text','string','displayname','toolTipText','TooltipString','actionCommand','name','Tag','style','UIClassID'}; - nodeTitle = ''; - strField = ''; %#ok - used for debugging - while ((~isa(nodeTitle,'java.lang.String') && ~ischar(nodeTitle)) || isempty(nodeTitle)) && ~isempty(labelsToCheck) - try - nodeTitle = get(hndl,labelsToCheck{1}); - strField = labelsToCheck{1}; %#ok - used for debugging - catch - % never mind - probably missing prop, so skip to next one - end - labelsToCheck(1) = []; - end - if length(nodeTitle) ~= numel(nodeTitle) - % Multi-line - convert to a long single line - nodeTitle = nodeTitle'; - nodeTitle = nodeTitle(:)'; - end - extraStr = regexprep(nodeTitle,{sprintf('(.{35,%d}).*',min(35,length(nodeTitle)-1)),' +'},{'$1...',' '},'once'); - if ~isempty(extraStr) - if ischar(extraStr) - nodeName = nodeName.concat(' (''').concat(extraStr).concat(''')'); - else - nodeName = nodeName.concat(' (').concat(num2str(extraStr)).concat(')'); - end - %nodeName = nodeName.concat(strField); - end - - % Append the numeric handle value if no extra text was found to describe this handle - if strcmp(char(nodeName),char(nodeType)) - if strcmp(char(nodeType),'figure') && strcmp(get(hndl,'NumberTitle'),'on') - nodeName = sprintf('%s (''Figure %d'')',char(nodeName),double(hndl)); - else - %nodeName = sprintf('%s (%.99g)',char(nodeName),double(hndl)); - % Never mind - the handle value will be presented in the tooltip - end - end - catch - % Never mind - use whatever we have so far - %dispError - end -%end % getNodeName - -%% Find a suitable node icon (the default icons for most types is an ugly gray box...) -function [icon, iconObj] = getNodeIcon(obj) - icon = []; - iconObj = []; - try - type = lower(get(obj,'type')); - %disp(type) - switch type - case 'root', icon = 'matlabicon.gif'; - case 'figure', icon = 'figureicon.gif'; - case 'uimenu', - if ~isempty(allchild(obj)) - icon = 'foldericon.gif'; - else - icon = 'text_arrow.gif'; - end - case 'text', icon = 'tool_text.gif'; - case 'image', icon = 'tool_legend.gif'; - case 'uitoolbar', icon = 'greenarrowicon.gif'; - case {'uipushtool','uitoggletool'} - icon = []; - cdata = get(obj,'cdata'); - cdata(isnan(cdata)) = 1; % transparent => white (default=black) - iconObj = im2java(cdata); - end - if ~isempty(icon) && ischar(icon) - % Ensure the icon file exists - if not then use the default icon - icon = fullfile(matlabroot, 'toolbox/matlab/icons', icon); - iconfile = dir(icon); - if isempty(iconfile) - icon = []; - end - end - catch - dispError; - end -%end % getNodeIcon - -%% Recursively expand all nodes (except toolbar/menubar) in startup -function expandNode(tree, tree_h, parentNode, parentRow) - try - if nargin < 4 - parentPath = javax.swing.tree.TreePath(parentNode.getPath); - parentRow = tree.getRowForPath(parentPath); - end - tree.expandRow(parentRow); - numChildren = parentNode.getChildCount; - if (numChildren == 0) - pause(0.001); % as short as possible... - drawnow; - end - nodesToUnExpand = {'FigureMenuBar','MLMenuBar','MJToolBar','Box','uimenu','uitoolbar','ScrollBar'}; - numChildren = parentNode.getChildCount; - for childIdx = 0 : numChildren-1 - childNode = parentNode.getChildAt(childIdx); - - % Select the current node - try - selectedNodeFlag = 0; - try - nodedata = get(childNode, 'userdata'); - catch - nodedata = getappdata(childNode, 'userdata'); - end - try - userdata = get(tree_h, 'userdata'); - catch - userdata = getappdata(tree_h, 'userdata'); - end - if userdata.initialHandle == nodedata.obj - pause(0.001); % as short as possible... - drawnow; - tree_h.setSelectedNode(childNode); - selectedNodeFlag = 1; - end - catch - % never mind... - dispError - end - - % Expand all non-leaf nodes beneath the current obj, except toolbar/menu items - if ~childNode.isLeafNode - normalizedNodeName = strtok(childNode.getName.char); - if selectedNodeFlag || (nargin==4 && handle(userdata.initialHandle)==handle(0)) || ... - ((nargin < 4) && ~any(strcmp(normalizedNodeName,nodesToUnExpand))) - expandNode(tree, tree_h, childNode); - end - end - end - catch - % never mind... - dispError - end -%end % expandNode - -%% Expand tree node -function nodeExpanded(src, evd, tree) %#ok src is unused - try - % tree = handle(src); - % evdsrc = evd.getSource; - evdnode = evd.getCurrentNode; - - if ~tree.isLoaded(evdnode) - - % Get the list of children TreeNodes - childnodes = getChildrenNodes(tree, evdnode); - if isempty(childnodes) - return; - end - - % If we have a single child handle, wrap it within a javaArray for tree.add() to "swallow" - if (length(childnodes) == 1) - chnodes = childnodes; - childnodes = javaArray('com.mathworks.hg.peer.UITreeNode', 1); - childnodes(1) = java(chnodes); - end - - % Add child nodes to the current node - tree.add(evdnode, childnodes); - tree.setLoaded(evdnode, true); - end - catch - dispError - end -%end % nodeExpanded - -%% Get list of children nodes -function nodes = getChildrenNodes(tree, parentNode) %#ok tree is unused - try - nodes = handle([]); - nodedata = get(parentNode,'userdata'); - - % Get the HG handles of all parentNode's direct children - %children = findall(nodedata.obj,'-depth',1); - %children(children==double(nodedata.obj)) = []; - children = allchild(nodedata.obj); - if isempty(children) - return; - end - - %iconpath = [matlabroot, '/toolbox/matlab/icons/']; - numChildren = length(children); - for cIdx = 1 : numChildren - thisChild = children(cIdx); - thisChildHandle = handle(thisChild); - childName = getNodeName(thisChildHandle); - try - visible = strcmp(thisChildHandle.Visible,'on'); - if ~visible - childName = ['' char(childName) '']; %#ok grow - end - catch - % never mind... - end - [icon, iconObj] = getNodeIcon(thisChild); - isLeaf = isempty(findall(thisChild)); - try - oldWarn = warning('off','MATLAB:uitreenode:DeprecatedFunction'); - nodes(cIdx) = uitreenode('v0', thisChildHandle, childName, icon, isLeaf); - warning(oldWarn); - catch % old matlab version don't have the 'v0' option - try - nodes(cIdx) = uitreenode(thisChildHandle, childName, icon, isLeaf); - catch - % probably an invalid handle - ignore... - end - end - if ~isempty(iconObj) - nodes(cIdx).setIcon(iconObj); - end - - % Add the handler to the node's internal data - % Note: could also use 'userdata', but setUserObject() is recommended for TreeNodes - % Note2: however, setUserObject() sets a java *BeenAdapter object for HG handles instead of the required original class, so use setappdata - % Note3: the following will error if invalid handle - ignore - try - %nodes(cIdx).setUserObject(thisChildHandle); - setappdata(nodes(cIdx),'childHandle',thisChildHandle); - nodedata.obj = thisChildHandle; - set(nodes(cIdx),'userdata',nodedata); - catch - % never mind (probably an invalid handle) - leave unchanged (like a leaf) - end - end - catch - % Never mind - leave unchanged (like a leaf) - %error('YMA:findjobj:UnknownNodeType', 'Error expanding component tree node'); - dispError - end -%end % getChildrenNodes - -%% Select tree node -function nodeSelected(src, evd, tree_h, hFig) - try - rescanFlag = 0; - %nodeHandle = evd.getCurrentNode.getUserObject; - nodedata = get(evd.getCurrentNode,'userdata'); - nodeHandle = nodedata.obj; - try - userdata = get(tree_h,'userdata'); - catch - userdata = getappdata(tree_h,'userdata'); - end - if nargin<4, hFig = gcf; end - - if ~isempty(nodeHandle) && ~isempty(userdata) && ~userdata.inInit - - % Ensure the object handle is valid - if ~ishandle(nodeHandle) - msgbox('The selected object does not appear to be a valid handle as defined by the ishandle() function. Perhaps this object was deleted after this hierarchy tree was already drawn. Refresh this tree by selecting a valid node handle and then retry.','FindJObj','warn'); - beep; - return; - end - - % Get the current uiinspect figure handle - %hFig = []; - %try - % hFig = ancestor(src,'figure'); % TODO - this fails: need to find a way to pass hFig... - % if isempty(hFig) - % hFig = gcf; - % end - %catch - % hFig = gcf; - %end - - % Temoprarily modify the curpor pointer to an hourglass - rescanFlag = 1; - oldPointer = get(hFig,'pointer'); - set(hFig,'pointer','watch') - drawnow; - - % Re-inspect the selected handle (rename the variable 'handle' for a nice title name... - handle = nodeHandle; - uiinspect(handle,hFig); - - % TODO: Auto-highlight selected object (?) - %nodeHandle.requestFocus; - end - catch - dispError - end - - % Restore the figure pointer to its original value - if rescanFlag - set(hFig,'pointer',oldPointer) - end -%end % nodeSelected - -%% Display object methods in a table -function methodsTable = getMethodsTable(methodsObj, methodsPanel) - - % Method A: taken from Matlab's methodsview function (slightly modified) - %{ - ncols = length(methodsObj.widths); - b = com.mathworks.mwt.MWListbox; - b.setColumnCount(ncols); - wb = 0; - for i=1:ncols, - wc = 7.5 * methodsObj.widths(i); - b.setColumnWidth(i-1, wc); - b.setColumnHeaderData(i-1, methodsObj.headers{i}); - wb = wb+wc; - end; - - co = b.getColumnOptions; - set(co, 'HeaderVisible', 'on'); - set(co, 'Resizable', 'on'); - b.setColumnOptions(co); - set(b.getHScrollbarOptions,'Visibility','Always'); %Yair: fix HScrollbar bug - - ds = javaArray('java.lang.String', ncols); - for i=1:size(methodsObj.methods,1) - for j=1:ncols - ds(j) = java.lang.String(methodsObj.methods{methodsObj.sortIdx(i),j}); - end; - b.addItem(ds); - end; - %} - - % Create a checkbox for extra methods info - import javax.swing.* - cbExtra = JCheckBox('Extra', 0); - hcbExtra = handle(cbExtra,'CallbackProperties'); - methodsPanel.add(cbExtra); - - % Hide the extra data by default - headers = methodsObj.headers; - validIdx = strcmpi(headers,'Return Type') | strcmpi(headers,'Name') | strcmpi(headers,'Arguments'); - headers(~validIdx) = []; - if ~isempty(headers) - data = methodsObj.methods(methodsObj.sortIdx,validIdx); - if all(validIdx) - cbExtra.setVisible(0); % hide the Extra checkbox if no extra info is available - end - else - data = methodsObj.methods(methodsObj.sortIdx,1); - headers = {' '}; - cbExtra.setVisible(0); % hide the Extra checkbox - end - - % Method B: use a JTable - looks & refreshes much better... - try - com.mathworks.mwswing.MJUtilities.initJIDE; - b = eval('com.jidesoft.grid.TreeTable(data, headers);'); % prevent JIDE alert by run-time (not load-time) evaluation - b.setRowAutoResizes(true); - b.setColumnAutoResizable(true); - b.setColumnResizable(true); - jideTableUtils = eval('com.jidesoft.grid.TableUtils;'); % prevent JIDE alert by run-time (not load-time) evaluation - jideTableUtils.autoResizeAllColumns(b); - catch - try - b = JTable(data, headers); - catch - % probably no data - so create an empty table - b = JTable; - end - end - - % Hide the column header if only one column is shown - if length(headers) < 2 - b.setTableHeader([]); % hide the column headers since now we can resize columns with the gridline - %cbExtra.setVisible(0); % hide the Extra checkbox - end - - % Add hyperlink support - try - set(handle(b,'CallbackProperties'),'MousePressedCallback',@tbMousePressed,'MouseMovedCallback',@tbMouseMoved); - catch - % never mind... - end - - b.setShowGrid(0); - scroll = JScrollPane(b); - scroll.setVerticalScrollBarPolicy(scroll.VERTICAL_SCROLLBAR_AS_NEEDED); - scroll.setHorizontalScrollBarPolicy(scroll.HORIZONTAL_SCROLLBAR_AS_NEEDED); - b.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); - b.setAutoResizeMode(b.AUTO_RESIZE_SUBSEQUENT_COLUMNS) - %b.setEnabled(0); - cbNameTextField = JTextField; - cbNameTextField.setEditable(false); % ensure that the method names are not modified... - cbNameCellEditor = DefaultCellEditor(cbNameTextField); - cbNameCellEditor.setClickCountToStart(intmax); % i.e, never enter edit mode... - for colIdx = 1:length(headers) - b.getColumnModel.getColumn(colIdx-1).setCellEditor(cbNameCellEditor); - end - - % Set meta-data for the Extra checkbox callback - methodsObj.tableObj = b; - set(hcbExtra, 'ActionPerformedCallback',{@updateMethodsTable,methodsObj}); - set(cbExtra, 'tooltip','Also show qualifiers, interrupts & inheritance'); - - % Return the scrollpane - methodsTable = scroll; -%end % getMethodsTable - -%% Prepare the children pane (Display additional props that are not inspectable by the inspector) -function [othersPane, propsNum] = getChildrenPane(obj, inspectorTable, propsPane) - import java.awt.* - import javax.swing.* - - % Label (for inspectable objects only) - othersPane = JPanel(BorderLayout); - othersTopPanel = JPanel; - othersTopPanel.setLayout(BoxLayout(othersTopPanel, BoxLayout.LINE_AXIS)); - othersLabel = JLabel(' Object properties'); - if ~isempty(inspectorTable) - othersLabel.setText(' Other properties'); - othersLabel.setToolTipText('Properties not inspectable by the inspect table above'); - else - try - oldWarn = warning('off','MATLAB:hg:JavaSetHGProperty'); - classNameLabel = get(propsPane, 'userdata'); - othersLabel.setToolTipText(classNameLabel.getToolTipText); - catch - % never mind... - end - warning(oldWarn); - end - othersLabel.setForeground(Color.blue); - ud.othersLabel = othersLabel; - othersTopPanel.add(othersLabel); - %othersPane.add(othersLabel, BorderLayout.NORTH); - - % Add checkbox to show/hide meta-data - othersTopPanel.add(Box.createHorizontalGlue); - cbMetaData = JCheckBox('Meta-data', 0); - ud.cbMetaData = cbMetaData; - othersTopPanel.add(cbMetaData); - - % Add checkbox to show/hide inspectable properties (for inspectable objects only) - if ~isempty(inspectorTable) - cbInspectable = JCheckBox('Inspectable', 0); - cbInspectable.setVisible(0); - ud.cbInspected = cbInspectable; - othersTopPanel.add(cbInspectable); - else - cbInspectable = []; - end - othersPane.add(othersTopPanel, BorderLayout.NORTH); - - % Data table - [propsData, propsHeaders, unused, propsNum] = getPropsData(obj, false, isempty(inspectorTable), inspectorTable, cbInspectable); - try - % Use JideTable if available on this system - com.mathworks.mwswing.MJUtilities.initJIDE; - %propsTableModel = javax.swing.table.DefaultTableModel(cbData,cbHeaders); %#ok - %propsTable = eval('com.jidesoft.grid.PropertyTable(propsTableModel);'); % prevent JIDE alert by run-time (not load-time) evaluation - propsTable = eval('com.jidesoft.grid.TreeTable(propsData,propsHeaders);'); % prevent JIDE alert by run-time (not load-time) evaluation - propsTable.setRowAutoResizes(true); - propsTable.setColumnAutoResizable(true); - propsTable.setColumnResizable(true); - jideTableUtils = eval('com.jidesoft.grid.TableUtils;'); % prevent JIDE alert by run-time (not load-time) evaluation - jideTableUtils.autoResizeAllColumns(propsTable); - %propsTable.setTableHeader([]); % hide the column headers since now we can resize columns with the gridline - catch - % Otherwise, use a standard Swing JTable (keep the headers to enable resizing) - propsTable = JTable(propsData,propsHeaders); - end - %propsToolTipText = ' Callbacks may be ''strings'' or {@myFunc,arg1,...}'; - %propsTable.setToolTipText(propsToolTipText); - %propsTable.setGridColor(inspectorTable.getGridColor); - propNameTextField = JTextField; - propNameTextField.setEditable(false); % ensure that the prop names are not modified... - propNameCellEditor = DefaultCellEditor(propNameTextField); - propNameCellEditor.setClickCountToStart(intmax); % i.e, never enter edit mode... - if ~isobject(obj) && isempty(inspectorTable) - readOnlyCols = 0 : propsTable.getColumnModel.getColumnCount-1; - else - readOnlyCols = 0; - end - for readOnlyIdx = readOnlyCols - propsTable.getColumnModel.getColumn(readOnlyIdx).setCellEditor(propNameCellEditor); - end - ud.obj = obj; - ud.inspectorTable = inspectorTable; - hModel = handle(propsTable.getModel, 'CallbackProperties'); - set(hModel, 'TableChangedCallback',@tbPropChanged); - try - set(propsTable.getModel, 'userdata',ud); - catch - setappdata(hModel,'userdata',ud); - end - scrollPane = JScrollPane(propsTable); - scrollPane.setVerticalScrollBarPolicy(scrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); - %scrollPane.setHorizontalScrollBarPolicy(scrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); - othersPane.add(scrollPane, BorderLayout.CENTER); - - % Preserve persistent info in the propsTable's userdata - if ~isempty(cbMetaData) - hcbMetaData = handle(cbMetaData,'CallbackProperties'); - set(hcbMetaData, 'ActionPerformedCallback',{@updatePropsTable,propsTable}); - set(cbMetaData, 'tooltip','Also show property meta-data (type, visibility, get/set availability, etc.)'); - end - if ~isempty(cbInspectable) - hcbInspectable = handle(cbInspectable,'CallbackProperties'); - set(hcbInspectable, 'ActionPerformedCallback',{@updatePropsTable,propsTable}); - set(cbInspectable, 'tooltip','Also show inspectable properties (displayed in the table above)'); - end - try - set(propsTable, 'userdata',ud); - catch - setappdata(propsTable, 'userdata',ud); - end -%end % getChildrenPane - -%% "dbstop if error" causes inspect.m to croak due to a bug - so workaround by temporarily disabling this dbstop -function identifiers = disableDbstopError - dbStat = dbstatus; - idx = find(strcmp({dbStat.cond},'error')); - identifiers = [dbStat(idx).identifier]; - v = version; - if ~isempty(idx) && v(1) < '8'; - dbclear if error; - msgbox('''dbstop if error'' had to be disabled due to a Matlab bug that would have caused Matlab to crash.', mfilename, 'warn'); - end -%end % disableDbstopError - -%% Restore any previous "dbstop if error" -function restoreDbstopError(identifiers) %#ok unused - for itemIdx = 1 : length(identifiers) - eval(['dbstop if error ' identifiers{itemIdx}]); - end -%end % restoreDbstopError - -%% Strip standard Swing callbacks from a list of events -function evNames = stripStdCbs(evNames) - try - stdEvents = {'AncestorAdded', 'AncestorMoved', 'AncestorRemoved', 'AncestorResized', ... - 'ComponentAdded', 'ComponentRemoved', 'ComponentHidden', ... - 'ComponentMoved', 'ComponentResized', 'ComponentShown', ... - 'FocusGained', 'FocusLost', 'HierarchyChanged', ... - 'KeyPressed', 'KeyReleased', 'KeyTyped', ... - 'MouseClicked', 'MouseDragged', 'MouseEntered', 'MouseExited', ... - 'MouseMoved', 'MousePressed', 'MouseReleased', 'MouseWheelMoved', ... - 'PropertyChange', 'VetoableChange', ... - 'CaretPositionChanged', 'InputMethodTextChanged', ... - 'ButtonDown', 'Create', 'Delete'}; - evNames = setdiff(evNames,strcat(stdEvents,'Callback'))'; - catch - % Never mind... - disp(lasterr); rethrow(lasterror) - end -%end % stripStdCbs - -%% Callback function for checkbox -function cbHideStdCbs_Callback(src, evd, varargin) - try - % Update callbacks table data according to the modified checkbox state - callbacksTable = get(src,'userdata'); - obj = get(callbacksTable, 'userdata'); - [cbData, cbHeaders] = getCbsData(obj, evd.getSource.isSelected); - try - list = getTreeData(cbData); %#ok - callbacksTableModel = eval('com.jidesoft.grid.PropertyTableModel(list);'); %#ok prevent JIDE alert by run-time (not load-time) evaluation - - % Auto-expand if only one category - if callbacksTableModel.getRowCount==1 % length(callbacksTableModel.getCategories)==1 fails for some unknown reason... - callbacksTableModel.expandFirstLevel; - end - catch - callbacksTableModel = javax.swing.table.DefaultTableModel(cbData,cbHeaders); - end - set(handle(callbacksTableModel,'CallbackProperties'), 'TableChangedCallback',@tbCallbacksChanged); - set(callbacksTableModel, 'userdata',handle(obj,'CallbackProperties')); - callbacksTable.setModel(callbacksTableModel) - try - % Try to auto-resize the columns - callbacksTable.setRowAutoResizes(true); - jideTableUtils = eval('com.jidesoft.grid.TableUtils;'); % prevent JIDE alert by run-time (not load-time) evaluation - jideTableUtils.autoResizeAllColumns(callbacksTable); - catch - % JIDE is probably unavailable - never mind... - end - catch - % Never mind... - %disp(lasterr); rethrow(lasterror) - end -%end % cbHideStdCbs_Callback - -%% Update the methods table following a checkbox modification -function updateMethodsTable(src, evd, methodsObj, varargin) %#ok partially unused - try - % Update callbacks table data according to the modified checkbox state - if nargin < 3 - try - methodsObj = get(src,'userdata'); - catch - methodsObj = getappdata(src,'userdata'); - end - end - data = methodsObj.methods(methodsObj.sortIdx,:); - headers = methodsObj.headers; - if ~evd.getSource.isSelected % Extra data requested - validIdx = strcmpi(headers,'Return Type') | strcmpi(headers,'Name') | strcmpi(headers,'Arguments'); - headers(~validIdx) = []; - data(:,~validIdx) = []; - end - tableModel = javax.swing.table.DefaultTableModel(data,headers); - methodsObj.tableObj.setModel(tableModel) - try - % Try to auto-resize the columns - methodsObj.tableObj.setRowAutoResizes(true); - jideTableUtils = eval('com.jidesoft.grid.TableUtils;'); % prevent JIDE alert by run-time (not load-time) evaluation - jideTableUtils.autoResizeAllColumns(methodsObj.tableObj); - catch - % JIDE is probably unavailable - never mind... - end - - % Disable editing - %methodsObj.tableObj.setEnabled(0); - cbNameTextField = javax.swing.JTextField; - cbNameTextField.setEditable(false); % ensure that the method names are not modified... - cbNameCellEditor = javax.swing.DefaultCellEditor(cbNameTextField); - cbNameCellEditor.setClickCountToStart(intmax); % i.e, never enter edit mode... - for colIdx = 1:length(headers) - methodsObj.tableObj.getColumnModel.getColumn(colIdx-1).setCellEditor(cbNameCellEditor); - end - catch - % Never mind... - %disp(lasterr); rethrow(lasterror) - end -%end % updateMethodsTable - -%% Update the properties table following a checkbox modification -function updatePropsTable(src, evd, propsTable, varargin) %#ok partially unused - try - % Update callbacks table data according to the modified checkbox state - if nargin < 3 - try - propsTable = get(src,'userdata'); - catch - propsTable = getappdata(src,'userdata'); - end - end - try - ud = get(propsTable, 'userdata'); - catch - ud = getappdata(propsTable, 'userdata'); - end - obj = ud.obj; - inspectorTable = ud.inspectorTable; - oldData = {}; - try - oldData = cellfun(@(c)(c.toArray.cell),propsTable.getModel.getActualModel.getDataVector.toArray.cell,'un',0); - catch - try - oldData = cellfun(@(c)(c.toArray.cell),propsTable.getModel.getDataVector.toArray.cell,'un',0); - catch - % never mind... - end - end - oldData = [oldData{:}]'; - if ~isfield(ud,'cbInspected'), ud.cbInspected.isSelected = true; end - [propData, propHeaders] = getPropsData(obj, ud.cbMetaData.isSelected, ud.cbInspected.isSelected, inspectorTable, ud.cbInspected); - if ~isequal(oldData,propData) - propsTableModel = javax.swing.table.DefaultTableModel(propData,propHeaders); - try - ud.obj = handle(obj,'CallbackProperties'); - catch - try - ud.obj = handle(obj); - catch - % never mind... - end - end - ud.inspectorTable = inspectorTable; - hpropsTableModel = handle(propsTableModel,'CallbackProperties'); - set(hpropsTableModel, 'TableChangedCallback',@tbPropChanged); - try - set(propsTableModel, 'userdata',ud); - catch - setappdata(hpropsTableModel, 'userdata',ud); - end - propsTable.setModel(propsTableModel) - try - % Try to auto-resize the columns - propsTable.setRowAutoResizes(true); - jideTableUtils = eval('com.jidesoft.grid.TableUtils;'); % prevent JIDE alert by run-time (not load-time) evaluation - jideTableUtils.autoResizeAllColumns(propsTable); - catch - % JIDE is probably unavailable - never mind... - end - end - - % Update the header label - if ~isempty(inspectorTable) - if ud.cbInspected.isSelected - set(ud.othersLabel,'Text',' All properties', 'ToolTipText','All properties (including those shown above)'); - else - set(ud.othersLabel,'Text',' Other properties', 'ToolTipText','Properties not inspectable by the inspect table above'); - end - end - - % Disable editing all columns except the property Value - import javax.swing.* - propTextField = JTextField; - propTextField.setEditable(false); % ensure that the prop names & meta-data are not modified... - propCellEditor = DefaultCellEditor(propTextField); - propCellEditor.setClickCountToStart(intmax); % i.e, never enter edit mode... - for colIdx = 0 : propsTable.getColumnModel.getColumnCount-1 - thisColumn = propsTable.getColumnModel.getColumn(colIdx); - if ~strcmp(thisColumn.getHeaderValue,'Value') || (~isobject(ud.obj) && isempty(ud.inspectorTable)) - thisColumn.setCellEditor(propCellEditor); - end - end - catch - % Never mind... - disp(lasterr); rethrow(lasterror) - end -%end % updatePropsTable - -%% Update component callback upon callbacksTable data change -function tbCallbacksChanged(src, evd) - persistent hash - try - % exit if invalid handle or already in Callback - %if ~ishandle(src) || ~isempty(getappdata(src,'inCallback')) % || length(dbstack)>1 %exit also if not called from user action - if isempty(hash), hash = java.util.Hashtable; end - if ~ishandle(src) || ~isempty(hash.get(src)) % || length(dbstack)>1 %exit also if not called from user action - return; - end - %setappdata(src,'inCallback',1); % used to prevent endless recursion % can't use getappdata(src,...) because it fails on R2010b!!! - hash.put(src,1); - - % Update the object's callback with the modified value - drawnow; pause(0.05); - modifiedColIdx = evd.getColumn; - modifiedRowIdx = evd.getLastRow; - if modifiedRowIdx>=0 %&& modifiedColIdx==1 %sanity check - should always be true - table = evd.getSource; - try - object = get(src,'userdata'); - catch - object = getappdata(src,'userdata'); - end - cbName = strtrim(table.getValueAt(modifiedRowIdx,0)); - try - cbValue = strtrim(char(table.getValueAt(modifiedRowIdx,1))); - if ~isempty(cbValue) && ismember(cbValue(1),'{[@''') - cbValue = eval(cbValue); - end - if (~ischar(cbValue) && ~isa(cbValue, 'function_handle') && (~iscell(cbValue) || iscom(object(1)))) - revertCbTableModification(table, modifiedRowIdx, modifiedColIdx, cbName, object, ''); - else - for objIdx = 1 : length(object) - obj = object(objIdx); - if ~iscom(obj) - try - try - if isjava(obj) - obj = handle(obj,'CallbackProperties'); - end - catch - % never mind... - end - set(obj, cbName, cbValue); - catch - try - set(handle(obj,'CallbackProperties'), cbName, cbValue); - catch - % never mind - probably a callback-group header - end - end - else - cbs = obj.eventlisteners; - if ~isempty(cbs) - cbs = cbs(strcmpi(cbs(:,1),cbName),:); - obj.unregisterevent(cbs); - end - if ~isempty(cbValue) && ~strcmp(cbName,'-') - obj.registerevent({cbName, cbValue}); - end - end - end - end - catch - revertCbTableModification(table, modifiedRowIdx, modifiedColIdx, cbName, object, lasterr) - end - end - catch - % never mind... - end - %setappdata(src,'inCallback',[]); % used to prevent endless recursion % can't use setappdata(src,...) because it fails on R2010b!!! - hash.remove(src); -%end % tbCallbacksChanged - -%% Revert Callback table modification -function revertCbTableModification(table, modifiedRowIdx, modifiedColIdx, cbName, object, errMsg) %#ok - try - % Display a notification MsgBox - msg = 'Callbacks must be a ''string'', or a @function handle'; - if ~iscom(object(1)), msg = [msg ' or a {@func,args...} construct']; end - if ~isempty(errMsg), msg = {errMsg, '', msg}; end - msgbox(msg, ['Error setting ' cbName ' value'], 'warn'); - - % Revert to the current value - curValue = ''; - try - if ~iscom(object(1)) - curValue = charizeData(get(object(1),cbName)); - else - cbs = object(1).eventlisteners; - if ~isempty(cbs) - cbs = cbs(strcmpi(cbs(:,1),cbName),:); - curValue = charizeData(cbs(1,2)); - end - end - catch - % never mind... - clear the current value - end - table.setValueAt(curValue, modifiedRowIdx, modifiedColIdx); - pause(0.05); % enable the table change to register and the callback to be ignored - catch - % never mind... - end -%end % revertCbTableModification - -%% Hyperlink to new uiinspector upon table hyperlink change -function tbMousePressed(src, evd) - % exit if invalid handle - if ~ishandle(src) % || length(dbstack)>1 %exit also if not called from user action - return; - end - - try - tableObj = evd.getComponent; % =src.java - selectedRowIdx = tableObj.getSelectedRow; - selectedColumnIdx = tableObj.getSelectedColumn; - if selectedRowIdx<0 || selectedColumnIdx<0 - return; % sanity check - prevents error message in case of right-click on unselected table - end - cellData = char(tableObj.getValueAt(selectedRowIdx,selectedColumnIdx)); - [a,b,c,d,e] = regexp(cellData,'">([^<]*)'); %#ok a-d are unused - classes = unique([e{:}]); - if iscell(classes) - cellfun(@uiinspect,classes); - elseif ~isempty(classes) - uiinspect(classes) - end - catch - % never mind... - disp(lasterr) - end -%end % tbMousePressed - -%% Update pointer to hand over hyperlinks -function tbMouseMoved(src, evd) - % exit if invalid handle - if ~ishandle(src) % || length(dbstack)>1 %exit also if not called from user action - return; - end - - try - tableObj = evd.getComponent; % =src.java - point = java.awt.Point(evd.getX, evd.getY); - selectedRowIdx = tableObj.originalRowAtPoint(point); - selectedColumnIdx = tableObj.originalColumnAtPoint(point); - cellData = char(tableObj.getValueAt(selectedRowIdx,selectedColumnIdx)); - if isempty(strfind(cellData,'')) - tableObj.setCursor([]); - else - tableObj.setCursor(java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); - end - catch - % never mind... - %lasterr - end -%end % tbMouseMoved - -%% Update component property upon properties table data change -function tbPropChanged(src, evd) - % exit if invalid handle - if ~ishandle(src) % || length(dbstack)>1 %exit also if not called from user action - return; - end - - % Update the object's property with the modified value - modifiedColIdx = evd.getColumn; - modifiedRowIdx = evd.getFirstRow; - if modifiedRowIdx>=0 && modifiedColIdx>=0 %sanity check - should always be true - table = evd.getSource; - try - ud = get(src,'userdata'); - catch - ud = getappdata(src,'userdata'); - end - object = ud.obj; - inspectorTable = ud.inspectorTable; - propName = strtrim(table.getValueAt(modifiedRowIdx,0)); - propName = strrep(propName,'',''); - propName = strrep(propName,'',''); - try - propValue = strtrim(table.getValueAt(modifiedRowIdx,modifiedColIdx)); - if ~isempty(propValue) && ismember(propValue(1),'{[@''') - propValue = eval(propValue); - end - for objIdx = 1 : length(object) - set(object(objIdx), propName, propValue); - end - catch - errMsg = lasterr; - errMsg(errMsg==13) = []; - errMsg(errMsg==9) = ' '; - msg = {errMsg, '', ... - 'Values are interpreted as strings except if enclosed by square brackets [] or curly braces {}', ... - '', 'Even simple boolean/numeric values need to be enclosed within [] brackets', ... - 'For example: [0] or: [pi]'}; - msgbox(msg,['Error setting ' regexprep(propName,'<[^>]*>','') ' property'],'error'); - try - % Revert to the current value (temporarily disable this callback to prevent recursion) - curValue = charizeData(get(object(1),propName)); - set(handle(table,'CallbackProperties'), 'TableChangedCallback',[]); - table.setValueAt(curValue, modifiedRowIdx, modifiedColIdx); - set(handle(table,'CallbackProperties'), 'TableChangedCallback',@tbPropChanged); - catch - % never mind... - end - end - %pause(0.2); awtinvoke(inspectorTable,'repaint(J)',2000); % not good enough... - start(timer('TimerFcn',{@repaintInspector,inspectorTable},'StartDelay',2)); - end -%end % tbPropChanged - -%% Repaint inspectorTable following a property modification -function repaintInspector(timerObj, timerData, inspectorTable) %#ok partially unused - try inspectorTable.repaint; catch, end -%end % repaintInspector - -%% Get an HTML representation of the object's properties -function dataFieldsStr = getPropsHtml(obj, dataFields) - try - % Get a text representation of the fieldnames & values - undefinedStr = ''; - hiddenStr = ''; - dataFieldsStr = ''; % just in case the following croaks... - if isempty(dataFields) - return; - end - %oldVal = get(0,'HideUndocumented'); - %set(0,'HideUndocumented','off'); - dataFieldsStr = evalc('disp(dataFields)'); - %set(0,'HideUndocumented',oldVal); - if dataFieldsStr(end)==char(10), dataFieldsStr=dataFieldsStr(1:end-1); end - - % Strip out callbacks - dataFieldsStr = regexprep(dataFieldsStr,'^\s*\w*Callback(Data)?:[^\n]*$','','lineanchors'); - - % Strip out internal HG2 mirror properties - dataFieldsStr = regexprep(dataFieldsStr,'^\s*\w*_I:[^\n]*$','','lineanchors'); - dataFieldsStr = regexprep(dataFieldsStr,'\n\n','\n'); - - % Sort the fieldnames - try - [a,b,c,d] = regexp(dataFieldsStr,'(\w*): '); - fieldNames = strrep(d,': ',''); - catch - fieldNames = fieldnames(dataFields); - end - try - [fieldNames, sortedIdx] = sort(fieldNames); - s = strsplit(dataFieldsStr, sprintf('\n'))'; - dataFieldsStr = strjoin(s(sortedIdx), sprintf('\n')); - catch - % never mind... - ignore, leave unsorted - end - - % HTMLize tooltip data - % First, set the fields' font based on its read-write status - try - % ensure this is a Matlab handle, not a java object - obj = handle(obj, 'CallbackProperties'); - catch - try - % HG handles don't allow CallbackProperties... - obj = handle(obj); - catch - % Some Matlab class objects simply cannot be converted into a handle() - end - end - for fieldIdx = 1 : length(fieldNames) - thisFieldName = fieldNames{fieldIdx}; - try - hProp = findprop(obj,thisFieldName); - accessFlags = get(hProp,'AccessFlags'); - visible = get(hProp,'Visible'); - catch - accessFlags = []; - visible = 'on'; - try if hProp.Hidden, visible='off'; end, catch, end - end - if (~isempty(hProp) && isprop(hProp,'SetAccess') && isequal(hProp.SetAccess,'public')) || ... % isequal(...'public') and not strcmpi(...) because might be a cell array of classes - (~isempty(accessFlags) && isfield(accessFlags,'PublicSet') && strcmpi(accessFlags.PublicSet,'on')) - % Bolden read/write fields - thisFieldFormat = ['' thisFieldName ':$2']; - elseif (isempty(hProp) || ~isprop(hProp,'SetAccess')) && ... - (isempty(accessFlags) || ~isfield(accessFlags,'PublicSet')) - % Undefined - probably a Matlab-defined field of com.mathworks.hg.peer.FigureFrameProxy... - thisFieldFormat = ['' thisFieldName ':$2']; - undefinedStr = ', undefined'; - else % PublicSet=='off' - % Gray-out & italicize any read-only fields - thisFieldFormat = ['' thisFieldName ':$2']; - end - if strcmpi(visible,'off') - %thisFieldFormat = ['' thisFieldFormat '']; %#ok - thisFieldFormat = regexprep(thisFieldFormat, {'(.*):(.*)','<.?b>'}, {'$1:$2',''}); %'(.*):(.*)', '$1:$2'); - hiddenStr = ', hidden'; - end - dataFieldsStr = regexprep(dataFieldsStr, ['([\s\n])' thisFieldName ':([^\n]*)'], ['$1' thisFieldFormat]); - end - catch - % never mind... - probably an ambiguous property name - disp(lasterr); rethrow(lasterror) - end - - try - % Method 1: simple
list - %dataFieldsStr = strrep(dataFieldsStr,char(10),' 
  '); - - % Method 2: 2x2-column - dataFieldsStr = regexprep(dataFieldsStr, '^\s*([^:]+:)([^\n]*)\n^\s*([^:]+:)([^\n]*)$', '', 'lineanchors'); - dataFieldsStr = regexprep(dataFieldsStr, '^[^<]\s*([^:]+:)([^\n]*)$', '', 'lineanchors'); - dataFieldsStr = ['(documented' undefinedStr hiddenStr ' & read-only fields)

  

 $1 $2    $3 $4 
 $1 $2  
' dataFieldsStr '
']; - catch - % never mind - bail out (Maybe matlab 6 that does not support regexprep?) - disp(lasterr); rethrow(lasterror) - end -%end % getPropsHtml - -%% Update tooltip string with an object's properties data -function dataFields = updateObjTooltip(obj, uiObject) - try - if ischar(obj) - toolTipStr = obj; - else - toolTipStr = builtin('class',obj); - end - dataFields = struct; % empty struct - dataFieldsStr = ''; - hgStr = ''; - - % Add HG annotation if relevant - if ishghandle(obj) - hgStr = ' HG Handle'; - end - - % Note: don't bulk-get because (1) not all properties are returned & (2) some properties cause a Java exception - % Note2: the classhandle approach does not enable access to user-defined schema.props - ch = classhandle(handle(obj)); - dataFields = []; - [sortedNames, sortedIdx] = sort(get(ch.Properties,'Name')); - oldWarn1 = warning('off','MATLAB:hg:JavaSetHGProperty'); - oldWarn2 = warning('off','MATLAB:hg:Root'); - for idx = 1 : length(sortedIdx) - sp = ch.Properties(sortedIdx(idx)); - % TODO: some fields (see EOL comment below) generate a Java Exception from: com.mathworks.mlwidgets.inspector.PropertyRootNode$PropertyListener$1$1.run - if strcmp(sp.AccessFlags.PublicGet,'on') % && ~any(strcmp(sp.Name,{'FixedColors','ListboxTop','Extent'})) - try - dataFields.(sp.Name) = get(obj, sp.Name); - catch - dataFields.(sp.Name) = 'Error!'; - end - else - dataFields.(sp.Name) = '(no public getter method)'; - end - end - warning(oldWarn2); - warning(oldWarn1); - dataFieldsStr = getPropsHtml(obj, dataFields); - catch - % Probably a non-HG java object - try - % Note: the bulk-get approach enables access to user-defined schema-props, but not to some original classhandle Properties... - try - oldWarn3 = warning('off','MATLAB:structOnObject'); - warning off MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame - dataFields = struct(obj); - warning(oldWarn3); - catch - dataFields = get(obj); - end - dataFieldsStr = getPropsHtml(obj, dataFields); - catch - % Probably a missing property getter implementation - try - % Inform the user - bail out on error - err = lasterror; - if ~ischar(obj) - dataFieldsStr = ['

' strrep(err.message, char(10), '
')]; - else - dataFieldsStr = '

Cannot inspect fields of class names - only of objects'; - end - catch - % forget it... - end - end - end - - % Set the object tooltip - if ~isempty(dataFieldsStr) - toolTipStr = [' ' char(toolTipStr) '' hgStr ': ' dataFieldsStr '']; - end - uiObject.setToolTipText(toolTipStr); -%end % updateObjTooltip - -%% Check for existence of a newer version -function checkVersion() - try - % If the user has not indicated NOT to be informed - if ~ispref(mfilename,'dontCheckNewerVersion') - - % Get the latest version date from the File Exchange webpage - baseUrl = 'http://www.mathworks.com/matlabcentral/fileexchange/'; - fexId = '17935'; - webUrl = [baseUrl fexId]; % 'loadFile.do?objectId=' fexId]; - webPage = urlread(webUrl); - modIdx = strfind(webPage,'>Updates<'); - if ~isempty(modIdx) - webPage = webPage(modIdx:end); - % Note: regexp hangs if substr not found, so use strfind instead... - %latestWebVersion = regexprep(webPage,'.*?>(20[\d-]+).*','$1'); - dateIdx = strfind(webPage,'class="date">'); - if ~isempty(dateIdx) - latestDate = webPage(dateIdx(end)+13 : dateIdx(end)+23); - try - startIdx = dateIdx(end)+27; - descStartIdx = startIdx + strfind(webPage(startIdx:startIdx+999),''); - descEndIdx = startIdx + strfind(webPage(startIdx:startIdx+999),''); - descStr = webPage(descStartIdx(1)+3 : descEndIdx(1)-2); - descStr = regexprep(descStr,'',''); - catch - descStr = ''; - end - - % Get this file's latest date - thisFileName = which(mfilename); %#ok - try - thisFileData = dir(thisFileName); - try - thisFileDatenum = thisFileData.datenum; - catch % old ML versions... - thisFileDatenum = datenum(thisFileData.date); - end - catch - thisFileText = evalc('type(thisFileName)'); - thisFileLatestDate = regexprep(thisFileText,'.*Change log:[\s%]+([\d-]+).*','$1'); - thisFileDatenum = datenum(thisFileLatestDate,'yyyy-mm-dd'); - end - - % If there's a newer version on the File Exchange webpage (allow 2 days grace period) - if (thisFileDatenum < datenum(latestDate,'dd mmm yyyy')-2) - - % Ask the user whether to download the newer version (YES, no, no & don't ask again) - msg = {['A newer version (' latestDate ') of ' mfilename ' is available on the MathWorks File Exchange:'], '', ... - ['\color{blue}' descStr '\color{black}'], '', ... - 'Download & install the new version?'}; - createStruct.Interpreter = 'tex'; - createStruct.Default = 'Yes'; - answer = questdlg(msg,mfilename,'Yes','No','No & never ask again',createStruct); - switch answer - case 'Yes' % => Yes: download & install newer file - try - %fileUrl = [baseUrl '/download.do?objectId=' fexId '&fn=' mfilename '&fe=.m']; - fileUrl = [baseUrl '/' fexId '?controller=file_infos&download=true']; - %contents = urlread(fileUrl); - %contents = regexprep(contents,[char(13),char(10)],'\n'); %convert to OS-dependent EOL - %fid = fopen(thisFileName,'wt'); - %fprintf(fid,'%s',contents); - %fclose(fid); - [fpath,fname,fext] = fileparts(thisFileName); - zipFileName = fullfile(fpath,[fname '.zip']); - urlwrite(fileUrl,zipFileName); - unzip(zipFileName,fpath); - rehash; - catch - % Error downloading: inform the user - msgbox(['Error in downloading: ' lasterr], mfilename, 'warn'); - web(webUrl); - end - case 'No & never ask again' % => No & don't ask again - setpref(mfilename,'dontCheckNewerVersion',1); - otherwise - % forget it... - end - end - end - else - % Maybe webpage not fully loaded or changed format - bail out... - end - end - catch - % Never mind... - end -%end % checkVersion - -%% Debuggable "quiet" error-handling -function dispError - err = lasterror; - msg = err.message; - for idx = 1 : length(err.stack) - filename = err.stack(idx).file; - if ~isempty(regexpi(filename,mfilename)) - funcname = err.stack(idx).name; - line = num2str(err.stack(idx).line); - msg = [msg ' at ' funcname ' line #' line '']; %#ok grow - break; - end - end - disp(msg); - return; % debug point -%end % dispError - - -%%%%%%%%%%%%%%%%%%%%%%%%%% TODO %%%%%%%%%%%%%%%%%%%%%%%%% -% - Enh: Cleanup internal functions, remove duplicates etc. -% - Enh: link property objects to another uiinspect window for these objects -% - Enh: display object children (& link to them) - COM/Java -% - Enh: find a way to merge the other-properties table into the inspector table -% - Enh: find a way to use the inspector without disabling dbstop if error -% - Fix: some fields generate a Java Exception from: com.mathworks.mlwidgets.inspector.PropertyRootNode$PropertyListener$1$1.run -% - Fix: using the "Hide standard callbacks" checkbox sometimes issues Java Exceptions on the console -% - Fix: In HG tree view, sometimes the currently-inspected handle is not automatically selected diff --git a/general functions/uiinspect.zip b/general functions/uiinspect.zip deleted file mode 100644 index 46ba135..0000000 Binary files a/general functions/uiinspect.zip and /dev/null differ diff --git a/general functions/viewClassTree.m b/general functions/viewClassTree.m deleted file mode 100644 index da661f6..0000000 --- a/general functions/viewClassTree.m +++ /dev/null @@ -1,99 +0,0 @@ -function viewClassTree(directory) -% View a class inheritence hierarchy. All classes residing in the directory -% or any subdirectory are discovered. Parents of these classes are also -% discovered as long as they are in the matlab search path. -% There are a few restrictions: -% (1) classes must be written using the new 2008a classdef syntax -% (2) classes must reside in their own @ directories. -% (3) requires the bioinformatics biograph class to display the tree. -% (4) works only on systems that support 'dir', i.e. windows. -% -% directory is an optional parameter specifying the directory one level -% above all of the @ class directories. The current working -% directory is used if this is not specified. -%Written by Matthew Dunham - - - -if nargin == 0 - directory = '.'; -end - - -info = dirinfo(directory); -baseClasses = vertcat(info.classes); - -if(isempty(baseClasses)) - fprintf('\nNo classes found in this directory.\n'); - return; -end - -allClasses = baseClasses; -for c=1:numel(baseClasses) - allClasses = union(allClasses,ancestors(baseClasses{c})); -end - -matrix = zeros(numel(allClasses)); -map = struct; -for i=1:numel(allClasses) - map.(allClasses{i}) = i; -end - -for i=1:numel(allClasses) - try - meta = eval(['?',allClasses{i}]); - parents = meta.SuperClasses; - catch ME - warning('CLASSTREE:discoveryWarning',['Could not discover information about class ',allClasses{i}]); - continue; - end - for j=1:numel(parents) - matrix(map.(allClasses{i}),map.(parents{j}.Name)) = 1; - end -end - -for i=1:numel(allClasses) - allClasses{i} = ['@',allClasses{i}]; -end - - - -view(biograph(matrix,allClasses)); - - - -function info = dirinfo(directory) -%Recursively generate an array of structures holding information about each -%directory/subdirectory beginning, (and including) the initially specified -%parent directory. - info = what(directory); - flist = dir(directory); - dlist = {flist([flist.isdir]).name}; - for i=1:numel(dlist) - dirname = dlist{i}; - if(~strcmp(dirname,'.') && ~strcmp(dirname,'..')) - info = [info, dirinfo([directory,'\',dirname])]; - end - end -end - -function list = ancestors(class) -%Recursively generate a list of all of the superclasses, (and superclasses -%of superclasses, etc) of the specified class. - list = {}; - try - meta = eval(['?',class]); - parents = meta.SuperClasses; - catch - return; - end - for p=1:numel(parents) - if(p > numel(parents)),continue,end %bug fix for version 7.5.0 (2007b) - list = [parents{p}.Name,ancestors(parents{p}.Name)]; - end -end - - - - -end \ No newline at end of file diff --git a/general functions/windowedFFT.m b/general functions/windowedFFT.m deleted file mode 100644 index 81956c2..0000000 --- a/general functions/windowedFFT.m +++ /dev/null @@ -1,86 +0,0 @@ -function [pSig,fSig,tSig]=windowedFFT(V,Fs,win,OL,varargin) -%[pSig,fSig,tSig]=windowedFFT(V,Fs,win,OL,varargin) -% Function purpose : Calculates the fourier transform in consecutive/overlapping time windows -% -% Recives : V - the input signal -% Fs - sampling frequency [Hz] -% win - window in time units [s]. -% OL - overlap [s] -% Options/varargin (format - 'option',value) -% FORCE_POWER2_SEQUENCES - optimize input windows to be an integer power of two in length -% NORMALIZATION - normalize spectrum in every window - -% 0=no normalization, -% 1=normalize to the fft sum, -% 2=normalize to the singal square amplitude -% 3=normalize to the numner of samples N -% 4=normalize to the square of samples N^2 -% METHOD - method for power spectrum estimation - 'FFT','MatlabPeriodogram','MatlabWelch' -% -% Gives back: pSig - the power spectrum in time windows -% fSig - the frequencies corresponding to the power spectrum -% tSig - the timing of each window [s] -% -% Recomended usage : -% Last updated : 13/11/2012 - -%paramters -FORCE_POWER2_SEQUENCES=0; -NORMALIZATION=0; -METHOD='FFT'; -%collect input arguments -for i=1:2:length(varargin) - eval([varargin{i} '=' 'varargin{i+1};']); -end - -nSamples=length(V); -%check that window contains an integer number of samples -if win*Fs~=round(win*Fs) - win=round(win*Fs)/Fs; - disp(['!!!Window size was changed to: ' num2str(win)]); -end -samplesWin=win*Fs; -%check that window overlap contains an integer number of samples -if OL*Fs~=round(OL*Fs) - OL=round(OL*Fs)/Fs; - disp(['!!!Window overlap was changed to: ' num2str(OL)]); -end -samplesOL=OL*Fs; -%Examine is window is an equal power of two -if FORCE_POWER2_SEQUENCES - win=2^round(log2(win)); - OL=2^round(log2(OL)); - disp(['!!!The window size was changed to: ' num2str(win) ' and overlap to ' num2str(OL)]); -else - if (2^floor(log2(win)))~=win && round(nSamples/OL)~=(nSamples/OL) - disp('!!!Input data vector is not of 2^N length (N=1,2,3,...)'); - end -end - -%buffering data into windows -[bufferedV,residualSamples] = buffer(V,samplesWin,samplesOL,'nodelay'); -nWindows=size(bufferedV,2); - -%generating hamming window -HammingWindow=hamming(samplesWin,'periodic')'; -HammingWindow=HammingWindow/sum(HammingWindow); - -[pSig,fSig,m0]=FourierAnalysis((HammingWindow'*ones(1,nWindows)).*bufferedV,Fs,'plotResults',0,'method',METHOD); -nFFT=length(fSig); -switch NORMALIZATION - case 0 - case 1 - pSig=pSig./(ones(nFFT,1)*sum(pSig)); - case 2 - pSig=pSig./(ones(nFFT,1)*sum(bufferedV.^2)); - case 3 - pSig=pSig/samplesWin; - case 4 - pSig=pSig/(samplesWin.^2); - case 5 - pSig=pSig./(ones(nFFT,1)*((m0)./(samplesWin.^2))); -end - -if nargin>=3 - tSig=(round(samplesWin/2):(samplesWin-samplesOL):(nSamples-samplesWin+samplesOL))/Fs; -end - diff --git a/general functions/xcorrmat.m b/general functions/xcorrmat.m deleted file mode 100644 index bde256e..0000000 --- a/general functions/xcorrmat.m +++ /dev/null @@ -1,25 +0,0 @@ -function [R,lags]=xcorrmat(X,Y,lag) -% R=xcorrmat(X,Y,lag) -% Function purpose : Calculated the peason normalized cross correlation for 2 sets of vectors -% -% Function recives : X [N x M] - matrix 1 containning M vectors where N is the length of the vectors -% Y [N x M] - matrix 2 containning M vectors where N is the length of the vectors -% lag [1 x 1] - the lag for cross corr calculation -% -% Function give back : R [1 x M]- cross correlation array -% -% Last updated : 23/07/14 -[N,M]=size(X); -if nargin==2 - lag=N-1; -end -if nargout==2 - lags=-lag:lag; -end - -R = real(ifft(fft(X,2^nextpow2(2*N-1)) .* conj(fft(Y,2^nextpow2(2*N-1))))); %convolution in fft space -R = [R(end-lag+1:end,:);R(1:lag+1,:)]; %fft shift -R = bsxfun(@rdivide,R,sqrt(sum(abs(X.^2)).*sum(abs(Y.^2)))); %according to Parseval's theorem - -%R=xcorr(X(:,1),Y(:,1),lag,'coeff'); -%plot(R);hold on;plot(R(:,1),'or'); diff --git a/imageProcessing/mriViewer.fig b/imageProcessing/mriViewer.fig index ae904d3..043f16d 100644 Binary files a/imageProcessing/mriViewer.fig and b/imageProcessing/mriViewer.fig differ diff --git a/imageProcessing/mriViewer.m b/imageProcessing/mriViewer.m index f53d113..486a38c 100644 --- a/imageProcessing/mriViewer.m +++ b/imageProcessing/mriViewer.m @@ -22,7 +22,7 @@ % Edit the above text to modify the response to help mriViewer -% Last Modified by GUIDE v2.5 02-Jan-2013 18:07:31 +% Last Modified by GUIDE v2.5 27-Sep-2023 19:10:12 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; @@ -48,8 +48,9 @@ function mriViewer_OpeningFcn(hObject, eventdata, handles, varargin) handles.output = hObject; if nargin<4 - addpath('/media/sil2/Experimental/Reptile anatomy data/TurtleMRIs/'); + addpath('/media/sil1/Data/MRI'); load turtle03_5_mriViewerData; + %load PogonaMRI_Matlab.mat; %load turtle03_5_Reduced_mriViewerData %load turtle03_5_ReducedOnlyBrain_mriViewerData; handles.data=turtleMRI; @@ -172,10 +173,14 @@ function mriViewer_OpeningFcn(hObject, eventdata, handles, varargin) %sliceImg(pValid) = interp3(handles.data,Y(pValid),X(pValid),Z(pValid),'linear'); sliceImg=sliceImg(handles.gui.minValidI:handles.gui.maxValidI,handles.gui.minValidJ:handles.gui.maxValidJ); - - %update mri slice plot axes(handles.imagePlot); - imagesc(flipud(sliceImg)); + if handles.norm3Std.Value + tmp=sort(sliceImg(:)); + imagesc(flipud(sliceImg),[tmp(round(numel(tmp)*0.01)) tmp(round(numel(tmp)*0.99))]); + else + imagesc(flipud(sliceImg)); + end + %update mri slice plot axis image; disp('Finished calculating interpolation'); else @@ -184,7 +189,9 @@ function mriViewer_OpeningFcn(hObject, eventdata, handles, varargin) case 1 net = denoisingNetwork('DnCNN'); I=denoiseImage(rot90(squeeze(handles.data(handles.gui.frameNumber,:,:))),net); - handles.gui.p1=imagesc(I,[0 10000]); + tmp=sort(I(:)); + handles.gui.p1=imagesc(I,[tmp(round(numel(tmp)*0.01)) tmp(round(numel(tmp)*0.99))]); + %handles.gui.p1=imagesc(rot90(squeeze(handles.data(handles.gui.frameNumber,:,:))),[0 10000]); %colormap(gca,'jet'); %colorbar; @@ -469,3 +476,12 @@ function interpolationMenu_CreateFcn(hObject, eventdata, handles) if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end + + +% --- Executes on button press in norm3Std. +function norm3Std_Callback(hObject, eventdata, handles) +% hObject handle to norm3Std (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hint: get(hObject,'Value') returns toggle state of norm3Std diff --git a/imageProcessing/rotationmat3D.m b/imageProcessing/rotationmat3D.m new file mode 100644 index 0000000..1d8d535 --- /dev/null +++ b/imageProcessing/rotationmat3D.m @@ -0,0 +1,55 @@ +function R= rotationmat3D(r,Axis) +%function R= rotationmat3D(radians,Axis) +% +% creates a rotation matrix such that R * x +% operates on x by rotating x around the origin r radians around line +% connecting the origin to the point "Axis" +% +% example: +% rotate around a random direction a random amount and then back +% the result should be an Identity matrix +% +%r = rand(4,1); +%rotationmat3D(r(1),[r(2),r(3),r(4)]) * rotationmat3D(-r(1),[r(2),r(3),r(4)]) +% +% example2: +% rotate around z axis 45 degrees +% Rtest = rotationmat3D(pi/4,[0 0 1]) +% +%Bileschi 2009 + +if nargin == 1 + if(length(rotX) == 3) + rotY = rotX(2); + rotZ = rotZ(3); + rotX = rotX(1); + end +end + +% useful intermediates +L = norm(Axis); +if (L < eps) + error('axis direction must be non-zero vector'); +end +Axis = Axis / L; +L = 1; +u = Axis(1); +v = Axis(2); +w = Axis(3); +u2 = u^2; +v2 = v^2; +w2 = w^2; +c = cos(r); +s = sin(r); +%storage +R = nan(3); +%fill +R(1,1) = u2 + (v2 + w2)*c; +R(1,2) = u*v*(1-c) - w*s; +R(1,3) = u*w*(1-c) + v*s; +R(2,1) = u*v*(1-c) + w*s; +R(2,2) = v2 + (u2+w2)*c; +R(2,3) = v*w*(1-c) - u*s; +R(3,1) = u*w*(1-c) - v*s; +R(3,2) = v*w*(1-c)+u*s; +R(3,3) = w2 + (u2+v2)*c; diff --git a/spikeSorting/._makeConfigKiloSort2.m b/spikeSorting/._makeConfigKiloSort2.m deleted file mode 100644 index 20b90a3..0000000 Binary files a/spikeSorting/._makeConfigKiloSort2.m and /dev/null differ diff --git a/spikeSorting/@gridSorter/.gitattributes b/spikeSorting/@gridSorter/.gitattributes deleted file mode 100644 index bdb0cab..0000000 --- a/spikeSorting/@gridSorter/.gitattributes +++ /dev/null @@ -1,17 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.cs diff=csharp - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/spikeSorting/@gridSorter/.gitignore b/spikeSorting/@gridSorter/.gitignore deleted file mode 100644 index cd2946a..0000000 --- a/spikeSorting/@gridSorter/.gitignore +++ /dev/null @@ -1,47 +0,0 @@ -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# ========================= -# Operating System Files -# ========================= - -# OSX -# ========================= - -.DS_Store -.AppleDouble -.LSOverride - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk diff --git a/spikeSorting/@gridSorter/SpikeTempDiffMerging.m b/spikeSorting/@gridSorter/SpikeTempDiffMerging.m deleted file mode 100644 index 7a9085f..0000000 --- a/spikeSorting/@gridSorter/SpikeTempDiffMerging.m +++ /dev/null @@ -1,48 +0,0 @@ -function [clusterMerged,Merge]=SpikeTempDiffMerging(spikeShapes,Clusters,Templates,crit) -%merge clusters in a group that have to be merge based on the residuals between spikes and templates. -%synthax : [clusterMerged,Merge]=SpikeTempDiffMerging(spikeShapes,Clusters,Templates,crit) -%input: -% - spikeShapes : all the spikeShapes Nspikes-sizeSpike-NbChannels -% - Clusters : vector containing the index of spikes in spikeShapes -% - Templates : The templates corresponding to the clusters -% nChannels-sizeTemplate-nTemplates -% - crit : the value of the threshold to merge clusters(default value : 1.5) -%output : -% - clusterMerged:vector of symbolic merging -% - Merge : binary symmetric merging decision matrix -% nclust-nclust. -if nargin<4 - crit=1.5; -end -numClust=size(Templates,3); -clusterMerged=1:numClust; % a group is assigned to every cluster -%build ajacent matrix of clusters -Merge=zeros(numClust,numClust); -for i=1:numClust - for j=1:numClust - if j~=i - clSel=find(Clusters==i); - cTmp1=Templates(:,:,i)'; - cTmp2=Templates(:,:,j)'; - diffSpikeTemp1=zeros(1,length(clSel));diffSpikeTemp2=zeros(1,length(clSel)); - for k=1:length(clSel) - cSpike=reshape(spikeShapes(clSel(k),:,:),size(spikeShapes,2),size(spikeShapes,3)); - diffSpikeTemp1(k)=sum((cTmp1(:)-cSpike(:)).^2); - diffSpikeTemp2(k)=sum((cTmp2(:)-cSpike(:)).^2); - end - Merge(i,j)=median(diffSpikeTemp2)/median(diffSpikeTemp1); - end - end -end - -%Symetrize matrix -for k=1:numClust - for m=k+1:numClust - if Merge(k,m)thr_dist_min & spikeFeatures(:,j) 10; - [ksstat]=test_ks(aux); - sd(j)=ksstat; - else - sd(j)=0; - end - end - [~,tmp1]=sort(sd(1:nCoeffs),'descend'); - [~,tmp2]=sort(sd(nCoeffs+1:end),'descend'); - spikeFeatures=spikeFeatures(:,[tmp1(1:obj.featuresNWaveletCoeff/2) nCoeffs+tmp2(1:obj.featuresNWaveletCoeff/2)]); - - if obj.featuresReduceDimensionsWithPCA - [PCAsimMat,spikeFeatures] = princomp(spikeFeatures); %run PCA for visualization purposes - spikeFeatures=spikeFeatures(:,1:obj.featuresDimensionReductionPCA); - end - case 'PCA' %this option was tested and gives worse results than wavelets - spikeShapes=double(spikeShapes(:,:,pComN2-min(pComN2)+1)) .* detectionInt2uV; - [~,spikeFeatures] = princomp(reshape(permute(spikeShapes,[1 3 2]),[nSamples*numel(pComN2-min(pComN2)+1) nSpikes])); - spikeFeatures=spikeFeatures(1:obj.featuresDimensionReductionPCA,:)'; - end - - [time,spks,chan]=size(spikeShapes); - spikeShapes=reshape(permute(spikeShapes,[1 3 2]),chan*time,spks)'; - allSpikeFeatures=[allSpikeFeatures; spikeFeatures]; - allSpikeShapes=[allSpikeShapes; spikeShapes]; - clustLabel=[clustLabel; tAll{c}(1:skipSpikes:end,1:2)]; - - end - - %find the spikes of the current neuron - - iSpikeIndices=find(sum(clustLabel==repmat(ic(1:2,neuron),1,size(clustLabel,1))',2)==2); - iSpikeFeatures=allSpikeFeatures(iSpikeIndices,:); - iSpikeShapes=allSpikeShapes(iSpikeIndices,:); - - %take error estimates if there are some spikes to work with -if numel(iSpikeIndices)>obj.assessMinSpikeNum - - %load up thresholds, top point of peak channel to estimate the percent error estimate due to thresholding - %detectFile=matfile(obj.sortingFileNames.spikeDetectionFile{ic(1,neuron)}); - Th=detectFile.Th; - [x loc]=max(abs(mean(iSpikeShapes))); - spikeAmps=abs(iSpikeShapes(:,loc)); - - [p,mu,stdev,n,x] = undetected(spikeAmps,mean(Th)); - - fres3=p; % percent error estimate due to thresholding - - %look at overlap with spikes of surrounding units - confusion=[]; - %allCSpikeFeatures=[]; - allCSpikeLabels=[]; - allCSpikeIndices=[]; - surroundingTally=1; - channelUnits=unique(clustLabel(:,1)); - for c=1:numel(channelUnits) - if any(channelUnits(c)==obj.chPar.surChExtVec{ic(1,neuron)}(obj.chPar.pSurCh{ic(1,neuron)})) %don't look at spikes from units not in the surrounding grid - currChanUnit=clustLabel(find(clustLabel(:,1)==channelUnits(c)),:); - - for unit= unique(currChanUnit(:,2))' - if ~all([currChanUnit(1,1); unit]==ic(1:2,neuron)) %don't double count the unit - cSpikeIndices=find(sum(clustLabel==repmat([currChanUnit(1,1); unit],1,size(clustLabel,1))',2)==2); - cSpikeFeatures=allSpikeFeatures(cSpikeIndices,:); - - try - confusion(:,:,surroundingTally)=gaussOverlap(iSpikeFeatures,cSpikeFeatures); %fit gaussians to look at overlapping clusters - catch - confusion(:,:,surroundingTally)=[0 0 ; 0 0]; - end - allCSpikeLabels=[allCSpikeLabels; surroundingTally*ones(numel(cSpikeIndices),1)]; - allCSpikeIndices=[allCSpikeIndices; cSpikeIndices]; - surroundingTally=surroundingTally+1; - end - end - end - end - - if ~isempty(confusion) - fres2(1)=min([max(squeeze(confusion(1,1,:))),1]); fres2(2)=min([max(squeeze(confusion(2,2,:))),1]); % percent error estimate due to overlapping clusters - else - fres2=[0 0]; - end - er(neuron).fpos=fres2(1)*100; %total false positive rate, in percentage. The sum is super conservative, so I took the max - er(neuron).fneg=(fres2(2)+fres3)*100; %total false negative rate, in percentage - % er.fres1=fres1*100; %contamination false positives due to refractory violations - er(neuron).fres2=fres2*100; %false pos and false neg due to proximity of neighboring clusters - er(neuron).fres3=fres3*100; %false negatives due to spikes falling below threshold - er(neuron).performed=1; - -else - er(neuron).fpos=100; %total false positive rate, in percentage. The sum is super conservative, so I took the max - er(neuron).fneg=100; %total false negative rate, in percentage - % er.fres1=fres1*100; %contamination false positives due to refractory violations - er(neuron).fres2=100; %false pos and false neg due to proximity of neighboring clusters - er(neuron).fres3=100; %false negatives due to spikes falling below threshold - er(neuron).performed=0; -end - - - matObj.er= er; - - %% plot stuff for assessment - if ~exist(['neur_' int2str(neuron) 'qualityAssessment.jpg'])&&numel(iSpikeShapes)>obj.assessMinSpikeNum - numChan=numel(obj.chPar.pSurCh{ic(1,neuron)}); - numDataPts=size(allWaveforms,1); - rowSize=surroundingTally+2; - columnSize=2; - - f=figure; - positionVec=[.05, 1-(2/rowSize), 1/columnSize-0.05, 1/rowSize]; - h=subplot('position',positionVec); - hold on - plot(mean(iSpikeShapes)) - - ylim([min(mean(iSpikeShapes)) max(mean(iSpikeShapes))]) - xlim([0 size(iSpikeShapes,2)]) - for ch=1:numChan - line([numDataPts*ch numDataPts*ch],[min(mean(iSpikeShapes)) max(mean(iSpikeShapes))],'color','k') - end - line([0 numDataPts*numChan],[mean(Th) mean(Th)],'color','r') - - set(h,'xtick',[]) - set(h,'xticklabel',[]) - ylabel('uV') - - %display the quality assessment and isi plots in top right - positionVec=[1/columnSize, 1-(2/rowSize), 1/(columnSize*2)-0.05, 1/rowSize]; - h=subplot('position',positionVec); - hold on - text(.010,.8,['false pos: ' int2str(er(neuron).fpos) '%'],'Units','normalized') - text(.010,.5,['false neg: ' int2str(er(neuron).fneg) '%'],'Units','normalized') - text(.010,.2,['thresh errors: ' int2str(er(neuron).fres3) '%'],'Units','normalized') - % text(.8,.8,[int2str(size(iSpikeShapes,1)) ' spikes'],'Units','normalized')% - set(h,'xtick',[]) - set(h,'xticklabel',[]) - set(h,'ytick',[]) - set(h,'yticklabel',[]) - - positionVec=[1.5*(1/columnSize)+0.05, 1-(2/rowSize), 1/(columnSize*2)-0.1, 1/rowSize]; - h=subplot('position',positionVec); - hold on - plot(0:0.01:1,histc(diff(t(ic(3,neuron):ic(4,neuron))),0:0.01:1)) - title('ISI histogram (0:1 ms)') - ylabel('spikes') - set(h,'xtick',[]) - set(h,'xticklabel',[]) - - if surroundingTally>=1 - for unit=1:(surroundingTally-1) - cSpikeIndices=allCSpikeIndices(find(allCSpikeLabels==unit)); - cSpikeShapes=allSpikeShapes(cSpikeIndices,:); - - positionVec=[.05, 1-((2+unit)/rowSize), 1/columnSize-0.05, 1/rowSize]; - h=subplot('position',positionVec); - plot(mean(cSpikeShapes),'r') - for c=1:numChan - line([numDataPts*c numDataPts*c],[min(mean(iSpikeShapes)) max(mean(iSpikeShapes))],'color','k') - end - ylim([min(mean(iSpikeShapes)) max(mean(iSpikeShapes))]) - xlim([0 numDataPts*numChan]) - set(h,'xtick',[]) - set(h,'xticklabel',[]) - set(h,'ytick',[]) - set(h,'yticklabel',[]) - - positionVec=[1/columnSize, 1-((2+unit)/rowSize), 1/columnSize-0.05, 1/rowSize]; - h=subplot('position',positionVec); - hold on - label=[ones(1,size(cSpikeShapes,1))+1 ones(1,size(iSpikeShapes,1))]; - relSpikes=[allSpikeFeatures(cSpikeIndices,:); iSpikeFeatures]; - - try - [redDimSpikes, x1] = lda(relSpikes, label, 2); - scatter( redDimSpikes(:,1),redDimSpikes(:,2),20,label,'filled') - - catch - end - y1=ylim; - x1=xlim; - line([x1(1) x1(2)],[y1(2) y1(2)],'color','k') - % text(.8,.8,[int2str(size(cSpikeShapes,1)) ' spikes'],'Units','normalized') - set(h,'xtick',[]) - set(h,'xticklabel',[]) - set(h,'ytick',[]) - set(h,'yticklabel',[]) - end - end - set(f,'units','normalized','outerposition',[.1 .1 .8 .8]) - printFile=[obj.sortingDir filesep 'neur_' int2str(neuron) 'qualityAssessment']; - set(f,'PaperPositionMode','auto'); - print(printFile,'-djpeg','-r300'); - close all - end - -end - -for x=1:size(er,2) - fpos(x)=er(x).fpos; - fneg(x)=er(x).fneg; - thresh(x)=er(x).fres3; -end - -figure -hist(thresh,30) -title('errors due to thresholding') -xlabel('error rate (%)') -ylabel('count') -xlim([0 100]) -figure -hist(fpos,30) -title('errors due to cluster overlap false positives') -xlabel('error rate (%)') -ylabel('count') -xlim([0 100]) -figure -hist(fneg-thresh,30) -title('errors due to cluster overlap false negatives') -xlabel('error rate (%)') -ylabel('count') -xlim([0 100]) - - - -% - - function [p,mu,stdev,n,x] = undetected(w,threshes) - % UltraMegaSort2000 by Hill DN, Mehta SB, & Kleinfeld D - 07/12/201 - %modified by Sam Reiter 7.4.2015 - - % Output: - % p - estimate of probability that a spike is missing because it didn't reach threshhold - % mu - mean estimated for gaussian fit - % stdev - standard deviation estimated for gaussian fit - % n - bin counts for histogram used to fit Gaussian - % x - bin centers for histogram used to fit Gaussian - % - bins=75; - % normalize all waveforms by threshold - w = abs(w); - w=w./ abs(threshes); - - - % create the histogram values - global_max = max(w); - mylims = linspace( 1,global_max,bins+1); - x = mylims + (mylims(2) - mylims(1))/2; - n = histc( w,mylims ); - - % fit the histogram with a cutoff gaussian - m = mode_guesser(w, .05); % use mode instead of mean, since tail might be cut off - [stdev,mu] = stdev_guesser(w, n, x, m); % fit the standard deviation as well - - % Now make an estimate of how many spikes are missing, given the Gaussian and the cutoff - p = normcdf( 1,mu,stdev); - - % attempt to keep values negative if all threshold values were negative - if all( threshes < 0 ) - mu = -mu; - x = -x; - end - - end - - - -% fit the standard deviation to the histogram by looking for an accurate -% match over a range of possible values - - function [stdev,m] = stdev_guesser( thresh_val, n, x, m) - % initial guess is juts the RMS of just the values below the mean - init = sqrt( mean( (m-thresh_val(thresh_val>=m)).^2 ) ); - - % try 20 values, within a factor of 2 of the initial guess - num = 20; - st_guesses = linspace( init/2, init*2, num ); - m_guesses = linspace( m-init,max(m+init,1),num); - for j = 1:length(m_guesses) - for k = 1:length(st_guesses) - b = normpdf(x,m_guesses(j),st_guesses(k)); - b = b *sum(n) / sum(b); - error(j,k) = sum(abs(b(:)-n(:))); - end - end - - % which one has the least error? - [val,pos] = min(error(:)); - jpos = mod( pos, num ); if jpos == 0, jpos = num; end - kpos = ceil(pos/num); - stdev = st_guesses(kpos); - - % refine mode estimate - m = m_guesses(jpos); - - end - - - function confusion = gaussOverlap( w1, w2 ) - % UltraMegaSort2000 by Hill DN, Mehta SB, & Kleinfeld D - 07/12/2010 - %modified by Sam Reiter 7.4.2015 - - % Input: - % waveforms1 - [Event x Sample ] waveforms of 1st cluster - % waveforms2 - [Event x Sample ] waveforms of 2nd cluster - % If your waveform data is in the form [Event X Sample X Channels ], - % you should call this function as - % confusion = gaussian_overlap( w1(:,:), w2(:,:) ); - % This will concatenate the waveforms from different channels. - % - % Output: - % C - a confusion matrix - % C(1,1) - False positive fraction in cluster 1 (waveforms of neuron 2 that were assigned to neuron 1) - % C(1,2) - False negative fraction in cluster 1 (waveforms of neuron 1 that were assigned to neuron 2) - % C(2,1) - False negative fraction in cluster 2 - % C(2,2) - False positive fraction in cluster 2 - % - - % fit 2 multivariate gaussians, use observed parameters to initialize - params.mu = [ mean(w1(:,:),1); mean(w2(:,:),1)]; - params.Sigma(:,:,1) = cov(w1(:,:)); - params.Sigma(:,:,2) = cov(w2(:,:)); - - % disp('Fitting 2-Gaussian Mixture Model ...') - gmfit = gmdistribution.fit([w1(:,:); w2(:,:)],2,'Start',params); - - % get posteriors - %disp('Calculating Confusion matrix ...') - pr1 = gmfit.posterior(w1); - pr2 = gmfit.posterior(w2); - - % in the unlikely case that the cluster identities were flipped during the fitting procedure, flip them back - if mean(pr1(:,1)) + mean(pr2(:,2)) < 1 - pr1 = pr1(:,[2 1]); - pr2 = pr2(:,[2 1]); - end - - % create confusion matrix - confusion(1,1) = mean(pr1(:,2)); % probability that a member of 1 is false - confusion(1,2) = sum(pr2(:,1))/size(w1,1); % relative proportion of spikes that were placed in cluster 2 by mistake - confusion(2,1) = sum(pr1(:,2))/size(w2,1); % relative proportion of spikes that were placed in cluster 1 by mistake - confusion(2,2) = mean(pr2(:,1)); % probability that a member of 2 was really from 1 - end - - - - function m = mode_guesser(x,p) - - % UltraMegaSort2000 by Hill DN, Mehta SB, & Kleinfeld D - 07/09/2010 - % - % mode_guesser - guess mode of the - % - % Usage: - % m = mode_guesser(x,p) - % - % Description: - % Guesses mode by looking for location where the data is most tightly - % distributed. This is accomplished by sorting the vector x and - % looking for the p*100 percentile range of data with the least range. - % - % Input: - % x - [1 x M] vector of scalars - % - % Option input: - % p - proportion of data to use in guessing the mode, defaults to 0.1 - % - % Output: - % m - guessed value of mode - % - - %check for whether p is specified - if nargin < 2, p = .1; end - - % determine how many samples is p proportion of the data - num_samples = length(x); - shift = round( num_samples * p ); - - % find the range of the most tightly distributed data - x = sort(x); - [val,m_spot] = min( x(shift+1:end) - x(1:end-shift) ); - - % use median of the tightest range as the guess of the mode - m = x( round(m_spot + (shift/2)) ); - end - - - - function [mappedX, mapping] = lda(X, labels, no_dims) - %LDA Perform the LDA algorithm - % - % [mappedX, mapping] = lda(X, labels, no_dims) - % - % The function runs LDA on a set of datapoints X. The variable - % no_dims sets the number of dimensions of the feature points in the - % embedded feature space (no_dims >= 1, default = 2). The maximum number - % for no_dims is the number of classes in your data minus 1. - % The function returns the coordinates of the low-dimensional data in - % mappedX. Furthermore, it returns information on the mapping in mapping. - % - % - - % This file is part of the Matlab Toolbox for Dimensionality Reduction. - % The toolbox can be obtained from http://homepage.tudelft.nl/19j49 - % You are free to use, change, or redistribute this code in any way you - % want for non-commercial purposes. However, it is appreciated if you - % maintain the name of the original author. - % - % (C) Laurens van der Maaten, Delft University of Technology - - - if ~exist('no_dims', 'var') || isempty(no_dims) - no_dims = 2; - end - - % Make sure data is zero mean - mapping.mean = mean(X, 1); - X = bsxfun(@minus, X, mapping.mean); - - % Make sure labels are nice - [classes, bar, labels] = unique(labels); - nc = length(classes); - - % Intialize Sw - Sw = zeros(size(X, 2), size(X, 2)); - - % Compute total covariance matrix - St = cov(X); - - % Sum over classes - for i=1:nc - - % Get all instances with class i - cur_X = X(labels == i,:); - - % Update within-class scatter - C = cov(cur_X); - p = size(cur_X, 1) / (length(labels) - 1); - Sw = Sw + (p * C); - end - - % Compute between class scatter - Sb = St - Sw; - Sb(isnan(Sb)) = 0; Sw(isnan(Sw)) = 0; - Sb(isinf(Sb)) = 0; Sw(isinf(Sw)) = 0; - - % Make sure not to embed in too high dimension - if nc < no_dims - no_dims = nc; - warning(['Target dimensionality reduced to ' num2str(no_dims) '.']); - end - - % Perform eigendecomposition of inv(Sw)*Sb - [M, lambda] = eig(Sb, Sw); - - % Sort eigenvalues and eigenvectors in descending order - lambda(isnan(lambda)) = 0; - [lambda, ind] = sort(diag(lambda), 'descend'); - M = M(:,ind(1:min([no_dims size(M, 2)]))); - - % Compute mapped data - mappedX = X * M; - - % Store mapping for the out-of-sample extension - mapping.M = M; - mapping.val = lambda; - - - end -end diff --git a/spikeSorting/@gridSorter/calculateChParameters.m b/spikeSorting/@gridSorter/calculateChParameters.m deleted file mode 100644 index 7ba027b..0000000 --- a/spikeSorting/@gridSorter/calculateChParameters.m +++ /dev/null @@ -1,68 +0,0 @@ -function obj=calculateChParameters(obj) -%Populate the chPar structure with morphological channel parameters to be later used in soring -%test that a valid channel layout is available -if isempty(obj.dataRecordingObj.chLayoutNumbers) - disp('No channel layout found in recording object,exiting...'); - return; -end - -if obj.localGridSize/2==round(obj.localGridSize/2) - error('Error constructing channel parameter: localGridSize should be an even integer'); -end -%determine channels -if isempty(obj.selectedChannelSubset) - obj.selectedChannelSubset=obj.dataRecordingObj.channelNumbers; %take all channel in the recording - disp('No specific channels selected: Sorting all channels in recording'); -end -obj.nCh=numel(obj.selectedChannelSubset); -obj.chPar.s2r=obj.selectedChannelSubset; %transformation between the serial channel number and the real ch number -obj.chPar.r2s(obj.selectedChannelSubset)=1:obj.nCh; %transformation between the real channel number and the serial ch number - -%get channel layout -obj.chPar.En=obj.dataRecordingObj.chLayoutNumbers; - -%limit layout only to the serial channels selected by user -obj.chPar.rEn=obj.chPar.En; -obj.chPar.rEn(~isnan(obj.chPar.En))=obj.chPar.r2s(obj.chPar.En(~isnan(obj.chPar.En))); -obj.chPar.rEn(obj.chPar.rEn==0)=NaN; -[nRowsTmp,nColsTmp]=size(obj.chPar.En); - -localGridSizeExt=obj.localGridSize+obj.localGridExt*2; - -%initiate arrays -obj.chPar.surChExt=cell(1,obj.nCh);obj.chPar.pValidSurChExt=cell(1,obj.nCh);obj.chPar.surChExtVec=cell(1,obj.nCh);obj.chPar.pCenterCh=zeros(1,obj.nCh);obj.chPar.nValidChExt=zeros(1,obj.nCh);obj.chPar.pSurCh=cell(1,obj.nCh);obj.chPar.pSurChOverlap=cell(1,obj.nCh); -if ~isempty(localGridSizeExt) - obj.arrayExt=(obj.localGridSize-1)/2; - overheadGridExtension=(localGridSizeExt-1)/2; - EnExt=NaN(nRowsTmp+overheadGridExtension*2,nColsTmp+overheadGridExtension*2); - EnExt(1+overheadGridExtension:end-overheadGridExtension,1+overheadGridExtension:end-overheadGridExtension)=obj.chPar.rEn; - for i=1:obj.nCh - [x,y]=find(EnExt==i); - - %find the surrounding channels on which feature extraction will be performed - surCh=EnExt(x-obj.arrayExt:x+obj.arrayExt,y-obj.arrayExt:y+obj.arrayExt); - pValidSurCh=find(~isnan(surCh)); %do not remove find - - %find the channels that are overhead step from the central channel - these are the channels who's waveforms should be checked for merging - surChOverlap=EnExt(x-obj.localGridExt:x+obj.localGridExt,y-obj.localGridExt:y+obj.localGridExt); - surChOverlap(obj.localGridExt+1,obj.localGridExt+1)=NaN; - pValidSurChOverlap=find(~isnan(surChOverlap)); %do not remove find - - %find the extended channels for merging of the same neurons detected on nearby channels - obj.chPar.surChExt{i}=EnExt(x-overheadGridExtension:x+overheadGridExtension,y-overheadGridExtension:y+overheadGridExtension); - obj.chPar.pValidSurChExt{i}=find(~isnan(obj.chPar.surChExt{i})); %do not remove find - obj.chPar.nValidChExt(i)=numel(obj.chPar.pValidSurChExt{i}); - - obj.chPar.surChExtVec{i}=obj.chPar.surChExt{i}(obj.chPar.pValidSurChExt{i}(:))'; - obj.chPar.pCenterCh(i)=find(obj.chPar.surChExtVec{i}==i); %the position of the central channel in surChExtVec - [~,obj.chPar.pSurCh{i}]=intersect(obj.chPar.surChExtVec{i},surCh(pValidSurCh(:))); - [~,obj.chPar.pSurChOverlap{i}]=intersect(obj.chPar.surChExtVec{i},surChOverlap(pValidSurChOverlap(:))); - end -end -%map channel intersections -for i=1:obj.nCh - for j=obj.chPar.surChExtVec{i}(obj.chPar.pSurChOverlap{i}) %the trivial case : (i,i) is also included (can be remove in not required) - [obj.chPar.sharedChNames{i}{j},obj.chPar.pSharedCh1{i}{j},obj.chPar.pSharedCh2{i}{j}]=intersect(obj.chPar.surChExtVec{i},obj.chPar.surChExtVec{j}); - end -end - diff --git a/spikeSorting/@gridSorter/detectedSpikes2TIC.m b/spikeSorting/@gridSorter/detectedSpikes2TIC.m deleted file mode 100644 index c5469cc..0000000 --- a/spikeSorting/@gridSorter/detectedSpikes2TIC.m +++ /dev/null @@ -1,37 +0,0 @@ -function [gridObj] = detectedSpikes2TIC(gridObj,varargin) -%DETECTEDSPIKES2TIC retrieves all spike times from the spike detection -%and converts it into a t,IC format -% detectedSpikes2TIC loads spike times from gridObj.sortingFileNames, and -% saves the output file to [gridObj.sortingDir '\GridSorterDetectedSpikes.m'] unless given -% otherwise in varargin (use 'ticPath' key,value to change this) -% NOTICE: changing these variables was not QA-ed, so use with caution - -ticPath=[gridObj.sortingDir '\GridSorterDetectedSpikes.mat']; - -for i=1:2:numel(varargin) - eval([varargin{i} '=varargin{' num2str(i+1) '};']); -end - -channels=gridObj.selectedChannelSubset; -nCh=length(channels); - -ic(1,:)=channels; -ic(2,:)=ones(1,nCh); %with no sorting - assuming 1 neuron per channel -t=[]; - -for i=1:nCh - spikeTimes=load(gridObj.sortingFileNames.spikeDetectionFile{i},'spikeTimes'); - try - spikeTimes=spikeTimes.spikeTimes; - catch - spikeTimes=[]; - end - ic(3,i)=length(t)+1; - ic(4,i)=length(t)+length(spikeTimes); - t=[t spikeTimes]; -end - -%remove channels without spikes -ic(:,ic(3,:)==(ic(4,:)+1))=[]; - -save(ticPath,'t','ic') diff --git a/spikeSorting/@gridSorter/findSortingFiles.m b/spikeSorting/@gridSorter/findSortingFiles.m deleted file mode 100644 index eadb553..0000000 --- a/spikeSorting/@gridSorter/findSortingFiles.m +++ /dev/null @@ -1,85 +0,0 @@ -function obj=findSortingFiles(obj) -%locate spike sorting related files from the same recording to determine which step were already done -%check conditions for recalculating the different stages of spike sorting. Notice that for the 3 first procedures only, calcululation of a subset of uncalculated channels is possiblee - -if obj.overwriteAll - obj.overwriteClustering=1; - obj.overwriteFeatureExtraction=1; - obj.overwriteFitting=1; - obj.overwriteMerging=1; - obj.overwritePostProcessingAnalysis=1; - obj.overwriteSpikeExtraction=1; - obj.overwriteQualityAssessment=1; -end - -obj.sortingFileNames=[]; - -for i=1:obj.nCh - obj.sortingFileNames.spikeDetectionFile{i}=[obj.sortingDir filesep 'ch_' num2str(obj.chPar.s2r(i)) '_spikeDetection.mat']; - if ~obj.overwriteSpikeExtraction - obj.sortingFileNames.spikeDetectionExist(i)=exist(obj.sortingFileNames.spikeDetectionFile{i},'file'); - else - obj.sortingFileNames.spikeDetectionExist(i)=0; - end - - obj.sortingFileNames.featureExtractionFile{i}=[obj.sortingDir filesep 'ch_' num2str(obj.chPar.s2r(i)) '_featureExtraction.mat']; - if ~obj.overwriteFeatureExtraction - obj.sortingFileNames.featureExtractionExist(i)=exist(obj.sortingFileNames.featureExtractionFile{i},'file'); - else - obj.sortingFileNames.featureExtractionExist(i)=0; - end - - obj.sortingFileNames.clusteringFile{i}=[obj.sortingDir filesep 'ch_' num2str(obj.chPar.s2r(i)) '_clustering.mat']; - if ~obj.overwriteClustering - obj.sortingFileNames.clusteringExist(i)=exist(obj.sortingFileNames.clusteringFile{i},'file'); - else - obj.sortingFileNames.clusteringExist(i)=0; - end -end - -obj.sortingFileNames.avgWaveformFile=[obj.sortingDir filesep 'avgClusteredWaveforms.mat']; - -obj.sortingFileNames.mergedAvgWaveformFile=[obj.sortingDir filesep 'AllMergedWaveforms.mat']; -if ~obj.overwriteMerging - obj.sortingFileNames.mergedAvgWaveformExist=exist(obj.sortingFileNames.mergedAvgWaveformFile,'file'); -else - obj.sortingFileNames.mergedAvgWaveformExist=0; -end - -obj.sortingFileNames.fittingFile=[obj.sortingDir filesep 'spikeSorting.mat']; -if ~obj.overwriteFitting - obj.sortingFileNames.fittingExist=exist(obj.sortingFileNames.fittingFile,'file'); -else - obj.sortingFileNames.fittingExist=0; -end - -obj.sortingFileNames.postProcessingAnalysisFile=[obj.sortingDir filesep 'postProcessingAnalysis.mat']; -if ~obj.overwritePostProcessingAnalysis - obj.sortingFileNames.postProcessingAnalysisExist=exist(obj.sortingFileNames.postProcessingAnalysisFile,'file'); - if obj.sortingFileNames.postProcessingAnalysisExist %check if part of the units were already processed in a previous run - tmp=load(obj.sortingFileNames.postProcessingAnalysisFile,'postProcessingAnalysisExist'); - if ~isempty(tmp) - if isfield(tmp,'postProcessingAnalysisExist') - obj.sortingFileNames.postProcessingAnalysisExist=tmp.postProcessingAnalysisExist; - end - else - warning('Field "postProcessingAnalysisExist" does not exist in post processing file, maybe this sorting was done with an earilier version'); - end - end -else - obj.sortingFileNames.postProcessingAnalysisExist=0; -end - -obj.sortingFileNames.STWaveformFile=[obj.sortingDir filesep 'STWaveform.mat']; -if ~obj.overwriteSTWaveform - obj.sortingFileNames.STWaveformExist=exist(obj.sortingFileNames.STWaveformFile,'file'); -else - obj.sortingFileNames.STWaveformExist=0; -end - -obj.sortingFileNames.assessQualityFile=[obj.sortingDir filesep 'errorEstimates.mat']; -if ~obj.overwriteQualityAssessment - obj.sortingFileNames.assessQualityExist=exist(obj.sortingFileNames.fittingFile,'file'); -else - obj.sortingFileNames.assessQualityExist=0; -end diff --git a/spikeSorting/@gridSorter/gaussOverlap.m b/spikeSorting/@gridSorter/gaussOverlap.m deleted file mode 100644 index 6990e43..0000000 --- a/spikeSorting/@gridSorter/gaussOverlap.m +++ /dev/null @@ -1,83 +0,0 @@ -function confusion = gaussOverlap( w1, w2 ) -% UltraMegaSort2000 by Hill DN, Mehta SB, & Kleinfeld D - 07/12/2010 -% -% gaussian_overlap - estimate cluster overlap from a 2-mean Gaussian mixture model -% -% Usage: -% C = gaussian_overlap( waveforms1, waveforms2 ) -% -% Description: -% Estimates the overlap between 2 spike clusters by fitting with two -% multivariate Gaussians. Implementation makes use of MATLAB statistics -% toolbox function "gmdistribution.fit". -% -% The percent of false positive and false negative errors are estimated for -% both classes and stored as a confusion matrix. Error rates are calculated -% by integrating the posterior probability of a misclassification. The -% integral is then normalized by the number of events in the cluster of -% interest. See description of confusion matrix below. -% -% NOTE: The dimensionality of the data set is reduced to the top 99% of -% principal components to increase the time efficiency of the fitting -% algorithm. -% -% Input: -% waveforms1 - [Event x Sample ] waveforms of 1st cluster -% waveforms2 - [Event x Sample ] waveforms of 2nd cluster -% If your waveform data is in the form [Event X Sample X Channels ], -% you should call this function as -% confusion = gaussian_overlap( w1(:,:), w2(:,:) ); -% This will concatenate the waveforms from different channels. -% -% -% Output: -% C - a confusion matrix -% C(1,1) - False positive fraction in cluster 1 (waveforms of neuron 2 that were assigned to neuron 1) -% C(1,2) - False negative fraction in cluster 1 (waveforms of neuron 1 that were assigned to neuron 2) -% C(2,1) - False negative fraction in cluster 2 -% C(2,2) - False positive fraction in cluster 2 -% - - % reduce dimensionality to 98% of top Principal Components - cutoff = .9; - N1 = size(w1,1); - N2 = size(w2,1); - % disp('Reducing data dimensionality ...'); - [COEFF, SCORE, LATENT] = pca([w1; w2]); - - cumvals =cumsum(LATENT)./sum(LATENT); - num_dims = find( cumvals < cutoff, 1, 'last' ) - 1; - if isempty(num_dims), num_dims = size( w1(:,:), 2 ); end - w1 = SCORE(1:N1,1:num_dims); - w2 = SCORE([N1+1:end],1:num_dims); - - % fit 2 multivariate gaussians, use observed parameters to initialize - params.mu = [ mean(w1(:,:),1); mean(w2(:,:),1)]; - params.Sigma(:,:,1) = cov(w1(:,:)); - params.Sigma(:,:,2) = cov(w2(:,:)); - params.PComponets = [N1 N2] / (N1 + N2); - % disp('Fitting 2-Gaussian Mixture Model ...') - gmfit = gmdistribution.fit([w1(:,:); w2(:,:)],2,'Start',params); - - % get posteriors - %disp('Calculating Confusion matrix ...') - pr1 = gmfit.posterior(w1); - pr2 = gmfit.posterior(w2); - - % in the unlikely case that the cluster identities were flipped during the fitting procedure, flip them back - if mean(pr1(:,1)) + mean(pr2(:,2)) < 1 - pr1 = pr1(:,[2 1]); - pr2 = pr2(:,[2 1]); - end - - % create confusion matrix - confusion(1,1) = mean(pr1(:,2)); % probability that a member of 1 is false - confusion(1,2) = sum(pr2(:,1))/N1 ; % relative proportion of spikes that were placed in cluster 2 by mistake - confusion(2,2) = mean(pr2(:,1)); % probability that a member of 2 was really from 1 - confusion(2,1) = sum(pr1(:,2))/N2; % relative proportion of spikes that were placed in cluster 1 by mistake - - % - % disp('Finished.') - -end - diff --git a/spikeSorting/@gridSorter/getHighpassFilter.m b/spikeSorting/@gridSorter/getHighpassFilter.m deleted file mode 100644 index 1f70567..0000000 --- a/spikeSorting/@gridSorter/getHighpassFilter.m +++ /dev/null @@ -1,35 +0,0 @@ -function obj=getHighpassFilter(obj,samplingFrequency) -%calculate the highpass filter for sorting -if ~isempty(obj.dataRecordingObj) - samplingFrequency=obj.dataRecordingObj.samplingFrequency; -elseif nargin==2 - disp(['Building filter with sampling freq. :' num2str(samplingFrequency)]); - %answer = inputdlg(prompt,dlg_title) -else - disp('No data recorded object exists, either add object or enter sampling freq.as a second argument'); - return; -end - -obj.filterObj=filterData(samplingFrequency); -if obj.simpleButter - obj.filterObj.highPassCutoff=obj.highPassCutoff; - obj.filterObj.lowPassCutoff=obj.lowPassCutoff; - obj.filterObj.filterOrder=obj.filterOrder; -else - obj.filterObj.highPassPassCutoff=obj.filterHighPassPassCutoff; - obj.filterObj.highPassStopCutoff=obj.filterHighPassStopCutoff; - obj.filterObj.lowPassPassCutoff=obj.filterLowPassPassCutoff; - obj.filterObj.lowPassStopCutoff=obj.filterLowPassStopCutoff; - obj.filterObj.attenuationInHighpass=obj.filterAttenuationInHighpass; - obj.filterObj.attenuationInLowpass=obj.filterAttenuationInLowpass; - obj.filterObj.rippleInPassband=obj.filterRippleInPassband; -end -obj.filterObj.filterDesign=obj.filterDesign; -obj.filterObj.padding=true; -%obj.filterObj.highPassCutoff=obj.filterHighPassPassCutoff; -%obj.filterObj.lowPassCutoff=obj.filterLowPassPassCutoff; -%obj.filterObj.filterOrder=8; - -obj.filterObj=obj.filterObj.designBandPass; - -end diff --git a/spikeSorting/@gridSorter/getProperties.m b/spikeSorting/@gridSorter/getProperties.m deleted file mode 100644 index cf3c76b..0000000 --- a/spikeSorting/@gridSorter/getProperties.m +++ /dev/null @@ -1,12 +0,0 @@ -function [publicProps]=getProperties(obj) -%get the properties of the gridSorter Class -metaClassData=metaclass(obj); -allPropName={metaClassData.PropertyList.Name}'; -allPropSetAccess={metaClassData.PropertyList.SetAccess}'; -pPublic=find(strcmp(allPropSetAccess, 'public')); -publicProps(:,1)=allPropName(pPublic); - -%collect all prop values -for i=1:size(publicProps,1) - publicProps{i,2}=obj.(publicProps{i,1}); -end \ No newline at end of file diff --git a/spikeSorting/@gridSorter/getSpikeTrigWF.m b/spikeSorting/@gridSorter/getSpikeTrigWF.m deleted file mode 100644 index 90ac1b5..0000000 --- a/spikeSorting/@gridSorter/getSpikeTrigWF.m +++ /dev/null @@ -1,212 +0,0 @@ -function obj=getSpikeTrigWF(obj) -%Detect spikes in raw data and save waveforms -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% OLD FUNCTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -error('This method is an old version, please use MEAAnalysis.getSpikeTrigWF instead'); - -load(obj.sortingFileNames.fittingFile,'t','ic'); -saveFileName='tmpPostProcessing'; -neuronNames=ic(1:2,:); - -%determine quantization -obj.detectionInt2uV=obj.detectionMaxSpikeAmp/2^(obj.detectionNQuantizationBits-1); - -obj=obj.getHighpassFilter; - -%start spike detection -fprintf('\nRunning waveform extraction on %s...',obj.dataRecordingObj.dataFileNames{1}); - -%determine the chunck size -if obj.detectionMaxChunkSize>obj.dataRecordingObj.recordingDuration_ms - startTimes=0; - endTimes=obj.dataRecordingObj.recordingDuration_ms; -else - startTimes=(0:obj.detectionMaxChunkSize:obj.dataRecordingObj.recordingDuration_ms); - endTimes=[startTimes(2:end) obj.dataRecordingObj.recordingDuration_ms]; -end -nChunks=numel(startTimes); - -obj.nCh=numel(obj.chPar.s2r); -nNeurons=size(ic,2); -nSpkTotal=ic(4,:)-ic(3,:)+1; - -windowSamplesRaw=obj.postTotalRawWindow*obj.dataRecordingObj.samplingFrequency/1000; -windowSamplesFiltered=obj.postTotalFilteredWindow*obj.dataRecordingObj.samplingFrequency/1000; -HPstartIdx=((obj.postTotalFilteredWindow-obj.postPreFilteredWindow)*obj.dataRecordingObj.samplingFrequency/1000+1); -HPIdx=HPstartIdx:(HPstartIdx+windowSamplesFiltered-1); - -keepAllInMemory=1; -if ispc - userview = memory; - doubleBytes=8; - if userview.MemAvailableAllArrays<(nNeurons*obj.nCh*windowSamplesRaw*doubleBytes*4) & keepAllInMemory - disp('Arrays too big for memory, moving to saving on disk (for using memory change chunk size'); - keepAllInMemory=0; - end -end - -par.binTRaw=1; %ms -par.binTHP=0.1; %ms -par.binV=0.5; -par.maxV=75; - -nBinsRaw=ceil(obj.postTotalRawWindow/par.binTRaw); -nBinsHP=ceil(obj.postTotalFilteredWindow/par.binTHP); -nBinsV=2*par.maxV/par.binV; - -if keepAllInMemory - avgRawWF=zeros(nNeurons,obj.nCh,windowSamplesRaw); - stdRawWF=zeros(nNeurons,obj.nCh,windowSamplesRaw); - avgHPWF=zeros(nNeurons,obj.nCh,windowSamplesFiltered); - stdHPWF=zeros(nNeurons,obj.nCh,windowSamplesFiltered); - histRawWF=zeros(nNeurons,obj.nCh,nBinsRaw,nBinsV,'uint8'); - histHPWF=zeros(nNeurons,obj.nCh,nBinsHP,nBinsV,'uint8'); -else - matFileObj = matfile(obj.sortingFileNames.STWaveformFile,'Writable',true); - if obj.postExtractRawLongWaveformsFromSpikeTimes - matFileObj.avgRawWF=zeros(nNeurons,obj.nCh,windowSamplesRaw); - matFileObj.stdRawWF=zeros(nNeurons,obj.nCh,windowSamplesRaw); - matFileObj.histRawWF=zeros(nNeurons,obj.nCh,nBinsRaw,nBinsV,'uint8'); - else - matFileObj.avgRawWF=[];matFileObj.stdRawWF=[];matFileObj.histRawWF=[]; - end - - if obj.postExtractFilteredWaveformsFromSpikeTimes - matFileObj.avgHPWF=zeros(nNeurons,obj.nCh,windowSamplesFiltered); - matFileObj.stdHPWF=zeros(nNeurons,obj.nCh,windowSamplesFiltered); - matFileObj.histHPWF=zeros(nNeurons,obj.nCh,nBinsHP,nBinsV,'uint8'); - else - matFileObj.avgHPWF=[];matFileObj.stdHPWF=[];matFileObj.histHPWF=[]; - end -end - -%load files if matlab crashed during analysis -if exist([obj.sortingDir filesep saveFileName '_tmp.mat'],'file') - load([obj.sortingDir filesep saveFileName '_tmp.mat']); - startChunk=max(1,lastGoodChunck+1); -else - startChunk=1; -end - -tBinRaw=shiftdim(ceil(((1:windowSamplesRaw)/obj.dataRecordingObj.samplingFrequency*1000)/par.binTRaw),-1); -tBinHP=shiftdim(ceil(((1:windowSamplesFiltered)/obj.dataRecordingObj.samplingFrequency*1000)/par.binTHP),-1); -VBins=(-par.maxV+par.binV/2):par.binV:par.maxV; -pPreBaselineSamples=((obj.dataRecordingObj.samplingFrequency(1)/1000)*(obj.postPreRawWindow-obj.detectionPreSpikeWindow-1)):((obj.dataRecordingObj.samplingFrequency(1)/1000)*(obj.postPreRawWindow-obj.detectionPreSpikeWindow)); -tBinsRaw=par.binTRaw/2:par.binTRaw:obj.postTotalRawWindow; -tBinsHP=par.binTHP/2:par.binTHP:obj.postTotalFilteredWindow; -try - tic; - %initiate arrays - fprintf('\nExtracting spikes from chunks (total %d): ',nChunks); - for i=startChunk:nChunks - fprintf('%d',i); - %get data - MAll=obj.dataRecordingObj.getData(obj.chPar.s2r(1:obj.nCh),startTimes(i)-obj.postPreRawWindow,endTimes(i)-startTimes(i)+obj.postTotalRawWindow); - MFAll=squeeze(obj.filterObj.getFilteredData(MAll))'; %filter class needs unsqueezed input - MAll=squeeze(MAll)'; - nSamples=size(MAll,1); - %tAll=((1:nSamples)/obj.dataRecordingObj.samplingFrequency*1000)-obj.postPreRawWindow+startTimes(i); - for j=1:nNeurons - tTmp=t(ic(3,j):ic(4,j)); - tTmp=tTmp(find(tTmp>=startTimes(i) & tTmp< (endTimes(i)-obj.postTotalRawWindow+obj.postPreRawWindow) )); - nSpkTmp=numel(tTmp); - if nSpkTmp>0 - startIdx=round((tTmp-startTimes(i))*obj.dataRecordingObj.samplingFrequency/1000); - idx=bsxfun(@plus,startIdx,(0:windowSamplesRaw-1)'); - WF=MAll(idx,:); - WF=permute(reshape(WF,[size(idx,1) size(idx,2) obj.nCh]),[2 3 1]); - %WF=bsxfun(@minus,WF,mean(WF(:,:,pPreBaselineSamples),3)); - avgRawWF(j,:,:)=avgRawWF(j,:,:)+sum(WF,1); - stdRawWF(j,:,:)=stdRawWF(j,:,:)+sum(WF.^2,1); - - idx=idx(HPIdx,:); - WFH=MFAll(idx,:); - WFH=permute(reshape(WFH,[size(idx,1) size(idx,2) obj.nCh]),[2 3 1]); - avgHPWF(j,:,:)=avgHPWF(j,:,:)+sum(WFH,1); - stdHPWF(j,:,:)=stdHPWF(j,:,:)+sum(WFH.^2,1); - - for k=1:obj.nCh - hVTmp=round((WF(:,k,:)+par.maxV)/(par.maxV*2/nBinsV)); %the reshape is important since otherwise when nSpkTmp==1 squeeze changes matrix from row to column - p=find(hVTmp>0 & hVTmp1 %if there is only one point to include in the statistics we can reject this trial. - htTmp=repmat(tBinRaw,[numel(tTmp) 1]); - if nSpkTmp>1 - histRawWF(j,k,:,:)=histRawWF(j,k,:,:)+shiftdim(uint8(accumarray([htTmp(p) hVTmp(p)],1,[nBinsRaw nBinsV])),-2); - else - histRawWF(j,k,:,:)=histRawWF(j,k,:,:)+shiftdim(uint8(accumarray(squeeze([htTmp(p) hVTmp(p)])',1,[nBinsRaw nBinsV])),-2); - end - - hVTmp=round((WFH(:,k,:)+par.maxV)/(par.maxV*2/nBinsV)); - p=find(hVTmp>0 & hVTmp1 - histHPWF(j,k,:,:)=histHPWF(j,k,:,:)+shiftdim(uint8(accumarray([htTmp(p) hVTmp(p)],1,[nBinsHP nBinsV])),-2); - else - histHPWF(j,k,:,:)=histHPWF(j,k,:,:)+shiftdim(uint8(accumarray(squeeze([htTmp(p) hVTmp(p)])',1,[nBinsHP nBinsV])),-2); - end - end - end - end - end - tChunk(i)=toc;tic; - fprintf('(%d) ',round(tChunk(i))); - end - - for i=1:nNeurons - tmpN=(ic(4,i)-ic(3,i)+1); - stdRawWF(i,:,:)=sqrt((stdRawWF(i,:,:)-avgRawWF(i,:,:))/(tmpN-1)); - stdHPWF(i,:,:)=sqrt((stdHPWF(i,:,:)-avgHPWF(i,:,:))/(tmpN-1)); - - avgRawWF(i,:,:)=avgRawWF(i,:,:)/tmpN; - avgHPWF(i,:,:)=avgHPWF(i,:,:)/tmpN; - end - - [mElecs,nElecs]=size(obj.chPar.En); - if obj.postPlotRawLongWaveforms - figurePosition=[100 50 min(1000,100*nElecs) min(900,100*mElecs)]; - for i=1:nNeurons - f=figure('position',figurePosition); - neuronString=['Neu ' num2str(ic(1,i)) '-' num2str(ic(2,i))]; - infoStr={['nSpk=' num2str(nSpkTotal(i))],neuronString}; - [h,hParent]=spikeDensityPlotPhysicalSpace(squeeze(histRawWF(i,:,:,:)),obj.dataRecordingObj.samplingFrequency(1),obj.chPar.s2r,obj.chPar.En,... - 'hParent',f,'avgSpikeWaveforms',permute(avgRawWF(i,:,:),[3 1 2]),'logColorScale',0,'spikeShapesIsAHist',1,'xBin',tBinsRaw,'yBin',unique(VBins)); - annotation('textbox',[0.01 0.89 0.1 0.1],'FitHeightToText','on','String',infoStr); - - printFile=[obj.sortingDir filesep 'neuron' neuronString '-spikeShapeRaw']; - set(f,'PaperPositionMode','auto'); - print(printFile,'-djpeg','-r300'); - close(f); - end - end - - if obj.postPlotFilteredWaveforms - figurePosition=[100 50 min(1000,100*nElecs) min(900,100*mElecs)]; - for i=1:nNeurons - f=figure('position',figurePosition); - neuronString=['Neu ' num2str(ic(1,i)) '-' num2str(ic(2,i))]; - infoStr={['nSpk=' num2str(nSpkTotal(i))],neuronString}; - [h,hParent]=spikeDensityPlotPhysicalSpace(squeeze(histHPWF(i,:,:,:)),obj.dataRecordingObj.samplingFrequency(1),obj.chPar.s2r,obj.chPar.En,... - 'hParent',f,'avgSpikeWaveforms',permute(avgHPWF(i,:,:),[3 1 2]),'logColorScale',0,'spikeShapesIsAHist',1,'xBin',tBinsHP,'yBin',unique(VBins)); - annotation('textbox',[0.01 0.89 0.1 0.1],'FitHeightToText','on','String',infoStr); - - printFile=[obj.sortingDir filesep 'neuron' neuronString '-spikeShapeHP']; - set(f,'PaperPositionMode','auto'); - print(printFile,'-djpeg','-r300'); - close(f); - end - end - -catch errorMsg - if i>1 - lastGoodChunck=i-1; - save([obj.sortingDir filesep saveFileName '_tmp.mat'],'avgRawWF','avgHPWF','stdRawWF','stdHPWF','histRawWF','histHPWF','par','lastGoodChunck','-v7.3'); - end - rethrow(errorMsg); -end -fprintf('\nTriggered waveform analysis took (%f) hours\nSaving data...\n',sum(tChunk)/60/60); - -save(obj.sortingFileNames.STWaveformFile,'avgRawWF','avgHPWF','stdRawWF','stdHPWF','neuronNames','histRawWF','histHPWF','nSpkTotal','par','-v7.3'); -fprintf('Deleting temporary files...'); -delete([obj.sortingDir filesep saveFileName '_tmp.mat']); -obj=obj.findSortingFiles; %update sorted files diff --git a/spikeSorting/@gridSorter/gridSorter.m b/spikeSorting/@gridSorter/gridSorter.m deleted file mode 100644 index b3ff91f..0000000 --- a/spikeSorting/@gridSorter/gridSorter.m +++ /dev/null @@ -1,333 +0,0 @@ -classdef gridSorter - properties (Constant) - gridSorterVersion=1.03; %the version of grid sorter - end - properties (SetAccess=public) - overwriteAll=0; %if true overwrites all sorting process - overwriteSpikeExtraction=0; %if true recalculate spike extraction - overwriteFeatureExtraction=0; %if true recalculate feature extraction - overwriteClustering=0; %if true recalculate clustering - overwriteMerging=0; %if true recalculate cluster merging - overwriteFitting=0; %if true recalculate spike fitting - overwritePostProcessingAnalysis=0; %if true recalculate post processign analysis - overwriteSTWaveform=0; %if true recalculate spike triggered analysis - overwriteQualityAssessment=0; %if true recalculate quality assessment - - sortingDir %the root directory of the sorted data - runWithoutSaving2File=false; %run without saving files to hard drive (applicable only for short recordings in which all data can be kept in memory) - fastPrinting=0; %uses fast printing of the figures (the resulting figures are low quality and require the screen to be turned on) - saveFigures=1; %save the figures plotted during sorting to file - - selectedChannelSubset=[]; %the numbers of a subset of channels to be sorted out of the whole recording - dataRecordingObj %the data recording object (must be a subclass of dataRecording, e.g. MCRackDataNeuroshare, Intan) - sendProgressEmail = true; %whether to send an email at the end or during errors - sendProgressEmailTo = 'shein.mark@gmail.com'; - - upSamplingFrequencySpike=60000; %Desired upsampling frequency for spike extrema and shape calculation. Must be an integer multiple of the sampling frequency (if not it is adjusted automatically) - - localGridSize=3; % The length of the local grid on which sorting is calculated, e.g. if==3, sorts on a 3x3 grid surrounding the central channel (must be an odd number). If empty uses all channels - localGridExt=1; %the overhead used by the algorithm to later merge neurons that were detected on more than one channel (according to peak amplitude). - - detectionRemoveAllElectrodeMedian=false; %spike detection - remove artifacts that appear on all electrodes using a median filter substruction - detectionMaxSpikeAmp=1000; %Spike detection - spike with higher max amplitude are considered as noise and are not analyzed - detectionNQuantizationBits=16; %Spike detection - the quantization depth for reducing the raw data resolution for reducing disk space (should be the same as the quantization of the recording hardware) - detectionGaussianityWindow=20;%Spike detection [ms] - window for estimating noise segments according to kurtosis - detectionPreSpikeWindow=2;%Spike detection [ms] - window before spike peak for spike shape extraction - detectionPostSpikeWindow=3;%Spike detection [ms] - window after spike peak for spike shape extraction - detectionSpikeTimeShiftInterval=1;%Spike detection [ms] - initial extension of the spike window used to compensate for aligning spikes to the peak - detectionPeakDetectionSmoothingWindow=0.3; %Spike detection [ms] - the smoothing window for detection of the exact spike occurance - detectionKurtosisNoiseThreshold=3;%Spike detection - the threshold on the kurtosis value that differentiates noise samples from spike samples - detectionSpikeDetectionThresholdStd=5;%Spike detection - number of standard deviations above the noise level for spike detection - detectionMaxChunkSize=2*60*1000; %Spike detection [ms] - the size of the consecutive chunks of raw data extracted (should fit memory capacity) - detectionChunkOverlap=1; %Spike detection - overlap between analyzed chunks to not miss a spike that fell between data chunks - detectionMinimumDetectionInterval=0.5;%Spike detection [ms] - the maximal interval on which the global spike minima is calculated for all surrounding local extended channels (spike with minima differnt than the center channel are not included) - detectionRemoveSpikesNotExtremalOnLocalGrid=true; %Spike detection - removes all spike that have a stronger minimum on another channel surrounding the detection channel on the grid - detectionRemoveSpikesSubMinimumDelays=true; %Spike detection - remove spikes with delays shorter than detectionMinimumDelayBetweenSpikes on the same channel - detectionMinimumDelayBetweenSpikes=1; %Spike detection - minimum delay allowed between spike peaks on the same channel - - simpleButter=1; %use simple butterworth or a more complex - - highPassCutoff=200; - lowPassCutoff=2500; - filterOrder=2; - filterDesign='butter'; %Filter - type of filter used usually 'butter' or 'elliptic' - - filterHighPassPassCutoff=250; %Filter - highpass cutoff - upper bound - filterHighPassStopCutoff=150; %Filter - highpass cutoff - lower bound - filterLowPassPassCutoff=2000; %Filter - lowpass cutoff - upper bound - filterLowPassStopCutoff=2500; %Filter - highpass cutoff - lower bound - filterAttenuationInHighpass=20; %Filter - attenuation of power [dB] for highpass between lower and upper - filterAttenuationInLowpass=10; %Filter - attenuation of power [dB] for lowpass between lower and upper - filterRippleInPassband=0.5; %Filter - allowed ripples [dB] in pass band - - featuresMaxSpikesToCluster=10000; %Feature extraction - maximum number of spikes for feature extraction (not to template matching) - featuresNWaveletCoeff=30; %Feature extraction - number of wavelet coefficient to extract - featuresReduceDimensionsWithPCA=true; %Feature extraction - if to reduce dimensions of extracted features with PCA - featuresDimensionReductionPCA=6; %Feature extraction - final dimension for clustering after wavelet decomposition - featuresSelectedWavelet='haar'; %Feature extraction - the mother wavelet used for wavelet decomposition - featuresWTdecompositionLevel=4; %Feature extraction - the level of wavelet decomposition - featuresFeatureExtractionMethod='wavelet'; %Feature extraction - the method for extracting features 'wavelet'/'PCA' - featuresConcatenateElectrodes=true; %Feature extraction - concatenate all surrounding electrodes to 1 big trace before extracting features - - clusteringMethod='meanShift';%Clustering - the clustering method used: 'meanShift'/'kMeans' - clusteringMergingMethod='projectionMeanStd';%Clustering - 'projectionMeanStd';%'MSEdistance' - clusteringMaxIter=1000; %Clustering - max itteration for clustering algorithm - clusteringNReplicates=50; %Clustering - number of clustering replicates in k-means clustering algorithm - clusteringInitialClusterCentersMethod='cluster'; %Clustering - method for initial conditions in k-means algorithm - clusteringMaxPointsInSilhoutte=1000; %Clustering - the maximal number of data points per cluster used for silloute quality estimation - clusteringMergeThreshold=0.18; %Clustering - threshold for merging clusters with 'projectionMeanStd' method, the higher the threshold the less cluster will merge - clusteringSTDMergeFac=2; %Clustering - the number of standard deviations for checking the crossing point on both sides (the higher the more clusters separate into groups) - clusteringRunSecondMerging=0; %Clustering - run merging again after initial merging - clusteringMaxClusters=12; %Clustering - the maximum number of clusters for a specific channels - clusteringMinimumChannelRate=0.01; %Clustering [Hz] - the minimal spike rate for spikes in a given clusters - clusteringMinNSpikesCluster=10; %Clustering - the minimal number of spikes in a cluster - clusteringMinSpikesTotal=20; %Clustering - the minimal total number of spikes per channel (if there was a lower spike count in the channel, channel is disgarded - clusteringPlotProjection=1; %Clustering - if to plot the projection data for 'projectionMeanStd' merging method - clusteringPlotClassification=1;%Clustering - if to plot the final clustering result for the channel - - mergingThreshold=0.1; %Merging - the threshold for merging similar waveforms - mergingRecalculateTemplates=true;%Merging - recalculate templates and not use the ones provided by the clustering algorithm - mergingNStdSpikeDetection=4;%Merging - standard deviation threshold for remove samples from the spike waveform for template comparison - mergingAllignSpikeBeforeAveraging=true;%Merging - allign spike before comparing templates - mergingAllignWaveShapes=true;%Merging - - mergingTestInitialTemplateMerging=false;%Merging - - mergingPlotStatistics=true;%Merging - if to plot merging statistics - mergingNStdNoiseDetection=6;%Merging - - mergingPreSpike4NoiseDetection=0.2;%Merging - - mergingPostSpike4NoiseDetection=0.2;%Merging - - mergingNoiseThreshold=0.2;%Merging - - mergingMaxSpikeShift=1; %%Merging [ms] - - - fittingTemplateMethod=1; - fittingMaxLag=0.5; - fittingLagIntervalSamples=1; - fittingSpikeNoiseEdgeInterval=0.5; - fittingMaxMinkowskiDist=4; %threshold for the distance of spike from template (distant templates are rejected - - postMaxSpikes2Present=600; %Post processing - max number of spike to extract per neuron - postPlotAllAvgSpikeTemplates=true; %Post processing - plot small templates for all neurons - postExtractFilteredWaveformsFromSpikeTimes=true;%Post processing - extract filtered short spike shapes with template - postExtractRawLongWaveformsFromSpikeTimes=true;%Post processing - extract raw long LFP shapes with template - postFilteredSNRStartEnd=[-0.2 0.2];%Post processing [ms] - [pre,post] spike interval for calculating spikeSNR - postRawSNRStartEnd=[5 20];%Post processing [ms] - [pre,post] LFP interval for calculating :LFP SNR - postPlotFilteredWaveforms=true;%Post processing - if to plot the filtered spike waveforms - postPlotRawLongWaveforms=true;%Post processing - if to plot the raw post spike field waveforms - postPlotSpikeReliability=true;%Post processing - if to plot the spike reliability plot - postPreFilteredWindow=2;%Post processing - pre spike window for plotting - postTotalFilteredWindow=5;%Post processing - post spike window for plotting - postPreRawWindow=20;%Post processing - pre raw window for plotting - postTotalRawWindow=100;%Post processing - post raw window for plotting - postRunPostProcessing=true;%if to run post processing - postAlternativeFileName;%if to save post processing results in a different file - - assessNumDiscrimDim=10; - assessMinSpikeNum=10; - assessMaxSpikeNumber=1000; - - sortingFileNames %a structure with all the files names that grid sorter calculates - end - - properties (SetAccess=protected) - nCh %number of channels to be sorted - chPar %a structure with channel arrangement parameters that are internally used by gridSorter - arrayExt %The extension of the array - - detectionInt2uV %Detection - translation between uint16 to microVolts (data is save in uint16 format to save space) - filterObj %Filter -the highpass filter object used to filter the raw data - end - - properties (SetObservable, AbortSet = true, SetAccess=public) - end - - properties (Hidden, SetAccess=protected) - end - - methods (Hidden) - %class constractor - function obj=gridSorter(dataRecordingObj,varargin) - %addlistener(obj,'visualFieldBackgroundLuminance','PostSet',@obj.initializeBackground); %add a listener to visualFieldBackgroundLuminance, after its changed its size is updated in the changedDataEvent method - - %Collects all options - if properties are given as a 'propertyName',propertyValue series - for i=1:2:length(varargin) - eval(['obj.' varargin{i} '=' 'varargin{i+1};']) - end - - if nargin==0 - disp('Data recording object not enter. In later versions a GUI will be imlemented for recording selection'); - return; - else - if isobject(dataRecordingObj) %if input is a data recording object - obj.dataRecordingObj=dataRecordingObj; - if iscell(obj.dataRecordingObj.recordingName) - [~, name, ~] = fileparts(obj.dataRecordingObj.recordingName{1}); - else - [~, name, ~] = fileparts(obj.dataRecordingObj.recordingName); - end - if ~iscell(obj.dataRecordingObj.recordingDir) - obj.sortingDir=[obj.dataRecordingObj.recordingDir filesep name '_spikeSort']; - else - obj.sortingDir=[obj.dataRecordingObj.recordingDir{1} '_spikeSort']; - end - initiateDataRecObj=0; - elseif exist(dataRecordingObj)==2 %if input is the name of the metadata file - metaData=load(dataRecordingObj); - sortingDir=metaData.props((strcmp(metaData.props(:,1),'sortingDir')),2); - obj=obj.loadMetaData(sortingDir{1}); - initiateDataRecObj=1; - elseif exist(dataRecordingObj)==7 - obj=obj.loadMetaData(dataRecordingObj); - initiateDataRecObj=1; - else - disp('First input must be a data recording object of a gridSorter metaData file'); - return; - end - end - %verify that the recording dir in the recording object is the same as for grid sorter in case directory was replaced - %if not it changes the dataObj folder assuming that the spikeSorting folder is always a subfolder of the data folder - if ~strcmp(obj.dataRecordingObj.recordingDir,obj.sortingDir(1:numel(obj.dataRecordingObj.recordingDir))) - fprintf('\nPlease notice that the data folder of the recording object is different than the one of gridSorter\nReplacing data folder in dataRecording object!!!\n'); - foldersDataRecObj = regexp(obj.dataRecordingObj.recordingDir,filesep,'split');foldersDataRecObj(strcmp(foldersDataRecObj,''))=[]; - foldersGSObj = regexp(obj.sortingDir,filesep,'split');foldersGSObj(strcmp(foldersGSObj,''))=[]; - nFolder=numel(foldersGSObj); - while nFolder>0 - k = find(strcmp(foldersGSObj(nFolder),foldersDataRecObj)); - if ~isempty(k) - p1=regexp(obj.dataRecordingObj.recordingDir,foldersGSObj(nFolder)); - p2=regexp(obj.sortingDir,foldersGSObj(nFolder)); - obj.dataRecordingObj.recordingDir=[obj.sortingDir(1:p2{1}-1) obj.dataRecordingObj.recordingDir(p1{1}:end)]; - nFolder=0; - else - nFolder=nFolder-1; - end - end - %reinitiate data recording obj - end - - if initiateDataRecObj - fullRecFiles=cellfun(@(x) [obj.dataRecordingObj.recordingDir x],obj.dataRecordingObj.dataFileNames,'UniformOutput',0); - disp('Reinitiating data recording object'); - eval(['obj.dataRecordingObj=' class(obj.dataRecordingObj) '(fullRecFiles);']); - end - - obj=obj.calculateChParameters; - if isempty(obj.nCh) - error('No channels in recording or no layout provided'); - end - - obj=obj.findSortingFiles; - - %make directory in recording folder with spike sorting data - if ~exist(obj.sortingDir,'dir') - mkdir(obj.sortingDir); - disp(['Creating spike sorting folder: ' obj.sortingDir]); - end - - end - - end - - methods - - function deleteSortingFiles(obj) - d=dir([obj.sortingDir filesep 'ch_*spikeDetection.mat']); - if numel(d)>0 - d=dir(obj.sortingDir); - tmpFiles=cellfun(@(x) [obj.sortingDir filesep x],{d.name},'UniformOutput',0); - delete(tmpFiles{:}); - else - fprintf('Please recheck that sorting data exists in this folder: %s\n',obj.sortingDir); - end - end - - function data=getSortedUnit(obj,neuronNames) - tmp=load(obj.sortingFileNames.fittingFile); - nNeu=size(neuronNames,2); - data=cell(1,nNeu); - for i=1:nNeu - pNeu=find(tmp.ic(1,:)==neuronNames(1,i) & tmp.ic(2,:)==neuronNames(2,i)); - data{i}=tmp.t(tmp.ic(3,pNeu):tmp.ic(4,pNeu)); - end - end - - function data=getSortedData(obj,vars) - if nargin==1 - data=load(obj.sortingFileNames.fittingFile); - else - if iscell(vars) - data=load(obj.sortingFileNames.fittingFile,vars{:}); - else - data=load(obj.sortingFileNames.fittingFile,vars); - end - end - end - - function data=getPostProcessedData(obj,vars) - if nargin==1 - data=load(obj.sortingFileNames.postProcessingAnalysisFile); - else - if iscell(vars) - data=load(obj.sortingFileNames.postProcessingAnalysisFile,vars{:}); - else - data=load(obj.sortingFileNames.postProcessingAnalysisFile,vars); - end - end - end - - function data=getSTData(obj,vars) - if nargin==1 - data=load(obj.sortingFileNames.STWaveformFile); - else - if iscell(vars) - data=load(obj.sortingFileNames.STWaveformFile,vars{:}); - else - data=load(obj.sortingFileNames.STWaveformFile,vars); - end - end - end - - [obj,t,ic,avgWaveform]=runSorting(obj) - - obj=spikeDetection(obj) - - gridObj=detectedSpikes2TIC(gridObj,varargin); - - [obj,spikeFeaturesAll]=spikeFeatureExtraction(obj) - - [obj,idx,initIdx,nClusters,avgSpikeWaveforms,stdSpikeWaveforms]=spikeClustering(obj) - - [obj,avgWF,stdWF,ch,mergedNeurons]=spikeMerging(obj) - - [obj,t,ic]=spikeFitting(obj) - - obj=spikePostProcessing(obj,tStartEnd) - - obj=calculateChParameters(obj) - - obj=findSortingFiles(obj) - - obj=setSortingFilesMainDir(obj) - - obj=getSpikeTrigWF(obj,startEnd); - - plotSpikeTrigWF(obj,startEnd,printFolder); - - [publicProps]=getProperties(obj) - - obj=manuallySelectValidUnits(obj) - - [obj, er]=assessQuality(obj) - - [obj,metaDataExistFlag] = loadMetaData(obj,dataRecordingFolder) - - saveMetaData(obj) - end %methods - - methods (Static) - - [clusterMerged,Merge]=SpikeTempDiffMerging(spikeShapes,Clusters,Templates,crit) - - [gc,f]=projectionMerge(spikeFeatures,initIdx,varargin) - - end %methods (static) - -end diff --git a/spikeSorting/@gridSorter/gridSorterOldFunctional.backup b/spikeSorting/@gridSorter/gridSorterOldFunctional.backup deleted file mode 100644 index 5b126bf..0000000 --- a/spikeSorting/@gridSorter/gridSorterOldFunctional.backup +++ /dev/null @@ -1,1724 +0,0 @@ -classdef gridSorter < handle - properties (Constant) - gridSorterVersion=1.00; - end - properties (SetAccess=public) - overwriteSpikeExtraction=0; - overwriteFeatureExtraction=0; - overwriteClustering=0; - overwriteMerging=0; - overwriteFitting=0; - overwritePostProcessignAnalysis=0; - - sortingDir - runWithoutSaving2File=false; - fastPrinting=0; - saveFigures=1; - - selectedChannelSubset=[]; - dataRecordingObj %the data recording object - sortingFileNames - - upSamplingFrequencySpike=60000; - localGridSize=3; %must be an odd number. If empty extracts using all channels - localGridExt=1; - - detectionChunkOverlap=1; %ms - - %for using a 16 bit signed integer to represent the spike shapes - detectionMaxSpikeAmp=1000; - detectionNQuantizationBits=16; - detectionGaussianityWindow=20;%ms - detectionPreSpikeWindow=2;%ms - detectionPostSpikeWindow=3;%ms - detectionSpikeTimeShiftInterval=1;%ms - the maximal interval on which the global spike minima is calculated - detectionPeakDetectionSmoothingWindow=0.3; %ms - the smoothing scale for detection of the exact spike occurance - detectionKurtosisNoiseThreshold=3; - detectionSpikeDetectionThresholdStd=5; - detectionMaxChunkSize=2*60*1000; %[ms] - detectionMinimumDetectionIntervalMs=0.5;%ms - detectionRemoveSpikesNotExtremalOnLocalGrid=true; %removes all spike that have a stronger minimum on another channel surrounding the detection channel on the grid - - filterHighPassPassCutoff=250; - filterHighPassStopCutoff=200; - filterLowPassPassCutoff=2500; - filterLowPassStopCutoff=3500; - filterAttenuationInHighpass=6; - filterAttenuationInLowpass=6; - filterRippleInPassband=0.4; - filterDesign='ellip'; - - featuresNWaveletCoeff=30; %number of wavelet coeff to extract - featuresDimensionReductionPCA=6; - featuresReduceDimensionsWithPCA=true; - featuresSelectedWavelet='haar'; %the mother wavelet - featuresWTdecompositionLevel=4; %the level of decomposition - featuresFeatureExtractionMethod='wavelet'; %the method for extracting features - featuresConcatenateElectrodes=true; %concatenate all surrounding electrodes to 1 big voltage trace - - clusteringMaxSpikesToCluster=10000; %maximum number of spikes to feed to feature extraction and clustering (not to template matching) - clusteringMethod='meanShift';%'meanShift';%'kMeans';%,'kMeans_MSEdistance';%'kMeans_merge';%'kMeans_merge'; %'kMeans_sil'/'kMeans_merge'/'GMMEM' - clusteringMergingMethod='projectionMeanStd';%'projectionMeanStd';%'MSEdistance' - clusteringMaxIter=1000; %max itteration for clustering algorithm - clusteringNReplicates=50; %number of obj.clusteringNReplicates in clustering algorithm - clusteringInitialClusterCentersMethod='cluster'; %method for initial conditions in k-means algorithm - clusteringMaxPointsInSilhoutte=1000; %the maximal number of data points per cluster used for silloute quality estimation - clusteringMergeThreshold=0.18; %threshold for merging clusters %the higher the threshold the less cluster will merge - clusteringSTDMergeFac=2; %the fraction of a gaussian to check from the crossing point on both sides (the higher the more clusters separate into groups) - clusteringRunSecondMerging=0; - clusteringMaxClusters=12; %the maximum number of clusters for a specific channels - clusteringMinimumChannelRate=0.01; %[Hz] - clusteringMinNSpikesCluster=10; - clusteringMinSpikesTotal=50; %do not attempt to cluster channels with less spikes - clusteringPlotProjection=1; - clusteringPlotClassification=1; - - mergingThreshold=0.1; - mergingRecalculateTemplates=true; - mergingNStdSpikeDetection=4; - mergingAllignSpikeBeforeAveraging=true; - mergingAllignWaveShapes=true; - mergingTestInitialTemplateMerging=false; - mergingPlotStatistics=true; - mergingNStdNoiseDetection=6; - mergingPreSpike4NoiseDetection=0.2; - mergingPostSpike4NoiseDetection=0.2; - mergingNoiseThreshold=0.2; - mergingMaxSpikeShift=1; %ms - - fittingTemplateMethod=1; - fittingMaxLag=1.6; - fittingLagIntervalSamples=3; - - postMaxSpikes2Present=1000; - postPlotAllAvgSpikeTemplates=true; - postExtractFilteredWaveformsFromSpikeTimes=true; - postExtractRawLongWaveformsFromSpikeTimes=true; - postFilteredSNRStartEnd=[-1 1]; - postRawSNRStartEnd=[5 40]; - postPlotFilteredWaveforms=true; - postPlotRawLongWaveforms=true; - postPlotSpikeReliability=true; - postPreFilteredWindow=2; - postTotalFilteredWindow=5; - postPreRawWindow=10; - postTotalRawWindow=90; - - end - - properties (SetAccess=protected) - nCh - chPar - arrayExt - - detectionInt2uV - filterObj - end - - properties (SetObservable, AbortSet = true, SetAccess=public) - end - - properties (Hidden, SetAccess=protected) - - end - methods - %class constractor - function obj=gridSorter(dataRecordingObj,varargin) - %addlistener(obj,'visualFieldBackgroundLuminance','PostSet',@obj.initializeBackground); %add a listener to visualFieldBackgroundLuminance, after its changed its size is updated in the changedDataEvent method - - %Collects all options - if properties are given as a 'propertyName',propertyValue series - for i=1:2:length(varargin) - eval(['obj.' varargin{i} '=' 'varargin{i+1};']) - end - - if nargin==1 - obj.dataRecordingObj=dataRecordingObj; - else - disp('Data recording object not enter. In later versions a GUI will be imlemented for recording selection'); - end - [~, name, ~] = fileparts(obj.dataRecordingObj.recordingName{1}); - obj.sortingDir=[obj.dataRecordingObj.recordingDir filesep name '_spikeSort']; - - %make directory in recording folder with spike sorting data - if ~exist(obj.sortingDir,'dir') - mkdir(obj.sortingDir); - disp(['Creating spike sorting folder: ' obj.sortingDir]); - end - - obj=obj.calculateChParameters; - - end - - function [obj,t,ic,avgWaveform]=runSorting(obj) - %default variables - - %initiate variables - t=[];ic=[];avgWaveform=[]; - obj=obj.findSortingFiles; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%% spike Detection %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - tic; - if all(obj.sortingFileNames.spikeDetectionExist) %check for the existence of spike shapes - disp('Sorting will be preformed on previously detected waveforms'); - else - obj=obj.spikeDetectionNSK; - end - toc; - - %save meta-data - [props]=getProperties(obj); - save([obj.sortingDir filesep 'metaData.mat'],'props'); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%% feature extraction %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - tic; - if all(obj.sortingFileNames.featureExtractionExist) %check for the existence of spike shapes - disp('Sorting will be preformed on previously extracted features'); - else - obj=obj.spikeFeatureExtractionNSK; - end - toc; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% clustering %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - tic; - if all(obj.sortingFileNames.clusteringExist) %check for the existence of spike shapes - disp('Sorting will be preformed on previously extracted clusters'); - else - obj=obj.spikeClusteringNSK; - end - toc; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Merging duplicate neurons %%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - tic; - if obj.sortingFileNames.mergedAvgWaveformExist %check for the existence of spike shapes - disp('Sorting will be preformed on previously merged clusters'); - else - obj=obj.spikeMergingClustersNSK; - end - toc; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Fitting duplicate neurons %%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - tic; - if obj.sortingFileNames.fittingExist %check for the existence of spike shapes - disp('No fitting performed!!!'); - else - obj=obj.spikeFittingNSK; - end - toc; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%% General final plots and access sorting quality %%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - tic; - if all(obj.sortingFileNames.postProcessignAnalysisExist) %check for the existence of spike shapes - disp('No post analysis performed!!!'); - else - obj=obj.spikePostProcessingNSK; - end - toc; - - end - - function obj=calculateChParameters(obj) - - %determine channels - if isempty(obj.selectedChannelSubset) - obj.selectedChannelSubset=obj.dataRecordingObj.channelNumbers; %take all channel in the recording - end - obj.nCh=numel(obj.selectedChannelSubset); - obj.chPar.s2r=obj.selectedChannelSubset; %transformation between the serial channel number and the real ch number - obj.chPar.r2s(obj.selectedChannelSubset)=1:obj.nCh; %transformation between the real channel number and the serial ch number - - %get channel layout - obj.chPar.En=obj.dataRecordingObj.chLayoutNumbers; - - %limit layout only to the serial channels selected by user - obj.chPar.rEn=obj.chPar.En; - obj.chPar.rEn(~isnan(obj.chPar.En))=obj.chPar.r2s(obj.chPar.En(~isnan(obj.chPar.En))); - obj.chPar.rEn(obj.chPar.rEn==0)=NaN; - [nRowsTmp,nColsTmp]=size(obj.chPar.En); - - localGridSizeExt=obj.localGridSize+obj.localGridExt*2; - - %initiate arrays - obj.chPar.surChExt=cell(1,obj.nCh);obj.chPar.pValidSurChExt=cell(1,obj.nCh);obj.chPar.surChExtVec=cell(1,obj.nCh);obj.chPar.pCenterCh=zeros(1,obj.nCh);obj.chPar.nValidChExt=zeros(1,obj.nCh);obj.chPar.pSurCh=cell(1,obj.nCh);obj.chPar.pSurChOverlap=cell(1,obj.nCh); - if ~isempty(localGridSizeExt) - obj.arrayExt=(obj.localGridSize-1)/2; - overheadGridExtension=(localGridSizeExt-1)/2; - EnExt=NaN(nRowsTmp+overheadGridExtension*2,nColsTmp+overheadGridExtension*2); - EnExt(1+overheadGridExtension:end-overheadGridExtension,1+overheadGridExtension:end-overheadGridExtension)=obj.chPar.rEn; - for i=1:obj.nCh - [x,y]=find(EnExt==i); - - %find the surrounding channels on which feature extraction will be performed - surCh=EnExt(x-obj.arrayExt:x+obj.arrayExt,y-obj.arrayExt:y+obj.arrayExt); - pValidSurCh=find(~isnan(surCh)); %do not remove find - - %find the channels that are overhead step from the central channel - these are the channels who's waveforms should be checked for merging - surChOverlap=EnExt(x-obj.localGridExt:x+obj.localGridExt,y-obj.localGridExt:y+obj.localGridExt); - surChOverlap(obj.localGridExt+1,obj.localGridExt+1)=NaN; - pValidSurChOverlap=find(~isnan(surChOverlap)); %do not remove find - - %find the extended channels for merging of the same neurons detected on nearby channels - obj.chPar.surChExt{i}=EnExt(x-overheadGridExtension:x+overheadGridExtension,y-overheadGridExtension:y+overheadGridExtension); - obj.chPar.pValidSurChExt{i}=find(~isnan(obj.chPar.surChExt{i})); %do not remove find - obj.chPar.nValidChExt(i)=numel(obj.chPar.pValidSurChExt{i}); - - obj.chPar.surChExtVec{i}=obj.chPar.surChExt{i}(obj.chPar.pValidSurChExt{i}(:))'; - obj.chPar.pCenterCh(i)=find(obj.chPar.surChExtVec{i}==i); %the position of the central channel in surChExtVec - [~,obj.chPar.pSurCh{i}]=intersect(obj.chPar.surChExtVec{i},surCh(pValidSurCh(:))); - [~,obj.chPar.pSurChOverlap{i}]=intersect(obj.chPar.surChExtVec{i},surChOverlap(pValidSurChOverlap(:))); - end - end - %map channel intersections - for i=1:obj.nCh - for j=obj.chPar.surChExtVec{i}(obj.chPar.pSurChOverlap{i}) %the trivial case : (i,i) is also included (can be remove in not required) - [obj.chPar.sharedChNames{i}{j},obj.chPar.pSharedCh1{i}{j},obj.chPar.pSharedCh2{i}{j}]=intersect(obj.chPar.surChExtVec{i},obj.chPar.surChExtVec{j}); - end - end - - end - - function obj=findSortingFiles(obj) - %check conditions for recalculating the different stages of spike sorting. Notice that for the 3 first procedures only, calcululation of a subset of uncalculated channels is possiblee - for i=1:obj.nCh - obj.sortingFileNames.spikeDetectionFile{i}=[obj.sortingDir filesep 'ch_' num2str(obj.chPar.s2r(i)) '_spikeDetection.mat']; - obj.sortingFileNames.spikeDetectionExist(i)=exist(obj.sortingFileNames.spikeDetectionFile{i},'file'); - - obj.sortingFileNames.featureExtractionFile{i}=[obj.sortingDir filesep 'ch_' num2str(obj.chPar.s2r(i)) '_featureExtraction.mat']; - obj.sortingFileNames.featureExtractionExist(i)=exist(obj.sortingFileNames.featureExtractionFile{i},'file'); - - obj.sortingFileNames.clusteringFile{i}=[obj.sortingDir filesep 'ch_' num2str(obj.chPar.s2r(i)) '_clustering.mat']; - obj.sortingFileNames.clusteringExist(i)=exist(obj.sortingFileNames.clusteringFile{i},'file'); - end - - obj.sortingFileNames.avgWaveformFile=[obj.sortingDir filesep 'AllClusteredWaveforms.mat']; - - obj.sortingFileNames.mergedAvgWaveformFile=[obj.sortingDir filesep 'AllMergedWaveforms.mat']; - obj.sortingFileNames.mergedAvgWaveformExist=exist(obj.sortingFileNames.mergedAvgWaveformFile,'file'); - - obj.sortingFileNames.fittingFile=[obj.sortingDir filesep 'spikeSorting.mat']; - obj.sortingFileNames.fittingExist=exist(obj.sortingFileNames.fittingFile,'file'); - - obj.sortingFileNames.postProcessignAnalysisFile=[obj.sortingDir filesep 'postProcessignAnalysis.mat']; - obj.sortingFileNames.postProcessignAnalysisExist=exist(obj.sortingFileNames.postProcessignAnalysisFile,'file'); - if obj.sortingFileNames.postProcessignAnalysisExist - tmp=load(obj.sortingFileNames.postProcessignAnalysisFile,'postProcessignAnalysisExist'); - obj.sortingFileNames.postProcessignAnalysisExist=tmp.postProcessignAnalysisExist; - end - - %the overwriting of files needed, treat all files as non existing - if obj.overwriteSpikeExtraction,obj.sortingFileNames.spikeDetectionExist(:)=0;end; - if obj.overwriteFeatureExtraction,obj.sortingFileNames.featureExtractionExist(:)=0;end; - if obj.overwriteClustering,obj.sortingFileNames.clusteringExist(:)=0;end; - if obj.overwriteMerging,obj.sortingFileNames.mergedAvgWaveformExist=0;end; - if obj.overwriteFitting,obj.sortingFileNames.fittingExist=0;end; - if obj.overwritePostProcessignAnalysis,obj.sortingFileNames.postProcessignAnalysisExist=0;end; - end - - function obj=getHighpassFilter(obj) - obj.filterObj=filterData(obj.dataRecordingObj.samplingFrequency); - obj.filterObj.highPassPassCutoff=obj.filterHighPassPassCutoff; - obj.filterObj.highPassStopCutoff=obj.filterHighPassStopCutoff; - obj.filterObj.lowPassPassCutoff=obj.filterLowPassPassCutoff; - obj.filterObj.lowPassStopCutoff=obj.filterLowPassStopCutoff; - obj.filterObj.attenuationInHighpass=obj.filterAttenuationInHighpass; - obj.filterObj.attenuationInLowpass=obj.filterAttenuationInLowpass; - obj.filterObj.filterDesign=obj.filterDesign; - obj.filterRippleInPassband=obj.filterRippleInPassband; - - %obj.filterObj.highPassCutoff=obj.filterHighPassPassCutoff; - %obj.filterObj.lowPassCutoff=obj.filterLowPassPassCutoff; - %obj.filterObj.filterOrder=8; - - obj.filterObj=obj.filterObj.designBandPass; - end - - function obj=spikeDetectionNSK(obj) - %Todo: - %Add detection of multiple spikes - - %determine quantization - obj.detectionInt2uV=obj.detectionMaxSpikeAmp/2^(obj.detectionNQuantizationBits-1); - - obj=obj.getHighpassFilter; - - %start spike detection - fprintf('\nRunning spike detection on %s...',obj.dataRecordingObj.dataFileNames{1}); - - upSamplingFactor=obj.upSamplingFrequencySpike/obj.dataRecordingObj.samplingFrequency; - if upSamplingFactor~=round(upSamplingFactor) %check that upsampling factor is an integer - upSamplingFactor=round(upSamplingFactor); - obj.upSamplingFrequencySpike=upSamplingFactor*obj.dataRecordingObj.samplingFrequency; - disp(['upSampling factor was not an integer and was rounded to: ' num2str(upSamplingFactor)]); - end - - gaussianityWindow=obj.detectionGaussianityWindow/1000*obj.dataRecordingObj.samplingFrequency; - testSamples=gaussianityWindow*1000; - - preSpikeSamples=obj.detectionPreSpikeWindow/1000*obj.dataRecordingObj.samplingFrequency; %must be > spikePeakInterval - postSpikeSamples=obj.detectionPostSpikeWindow/1000*obj.dataRecordingObj.samplingFrequency; %must be > spikePeakInterval - spikeTimeShiftIntervalSamples=obj.detectionSpikeTimeShiftInterval/1000*obj.dataRecordingObj.samplingFrequency; - postSpikeSamplesInitial=postSpikeSamples+spikeTimeShiftIntervalSamples; - - timeVec=-preSpikeSamples:postSpikeSamplesInitial; - intrpTimeVec=timeVec(1):(1/upSamplingFactor):timeVec(end); - pZeroTimeVec=find(intrpTimeVec>=0,1,'first'); - - preSpikeSamplesIntrp=preSpikeSamples*upSamplingFactor; %must be > spikePeakInterval - postSpikeSamplesIntrp=postSpikeSamples*upSamplingFactor; %must be > spikePeakInterval - spikeTimeShiftIntervalIntrp=spikeTimeShiftIntervalSamples*upSamplingFactor; %must be > spikePeakInterval - - minimumDetectionIntervalSamplesIntrp=obj.detectionMinimumDetectionIntervalMs/1000*obj.dataRecordingObj.samplingFrequency*upSamplingFactor; - peakDetectionSmoothingSamples=round(obj.detectionPeakDetectionSmoothingWindow/1000*obj.dataRecordingObj.samplingFrequency*upSamplingFactor); - peakSmoothingKernel=fspecial('gaussian', [3*peakDetectionSmoothingSamples 1] ,peakDetectionSmoothingSamples); - - %determine the chunck size - if obj.detectionMaxChunkSize>obj.dataRecordingObj.recordingDuration_ms - startTimes=0; - endTimes=obj.dataRecordingObj.recordingDuration_ms; - else - startTimes=0:obj.detectionMaxChunkSize:obj.dataRecordingObj.recordingDuration_ms; - endTimes=[startTimes(2:end)-obj.detectionChunkOverlap obj.dataRecordingObj.recordingDuration_ms]; - end - nChunks=numel(startTimes); - - obj.nCh=numel(obj.chPar.s2r); - - matFileObj=cell(1,obj.nCh); - if obj.runWithoutSaving2File %if saving data is not required - obj.runWithoutSaving2File=true; - spikeShapesAll=cell(obj.nCh,nChunks); - spikeTimesAll=cell(obj.nCh,nChunks); - else - obj.runWithoutSaving2File=false; - for i=find(obj.sortingFileNames.spikeDetectionExist==0) - matFileObj{i} = matfile(obj.sortingFileNames.spikeDetectionFile{i},'Writable',true); - matFileObj{i}.spikeShapes=zeros(preSpikeSamplesIntrp+postSpikeSamplesIntrp,0,obj.chPar.nValidChExt(i),'int16'); - end - end - - %initiate arrays - Th=zeros(obj.nCh,nChunks);nCumSpikes=zeros(1,obj.nCh); - fprintf('\nExtracting spikes from chunks (total %d): ',nChunks); - for j=1:nChunks - fprintf('%d ',j); - %get data - MAll=squeeze(obj.filterObj.getFilteredData(obj.dataRecordingObj.getData(obj.chPar.s2r(1:obj.nCh),startTimes(j),endTimes(j)-startTimes(j))))'; - nSamples=size(MAll,1); - for i=find(obj.sortingFileNames.spikeDetectionExist==0) %go over all channels that require rewriting - %get local data - Mlong=MAll(:,obj.chPar.surChExtVec{i}); - - %estimate channel noise - tmpData=buffer(Mlong(1:min(testSamples,nSamples),obj.chPar.pCenterCh(i)),gaussianityWindow,gaussianityWindow/2); - noiseSamples=tmpData(:,kurtosis(tmpData,0)Th(i,j) & Mlong(2:end,obj.chPar.pCenterCh(i))preSpikeSamples & thresholdCrossings0 - nCumSpikes(i)=nCumSpikes(i)+numel(spikeTimesTmp); - matFileObj{i}.spikeShapes(:,(nCumSpikes(i)-tmpSpikeCount+1):nCumSpikes(i),:)=int16(M./obj.detectionInt2uV); - end - else - spikeShapesAll{i,j}=int16(M./obj.detectionInt2uV); - end - else - spikeTimesAll{i,j}=[]; - if obj.runWithoutSaving2File - spikeShapesAll{i,j}=[]; - end - end - end - end - clear MAll Mlong M; - - if ~obj.runWithoutSaving2File %write files to disk - for i=find(obj.sortingFileNames.spikeDetectionExist==0) - matFileObj{i}.Th=Th(i,:); - - matFileObj{i}.spikeTimes=cell2mat(spikeTimesAll(i,:)); - matFileObj{i}.preSpikeSamplesIntrp=preSpikeSamplesIntrp; - matFileObj{i}.postSpikeSamplesIntrp=postSpikeSamplesIntrp; - matFileObj{i}.upSamplingFrequencySpike=obj.upSamplingFrequencySpike; - matFileObj{i}.minimumDetectionIntervalSamplesIntrp=minimumDetectionIntervalSamplesIntrp; - matFileObj{i}.detectionInt2uV=obj.detectionInt2uV; - end - else %keep files in memory - obj.spikeDetectionData.spikeShapes=cell(1,obj.nCh); - obj.spikeDetectionData.spikeTimes=cell(1,obj.nCh); - for i=find(obj.sortingFileNames.spikeDetectionExist>0) - obj.spikeDetectionData.spikeShapes{i}=cell2mat(spikeShapesAll(i,:)); - obj.spikeDetectionData.spikeTimes{i}=cell2mat(spikeTimesAll(i,:)); - end - obj.spikeDetectionData.Th=Th; - - obj.spikeDetectionData.preSpikeSamplesIntrp=preSpikeSamplesIntrp; - obj.spikeDetectionData.postSpikeSamplesIntrp=postSpikeSamplesIntrp; - obj.spikeDetectionData.minimumDetectionIntervalSamplesIntrp=minimumDetectionIntervalSamplesIntrp; - obj.spikeDetectionData.upSamplingFrequencySpike=obj.upSamplingFrequencySpike; - obj.spikeDetectionData.detectionInt2uV=obj.detectionInt2uV; - end - end - - - function [obj,spikeFeaturesAll]=spikeFeatureExtractionNSK(obj) - - if isempty(obj.sortingDir) - obj.runWithoutSaving2File=true; - spikeFeaturesAll=cell(1,obj.nCh); - else - obj.runWithoutSaving2File=false; - end - - fprintf('\nExtracting spike features from channels (total %d): ',obj.nCh); - for i=find(obj.sortingFileNames.featureExtractionExist==0) - spikeFeatures=[]; - fprintf('%d ',i); - - if ~exist(obj.sortingFileNames.spikeDetectionFile{i},'file') - warning(['No spike detection file was found for Channel ' num2str(i) '. Feature extraction not performed!']); - continue; - else - load(obj.sortingFileNames.spikeDetectionFile{i}); - end - - if ~isempty(spikeShapes) - %choose a random subset of the spikes for clustering - nSurroundingChannels=numel(obj.chPar.pSurCh{i}); - [nSamples,nSpikes,nLocalCh]=size(spikeShapes); - - nSpikes4Clustering=min(obj.clusteringMaxSpikesToCluster,nSpikes); - - sd=[]; - switch obj.featuresFeatureExtractionMethod - case 'wavelet' - spikeShapes=double(spikeShapes) .* detectionInt2uV; - if obj.featuresConcatenateElectrodes==1 %all waveforms are ordered channel by channel - spikeFeatures=wavedec(spikeShapes(:,1,obj.chPar.pSurCh{i}),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); - nCoeffs=numel(spikeFeatures); - spikeFeatures=zeros(nSpikes4Clustering,nCoeffs); - for j=1:nSpikes4Clustering - spikeFeatures(j,:)=wavedec(spikeShapes(:,j,obj.chPar.pSurCh{i}),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); %'haar','coif1' - end - - spikeFeatures2=zeros(nSpikes4Clustering,nCoeffs); - for j=1:nSpikes4Clustering - spikeFeatures2(j,:)=wavedec(permute(spikeShapes(:,j,obj.chPar.pSurCh{i}),[3 2 1]),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); %'haar','coif1' - end - spikeFeatures=[spikeFeatures spikeFeatures2]; - else - spikeFeatures=wavedec(spikeShapes(:,1,obj.chPar.pSurCh{i}(1)),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); - nCoeffs=numel(spikeFeatures); - spikeFeatures=zeros(nCoeffs,nSpikes4Clustering,nSurroundingChannels); - for j=1:nSpikes4Clustering - for k=1:nSurroundingChannels - spikeFeatures(:,j,k)=wavedec(spikeShapes(:,j,obj.chPar.pSurCh{i}(k)),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); %'haar','coif1' - end - end - spikeFeatures=reshape(permute(spikeFeatures,[1 3 2]),[size(spikeFeatures,1)*size(spikeFeatures,3) size(spikeFeatures,2)])'; - nCoeffs=nCoeffs*nSurroundingChannels; - end - for j=1:(nCoeffs*2) % KS test for coefficient selection - thr_dist = std(spikeFeatures(:,j)) * 3; - thr_dist_min = mean(spikeFeatures(:,j)) - thr_dist; - thr_dist_max = mean(spikeFeatures(:,j)) + thr_dist; - aux = spikeFeatures(spikeFeatures(:,j)>thr_dist_min & spikeFeatures(:,j) 10; - [ksstat]=test_ks(aux); - sd(j)=ksstat; - else - sd(j)=0; - end - end - [~,tmp1]=sort(sd(1:nCoeffs),'descend'); - [~,tmp2]=sort(sd(nCoeffs+1:end),'descend'); - spikeFeatures=spikeFeatures(:,[tmp1(1:obj.featuresNWaveletCoeff/2) nCoeffs+tmp2(1:obj.featuresNWaveletCoeff/2)]); - - if obj.featuresReduceDimensionsWithPCA - [PCAsimMat,spikeFeatures] = princomp(spikeFeatures); %run PCA for visualization purposes - spikeFeatures=spikeFeatures(:,1:obj.featuresDimensionReductionPCA); - end - - case 'PCA' %this option was tested and gives worse results than wavelets - spikeShapes=double(spikeShapes(:,:,obj.chPar.pSurCh{i})) .* detectionInt2uV; - [~,spikeFeatures] = princomp(reshape(permute(spikeShapes,[1 3 2]),[nSamples*numel(obj.chPar.pSurCh{i}) nSpikes])); - spikeFeatures=spikeFeatures(1:obj.featuresDimensionReductionPCA,:)'; - end - end - if ~obj.runWithoutSaving2File - save(obj.sortingFileNames.featureExtractionFile{i},'spikeFeatures','-v7.3'); - else - spikeFeaturesAll{i}=spikeFeatures; - end - end - end - - - function [idx,initIdx,nClusters,avgSpikeWaveforms,stdSpikeWaveforms]=spikeClusteringNSK(obj) - - avgClusteredWaveforms=cell(1,obj.nCh); - stdClusteredWaveforms=cell(1,obj.nCh); - - if isempty(obj.sortingDir) - obj.runWithoutSaving2File=true; - idxAll=cell(1,obj.nCh); - initIdxAll=cell(1,obj.nCh); - nClustersAll=cell(1,obj.nCh); - else - obj.runWithoutSaving2File=false; - end - - fprintf('\nClustering on channel (total %d): ',obj.nCh); - for i=find(obj.sortingFileNames.clusteringExist==0) %go over all channels in the recording - fprintf('%d ',i); - MaxClustersTmp=obj.clusteringMaxClusters; - - if ~exist(obj.sortingFileNames.featureExtractionFile{i},'file') - warning(['No feature extraction file was found for Channel ' num2str(i) '. Clustering not performed!']); - continue; - else - load(obj.sortingFileNames.featureExtractionFile{i}); - load(obj.sortingFileNames.spikeDetectionFile{i},'spikeTimes'); - end - - [nSpikes,nFeatures]=size(spikeFeatures); - - if nSpikes >= obj.clusteringMinSpikesTotal && nSpikes >= (spikeTimes(end)-spikeTimes(1))/1000*obj.clusteringMinimumChannelRate - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%% Clustering %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - switch obj.clusteringMethod - case 'kMeans' - % set options to k-Means - opts = statset('obj.clusteringMaxIter',obj.clusteringMaxIter); - try - [initIdx] = kmeans(spikeFeatures,obj.clusteringMaxClusters,'options',opts,... - 'emptyaction','singleton','distance','city','onlinephase','on','obj.clusteringNReplicates',obj.clusteringNReplicates,'start',obj.clusteringInitialClusterCentersMethod); - catch %if the number of samples is too low, kmeans gives an error -> try kmeans with a lower number of clusters - MaxClustersTmp=round(obj.clusteringMaxClusters/2); - [initIdx] = kmeans(spikeFeatures,MaxClustersTmp,'options',opts,... - 'emptyaction','singleton','distance','city','onlinephase','on','obj.clusteringNReplicates',obj.clusteringNReplicates,'start',obj.clusteringInitialClusterCentersMethod); - end - case 'meanShift' - initIdx=zeros(nSpikes,1); - out=MSAMSClustering(spikeFeatures'); - for j=1:numel(out) - initIdx(out{j})=j; - end - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%% Merging %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - switch obj.clusteringMergingMethod - case 'MSEdistance' - %calculate templates - load(obj.sortingFileNames.spikeDetectionFile{i},'spikeShapes'); - avgSpikeWaveforms=zeros(nSpikeSamples,max(1,MaxClustersTmp),nSurroundingChannels); - for j=1:MaxClustersTmp - avgSpikeWaveforms(:,j,:)=median(spikes4Clustering(:,initIdx==j,:),2); - end - - [gc,Merge]=obj.SpikeTempDiffMerging(permute(spikes4Clustering,[2 1 3]),initIdx,permute(avgSpikeWaveforms,[3 1 2])); - - if obj.saveFigures - f1=figure('Position',[50 50 1400 900]); - set(f1,'PaperPositionMode','auto'); - if obj.fastPrinting - imwrite(frame2im(getframe(f1)),[obj.sortingDir filesep 'Ch_' num2str(obj.chPar.s2r(i)) 'projectionTest.jpeg'],'Quality',90); - else - print([obj.sortingDir filesep 'Ch_' num2str(obj.chPar.s2r(i)) 'projectionTest'],'-djpeg','-r300'); - end - close(f1); - end - - case 'projectionMeanStd' - [gc,f1]=obj.projectionMerge(spikeFeatures,initIdx,'obj.clusteringMinNSpikesCluster',obj.clusteringMinNSpikesCluster,'obj.clusteringSTDMergeFac',obj.clusteringSTDMergeFac,'obj.clusteringMergeThreshold',obj.clusteringMergeThreshold,'obj.clusteringPlotProjection',obj.clusteringPlotProjection); - - if obj.saveFigures && ~isempty(f1); - set(f1,'PaperPositionMode','auto'); - if obj.fastPrinting - imwrite(frame2im(getframe(f1)),[obj.sortingDir filesep 'Ch_' num2str(obj.chPar.s2r(i)) 'projectionTest.jpeg'],'Quality',90); - else - print([obj.sortingDir filesep 'Ch_' num2str(obj.chPar.s2r(i)) 'projectionTest'],'-djpeg','-r300'); - end - close(f1); - end - - if obj.clusteringRunSecondMerging - uniqueClusters=unique(gc); - nClusters=numel(uniqueClusters); - idx=zeros(nSpikes4Clustering,1); - for k=1:nClusters - p=find(gc==uniqueClusters(k)); - for j=1:numel(p) - idx(initIdx==p(j))=k; - end - end - MaxClustersTmp=nClusters; - initIdx=idx; - - [gc,f1]=obj.projectionMerge(spikeFeatures,initIdx,'obj.clusteringMinNSpikesCluster',obj.clusteringMinNSpikesCluster,'obj.clusteringSTDMergeFac',obj.clusteringSTDMergeFac,'obj.clusteringMergeThreshold',obj.clusteringMergeThreshold,'obj.clusteringPlotProjection',obj.clusteringPlotProjection); - - if obj.saveFigures - set(f1,'PaperPositionMode','auto'); - if obj.fastPrinting - imwrite(frame2im(getframe(f1)),[obj.sortingDir '\Ch_' num2str(obj.chPar.s2r(i)) 'projectionTest.jpeg'],'Quality',90); - else - print([obj.sortingDir '\Ch_' num2str(obj.chPar.s2r(i)) 'projectionTest'],'-djpeg','-r300'); - end - close(f1); - end - end - end - - %reclassify clusters - uniqueClusters=unique(gc); - nClusters=numel(uniqueClusters); - idx=zeros(nSpikes,1); - for k=1:nClusters - p=find(gc==uniqueClusters(k)); - for j=1:numel(p) - idx(initIdx==p(j))=k; - end - end - - %calculate spikeShape statistics - load(obj.sortingFileNames.spikeDetectionFile{i},'spikeShapes','detectionInt2uV'); - spikeShapes=double(spikeShapes) .* detectionInt2uV; - - [nSpikeSamples,nSpikes,nSurroundingChannels]=size(spikeShapes); - if nSpikes>obj.clusteringMaxSpikesToCluster - spikeShapes=spikeShapes(:,1:obj.clusteringMaxSpikesToCluster,:); - end - - avgSpikeWaveforms=zeros(nSpikeSamples,max(1,nClusters),nSurroundingChannels); - stdSpikeWaveforms=zeros(nSpikeSamples,max(1,nClusters),nSurroundingChannels); - for j=1:nClusters - pCluster=idx==j; - avgSpikeWaveforms(:,j,:)=median(spikeShapes(:,pCluster,:),2); - stdSpikeWaveforms(:,j,:)=1.4826*median(abs(spikeShapes(:,pCluster,:)- bsxfun(@times,avgSpikeWaveforms(:,j,:),ones(1,sum(pCluster),1)) ),2); - nSpk(j)=numel(pCluster); - end - else - fprintf('X '); %to note than no neurons were detected on this electrode - - idx=ones(nSpikes,1); - initIdx=ones(nSpikes,1); - avgSpikeWaveforms=[]; - stdSpikeWaveforms=[]; - nClusters=0; - nSpk=0; - end - - avgClusteredWaveforms{i}=avgSpikeWaveforms; - stdClusteredWaveforms{i}=stdSpikeWaveforms; - nAvgSpk{i}=nSpk; - - if ~obj.runWithoutSaving2File - save(obj.sortingFileNames.clusteringFile{i},'idx','initIdx','nClusters','avgSpikeWaveforms','stdSpikeWaveforms'); - else - idxAll{i}=idx; - initIdxAll{i}=initIdx; - nClustersAll{i}=nClusters; - end - - if obj.clusteringPlotClassification && nClusters>0 - - cmap=lines; - - f2=figure('Position',[100 100 1200 800],'color','w'); - PCAfeaturesSpikeShapePlot(spikeFeatures,spikeShapes,obj.upSamplingFrequencySpike,initIdx,idx,obj.chPar.En,obj.chPar.s2r(obj.chPar.surChExtVec{i}),'hFigure',f2,'cmap',cmap); - - f3=figure('Position',[100 100 1200 800],'color','w'); - featureSubSpacePlot(spikeFeatures,idx,'hFigure',f3,'cmap',cmap); - - if obj.saveFigures - figure(f2); - set(f2,'PaperPositionMode','auto'); - if obj.fastPrinting - imwrite(frame2im(getframe(f2)),[obj.sortingDir '\Ch_' num2str(obj.chPar.s2r(i)) 'classification.jpeg'],'Quality',90); - else - print([obj.sortingDir '\Ch_' num2str(obj.chPar.s2r(i)) 'classification'],'-djpeg','-r300'); - end - - figure(f3); - set(f3,'PaperPositionMode','auto'); - if obj.fastPrinting - imwrite(frame2im(getframe(f3)),[obj.sortingDir '\Ch_' num2str(obj.chPar.s2r(i)) 'featureSpace.jpeg'],'Quality',90); - else - print([obj.sortingDir '\Ch_' num2str(obj.chPar.s2r(i)) 'featureSpace'],'-djpeg','-r300'); - end - if ishandle(f2) - close(f2); - end - if ishandle(f3) - close(f3); - end - end - end %plot initial classification classification - end %go over all channels - - if ~obj.runWithoutSaving2File - save(obj.sortingFileNames.avgWaveformFile,'avgClusteredWaveforms','stdClusteredWaveforms','nAvgSpk'); - end - end - - - function [obj,avgWF,stdWF,ch,mergedNeurons]=spikeMergingClustersNSK(obj) - - avgWF=cell(1,obj.nCh); - stdWF=cell(1,obj.nCh); - ch=cell(1,obj.nCh); - isNoise=cell(1,obj.nCh); - if isempty(obj.sortingDir) - obj.runWithoutSaving2File=true; - else - obj.runWithoutSaving2File=false; - end - - %steepness=1.2; - %nonLin = @(x) x+x./sqrt(1+abs(x).^steepness); - %x=-100:100;plot(x,nonLin(x)); - - load(obj.sortingFileNames.spikeDetectionFile{1},'postSpikeSamplesIntrp','preSpikeSamplesIntrp','preSpikeSamplesIntrp','obj.upSamplingFrequencySpike'); - nSamples=postSpikeSamplesIntrp+preSpikeSamplesIntrp; - preSpikeSamples4NoiseDetection=obj.mergingPreSpike4NoiseDetection*preSpikeSamplesIntrp; - postSpikeSamples4NoiseDetection=obj.mergingPostSpike4NoiseDetection*postSpikeSamplesIntrp; - pSamples4NoiseDetection=round(nSamples/2-preSpikeSamples4NoiseDetection):round(nSamples/2+postSpikeSamples4NoiseDetection); - - maxSpikeShiftSamples=obj.mergingMaxSpikeShift*obj.upSamplingFrequencySpike/1000; - - load(obj.sortingFileNames.avgWaveformFile,'avgClusteredWaveforms','stdClusteredWaveforms','nAvgSpk'); - - validSamplesInTemplate=cell(1,obj.nCh); - isNoise=cell(1,obj.nCh); - for n=1:obj.nCh - for c=1:size(avgClusteredWaveforms{n},2) - tmpSpikes1=squeeze(avgClusteredWaveforms{n}(:,c,:)); - tmpSpikesStd1=squeeze(stdClusteredWaveforms{n}(:,c,:)); - pValid=~(tmpSpikes1>-obj.mergingNStdNoiseDetection*tmpSpikesStd1/sqrt(nAvgSpk{n}(c)-1) & tmpSpikes10 - tmpSpikes1=tmpSpikes1(d+1:end,:); - tmpSpikes2=tmpSpikes2(1:end-d,:); - tmpSpikesStd1=tmpSpikesStd1(d+1:end,:); - tmpSpikesStd2=tmpSpikesStd2(1:end-d,:); - else - tmpSpikes1=tmpSpikes1(1:end+d,:); - tmpSpikes2=tmpSpikes2(-d+1:end,:); - tmpSpikesStd1=tmpSpikesStd1(1:end+d,:); - tmpSpikesStd2=tmpSpikesStd2(-d+1:end,:); - end - end - - %remove from spike shapes all noise points estimated as points below obj.mergingNStdSpikeDetection standard deviation - pValid=~( tmpSpikes1>-obj.mergingNStdSpikeDetection*tmpSpikesStd1/sqrt(nAvgSpk{n1}(c1)-1) & tmpSpikes1-obj.mergingNStdSpikeDetection*tmpSpikesStd2/sqrt(nAvgSpk{n2}(c2)-1) & tmpSpikes2-obj.mergingNStdSpikeDetection*tmpSpikesStd1/sqrt(nAvgSpk{n1}(c1)-1) & tmpSpikes1-obj.mergingNStdSpikeDetection*tmpSpikesStd2/sqrt(nAvgSpk{n2}(c2)-1) & tmpSpikes2= 0 - tmpSpikeShapes(1 : (end-tmpDelays(j)) , : , pComN1)=detectionInt2uV.*double(spikeShapes( (tmpDelays(j)+1) : end , pRelevantSpikes , pComN2)); %there is a conversion 2 double here - else - tmpSpikeShapes(-tmpDelays(j)+1:end,:,pComN1)=detectionInt2uV.*double(spikeShapes(1:end+tmpDelays(j),pRelevantSpikes,pComN2)); %there is a conversion 2 double here - end - %} - newSpikeShapes=cat(2,newSpikeShapes,tmpSpikeShapes); - end - - %newSpikeShapes=permute(allignSpikeShapes(permute(newSpikeShapes,[2 3 1])),[3 1 2]); - %newSpikeShapes(newSpikeShapes==0)=NaN; %to not include in the averages the padding due to spike shifting - - avgSpikeWaveforms=nanmedian(newSpikeShapes,2); - stdSpikeWaveforms=1.4826*nanmedian(abs(newSpikeShapes- bsxfun(@times,avgSpikeWaveforms,ones(1,size(newSpikeShapes,2),1)) ),2); - avgSpikeWaveforms(isnan(avgSpikeWaveforms))=0; %average waveform should not contain NaNs - stdSpikeWaveforms(isnan(stdSpikeWaveforms))=0; %average waveform should not contain NaNs - - [~,pMin]=min(min(avgSpikeWaveforms((preSpikeSamplesIntrp-minimumDetectionIntervalSamplesIntrp):(preSpikeSamplesIntrp+minimumDetectionIntervalSamplesIntrp),:,:),[],1),[],3); - maxChannel=commonCh(pMin); %real channel - pMergedNeuron=find(channel==maxChannel,1,'first'); %select ch with largest amp. if there are several neurons on the same channel with the same waveform just takes the first - if isempty(pMergedNeuron) %for the special case where the peak waveform of the joined neurons sits on a different channel than any of the original neurons - pMergedNeuron=1; - fprintf('Maximum amplitude channel for group %d, channel %d, neuron %d - detected on a different channel than any of the original neurons before merging.\n',i,neuron{i}(:,1),neuron{i}(:,2)); - end - - %M=newSpikeShapes;plotShifted(reshape(permute(M,[1 3 2]),[size(M,1)*size(M,3) size(M,2)]),'verticalShift',30);line([(pMin-1)*size(M,1) pMin*size(M,1)],[0 0],'color','g','lineWidth',3); - %f=figure;h=axes;activityTracePhysicalSpacePlot(h,commonCh,squeeze(avgSpikeWaveforms(:,1,:))',obj.chPar.rEn); - %pause;hold off; - - [commonCh,pComN1,pComN2]=intersect(minimalChMap,obj.chPar.surChExtVec{neuron{i}(pMergedNeuron,1)}); - avgWF{neuron{i}(pMergedNeuron,1)}{neuron{i}(pMergedNeuron,2)}=avgSpikeWaveforms; - stdWF{neuron{i}(pMergedNeuron,1)}{neuron{i}(pMergedNeuron,2)}=stdSpikeWaveforms; - ch{neuron{i}(pMergedNeuron,1)}{neuron{i}(pMergedNeuron,2)}=commonCh; - isNoise{neuron{i}(pMergedNeuron,1)}{neuron{i}(pMergedNeuron,2)}=any(noiseSpike); - - %collect all neurons to remove from waveforms - for j=[1:(pMergedNeuron-1) (pMergedNeuron+1):numel(groups{i})] - neurons2Remove=[neurons2Remove ; neuron{i}(j,:)]; - end - end - end - %remove all merged waveforms - for i=unique(neurons2Remove(:,1))' - p=neurons2Remove(find(neurons2Remove(:,1)==i),2); - for j=1:numel(p) - avgWF{i}{p(j)}=[]; - stdWF{i}{p(j)}=[]; - ch{i}{p(j)}=[]; - isNoise{i}{p(j)}=[]; - end - if all(cellfun(@(x) isempty(x),avgWF{i})) %if after removal the channel i has no neurons this channel has to be replaced by an empty value - avgWF{i}=[]; - stdWF{i}=[]; - ch{i}=[]; - isNoise{i}=[]; - end - end - for i=find(cellfun(@(x) ~isempty(x),avgWF)) - pEmptyNeurons=cellfun(@(x) isempty(x),avgWF{i}); - avgWF{i}(pEmptyNeurons)=[]; - stdWF{i}(pEmptyNeurons)=[]; - ch{i}(pEmptyNeurons)=[]; - isNoise{i}(pEmptyNeurons)=[]; - end - else - % take the average of the largest group as the average - end - mergedNeurons=cellfun(@(x) [x(:,1) x(:,2)],neuron,'UniformOutput',0); - else - mergedNeurons=[]; - end - if ~obj.runWithoutSaving2File - save(obj.sortingFileNames.mergedAvgWaveformFile,'avgWF','stdWF','ch','mergedNeurons','isNoise'); - end - end - - - function [obj,t,ic]=spikeFittingNSK(obj) - - if isempty(obj.sortingDir) - obj.runWithoutSaving2File=true; - else - obj.runWithoutSaving2File=false; - end - - fprintf('\nFitting spikes...'); - load(obj.sortingFileNames.mergedAvgWaveformFile,'avgWF','ch','isNoise'); - - %Plots for testing - %{ - p=cellfun(@(x) numel(x),avgWF); - pV=find(p>0); - nPlots=min(ceil(sqrt(sum(p))),7); - c=1; - for i=1:numel(pV) - for j=1:p(pV(i)) - h=subaxis(nPlots,nPlots,c,'S',0.03,'M',0.03); - activityTracePhysicalSpacePlot(h,ch{pV(i)}{j},0.03*squeeze(avgWF{pV(i)}{j})',obj.chPar.rEn,'scaling','none'); - title([num2str(pV(i)) '-' num2str(j) ', noise=' num2str(isNoise{pV(i)}{j})]); - c=c+1; - end - end - %} - - %get noise thresholds for all channels - for i=1:obj.nCh %go over all channels in the recording - load(obj.sortingFileNames.spikeDetectionFile{i},'Th'); - T(i)=mean(Th); - end - edges=[0.5:1:20.5]; - centers=(edges(1:end-1)+edges(2:end))/2; - gauss=@(x,m,s) (1/s/sqrt(2*pi)).*exp(-(x-m).^2./2./s.^2); - - maxCCLag=obj.fittingMaxLag*obj.upSamplingFrequencySpike/1000; - - lags=[fliplr(0:-obj.fittingLagIntervalSamples:-maxCCLag) obj.fittingLagIntervalSamples:obj.fittingLagIntervalSamples:maxCCLag]; - lag=(numel(lags)-1)/2; - lagSamples=lags((lag+1):end); - - tAll=cell(obj.nCh,1); - fprintf('\nFitting data on Ch (total %d): ',obj.nCh); - for i1=1:obj.nCh %go over all channels in the recording - fprintf('%d ',i1); - tmpWFs=[]; - if ~exist(obj.sortingFileNames.spikeDetectionFile{i1},'file') - warning(['No spike detection file was found for Channel ' num2str(i1) '. Fitting not performed!']); - continue; - else - load(obj.sortingFileNames.spikeDetectionFile{i1},'spikeShapes','spikeTimes','detectionInt2uV'); - [nSamples,nSpikes,nChTmp]=size(spikeShapes); - spikeShapes=double(spikeShapes)*detectionInt2uV; - end - - noiseStd=std(spikeShapes([1:50 251:300],:,:),1); - [stdHist]=histc(squeeze(noiseStd),edges); - [~,pMax]=max(stdHist); - noiseStd=centers(pMax); - - match=[]; - correspCh=[]; - for i2=[i1 obj.chPar.surChExtVec{i1}(obj.chPar.pSurChOverlap{i1})] - for neu=1:numel(avgWF{i2}) - [commonCh,pComN1,pComN2]=intersect(obj.chPar.surChExtVec{i1},ch{i2}{neu}); - %try and revise this criteria - tmpWF=avgWF{i2}{neu}(:,pComN2); - - if obj.fittingTemplateMethod==1 %'minkowski' exp 2 + cross-corr - tmpWF=reshape(tmpWF,[size(tmpWF,1),size(tmpWF,2),1]); - spikes=permute(spikeShapes(:,:,pComN1),[1 3 2]); - tmpMatch=zeros(lag*2+1,nSpikes); - for l=0:lag - %spike is after the template - tmpMatch(lag+l+1,:)=( nanmean(reshape( bsxfun(@minus,spikes((lagSamples(l+1)+1):end,:,:),tmpWF(1:end-lagSamples(l+1),:,:)).^2 , [(nSamples-lagSamples(l+1))*numel(commonCh) nSpikes] )) ).^(1/2); - %spike is before the template - tmpMatch(lag-l+1,:)=( nanmean(reshape( bsxfun(@minus,spikes(1:end-lagSamples(l+1),:,:),tmpWF((lagSamples(l+1)+1):end,:,:)).^2 , [(nSamples-lagSamples(l+1))*numel(commonCh) nSpikes] )) ).^(1/2); - end - match=cat(3,match,tmpMatch); - correspCh=[correspCh ; i2 neu]; - - elseif obj.fittingTemplateMethod==2 %implement 'minkowski' distance with exponent 24 - tmpWF=reshape(tmpWF,[size(tmpWF,1),1,size(tmpWF,2)]); - spikes=reshape(permute(spikeShapes(:,:,pComN1),[1 3 2]),[nSamples*numel(commonCh) nSpikes]); - tmpMatch=bsxfun(@minus,spikes,tmpWF(:)).^2; - tmpMatch=(nanmean(tmpMatch)).^(1/2);%./(nanstd(tmpMatch)+nanstd(tmpWF(:))); - - match=[match ; tmpMatch]; - correspCh=[correspCh ; i2 neu]; - - elseif obj.fittingTemplateMethod==3 - tmpWF=reshape(tmpWF,[size(tmpWF,1),1,size(tmpWF,2)]); - spikes=reshape(permute(spikeShapes(:,:,pComN1),[1 3 2]),[nSamples*numel(commonCh) nSpikes]); - %noiseStd=mean(T)/5; - noiseStd=mean(noiseStd); - tmpMatch=bsxfun(@minus,spikes,tmpWF(:)); - tmpMatch=gauss(0,0,noiseStd)-gauss(tmpMatch,0,noiseStd); - tmpMatch=mean(tmpMatch); - - match=[match ; tmpMatch]; - correspCh=[correspCh ; i2 neu]; - end - - %mS=mean(spikes(:)); - %sS=std(spikes(:)); - %spikes(spikesmS-1*sS)=NaN; - %tmpWF(tmpWFmS-1*sS)=NaN; - - %{ - f=figure('position',[83 120 1699 852]); - M=spikeShapes(:,:,pComN1); - plotShifted(reshape(permute(M,[1 3 2]),[size(M,1)*size(M,3) size(M,2)]),'verticalShift',30);hold on; - M=repmat(tmpWF,[1 nSpikes 1]); - plotShifted(reshape(permute(M,[1 3 2]),[size(M,1)*size(M,3) size(M,2)]),'verticalShift',30,'color','k');set(gca,'YTickLabel',[]); - text(zeros(nSpikes,1),0:30:(30*(nSpikes-1)),num2cell(tmpMatch),'HorizontalAlignment','right'); - pause;close(f); - %} - end - end - if ~isempty(match) - if obj.fittingTemplateMethod==1 - [tmpMin,delay]=min(match,[],1); - [~,idxOut]=min(tmpMin,[],3); - delay=lags(delay(sub2ind(size(delay),ones(1,nSpikes),1:nSpikes,idxOut))); - tAll{i1}=[correspCh(idxOut,[1 2]) (spikeTimes+delay/obj.upSamplingFrequencySpike*1000)']; - else - [~,idxOut]=min(match,[],1); - tAll{i1}=[correspCh(idxOut,[1 2]) spikeTimes']; - end - else - tAll{i1}=[]; - end - %{ - f=figure('position',[83 120 1699 852]); - [~,p]=sort(idxOut); - n=min(numel(p),50); - M=spikeShapes(:,p(1:n),:); - plotShifted(reshape(permute(M,[1 3 2]),[size(M,1)*size(M,3) size(M,2)]),'verticalShift',30);hold on; - text(zeros(n,1),0:30:(30*(n-1)),num2cell(idxOut(p(1:n)))); - pause;close(f); - %} - %{ - M=spikeShapes;plotShifted(reshape(permute(M,[1 3 2]),[size(M,1)*size(M,3) size(M,2)]),'verticalShift',30);line([(pMin-1)*size(M,1) pMin*size(M,1)],[0 0],'color','g','lineWidth',3); - f=figure;load layout_40_Hexa;En=flipud(En); - for c=1:20 - h=subaxis(4,5,c,'S',0.03,'M',0.03); - activityTracePhysicalSpacePlot(h,commonCh,0.03*squeeze(spikeShapes(:,c,pComN1))',En,'scaling','none'); - title(num2str(idxOut(c))); - end - %} - - end - t=sortrows(cell2mat(tAll)); - - if ~isempty(t) - icCh = unique(t(:,[1 2]),'rows'); - chTransitions=unique([find(diff(t(:,1))~=0);find(diff(t(:,2))~=0)]); - - ic([1 2],:)=icCh'; - ic(4,:)=[chTransitions' size(t,1)]; - ic(3,:)=[1 ic(4,1:end-1)+1]; - t=round((obj.upSamplingFrequencySpike/1000)*t(:,3)')/(obj.upSamplingFrequencySpike/1000); %make sure that the maximal resolution is in units of upSampling frequency - - nNeurons=size(icCh,1); - - %calculate matrix with all avg spike shapes - allWaveforms=nan(nSamples,nNeurons,obj.nCh); - for i=1:nNeurons - allWaveforms(:,i,ch{ic(1,i)}{ic(2,i)})=avgWF{ic(1,i)}{ic(2,i)}; - isNoiseAll(i)=isNoise{ic(1,i)}{ic(2,i)}; - end - %{ - f=figure; - [h,hParent]=spikeDensityPlotPhysicalSpace([],obj.upSamplingFrequencySpike,obj.chPar.s2r,obj.chPar.En,... - 'hParent',f,'avgSpikeWaveforms',allWaveforms,'logDensity',true); - %} - - %move back to original channel numbers - ic(1,:)=obj.chPar.s2r(ic(1,:)); - else - ic=[]; - allWaveforms=[]; - isNoiseAll=[]; - end - if ~obj.runWithoutSaving2File - save(obj.sortingFileNames.fittingFile,'t','ic','allWaveforms','isNoiseAll'); - end - end - - - - function obj=spikePostProcessingNSK(obj) - - if obj.postPlotRawLongWaveforms || obj.postPlotFilteredWaveforms %calculate figure aspect ration based on electrode layout - [mElecs,nElecs]=size(obj.chPar.En); - figurePosition=[100 50 min(1000,100*mElecs) min(900,100*nElecs)]; - end - fprintf('\nPost processing spikes...'); - - load(obj.sortingFileNames.fittingFile,'t','ic','allWaveforms','isNoiseAll'); - [nSamples,nNeurons,obj.nCh]=size(allWaveforms); - - if ~isempty(ic) - neuronNames=ic(1:2,:); - else - neuronNames=[]; - end - - if isempty(obj.filterObj) - obj=getHighpassFilter(obj); - end - - nonExistingNeurons=find(~obj.sortingFileNames.postProcessignAnalysisExist); - nNonExistingNeurons=numel(nonExistingNeurons); - - matFileObj = matfile(obj.sortingFileNames.postProcessignAnalysisFile,'Writable',true); - if nNonExistingNeurons==1 %there is no matfile - matFileObj.postProcessignAnalysisExist=zeros(1,nNeurons); - nonExistingNeurons=zeros(1,nNeurons); - nNonExistingNeurons=numel(nonExistingNeurons); - matFileObj.neuronNames=neuronNames; - if obj.postExtractRawLongWaveformsFromSpikeTimes - matFileObj.avgLongWF=zeros(nNeurons,obj.nCh,obj.postTotalRawWindow*obj.dataRecordingObj.samplingFrequency/1000); - matFileObj.stdLongWF=zeros(nNeurons,obj.nCh,obj.postTotalRawWindow*obj.dataRecordingObj.samplingFrequency/1000); - matFileObj.PSDSNR=zeros(1,nNeurons); - else - matFileObj.avgLongWF=[];matFileObj.stdLongWF=[];matFileObj.PSDSNR=[]; - end - - if obj.postExtractFilteredWaveformsFromSpikeTimes - matFileObj.avgFinalWF=zeros(nNeurons,obj.nCh,obj.postTotalFilteredWindow*obj.dataRecordingObj.samplingFrequency/1000); - matFileObj.stdFinalWF=zeros(nNeurons,obj.nCh,obj.postTotalFilteredWindow*obj.dataRecordingObj.samplingFrequency/1000); - matFileObj.spkSNR=zeros(1,nNeurons); - matFileObj.nSpkTotal=zeros(1,nNeurons); - matFileObj.spkMaxAmp=zeros(1,nNeurons); - else - matFileObj.avgFinalWF=[];matFileObj.stdFinalWF=[];matFileObj.spkSNR=[];matFileObj.nSpkTotal=[];matFileObj.spkMaxAmp=[]; - end - end - - for i=nonExistingNeurons - tTmp=t(ic(3,i):ic(4,i)); - nSpk=numel(tTmp); - if obj.postExtractRawLongWaveformsFromSpikeTimes - [V_uV,T_ms]=obj.dataRecordingObj.getData(obj.dataRecordingObj.channelNumbers,tTmp(1:min(nSpk,obj.postMaxSpikes2Present))-obj.postPreRawWindow,obj.postTotalRawWindow); - - %standard deviation - stdLongWF(1,:,:)=squeeze(std(V_uV,[],2)); - - %average substruction mean - avgLongWF(1,:,:)=squeeze(median(V_uV,2)); - tmpMean=mean(avgLongWF(1,:,T_ms<(obj.postPreRawWindow-1)),3); %calculate the baseline according to the average voltage before the spike (1ms before spike peak) - V_uV=bsxfun(@minus,V_uV,tmpMean'); - avgLongWF(1,:,:)=bsxfun(@minus,avgLongWF(1,:,:),tmpMean); - - - p=find(T_ms>obj.postRawSNRStartEnd(1) & T_ms<=obj.postRawSNRStartEnd(2)); %find relevant time points surrounding the spike - tmpSNR=avgLongWF(1,obj.chPar.surChExtVec{ic(1,i)},p)./stdLongWF(1,obj.chPar.surChExtVec{ic(1,i)},p); %calculated at the position of the extended grid - - if obj.postPlotRawLongWaveforms - - f=figure('position',figurePosition); - neuronString=['Neu ' num2str(ic(1,i)) '-' num2str(ic(2,i))]; - infoStr={['nSpk=' num2str(nSpk)],neuronString,['noise=' num2str(isNoiseAll(i))]}; - - [h,hParent]=spikeDensityPlotPhysicalSpace(permute(V_uV,[3 2 1]),obj.dataRecordingObj.samplingFrequency,obj.chPar.s2r,obj.chPar.En,... - 'hParent',f,'avgSpikeWaveforms',permute(avgLongWF(1,:,:),[3 1 2]),'logDensity',true); - - annotation('textbox',[0.01 0.89 0.1 0.1],'FitHeightToText','on','String',infoStr); - - printFile=[obj.sortingDir filesep 'neuron' neuronString '-spikeShapeRaw']; - - set(f,'PaperPositionMode','auto'); - print(printFile,'-djpeg','-r300'); - close(f); - end - - matFileObj.PSDSNR(1,i)=mean(abs(tmpSNR(:))); - matFileObj.stdLongWF(i,:,:)=stdLongWF; - matFileObj.avgLongWF(i,:,:)=avgLongWF; - end - - if obj.postExtractFilteredWaveformsFromSpikeTimes - if obj.postExtractRawLongWaveformsFromSpikeTimes - [V_uV,T_ms]=obj.filterObj.getFilteredData(V_uV( : , : , T_ms>=(obj.postPreRawWindow-obj.postPreFilteredWindow) & T_ms<(obj.postPreRawWindow-obj.postPreFilteredWindow+obj.postTotalFilteredWindow))); - else - [V_uV,T_ms]=obj.filterObj.getFilteredData(obj.dataRecordingObj.getData(obj.dataRecordingObj.channelNumbers,tTmp(1:min(nSpk,obj.postMaxSpikes2Present))-obj.postPreFilteredWindow,obj.postTotalFilteredWindow)); - end - - avgFinalWF(1,:,:)=squeeze(median(V_uV,2)); - stdFinalWF(1,:,:)=squeeze(std(V_uV,[],2)); - - p=find(T_ms>obj.postFilteredSNRStartEnd(1) & T_ms<=obj.postFilteredSNRStartEnd(2)); %find relevant time points surrounding the spike - tmpSNR=avgFinalWF(1,obj.chPar.surChExtVec{ic(1,i)}(obj.chPar.pSurCh{ic(1,i)}),p)./stdFinalWF(1,obj.chPar.surChExtVec{ic(1,i)}(obj.chPar.pSurCh{ic(1,i)}),p); %calculated at the positions of the surrounding grid - - if obj.postPlotFilteredWaveforms - - f=figure('position',figurePosition); - neuronString=['Neu ' num2str(ic(1,i)) '-' num2str(ic(2,i))]; - infoStr={['nSpk=' num2str(nSpk)],neuronString,['noise=' num2str(isNoiseAll(i))]}; - - [h,hParent]=spikeDensityPlotPhysicalSpace(permute(V_uV,[3 2 1]),obj.dataRecordingObj.samplingFrequency,obj.chPar.s2r,obj.chPar.En,... - 'hParent',f,'avgSpikeWaveforms',permute(avgFinalWF(1,:,:),[3 1 2]),'logDensity',true); - - annotation('textbox',[0.01 0.89 0.1 0.1],'FitHeightToText','on','String',infoStr); - - %print to file - printFile=[obj.sortingDir filesep 'neuron' neuronString '-spikeShape']; - set(f,'PaperPositionMode','auto'); - print(printFile,'-djpeg','-r300'); - close(f); - end - - matFileObj.avgFinalWF(i,:,:)=avgFinalWF; - matFileObj.stdFinalWF(i,:,:)=stdFinalWF; - matFileObj.spkSNR(1,i)=abs(mean(tmpSNR(:))); - matFileObj.spkMaxAmp(1,i)=max(max(abs(avgFinalWF))); %the extremal spike amplitude - matFileObj.nSpkTotal(1,i)=ic(4,i)-ic(3,i)+1; - - end - matFileObj.postProcessignAnalysisExist(1,i)=1; - end %loop over all neurons - - - if obj.postPlotAllAvgSpikeTemplates - nPlotAxis=min(ceil(sqrt(nNeurons)),5); - nPlotsPerFigure=nPlotAxis.^2; - if nNeurons>0 - for i=1:(nNeurons+1) - if mod((i-1),nPlotsPerFigure)==0 || i==(nNeurons+1) - if i~=1 - printFile=[obj.sortingDir filesep 'avgSpikeShapes' num2str(ceil((i-1)/nPlotsPerFigure))]; - if obj.fastPrinting - imwrite(frame2im(getframe(f)),[printFile '.jpeg'],'Quality',90); - else - set(f,'PaperPositionMode','auto'); - print(printFile,'-djpeg','-r300'); - end - close(f); - end - if i~=(nNeurons+1) - f=figure('position',figurePosition); - end - end - if i0 - f=figure('position',[300 50 900 700]); - mNSpkTotal=mean(matFileObj.nSpkTotal); - %generate size legend - plotSpikeSNR=[matFileObj.spkSNR (max(matFileObj.spkSNR)-(max(matFileObj.spkSNR)-min(matFileObj.spkSNR))*0.01)*ones(1,5)]; - plotPSDSNR=[matFileObj.PSDSNR [0.9 1 1.1 1.2 1.3]*((max(matFileObj.PSDSNR)+min(matFileObj.PSDSNR))/2)]; - legendSpikeNums=round([mNSpkTotal/6 mNSpkTotal/3 mNSpkTotal mNSpkTotal*3 mNSpkTotal*6]); - plotnSpkTotal=[matFileObj.nSpkTotal legendSpikeNums]; - plotspkMaxAmp=[matFileObj.spkMaxAmp ones(1,5)*min(matFileObj.spkMaxAmp)]; - - scatter(plotSpikeSNR,plotPSDSNR,(plotnSpkTotal/mNSpkTotal)*50+5,plotspkMaxAmp,'linewidth',2); - text(plotSpikeSNR(end-4:end)*1.02,plotPSDSNR(end-4:end),num2str(legendSpikeNums'/(obj.dataRecordingObj.recordingDuration_ms/1000),3),'FontSize',8) - xlabel('$$\sqrt{SNR_{spike}}$$','Interpreter','latex','FontSize',14);ylabel('$$\sqrt{SNR_{PSD}}$$','Interpreter','latex','FontSize',14); - cb=colorbar('position',[0.8511 0.6857 0.0100 0.2100]);ylabel(cb,'Max spk. amp.'); - - printFile=[obj.sortingDir filesep 'SNR_spikePSD']; - set(f,'PaperPositionMode','auto'); - print(printFile,'-djpeg','-r300'); - end - end - - end - %Plots for testing - %{ - for i=1:numel(pV) - for j=1:p(pV(i)) - h=subaxis(nPlots,nPlots,c,'S',0.03,'M',0.03); - activityTracePhysicalSpacePlot(h,ch{pV(i)}{j},0.03*squeeze(avgWF{pV(i)}{j})',obj.chPar.rEn,'scaling','none'); - title([num2str(pV(i)) '-' num2str(j)]); - c=c+1; - end - end - %} - - - function [publicProps]=getProperties(obj) - metaClassData=metaclass(obj); - allPropName={metaClassData.PropertyList.Name}'; - allPropSetAccess={metaClassData.PropertyList.SetAccess}'; - publicProps(:,1)=allPropName(find(strcmp(allPropSetAccess, 'public'))); - - %collect all prop values - for i=1:numel(publicProps) - publicProps{i,2}=obj.(allPropName{i}); - end - end - - end - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%% Additional functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - methods (Static) - - function [clusterMerged,Merge]=SpikeTempDiffMerging(spikeShapes,Clusters,Templates,crit) - %merge clusters in a group that have to be merge based on the residuals - %between spikes and templates. - %synthax : [clusterMerged,Merge]=SpikeTempDiffMerging(spikeShapes,Clusters,Templates,crit) - %input: - % - spikeShapes : all the spikeShapes Nspikes-sizeSpike-NbChannels - % - Clusters : vector containing the index of spikes in spikeShapes - % - Templates : The templates corresponding to the clusters - % nChannels-sizeTemplate-nTemplates - % - crit : the value of the threshold to merge clusters(default value : 1.5) - %output : - % - clusterMerged:vector of symbolic merging - % - Merge : binary symmetric merging decision matrix - % nclust-nclust. - if nargin<4 - crit=1.5; - end - numClust=size(Templates,3); - clusterMerged=1:numClust; % a group is assigned to every cluster - %build ajacent matrix of clusters - Merge=zeros(numClust,numClust); - for i=1:numClust - for j=1:numClust - if j~=i - clSel=find(Clusters==i); - cTmp1=Templates(:,:,i)'; - cTmp2=Templates(:,:,j)'; - diffSpikeTemp1=zeros(1,length(clSel));diffSpikeTemp2=zeros(1,length(clSel)); - for k=1:length(clSel) - cSpike=reshape(spikeShapes(clSel(k),:,:),size(spikeShapes,2),size(spikeShapes,3)); - diffSpikeTemp1(k)=sum((cTmp1(:)-cSpike(:)).^2); - diffSpikeTemp2(k)=sum((cTmp2(:)-cSpike(:)).^2); - end - Merge(i,j)=median(diffSpikeTemp2)/median(diffSpikeTemp1); - end - end - end - - %Symetrize matrix - for k=1:numClust - for m=k+1:numClust - if Merge(k,m)0,1,'first')+1; - secondCross=find(n(1:end-1)>=0 & n(2:end)<0,1,'last'); - intersection=(edges(firstCross) + edges(secondCross))/2; - %D(k,m)=max(sum(p2>(intersection-std_p2/obj.clusteringSTDMergeFac))/sum(n2),sum(p1<(intersection+std_p1/obj.clusteringSTDMergeFac))/sum(n1)); - %D(k,m)=sum([p1 p2]<(intersection+std_p2/obj.clusteringSTDMergeFac) & [p1 p2]>(intersection-std_p1/obj.clusteringSTDMergeFac))/sum([n1 n2]); - if isempty(intersection) %one cluster is contained within the other - D(k,m)=1; - else - D(k,m)=( sum(p2>(intersection-std_p2/obj.clusteringSTDMergeFac)) + sum(p1<(intersection+std_p1/obj.clusteringSTDMergeFac)) ) /sum([n1 n2] ); - end - %figure;plot([p1 p2]);hold on;plot(ones(1,numel(edges)),edges,'or');line([1 sum([n1 n2])],[intersection intersection],'color','k','LineWidth',2); - end - %D(k,m)=(sqrt(sum(v.^2))/sqrt(std_p1^2 + std_p2.^2)); - %D(k,m)=(sqrt(sum(v.^2))/(std_p + std_p2); - %D(k,m)=(1+skewness([p1 p2])^2)/(kurtosis([p1 p2])+3); - %D(k,m) = kstest2(p1,p2,[],0.0.05); - - if D(k,m)>obj.clusteringMergeThreshold - %find in which group k is and add all is group to m - groupOfK=gc(k); - groupOfM=gc(m); - gc(gc==groupOfK)=groupOfM; - end - - if obj.clusteringPlotProjection - - subaxis(nClustersIn,nClustersIn,(m-1)*nClustersIn+k,'Spacing', 0.001, 'Padding', 0.001, 'Margin', 0.001); - - edges=[min([p1 p2]):((max([p1 p2])-min([p1 p2]))/30):max([p1 p2])]; %edges different from before - n1=hist(p1,edges); - n2=hist(p2,edges); - bar(edges,[n1;n2]',1,'stacked'); - axis tight; - set(gca,'XTickLabel',[],'YTickLabel',[]); - - subaxis(nClustersIn,nClustersIn,(k-1)*nClustersIn+m,'Spacing', 0.001, 'Padding', 0.001, 'Margin', 0.001); - strTxt={['F=' num2str(D(k,m))],['s1=' num2str(std_p1)],['s2=' num2str(std_p2)],['D=' num2str(sqrt(sum(v.^2)))]}; - text(0,0.5,strTxt); - axis off; - end - - end - end - - function p=projectionND(v,d) - %Calculate projection between a vector and a set of dots in multi dimensional space - %v = [1 x N] - vector - %d = [M X N] - M dot locations - - %calculate the cos angle between vector and dots - cosAng=v*d'./(sqrt(sum(v.^2))*sqrt(sum(d'.^2))); - p=cosAng.*sqrt(sum(d'.^2)); - end - - end - - end %methods (static) - -end diff --git a/spikeSorting/@gridSorter/loadMetaData.m b/spikeSorting/@gridSorter/loadMetaData.m deleted file mode 100644 index fca835a..0000000 --- a/spikeSorting/@gridSorter/loadMetaData.m +++ /dev/null @@ -1,21 +0,0 @@ -function [obj,metaDataExistFlag] = loadMetaData(obj,dataRecordingFolder) %gridSorter -if nargin==1 - dataRecordingFolder=obj.sortingDir; -end -if ~exist([dataRecordingFolder filesep 'metaData.mat'],'file') - metaDataExistFlag=0; - disp('Meta data file does not exist!!!'); -else - disp('Setting gridSorted properties according to metaData file'); - metaData=load([dataRecordingFolder filesep 'metaData.mat']); - for i=1:size(metaData.props,1) - if isprop(obj,metaData.props{i,1}) & ~strcmp(metaData.props{i,1},'dataRecordingObj') - obj.(metaData.props{i,1})=metaData.props{i,2}; - else - disp(['Property ' metaData.props{i,1} ' not loaded!']); - end - end - metaDataExistFlag=1; -end - -end \ No newline at end of file diff --git a/spikeSorting/@gridSorter/manualClustering.m b/spikeSorting/@gridSorter/manualClustering.m deleted file mode 100644 index 9497dd5..0000000 --- a/spikeSorting/@gridSorter/manualClustering.m +++ /dev/null @@ -1,63 +0,0 @@ -function [obj]=manualClustering(obj) -%manually select valid spike units after sorting - -obj=obj.findSortingFiles; - -if ~obj.sortingFileNames.fittingExist || ~all(obj.sortingFileNames.postProcessingAnalysisExist) - error('Cant run manual selection since spike sorting on this data set was not completed'); -end - -load(obj.sortingFileNames.fittingFile,'t','ic'); -plotNames=dir([obj.sortingDir filesep '*spikeShape.jpg']); -plotNames=cellfun(@(x) [obj.sortingDir filesep x],{plotNames.name},'UniformOutput',0)'; - -f=figure('Position',[100 50 1100 900]); -uipAxes = uipanel('Parent',f,'Title','Spike plot','FontSize',12,'Position',[.005 .1 0.99 .9]); -uipControl = uipanel('Parent',f,'Title','Spike selection','FontSize',12,'Position',[.005 .005 0.99 .09]); -pushAccept = uicontrol('Parent',uipControl,'String','Accept','Position',[10 10 72 36],'Callback',{@acceptReject_Callback,true}); -pushReject = uicontrol('Parent',uipControl,'String','Reject','Position',[100 10 72 36],'Callback',{@acceptReject_Callback,false}); - -hAxesSpike=axes('Parent',uipAxes,'Position',[.005 .005 0.6 0.9]); -hAxesHistHighRes=axes('Parent',uipAxes,'Position',[.62 .005 .35 .4]); -hAxesHist=axes('Parent',uipAxes,'Position',[.62 .5 .35 .4]); - -%set(hAxesSpike,'Position',get(hAxesSpike,'OuterPosition')); - -edgesH=[0:10:500]; -edgesL=[0:100:10000]; - -nNeu=size(ic,2); -for i=1:size(ic,2) - printFile=[obj.sortingDir filesep 'neuron' 'Neu ' num2str(ic(1,i)) '-' num2str(ic(2,i)) '-spikeShape.jpg']; - if exist(printFile,'file') - - - histHigh=histc(diff(t(ic(3,i):ic(4,i))),edgesH); - histLow=histc(diff(t(ic(3,i):ic(4,i))),edgesL); - bar(hAxesHistHighRes,(edgesH(1:end-1)+edgesH(2:end))/2,histHigh(1:end-1)); - bar(hAxesHist,(edgesL(1:end-1)+edgesL(2:end))/2,histLow(1:end-1)); - - imshow(printFile,'Parent',hAxesSpike); - set(pushAccept,'Selected','off'); - set(pushReject,'Selected','off'); - uiwait; - selectedTrue=get(pushAccept,'Selected'); - RejectedTrue=get(pushReject,'Selected'); - if strcmp(selectedTrue,'on') & strcmp(RejectedTrue,'off') - neurons2keep(i)=true; - else - neurons2keep(i)=false; - end - else - disp(['No plot exists for unit: ' num2str(ic(1:2,i)')]); - end -end - -[t,ic]=RemainNeurons(t,ic,ic(1:2,neurons2keep)); -save([obj.sortingDir filesep 'manuallySelectedSpikeSorting'],'t','ic','neurons2keep'); - -delete(f); - -function acceptReject_Callback(hObject, eventdata, handle, isValid) -set(hObject,'Selected','on'); -uiresume(gcbf); \ No newline at end of file diff --git a/spikeSorting/@gridSorter/manuallySelectValidUnits.m b/spikeSorting/@gridSorter/manuallySelectValidUnits.m deleted file mode 100644 index 13af1a1..0000000 --- a/spikeSorting/@gridSorter/manuallySelectValidUnits.m +++ /dev/null @@ -1,63 +0,0 @@ -function [obj]=manuallySelectValidUnits(obj) -%manually select valid spike units after sorting - -obj=obj.findSortingFiles; - -if ~obj.sortingFileNames.fittingExist || ~all(obj.sortingFileNames.postProcessingAnalysisExist) - error('Cant run manual selection since spike sorting on this data set was not completed'); -end - -load(obj.sortingFileNames.fittingFile,'t','ic'); -plotNames=dir([obj.sortingDir filesep '*spikeShape.jpg']); -plotNames=cellfun(@(x) [obj.sortingDir filesep x],{plotNames.name},'UniformOutput',0)'; - -f=figure('Position',[100 50 1100 900]); -uipAxes = uipanel('Parent',f,'Title','Spike plot','FontSize',12,'Position',[.005 .1 0.99 .9]); -uipControl = uipanel('Parent',f,'Title','Spike selection','FontSize',12,'Position',[.005 .005 0.99 .09]); -pushAccept = uicontrol('Parent',uipControl,'String','Accept','Position',[10 10 72 36],'Callback',{@acceptReject_Callback,true}); -pushReject = uicontrol('Parent',uipControl,'String','Reject','Position',[100 10 72 36],'Callback',{@acceptReject_Callback,false}); - -hAxesSpike=axes('Parent',uipAxes,'Position',[.005 .005 0.6 0.9]); -hAxesHistHighRes=axes('Parent',uipAxes,'Position',[.62 .005 .35 .4]); -hAxesHist=axes('Parent',uipAxes,'Position',[.62 .5 .35 .4]); - -%set(hAxesSpike,'Position',get(hAxesSpike,'OuterPosition')); - -edgesH=[0:10:500]; -edgesL=[0:100:10000]; - -nNeu=size(ic,2); -for i=1:size(ic,2) - printFile=[obj.sortingDir filesep 'neuron' 'Neu ' num2str(ic(1,i)) '-' num2str(ic(2,i)) '-spikeShape.jpg']; - if exist(printFile,'file') - - - histHigh=histc(diff(t(ic(3,i):ic(4,i))),edgesH); - histLow=histc(diff(t(ic(3,i):ic(4,i))),edgesL); - bar(hAxesHistHighRes,(edgesH(1:end-1)+edgesH(2:end))/2,histHigh(1:end-1)); - bar(hAxesHist,(edgesL(1:end-1)+edgesL(2:end))/2,histLow(1:end-1)); - - imshow(printFile,'Parent',hAxesSpike); - set(pushAccept,'Selected','off'); - set(pushReject,'Selected','off'); - uiwait; - selectedTrue=get(pushAccept,'Selected'); - RejectedTrue=get(pushReject,'Selected'); - if strcmp(selectedTrue,'on') & strcmp(RejectedTrue,'off') - neurons2keep(i)=true; - else - neurons2keep(i)=false; - end - else - disp(['No plot exists for unit: ' num2str(ic(1:2,i)')]); - end -end - -[t,ic]=RemainNeurons(t,ic,ic(1:2,neurons2keep)); -save([obj.sortingDir filesep 'manuallySelectedSpikeSorting'],'t','ic','neurons2keep'); - -delete(f); - -function acceptReject_Callback(hObject, eventdata, handle, isValid) -set(hObject,'Selected','on'); -uiresume(gcbf); \ No newline at end of file diff --git a/spikeSorting/@gridSorter/plotSpikeTrigWF.m b/spikeSorting/@gridSorter/plotSpikeTrigWF.m deleted file mode 100644 index 74f56f3..0000000 --- a/spikeSorting/@gridSorter/plotSpikeTrigWF.m +++ /dev/null @@ -1,68 +0,0 @@ -function getSpikeTrigWF(obj,startEnd,printFolder) -%Detect spikes in raw data and save waveforms -%Todo: -%Add detection of multiple spikes -if nargin<3 - printFolder=obj.sortingDir; -end - -%determine the chunck size - -if nargin>1 - if ~isempty(startEnd) - disp(['Plotting post processing on a subset of data ' num2str(round(startEnd(1)/1000)) ' - ' num2str(round(startEnd(2)/1000)) 's']); - postFix=[num2str(round(startEnd(1)/1000)) '_' num2str(round(startEnd(2)/1000)) 's']; - else - startEnd=[0 obj.dataRecordingObj.recordingDuration_ms]; - postFix=''; - end -else - startEnd=[0 obj.dataRecordingObj.recordingDuration_ms]; - postFix=''; -end - -load([obj.sortingFileNames.STWaveformFile(1:end-4) postFix],'avgRawWF','avgHPWF','neuronNames','histRawWF','histHPWF','nSpkTotal','par'); -nNeurons=size(neuronNames,2); - -windowSamplesRaw=obj.postTotalRawWindow*obj.dataRecordingObj.samplingFrequency(1)/1000; -windowSamplesFiltered=obj.postTotalFilteredWindow*obj.dataRecordingObj.samplingFrequency(1)/1000; -tBinRaw=shiftdim(ceil(((1:windowSamplesRaw)/obj.dataRecordingObj.samplingFrequency(1)*1000)/par.binTRaw),-1); -tBinHP=shiftdim(ceil(((1:windowSamplesFiltered)/obj.dataRecordingObj.samplingFrequency(1)*1000)/par.binTHP),-1); -VBins=(-par.maxV+par.binV/2):par.binV:par.maxV; -tBinsRaw=par.binTRaw/2:par.binTRaw:obj.postTotalRawWindow; -tBinsHP=par.binTHP/2:par.binTHP:obj.postTotalFilteredWindow; - -[mElecs,nElecs]=size(obj.chPar.En); -if obj.postPlotRawLongWaveforms - figurePosition=[100 50 min(1000,100*nElecs) min(900,100*mElecs)]; - for i=1:nNeurons - f=figure('position',figurePosition); - neuronString=['Neu' num2str(neuronNames(1,i)) '-' num2str(neuronNames(2,i))]; - infoStr={['nSpk=' num2str(nSpkTotal(i))],neuronString}; - [h,hParent]=spikeDensityPlotPhysicalSpace(squeeze(histRawWF(i,:,:,:)),obj.dataRecordingObj.samplingFrequency(1),obj.chPar.s2r,obj.chPar.En,... - 'hParent',f,'avgSpikeWaveforms',permute(avgRawWF(i,:,:),[3 1 2]),'logColorScale',1,'spikeShapesIsAHist',1,'xBin',tBinsRaw,'yBin',unique(VBins)); - annotation('textbox',[0.01 0.89 0.1 0.1],'FitHeightToText','on','String',infoStr); - - printFile=[printFolder filesep 'neuron' neuronString '-spikeShapeRaw' postFix]; - set(f,'PaperPositionMode','auto'); - print(printFile,'-djpeg','-r300'); - close(f); - end -end - -if obj.postPlotFilteredWaveforms - figurePosition=[100 50 min(1000,100*nElecs) min(900,100*mElecs)]; - for i=1:nNeurons - f=figure('position',figurePosition); - neuronString=['Neu' num2str(neuronNames(1,i)) '-' num2str(neuronNames(2,i))]; - infoStr={['nSpk=' num2str(nSpkTotal(i))],neuronString}; - [h,hParent]=spikeDensityPlotPhysicalSpace(squeeze(histHPWF(i,:,:,:)),obj.dataRecordingObj.samplingFrequency(1),obj.chPar.s2r,obj.chPar.En,... - 'hParent',f,'avgSpikeWaveforms',permute(avgHPWF(i,:,:),[3 1 2]),'logColorScale',1,'spikeShapesIsAHist',1,'xBin',tBinsHP,'yBin',unique(VBins)); - annotation('textbox',[0.01 0.89 0.1 0.1],'FitHeightToText','on','String',infoStr); - - printFile=[printFolder filesep 'neuron' neuronString '-spikeShapeHP' postFix]; - set(f,'PaperPositionMode','auto'); - print(printFile,'-djpeg','-r300'); - close(f); - end -end \ No newline at end of file diff --git a/spikeSorting/@gridSorter/projectionMerge.m b/spikeSorting/@gridSorter/projectionMerge.m deleted file mode 100644 index a76ea85..0000000 --- a/spikeSorting/@gridSorter/projectionMerge.m +++ /dev/null @@ -1,131 +0,0 @@ -function [gc,f]=projectionMerge(spikeFeatures,initIdx,varargin) -%merge clusters in a group that have to be merge based on the residuals between spikes and templates. -%synthax : [gc,f]=projectionMerge(spikeFeatures,initIdx,varargin) -%input: -% - spikeFeatures : spike features () -% - initIdx : the clusters index of every spike -% vararin - 'property','value' -%output : -% - gc: a binary matrix with ones indicating a necessary merge -% - f: a figure handle for the generated plot - -%default variables -obj.clusteringMinNSpikesCluster=10; -obj.clusteringSTDMergeFac=2; -obj.clusteringMergeThreshold=0.18; -obj.clusteringPlotProjection=1; - -%Collects all options -for i=1:2:length(varargin) - eval([varargin{i} '=' 'varargin{i+1};']) -end - -%find robust cluster centers -nClustersIn=numel(unique(initIdx)); -for k=1:nClustersIn - cent(k,:)=median(spikeFeatures(initIdx==k,:)); -end - -if nClustersIn<=1 - gc=1; - f=[]; - return; -end - -if obj.clusteringPlotProjection - f=figure('Position',[50 50 1400 900]); -else - f=[]; -end - -D=zeros(nClustersIn); -groups=mat2cell(1:nClustersIn,1,ones(1,nClustersIn)); -gc=1:nClustersIn; % a group is assigned to every cluster -for k=2:nClustersIn - for m=1:k-1 - v=(cent(k,:)-cent(m,:)); - p1=projectionND(v,spikeFeatures(initIdx==k,:)); - p2=projectionND(v,spikeFeatures(initIdx==m,:)); - - pCent=projectionND(v,[cent(k,:);cent(m,:)]);%for plotting purpuses - - if numel(p1)0,1,'first')+1; - secondCross=find(n(1:end-1)>=0 & n(2:end)<0,1,'last'); - intersection=(edges(firstCross) + edges(secondCross))/2; - %D(k,m)=max(sum(p2>(intersection-std_p2/obj.clusteringSTDMergeFac))/sum(n2),sum(p1<(intersection+std_p1/obj.clusteringSTDMergeFac))/sum(n1)); - %D(k,m)=sum([p1 p2]<(intersection+std_p2/obj.clusteringSTDMergeFac) & [p1 p2]>(intersection-std_p1/obj.clusteringSTDMergeFac))/sum([n1 n2]); - if isempty(intersection) %one cluster is contained within the other - D(k,m)=1; - else - D(k,m)=( sum(p2>(intersection-std_p2/obj.clusteringSTDMergeFac)) + sum(p1<(intersection+std_p1/obj.clusteringSTDMergeFac)) ) /sum([n1 n2] ); - end - %figure;plot([p1 p2]);hold on;plot(ones(1,numel(edges)),edges,'or');line([1 sum([n1 n2])],[intersection intersection],'color','k','LineWidth',2); - end - %D(k,m)=(sqrt(sum(v.^2))/sqrt(std_p1^2 + std_p2.^2)); - %D(k,m)=(sqrt(sum(v.^2))/(std_p + std_p2); - %D(k,m)=(1+skewness([p1 p2])^2)/(kurtosis([p1 p2])+3); - %D(k,m) = kstest2(p1,p2,[],0.0.05); - - if D(k,m)>obj.clusteringMergeThreshold - %find in which group k is and add all is group to m - groupOfK=gc(k); - groupOfM=gc(m); - gc(gc==groupOfK)=groupOfM; - end - - if obj.clusteringPlotProjection - - subaxis(nClustersIn,nClustersIn,(m-1)*nClustersIn+k,'Spacing', 0.001, 'Padding', 0.001, 'Margin', 0.001); - - edges=[min([p1 p2]):((max([p1 p2])-min([p1 p2]))/30):max([p1 p2])]; %edges different from before - n1=hist(p1,edges); - n2=hist(p2,edges); - bar(edges,[n1;n2]',1,'stacked'); - axis tight; - set(gca,'XTickLabel',[],'YTickLabel',[]); - - subaxis(nClustersIn,nClustersIn,(k-1)*nClustersIn+m,'Spacing', 0.001, 'Padding', 0.001, 'Margin', 0.001); - strTxt={['F=' num2str(D(k,m))],['s1=' num2str(std_p1)],['s2=' num2str(std_p2)],['D=' num2str(sqrt(sum(v.^2)))]}; - text(0,0.5,strTxt); - axis off; - end - - end -end - - function p=projectionND(v,d) - %Calculate projection between a vector and a set of dots in multi dimensional space - %v = [1 x N] - vector - %d = [M X N] - M dot locations - - %calculate the cos angle between vector and dots - cosAng=v*d'./(sqrt(sum(v.^2))*sqrt(sum(d'.^2))); - p=cosAng.*sqrt(sum(d'.^2)); - end -end \ No newline at end of file diff --git a/spikeSorting/@gridSorter/runSorting.m b/spikeSorting/@gridSorter/runSorting.m deleted file mode 100644 index 9c1ff5d..0000000 --- a/spikeSorting/@gridSorter/runSorting.m +++ /dev/null @@ -1,95 +0,0 @@ -function [obj,t,ic,avgWaveform]=runSorting(obj) -%run the grid sorter (check existance of sorting stages and runs the ones that were not yet done or that needs to be overwritten) - -try - obj=obj.findSortingFiles; %update sorted files - - %initiate variables - t=[];ic=[];avgWaveform=[]; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%% spike Detection %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - tic; - if all(obj.sortingFileNames.spikeDetectionExist) %check for the existence of spike shapes - disp('Sorting will be preformed on previously detected waveforms'); - else - obj=obj.spikeDetection; - end - toc; - obj.saveMetaData; % Save meta data if something was changed in this stage - - %%%%%%%%%%%%%%%%%%%%%%%%%%%% feature extraction %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - tic; - if all(obj.sortingFileNames.featureExtractionExist) %check for the existence of spike shapes - disp('Sorting will be preformed on previously extracted features'); - else - obj=obj.spikeFeatureExtraction; - end - toc; - obj.saveMetaData; % Save meta data if something was changed in this stage - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% clustering %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - tic; - if all(obj.sortingFileNames.clusteringExist) %check for the existence of spike shapes - disp('Sorting will be preformed on previously extracted clusters'); - else - obj=obj.spikeClustering; - end - toc; - obj.saveMetaData; % Save meta data if something was changed in this stage - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Merging duplicate neurons %%%%%%%%%%%%%%%%%%%%% - tic; - if obj.sortingFileNames.mergedAvgWaveformExist %check for the existence of spike shapes - disp('Sorting will be preformed on previously merged clusters'); - else - obj=obj.spikeMerging; - end - toc; - obj.saveMetaData; % Save meta data if something was changed in this stage - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Fitting duplicate neurons %%%%%%%%%%%%%%%%%%%%% - tic; - if obj.sortingFileNames.fittingExist %check for the existence of spike shapes - disp('No fitting performed!!!'); - else - obj=obj.spikeFitting; - end - toc; - obj.saveMetaData; % Save meta data if something was changed in this stage - - %{ - %%%%%%%%%%%%%%% Post-processing - general final plots and accesses sorting quality %%%%%%%%%%%%%%%%%%%%% - tic; - if all(obj.sortingFileNames.STWaveformExist) || ~obj.postRunPostProcessing %check for the existence of spike shapes - disp('No post analysis performed!!!'); - else - obj=obj.getSpikeTrigWF; - obj.plotSpikeTrigWF; - end - toc; - obj.saveMetaData; % Save meta data if something was changed in this stage - %} - - sendMailViaGmail('shein.mark@gmail.com',['grid sorter finished!!! ' getenv('COMPUTERNAME') 'running ' obj.dataRecordingObj.recordingDir],''); - -catch errorMsg - if obj.sendProgressEmail - sendMailViaGmail(obj.sendProgressEmailTo,['grid sorter error on computer ' getenv('COMPUTERNAME') 'running ' obj.dataRecordingObj.recordingDir],errorMsg.getReport); - rethrow(errorMsg); - end -end -%%%%%%%%%%% Further assessment of Cluster Quality %%%%%%%%%%%%%%%%%%%% -%{ -tic -if obj.sortingFileNames.assessQualityExist %check for the existence of all error estimates - load(obj.sortingFileNames.assessQualityFile,'er'); - if numel(er)==size(ic,2) - disp('No fitting performed!!!'); - else - [obj, er]=assessQuality(obj); - end -else -[obj, er]=assessQuality(obj); -end -toc -%} diff --git a/spikeSorting/@gridSorter/saveMetaData.m b/spikeSorting/@gridSorter/saveMetaData.m deleted file mode 100644 index 3ddaff9..0000000 --- a/spikeSorting/@gridSorter/saveMetaData.m +++ /dev/null @@ -1,3 +0,0 @@ -function saveMetaData(obj) -[props]=getProperties(obj); -save([obj.sortingDir filesep 'metaData.mat'],'props'); \ No newline at end of file diff --git a/spikeSorting/@gridSorter/spikeClustering.m b/spikeSorting/@gridSorter/spikeClustering.m deleted file mode 100644 index 2a72904..0000000 --- a/spikeSorting/@gridSorter/spikeClustering.m +++ /dev/null @@ -1,214 +0,0 @@ -function [obj,idx,initIdx,nClusters,avgSpikeWaveforms,stdSpikeWaveforms]=spikeClustering(obj) -% Run clustering on previously extracted features -% [obj,idx,initIdx,nClusters,avgSpikeWaveforms,stdSpikeWaveforms]=spikeClustering(obj) -avgClusteredWaveforms=cell(1,obj.nCh); -stdClusteredWaveforms=cell(1,obj.nCh); - -if isempty(obj.sortingDir) - obj.runWithoutSaving2File=true; - idxAll=cell(1,obj.nCh); - initIdxAll=cell(1,obj.nCh); - nClustersAll=cell(1,obj.nCh); -else - obj.runWithoutSaving2File=false; -end - -fprintf('\nClustering on channel (total %d): ',obj.nCh); -for i=find(obj.sortingFileNames.clusteringExist==0 | obj.overwriteClustering) %go over all channels in the recording - fprintf('%d ',i); - MaxClustersTmp=obj.clusteringMaxClusters; - - if ~exist(obj.sortingFileNames.featureExtractionFile{i},'file') - warning(['No feature extraction file was found for Channel ' num2str(i) '. Clustering not performed!']); - continue; - else - load(obj.sortingFileNames.featureExtractionFile{i}); - load(obj.sortingFileNames.spikeDetectionFile{i},'spikeTimes'); - end - - [nSpikes,nFeatures]=size(spikeFeatures); - - if nSpikes >= obj.clusteringMinSpikesTotal && nSpikes >= (spikeTimes(end)-spikeTimes(1))/1000*obj.clusteringMinimumChannelRate - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%% Clustering %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - switch obj.clusteringMethod - case 'kMeans' - % set options to k-Means - opts = statset('obj.clusteringMaxIter',obj.clusteringMaxIter); - try - [initIdx] = kmeans(spikeFeatures,obj.clusteringMaxClusters,'options',opts,... - 'emptyaction','singleton','distance','city','onlinephase','on','obj.clusteringNReplicates',obj.clusteringNReplicates,'start',obj.clusteringInitialClusterCentersMethod); - catch %if the number of samples is too low, kmeans gives an error -> try kmeans with a lower number of clusters - MaxClustersTmp=round(obj.clusteringMaxClusters/2); - [initIdx] = kmeans(spikeFeatures,MaxClustersTmp,'options',opts,... - 'emptyaction','singleton','distance','city','onlinephase','on','obj.clusteringNReplicates',obj.clusteringNReplicates,'start',obj.clusteringInitialClusterCentersMethod); - end - case 'meanShift' - initIdx=zeros(nSpikes,1); - out=MSAMSClustering(spikeFeatures'); - for j=1:numel(out) - initIdx(out{j})=j; - end - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%% Merging %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - switch obj.clusteringMergingMethod - case 'MSEdistance' - %calculate templates - load(obj.sortingFileNames.spikeDetectionFile{i},'spikeShapes'); - avgSpikeWaveforms=zeros(nSpikeSamples,max(1,MaxClustersTmp),nSurroundingChannels); - for j=1:MaxClustersTmp - avgSpikeWaveforms(:,j,:)=median(spikes4Clustering(:,initIdx==j,:),2); - end - - [gc,Merge]=obj.SpikeTempDiffMerging(permute(spikes4Clustering,[2 1 3]),initIdx,permute(avgSpikeWaveforms,[3 1 2])); - - if obj.saveFigures - f1=figure('Position',[50 50 1400 900]); - set(f1,'PaperPositionMode','auto'); - if obj.fastPrinting - imwrite(frame2im(getframe(f1)),[obj.sortingDir filesep 'Ch_' num2str(obj.chPar.s2r(i)) 'projectionTest.jpeg'],'Quality',90); - else - print([obj.sortingDir filesep 'Ch_' num2str(obj.chPar.s2r(i)) 'projectionTest'],'-djpeg','-r300'); - end - close(f1); - end - - case 'projectionMeanStd' - [gc,f1]=obj.projectionMerge(spikeFeatures,initIdx,'obj.clusteringMinNSpikesCluster',obj.clusteringMinNSpikesCluster,'obj.clusteringSTDMergeFac',obj.clusteringSTDMergeFac,'obj.clusteringMergeThreshold',obj.clusteringMergeThreshold,'obj.clusteringPlotProjection',obj.clusteringPlotProjection); - - if obj.saveFigures && ~isempty(f1); - set(f1,'PaperPositionMode','auto'); - if obj.fastPrinting - imwrite(frame2im(getframe(f1)),[obj.sortingDir filesep 'Ch_' num2str(obj.chPar.s2r(i)) 'projectionTest.jpeg'],'Quality',90); - else - print([obj.sortingDir filesep 'Ch_' num2str(obj.chPar.s2r(i)) 'projectionTest'],'-djpeg','-r300'); - end - close(f1); - end - - if obj.clusteringRunSecondMerging - uniqueClusters=unique(gc); - nClusters=numel(uniqueClusters); - idx=zeros(nSpikes4Clustering,1); - for k=1:nClusters - p=find(gc==uniqueClusters(k)); - for j=1:numel(p) - idx(initIdx==p(j))=k; - end - end - MaxClustersTmp=nClusters; - initIdx=idx; - - [gc,f1]=obj.projectionMerge(spikeFeatures,initIdx,'obj.clusteringMinNSpikesCluster',obj.clusteringMinNSpikesCluster,'obj.clusteringSTDMergeFac',obj.clusteringSTDMergeFac,'obj.clusteringMergeThreshold',obj.clusteringMergeThreshold,'obj.clusteringPlotProjection',obj.clusteringPlotProjection); - - if obj.saveFigures - set(f1,'PaperPositionMode','auto'); - if obj.fastPrinting - imwrite(frame2im(getframe(f1)),[obj.sortingDir '\Ch_' num2str(obj.chPar.s2r(i)) 'projectionTest.jpeg'],'Quality',90); - else - print([obj.sortingDir '\Ch_' num2str(obj.chPar.s2r(i)) 'projectionTest'],'-djpeg','-r300'); - end - close(f1); - end - end - end - - %reclassify clusters - uniqueClusters=unique(gc); - nClusters=numel(uniqueClusters); - idx=zeros(nSpikes,1); - for k=1:nClusters - p=find(gc==uniqueClusters(k)); - for j=1:numel(p) - idx(initIdx==p(j))=k; - end - end - - %calculate spikeShape statistics - load(obj.sortingFileNames.spikeDetectionFile{i},'spikeShapes','detectionInt2uV'); - spikeShapes=double(spikeShapes) .* detectionInt2uV; - - [nSpikeSamples,nSpikes,nSurroundingChannels]=size(spikeShapes); - if nSpikes>obj.featuresMaxSpikesToCluster - spikeShapes=spikeShapes(:,1:obj.featuresMaxSpikesToCluster,:); - end - - avgSpikeWaveforms=zeros(nSpikeSamples,max(1,nClusters),nSurroundingChannels); - stdSpikeWaveforms=zeros(nSpikeSamples,max(1,nClusters),nSurroundingChannels); - for j=1:nClusters - pCluster=idx==j; - avgSpikeWaveforms(:,j,:)=median(spikeShapes(:,pCluster,:),2); - stdSpikeWaveforms(:,j,:)=1.4826*median(abs(spikeShapes(:,pCluster,:)- bsxfun(@times,avgSpikeWaveforms(:,j,:),ones(1,sum(pCluster),1)) ),2); - nSpk(j)=numel(pCluster); - end - else - fprintf('X '); %to note than no neurons were detected on this electrode - - idx=ones(nSpikes,1); - initIdx=ones(nSpikes,1); - avgSpikeWaveforms=[]; - stdSpikeWaveforms=[]; - nClusters=0; - nSpk=0; - end - - avgClusteredWaveforms{i}=avgSpikeWaveforms; - stdClusteredWaveforms{i}=stdSpikeWaveforms; - nAvgSpk{i}=nSpk; - - if ~obj.runWithoutSaving2File - save(obj.sortingFileNames.clusteringFile{i},'idx','initIdx','nClusters','avgSpikeWaveforms','stdSpikeWaveforms'); - else - idxAll{i}=idx; - initIdxAll{i}=initIdx; - nClustersAll{i}=nClusters; - end - - if obj.clusteringPlotClassification && nClusters>0 - - cmap=lines; - - f2=figure('Position',[100 100 1200 800],'color','w'); - PCAfeaturesSpikeShapePlot(spikeFeatures,spikeShapes,obj.upSamplingFrequencySpike,initIdx,idx,obj.chPar.En,obj.chPar.s2r(obj.chPar.surChExtVec{i}),'hFigure',f2,'cmap',cmap); - - f3=figure('Position',[100 100 1200 800],'color','w'); - featureSubSpacePlot(spikeFeatures,idx,'hFigure',f3,'cmap',cmap); - - if obj.saveFigures - figure(f2); - set(f2,'PaperPositionMode','auto'); - if obj.fastPrinting - imwrite(frame2im(getframe(f2)),[obj.sortingDir '\Ch_' num2str(obj.chPar.s2r(i)) 'classification.jpeg'],'Quality',90); - else - print([obj.sortingDir '\Ch_' num2str(obj.chPar.s2r(i)) 'classification'],'-djpeg','-r300'); - end - - figure(f3); - set(f3,'PaperPositionMode','auto'); - if obj.fastPrinting - imwrite(frame2im(getframe(f3)),[obj.sortingDir '\Ch_' num2str(obj.chPar.s2r(i)) 'featureSpace.jpeg'],'Quality',90); - else - print([obj.sortingDir '\Ch_' num2str(obj.chPar.s2r(i)) 'featureSpace'],'-djpeg','-r300'); - end - if ishandle(f2) - close(f2); - end - if ishandle(f3) - close(f3); - end - end - end %plot initial classification classification -end %go over all channels - -if ~obj.runWithoutSaving2File - save(obj.sortingFileNames.avgWaveformFile,'avgClusteredWaveforms','stdClusteredWaveforms','nAvgSpk'); -end - -obj=obj.findSortingFiles; %update sorted files diff --git a/spikeSorting/@gridSorter/spikeDetection.m b/spikeSorting/@gridSorter/spikeDetection.m deleted file mode 100644 index 8d13384..0000000 --- a/spikeSorting/@gridSorter/spikeDetection.m +++ /dev/null @@ -1,180 +0,0 @@ -function obj=spikeDetection(obj) -%Detect spikes in raw data and save waveforms -%Todo: -%Add detection of multiple spikes - -%determine quantization -obj.detectionInt2uV=obj.detectionMaxSpikeAmp/2^(obj.detectionNQuantizationBits-1); - -obj=obj.getHighpassFilter; - -%start spike detection -fprintf('\nRunning spike detection on %s...',obj.dataRecordingObj.dataFileNames{1}); - -upSamplingFactor=obj.upSamplingFrequencySpike/obj.dataRecordingObj.samplingFrequency(1); -if upSamplingFactor~=round(upSamplingFactor) %check that upsampling factor is an integer - upSamplingFactor=round(upSamplingFactor); - obj.upSamplingFrequencySpike=upSamplingFactor*obj.dataRecordingObj.samplingFrequency(1); - disp(['upSampling factor was not an integer and was rounded to: ' num2str(upSamplingFactor)]); -end - -gaussianityWindow=obj.detectionGaussianityWindow/1000*obj.dataRecordingObj.samplingFrequency(1); -testSamples=gaussianityWindow*1000; - -preSpikeSamples=obj.detectionPreSpikeWindow/1000*obj.dataRecordingObj.samplingFrequency(1); %must be > spikePeakInterval -postSpikeSamples=obj.detectionPostSpikeWindow/1000*obj.dataRecordingObj.samplingFrequency(1); %must be > spikePeakInterval -spikeTimeShiftIntervalSamples=obj.detectionSpikeTimeShiftInterval/1000*obj.dataRecordingObj.samplingFrequency(1); -postSpikeSamplesInitial=postSpikeSamples+spikeTimeShiftIntervalSamples; - -timeVec=-preSpikeSamples:postSpikeSamplesInitial; -intrpTimeVec=timeVec(1):(1/upSamplingFactor):timeVec(end); -pZeroTimeVec=find(intrpTimeVec>=0,1,'first'); - -preSpikeSamplesIntrp=round(preSpikeSamples*upSamplingFactor); %must be > spikePeakInterval -postSpikeSamplesIntrp=round(postSpikeSamples*upSamplingFactor); %must be > spikePeakInterval -spikeTimeShiftIntervalIntrp=spikeTimeShiftIntervalSamples*upSamplingFactor; %must be > spikePeakInterval - -minimumDetectionIntervalSamplesIntrp=obj.detectionMinimumDetectionInterval/1000*obj.dataRecordingObj.samplingFrequency(1)*upSamplingFactor; -peakDetectionSmoothingSamples=round(obj.detectionPeakDetectionSmoothingWindow/1000*obj.dataRecordingObj.samplingFrequency(1)*upSamplingFactor); -peakSmoothingKernel=fspecial('gaussian', [3*peakDetectionSmoothingSamples 1] ,peakDetectionSmoothingSamples); - -%determine the chunck size -if obj.detectionMaxChunkSize>obj.dataRecordingObj.recordingDuration_ms - startTimes=0; - endTimes=obj.dataRecordingObj.recordingDuration_ms; -else - startTimes=0:obj.detectionMaxChunkSize:obj.dataRecordingObj.recordingDuration_ms; - endTimes=[startTimes(2:end)+obj.detectionChunkOverlap obj.dataRecordingObj.recordingDuration_ms]; -end -nChunks=numel(startTimes); - -obj.nCh=numel(obj.chPar.s2r); - -matFileObj=cell(1,obj.nCh); -if obj.runWithoutSaving2File %if saving data is not required - obj.runWithoutSaving2File=true; - spikeShapesAll=cell(obj.nCh,nChunks); - spikeTimesAll=cell(obj.nCh,nChunks); -else - obj.runWithoutSaving2File=false; - for i=find(obj.sortingFileNames.spikeDetectionExist==0) - matFileObj{i} = matfile(obj.sortingFileNames.spikeDetectionFile{i},'Writable',true); - matFileObj{i}.spikeShapes=zeros(preSpikeSamplesIntrp+postSpikeSamplesIntrp,0,obj.chPar.nValidChExt(i),'int16'); - end -end - -%initiate arrays -Th=zeros(obj.nCh,nChunks);nCumSpikes=zeros(1,obj.nCh); -fprintf('\nExtracting spikes from chunks (total %d): ',nChunks); -for j=1:nChunks - fprintf('%d ',j); - %get data - MAll=squeeze(obj.filterObj.getFilteredData(obj.dataRecordingObj.getData(obj.chPar.s2r(1:obj.nCh),startTimes(j),endTimes(j)-startTimes(j))))'; - if obj.detectionRemoveAllElectrodeMedian % if there are noise signals that are shared by all electrodes, like perfusion of other global artifacts - MAll=bsxfun(@minus,MAll,median(MAll,2)); - end - nSamples=size(MAll,1); - for i=find(obj.sortingFileNames.spikeDetectionExist==0) %go over all channels that require rewriting - %get local data - Mlong=MAll(:,obj.chPar.surChExtVec{i}); - - %estimate channel noise - tmpData=buffer(Mlong(1:min(testSamples,nSamples),obj.chPar.pCenterCh(i)),gaussianityWindow,gaussianityWindow/2); - noiseSamples=tmpData(:,kurtosis(tmpData,0)Th(i,j) & Mlong(2:end,obj.chPar.pCenterCh(i))preSpikeSamples & thresholdCrossingsobj.detectionMinimumDelayBetweenSpikes)+1; - M=M(:,p,:); - spikeTimesTmp=spikeTimesTmp(p'); %the p' is important to create a 1-0 empty matrix (not 0-1) which cell2mat can handle - end - spikeTimesAll{i,j}=spikeTimesTmp; - if ~obj.runWithoutSaving2File - tmpSpikeCount=numel(spikeTimesTmp); - if numel(spikeTimesTmp)>0 - nCumSpikes(i)=nCumSpikes(i)+numel(spikeTimesTmp); - matFileObj{i}.spikeShapes(:,(nCumSpikes(i)-tmpSpikeCount+1):nCumSpikes(i),:)=int16(M./obj.detectionInt2uV); - end - else - spikeShapesAll{i,j}=int16(M./obj.detectionInt2uV); - end - else - spikeTimesAll{i,j}=[]; - if obj.runWithoutSaving2File - spikeShapesAll{i,j}=[]; - end - end - end -end -clear MAll Mlong M; - -if ~obj.runWithoutSaving2File %write files to disk - for i=find(obj.sortingFileNames.spikeDetectionExist==0) - matFileObj{i}.Th=Th(i,:); - - matFileObj{i}.spikeTimes=cell2mat(spikeTimesAll(i,:)); - matFileObj{i}.preSpikeSamplesIntrp=preSpikeSamplesIntrp; - matFileObj{i}.postSpikeSamplesIntrp=postSpikeSamplesIntrp; - matFileObj{i}.upSamplingFrequencySpike=obj.upSamplingFrequencySpike; - matFileObj{i}.minimumDetectionIntervalSamplesIntrp=minimumDetectionIntervalSamplesIntrp; - matFileObj{i}.detectionInt2uV=obj.detectionInt2uV; - end -else %keep files in memory - obj.spikeDetectionData.spikeShapes=cell(1,obj.nCh); - obj.spikeDetectionData.spikeTimes=cell(1,obj.nCh); - for i=find(obj.sortingFileNames.spikeDetectionExist>0) - obj.spikeDetectionData.spikeShapes{i}=cell2mat(spikeShapesAll(i,:)); - obj.spikeDetectionData.spikeTimes{i}=cell2mat(spikeTimesAll(i,:)); - end - obj.spikeDetectionData.Th=Th; - - obj.spikeDetectionData.preSpikeSamplesIntrp=preSpikeSamplesIntrp; - obj.spikeDetectionData.postSpikeSamplesIntrp=postSpikeSamplesIntrp; - obj.spikeDetectionData.minimumDetectionIntervalSamplesIntrp=minimumDetectionIntervalSamplesIntrp; - obj.spikeDetectionData.upSamplingFrequencySpike=obj.upSamplingFrequencySpike; - obj.spikeDetectionData.detectionInt2uV=obj.detectionInt2uV; -end - -obj=obj.findSortingFiles; %update sorted files diff --git a/spikeSorting/@gridSorter/spikeFeatureExtraction.m b/spikeSorting/@gridSorter/spikeFeatureExtraction.m deleted file mode 100644 index 50db4d5..0000000 --- a/spikeSorting/@gridSorter/spikeFeatureExtraction.m +++ /dev/null @@ -1,100 +0,0 @@ -function [obj,spikeFeaturesAll]=spikeFeatureExtraction(obj) -%extract features from the detected spike waveforms -if isempty(obj.sortingDir) - obj.runWithoutSaving2File=true; - spikeFeaturesAll=cell(1,obj.nCh); -else - obj.runWithoutSaving2File=false; -end - -fprintf('\nExtracting spike features from channels (total %d): ',obj.nCh); -for i=find(obj.sortingFileNames.featureExtractionExist==0 | obj.overwriteFeatureExtraction) - spikeFeatures=[]; - fprintf('%d ',i); - - if ~exist(obj.sortingFileNames.spikeDetectionFile{i},'file') - warning(['No spike detection file was found for Channel ' num2str(i) '. Feature extraction not performed!']); - continue; - else - load(obj.sortingFileNames.spikeDetectionFile{i}); - end - - if ~isempty(spikeShapes) - %choose a random subset of the spikes for clustering - nSurroundingChannels=numel(obj.chPar.pSurCh{i}); - [nSamples,nSpikes,nLocalCh]=size(spikeShapes); - - nSpikes4Clustering=min(obj.featuresMaxSpikesToCluster,nSpikes); - - sd=[]; - switch obj.featuresFeatureExtractionMethod - case 'wavelet' - spikeShapes=double(spikeShapes) .* detectionInt2uV; - if obj.featuresConcatenateElectrodes==1 %all waveforms are ordered channel by channel - tmp=spikeShapes(:,1,obj.chPar.pSurCh{i}); - spikeFeatures=wavedec(tmp(:),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); - nCoeffs=numel(spikeFeatures); - spikeFeatures=zeros(nSpikes4Clustering,nCoeffs); - for j=1:nSpikes4Clustering - tmp=spikeShapes(:,j,obj.chPar.pSurCh{i}); - spikeFeatures(j,:)=wavedec(tmp(:),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); %'haar','coif1' - end - - extractFeaturesBySamples=1; - if extractFeaturesBySamples %use as features also wavelet on waveforms concatenated by samples, first all sample 1 in all elec, than sample 2.... - spikeFeatures2=zeros(nSpikes4Clustering,nCoeffs); - for j=1:nSpikes4Clustering - tmp=permute(spikeShapes(:,j,obj.chPar.pSurCh{i}),[3 2 1]); - spikeFeatures2(j,:)=wavedec(tmp(:),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); %'haar','coif1' - end - spikeFeatures=[spikeFeatures spikeFeatures2]; - end - %} - else - spikeFeatures=wavedec(spikeShapes(:,1,obj.chPar.pSurCh{i}(1)),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); - nCoeffs=numel(spikeFeatures); - spikeFeatures=zeros(nCoeffs,nSpikes4Clustering,nSurroundingChannels); - for j=1:nSpikes4Clustering - for k=1:nSurroundingChannels - spikeFeatures(:,j,k)=wavedec(spikeShapes(:,j,obj.chPar.pSurCh{i}(k)),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); %'haar','coif1' - end - end - spikeFeatures=reshape(permute(spikeFeatures,[1 3 2]),[size(spikeFeatures,1)*size(spikeFeatures,3) size(spikeFeatures,2)])'; - nCoeffs=nCoeffs*nSurroundingChannels; - end - - for j=1:(nCoeffs*2) % KS test for coefficient selection - thr_dist = std(spikeFeatures(:,j)) * 3; - thr_dist_min = mean(spikeFeatures(:,j)) - thr_dist; - thr_dist_max = mean(spikeFeatures(:,j)) + thr_dist; - aux = spikeFeatures(spikeFeatures(:,j)>thr_dist_min & spikeFeatures(:,j) 10; - [ksstat]=test_ks(aux); - sd(j)=ksstat; - else - sd(j)=0; - end - end - [~,tmp1]=sort(sd(1:nCoeffs),'descend'); - [~,tmp2]=sort(sd(nCoeffs+1:end),'descend'); - spikeFeatures=spikeFeatures(:,[tmp1(1:obj.featuresNWaveletCoeff/2) nCoeffs+tmp2(1:obj.featuresNWaveletCoeff/2)]); - - if obj.featuresReduceDimensionsWithPCA - [PCAsimMat,spikeFeatures] = pca(spikeFeatures,'NumComponents',obj.featuresDimensionReductionPCA,'Economy',false); %run PCA for visualization purposes - end - - case 'PCA' %this option was tested and gives worse results than wavelets - spikeShapes=double(spikeShapes(:,:,obj.chPar.pSurCh{i})) .* detectionInt2uV; - [~,spikeFeatures] = pca(reshape(permute(spikeShapes,[1 3 2]),[nSamples*numel(obj.chPar.pSurCh{i}) nSpikes])); - spikeFeatures=spikeFeatures(1:obj.featuresDimensionReductionPCA,:)'; - end - end - if ~obj.runWithoutSaving2File - save(obj.sortingFileNames.featureExtractionFile{i},'spikeFeatures','-v7.3'); - else - spikeFeaturesAll{i}=spikeFeatures; - end -end - -obj=obj.findSortingFiles; %update sorted files \ No newline at end of file diff --git a/spikeSorting/@gridSorter/spikeFeatureExtraction.m.orig b/spikeSorting/@gridSorter/spikeFeatureExtraction.m.orig deleted file mode 100644 index 72d78c3..0000000 --- a/spikeSorting/@gridSorter/spikeFeatureExtraction.m.orig +++ /dev/null @@ -1,109 +0,0 @@ -function [obj,spikeFeaturesAll]=spikeFeatureExtraction(obj) -%extract features from the detected spike waveforms -if isempty(obj.sortingDir) - obj.runWithoutSaving2File=true; - spikeFeaturesAll=cell(1,obj.nCh); -else - obj.runWithoutSaving2File=false; -end - -fprintf('\nExtracting spike features from channels (total %d): ',obj.nCh); -for i=find(obj.sortingFileNames.featureExtractionExist==0 | obj.overwriteFeatureExtraction) - spikeFeatures=[]; - fprintf('%d ',i); - - if ~exist(obj.sortingFileNames.spikeDetectionFile{i},'file') - warning(['No spike detection file was found for Channel ' num2str(i) '. Feature extraction not performed!']); - continue; - else - load(obj.sortingFileNames.spikeDetectionFile{i}); - end - - if ~isempty(spikeShapes) - %choose a random subset of the spikes for clustering - nSurroundingChannels=numel(obj.chPar.pSurCh{i}); - [nSamples,nSpikes,nLocalCh]=size(spikeShapes); - - nSpikes4Clustering=min(obj.featuresMaxSpikesToCluster,nSpikes); - - sd=[]; - switch obj.featuresFeatureExtractionMethod - case 'wavelet' - spikeShapes=double(spikeShapes) .* detectionInt2uV; - if obj.featuresConcatenateElectrodes==1 %all waveforms are ordered channel by channel - tmp=spikeShapes(:,1,obj.chPar.pSurCh{i}); - spikeFeatures=wavedec(tmp(:),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); - nCoeffs=numel(spikeFeatures); - spikeFeatures=zeros(nSpikes4Clustering,nCoeffs); - for j=1:nSpikes4Clustering - tmp=spikeShapes(:,j,obj.chPar.pSurCh{i}); - spikeFeatures(j,:)=wavedec(tmp(:),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); %'haar','coif1' - end - - extractFeaturesBySamples=1; - if extractFeaturesBySamples %use as features also wavelet on waveforms concatenated by samples, first all sample 1 in all elec, than sample 2.... - spikeFeatures2=zeros(nSpikes4Clustering,nCoeffs); - for j=1:nSpikes4Clustering - tmp=permute(spikeShapes(:,j,obj.chPar.pSurCh{i}),[3 2 1]); - spikeFeatures2(j,:)=wavedec(tmp(:),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); %'haar','coif1' - end - spikeFeatures=[spikeFeatures spikeFeatures2]; - end - %} - else - spikeFeatures=wavedec(spikeShapes(:,1,obj.chPar.pSurCh{i}(1)),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); - nCoeffs=numel(spikeFeatures); - spikeFeatures=zeros(nCoeffs,nSpikes4Clustering,nSurroundingChannels); - for j=1:nSpikes4Clustering - for k=1:nSurroundingChannels - spikeFeatures(:,j,k)=wavedec(spikeShapes(:,j,obj.chPar.pSurCh{i}(k)),obj.featuresWTdecompositionLevel,obj.featuresSelectedWavelet); %'haar','coif1' - end - end - spikeFeatures=reshape(permute(spikeFeatures,[1 3 2]),[size(spikeFeatures,1)*size(spikeFeatures,3) size(spikeFeatures,2)])'; - nCoeffs=nCoeffs*nSurroundingChannels; - end - - for j=1:(nCoeffs*2) % KS test for coefficient selection - thr_dist = std(spikeFeatures(:,j)) * 3; - thr_dist_min = mean(spikeFeatures(:,j)) - thr_dist; - thr_dist_max = mean(spikeFeatures(:,j)) + thr_dist; - aux = spikeFeatures(spikeFeatures(:,j)>thr_dist_min & spikeFeatures(:,j) 10; - [ksstat]=test_ks(aux); - sd(j)=ksstat; - else - sd(j)=0; - end - end - [~,tmp1]=sort(sd(1:nCoeffs),'descend'); - [~,tmp2]=sort(sd(nCoeffs+1:end),'descend'); - spikeFeatures=spikeFeatures(:,[tmp1(1:obj.featuresNWaveletCoeff/2) nCoeffs+tmp2(1:obj.featuresNWaveletCoeff/2)]); - - if obj.featuresReduceDimensionsWithPCA -<<<<<<< HEAD - [PCAsimMat,spikeFeatures] = princomp(spikeFeatures); %run PCA for visualization purposes -======= - [PCAsimMat,spikeFeatures] = pca(spikeFeatures); %run PCA for visualization purposes ->>>>>>> upstream/master - spikeFeatures=spikeFeatures(:,1:obj.featuresDimensionReductionPCA); - end - - case 'PCA' %this option was tested and gives worse results than wavelets - spikeShapes=double(spikeShapes(:,:,obj.chPar.pSurCh{i})) .* detectionInt2uV; -<<<<<<< HEAD - [~,spikeFeatures] = princomp(reshape(permute(spikeShapes,[1 3 2]),[nSamples*numel(obj.chPar.pSurCh{i}) nSpikes])); -======= - [~,spikeFeatures] = pca(reshape(permute(spikeShapes,[1 3 2]),[nSamples*numel(obj.chPar.pSurCh{i}) nSpikes])); ->>>>>>> upstream/master - spikeFeatures=spikeFeatures(1:obj.featuresDimensionReductionPCA,:)'; - end - end - if ~obj.runWithoutSaving2File - save(obj.sortingFileNames.featureExtractionFile{i},'spikeFeatures','-v7.3'); - else - spikeFeaturesAll{i}=spikeFeatures; - end -end - -obj=obj.findSortingFiles; %update sorted files \ No newline at end of file diff --git a/spikeSorting/@gridSorter/spikeFitting.m b/spikeSorting/@gridSorter/spikeFitting.m deleted file mode 100644 index 23fe30f..0000000 --- a/spikeSorting/@gridSorter/spikeFitting.m +++ /dev/null @@ -1,223 +0,0 @@ -function [obj,t,ic,md]=spikeFitting(obj) -%Fit all detected spikes to calculated spike templates -if isempty(obj.sortingDir) - obj.runWithoutSaving2File=true; -else - obj.runWithoutSaving2File=false; -end - -fprintf('\nFitting spikes...'); -load(obj.sortingFileNames.mergedAvgWaveformFile,'avgWF','ch','isNoise'); - -%Plots for testing -%{ - p=cellfun(@(x) numel(x),avgWF); - pV=find(p>0); - nPlots=min(ceil(sqrt(sum(p))),7); - c=1; - for i=1:numel(pV) - for j=1:p(pV(i)) - h=subaxis(nPlots,nPlots,c,'S',0.03,'M',0.03); - activityTracePhysicalSpacePlot(h,ch{pV(i)}{j},0.03*squeeze(avgWF{pV(i)}{j})',obj.chPar.rEn,'scaling','none'); - title([num2str(pV(i)) '-' num2str(j) ', noise=' num2str(isNoise{pV(i)}{j})]); - c=c+1; - end - end -%} - -%get noise thresholds for all channels -for i=1:obj.nCh %go over all channels in the recording and extract noise level (Should be modified for using!!!) - load(obj.sortingFileNames.spikeDetectionFile{i},'Th'); - T(i)=mean(Th); -end -edges=[0.5:1:20.5]; -centers=(edges(1:end-1)+edges(2:end))/2; -gauss=@(x,m,s) (1/s/sqrt(2*pi)).*exp(-(x-m).^2./2./s.^2); - -maxCCLag=obj.fittingMaxLag*obj.upSamplingFrequencySpike/1000; -spikeNoiseEdgeIntervalSamples=obj.fittingSpikeNoiseEdgeInterval*obj.upSamplingFrequencySpike/1000; - - -lags=[fliplr(0:-obj.fittingLagIntervalSamples:-maxCCLag) obj.fittingLagIntervalSamples:obj.fittingLagIntervalSamples:maxCCLag]; -lag=(numel(lags)-1)/2; -lagSamples=lags((lag+1):end); - -tAll=cell(obj.nCh,1); -fprintf('\nFitting data on Ch (total %d): ',obj.nCh); -for i1=1:obj.nCh %go over all channels in the recording - fprintf('%d ',i1); - tmpWFs=[]; - if ~exist(obj.sortingFileNames.spikeDetectionFile{i1},'file') - warning(['No spike detection file was found for Channel ' num2str(i1) '. Fitting not performed!']); - continue; - else - load(obj.sortingFileNames.spikeDetectionFile{i1},'spikeShapes','spikeTimes','detectionInt2uV'); - [nSamples,nSpikes,nChTmp]=size(spikeShapes); - spikeShapes=double(spikeShapes)*detectionInt2uV; - end - %estimate std for fitting template method - noiseStd=std(spikeShapes([1:spikeNoiseEdgeIntervalSamples end-spikeNoiseEdgeIntervalSamples+1:end],:,:),1); - [stdHist]=histc(squeeze(noiseStd),edges); - [~,pMax]=max(stdHist); - noiseStd=centers(pMax); - - match=[]; - correspCh=[]; - for i2=[i1 obj.chPar.surChExtVec{i1}(obj.chPar.pSurChOverlap{i1})] - for neu=1:numel(avgWF{i2}) - [commonCh,pComN1,pComN2]=intersect(obj.chPar.surChExtVec{i1},ch{i2}{neu}); - %try and revise this criteria - tmpWF=avgWF{i2}{neu}(:,pComN2); - - if obj.fittingTemplateMethod==1 %'minkowski' exp 2 + cross-corr - tmpWF=reshape(tmpWF,[size(tmpWF,1),size(tmpWF,2),1]); - spikes=permute(spikeShapes(:,:,pComN1),[1 3 2]); - tmpMatch=zeros(lag*2+1,nSpikes); - for l=0:lag - %spike is after the template sqrt(mean(spike-template)^2) - tmpMatch(lag+l+1,:)=( nanmean(reshape( bsxfun(@minus,spikes((lagSamples(l+1)+1):end,:,:),tmpWF(1:end-lagSamples(l+1),:,:)).^2 , [(nSamples-lagSamples(l+1))*numel(commonCh) nSpikes] )) ).^(1/2); - %spike is before the template - tmpMatch(lag-l+1,:)=( nanmean(reshape( bsxfun(@minus,spikes(1:end-lagSamples(l+1),:,:),tmpWF((lagSamples(l+1)+1):end,:,:)).^2 , [(nSamples-lagSamples(l+1))*numel(commonCh) nSpikes] )) ).^(1/2); - end - match=cat(3,match,tmpMatch); - correspCh=[correspCh ; i2 neu]; - - elseif obj.fittingTemplateMethod==2 %implement 'minkowski' distance with exponent 24 - tmpWF=reshape(tmpWF,[size(tmpWF,1),1,size(tmpWF,2)]); - spikes=reshape(permute(spikeShapes(:,:,pComN1),[1 3 2]),[nSamples*numel(commonCh) nSpikes]); - tmpMatch=bsxfun(@minus,spikes,tmpWF(:)).^2; - tmpMatch=(nanmean(tmpMatch)).^(1/2);%./(nanstd(tmpMatch)+nanstd(tmpWF(:))); - - match=[match ; tmpMatch]; - correspCh=[correspCh ; i2 neu]; - - elseif obj.fittingTemplateMethod==3 - tmpWF=reshape(tmpWF,[size(tmpWF,1),1,size(tmpWF,2)]); - spikes=reshape(permute(spikeShapes(:,:,pComN1),[1 3 2]),[nSamples*numel(commonCh) nSpikes]); - %noiseStd=mean(T)/5; - noiseStd=mean(noiseStd); - tmpMatch=bsxfun(@minus,spikes,tmpWF(:)); - tmpMatch=gauss(0,0,noiseStd)-gauss(tmpMatch,0,noiseStd); - tmpMatch=mean(tmpMatch); - - match=[match ; tmpMatch]; - correspCh=[correspCh ; i2 neu]; - end - - %mS=mean(spikes(:)); - %sS=std(spikes(:)); - %spikes(spikesmS-1*sS)=NaN; - %tmpWF(tmpWFmS-1*sS)=NaN; - - %{ - f=figure('position',[83 120 1699 852]); - M=spikeShapes(:,:,pComN1); - plotShifted(reshape(permute(M,[1 3 2]),[size(M,1)*size(M,3) size(M,2)]),'verticalShift',30);hold on; - M=repmat(tmpWF,[1 nSpikes 1]); - plotShifted(reshape(permute(M,[1 3 2]),[size(M,1)*size(M,3) size(M,2)]),'verticalShift',30,'color','k');set(gca,'YTickLabel',[]); - text(zeros(nSpikes,1),0:30:(30*(nSpikes-1)),num2cell(tmpMatch),'HorizontalAlignment','right'); - pause;close(f); - %} - end - end - if ~isempty(match) - if obj.fittingTemplateMethod==1 - [tmpMin,delay]=min(match,[],1); - [~,idxOut]=min(tmpMin,[],3); - delay=lags(delay(sub2ind(size(delay),ones(1,nSpikes),1:nSpikes,idxOut))); - distVal=tmpMin(sub2ind(size(tmpMin),ones(1,nSpikes),1:nSpikes,idxOut)); - tAll{i1}=[correspCh(idxOut,[1 2]) (spikeTimes+delay/obj.upSamplingFrequencySpike*1000)' distVal']; - else - [~,idxOut]=min(match,[],1); - tAll{i1}=[correspCh(idxOut,[1 2]) spikeTimes' distVal']; - end - else - tAll{i1}=[]; - end - - plotFitting=0; - if plotFitting - f=figure('position',[83 120 1699 852]); - c=1; - %plot all templates - for i2=[i1 obj.chPar.surChExtVec{i1}(obj.chPar.pSurChOverlap{i1})] - for neu=1:numel(avgWF{i2}) - c=c+1; - [commonCh,pComN1,pComN2]=intersect(obj.chPar.surChExtVec{i1},ch{i2}{neu}); - %try and revise this criteria - tmpWF=avgWF{i2}{neu}(:,pComN2); - h=subaxis(5,6,c,'S',0.01,'m',0.01); - activityTracePhysicalSpacePlot(h,ch{i2}{neu}(pComN2),tmpWF',obj.chPar.surChExt{i1}); - text(0.5,0.5,num2str(c-1),'color','r'); - end - end - - h1=subaxis(5,6,1,'S',0.01,'m',0.01); - for i=1:nSpikes - hP=activityTracePhysicalSpacePlot(h1,obj.chPar.surChExtVec{i1},squeeze(spikeShapes(:,i,:))',obj.chPar.surChExt{i1},'traceColor','k'); - hT=text(0.5,0.5,['i:' num2str(idxOut(i)) ' -delay:' num2str(delay(i)) ' -dist:' num2str(distVal(i))],'color','r'); - pause; - delete([hP;hT]); - end - - end - %{ - f=figure('position',[83 120 1699 852]); - [~,p]=sort(idxOut); - n=min(numel(p),50); - M=spikeShapes(:,p(1:n),:); - plotShifted(reshape(permute(M,[1 3 2]),[size(M,1)*size(M,3) size(M,2)]),'verticalShift',30);hold on; - text(zeros(n,1),0:30:(30*(n-1)),num2cell(idxOut(p(1:n)))); - pause;close(f); - %} - %{ - M=spikeShapes;plotShifted(reshape(permute(M,[1 3 2]),[size(M,1)*size(M,3) size(M,2)]),'verticalShift',30);line([(pMin-1)*size(M,1) pMin*size(M,1)],[0 0],'color','g','lineWidth',3); - f=figure;load layout_40_Hexa;En=flipud(En); - for c=1:20 - h=subaxis(4,5,c,'S',0.03,'M',0.03); - activityTracePhysicalSpacePlot(h,commonCh,0.03*squeeze(spikeShapes(:,c,pComN1))',En,'scaling','none'); - title(num2str(idxOut(c))); - end - %} - -end -t=sortrows(cell2mat(tAll)); -%p2Remove=t(:,4)>obj.fittingMaxMinkowskiDist; -%fractionRemovedSpikes=sum(p2Remove)/size(t,1); -%t(p2Remove,:)=[]; - -if ~isempty(t) - icCh = unique(t(:,[1 2]),'rows'); - chTransitions=unique([find(diff(t(:,1))~=0);find(diff(t(:,2))~=0)]); - - ic([1 2],:)=icCh'; - ic(4,:)=[chTransitions' size(t,1)]; - ic(3,:)=[1 ic(4,1:end-1)+1]; - md=t(:,4)'; - t=round((obj.upSamplingFrequencySpike/1000)*t(:,3)')/(obj.upSamplingFrequencySpike/1000); %make sure that the maximal resolution is in units of upSampling frequency - nNeurons=size(icCh,1); - - %calculate matrix with all avg spike shapes - allWaveforms=nan(nSamples,nNeurons,obj.nCh); - for i=1:nNeurons - allWaveforms(:,i,ch{ic(1,i)}{ic(2,i)})=avgWF{ic(1,i)}{ic(2,i)}; - isNoiseAll(i)=isNoise{ic(1,i)}{ic(2,i)}; - end - %{ - f=figure; - [h,hParent]=spikeDensityPlotPhysicalSpace([],obj.upSamplingFrequencySpike,obj.chPar.s2r,obj.chPar.En,... - 'hParent',f,'avgSpikeWaveforms',allWaveforms,'logDensity',true); - %} - - %move back to original channel numbers - ic(1,:)=obj.chPar.s2r(ic(1,:)); -else - ic=[]; - allWaveforms=[]; - isNoiseAll=[]; -end -if ~obj.runWithoutSaving2File - save(obj.sortingFileNames.fittingFile,'t','ic','allWaveforms','isNoiseAll','md'); -end - -obj=obj.findSortingFiles; %update sorted files \ No newline at end of file diff --git a/spikeSorting/@gridSorter/spikeMerging.m b/spikeSorting/@gridSorter/spikeMerging.m deleted file mode 100644 index 346693c..0000000 --- a/spikeSorting/@gridSorter/spikeMerging.m +++ /dev/null @@ -1,300 +0,0 @@ -function [obj,avgWF,stdWF,ch,mergedNeurons]=spikeMergingClusters(obj) -%Merge waveforms belonging to the same neurons which were either not clustered correctly or were associated with different channels -avgWF=cell(1,obj.nCh); -stdWF=cell(1,obj.nCh); -ch=cell(1,obj.nCh); -isNoise=cell(1,obj.nCh); -if isempty(obj.sortingDir) - obj.runWithoutSaving2File=true; -else - obj.runWithoutSaving2File=false; -end - -%steepness=1.2; -%nonLin = @(x) x+x./sqrt(1+abs(x).^steepness); -%x=-100:100;plot(x,nonLin(x)); - -load(obj.sortingFileNames.spikeDetectionFile{1},'postSpikeSamplesIntrp','preSpikeSamplesIntrp'); -nSamples=postSpikeSamplesIntrp+preSpikeSamplesIntrp; -preSpikeSamples4NoiseDetection=obj.mergingPreSpike4NoiseDetection*preSpikeSamplesIntrp; -postSpikeSamples4NoiseDetection=obj.mergingPostSpike4NoiseDetection*postSpikeSamplesIntrp; -pSamples4NoiseDetection=round(nSamples/2-preSpikeSamples4NoiseDetection):round(nSamples/2+postSpikeSamples4NoiseDetection); - -maxSpikeShiftSamples=obj.mergingMaxSpikeShift*obj.upSamplingFrequencySpike/1000; - -load(obj.sortingFileNames.avgWaveformFile,'avgClusteredWaveforms','stdClusteredWaveforms','nAvgSpk'); - -%classify tempates as noise if the number of points exceeding N std is smaller than a threshold -validSamplesInTemplate=cell(1,obj.nCh); -isNoise=cell(1,obj.nCh); -for n=1:obj.nCh - for c=1:size(avgClusteredWaveforms{n},2) - tmpSpikes1=squeeze(avgClusteredWaveforms{n}(:,c,:)); - tmpSpikesStd1=squeeze(stdClusteredWaveforms{n}(:,c,:)); - pValid=~(tmpSpikes1>-obj.mergingNStdNoiseDetection*tmpSpikesStd1/sqrt(nAvgSpk{n}(c)-1) & tmpSpikes10 - tmpSpikes1=tmpSpikes1(d+1:end,:); - tmpSpikes2=tmpSpikes2(1:end-d,:); - tmpSpikesStd1=tmpSpikesStd1(d+1:end,:); - tmpSpikesStd2=tmpSpikesStd2(1:end-d,:); - else - tmpSpikes1=tmpSpikes1(1:end+d,:); - tmpSpikes2=tmpSpikes2(-d+1:end,:); - tmpSpikesStd1=tmpSpikesStd1(1:end+d,:); - tmpSpikesStd2=tmpSpikesStd2(-d+1:end,:); - end - end - - %remove from spike shapes all noise points estimated as points below obj.mergingNStdSpikeDetection standard deviation - pValid=~( tmpSpikes1>-obj.mergingNStdSpikeDetection*tmpSpikesStd1/sqrt(nAvgSpk{n1}(c1)-1) & tmpSpikes1-obj.mergingNStdSpikeDetection*tmpSpikesStd2/sqrt(nAvgSpk{n2}(c2)-1) & tmpSpikes2-obj.mergingNStdSpikeDetection*tmpSpikesStd1/sqrt(nAvgSpk{n1}(c1)-1) & tmpSpikes1-obj.mergingNStdSpikeDetection*tmpSpikesStd2/sqrt(nAvgSpk{n2}(c2)-1) & tmpSpikes2= 0 - tmpSpikeShapes(1 : (end-tmpDelays(j)) , : , pComN1)=detectionInt2uV.*double(spikeShapes( (tmpDelays(j)+1) : end , pRelevantSpikes , pComN2)); %there is a conversion 2 double here - else - tmpSpikeShapes(-tmpDelays(j)+1:end,:,pComN1)=detectionInt2uV.*double(spikeShapes(1:end+tmpDelays(j),pRelevantSpikes,pComN2)); %there is a conversion 2 double here - end - %} - newSpikeShapes=cat(2,newSpikeShapes,tmpSpikeShapes); - end - - %newSpikeShapes=permute(allignSpikeShapes(permute(newSpikeShapes,[2 3 1])),[3 1 2]); - %newSpikeShapes(newSpikeShapes==0)=NaN; %to not include in the averages the padding due to spike shifting - - avgSpikeWaveforms=nanmedian(newSpikeShapes,2); - stdSpikeWaveforms=1.4826*nanmedian(abs(newSpikeShapes- bsxfun(@times,avgSpikeWaveforms,ones(1,size(newSpikeShapes,2),1)) ),2); - avgSpikeWaveforms(isnan(avgSpikeWaveforms))=0; %average waveform should not contain NaNs - stdSpikeWaveforms(isnan(stdSpikeWaveforms))=0; %average waveform should not contain NaNs - - [~,pMin]=min(min(avgSpikeWaveforms((preSpikeSamplesIntrp-minimumDetectionIntervalSamplesIntrp):(preSpikeSamplesIntrp+minimumDetectionIntervalSamplesIntrp),:,:),[],1),[],3); - maxChannel=commonCh(pMin); %real channel - pMergedNeuron=find(channel==maxChannel,1,'first'); %select ch with largest amp. if there are several neurons on the same channel with the same waveform just takes the first - if isempty(pMergedNeuron) %for the special case where the peak waveform of the joined neurons sits on a different channel than any of the original neurons - pMergedNeuron=1; - fprintf('Maximum amplitude channel for group %d, channel %d, neuron %d - detected on a different channel than any of the original neurons before merging.\n',i,neuron{i}(:,1),neuron{i}(:,2)); - end - - %M=newSpikeShapes;plotShifted(reshape(permute(M,[1 3 2]),[size(M,1)*size(M,3) size(M,2)]),'verticalShift',30);line([(pMin-1)*size(M,1) pMin*size(M,1)],[0 0],'color','g','lineWidth',3); - %f=figure;h=axes;activityTracePhysicalSpacePlot(h,commonCh,squeeze(avgSpikeWaveforms(:,1,:))',obj.chPar.rEn); - %pause;hold off; - - [commonCh,pComN1,pComN2]=intersect(minimalChMap,obj.chPar.surChExtVec{neuron{i}(pMergedNeuron,1)}); - avgWF{neuron{i}(pMergedNeuron,1)}{neuron{i}(pMergedNeuron,2)}=avgSpikeWaveforms; - stdWF{neuron{i}(pMergedNeuron,1)}{neuron{i}(pMergedNeuron,2)}=stdSpikeWaveforms; - ch{neuron{i}(pMergedNeuron,1)}{neuron{i}(pMergedNeuron,2)}=commonCh; - isNoise{neuron{i}(pMergedNeuron,1)}{neuron{i}(pMergedNeuron,2)}=any(noiseSpike); - - %collect all neurons to remove from waveforms - for j=[1:(pMergedNeuron-1) (pMergedNeuron+1):numel(groups{i})] - neurons2Remove=[neurons2Remove ; neuron{i}(j,:)]; - end - end - end - %remove all merged waveforms - if ~isempty(neurons2Remove) - for i=unique(neurons2Remove(:,1))' - p=neurons2Remove(find(neurons2Remove(:,1)==i),2); - for j=1:numel(p) - avgWF{i}{p(j)}=[]; - stdWF{i}{p(j)}=[]; - ch{i}{p(j)}=[]; - isNoise{i}{p(j)}=[]; - end - if all(cellfun(@(x) isempty(x),avgWF{i})) %if after removal the channel i has no neurons this channel has to be replaced by an empty value - avgWF{i}=[]; - stdWF{i}=[]; - ch{i}=[]; - isNoise{i}=[]; - end - end - end - for i=find(cellfun(@(x) ~isempty(x),avgWF)) - pEmptyNeurons=cellfun(@(x) isempty(x),avgWF{i}); - avgWF{i}(pEmptyNeurons)=[]; - stdWF{i}(pEmptyNeurons)=[]; - ch{i}(pEmptyNeurons)=[]; - isNoise{i}(pEmptyNeurons)=[]; - end - else - % take the average of the largest group as the average - end - mergedNeurons=cellfun(@(x) [x(:,1) x(:,2)],neuron,'UniformOutput',0); -else - mergedNeurons=[]; -end -if ~obj.runWithoutSaving2File - save(obj.sortingFileNames.mergedAvgWaveformFile,'avgWF','stdWF','ch','mergedNeurons','isNoise'); -end - -obj=obj.findSortingFiles; %update sorted files diff --git a/spikeSorting/@gridSorter/spikePostProcessing.m b/spikeSorting/@gridSorter/spikePostProcessing.m deleted file mode 100644 index 40b4ad2..0000000 --- a/spikeSorting/@gridSorter/spikePostProcessing.m +++ /dev/null @@ -1,227 +0,0 @@ -function obj=spikePostProcessing(obj,tStartEnd) -% Run post-processing steps on spike data. Calculate post-spike fields, and spike neuron identification reliability -% obj=spikePostProcessingNSK(obj,tStart,tEnd) -% Method recieves : gridSorter object -% tStartEnd - [1 x 2] the start and end of a desired segment of the recording one which post processing is calculated -% Default - uses the t,ic of the whole recording -% -% Function give back -% Last updated : 28/03/15 - -load(obj.sortingFileNames.fittingFile,'t','ic','md','allWaveforms','isNoiseAll'); - -if nargin==2 - disp(['Calculating post processing on a subset of data ' num2str(tStartEnd(1)/1000/60/60) ' - ' num2str(tStartEnd(2)/1000/60/60) 'h']); - [t,ic]=CutSortChannel(t,ic,tStartEnd(1),tStartEnd(2),false); - postFix=[num2str(tStartEnd(1)/1000/60/60,3) '_' num2str(tStartEnd(2)/1000/60/60,3)]; - obj.sortingFileNames.postProcessingAnalysisExist=0; %overwriting -else - postFix=[]; -end - -if obj.postPlotRawLongWaveforms || obj.postPlotFilteredWaveforms %calculate figure aspect ration based on electrode layout - [mElecs,nElecs]=size(obj.chPar.En); - figurePosition=[100 50 min(1000,100*nElecs) min(900,100*mElecs)]; -end -fprintf('\nPost processing spikes...'); - -[nSamples,nNeurons,obj.nCh]=size(allWaveforms); - -if ~isempty(ic) - neuronNames=ic(1:2,:); -else - neuronNames=[]; -end - -if isempty(obj.filterObj) - obj=getHighpassFilter(obj); -end - -%for fast plotting do not pad filtered waveforms (this increases the speed considerably since padding requires about 20 sec!!!!!!!!!!! -obj.filterObj.padding=false; - -nonExistingNeurons=find(~obj.sortingFileNames.postProcessingAnalysisExist | obj.overwritePostProcessingAnalysis); -nNonExistingNeurons=numel(nonExistingNeurons); - -matFileObj = matfile([obj.sortingFileNames.postProcessingAnalysisFile(1:end-4) postFix '.mat'],'Writable',true); -if nNonExistingNeurons==1 %there is no matfile - matFileObj.postProcessingAnalysisExist=zeros(1,nNeurons); - nonExistingNeurons=1:nNeurons; - nNonExistingNeurons=numel(nonExistingNeurons); - matFileObj.neuronNames=neuronNames; - if obj.postExtractRawLongWaveformsFromSpikeTimes - matFileObj.avgLongWF=zeros(nNeurons,obj.nCh,round(obj.postTotalRawWindow*obj.dataRecordingObj.samplingFrequency(1)/1000)); - matFileObj.stdLongWF=zeros(nNeurons,obj.nCh,round(obj.postTotalRawWindow*obj.dataRecordingObj.samplingFrequency(1)/1000)); - matFileObj.PSDSNR=zeros(1,nNeurons); - else - matFileObj.avgLongWF=[];matFileObj.stdLongWF=[];matFileObj.PSDSNR=[]; - end - - if obj.postExtractFilteredWaveformsFromSpikeTimes - matFileObj.avgFinalWF=zeros(nNeurons,obj.nCh,round(obj.postTotalFilteredWindow*obj.dataRecordingObj.samplingFrequency(1)/1000)); - matFileObj.stdFinalWF=zeros(nNeurons,obj.nCh,round(obj.postTotalFilteredWindow*obj.dataRecordingObj.samplingFrequency(1)/1000)); - matFileObj.spkSNR=zeros(1,nNeurons); - matFileObj.nSpkTotal=zeros(1,nNeurons); - matFileObj.spkMaxAmp=zeros(1,nNeurons); - else - matFileObj.avgFinalWF=[];matFileObj.stdFinalWF=[];matFileObj.spkSNR=[];matFileObj.nSpkTotal=[];matFileObj.spkMaxAmp=[]; - end -end - -fprintf('Calculating SIFs (nNeurons=%d)...',numel(nonExistingNeurons)); -tic; -for i=nonExistingNeurons - tInter=toc; - fprintf('(%d) %d-%d, ',round(tInter/60),ic(1,i),ic(2,i)); - tic; - tTmp=t(ic(3,i):ic(4,i)); - mdTmp=md(ic(3,i):ic(4,i)); - nSpk=numel(tTmp); - if obj.postExtractRawLongWaveformsFromSpikeTimes - [~,pOrder]=sort(mdTmp); - tSpk=sort(tTmp(pOrder(1:min(nSpk,obj.postMaxSpikes2Present)))); %the the best spikes for SIFs according to lowest minkowski distance - - [V_uV,T_ms]=obj.dataRecordingObj.getData(obj.chPar.s2r(1:obj.nCh),tSpk-obj.postPreRawWindow,obj.postTotalRawWindow); - - %standard deviation - stdLongWF(1,:,:)=squeeze(std(V_uV,[],2)); - - %average substruction mean - avgLongWF(1,:,:)=squeeze(median(V_uV,2)); - tmpMean=mean(avgLongWF(1,:,T_ms<(obj.postPreRawWindow-1)),3); %calculate the baseline according to the average voltage before the spike (1ms before spike peak) - V_uV=bsxfun(@minus,V_uV,tmpMean'); - avgLongWF(1,:,:)=bsxfun(@minus,avgLongWF(1,:,:),tmpMean); - - p=find(T_ms>obj.postRawSNRStartEnd(1) & T_ms<=obj.postRawSNRStartEnd(2)); %find relevant time points surrounding the spike - tmpSNR=avgLongWF(1,obj.chPar.surChExtVec{obj.chPar.r2s(ic(1,i))},p)./stdLongWF(1,obj.chPar.surChExtVec{obj.chPar.r2s(ic(1,i))},p); %calculated at the position of the extended grid - - if obj.postPlotRawLongWaveforms - - f=figure('position',figurePosition); - neuronString=['Neu ' num2str(ic(1,i)) '-' num2str(ic(2,i))]; - infoStr={['nSpk=' num2str(nSpk)],neuronString,['noise=' num2str(isNoiseAll(i))]}; - - [h,hParent]=spikeDensityPlotPhysicalSpace(permute(V_uV,[3 2 1]),obj.dataRecordingObj.samplingFrequency(1),obj.chPar.s2r,obj.chPar.En,... - 'hParent',f,'avgSpikeWaveforms',permute(avgLongWF(1,:,:),[3 1 2]),'logDensity',true); - - annotation('textbox',[0.01 0.89 0.1 0.1],'FitHeightToText','on','String',infoStr); - - printFile=[obj.sortingDir filesep 'neuron' neuronString postFix '-spikeShapeRaw']; - - set(f,'PaperPositionMode','auto'); - print(printFile,'-djpeg','-r300'); - close(f); - end - - matFileObj.PSDSNR(1,i)=mean(abs(tmpSNR(:))); - matFileObj.stdLongWF(i,:,:)=stdLongWF; - matFileObj.avgLongWF(i,:,:)=avgLongWF; - end - - if obj.postExtractFilteredWaveformsFromSpikeTimes - if obj.postExtractRawLongWaveformsFromSpikeTimes - [V_uV]=obj.filterObj.getFilteredData(V_uV( : , : , :)); - V_uV=V_uV(:,:,T_ms>=(obj.postPreRawWindow-obj.postPreFilteredWindow) & T_ms<(obj.postPreRawWindow-obj.postPreFilteredWindow+obj.postTotalFilteredWindow)); - T_ms=T_ms(T_ms>=(obj.postPreRawWindow-obj.postPreFilteredWindow) & T_ms<(obj.postPreRawWindow-obj.postPreFilteredWindow+obj.postTotalFilteredWindow)); - %[V_uV,T_ms]=V_uV( : , : , T_ms>=(obj.postPreRawWindow-obj.postPreFilteredWindow) & T_ms<(obj.postPreRawWindow-obj.postPreFilteredWindow+obj.postTotalFilteredWindow)); - else - %[V_uV,T_ms]=obj.filterObj.getFilteredData(obj.dataRecordingObj.getData(obj.chPar.s2r(1:obj.nCh),tTmp(1:min(nSpk,obj.postMaxSpikes2Present))-obj.postPreFilteredWindow,obj.postTotalFilteredWindow)); - [V_uV,T_ms]=obj.dataRecordingObj.getData(obj.chPar.s2r(1:obj.nCh),tTmp(1:min(nSpk,obj.postMaxSpikes2Present))-obj.postPreFilteredWindow,obj.postTotalFilteredWindow); - end - - avgFinalWF(1,:,:)=squeeze(median(V_uV,2)); - stdFinalWF(1,:,:)=squeeze(std(V_uV,[],2)); - - p=find(T_ms>obj.postFilteredSNRStartEnd(1) & T_ms<=obj.postFilteredSNRStartEnd(2)); %find relevant time points surrounding the spike - tmpSNR=avgFinalWF(1,obj.chPar.surChExtVec{obj.chPar.r2s(ic(1,i))}(obj.chPar.pSurCh{obj.chPar.r2s(ic(1,i))}),p)./... - stdFinalWF(1,obj.chPar.surChExtVec{obj.chPar.r2s(ic(1,i))}(obj.chPar.pSurCh{obj.chPar.r2s(ic(1,i))}),p); %calculated at the positions of the surrounding grid - - if obj.postPlotFilteredWaveforms - - f=figure('position',figurePosition); - neuronString=['Neu ' num2str(ic(1,i)) '-' num2str(ic(2,i))]; - infoStr={['nSpk=' num2str(nSpk)],neuronString,['noise=' num2str(isNoiseAll(i))]}; - - [h,hParent]=spikeDensityPlotPhysicalSpace(permute(V_uV,[3 2 1]),obj.dataRecordingObj.samplingFrequency(1),obj.chPar.s2r,obj.chPar.En,... - 'hParent',f,'avgSpikeWaveforms',permute(avgFinalWF(1,:,:),[3 1 2]),'logDensity',true); - - annotation('textbox',[0.01 0.89 0.1 0.1],'FitHeightToText','on','String',infoStr); - - %print to file - printFile=[obj.sortingDir filesep 'neuron' neuronString postFix '-spikeShape']; - set(f,'PaperPositionMode','auto'); - print(printFile,'-djpeg','-r300'); - close(f); - end - - matFileObj.avgFinalWF(i,:,:)=avgFinalWF; - matFileObj.stdFinalWF(i,:,:)=stdFinalWF; - matFileObj.spkSNR(1,i)=mean(abs(tmpSNR(:))); - matFileObj.spkMaxAmp(1,i)=max(max(abs(avgFinalWF))); %the extremal spike amplitude - matFileObj.nSpkTotal(1,i)=ic(4,i)-ic(3,i)+1; - - end - matFileObj.postProcessingAnalysisExist(1,i)=1; -end %loop over all neurons -fprintf('Done!\n'); - -if obj.postPlotAllAvgSpikeTemplates - nPlotAxis=min(ceil(sqrt(nNeurons)),5); - nPlotsPerFigure=nPlotAxis.^2; - if nNeurons>0 - for i=1:(nNeurons+1) - if mod((i-1),nPlotsPerFigure)==0 || i==(nNeurons+1) - if i~=1 - printFile=[obj.sortingDir filesep 'avgSpikeShapes' postFix num2str(ceil((i-1)/nPlotsPerFigure))]; - if obj.fastPrinting - imwrite(frame2im(getframe(f)),[printFile '.jpeg'],'Quality',90); - else - set(f,'PaperPositionMode','auto'); - print(printFile,'-djpeg','-r300'); - end - close(f); - end - if i~=(nNeurons+1) - f=figure('position',figurePosition); - end - end - if i0 - f=figure('position',[300 50 900 700]); - mNSpkTotal=mean(matFileObj.nSpkTotal); - %generate size legend - plotSpikeSNR=[matFileObj.spkSNR (max(matFileObj.spkSNR)-(max(matFileObj.spkSNR)-min(matFileObj.spkSNR))*0.01)*ones(1,5)]; - plotPSDSNR=[matFileObj.PSDSNR [0.9 1 1.1 1.2 1.3]*((max(matFileObj.PSDSNR)+min(matFileObj.PSDSNR))/2)]; - legendSpikeNums=round([mNSpkTotal/6 mNSpkTotal/3 mNSpkTotal mNSpkTotal*3 mNSpkTotal*6]); - plotnSpkTotal=[matFileObj.nSpkTotal legendSpikeNums]; - plotspkMaxAmp=[matFileObj.spkMaxAmp ones(1,5)*min(matFileObj.spkMaxAmp)]; - - scatter(plotSpikeSNR,plotPSDSNR,(plotnSpkTotal/mNSpkTotal)*50+5,plotspkMaxAmp,'linewidth',2); - text(plotSpikeSNR(end-4:end)*1.02,plotPSDSNR(end-4:end),num2str(legendSpikeNums'/(obj.dataRecordingObj.recordingDuration_ms/1000),3),'FontSize',8) - xlabel('$$\sqrt{SNR_{spike}}$$','Interpreter','latex','FontSize',14);ylabel('$$\sqrt{SNR_{PSD}}$$','Interpreter','latex','FontSize',14); - cb=colorbar('position',[0.8511 0.6857 0.0100 0.2100]);ylabel(cb,'Max spk. amp.'); - - printFile=[obj.sortingDir filesep 'SNR_spikePSD' postFix]; - set(f,'PaperPositionMode','auto'); - print(printFile,'-djpeg','-r300'); - end -end - -%[obj, er]=assessQuality(obj); - -obj=obj.findSortingFiles; %update sorted files diff --git a/spikeSorting/@gridSorter/testFile.mat b/spikeSorting/@gridSorter/testFile.mat deleted file mode 100644 index 0582391..0000000 Binary files a/spikeSorting/@gridSorter/testFile.mat and /dev/null differ diff --git a/spikeSorting/@gridSorter/undetected.m b/spikeSorting/@gridSorter/undetected.m deleted file mode 100644 index c7efb4d..0000000 --- a/spikeSorting/@gridSorter/undetected.m +++ /dev/null @@ -1,136 +0,0 @@ -function [p,mu,stdev,n,x] = undetected(w,threshes,criteria_func) -% UltraMegaSort2000 by Hill DN, Mehta SB, & Kleinfeld D - 07/12/201 -%modified by Sam Reiter 7.4.2015 -% -% undetected - estimate fraction of events that did not reach threshold -% -% Usage: -% [p,mu,stdev,n,x] = undetected(waveforms,threshes,criteria_func) -% -% Description: -% Estimates fraction of events that did not reach threshold by applying -% the detection metric to each waveform and then fitting it with a Gaussian -% that has a missing tail. -% -% The distribution of detection metric values is turned into a histogram. -% A Gaussian is fit to the historgram to minimize the absolute error -% between the Gaussian and the histogram for values above threshold. -% The integral of this Gaussian that is below threshold is the estimate of -% the fraction of missing events. -% -% Note that values are normalized so that the threshold is +/- 1. The function -% attempts to preserve the sign of the original threshold, unless thresholds -% on different channels had different signs. In the case of multiple channels, -% each channel is normalized so that the threshold has a magnitude of 1. Then, -% for each event, only the channel with the most extreme value of the detection -% metric is used. -% -% By default, this function assumes that a simple voltage crossing was used -% for detection, but see "criteria_fun" below for alternatives. In the case -% of a simple voltage threshold, note that the threshold is interpreted as -% responding to crossings away from zero, i.e., negative thresholds -% imply negative-going crossings and positive thresholds imply -% positive-going crossings. -% -% -% Input: -% waveforms - [Events X Samples X Channels] the waveforms of the cluster -% threshes - [1 X Channels] the threshold for each channel -% criteria_func - Used to determine what the detection metric is on each -% waveform. If this is the string "auto" or "manual" then -% it is assumed that a simple voltage threshold was used. -% The detection criterion then is to divide each channel -% by its threhsold and use the maximum value. Otherwise -% the criteria_func is assumed to be a function handle that -% takes in waveforms and threshes and returns the detection -% metric for each event [Events x 1]. The function will -% be called as -% criteria = criteria_func( waveforms, threshes) -% It is assumed that the values of criteria are normalized -% to use a threshold value of + 1. -% -% Output: -% p - estimate of probability that a spike is missing because it didn't reach threshhold -% mu - mean estimated for gaussian fit -% stdev - standard deviation estimated for gaussian fit -% n - bin counts for histogram used to fit Gaussian -% x - bin centers for histogram used to fit Gaussian -% - - % constant bin count - bins = 75; - - % check for detection method - if isequal( criteria_func, 'auto') | isequal( criteria_func, 'manual' ) - % normalize all waveforms by threshold - th(1,1,:) = threshes; - w = w ./ repmat( th, [size(w,1) size(w,2) 1] ); - - % find maximum channel - meanSpike=squeeze(mean(w)); - [val maxTime]=max(meanSpike); - [val maxChan]=max(max(meanSpike)); - - criteria=squeeze(w(:,maxTime(maxChan),maxChan)); - - else - criteria = criteria_func( w, threshes); - end - - % create the histogram values - global_max = max(criteria); - mylims = linspace( 1,global_max,bins+1); - x = mylims + (mylims(2) - mylims(1))/2; - n = histc( criteria,mylims ); - - % fit the histogram with a cutoff gaussian - m = mode_guesser(criteria, .05); % use mode instead of mean, since tail might be cut off - [stdev,mu] = stdev_guesser(criteria, n, x, m); % fit the standard deviation as well - - % Now make an estimate of how many spikes are missing, given the Gaussian and the cutoff - p = normcdf( 1,mu,stdev); - - % attempt to keep values negative if all threshold values were negative - if all( threshes < 0 ) - mu = -mu; - x = -x; - end - -end - -% fit the standard deviation to the histogram by looking for an accurate -% match over a range of possible values -function [stdev,m] = stdev_guesser( thresh_val, n, x, m) - - % initial guess is juts the RMS of just the values below the mean - init = sqrt( mean( (m-thresh_val(thresh_val>=m)).^2 ) ); - - % try 20 values, within a factor of 2 of the initial guess - num = 20; - st_guesses = linspace( init/2, init*2, num ); - m_guesses = linspace( m-init,max(m+init,1),num); - for j = 1:length(m_guesses) - for k = 1:length(st_guesses) - b = normpdf(x,m_guesses(j),st_guesses(k)); - b = b *sum(n) / sum(b); - error(j,k) = sum(abs(b(:)-n(:))); - end - end - - % which one has the least error? - [val,pos] = min(error(:)); - jpos = mod( pos, num ); if jpos == 0, jpos = num; end - kpos = ceil(pos/num); - stdev = st_guesses(kpos); - - % refine mode estimate - m = m_guesses(jpos); - -end - - - - - - - diff --git a/spikeSorting/PCAfeaturesSpikeShapePlot.m b/spikeSorting/PCAfeaturesSpikeShapePlot.m deleted file mode 100644 index a00e935..0000000 --- a/spikeSorting/PCAfeaturesSpikeShapePlot.m +++ /dev/null @@ -1,83 +0,0 @@ -function [hFigure]=PCAfeaturesSpikeShapePlot(spikeFeatures,spikeShapes,Fs,idx1,idx2,En,ch,varargin) -removeOutliers=0; -hFigure=[]; -cmap=lines; -rejectPCAStd=20; %the multiplicator in PCA space for determining a thershold for outlier rejection -maxNumberOutliers=50; - -%print out default arguments and values if no inputs are given -if nargin==0 - defaultArguments=who; - for i=1:numel(defaultArguments) - eval(['defaultArgumentValue=' defaultArguments{i} ';']); - disp([defaultArguments{i} ' = ' num2str(defaultArgumentValue)]); - end - return; -end - -%Collects all options -for i=1:2:length(varargin) - eval([varargin{i} '=' 'varargin{i+1};']) -end - -if isempty(hFigure) - hFigure=figure('Position',[100 100 1200 800],'color','w'); -end -set(hFigure,'DefaultAxesColorOrder',cmap); - -hHBox = uix.HBox( 'Parent', hFigure, 'Padding', 5, 'Spacing', 1 ); -hVBox = uix.VBox( 'Parent', hHBox, 'Padding', 5, 'Spacing', 1 ); -hPanel = uipanel( 'Parent', hHBox, 'BorderType','none','BackgroundColor','w'); -set( hHBox, 'Widths', [-1 -2] ); -h1=axes('Parent',hVBox); -h2=axes('Parent',hVBox); -set( hVBox, 'Heights', [-1 -1] ); - -[PCAFeatureSimMat,PCAspikeFeatures] = pca(spikeFeatures); %run PCA for visualization purposes -sPC1=median(abs( PCAspikeFeatures(:,1)-median(PCAspikeFeatures(:,1)) )) / 0.6745; -sPC2=median(abs( PCAspikeFeatures(:,2)-median(PCAspikeFeatures(:,2)) )) / 0.6745; -pOutliers=find( PCAspikeFeatures(:,1)>rejectPCAStd*sPC1 | PCAspikeFeatures(:,1)<-rejectPCAStd*sPC1 | PCAspikeFeatures(:,2)>rejectPCAStd*sPC2 | PCAspikeFeatures(:,2)<-rejectPCAStd*sPC2); -nOutliers=numel(pOutliers); - -if nOutliers current thread ) -=>0x000000000f718800 JavaThread "Main message loop" daemon [_thread_in_native, id=1012, stack(0x000000001a1f0000,0x000000001a270000)] - 0x00000000090b6800 JavaThread "Timer-248" daemon [_thread_blocked, id=5112, stack(0x0000000029a40000,0x0000000029ac0000)] - 0x00000000090b7000 JavaThread "Main message loop" daemon [_thread_in_native, id=6608, stack(0x0000000019cc0000,0x0000000019d40000)] - 0x00000000090b0800 JavaThread "com.jniwrapper.NativeResourceCollector" daemon [_thread_blocked, id=7560, stack(0x000000001d040000,0x000000001d0c0000)] - 0x00000000090ba000 JavaThread "pool-5-thread-1" [_thread_blocked, id=6416, stack(0x0000000029860000,0x00000000298e0000)] - 0x00000000090b9800 JavaThread "Code Analyzer updating thread" [_thread_blocked, id=2948, stack(0x0000000019430000,0x00000000194b0000)] - 0x00000000090bb000 JavaThread "Prefs Updater" daemon [_thread_blocked, id=6096, stack(0x00000000193b0000,0x0000000019430000)] - 0x00000000090b8000 JavaThread "Swing-Shell" daemon [_thread_blocked, id=5888, stack(0x0000000029ac0000,0x0000000029b40000)] - 0x00000000090b5800 JavaThread "Code Analyzer updating thread" [_thread_blocked, id=6264, stack(0x00000000656a0000,0x0000000065720000)] - 0x00000000090b5000 JavaThread "Code Analyzer updating thread" [_thread_blocked, id=2600, stack(0x00000000655f0000,0x0000000065670000)] - 0x00000000090b4800 JavaThread "Code Analyzer updating thread" [_thread_blocked, id=4752, stack(0x00000000654c0000,0x0000000065540000)] - 0x00000000090b2000 JavaThread "Active Reference Queue Daemon" daemon [_thread_blocked, id=4376, stack(0x00000000653f0000,0x0000000065470000)] - 0x00000000090b3800 JavaThread "Timer-7" daemon [_thread_blocked, id=7016, stack(0x00000000295e0000,0x0000000029660000)] - 0x00000000090b3000 JavaThread "Timer-6" daemon [_thread_blocked, id=7504, stack(0x0000000060b10000,0x0000000060b90000)] - 0x00000000090b1800 JavaThread "Explorer NavigationContext request queue" [_thread_blocked, id=1164, stack(0x0000000065300000,0x0000000065380000)] - 0x00000000090b0000 JavaThread "AddressBar directory emptiness poller" [_thread_blocked, id=5528, stack(0x0000000060a70000,0x0000000060af0000)] - 0x00000000090af000 JavaThread "Explorer Refresh Service 1817960366" [_thread_blocked, id=5692, stack(0x00000000605b0000,0x0000000060630000)] - 0x000000000f71a800 JavaThread "Timer-1" daemon [_thread_blocked, id=7964, stack(0x0000000060680000,0x0000000060700000)] - 0x000000000f717000 JavaThread "TimerQueue" daemon [_thread_blocked, id=5804, stack(0x0000000058e50000,0x0000000058ed0000)] - 0x000000000f714000 JavaThread "Thread-5" daemon [_thread_blocked, id=5360, stack(0x0000000029560000,0x00000000295e0000)] - 0x000000000f716000 JavaThread "FelixPackageAdmin" daemon [_thread_blocked, id=5708, stack(0x0000000021290000,0x0000000021310000)] - 0x000000000f715800 JavaThread "FelixStartLevel" daemon [_thread_blocked, id=7796, stack(0x0000000048b30000,0x0000000048bb0000)] - 0x000000000f714800 JavaThread "FelixDispatchQueue" daemon [_thread_blocked, id=8124, stack(0x0000000050c10000,0x0000000050c90000)] - 0x000000000f713000 JavaThread "AWT-EventQueue-0" [_thread_blocked, id=1540, stack(0x000000001d130000,0x000000001d1b0000)] - 0x000000000f712800 JavaThread "com.google.common.base.internal.Finalizer" daemon [_thread_blocked, id=5444, stack(0x0000000025490000,0x0000000025510000)] - 0x000000000f711000 JavaThread "AWT-Windows" daemon [_thread_in_native, id=5152, stack(0x000000001d1e0000,0x000000001d260000)] - 0x000000000f710800 JavaThread "AWT-Shutdown" [_thread_blocked, id=6036, stack(0x0000000019060000,0x00000000190e0000)] - 0x000000000f70f800 JavaThread "Java2D Disposer" daemon [_thread_blocked, id=1288, stack(0x000000000ff60000,0x000000000ffe0000)] - 0x000000000f70f000 JavaThread "Timer-0" [_thread_blocked, id=5732, stack(0x0000000010ec0000,0x0000000010f40000)] - 0x000000000f70e000 JavaThread "EventMgr Dispatcher" daemon [_thread_in_native, id=1844, stack(0x00000000099d0000,0x000000000d9d0000)] - 0x000000000f70c800 JavaThread "Low Memory Detector" daemon [_thread_blocked, id=3240, stack(0x000000000f8f0000,0x000000000f970000)] - 0x000000000f71f800 JavaThread "CompilerThread1" daemon [_thread_blocked, id=1132, stack(0x0000000090490000,0x0000000094490000)] - 0x000000000f71c000 JavaThread "CompilerThread0" daemon [_thread_blocked, id=7628, stack(0x000000008c330000,0x0000000090330000)] - 0x000000000f70c000 JavaThread "Attach Listener" daemon [_thread_blocked, id=6804, stack(0x000000000f990000,0x000000000fa10000)] - 0x000000000f6b3000 JavaThread "Finalizer" daemon [_thread_blocked, id=2596, stack(0x000000000f480000,0x000000000f500000)] - 0x000000000f6a9000 JavaThread "Reference Handler" daemon [_thread_blocked, id=7724, stack(0x000000000f820000,0x000000000f8a0000)] - 0x0000000005cb1800 JavaThread "main" [_thread_in_native, id=6388, stack(0x0000000000080000,0x0000000004080000)] - -Other Threads: - 0x000000000f6a4000 VMThread [stack: 0x00000000882f0000,0x000000008c2f0000] [id=7196] - 0x000000000f74b800 WatcherThread [stack: 0x0000000094580000,0x0000000098580000] [id=7036] - -VM state:not at safepoint (normal execution) - -VM Mutex/Monitor currently owned by a thread: None - -Heap - PSYoungGen total 32832K, used 7080K [0x00000000419e0000, 0x00000000442c0000, 0x0000000044ae0000) - eden space 24448K, 21% used [0x00000000419e0000,0x0000000041f1a070,0x00000000431c0000) - from space 8384K, 20% used [0x0000000043a00000,0x0000000043bb0018,0x0000000044230000) - to space 8448K, 0% used [0x00000000431c0000,0x00000000431c0000,0x0000000043a00000) - PSOldGen total 101376K, used 63968K [0x00000000386e0000, 0x000000003e9e0000, 0x00000000419e0000) - object space 101376K, 63% used [0x00000000386e0000,0x000000003c5581d0,0x000000003e9e0000) - PSPermGen total 100416K, used 76514K [0x00000000306e0000, 0x00000000368f0000, 0x00000000386e0000) - object space 100416K, 76% used [0x00000000306e0000,0x0000000035198ab0,0x00000000368f0000) - -Dynamic libraries: -0x000000013f640000 - 0x000000013f66d000 C:\Program Files\MATLAB\R2012b\bin\win64\MATLAB.exe -0x0000000076e90000 - 0x0000000077039000 C:\Windows\SYSTEM32\ntdll.dll -0x0000000076c70000 - 0x0000000076d8f000 C:\Windows\system32\kernel32.dll -0x000007fefcf80000 - 0x000007fefcfeb000 C:\Windows\system32\KERNELBASE.dll -0x0000000074460000 - 0x000000007451f000 C:\Program Files\MATLAB\R2012b\bin\win64\libut.dll -0x00000000758a0000 - 0x000000007595c000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwi18n.dll -0x0000000180000000 - 0x000000018000b000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwresource_core.dll -0x000000006a890000 - 0x000000006a963000 C:\Windows\WinSxS\amd64_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.6161_none_08e61857a83bc251\MSVCP90.dll -0x0000000073210000 - 0x00000000732b3000 C:\Windows\WinSxS\amd64_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.6161_none_08e61857a83bc251\MSVCR90.dll -0x000000007a170000 - 0x000000007a19c000 C:\Program Files\MATLAB\R2012b\bin\win64\boost_filesystem-vc90-mt-1_44.dll -0x000000007a560000 - 0x000000007a569000 C:\Program Files\MATLAB\R2012b\bin\win64\boost_system-vc90-mt-1_44.dll -0x000007fefec00000 - 0x000007fefecdb000 C:\Windows\system32\ADVAPI32.dll -0x000007fefedf0000 - 0x000007fefee8f000 C:\Windows\system32\msvcrt.dll -0x000007fefebe0000 - 0x000007fefebff000 C:\Windows\SYSTEM32\sechost.dll -0x000007fefefa0000 - 0x000007feff0cd000 C:\Windows\system32\RPCRT4.dll -0x000000007a010000 - 0x000000007a035000 C:\Program Files\MATLAB\R2012b\bin\win64\LIBEXPAT.dll -0x000000006aa50000 - 0x000000006ac41000 C:\Program Files\MATLAB\R2012b\bin\win64\icuin44.dll -0x000000006ae90000 - 0x000000006b001000 C:\Program Files\MATLAB\R2012b\bin\win64\icuuc44.dll -0x0000000010000000 - 0x0000000010e41000 C:\Program Files\MATLAB\R2012b\bin\win64\icudt44.dll -0x0000000073f70000 - 0x000000007411d000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwfl.dll -0x0000000004330000 - 0x00000000046e6000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwMATLAB_res.dll -0x000000007a3b0000 - 0x000000007a3c0000 C:\Program Files\MATLAB\R2012b\bin\win64\boost_date_time-vc90-mt-1_44.dll -0x000000007a250000 - 0x000000007a263000 C:\Program Files\MATLAB\R2012b\bin\win64\boost_signals-vc90-mt-1_44.dll -0x000000007a2d0000 - 0x000000007a2e2000 C:\Program Files\MATLAB\R2012b\bin\win64\boost_thread-vc90-mt-1_44.dll -0x00000000046f0000 - 0x00000000047ad000 C:\Program Files\MATLAB\R2012b\bin\win64\boost_log-vc90-mt-1_44.dll -0x0000000077050000 - 0x0000000077057000 C:\Windows\system32\PSAPI.DLL -0x000007fefd500000 - 0x000007fefd54d000 C:\Windows\system32\WS2_32.dll -0x000007fefd0b0000 - 0x000007fefd0b8000 C:\Windows\system32\NSI.dll -0x00000000041b0000 - 0x00000000041f6000 C:\Program Files\MATLAB\R2012b\bin\win64\tbb.dll -0x000007fefd090000 - 0x000007fefd0a9000 C:\Windows\system32\imagehlp.dll -0x000000006eac0000 - 0x000000006ead3000 C:\Program Files\MATLAB\R2012b\bin\win64\icuio44.dll -0x000007fef8750000 - 0x000007fef8875000 C:\Windows\system32\dbghelp.dll -0x0000000076d90000 - 0x0000000076e8a000 C:\Windows\system32\USER32.dll -0x000007fefeb70000 - 0x000007fefebd7000 C:\Windows\system32\GDI32.dll -0x000007fefd2f0000 - 0x000007fefd2fe000 C:\Windows\system32\LPK.dll -0x000007feff0d0000 - 0x000007feff199000 C:\Windows\system32\USP10.dll -0x00000000047b0000 - 0x0000000004a8c000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwservices.dll -0x0000000075a20000 - 0x0000000075af3000 C:\Program Files\MATLAB\R2012b\bin\win64\libmx.dll -0x0000000004aa0000 - 0x0000000004ac9000 C:\Program Files\MATLAB\R2012b\bin\win64\tbbmalloc.dll -0x000000007a210000 - 0x000000007a228000 C:\Program Files\MATLAB\R2012b\bin\win64\zlib1.dll -0x0000000004af0000 - 0x0000000004b3d000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwregexp.dll -0x0000000004b50000 - 0x0000000004b73000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwmfl_scalar.dll -0x0000000075f10000 - 0x0000000075f60000 C:\Program Files\MATLAB\R2012b\bin\win64\mpath.dll -0x000000007b680000 - 0x000000007bc9a000 C:\Program Files\MATLAB\R2012b\bin\win64\mlutil.dll -0x00000000754d0000 - 0x0000000075551000 C:\Program Files\MATLAB\R2012b\bin\win64\xmlcore.dll -0x0000000004bc0000 - 0x0000000004e13000 C:\Program Files\MATLAB\R2012b\bin\win64\xerces-c_2_7.dll -0x0000000004e30000 - 0x0000000004e50000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwMATLAB_settings_res.dll -0x0000000004e60000 - 0x0000000004e70000 C:\Program Files\MATLAB\R2012b\bin\win64\boost_iostreams-vc90-mt-1_44.dll -0x0000000004e80000 - 0x0000000004ec7000 C:\Program Files\MATLAB\R2012b\bin\win64\boost_serialization-vc90-mt-1_44.dll -0x000007fefd7d0000 - 0x000007fefe558000 C:\Windows\system32\SHELL32.dll -0x000007fefece0000 - 0x000007fefed51000 C:\Windows\system32\SHLWAPI.dll -0x000007fef7310000 - 0x000007fef73b0000 C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_5.82.7601.17514_none_a4d6a923711520a9\COMCTL32.dll -0x000007fefd550000 - 0x000007fefd5e7000 C:\Windows\system32\COMDLG32.dll -0x000007fefa6b0000 - 0x000007fefa6c6000 C:\Windows\system32\NETAPI32.dll -0x000007fefc160000 - 0x000007fefc16c000 C:\Windows\system32\netutils.dll -0x000007fefc890000 - 0x000007fefc8b3000 C:\Windows\system32\srvcli.dll -0x000007fefa690000 - 0x000007fefa6a5000 C:\Windows\system32\wkscli.dll -0x000007fefe960000 - 0x000007fefeb63000 C:\Windows\system32\ole32.dll -0x000007fefe880000 - 0x000007fefe957000 C:\Windows\system32\OLEAUT32.dll -0x0000000074970000 - 0x0000000074a31000 C:\Program Files\MATLAB\R2012b\bin\win64\mcr.dll -0x0000000075000000 - 0x00000000753e9000 C:\Program Files\MATLAB\R2012b\bin\win64\iqm.dll -0x0000000074e80000 - 0x0000000074f38000 C:\Program Files\MATLAB\R2012b\bin\win64\m_dispatcher.dll -0x0000000074880000 - 0x000000007496d000 C:\Program Files\MATLAB\R2012b\bin\win64\boost_regex-vc90-mt-1_44.dll -0x000007fee9ab0000 - 0x000007feea321000 C:\Program Files\MATLAB\R2012b\bin\win64\m_interpreter.dll -0x000000006ea90000 - 0x000000006eab7000 C:\Program Files\MATLAB\R2012b\bin\win64\libmex.dll -0x000000006b160000 - 0x000000006b1e4000 C:\Program Files\MATLAB\R2012b\bin\win64\profiler.dll -0x0000000004f50000 - 0x00000000051ba000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwmathutil.dll -0x0000000079f40000 - 0x0000000079f6e000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwmathrng.dll -0x00000000051e0000 - 0x00000000051f2000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwmfl_rng.dll -0x0000000074c10000 - 0x0000000074cee000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwmathcore.dll -0x0000000076160000 - 0x00000000761ca000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwspmatrix.dll -0x0000000075ea0000 - 0x0000000075f02000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwcholmod.dll -0x000000007a460000 - 0x000000007a46d000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwamd.dll -0x000000007a4b0000 - 0x000000007a4bc000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwcolamd.dll -0x000000007a290000 - 0x000000007a2a9000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwblas.dll -0x000000007a310000 - 0x000000007a321000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwbinder.dll -0x000000007a4d0000 - 0x000000007a4dc000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwompwrapper.dll -0x0000000005290000 - 0x0000000005315000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwlapack.dll -0x000000006ea50000 - 0x000000006ea71000 C:\Program Files\MATLAB\R2012b\bin\win64\m_pcodeio.dll -0x0000000079b10000 - 0x0000000079b77000 C:\Program Files\MATLAB\R2012b\bin\win64\m_ir.dll -0x0000000061790000 - 0x0000000061e00000 C:\Program Files\MATLAB\R2012b\bin\win64\m_parser.dll -0x000000006eb80000 - 0x000000006eb9a000 C:\Program Files\MATLAB\R2012b\bin\win64\ir_xfmr.dll -0x000007feea910000 - 0x000007feeaba6000 C:\Program Files\MATLAB\R2012b\bin\win64\mcos.dll -0x000000006ea30000 - 0x000000006ea41000 C:\Program Files\MATLAB\R2012b\bin\win64\mtok.dll -0x000000006e9f0000 - 0x000000006ea21000 C:\Program Files\MATLAB\R2012b\bin\win64\m_pcodegen.dll -0x0000000079fb0000 - 0x0000000079fe6000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwbridge.dll -0x000000006b090000 - 0x000000006b158000 C:\Program Files\MATLAB\R2012b\bin\win64\udd.dll -0x000000006ad30000 - 0x000000006ae82000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwgui.dll -0x000000006b280000 - 0x000000006b297000 C:\Program Files\MATLAB\R2012b\bin\win64\graphics_util.dll -0x0000000060d30000 - 0x000000006178f000 C:\Program Files\MATLAB\R2012b\bin\win64\hg.dll -0x00000000053f0000 - 0x0000000005458000 C:\Program Files\MATLAB\R2012b\bin\win64\libmat.dll -0x0000000072d30000 - 0x0000000072f44000 C:\Program Files\MATLAB\R2012b\bin\win64\hdf5dll.dll -0x0000000075710000 - 0x00000000757de000 C:\Program Files\MATLAB\R2012b\bin\win64\jmi.dll -0x0000000005490000 - 0x000000000549d000 C:\Program Files\MATLAB\R2012b\bin\win64\nativejava_services.dll -0x000000006b040000 - 0x000000006b086000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwhardcopy.dll -0x000000006acc0000 - 0x000000006ad23000 C:\Program Files\MATLAB\R2012b\bin\win64\libuij.dll -0x0000000065e80000 - 0x00000000660e4000 C:\Program Files\MATLAB\R2012b\bin\win64\hgdatatypes.dll -0x000000006a3f0000 - 0x000000006a50f000 C:\Program Files\MATLAB\R2012b\bin\win64\hgutils.dll -0x000000006a570000 - 0x000000006a630000 C:\Program Files\MATLAB\R2012b\bin\win64\udd_mi.dll -0x0000000005500000 - 0x000000000553b000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwgbtutils.dll -0x0000000005550000 - 0x000000000556b000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwgbt.dll -0x0000000005580000 - 0x0000000005851000 C:\Program Files\MATLAB\R2012b\bin\win64\uiw.dll -0x000000006e970000 - 0x000000006e97f000 C:\Program Files\MATLAB\R2012b\bin\win64\uinone.dll -0x0000000005880000 - 0x00000000058a9000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwnativefiledialogs.dll -0x00000000058c0000 - 0x00000000058c8000 C:\Program Files\MATLAB\R2012b\bin\win64\libmwplatform_res.dll -0x000007fefb5a0000 - 0x000007fefb5b8000 C:\Windows\system32\MPR.dll -0x0000000063dc0000 - 0x00000000642a4000 C:\Windows\WinSxS\amd64_microsoft.vc90.mfc_1fc8b3b9a1e18e3b_9.0.30729.6161_none_044aad0bab1eb146\mfc90.dll -0x000007fefab20000 - 0x000007fefab27000 C:\Windows\system32\MSIMG32.dll -0x000007fef88f0000 - 0x000007fef8961000 C:\Windows\system32\WINSPOOL.DRV -0x000000006b250000 - 0x000000006b272000 C:\Program Files\MATLAB\R2012b\bin\win64\mwoles05.DLL -0x000000006a040000 - 0x000000006a0bd000 C:\Program Files\MATLAB\R2012b\bin\win64\comcli.dll -0x0000000071cc0000 - 0x0000000071cef000 C:\Windows\WinSxS\amd64_microsoft.vc90.atl_1fc8b3b9a1e18e3b_9.0.30729.6161_none_0a1fd3a3a768b895\ATL90.DLL -0x000000006e9e0000 - 0x000000006e9ec000 C:\Program Files\MATLAB\R2012b\bin\win64\mlautoregister.dll -0x000007fefcb40000 - 0x000007fefcb97000 C:\Windows\system32\apphelp.dll -0x000007fef3e40000 - 0x000007fef3e91000 C:\Windows\AppPatch\AppPatch64\AcGenral.DLL -0x000007fefcb00000 - 0x000007fefcb25000 C:\Windows\system32\SspiCli.dll -0x0000000072b40000 - 0x0000000072b43000 C:\Windows\system32\sfc.dll -0x000007fef8ab0000 - 0x000007fef8ac0000 C:\Windows\system32\sfc_os.DLL -0x000007fefbfa0000 - 0x000007fefbfbe000 C:\Windows\system32\USERENV.dll -0x000007fefcc60000 - 0x000007fefcc6f000 C:\Windows\system32\profapi.dll -0x000007fefa9a0000 - 0x000007fefa9b8000 C:\Windows\system32\dwmapi.dll -0x000007fefedc0000 - 0x000007fefedee000 C:\Windows\system32\IMM32.DLL -0x000007fefee90000 - 0x000007fefef99000 C:\Windows\system32\MSCTF.dll -0x0000000074a70000 - 0x0000000074aa8000 C:\PROGRA~2\Sophos\SOPHOS~1\SOPHOS~2.DLL -0x000007fefae10000 - 0x000007fefae66000 C:\Windows\system32\UxTheme.dll -0x000000006c5b0000 - 0x000000006c5bd000 C:\Windows\WinSxS\amd64_microsoft.vc90.mfcloc_1fc8b3b9a1e18e3b_9.0.30729.6161_none_01c9581e60cbee58\MFC90ENU.DLL -0x0000000078870000 - 0x0000000078ecd000 C:\Program Files\MATLAB\R2012b\sys\java\jre\win64\jre\bin\server\jvm.dll -0x000007fefa330000 - 0x000007fefa36b000 C:\Windows\system32\WINMM.dll - -VM Arguments: -jvm_args: -Xss512k -XX:PermSize=32m -Xms64m -XX:NewRatio=3 -XX:MaxPermSize=128m -Xmx196m -XX:MaxDirectMemorySize=2147400000 -Dsun.java2d.noddraw=true -Dsun.awt.nopixfmt=true -Xshare:off -Xrs -Dsun.awt.disableMixing=true -Djava.library.path=C:\Program Files\MATLAB\R2012b\bin\win64;C:\Program Files\MATLAB\R2012b\sys\jxbrowser\win64\lib vfprintf abort -java_command: -Launcher Type: generic - -Environment Variables: -PATH=C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\MATLAB\R2012b_tmp\runtime\win64;C:\Program Files\MATLAB\R2012b_tmp\bin;C:\Program Files\MATLAB\R2012b\runtime\win64;C:\Program Files\MATLAB\R2012b\bin;C:\Program Files\Microsoft Windows Performance Toolkit\ -USERNAME=sheinidm -OS=Windows_NT -PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 58 Stepping 9, GenuineIntel - - - ---------------- S Y S T E M --------------- - -OS: Windows 7 Build 7601 Service Pack 1 - -CPU:total 8 (8 cores per cpu, 2 threads per core) family 6 model 58 stepping 9, cmov, cx8, fxsr, mmx, sse, sse2, sse3, ssse3, sse4.1, sse4.2, ht - -Memory: 4k page, physical 16717308k(12316204k free), swap 33432760k(29226416k free) - -vm_info: Java HotSpot(TM) 64-Bit Server VM (14.3-b01) for windows-amd64 JRE (1.6.0_17-b04), built on Oct 11 2009 00:46:08 by "java_re" with MS VC++ 8.0 - -time: Tue Apr 09 11:37:31 2013 -elapsed time: 1408 seconds - diff --git a/spikeSorting/makeConfigKiloSort.m b/spikeSorting/makeConfigKiloSort.m deleted file mode 100644 index 1ce9a4f..0000000 --- a/spikeSorting/makeConfigKiloSort.m +++ /dev/null @@ -1,94 +0,0 @@ -function ops=makeConfigKiloSort(sortingDir,nCh,varargin) - -ops.datatype = 'bin'; % binary ('dat', 'bin') or 'openEphys' - -ops.GPU = 1; % whether to run this code on an Nvidia GPU (much faster, mexGPUall first) -ops.parfor = 0; % whether to use parfor to accelerate some parts of the algorithm -ops.verbose = 1; % whether to print command line progress -ops.showfigures = 1; % whether to plot figures during optimization - -ops.FiltersPerCh = 3; -ops.nNeighPC = 12; % visualization only (Phy): number of channnels to mask the PCs, leave empty to skip (12) -ops.nNeigh = 16; % visualization only (Phy): number of neighboring templates to retain projections of (16) - -% options for channel whitening -ops.whitening = 'full'; % type of whitening (default 'full', for 'noSpikes' set options for spike detection below) -ops.nSkipCov = 1; % compute whitening matrix from every N-th batch (1) -ops.whiteningRange = 36; % how many channels to whiten together (Inf for whole probe whitening, should be fine if Nchan<=32) - -ops.criterionNoiseChannels = 0.2; % fraction of "noise" templates allowed to span all channel groups (see createChannelMapFile for more info). - -% other options for controlling the model and optimization -ops.Nrank = 3; % matrix rank of spike template model (3) -ops.nfullpasses = 6; % number of complete passes through data during optimization (6) -ops.maxFR = 20000; % maximum number of spikes to extract per batch (20000) -ops.fshigh = 250; % frequency for high pass filtering -ops.fslow = 3000; % frequency for low pass filtering (optional) -ops.ntbuff = 64; % samples of symmetrical buffer for whitening and spike detection -ops.scaleproc = 200; % int16 scaling of whitened data -ops.NT = 128*1024+ ops.ntbuff;% this is the batch size (try decreasing if out of memory) -% for GPU should be multiple of 32 + ntbuff - -% the following options can improve/deteriorate results. -% when multiple values are provided for an option, the first two are beginning and ending anneal values, -% the third is the value used in the final pass. -ops.Th = [6 12 12]; % threshold for detecting spikes on template-filtered data ([6 12 12]) / default=[4 10 10] -ops.lam = [5 5 5]; % large means amplitudes are forced around the mean ([10 30 30]) -ops.nannealpasses = 4; % should be less than nfullpasses (4) -ops.momentum = 1./[20 400]; % start with high momentum and anneal (1./[20 1000]) -ops.shuffle_clusters = 1; % allow merges and splits during optimization (1) -ops.mergeT = .1; % upper threshold for merging (.1) -ops.splitT = .1; % lower threshold for splitting (.1) - -% options for initializing spikes from data -ops.initialize = 'fromData'; %'fromData' or 'no' -ops.spkTh = -6; % spike threshold in standard deviations (4) -ops.loc_range = [3 1]; % ranges to detect peaks; plus/minus in time and channel ([3 1]) -ops.long_range = [30 6]; % ranges to detect isolated peaks ([30 6]) -ops.maskMaxChannels = 5; % how many channels to mask up/down ([5]) -ops.crit = .65; % upper criterion for discarding spike repeates (0.65) -ops.nFiltMax = 10000; % maximum "unique" spikes to consider (10000) - -% options for posthoc merges (under construction) -ops.fracse = 0.1; % binning step along discriminant axis for posthoc merges (in units of sd) -ops.epu = Inf; - -ops.ForceMaxRAMforDat = 20e9; % maximum RAM the algorithm will try to use; on Windows it will autodetect. - -% load predefined principal components (visualization only (Phy): used for features) -dd = load('PCspikes2.mat'); % you might want to recompute this from your own data -ops.wPCA = dd.Wi(:,1:7); % PCs - -%% Output list of default variables -%print out default arguments and values if no inputs are given -if nargin==0 - defaultArguments=fields(ops); - for i=1:numel(defaultArguments) - eval(['defaultArgumentValue=ops.' defaultArguments{i} ';']); - if numel(defaultArgumentValue)==1 - disp([defaultArguments{i} ' = ' num2str(defaultArgumentValue)]); - else - fprintf([defaultArguments{i} ' = ']); - disp(defaultArgumentValue); - end - end - return; -end - -%options depending on the input data object -binaryFileName='data4KiloSort.bin'; -channelMapFile='chanMap.mat'; - -ops.fbinary = fullfile(sortingDir, binaryFileName); % will be created for 'openEphys' -ops.fproc = fullfile(sortingDir, 'temp_wh.dat'); % residual from RAM of preprocessed data -ops.root = sortingDir; % 'openEphys' only: where raw files are -% define the channel map as a filename (string) or simply an array -ops.chanMap = fullfile(sortingDir, channelMapFile); % make this file using createChannelMapFile.m -% ops.chanMap = 1:ops.Nchan; % treated as linear probe if unavailable chanMap file -ops.Nfilt = round(nCh*ops.FiltersPerCh/32)*32; % number of clusters to use (2-4 times more than Nchan, should be a multiple of 32) - - -%% Overwrite with input values -for i=1:2:length(varargin) - eval(['ops.' varargin{i} '=' 'varargin{i+1};']) -end diff --git a/spikeSorting/makeConfigKiloSort2.m b/spikeSorting/makeConfigKiloSort2.m deleted file mode 100644 index b4326d2..0000000 --- a/spikeSorting/makeConfigKiloSort2.m +++ /dev/null @@ -1,134 +0,0 @@ -function ops=makeConfigKiloSort2(sortingDir,nCh,varargin) - -ops.datatype = 'bin'; % binary ('dat', 'bin') or 'openEphys' -ops.GPU = 1; % has to be 1, no CPU version yet, sorry -ops.parfor = 1; -ops.verbose = 1; -ops.showfigures = 1; - -ops.FiltersPerCh = 3; -ops.nNeighPC = 12; % visualization only (Phy): number of channnels to mask the PCs, leave empty to skip (12) -ops.nNeigh = 16; % visualization only (Phy): number of neighboring templates to retain projections of (16) - -ops.whitening = 'full'; % type of whitening (default 'full', for 'noSpikes' set options for spike detection below) -ops.spkTh = -4; % spike threshold in standard deviations (-6) -ops.reorder = 1; % whether to reorder batches for drift correction. -ops.nskip = 32; % how many batches to skip for determining spike PCs -ops.whiteningRange = 32; % number of channels to use for whitening each channel -ops.nSkipCov = 25; %not sure about this. % compute whitening matrix from every N-th batch (1) - -ops.fs = 20000; -% frequency for high pass filtering (150) -ops.fshigh = 200; -% minimum firing rate on a "good" channel (0 to skip) -ops.minfr_goodchannels = 0.1; -% threshold on projections (like in Kilosort1, can be different for last pass like [10 4]) -ops.Th = [6 12 12]; -% ops.Th = [12 6]; -% how important is the amplitude penalty (like in Kilosort1, 0 means not used, 10 is average, 50 is a lot) -ops.lam = [5 5 5]; - -ops.nannealpasses = 4; - -% splitting a cluster at the end requires at least this much isolation for each sub-cluster (max = 1) -ops.AUCsplit = 0.9; -% minimum spike rate (Hz), if a cluster falls below this for too long it gets removed -ops.minFR = 1/50; -% number of samples to average over (annealed from first to second value) -ops.momentum = [20 400]; - -ops.shuffle_clusters = 1; % allow merges and splits during optimization (1) -ops.mergeT = .1; % upper threshold for merging (.1) -ops.splitT = .1; - -% spatial constant in um for computing residual variance of spike -ops.sigmaMask = 30; -% threshold crossings for pre-clustering (in PCA projection space) -ops.ThPre = 8; -%% danger, changing these settings can lead to fatal errors -% options for determining PCs - -ops.criterionNoiseChannels = 0.2; % fraction of "noise" templates allowed to span all channel groups (see createChannelMapFile for more info). - -% other options for controlling the model and optimization -ops.Nrank = 3; % matrix rank of spike template model (3) -ops.nfullpasses = 6; % number of complete passes through data during optimization (6) -ops.maxFR = 20000; % maximum number of spikes to extract per batch (20000) -ops.fslow = 3000; % frequency for low pass filtering (optional) - -ops.Nfilt = 1024; %64; % max number of clusters -% ops.Nfilt = round(nCh*ops.FiltersPerCh/32)*32; -ops.nfilt_factor = 3; % max number of clusters per good channel (even temporary ones) -% ops.Nfilt = round(nCh*ops.FiltersPerCh/32)*32; % number of clusters to use (2-4 times more than Nchan, should be a multiple of 32) -ops.ntbuff = 64; % samples of symmetrical buffer for whitening and spike detection -ops.NT = 128*1024+ops.ntbuff; % must be multiple of 32 + ntbuff. This is the batch size (try decreasing if out of memory). - - -ops.scaleproc = 200; % int16 scaling of whitened data -ops.nPCs = 3; % how many PCs to project the spikes into -ops.useRAM = 0; % not yet available - -ops.initialize = 'fromData'; -ops.loc_range = [3 1]; % ranges to detect peaks; plus/minus in time and channel ([3 1]) -ops.long_range = [30 6]; % ranges to detect isolated peaks ([30 6]) -ops.maskMaxChannels = 5; % how many channels to mask up/down ([5]) -ops.crit = .65; % upper criterion for discarding spike repeates (0.65) -ops.nFiltMax = 10000; % maximum "unique" spikes to consider (10000) - -ops.fracse = 0.1; % binning step along discriminant axis for posthoc merges (in units of sd) -ops.epu = Inf; - -ops.ForceMaxRAMforDat = 20e9; % maximum RAM the algorithm will try to use; on Windows it will autodetect. -dd = load('PCspikes2.mat'); % you might want to recompute this from your own data -ops.wPCA = dd.Wi(:,1:7); % PCs - -ops.trange = [0 Inf]; -% ops.NchanTOT = 252; -ops.NchanTOT = nCh; -%% -if nargin~=0 - defaultArguments=fields(ops); - for i=1:numel(defaultArguments) - eval(['defaultArgumentValue=ops.' defaultArguments{i} ';']); -% if numel(defaultArgumentValue)==1 -% disp([defaultArguments{i} ' = ' num2str(defaultArgumentValue)]); -% else -% fprintf([defaultArguments{i} ' = ']); -% disp(defaultArgumentValue); -% end - end -% return; -end - -%options depending on the input data object -binaryFileName='data4KiloSort.bin'; -channelMapFile='chanMap.mat'; - -ops.fbinary = fullfile(sortingDir, binaryFileName); % will be created for 'openEphys' -ops.fproc = fullfile(sortingDir, 'temp_wh.dat'); % residual from RAM of preprocessed data -ops.root = sortingDir; % 'openEphys' only: where raw files are -% define the channel map as a filename (string) or simply an array -ops.chanMap = fullfile(sortingDir, channelMapFile); % make this file using createChannelMapFile.m -% ops.chanMap = 1:ops.Nchan; % treated as linear probe if unavailable chanMap file - -ops.nt0 = 25; -ops.fig = 0; -%% Overwrite with input values -for i=1:2:length(varargin) - eval(['ops.' varargin{i} '=' 'varargin{i+1};']) -end - -NSKToolBoxMainDir=fileparts(which('identifierOfMainDir4NSKToolBox')); -configText=fscanf(fopen([NSKToolBoxMainDir filesep 'PCspecificFiles' filesep 'kiloSortOpsPath.txt']),'%c'); -ops_temp = load(configText); -% ops_gui = ops_temp.saveDat.ops; -ops_gui = ops_temp.ops; -% ops_gui = rmfield(ops_gui, 'fbinary'); -ops_gui = rmfield(ops_gui,'fproc'); -ops_gui = rmfield(ops_gui,'saveDir'); -ops_gui = rmfield(ops_gui,'chanMap'); -ops_gui = rmfield(ops_gui,'fshigh'); -for fn = fieldnames(ops_gui)' - ops.(fn{1}) = ops_gui.(fn{1}); -end -end diff --git a/spikeSorting/meanShift/MSAMSClustering.m b/spikeSorting/meanShift/MSAMSClustering.m deleted file mode 100644 index 1aaade0..0000000 --- a/spikeSorting/meanShift/MSAMSClustering.m +++ /dev/null @@ -1,14 +0,0 @@ -function clusters=MSAMSClustering(in) -%clustering using automatic meanshift with chooseLandmarks to select the -%initial points -%synthax : clusters=MSAMSClustering(in) -%input : -% -in : matrix to clusterize -%output : -% - clusters containing index of data points. -[nfeature,nspike]=size(in); %clustering now -lminfo =choose_landmarks(in,round(nspike/10)+1,struct('frac_random',1,'center',1)); -landmarkClust = msams(in,lminfo); -landmarkClust = landmarkClust(lminfo.landmarkAssignment); -[clusters,n_per_group] = agglabel(landmarkClust); -end \ No newline at end of file diff --git a/spikeSorting/meanShift/agglabel.m b/spikeSorting/meanShift/agglabel.m deleted file mode 100644 index e83d7cb..0000000 --- a/spikeSorting/meanShift/agglabel.m +++ /dev/null @@ -1,58 +0,0 @@ -function [clabel,clabelsize] = agglabel(label,maxlabel) -% AGGLABEL: aggregate entries with the same label -% This is basically a substitute for looping over find(label == i) -% statements, which is an O(nlabels*N) operation. -% -% Syntax: -% clabel = agglabel(label) -% [clabel,nlabel] = agglabel(label) -% where -% label is a set of integer labels (must not be less than 1) -% and -% clabel is a cell array, where clabel{i} = find(label == i); -% nlabel is a vector containing the number of each label type. -% -% When the number of labels is large, this algorithm is rather more -% efficient than looping over find(label == i) statements. However, it -% doesn't get down to O(N logN) as would be possible with better control over -% memory management. -% -% Update: this now calls a MEX file, which does yield O(N logN). In fact, -% the performance is almost as good as a single call to find(label == i). -% However, it only works with labels of type double. - -% Copyright 2004 Timothy E. Holy - -%fprintf('Using the matlab version') - - if ~all(label >= 1) - warning('Some labels were less than 1 and will be discarded'); - end - [clabel,clabelsize] = agglabel_mex(label); - return - - - - - % Here's the old algorithm - llabel = length(label); - if (nargin < 2) - maxlabel = max(label); - end - if (maxlabel < 100) - for i = 1:maxlabel - clabel{i} = find(label == i); - end - else - m = sparse(1:llabel,label,ones(1,llabel),llabel,maxlabel); - % m = sparse(label,1:llabel,ones(1,llabel),maxlabel,length(label)); - for i = 1:maxlabel - clabel{i} = find(m(:,i))'; - % clabel{i} = find(m(i,:)); - end - end - if (nargout > 1) - for i = 1:length(clabel) - clabelsize(i) = length(clabel{i}); - end - end \ No newline at end of file diff --git a/spikeSorting/meanShift/agglabel_mex.cpp b/spikeSorting/meanShift/agglabel_mex.cpp deleted file mode 100644 index ca84588..0000000 --- a/spikeSorting/meanShift/agglabel_mex.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/*================================================================= - Aggregate entries with the same label - *=================================================================*/ - -#include "mex.h" -#include - -using namespace std; - - -//--------------------------------------------------------------------- - -void -mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]) -{ - long mrows,ncols,nelem,i,labelsize; - double *label,*labelend,*clabelsize; - int clabel; - vector > labeltable; // This is where the labels are stored - mxArray *tArray; - - // Check for proper number of input and output arguments - if (nrhs !=1) { - mexErrMsgTxt("One input argument required."); - } - if(nlhs != 2) - mexErrMsgTxt("Two output arguments required."); - - // input must be a real vector - if( !mxIsDouble(prhs[0]) ) mexErrMsgTxt("Input must be double."); - if( mxIsComplex(prhs[0]) ) mexErrMsgTxt("Input cannot be complex."); - mrows = mxGetM(prhs[0]); - ncols = mxGetN(prhs[0]); - //mexPrintf("mrows: %d, ncols: %d\n",mrows,ncols); - if (mrows > 1 && ncols > 1) mexErrMsgTxt("Input must be a vector."); - nelem = mrows*ncols; - label = mxGetPr(prhs[0]); - - // Now start aggregating. Don't separate this out to a work - // function, because it requires a lot of interaction with Matlab - // memory allocation to report the results back to Matlab. - // Using STL here, with growing containers, allows O(N logN) behavior - - for (i = 0; i < nelem; i++) { - clabel = int(label[i]); // current label - if (clabel > 0) { - // Do we have a new label we've never seen? - // Check first if we need to grow the labeltable - if (clabel > labeltable.capacity()) - labeltable.reserve(2*clabel); // So don't realloc often - if (clabel > labeltable.size()) - labeltable.resize(clabel); - - // Now add this index onto the end of the list - labeltable[clabel-1].push_back(double(i+1)); - } - } - //mexPrintf("Processed %d elements, with the largest label being %d\n",nelem,labeltable.size()); - - // Now convert results to MATLAB format - plhs[0] = mxCreateCellMatrix(1,labeltable.size()); // the label list - plhs[1] = mxCreateDoubleMatrix(1,labeltable.size(),mxREAL); // the lengths of lists - clabelsize = mxGetPr(plhs[1]); - for (i = 0; i < labeltable.size(); i++) { - labelsize = labeltable[i].size(); - // Store the length of each label list - clabelsize[i] = double(labelsize); - // Allocate a matlab vector for each label list - tArray = mxCreateDoubleMatrix(1,labelsize,mxREAL); - mxSetCell(plhs[0],i,tArray); - // Copy the values - copy(labeltable[i].begin(),labeltable[i].end(),mxGetPr(tArray)); - } -} diff --git a/spikeSorting/meanShift/agglabel_mex.mexa64 b/spikeSorting/meanShift/agglabel_mex.mexa64 deleted file mode 100644 index 4df5e44..0000000 Binary files a/spikeSorting/meanShift/agglabel_mex.mexa64 and /dev/null differ diff --git a/spikeSorting/meanShift/agglabel_mex.mexw64 b/spikeSorting/meanShift/agglabel_mex.mexw64 deleted file mode 100644 index e1ec635..0000000 Binary files a/spikeSorting/meanShift/agglabel_mex.mexw64 and /dev/null differ diff --git a/spikeSorting/meanShift/choose_landmarks.m b/spikeSorting/meanShift/choose_landmarks.m deleted file mode 100644 index 7dcb72e..0000000 --- a/spikeSorting/meanShift/choose_landmarks.m +++ /dev/null @@ -1,213 +0,0 @@ -function lminfo = choose_landmarks(x,k,options) -% choose_landmarks: split a group of points up into local regions -% Syntax: -% lminfo = choose_landmarks(x,k) -% lminfo = choose_landmarks(x,k,options) -% where -% x is a d-by-N matrix of data points, each column a separate data -% point in d dimensions; -% k is the number of landmarks desired; -% options is a structure with the following fields: -% frac_random (default 0): the fraction of landmarks chosen randomly -% from the data points. The remainder of landmarks will be chosen -% iteratively as the point farthest from the existing landmarks. -% A value of 0 will choose the first landmark randomly, and the rest -% according to distance. frac_random = 0 will tend to make landmark -% groupings of very similar physical size; frac_random = 1 will tend -% to make landmark groupings containing relatively similar #s of -% points. -% metric (default @sqrdist): a handle to a function that computes the -% distance between points. This function must be able to handle a -% matrix of data points for its first argument. 'sqrdist' is an -% example of such a function. -% seed_landmarks: if present, starts the process of landmark creation -% using the supplied landmarks, and then creates the rest as needed. -% center: if true, causes the landmarks to move inward from the "edge" -% of their assigned group towards the mean (it's like doing a single -% round of k-means). -% progress (default true): if true, will provide an update about -% progress every five seconds. -% and -% lminfo is an output structure with the following fields: -% landmarks: a d-by-k matrix, giving the positions of the landmarks; -% landmarkAssignment: a 1-by-N vector, landmarkAssignment(i) is the -% index of the landmark closest to the ith data point, x(:,i); -% landmarkList: a 1-by-k cell array, each element giving the indices of -% the points in x closest to this landmark; -% dist_to_closest_landmark: an N-by-1 vector, containing the distance -% to the closest landmark for each data point; -% radius_of_neighborhood: a k-by-1 vector, giving the distance to the -% farthest point assigned to each landmark; -% landmark_xIndex: a 1-by-k vector, giving the indices of the points in -% x used as landmarks (NaNs are used for seed_landmarks); -% metric: the function handle used to compute distances. -% -% See also: REINDEX_LANDMARKS. - -% Copyright 2006 by Timothy E. Holy - - if (nargin < 3) - options = struct; - end - if ~isfield(options,'metric') - options.metric = @sqrdist; - end - if ~isfield(options,'frac_random') - options.frac_random = 0; - end - if ~isfield(options,'center') - options.center = false; - end - if ~isfield(options,'progress') - options.progress = true; - end - - % See if we're using sqrdist (that will allow us to use mindist to save memory) - funcstr = func2str(options.metric); - if isequal(funcstr,'sqrdist') - using_sqrdist = true; - end - - [d,N] = size(x); - - if options.progress - first_update = true; - try - % Try to avoid resetting the timer if possible - tprev = toc; - catch - tic; - tprev = 0; - end - end - - if(k>=N) - lminfo.landmarks=x; - lminfo.landmarkAssignment=1:N; - lminfo.landmarkList=agglabel(1:N); - lminfo.dist_to_closest_landmark = zeros(1,N); - lminfo.radius_of_neighborhood = zeros(1,N); - lminfo.landmark_xIndex = 1:N; - lminfo.metric = options.metric; - return - end - - y = nan([d k],class(x)); - - if isfield(options,'seed_landmarks') - % Use the seed landmarks - n_start = min(k,size(options.seed_landmarks,2)); - y(:,1:n_start) = options.seed_landmarks(:,1:n_start); - xIndex(1:n_start) = nan; - else - % Start with random point(s) - n_start = 1; - if (n_start < 1) - n_start = 1; - end - if (n_start > k) - n_start = k; - end - if (n_start == 1) - xIndex = round(N*rand(1,1)+0.5); - xIndex=1; - else - xIndex = randperm(N); - end - xIndex = xIndex(1:n_start); - y(:,1:n_start) = x(:,xIndex); - end - % Calculate distances to "starter" landmarks - % Do this in a way that will work even if memory is tight - if using_sqrdist - if (options.progress && d*N*n_start > 1e7) - fprintf('Choosing %d landmarks: ',k); - first_update = false; - end - - [R2x,landmarkIndex] = mindist(x,y(:,1:n_start)); - else - try - cdist = options.metric(x,y(:,1:n_start)); - % For each data point, calculate the distance to the closest landmark (& - % keep track of which one it is) - [R2x,landmarkIndex] = min(cdist,[],2); - landmarkIndex = landmarkIndex'; - catch - % We go here if memory is insufficient for doing them all at once - R2x = zeros(1,N); - landmarkIndex = zeros(1,N); - for i = 1:N - cdist = options.metric(x(:,i),y(:,1:n_start)); - [R2x(i),landmarkIndex(i)] = min(cdist); - end - end - end - % In case the data set contains duplicated points, we need to make sure - % that every one of the starter landmarks has points assigned, and toss - % any that have no points - [xlabel,nlabel] = agglabel_mex(landmarkIndex); - keepFlag = (nlabel > 0); - xlabel = xlabel(keepFlag); - n_start = sum(keepFlag); - xIndex = xIndex(keepFlag); - y(:,1:n_start) = x(:,xIndex); - for i = 1:n_start - landmarkIndex(xlabel{i}) = i; - end - % Now choose the rest of the landmarks iteratively by finding the point - % that is most distance from the current landmarks - for yIndex = n_start+1:k - % Find the point farthest from the existing landmarks - [maxdist,maxIndex] = max(R2x); - xIndex(yIndex) = maxIndex; % this is the new landmark - % Compute the distance of each point to this new landmark - cdist = options.metric(x(:,maxIndex),x); - % Determine the set of points for which this landmark is the closest yet - is_closest = (cdist < R2x); - landmarkIndex(is_closest) = yIndex; - R2x(is_closest) = cdist(is_closest); - y(:,yIndex) = x(:,maxIndex); - if options.progress - if (toc - tprev > 5) - tprev = toc; - if first_update - fprintf('Choosing %d landmarks: ',k); - first_update = false; - end - fprintf('%d...',yIndex); - end - end - end - - if (options.progress && ~first_update) - fprintf('done\n'); - end - - [xlabel,nlabel] = agglabel(landmarkIndex); - if (options.center && using_sqrdist) - % Move each landmark to the center of the points that are currently - % assigned to it - for yIndex = 1:k - y(:,yIndex) = mean(x(:,xlabel{yIndex}),2); - end - [R2x,landmarkIndex] = mindist(x,y); - [xlabel,nlabel] = agglabel(landmarkIndex); - % Toss any that have no points assigned - keepflag = (nlabel > 0); - y = y(:,keepflag); - xlabel = xlabel(keepflag); - k = sum(keepflag); - end - %compute radii - for yIndex = 1:k - R2y(yIndex) = max(R2x(xlabel{yIndex})); - end - - lminfo.landmarks = y; - lminfo.landmarkAssignment = landmarkIndex; - lminfo.landmarkList = xlabel; - lminfo.dist_to_closest_landmark = sqrt(R2x); - lminfo.radius_of_neighborhood = sqrt(R2y(:)); - lminfo.landmark_xIndex = xIndex; - lminfo.metric = options.metric; diff --git a/spikeSorting/meanShift/findainb.m b/spikeSorting/meanShift/findainb.m deleted file mode 100644 index b447ea8..0000000 --- a/spikeSorting/meanShift/findainb.m +++ /dev/null @@ -1,49 +0,0 @@ -function indx = findainb(a,b) -% FINDAINB: find the index of elements of A in B -% -% indx = findainb(a,b) -% a,b may be vectors or cell arrays of strings -% On output, indx is such that a = b(indx). -% Limitation: if b has repeated elements, only the -% index of the first example is used. -% -% See also: INTERSECT, INDEXAINB. - -if iscell(b) && ~iscell(a) - a = {a}; -end -% Main challenge: handle repeated elements in a -[sab,index] = sort([a(:);b(:)]); -ia = find(index <= length(a)); -% ia contains the indices of the elements in sab that come from a -% Now compute the index of the next element in sab coming from b -% This step is potentially slow if a has a lot of repeated elements -ib = ia+1; -froma = find(index(ib) <= length(a)); -while ~isempty(froma) - ib(froma) = ib(froma)+1; - %froma = find(index(ib) <= length(a)); - froma = froma(find(index(ib(froma)) <= length(a))); -end -% Check that the values are equal -if ((~iscell(a) & any(sab(ia) ~= sab(ib))) | ... % This works for vectors - (iscell(a) & any(~strcmp(sab(ia),sab(ib))))) % This works for cell array of strings - error('Not all of a is in b'); -end -% Map indices back to original orderings -%isb = index(find(index > length(a))) - length(a); -isb = index(ib) - length(a); -[tmp,iai] = sort(index(ia)); -%indx = isb(iai); -indx = isb(iai); -indx = reshape(indx,size(a)); -return; - -% Old code: didn't handle repeated elements correctly, though -% it certainly is simpler! -[com,ia,ib] = intersect(a(:),b(:)); -if (length(com) < length(unique(a))) - error('Not all of a is in b'); -end -[tmp,iai] = sort(ia); % inverse permutation of a -indx = ib(iai); diff --git a/spikeSorting/meanShift/landmarked_neighbors.cpp b/spikeSorting/meanShift/landmarked_neighbors.cpp deleted file mode 100644 index 4b7e2dd..0000000 --- a/spikeSorting/meanShift/landmarked_neighbors.cpp +++ /dev/null @@ -1,201 +0,0 @@ -#include "landmarked_neighbors.h" -#include -#include - -template -Tdata sqrdist(const Tdata *start1,const Tdata *end1,const Tdata *start2) -{ - Tdata ret; - Tdata dx; - - ret = 0; - for (; start1 < end1; start1++,start2++) { - dx = *start1 - *start2; - ret += dx*dx; - } - return ret; -} - -template -void landmarked_neighbors::initialize(const Tdata *yi,const Tdata *xi,landmarkStruct &lminfoi) -{ - x = xi; - lminfo = lminfoi; - - //const Tdata *yEnd = y+lminfoi.d; - Tdata *lmData; - Tdata closestLandmarkR2,tmpR2; // variables for square-distance - Tdata tmpR; // variable for distance - int landmarkIndex; - int i; - - // Copy the "vantage point," to prevent bugs that arise from the - // user changing the value of y (this is practical because y is - // small; x and lminfo are large enough that we don't want to make a - // copy) - y.clear(); - y.insert(y.end(),yi,yi+lminfo.d); - - landmarks_sdi.clear(); - point_heap.clear(); - - // Step #1: determine the distance of each landmark from the current - // probe point. While doing this, keep track of the closest one, so - // we can return its index - closestLandmarkR2 = -1; - //mexPrintf("lminfo.landmarks[0] %g, n_landmarks %d, d %d\n",*(lminfo.landmarks),lminfo.n_landmarks,lminfo.d); - //mexPrintf("y %x, yEnd %x, diff %d\n",y,y.end(),y.end()-y); - - //mexPrintf("Landmark groups & R2s:\n"); - for (landmarkIndex = 0, lmData = lminfo.landmarks; landmarkIndex < lminfo.n_landmarks; landmarkIndex++, lmData+=lminfo.d) { - tmpR2 = sqrdist(&(*y.begin()),&(*y.end()),lmData); - //mexPrintf("%d %g\n",landmarkIndex,tmpR2); - landmarks_sdi.push_back(SqrdistIndex(tmpR2,landmarkIndex)); - if (closestLandmarkR2 < 0 || tmpR2 < closestLandmarkR2) { - closestLandmarkR2 = tmpR2; - closestLandmarkIndex = landmarkIndex; - } - } - - if (use_landmarks) { - // Step #2: For each landmark group, determine (using the triangle - // inequality) the lower bound on distance between points in the - // grouping and the probe point. This is the distance we'll store - // and sort by. - for (landmarkIndex = 0; landmarkIndex < lminfo.n_landmarks; landmarkIndex++) { - tmpR = lminfo.landmarkR[landmarkIndex]; // the radius of the group - if (landmarks_sdi[landmarkIndex].R2 < tmpR*tmpR) { - // The current probe point could be inside this landmark - // group, so the lower bound on distance is 0 - landmarks_sdi[landmarkIndex].R2 = 0; - } else { - // The landmark group is farther away, use the triangle - // inequality to determine the lower bound on the (square) - // distance - tmpR = sqrt(landmarks_sdi[landmarkIndex].R2) - tmpR; - landmarks_sdi[landmarkIndex].R2 = tmpR*tmpR; - } - } - - // Step #3: Sort groups by this lower-bound distance (in - // increasing order). - //mexPrintf("Unsorted landmark order:\n"); - //for (landmarkIndex = 0; landmarkIndex < lminfo.n_landmarks; landmarkIndex++) - // mexPrintf("%d (%g) ",landmarks_sdi[landmarkIndex].index,landmarks_sdi[landmarkIndex].R2); - //mexPrintf("\n"); - std::sort(landmarks_sdi.begin(),landmarks_sdi.end()); - //mexPrintf("Sorted landmark order:\n"); - //for (landmarkIndex = 0; landmarkIndex < lminfo.n_landmarks; landmarkIndex++) - // mexPrintf("%d (%g) ",landmarks_sdi[landmarkIndex].index,landmarks_sdi[landmarkIndex].R2); - //mexPrintf("\n"); - - // Step #4: Clear the heap and initialize the progress variables - point_heap.clear(); - point_heap_end = point_heap.begin(); - lmIterator = landmarks_sdi.begin(); - currentR2 = lmIterator->R2; - - // Step #5: Get the point_heap set up for the first requests - advance_heap(); - } - - - else { - // We're not going to be using the landmarks to triage the data - // points. So instead, compute the distance to each data point and - // then sort. - const Tdata *dataEnd = x + lminfo.d * N; - const Tdata *y_begin = &(*y.begin()); - const Tdata *y_end = &(*y.end()); - const Tdata *dataIterator; - int dataIndex; - for (dataIndex = 0, dataIterator = x; dataIterator < dataEnd; dataIterator += lminfo.d, dataIndex++) { - tmpR2 = sqrdist(y_begin,y_end,dataIterator); - point_heap.push_back(SqrdistIndex(tmpR2,dataIndex)); - } - - std::sort(point_heap.begin(),point_heap.end()); - - cur_position = point_heap.begin(); - } -} - -template -void landmarked_neighbors::advance_heap() -{ - int thisGroup,pointIndex,thisPointIndex; - const Tdata *thisPoint; - Tdata tmpR2; - - if (!use_landmarks) { - return; - } - - // Add points to heap (if necessary). Here's the scheme & - // considerations: - // (1) add all groups that have a lower-bound distance - // within the currentR2 - // (2) if the closest point yet has a square distance larger than - // currentR2, it might not be the closest point: there might be - // another landmark group containing a closer point. So we increase - // currentR2 and add all the groups up to that distance. - // - // This leads to a double-while construction. We could do it with a - // single-while, but it could result in unnecessary points being - // added to the heap, if a later group already scheduled for - // addition has the closest point. - //mexPrintf("1: currentR2 %g, lmIterator->R2 %g\n",currentR2,lmIterator->R2); - while (lmIterator < landmarks_sdi.end() && lmIterator->R2 <= currentR2) { - //mexPrintf("2: currentR2 %g, lmIterator->R2 %g\n",currentR2,lmIterator->R2); - while (lmIterator < landmarks_sdi.end() && lmIterator->R2 <= currentR2) { - // Add all the points in the current group - thisGroup = lmIterator->index; - //mexPrintf("Adding group %d\n",thisGroup); - for (pointIndex = 0; pointIndex < lminfo.n_landmarkList[thisGroup]; pointIndex++) { - thisPointIndex = (int) lminfo.landmarkList[thisGroup][pointIndex] - lminfo.index_offset; - thisPoint = x + lminfo.d*thisPointIndex; - tmpR2 = sqrdist(&(*y.begin()),&(*y.end()),thisPoint); - *point_heap_end = SqrdistIndex(tmpR2,thisPointIndex); - // make it so the top of the heap is the closest point - push_heap(point_heap.begin(),++point_heap_end,is_farther()); - } - //mexPrintf("Heap status:\n"); - //typename vector< SqrdistIndex >::iterator phI; - //for (phI = point_heap.begin(); phI < point_heap_end; phI++) - // mexPrintf("x%d (%g) ",phI->index,phI->R2); - //mexPrintf("\n"); - lmIterator++; - } // end of inside while loop - // We want to make sure we keep including groups until we get some - // points on the heap that are closer than any points not on the - // heap. The way to do that is to adjust currentR2 to reflect the - // distance to the closest point. - if (!is_empty()) - currentR2 = point_heap.begin()->R2; - else if (lmIterator < landmarks_sdi.end()) { - // If the heap is still empty, but we haven't exhausted all - // landmarks, then we must have had only empty landmark - // groups. In that case, increment to the next landmarkR2. - currentR2 = lmIterator->R2; - } - } -} - -template -void landmarked_neighbors::next_point() -{ - if (!use_landmarks) { - cur_position++; - return; - } - - pop_heap(point_heap.begin(),point_heap_end,is_farther()); - point_heap_end--; - - if (!is_empty()) - currentR2 = point_heap.begin()->R2; - else if (lmIterator < landmarks_sdi.end()) - currentR2 = lmIterator->R2; - advance_heap(); -} - diff --git a/spikeSorting/meanShift/landmarked_neighbors.h b/spikeSorting/meanShift/landmarked_neighbors.h deleted file mode 100644 index 1d42a88..0000000 --- a/spikeSorting/meanShift/landmarked_neighbors.h +++ /dev/null @@ -1,111 +0,0 @@ -#include -#include - -using namespace std; - -// A structure to hold landmarks. This is implemented in terms of basic -// pointers so that it's easy to bind to Matlab or other sources -template -struct landmarkStruct { - int n_landmarks; - int d; // The dimensionality - Tdata *landmarks; // landmark positions (by-by-n_landmarks) - Tint **landmarkList; // List of points associated with each landmark - int *n_landmarkList; // Number of points associated with each landmark - double *landmarkR; // Radius of each landmark group around the landmark - int index_offset; // (For Matlab this should be 1 because it's unit-offset) - - landmarkStruct() { - n_landmarks = 0; - d = 0; - landmarks = NULL; - landmarkR = NULL; - landmarkList = NULL; - n_landmarkList = NULL; - index_offset = 0; - } -}; - - - -// Class for holding a square-distance and a corresponding index; this -// will be heavily used in heapsort routines -template -struct SqrdistIndex { - T R2; // distance^2 - int index; - - SqrdistIndex() {;} - SqrdistIndex(T r2,int i) {R2 = r2; index = i;} - bool operator<(const SqrdistIndex &sdi) const {return (R2 < sdi.R2);} - bool operator>(const SqrdistIndex &sdi) const {return (R2 > sdi.R2);} -}; - -template -struct is_farther : public binary_function,SqrdistIndex,bool> { - bool operator()(SqrdistIndex &sdi1,SqrdistIndex &sdi2) { return sdi1.R2 > sdi2.R2;} -}; - - -// Class for returning neighbors, in order of distance. If -// use_landmarks is true, it makes use of landmarked groups of points, -// so that one doesn't have to examine each point. -const bool use_landmarks = 1; // use a const so checks are optimized away -template -class landmarked_neighbors { - private: - vector< SqrdistIndex > landmarks_sdi; - typename vector< SqrdistIndex >::iterator lmIterator; - int closestLandmarkIndex; - vector< SqrdistIndex > point_heap; - typename vector< SqrdistIndex >::iterator point_heap_end; - Tdata currentR2; // the radius-squared up to which we're delivering points - - vector y; - const Tdata *x; - landmarkStruct lminfo; - int N; - - void advance_heap(); - - // These are variables that are used when we turn off the triaging - // by landmark, which we only want to do when we want to find out - // how much time that's saving us. - typename vector< SqrdistIndex >:: iterator cur_position; - - public: - landmarked_neighbors() {;} - - // "allocate" has to be called explicitly, before anything else is done - void allocate(int n_landmarks,int n_points) { - landmarks_sdi.reserve(n_landmarks); - point_heap.reserve(n_points); - N = n_points; - } - // "initialize" sets up the data structure that allows one to ask - // for information about points and landmarks - void initialize(const Tdata *yi,const Tdata *xi,landmarkStruct &lminfoi); - - // Information about landmarks - int closest_landmark() {return closestLandmarkIndex;} - - // - // Information about points - // - // Get the current point: - SqrdistIndex* current_point() { - if (use_landmarks) - return &point_heap[0]; - else - return &cur_position[0]; - } - // Discard the current point and advance to the next-closest: - void next_point(); - // Test to see if we've exhausted all the points: - bool is_empty() { - if (use_landmarks) - return point_heap_end == point_heap.begin(); - else - return cur_position == point_heap.end(); - } -}; diff --git a/spikeSorting/meanShift/leapfrog.m b/spikeSorting/meanShift/leapfrog.m deleted file mode 100644 index 7018427..0000000 --- a/spikeSorting/meanShift/leapfrog.m +++ /dev/null @@ -1,100 +0,0 @@ -function [map,leapfrog_info] = leapfrog(map,n) -% LEAPFROG: rapid convergence for mean shift algorithms by graph iteration -% Syntax: -% mapout = leapfrog(mapin) -% where map defines a directed graph, i->map(i). -% mapin is the input map; -% mapout is the output map, where each point maps to its "final" -% location. -% The notion of a "final" location can run into trouble when the input -% graph contains cycles. In that case, cycles need to be broken, so that -% all connected points map to the same location. The syntax -% -% mapout = leapfrog(mapin,priority) -% -% with the optional input "priority", a vector with one entry per map -% point, allows one to control how cycles are broken: points with the -% highest priority will win. In cases of a tie, the point with the -% smallest index wins. The default priority is 1 for all points. -% -% -% [map,leapfrog_info] = leapfrog(mapin,...) -% -% allows you to obtain some information about the performance of leapfrog. -% -% See also: MSAMS, MEANSHIFT. - -% Copyright 2006 by Timothy E. Holy - - if (nargin < 2) - % n can be used so that consolidation occurs at the peak. But if it's - % not available, set a default so that it will simply go to the - % lowest index. - n = ones(1,length(map)); - end - if (nargout > 1) - leapfrog_info = struct('n_leapfrog_steps',0,'n_repair_steps',0); - end - - % Every landmark "maps" to some landmark, either itself (usually - % rare) or to another landmark. - % We can accelerate convergence by iterating this map, so that points - % leapfrog uphill. - map0 = map; - umap = unique(map); - umapOld = []; - while ~isequal(umapOld,umap) - umapOld = umap; - map = map(map); - umap = unique(map); - if (nargout > 1) - leapfrog_info.n_leapfrog_steps = leapfrog_info.n_leapfrog_steps+1; - end - end - % The leapfrogging process can cut off some points: consider a map of - % only three points, where the mapping is - % 2 3 2 - % i.e., 1->2, 2->3, 3->2. Note there is a cycle. If we iterate this map - % we get - % 3 2 3 - % which is stable under further iterations with itself. However, it looks - % like there are two "clusters," [1 3] and [2]. But in fact they were all - % connected originally. Consolidate these splits due to cycles by - % checking the original map again, and moving each point to our best - % guess for the most uphill point of two possible mappings. (We could - % just choose, say, the lower index of two possible mappings, but in fact - % the map is interesting in its own right, and we might as well try to - % preserve as much of its character as possible.) - % This usually converges very quickly, although there may not be - % guarantees that it will do so. This could be replaced by a 'real' - % (well-optimized) graph theory approach, computing the reduced graph of - % vertices and then calculating the number of components by standard - % algorithms. But this converges so fast, by comparison with the other - % steps, that it seems that a low-tech approach is fine. - is_changed = true; - iter = 0; - maxiter = length(umap); - while (any(is_changed) && iter < maxiter) - map_compare = [map; map(map0)]; - is_changed = (map_compare(1,:) ~= map_compare(2,:)); - map_compare = map_compare(:,is_changed); - n1 = n(map_compare(1,:)); % estimate max density from landmark that ... - n2 = n(map_compare(2,:)); % ... averages over the most data points - [tmp,index_max] = max([n1; n2]); - is_tie = (n1 == n2); - if any(is_tie) - % Ties can result it an infinte loop. Break them by choosing the one - % with the lower index - [tmp,index_max(is_tie)] = min(map_compare(:,is_tie)); - end - map_uphill_index = sub2ind([2 length(n1)],index_max,1:length(n1)); - map(is_changed) = map_compare(map_uphill_index); - iter = iter+1; - end - if (iter > maxiter) - error('Map repair failed to be fast') - end - if (nargout > 1) - leapfrog_info.n_repair_steps = iter; - end - \ No newline at end of file diff --git a/spikeSorting/meanShift/mindist.cpp b/spikeSorting/meanShift/mindist.cpp deleted file mode 100644 index ea14b97..0000000 --- a/spikeSorting/meanShift/mindist.cpp +++ /dev/null @@ -1,202 +0,0 @@ -#include "mex.h" -//#include // for # of CPUs -#include -template -int mindist_thread_launcher(const Tdata *x,const Tdata *y,int N,int d,int q,double *md,double *ident,int n_threads); - -template -void mindist_generic(const Tdata *x,const Tdata *y,int N,int d,int q,double *md,double *ident); - -/* - * This is the Matlab wrapper - */ - -void mexFunction( - int nlhs, mxArray *plhs[], - int nrhs, const mxArray *prhs[]) -{ - const double *x, *y; - double *md, *ident; - int N,d,q; - const mxArray *curarg; - int ncpus,nthreads,ret; - - if (nrhs < 2) - mexErrMsgTxt("mindist: requires two inputs"); - - // Parse the inputs - curarg = prhs[0]; - if (!mxIsNumeric(curarg) || mxIsComplex(curarg)) - mexErrMsgTxt("mindist: x must be a real matrix"); - x = mxGetPr(curarg); - d = mxGetM(curarg); - N = mxGetN(curarg); - - curarg = prhs[1]; - if (!mxIsNumeric(curarg) || mxIsComplex(curarg)) - mexErrMsgTxt("mindist: y must be a real matrix"); - y = mxGetPr(curarg); - if (d != mxGetM(curarg)) - mexErrMsgTxt("mindist: the dimensionality of x and y disagree"); - q = mxGetN(curarg); - - //mexPrintf("d %d, N %d, q %d, nlhs %d, nrhs %d\n",d,N,q,nlhs,nrhs); - - // Set up the outputs - plhs[0] = mxCreateDoubleMatrix(1,N,mxREAL); - md = mxGetPr(plhs[0]); - ident = NULL; - if (nlhs > 1) { - plhs[1] = mxCreateDoubleMatrix(1,N,mxREAL); - ident = mxGetPr(plhs[1]); - } - - ncpus =1;// sysconf(_SC_NPROCESSORS_ONLN); - /* - if (ncpus > 4) - ncpus = 4; // performance is not very linear, so don't go crazy - */ - nthreads = (int) ((double(d)*double(q)*double(N))/100000); - if (nthreads > ncpus) - nthreads = ncpus; - if (nthreads > N) - nthreads = N; // since we thread on N, no point if N == 1 - if (nthreads < 1) - nthreads = 1; - //mexPrintf("nthreads = %d (ncpus = %d)\n",nthreads,ncpus); - - // Do the actual work - if (mxIsDouble(prhs[0]) && mxIsDouble(prhs[1])) { - //ret = mindist_thread_launcher(x,y,N,d,q,md,ident,nthreads); - mindist_generic(x,y,N,d,q,md,ident); - } - else if (mxIsSingle(prhs[0]) && mxIsSingle(prhs[1])) - mindist_generic((float *)x,(float *)y,N,d,q,md,ident); - else - mexErrMsgTxt("mindist: x and y must both be either single or double"); - - if (ret == 0) - mexErrMsgTxt("mindist: error launching threads"); - - return; -} - - -/* - * Given x and y, compute the distance (md) between x and its closest - * point in y, and the index (ident) of that closest point. x is - * d-by-N, y is d-by-q, and both are organized by column in memory. - */ -template -void mindist_generic(const Tdata *x,const Tdata *y,int N,int d,int q,double *md,double *ident) -{ - double distsq,mdtemp,dtemp; - Tdata sqrtmp; - const Tdata *yp; - int i,j,k,identtemp; - - for (i = 0; i < N; i++) { // Loop over the points of x - mdtemp = DBL_MAX; - identtemp = -1; - yp = y; // We're using pointer arithmetic to - // avoid a multiplication - for (j = 0; j < q; j++) { // Loop over the points of y - dtemp = 0; - for (k = 0; k < d; k++,yp++) { // Loop over coordinates - sqrtmp = x[k]-*yp; - dtemp += sqrtmp*sqrtmp; - } - if (dtemp < mdtemp) { // Keep track of closest-yet - mdtemp = dtemp; - identtemp = j+1; // j+1 because Matlab is unit-offset - } - } - md[i] = mdtemp; - if (ident != NULL) - ident[i] = (double) identtemp; // Because Matlab uses doubles... - x += d; // Go on to the next point of x - } - return; -} - -// A structure for passing data to pthreads -template -struct thread_data_type { - const Tdata *x; - const Tdata *y; - int d; - int N; - int q; - double *md; - double *ident; -}; - -// A wrapper for multithreading -template -void *mindist_thread(void *p) -{ - thread_data_type *td; - - td = (thread_data_type*) p; - mindist_generic(td->x,td->y,td->N,td->d,td->q,td->md,td->ident); -} - -// The launcher for multithreading -template -int mindist_thread_launcher(const Tdata *x,const Tdata *y,int N,int d,int q,double *md,double *ident,int n_threads) -{ - int i,j; - int *splits,extras,n_pts_per_thread; - thread_data_type *td; - pthread_t *thread; - - if (n_threads == 1) { - mindist_generic(x,y,N,d,q,md,ident); - return 1; - } - - // Decide how the data will be split among threads - n_pts_per_thread = N/n_threads; - extras = N - n_threads*n_pts_per_thread; - splits = new int[n_threads+1]; - splits[0] = 0; - for (i = 0; i < n_threads; i++) - splits[i+1] = splits[i] + n_pts_per_thread + (extras-- > 0); - - // Pack arguments into thread data type, splitting out the various - // points in x to be handled by different CPUs. - td = new thread_data_type[n_threads]; - for (i = 0; i < n_threads; i++) { - td[i].x = x + d*splits[i]; - td[i].y = y; - td[i].N = splits[i+1]-splits[i]; - td[i].d = d; - td[i].q = q; - td[i].md = md+splits[i]; - if (ident != NULL) - td[i].ident = ident+splits[i]; - else - td[i].ident = NULL; - } - - delete[] splits; - - // Launch threads - thread = new pthread_t[n_threads]; - for (i = 0; i < n_threads && td[i].q > 0; i++) - if (pthread_create(thread+i,NULL,mindist_thread,(void*) (td+i)) != 0) - return 0; // error creating thread - - // Wait for threads to return - // Only do this for the ones that got launched; i should be - // initialized to the first thread that _didn't_ run (or to - // n_threads, if q > n_threads) - for (i--; i >= 0; i--) - pthread_join(thread[i],NULL); - - delete[] thread; - delete[] td; - - return 1; // success! -} - diff --git a/spikeSorting/meanShift/mindist.mexa64 b/spikeSorting/meanShift/mindist.mexa64 deleted file mode 100644 index e074537..0000000 Binary files a/spikeSorting/meanShift/mindist.mexa64 and /dev/null differ diff --git a/spikeSorting/meanShift/mindist.mexw64 b/spikeSorting/meanShift/mindist.mexw64 deleted file mode 100644 index 69d5031..0000000 Binary files a/spikeSorting/meanShift/mindist.mexw64 and /dev/null differ diff --git a/spikeSorting/meanShift/msams.m b/spikeSorting/meanShift/msams.m deleted file mode 100644 index 3f6683f..0000000 --- a/spikeSorting/meanShift/msams.m +++ /dev/null @@ -1,222 +0,0 @@ -function [clust,clustinfo] = msams(varargin) -%NOTE OLIVIER: x has been replaced by varargin{1} everywhere to spare some -%memory. - -% MSAMS: clustering by Minimally-Significant Adaptive Mean Shift -% -% MSAMS is a variant of a mean shift clustering algorithm that adaptively -% chooses the size of the region to average over. It also has a number of -% implementation details that make it quite efficient. -% -% Syntax: -% -% clust = msams(x) -% -% Here x is a d-by-N matrix of data points, where each column of x is one -% point in d dimensions (N points total). On output, clust will be a -% 1-by-N vector giving the cluster # assigned to each point. -% -% clust = msams(x,lminfo) -% -% Perform MSAMS using landmark-based optimizations. lminfo is a structure -% of the type returned by CHOOSE_LANDMARKS. As a rough guideline, you might -% want to choose the # of landmarks as sqrt(N). This syntax allows MSAMS to run -% somewhat faster, because only the landmark points are used; however, the -% cost is somewhat lower "resolution" on your clustering. In this case, -% clust is assigned for the landmark points; you can obtain assignments for -% all the points in x from clust(lminfo.landmarkAssignment). -% -% clust = msams(x,y) -% -% An alternative syntax in which clustering is performed for "probe points" -% y, moving on a fixed background of "data points" x. This is useful in -% cases where you don't want to use landmark points as probe points. -% -% [clust,clustinfo] = msams(...) -% -% This provides extra diagnostic information in the structure clustinfo. -% The precise form of this structure depends on the version of the -% algorithm being run (MEX or non-MEX). The most detailed description can -% be found in the help for MSAMS_CONVERGE_MEX. -% -% clust = msams(...,options) -% -% This syntax allows you to control the algorithm with some options. See -% MSAMS_CONVERGE_MEX for the details in the "fast" case (when you -% supply lminfo), see MSAMS_CONVERGE and MSAMS_STEP1 for other cases. The -% field "compute_lminfo_if_missing" (default true) allows you to control -% whether the lminfo is calculated for calls like msams(x,y). -% -% See also: MSAMS_CONVERGE_MEX, CHOOSE_LANDMARKS, MSAMS_RESAMPLE, MSAMS_CONVERGE, MSAMS_STEP1, VMAMS_STEP1. - -% Copyright 2006-2008 by Timothy E. Holy - - -if (length(varargin) < 1) - error('Must supply at least one input argument'); -end -% x = varargin{1}; -N = size(varargin{1},2); -have_lminfo = true; -probePointsAreDataPoints = false; -options = struct; -if (length(varargin) == 1) - probePointsAreDataPoints = true; - lminfo = choose_landmarks(varargin{1},ceil(sqrt(N))); -else - if isnumeric(varargin{2}) - y = varargin{2}; - have_lminfo = false; - if (length(varargin) > 2) - options = varargin{3}; - end - elseif isstruct(varargin{2}) - % is this a landmark structure or an options structure? - if isfield(varargin{2},'landmarks') - lminfo = varargin{2}; - if (length(varargin) > 2) - options = varargin{3}; - end - else - lminfo = choose_landmarks(varargin{1},N); - options = varargin{2}; - end - else - error('Input argument #2 not recognized'); - end -end - -if ~isfield(options,'leapfrog') - options.leapfrog = true; -end -if ~isfield(options,'consolidate') - options.consolidate = true; % change this to true once debugged -end -if ~isfield(options,'use_mex') - options.use_mex = (exist('msams_converge_mex','file') == 3); -end -if ~isfield(options,'compute_lminfo_if_missing') - options.compute_lminfo_if_missing = true; -end - -if have_lminfo - if probePointsAreDataPoints - y = varargin{1}; - else - y = lminfo.landmarks; - end -elseif options.compute_lminfo_if_missing - lminfo = choose_landmarks(varargin{1},size(y,2),struct('seed_landmarks',y)); - have_lminfo = true; -end - -% -% Do the MSAMS steps -% - - -if options.use_mex && have_lminfo - if probePointsAreDataPoints - clustinfo = msams_converge_mex(varargin{1},lminfo,[],options); - else - time_passing = now; - clustinfo = msams_converge_mex(varargin{1},lminfo,y,options); - end - yf = clustinfo.yf; - map = clustinfo.closestLandmark; - n = clustinfo.n; -else - [yf,map,n,clustinfo] = msams_converge(varargin{1},y,options); - clustinfo.yf = yf; -end -clustinfo.y0 = y; -clustinfo.map0 = map; -clustinfo.n = n; -% Wait to set variable_metric here so that msams_converge can handle -% defaults correctly -options.variable_metric = isfield(clustinfo,'scale'); - -% -% Aggregate points -% -if options.leapfrog - % Do leapfrog convergence - time_passing = now; - - map = leapfrog(map,n); - %fprintf('Done in %.3f s\n',24*3600*(now-time_passing)); -else - % We have to aggregate the points some other way - error('Aggregation by means other than leapfrog not yet implemented'); -end -clustinfo.map1 = map; - -% -% Now each cluster is defined by landmarks that map to themselves; these -% should correspond in some sense to the peaks (or at least flattest -% regions) of density. We need to check these to make sure they're not -% just some "local cycle" by testing to see whether a plurality of the -% points within the local neighborhood are a member of this cluster. -% Essentially, each point identified as belonging to the local -% neighborhood of a self-mapping landmark will "vote" for the assignment -% of the cluster overall. -% -time_passing = now; - -if (options.consolidate && have_lminfo) - mapOld = []; - clustinfo.n_consolidated = 0; - % For all that start out mapping to self, determine the list of - % neighbors. We only need to do this once. - maps_to_self0 = find(map == 1:length(map)); - maps_to_self = maps_to_self0; - neighbor_list = cell(1,length(maps_to_self)); - for clusterIndex = 1:length(maps_to_self) - tLandmark = maps_to_self(clusterIndex); - sd = sqrdist(varargin{1},yf(:,tLandmark)); - [sd,neighbor_list_tmp] = sort(sd); - neighbor_list{clusterIndex} = neighbor_list_tmp(1:n(tLandmark)); - end - while ~isequal(mapOld,map) - mapOld = map; - n_maps_to_self = length(maps_to_self); - votes = zeros(n_maps_to_self,n_maps_to_self); - index0 = findainb(maps_to_self,maps_to_self0); - for clusterIndex = 1:length(maps_to_self) - % Recreate the local set of points, as the list "indexContrib" - % We have to recalculate this (rather than saving it from before), - % because cycling might mean that the last iteration was not the - % one kept, and it's too memory intensive to store the full list on - % each iteration. - tLandmark = maps_to_self(clusterIndex); - indexContrib = neighbor_list{index0(clusterIndex)}; - % Of the points in the neighborhood, what is their cluster - % assignment? - if probePointsAreDataPoints - nbrmap = map(indexContrib); - else - nbrmap = map(lminfo.landmarkAssignment(indexContrib)); - end - % Calculate the number of points assigned to each cluster within the - % local neighborhood---this tallies the "votes" - [unbrmap,tmp,relabelled_nbrmap] = unique(nbrmap); - [tmp,votes_tmp] = agglabel(relabelled_nbrmap); - votes(clusterIndex,findainb(unbrmap,maps_to_self)) = votes_tmp; - end - % Re-assign each self-mapping landmark to the one that receives the - % most "votes" in its local neighborhood (note we do this only after - % all votes have been tallied for all "candidates," so that there can't - % be any order effects. Not that those seem likely...) - [max_votes,maxIndex] = max(votes,[],2); - map(maps_to_self) = maps_to_self(maxIndex); - clustinfo.n_consolidated = clustinfo.n_consolidated + sum(maxIndex' ~= 1:n_maps_to_self); - % Iterate map to get final assignments - map = leapfrog(map); - maps_to_self = find(map == 1:length(map)); - end -end - -clustinfo.map = map; -% Re-label the clusters 1,2,3,... -[umap,tmp,clust] = unique(map); -%fprintf('Done in %.3f s\n',24*3600*(now-time_passing)); diff --git a/spikeSorting/meanShift/msams_converge_core.cpp b/spikeSorting/meanShift/msams_converge_core.cpp deleted file mode 100644 index 744ecd1..0000000 --- a/spikeSorting/meanShift/msams_converge_core.cpp +++ /dev/null @@ -1,325 +0,0 @@ -#include "landmarked_neighbors.cpp" -#include "msams_converge_core.h" -//#include -#include -#include - -// Copyright 2006-2008 by Timothy E. Holy - -// This is the function that is called by pthread -// It just casts the void* to an appropriate pointer type -template -void *msams_core_thread(void *p) -{ - msams_core_work((thread_data_type*) p); -} - -// This does housekeeping and launches the threads. Question: what if -// user wants to start from y that are not on the landmarks? May need -// some new fields in the option structure, or change the decision re -// lmIndex. -template -int msams_core(const Tdata *x,int d,int N,landmarkStruct &lminfo,int q,outputStruct &out,const optionStruct &ops) -{ - //Tdata *ytmp; - int i,j,thisIndex; - thread_data_type td; - - // Pack arguments into thread data type - td.x = x; - td.d = d; - td.N = N; - td.lminfo = &lminfo; - td.q = q; - td.out = &out; - td.ops = &ops; - - // Launch threads - if (q == 1 || ops.n_threads == 1) { - // single thread - td.probePtIndex_start = 0; - td.probePtIndex_end = q; - msams_core_work(&td); - } - return 1; // success -} - -// This does the real work -template -void msams_core_work(thread_data_type *td) -{ - int probeIndex,d,n_landmarks,i,iter; - int closestIndex,closestIndexOld; - Tdata *thisY, *thisYend; - bool isdone,iscycling; - Tdata *ytraj, *ytrajtmp, *R2traj; - Tint *ntraj; - bool traj_is_tmp; - int n; - Tdata R2; - - Tdata tol = td->ops->convergence_thresh; - - - /* - // Thread debugging - for (i = td->probePtIndex_start; i < td->probePtIndex_end; i++) - td->out->closestLandmark[i] = (Tint) pthread_self(); - */ - - // Unpack commonly-used information from the structure created to - // support multithreading - d = td->d; - n_landmarks = td->lminfo->n_landmarks; - - // Allocate temporary storage - vector x_cum(d); - vector deltax_cum(d); - vector x_backtrack(d); - vector sumsq_cum(d); - landmarked_neighbors lm_nbrs; - lm_nbrs.allocate(n_landmarks,td->N); - - - if (td->out->ytraj == NULL) { - ytraj = new Tdata[d*(td->ops->max_iter+1)]; - ntraj = new Tint[td->ops->max_iter]; - traj_is_tmp = true; - } else { - ytraj = td->out->ytraj; - ntraj = td->out->ntraj; - traj_is_tmp = false; - } - R2traj = new Tdata[td->ops->max_iter]; - - - - // Loop over the probe points assigned to this particular thread - for (probeIndex = td->probePtIndex_start; probeIndex < td->probePtIndex_end; probeIndex++) { - isdone = false; - iscycling = false; - thisY = td->out->y + d*probeIndex; // the current probe point - thisYend = thisY+d; - // Put the starting location on the trajectory history - ytrajtmp = ytraj; - for (i = 0; i < d; i++) - ytrajtmp[i] = thisY[i]; - // We'll abort when the closest landmark (or data point, when - // applicable) changes, so keep track of it. - closestIndexOld = -1; - iter = 0; - while (!isdone) { - // Do all the preparation to find neighbors efficiently - lm_nbrs.initialize(thisY,td->x,*(td->lminfo)); - // Test for convergence - if (!td->ops->probePointsAreDataPoints) - // Find the closest landmark - closestIndex = lm_nbrs.closest_landmark(); - else - // Find the closest data point - closestIndex = lm_nbrs.current_point()->index; - // See whether the closest landmark/point changed - if (td->ops->leapfrog && closestIndexOld != closestIndex && closestIndexOld >= 0) - break; // quit on this probe point, we've reached a stopping criterion - closestIndexOld = closestIndex; - - expand_neighborhood_msams(td->x,td->d,thisY,lm_nbrs,td->ops,x_cum,deltax_cum,sumsq_cum,x_backtrack,n,R2,td->lminfo->index_offset,(Tint *) NULL); - - // The MSAMS criterion has been met, in one form or another - if (lm_nbrs.is_empty()) { - // We used the entire data set. Put y at the mean of the whole set - for (i = 0; i < d; i++) - thisY[i] = x_cum[i]/n; - td->out->n[probeIndex] = n; - td->out->R2[probeIndex] = R2; - isdone = true; - } else { - // We satisfied the MSAMS criterion without using the whole - // data set. Update the current y position, using the - // backtracked-value if appropriate - assert(msams_criterion_met == true); - if (td->ops->backtrack) - for (i = 0; i < d; i++) - thisY[i] = x_backtrack[i]/n; - else - for (i = 0; i < d; i++) - thisY[i] = x_cum[i]/n; - td->out->n[probeIndex] = n; - td->out->R2[probeIndex] = R2; - - // The test for convergence by means of closer approach to a - // different landmark is done above (and will be done again on the - // next iteration). Here we have to test for cycling, i.e., - // revisiting the same sequence of positions. - // Put current point on trajectory history - ytrajtmp = ytraj+(iter+1)*d; - for (i = 0; i < d; i++) - ytrajtmp[i] = thisY[i]; - ntraj[iter] = td->out->n[probeIndex]; - R2traj[iter] = td->out->R2[probeIndex]; - // Check previous points in reverse order since it's likely - // the cycling starts at the end of the trajectory - for (i = iter-1, ytrajtmp = ytraj+(i+1)*d; i >= 0; i--, ytrajtmp-=d) - if (sqrdist(thisY,thisYend,ytrajtmp) < tol*R2/n) { - isdone = true; - iscycling = true; - break; - } - if (iscycling && i < iter-1) { - // It's cycling but not stable. Find the place where the - // maximum density was achieved, which is indicated by the - // largest n. (In case of a tie, use the smallest R2 to - // break the tie.) - int imax,istart; - Tint nmax; - Tdata R2min; - // By default keep the last visit, since that's the one that - // is least likely to be contaminated by roundoff - nmax = ntraj[iter]; - imax = iter; - R2min = R2traj[iter]; - istart = i; - // Note: don't choose the first one, that's most likely to - // be contaminated by roundoff errors - for (i++; i < iter; i++) - if ((ntraj[i] > nmax) || (ntraj[i] == nmax && R2traj[i] < R2min)) { - nmax = ntraj[i]; - imax = i; - R2min = R2traj[i]; - } - // Copy that location to the current point. - /* - // We actually copy the next location, as that one is the - // one that is guaranteed to not have roundoff errors (all - // points that end up at this location should include the - // same points, in the same order) - - // Update: this seems like a bad idea. Better to be just a - // little sloppier about the tolerance. The problem is you - // might get trapped in some weird local constellation of - // points---better to stick with the "Olympian view". So - // this bit has been commented out. - imax++; - if (imax > iter) - imax = iter; - */ - ytrajtmp = ytraj + imax*d; - for (i = 0; i < d; i++) - thisY[i] = ytrajtmp[i]; - td->out->n[probeIndex] = nmax; - td->out->R2[probeIndex] = R2min; - } // if (iscycling) - } // end of processing after satisfying MSAMS criterion - iter++; - isdone = isdone || (iter >= td->ops->max_iter); - } // Convergence of probe point while(!isdone) - // Do the last bit of reporting - td->out->closestLandmark[probeIndex] = closestIndex + td->lminfo->index_offset; - td->out->n_iter[probeIndex] = iter; - if (iter < td->ops->max_iter) - td->out->convergedFlag[probeIndex] = 1+iscycling; - else - td->out->convergedFlag[probeIndex] = 0; - } // Loop over probe points - - - // Clean up - if (traj_is_tmp) { - delete[] ytraj; - delete[] ntraj; - } - delete[] R2traj; - return; -} - -template -void expand_neighborhood_msams(const Tdata *x,int d,const Tdata *thisY,landmarked_neighbors &lm_nbrs,const optionStruct *ops,vector &x_cum,vector &deltax_cum,vector &sumsq_cum,vector &x_backtrack,int &n,Tdata &R2,int offset,Tint *pointIndex) -{ - // A lot of intermediate storage is passed so that we don't have to - // allocate fresh storage on each call - - int i; - int n_backtrack; // the number of points at which ratio first exceeded 1 - bool msams_criterion_met, msams_backtrack_met, this_backtrack_met; - Tdata tmpR,tmpR2,R2_backtrack; - int thisPointIndex; - const Tdata *thisPoint; - - const Tdata *thisYend = thisY + d; - Tdata factor2 = ops->factor; - factor2 = factor2*factor2; - Tdata tol = ops->convergence_thresh; - - // Initialize the cumulative variables that we'll use to check - // the MSAMS criterion - for (i = 0; i < d; i++) { - x_cum[i] = 0; - deltax_cum[i] = 0; - sumsq_cum[i] = 0; - } - - // Process the data points needed to satisfy the MSAMS criterion - msams_criterion_met = false; - msams_backtrack_met = false; - n = 0; // The number of points we've checked so far - n_backtrack = 0; - while (!msams_criterion_met && !lm_nbrs.is_empty()) { - thisPointIndex = lm_nbrs.current_point()->index; - if (pointIndex != NULL) - pointIndex[n] = thisPointIndex + offset; - n++; // Keep track of the # of points we've tested - // Test the MSAMS criterion at the current point (i.e., radius) - R2 = lm_nbrs.current_point()->R2; - thisPoint = x+d*thisPointIndex; - this_backtrack_met = false; - typename vector::iterator xIterator,dxIterator,sqIterator; - const Tdata *dataIterator; - if (ops->any_coordinate) { - for (dataIterator = thisY,xIterator = x_cum.begin(),dxIterator = deltax_cum.begin(),sqIterator = sumsq_cum.begin(); dataIterator < thisYend; dataIterator++,xIterator++,dxIterator++,sqIterator++,thisPoint++) { - // The any_coordinate == true case - *xIterator += *thisPoint; - tmpR = *thisPoint - *dataIterator; - *dxIterator += tmpR; - *sqIterator += tmpR*tmpR; - tmpR2 = (*dxIterator)*(*dxIterator); - msams_criterion_met = msams_criterion_met || (n >= ops->n_min && tmpR2 > factor2 * *sqIterator); - if (tmpR2 > *sqIterator) - this_backtrack_met = true; - } - } else { - tmpR2 = 0; - Tdata tmpssq = 0; - for (dataIterator = thisY,xIterator = x_cum.begin(),dxIterator = deltax_cum.begin(),sqIterator = sumsq_cum.begin(); dataIterator < thisYend; dataIterator++,xIterator++,dxIterator++,sqIterator++,thisPoint++) { - // The any_coordinate == false case - *xIterator += *thisPoint; - tmpR = *thisPoint - *dataIterator; - *dxIterator += tmpR; - *sqIterator += tmpR*tmpR; - tmpR2 += (*dxIterator)*(*dxIterator); - tmpssq += *sqIterator; - } - msams_criterion_met = msams_criterion_met || (n >= ops->n_min && tmpR2 > factor2 * tmpssq); - if (tmpR2 > tmpssq) - this_backtrack_met = true; - } - if (this_backtrack_met) { - if (!msams_backtrack_met) { - // This is the first time (at least in a while) that - // we've satisfied the backtrack criterion, so store the - // cumulative deltax - msams_backtrack_met = true; - for (i = 0; i < d; i++) - x_backtrack[i] = x_cum[i]; - n_backtrack = n; - R2_backtrack = R2; - } - } else - msams_backtrack_met = false; //clear if pt fails this_backtrack_met - // Advance to the next point - lm_nbrs.next_point(); - } - if (ops->backtrack) { - n = n_backtrack; - R2 = R2_backtrack; - } -} diff --git a/spikeSorting/meanShift/msams_converge_core.h b/spikeSorting/meanShift/msams_converge_core.h deleted file mode 100644 index 7c3c904..0000000 --- a/spikeSorting/meanShift/msams_converge_core.h +++ /dev/null @@ -1,81 +0,0 @@ -// A structure that is used to control the behavior of the algorithm -struct optionStruct { - int n_min; - double factor; - bool leapfrog; - bool backtrack; - bool any_coordinate; - bool probePointsAreDataPoints; - double convergence_thresh; - int max_iter; - int n_threads; - int n_cpus; - - optionStruct() { - n_min = 3; - factor = 3; - leapfrog = true; - backtrack = true; - any_coordinate = false; - probePointsAreDataPoints = false; - convergence_thresh = 1e-12; - max_iter = 1000; - n_cpus = 1;//sysconf(_SC_NPROCESSORS_ONLN); - n_threads = n_cpus; - } -}; - -// An output structure -template -struct outputStruct { - Tdata *y; - Tint *closestLandmark; - Tint *n; - Tdata *R2; - Tint *n_iter; - Tint *convergedFlag; - Tint *ntraj; - Tdata *ytraj; - - outputStruct() { - y = NULL; - closestLandmark = NULL; - n = NULL; - R2 = NULL; - n_iter = NULL; - convergedFlag = NULL; - ntraj = NULL; - ytraj = NULL; - } -}; - -// A catch-all structure that is needed to support multithreading -template -struct thread_data_type { - const Tdata *x; - int d; - int N; - landmarkStruct *lminfo; - int q; - outputStruct *out; - const optionStruct *ops; - - int probePtIndex_start; - int probePtIndex_end; -}; - -/* -// A comparison function for heapsort routines, arranged so that the -// top of the heap will be the closest point -struct is_farther: public binary_function { - bool operator()(const SqrdistIndex &sd1,const SqrdistIndex &ds2) {return sd1.R2 > sd2.R2;}}; -*/ - -template -extern int msams_core(const Tdata *x,int d,int N,landmarkStruct &lminfo,const Tdata *y,int q,outputStruct &out,const optionStruct &ops); -template -extern void msams_core_work(thread_data_type *td); - - -template -extern void expand_neighborhood_msams(const Tdata *x,int d,const Tdata *thisY,landmarked_neighbors &lm_nbrs,const optionStruct *ops,vector &x_cum,vector &deltax_cum,vector &sumsq_cum,vector &x_backtrack,int &n,Tdata &R2,int offset,Tint *pointIndex); diff --git a/spikeSorting/meanShift/msams_converge_mex.cpp b/spikeSorting/meanShift/msams_converge_mex.cpp deleted file mode 100644 index 70cd4c4..0000000 --- a/spikeSorting/meanShift/msams_converge_mex.cpp +++ /dev/null @@ -1,368 +0,0 @@ -#ifdef MAIN -#include "mat.h" -#include "mat_variables.h" -#include -#else -#include "mex.h" -#endif - -//#include -#include "msams_converge_core.cpp" - -/* msams_converge_mex: move point(s) by adaptive meanshift, using landmarking - * - * Syntax: - * outdata = msams_converge_mex(x,lminfo,y,options) - * where (syntax is similar to msams_converge) - * x is a d-by-N matrix of data points in d-dimensional space; - * lminfo is a landmark structure of the type returned by - * choose_landmarks; - * y is a d-by-q matrix of probe points in d-dimensional space; - * options is a structure which may have the following fields: - * min_to_check (default 3) - * factor (default 3) - * leapfrog (default true) - * backtrack (default true) - * any_coordinate (default false) - * convergence_thresh (default 1e-12) - * max_iter (default 1000) - * n_threads (default # of cores) - * and outdata is a structure which has the following fields: - * yf is d-by-q matrix containing the final position of the - * selected landmark(s) (as moving probe points) - * closestLandmark is the 1-by-q index of the landmark closest to each yf - * n is the 1-by-q vector containing the number of points - * contributing to each probe point at their final positions - * R2 is the squared radius for each final probe point - * n_iter is the number of iterations required for convergence for - * each probe point - * convergedFlag is a flag indicating whether each point converged - * (0 = no convergence, 1 = converged, 2 = "converged" by cycling) - * settings is a copy of the options structure with defaults filled - * in (checking this is the most reliable way to learn what the - * defaults really are!) - * ntraj (present only for q = 1) is the sequence of # of contributing - * neighbors on each mean shift cycle - * ytraj (present only for q = 1) is a d-by-niterations matrix that - * stores the history of positions visited - */ - -// Utility functions -//int is_scalar(const mxArray *m); -//double mcm_get_scalar_field(const mxArray *mxPtr,const char *name); -template -void fillOptionalScalarField(const mxArray *m,const char *name,T *v); -template -void setFieldPtr(const mxArray *m,const char *name,T **d); -void mat2C(const mxArray *mxOptions,optionStruct &ops); -void C2mat(const optionStruct &ops,mxArray *mxOptions); -template -void mat2C(const mxArray *mxOut,outputStruct &out); - - -// Information specifying structures for Matlab's consumption -const char* settingsfields[] = { - "min_to_check", - "factor", - "leapfrog", - "backtrack", - "any_coordinate", - "convergence_thresh", - "max_iter", - "n_threads" -}; -const int n_settingsfields = 8; - -const char* outputfields[] = { - "yf", - "closestLandmark", - "n", - "R2", - "n_iter", - "convergedFlag", - "settings", - "ntraj", - "ytraj" -}; -const int n_outputfields = 7; // add 2 if q==1 to get ntraj & ytraj - -const int matlab_offset = 1; - -// This is the "inner" matlab wrapper. It is called by mexFunction -// (below), but this one does all the real work. It's templated so -// that it can work with a variety of data types. -template -void msams_wrapper(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[],bool (*validationFunction)(const mxArray*),mxClassID allocationTypeFlag) -{ - dataType *x,*y; - double *lmIndex; - int N,d,q,i; - const mxArray *curarg; - mxArray *mxPtr, *mxPtr2, *mxOutput, *settingsStruct; - landmarkStruct lminfo; - optionStruct ops; - outputStruct out; - - // Parse the inputs - // Get the data points - curarg = prhs[0]; - x = (dataType*) mxGetData(curarg); - d = mxGetM(curarg); - N = mxGetN(curarg); - - // Collect the landmark info - curarg = prhs[1]; - if (!mxIsStruct(curarg)) - mexErrMsgTxt("msams_converge_mex: lminfo must be a structure"); - //Landmark info: landmarks field - mxPtr = mxGetField(curarg,0,"landmarks"); - if (mxPtr == NULL) - mexErrMsgTxt("msams_converge_mex: error parsing lminfo's 'landmarks' field"); - lminfo.n_landmarks = mxGetN(mxPtr); - if (mxGetM(mxPtr) != d) - mexErrMsgTxt("msams_converge_mex: landmarks must have the same dimensionality as the data"); - if (!validationFunction(mxPtr)) - mexErrMsgTxt("msams_converge_mex: landmarks must be of the same data type as the data points"); - lminfo.landmarks = (dataType*) mxGetData(mxPtr); - //Landmark info: radius_of_neighborhood field - mxPtr = mxGetField(curarg,0,"radius_of_neighborhood"); - if (mxPtr == NULL) - mexErrMsgTxt("msams_converge_mex: error parsing lminfo's 'radius_of_neighborhood' field"); - if (mxGetNumberOfElements(mxPtr) != lminfo.n_landmarks) - mexErrMsgTxt("msams_converge_mex: wrong number of entries in 'radius_of_neighborhood' field"); - lminfo.landmarkR = mxGetPr(mxPtr); - //Landmark info: landmarkList field - mxPtr = mxGetField(curarg,0,"landmarkList"); - if (mxPtr == NULL) - mexErrMsgTxt("msams_converge_mex: error parsing lminfo's 'landmarkList' field"); - if (!mxIsCell(mxPtr)) - mexErrMsgTxt("msams_converge_mex: lminfo's 'landmarkList' field must be a cell array"); - if (mxGetN(mxPtr) != lminfo.n_landmarks) - mexErrMsgTxt("msams_converge_mex: landmarkList must have the same number of elements as there are landmarks"); - lminfo.landmarkList = (double **) mxMalloc(lminfo.n_landmarks * sizeof(double*)); - lminfo.n_landmarkList = (int *) mxMalloc(lminfo.n_landmarks * sizeof(int)); - for (i = 0; i < lminfo.n_landmarks; i++) { - mxPtr2 = mxGetCell(mxPtr,i); - lminfo.landmarkList[i] = mxGetPr(mxPtr2); - lminfo.n_landmarkList[i] = mxGetNumberOfElements(mxPtr2); - } - lminfo.d = d; - lminfo.index_offset = matlab_offset; - - // Get the probe points - curarg = prhs[2]; - if (mxIsEmpty(curarg)) { - // Passing an empty matrix uses the data points as the probe points - y = x; - q = N; - ops.probePointsAreDataPoints = true; - } else { - // Read the probe points - if (!mxIsNumeric(curarg) || mxIsComplex(curarg) || !validationFunction(curarg)) - mexErrMsgTxt("msams_converge_mex: y must be of the same data type as the data points"); - if (mxGetM(curarg) != d) - mexErrMsgTxt("msams_converge_mex: the number of rows in x and y must be the same"); - q = mxGetN(curarg); - y = (dataType*) mxGetData(curarg); - } - - /* - landmarked_neighbors lm_nbrs; - lm_nbrs.allocate(lminfo.n_landmarks,N); - lm_nbrs.initialize(y,x,lminfo); - return; - */ - - // Parse the options - if (nrhs > 3) { - curarg = prhs[3]; - if (!mxIsStruct(curarg)) - mexErrMsgTxt("msams_converge_mex: options must be a structure"); - mat2C(curarg,ops); - } - ops.n_min = (N >= ops.n_min) ? ops.n_min : N; // set to min(n_min,N) - if (q == 1) - ops.n_threads = 1; - ops.n_threads = (ops.n_cpus < ops.n_threads) ? ops.n_cpus : ops.n_threads; - - // Print info - - //mexPrintf("d %d, N %d, q %d, nlhs %d, nrhs %d\n",d,N,q,nlhs,nrhs); - //mexPrintf("factor %g, convergence_thresh %g\n",ops.factor,ops.convergence_thresh); - //mexPrintf("leapfrog %d, n_min %d, backtrack %d, any_coordinate %d, max_iter %d\n",ops.leapfrog,ops.n_min,ops.backtrack,ops.any_coordinate,ops.max_iter); - //mexPrintf("n_landmarks_in_list: "); - //for (i = 0; i < lminfo.n_landmarks; i++) - // mexPrintf("%d ",lminfo.n_landmarkList[i]); - //mexPrintf("\n"); - - - // Set up the output; the fields depend on whether q == 1 - plhs[0] = mxCreateStructMatrix(1,1,n_outputfields+2*(q==1),outputfields); - mxOutput = plhs[0]; - mxSetField(mxOutput,0,"yf",mxCreateNumericMatrix(d,q,allocationTypeFlag,mxREAL)); - mxSetField(mxOutput,0,"closestLandmark",mxCreateDoubleMatrix(1,q,mxREAL)); - mxSetField(mxOutput,0,"n",mxCreateDoubleMatrix(1,q,mxREAL)); - mxSetField(mxOutput,0,"R2",mxCreateNumericMatrix(1,q,allocationTypeFlag,mxREAL)); - mxSetField(mxOutput,0,"n_iter",mxCreateDoubleMatrix(1,q,mxREAL)); - mxSetField(mxOutput,0,"convergedFlag",mxCreateDoubleMatrix(1,q,mxREAL)); - mat2C(mxOutput,out); - memcpy(out.y,y,d*q*sizeof(dataType)); // copy the probe point positions - settingsStruct = mxCreateStructMatrix(1,1,n_settingsfields,settingsfields); - C2mat(ops,settingsStruct); - mxSetField(mxOutput,0,"settings",settingsStruct); - if (q == 1) { - // Do ntraj and ytraj as temporary variables - out.ntraj = (double *) mxMalloc(ops.max_iter * sizeof(double)); - out.ytraj = (dataType*) mxMalloc((ops.max_iter+1)*d*sizeof(dataType)); - } - - if (!msams_core(x,d,N,lminfo,q,out,ops)) - mexErrMsgTxt("msams_converge_mex: error creating threads"); - - if (q == 1) { - // Convert ntraj & ytraj to output mxArrays - int n_iter = (int) out.n_iter[0]; - mxArray *ntrajMx,*ytrajMx; - ntrajMx = mxCreateDoubleMatrix(1,n_iter,mxREAL); - mxSetField(mxOutput,0,"ntraj",ntrajMx); - ytrajMx = mxCreateNumericMatrix(d,n_iter+1,allocationTypeFlag,mxREAL); - mxSetField(mxOutput,0,"ytraj",ytrajMx); - memcpy(mxGetPr(ntrajMx),out.ntraj,n_iter*sizeof(double)); - memcpy(mxGetPr(ytrajMx),out.ytraj,(n_iter+1)*d*sizeof(dataType)); - mxFree(out.ntraj); - mxFree(out.ytraj); - } - - mxFree(lminfo.landmarkList); - mxFree(lminfo.n_landmarkList); - return; -} - -// The "outer" matlab wrapper. All this does is act as a switchyard -// for choosing the single-precision or double-precision templated code. -void mexFunction( - int nlhs, mxArray *plhs[], - int nrhs, const mxArray *prhs[]) -{ - const mxArray *curarg; - - if (nrhs < 3 || nrhs > 4) - mexErrMsgTxt("msams_converge_mex: requires three or four inputs"); - if (nlhs != 1) - mexErrMsgTxt("msams_converge_mex: requires one output"); - - curarg = prhs[0]; - if (!mxIsNumeric(curarg) || mxIsComplex(curarg)) - mexErrMsgTxt("msams_converge_mex: x must be a real matrix"); - - if (mxIsDouble(curarg)) - msams_wrapper(nlhs,plhs,nrhs,prhs,&mxIsDouble,mxDOUBLE_CLASS); - else if (mxIsSingle(curarg)) - msams_wrapper(nlhs,plhs,nrhs,prhs,&mxIsSingle,mxSINGLE_CLASS); - else - mexErrMsgTxt("msams_converge_mex: x must be a single- or double-precision"); - - return; -} - -template -void fillOptionalScalarField(const mxArray *mxPtr,const char *name,T *v) -{ - const mxArray *fieldPtr; - - fieldPtr = mxGetField(mxPtr,0,name); - if (fieldPtr != NULL) { - if (mxGetNumberOfElements(fieldPtr) != 1) - mexErrMsgIdAndTxt("msams_converge_mex:field_parsing_error","msams_converge_mex: expect field '%s' to be a scalar",name); - *v = (T) mxGetScalar(fieldPtr); - //mexPrintf("Field %s was set to %g\n",name,mxGetScalar(fieldPtr)); - } -} - -template -void setFieldPtr(const mxArray *mxPtr,const char *name,T **d) -{ - const mxArray *fieldPtr; - - fieldPtr = mxGetField(mxPtr,0,name); - if (fieldPtr != NULL) - *d = (T*) mxGetData(fieldPtr); -} - -void mat2C(const mxArray *mxOptions,optionStruct &ops) -{ - fillOptionalScalarField(mxOptions,"min_to_check",&(ops.n_min)); - fillOptionalScalarField(mxOptions,"factor",&(ops.factor)); - fillOptionalScalarField(mxOptions,"leapfrog",&(ops.leapfrog)); - fillOptionalScalarField(mxOptions,"backtrack",&(ops.backtrack)); - fillOptionalScalarField(mxOptions,"any_coordinate",&(ops.any_coordinate)); - fillOptionalScalarField(mxOptions,"convergence_thresh",&(ops.convergence_thresh)); - fillOptionalScalarField(mxOptions,"max_iter",&(ops.max_iter)); - fillOptionalScalarField(mxOptions,"n_threads",&(ops.n_threads)); -} - -void C2mat(const optionStruct &ops,mxArray *mxOptions) -{ - mxSetField(mxOptions,0,"min_to_check",mxCreateDoubleScalar(double(ops.n_min))); - mxSetField(mxOptions,0,"factor",mxCreateDoubleScalar(ops.factor)); - mxSetField(mxOptions,0,"leapfrog",mxCreateDoubleScalar(double(ops.leapfrog))); - mxSetField(mxOptions,0,"backtrack",mxCreateDoubleScalar(double(ops.backtrack))); - mxSetField(mxOptions,0,"any_coordinate",mxCreateDoubleScalar(double(ops.any_coordinate))); - mxSetField(mxOptions,0,"convergence_thresh",mxCreateDoubleScalar(ops.convergence_thresh)); - mxSetField(mxOptions,0,"max_iter",mxCreateDoubleScalar(double(ops.max_iter))); - mxSetField(mxOptions,0,"n_threads",mxCreateDoubleScalar(double(ops.n_threads))); -} - -template -void mat2C(const mxArray *mxOut,outputStruct &out) { - setFieldPtr(mxOut,"yf",&(out.y)); - setFieldPtr(mxOut,"closestLandmark",&(out.closestLandmark)); - setFieldPtr(mxOut,"n",&(out.n)); - setFieldPtr(mxOut,"R2",&(out.R2)); - setFieldPtr(mxOut,"n_iter",&(out.n_iter)); - setFieldPtr(mxOut,"convergedFlag",&(out.convergedFlag)); -}; - - -// For debugging & profiling: build a stand-alone application -#ifdef MAIN -int main(int argc,char *argv[]) -{ - char *filein,*fileout; - const int n_inputs = 4; - const int n_outputs = 1; - mxArray *input[n_inputs]; - mxArray *output[n_outputs]; - const char *input_names[] = { - "x", - "lminfo", - "y", - "ops" - }; - const char *output_names[] = { - "out" - }; - - if (argc < 3) { - printf("Usage:\n %s infile outfile\nwhere infile is a .mat file with variables x, y, lminfo, and ops\n",argv[0]); - return EXIT_FAILURE; - } - - filein = argv[1]; - fileout = argv[2]; - printf("Input file: %s\nOutput file: %s\n",filein,fileout); - - // Load the inputs - mat_load_variables(filein,input_names,n_inputs,input); - - printf("Output file just before calling mexfcn: %s\n",fileout); - // Call the C program, using the MEX interface function - mexFunction(n_outputs,output,n_inputs,(const mxArray**) input); - - // Save the outputs - printf("Output file just before save: %s\n",fileout); - mat_save_variables(fileout,output_names,n_outputs,output); - - return EXIT_SUCCESS; -} -#endif diff --git a/spikeSorting/meanShift/msams_converge_mex.mexa64 b/spikeSorting/meanShift/msams_converge_mex.mexa64 deleted file mode 100644 index 24e7efe..0000000 Binary files a/spikeSorting/meanShift/msams_converge_mex.mexa64 and /dev/null differ diff --git a/spikeSorting/meanShift/msams_converge_mex.mexw64 b/spikeSorting/meanShift/msams_converge_mex.mexw64 deleted file mode 100644 index 65b8da4..0000000 Binary files a/spikeSorting/meanShift/msams_converge_mex.mexw64 and /dev/null differ diff --git a/spikeSorting/meanShift/sqrdist.cpp b/spikeSorting/meanShift/sqrdist.cpp deleted file mode 100644 index 7360608..0000000 --- a/spikeSorting/meanShift/sqrdist.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include "mex.h" -//#include -//#include // for # of CPUs - -template -int sqrdist_thread_launcher(const Tdata *x,const Tdata *y,int N,int d,int q,double *distmtrx,int n_threads); - -/* - * This is the Matlab wrapper - */ - -/* - * Given x and y, compute the distance between them. x is - * d-by-N, y is d-by-q, and both are organized by column in memory. - */ -// with multithreading one might be able to get a performance boost by -// switching the order of the loops (fewer cache misses on x?), but -// this hasn't been tried yet. -template -void sqrdist_generic(const dataT *x,const dataT *y,int N,int d,int q,double *distmtrx) -{ - double distsq,distmtrxtemp,dtemp,sqrtmp; - const dataT *xp; - int i,j,k,identtemp; - - for (j = 0; j < q; j++) { // Loop over points of y - xp = x; // Restart at first x point - for (i = 0; i < N; i++,distmtrx++) { // Loop over the points of x - dtemp = 0; - for (k = 0; k < d; k++,xp++) { // Loop over coordinates - sqrtmp = y[k]-*xp; - dtemp += sqrtmp*sqrtmp; - } - *distmtrx = dtemp; - } - y += d; // Go on to the next point of y - } - return; -} - -// A structure for passing data to pthreads -template -struct thread_data_type { - const Tdata *x; - const Tdata *y; - int d; - int N; - int q; - double *distmtrx; -}; - - -void mexFunction( - int nlhs, mxArray *plhs[], - int nrhs, const mxArray *prhs[]) -{ - double *x, *y, *distmtrx; - int N,d,q; - const mxArray *curarg; - int ncpus,nthreads,ret; - - if (nrhs < 2) - mexErrMsgTxt("sqrdist: requires two inputs"); - - // Parse the inputs - curarg = prhs[0]; - if (!mxIsNumeric(curarg) || mxIsComplex(curarg)) - mexErrMsgTxt("sqrdist: x must be a real matrix"); - x = mxGetPr(curarg); - d = mxGetM(curarg); - N = mxGetN(curarg); - - curarg = prhs[1]; - if (!mxIsNumeric(curarg) || mxIsComplex(curarg)) - mexErrMsgTxt("sqrdist: y must be a real matrix"); - y = mxGetPr(curarg); - if (d != mxGetM(curarg)) - mexErrMsgTxt("sqrdist: the dimensionality of x and y disagree"); - q = mxGetN(curarg); - - ncpus = 1;//sysconf(_SC_NPROCESSORS_ONLN); - if (ncpus > 4) - ncpus = 4; // performance is not very linear, so don't go crazy - nthreads = (int) (double(d)*double(q)*double(N)/100000); - if (nthreads > ncpus) - nthreads = ncpus; - if (nthreads > q) - nthreads = q; // since we thread on q, no point if q == 1 - if (nthreads < 1) - nthreads = 1; - nthreads = 1; - //mexPrintf("nthreads = %d\n",nthreads); - - //mexPrintf("d %d, N %d, q %d, nlhs %d, nrhs %d\n",d,N,q,nlhs,nrhs); - - // Set up the output - plhs[0] = mxCreateDoubleMatrix(N,q,mxREAL); - distmtrx = mxGetPr(plhs[0]); - // Do the actual work - if (mxIsDouble(prhs[0]) && mxIsDouble(prhs[1])) - sqrdist_generic(x,y,N,d,q,distmtrx);//sqrdist_thread_launcher(x,y,N,d,q,distmtrx,nthreads); - else if (mxIsSingle(prhs[0]) && mxIsSingle(prhs[1])) - sqrdist_generic(x,y,N,d,q,distmtrx);//sqrdist_thread_launcher((float *)x,(float *)y,N,d,q,distmtrx,nthreads); - else - mexErrMsgTxt("sqrdist: both x and y must either be single or double"); - return; -} - - - -// A wrapper for multithreading -template -void *sqrdist_thread(void *p) -{ - thread_data_type *td; - - td = (thread_data_type*) p; - sqrdist_generic(td->x,td->y,td->N,td->d,td->q,td->distmtrx); -} - -// The launcher for multithreading -template -int sqrdist_thread_launcher(const Tdata *x,const Tdata *y,int N,int d,int q,double *distmtrx,int n_threads) -{ - int i,j; - int *splits,extras,n_pts_per_thread; - thread_data_type *td; - pthread_t *thread; - - if (n_threads == 1) { - sqrdist_generic(x,y,N,d,q,distmtrx); - return 1; - } - - // Decide how the data will be split among threads - n_pts_per_thread = q/n_threads; - extras = q - n_threads*n_pts_per_thread; - splits = new int[n_threads+1]; - splits[0] = 0; - for (i = 0; i < n_threads; i++) - splits[i+1] = splits[i] + n_pts_per_thread + (extras-- > 0); - - // Pack arguments into thread data type, splitting out the various - // points in y to be handled by different CPUs. - td = new thread_data_type[n_threads]; - for (i = 0; i < n_threads; i++) { - td[i].x = x; - td[i].y = y + d*splits[i]; - td[i].N = N; - td[i].d = d; - td[i].q = splits[i+1]-splits[i]; - td[i].distmtrx = distmtrx+N*splits[i]; - } - - delete[] splits; - - // Launch threads - thread = new pthread_t[n_threads]; - for (i = 0; i < n_threads && td[i].q > 0; i++) - if (pthread_create(thread+i,NULL,sqrdist_thread,(void*) (td+i)) != 0) - return 0; // error creating thread - - // Wait for threads to return - // Only do this for the ones that got launched; i should be - // initialized to the first thread that _didn't_ run (or to - // n_threads, if q > n_threads) - for (i--; i >= 0; i--) - pthread_join(thread[i],NULL); - - delete[] td; - delete[] thread; - - return 1; // success! -} diff --git a/spikeSorting/meanShift/sqrdist.mexa64 b/spikeSorting/meanShift/sqrdist.mexa64 deleted file mode 100644 index b2cb755..0000000 Binary files a/spikeSorting/meanShift/sqrdist.mexa64 and /dev/null differ diff --git a/spikeSorting/meanShift/sqrdist.mexw64 b/spikeSorting/meanShift/sqrdist.mexw64 deleted file mode 100644 index cfcbe4d..0000000 Binary files a/spikeSorting/meanShift/sqrdist.mexw64 and /dev/null differ diff --git a/spikeSorting/merge.m b/spikeSorting/merge.m deleted file mode 100644 index 3cc5289..0000000 --- a/spikeSorting/merge.m +++ /dev/null @@ -1,49 +0,0 @@ -function mergeUnits() -% Notice!!!! In this process waveforms are not merged. To do so, we need to go over all spikes are recalculate - -%merge all waveforms -clustersInCh=cellfun(@(x) size(x,2),avgWaveform); -pClustersInActiveCh=find(clustersInCh>0); -clustersInActiveCh=clustersInCh(pClustersInActiveCh); -activeChannels=selectedChannels(pClustersInActiveCh); - -%calculate indices in merged waveform matrix -endIdxClustersInActiveCh=cumsum(clustersInActiveCh); -startIdxClustersInActiveCh=[1 endIdxClustersInActiveCh(1:end-1)+1]; -%build merged waveform matrix -nWaveforms=sum(clustersInActiveCh); -avgWaveformAll=zeros(size(avgWaveform{pClustersInActiveCh(1)},1),nWaveforms,size(avgWaveform{pClustersInActiveCh(1)},3)); -for i=1:numel(clustersInActiveCh) - avgWaveformAll(:,startIdxClustersInActiveCh(i):endIdxClustersInActiveCh(i),:)=avgWaveform{pClustersInActiveCh(i)}; -end -%examine distances between all waveforms in merged matrix -waveformSimilarity=nan(nWaveforms); -for i=1:nWaveforms - for j=(i+1):nWaveforms - waveformSimilarity(i,j)=mean(mean(bsxfun(@minus,avgWaveformAll(:,i,:),avgWaveformAll(:,j,:)).^2,1),3); - end -end -[pMerge1 pMerge2]=find(waveformSimilarity<4); - -%merge all neurons below threshold -for i=1:numel(pMerge1) - if pMerge1(i)~=pMerge2(i) - %find the - mergeCh1(i)=find(pMerge1(i)>=startIdxClustersInActiveCh & pMerge1(i)<=endIdxClustersInActiveCh); - mergeCh2(i)=find(pMerge2(i)>=startIdxClustersInActiveCh & pMerge2(i)<=endIdxClustersInActiveCh); - - %real electrode name for merged neuron - mergeCh1Name(i)=activeChannels(mergeCh1(i)); - mergeCh2Name(i)=activeChannels(mergeCh2(i)); - %real neuron number in electrode for merged neuron - mergeNeu1(i)=pMerge1(i)-startIdxClustersInActiveCh(mergeCh1(i))+1; - mergeNeu2(i)=pMerge2(i)-startIdxClustersInActiveCh(mergeCh2(i))+1; - %merge neurons - [t,ic]=MergeNeurons(t,ic,[mergeCh1Name(i);mergeNeu1(i)],[mergeCh2Name(i);mergeNeu2(i)]); - %update the merging list since some of the neurons were already merged previously - - deleteChPlace=pMerge2(i); - pMerge2(pMerge2==deleteChPlace)=pMerge1(i); - pMerge1(pMerge1==deleteChPlace)=pMerge1(i); - end -end \ No newline at end of file diff --git a/spikeSorting/projectionND.m b/spikeSorting/projectionND.m deleted file mode 100644 index c1c62d7..0000000 --- a/spikeSorting/projectionND.m +++ /dev/null @@ -1,9 +0,0 @@ -function p=projectionND(v,d) -%Calculate projection between a vector and a set of dots in multi dimensional space -%v = [1 x N] - vector -%d = [M X N] - M dot locations - -%calculate the cos angle between vector and dots -cosAng=v*d'./(sqrt(sum(v.^2))*sqrt(sum(d'.^2))); -p=cosAng.*sqrt(sum(d'.^2)); - diff --git a/spikeSorting/spikePositionEstimation.m b/spikeSorting/spikePositionEstimation.m deleted file mode 100644 index 61596c9..0000000 --- a/spikeSorting/spikePositionEstimation.m +++ /dev/null @@ -1,511 +0,0 @@ -function [est,hand,testData]=spikePositionEstimation(WF,ch,preMs,Fs,En,varargin) -% [est,h,testData]=spikePositionEstimation(WF,ch,preMs,Fs,En,varargin) -% Function purpose : Calculate parameters of spike shapes -% -% Function recives : WF - average spike waveforms over all electrodes in ch [Double [neurons x ch x samples] -% ch - the channel numbers of the channels in avgWFWaveform [NChannels,Time] - the raw voltage samples of all channels -% preMs - pre spike time in WF [ms] -% Fs - sampling frequency of the WFs -% En - electrode layout -% neuronIdentity [1 x neurons] - neuron identity (1=none, 2=Inhibitory, 3=Excitatory)] -% -% varargin ('property name','property value') -% -% Function give back : par - a structure of output parameters -% hand - a structure of handles from generated plots -% -% Last updated : 29/07/15 - -%default parameters -smoothingDuration=0.5; %[ms] -maxDistForElectrodes=190; %[uM] -electrodePitch=100; %[uM] -useSameTimePoint=true; %if true takes the time point of max channel of every neuron and uses this time for all channels, if false checks for the max of each ch seperately -dXY=1; %[uM] -dZ=1; %[uM] -dL=1; -dV0=1; %[uV] -maxZ=200; %[uM] -minMaxV0=[100 300]; %[uV] -minMaxL=[50 150]; %[uM] - -gridColor=[0.8 0.8 0.8]; -cellDiameter=15; %[um] -modelType='reducedModelOpt';%,'realModelOpt','globalMinima','reducedModelOpt'; -smoothSpikes=false; -L0=70; -V0=160; -Xc=[]; -Yc=[]; -useSpikeExtremum=true; -est=[]; %if this is given as input, no calculation is made but plots are still calculated -LGrid=25:1:125; %decay constants to use as initial conditions in optimization -V0Grid=100:5:300; -Icell=10.^(-10:0.05:-7); %current density in initial axon segment -neuronIdentity=[]; - -plot3D=true; -elecNumFontSize=5; -plotTriangulationOnWaveforms=true; -plot1NeuronPerPlotInTriangulation=false; - -%% Output list of default variables -%print out default arguments and values if no inputs are given -if nargin==0 - defaultArguments=who; - for i=1:numel(defaultArguments) - eval(['defaultArgumentValue=' defaultArguments{i} ';']); - if numel(defaultArgumentValue)==1 - disp([defaultArguments{i} ' = ' num2str(defaultArgumentValue)]); - else - fprintf([defaultArguments{i} ' = ']); - disp(defaultArgumentValue); - end - end - return; -end - -%Collects all options -for i=1:2:length(varargin) - eval([varargin{i} '=' 'varargin{i+1};']); -end - -hand=[];testData=[]; - -if isempty(WF) %run on artificial data - nNeurons=10; - nCh=numel(unique(En(~isnan(En)))); - nSpikeSamples=preMs*2*Fs/1000; - - neuronIdentity=round(rand(1,nNeurons))+2; - tX=rand(1,nNeurons)*100-50; - tY=rand(1,nNeurons)*100-50; - tZ=rand(1,nNeurons)*100; - - %tV0=V0+rand(1,nNeurons)*10; - tV0=rand(1,nNeurons)*(minMaxV0(2)-minMaxV0(1))+minMaxV0(1); - %tL=L0+rand(1,nNeurons)*50-25; - tL=rand(1,nNeurons)*(minMaxL(2)-minMaxL(1))+minMaxL(1); - tCh=ceil(rand(1,nNeurons)*nCh); - tCh(tCh==0)=1; - - %Build inverse map between electrode and location - [meshX,meshY]=meshgrid(1:size(En,1),1:size(En,2)); - Xc(En(~isnan(En)))=meshX(~isnan(En))*electrodePitch; - Yc(En(~isnan(En)))=meshY(~isnan(En))*electrodePitch; - - smoothingSamples=round(smoothingDuration*Fs/1000); - preSpkSamples=preMs*Fs/1000; - WF=zeros([nNeurons,nCh,nSpikeSamples]); - for i=1:nNeurons - for j=1:nCh - WF(i,j,preSpkSamples:(preSpkSamples+3*smoothingSamples))=... - -tV0(i).*exp(-sqrt( (Xc(tCh(i))+tX(i)-Xc(j)).^2 + (Yc(tCh(i))+tY(i)-Yc(j)).^2+(tZ(i)-0).^2 )./tL(i)); - %WF(i,j,preSpkSamples:(preSpkSamples+3*smoothingSamples))=... - % -tV0(i).*exp(-sqrt( (Xc(tCh(i))+tX(i)-Xc(j)).^2 + (Yc(tCh(i))+tY(i)-Yc(j)).^2 )./tL(i)); - end - %h=axes;activityTracePhysicalSpacePlot(h,1:nCh,squeeze(WF(i,:,:)),En,'traceColor',[0.2 0.2 0.8],'scaling','none'); - end - - %save parameter for output - testData.neuronIdentity=neuronIdentity; - testData.tX=tX; - testData.tY=tY; - testData.tZ=tZ; - testData.tV0=tV0; - testData.tL=tL; - testData.tCh=tCh; -end - -% Find neuron with reliable spiking -[nNeurons,nCh,nSpikeSamples]=size(WF); - -if isempty(neuronIdentity) %if no an empty neuron identity is given - neuronIdentity=ones(1,nNeurons); -else - neuronIdentity(neuronIdentity==0)=1; -end - -% calculate pre and post samples and their position in the waveform -preSpkSamples=preMs*Fs/1000; -postSpkSamples=nSpikeSamples-preSpkSamples; - - -%% model with x,y,z,V -%according to the current grid arrangement positive Y is down on real MEA space and positive X is right on real MEA space - -%check if ch numbers vector was given and if not, take all channels in array in serial order -if isempty(ch) - ch=unique(En(~isnan(En))); - if numel(ch)~=nCh - error('Number of channels in waveform does not match the channels in En'); - end -else - if size(ch,1)==1 - ch=ch'; - end -end - -%Build inverse map between electrode and location -[meshX,meshY]=meshgrid(1:size(En,1),1:size(En,2)); -if isempty(Xc) - Xc(En(~isnan(En)))=meshX(~isnan(En))*electrodePitch; - Xc=Xc(ch); -end -if isempty(Yc) - Yc(En(~isnan(En)))=meshY(~isnan(En))*electrodePitch; - Yc=Yc(ch); -end - -% find spike extremum ch and position -if useSpikeExtremum - [vMaxAll,pMaxAll]=max(abs(WF),[],3); - [vMax,pChMax]=max(vMaxAll,[],2); -else - [vMaxAll,pMaxAll]=min(WF,[],3); - [vMax,pChMax]=min(vMaxAll,[],2); - vMax=abs(vMax); - vMaxAll=abs(vMaxAll); -end -pMaxSampleInMaxCh=pMaxAll( sub2ind(size(pMaxAll), 1:nNeurons, pChMax') ); - -if isempty(est) %if no previous estimation was entered - - %smooth spike shapes with local linear regression - if smoothSpikes - smoothingSamples=round(smoothingDuration*Fs/1000); - for i=1:nNeurons - for j=1:nCh - WF(i,j,:) = smooth(WF(i,j,:),smoothingSamples,'loess'); - end - end - end - - if strcmp(modelType,'globalMinima') - %define search limits - X=-electrodePitch:dXY:electrodePitch; - Y=-electrodePitch:dXY:electrodePitch; - Z=0:dZ:maxZ; - L=minMaxL(1):dL:minMaxL(2); - V0=minMaxV0(1):dV0:minMaxV0(2); - - %initialize arrays - V0All=ones(numel(X),numel(Y),numel(Z),numel(L),numel(V0)); - XAll=V0All; - YAll=V0All; - ZAll=V0All; - LAll=V0All; - - X5D(:,1,1,1,1)=X; - Y5D(1,:,1,1,1)=Y; - Z5D(1,1,:,1,1)=Z; - L5D(1,1,1,:,1)=L; - V05D(1,1,1,1,:)=V0; - - XAll=bsxfun(@times,XAll,X5D); - YAll=bsxfun(@times,YAll,Y5D); - ZAll=bsxfun(@times,ZAll,Z5D); - LAll=bsxfun(@times,LAll,L5D); - V0All=bsxfun(@times,V0All,V05D); - end - - % main loop - estX=zeros(1,nCh); - estY=zeros(1,nCh); - estV0=zeros(1,nCh); - estZ=zeros(1,nCh); - - hWait=waitbar(0,'Triangulating neurons...'); - for i=1:nNeurons - waitbar(i/nNeurons,hWait); - - pXY=sqrt((Xc-Xc(pChMax(i))).^2+(Yc-Yc(pChMax(i))).^2)widthVolt(i),1,'last'); - pUp=preSpkSamples+find(spikeShapeSmooth(i,pPost)>widthVolt(i),1,'first'); - if ~(isempty(pDown) || isempty(pUp)) - spkWidthSamples(i)=(pUp-pDown); - else - spkWidthSamples(i)=NaN; - end -end -par.width=spkWidthSamples/Fs*1000; - -%calculate width from time difference between minimal and maximal derivative -spikeShapeDer=diff(spikeShapeSmooth,[],2); -[~,derMinP]=min(spikeShapeDer(:,pPre),[],2); -[~,derMaxP]=max(spikeShapeDer(:,pPost(1:end-1)),[],2); -par.widthDer=( (preSpkSamples+derMaxP)-derMinP)/Fs*1000; - -if plotWidth - if plotWidthAddNoise - noiseAdd=(rand(nSpikes,2)-0.5)/Fs*1000; - else - noiseAdd=zeros(nSpikes,2); - end - - f=figure;h.widthAxes=axes; - if plotWidthLogColormap - h.widthScatter=scatter(par.widthDer+noiseAdd(:,1),par.width+noiseAdd(:,2),25,log(par.extermalAmp)); - else - h.widthScatter=scatter(par.widthDer+noiseAdd(:,1),par.width+noiseAdd(:,2),25,par.extermalAmp); - end - xlabel('Width (derivative)'); - ylabel('Width @ half maxima'); - - if plotWidthSpkNumbers - text(par.widthDer+noiseAdd(:,1),par.width+noiseAdd(:,2),num2str((1:nSpikes)'),'fontSize',8); - end - - if plotWidthColorBar - h.widthCb=colorbar; - if plotWidthLogColormap - cbTicks=get(h.widthCb,'YTick'); - set(h.widthCb,'YTickLabel',num2str(exp(cbTicks)',3)); - end - set(gca,'position',[0.1300 0.1100 0.7164 0.8150]); - set(h.widthCb,'position',[0.8607 0.1071 0.0179 0.8167]); - ylabel(h.widthCb,'Extermal Amp [\muV]'); - end - -end - diff --git a/spikeSorting/testGridSorter.m b/spikeSorting/testGridSorter.m deleted file mode 100644 index a6e7f33..0000000 --- a/spikeSorting/testGridSorter.m +++ /dev/null @@ -1,7 +0,0 @@ -files=dir('\\storage.laur.corp.brain.mpg.de\Data\Shein-IdelsonMark\Experiments2014\U4_071014\MCRackData\Images3*.mcd'); -files={files.name}; -dataObj=MCRackRecording(fullfile('\\storage.laur.corp.brain.mpg.de\Data\Shein-IdelsonMark\Experiments2014\U4_071014\MCRackData\',files)); - -GS=gridSorter(dataObj); -GS.detectionMinimumDetectionInterval=1; -GS=GS.runSorting; \ No newline at end of file diff --git a/spikeSorting/testWavelets.m b/spikeSorting/testWavelets.m deleted file mode 100644 index 30c0d1a..0000000 --- a/spikeSorting/testWavelets.m +++ /dev/null @@ -1,24 +0,0 @@ -s=randn(1,256); %256 elements, Fs = 1Hz. -s=sin(2*pi*10*(0.01:0.01:2.56)); -numlevels = wmaxlev(length(s), 'haar'); -numlevels=4; -[C,L]= wavedec(s, numlevels, 'haar'); -D = detcoef(C,L,'cells'); -[Ea,Ed] = wenergy(C,L); - -T = wptree(2,10,s,'haar'); -plot(T) - -[phi,psi,xval] = wavefun('coif3',8); -plot(xval,psi); - -[Lo_D,Hi_D,Lo_R,Hi_R] = wfilters('coif1') - -subplot(1.3,1,1); -PlotPacketBasis(ijk,abs(wpd).^0.5); -if nargin==2 - fsig = Fs*(0:0.5:(Lt/2))/Lt;%this freq. may not be accurate, should be checked - jumpFactor=round(length(fsig)/10); - set(gca,'YTick',0:jumpFactor:Lt,'YTickLabel',fsig(1:jumpFactor:end)); - ylabel('Freq [Hz]'); -end diff --git a/spikeSorting/test_ks.m b/spikeSorting/test_ks.m deleted file mode 100644 index 2cfcea1..0000000 --- a/spikeSorting/test_ks.m +++ /dev/null @@ -1,21 +0,0 @@ -function [KSmax] = test_ks(x) -% -% Calculates the CDF (expcdf) -[y_expcdf,x_expcdf]=cdfcalc(x); - -% -% The theoretical CDF (theocdf) is assumed to be normal -% with unknown mean and sigma - -zScores = (x_expcdf - mean(x))./std(x); -theocdf = normcdf(zScores , 0 , 1); - -% -% Compute the Maximum distance: max|S(x) - theocdf(x)|. -% - -delta1 = y_expcdf(1:end-1) - theocdf; % Vertical difference at jumps approaching from the LEFT. -delta2 = y_expcdf(2:end) - theocdf; % Vertical difference at jumps approaching from the RIGHT. -deltacdf = abs([delta1 ; delta2]); - -KSmax = max(deltacdf); diff --git a/startup.m b/startup.m index 2d19588..71077ae 100644 --- a/startup.m +++ b/startup.m @@ -2,7 +2,6 @@ % Call Psychtoolbox-3 specific startup function: if exist('PsychStartup'), PsychStartup; end; -addpath(genpath('/home/mark/Documents/MATLAB/npy-matlab')) % for converting to/from Python numpy %fix zoom buttons in figures set(groot,'defaultFigureCreateFcn',@(fig,~)addToolbarExplorationButtons(fig)) @@ -10,3 +9,32 @@ format long g; +%{ +folder='/home/mark/Documents/MATLAB/NET'; +addpath(genpath(folder)); +rmpath(genpath([folder '/.git'])) + +folder='/home/mark/Documents/MATLAB/Psychtoolbox'; +addpath(genpath(folder)); +rmpath(genpath([folder '/.git'])) + +folder='/home/mark/Documents/MATLAB/time-series-viewer'; +addpath(genpath(folder)); +rmpath(genpath([folder '/.git'])) + +folder='/home/mark/Documents/MATLAB/visual-stimulation-gui'; +addpath(genpath(folder)); +rmpath(genpath([folder '/.git'])) + +folder='/home/mark/Documents/MATLAB/npy-matlab'; +addpath(genpath(folder)); +rmpath(genpath([folder '/.git'])) + +folder='/home/mark/Documents/MATLAB/generalAnalysis'; +addpath(genpath(folder)); +rmpath(genpath([folder '/.git'])) + +folder='/home/mark/Documents/MATLAB/Kilosort'; +addpath(genpath(folder)); +rmpath(genpath([folder '/.git'])) +%} \ No newline at end of file diff --git a/tIc_Analysis/ArtifactRemove.asv b/tIc_Analysis/ArtifactRemove.asv deleted file mode 100644 index cb9ff53..0000000 --- a/tIc_Analysis/ArtifactRemove.asv +++ /dev/null @@ -1,27 +0,0 @@ -% [t_clean,ic_clean]=ArtifactRemove(t,ic,Fraction,ArtifWidth); -% Function purpose : removes artifact of 1ms synchoronization in many channels -% -% Recives : t [1/12 ms only] - firing timings -% ic - index chanel -% Fraction - the minmal fraction of neurons with artifact to remove artifact (best with ~0.3) -% ArtifWidth-the maximal delay of a between -% -% Function give back : t_clean [1/12 ms only] - firing timings -% ic_clean - index chanel -% Recomended usage : [t_clean,ic_clean]=ArtifactRemove(t,ic,0.3,3); -% Last updated : 26/03/08 -function [t_clean,ic_clean]=ArtifactRemove(t,ic,Fraction,ArtifWidth); - -%move to resolution where spikes are alligned. -t=round(t./ArtifWidth); -NConsecutiveSpike_Threshold=round(size(ic,2)*Fraction); -t_clean=t;ic_clean=ic; -SortedT=sort(t); -[UniqueTimes LastAppearace n]=unique(SortedT); -ToDelete=UniqueTimes(logical([0 diff(LastAppearace)>NConsecutiveSpike_Threshold])); - -t_clean=t_clean*ArtifWidth; -ToDelete=ToDelete*ArtifWidth; -for i=1:length(ToDelete) - [t_clean,ic_clean]=RemoveSegment(t_clean,ic_clean,ToDelete(i)-(6/ArtifWidth),ToDelete(i)+(6/ArtifWidth)); -end diff --git a/tIc_Analysis/ArtifactRemove.m b/tIc_Analysis/ArtifactRemove.m deleted file mode 100644 index b682bfc..0000000 --- a/tIc_Analysis/ArtifactRemove.m +++ /dev/null @@ -1,27 +0,0 @@ -% [t_clean,ic_clean]=ArtifactRemove(t,ic,Fraction,ArtifWidth); -% Function purpose : removes artifact of 1ms synchoronization in many channels -% -% Recives : t [1/12 ms only] - firing timings -% ic - index chanel -% Fraction - the minmal fraction of neurons with artifact to remove artifact (best with ~0.3) -% ArtifWidth [1/12 ms]-the maximal delay of artifact between different neurons. -% -% Function give back : t_clean [1/12 ms only] - firing timings -% ic_clean - index chanel -% Recomended usage : [t_clean,ic_clean]=ArtifactRemove(t,ic,0.3,3); -% Last updated : 07/01/09 -function [t_clean,ic_clean]=ArtifactRemove(t,ic,Fraction,ArtifWidth); - -%move to resolution where spikes are alligned. -t=round(t./ArtifWidth); -NConsecutiveSpike_Threshold=round(size(ic,2)*Fraction); -t_clean=t;ic_clean=ic; -SortedT=sort(t); -[UniqueTimes LastAppearace n]=unique(SortedT); -ToDelete=UniqueTimes(logical([0 diff(LastAppearace)>NConsecutiveSpike_Threshold])); - -t_clean=t_clean*ArtifWidth; -ToDelete=ToDelete*ArtifWidth; -for i=1:length(ToDelete) - [t_clean,ic_clean]=RemoveSegment(t_clean,ic_clean,ToDelete(i)-(6/ArtifWidth),ToDelete(i)+(6/ArtifWidth)); -end diff --git a/tIc_Analysis/ArtifactRemoveA.asv b/tIc_Analysis/ArtifactRemoveA.asv deleted file mode 100644 index 865ebdc..0000000 --- a/tIc_Analysis/ArtifactRemoveA.asv +++ /dev/null @@ -1,28 +0,0 @@ -% [t_clean,ic_clean]=ArtifactRemove(t,ic,Fraction,ArtifWidth); -% Function purpose : removes artifact of 1ms synchoronization in many channels -% -% Recives : I - activity intensity -% ```t [1 ms only] - firing timings -% ic - index chanel -% Fraction - the minmal fraction of neurons with artifact to remove artifact (best with ~0.3) -% ArtifWidth [1/12 ms]-the maximal delay of artifact between different neurons. -% -% Function give back : t_clean [1/12 ms only] - firing timings -% ic_clean - index chanel -% Recomended usage : [t_clean,ic_clean]=ArtifactRemove(t,ic,0.3,3); -% Last updated : 01/08/09 -function [t_clean,ic_clean]=ArtifactRemoveA(I,t,ic,Fraction,ArtifWidth); - -%move to resolution where spikes are alligned. -t=round(t./ArtifWidth); -NConsecutiveSpike_Threshold=round(size(ic,2)*Fraction); -t_clean=t;ic_clean=ic; -SortedT=sort(t); -[UniqueTimes LastAppearace n]=unique(SortedT); -ToDelete=UniqueTimes(logical([0 diff(LastAppearace)>NConsecutiveSpike_Threshold])); - -t_clean=t_clean*ArtifWidth; -ToDelete=ToDelete*ArtifWidth; -for i=1:length(ToDelete) - [t_clean,ic_clean]=RemoveSegment(t_clean,ic_clean,ToDelete(i)-(6/ArtifWidth),ToDelete(i)+(6/ArtifWidth)); -end diff --git a/tIc_Analysis/ArtifactRemoveA.m b/tIc_Analysis/ArtifactRemoveA.m deleted file mode 100644 index 7722032..0000000 --- a/tIc_Analysis/ArtifactRemoveA.m +++ /dev/null @@ -1,29 +0,0 @@ -% [t_clean,ic_clean]=ArtifactRemove(t,ic,Fraction,ArtifWidth); -% Function purpose : removes artifact of 1ms synchoronization in many channels -% -% Recives : I - activity intensity -% t [ms only] - firing timings -% ic - index chanel -% Fraction - the minmal fraction of neurons with artifact to remove artifact (best with ~0.3) -% ArtifWidth [ms]-the maximal delay of artifact between different neurons. -% -% Function give back : I_clean - activity intensity -% t_clean [ms only] - firing timings -% ic_clean - index chanel -% Recomended usage : [I_clean,t_clean,ic_clean]=ArtifactRemove(I,t,ic,0.3,0.2); -% Last updated : 01/08/09 -function [I_clean, t_clean,ic_clean]=ArtifactRemoveA(I,t,ic,Fraction,ArtifWidth); - -%move to resolution where spikes are alligned. -t=round(t./ArtifWidth); -NConsecutiveSpike_Threshold=round(size(ic,2)*Fraction); -I_clean=I;t_clean=t;ic_clean=ic; -SortedT=sort(t); -[UniqueTimes LastAppearace n]=unique(SortedT); -ToDelete=UniqueTimes(logical([0 diff(LastAppearace)>NConsecutiveSpike_Threshold])); - -t_clean=t_clean*ArtifWidth; -ToDelete=ToDelete*ArtifWidth; -for i=1:length(ToDelete) - [I_clean,t_clean,ic_clean]=RemoveSegmentA(I_clean,t_clean,ic_clean,ToDelete(i)-(6/ArtifWidth),ToDelete(i)+(6/ArtifWidth)); -end diff --git a/tIc_Analysis/Bursts2Spikes.m b/tIc_Analysis/Bursts2Spikes.m deleted file mode 100644 index 0edd699..0000000 --- a/tIc_Analysis/Bursts2Spikes.m +++ /dev/null @@ -1,29 +0,0 @@ -function [IB,tB,icB]=Bursts2Spikes(BP,BI,icA) -%[IB,tB,icB]=Bursts2Spikes(BP,BI,icA); -% Function purpose : Coverts burst timing (Burst peak) and intensity (burst intensity) cell arrays to index channel representation -% -% Function recives : BI [ms]- cell array of the number of clusters length with the total activty intensity of every burst -% BP [ms]- cell array of the number of clusters length with the time (peak location) of every burst -% icA - the indexc channel of the recording -% -% Function give back : IB - total activity intesities of the bursts -% tI [ms] - timings of the bursts -% icB - index channel of the bursts -% -% Last updated : 18/06/10 -icB(3,1)=1; -tB=[]; -IB=[]; -c=0; -for i=1:size(icA,2) - if ~isempty(BP{i}) - c=c+1; - tB=[tB BP{i}]; - IB=[IB BI{i}]; - icB(1:2,c)=icA(1:2,i); - icB(4,c)=icB(3,c)+length(BP{i})-1; - icB(3,c+1)=icB(4,c)+1; - end -end -icB(:,end)=[]; - \ No newline at end of file diff --git a/tIc_Analysis/CheckRefPeriodViolation.m b/tIc_Analysis/CheckRefPeriodViolation.m deleted file mode 100644 index 4037e27..0000000 --- a/tIc_Analysis/CheckRefPeriodViolation.m +++ /dev/null @@ -1,97 +0,0 @@ -function [t_new,ic_new,V_new]=CheckRefPeriodViolation(t,ic,ref,SeeRefHist,V) -% [t_new,ic_new,V_new]=CheckRefPeriodViolation(t,indexchannel,ref,SeeRefHist,V); -% -% Function purpose : 1)Calculates the number of times in which differences between spikes -% are more than ref and plot a histogram of refractory period violations. -% 2)Eliminates violations from data. -% 3)Elliminates NaNs from data -% Function recives : t - firing timings ([ms] -% ic - indexchannel -% ref [ms] - the refracory period for spike elimination from t,ic -% in (defult valure ref=0). -% SeeRefHist='y' to see histograms and 'n' to not see -% V - the voltages of another vector corresponding to t -% Function give back : t_new [ms] - sorted t with no violation of refractory period. -% ic_new - non violating indexchannel -% V_new - non violating V vector -% *indexchannel must be in order in times. -% -% Last updated : 06/01/10 -% Remark: The use of ifexist('V','var') should be optimized - -if nargin==2 - ref=0; -end - -fprintf('Calculating Refractory Peroid violations - set to %f ms \n ---- \n',ref); - -for i=1:size(ic,2) - fails=length(find(diff(sort(t(ic(3,i):ic(4,i))))<=ref)); - tot=length(t(ic(3,i):ic(4,i))); - fprintf('Channel:%d neuron: %d - %d out of %d (%f %%) \n',ic(1,i),ic(2,i),fails,tot,fails/tot*100); -end - - -if (ref~=0 && ~exist('SeeRefHist','var')) - SeeRefHist=input('Do you want to see the violations histograms (y/n) ? ','s'); -else - if ~exist('SeeRefHist','var') - SeeRefHist='n'; - end -end -if SeeRefHist=='y' - for i=1:size(ic,2) - diffs=diff(sort(t(ic(3,i):ic(4,i)))); - small_diffs=diffs(find(diffs<=6)); - if ~isempty(small_diffs) - IntervalHist(i,:)=histc(small_diffs,0:0.25:6); - bar(0:0.25:6,IntervalHist(i,:),'hist'); - title(['channel ', int2str(ic(1,i)),' neuron ', int2str(ic(2,i))]); - pause; - end - end - close; -end - -count=1; -ic_new=ic(1:2,:); -t_new=[]; -V_new=[]; -count=1; -for i=1:size(ic,2) - ic_new(3,i)=count; - if exist('V','var') - channel_V=V(ic(3,i):ic(4,i)); - end - channel_t=t(ic(3,i):ic(4,i)); - if ~issorted(t(ic(3,i):ic(4,i))) - [channel_t P]=sort(channel_t); - disp(['Warning - the input t vector was not sorted in channel: ' num2str(ic_new(1,i))]); - if exist('V','var') - channel_V=channel_V(P); - end - end - if isempty(find(channel_t>=0)) - channel_t=abs(channel_t); - disp(['Warning - the input t vector had non positive values in channel: ' num2str(ic_new(1,i))]); - end - ToDelete=find(diff(channel_t)<=ref)+1; - channel_t(ToDelete)=[]; - if exist('V','var') - channel_V(ToDelete)=[]; - end - NanPlaces=find(isnan(channel_t)); - if ~isempty(NanPlaces) - channel_t(NanPlaces)=[]; %Elliminates NaN from Data - disp(['Warning - the input t vector had NaN values in channel: ' num2str(ic_new(1,i))]); - if exist('V','var') - channel_V(NanPlaces)=[]; %Elliminates NaN from Data - end - end - if exist('V','var') - V_new=[V_new channel_V]; - end - t_new=[t_new channel_t]; - ic_new(4,i)=length(t_new); - count=ic_new(4,i)+1; -end \ No newline at end of file diff --git a/tIc_Analysis/CutASortChannel.asv b/tIc_Analysis/CutASortChannel.asv deleted file mode 100644 index e0c3a32..0000000 --- a/tIc_Analysis/CutASortChannel.asv +++ /dev/null @@ -1,41 +0,0 @@ -% [ANew,tNew,icNew]=CutASortChannel(I,t,ic,tStart,tEnd); -% Function purpose : cuts out a peace of a Activity recording between timings tStart -% if a neuron does not fire in this piece it is deleted -% -% Function recives : I - activity intensity file -% t [ms] - firing timings -% ic - indexc channel -% tStart - starting time [ms] -% tEnd - ending time [ms] -% -% Function give back : tNew [ms]- new firing timings -% icNew - new indexc channel -% INew - new activity intensity -% -% To show paster plot use : plotraster(tNew,icNew); -% Last updated : 14/05/09 - -function [ANew,tNew,icNew]=CutSortChannel(t,ic,tStart,tEnd); - -to_delete=[]; -icNew=zeros(size(ic)); -icNew(1:2,:)=ic(1:2,:); -tNew=[]; -for i=1:size(ic,2), - tChannel=t(ic(3,i):ic(4,i)); - [tCut P]=tChannel(find(tChannel>tStart & tChanneltStart & tChanneltStart & tChanneltStart & tChannelmin(t_tmp2) - fprintf('\nWarning: Both recordings are one same times or the order is swiched\nRemember the first recording chronologically comes first'); - end - ic=[ic [all_channels(1:2,i);(length(t)+1);(length(t)+length([t_tmp1 t_tmp2]))]]; - [t_m,P]=sort([t_tmp1 t_tmp2]); - I_m=[I_tmp1 t_tmp2] - t=[t t_m]; -end \ No newline at end of file diff --git a/tIc_Analysis/MergeSortChannelA.m b/tIc_Analysis/MergeSortChannelA.m deleted file mode 100644 index a669811..0000000 --- a/tIc_Analysis/MergeSortChannelA.m +++ /dev/null @@ -1,43 +0,0 @@ -% [I,t,ic]=MergeSortChannelA(I1,t1,ic1,I2,t2,ic2); -% -% Function purpose : takes two sort channels and merges them into one each -% channel is taken from both recordings sorted and combined to the rest. -% -% Function recives : I1,2 - the intensity of activity -% t1,2 - firing timings of input timings -% ic1,2 - index channel of t1,2 -% -% Function give back : t - firing timings -% ic - index channel -% Last updated : 09/12/09 -function [I,t,ic]=MergeSortChannelA(I1,t1,ic1,I2,t2,ic2) - -channels=sort(unique([ic1(1,:) ic2(1,:)])); - -%Making a vector all channels with all channels and neurons in merged recoding -all_channels=[]; -for i=1:length(channels) - max_neurons=max([length((find(ic1(1,:)==channels(i)))) length((find(ic2(1,:)==channels(i))))]); - all_channels=[all_channels [(ones(1,max_neurons).*channels(i));(1:max_neurons)]]; -end - -%going over on all channels combines both recordings and build ic -t=[]; -I=[]; -ic=[]; -for i=1:size(all_channels,2) - tmp_ind1=find(ic1(1,:)==all_channels(1,i) & ic1(2,:)==all_channels(2,i)); - t_tmp1=t1(ic1(3,tmp_ind1):ic1(4,tmp_ind1)); - I_tmp1=I1(ic1(3,tmp_ind1):ic1(4,tmp_ind1)); - tmp_ind2=find(ic2(1,:)==all_channels(1,i) & ic2(2,:)==all_channels(2,i)); - t_tmp2=t2(ic2(3,tmp_ind2):ic2(4,tmp_ind2)); - I_tmp2=I2(ic2(3,tmp_ind2):ic2(4,tmp_ind2)); - if max(t_tmp1)>min(t_tmp2) - fprintf('\nWarning: Both recordings are one same times or the order is swiched\nRemember the first recording chronologically comes first'); - end - ic=[ic [all_channels(1:2,i);(length(t)+1);(length(t)+length([t_tmp1 t_tmp2]))]]; - [t_m,P]=sort([t_tmp1 t_tmp2]); - t=[t t_m]; - I_m=[I_tmp1 I_tmp2]; - I=[I I_m(P)]; -end \ No newline at end of file diff --git a/tIc_Analysis/ReduceAllNeurons2Channels.m b/tIc_Analysis/ReduceAllNeurons2Channels.m deleted file mode 100644 index 2869bb8..0000000 --- a/tIc_Analysis/ReduceAllNeurons2Channels.m +++ /dev/null @@ -1,23 +0,0 @@ -%[ic]=ReduceAllNeurons2Channels(ic); -% -% Function purpose : Reduces sort channel to one neurons per channel, by -% merging all the neurons at each channel -% -% Function recives : t - firing timings -% ic - index channel -% -% Function give back : t , ic - after reducing to a sigle neurons at each channel -% -% Last updated : 27/12/16 - -function [t_new,ic_new]=ReduceAllNeurons2Channels(t,ic) -%function assumes that ic is sorted -channels=unique(ic(1,:)); -t_new=zeros(size(t)); -for i=1:numel(channels) - pNeurons=find(ic(1,:)==channels(i)); - startIdx=ic(3,pNeurons(1)); - endIdx=ic(4,pNeurons(end)); - ic_new(:,i)=[channels(i);1;startIdx;endIdx]; - t_new(startIdx:endIdx)=sort(t(startIdx:endIdx)); -end diff --git a/tIc_Analysis/ReduceSortChannel.asv b/tIc_Analysis/ReduceSortChannel.asv deleted file mode 100644 index bdf057c..0000000 --- a/tIc_Analysis/ReduceSortChannel.asv +++ /dev/null @@ -1,33 +0,0 @@ -%[t,ic]=ReduceAllNeurons2Channels(t,ic); -% -% Function purpose : Reduces sort channel to one neurons per channel, by -% merging all the neurons at each channel -% -% Function recives : t - firing timings -% ic - index channel -% -% Function give back : t , ic - after reducing to a sigle neurons at each channel -% -% Last updated : 27/12/0 - -function [t,ic]=ReduceSortChannel(t,ic,neurons_not_to_reduce); - -if nargin<3 - neurons_not_to_reduce=[]; -end -channels=unique(ic(1,:)); - -if ~isempty(neurons_not_to_reduce) - for i=1:length(neurons_not_to_reduce) - channels(find(channels==neurons_not_to_reduce(i)))=[]; - end -end - -for i=1:size(channels,2) - neurons=ic(2,find(ic(1,:)==channels(i))); - if size(neurons,2)>1 - for j=neurons(2:end) - [t,ic]=MergeNeurons(t,ic,[channels(i);neurons(1)],[channels(i);j]); - end - end -end diff --git a/tIc_Analysis/ReduceSortChannel.m b/tIc_Analysis/ReduceSortChannel.m deleted file mode 100644 index 47cd28c..0000000 --- a/tIc_Analysis/ReduceSortChannel.m +++ /dev/null @@ -1,35 +0,0 @@ -%[t,ic]=ReduceSortChannel(t,ic,neurons_not_to_reduce); -% -% Function purpose : Reduces sort channel to one neurons per channel, by -% merging all the neurons at each channel -% -% Function recives : t - firing timings -% ic - index channel -% neurons_not_to_reduce - ignores reducing these neurons -% form of vector : [26 56...] . Defult empty -% -% Function give back : t , ic - after reducing to a sigle neurons at each channel -% -% Last updated : 27/12/05 - -function [t,ic]=ReduceSortChannel(t,ic,neurons_not_to_reduce); - -if nargin<3 - neurons_not_to_reduce=[]; -end -channels=unique(ic(1,:)); - -if ~isempty(neurons_not_to_reduce) - for i=1:length(neurons_not_to_reduce) - channels(find(channels==neurons_not_to_reduce(i)))=[]; - end -end - -for i=1:size(channels,2) - neurons=ic(2,find(ic(1,:)==channels(i))); - if size(neurons,2)>1 - for j=neurons(2:end) - [t,ic]=MergeNeurons(t,ic,[channels(i);neurons(1)],[channels(i);j]); - end - end -end diff --git a/tIc_Analysis/RemainNeurons.m b/tIc_Analysis/RemainNeurons.m deleted file mode 100644 index 319a8c3..0000000 --- a/tIc_Analysis/RemainNeurons.m +++ /dev/null @@ -1,53 +0,0 @@ -function [tNew,icNew]=RemainNeurons(t,ic,varargin) -% [t,ic]=RemainNeurons(t,ic,varargin); -% Function purpose : deletes all neurons except the ones mentioned. -% -% Recives : t [units of choice] - firing timings -% ic - index chanel -% varargin - a) the list of channels to be deleted: e.g. [12;1],[15;3],.... -% b) [1XN] vector (assuming every channel has only one neuron) : [2 13 14 16 25...] -% c) [2XN] vector with channel number and neuron number -% -% Function give back : newt [units of choice] - new firing timings -% newic - new index chanel -% Recomended usage : [newt,newic]=RemainNeurons(t,ic,[2;1],[2;3],[2;4]); -% [newt,newic]=RemainNeurons(t,ic,[1 4 23]); -% Last updated : 17/12/14 - -%get neurons to keep -tmp=[]; -if numel(varargin)>0 %checks if there are enough inputs - %if channels are given in a format of [ch;neuron] - if size(varargin{1},1)==2 - if size(varargin{1},2)==1 - for i=1:length(varargin) - tmp(:,i)=varargin{i}; - end - else - tmp=varargin{1}; - end - else - %if channels are given as a vector of channels - for i=1:length(varargin{1}) - p=find(ic(1,:)==varargin{1}(i)); - v=ic(1:2,p); - tmp=[tmp v]; - end - end -else - error('No channels to keep in input'); -end - -%calculate output channels -x=[];counter=0; -nNeuorns=size(tmp,2); -tNew=cell(1,nNeuorns); -icNew=cell(1,nNeuorns); -for i=1:nNeuorns - idx2Keep=find(ic(1,:)==tmp(1,i) & ic(2,:)==tmp(2,i)); - tNew{i}=t(ic(3,idx2Keep):ic(4,idx2Keep)); - icNew{i}=[ic(1:2,idx2Keep);counter+1;counter+numel(tNew{i})]; - counter=counter+numel(tNew{i}); -end -tNew=cell2mat(tNew); -icNew=cell2mat(icNew); \ No newline at end of file diff --git a/tIc_Analysis/RemainNeuronsA.m b/tIc_Analysis/RemainNeuronsA.m deleted file mode 100644 index 59aa775..0000000 --- a/tIc_Analysis/RemainNeuronsA.m +++ /dev/null @@ -1,79 +0,0 @@ -function [I,t,ic]=RemainNeuronsA(I,t,ic,varargin) -% [I,t,ic]=RemainNeuronsA(I,t,ic,varargin); -% Function purpose : deletes all neurons except the ones mentioned. -% -% Recives : I - Activity intensity function -% t [units of choice] - firing timings -% ic - index chanel -% varargin - the list of channels to not be deleted: e.g. [12;1],[15;3],.... -% can be entered also as [1XN] vector (assuming every channel has only one neuron) : [2 13 14 16 25...] -% -% Function give back : newI - new activity intensity function -% newt [units of choice] - new firing timings -% newic - new index chanel -% Recomended usage : [newI,newt,newic]=RemainNeuronsA(I,t,ic,[2;1],[2;3],[2;4]); -% Last updated : 25/01/10 - -if length(varargin)>=1 - if size(varargin{1})==2 - for i=1:length(varargin) - tmp(:,i)=varargin{i}; - end - else - for i=1:length(varargin{1}) - tmp(:,i)=[varargin{1}(i);1]; - end - end -else - error('No channels in input'); -end -x=[]; -for i=1:size(ic,2) - index=find(ic(1,i)==tmp(1,:) & ic(2,i)==tmp(2,:)); - if isempty(index) - x=[x [ic(1,i);ic(2,i)]]; - end -end - -if isempty(varargin), - error('not enough inputs'); -end -%if ~isempty(find(x(1,:)>size(ic,2))), -% error('channel does not exist'); -%end -if size(x,2)>length(ic), - error('too many inputs'); -end - -ic_old=ic; -Idx=[];indexes=[]; -for i=1:size(x,2), - %fprintf('removing neuron [%d;%d]\n',x(1,i),x(2,i)); - indexes(i)=find(ic(1,:)==x(1,i) & ic(2,:)==x(2,i)); - %cut out a peace of t: - Idx=[Idx ic_old(3,indexes(i)):ic_old(4,indexes(i))]; - - %update indexes: - Lt=ic(4,indexes(i))-ic(3,indexes(i))+1; - ic(3,find(ic(3,:)>ic(3,indexes(i))))=ic(3,find(ic(3,:)>ic(3,indexes(i))))-Lt; - ic(4,find(ic(4,:)>ic(4,indexes(i))))=ic(4,find(ic(4,:)>ic(4,indexes(i))))-Lt; - -end - -%remove channels: -ic(:,indexes)=[]; - -t(Idx)=[]; -I(Idx)=[]; - -%%%%%%% To remove neurons that dont fire (instead of the nan assigned to them); -for i=1:size(ic,2) - if isnan(t(ic(3,i))) - I(ic(3,i))=[]; - t(ic(3,i))=[]; - ic(:,i)=NaN; - ic(3:4,(i+1):end)=ic(3:4,(i+1):end)-1; - end -end -ic(:,isnan(ic(1,:)))=[]; - diff --git a/tIc_Analysis/RemainNeurons_old.m b/tIc_Analysis/RemainNeurons_old.m deleted file mode 100644 index d59386d..0000000 --- a/tIc_Analysis/RemainNeurons_old.m +++ /dev/null @@ -1,78 +0,0 @@ -function [t,ic]=RemainNeurons(t,ic,varargin) -% [t,ic]=RemainNeurons(t,ic,varargin); -% Function purpose : deletes all neurons except the ones mentioned. -% -% Recives : t [units of choice] - firing timings -% ic - index chanel -% varargin - the list of channels to not be deleted: e.g. [12;1],[15;3],.... -% can be entered also as [1XN] vector (assuming every channel has only one neuron) : [2 13 14 16 25...] -% -% Function give back : newt [units of choice] - new firing timings -% newic - new index chanel -% Recomended usage : [newt,newic]=RemainNeurons(t,ic,[2;1],[2;3],[2;4]); -% Last updated : 25/01/10 - -tmp=[]; -if length(varargin)>=1 - if size(varargin{1},1)==2 - for i=1:length(varargin) - tmp(:,i)=varargin{i}; - end - else - for i=1:length(varargin{1}) - p=find(ic(1,:)==varargin{1}(i)); - v=ic(1:2,p); - tmp=[tmp v]; - end - end -else - error('No channels in input'); -end -x=[]; -for i=1:size(ic,2) - index=find(ic(1,i)==tmp(1,:) & ic(2,i)==tmp(2,:)); - if isempty(index) - x=[x [ic(1,i);ic(2,i)]]; - end -end - -if isempty(varargin), - error('not enough inputs'); -end -%if ~isempty(find(x(1,:)>size(ic,2))), -% error('channel does not exist'); -%end -if size(x,2)>length(ic), - error('too many inputs'); -end - -ic_old=ic; -Idx=[];indexes=[]; -for i=1:size(x,2), - %fprintf('removing neuron [%d;%d]\n',x(1,i),x(2,i)); - indexes(i)=find(ic(1,:)==x(1,i) & ic(2,:)==x(2,i)); - %cut out a peace of t: - Idx=[Idx ic_old(3,indexes(i)):ic_old(4,indexes(i))]; - - %update indexes: - Lt=ic(4,indexes(i))-ic(3,indexes(i))+1; - ic(3,find(ic(3,:)>ic(3,indexes(i))))=ic(3,find(ic(3,:)>ic(3,indexes(i))))-Lt; - ic(4,find(ic(4,:)>ic(4,indexes(i))))=ic(4,find(ic(4,:)>ic(4,indexes(i))))-Lt; - -end - -%remove channels: -ic(:,indexes)=[]; - -t(Idx)=[]; - -%%%%%%% To remove neurons that dont fire (instead of the nan assigned to them); -for i=1:size(ic,2) - if isnan(t(ic(3,i))) - t(ic(3,i))=[]; - ic(:,i)=NaN; - ic(3:4,(i+1):end)=ic(3:4,(i+1):end)-1; - end -end -ic(:,isnan(ic(1,:)))=[]; - diff --git a/tIc_Analysis/RemoveEmptyChannels.asv b/tIc_Analysis/RemoveEmptyChannels.asv deleted file mode 100644 index e3e73d7..0000000 --- a/tIc_Analysis/RemoveEmptyChannels.asv +++ /dev/null @@ -1,49 +0,0 @@ -function [newT,newic]=RemoveEmptyChannels(t,ic) -%function [newT,newic]=RemoveEmptyChannels(t,ic); -% a function that removes empty channels data - -for i=1:length(ic,2) - if ~(ic(4,i)>=ic(3,i)) - -end - -for i=1:size(x,2), - fprintf('removing neuron [%d;%d]\n',x(1,i),x(2,i)); - index=find(ic(1,:)==x(1,i) & ic(2,:)==x(2,i)); - %cut out a peace of t: - cutT=t(ic(3,index):ic(4,index)); - if ic(3,index)~=1, - tBefore=t(1:ic(3,index)-1); - else - tBefore=[]; - end - if ic(4,index)~=length(t), - tAfter=t(ic(4,index)+1:end); - else - tAfter=[]; - end - t=[tBefore,tAfter]; - %update indexes: - ic(3,find(ic(3,:)>ic(3,index)))=ic(3,find(ic(3,:)>ic(3,index)))-length(cutT); - ic(4,find(ic(4,:)>ic(4,index)))=ic(4,find(ic(4,:)>ic(4,index)))-length(cutT); -end -%remove channels: -for i=1:size(x,2), - indexes(i)=find(ic(1,:)==x(1,i) & ic(2,:)==x(2,i)); -end -ic(:,indexes)=[]; - -newT=t; -newic=ic; - -%%%%%%% To remove neurons that dont fire (instead of the nan assigned to them); -for i=1:size(newic,2) - if isnan(newT(newic(3,i))) - newT(newic(3,i))=[]; - newic(:,i)=NaN; - newic(3:4,(i+1):end)=newic(3:4,(i+1):end)-1; - end -end -newic(:,isnan(newic(1,:)))=[]; - - diff --git a/tIc_Analysis/RemoveEmptyChannels.m b/tIc_Analysis/RemoveEmptyChannels.m deleted file mode 100644 index b550d11..0000000 --- a/tIc_Analysis/RemoveEmptyChannels.m +++ /dev/null @@ -1,57 +0,0 @@ -function [newT,newic]=RemoveEmptyChannels(t,ic) -%function [newT,newic]=RemoveEmptyChannels(t,ic); -% a function that removes empty channels data - -x=[]; -for i=1:size(ic,2) - if ~(ic(4,i)>=ic(3,i)) - x=[x ic([3 4],i)]; - end -end -if isempty(x) - newT=t; - newic=ic; - disp('No empty channels were detected'); - return; -end - -for i=1:size(x,2), - fprintf('removing neuron [%d;%d]\n',x(1,i),x(2,i)); - index=find(ic(1,:)==x(1,i) & ic(2,:)==x(2,i)); - %cut out a peace of t: - cutT=t(ic(3,index):ic(4,index)); - if ic(3,index)~=1, - tBefore=t(1:ic(3,index)-1); - else - tBefore=[]; - end - if ic(4,index)~=length(t), - tAfter=t(ic(4,index)+1:end); - else - tAfter=[]; - end - t=[tBefore,tAfter]; - %update indexes: - ic(3,find(ic(3,:)>ic(3,index)))=ic(3,find(ic(3,:)>ic(3,index)))-length(cutT); - ic(4,find(ic(4,:)>ic(4,index)))=ic(4,find(ic(4,:)>ic(4,index)))-length(cutT); -end -%remove channels: -for i=1:size(x,2), - indexes(i)=find(ic(1,:)==x(1,i) & ic(2,:)==x(2,i)); -end -ic(:,indexes)=[]; - -newT=t; -newic=ic; - -%%%%%%% To remove neurons that dont fire (instead of the nan assigned to them); -for i=1:size(newic,2) - if isnan(newT(newic(3,i))) - newT(newic(3,i))=[]; - newic(:,i)=NaN; - newic(3:4,(i+1):end)=newic(3:4,(i+1):end)-1; - end -end -newic(:,isnan(newic(1,:)))=[]; - - diff --git a/tIc_Analysis/RemoveSegment.asv b/tIc_Analysis/RemoveSegment.asv deleted file mode 100644 index fab7832..0000000 --- a/tIc_Analysis/RemoveSegment.asv +++ /dev/null @@ -1,32 +0,0 @@ -% [INew,tNew,icNew]=RemoveSegment(I,t,ic,tStart,tEnd); -% -% Function purpose : removes a time segment from t and sort channel -% -% Function recives : I - activity intensity -% t - firing timings -% ic - index channel -% tStart - begining of segment time -% tEnd - ending of segment time -% -% Function give back : tNew - new firing timings -% icNew - new index channel -% Last updated : 28/06/05 - -function [tNew,icNew]=RemoveSegment(t,ic,tStart,tEnd); - -icNew=zeros(size(ic)); -icNew(1:2,:)=ic(1:2,:); -tNew=[]; -for i=1:length(ic), - tChannel=t(ic(3,i):ic(4,i)); - tChannel(find(tChannel>tStart & tChanneltStart & tChanneltStart & tChanneltStart & tChannel(i-1)*hours*3600*12000 & t(i-1)*hours*3600*12000 & t= count - fprintf('channel %d neuron %d -',ic(1,count),ic(2,count)); - answ=input(' ','s'); - if answ=='a' - a=[a ic(1:2,count)]; - count=count+1; - else - if answ=='b' - b=[b ic(1:2,count)]; - count=count+1; - else - fprintf('\n Your answer is not a or b,try again ! \n'); - end - end - end -else - for i=1:size(ic,2) - if ~isempty(find(side_a==ic(1,i))) - a=[a ic(1:2,i)]; - else - b=[b ic(1:2,i)]; - end - end -end -if outputMessages - fprintf('Removing the Neurons from A:\n'); -end -for i=1:size(b,2) - [t_a,ic_a]=removeNeurons(t_a,ic_a,b(:,i)); -end -if outputMessages - fprintf('Removing the Neurons from B:\n'); -end -for i=1:size(a,2) - [t_b,ic_b]=removeNeurons(t_b,ic_b,a(:,i)); -end - diff --git a/tIc_Analysis/Separate_networks.asv b/tIc_Analysis/Separate_networks.asv deleted file mode 100644 index 541d045..0000000 --- a/tIc_Analysis/Separate_networks.asv +++ /dev/null @@ -1,16 +0,0 @@ -% [ic_sep]=Separate_ic(ic); -function [ic_sep]=Separate_ic(ic); - -side_a=[1 2 3 7 8 9 10 15 16 17 18 23 24 25 26 31 32 33 34 39 40 41 42 47 48 49 50 55 56 57]; -side_b=[4 5 6 11 12 13 14 19 20 21 22 27 28 29 30 35 36 37 38 43 44 45 46 51 52 53 54 58 59 60]; - -place=[]; -for i=1:size(ic,2) - if size(find(side_a==ic(1,i)),2)~=0 - place=[place 1]; - else - place=[place 2]; - end -end -[sorted,order]=sort(place); -ic_sep=ic(:,order); diff --git a/tIc_Analysis/Separate_networks.m b/tIc_Analysis/Separate_networks.m deleted file mode 100644 index d932992..0000000 --- a/tIc_Analysis/Separate_networks.m +++ /dev/null @@ -1,16 +0,0 @@ -% [ic_sep]=Separate_networks(ic); -function [ic_sep]=Separate_networks(ic); - -side_a=[1 2 3 7 8 9 10 15 16 17 18 23 24 25 26 31 32 33 34 39 40 41 42 47 48 49 50 55 56 57]; -side_b=[4 5 6 11 12 13 14 19 20 21 22 27 28 29 30 35 36 37 38 43 44 45 46 51 52 53 54 58 59 60]; - -place=[]; -for i=1:size(ic,2) - if size(find(side_a==ic(1,i)),2)~=0 - place=[place 1]; - else - place=[place 2]; - end -end -[sorted,order]=sort(place); -ic_sep=ic(:,order); diff --git a/tIc_Analysis/addNeurons.m b/tIc_Analysis/addNeurons.m deleted file mode 100644 index 0077c28..0000000 --- a/tIc_Analysis/addNeurons.m +++ /dev/null @@ -1,38 +0,0 @@ -%[t_new,ic_new]=addNeurons(t,ic,varargin); -% -% Function purpose : adds neurons to t and ic -% -% Function recives : t - firing timings -% ic - index channel -% varargin - [ch1;neu1],t1,[ch2;neu2],t2,... -% -% Function give back : t_new , ic_new - t and ic after merging neurons -% -% Last updated : 13/07/14 - -function [t_new,ic_new]=MergeNeurons(t,ic,varargin) -%sort neurons in ascending order -times=varargin(2:2:end); -chNames=cell2mat(varargin(1:2:end)); - -nNeurons=size(chNames,2); -% get the spike times of the merged channels and remove them from the original time list (t_new) -t_new=t; -ic_new=ic; -for i=1:nNeurons - nNewSpikes=numel(times{i}); - pCh=find(ic_new(1,:)==chNames(1,i)); - if isempty(pCh) - pInIc=find(ic_new(1,:)>=chNames(1,i),1,'first'); - else - neuronsInCh=ic_new(2,pCh); - [~,pSort]=sort([neuronsInCh chNames(2,i)]); - pInIc=pCh(1)+find(pSort==numel(neuronsInCh)+1)-1; - end - pInt=ic_new(3,pInIc); - t_new=[t_new(1:(pInt-1)) times{i} t_new(pInt:end)]; - ic_new(3:4,pInIc:end)=ic_new(3:4,pInIc:end)+nNewSpikes; - ic_new=[ic_new(:,1:pInIc-1),... - [chNames([1 2],i);pInt;pInt+nNewSpikes-1],... - ic_new(:,pInIc:end)]; -end diff --git a/tIc_Analysis/addNeuronsA.m b/tIc_Analysis/addNeuronsA.m deleted file mode 100644 index 7c58ffc..0000000 --- a/tIc_Analysis/addNeuronsA.m +++ /dev/null @@ -1,41 +0,0 @@ -%[I_new,t_new,ic_new]=addNeuronsA(I,t,ic,varargin); -% -% Function purpose : adds neurons to t and ic -% -% Function recives : t - firing timings -% ic - index channel -% varargin - [ch1;neu1],t1,[ch2;neu2],t2,... -% -% Function give back : t_new , ic_new - t and ic after merging neurons -% -% Last updated : 13/07/14 - -function [I_new,t_new,ic_new]=addNeuronsA(I,t,ic,varargin) -%sort neurons in ascending order -times=varargin(2:3:end); -intensities=varargin(3:3:end); -chNames=cell2mat(varargin(1:3:end)); - -nNeurons=size(chNames,2); -% get the spike times of the merged channels and remove them from the original time list (t_new) -t_new=t; -ic_new=ic; -I_new=I; -for i=1:nNeurons - nNewSpikes=numel(times{i}); - pCh=find(ic_new(1,:)==chNames(1,i)); - if isempty(pCh) - pInIc=find(ic_new(1,:)>=chNames(1,i),1,'first'); - else - neuronsInCh=ic_new(2,pCh); - [~,pSort]=sort([neuronsInCh chNames(2,i)]); - pInIc=pCh(1)+find(pSort==numel(neuronsInCh)+1)-1; - end - pInt=ic_new(3,pInIc); - t_new=[t_new(1:(pInt-1)) times{i} t_new(pInt:end)]; - I_new=[I_new(1:(pInt-1)) intensities{i} I_new(pInt:end)]; - ic_new(3:4,pInIc:end)=ic_new(3:4,pInIc:end)+nNewSpikes; - ic_new=[ic_new(:,1:pInIc-1),... - [chNames([1 2],i);pInt;pInt+nNewSpikes-1],... - ic_new(:,pInIc:end)]; -end diff --git a/tIc_Analysis/cell2tIc.m b/tIc_Analysis/cell2tIc.m deleted file mode 100644 index f9770ce..0000000 --- a/tIc_Analysis/cell2tIc.m +++ /dev/null @@ -1,11 +0,0 @@ -function [t,ic]=cell2tIc(c,neuronNames) -% [t,ic]=cellArray2tIc(c,neuronNames) -% Convert cell array with neuron names to t+ic format -if numel(c)~=size(neuronNames,2) - error('Size of input vectors does not match'); -end -nSpk=cellfun(@(x) numel(x),c); -cumSpk=cumsum(nSpk); -ic=[neuronNames;[1 cumSpk(1:end-1)+1];cumSpk]; -t=cell2mat(c); -t=t(:)'; \ No newline at end of file diff --git a/tIc_Analysis/eventLocator.m b/tIc_Analysis/eventLocator.m deleted file mode 100644 index e9d6527..0000000 --- a/tIc_Analysis/eventLocator.m +++ /dev/null @@ -1,187 +0,0 @@ -%[BS,BP,BE,BI,BCM]=eventLocator(I,t,ic,minSBInterval,varargin) -% Function purpose : Removes single spikes from CAI data by removing isolated spikes with low activity around them -% -% Function recives : I - activity intensity file (if spiking data, leave empty) -% t [ms] - firing times -% ic - index channel -% minSBInterval - collapses SB with intervals less than minSBInterval into one SB -% varargin: 'property name',property value (see list of properties in default values) -% sigma=5; %gaussian width in convolution -% smoothFuncNBins=; %number of samples in the gaussian function for convolution -% res=10; % resolution of SB detection -% stdThresh=2; %the threshold for rejecting noise in the floating median filter -% medianWindow=10000; %[ms] the window for floating median -% plotResults=0; %whether to plot the results of event detection -% mergeAccordingToEventCenter=0; %whether to merge events according to distances between event centers of event edges -% -% Function give back : BS [ms] - the start times of SBs -% BP [ms] - the peak times of SBs -% BE [ms] - the end times of SBs -% BI [input votage units] - the total intensity of the SB -% BCM [ms] - the time of the event center of mass -% -% Last updated : 01/08/21 -function [BS,BP,BE,BI,BCM,Act,mAct,sAct]=eventLocator(I,t,ic,minSBInterval,varargin) -%default variables -sigma=5; %[bins of res] gaussian width in convolution -smoothFuncNBins=[]; %number of samples in the gaussian function for convolution, if empty takes 6*sigma+1 -res=10; % [ms] resolution of SB detection -addToSides=500; %[ms] widening of burst period in ms. -stdThresh=2; %the threshold for rejecting noise in the floating median filter -medianWindow=10000; %[ms] the window for floating median -plotResults=0; %whether to plot the results of event detection -mergeAccordingToEventCenter=0; %whether to merge events according to distances between event centers of event edges -refineDetection=true; %reextract events and calculate exact edges -constantThreshold=0; %a non floating threshold below which events are not detected. - -warning('Function is under development, notice that the two inputs do not influence the result'); -%print out default arguments and values if no inputs are given -if nargin==0 - defaultArguments=who; - for i=1:numel(defaultArguments) - eval(['defaultArgumentValue=' defaultArguments{i} ';']); - if numel(defaultArgumentValue)==1 - disp([defaultArguments{i} ' = ' num2str(defaultArgumentValue)]); - else - fprintf([defaultArguments{i} ' = ']); - disp(defaultArgumentValue); - end - end - return; -end - -%sanity checks -BP=[];BS=[];BE=[];BI=[]; -if isempty(t) || isempty(ic) - BP=[];BS=[];BE=[];BI=[];BCM=[]; - disp('One of the input vectors is empty'); - return; -end -if any(isnan(t)) || any(isnan(I)) - BP=[];BS=[];BE=[];BI=[];BCM=[]; - disp('Input arrays have NaNs'); - return; -end - -%Collects all options -for i=1:2:length(varargin) - eval([varargin{i} '=' 'varargin{i+1};']) -end - -if isempty(smoothFuncNBins) - smoothFuncNBins=sigma*6+1; -end -addToSidesRes=round(addToSides/res); -medianWindowRes=round(medianWindow/res); - -SmoothFunc=fspecial('gaussian', [1 smoothFuncNBins], sigma); -LSmoothFunc=length(SmoothFunc); -SmoothFuncOffset=ceil(LSmoothFunc/2); - -NChannels=size(ic,2); - -MaxT=max(t); - -if ~isempty(I) - [t,p]=sort(t); - I=I(p); - ic=[1;1;1;numel(t)]; - clear p; - Act=squeeze(BuildBurstMatrixA(ic,round(t/res),I,0,round(MaxT/res)))'; -else - [t]=sort(t); - ic=[1;1;1;numel(t)]; - Act=squeeze(BuildBurstMatrix(ic,round(t/res),0,round(MaxT/res)))'; -end -Act=convn(Act,SmoothFunc,'same'); -%these median filters are the slowest part of the function to increase speed reduce medianWindowRes or increase res -mAct = fastmedfilt1d(Act,medianWindowRes)'; -sAct = fastmedfilt1d(abs(Act-mAct),medianWindowRes)' / 0.6745; -nSamples=numel(Act); - -ActBinary=Act>(mAct+stdThresh*sAct) & Act>=constantThreshold; -ActBinary([1:round(medianWindowRes/2) end+1-round(medianWindowRes/2):end])=false; - -BS=find(diff([0 ActBinary])>0);%SB beginnings -BE=find(diff([ActBinary 0])<0);%SB endings -BM=(BS+BE)/2;%SB middles - -if isempty(BS) || isempty(BE), - fprintf('\nChannel %d %d has only single spikes and consequently was not analyzed',ic(1:2,i)); - BI=[]; - BP=[]; -else - %Collapse SBs with intervals less than minSBInterval into one SB (decision is made according to distances between peaks) - %decision can also be diverted to distances between endings and beginnings - M=round(minSBInterval/res); - if mergeAccordingToEventCenter - Changes=diff(BM); - else %merges according to start and end points - Changes=BS(2:end)-BE(1:end-1); - end - Back=[2*M Changes(1:end)]; - Forward=[Changes(1:end) 2*M]; - BBeginners=(Back>=M & Forward=M); - %BMiddles=(Back=M & Forward>=M); - - BS=BS((BRegular | BBeginners)>0); % Marks the beginning of a SBE sequence - BE=BE((BRegular | BEnders)>0); % Marks the end of the SBE sequence - NSBs=length(BS); - - %separate the first and last events to prevent checking limit cases - if refineDetection - disp('Calculating refined detection on individual events'); - for j=1:NSBs - pBS=(BS(j)-addToSidesRes):BS(j); - pBS(pBS<=0)=1; - pBE=BE(j):(BE(j)+addToSidesRes); - pBE(pBE>nSamples)=nSamples; - - BS(j)=BS(j)-addToSidesRes+find([0 Act(pBS)]<=[1 mAct(pBS)],1,'last'); - BE(j)=BE(j)+find([Act(pBE) 0]<=[mAct(pBE) 1],1,'first'); - - pTmp=BS(j):BE(j); - tmpEvent=Act(pTmp); - BI(j)=sum(tmpEvent); - BCM(j)=round(sum(tmpEvent.*pTmp)/sum(tmpEvent)); %calculate center of mass - [~,pPeak]=max(tmpEvent); %calculate center of mass - BP(j)=pTmp(pPeak); - end - BS(BS<=0)=1; - BE(BE>=nSamples)=nSamples; - else - BCM=[]; - BP=(BS+BE)/2;%SB middles - end - if plotResults - figure('position',[50 100 1800 800]); - subplot(2,2,1:2); - plot((1:numel(Act))*res/1000,Act);hold on; - plot((1:numel(Act))*res/1000,mAct,'c'); - plot((1:numel(Act))*res/1000,mAct+stdThresh*sAct,'m'); - plot(BS*res/1000,Act(BS),'og','linewidth',2); - plot(BP*res/1000,Act(BP),'ok','linewidth',2); - plot(BE*res/1000,Act(BE),'or','linewidth',2); - xlabel('Time [s]'); - ylabel('Activity intensity'); - l=legend('AI','median','MAD','start','CM','end'); - set(l,'box','off'); - - binsInHist=max(10,numel(BS)/30); - subplot(2,2,3); - hist(BI,binsInHist); - xlabel('Event intensity'); - ylabel('number of events'); - - subplot(2,2,4); - hist((BE-BS)*res,binsInHist); - xlabel('Event duration [ms]'); - ylabel('number of events'); - end - BS=BS*res-res/2; - BE=BE*res+res/2; - BP=BP*res-res/2; - BCM=BCM*res-res/2; -end diff --git a/tIc_Analysis/flipnameNeurons.m b/tIc_Analysis/flipnameNeurons.m deleted file mode 100644 index 1cd8a96..0000000 --- a/tIc_Analysis/flipnameNeurons.m +++ /dev/null @@ -1,23 +0,0 @@ -function [newIndexchannel]=flipnameNeurons(indexchannel,varargin); -%function [newIndexchannel]=flipnameNeurons(indexchannel,varargin); -% a function that flip names in indexchannel. takes varagin{2:end} and -% flips with varargin{1} -%example: [newIndexchannel]=flipnameNeurons(indexchannel,[2;1],[2;3]) - - -for i=1:length(varargin) - x(:,i)=varargin{i}; -end - -if length(x)~=2, - error('improper inputs'); -end - -fprintf('flip names of neurons [%d;%d],[%d,%d]\n',x(1,1),x(2,1),x(1,2),x(2,2)); -channel1=find(indexchannel(1,:)==x(1,1) & indexchannel(2,:)==x(2,1)); -channel2=find(indexchannel(1,:)==x(1,2) & indexchannel(2,:)==x(2,2)); -indexchannel(1:2,channel1)=x(:,2); -indexchannel(1:2,channel2)=x(:,1); - -newIndexchannel=indexchannel; - - diff --git a/tIc_Analysis/mergesortchannel.m b/tIc_Analysis/mergesortchannel.m deleted file mode 100644 index 336ea5f..0000000 --- a/tIc_Analysis/mergesortchannel.m +++ /dev/null @@ -1,36 +0,0 @@ -function [t,indexchannel]=MergeSortChannel(t1,ic1,t2,ic2); -% [t,indexchannel]=MergeSortChannel(t1,ic1,t2,ic2); -% -% Function purpose : takes two sort chanels and merges them into one each -% channel is taken from both recordings sorted and combined to the rest. -% -% Function recives : t1,2 - firing timings of input timings -% ic1,2 - index channel of t1,2 -% -% Function give back : t - firing timings -% indexchannel - index channel -% Last updated : 07/06/05 - -channels=sort(unique([ic1(1,:) ic2(1,:)])); - -%Making a vector all channels with all channels and neurons in merged recoding -all_channels=[]; -for i=1:length(channels) - max_neurons=max([length((find(ic1(1,:)==channels(i)))) length((find(ic2(1,:)==channels(i))))]); - all_channels=[all_channels [(ones(1,max_neurons).*channels(i));(1:max_neurons)]]; -end - -%going over on all channels combines both recordings and build indexchannel -t=[]; -indexchannel=[]; -for i=1:size(all_channels,2) - tmp_ind1=find(ic1(1,:)==all_channels(1,i) & ic1(2,:)==all_channels(2,i)); - t_tmp1=t1(ic1(3,tmp_ind1):ic1(4,tmp_ind1)); - tmp_ind2=find(ic2(1,:)==all_channels(1,i) & ic2(2,:)==all_channels(2,i)); - t_tmp2=t2(ic2(3,tmp_ind2):ic2(4,tmp_ind2)); - if max(t_tmp1)>min(t_tmp2) - fprintf('\nBoth recordings are one same times or the order is swiched\nRemember the first recording chronologically comes first'); - end - indexchannel=[indexchannel [all_channels(1:2,i);(length(t)+1);(length(t)+length([t_tmp1 t_tmp2]))]]; - t=[t sort([t_tmp1 t_tmp2])]; -end \ No newline at end of file diff --git a/tIc_Analysis/reduceNeurons.m b/tIc_Analysis/reduceNeurons.m deleted file mode 100644 index a65f0a6..0000000 --- a/tIc_Analysis/reduceNeurons.m +++ /dev/null @@ -1,65 +0,0 @@ -function [newT,newIndexchannel]=reduceNeurons(t,indexchannel,varargin); -%function [newT,newIndexchannel]=reduceNeurons(t,indexchannel,varargin); -% a function that reduce size of indexchannel. takes varagin{2:end} and -% adds them to varargin{1} -%example: [newT,newIndexchannel]=reduceNeurons(t,indexchannel,[2;1],[2;3],[2;4]) - -%takes neurons [2;3] and [2;4] in indexchannel and adds them to index [2;1]. - -for i=1:length(varargin) - x(:,i)=varargin{i}; -end - -if length(x)<2, - error('not enough inputs'); -end -%if ~isempty(find(x(1,:)>length(indexchannel))), -% error('channel does not exist'); -%end -if length(x)>length(indexchannel), - error('too many inputs'); -end - -channel=find(indexchannel(1,:)==x(1,1) & indexchannel(2,:)==x(2,1)); -for i=2:length(x), - fprintf('reducing neuron [%d;%d] into neuron [%d;%d]\n',x(1,i),x(2,i),x(1,1),x(2,1)); - index=find(indexchannel(1,:)==x(1,i) & indexchannel(2,:)==x(2,i)); - %cut out a peace of t: - cutT=t(indexchannel(3,index):indexchannel(4,index)); - if indexchannel(3,index)~=1, - tBefore=t(1:indexchannel(3,index)-1); - else - tBefore=[]; - end - if indexchannel(4,index)~=length(t), - tAfter=t(indexchannel(4,index)+1:end); - else - tAfter=[]; - end - t=[tBefore,tAfter]; - %update indexes: - indexchannel(3,find(indexchannel(3,:)>indexchannel(3,index)))=indexchannel(3,find(indexchannel(3,:)>indexchannel(3,index)))-length(cutT); - indexchannel(4,find(indexchannel(4,:)>indexchannel(4,index)))=indexchannel(4,find(indexchannel(4,:)>indexchannel(4,index)))-length(cutT); - %and paste it in a new location: - tBefore=t(1:indexchannel(4,channel)); - if indexchannel(3,channel)~=length(t), - tAfter=t(indexchannel(4,channel)+1:end); - else - tAfter=[]; - end - t=[tBefore,cutT,tAfter]; - %update indexes: - indexchannel(3,find(indexchannel(3,:)>indexchannel(3,channel)))=indexchannel(3,find(indexchannel(3,:)>indexchannel(3,channel)))+length(cutT); - indexchannel(4,find(indexchannel(4,:)>indexchannel(4,channel)))=indexchannel(4,find(indexchannel(4,:)>indexchannel(4,channel)))+length(cutT); - indexchannel(4,channel)=indexchannel(4,channel)+length(cutT); -end - -%remove channels: -for i=2:length(x), - indexes(i-1)=find(indexchannel(1,:)==x(1,i) & indexchannel(2,:)==x(2,i)); -end -indexchannel(:,indexes)=[]; - -newT=t; -newIndexchannel=indexchannel; - - diff --git a/tIc_Analysis/removeInactiveChannels.m b/tIc_Analysis/removeInactiveChannels.m deleted file mode 100644 index a591644..0000000 --- a/tIc_Analysis/removeInactiveChannels.m +++ /dev/null @@ -1,35 +0,0 @@ -% [channelsToRemove,channelEventFraction]=removeInactiveChannels(t,ic,res,minimalEventFraction,varargin); -% Function purpose : Finds inactive neurons in a recording -% -% Recives :t [ms] - firing timings -% ic - index chanel -% res [ms] - resolution of finding bursts (100); -% minimalEventFraction - the minimal fraction of time the channel was active. Below this fraction the channel is removed -% varargin - 'Plot' - if entered the results are plotted -% -% Function give back : channelsToRemove - the channel with activity below the predefined threshold -% channelEventFraction - the fraction of time every channel was active -% Recomended usage : [channelsToRemove]=removeInactiveChannels(t,ic,res,5e-5,'Plot'); -% Last updated : 20/09/10 -function [channelsToRemove,channelEventFraction]=removeInactiveChannels(t,ic,res,minimalEventFraction,varargin) -for i=1:nargin-4 - eval([varargin{i} '=1;']); -end -NChannels=size(ic,2); -Duration=max(t)-min(t); -minimalEventNumber=(minimalEventFraction*res)/Duration; -for i=1:NChannels - channelEventFraction(i)=(ic(4,i)-ic(3,i))*res/Duration; -end -if exist('Plot','var') - figure;hold on; - bar(channelEventFraction) - set(gca,'XTick',1:NChannels); - set(gca,'XTickLabel',ic(1,:),'FontSize',8); - xl=xlim; - line([xl],[minimalEventFraction minimalEventFraction],'color','r'); - hold off; - ylim([0 minimalEventFraction*3]); -end -channelsToRemove=ic(1:2,channelEventFraction0 %checks if there are enough inputs - %if channels are given in a format of [ch;neuron] - if size(varargin{1},1)==2 - if size(varargin{1},2)==1 - for i=1:length(varargin) - x(:,i)=varargin{i}; - end - else - x=varargin{1}; - end - else - %if channels are given as a vector of channels - for i=1:length(varargin{1}) - p=find(ic(1,:)==varargin{1}(i)); - v=ic(1:2,p); - x=[x v]; - end - end -else - error('No channels to keep in input'); -end -x(3,:)=0; - - -if isempty(varargin{1}), - disp('not enough inputs!!!!!!!!!!'); - newt=t;newic=ic; - return; -end -%if ~isempty(find(x(1,:)>size(ic,2))), -% error('channel does not exist'); -%end -if size(x,2)>length(ic), - error('too many inputs'); -end - -for i=1:size(x,2), - index=find(ic(1,:)==x(1,i) & ic(2,:)==x(2,i)); - if ~isempty(index) - if outputMessages - fprintf('removing neuron [%d;%d]\n',x(1,i),x(2,i)); - end - %cut out a peace of t: - cutt=t(ic(3,index):ic(4,index)); - if ic(3,index)~=1, - tBefore=t(1:ic(3,index)-1); - else - tBefore=[]; - end - if ic(4,index)~=length(t), - tAfter=t(ic(4,index)+1:end); - else - tAfter=[]; - end - t=[tBefore,tAfter]; - %update indexes: - ic(3,find(ic(3,:)>ic(3,index)))=ic(3,find(ic(3,:)>ic(3,index)))-length(cutt); - ic(4,find(ic(4,:)>ic(4,index)))=ic(4,find(ic(4,:)>ic(4,index)))-length(cutt); - else - if outputMessages - fprintf('Neuron [%d;%d] was not removed since it does not exist\n',x(1,i),x(2,i)); - end - x(3,i)=1; - end -end -%remove channels: -x(:,x(3,:)==1)=[]; -for i=1:size(x,2), - indexes(i)=find(ic(1,:)==x(1,i) & ic(2,:)==x(2,i)); -end -ic(:,indexes)=[]; - -newt=t; -newic=ic; - -%%%%%%% To remove neurons that dont fire (instead of the nan assigned to them); -for i=1:size(newic,2) - if isnan(newt(newic(3,i))) - newt(newic(3,i))=[]; - newic(:,i)=NaN; - newic(3:4,(i+1):end)=newic(3:4,(i+1):end)-1; - end -end -newic(:,isnan(newic(1,:)))=[]; \ No newline at end of file diff --git a/tIc_Analysis/removeNeuronsA.m b/tIc_Analysis/removeNeuronsA.m deleted file mode 100644 index 461bc54..0000000 --- a/tIc_Analysis/removeNeuronsA.m +++ /dev/null @@ -1,94 +0,0 @@ -function [newI,newt,newic]=RemoveNeuronsA(I,t,ic,varargin) -% [newI,newt,newic]=RemoveNeuronsA(I,t,ic,varargin); -% Function purpose : deletes all neurons except the ones mentioned. -% -% Recives : I - Activity intensity function -% t [units of choice] - firing timings -% ic - index chanel -% varargin - the list of channels to be deleted: e.g. [12;1],[15;3],.... -% can be entered also as [1XN] vector (assuming every channel has only one neuron) : [2 13 14 16 25...] -% -% Function give back : newI - new activity intensity function -% newt [units of choice] - new firing timings -% newic - new index chanel -% Recomended usage : [newI,newt,newic]=RemoveNeuronsA(I,t,ic,[2;1],[2;3],[2;4]); -% Last updated : 16/09/09 - -if length(varargin)>=1 - if size(varargin{1},1)==2 - for i=1:length(varargin) - x(:,i)=varargin{i}; - end - else - for i=1:length(varargin{1}) - x(:,i)=[varargin{1}(i);1]; - end - end -end -x(3,:)=0; - -if isempty(varargin{1}), - disp('not enough inputs!!!!!!!!!!'); - newI=I;newt=t;,newic=ic; - return; -end -%if ~isempty(find(x(1,:)>size(ic,2))), -% error('channel does not exist'); -%end -if size(x,2)>length(ic), - error('too many inputs'); -end - -for i=1:size(x,2), - index=find(ic(1,:)==x(1,i) & ic(2,:)==x(2,i)); - if ~isempty(index) - fprintf('removing neuron [%d;%d]\n',x(1,i),x(2,i)); - %cut out a peace of t: - cutt=t(ic(3,index):ic(4,index)); - if ic(3,index)~=1, - tBefore=t(1:ic(3,index)-1); - IBefore=I(1:ic(3,index)-1); - else - tBefore=[]; - IBefore=[]; - end - if ic(4,index)~=length(t), - tAfter=t(ic(4,index)+1:end); - IAfter=I(ic(4,index)+1:end); - else - tAfter=[]; - IAfter=[]; - end - t=[tBefore,tAfter]; - I=[IBefore,IAfter]; - %update indexes: - ic(3,find(ic(3,:)>ic(3,index)))=ic(3,find(ic(3,:)>ic(3,index)))-length(cutt); - ic(4,find(ic(4,:)>ic(4,index)))=ic(4,find(ic(4,:)>ic(4,index)))-length(cutt); - else - fprintf('Neuron [%d;%d] was not removed since it does not exist\n',x(1,i),x(2,i)); - x(3,i)=1; - end -end -%remove channels: -x(:,x(3,:)==1)=[]; -for i=1:size(x,2), - indexes(i)=find(ic(1,:)==x(1,i) & ic(2,:)==x(2,i)); -end -ic(:,indexes)=[]; - -newt=t; -newI=I; -newic=ic; - -%%%%%%% To remove neurons that dont fire (instead of the nan assigned to them); -for i=1:size(newic,2) - if isnan(newt(newic(3,i))) - newI(newic(3,i))=[]; - newt(newic(3,i))=[]; - newic(:,i)=NaN; - newic(3:4,(i+1):end)=newic(3:4,(i+1):end)-1; - end -end -newic(:,isnan(newic(1,:)))=[]; - - diff --git a/tIc_Analysis/renameNeuron.m b/tIc_Analysis/renameNeuron.m deleted file mode 100644 index 54937d1..0000000 --- a/tIc_Analysis/renameNeuron.m +++ /dev/null @@ -1,21 +0,0 @@ -function [newIndexchannel]=renameNeuron(indexchannel,varargin); -%function [newIndexchannel]=renameNeuron(indexchannel,oldname,newname); -% a function that reduce size of indexchannel. takes varagin{2:end} and -% adds them to varargin{1} -%example: [newT,newIndexchannel]=reduceNeurons(t,indexchannel,[2;1],[2;3],[2;4]) - -%takes neurons [2;3] and [2;4] in indexchannel and adds them to index [2;1]. - -for i=1:length(varargin) - x(:,i)=varargin{i}; -end - -if length(x)~=2, - error('improper inputs'); -end - -fprintf('rename neuron [%d;%d] to [%d,%d]\n',x(1,1),x(2,1),x(1,2),x(2,2)); -channel=find(indexchannel(1,:)==x(1,1) & indexchannel(2,:)==x(2,1)); -indexchannel(1:2,channel)=x(:,2); -newIndexchannel=indexchannel; - - diff --git a/tIc_Analysis/reorderIndexChannel.m b/tIc_Analysis/reorderIndexChannel.m deleted file mode 100644 index b02b772..0000000 --- a/tIc_Analysis/reorderIndexChannel.m +++ /dev/null @@ -1,26 +0,0 @@ -%[tNew,icNew]=reorderIndexChannel(t,ic) -% Function purpose : order channels in t,ic in increasing order -% -% Function recives : t [ms] - firing timings -% ic - indexc channel -% -% Function give back : tNew [ms] - firing timings after ordering -% icNew - firing timings after ordering -% -% Last updated : 27/06/12 -function [tNew,icNew]=reorderIndexChannel(t,ic) - -tNew=[];icNew=[]; -ch=unique(ic(1,:)); -c=0; -for i=1:numel(ch) - p=find(ic(1,:)==ch(i)); - p2=unique(ic(2,p)); - for j=1:numel(p2) - pOld=p(p2(j)); - tNew=[tNew t( ic(3,pOld):ic(4,pOld) )]; - L=ic(4,pOld)-ic(3,pOld)+1; - icNew=[icNew [ic(1:2,pOld);c+1;c+L] ]; - c=c+L; - end -end \ No newline at end of file diff --git a/tIc_Analysis/shuffleSpikes.asv b/tIc_Analysis/shuffleSpikes.asv deleted file mode 100644 index 8d8a7e5..0000000 --- a/tIc_Analysis/shuffleSpikes.asv +++ /dev/null @@ -1,13 +0,0 @@ -function [tOut,icOut]=shuffleSpikes(t,ic) -networkLevelShuffle=1; -nNeu=size(ic,2); -tOut=t; -icOut=ic; -if networkLevelShuffle %shuffles the spikes between neurons - tOut=t(randperm(numel(t))); -else %shuffle times within neurons - for i=1:nNeu - tmpT=diff(t(ic(3,i):ic(4,i)); - tOut(ic(3,i):ic(4,i))=tmpT(randperm(numel(tmpT))); - end -end \ No newline at end of file diff --git a/tIc_Analysis/shuffleSpikes.m b/tIc_Analysis/shuffleSpikes.m deleted file mode 100644 index 9548e3d..0000000 --- a/tIc_Analysis/shuffleSpikes.m +++ /dev/null @@ -1,13 +0,0 @@ -function [tOut,icOut]=shuffleSpikes(t,ic) -networkLevelShuffle=0; -nNeu=size(ic,2); -tOut=t; -icOut=ic; -if networkLevelShuffle %shuffles the spikes between neurons - tOut=t(randperm(numel(t))); -else %shuffle times within neurons - for i=1:nNeu - tmpT=diff(t(ic(3,i):ic(4,i))); - tOut(ic(3,i):ic(4,i))=[t(ic(3,1)) cumsum(tmpT(randperm(numel(tmpT))))]; - end -end \ No newline at end of file