diff --git a/CellExplorer.m b/CellExplorer.m index eb125ac0..ac0a96e4 100644 --- a/CellExplorer.m +++ b/CellExplorer.m @@ -103,6 +103,7 @@ fig2_axislimit_x = []; fig2_axislimit_y = []; fig3_axislimit_x = []; fig3_axislimit_y = []; groundTruthSelection = []; subsetGroundTruth = []; positionsTogglebutton = [[1 29 27 13];[29 29 27 13];[1 15 27 13];[29 15 27 13];[1 1 27 13];[29 1 27 13]]; dispTags = []; dispTags2 = []; incoming = []; outgoing = []; connections = []; plotName = ''; db = {}; plotConnections = [1 1 1]; tableDataOrder = []; +groundTruthCelltypesList = {''}; set(groot, 'DefaultFigureVisible', 'on'), maxFigureSize = get(groot,'ScreenSize'); UI.settings.figureSize = [50, 50, min(1200,maxFigureSize(3)-50), min(800,maxFigureSize(4)-50)]; if isempty(basename) @@ -1784,7 +1785,7 @@ colormap hot(512), xlabel('Time (ms)'), title(['All ACGs (image)']), axis tight end end end - plot(x_bins,rippleCorrelogram,'color', col,'linewidth',2, 'HitTest','off'), xlabel('time'),ylabel('Voltage') + plot(x_bins,rippleCorrelogram,'color', col,'linewidth',2, 'HitTest','off'), xlabel('time'),ylabel('') axis tight, ax6 = axis; grid on plot([0, 0], [ax6(3) ax6(4)],'color','k', 'HitTest','off'); set(gca, 'XTickMode', 'auto', 'XTickLabelMode', 'auto', 'YTickMode', 'auto', 'YTickLabelMode', 'auto', 'ZTickMode', 'auto', 'ZTickLabelMode', 'auto') @@ -1817,7 +1818,7 @@ colormap hot(512), xlabel('Time (ms)'), title(['All ACGs (image)']), axis tight end end end - plot(x_bins,rippleCorrelogram,'color', col,'linewidth',2, 'HitTest','off'), xlabel('time'),ylabel('Voltage') + plot(x_bins,rippleCorrelogram,'color', col,'linewidth',2, 'HitTest','off'), xlabel('time'),ylabel('') axis tight, ax6 = axis; grid on plot([0, 0], [ax6(3) ax6(4)],'color','k', 'HitTest','off'); set(gca, 'XTickMode', 'auto', 'XTickLabelMode', 'auto', 'YTickMode', 'auto', 'YTickLabelMode', 'auto', 'ZTickMode', 'auto', 'ZTickLabelMode', 'auto') @@ -2280,7 +2281,7 @@ function tSNE_redefineMetrics(~,~) X(isnan(X) | isinf(X)) = 0; waitbar(0.1,f_waitbar,'Calculating tSNE space...') - tSNE_metrics.plot = tsne(X','Standardize',true,'Distance',UI.settings.tSNE_dDistanceMetric,'Exaggeration',10); + tSNE_metrics.plot = tsne(X','Standardize',true,'Distance',UI.settings.tSNE_dDistanceMetric,'Exaggeration',15); if size(tSNE_metrics.plot,2)==1 tSNE_metrics.plot = [tSNE_metrics.plot,tSNE_metrics.plot]; @@ -4679,7 +4680,7 @@ function saveMetrics(cell_metrics,file) cell_metrics = saveCellMetricsStruct(cell_metrics); if nargin > 1 - save(file,'cell_metrics'); + save(file,'cell_metrics','-v7.3','-nocompression'); MsgLog(['Classification saved to ', file],[1,2]); elseif length(unique(cell_metrics.spikeSortingID)) > 1 MsgLog('Saving cell metrics from batch',1); @@ -4757,8 +4758,8 @@ function saveMetrics(cell_metrics,file) else saveAs = 'cell_metrics'; end - file = fullfile(clusteringpath,[saveAs,'.mat']); - save(file,'cell_metrics'); + file = fullfile(cell_metrics.general.clusteringpath,[cell_metrics.general.basename, '.',saveAs,'.cellinfo.mat']); + save(file,'cell_metrics','-v7.3','-nocompression'); classificationTrackChanges = []; UI.menu.file.save.ForegroundColor = 'k'; MsgLog(['Classification saved to ', file],[1,2]); @@ -5006,22 +5007,22 @@ function SignificanceMetricsMatrix(~,~) if UI.settings.tSNE_calcWideAcg && ~isfield(tSNE_metrics,'acg1') disp('Calculating tSNE space for wide ACGs') - tSNE_metrics.acg_wide = tsne([cell_metrics.acg.wide_zscored(ceil(size(cell_metrics.acg.wide_zscored,1)/2):end,:)]','Distance',UI.settings.tSNE_dDistanceMetric); + tSNE_metrics.acg_wide = tsne([cell_metrics.acg.wide_zscored(ceil(size(cell_metrics.acg.wide_zscored,1)/2):end,:)]','Distance',UI.settings.tSNE_dDistanceMetric,'Exaggeration',15); end if UI.settings.tSNE_calcNarrowAcg && ~isfield(tSNE_metrics,'acg2') disp('Calculating tSNE space for narrow ACGs') - tSNE_metrics.acg_narrow = tsne([cell_metrics.acg.narrow_zscored(ceil(size(cell_metrics.acg.narrow_zscored,1)/2):end,:)]','Distance',UI.settings.tSNE_dDistanceMetric); + tSNE_metrics.acg_narrow = tsne([cell_metrics.acg.narrow_zscored(ceil(size(cell_metrics.acg.narrow_zscored,1)/2):end,:)]','Distance',UI.settings.tSNE_dDistanceMetric,'Exaggeration',15); end if UI.settings.tSNE_calcFiltWaveform && ~isfield(tSNE_metrics,'filtWaveform') disp('Calculating tSNE space for filtered waveforms') X = cell_metrics.waveforms.filt_zscored'; - tSNE_metrics.filtWaveform = tsne(X(:,find(~any(isnan(X)))),'Standardize',true,'Distance',UI.settings.tSNE_dDistanceMetric); + tSNE_metrics.filtWaveform = tsne(X(:,find(~any(isnan(X)))),'Standardize',true,'Distance',UI.settings.tSNE_dDistanceMetric,'Exaggeration',15); end if UI.settings.tSNE_calcRawWaveform && ~isfield(tSNE_metrics,'rawWaveform') && isfield(cell_metrics.waveforms,'raw') disp('Calculating tSNE space for raw waveforms') X = cell_metrics.waveforms.raw_zscored'; if ~isempty(find(~any(isnan(X)))) - tSNE_metrics.rawWaveform = tsne(X(:,find(~any(isnan(X)))),'Standardize',true,'Distance',UI.settings.tSNE_dDistanceMetric); + tSNE_metrics.rawWaveform = tsne(X(:,find(~any(isnan(X)))),'Standardize',true,'Distance',UI.settings.tSNE_dDistanceMetric,'Exaggeration',15); end end if ~isfield(tSNE_metrics,'plot') @@ -5029,7 +5030,7 @@ function SignificanceMetricsMatrix(~,~) UI.settings.tSNE_metrics = intersect(UI.settings.tSNE_metrics,fieldnames(cell_metrics)); X = cell2mat(cellfun(@(X) cell_metrics.(X),UI.settings.tSNE_metrics,'UniformOutput',false)); X(isnan(X) | isinf(X)) = 0; - tSNE_metrics.plot = tsne(X','Standardize',true,'Distance',UI.settings.tSNE_dDistanceMetric); + tSNE_metrics.plot = tsne(X','Standardize',true,'Distance',UI.settings.tSNE_dDistanceMetric,'Exaggeration',15); end % Setting initial settings for plots, popups and listboxes @@ -5276,7 +5277,7 @@ function LoadDatabaseSession(~,~) uicontrol('Parent',loadDB.dialog,'Style','pushbutton','Position',[700, 10, 90, 30],'String','OK','Callback',@(src,evnt)CloseDB_dialog); uicontrol('Parent',loadDB.dialog,'Style','pushbutton','Position',[800, 10, 90, 30],'String','Cancel','Callback',@(src,evnt)CancelDB_dialog); updateSummaryText - uiwait(loadDB.dialog) + uiwait(loadDB.popupmenu.filter) function reloadSessionlist loadDB_sessionlist @@ -5339,7 +5340,7 @@ function LoadDatabaseSession(~,~) db.dataTable(:,1) = {false}; [db_path,~,~] = fileparts(which('db_load_sessions.m')); try - save(fullfile(db_path,'db_cell_metrics_session_list.mat'),'db'); + save(fullfile(db_path,'db_cell_metrics_session_list.mat'),'db','-v7.3','-nocompression'); catch warning('failed to save session list with metrics'); end @@ -5602,7 +5603,7 @@ function editDBcredentials(~,~) clusteringpath1 = cell_metrics.general.paths{batchIDsPrivate}; basename1 = cell_metrics.general.basenames{batchIDsPrivate}; else - clusteringpath1 = clusteringpath; + clusteringpath1 = cell_metrics.general.clusteringpath; basename1 = cell_metrics.general.basename; end @@ -6187,8 +6188,10 @@ function buttonGroundTruthClassification(input) function [choice,dialog_canceled] = groundTruthDlg(groundTruthCelltypes,groundTruthSelectionIn) choice = ''; dialog_canceled = 1; + updateGroundTruthCount; + groundTruth_dialog = dialog('Position', [300, 300, 600, 350],'Name','Ground truth cell types'); movegui(groundTruth_dialog,'center') - groundTruthList = uicontrol('Parent',groundTruth_dialog,'Style', 'ListBox', 'String', groundTruthCelltypes, 'Position', [10, 50, 580, 220],'Min', 0, 'Max', 100,'Value',groundTruthSelectionIn); + groundTruthList = uicontrol('Parent',groundTruth_dialog,'Style', 'ListBox', 'String', groundTruthCelltypesList, 'Position', [10, 50, 580, 220],'Min', 0, 'Max', 100,'Value',groundTruthSelectionIn); groundTruthTextfield = uicontrol('Parent',groundTruth_dialog,'Style', 'Edit', 'String', '', 'Position', [10, 300, 580, 25],'Callback',@(src,evnt)UpdateGroundTruthList,'HorizontalAlignment','left'); uicontrol('Parent',groundTruth_dialog,'Style','pushbutton','Position',[10, 10, 180, 30],'String','OK','Callback',@(src,evnt)CloseGroundTruth_dialog); uicontrol('Parent',groundTruth_dialog,'Style','pushbutton','Position',[200, 10, 190, 30],'String','Cancel','Callback',@(src,evnt)CancelGroundTruth_dialog); @@ -6197,20 +6200,39 @@ function buttonGroundTruthClassification(input) uicontrol('Parent',groundTruth_dialog,'Style', 'text', 'String', 'Selct the cell types below', 'Position', [10, 270, 580, 20],'HorizontalAlignment','left'); uicontrol(groundTruthTextfield) uiwait(groundTruth_dialog); + + function updateGroundTruthCount + tagFilter2 = find(cellfun(@(X) ~isempty(X), cell_metrics.groundTruthClassification)); + cellCount = zeros(1,length(groundTruthCelltypes)); + if ~isempty(tagFilter2) + filter = []; + for i = 1:length(tagFilter2) + filter(i,:) = strcmp(cell_metrics.groundTruthClassification{tagFilter2(i)},groundTruthCelltypes); + end + + for j = 1:length({groundTruthCelltypes}) + cellCount = sum(filter); + end + end + cellCount = cellstr(num2str(cellCount'))'; + groundTruthCelltypesList = strcat(groundTruthCelltypes,' (',cellCount,')'); + end + function UpdateGroundTruthList - temp = contains(groundTruthCelltypes,groundTruthTextfield.String,'IgnoreCase',true); + temp = find(contains(groundTruthCelltypes,groundTruthTextfield.String,'IgnoreCase',true)); + if ~isempty(groundTruthList.Value) && ~any(temp == groundTruthList.Value) groundTruthList.Value = 1; end if ~isempty(temp) - groundTruthList.String = groundTruthCelltypes(temp); + groundTruthList.String = groundTruthCelltypesList(temp); else groundTruthList.String = {''}; end end function CloseGroundTruth_dialog if length(groundTruthList.String)>=groundTruthList.Value - choice = groundTruthList.String(groundTruthList.Value); + choice = groundTruthCelltypes(groundTruthList.Value); end dialog_canceled = 0; delete(groundTruth_dialog); diff --git a/CellExplorer_Preferences.m b/CellExplorer_Preferences.m index 8f1345d0..3747fe98 100644 --- a/CellExplorer_Preferences.m +++ b/CellExplorer_Preferences.m @@ -40,7 +40,7 @@ UI.settings.deepSuperficial = {'Unknown','Cortical','Deep','Superficial'}; UI.settings.tags = {'Good','Bad','Mua','Noise','InverseSpike','Other'}; UI.settings.groundTruth = {'PV+','NOS1+','GAT1+','SST+','Axoaxonic','5HT3a'}; -UI.settings.groundTruthMarkers = {'ok','db','sm','*k','+k','+p'}; % Supports any Matlab marker symbols: https://www.mathworks.com/help/matlab/creating_plots/create-line-plot-with-markers.html +UI.settings.groundTruthMarkers = {'om','dg','sm','*k','+k','+p'}; % Supports any Matlab marker symbols: https://www.mathworks.com/help/matlab/creating_plots/create-line-plot-with-markers.html % Cell type classification colors UI.settings.cellTypeColors = [[.5,.5,.5];[.8,.2,.2];[.2,.2,.8];[0.2,0.8,0.8];[0.8,0.2,0.8];[.2,.8,.2]]; diff --git a/LoadCellMetricBatch.m b/LoadCellMetricBatch.m index ed9f7151..994dcc8e 100644 --- a/LoadCellMetricBatch.m +++ b/LoadCellMetricBatch.m @@ -115,9 +115,11 @@ end if exist(fullfile(clustering_paths{iii},[basenames{iii},'.',saveAs,'.cellinfo.mat'])) cell_metrics2{iii} = load(fullfile(clustering_paths{iii},[basenames{iii},'.',saveAs,'.cellinfo.mat'])); - else + elseif fullfile(clustering_paths{iii},[saveAs,'.mat']) warning('Loading legacy format') disp([fullfile(clustering_paths{iii},[basenames{iii},'.',saveAs,'.cellinfo.mat']), ' does not exist']) + else + warning('session not found') end subfields2 = [subfields2(:);fieldnames(cell_metrics2{iii}.cell_metrics)]; temp = struct2cell(structfun(@class,cell_metrics2{iii}.cell_metrics,'UniformOutput',false)); diff --git a/calc_CellMetrics/calc_CellMetrics.m b/calc_CellMetrics/calc_CellMetrics.m index e07db49e..bf2a570d 100644 --- a/calc_CellMetrics/calc_CellMetrics.m +++ b/calc_CellMetrics/calc_CellMetrics.m @@ -724,6 +724,9 @@ if any(contains(metrics,{'manipulation_metrics','all'})) && ~any(contains(excludeMetrics,{'manipulation_metrics'})) disp('* Calculating manipulaiton metrics'); + field2remove = {'manipulations'}; + test = isfield(cell_metrics,field2remove); + cell_metrics = rmfield(cell_metrics,field2remove(test)); eventFiles = dir(fullfile(basepath,[basename,'.*.manipulation.mat'])); eventFiles = {eventFiles.name}; if ~isempty(eventFiles) diff --git a/db/db_cell_metrics_session_list.mat b/db/db_cell_metrics_session_list.mat index fcd0595e..c35d3f38 100644 Binary files a/db/db_cell_metrics_session_list.mat and b/db/db_cell_metrics_session_list.mat differ diff --git a/db/db_update_session.m b/db/db_update_session.m index 4946b88e..e7f76a69 100644 --- a/db/db_update_session.m +++ b/db/db_update_session.m @@ -1,7 +1,7 @@ function session = db_update_session(session,varargin) % Peter Petersen % petersen.peter@gmail.com -% Last edited: 17-06-2019 +% Last edited: 27-06-2019 p = inputParser; addParameter(p,'forceReload',false,@islogical); @@ -18,7 +18,7 @@ %% % % % % % % % % % % % % % % % % % % % % Extracellular % % % % % % % % % % % % % % % % % % % % -if session.general.duration == 0 | forceReload +if ~isfield(session.general,'duration') | session.general.duration == 0 | forceReload sr = sessionInfo.rates.wideband; if exist(fullfile(session.general.basePath,'info.rhd')) Intan_rec_info = read_Intan_RHD2000_file_Peter(pwd); @@ -52,7 +52,7 @@ %% % % % % % % % % % % % % % % % % % % % % Epochs % % % % % % % % % % % % % % % % % % % % -if any(session.epochs.duration == 0) | forceReload +if isempty(session.epochs.duration) | any(session.epochs.duration == 0) | forceReload duration = []; for i = 1:size(session.epochs.name,2) fname = 'amplifier.dat'; diff --git a/get_CellMetrics.m b/get_CellMetrics.m index 6dd30ca3..4f591793 100644 --- a/get_CellMetrics.m +++ b/get_CellMetrics.m @@ -66,6 +66,7 @@ addParameter(p,'deepSuperficial',[],@iscell); addParameter(p,'animal',[],@iscell); addParameter(p,'tags',[],@iscell); +addParameter(p,'groundTruthClassification',[],@iscell); parse(p,varargin{:}) @@ -99,6 +100,7 @@ deepSuperficial = p.Results.deepSuperficial; animal = p.Results.animal; tags = p.Results.tags; +groundTruthClassification = p.Results.groundTruthClassification; if isempty(basename) s = regexp(basepath, filesep, 'split'); @@ -123,7 +125,7 @@ cell_metrics = LoadCellMetricBatch('sessions',sessions); end -filterIndx = ones(length(cell_metrics.UID),6); +filterIndx = ones(length(cell_metrics.UID),7); if ~isempty(brainRegion) filterIndx(:,1) = strcmp(cell_metrics.brainRegion,brainRegion); end @@ -148,6 +150,14 @@ end end end - -cell_metrics_idxs = find(sum(filterIndx')==6); +if ~isempty(groundTruthClassification) + for i = 1:length(cell_metrics.UID) + if ~isempty(cell_metrics.groundTruthClassification{i}) + filterIndx(i,7) = any(strcmp(cell_metrics.groundTruthClassification{i},groundTruthClassification)); + else + filterIndx(i,7) = 0; + end + end +end +cell_metrics_idxs = find(sum(filterIndx')==7);