Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 42 additions & 30 deletions +spoke/SpikeGrid.m
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
%Spike waveform display properties
spikeTimeWindow = [-1 2] * 1e-3; %2 element vector ([pre post]) indicating times, in seconds, to display before and after threshold crossing
spikeAmpUnits = 'volts'; %One of {'volts' 'rmsMultiple'} indicating units to use for spike plot display. Value of 'rmsMultiple' only available if thresholdType='rmsMultiple'
%spikeAmpWindow = [-4000 4000];
%spikeAmpWindow_ = [-4000 4000];

spikesPerPlot = 100; %Number of sweeps to display in each grid figure
spikesPerPlotClearMode = 'all'; %One of {'all' 'oldest'}
Expand All @@ -115,16 +115,24 @@
psthTimerPeriod = inf; %Period, in seconds, at which plotPSTH() method is called automatically when displayMode='raster'

channelSubset = inf; %Subset of channels to acquire from

% The following are properties that were SetAccess=protected, but
% have been moved out of protected to allow config file saves with
% most.
refreshPeriodMaxSpikeRate = inf; %Maximum spike rate (Hz) to detect/plot at each refresh period; spikes above this rate are discarded

% The following are properties that back up dependent properties.
% This is for properties that need to be saved to disk.
spikeAmpWindow; % backs up property spikeAmpWindow_
end

properties (SetObservable, Transient)
stimEventClassifyFcn = []; %Function handle specifying function used to classify stimuli into event types. See class notes for further information.
end

properties (SetObservable, Dependent)
spikeAmpWindow; %2 element vector ([min max]) indicating voltage bounds or RMSMultiple (depending on thresholdType) for each spike plot
refreshPeriodMaxSpikeRate = inf; %Maximum spike rate (Hz) to detect/plot at each refresh period; spikes above this rate are discarded
spikeAmpWindow_; %2 element vector ([min max]) indicating voltage bounds or RMSMultiple (depending on thresholdType) for each spike plot
refreshPeriodMaxNumSpikes = inf; %Maximum number of spikes to detect/plot during a given refresh period
numAuxChans; %Number of auxiliary
end

Expand Down Expand Up @@ -157,7 +165,6 @@
maxBufSizeSeconds = 1;
end


properties (Hidden,SetAccess=protected)
hSGL; %Handle to SpikeGLX object
sglParamCache; %cached SpikeGL parameters
Expand Down Expand Up @@ -225,9 +232,7 @@
stimLastEventScanNumWindow; %1x2 array indicating start/end scan numbers for last stimulus trial

stimEventCount_; %Struct var containing stimEventCount value for each of the stimEventTypes_

refreshPeriodMaxNumSpikes = inf; %Maximum number of spikes to detect/plot during a given refresh period


bmarkReadTimeStats = zeros(3,1); %Array of [mean std n]
bmarkPreProcessTimeStats = zeros(3,1);; %Array of [mean std n]
bmarkPlotTimeStats = zeros(3,1);; %Array of [mean std n]
Expand Down Expand Up @@ -301,7 +306,7 @@
obj.hThresholdLines = repmat({ones(numPadChans,1) * -1},2,1);
obj.hSpikeLines = gobjects(numPadChans,1);

obj.spikeAmpWindow = [-aiRangeMax aiRangeMax];
obj.spikeAmpWindow_ = [-aiRangeMax aiRangeMax];
obj.tabDisplayed = 1;
obj.refreshRate = obj.refreshRate; %apply default value

Expand Down Expand Up @@ -365,7 +370,7 @@ function ziniCreateGrids(obj)
obj.hPanels.psth(i) = uipanel(obj.hFigs.psth,'Position',panelPosn);

%Places axes in panel and configure
obj.hPlots(i) = axes('Parent',obj.hPanels.waveform(i),'Position',[0 0 1 1],'XLim',obj.spikeTimeWindow); %,'YLim',obj.spikeAmpWindow);
obj.hPlots(i) = axes('Parent',obj.hPanels.waveform(i),'Position',[0 0 1 1],'XLim',obj.spikeTimeWindow); %,'YLim',obj.spikeAmpWindow_);
obj.hRasters(i) = axes('Parent',obj.hPanels.raster(i),'Position',[0 0 1 1],'XLim',obj.stimTimeWindow);
obj.hPSTHs(i) = axes('Parent',obj.hPanels.psth(i),'Position',[0 0 1 1]);

Expand Down Expand Up @@ -498,8 +503,8 @@ function ziniCreateGrids(obj)

function val = get.numChans(obj)
%val = obj.hSpoke.n_chan;
neuralChans = str2num(obj.sglParamCache.niMNChans1); %#ok<ST2NM>
muxAnalogChans = str2num(obj.sglParamCache.niMAChans1); %#ok<ST2NM>
neuralChans = str2num(char(obj.sglParamCache.niMNChans1)); %#ok<ST2NM>
muxAnalogChans = str2num(char(obj.sglParamCache.niMAChans1)); %#ok<ST2NM>

val = obj.sglParamCache.niMuxFactor * (numel(neuralChans) + numel(muxAnalogChans)) + obj.numAuxChans;
end
Expand Down Expand Up @@ -560,14 +565,14 @@ function ziniCreateGrids(obj)
val = ceil(numPadChans/obj.PLOTS_PER_TAB);
end

function val = get.refreshPeriodMaxSpikeRate(obj)
val = obj.refreshPeriodMaxNumSpikes * obj.refreshRate;
function val = get.refreshPeriodMaxNumSpikes(obj) % DEPENDENT PROPERTY
val = obj.refreshPeriodMaxSpikeRate / obj.refreshRate;
end

