% GUI for detecting PSPs
function handles = pspGui(lastVals)
if ~isappdata(0, 'pspDetector')
if nargin < 1
% set the default values
lastVals.minAmp = .5;
lastVals.maxAmp = 10;
lastVals.minTau = 5;
lastVals.maxTau = 100;
lastVals.minYOffset = -100;
lastVals.maxYOffset = -30;
lastVals.minDecay = 5;
lastVals.maxDecay = 500;
lastVals.derThresh = 1;
lastVals.closestEPSPs = 5;
lastVals.errThresh = 0.08;
lastVals.dataFilterType = 1;
lastVals.derFilterType = 3;
lastVals.dataFilterLength = 5;
lastVals.derFilterLength = 5;
lastVals.debugging = 0;
lastVals.outputAxis = 0;
lastVals.dataStart = 1;
lastVals.forceDisplay = 1;
lastVals.alphaFit = 0;
lastVals.decayFit = 0;
lastVals.riseFit = 0;
end
figure('menu', 'none',...
'name', 'PSP Detector',...
'numbertitle', 'off',...
'units', 'pixels',...
'resize', 'off',...
'color', [0.9255 0.9137 0.8471],...
'position', [100 100 177 852],...
'closeRequestFcn', @closeWindow);
% menus
f = uimenu('Label','Data');
uimenu(f,'Label','Save PSPs...','Callback', @savePSPs);
uimenu(f,'Label','Export to Workspace...','Callback', @exportPSPs);
uimenu(f, 'Label', 'Characterize PSPs', 'callback', @characterizePSPsClick);
uimenu(f, 'Label', 'Overlay PSPs', 'callback', @overlayPSPsClick);
uimenu(f, 'Label', 'Covariances', 'callback', @genCovariances);
uimenu(f,'Label','End','Callback', @closeWindow,...
'Separator','on','Accelerator','Q');
if ~ispref('pspGUI','presets')
setpref('pspGUI','presets',{'presetEPSPs', 'presetIPSPs', 'presetEPSCs', 'presetIPSCs', 'presetNoisyEPSPs'});
setpref('pspGUI','presetEPSPs', {'0.5','30','5','100','5','500','-100','-30',2,'5',4,'5',0,1,'1','0.08','5',0,0,'PSPsUp'})
setpref('pspGUI', 'presetEPSCs', {'-2000','-5','2','200','5','500','-inf','inf',2,'11',4,'7',0,1,'1','0.08','5',1,0,'PSPsDown'});
setpref('pspGUI','presetIPSPs', {'-30','0.5','5','100','5','500','-100','-30',2,'5',4,'5',0,1,'1','0.08','5',0,0,'PSPsDown'})
setpref('pspGUI', 'presetIPSCs', {'5','2000','2','200','5','500','-inf','inf',2,'11',4,'7',0,1,'1','0.08','5',1,0,'PSPsUp'});
setpref('pspGUI','presetNoisyEPSPs', {'0.2','30','5','100','5','500','-100','-30',2,'15',4,'5',0,1,'.2','0.08','5',0,0,'PSPsUp'})
end
g = uimenu('Label','Presets');
uimenu(g,'Label','Add Current...','callback', @addPreset);
uimenu(g,'Label','Remove Preset...','callback', @removePreset);
tempPresets = getpref('pspGUI','presets');
uimenu(g,'Label',tempPresets{1}(7:end),'callback', @setPreset,'separator','on');
for i = 2:numel(tempPresets)
uimenu(g,'Label',tempPresets{i}(7:end),'callback', @setPreset);
end
% uicontrols
panel = uipanel('Title','Amplitude', 'units', 'pixel','FontSize',12,'Position',[9.8500 782.5000 159.3000 73.5000]);
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'Min:', 'position', [.1 .6 .5 .4], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
handles.ampMin = uicontrol('tooltipstring', 'Minimum allowable amplitude (pa\mV)', 'callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', lastVals.minAmp, 'position', [.6 .6 .3 .4], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'Max:', 'position', [.1 .1 .5 .4], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
handles.ampMax = uicontrol('tooltipstring', 'Maximum allowable amplitude (in pa\mV)', 'callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', lastVals.maxAmp, 'position', [.6 .1 .3 .4], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
panel = uipanel('Title','Alpha Tau', 'units', 'pixel','FontSize',12,'Position',[9.8500 711.0000 159.3000 73.5000]);
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'Min:', 'position', [.1 .6 .5 .4], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
handles.alphaTauMin = uicontrol('tooltipstring', 'Minimum allowable tau of first pass alpha function (msec)', 'callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', lastVals.minTau, 'position', [.6 .6 .3 .4], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'Max:', 'position', [.1 .1 .5 .4], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
handles.alphaTauMax = uicontrol('tooltipstring', 'Maximum allowable tau of first pass alpha function (msec)', 'callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', lastVals.maxTau, 'position', [.6 .1 .3 .4], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
panel = uipanel('Title','Decay Time', 'units', 'pixel','FontSize',12,'Position',[9.8500 638.5000 159.3000 73.5000]);
uicontrol('tooltipstring', 'Minimum allowable tau of exponential decay fitting (msec)', 'Style', 'Text', 'units', 'normal', 'String', 'Min:', 'position', [.1 .6 .5 .4], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
handles.decayMin = uicontrol('callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', lastVals.minDecay, 'position', [.6 .6 .3 .4], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'Max:', 'position', [.1 .1 .5 .4], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
handles.decayMax = uicontrol('tooltipstring', 'Maximum allowable tau of exponential decay fitting (msec)', 'callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', lastVals.maxDecay, 'position', [.6 .1 .3 .4], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
panel = uipanel('Title','Y Offset', 'units', 'pixel','FontSize',12,'Position',[9.8500 566.0000 159.3000 73.5000]);
uicontrol('tooltipstring', 'Minimum allowable offset of alpha function from baseline (pa\mV)','Style', 'Text', 'units', 'normal', 'String', 'Min:', 'position', [.1 .6 .5 .4], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
handles.offsetMin = uicontrol('callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', lastVals.minYOffset, 'position', [.6 .6 .3 .4], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'Max:', 'position', [.1 .1 .5 .4], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
handles.offsetMax = uicontrol('tooltipstring', 'Maximum allowable offset of alpha function from baseline (pa\mV)','callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', lastVals.maxYOffset, 'position', [.6 .1 .3 .4], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
panel = uipanel('Title','Filtering', 'units', 'pixel','FontSize',12,'Position',[9.8500 446.5000 159.3000 120.5000]);
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'Data', 'position', [0 .75 .45 .2], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'Derivative', 'position', [0 .25 .45 .2], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'Length', 'position', [.1 .50 .4 .2], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'Length', 'position', [.1 0 .4 .2], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
handles.dataFilterType = uicontrol('tooltipstring', 'Filtering of data trace', 'callback', @updatePSPs, 'Style', 'popup', 'units', 'normal', 'String', {'None'; 'Average'; 'Median'; 'S Golay'}, 'value', lastVals.dataFilterType + 1, 'position', [.45 .8 .55 .2], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
handles.derFilterType = uicontrol('tooltipstring', 'Filtering of derivative trace', 'callback', @updatePSPs, 'Style', 'popup', 'units', 'normal', 'String', {'None'; 'Average'; 'Median'; 'S Golay'}, 'value', lastVals.derFilterType + 1, 'position', [.45 .3 .55 .2], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
handles.dataFilterLength = uicontrol('tooltipstring', 'Length of filter for data trace', 'callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', lastVals.dataFilterLength, 'position', [.5 .50 .3 .2], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
handles.derFilterLength = uicontrol('tooltipstring', 'Length of filter for derivative trace','callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', lastVals.derFilterLength, 'position', [.5 0 .3 .2], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
panel = uipanel('Title','Fitting', 'units', 'pixel','FontSize',12,'Position',[9.8500 357 159.3000 90]);
handles.alphaFit = uicontrol('tooltipstring', 'Alpha fit to event', 'callback', @updatePSPs, 'Style', 'check', 'units', 'normal', 'String', 'Alpha', 'value', lastVals.alphaFit, 'position', [.1 .05 .8 .3], 'parent', panel, 'fontsize', 12);
handles.decayFit = uicontrol('tooltipstring', 'Exponential fit to decay', 'callback', @updatePSPs, 'Style', 'check', 'units', 'normal', 'String', 'Decay', 'value', lastVals.decayFit, 'position', [.1 .35 .8 .3], 'parent', panel, 'fontsize', 12);
handles.riseFit = uicontrol('tooltipstring', 'Exponential fit to rise', 'callback', @updatePSPs, 'Style', 'check', 'units', 'normal', 'String', 'Rise', 'value', lastVals.riseFit, 'position', [.1 .65 .8 .3], 'parent', panel, 'fontsize', 12);
panel = uipanel('Title','', 'units', 'pixel','FontSize',12,'Position',[9.8500 185 159.3000 170]);
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'Der Thresh', 'position', [.1 .65 .5 .12], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
handles.derThresh = uicontrol('tooltipstring', 'Value which derivative must exceed to trigger an event start', 'callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', lastVals.derThresh, 'position', [.6 .65 .3 .12], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
handles.debugging = uicontrol('tooltipstring', 'Whether debugging plots are shown along the way', 'callback', @updatePSPs, 'Style', 'check', 'units', 'normal', 'String', 'Debugging', 'position', [.1 .85 .8 .12], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [0.9255 0.9137 0.8471]);
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'Err Thresh', 'position', [.1 .5 .5 .12], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
handles.errThresh = uicontrol('tooltipstring', 'Error threshold used for fitting alpha functions and decay taus', 'callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', lastVals.errThresh, 'position', [.6 .5 .3 .12], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'PSP Gap', 'position', [.1 .35 .5 .12], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
handles.closestPSPs = uicontrol('tooltipstring', 'Closest that two PSPs can be without the first one being disregarded (msec)', 'callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', lastVals.closestEPSPs, 'position', [.6 .35 .3 .12], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
handles.windowTimes = uicontrol('tooltipstring', 'Window of possible times (windowLength @ windowStarts); leave blank for whole time', 'callback', @updatePSPs, 'Style', 'edit', 'units', 'normal', 'String', '', 'position', [.6 .2 .3 .12], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1]);
uicontrol('Style', 'Text', 'units', 'normal', 'String', 'Window', 'position', [.1 .2 .5 .12], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
handles.goButton = uicontrol('tooltipstring', 'Re-detect PSPs', 'callback', @updatePSPs, 'Style', 'pushbutton', 'units', 'normal', 'String', 'Detect', 'position', [.3 .03 .4 .12], 'parent', panel, 'fontsize', 12,'horizontalalignment', 'left');
panel = uipanel('Title', 'Data', 'units', 'pixel','FontSize',12,'Position',[9.8500 8.3500 159.3000 95.5500]);
handles.dataSource = uicontrol('callback', @updatePSPs, 'Style', 'list', 'units', 'normal', 'String', '', 'position', [0.02 0.02 .96 1], 'parent', panel, 'fontsize', 12, 'backgroundcolor', [1 1 1], 'min', 0, 'max', 0);
handles.refreshData = uicontrol('callback', @loadChannels, 'style', 'pushbutton', 'units', 'pixel', 'position', [90 85.55 50 20], 'string', 'refresh');
handles.PSPtype = uibuttongroup('visible', 'off', 'units', 'pixel', 'Position', [9.8500 108.3500 159.3000 75]);
handles.PSPsAuto = uicontrol('tag','PSPsAuto','Style','Radio','String','Auto Detect','units', 'normal','fontsize', 12, 'pos',[.1 .65 .8 .3],'parent',handles.PSPtype,'HandleVisibility','off');
handles.PSPsUp = uicontrol('tag','PSPsUp','Style','Radio','String','Up','units', 'normal','fontsize', 12, 'pos',[.1 .35 .8 .3],'parent',handles.PSPtype,'HandleVisibility','off');
handles.PSPsDown = uicontrol('tag','PSPsDown','Style','Radio','String','Down','units', 'normal','fontsize', 12, 'pos',[.1 .05 .8 .3],'parent',handles.PSPtype,'HandleVisibility','off');
set(handles.PSPtype,'SelectionChangeFcn',@updatePSPs,'SelectedObject',handles.PSPsAuto,'Visible','on', 'userdata', handles.PSPsAuto);
setappdata(gcf, 'lastVals', lastVals);
setappdata(0, 'pspDetector', handles);
setappdata(handles.dataSource, 'lastSelection', []);
else
if nargin > 0
% just reset the values
handleList = getappdata(0, 'pspDetector');
set(handleList.ampMin, 'string', lastVals.minAmp);
set(handleList.ampMax, 'string', lastVals.maxAmp);
set(handleList.alphaTauMin, 'string', lastVals.minTau);
set(handleList.alphaTauMax, 'string', lastVals.maxTau);
set(handleList.decayMin, 'string', lastVals.minDecay);
set(handleList.decayMax, 'string', lastVals.maxDecay);
set(handleList.offsetMin, 'string', lastVals.minOffset);
set(handleList.offsetMax, 'string', lastVals.maxOffset);
set(handleList.dataFilterType, 'value', lastVals.dataFilterType);
set(handleList.dataFilterLength, 'string', lastVals.dataFilterLength);
set(handleList.derFilterType, 'value', lastVals.derFilterType);
set(handleList.derFilterLength, 'string', lastVals.derFilterLength);
set(handleList.debugging, 'value', lastVals.debugging);
set(handleList.alphaFit, 'value', lastVals.alphaFit);
set(handleList.decayFit, 'value', lastVals.decayFit);
set(handleList.riseFit, 'value', lastVals.riseFit);
set(handleList.derThresh, 'string', lastVals.derThresh);
set(handleList.errThresh, 'string', lastVals.errThresh);
set(handleList.closestPSPs, 'string', lastVals.closestPSPs);
setappdata(gcf, 'lastVals', lastVals);
end
end
loadChannels
function closeWindow(varargin)
button = questdlg('Save PSP data?');
if strcmp(button, 'Yes')
savePSPs;
end
if ~strcmp(button, 'Cancel')
rmappdata(0, 'pspDetector');
delete(gcf);
end
function savePSPs(varargin)
if isappdata(gcf, 'PSPs')
[FileName PathName] = uiputfile({'*.mat', 'Matlab Data Files (*.mat)';' *.*', 'All Files (*.*)'},'Choose name and location for file', 'PSPs');
PSPs = getappdata(gcf, 'PSPs');
save([PathName FileName], 'PSPs');
else
msgbox('No PSPs to save');
end
function exportPSPs(varargin)
varName = inputdlg('Enter a name for the workspace variable', 'Export', 1, {'PSPs'});
tempVarName = genvarname(varName, evalin('base', 'who'));
if strcmp(varName, tempVarName)
assignin('base', varName{1}, getappdata(gcf, 'PSPs'));
else
switch questdlg(strcat('''', varName, ''' is not a valid variable name in the base workspace. Is ''', tempVarName, ''' ok?'), 'Uh oh');
case 'Yes'
assignin('base', tempVarName{1}, getappdata(gcf, 'PSPs'));
case 'No'
varName = inputdlg('Enter a name for the workspace variable', 'Export', 1, tempVarName);
assignin('base', genvarname(varName{1}), getappdata(gcf, 'PSPs'));
case 'Cancel'
% do nothing
end
end
function characterizePSPsClick(varargin)
if isappdata(gcf, 'PSPs')
PSPs = getappdata(gcf, 'PSPs');
if numel(PSPs.params) > 1
params = [];
for i = 1:numel(PSPs.params)
params(end + 1:end + size(PSPs.params{i}, 1), :) = PSPs.params{i};
end
PSPs = [];
PSPs.params{1} = params;
end
characterizePSPs(PSPs.params{1,1}, diff(getappdata(gcf, 'xLims')) / 1000);
end
function overlayPSPsClick(varargin)
persistent lastValues
if isappdata(gcf, 'PSPs')
if isempty(lastValues)
lastValues = [-2 10];
end
whereBounds = inputdlg({'Start of window (msec)', 'End of Window (msec)'},'Time Window...',1, {num2str(lastValues(1)), num2str(lastValues(2))});
if numel(whereBounds) > 0 % bail if they hit 'Cancel'
whereBounds = str2double(whereBounds);
lastValues = whereBounds;
PSPs = getappdata(gcf, 'PSPs');
overlayPSPs(getappdata(gcf, 'traceData'), [whereBounds(1) whereBounds(2)], PSPs.params, getappdata(gcf, 'timePerPoint'));
end
end
function genCovariances(varargin)
if isappdata(gcf, 'PSPs')
PSPs = getappdata(gcf, 'PSPs');
if numel(PSPs.params) > 1
params = [];
for i = 1:numel(PSPs.params)
params(end + 1:end + size(PSPs.params{i}, 1), :) = PSPs.params{i};
end
PSPs = [];
PSPs.params{1} = params;
end
outData = char(ones(5, 60) * 32);
tempData = num2str(cov(normalizeMatrix(PSPs.params{1}, 2)));
outData(2:5, end - size(tempData, 2) + 1:end) = tempData;
outData(1,:) = ' Amplitude Rise Tau Location Decay Tau';
outData(2,1:9) = 'Amplitude';
outData(3,1:8) = 'Rise Tau';
outData(4,1:8) = 'Location';
outData(5,1:9) = 'Decay Tau';
disp(outData);
corVals = corrcoef(PSPs.params{1});
corVals = corVals .^ 2;
figure('name', 'Covariance', 'numbertitle', 'off');
subplot(3,2,1), plot(PSPs.params{1}(:,1), PSPs.params{1}(:,2), 'linestyle', 'none', 'marker', '.', 'markerSize', 12), m = polyfit(PSPs.params{1}(:,1), PSPs.params{1}(:,2), 1); line([min(PSPs.params{1}(:,1)) max(PSPs.params{1}(:,1))], [m(1) * min(PSPs.params{1}(:,1)) + m(2) m(1) * max(PSPs.params{1}(:,1)) + m(2)], 'color', [1 0 0]), title(['Rise Tau vs. Amplitude, R^{2} = ' sprintf('%4.2f', corVals(2,1))]), axis tight;
subplot(3,2,3), plot(PSPs.params{1}(:,1), PSPs.params{1}(:,3), 'linestyle', 'none', 'marker', '.', 'markerSize', 12), m = polyfit(PSPs.params{1}(:,1), PSPs.params{1}(:,3), 1); line([min(PSPs.params{1}(:,1)) max(PSPs.params{1}(:,1))], [m(1) * min(PSPs.params{1}(:,1)) + m(2) m(1) * max(PSPs.params{1}(:,1)) + m(2)], 'color', [1 0 0]),title(['Location vs. Amplitude, R^{2} = ' sprintf('%4.2f', corVals(3,1))]), axis tight;
subplot(3,2,5), plot(PSPs.params{1}(:,1), PSPs.params{1}(:,4), 'linestyle', 'none', 'marker', '.', 'markerSize', 12), m = polyfit(PSPs.params{1}(:,1), PSPs.params{1}(:,4), 1); line([min(PSPs.params{1}(:,1)) max(PSPs.params{1}(:,1))], [m(1) * min(PSPs.params{1}(:,1)) + m(2) m(1) * max(PSPs.params{1}(:,1)) + m(2)], 'color', [1 0 0]),title(['Decay Tau vs. Amplitude, R^{2} = ' sprintf('%4.2f', corVals(4,1))]), axis tight;
subplot(3,2,2), plot(PSPs.params{1}(:,4), PSPs.params{1}(:,3), 'linestyle', 'none', 'marker', '.', 'markerSize', 12), m = polyfit(PSPs.params{1}(:,4), PSPs.params{1}(:,3), 1); line([min(PSPs.params{1}(:,4)) max(PSPs.params{1}(:,4))], [m(1) * min(PSPs.params{1}(:,4)) + m(2) m(1) * max(PSPs.params{1}(:,4)) + m(2)], 'color', [1 0 0]),title(['Location vs. Decay Tau, R^{2} = ' sprintf('%4.2f', corVals(3,4))]), axis tight;
subplot(3,2,4), plot(PSPs.params{1}(:,2), PSPs.params{1}(:,3), 'linestyle', 'none', 'marker', '.', 'markerSize', 12), m = polyfit(PSPs.params{1}(:,2), PSPs.params{1}(:,3), 1); line([min(PSPs.params{1}(:,2)) max(PSPs.params{1}(:,2))], [m(1) * min(PSPs.params{1}(:,2)) + m(2) m(1) * max(PSPs.params{1}(:,2)) + m(2)], 'color', [1 0 0]),title(['Location vs. Rise Tau, R^{2} = ' sprintf('%4.2f', corVals(3,2))]), axis tight;
subplot(3,2,6), plot(PSPs.params{1}(:,2), PSPs.params{1}(:,4), 'linestyle', 'none', 'marker', '.', 'markerSize', 12), m = polyfit(PSPs.params{1}(:,2), PSPs.params{1}(:,4), 1); line([min(PSPs.params{1}(:,2)) max(PSPs.params{1}(:,2))], [m(1) * min(PSPs.params{1}(:,2)) + m(2) m(1) * max(PSPs.params{1}(:,2)) + m(2)], 'color', [1 0 0]),title(['Decay Tau vs. Rise Tau, R^{2} = ' sprintf('%4.2f', corVals(4,2))]), axis tight;
end
function updatePSPs(varargin)
lastVals = getappdata(gcf, 'lastVals');
handleList = getappdata(0, 'pspDetector');
pspFigure = gcf;
if varargin{1} == handleList.goButton
% set these as the values
lastVals = loadVals;
setappdata(pspFigure, 'lastVals', lastVals);
setappdata(handleList.dataSource, 'lastSelection', get(handleList.dataSource, 'value'));
% call detect
axisHandles = get(handleList.dataSource, 'userData');
lastVals.outputAxis = axisHandles(get(handleList.dataSource, 'value'));
if ishandle(lastVals.outputAxis)
kids = get(lastVals.outputAxis, 'children');
kids = kids(strcmp(get(kids(1:end - 2), 'userData'), 'data'));
xdata = get(kids(end), 'xdata');
xDiff = diff(xdata(1:2));
setappdata(pspFigure, 'timePerPoint', xDiff);
lims = get(lastVals.outputAxis, 'xlim');
lastVals.dataStart = round((lims(1) + 1)/ xDiff);
setappdata(pspFigure, 'lastVals', lastVals);
try
data = cell2mat(get(kids, 'ydata'));
data = data(:, (min([1 round((lims(1) + 1 - xdata(1)) / xDiff)]):round((lims(2) - xdata(1)) / xDiff)));
lastVals.minTau = lastVals.minTau / xDiff;
lastVals.maxTau = lastVals.maxTau / xDiff;
numEvents = [];
stringData = '';
for traceIndex = 1:numel(kids)
if isempty(get(handleList.windowTimes, 'string'))
switch get(get(handleList.PSPtype,'SelectedObject'), 'string')
case 'Auto Detect'
[PSPs.params{traceIndex} PSPs.decayFits{traceIndex}] = detectPSPs(data(traceIndex, max([1 round((lims(1) + 1 - xdata(1)) / xDiff)]):round((lims(2) - xdata(1)) / xDiff)), lastVals);
if traceIndex == 1
disp(['detectPSPs(data(' sprintf('%1.1f', max([1 round((lims(1) + 1 - xdata(1)) / xDiff)]) * xDiff) ':' sprintf('%1.1f', round((lims(2) - xdata(1)) / xDiff) * xDiff) ')' struct2stream(lastVals, lims(1)) ');'])
end
case 'Up'
[PSPs.params{traceIndex} PSPs.decayFits{traceIndex}] = detectPSPs(data(traceIndex, max([1 round((lims(1) + 1 - xdata(1)) / xDiff)]):round((lims(2) - xdata(1)) / xDiff)), 0, lastVals);
if traceIndex == 1
disp(['detectPSPs(data(' sprintf('%1.1f', max([1 round((lims(1) + 1 - xdata(1)) / xDiff)]) * xDiff) ':' sprintf('%1.1f', round((lims(2) - xdata(1)) / xDiff) * xDiff) '), 0' struct2stream(lastVals, lims(1)) ');'])
end
case 'Down'
[PSPs.params{traceIndex} PSPs.decayFits{traceIndex}] = detectPSPs(data(traceIndex, max([1 round((lims(1) + 1 - xdata(1)) / xDiff)]):round((lims(2) - xdata(1)) / xDiff)), 1, lastVals);
if traceIndex == 1
disp(['detectPSPs(data(' sprintf('%1.1f', max([1 round((lims(1) + 1 - xdata(1)) / xDiff)]) * xDiff) ':' sprintf('%1.1f', round((lims(2) - xdata(1)) / xDiff) * xDiff) '), 1' struct2stream(lastVals, lims(1)) ');'])
end
end
else
tempString = get(handleList.windowTimes, 'string');
windowLength = round(str2double(tempString(1:find(tempString == '@', 1, 'first') - 1)) / xDiff);
windowStarts = round(str2num(tempString(find(tempString == '@', 1, 'first') + 1:end)) / xDiff) - max([1 round((lims(1) + 1 - xdata(1)) / xDiff)]);
switch get(get(handleList.PSPtype,'SelectedObject'), 'string')
case 'Auto Detect'
[PSPs.params{traceIndex} PSPs.decayFits{traceIndex}] = detectPSPs(data(traceIndex, max([1 round((lims(1) + 1 - xdata(1)) / xDiff)]):round((lims(2) - xdata(1)) / xDiff)), windowStarts, windowLength, lastVals);
if traceIndex == 1
disp(['detectPSPs(data(' sprintf('%1.1f', max([1 round((lims(1) + 1 - xdata(1)) / xDiff)]) * xDiff) ':' sprintf('%1.1f', round((lims(2) - xdata(1)) / xDiff) * xDiff) ')' struct2stream(lastVals, lims(1)) ');'])
end
case 'Up'
[PSPs.params{traceIndex} PSPs.decayFits{traceIndex}] = detectPSPs(data(traceIndex, max([1 round((lims(1) + 1 - xdata(1)) / xDiff)]):round((lims(2) - xdata(1)) / xDiff)), 0, windowStarts, windowLength, lastVals);
if traceIndex == 1
disp(['detectPSPs(data(' sprintf('%1.1f', max([1 round((lims(1) + 1 - xdata(1)) / xDiff)]) * xDiff) ':' sprintf('%1.1f', round((lims(2) - xdata(1)) / xDiff) * xDiff) '), 0' struct2stream(lastVals, lims(1)) ');'])
end
case 'Down'
[PSPs.params{traceIndex} PSPs.decayFits{traceIndex}] = detectPSPs(data(traceIndex, max([1 round((lims(1) + 1 - xdata(1)) / xDiff)]):round((lims(2) - xdata(1)) / xDiff)), 1, windowStarts, windowLength, lastVals);
if traceIndex == 1
disp(['detectPSPs(data(' sprintf('%1.1f', max([1 round((lims(1) + 1 - xdata(1)) / xDiff)]) * xDiff) ':' sprintf('%1.1f', round((lims(2) - xdata(1)) / xDiff) * xDiff) '), 1' struct2stream(lastVals, lims(1)) ');'])
end
end
end
if PSPs.params{1}(1,1) == 0
PSPs = [];
disp('No PSPs detected');
end
PSPs.params{traceIndex}(:,3) = PSPs.params{traceIndex}(:,3) + 1 + lims(1);
events(traceIndex).data = PSPs.params{traceIndex}(:,3)';
events(traceIndex).traceName = getappdata(kids(traceIndex), 'traceName');
events(traceIndex).type = 'PSPs';
numEvents(end + 1) = size(PSPs.params{traceIndex}, 1);
stringData = [stringData num2str(numEvents(end)) ' events' char(13)];
end
setappdata(lastVals.outputAxis, 'events', events);
if numel(numEvents) > 1
stringData = ['mean = ' num2str(mean(numEvents)) ', STE = ' num2str(std(numEvents)/sqrt(numel(numEvents))) char(13) stringData];
end
set(get(lastVals.outputAxis, 'userData'), 'string', stringData);
catch
setappdata(lastVals.outputAxis, 'events', []);
PSPs = [];
end
showEvents(lastVals.outputAxis);
end
if exist('PSPs', 'var')
setappdata(pspFigure, 'PSPs', PSPs);
setappdata(pspFigure, 'traceData', data);
setappdata(pspFigure, 'xLims', lims);
setappdata(pspFigure, 'xStep', xDiff);
end
elseif str2double(get(handleList.ampMin, 'string')) >= lastVals.minAmp &&...
str2double(get(handleList.ampMax, 'string')) <= lastVals.maxAmp &&...
str2double(get(handleList.alphaTauMin, 'string')) >= lastVals.minTau &&...
str2double(get(handleList.alphaTauMax, 'string')) <= lastVals.maxTau &&...
str2double(get(handleList.decayMin, 'string')) >= lastVals.minDecay &&...
str2double(get(handleList.decayMax, 'string')) <= lastVals.maxDecay &&...
str2double(get(handleList.offsetMin, 'string')) >= lastVals.minYOffset &&...
str2double(get(handleList.offsetMax, 'string')) <= lastVals.maxYOffset &&...
get(handleList.dataFilterType, 'value') == lastVals.dataFilterType + 1 &&...
get(handleList.derFilterType, 'value') == lastVals.derFilterType + 1 &&...
str2double(get(handleList.dataFilterLength, 'string')) >= lastVals.dataFilterLength &&...
str2double(get(handleList.derFilterLength, 'string')) <= lastVals.derFilterLength &&...
str2double(get(handleList.derThresh, 'string')) >= lastVals.derThresh &&...
str2double(get(handleList.errThresh, 'string')) <= lastVals.errThresh &&...
str2double(get(handleList.closestPSPs, 'string')) <= lastVals.closestEPSPs &&...
length(getappdata(handleList.dataSource, 'lastSelection')) == length(get(handleList.dataSource, 'value')) &&...
getappdata(handleList.dataSource, 'lastSelection') == get(handleList.dataSource, 'value') &&...
get(handleList.PSPtype, 'userData') == get(handleList.PSPtype, 'selectedObject')
% set these as the values
lastVals = loadVals;
setappdata(pspFigure, 'lastVals', lastVals);
setappdata(handleList.dataSource, 'lastSelection', get(handleList.dataSource, 'value'));
set(handleList.PSPtype, 'userData', get(handleList.PSPtype, 'selectedObject'));
% filter out the ones that are out of bounds
PSPs = getappdata(pspFigure, 'PSPs');
if size(PSPs, 1) == 1
return
end
if ~iscell(PSPs)
PSPs = {PSPs};
end
for traceIndex = 1:numel(PSPs)
keepers = PSPs{traceIndex}.params{1}(:, 1) >= lastVals.minAmp &...
PSPs{traceIndex}.params{1}(:, 1) <= lastVals.maxAmp &...
PSPs{traceIndex}.params{1}(:, 4) >= lastVals.minDecay &...
PSPs{traceIndex}.params{1}(:, 4) <= lastVals.maxDecay;
PSPs{traceIndex}.params{1} = PSPs{traceIndex}.params{1}(keepers, :);
PSPs{traceIndex}.decayFits = {PSPs{traceIndex}.decayFits{1}(:, keepers)};
end
setappdata(pspFigure, 'PSPs', PSPs);
% update the display
axisHandles = get(handleList.dataSource, 'userData');
axisHandles = axisHandles(get(handleList.dataSource, 'value'));
axisKids = get(axisHandles, 'children');
delete(axisKids(~strcmp(get(axisKids(1:end - 2), 'userdata'), 'data')))
xDiff = get(axisKids(end - 2), 'xdata');
xDiff = diff(xDiff(1:2));
for traceIndex = 1:numel(axisKids)
data = get(axisKids(traceIndex), 'ydata');
for i = 1:size(PSPs{traceIndex}.params{1}, 1)
% plot starts
line(PSPs{traceIndex}.params{1}(i, 3), data(int32(PSPs{traceIndex}.params{1}(i, 3) / xDiff) - lastVals.dataStart), 'parent', axisHandles, 'Color', [0 0 1], 'linestyle', 'none', 'marker', '+', 'buttondownfcn', ['set(get(get(gcbo, ''parent''), ''userdata''), ''string'', ''Start time = ' sprintf('%6.1f', PSPs{traceIndex}.params{1}(i,3)) ''')']);
% plot amplitudes
line([PSPs{traceIndex}.params{1}(i, 3) + PSPs{traceIndex}.params{1}(i, 2) PSPs{traceIndex}.params{1}(i, 3) + PSPs{traceIndex}.params{1}(i, 2)], [data(int32((PSPs{traceIndex}.params{1}(i, 3) + PSPs{traceIndex}.params{1}(i, 2)) / xDiff) - lastVals.dataStart) - PSPs{traceIndex}.params{1}(i, 1) data(int32((PSPs{traceIndex}.params{1}(i, 3) + PSPs{traceIndex}.params{1}(i, 2)) / xDiff) - lastVals.dataStart)], 'parent', axisHandles, 'Color', [0 1 0], 'buttondownfcn', ['set(get(get(gcbo, ''parent''), ''userdata''), ''string'', {''Rise time = ' sprintf('%4.1f', PSPs{traceIndex}.params{1}(i,2)) '''; ''Amplitude = ' sprintf('%7.2f', PSPs{traceIndex}.params{1}(i,1)) '''})']);
% plot decay tau
line(PSPs{traceIndex}.params{1}(i, 3) + PSPs{traceIndex}.params{1}(i, 2) * 1.5:xDiff:PSPs{traceIndex}.params{1}(i, 3) + PSPs{traceIndex}.params{1}(i, 2) * 1.5 + numel(PSPs{traceIndex}.decayFits{i}) * xDiff - xDiff, PSPs{traceIndex}.decayFits{i}, 'parent', axisHandles, 'Color', [1 0 0], 'buttondownfcn', ['set(get(get(gcbo, ''parent''), ''userdata''), ''string'', ''Decay tau = ' sprintf('%6.2f', PSPs{traceIndex}.params{1}(i,4)) ''')']);
end
events(traceIndex).data = PSPs.params{traceIndex}(:,3)';
end
setappdata(axisHandles, 'events', events);
showEvents(axisHandles);
end
function lastVals = loadVals
handleList = getappdata(0, 'pspDetector');
lastVals.minAmp = str2double(get(handleList.ampMin, 'string'));
lastVals.maxAmp = str2double(get(handleList.ampMax, 'string'));
lastVals.minTau = str2double(get(handleList.alphaTauMin, 'string'));
lastVals.maxTau = str2double(get(handleList.alphaTauMax, 'string'));
lastVals.minYOffset = str2double(get(handleList.offsetMin, 'string'));
lastVals.maxYOffset = str2double(get(handleList.offsetMax, 'string'));
lastVals.minDecay = str2double(get(handleList.decayMin, 'string'));
lastVals.maxDecay = str2double(get(handleList.decayMax, 'string'));
lastVals.derThresh = str2double(get(handleList.derThresh, 'string'));
lastVals.closestEPSPs = str2double(get(handleList.closestPSPs, 'string'));
lastVals.errThresh = str2double(get(handleList.errThresh, 'string'));
lastVals.dataFilterType = get(handleList.dataFilterType, 'value') - 1;
lastVals.derFilterType = get(handleList.derFilterType, 'value') - 1;
lastVals.dataFilterLength = str2double(get(handleList.dataFilterLength, 'string'));
lastVals.derFilterLength = str2double(get(handleList.derFilterLength, 'string'));
lastVals.debugging = get(handleList.debugging, 'value');
lastVals.outputAxis = 0;
lastVals.dataStart = 0;
lastVals.forceDisplay = 1;
lastVals.alphaFit = get(handleList.alphaFit, 'value');
lastVals.decayFit = get(handleList.decayFit, 'value');
lastVals.riseFit = get(handleList.riseFit, 'value');
function outText = struct2stream(inVals, dataStart)
outText = [', ''minAmp'', ' num2str(inVals.minAmp) ...
', ''maxAmp'', ' num2str(inVals.maxAmp) ...
', ''minTau'', ' num2str(inVals.minTau) ...
', ''maxTau'', ' num2str(inVals.maxTau) ...
', ''minYOffset'', ' num2str(inVals.minYOffset) ...
', ''maxYOffset'', ' num2str(inVals.maxYOffset) ...
', ''minDecay'', ' num2str(inVals.minDecay) ...
', ''maxDecay'', ' num2str(inVals.maxDecay) ...
', ''derThresh'', ' num2str(inVals.derThresh) ...
', ''closestEPSPs'', ' num2str(inVals.closestEPSPs) ...
', ''errThresh'', ' num2str(inVals.errThresh) ...
', ''dataFilterType'', ' num2str(inVals.dataFilterType) ...
', ''derFilterType'', ' num2str(inVals.derFilterType) ...
', ''dataFilterLength'', ' num2str(inVals.dataFilterLength) ...
', ''derFilterLength'', ' num2str(inVals.derFilterLength) ...
', ''debugging'', ' num2str(inVals.debugging) ...
', ''outputAxis'', handles.axes(axisNum)' ...
', ''dataStart'', ' num2str(dataStart) ...
', ''forceDisplay'', 1' ...
', ''alphaFit'', ' num2str(inVals.alphaFit) ...
', ''decayFit'', ' num2str(inVals.decayFit) ...
', ''riseFit'', ' num2str(inVals.riseFit)];
function loadChannels(varargin)
stringData = [];
userData = [];
handles = getappdata(0, 'pspDetector');
if isappdata(0, 'scopes')
scopes = getappdata(0, 'scopes');
handleList = get(scopes(1), 'userData');
whatChoices = get(handleList.channelControl(1).channel, 'string');
if ~iscell(whatChoices)
whatChoices = {whatChoices};
end
for axisIndex = 1:handleList.axesCount
whichChannel = get(handleList.channelControl(axisIndex).channel, 'value');
stringData{end + 1} = whatChoices{whichChannel};
end
userData(end + 1:end + handleList.axesCount) = handleList.axes;
set(handles.dataSource, 'string', stringData, 'userdata', userData, 'value', 1);
setappdata(ancestor(handles.dataSource, 'figure'), 'xStep', handleList.xStep);
else
set(handles.dataSource, 'string', '', 'userdata', [], 'value', 0);
setappdata(ancestor(handles.dataSource, 'figure'), 'xStep', 1);
end
function addPreset(varargin)
tempName = inputdlg('Please enter a name for the preset:');
tempName = tempName{1};
if ~isvarname(tempName)
switch questdlg(['Change to ' genvarname(tempName) '?'], 'Input must be a valid variable name','Yes','No','Yes')
case 'Yes'
tempName = genvarname(tempName);
case 'No'
return
end
end
tempPresets = getpref('pspGUI','presets');
if ~ismember(tempName, tempPresets)
tempPresets{end + 1} = ['preset' tempName];
setpref('pspGUI','presets',tempPresets);
end
handleList = getappdata(0, 'pspDetector');
setpref('pspGUI',['preset' tempName],{...
get(handleList.ampMin, 'string'), get(handleList.ampMax, 'string'),...
get(handleList.alphaTauMin, 'string'), get(handleList.alphaTauMax, 'string'),...
get(handleList.decayMin, 'string'), get(handleList.decayMax, 'string'),...
get(handleList.offsetMin, 'string'), get(handleList.offsetMax, 'string'),...
get(handleList.dataFilterType, 'value'), get(handleList.dataFilterLength, 'string'),...
get(handleList.derFilterType, 'value'), get(handleList.derFilterLength, 'string'),...
get(handleList.debugging, 'value'), get(handleList.alphaFit, 'value'),...
get(handleList.derThresh, 'string'), get(handleList.errThresh, 'string'),...
get(handleList.closestPSPs, 'string'), get(handleList.decayFit, 'value'),...
get(handleList.riseFit, 'value'), get(get(handleList.PSPtype,'SelectedObject'), 'tag')});
uimenu(get(varargin{1},'parent'),'Label',tempName,'callback', @setPreset);
function removePreset(varargin)
tempPresets = getpref('pspGUI','presets');
for i = 1:numel(tempPresets)
prettyPresets{i} = tempPresets{i}(7:end);
end
[selection,isOK] = listdlg('PromptString','Select presets to delete:',...
'SelectionMode','multiple',...
'okstring','Delete',...
'ListString',prettyPresets);
if isOK
for i = 1:numel(tempPresets)
if ismember(i,selection)
rmpref('pspGUI',tempPresets{i});
delete(findobj('parent', get(varargin{1}, 'parent'), 'Label', tempPresets{i}(7:end)));
end
end
setpref('pspGUI','presets',tempPresets(selection));
end
function setPreset(varargin)
tempPreset = getpref('pspGUI',['preset' get(varargin{1}, 'Label')]);
handleList = getappdata(0, 'pspDetector');
set(handleList.ampMin, 'string', tempPreset{1});
set(handleList.ampMax, 'string', tempPreset{2});
set(handleList.alphaTauMin, 'string', tempPreset{3});
set(handleList.alphaTauMax, 'string', tempPreset{4});
set(handleList.decayMin, 'string', tempPreset{5});
set(handleList.decayMax, 'string', tempPreset{6});
set(handleList.offsetMin, 'string', tempPreset{7});
set(handleList.offsetMax, 'string', tempPreset{8});
set(handleList.dataFilterType, 'value', tempPreset{9});
set(handleList.dataFilterLength, 'string', tempPreset{10});
set(handleList.derFilterType, 'value', tempPreset{11});
set(handleList.derFilterLength, 'string', tempPreset{12});
set(handleList.debugging, 'value', tempPreset{13});
set(handleList.alphaFit, 'value', tempPreset{14});
set(handleList.derThresh, 'string', tempPreset{15});
set(handleList.errThresh, 'string', tempPreset{16});
set(handleList.closestPSPs, 'string', tempPreset{17});
set(handleList.decayFit, 'value', tempPreset{18});
set(handleList.riseFit, 'value', tempPreset{19});
set(handleList.PSPtype, 'SelectedObject', handleList.(tempPreset{20}));