Skip to content

Commit

Permalink
improovements related to ground truth classification and stimulation …
Browse files Browse the repository at this point in the history
…pipeline
  • Loading branch information
petersenpeter committed Jul 27, 2019
1 parent bd8d6be commit b63d9ff
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 59 deletions.
21 changes: 12 additions & 9 deletions CellExplorer.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
% initializeSession, LoadDatabaseSession, buttonSave, keyPress, defineSpikesPlots, customPlot, GroupAction, brainRegionDlg

% TODO
% Gui to Reverse changes from backup files
% GUI to reverse changes from backup files
% Separate loading of ground truth features
% Submit ground truth cells from new session

Expand Down Expand Up @@ -110,7 +110,7 @@
basename = s{end};
end

CellExplorerVersion = 1.39;
CellExplorerVersion = 1.40;

UI.fig = figure('Name',['Cell Explorer v' num2str(CellExplorerVersion)],'NumberTitle','off','renderer','opengl', 'MenuBar', 'None','PaperOrientation','landscape','windowscrollWheelFcn',@ScrolltoZoomInPlot,'KeyPressFcn', {@keyPress});
hManager = uigetmodemanager(UI.fig);
Expand Down Expand Up @@ -926,8 +926,9 @@

% Ground truth cell types
if groundTruthSelection
for jj = 1:length(subsetGroundTruth)
plot(plotX(subsetGroundTruth{jj}), plotY(subsetGroundTruth{jj}),UI.settings.groundTruthMarkers{jj},'HitTest','off','LineWidth', 1.5, 'MarkerSize',8);
idGroundTruth = find(~cellfun(@isempty,subsetGroundTruth));
for jj = 1:length(idGroundTruth)
plot(plotX(subsetGroundTruth{idGroundTruth(jj)}), plotY(subsetGroundTruth{idGroundTruth(jj)}),UI.settings.groundTruthMarkers{jj},'HitTest','off','LineWidth', 1.5, 'MarkerSize',8);
end
end

Expand Down Expand Up @@ -1152,8 +1153,9 @@

% Ground truth cell types
if groundTruthSelection
for jj = 1:length(subsetGroundTruth)
plot(cell_metrics.troughToPeak(subsetGroundTruth{jj}) * 1000, cell_metrics.burstIndex_Royer2012(subsetGroundTruth{jj}),UI.settings.groundTruthMarkers{jj},'HitTest','off','LineWidth', 1.5, 'MarkerSize',8);
idGroundTruth = find(~cellfun(@isempty,subsetGroundTruth));
for jj = 1:length(idGroundTruth)
plot(cell_metrics.troughToPeak(subsetGroundTruth{idGroundTruth(jj)}) * 1000, cell_metrics.burstIndex_Royer2012(subsetGroundTruth{idGroundTruth(jj)}),UI.settings.groundTruthMarkers{jj},'HitTest','off','LineWidth', 1.5, 'MarkerSize',8);
end
end
% Setting legend
Expand Down Expand Up @@ -1214,8 +1216,9 @@

% Ground truth cell types
if groundTruthSelection
for jj = 1:length(subsetGroundTruth)
plot(tSNE_metrics.plot(subsetGroundTruth{jj},1), tSNE_metrics.plot(subsetGroundTruth{jj},2),UI.settings.groundTruthMarkers{jj},'HitTest','off','LineWidth', 1.5, 'MarkerSize',8);
idGroundTruth = find(~cellfun(@isempty,subsetGroundTruth));
for jj = 1:length(idGroundTruth)
plot(tSNE_metrics.plot(subsetGroundTruth{idGroundTruth(jj)},1), tSNE_metrics.plot(subsetGroundTruth{idGroundTruth(jj)},2),UI.settings.groundTruthMarkers{jj},'HitTest','off','LineWidth', 1.5, 'MarkerSize',8);
end
end

Expand Down Expand Up @@ -2415,7 +2418,7 @@ function buttonCellType(selectedClas)
rows = max(ceil(length(buttonLabels)/2),3);
positionToogleButtons = getpixelposition(parentPanelName);
positionToogleButtons = [positionToogleButtons(3)/2,(positionToogleButtons(4)-0.03)/rows];
for i = 1:min(length(buttonLabels),6)
for i = 1:max(length(buttonLabels),6)
buttonPosition{i} = [(1.04-mod(i,2))*positionToogleButtons(1),0.05+(rows-ceil(i/2))*positionToogleButtons(2),positionToogleButtons(1),positionToogleButtons(2)];
end
end
Expand Down
8 changes: 4 additions & 4 deletions CellExplorer_Preferences.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
UI.settings.cellTypes = {'Unknown','Pyramidal Cell','Narrow Interneuron','Wide Interneuron'};
UI.settings.deepSuperficial = {'Unknown','Cortical','Deep','Superficial'};
UI.settings.tags = {'Good','Bad','Mua','Noise','InverseSpike','Other'};
UI.settings.groundTruth = {'PV+','NOS1+','GAT1+','SST+'};
UI.settings.groundTruthMarkers = {'ok','db','sm','*k','+d','p'}; % Supports any Matlab marker symbols: https://www.mathworks.com/help/matlab/creating_plots/create-line-plot-with-markers.html
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