function set.refreshPeriodMaxSpikeRate(obj,val)
function set.refreshPeriodMaxSpikeRate(obj,val) % REAL DEAL
obj.validatePropArg('refreshPeriodMaxSpikeRate',val);

obj.refreshPeriodMaxNumSpikes = ceil(val / obj.refreshRate);
lclVar = ceil(val / obj.refreshRate);
obj.refreshPeriodMaxSpikeRate = lclVar * obj.refreshRate;
end

function val = get.refreshPeriodAvgScans(obj)
Expand Down Expand Up @@ -635,28 +640,28 @@ function ziniCreateGrids(obj)

%Side-effects
if ~strcmpi(oldVal,val)
%Adjust thresholdVal & spikeAmpWindow
%Adjust thresholdVal & spikeAmpWindow_

%TODO(?): A smarter adjustment based on the last-cached RMS values, somehow handlign the variety across channels
switch val
case 'volts'
obj.spikeAmpWindow = [-1 1] * obj.sglParamCache.niAiRangeMax;
obj.spikeAmpWindow_ = [-1 1] * obj.sglParamCache.niAiRangeMax;
case 'rmsMultiple'
obj.spikeAmpWindow = [-2 10] * obj.thresholdVal;
obj.spikeAmpWindow_ = [-2 10] * obj.thresholdVal;
end

%Refresh threshold lines
obj.zprvDrawThresholdLines();
end
end


function val = get.spikeAmpWindow(obj)
val = get(obj.hPlots(1),'YLim');
function val = get.spikeAmpWindow_(obj)
%val = get(obj.hPlots(1),'YLim');
val = obj.spikeAmpWindow;
end

function set.spikeAmpWindow(obj,val)
obj.validatePropArg('spikeAmpWindow',val);
function set.spikeAmpWindow_(obj,val)
obj.validatePropArg('spikeAmpWindow_',val);

if strcmpi(obj.spikeAmpUnits,'volts');
aiRangeMax = obj.sglParamCache.niAiRangeMax;
Expand All @@ -669,6 +674,13 @@ function ziniCreateGrids(obj)

set(obj.hPlots,'YLim',val);

%Set real property
obj.spikeAmpWindow = val;
end

function set.spikeAmpWindow(obj,val)
%force recalc of dependent property
obj.spikeAmpWindow = val;
end

function set.spikeTimeWindow(obj,val)
Expand Down Expand Up @@ -913,17 +925,17 @@ function ziniCreateGrids(obj)
%Side Effects
if ~strcmpi(oldVal,val)

%Adjust thresholdVal & spikeAmpWindow
%Adjust thresholdVal & spikeAmpWindow_

%TODO(?): A smarter adjustment based on the last-cached RMS values, somehow handlign the variety across channels
switch val
case 'volts'
aiRangeMax = obj.sglParamCache.niAiRangeMax;
obj.thresholdVal = .1 * aiRangeMax;
obj.spikeAmpWindow = [-1 1] * aiRangeMax;
obj.spikeAmpWindow_ = [-1 1] * aiRangeMax;
case 'rmsMultiple'
obj.thresholdVal = 5;
obj.spikeAmpWindow = [-2*obj.thresholdVal 10*obj.thresholdVal];
obj.spikeAmpWindow_ = [-2*obj.thresholdVal 10*obj.thresholdVal];
end

%Redraw threshold lines
Expand Down Expand Up @@ -1164,7 +1176,7 @@ function saveConfigAs(obj,filename)
end

%Save model properties
obj.mdlSaveConfig(filename,'include',{'spikeAmpWindow' 'numAuxChans' 'gridFigPosition' 'psthFigPosition'});
obj.mdlSaveConfig(filename,'include',{'spikeAmpWindow_' 'numAuxChans' 'gridFigPosition' 'psthFigPosition'});

%Save controller fig layout
if ~isempty(obj.hController)
Expand Down Expand Up @@ -2546,8 +2558,8 @@ function zprvClearPlots(obj,displaysToClear,reuseThreshold)
s.thresholdRMSRefreshOnRetrigger = struct('Classes','binaryflex','Attributes','scalar');

s.spikeTimeWindow = struct('Attributes',{{'numel' 2 'finite'}});
%s.spikeAmpWindow = struct('Attributes',{{'finite' '1d'}});
s.spikeAmpWindow = struct('Attributes',{{'numel' 2 'finite'}});
%s.spikeAmpWindow_ = struct('Attributes',{{'finite' '1d'}});
s.spikeAmpWindow_ = struct('Attributes',{{'numel' 2 'finite'}});

s.spikeAmpUnits = struct('Options',{{'volts' 'rmsMultiple'}});

Expand Down
2 changes: 1 addition & 1 deletion +spoke/SpikeGridController.m
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ function stepThresholdVal(obj,direction)


%frequently-adjusted property table bindings
s.spikeAmpWindow = struct('GuiIDs',{{'SpikeGrid','pcFreqAdjustProps'}},'PropControlData',struct('format','char'));
s.spikeAmpWindow_ = struct('GuiIDs',{{'SpikeGrid','pcFreqAdjustProps'}},'PropControlData',struct('format','char'));
s.spikeTimeWindow = struct('GuiIDs',{{'SpikeGrid','pcFreqAdjustProps'}},'PropControlData',struct('format','char'));
s.spikesPerPlot = struct('GuiIDs',{{'SpikeGrid','pcFreqAdjustProps'}},'PropControlData',struct('format','numeric'));

Expand Down