diff --git a/+spoke/SpikeGrid.m b/+spoke/SpikeGrid.m index 629d3b8..3518acd 100644 --- a/+spoke/SpikeGrid.m +++ b/+spoke/SpikeGrid.m @@ -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'} @@ -115,7 +115,15 @@ 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) @@ -123,8 +131,8 @@ 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 @@ -157,7 +165,6 @@ maxBufSizeSeconds = 1; end - properties (Hidden,SetAccess=protected) hSGL; %Handle to SpikeGLX object sglParamCache; %cached SpikeGL parameters @@ -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] @@ -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 @@ -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]); @@ -498,8 +503,8 @@ function ziniCreateGrids(obj) function val = get.numChans(obj) %val = obj.hSpoke.n_chan; - neuralChans = str2num(obj.sglParamCache.niMNChans1); %#ok - muxAnalogChans = str2num(obj.sglParamCache.niMAChans1); %#ok + neuralChans = str2num(char(obj.sglParamCache.niMNChans1)); %#ok + muxAnalogChans = str2num(char(obj.sglParamCache.niMAChans1)); %#ok val = obj.sglParamCache.niMuxFactor * (numel(neuralChans) + numel(muxAnalogChans)) + obj.numAuxChans; end @@ -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) @@ -635,14 +640,14 @@ 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 @@ -650,13 +655,13 @@ function ziniCreateGrids(obj) 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; @@ -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) @@ -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 @@ -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) @@ -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'}}); diff --git a/+spoke/SpikeGridController.m b/+spoke/SpikeGridController.m index ebf0e1f..71cc917 100644 --- a/+spoke/SpikeGridController.m +++ b/+spoke/SpikeGridController.m @@ -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'));