% 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]];
Expand Down Expand Up @@ -170,7 +170,7 @@
spikesPlots.(plotName).plotDuration = 1;
spikesPlots.(plotName).plotCount = 0;

plotName = 'spikes_pvLightStimulation';
plotName = 'spikes_optoStim';
spikesPlots.(plotName).x = 'times';
spikesPlots.(plotName).y = 'times';
spikesPlots.(plotName).x_label = 'Time';
Expand All @@ -179,7 +179,7 @@
spikesPlots.(plotName).filter = '';
spikesPlots.(plotName).filterType = ''; % [none, equal to, less than, greater than]
spikesPlots.(plotName).filterValue = 0;
spikesPlots.(plotName).event = 'pvLightStimulation';
spikesPlots.(plotName).event = 'optoStim';
spikesPlots.(plotName).eventAlignment = 'onset'; % [onset, offset, center, peak]
spikesPlots.(plotName).eventSorting = 'time'; % [none, time, amplitude, duration]
spikesPlots.(plotName).eventSecBefore = 0.1; % in seconds
Expand Down
65 changes: 21 additions & 44 deletions calc_CellMetrics/calc_CellMetrics.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
% clusteringpath - Path to cluster data if different from basepath
% showGUI - Show GUI dialog to adjust settings/parameters
% metrics - Metrics that will be calculated. A cell with strings
% Examples: 'waveform_metrics','PCA_features','acg_metrics','c',
% Examples: 'waveform_metrics','PCA_features','acg_metrics','deepSuperficial',
% 'ripple_metrics','monoSynaptic_connections','spatial_metrics'
% 'perturbation_metrics','theta_metrics','psth_metrics',
% 'manipulation_metrics', 'event_metrics'.
Expand All @@ -34,6 +34,7 @@
% saveAs - name of .mat file
% saveBackup - logical. Whether a backup file should be created
% plots - logical. Plot summary figures
% debugMode - logical. Activate a debug mode avoiding try/catch
%
% OUTPUT
% Cell_metrics matlab structure
Expand Down Expand Up @@ -73,6 +74,7 @@
addParameter(p,'saveAs','cell_metrics',@isstr);
addParameter(p,'saveBackup',true,@islogical);
addParameter(p,'plots',true,@islogical);
addParameter(p,'debugMode',false,@islogical);

parse(p,varargin{:})

Expand All @@ -97,6 +99,7 @@
saveAs = p.Results.saveAs;
saveBackup = p.Results.saveBackup;
plots = p.Results.plots;
debugMode = p.Results.debugMode;
timerCalcMetrics = tic;


Expand Down Expand Up @@ -414,7 +417,6 @@
if any(contains(metrics,{'deepSuperficial','all'})) && ~any(contains(excludeMetrics,{'deepSuperficial'}))
disp('* Deep-Superficial by ripple polarity reversal')
% lfpExtension = exist_LFP(basepath,basename);

if (~exist(fullfile(basepath,[basename,'.ripples.events.mat']),'file')) % ~isempty(excludeManipulationIntervals)
lfpExtension = exist_LFP(basepath,basename);
if isfield(session.channelTags,'RippleNoise') & isfield(session.channelTags,'Ripple') & isnumeric(session.channelTags.Ripple)
Expand All @@ -424,7 +426,7 @@
elseif isfield(session.channelTags,'Ripple') & isnumeric(session.channelTags.Ripple)
ripples = bz_FindRipples('basepath',basepath,'channel',session.channelTags.Ripple.channels-1,'basepath',basepath,'durations',[50 150],'passband',[120 180],'EMGThresh',0.5);
else
warning('Ripple')
warning('Ripple channel not defined')
end
end

Expand All @@ -435,17 +437,16 @@
if ~isfield(session.extracellular,'probesVerticalSpacing') & ~isfield(session.extracellular,'probesLayout')
session = determineProbeSpacing(session);
end
classification_DeepSuperficial(session);
% classification_DeepSuperficial(session);
end
load(deepSuperficial_file)
cell_metrics.general.SWR = deepSuperficialfromRipple;
deepSuperficial_ChDistance = deepSuperficialfromRipple.channelDistance; %
deepSuperficial_ChClass = deepSuperficialfromRipple.channelClass;% cell_deep_superficial
cell_metrics.general.deepSuperficial_file = deepSuperficial_file;

