https://github.com/JohnTyCa/The-SPN-Catalogue
Tip revision: 35eb549c1963f083f6fc5d4442f6b5c6f52cb6d3 authored by JohnTyCa on 25 February 2022, 13:13:03 UTC
Update README.md
Update README.md
Tip revision: 35eb549
SPNCAT_func.m
classdef SPNCAT_func < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure
GridLayout matlab.ui.container.GridLayout
LeftPanel matlab.ui.container.Panel
ProjectsListBox matlab.ui.control.ListBox
Experiment1Panel matlab.ui.container.Panel
Experiment1ListBox matlab.ui.control.ListBox
ClusterDropDownLabel matlab.ui.control.Label
Cluster1DropDown matlab.ui.control.DropDown
TimeDropDownLabel matlab.ui.control.Label
Time1DropDown matlab.ui.control.DropDown
StartEditFieldLabel matlab.ui.control.Label
Start1EditField matlab.ui.control.NumericEditField
EndEditFieldLabel matlab.ui.control.Label
End1EditField matlab.ui.control.NumericEditField
Electrodes1ListBox matlab.ui.control.ListBox
Experiment2Panel matlab.ui.container.Panel
Experiment2ListBox matlab.ui.control.ListBox
Electrodes2ListBox matlab.ui.control.ListBox
ClusterDropDownLabel_2 matlab.ui.control.Label
Cluster2DropDown matlab.ui.control.DropDown
TimeDropDownLabel_2 matlab.ui.control.Label
Time2DropDown matlab.ui.control.DropDown
StartEditFieldLabel_2 matlab.ui.control.Label
Start2EditField matlab.ui.control.NumericEditField
EndEditFieldLabel_2 matlab.ui.control.Label
End2EditField matlab.ui.control.NumericEditField
Experiment3Panel matlab.ui.container.Panel
Experiment3ListBox matlab.ui.control.ListBox
Electrodes3ListBox matlab.ui.control.ListBox
ClusterDropDownLabel_3 matlab.ui.control.Label
Cluster3DropDown matlab.ui.control.DropDown
TimeDropDownLabel_3 matlab.ui.control.Label
Time3DropDown matlab.ui.control.DropDown
StartEditFieldLabel_3 matlab.ui.control.Label
Start3EditField matlab.ui.control.NumericEditField
EndEditFieldLabel_3 matlab.ui.control.Label
End3EditField matlab.ui.control.NumericEditField
Experiment4Panel matlab.ui.container.Panel
Experiment4ListBox matlab.ui.control.ListBox
Electrodes4ListBox matlab.ui.control.ListBox
ClusterDropDownLabel_4 matlab.ui.control.Label
Cluster4DropDown matlab.ui.control.DropDown
TimeDropDownLabel_4 matlab.ui.control.Label
Time4DropDown matlab.ui.control.DropDown
StartEditFieldLabel_4 matlab.ui.control.Label
Start4EditField matlab.ui.control.NumericEditField
EndEditFieldLabel_4 matlab.ui.control.Label
End4EditField matlab.ui.control.NumericEditField
Experiment5Panel matlab.ui.container.Panel
Experiment5ListBox matlab.ui.control.ListBox
Electrodes5ListBox matlab.ui.control.ListBox
ClusterDropDownLabel_5 matlab.ui.control.Label
Cluster5DropDown matlab.ui.control.DropDown
TimeDropDownLabel_5 matlab.ui.control.Label
Time5DropDown matlab.ui.control.DropDown
StartEditFieldLabel_5 matlab.ui.control.Label
Start5EditField matlab.ui.control.NumericEditField
EndEditFieldLabel_5 matlab.ui.control.Label
End5EditField matlab.ui.control.NumericEditField
RightPanel matlab.ui.container.Panel
PlotButton matlab.ui.control.StateButton
DifferenceWaveButton matlab.ui.control.StateButton
PlotIrregularButton matlab.ui.control.StateButton
UITableSPN matlab.ui.control.Table
DiaryOutput matlab.ui.control.TextArea
ExportButton matlab.ui.control.Button
UIAxesWaveform matlab.ui.control.UIAxes
UIAxesBar matlab.ui.control.UIAxes
end
% Properties that correspond to apps with auto-reflow
properties (Access = private)
onePanelWidth = 576;
end
properties (Access = private)
MAXEXP = 5; % Max number of experiments for UI.
CONDITIONS = struct(); % Details conditions and their corresponding file names.
INITIATED = 0;
DFILE = 'DiaryOutput';
ExportApp;
VALIDATE;
CATALOGUELOADED;
end
properties (Access = public)
PROJECTS = struct(); % Structure detailing all aspects of projects.
CURRENTPROJECT = struct(); % All details of current project selected.
E; % Electrode locations.
PROJECT;
EXP;
CAT;
DATADIR;
Dependencies_Folder;
APPENDIX;
end
methods (Access = private)
function ThrowError(app,ME)
% Displays the report for the exception ME in a dialog box.
ErrorReport = getReport(ME,'extended','hyperlinks','off');
Stack = dbstack;
FunctionString = Stack(2).name;
errordlg(ErrorReport,['Error in ' FunctionString]);
end
function UpdateDiary(app)
% Updates the output window in the APP with the most recent
% Diary Output.
try
DiaryData = fileread(app.DFILE);
app.DiaryOutput.Value = DiaryData;
catch ME
ThrowError(app,ME);
end
end
function SelectConditions(app,Selection)
% Selects a subset of the CONDITIONS in the EXPERIMENT LISTBOX.
% This is useful for when the project is changed and we need to
% automatically select some conditions so that the data can be
% extracted properly.
UniqueExperiments = unique({app.CURRENTPROJECT.Experiment});
try
if strcmp(Selection,'all')
for iExp = 1:length(UniqueExperiments)
app.(['Experiment' num2str(iExp) 'ListBox']).Value = app.(['Experiment' num2str(iExp) 'ListBox']).ItemsData;
end
elseif strcmp(Selection,'first')
for iExp = 1:length(UniqueExperiments)
app.(['Experiment' num2str(iExp) 'ListBox']).Value = app.(['Experiment' num2str(iExp) 'ListBox']).ItemsData(1);
end
elseif isempty(Selection)
if app.PlotButton.Value
for iExp = 1:length(UniqueExperiments)
app.(['Experiment' num2str(iExp) 'ListBox']).Value = [app.CURRENTPROJECT(strcmp({app.CURRENTPROJECT.Experiment},UniqueExperiments{iExp}) & [app.CURRENTPROJECT.Plot_Selection]).SPNID];
end
else
for iExp = 1:length(UniqueExperiments)
app.(['Experiment' num2str(iExp) 'ListBox']).Value = [app.CURRENTPROJECT(strcmp({app.CURRENTPROJECT.Experiment},UniqueExperiments{iExp}) & [app.CURRENTPROJECT.Configure_Selection]).SPNID];
end
end
end
catch ME
ThrowError(app,ME);
end
UpdateDiary(app);
end
function ExtractPlotData(app)
% Extracts the data required for plotting the current project.
try
% =================================================== %
% Extract the REGULARITY condition first.
% =================================================== %
for iCond = 1:length(app.CURRENTPROJECT)
% =============================================== %
% Based on the options selected for each EXPERIMENT
% and CONDITION, we only want to select the
% ELECTRODES and TIMEPOINTS of interest.
% =============================================== %
ElectrodeSelection = app.CURRENTPROJECT(iCond).Cluster_Options_Electrodes;
Time_Windows = app.CURRENTPROJECT(iCond).Cluster_Options_Time;
Time_Windows(ismember(Time_Windows,{'and', 'to'})) = [];
TimeSelection = cellfun(@str2num,Time_Windows);
% =============================================== %
% Get the indices for the desired ELECTRODES and
% TIMEPOINTS from the respective variables.
% =============================================== %
ElectrodeIndices = ismember({app.E.labels}, ElectrodeSelection);
TimeIndices = app.CURRENTPROJECT(iCond).TimeVector >= TimeSelection(1) & app.CURRENTPROJECT(iCond).TimeVector <= TimeSelection(2);
% =============================================== %
% Extract the data for both REGULARITY and
% IRREGULARITY.
% =============================================== %
PlotData_All = app.CURRENTPROJECT(iCond).Data;
PlotData_All_Irregular = app.CURRENTPROJECT(iCond).Data_Irregular;
% =============================================== %
% If we want to plot the difference wave, as
% indicated by the DIFFERENCEWAVEBUTTON, we
% subtract the IRREGULARITY data from the
% REGULARITY data.
% =============================================== %
if app.DifferenceWaveButton.Value
PlotData_All = PlotData_All - PlotData_All_Irregular;
end
% =============================================== %
% Get the average across the selected ELECTRODES.
% =============================================== %
PlotData_ElectrodeMean = squeeze(mean(PlotData_All(ElectrodeIndices,:,:),1));
PlotData_Irregular_ElectrodeMean = squeeze(mean(PlotData_All_Irregular(ElectrodeIndices,:,:),1));
% =============================================== %
% Get the average across the TIMEPOINTS for the
% selected ELECTRODES.
% =============================================== %
PlotData_MeanInRange = mean(PlotData_ElectrodeMean(TimeIndices,:),1);
PlotData_Irregular_MeanInRange = mean(PlotData_Irregular_ElectrodeMean(TimeIndices,:),1);
% =============================================== %
% Here is where we assign an extra suffix depending
% on whether REGULARITY was attended to or now.
% This is to differentiate identical conditions
% that only differ in terms of attention.
% =============================================== %
if app.CURRENTPROJECT(iCond).Attend_Regularity
NameSuffix = '(Attend Reg)';
else
NameSuffix = '(Disregard Reg)';
end
% =============================================== %
% Add the necessary information for each CONDITION,
% including the plot data and the name of the
% condition. We also define the LEGENDNAME
% variable, a variable containing a list of names
% indicating whether REGULARITY was attended to or
% now. This is important for differentiating
% conditions.
% =============================================== %
app.CURRENTPROJECT(iCond).PlotData = mean(PlotData_ElectrodeMean,2);
app.CURRENTPROJECT(iCond).PlotData_Irregular = mean(PlotData_Irregular_ElectrodeMean,2);
app.CURRENTPROJECT(iCond).PlotData_LegendName = ['(' num2str(app.CURRENTPROJECT(iCond).SPNID) ') ' app.CURRENTPROJECT(iCond).Full_Name ' ' NameSuffix];
app.CURRENTPROJECT(iCond).PlotData_MeanInRange = PlotData_MeanInRange;
app.CURRENTPROJECT(iCond).PlotData_Irregular_MeanInRange = PlotData_Irregular_MeanInRange;
app.CURRENTPROJECT(iCond).PlotData_Time = TimeSelection;
app.CURRENTPROJECT(iCond).PlotData_Electrodes = ElectrodeSelection;
app.CURRENTPROJECT(iCond).PlotData_TimeVector = app.CURRENTPROJECT(iCond).TimeVector;
end
% ======================================================= %
% Since some projects have different time vectors, we need to
% create an "average" time series. Combining multiple time
% vectors and interpolating values might produce interpolated
% values asymmetrically across the time series, thus changing
% the mean. Hence, we will assume that the time vectors for any
% single experiment all have the same starting point and
% sampling rate. This SHOULD produce the same time samples up
% until the point at which they diverge, hopefully at the end
% of the respective epochs rather than within them. This way,
% the size of the time vectors can simply be padded with NaN
% values at the end.
% ======================================================= %
CurrentTimeVectors = {app.CURRENTPROJECT.PlotData_TimeVector}';
MinValue = cellfun(@min,CurrentTimeVectors);
MaxValue = cellfun(@max,CurrentTimeVectors);
if length(unique(MinValue)) > 1
error('Epochs have different starting times. You will have to figure out another way of equalising time vector lengths.')
end
% ======================================================= %
% We find the epoch with the latest value and create a
% unified TIMEVECTOR, with the conditions that do not
% contain those values simply being padded with NAN values.
% ======================================================= %
LongestTimeVector = CurrentTimeVectors{find(MaxValue == max(MaxValue))};
if length(unique(MaxValue)) > 1
MaxLength = max(cellfun(@length,{app.CURRENTPROJECT.PlotData}));
for iCond = 1:length(app.CURRENTPROJECT)
if length(app.CURRENTPROJECT(iCond).PlotData) < MaxLength
app.CURRENTPROJECT(iCond).PlotData(end+1:MaxLength) = NaN;
end
end
end
% ======================================================= %
% Remove conditions we do not want to plot.
% ======================================================= %
PLOT = [];
PLOT.PLOTDATA = struct();
for iCond = 1:length(app.CURRENTPROJECT)
PLOT.PLOTDATA(iCond).SPNID = app.CURRENTPROJECT(iCond).SPNID;
PLOT.PLOTDATA(iCond).Full_Name = app.CURRENTPROJECT(iCond).Full_Name;
PLOT.PLOTDATA(iCond).Regular_Condition = app.CURRENTPROJECT(iCond).Regular_Condition;
PLOT.PLOTDATA(iCond).Irregular_Condition = app.CURRENTPROJECT(iCond).Irregular_Condition;
PLOT.PLOTDATA(iCond).Window_Original = app.CURRENTPROJECT(iCond).Window_Original;
PLOT.PLOTDATA(iCond).Plot_Data = app.CURRENTPROJECT(iCond).PlotData;
PLOT.PLOTDATA(iCond).Plot_Data_Irregular = app.CURRENTPROJECT(iCond).PlotData_Irregular;
PLOT.PLOTDATA(iCond).Legend = app.CURRENTPROJECT(iCond).PlotData_LegendName;
PLOT.PLOTDATA(iCond).Mean_in_Range = app.CURRENTPROJECT(iCond).PlotData_MeanInRange;
PLOT.PLOTDATA(iCond).Mean_in_Range_Irregular = app.CURRENTPROJECT(iCond).PlotData_Irregular_MeanInRange;
PLOT.PLOTDATA(iCond).Mean_Original_SPN = app.CURRENTPROJECT(iCond).SPN;
PLOT.PLOTDATA(iCond).Plot_Selection = app.CURRENTPROJECT(iCond).Plot_Selection;
end
PLOT.PLOTDATA(~[PLOT.PLOTDATA.Plot_Selection]) = [];
% ======================================================= %
% Assign irregular conditions to plot variable.
% ======================================================= %
if ~app.DifferenceWaveButton.Value && app.PlotIrregularButton.Value
UniqueExperiments = unique({PLOT.PLOTDATA.Full_Name});
for iExp = 1:length(UniqueExperiments)
Experiment_Index = strcmp({PLOT.PLOTDATA.Full_Name},UniqueExperiments{iExp});
Experiment_Irregular_Conditions = unique({PLOT.PLOTDATA(Experiment_Index).Irregular_Condition});
for iCond = 1:length(Experiment_Irregular_Conditions)
Condition_Index = find(Experiment_Index & strcmp({PLOT.PLOTDATA.Irregular_Condition},Experiment_Irregular_Conditions{iCond}));
Experiment_Index(end+1) = 0;
PLOT.PLOTDATA(end+1) = PLOT.PLOTDATA(Condition_Index(end));
PLOT.PLOTDATA(end).Plot_Data = PLOT.PLOTDATA(end).Plot_Data_Irregular;
PLOT.PLOTDATA(end).Mean_in_Range = PLOT.PLOTDATA(end).Mean_in_Range_Irregular;
PLOT.PLOTDATA(end).Legend = [PLOT.PLOTDATA(end).Full_Name ' (' PLOT.PLOTDATA(end).Irregular_Condition ')'];
end
end
PLOT.PLOTDATA = table2struct(sortrows(struct2table(PLOT.PLOTDATA),'SPNID'));
end
% ======================================================= %
% Now that we have the longest time vector, we can extract
% plot data. First, we extract the line data for the plots,
% the legend and the TIMEVECTOR.
% ======================================================= %
PLOT.Line_Data = cat(2,PLOT.PLOTDATA.Plot_Data);
PLOT.Legend = strrep({PLOT.PLOTDATA.Legend},'_',' ');
PLOT.Time = LongestTimeVector;
% ======================================================= %
% Get the MEAN and STD for each condition.
% ======================================================= %
PLOT.Mean_in_Range = cellfun(@double,cellfun(@mean,{PLOT.PLOTDATA.Mean_in_Range},'UniformOutput',false));
PLOT.STD_in_Range = cellfun(@double,cellfun(@std,{PLOT.PLOTDATA.Mean_in_Range},'UniformOutput',false));
PLOT.N = cellfun(@length,{PLOT.PLOTDATA.Mean_in_Range});
PLOT.Mean_Original_SPN = [PLOT.PLOTDATA.Mean_Original_SPN];
% ======================================================= %
% Let's give some warnings about values that do not match
% the catalogue with respect to mean SPN amplitude, but
% only when plotting ORIGINAL ELECTRODES and TIME, as well
% as the DIFFERENCE WAVE, as these are the values used in
% the catalogue. We will use a sensible tolerance here. We
% do not care if the values do not match to 10 decimal
% places, so we will set it to 10^-5.
% ======================================================= %
if app.CATALOGUELOADED && app.DifferenceWaveButton.Value
MultipleWindows = 0;
for iCond = 1:length(PLOT.PLOTDATA)
if length(PLOT.PLOTDATA(iCond).Window_Original) > 2
MultipleWindows = 1;
end
end
Tolerance = 10^-5;
for iCond = 1:length(PLOT.PLOTDATA)
if abs(PLOT.Mean_in_Range(iCond) - PLOT.Mean_Original_SPN(iCond)) > Tolerance
if ~MultipleWindows
warning([PLOT.Legend{iCond} ' - SPN Mean in CAT_ORIG (' num2str(round(PLOT.Mean_Original_SPN(iCond),5)) ') does not match that extracted here (' num2str(round(PLOT.Mean_in_Range(iCond),5)) ' - Difference of ' num2str(PLOT.Mean_in_Range(iCond) - PLOT.Mean_Original_SPN(iCond)) ').'])
end
end
end
app.CATALOGUELOADED = 0;
end
% ======================================================= %
% We want to present a table within the APP that details
% means, std's, N, etc. Hence, we build a table variable to
% be used later, with each column representing a condition.
% ======================================================= %
PLOT.TableColumns = PLOT.Legend;
PLOT.TableColumns = strrep(strrep(PLOT.TableColumns,';','_'),' ','');
StringInput = repmat('nan(6,1),',1,length(PLOT.Legend));
StringInput(end) = [];
PLOT.Table = eval(['table(' StringInput ')']);
PLOT.Table.Properties.RowNames = {'SPN' 'SD' 'D' 'N' 't' 'p'};
PLOT.Table.Properties.VariableNames = PLOT.TableColumns;
for iCond = 1:length(PLOT.Legend)
ColumnName = PLOT.TableColumns{iCond};
PLOT.Table.(ColumnName)(1,1) = PLOT.Mean_in_Range(iCond);
PLOT.Table.(ColumnName)(2,1) = PLOT.STD_in_Range(iCond);
PLOT.Table.(ColumnName)(3,1) = PLOT.Mean_in_Range(iCond)/PLOT.STD_in_Range(iCond);
PLOT.Table.(ColumnName)(4,1) = PLOT.N(iCond);
PLOT.Table.(ColumnName)(5,1) = PLOT.Table.(ColumnName)(3,1) * sqrt(PLOT.N(iCond));
[~,PLOT.Table.(ColumnName)(6,1)] = ttest(PLOT.PLOTDATA(iCond).Mean_in_Range);
end
% ======================================================= %
% Now that the table has been built, we put the table
% inside the UITABLE.
% ======================================================= %
app.UITableSPN.Data = PLOT.Table;
app.UITableSPN.RowName = PLOT.Table.Properties.RowNames;
app.UITableSPN.ColumnName = PLOT.Table.Properties.VariableNames;
% app.UITableSPN.ColumnFormat = repmat({'bank'},1,length(PLOT.Legend));
app.UITableSPN.Visible = 1;
% ======================================================= %
% Determine XTick for the line plot and set the UIAXES
% XTICK property.
% ======================================================= %
if any(PLOT.Time > 100)
TimeFormat = 'ms';
PLOT.StartEnd = [round(PLOT.Time(1),-2) round(PLOT.Time(end),-2)];
PLOT.Intervals = ((PLOT.StartEnd(2) - PLOT.StartEnd(1)) / 100) + 1;
PLOT.NewTime = linspace(PLOT.StartEnd(1),PLOT.StartEnd(2),PLOT.Intervals);
else
TimeFormat = 's';
PLOT.StartEnd = [round(PLOT.Time(1),1) round(PLOT.Time(end),1)];
PLOT.Intervals = ((PLOT.StartEnd(2) - PLOT.StartEnd(1)) / 0.1) + 1;
PLOT.NewTime = linspace(PLOT.StartEnd(1),PLOT.StartEnd(2),PLOT.Intervals);
end
set(app.UIAxesWaveform,'XTick',PLOT.NewTime);
% ======================================================= %
% Clear the UIAXESWAVEFORM, then plot the waveform.
% ======================================================= %
cla(app.UIAxesWaveform);
for iLine = 1:size(PLOT.Line_Data,2)
plot(app.UIAxesWaveform,PLOT.Time,PLOT.Line_Data(:,iLine));
if ~ishold(app.UIAxesWaveform)
hold(app.UIAxesWaveform,'on');
end
end
legend(app.UIAxesWaveform,PLOT.Legend);
hold(app.UIAxesWaveform,'off');
% ======================================================= %
% We do some maths to get an appropriate value
% for the Y AXIS.
% ======================================================= %
MinVal = min(PLOT.Line_Data,[],'all');
MaxVal = max(PLOT.Line_Data,[],'all');
if MinVal < 0
MinVal = MinVal*1.2;
else
MinVal = MinVal - (MinVal*0.2);
end
if MaxVal < 0
MaxVal = MaxVal + (MaxVal*0.2);
else
MaxVal = MaxVal*1.2;
end
axis(app.UIAxesWaveform,[PLOT.NewTime(1) PLOT.NewTime(end) MinVal MaxVal])
% ======================================================= %
% Now we do some general configuration to make the plot
% look a bit nicer.
% ======================================================= %
grid(app.UIAxesWaveform,'on');
box(app.UIAxesWaveform,'on');
set(app.UIAxesWaveform, 'XTickMode', 'auto', 'XTickLabelMode', 'auto')
app.UIAxesWaveform.XLabel.String = ['Time (' TimeFormat ')'];
app.UIAxesWaveform.YLabel.String = 'Amplitude (uV)';
app.UIAxesWaveform.Visible = 1;
% ======================================================= %
% Plot and configure the bar chart containing mean values.
% ======================================================= %
cla(app.UIAxesBar);
BarHandle = bar(app.UIAxesBar,1:length(PLOT.Mean_in_Range),PLOT.Mean_in_Range);
hold(app.UIAxesBar,'on');
ErrorHandle = errorbar(app.UIAxesBar,PLOT.Mean_in_Range,PLOT.STD_in_Range);
ErrorHandle.Color = [0 0 0];
ErrorHandle.LineStyle = 'none';
grid(app.UIAxesBar,'on');
box(app.UIAxesBar,'on');
set(app.UIAxesBar,'XTick',1:length(PLOT.Legend));
set(app.UIAxesBar,'XTickLabel',PLOT.Legend);
app.UIAxesBar.XLabel.String = 'Condition';
app.UIAxesBar.YLabel.String = 'Mean Amplitude (uV)';
yline(app.UIAxesBar,0,'LineWidth',2);
hold(app.UIAxesBar,'off');
app.UIAxesBar.Visible = 1;
drawnow;
catch ME
ThrowError(app,ME);
end
UpdateDiary(app);
end
function RefreshExperimentLists(app)
% Refreshes the EXPERIMENT LSITBOX for each experiment to the
% values inside the CURRENTPROJECT structure.
try
UniqueExperiments = unique({app.CURRENTPROJECT.Experiment});
for iExp = 1:length(UniqueExperiments)
% =================================================== %
% This will only run if there are actually conditions
% that have been selected in the EXPERIMENTS LISTBOX.
% ======================================================= %
value = app.(['Experiment' num2str(iExp) 'ListBox']).Value;
if isempty(value)
continue
end
for iVal = value
ConditionIndex = find([app.CURRENTPROJECT.SPNID] == iVal);
ElectrodeSelection = app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes;
TimeSelection = app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Time;
ElectrodeOption = app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes_Option;
TimeOption = app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Time_Option;
ElectrodeSelection = unique(ElectrodeSelection);
app.(['Electrodes' num2str(iExp) 'ListBox']).Value = ElectrodeSelection;
app.(['Start' num2str(iExp) 'EditField']).Value = str2num(TimeSelection{1});
app.(['End' num2str(iExp) 'EditField']).Value = str2num(TimeSelection{2});
app.(['Cluster' num2str(iExp) 'DropDown']).Value = ElectrodeOption;
app.(['Time' num2str(iExp) 'DropDown']).Value = TimeOption;
end
end
catch ME
ThrowError(app,ME);
end
UpdateDiary(app);
end
function ParametersStatusCheck(app)
% This enables and disables the appropriate editable fields
% depending on whether conditions have been selected in the
% EXPERIMENTS LISTBOX for each EXPERIMENT.
try
UniqueExperiments = unique({app.CURRENTPROJECT.Experiment});
for iExp = 1:length(UniqueExperiments)
% =================================================== %
% Get the selected experiments and whether plotting is
% enabled.
% =================================================== %
SelectedExperiments = app.(['Experiment' num2str(iExp) 'ListBox']).Value;
PlottingEnabled = app.PlotButton.Value;
% =================================================== %
% Enable/disable multiselect depending on whether
% plotting is enabled.
% =================================================== %
app.(['Experiment' num2str(iExp) 'ListBox']).Multiselect = PlottingEnabled;
% =================================================== %
% If plotting is enabled, disable all boxes, besides
% the experiments listbox. If plotting is disabled and
% experiments are not selected, disable all boxes
% besides the experiments listbox. If plotting is
% disabled and experiments are selected, enable the
% cluster and time drop down boxes. If CUSTOM is
% selected for any box, enable the appropriate boxes.
% =================================================== %
if PlottingEnabled
app.(['Cluster' num2str(iExp) 'DropDown']).Enable = 0;
app.(['Time' num2str(iExp) 'DropDown']).Enable = 0;
app.(['Electrodes' num2str(iExp) 'ListBox']).Enable = 0;
app.(['Start' num2str(iExp) 'EditField']).Enable = 0;
app.(['End' num2str(iExp) 'EditField']).Enable = 0;
elseif isempty(SelectedExperiments)
app.(['Cluster' num2str(iExp) 'DropDown']).Enable = 0;
app.(['Time' num2str(iExp) 'DropDown']).Enable = 0;
app.(['Electrodes' num2str(iExp) 'ListBox']).Enable = 0;
app.(['Start' num2str(iExp) 'EditField']).Enable = 0;
app.(['End' num2str(iExp) 'EditField']).Enable = 0;
else
app.(['Cluster' num2str(iExp) 'DropDown']).Enable = 1;
app.(['Time' num2str(iExp) 'DropDown']).Enable = 1;
TimeOption = app.(['Time' num2str(iExp) 'DropDown']).Value;
ElectrodeOption = app.(['Cluster' num2str(iExp) 'DropDown']).Value;
% =============================================== %
% Configure time.
% =============================================== %
if strcmp(TimeOption, 'Custom')
app.(['Start' num2str(iExp) 'EditField']).Enable = 1;
app.(['End' num2str(iExp) 'EditField']).Enable = 1;
else
app.(['Start' num2str(iExp) 'EditField']).Enable = 0;
app.(['End' num2str(iExp) 'EditField']).Enable = 0;
end
% =============================================== %
% Configure electrodes.
% =============================================== %
if strcmp(ElectrodeOption, 'Custom')
app.(['Electrodes' num2str(iExp) 'ListBox']).Enable = 1;
else
app.(['Electrodes' num2str(iExp) 'ListBox']).Enable = 0;
end
end
end
catch ME
ThrowError(app,ME);
end
end
% % % function [PROJECT,EXP,CAT,APPENDIX,VALIDATE] = CreateSimplifiedCatalogue(app)
% % %
% % % % ======================================================= %
% % % % Read CAT_ORIG file.
% % % % ======================================================= %
% % %
% % % CAT_ORIG = readtable('Catalogue.csv');
% % %
% % % APPENDIX_opts = detectImportOptions('Appendix.csv');
% % % APPENDIX_opts = setvaropts(APPENDIX_opts,{'SET_Suffix' 'SET_ICA_Suffix' 'SET_ICA_Max_Suffix'},'WhiteSpaceRule','preserve');
% % % APPENDIX = readtable('Appendix.csv',APPENDIX_opts);
% % %
% % % % ======================================================= %
% % % % Remove NaN rows.
% % % % ======================================================= %
% % %
% % % CAT_ORIG(find(isnan(table2array(CAT_ORIG(2:end,1))))+1,:) = [];
% % %
% % % % ======================================================= %
% % % % Let's get the mean SPN for the original clusters to do
% % % % some validation later.
% % % % ======================================================= %
% % %
% % % VALIDATE = table(CAT_ORIG.ProjectFolder, CAT_ORIG.SubFolder, CAT_ORIG.SPNID, CAT_ORIG.M, CAT_ORIG.SD, CAT_ORIG.M_1,CAT_ORIG.M_2,CAT_ORIG.M_3,CAT_ORIG.D,'VariableNames',{'Project' 'Experiment' 'SPNID' 'MeanSPN' 'SPN_SD' 'MeanSPN1' 'MeanSPN2' 'MeanSPN3' 'D'});
% % %
% % % % ======================================================= %
% % % % We are only interested in certain columns of CAT_ORIG. Some
% % % % columns have duplicate names so we need to avoid them.
% % % % ======================================================= %
% % %
% % % CAT_ORIG = CAT_ORIG(:,1:26);
% % %
% % % % ======================================================= %
% % % % Extract appropriate columns and rename as necessary.
% % % % ======================================================= %
% % %
% % % Titles = CAT_ORIG.Properties.VariableNames;
% % % % Titles = CAT_ORIG(1,:);
% % % ColsToKeep = find(~cell2mat(cellfun(@(x) isnumeric(x), Titles, 'UniformOutput',false)));
% % % Titles = Titles(ColsToKeep);
% % % ColToRename = find(cellfun(@(x) ~isempty(str2num(x(1))),Titles));
% % % Titles(ColToRename) = cellfun(@(x) ['C' x],Titles(ColToRename),'UniformOutput',false);
% % % Titles = strrep(strrep(strrep(Titles,' ',''),'.','_'),'%','');
% % %
% % % % ======================================================= %
% % % % Extract appropriate portion of catlogue.
% % % % ======================================================= %
% % %
% % % CAT_ORIG = CAT_ORIG(:,ColsToKeep);
% % % CAT_ORIG = table2struct(CAT_ORIG);
% % %
% % % % ======================================================= %
% % % % Create simplified catalogue.
% % % % ======================================================= %
% % %
% % % CAT = table();
% % %
% % % CAT.SPNID = [CAT_ORIG.SPNID]';
% % % CAT.Project = [CAT_ORIG.ProjectFolder]';
% % %
% % % for iCond = 1:length(CAT_ORIG)
% % % CAT.Experiment{iCond,1} = strrep(strrep(CAT_ORIG(iCond).SubFolder,'N/A','EX1'),'Sup EX','SX');
% % % CAT.Experiment{iCond,1} = CAT.Experiment{iCond,1}(1:3);
% % % CAT.Full_Name{iCond,1} = ['P' nDigitString(CAT.Project(iCond,1),3) '_' CAT.Experiment{iCond,1}];
% % % end
% % %
% % % CAT.Experiment_Folder = {CAT_ORIG.SubFolder}';
% % %
% % % CAT.N = [CAT_ORIG.NInCondition]';
% % % CAT.AKA = {CAT_ORIG.NickName}';
% % % CAT.Year = {CAT_ORIG.Year}';
% % % CAT.Regular_Condition = {CAT_ORIG.Regular}';
% % % CAT.Irregular_Condition = {CAT_ORIG.LessRegularComparision}';
% % %
% % % CAT.Electrodes_Original = cellfun(@(x) strsplit(x,{',',' '}), {CAT_ORIG.OriginalElectrodeCluster},'UniformOutput',false)';
% % % CAT.Electrodes_Cluster_1 = cellfun(@(x) strsplit(x,{',',' '}), {CAT_ORIG.Cluster1},'UniformOutput',false)';
% % % CAT.Electrodes_Cluster_2 = cellfun(@(x) strsplit(x,{',',' '}), {CAT_ORIG.Cluster2},'UniformOutput',false)';
% % % CAT.Electrodes_Cluster_3 = cellfun(@(x) strsplit(x,{',',' '}), {CAT_ORIG.Cluster3},'UniformOutput',false)';
% % % CAT.Electrodes_Custom = cellfun(@(x) strsplit(x,{',',' '}), {CAT_ORIG.OriginalElectrodeCluster},'UniformOutput',false)';
% % % CAT.Window_Original = cellfun(@(x) strsplit(x,{',' ' ' '-'}), {CAT_ORIG.OriginalTimeWindow},'UniformOutput',false)';
% % % % CAT.Window_Cluster = cellfun(@(x) strsplit(x,{',' ' ' '-'}), {CAT_ORIG.TimeWindowForClusters},'UniformOutput',false)';
% % % CAT.Window_Custom = cellfun(@(x) strsplit(x,{',' ' ' '-'}), {CAT_ORIG.OriginalTimeWindow},'UniformOutput',false)';
% % %
% % % CAT.Attend_Regularity = [CAT_ORIG.AttendRegularity]';
% % % CAT.W = [CAT_ORIG.WCalculation]';
% % % CAT.SPN = VALIDATE.MeanSPN;
% % % CAT.SD = VALIDATE.SPN_SD;
% % % CAT.D = VALIDATE.D;
% % % CAT.SPN1 = VALIDATE.MeanSPN1;
% % % CAT.SPN2 = VALIDATE.MeanSPN2;
% % % CAT.SPN3 = VALIDATE.MeanSPN3;
% % %
% % % CAT.Regular_Prefix = APPENDIX.Prefix_Regular;
% % % CAT.Irregular_Prefix = APPENDIX.Prefix_Irregular;
% % %
% % % CAT.Regular_Prefix_AllData = APPENDIX.Prefix_Regular_AllData;
% % % CAT.Irregular_Prefix_AllData = APPENDIX.Prefix_Irregular_AllData;
% % %
% % % CAT.Time_Vector_Name = APPENDIX.TimeVectorName;
% % %
% % % CAT.Post_AVG_Suffix = APPENDIX.PostAVGSuffix;
% % % CAT.Post_AVG_Suffix_AllData = APPENDIX.PostAVGSuffix_AllData;
% % %
% % % CAT.Skip_Subjects = cellfun(@(x) strsplit(x,'; '),APPENDIX.SkipSubjects,'UniformOutput',false);
% % % CAT.Skip_Subjects = cellfun(@(x) cellfun(@str2num,x,'UniformOutput',false),CAT.Skip_Subjects,'UniformOutput',false);
% % %
% % % CAT.Skip_Subjects_AllData = cellfun(@(x) strsplit(x,'; '),APPENDIX.SkipSubjects_AllData,'UniformOutput',false);
% % % CAT.Skip_Subjects_AllData = cellfun(@(x) cellfun(@str2num,x,'UniformOutput',false),CAT.Skip_Subjects_AllData,'UniformOutput',false);
% % %
% % % CAT.Folder_Override = cellfun(@(x) strsplit(x,'; '), APPENDIX.FolderOverride,'UniformOutput',false);
% % % CAT.Folder_Override_AllData = cellfun(@(x) strsplit(x,'; '), APPENDIX.FolderOverride_AllData,'UniformOutput',false);
% % %
% % % CAT.Condition_Name_Override = APPENDIX.ConditionOverride;
% % %
% % % CAT.Two_Digit_Subject_String = APPENDIX.Two_Digit_Subject_String_Original;
% % % CAT.Two_Digit_Subject_String_AllData = APPENDIX.Two_Digit_Subject_String_AllData;
% % %
% % % CAT.SET_Suffix = APPENDIX.SET_Suffix;
% % % CAT.SET_ICA_Suffix = APPENDIX.SET_ICA_Suffix;
% % % CAT.SET_ICA_Max_Suffix = APPENDIX.SET_ICA_Max_Suffix;
% % %
% % % CAT.Task_Names = APPENDIX.Task_Names;
% % % CAT.File_Notes = APPENDIX.File_Notes;
% % %
% % % CAT = table2struct(CAT);
% % %
% % % % ======================================================= %
% % % % Produce Projects.
% % % % ======================================================= %
% % %
% % % UniqueProjects = unique([CAT.Project]);
% % %
% % % PROJECT = struct();
% % % Count = 0;
% % % for iProject = 1:length(UniqueProjects)
% % %
% % % CurrentProjectIndices = [CAT.Project] == UniqueProjects(iProject);
% % % CurrentProjectCond = CAT(CurrentProjectIndices);
% % %
% % % PROJECT(iProject).Project = CurrentProjectCond(1).Project;
% % % PROJECT(iProject).Experiment = {CurrentProjectCond.Experiment};
% % % PROJECT(iProject).Full_Name = {CurrentProjectCond.Full_Name};
% % % PROJECT(iProject).N = [CurrentProjectCond.N];
% % % PROJECT(iProject).SPNID = [CurrentProjectCond.SPNID];
% % % PROJECT(iProject).Regular_Condition = {CurrentProjectCond.Regular_Condition};
% % % PROJECT(iProject).W = [CurrentProjectCond.W];
% % % PROJECT(iProject).Attend_Regularity = [CurrentProjectCond.Attend_Regularity];
% % %
% % % end
% % %
% % % % ======================================================= %
% % % % Produce Experiments.
% % % % ======================================================= %
% % %
% % % UniqueExperiments = unique({CAT.Full_Name});
% % %
% % % EXP = struct();
% % % Count = 0;
% % % for iExp = 1:length(UniqueExperiments)
% % %
% % % CurrentExperimentIndices = strcmp({CAT.Full_Name},UniqueExperiments{iExp});
% % % CurrentExperimentCond = CAT(CurrentExperimentIndices);
% % %
% % % EXP(iExp).Project = CurrentExperimentCond(1).Project;
% % % EXP(iExp).Experiment = CurrentExperimentCond(1).Experiment;
% % % EXP(iExp).Full_Name = CurrentExperimentCond(1).Full_Name;
% % % EXP(iExp).N = CurrentExperimentCond(1).N;
% % % EXP(iExp).SPNID = [CurrentExperimentCond.SPNID];
% % % EXP(iExp).Regular_Condition = {CurrentExperimentCond.Regular_Condition};
% % % EXP(iExp).W = [CurrentExperimentCond.W];
% % % EXP(iExp).Attend_Regularity = [CurrentExperimentCond.Attend_Regularity];
% % %
% % % end
% % %
% % % end
end
methods (Access = public)
% % % function [Condition_Data, Error] = ExtractConditionData(app,SPNID,InfoOnly,varargin)
% % %
% % % % varargin input order:
% % % %
% % % % varargin{1} = BDF
% % % % varargin{2} = SET (Epoched)
% % % % varargin{3} = SET (Epoched, ICA)
% % % % varargin{4} = SET (Epoched, ICA, Max)
% % % % varargin{5} = TriggerInfo
% % %
% % % if length(varargin) == 0
% % % varargin = {0 0 0 0 0};
% % % elseif length(varargin) == 1
% % % varargin = {varargin{1} 0 0 0};
% % % elseif length(varargin) == 2
% % % varargin = {varargin{1} varargin{2} 0 0};
% % % elseif length(varargin) == 3
% % % varargin = {varargin{1} varargin{2} varargin{3} 0};
% % % elseif length(varargin) == 4
% % % varargin = {varargin{1} varargin{2} varargin{3} varargin{4} 0};
% % % end
% % %
% % % Condition_Data = app.CAT([app.CAT.SPNID] == SPNID);
% % %
% % % % ======================================================= %
% % % % Check existence of the REGULARITY condition files.
% % % % ======================================================= %
% % %
% % % Error = 0;
% % %
% % % % =============================================== %
% % % % The suffix is defined based on the corresponding
% % % % SUFFIX from the CONDITIONS file.
% % % % =============================================== %
% % %
% % % Prefix_Reg = Condition_Data.Regular_Prefix;
% % % Prefix_Irreg = Condition_Data.Irregular_Prefix;
% % %
% % % Prefix_Reg_AllData = Condition_Data.Regular_Prefix_AllData;
% % % Prefix_Irreg_AllData = Condition_Data.Irregular_Prefix_AllData;
% % %
% % % PostAVGSuffix = Condition_Data.Post_AVG_Suffix;
% % % PostAVGSuffix_AllData = Condition_Data.Post_AVG_Suffix_AllData;
% % %
% % % Suffix_Reg = [Prefix_Reg 'AVG' PostAVGSuffix '.mat'];
% % % Suffix_Irreg = [Prefix_Irreg 'AVG' PostAVGSuffix '.mat'];
% % %
% % % Suffix_Reg_AllData = [Prefix_Reg_AllData PostAVGSuffix_AllData '.set'];
% % % Suffix_Irreg_AllData = [Prefix_Irreg_AllData PostAVGSuffix_AllData '.set'];
% % %
% % % % =============================================== %
% % % % The folder depends on whether there were multiple
% % % % experiments for the project. For example, if
% % % % there was more than one experiment, the path is
% % % % directed to the corresponding sub folder in the
% % % % PROJECT folder.
% % % % =============================================== %
% % %
% % % Folder = {};
% % % if ~isempty(Condition_Data.Folder_Override{1})
% % % for iFolder = 1:length(Condition_Data.Folder_Override)
% % % Folder{iFolder} = [app.DATADIR filesep 'Project ' num2str(Condition_Data.Project) filesep Condition_Data.Folder_Override{iFolder} filesep];
% % % end
% % % elseif strcmp(Condition_Data.Experiment_Folder,'N/A')
% % % Folder{1} = [app.DATADIR filesep 'Project ' num2str(Condition_Data.Project) filesep];
% % % else
% % % Folder{1} = [app.DATADIR filesep 'Project ' num2str(Condition_Data.Project) filesep Condition_Data.Experiment_Folder filesep];
% % % end
% % %
% % % Folder_AllData = {};
% % % if ~isempty(Condition_Data.Folder_Override_AllData{1})
% % % for iFolder = 1:length(Condition_Data.Folder_Override_AllData)
% % % Folder_AllData{iFolder} = [app.DATADIR filesep 'Project ' num2str(Condition_Data.Project) 'alldata' filesep Condition_Data.Folder_Override_AllData{iFolder} filesep];
% % % end
% % % elseif strcmp(Condition_Data.Experiment_Folder,'N/A')
% % % Folder_AllData{1} = [app.DATADIR filesep 'Project ' num2str(Condition_Data.Project) 'alldata' filesep];
% % % else
% % % Folder_AllData{1} = [app.DATADIR filesep 'Project ' num2str(Condition_Data.Project) 'alldata' filesep Condition_Data.Experiment_Folder filesep];
% % % end
% % %
% % % % =============================================== %
% % % % We extract the subject numbers that are in the
% % % % project folder.
% % % % =============================================== %
% % %
% % % SubjectNumbers_Reg = {}; SubjectFiles_Reg = {};
% % % SubjectNumbers_Irreg = {}; SubjectFiles_Irreg = {};
% % % for iFolder = 1:length(Folder)
% % % [SubjectNumbers_Reg{iFolder}, SubjectFiles_Reg{iFolder}] = CheckFileExistence(app,Folder{iFolder},Suffix_Reg,Condition_Data.Two_Digit_Subject_String);
% % % [SubjectNumbers_Irreg{iFolder}, SubjectFiles_Irreg{iFolder}] = CheckFileExistence(app,Folder{iFolder},Suffix_Irreg,Condition_Data.Two_Digit_Subject_String);
% % % end
% % %
% % % SubjectNumbers_Reg_AllData = {}; SubjectFiles_Reg_AllData = {};
% % % SubjectNumbers_Irreg_AllData = {}; SubjectFiles_Irreg_AllData = {};
% % % for iFolder = 1:length(Folder_AllData)
% % % [SubjectNumbers_Reg_AllData{iFolder}, SubjectFiles_Reg_AllData{iFolder}] = CheckFileExistence(app,Folder_AllData{iFolder},Suffix_Reg_AllData,Condition_Data.Two_Digit_Subject_String_AllData);
% % % [SubjectNumbers_Irreg_AllData{iFolder}, SubjectFiles_Irreg_AllData{iFolder}] = CheckFileExistence(app,Folder_AllData{iFolder},Suffix_Irreg_AllData,Condition_Data.Two_Digit_Subject_String_AllData);
% % % end
% % %
% % % % =============================================== %
% % % % Delete subjects present in the SKIP column.
% % % % =============================================== %
% % %
% % % for iFolder = 1:length(Folder)
% % %
% % % try
% % % SubjectsToSkip = Condition_Data.Skip_Subjects{iFolder};
% % % catch
% % % SubjectsToSkip = [];
% % % end
% % %
% % % DeleteIndices_Reg = ismember(SubjectNumbers_Reg{iFolder},SubjectsToSkip);
% % % SubjectNumbers_Reg{iFolder}(DeleteIndices_Reg) = [];
% % % SubjectFiles_Reg{iFolder}(DeleteIndices_Reg) = [];
% % %
% % % DeleteIndices_Irreg = ismember(SubjectNumbers_Irreg{iFolder},SubjectsToSkip);
% % % SubjectNumbers_Irreg{iFolder}(DeleteIndices_Irreg) = [];
% % % SubjectFiles_Irreg{iFolder}(DeleteIndices_Irreg) = [];
% % %
% % % end
% % %
% % % for iFolder = 1:length(Folder_AllData)
% % %
% % % try
% % % SubjectsToSkip = Condition_Data.Skip_Subjects_AllData{iFolder};
% % % catch
% % % SubjectsToSkip = [];
% % % end
% % %
% % % DeleteIndices_Reg = ismember(SubjectNumbers_Reg_AllData{iFolder},SubjectsToSkip);
% % % SubjectNumbers_Reg_AllData{iFolder}(DeleteIndices_Reg) = [];
% % % SubjectFiles_Reg_AllData{iFolder}(DeleteIndices_Reg) = [];
% % %
% % % DeleteIndices_Irreg = ismember(SubjectNumbers_Irreg_AllData{iFolder},SubjectsToSkip);
% % % SubjectNumbers_Irreg_AllData{iFolder}(DeleteIndices_Irreg) = [];
% % % SubjectFiles_Irreg_AllData{iFolder}(DeleteIndices_Irreg) = [];
% % %
% % % end
% % %
% % % % =============================================== %
% % % % Compare subject numbers between different project
% % % % folders for same exeriment.
% % % % =============================================== %
% % %
% % % if varargin{1} | varargin{2} | varargin{3} | varargin{4}
% % %
% % % if length(cat(2,SubjectNumbers_Reg{:})) ~= length(cat(2,SubjectNumbers_Reg_AllData{:}))
% % % disp(['Subject numbers not the same between original folder and alldata - ' Condition_Data.Full_Name ' (SPN ' num2str(Condition_Data.SPNID) ' Reglar Condition)!']);
% % % disp(['Original Folder = ' num2str(cat(2,SubjectNumbers_Reg{:}))]);
% % % disp(['AllData Folder = ' num2str(cat(2,SubjectNumbers_Reg_AllData{:}))]);
% % % Error = 1;
% % % end
% % %
% % % if length(cat(2,SubjectNumbers_Irreg{:})) ~= length(cat(2,SubjectNumbers_Irreg_AllData{:}))
% % % disp(['Subject numbers not the same between original folder and alldata - ' Condition_Data.Full_Name ' (SPN ' num2str(Condition_Data.SPNID) ' Irregular Condition)!']);
% % % disp(['Original Folder = ' num2str(cat(2,SubjectNumbers_Reg{:}))]);
% % % disp(['AllData Folder = ' num2str(cat(2,SubjectNumbers_Reg_AllData{:}))]);
% % % Error = 1;
% % % end
% % %
% % % end
% % %
% % % % =============================================== %
% % % % We configure some output depending on what we
% % % % would expect. We would expect the SUBJECTNUMBERS
% % % % to correspond to the expected number in the
% % % % catalogue.
% % % % =============================================== %
% % %
% % % if Condition_Data.N ~= length(cat(2,SubjectNumbers_Reg{:})) | Condition_Data.N ~= length(cat(2,SubjectNumbers_Irreg{:}))
% % % disp(['Catalogue reports ' num2str(Condition_Data.N) ' subjects, but ' num2str(length(cat(2,SubjectNumbers_Reg{:}))) ' were found for [' Condition_Data.Full_Name '] - [SPN ' num2str(Condition_Data.SPNID) ' ' Condition_Data.Regular_Prefix ']']);
% % % disp(['Subjects Found = ' num2str(cat(2,SubjectNumbers_Reg{:}))]);
% % % disp(['Catalogue reports ' num2str(Condition_Data.N) ' subjects, but ' num2str(length(cat(2,SubjectNumbers_Irreg{:}))) ' were found for [' Condition_Data.Full_Name '] - [SPN ' num2str(Condition_Data.SPNID) ' ' Condition_Data.Irregular_Prefix ']'])
% % % disp(['Subjects Found = ' num2str(cat(2,SubjectNumbers_Irreg{:}))]);
% % % Error = 1;
% % % elseif ~all(cat(2,SubjectNumbers_Reg{:}) == cat(2,SubjectNumbers_Irreg{:}))
% % % disp(['Subject numbers for [' Condition_Data.Full_Name '] - [SPN ' num2str(num2str(Condition_Data.SPNID)) ' ' Condition_Data.Regular_Prefix '] do not match numbers for [' Condition_Data.Full_Name '] - [SPN ' num2str(num2str(Condition_Data.SPNID)) ' ' Condition_Data.Irregular_Prefix ']']);
% % % Error = 1;
% % % end
% % %
% % % % =========================================== %
% % % % We can assume the BDF files have the same subject numbers as
% % % % the set files, so we just use those subject numbers.
% % % % =========================================== %
% % %
% % % BDF_Files = {};
% % % if varargin{1}
% % % for iFolder = 1:length(Folder_AllData)
% % % for iSub = 1:length(SubjectNumbers_Reg_AllData{iFolder})
% % % if Condition_Data.Two_Digit_Subject_String_AllData
% % % BDF_Files{iFolder}{iSub} = dir([Folder_AllData{iFolder} 'S' nDigitString(SubjectNumbers_Reg_AllData{iFolder}(iSub),2) filesep '*.bdf']);
% % % else
% % % BDF_Files{iFolder}{iSub} = dir([Folder_AllData{iFolder} 'S' num2str(SubjectNumbers_Reg_AllData{iFolder}(iSub)) filesep '*.bdf']);
% % % end
% % % if isempty(BDF_Files{iFolder}{iSub})
% % % disp(['No BDF file present for ' Folder_AllData{iFolder} 'S' nDigitString(SubjectNumbers_Reg_AllData{iFolder}(iSub),2) filesep]);
% % % Error = 1;
% % % end
% % % end
% % % end
% % % end
% % %
% % % % =========================================== %
% % % % We can assume the SET files have the same subject numbers as
% % % % the set files, so we just use those subject numbers.
% % % % =========================================== %
% % %
% % % % SET (Epoched).
% % %
% % % SET_Epoched_Files = {};
% % % if varargin{2}
% % % if isempty(Condition_Data.SET_Suffix)
% % % disp(['No SET file (Epoched) listed in APPENDIX for ' Condition_Data.Full_Name]);
% % % Error = 1;
% % % else
% % % for iFolder = 1:length(Folder_AllData)
% % % for iSub = 1:length(SubjectNumbers_Reg_AllData{iFolder})
% % % if Condition_Data.Two_Digit_Subject_String_AllData
% % % SET_Epoched_Files{iFolder}{iSub} = dir([Folder_AllData{iFolder} 'S' nDigitString(SubjectNumbers_Reg_AllData{iFolder}(iSub),2) filesep 'S' nDigitString(SubjectNumbers_Reg_AllData{iFolder}(iSub),2) Condition_Data.SET_Suffix]);
% % % else
% % % SET_Epoched_Files{iFolder}{iSub} = dir([Folder_AllData{iFolder} 'S' num2str(SubjectNumbers_Reg_AllData{iFolder}(iSub)) filesep 'S' num2str(SubjectNumbers_Reg_AllData{iFolder}(iSub)) Condition_Data.SET_Suffix]);
% % % end
% % % if isempty(SET_Epoched_Files{iFolder}{iSub})
% % % disp(['No SET file (Epoched) present for ' Folder_AllData{iFolder} 'S' nDigitString(SubjectNumbers_Reg_AllData{iFolder}(iSub),2) filesep]);
% % % Error = 1;
% % % end
% % % end
% % % end
% % % end
% % % end
% % %
% % % % SET (Epoched, ICA).
% % %
% % % SET_Epoched_ICA_Files = {};
% % % if varargin{3}
% % % if isempty(Condition_Data.SET_ICA_Suffix)
% % % disp(['No SET file (Epoched, ICA) listed in APPENDIX for ' Condition_Data.Full_Name]);
% % % Error = 1;
% % % else
% % % for iFolder = 1:length(Folder_AllData)
% % % for iSub = 1:length(SubjectNumbers_Reg_AllData{iFolder})
% % % if Condition_Data.Two_Digit_Subject_String_AllData
% % % SET_Epoched_ICA_Files{iFolder}{iSub} = dir([Folder_AllData{iFolder} 'S' nDigitString(SubjectNumbers_Reg_AllData{iFolder}(iSub),2) filesep 'S' nDigitString(SubjectNumbers_Reg_AllData{iFolder}(iSub),2) Condition_Data.SET_ICA_Suffix]);
% % % else
% % % SET_Epoched_ICA_Files{iFolder}{iSub} = dir([Folder_AllData{iFolder} 'S' num2str(SubjectNumbers_Reg_AllData{iFolder}(iSub)) filesep 'S' num2str(SubjectNumbers_Reg_AllData{iFolder}(iSub)) Condition_Data.SET_ICA_Suffix]);
% % % end
% % % if isempty(SET_Epoched_ICA_Files{iFolder}{iSub})
% % % disp(['No SET file (Epoched, ICA) present for ' Folder_AllData{iFolder} 'S' nDigitString(SubjectNumbers_Reg_AllData{iFolder}(iSub),2) filesep]);
% % % Error = 1;
% % % end
% % % end
% % % end
% % % end
% % % end
% % %
% % % % SET (Epoched, ICA, Max).
% % %
% % % SET_Epoched_ICA_Max_Files = {};
% % % if varargin{4}
% % % if isempty(Condition_Data.SET_ICA_Max_Suffix)
% % % disp(['No SET file (Epoched, ICA, Max) listed in APPENDIX for ' Condition_Data.Full_Name]);
% % % Error = 1;
% % % else
% % % for iFolder = 1:length(Folder_AllData)
% % % for iSub = 1:length(SubjectNumbers_Reg_AllData{iFolder})
% % % if Condition_Data.Two_Digit_Subject_String_AllData
% % % SET_Epoched_ICA_Max_Files{iFolder}{iSub} = dir([Folder_AllData{iFolder} 'S' nDigitString(SubjectNumbers_Reg_AllData{iFolder}(iSub),2) filesep 'S' nDigitString(SubjectNumbers_Reg_AllData{iFolder}(iSub),2) Condition_Data.SET_ICA_Max_Suffix]);
% % % else
% % % SET_Epoched_ICA_Max_Files{iFolder}{iSub} = dir([Folder_AllData{iFolder} 'S' num2str(SubjectNumbers_Reg_AllData{iFolder}(iSub)) filesep 'S' num2str(SubjectNumbers_Reg_AllData{iFolder}(iSub)) Condition_Data.SET_ICA_Max_Suffix]);
% % % end
% % % if isempty(SET_Epoched_ICA_Max_Files{iFolder}{iSub})
% % % disp(['No SET file (Epoched, ICA, Max) present for ' Folder_AllData{iFolder} 'S' nDigitString(SubjectNumbers_Reg_AllData{iFolder}(iSub),2) filesep]);
% % % Error = 1;
% % % end
% % % end
% % % end
% % % end
% % % end
% % %
% % % % =========================================== %
% % % % We can also extract the triggerInfo file from the parent
% % % % alldata directory.
% % % % =========================================== %
% % %
% % % Trigger_Info_Files = {}; TEMP = {};
% % % if varargin{5}
% % % for iFolder = 1:length(Folder_AllData)
% % % Trigger_Info_Files{iFolder} = dir([Folder_AllData{iFolder} 'triggerInfo.mat']);
% % % if isempty(Trigger_Info_Files{iFolder})
% % % disp(['No triggerInfo file for ' Condition_Data.Full_Name '!'])
% % % Error = 1;
% % % else
% % % TEMP{iFolder} = load(fullfile(Trigger_Info_Files{iFolder}.folder,Trigger_Info_Files{iFolder}.name));
% % % TEMP{iFolder} = TEMP{iFolder}.triggerInfo;
% % % TEMP{iFolder}(cellfun(@isnumeric,TEMP{iFolder})) = cellfun(@num2str,(TEMP{iFolder}(cellfun(@isnumeric,TEMP{iFolder}))),'UniformOutput',false);
% % % end
% % % end
% % % if ~isempty(TEMP) & length(TEMP) > 1
% % % if isempty(setdiff(TEMP{:}))
% % % Trigger_Info_Files = Trigger_Info_Files{1};
% % % else
% % % disp(['Multiple triggerInfo files that do not match for ' Condition_Data.Full_Name ' do not match!']);
% % % Error = 1;
% % % end
% % % else
% % % Trigger_Info_Files = Trigger_Info_Files{1};
% % % end
% % % end
% % %
% % % % % % % =========================================== %
% % % % % % % Extract all .m files to detail all code files in alldata.
% % % % % % % =========================================== %
% % % % % %
% % % % % % Code_Files_AllData = {};
% % % % % % for iFolder = 1:length(Folder_AllData)
% % % % % % Code_Files_AllData{iFolder} = dir([Folder_AllData{iFolder} '*.m']);
% % % % % %
% % % % % %
% % % % % % [Folder_AllData{iFolder} 'triggerInfo.mat'];
% % % % % % if ~exist(Trigger_Info_Files{iFolder})
% % % % % % disp([Trigger_Info_Files{iFolder} ' does not exist, but expected!'])
% % % % % % end
% % % % % % end
% % %
% % % % =========================================== %
% % % % If no errors found above, we assign the
% % % % variables to the APP.CURRENTPROJECT
% % % % structure.
% % % % =============================================== %
% % %
% % % Condition_Data.Folder = Folder;
% % % Condition_Data.SubjectNumbers = cat(2,SubjectNumbers_Reg{:});
% % % Condition_Data.SubjectNumbers_AllData = cat(2,SubjectNumbers_Reg_AllData{:});
% % % Condition_Data.SubjectFiles_Reg = cat(2,SubjectFiles_Reg{:});
% % % Condition_Data.SubjectFiles_Irreg = cat(2,SubjectFiles_Irreg{:});
% % % Condition_Data.SubjectFiles_Reg_AllData = cat(2,SubjectFiles_Reg_AllData{:});
% % % Condition_Data.SubjectFiles_Irreg_AllData = cat(2,SubjectFiles_Irreg_AllData{:});
% % % Condition_Data.SubjectFiles_BDF_AllData = cat(2,BDF_Files{:});
% % % Condition_Data.SubjectFiles_SET_Epoched_AllData = cat(2,SET_Epoched_Files{:});
% % % Condition_Data.SubjectFiles_SET_Epoched_ICA_AllData = cat(2,SET_Epoched_ICA_Files{:});
% % % Condition_Data.SubjectFiles_SET_Epoched_ICA_Max_AllData = cat(2,SET_Epoched_ICA_Max_Files{:});
% % % Condition_Data.SubjectFiles_Trigger_Info_AllData = Trigger_Info_Files;
% % %
% % % if Error; return; end
% % %
% % % % ======================================================= %
% % % % If only the info is needed, we return so as to not load the
% % % % data and waste processing time.
% % % % ======================================================= %
% % %
% % % if InfoOnly
% % % return
% % % end
% % %
% % % % ======================================================= %
% % % % Load up the data from .mat files.
% % % % ======================================================= %
% % %
% % % % =============================================== %
% % % % Loop through each subject number found in the
% % % % previous section.
% % % % =============================================== %
% % %
% % % SubCount = 0;
% % %
% % % for iSub = 1:length(Condition_Data.SubjectNumbers)
% % %
% % % FileName_Reg = Condition_Data.SubjectFiles_Reg{iSub};
% % % FileName_Irreg = Condition_Data.SubjectFiles_Irreg{iSub};
% % %
% % % % =========================================== %
% % % % Load up the regularity condition.
% % % % =========================================== %
% % %
% % % if exist(FileName_Reg)
% % % LoadedData = load(FileName_Reg);
% % % FieldNames = fieldnames(LoadedData);
% % % LoadedData = LoadedData.(FieldNames{1});
% % % Condition_Data.Data(:,:,iSub) = LoadedData;
% % % else
% % % error(['File not found - ' FileName_Reg])
% % % end
% % %
% % % % =========================================== %
% % % % Load up the corresponding irregularity condition.
% % % % =========================================== %
% % %
% % % if exist(FileName_Irreg)
% % % LoadedData = load(FileName_Irreg);
% % % FieldNames = fieldnames(LoadedData);
% % % LoadedData = LoadedData.(FieldNames{1});
% % % Condition_Data.Data_Irregular(:,:,iSub) = LoadedData;
% % % else
% % % error(['File not found - ' FileName_Irreg])
% % % end
% % %
% % % end
% % %
% % % % ======================================================= %
% % % % Load up time vector for each EXPERIMENT and CONDITION.
% % % % Some conditions for the same experiment have different
% % % % time vectors. Hence, we load up the time vector for each
% % % % CONDITION individually.
% % % % ======================================================= %
% % %
% % % TimeVectorFile = [Condition_Data.Folder{1} filesep Condition_Data.Time_Vector_Name '.mat'];
% % %
% % % if exist(TimeVectorFile)
% % % TempVar = load(TimeVectorFile);
% % % else
% % % error(['Time Vector file not found - ' TimeVectorFile]);
% % % end
% % %
% % % FieldNames = fieldnames(TempVar);
% % % Condition_Data.TimeVector = TempVar.(FieldNames{1});
% % %
% % % end
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app, varargin)
warning on;
try
% ======================================================= %
% Get the folder in which the EXE was ran.
% ======================================================= %
ExeFolder = GetExecutableFolder();
cd(ExeFolder);
% ======================================================= %
% Get folder for DATA.
% ======================================================= %
if isempty(varargin)
app.DATADIR = [ExeFolder '/Data/'];
else
app.DATADIR = varargin{1};
end
% ======================================================= %
% If the directory is not found in either the EXE folder or
% in the first VARARGIN argument, a dialog box appears to
% select the path.
% ======================================================= %
if ~exist(app.DATADIR,'dir')
disp('Data folder not found, please provide the path to the Data folder.')
app.DATADIR = uigetdir;
waitfor(app.DATADIR);
end
% ======================================================= %
% Create simplified catalogue files.
% ======================================================= %
[app.PROJECT,app.EXP,app.CAT,app.APPENDIX,app.VALIDATE] = CreateSimplifiedCatalogue();
% ======================================================= %
% Determine which folders are present in Data folder and remove
% all other entries in CAT_ORIG.
% ======================================================= %
SubFolders = ListSubfolders(app.DATADIR);
SubFolders(~contains(SubFolders,'Project')) = [];
FoldersPresent = cellfun(@str2num,cellfun(@(x) regexp(x,'\d*','Match'),SubFolders));
app.PROJECT(~ismember([app.PROJECT.Project],FoldersPresent)) = [];
app.EXP(~ismember([app.EXP.Project],FoldersPresent)) = [];
app.CAT(~ismember([app.CAT.Project],FoldersPresent)) = [];
% ======================================================= %
% Add names of project to project PROJECTS LISTBOX.
% ======================================================= %
app.ProjectsListBox.Items = cellfun(@(x) strjoin({'Project' x},' '), cellstr(num2str(cell2mat({app.PROJECT.Project})')),'UniformOutput',false);
app.ProjectsListBox.ItemsData = [app.PROJECT.Project];
% ======================================================= %
% Load electrode locations file.
% ======================================================= %
LoadedData = load('BioSemi-64.mat');
app.E = LoadedData.E;
% ======================================================= %
% Add electrode labels to ELECTRODES LISTBOX for each
% EXPERIMENT.
% ======================================================= %
for iExp = 1:app.MAXEXP
app.(['Electrodes' num2str(iExp) 'ListBox']).Items = {app.E.labels};
end
% ======================================================= %
% We change the PROJECTS LISTBOX value to the first folder
% that was found.
% ======================================================= %
app.ProjectsListBox.Value = app.PROJECT(1).Project;
% ======================================================= %
% Configure diary. This creates a file that command window
% output is sinked to. This file is then loaded and
% displayed in the APP window.
% ======================================================= %
if exist(app.DFILE, 'file') ; diary off; delete(app.DFILE); end
diary(app.DFILE)
diary on
% ======================================================= %
% In order to set of the chain of events from changing the
% current project, we manually reference the
% ProjectsListBoxValueChanged callback. This is because
% simply changing the value programatically does not
% initiate the callback.
% ======================================================= %
ProjectsListBoxValueChanged(app, []);
catch ME
ThrowError(app,ME);
end
% ======================================================= %
% Configure diary. This creates a file that command window
% output is sinked to. This file is then loaded and
% displayed in the APP window. This is duplicated from within
% the above loop since, if it fails, this will at least run to
% give some sort of log file.
% ======================================================= %
if exist(app.DFILE, 'file') ; diary off; delete(app.DFILE); end
diary(app.DFILE)
diary on
% =========================================================== %
% Update the diary window.
% =========================================================== %
UpdateDiary(app);
end
% Value changed function: ProjectsListBox
function ProjectsListBoxValueChanged(app, event)
try
% ======================================================= %
% Get the value of the project that is selected. This value
% will be an integer corresponding to the project number.
% Next, find the index of this project inside the
% APP.PROJECTS structure.
% ======================================================= %
Current_Project = app.ProjectsListBox.ItemsData(app.ProjectsListBox.Value);
% ======================================================= %
% Rather than having to reference the master APP.PROJECTS
% variable each time we need data, we create another
% structure inside the APP structure called CURRENTPROJECT.
% This contains all of the data for the currently selected
% project. This section will only initiate in two
% scenarios. Firstly, it will only run if a different
% project is selected to what has already been displayed.
% This saves having to rerun the same code unnecessarily.
% Secondly, it will only run if it has not been ran at all
% yet, such as when the APP has only just opened.
% ======================================================= %
if app.INITIATED && strcmp(app.CURRENTPROJECT(1).Project,Current_Project)
return
else
Current_Conditions = [app.CAT([app.CAT.Project] == Current_Project).SPNID];
app.CURRENTPROJECT = {};
for iCond = 1:length(Current_Conditions)
[app.CURRENTPROJECT{iCond}, Error] = ExtractConditionData(app.CAT,app.DATADIR,Current_Conditions(iCond),0);
end
app.CURRENTPROJECT = vertcat(app.CURRENTPROJECT{:});
if ~app.INITIATED; app.INITIATED = 1; end
app.CATALOGUELOADED = 1;
% ======================================================= %
% If error found, then return the script, since there is no
% point trying to load the files below. We will also update
% the diary so it is visible in the APP.
% ======================================================= %
if Error; UpdateDiary(app); return; end
end
% =================================================== %
% In addition to the data, we also extract the relevant
% information regarding the currently selected TIME and
% ELECTRODE for each EXPERIMENT and CONDITION. By
% default, the original TIME and ELECTRODE cluster is
% selected.
% =================================================== %
for iCond = 1:length(app.CURRENTPROJECT)
app.CURRENTPROJECT(iCond).Cluster_Options_Electrodes = unique(app.CURRENTPROJECT(iCond).Electrodes_Original);
app.CURRENTPROJECT(iCond).Cluster_Options_Time = app.CURRENTPROJECT(iCond).Window_Original;
app.CURRENTPROJECT(iCond).Cluster_Options_Electrodes_Option = 'Original';
app.CURRENTPROJECT(iCond).Cluster_Options_Time_Option = 'Original';
end
% ======================================================= %
% Assign conditions to each EXPERIMENT LISTBOX.
% ======================================================= %
UniqueExperiments = unique({app.CURRENTPROJECT.Full_Name});
for iExp = 1:length(UniqueExperiments)
Experiment_Index = find(strcmp({app.CURRENTPROJECT.Full_Name},UniqueExperiments{iExp}));
EXPERIMENT_DATA = app.CURRENTPROJECT(Experiment_Index);
% =================================================== %
% Some experiments have identical condition names,
% with the only thing differentiating them is whether
% regularity was attended to or not. Hence, we create
% new condition names that indicate whether regularity
% was attended or not.
% =================================================== %
AttendRegularity = repmat({'(Attend Reg)'},length(EXPERIMENT_DATA),1);
AttendRegularity(~[EXPERIMENT_DATA.Attend_Regularity]) = {'(Disregard Reg)'};
ConditionNames = {};
for iCond = 1:length(EXPERIMENT_DATA)
if isempty(EXPERIMENT_DATA(iCond).Condition_Name_Override)
ConditionNames{iCond} = EXPERIMENT_DATA(iCond).Regular_Condition;
else
ConditionNames{iCond} = EXPERIMENT_DATA(iCond).Condition_Name_Override;
end
end
ListNames = ConditionNames';
ListNames(:,2) = AttendRegularity;
ListNames = join(ListNames);
% =================================================== %
% Title the EXPERIMENT LSITBOX, the CONDITIONS and the
% ItemsData variable. There are two ways of assigning
% a value for a LISTBOX. First, if only the ITEMS field
% is given, the selected VALUE will correspond to the
% name of the selected value, e.g. "Reflection1".
% However, if the ITEMSDATA field is also given, the
% value will correspond to the ITEMSDATA values. Since
% some conditions have duplicate names, using the name
% of the condition is not an appropiate way to select
% the value. Hence, we use the SPNID value as the way
% to select a VALUE for the LISTBOX. Thus, the SPNID is
% used as the ITEMSDATA variable.
% =================================================== %
app.(['Experiment' num2str(iExp) 'Panel']).Title = UniqueExperiments{iExp};
app.(['Experiment' num2str(iExp) 'ListBox']).Items = ListNames;
app.(['Experiment' num2str(iExp) 'ListBox']).Value = {};
app.(['Experiment' num2str(iExp) 'ListBox']).ItemsData = [EXPERIMENT_DATA.SPNID];
app.(['Experiment' num2str(iExp) 'Panel']).Visible = 1;
for iCond = Experiment_Index
app.CURRENTPROJECT(iCond).Plot_Selection = 1;
app.CURRENTPROJECT(iCond).Configure_Selection = 0;
end
app.CURRENTPROJECT(Experiment_Index(1)).Configure_Selection = 1;
end
% ======================================================= %
% Since we do not want all the EXPERIMENT boxes to be
% visible all of the time, only when being used, we empty
% out the unused panels and make them invisible.
% ======================================================= %
if iExp < app.MAXEXP
for iExp = length(UniqueExperiments)+1:app.MAXEXP
app.(['Experiment' num2str(iExp) 'Panel']).Title = '';
app.(['Experiment' num2str(iExp) 'ListBox']).Items = {};
app.(['Experiment' num2str(iExp) 'ListBox']).Value = {};
app.(['Experiment' num2str(iExp) 'ListBox']).ItemsData = [];
app.(['Experiment' num2str(iExp) 'Panel']).Visible = 0;
end
end
% If the function runs without this section in, delete it.
% The structure is defined soon after in ExtractPlotData.
% % % % ======================================================= %
% % % % Create empty plot data variable. This structure will
% % % % contain all data we need for plotting.
% % % % ======================================================= %
% % %
% % % Condition_Data.PlotData = struct();
% ======================================================= %
% If the PLOTBUTTON is pushed down, we select all
% conditions first, and then we extract the plot data. If
% we are already plotting the data and then change the
% project, selecting all of the conditions automatically
% will stop it from crashing. If we are not plotting the
% data, we only select the first condition for each
% experiment. This is because multi-select of conditions is
% only enabled when we are plotting data.
% ======================================================= %
ParametersStatusCheck(app);
if app.PlotButton.Value
SelectConditions(app,[]);
ExtractPlotData(app);
else
SelectConditions(app,'first');
end
% ======================================================= %
% This allows us to refresh the selected ELECTRODES and
% TIMES for each EXPERIMENT LISTBOX.
% ======================================================= %
RefreshExperimentLists(app);
catch ME
ThrowError(app,ME);
end
disp(['Data loaded successfully for ' num2str(app.CURRENTPROJECT(1).Project) '.']);
UpdateDiary(app);
updateAppLayout(app, []);
end
% Value changed function: Experiment1ListBox,
% Experiment2ListBox, Experiment3ListBox,
% Experiment4ListBox, Experiment5ListBox
function ExperimentListBoxValueChanged(app, event)
% Initiated when the selected CONDITIONS for any EXPERIMENT
% LISTBOX are changed.
try
% ======================================================= %
% If we are current plotting data, as is the case if the
% PLOTBUTTON is currently ON, we extract the plot data.
% Else, we refresh the selected ELETRODES and TIME in the
% EXPERIMENT PANELS, as well as check the status of the
% EDITABLE FIELDS to be enabled or disabled depending on
% whether there are CONDITIONS selected.
% ======================================================= %
if app.PlotButton.Value
% =================================================== %
% To allow memory of previously selected conditions when
% plotting data, we will update a variable inside of the
% APP.CURRENTPROJECT structure. However, we only update
% this if we are currently plotting the data.
% =================================================== %
UniqueExperiments = unique({app.CURRENTPROJECT.Full_Name});
for iCond = 1:length(app.CURRENTPROJECT)
Experiment_Index = find(strcmp({app.CURRENTPROJECT(iCond).Full_Name},UniqueExperiments));
if isempty(app.(['Experiment' num2str(Experiment_Index) 'ListBox']).Value)
app.CURRENTPROJECT(iCond).Plot_Selection = 0;
else
app.CURRENTPROJECT(iCond).Plot_Selection = any(ismember(app.(['Experiment' num2str(Experiment_Index) 'ListBox']).Value,app.CURRENTPROJECT(iCond).SPNID));
end
end
% =================================================== %
% If no conditions are selected across all experiments,
% we simply skip plotting to avoid errors. Also, turn
% off plots if nothing is being plotted.
% =================================================== %
SelectedConditions = [app.CURRENTPROJECT.Plot_Selection];
if all(~SelectedConditions)
app.UIAxesWaveform.Legend.Visible = 'off';
cla(app.UIAxesBar);
cla(app.UIAxesWaveform);
app.UIAxesBar.Visible = 'off';
app.UIAxesWaveform.Visible = 'off';
app.UITableSPN.Visible = 'off';
return
else
app.UIAxesBar.Visible = 'on';
app.UIAxesWaveform.Visible = 'on';
app.UITableSPN.Visible = 'on';
app.UIAxesWaveform.Legend.Visible = 'on';
end
% % % % =================================================== %
% % % % A little workaround to allow toggle of listbox, rather
% % % % than requiring control click.
% % % % =================================================== %
% % %
% % % Value = event.Value;
% % % ValuePrevious = event.PreviousValue;
% % %
% % % Value2 = Value;
% % % ValuePrevious2 = ValuePrevious;
% % %
% % % if any(ismember(ValuePrevious,Value))
% % % ValuePrevious2(ismember(ValuePrevious,Value)) = [];
% % % Value2(ismember(Value,ValuePrevious)) = [];
% % % end
% % %
% % % ValueNew = sort([Value2 ValuePrevious2]);
% % %
% % % if isempty(ValueNew); ValueNew = []; end
% % %
% % % event.Source.Value = ValueNew;
ExtractPlotData(app);
else
% =================================================== %
% To allow memory of previously selected conditions when
% configuring data, we will update a variable inside of
% the APP.CURRENTPROJECT structure. However, we only
% update this if we are not plotting the data.
% =================================================== %
UniqueExperiments = unique({app.CURRENTPROJECT.Experiment});
for iExp = 1:length(UniqueExperiments)
Experiment_Index = find(strcmp({app.CURRENTPROJECT.Experiment},UniqueExperiments{iExp}));
ConditionIndex = find([app.CURRENTPROJECT.SPNID] == app.(['Experiment' num2str(iExp) 'ListBox']).Value);
for iCond = Experiment_Index
app.CURRENTPROJECT(iCond).Configure_Selection = 0;
end
app.CURRENTPROJECT(ConditionIndex).Configure_Selection = 1;
end
end
RefreshExperimentLists(app);
ParametersStatusCheck(app);
catch ME
ThrowError(app,ME);
end
UpdateDiary(app);
end
% Value changed function: Cluster1DropDown,
% Cluster2DropDown, Cluster3DropDown, Cluster4DropDown,
% Cluster5DropDown
function ClusterDropDownValueChanged(app, event)
% Initiated when the ELECTRODES DOGMA DROPDOWN is changed.
try
% ======================================================= %
% Since we use the same callback for all EXPERIMENTS, we
% need to figure out which one actually initiated the
% callback. I've done this using the title of the
% experiment as this is stored in the event.Source
% variable.
% ======================================================= %
UniqueExperiments = unique({app.CURRENTPROJECT.Full_Name});
ExperimentTitle = event.Source.Parent.Title;
Experiment_Index = find(strcmp(UniqueExperiments,ExperimentTitle));
ConditionIndex = find([app.CURRENTPROJECT.SPNID] == app.(['Experiment' num2str(Experiment_Index) 'ListBox']).Value);
% ======================================================= %
% Depending on the value that was selected for the
% ELECTRODE DOGMA DROPDOWN, we extract the corresponding
% electrodes.
% ======================================================= %
value = app.(['Cluster' num2str(Experiment_Index) 'DropDown']).Value;
if strcmp(value, 'Original')
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes = app.CURRENTPROJECT(ConditionIndex).Electrodes_Original;
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes_Option = 'Original';
elseif strcmp(value, 'Cluster 1')
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes = app.CURRENTPROJECT(ConditionIndex).Electrodes_Cluster_1;
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes_Option = 'Cluster 1';
elseif strcmp(value, 'Cluster 2')
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes = app.CURRENTPROJECT(ConditionIndex).Electrodes_Cluster_2;
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes_Option = 'Cluster 2';
elseif strcmp(value, 'Cluster 3')
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes = app.CURRENTPROJECT(ConditionIndex).Electrodes_Cluster_3;
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes_Option = 'Cluster 3';
elseif strcmp(value, 'Custom')
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes = app.CURRENTPROJECT(ConditionIndex).Electrodes_Custom;
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes_Option = 'Custom';
end
app.(['Electrodes' num2str(Experiment_Index) 'ListBox']).Value = app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes;
RefreshExperimentLists(app);
ParametersStatusCheck(app);
catch ME
ThrowError(app,ME);
end
UpdateDiary(app);
end
% Value changed function: Time1DropDown, Time2DropDown,
% Time3DropDown, Time4DropDown, Time5DropDown
function TimeDropDownValueChanged(app, event)
% Initiated when the time option is changed for any EXPERIMENT.
try
% ======================================================= %
% Since we use the same callback for all EXPERIMENTS, we
% need to figure out which one actually initiated the
% callback. I've done this using the title of the
% experiment as this is stored in the event.Source
% variable.
% ======================================================= %
UniqueExperiments = unique({app.CURRENTPROJECT.Full_Name});
ExperimentTitle = event.Source.Parent.Title;
Experiment_Index = find(strcmp(UniqueExperiments,ExperimentTitle));
ConditionIndex = find([app.CURRENTPROJECT.SPNID] == app.(['Experiment' num2str(Experiment_Index) 'ListBox']).Value);
% ======================================================= %
% Depending on the value that was selected for the TIME
% DROPDOWN, we extract the corresponding times.
% ======================================================= %
value = app.(['Time' num2str(Experiment_Index) 'DropDown']).Value;
if strcmp(value, 'Original')
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Time = app.CURRENTPROJECT(ConditionIndex).Window_Original;
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Time_Option = 'Original';
elseif strcmp(value, 'Dogma')
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Time = app.CURRENTPROJECT(ConditionIndex).Window_Cluster;
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Time_Option = 'Dogma';
elseif strcmp(value, 'Custom')
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Time = app.CURRENTPROJECT(ConditionIndex).Window_Custom;
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Time_Option = 'Custom';
end
app.(['Start' num2str(Experiment_Index) 'EditField']).Value = str2num(app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Time{1});
app.(['End' num2str(Experiment_Index) 'EditField']).Value = str2num(app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Time{2});
RefreshExperimentLists(app);
ParametersStatusCheck(app);
catch ME
ThrowError(app,ME);
end
UpdateDiary(app);
end
% Value changed function: Electrodes1ListBox,
% Electrodes2ListBox, Electrodes3ListBox,
% Electrodes4ListBox, Electrodes5ListBox
function ElectrodesListBoxValueChanged(app, event)
try
% =========================================================== %
% Since we use the same callback for all EXPERIMENTS, we
% need to figure out which one actually initiated the
% callback. I've done this using the title of the
% experiment as this is stored in the event.Source
% variable.
% =========================================================== %
UniqueExperiments = unique({app.CURRENTPROJECT.Full_Name});
ExperimentTitle = event.Source.Parent.Title;
Experiment_Index = find(strcmp(UniqueExperiments,ExperimentTitle));
value = app.(['Electrodes' num2str(Experiment_Index) 'ListBox']).Value;
ConditionIndex = find([app.CURRENTPROJECT.SPNID] == app.(['Experiment' num2str(Experiment_Index) 'ListBox']).Value);
% =========================================================== %
% We can now assign the selected electrodes to the appropriate
% variables.
% =========================================================== %
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Electrodes = value;
app.CURRENTPROJECT(ConditionIndex).Electrodes_Custom = value;
RefreshExperimentLists(app);
catch ME
ThrowError(app,ME);
end
end
% Value changed function: Start1EditField, Start2EditField,
% Start3EditField, Start4EditField, Start5EditField
function StartEditFieldValueChanged(app, event)
try
% =========================================================== %
% Since we use the same callback for all EXPERIMENTS, we
% need to figure out which one actually initiated the
% callback. I've done this using the title of the
% experiment as this is stored in the event.Source
% variable.
% =========================================================== %
UniqueExperiments = unique({app.CURRENTPROJECT.Full_Name});
ExperimentTitle = event.Source.Parent.Title;
Experiment_Index = find(strcmp(UniqueExperiments,ExperimentTitle));
value = app.(['Start' num2str(Experiment_Index) 'EditField']).Value;
ConditionIndex = find([app.CURRENTPROJECT.SPNID] == app.(['Experiment' num2str(Experiment_Index) 'ListBox']).Value);
% =========================================================== %
% We can now assign the selected electrodes to the appropriate
% variables.
% =========================================================== %
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Time{1} = num2str(value);
app.CURRENTPROJECT(ConditionIndex).Window_Custom{1} = num2str(value);
RefreshExperimentLists(app);
catch ME
ThrowError(app,ME);
end
end
% Value changed function: End1EditField, End2EditField,
% End3EditField, End4EditField, End5EditField
function EndEditFieldValueChanged(app, event)
try
% =========================================================== %
% Since we use the same callback for all EXPERIMENTS, we
% need to figure out which one actually initiated the
% callback. I've done this using the title of the
% experiment as this is stored in the event.Source
% variable.
% =========================================================== %
UniqueExperiments = unique({app.CURRENTPROJECT.Full_Name});
ExperimentTitle = event.Source.Parent.Title;
Experiment_Index = find(strcmp(UniqueExperiments,ExperimentTitle));
value = app.(['End' num2str(Experiment_Index) 'EditField']).Value;
ConditionIndex = find([app.CURRENTPROJECT.SPNID] == app.(['Experiment' num2str(Experiment_Index) 'ListBox']).Value);
% =========================================================== %
% We can now assign the selected electrodes to the appropriate
% variables.
% =========================================================== %
app.CURRENTPROJECT(ConditionIndex).Cluster_Options_Time{2} = num2str(value);
app.CURRENTPROJECT(ConditionIndex).Window_Custom{2} = num2str(value);
RefreshExperimentLists(app);
catch ME
ThrowError(app,ME);
end
end
% Value changed function: PlotButton
function PlotButtonValueChanged(app, event)
% If PLOTBUTTON is selected, this callback is referenced.
try
PlottingEnabled = app.PlotButton.Value;
ParametersStatusCheck(app);
if PlottingEnabled
% =================================================== %
% If the PLOTBUTTON is enabled, we want to select
% conditions in the EXPERIMENT LISTBOX. We also extract
% the plot data and ultimately plot it.
% =================================================== %
SelectConditions(app,[]);
ExtractPlotData(app);
% =================================================== %
% We enable the PLOT IRREGULAR and DIFFERENCE WAVE
% buttons when plotting.
app.PlotIrregularButton.Enable = 1;
app.DifferenceWaveButton.Enable = 1;
else
% =================================================== %
% Refresh the parameters in the experiments panel.
% =================================================== %
SelectConditions(app,[]);
RefreshExperimentLists(app);
% =================================================== %
% We disable the PLOT IRREGULAR and DIFFERENCE WAVE
% buttons when not plotting.
% =================================================== %
app.PlotIrregularButton.Enable = 0;
app.DifferenceWaveButton.Enable = 0;
end
catch ME
ThrowError(app,ME);
end
UpdateDiary(app);
end
% Value changed function: DifferenceWaveButton
function DifferenceWaveButtonValueChanged(app, event)
% If the DIFFERENCE WAVE BUTTON is pressed, the data is
% extracted again and plotted.
try
ExtractPlotData(app);
catch ME
ThrowError(app,ME);
end
UpdateDiary(app);
end
% Value changed function: PlotIrregularButton
function PlotIrregularButtonValueChanged(app, event)
% If the PLOT IRREGULAR button is pressed, the data is
% extracted again and plotted.
try
ExtractPlotData(app);
catch ME
ThrowError(app,ME);
end
UpdateDiary(app);
end
% Button pushed function: ExportButton
function ExportButtonValueChanged(app, event)
% Disable Plot Options button while dialog is open
app.ExportButton.Enable = 'off';
% Open the options dialog and pass inputs
File_Name = mfilename;
if isdeployed() | strcmp(File_Name,'SPNCAT')
app.ExportApp = SPNCAT_Export(app);
else
app.ExportApp = SPNCAT_Export_func(app);
end
end
% Close request function: UIFigure
function UIFigureCloseRequest(app, event)
delete(app.ExportApp);
delete(app);
end
% Changes arrangement of the app based on UIFigure width
function updateAppLayout(app, event)
currentFigureWidth = app.UIFigure.Position(3);
if(currentFigureWidth <= app.onePanelWidth)
% Change to a 2x1 grid
app.GridLayout.RowHeight = {831, 831};
app.GridLayout.ColumnWidth = {'1x'};
app.RightPanel.Layout.Row = 2;
app.RightPanel.Layout.Column = 1;
else
% Change to a 1x2 grid
app.GridLayout.RowHeight = {'1x'};
app.GridLayout.ColumnWidth = {443, '1x'};
app.RightPanel.Layout.Row = 1;
app.RightPanel.Layout.Column = 2;
end
end
end
% Component initialization
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure and hide until all components are created
app.UIFigure = uifigure('Visible', 'off');
app.UIFigure.AutoResizeChildren = 'off';
app.UIFigure.Position = [100 100 783 831];
app.UIFigure.Name = 'MATLAB App';
app.UIFigure.CloseRequestFcn = createCallbackFcn(app, @UIFigureCloseRequest, true);
app.UIFigure.SizeChangedFcn = createCallbackFcn(app, @updateAppLayout, true);
app.UIFigure.Scrollable = 'on';
% Create GridLayout
app.GridLayout = uigridlayout(app.UIFigure);
app.GridLayout.ColumnWidth = {443, '1x'};
app.GridLayout.RowHeight = {'1x'};
app.GridLayout.ColumnSpacing = 0;
app.GridLayout.RowSpacing = 0;
app.GridLayout.Padding = [0 0 0 0];
app.GridLayout.Scrollable = 'on';
% Create LeftPanel
app.LeftPanel = uipanel(app.GridLayout);
app.LeftPanel.Layout.Row = 1;
app.LeftPanel.Layout.Column = 1;
% Create ProjectsListBox
app.ProjectsListBox = uilistbox(app.LeftPanel);
app.ProjectsListBox.Items = {};
app.ProjectsListBox.ValueChangedFcn = createCallbackFcn(app, @ProjectsListBoxValueChanged, true);
app.ProjectsListBox.Position = [21 20 80 790];
app.ProjectsListBox.Value = {};
% Create Experiment1Panel
app.Experiment1Panel = uipanel(app.LeftPanel);
app.Experiment1Panel.Title = 'Experiment 1';
app.Experiment1Panel.Position = [111 660 320 150];
% Create Experiment1ListBox
app.Experiment1ListBox = uilistbox(app.Experiment1Panel);
app.Experiment1ListBox.Items = {};
app.Experiment1ListBox.ValueChangedFcn = createCallbackFcn(app, @ExperimentListBoxValueChanged, true);
app.Experiment1ListBox.Position = [11 10 80 110];
app.Experiment1ListBox.Value = {};
% Create ClusterDropDownLabel
app.ClusterDropDownLabel = uilabel(app.Experiment1Panel);
app.ClusterDropDownLabel.HorizontalAlignment = 'right';
app.ClusterDropDownLabel.Position = [161 98 40 22];
app.ClusterDropDownLabel.Text = 'Cluster';
% Create Cluster1DropDown
app.Cluster1DropDown = uidropdown(app.Experiment1Panel);
app.Cluster1DropDown.Items = {'Original', 'Cluster 1', 'Cluster 2', 'Cluster 3', 'Custom'};
app.Cluster1DropDown.ValueChangedFcn = createCallbackFcn(app, @ClusterDropDownValueChanged, true);
app.Cluster1DropDown.Position = [211 100 100 20];
app.Cluster1DropDown.Value = 'Original';
% Create TimeDropDownLabel
app.TimeDropDownLabel = uilabel(app.Experiment1Panel);
app.TimeDropDownLabel.HorizontalAlignment = 'right';
app.TimeDropDownLabel.Position = [161 68 40 22];
app.TimeDropDownLabel.Text = 'Time';
% Create Time1DropDown
app.Time1DropDown = uidropdown(app.Experiment1Panel);
app.Time1DropDown.Items = {'Original', 'Dogma', 'Custom'};
app.Time1DropDown.ValueChangedFcn = createCallbackFcn(app, @TimeDropDownValueChanged, true);
app.Time1DropDown.Position = [211 70 100 20];
app.Time1DropDown.Value = 'Original';
% Create StartEditFieldLabel
app.StartEditFieldLabel = uilabel(app.Experiment1Panel);
app.StartEditFieldLabel.HorizontalAlignment = 'right';
app.StartEditFieldLabel.Position = [161 39 40 22];
app.StartEditFieldLabel.Text = 'Start';
% Create Start1EditField
app.Start1EditField = uieditfield(app.Experiment1Panel, 'numeric');
app.Start1EditField.ValueChangedFcn = createCallbackFcn(app, @StartEditFieldValueChanged, true);
app.Start1EditField.Position = [211 39 100 22];
% Create EndEditFieldLabel
app.EndEditFieldLabel = uilabel(app.Experiment1Panel);
app.EndEditFieldLabel.HorizontalAlignment = 'right';
app.EndEditFieldLabel.Position = [161 8 40 22];
app.EndEditFieldLabel.Text = 'End';
% Create End1EditField
app.End1EditField = uieditfield(app.Experiment1Panel, 'numeric');
app.End1EditField.ValueChangedFcn = createCallbackFcn(app, @EndEditFieldValueChanged, true);
app.End1EditField.Position = [211 8 100 22];
% Create Electrodes1ListBox
app.Electrodes1ListBox = uilistbox(app.Experiment1Panel);
app.Electrodes1ListBox.Items = {};
app.Electrodes1ListBox.Multiselect = 'on';
app.Electrodes1ListBox.ValueChangedFcn = createCallbackFcn(app, @ElectrodesListBoxValueChanged, true);
app.Electrodes1ListBox.Position = [101 10 50 110];
app.Electrodes1ListBox.Value = {};
% Create Experiment2Panel
app.Experiment2Panel = uipanel(app.LeftPanel);
app.Experiment2Panel.Title = 'Experiment 2';
app.Experiment2Panel.Position = [111 500 320 150];
% Create Experiment2ListBox
app.Experiment2ListBox = uilistbox(app.Experiment2Panel);
app.Experiment2ListBox.Items = {};
app.Experiment2ListBox.ValueChangedFcn = createCallbackFcn(app, @ExperimentListBoxValueChanged, true);
app.Experiment2ListBox.Position = [11 10 80 110];
app.Experiment2ListBox.Value = {};
% Create Electrodes2ListBox
app.Electrodes2ListBox = uilistbox(app.Experiment2Panel);
app.Electrodes2ListBox.Items = {};
app.Electrodes2ListBox.Multiselect = 'on';
app.Electrodes2ListBox.ValueChangedFcn = createCallbackFcn(app, @ElectrodesListBoxValueChanged, true);
app.Electrodes2ListBox.Position = [101 10 50 110];
app.Electrodes2ListBox.Value = {};
% Create ClusterDropDownLabel_2
app.ClusterDropDownLabel_2 = uilabel(app.Experiment2Panel);
app.ClusterDropDownLabel_2.HorizontalAlignment = 'right';
app.ClusterDropDownLabel_2.Position = [161 98 40 22];
app.ClusterDropDownLabel_2.Text = 'Cluster';
% Create Cluster2DropDown
app.Cluster2DropDown = uidropdown(app.Experiment2Panel);
app.Cluster2DropDown.Items = {'Original', 'Cluster 1', 'Cluster 2', 'Cluster 3', 'Custom'};
app.Cluster2DropDown.ValueChangedFcn = createCallbackFcn(app, @ClusterDropDownValueChanged, true);
app.Cluster2DropDown.Position = [211 100 100 20];
app.Cluster2DropDown.Value = 'Original';
% Create TimeDropDownLabel_2
app.TimeDropDownLabel_2 = uilabel(app.Experiment2Panel);
app.TimeDropDownLabel_2.HorizontalAlignment = 'right';
app.TimeDropDownLabel_2.Position = [161 68 40 22];
app.TimeDropDownLabel_2.Text = 'Time';
% Create Time2DropDown
app.Time2DropDown = uidropdown(app.Experiment2Panel);
app.Time2DropDown.Items = {'Original', 'Dogma', 'Custom'};
app.Time2DropDown.ValueChangedFcn = createCallbackFcn(app, @TimeDropDownValueChanged, true);
app.Time2DropDown.Position = [211 70 100 20];
app.Time2DropDown.Value = 'Original';
% Create StartEditFieldLabel_2
app.StartEditFieldLabel_2 = uilabel(app.Experiment2Panel);
app.StartEditFieldLabel_2.HorizontalAlignment = 'right';
app.StartEditFieldLabel_2.Position = [161 39 40 22];
app.StartEditFieldLabel_2.Text = 'Start';
% Create Start2EditField
app.Start2EditField = uieditfield(app.Experiment2Panel, 'numeric');
app.Start2EditField.ValueChangedFcn = createCallbackFcn(app, @StartEditFieldValueChanged, true);
app.Start2EditField.Position = [211 39 100 22];
% Create EndEditFieldLabel_2
app.EndEditFieldLabel_2 = uilabel(app.Experiment2Panel);
app.EndEditFieldLabel_2.HorizontalAlignment = 'right';
app.EndEditFieldLabel_2.Position = [161 8 40 22];
app.EndEditFieldLabel_2.Text = 'End';
% Create End2EditField
app.End2EditField = uieditfield(app.Experiment2Panel, 'numeric');
app.End2EditField.ValueChangedFcn = createCallbackFcn(app, @EndEditFieldValueChanged, true);
app.End2EditField.Position = [211 8 100 22];
% Create Experiment3Panel
app.Experiment3Panel = uipanel(app.LeftPanel);
app.Experiment3Panel.Title = 'Experiment 3';
app.Experiment3Panel.Position = [111 340 320 150];
% Create Experiment3ListBox
app.Experiment3ListBox = uilistbox(app.Experiment3Panel);
app.Experiment3ListBox.Items = {};
app.Experiment3ListBox.ValueChangedFcn = createCallbackFcn(app, @ExperimentListBoxValueChanged, true);
app.Experiment3ListBox.Position = [11 10 80 110];
app.Experiment3ListBox.Value = {};
% Create Electrodes3ListBox
app.Electrodes3ListBox = uilistbox(app.Experiment3Panel);
app.Electrodes3ListBox.Items = {};
app.Electrodes3ListBox.Multiselect = 'on';
app.Electrodes3ListBox.ValueChangedFcn = createCallbackFcn(app, @ElectrodesListBoxValueChanged, true);
app.Electrodes3ListBox.Position = [101 10 50 110];
app.Electrodes3ListBox.Value = {};
% Create ClusterDropDownLabel_3
app.ClusterDropDownLabel_3 = uilabel(app.Experiment3Panel);
app.ClusterDropDownLabel_3.HorizontalAlignment = 'right';
app.ClusterDropDownLabel_3.Position = [161 98 40 22];
app.ClusterDropDownLabel_3.Text = 'Cluster';
% Create Cluster3DropDown
app.Cluster3DropDown = uidropdown(app.Experiment3Panel);
app.Cluster3DropDown.Items = {'Original', 'Cluster 1', 'Cluster 2', 'Cluster 3', 'Custom'};
app.Cluster3DropDown.ValueChangedFcn = createCallbackFcn(app, @ClusterDropDownValueChanged, true);
app.Cluster3DropDown.Position = [211 100 100 20];
app.Cluster3DropDown.Value = 'Original';
% Create TimeDropDownLabel_3
app.TimeDropDownLabel_3 = uilabel(app.Experiment3Panel);
app.TimeDropDownLabel_3.HorizontalAlignment = 'right';
app.TimeDropDownLabel_3.Position = [161 68 40 22];
app.TimeDropDownLabel_3.Text = 'Time';
% Create Time3DropDown
app.Time3DropDown = uidropdown(app.Experiment3Panel);
app.Time3DropDown.Items = {'Original', 'Dogma', 'Custom'};
app.Time3DropDown.ValueChangedFcn = createCallbackFcn(app, @TimeDropDownValueChanged, true);
app.Time3DropDown.Position = [211 70 100 20];
app.Time3DropDown.Value = 'Original';
% Create StartEditFieldLabel_3
app.StartEditFieldLabel_3 = uilabel(app.Experiment3Panel);
app.StartEditFieldLabel_3.HorizontalAlignment = 'right';
app.StartEditFieldLabel_3.Position = [161 39 40 22];
app.StartEditFieldLabel_3.Text = 'Start';
% Create Start3EditField
app.Start3EditField = uieditfield(app.Experiment3Panel, 'numeric');
app.Start3EditField.ValueChangedFcn = createCallbackFcn(app, @StartEditFieldValueChanged, true);
app.Start3EditField.Position = [211 39 100 22];
% Create EndEditFieldLabel_3
app.EndEditFieldLabel_3 = uilabel(app.Experiment3Panel);
app.EndEditFieldLabel_3.HorizontalAlignment = 'right';
app.EndEditFieldLabel_3.Position = [161 8 40 22];
app.EndEditFieldLabel_3.Text = 'End';
% Create End3EditField
app.End3EditField = uieditfield(app.Experiment3Panel, 'numeric');
app.End3EditField.ValueChangedFcn = createCallbackFcn(app, @EndEditFieldValueChanged, true);
app.End3EditField.Position = [211 8 100 22];
% Create Experiment4Panel
app.Experiment4Panel = uipanel(app.LeftPanel);
app.Experiment4Panel.Title = 'Experiment 4';
app.Experiment4Panel.Position = [111 180 320 150];
% Create Experiment4ListBox
app.Experiment4ListBox = uilistbox(app.Experiment4Panel);
app.Experiment4ListBox.Items = {};
app.Experiment4ListBox.ValueChangedFcn = createCallbackFcn(app, @ExperimentListBoxValueChanged, true);
app.Experiment4ListBox.Position = [11 10 80 110];
app.Experiment4ListBox.Value = {};
% Create Electrodes4ListBox
app.Electrodes4ListBox = uilistbox(app.Experiment4Panel);
app.Electrodes4ListBox.Items = {};
app.Electrodes4ListBox.Multiselect = 'on';
app.Electrodes4ListBox.ValueChangedFcn = createCallbackFcn(app, @ElectrodesListBoxValueChanged, true);
app.Electrodes4ListBox.Position = [101 10 50 110];
app.Electrodes4ListBox.Value = {};
% Create ClusterDropDownLabel_4
app.ClusterDropDownLabel_4 = uilabel(app.Experiment4Panel);
app.ClusterDropDownLabel_4.HorizontalAlignment = 'right';
app.ClusterDropDownLabel_4.Position = [161 98 40 22];
app.ClusterDropDownLabel_4.Text = 'Cluster';
% Create Cluster4DropDown
app.Cluster4DropDown = uidropdown(app.Experiment4Panel);
app.Cluster4DropDown.Items = {'Original', 'Cluster 1', 'Cluster 2', 'Cluster 3', 'Custom'};
app.Cluster4DropDown.ValueChangedFcn = createCallbackFcn(app, @ClusterDropDownValueChanged, true);
app.Cluster4DropDown.Position = [211 100 100 20];
app.Cluster4DropDown.Value = 'Original';
% Create TimeDropDownLabel_4
app.TimeDropDownLabel_4 = uilabel(app.Experiment4Panel);
app.TimeDropDownLabel_4.HorizontalAlignment = 'right';
app.TimeDropDownLabel_4.Position = [161 68 40 22];
app.TimeDropDownLabel_4.Text = 'Time';
% Create Time4DropDown
app.Time4DropDown = uidropdown(app.Experiment4Panel);
app.Time4DropDown.Items = {'Original', 'Dogma', 'Custom'};
app.Time4DropDown.ValueChangedFcn = createCallbackFcn(app, @TimeDropDownValueChanged, true);
app.Time4DropDown.Position = [211 70 100 20];
app.Time4DropDown.Value = 'Original';
% Create StartEditFieldLabel_4
app.StartEditFieldLabel_4 = uilabel(app.Experiment4Panel);
app.StartEditFieldLabel_4.HorizontalAlignment = 'right';
app.StartEditFieldLabel_4.Position = [161 39 40 22];
app.StartEditFieldLabel_4.Text = 'Start';
% Create Start4EditField
app.Start4EditField = uieditfield(app.Experiment4Panel, 'numeric');
app.Start4EditField.ValueChangedFcn = createCallbackFcn(app, @StartEditFieldValueChanged, true);
app.Start4EditField.Position = [211 39 100 22];
% Create EndEditFieldLabel_4
app.EndEditFieldLabel_4 = uilabel(app.Experiment4Panel);
app.EndEditFieldLabel_4.HorizontalAlignment = 'right';
app.EndEditFieldLabel_4.Position = [161 8 40 22];
app.EndEditFieldLabel_4.Text = 'End';
% Create End4EditField
app.End4EditField = uieditfield(app.Experiment4Panel, 'numeric');
app.End4EditField.ValueChangedFcn = createCallbackFcn(app, @EndEditFieldValueChanged, true);
app.End4EditField.Position = [211 8 100 22];
% Create Experiment5Panel
app.Experiment5Panel = uipanel(app.LeftPanel);
app.Experiment5Panel.Title = 'Experiment 5';
app.Experiment5Panel.Position = [111 21 320 150];
% Create Experiment5ListBox
app.Experiment5ListBox = uilistbox(app.Experiment5Panel);
app.Experiment5ListBox.Items = {};
app.Experiment5ListBox.ValueChangedFcn = createCallbackFcn(app, @ExperimentListBoxValueChanged, true);
app.Experiment5ListBox.Position = [11 9 80 110];
app.Experiment5ListBox.Value = {};
% Create Electrodes5ListBox
app.Electrodes5ListBox = uilistbox(app.Experiment5Panel);
app.Electrodes5ListBox.Items = {};
app.Electrodes5ListBox.Multiselect = 'on';
app.Electrodes5ListBox.ValueChangedFcn = createCallbackFcn(app, @ElectrodesListBoxValueChanged, true);
app.Electrodes5ListBox.Position = [101 9 50 110];
app.Electrodes5ListBox.Value = {};
% Create ClusterDropDownLabel_5
app.ClusterDropDownLabel_5 = uilabel(app.Experiment5Panel);
app.ClusterDropDownLabel_5.HorizontalAlignment = 'right';
app.ClusterDropDownLabel_5.Position = [161 97 40 22];
app.ClusterDropDownLabel_5.Text = 'Cluster';
% Create Cluster5DropDown
app.Cluster5DropDown = uidropdown(app.Experiment5Panel);
app.Cluster5DropDown.Items = {'Original', 'Cluster 1', 'Cluster 2', 'Cluster 3', 'Custom'};
app.Cluster5DropDown.ValueChangedFcn = createCallbackFcn(app, @ClusterDropDownValueChanged, true);
app.Cluster5DropDown.Position = [211 99 100 20];
app.Cluster5DropDown.Value = 'Original';
% Create TimeDropDownLabel_5
app.TimeDropDownLabel_5 = uilabel(app.Experiment5Panel);
app.TimeDropDownLabel_5.HorizontalAlignment = 'right';
app.TimeDropDownLabel_5.Position = [161 67 40 22];
app.TimeDropDownLabel_5.Text = 'Time';
% Create Time5DropDown
app.Time5DropDown = uidropdown(app.Experiment5Panel);
app.Time5DropDown.Items = {'Original', 'Dogma', 'Custom'};
app.Time5DropDown.ValueChangedFcn = createCallbackFcn(app, @TimeDropDownValueChanged, true);
app.Time5DropDown.Position = [211 69 100 20];
app.Time5DropDown.Value = 'Original';
% Create StartEditFieldLabel_5
app.StartEditFieldLabel_5 = uilabel(app.Experiment5Panel);
app.StartEditFieldLabel_5.HorizontalAlignment = 'right';
app.StartEditFieldLabel_5.Position = [161 38 40 22];
app.StartEditFieldLabel_5.Text = 'Start';
% Create Start5EditField
app.Start5EditField = uieditfield(app.Experiment5Panel, 'numeric');
app.Start5EditField.ValueChangedFcn = createCallbackFcn(app, @StartEditFieldValueChanged, true);
app.Start5EditField.Position = [211 38 100 22];
% Create EndEditFieldLabel_5
app.EndEditFieldLabel_5 = uilabel(app.Experiment5Panel);
app.EndEditFieldLabel_5.HorizontalAlignment = 'right';
app.EndEditFieldLabel_5.Position = [161 7 40 22];
app.EndEditFieldLabel_5.Text = 'End';
% Create End5EditField
app.End5EditField = uieditfield(app.Experiment5Panel, 'numeric');
app.End5EditField.ValueChangedFcn = createCallbackFcn(app, @EndEditFieldValueChanged, true);
app.End5EditField.Position = [211 7 100 22];
% Create RightPanel
app.RightPanel = uipanel(app.GridLayout);
app.RightPanel.Layout.Row = 1;
app.RightPanel.Layout.Column = 2;
% Create PlotButton
app.PlotButton = uibutton(app.RightPanel, 'state');
app.PlotButton.ValueChangedFcn = createCallbackFcn(app, @PlotButtonValueChanged, true);
app.PlotButton.Text = 'Plot';
app.PlotButton.Position = [11 780 50 30];
% Create DifferenceWaveButton
app.DifferenceWaveButton = uibutton(app.RightPanel, 'state');
app.DifferenceWaveButton.ValueChangedFcn = createCallbackFcn(app, @DifferenceWaveButtonValueChanged, true);
app.DifferenceWaveButton.Text = 'Difference Wave';
app.DifferenceWaveButton.Position = [69 780 104 30];
% Create PlotIrregularButton
app.PlotIrregularButton = uibutton(app.RightPanel, 'state');
app.PlotIrregularButton.ValueChangedFcn = createCallbackFcn(app, @PlotIrregularButtonValueChanged, true);
app.PlotIrregularButton.Text = 'Plot Irregular';
app.PlotIrregularButton.Position = [180 780 84 30];
% Create UITableSPN
app.UITableSPN = uitable(app.RightPanel);
app.UITableSPN.ColumnName = {'Column 1'; 'Column 2'; 'Column 3'; 'Column 4'};
app.UITableSPN.RowName = {};
app.UITableSPN.FontSize = 10;
app.UITableSPN.Position = [11 110 302 200];
% Create DiaryOutput
app.DiaryOutput = uitextarea(app.RightPanel);
app.DiaryOutput.Position = [11 20 300 70];
% Create ExportButton
app.ExportButton = uibutton(app.RightPanel, 'push');
app.ExportButton.ButtonPushedFcn = createCallbackFcn(app, @ExportButtonValueChanged, true);
app.ExportButton.Position = [271 779 50 30];
app.ExportButton.Text = 'Export';
% Create UIAxesWaveform
app.UIAxesWaveform = uiaxes(app.RightPanel);
title(app.UIAxesWaveform, 'Title')
xlabel(app.UIAxesWaveform, 'X')
ylabel(app.UIAxesWaveform, 'Y')
zlabel(app.UIAxesWaveform, 'Z')
app.UIAxesWaveform.PlotBoxAspectRatio = [1.75483870967742 1 1];
app.UIAxesWaveform.FontSize = 10;
app.UIAxesWaveform.Position = [11 550 310 200];
% Create UIAxesBar
app.UIAxesBar = uiaxes(app.RightPanel);
title(app.UIAxesBar, 'Title')
xlabel(app.UIAxesBar, 'X')
ylabel(app.UIAxesBar, 'Y')
zlabel(app.UIAxesBar, 'Z')
app.UIAxesBar.PlotBoxAspectRatio = [1.75483870967742 1 1];
app.UIAxesBar.FontSize = 10;
app.UIAxesBar.Position = [11 330 310 200];
% Show the figure after all components are created
app.UIFigure.Visible = 'on';
end
end
% App creation and deletion
methods (Access = public)
% Construct app
function app = SPNCAT_func(varargin)
% Create UIFigure and components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
% Execute the startup function
runStartupFcn(app, @(app)startupFcn(app, varargin{:}))
if nargout == 0
clear app
end
end
% Code that executes before app deletion
function delete(app)
% Delete UIFigure when app is deleted
delete(app.UIFigure)
end
end
end