for j = 1:cell_metrics.general.cellCount
cell_metrics.deepSuperficial(j) = deepSuperficial_ChClass(spikes.maxWaveformCh1(j)); % cell_deep_superficial OK
cell_metrics.deepSuperficialDistance(j) = deepSuperficial_ChDistance(spikes.maxWaveformCh(j)); % cell_deep_superficial_distance
cell_metrics.deepSuperficialDistance(j) = deepSuperficial_ChDistance(spikes.maxWaveformCh1(j)); % cell_deep_superficial_distance
end
end
end
Expand Down Expand Up @@ -673,6 +674,7 @@
eventName = strsplit(eventFiles{i},'.');
eventName = eventName{end-2};
eventOut = load(eventFiles{i});
disp([' Importing ' eventName]);
if strcmp(fieldnames(eventOut),eventName)
if strcmp(eventName,'ripples')
[PSTH,PSTH_time] = calc_PSTH(eventOut.ripples.peaks,spikes);
Expand Down Expand Up @@ -721,13 +723,16 @@
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %

if any(contains(metrics,{'manipulation_metrics','all'})) && ~any(contains(excludeMetrics,{'manipulation_metrics'}))
disp('* Calculating manipulaiton metrics');
eventFiles = dir(fullfile(basepath,[basename,'.*.manipulation.mat']));
eventFiles = {eventFiles.name};
if ~isempty(eventFiles)
for iEvents = 1:length(eventFiles)
eventName = strsplit(eventFiles{iEvents},'.'); eventName = eventName{end-2};
eventOut = load(eventFiles{iEvents});
[PSTH,PSTH_time] = calc_PSTH(eventOut.(eventName).timestamps(:,1),spikes);
disp([' Importing ' eventName]);
window_smoothing = 10;
[PSTH,PSTH_time] = calc_PSTH(eventOut.(eventName).timestamps(:,1),spikes,'smoothing',window_smoothing);
eventFieldName = ['manipulation_',eventName];
cell_metrics.manipulations.(eventName) = num2cell(PSTH,1);
cell_metrics.general.manipulations.(eventName).event_file = eventFiles{iEvents};
Expand All @@ -738,39 +743,6 @@
end


%% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
% Perturbation metrics
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %

if any(contains(metrics,{'perturbation_metrics','all'})) && ~any(contains(excludeMetrics,{'perturbation_metrics'}))
if exist(fullfile(basepath,'optogenetics.mat'),'file')
disp('* Calculating perturbation metrics');
spikes2 = loadSpikes('basename',basename,'clusteringformat',session.spikeSorting.format{1},'clusteringpath',clusteringpath,'basepath',basepath);

field2remove = {'optoPSTH','psth_optostim'};
test = isfield(cell_metrics,field2remove);
cell_metrics = rmfield(cell_metrics,field2remove(test));

cell_metrics.psth.optostim = [];
temp = load('optogenetics.mat');
trigger = temp.optogenetics.peak;
edges = [-1:0.1:1];
for j = 1:cell_metrics.general.cellCount
psth = zeros(size(edges));
for jj = 1:length(trigger)
psth = psth + histc(spikes2.times{j}'-trigger(jj),edges);
end
cell_metrics.psth.optostim{j} = (psth(1:end-1)/length(trigger))/0.1;
cell_metrics.psth.optostim{j} = cell_metrics.psth.optostim{j}(:);
end

cell_metrics.general.psth.optostim.x_label = 'Time (s)';
cell_metrics.general.psth.optostim.x_bins = edges(1:end-1)+(edges(2)-edges(1))/2;
figure, plot(cell_metrics.general.psth.optostim.x_bins, horzcat(cell_metrics.psth.optostim{:}))
end
end


%% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
% PSTH metrics
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
Expand Down Expand Up @@ -958,12 +930,17 @@

if submitToDatabase
disp('* Submitting cells to database');
try
if debugMode
session = db_update_session(session,'forceReload',true);
cell_metrics = db_submit_cells(cell_metrics,session);
catch exception
disp(exception.identifier)
warning('Failed to submit to database');
else
try
session = db_update_session(session,'forceReload',true);
cell_metrics = db_submit_cells(cell_metrics,session);
catch exception
disp(exception.identifier)
warning('Failed to submit to database');
end
end
end

Expand Down
4 changes: 2 additions & 2 deletions calc_CellMetrics/calc_PSTH.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
[~, ~, spike_cluster_index] = unique(spike_cluster_index);

[ccg,time] = CCG(spike_times,spike_cluster_index,'binSize',binSize,'duration',duration,'norm','rate');
PSTH_out = ccg(:,2:end,1);
PSTH_out = flip(ccg(:,2:end,1),1);
if smoothing>0
PSTH_out = nanconv(PSTH_out,ones(1,smoothing)/smoothing,'edge');
PSTH_out = nanconv(PSTH_out,gausswin(smoothing)/sum(gausswin(smoothing)),'edge');
end

0 comments on commit b63d9ff

Please sign in to comment.