init
This commit is contained in:
BIN
PDToolkit/@PDExperiment/.DS_Store
vendored
Normal file
BIN
PDToolkit/@PDExperiment/.DS_Store
vendored
Normal file
Binary file not shown.
87
PDToolkit/@PDExperiment/PDExperiment.m
Normal file
87
PDToolkit/@PDExperiment/PDExperiment.m
Normal file
@@ -0,0 +1,87 @@
|
||||
classdef PDExperiment
|
||||
properties
|
||||
name
|
||||
description
|
||||
filename
|
||||
subjects
|
||||
date
|
||||
handle
|
||||
settings = PDSettings
|
||||
% struct('BaselineCorrection', 0,...
|
||||
% 'FilterSize', 100, ...
|
||||
% 'BlinkExtension', [10 10],...
|
||||
% 'MaximumBlinkSize', 1000,...
|
||||
% 'QualityThreshold',50);
|
||||
%
|
||||
% bl_types = {'None',...
|
||||
% 'Average', ...
|
||||
% 'Min', ...
|
||||
% 'Percentile', ...
|
||||
% 'Offset (fitted line)'};
|
||||
|
||||
aggregates %= PDAggregate;
|
||||
|
||||
end
|
||||
methods
|
||||
|
||||
function[obj] = PDExperiment(varargin)
|
||||
if nargin > 0
|
||||
if strcmp(class(varargin{1}), 'PDSubject')
|
||||
obj.subjects = varargin{1};
|
||||
|
||||
for s = 1:length(obj.subjects)
|
||||
obj.subjects(s).index = s;
|
||||
obj.subjects(s).name = sprintf('Subject %d', s);
|
||||
end
|
||||
else
|
||||
if exist(varargin{1},'dir')
|
||||
obj = obj.buildExperiment(varargin{1});
|
||||
else
|
||||
if strcmp(varargin{1}, 'placeholder');
|
||||
% create an empty PDExperiment object (for GUI purposes)
|
||||
else
|
||||
error('Incorrect path entered / No PDSubjects entered');
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if nargin ==1
|
||||
if (strcmp(varargin{1}, 'placeholder'))
|
||||
else
|
||||
obj = obj.askForBaseline;
|
||||
end
|
||||
else
|
||||
if ischar(varargin{2})
|
||||
is_bl_type = find(strcmp(obj.bl_types, varargin{2}));
|
||||
if isempty(is_bl_type)
|
||||
warning('Baseline correction type is unknown.');
|
||||
obj = obj.askForBaseline;
|
||||
|
||||
else
|
||||
obj.settings.BaselineCorrection = is_bl_type;
|
||||
try
|
||||
obj.settings.BaselineCorrectionPercentile = varargin{3};
|
||||
catch
|
||||
end
|
||||
|
||||
end
|
||||
else
|
||||
obj.settings.BaselineCorrection = varargin{2};
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
error('No subjects entered');
|
||||
end
|
||||
|
||||
|
||||
|
||||
obj = obj.consolidateSettings;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
108
PDToolkit/@PDExperiment/add_aggregate.m
Normal file
108
PDToolkit/@PDExperiment/add_aggregate.m
Normal file
@@ -0,0 +1,108 @@
|
||||
function[e] = add_aggregate(varargin)
|
||||
e = varargin{1}
|
||||
|
||||
%% magical stuff so we are not overwriting...
|
||||
fig = gcf;%e.handle(2);
|
||||
figure(fig);
|
||||
plotwindow_id = num2str(fig);
|
||||
|
||||
subj_pop = findobj('Tag', ['subj_pop.' plotwindow_id]);
|
||||
sess_pop = findobj('Tag', ['sess_pop.' plotwindow_id]);
|
||||
trial_pop = findobj('Tag', ['trial_pop.' plotwindow_id]);
|
||||
select_edit = findobj('Tag', ['select_edit.' plotwindow_id]);
|
||||
|
||||
subject_val = get(subj_pop, 'Value');
|
||||
session_val = get(sess_pop, 'Value');
|
||||
trial_val = get(trial_pop, 'Value');
|
||||
select_edit = get(select_edit, 'String');
|
||||
|
||||
subject_strings = cellstr(get(subj_pop, 'String'));
|
||||
session_strings = cellstr(get(sess_pop, 'String'));
|
||||
trial_strings = cellstr(get(trial_pop, 'String'));
|
||||
|
||||
if iscell(subject_val)
|
||||
subjects = subject_strings{subject_val{1}};
|
||||
else
|
||||
subjects = subject_strings{subject_val};
|
||||
end
|
||||
|
||||
|
||||
if iscell(session_val)
|
||||
sessions = session_val{1};
|
||||
else
|
||||
sessions = session_val;
|
||||
end
|
||||
|
||||
if iscell(trial_val)
|
||||
trials = trial_strings{trial_val{1}};
|
||||
else
|
||||
trials = trial_strings{trial_val};
|
||||
end
|
||||
tmp = get(fig, 'UserData');
|
||||
|
||||
if isempty(tmp)
|
||||
tmp;
|
||||
end
|
||||
|
||||
switch subjects
|
||||
case 1
|
||||
subjects = 1:length(e.subjects);
|
||||
case 2
|
||||
subjects = tmp.selected_subjects;
|
||||
end
|
||||
|
||||
switch sessions
|
||||
case 1
|
||||
sessions= 1:length(e.subjects(1).sessions);
|
||||
case 2
|
||||
sessions = tmp.selected_subjects;
|
||||
end
|
||||
|
||||
switch trials
|
||||
case 1
|
||||
trials = 1:length(e.subjects(1).sessions(1).trials);
|
||||
case 2
|
||||
trials = tmp.selected_subjects;
|
||||
end
|
||||
|
||||
|
||||
groupname = inputdlg('Give a name for the group');
|
||||
if isempty(groupname)
|
||||
return;
|
||||
end
|
||||
|
||||
color = uisetcolor('Choose a color');
|
||||
if length(color) ==1
|
||||
return;
|
||||
end
|
||||
|
||||
|
||||
|
||||
agg_id = length(e.aggregates)+1
|
||||
|
||||
if (length(color) == 1)
|
||||
color = repmat(color, 1,3);
|
||||
end
|
||||
|
||||
|
||||
|
||||
e.aggregates(agg_id).name = groupname;
|
||||
e.aggregates(agg_id).subjects = subjects;
|
||||
e.aggregates(agg_id).sessions = sessions;
|
||||
e.aggregates(agg_id).trials = trials;
|
||||
e.aggregates(agg_id).color = color;
|
||||
|
||||
e.aggregates(agg_id).mean = [];
|
||||
e.aggregates(agg_id).std = [];
|
||||
e.aggregates(agg_id).var = [];
|
||||
|
||||
e.aggregates(agg_id).error.name = 'None';
|
||||
%e.aggregates(agg_id).variance = variance;
|
||||
|
||||
|
||||
e = e.update_aggregates;
|
||||
|
||||
assignin('base','e',e);
|
||||
|
||||
|
||||
|
45
PDToolkit/@PDExperiment/askForBaseline.m
Normal file
45
PDToolkit/@PDExperiment/askForBaseline.m
Normal file
@@ -0,0 +1,45 @@
|
||||
function[obj] = askForBaseline(obj)
|
||||
|
||||
bl_types = {'None',...
|
||||
'Average', ...
|
||||
'Min', ...
|
||||
'Lowest n% average', ...
|
||||
'Offset (fitted line)',...
|
||||
'Fixed point'};
|
||||
|
||||
np_types = [10 15 20 25 50];
|
||||
np_labels= {'10%',...
|
||||
'15%', ...
|
||||
'20%', ...
|
||||
'25%', ...
|
||||
'50%',...
|
||||
'Other'};
|
||||
|
||||
[s,OkClicked] = listdlg('PromptString','Select a baseline correction:',...
|
||||
'SelectionMode','single',...
|
||||
'ListString',bl_types, 'ListSize', [150 75]);
|
||||
|
||||
if OkClicked
|
||||
if (s == 4)
|
||||
[s2,OkClicked] = listdlg('PromptString','Select a percentile:',...
|
||||
'SelectionMode','single',...
|
||||
'ListString',np_labels, 'ListSize', [150 75]);
|
||||
|
||||
if (s2 == 6)
|
||||
wrong_answer =1;
|
||||
while wrong_answer
|
||||
line = inputdlg({'Other percentile :'}, 'Percentile', 1, {'25'});
|
||||
answer = str2num(line{1});
|
||||
wrong_answer = ~((answer > 0) && (answer < 100));
|
||||
end
|
||||
percentile = answer;
|
||||
else
|
||||
percentile = np_types(s2);
|
||||
end
|
||||
|
||||
obj.settings.BaselineCorrection = [s-1 percentile];
|
||||
else
|
||||
obj.settings.BaselineCorrection = [s-1];
|
||||
end
|
||||
end
|
||||
|
17
PDToolkit/@PDExperiment/buildExperiment.m
Normal file
17
PDToolkit/@PDExperiment/buildExperiment.m
Normal file
@@ -0,0 +1,17 @@
|
||||
function[e] = buildExperiment(obj, path)
|
||||
|
||||
e = obj;
|
||||
folder_contents = dir(path);
|
||||
|
||||
folders = [folder_contents.isdir];
|
||||
folder_ind = find(folders);
|
||||
j=1;
|
||||
for s = 3:length(folder_ind) % 1 and 2 are . and ..
|
||||
%% load subject s
|
||||
|
||||
subject_path = [path filesep folder_contents(folder_ind(s)).name];
|
||||
subjects(j) = PDSubject(subject_path);
|
||||
j=j+1;
|
||||
end
|
||||
|
||||
e.subjects = subjects;
|
155
PDToolkit/@PDExperiment/build_averages.m
Normal file
155
PDToolkit/@PDExperiment/build_averages.m
Normal file
@@ -0,0 +1,155 @@
|
||||
function[e] = build_averages(e)
|
||||
|
||||
plotwindow = figure;
|
||||
plotwindow_id = num2str(plotwindow);
|
||||
|
||||
pos = get(plotwindow, 'Position');
|
||||
pos(3) = 900;
|
||||
|
||||
set(plotwindow, 'Position', pos);
|
||||
set(plotwindow, 'Color', [1 1 1]);
|
||||
|
||||
e.handle(2) = plotwindow;
|
||||
|
||||
subj_pop = uicontrol('Style','popupmenu');
|
||||
sess_pop = uicontrol('Style','popupmenu');
|
||||
trial_pop = uicontrol('Style','popupmenu');
|
||||
|
||||
add_group_btn = uicontrol('Style', 'pushbutton');
|
||||
rem_group_btn = uicontrol('Style', 'pushbutton');
|
||||
|
||||
subj_pop_string = 'All subjects|Selection of subjects'; subj_pop_vals =[999 998];
|
||||
sess_pop_string = 'All sessions|First sessions|Second sessions'; sess_pop_vals =[999 998 997];
|
||||
trial_pop_string = 'All trials|Selection of trials';
|
||||
|
||||
for s = 1:length(e.subjects)
|
||||
subj_pop_string = [subj_pop_string '|' e.subjects(s).name];
|
||||
subj_pop_vals = [subj_pop_vals s];
|
||||
end
|
||||
|
||||
set(subj_pop, 'Position', [10 400 150 20]);
|
||||
set(subj_pop, 'String', subj_pop_string);
|
||||
set(subj_pop, 'Value', 1);
|
||||
set(subj_pop, 'Callback', 'e.enable_selection_edit(''subject'')');
|
||||
set(subj_pop, 'FontName', 'Verdana');
|
||||
set(subj_pop, 'FontWeight', 'bold');
|
||||
set(subj_pop, 'FontSize', 11);
|
||||
|
||||
sel=get(subj_pop, 'Value');
|
||||
|
||||
for s = 1:length(e.subjects(sel).sessions);
|
||||
sess_pop_string = [sess_pop_string '|' e.subjects(sel).sessions(s).name];
|
||||
sess_pop_vals = [sess_pop_vals s];
|
||||
end
|
||||
|
||||
set(sess_pop, 'Position', [10 375 150 20]);
|
||||
set(sess_pop, 'String', sess_pop_string);
|
||||
set(sess_pop, 'Value', 1);
|
||||
set(sess_pop, 'Callback', 'e.enable_selection_edit(''session'')');
|
||||
set(sess_pop, 'FontName', 'Verdana');
|
||||
set(sess_pop, 'FontWeight', 'bold');
|
||||
set(sess_pop, 'FontSize', 11);
|
||||
|
||||
selsess = get(sess_pop, 'Value');
|
||||
|
||||
set(sess_pop, 'Position', [10 375 150 20]);
|
||||
set(sess_pop, 'String', sess_pop_string);
|
||||
set(sess_pop, 'Value', 1);
|
||||
set(sess_pop, 'Callback', '');
|
||||
set(sess_pop, 'FontName', 'Verdana');
|
||||
set(sess_pop, 'FontWeight', 'bold');
|
||||
set(sess_pop, 'FontSize', 11);
|
||||
|
||||
unique_matches = unique({e.subjects(1).sessions(1).labels.match});
|
||||
unique_labels = unique({e.subjects(1).sessions(1).labels.label});
|
||||
|
||||
for t = 1:length(unique_matches)
|
||||
trial_pop_string = [trial_pop_string '|' unique_matches{t}];
|
||||
end
|
||||
|
||||
for t = 1:length(unique_labels)
|
||||
trial_pop_string = [trial_pop_string '|' unique_labels{t}];
|
||||
end
|
||||
|
||||
set(trial_pop, 'Position', [10 350 150 20]);
|
||||
set(trial_pop, 'String', trial_pop_string);
|
||||
set(trial_pop, 'Value', 1);
|
||||
set(trial_pop, 'Callback', 'e.enable_selection_edit(''trial'')');
|
||||
set(trial_pop, 'FontName', 'Verdana');
|
||||
set(trial_pop, 'FontWeight', 'bold');
|
||||
set(trial_pop, 'FontSize', 11);
|
||||
|
||||
select_edit(1) = uicontrol('Style', 'edit');
|
||||
select_edit(2) = uicontrol('Style', 'edit');
|
||||
select_edit(3) = uicontrol('Style', 'edit');
|
||||
set(select_edit(1), 'Position', [170 400 150 20]);
|
||||
set(select_edit(2), 'Position', [170 375 150 20]);
|
||||
set(select_edit(3), 'Position', [170 350 150 20]);
|
||||
set(select_edit, 'Visible' ,'off');
|
||||
|
||||
set(select_edit, 'String', []);
|
||||
set(select_edit, 'FontName', 'Verdana');
|
||||
set(select_edit, 'FontWeight', 'bold');
|
||||
set(select_edit, 'FontSize', 11);
|
||||
set(select_edit, 'Enable' ,'off');
|
||||
|
||||
set(select_edit(1), 'Tag', ['selection_edit.subject.' plotwindow_id]);
|
||||
set(select_edit(1), 'Callback', 'e.evaluate_selection(''subject'')');
|
||||
set(select_edit(2), 'Tag', ['selection_edit.session.' plotwindow_id]);
|
||||
set(select_edit(2), 'Callback', 'e.evaluate_selection(''session'')');
|
||||
set(select_edit(3), 'Tag', ['selection_edit.trial.' plotwindow_id]);
|
||||
set(select_edit(3), 'Callback', 'e.evaluate_selection(''trial'')');
|
||||
plot([]);
|
||||
pos = get(gca, 'Position');
|
||||
set(gca, 'Position', [.225 .275 .6 .7]);
|
||||
set(gca, 'FontName', 'Verdana');
|
||||
set(gca, 'FontWeight', 'bold');
|
||||
set(gca, 'FontSize', 10);
|
||||
set(gca, 'Box', 'on');
|
||||
|
||||
set(add_group_btn, 'Position', [10 190 70 20]);
|
||||
set(rem_group_btn, 'Position', [90 190 70 20]);
|
||||
|
||||
set(add_group_btn, 'String', 'Add');
|
||||
set(add_group_btn, 'Callback', @e.add_aggregate);
|
||||
|
||||
set(rem_group_btn, 'String', 'Remove');
|
||||
set(rem_group_btn, 'Callback', 'e.remove_aggregate');
|
||||
|
||||
jList = java.util.ArrayList;
|
||||
|
||||
%% set Tags
|
||||
set(subj_pop, 'Tag', ['subj_pop.' plotwindow_id]);
|
||||
set(sess_pop, 'Tag', ['sess_pop.' plotwindow_id]);
|
||||
set(trial_pop, 'Tag', ['trial_pop.' plotwindow_id]);
|
||||
|
||||
%% list aggregates
|
||||
agg_strings={};
|
||||
for i = 1:length(e.aggregates)
|
||||
add_strings{i,1} = 1;
|
||||
|
||||
color_str = ['#' sprintf('%02s', dec2hex(e.aggregates(i).color(1)*255)) ...
|
||||
sprintf('%02s', dec2hex(e.aggregates(i).color(2)*255)) ...
|
||||
sprintf('%02s', dec2hex(e.aggregates(i).color(3)*255))];
|
||||
agg_strings{i,2} = ['<html><li color=' color_str '><font color=#000000>'...
|
||||
e.aggregates(i).name{1} ...
|
||||
'</font></li></html>'];
|
||||
%agg_strings{i,3} = e.aggregates(i).error.name;
|
||||
|
||||
end
|
||||
cheaders = {'', 'Name', 'Error'};
|
||||
cformats = {'logical' ,'char', {'None', 'Std', 'Var'}};
|
||||
editable = [true false true],
|
||||
table = uitable('Position', [10 215 150 125], ...
|
||||
'Data', agg_strings, ...
|
||||
'ColumnName', cheaders, ...
|
||||
'ColumnFormat', cformats, ...
|
||||
'ColumnWidth', {20 'auto' 65},...
|
||||
'ColumnEditable', editable, ...
|
||||
'RowName',[]);
|
||||
|
||||
%set(table, 'ButtonDownFcn', 'e.select_aggregate');
|
||||
set(table, 'CellSelectionCallback', @e.select_aggregate);
|
||||
set(table, 'ButtonDownFcn', @e.button_down_on_aggregate);
|
||||
set(table, 'Tag', 'aggragate_table');
|
||||
|
104
PDToolkit/@PDExperiment/calculate_aggregate.m
Normal file
104
PDToolkit/@PDExperiment/calculate_aggregate.m
Normal file
@@ -0,0 +1,104 @@
|
||||
function[e] = calculate_aggregate(e, index);
|
||||
%
|
||||
% Extract aggregated data based on parameters / selection of
|
||||
% subjects/sessions/trials
|
||||
%
|
||||
aggregate = e.aggregates(index);
|
||||
|
||||
try
|
||||
tmp = aggregate.trials;
|
||||
aggregate.trials = str2num(aggregate.trials);
|
||||
if (isempty(aggregate.trials))
|
||||
aggregate.trials = tmp;
|
||||
end
|
||||
catch
|
||||
end
|
||||
|
||||
%% rewrite all subjects to list of subjects...
|
||||
|
||||
if strcmp(aggregate.subjects, 'All subjects')
|
||||
e.aggregates(index).subjects = 1:length(e.subjects);
|
||||
end
|
||||
|
||||
if strcmp(aggregate.sessions, 'All sessions')
|
||||
e.aggregates(index).sessions = 1:length(e.subjects(1).sessions);
|
||||
end
|
||||
aggregate = e.aggregates(index);
|
||||
|
||||
stimulus_onsets = {};
|
||||
|
||||
idx =1;
|
||||
for sub = 1:length(aggregate.subjects)
|
||||
|
||||
subject_id = aggregate.subjects(sub);
|
||||
|
||||
|
||||
for sess = 1:length(aggregate.sessions)
|
||||
|
||||
sess_id = aggregate.sessions(sess);
|
||||
%trial_query = aggregate.trials;
|
||||
|
||||
trials = aggregate.trials{subject_id}{sess_id};
|
||||
%aggregate.e.get_trials_based_on_label(e.subjects(subject_id).sessions(sess_id), trial_query);
|
||||
|
||||
for t = 1:length(trials)
|
||||
trial_id = trials(t);
|
||||
trial_list(idx) = e.subjects(subject_id).sessions(sess_id).trials(trial_id).data;
|
||||
stimulus_onsets{idx} = e.subjects(subject_id).sessions(sess_id).trials(trial_id).stimulus_onset - ...
|
||||
e.subjects(subject_id).sessions(sess_id).trials(trial_id).trial_start;
|
||||
idx = idx + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if isempty(find(~cellfun(@isempty,stimulus_onsets)));
|
||||
display('return?');
|
||||
return;
|
||||
|
||||
end
|
||||
|
||||
min_onset = min([stimulus_onsets{:}]);
|
||||
max_onset = min([stimulus_onsets{:}]);
|
||||
|
||||
diffs = [stimulus_onsets{:}] - min_onset;
|
||||
|
||||
max_diff = max(diffs);
|
||||
|
||||
clear trials
|
||||
for t = 1:length(trial_list)
|
||||
try
|
||||
trials{t} = [ nan(1,max_diff - diffs(t)) trial_list(t).baseline_corrected.filtered(diffs(t)+1:end-max_diff)' ];
|
||||
catch
|
||||
display('error');
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
min_trial_length = min(cellfun(@length, trials));
|
||||
|
||||
|
||||
for t = 1:length(trial_list)
|
||||
try
|
||||
trial_mat(t,:) = trials{t}(1:min_trial_length);
|
||||
catch
|
||||
end
|
||||
end
|
||||
|
||||
mean_trial = mean(trial_mat);
|
||||
std_trial = std(trial_mat);
|
||||
var_trial = var(trial_mat);
|
||||
|
||||
l = length(mean_trial);
|
||||
|
||||
mean_trial([1:e.settings.FilterSize end-e.settings.FilterSize:end]) = NaN;
|
||||
std_trial([1:e.settings.FilterSize end-e.settings.FilterSize:end]) = NaN;
|
||||
var_trial([1:e.settings.FilterSize end-e.settings.FilterSize:end]) = NaN;
|
||||
|
||||
aggregate.mean = mean_trial;
|
||||
aggregate.std = std_trial;
|
||||
aggregate.var = var_trial;
|
||||
|
||||
|
||||
e.aggregates(index).data = aggregate;
|
||||
|
7
PDToolkit/@PDExperiment/calculate_aggregates.m
Normal file
7
PDToolkit/@PDExperiment/calculate_aggregates.m
Normal file
@@ -0,0 +1,7 @@
|
||||
function[e] = calculate_aggregates(e)
|
||||
|
||||
for a = 1:length(e.aggregates)
|
||||
display(sprintf('calculating aggregate %d...', a));
|
||||
e = e.calculate_aggregate(a);
|
||||
|
||||
end
|
6
PDToolkit/@PDExperiment/consolidateSettings.m
Normal file
6
PDToolkit/@PDExperiment/consolidateSettings.m
Normal file
@@ -0,0 +1,6 @@
|
||||
function[obj] = consolidateSettings(obj);
|
||||
|
||||
|
||||
for s = 1:length(obj.subjects)
|
||||
obj.subjects(s) = obj.subjects(s).setSettings(obj.settings);
|
||||
end
|
51
PDToolkit/@PDExperiment/enable_selection_edit.m
Normal file
51
PDToolkit/@PDExperiment/enable_selection_edit.m
Normal file
@@ -0,0 +1,51 @@
|
||||
function[e] = enable_selection_edit(e, type)
|
||||
|
||||
fig = gcf;%e.handle(2);
|
||||
plotwindow_id = num2str(fig);
|
||||
figure(fig);
|
||||
|
||||
if strcmp(type,'subject'), code = 'subj'; end
|
||||
if strcmp(type,'session'), code = 'sess'; end
|
||||
if strcmp(type,'trial'), code = 'trial'; end
|
||||
|
||||
% Only continue if selection edit is requested:
|
||||
popup = findobj('Tag', [code '_pop.' plotwindow_id]);
|
||||
select_edit = findobj('Tag', ['selection_edit.' type '.' plotwindow_id]);
|
||||
|
||||
if ~(get(popup,'Value') == 2)
|
||||
uicontrol(popup);
|
||||
set(select_edit, 'Visible', 'off');
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
tmp = get(fig, 'UserData');
|
||||
|
||||
select_edit = findobj('Tag', ['selection_edit.' type '.' plotwindow_id]);
|
||||
string = '';
|
||||
if ~isempty(tmp)
|
||||
|
||||
switch type
|
||||
case 'subject'
|
||||
if isfield(tmp, 'selected_subjects')
|
||||
string = num2str(tmp.selected_subjects);
|
||||
end
|
||||
case 'session'
|
||||
if isfield(tmp, 'selected_sessions')
|
||||
string = num2str(tmp.selected_sessions);
|
||||
end
|
||||
case 'trial'
|
||||
if isfield(tmp, 'selected_trials')
|
||||
string = num2str(tmp.selected_trials);
|
||||
end
|
||||
end
|
||||
|
||||
set(select_edit, 'String', string);
|
||||
set(select_edit, 'Callback', ['e.evaluate_selection(''' type ''')']);
|
||||
set(select_edit, 'UserData', type);
|
||||
else
|
||||
end
|
||||
set(fig, 'UserData', tmp);
|
||||
set(select_edit, 'Visible', 'on');
|
||||
set(select_edit, 'Enable', 'on');
|
||||
uicontrol(select_edit);
|
69
PDToolkit/@PDExperiment/evaluate_selection.m
Normal file
69
PDToolkit/@PDExperiment/evaluate_selection.m
Normal file
@@ -0,0 +1,69 @@
|
||||
function[] = evaluate_selection(e, type)
|
||||
|
||||
if strcmp(type,'subject'), code = 'subj'; end
|
||||
if strcmp(type,'session'), code = 'sess'; end
|
||||
if strcmp(type,'trial'), code = 'trial'; end
|
||||
|
||||
plotwindow = gcf;
|
||||
plotwindow_id = num2str(plotwindow);
|
||||
|
||||
|
||||
|
||||
fig = gcf;
|
||||
plotwindow_id = num2str(fig);
|
||||
select_edit = findobj('Tag', ['selection_edit.' type '.' plotwindow_id]);
|
||||
|
||||
|
||||
selection_cell = get(select_edit, 'String');
|
||||
try
|
||||
selection = eval(str2num(selection_cell));
|
||||
catch
|
||||
selection = str2num(selection_cell);
|
||||
if ~isnumeric(selection)
|
||||
msgbox('Could not parse entered data');
|
||||
end
|
||||
end
|
||||
|
||||
%fig = e.handle(2);
|
||||
|
||||
tmp = get(fig, 'UserData');
|
||||
|
||||
if (strcmp(type, 'subject'))
|
||||
selection = intersect(selection, 1:length(e.subjects));
|
||||
if isempty(selection)
|
||||
display('Empty selection');
|
||||
else
|
||||
set(select_edit,'String', num2str(selection));
|
||||
tmp.selected_subjects = selection;
|
||||
end
|
||||
end
|
||||
|
||||
if (strcmp(type, 'session'))
|
||||
tmp.selected_sessions = selection;
|
||||
end
|
||||
|
||||
if (strcmp(type, 'trial'))
|
||||
tmp.selected_trials = selection;
|
||||
end
|
||||
|
||||
set(fig, 'UserData', tmp);
|
||||
|
||||
%% Add the selection to the list and set the popup
|
||||
|
||||
popup = findobj('Tag', [code '_pop.' plotwindow_id]);
|
||||
pop_string = get(popup,'String');
|
||||
itemsize= size(pop_string);
|
||||
new_item = num2str(selection);
|
||||
|
||||
newsize = max(length(new_item), itemsize(2));
|
||||
pop_string(:,itemsize(2)+1:newsize) = ' ';
|
||||
new_item(end+1:newsize)= ' ';
|
||||
pop_string(itemsize(1)+1,:) = new_item;
|
||||
|
||||
[ui ui_ind] = unique(cellstr(pop_string));
|
||||
|
||||
set(popup, 'String', pop_string(sort(ui_ind),:));
|
||||
set(popup, 'Value', length(ui_ind));
|
||||
|
||||
set(select_edit, 'Visible', 'off');
|
||||
assignin('base','e',e);
|
189
PDToolkit/@PDExperiment/export_data.m
Normal file
189
PDToolkit/@PDExperiment/export_data.m
Normal file
@@ -0,0 +1,189 @@
|
||||
function[data] = export_data(e, file_out, varargin)
|
||||
% Export routine for the PDExperiment class:
|
||||
%
|
||||
% Exports a datatable with relevant properties and statistics
|
||||
%
|
||||
% Thresholding:
|
||||
%
|
||||
% Quality -> Thresholding.Quality = [0/1],
|
||||
% Default Quality Threshold adopted from
|
||||
% PDExperiment class, can be altered in
|
||||
% extra parameter QualityThreshold
|
||||
%
|
||||
% Baseline -> Thresholding.Baseline = [0/1]
|
||||
% Check whether baseline is within range
|
||||
% BaselineThreshold specifies this setting
|
||||
%
|
||||
|
||||
% BlinkCount -> Thresholding.BlinkCount = [0/1]
|
||||
% Check whether BlinkCount is within range
|
||||
% BlinkCountThreshold specifies this setting
|
||||
%
|
||||
% MissingLabels -> Thresholding.MissingLabels = [0/1]
|
||||
% MissingLabels is an optional cell array
|
||||
% to filter trials without those labels/fieldnames
|
||||
%
|
||||
% MatchingLabels -> Thresholding.Label = [0/1]
|
||||
% MatchingLabels is an optional cell array
|
||||
% to filter labels with a certain value
|
||||
%
|
||||
|
||||
settings = struct('Delimiter', ',',...
|
||||
'LineEndings', '\n',...
|
||||
'Thresholding', struct('Quality', 0, ...
|
||||
'Baseline', 0, ...
|
||||
'BlinkCount', 0, ...
|
||||
'MissingLabels',0,...
|
||||
'Label',0), ...), ...
|
||||
'QualityThreshold', e.settings.QualityThreshold, ...
|
||||
'BaselineThreshold', [],...
|
||||
'BlinkCountThreshold', Inf, ...
|
||||
'MissingLabels', {},...
|
||||
'MatchingLabels', {});
|
||||
|
||||
settings(1).QualityThreshold = e.settings.QualityThreshold;
|
||||
settings = parse(settings, varargin);
|
||||
|
||||
max_typelength = -1; max_tl_ind = -1;
|
||||
for i = 1:length(e.subjects(1).sessions(1).trials)
|
||||
if max_typelength < length(fieldnames(e.subjects(1).sessions(1).trials(i).type))
|
||||
max_tl_ind = i;
|
||||
end
|
||||
max_typelength = max(max_typelength, length(fieldnames(e.subjects(1).sessions(1).trials(i).type)));
|
||||
end
|
||||
|
||||
types = fieldnames(e.subjects(1).sessions(1).trials(max_tl_ind).type);
|
||||
type_header = '';format_type_header ='';
|
||||
|
||||
for t = 1:length(types)
|
||||
type_header = [type_header types{t} sep '# of chars' sep];
|
||||
format_type_header = [format_type_header str_f sep];
|
||||
end
|
||||
|
||||
header = ['Subject' sep ...
|
||||
'Datafile' sep ...
|
||||
'Subject Id' sep ...
|
||||
'Session' sep ...
|
||||
'Trial' sep ...
|
||||
'Quality (%)' sep ...
|
||||
'BlinkCount' sep ...
|
||||
type_header, ...
|
||||
'Baseline (raw)' sep ...
|
||||
'Max' sep ...
|
||||
'TimeOfMax (rel to s.o.)' sep ...
|
||||
'Mean' sep ...
|
||||
'Median' sep ...
|
||||
'Mode' sep ...
|
||||
'Q1 (25%)' sep ...
|
||||
'Q2 (median)' sep ...
|
||||
'Q3 (75%)' sep ...
|
||||
'AUC' le];
|
||||
|
||||
format = [str_f sep ... % subject
|
||||
str_f sep ... % datafile
|
||||
int_f sep ... % subject id
|
||||
int_f sep ... % session
|
||||
int_f sep ... % trial
|
||||
dec_f sep ... % quality
|
||||
int_f sep ... % blinkcount
|
||||
'%s' ... % types are formatted within trial, so string with no formatting
|
||||
dec_f sep ... % baseline
|
||||
dec_f sep ... % max
|
||||
dec_f sep ... % maxtime
|
||||
dec_f sep ... % mean
|
||||
dec_f sep ... % median
|
||||
dec_f sep ... % mode
|
||||
dec_f sep ... % q1
|
||||
dec_f sep ... % q2
|
||||
dec_f sep ... % q3
|
||||
dec_f le]; % AUC
|
||||
|
||||
data = {};
|
||||
|
||||
for s = 1:length(e.subjects)
|
||||
for sess = 1:length(e.subjects(s).sessions)
|
||||
for t = 1:length(e.subjects(s).sessions(sess).trials)
|
||||
trial = e.subjects(s).sessions(sess).trials(t);
|
||||
|
||||
%Continue with the next trial if thresholding is enabled and
|
||||
%trial suffers quality
|
||||
if ((settings.Thresholding.Quality) && (trial.quality < settings.QualityThreshold))
|
||||
continue;
|
||||
end
|
||||
|
||||
if ((settings.Thresholding.Quality) && (trial.quality < settings.QualityThreshold))
|
||||
continue;
|
||||
end
|
||||
|
||||
%% Baseline items can be skipped
|
||||
if (strmatch(trial.type.TRIAL_VAR_stim, 'Baseline'))
|
||||
continue;
|
||||
end
|
||||
|
||||
tt_string = ''; % build string containg type identifiers
|
||||
for tt = 1:length(types)
|
||||
if isfield(trial.type,types{tt})
|
||||
if ischar(trial.type.(types{tt}))
|
||||
numchars = length(strtrim(trial.type.(types{tt})));
|
||||
else
|
||||
numchars = -1;
|
||||
end
|
||||
trial_type_value = trial.type.(types{tt});
|
||||
tt_string = [tt_string ...
|
||||
sprintf([str_f sep], strrep(trial_type_value(1,:),'"', '')) ...
|
||||
sprintf([int_f sep], numchars)];
|
||||
else
|
||||
tt_string = [tt_string ...
|
||||
sprintf([str_f sep], ''), ...
|
||||
sprintf([int_f sep], numchars)];
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
if ~isempty(trial.stats)
|
||||
fprintf(fp, format, ...
|
||||
e.subjects(s).name, ...
|
||||
e.subjects(s).sessions(sess).datafile, ...
|
||||
s, ...
|
||||
sess, ...
|
||||
t, ...
|
||||
trial.quality, ...
|
||||
trial.blink_count, ...
|
||||
tt_string, ...
|
||||
trial.baseline, ...
|
||||
trial.stats.max.value, ...
|
||||
trial.stats.max.time, ...
|
||||
trial.stats.mean, ...
|
||||
trial.stats.median, ...
|
||||
trial.stats.mode, ...
|
||||
trial.stats.q1, ...
|
||||
trial.stats.q2, ...
|
||||
trial.stats.q3, ...
|
||||
trial.stats.auc);
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
fclose(fp);
|
||||
display(sprintf('\t*) Statistics written to %s', file_out));
|
||||
|
||||
|
||||
function[settings] = parse(settings,varlist);
|
||||
if length(varlist)<2;return;end
|
||||
f=fieldnames(settings);
|
||||
for k=2:2:length(varlist);
|
||||
if ~any(strcmp(varlist{k-1},f));
|
||||
error(sprintf('invalid field %s\n',varlist{k-1}));
|
||||
end
|
||||
if isstruct(varlist{k})
|
||||
substructfields = fieldnames(varlist{k});
|
||||
for sf = 1:length(substructfields)
|
||||
settings(1).(varlist{k-1}).(substructfields{sf}) = varlist{k}.(substructfields{sf});
|
||||
end
|
||||
else
|
||||
settings=setfield(settings,varlist{k-1},varlist{k});
|
||||
end
|
||||
end
|
||||
|
224
PDToolkit/@PDExperiment/export_stats.m
Normal file
224
PDToolkit/@PDExperiment/export_stats.m
Normal file
@@ -0,0 +1,224 @@
|
||||
function[] = export_stats(e, file_out, varargin)
|
||||
% Export routine for the PDExperiment class:
|
||||
%
|
||||
% Writes a textfile with relevant properties and statistics
|
||||
% Options: Delimiter -> ','
|
||||
%
|
||||
% Thresholding:
|
||||
%
|
||||
% Quality -> Thresholding.Quality = [0/1],
|
||||
% Default Quality Threshold adopted from
|
||||
% PDExperiment class, can be altered in
|
||||
% extra parameter QualityThreshold
|
||||
%
|
||||
% Baseline -> Thresholding.Baseline = [0/1]
|
||||
% Check whether baseline is within range
|
||||
% BaselineThreshold specifies this setting
|
||||
%
|
||||
|
||||
% BlinkCount -> Thresholding.BlinkCount = [0/1]
|
||||
% Check whether BlinkCount is within range
|
||||
% BlinkCountThreshold specifies this setting
|
||||
%
|
||||
% MissingLabels -> Thresholding.MissingLabels = [0/1]
|
||||
% MissingLabels is an optional cell array
|
||||
% to filter trials without those labels/fieldnames
|
||||
%
|
||||
% MatchingLabels -> Thresholding.Label = [0/1]
|
||||
% MatchingLabels is an optional cell array
|
||||
% to filter labels with a certain value
|
||||
%
|
||||
|
||||
settings = struct('Delimiter', ',',...
|
||||
'LineEndings', '\n',...
|
||||
'Thresholding', struct('Quality', 0, ...
|
||||
'Baseline', 0, ...
|
||||
'BlinkCount', 0, ...
|
||||
'MissingLabels',0,...
|
||||
'Label',0), ...), ...
|
||||
'QualityThreshold', e.settings.QualityThreshold, ...
|
||||
'BaselineThreshold', [],...
|
||||
'BlinkCountThreshold', Inf, ...
|
||||
'MissingLabels', {},...
|
||||
'MatchingLabels', {});
|
||||
|
||||
settings(1).QualityThreshold = e.settings.QualityThreshold;
|
||||
settings(1).Delimiter = ',';
|
||||
settings(1).LineEndings = '\n';
|
||||
|
||||
settings = parse(settings, varargin);
|
||||
fp = fopen(file_out, 'w+');
|
||||
|
||||
fprintf(fp,'%s\\n', repmat('-',1,100));
|
||||
fprintf(fp,'\tExport on:\t %s\n', datestr(now));
|
||||
%sprintf('\tPDParser version:\t%s\n', num2str(e.version));
|
||||
sep = settings.Delimiter; % separator
|
||||
le = settings.LineEndings; %'\n'; % line ending
|
||||
int_f = '%d'; % integer format
|
||||
dec_f = '%8.4f'; % decimal format
|
||||
str_f = '"%s"'; %string format
|
||||
|
||||
|
||||
max_typelength = -1; max_tl_ind = -1;
|
||||
for i = 1:length(e.subjects(1).sessions(1).trials)
|
||||
if max_typelength < length(fieldnames(e.subjects(1).sessions(1).trials(i).type))
|
||||
max_tl_ind = i;
|
||||
end
|
||||
max_typelength = max(max_typelength, length(fieldnames(e.subjects(1).sessions(1).trials(i).type)));
|
||||
end
|
||||
|
||||
types = fieldnames(e.subjects(1).sessions(1).trials(max_tl_ind).type);
|
||||
type_header = '';format_type_header ='';
|
||||
|
||||
for t = 1:length(types)
|
||||
type_header = [type_header types{t} sep '# of chars' sep];
|
||||
format_type_header = [format_type_header str_f sep];
|
||||
end
|
||||
|
||||
cov_header = []; cov_format = [];
|
||||
for i =1:length(e.subjects(1).covariates)
|
||||
cov_header = [cov_header sprintf('Covariate%d', i) sep];
|
||||
cov_format = [cov_format int_f sep];
|
||||
end
|
||||
|
||||
header = ['Subject' sep ...
|
||||
cov_header ...
|
||||
'Datafile' sep ...
|
||||
'Subject Id' sep ...
|
||||
'Session' sep ...
|
||||
'Trial' sep ...
|
||||
'Quality (%)' sep ...
|
||||
'BlinkCount' sep ...
|
||||
type_header, ...
|
||||
'Baseline (raw)' sep ...
|
||||
'Max' sep ...
|
||||
'TimeOfMax (rel to s.o.)' sep ...
|
||||
'Mean' sep ...
|
||||
'Median' sep ...
|
||||
'Mode' sep ...
|
||||
'Q1 (25%)' sep ...
|
||||
'Q2 (median)' sep ...
|
||||
'Q3 (75%)' sep ...
|
||||
'AUC' ];
|
||||
|
||||
|
||||
|
||||
format = [str_f sep ... % subject
|
||||
'%s' ... % covariates
|
||||
str_f sep ... % datafile
|
||||
int_f sep ... % subject id
|
||||
int_f sep ... % session
|
||||
int_f sep ... % trial
|
||||
dec_f sep ... % quality
|
||||
int_f sep ... % blinkcount
|
||||
'%s' ... % types are formatted within trial, so string with no formatting
|
||||
dec_f sep ... % baseline
|
||||
dec_f sep ... % max
|
||||
dec_f sep ... % maxtime
|
||||
dec_f sep ... % mean
|
||||
dec_f sep ... % median
|
||||
dec_f sep ... % mode
|
||||
dec_f sep ... % q1
|
||||
dec_f sep ... % q2
|
||||
dec_f sep ... % q3
|
||||
dec_f le]; % AUC
|
||||
|
||||
fprintf(fp,'%s\n', repmat('-',1,100));
|
||||
fprintf(fp, '%s', header);
|
||||
fprintf(fp, '\n');
|
||||
|
||||
for s = 1:length(e.subjects)
|
||||
|
||||
covariates = [];
|
||||
for cov =1:length(e.subjects(1).covariates)
|
||||
covariates = [covariates sprintf([dec_f sep], e.subjects(s).covariates(cov))];
|
||||
end
|
||||
|
||||
for sess = 1:length(e.subjects(s).sessions)
|
||||
|
||||
for t = 1:length(e.subjects(s).sessions(sess).trials)
|
||||
trial = e.subjects(s).sessions(sess).trials(t);
|
||||
|
||||
%Continue with the next trial if thresholding is enabled and
|
||||
%trial suffers quality
|
||||
if ((~isempty(settings.Thresholding)) && (settings.Thresholding.Quality) && (trial.quality < settings.QualityThreshold))
|
||||
continue;
|
||||
end
|
||||
|
||||
if ((~isempty(settings.Thresholding)) && (settings.Thresholding.Quality) && (trial.quality < settings.QualityThreshold))
|
||||
continue;
|
||||
end
|
||||
|
||||
%% Baseline items can be skipped
|
||||
if (strmatch(trial.type.TRIAL_VAR_stim, 'Baseline'))
|
||||
continue;
|
||||
end
|
||||
|
||||
tt_string = ''; % build string containg type identifiers
|
||||
for tt = 1:length(types)
|
||||
if isfield(trial.type,types{tt})
|
||||
if ischar(trial.type.(types{tt}))
|
||||
numchars = length(strtrim(trial.type.(types{tt})));
|
||||
else
|
||||
numchars = -1;
|
||||
end
|
||||
trial_type_value = trial.type.(types{tt});
|
||||
tt_string = [tt_string ...
|
||||
sprintf([str_f sep], strrep(trial_type_value(1,:),'"', '')) ...
|
||||
sprintf([int_f sep], numchars)];
|
||||
else
|
||||
tt_string = [tt_string ...
|
||||
sprintf([str_f sep], ''), ...
|
||||
sprintf([int_f sep], numchars)];
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
if ~isempty(trial.stats)
|
||||
fprintf(fp, format, ...
|
||||
e.subjects(s).name, ...
|
||||
covariates,...
|
||||
e.subjects(s).sessions(sess).datafile, ...
|
||||
s, ...
|
||||
sess, ...
|
||||
t, ...
|
||||
trial.quality, ...
|
||||
trial.blink_count, ...
|
||||
tt_string, ...
|
||||
trial.baseline, ...
|
||||
trial.stats.max.value, ...
|
||||
trial.stats.max.time, ...
|
||||
trial.stats.mean, ...
|
||||
trial.stats.median, ...
|
||||
trial.stats.mode, ...
|
||||
trial.stats.q1, ...
|
||||
trial.stats.q2, ...
|
||||
trial.stats.q3, ...
|
||||
trial.stats.auc);
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
fclose(fp);
|
||||
display(sprintf('\t*) Statistics written to %s', file_out));
|
||||
|
||||
|
||||
function[settings] = parse(settings,varlist);
|
||||
if length(varlist)<2;return;end
|
||||
f=fieldnames(settings);
|
||||
for k=2:2:length(varlist);
|
||||
if ~any(strcmp(varlist{k-1},f));
|
||||
error(sprintf('invalid field %s\n',varlist{k-1}));
|
||||
end
|
||||
if isstruct(varlist{k})
|
||||
substructfields = fieldnames(varlist{k});
|
||||
for sf = 1:length(substructfields)
|
||||
settings(1).(varlist{k-1}).(substructfields{sf}) = varlist{k}.(substructfields{sf});
|
||||
end
|
||||
else
|
||||
settings=setfield(settings,varlist{k-1},varlist{k});
|
||||
end
|
||||
end
|
||||
|
18
PDToolkit/@PDExperiment/getIndexFromSubjectName.m
Normal file
18
PDToolkit/@PDExperiment/getIndexFromSubjectName.m
Normal file
@@ -0,0 +1,18 @@
|
||||
function[list_out] = getIndexFromSubjectName(e, list_in)
|
||||
|
||||
list_out = [];
|
||||
|
||||
for s = 1:length(list_in)
|
||||
found = 0; index =1;
|
||||
|
||||
while ~found
|
||||
if ~isempty(strmatch(e.subjects(index).name, sprintf('Subject %d', list_in(s)), 'exact'))
|
||||
found = 1;
|
||||
list_out = [list_out index];
|
||||
end
|
||||
index = index +1;
|
||||
if index > length(e.subjects)
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
7
PDToolkit/@PDExperiment/get_aggregate_data.m
Normal file
7
PDToolkit/@PDExperiment/get_aggregate_data.m
Normal file
@@ -0,0 +1,7 @@
|
||||
function[mat time] = get_aggregate_data(exp, index)
|
||||
%
|
||||
% return matrix of trials for aggregate,
|
||||
% i.e. a reverse lookup of all trials which are used for the aggregate
|
||||
%
|
||||
% this function is used in statistics for permutation
|
||||
|
38
PDToolkit/@PDExperiment/get_trials_based_on_label.m
Normal file
38
PDToolkit/@PDExperiment/get_trials_based_on_label.m
Normal file
@@ -0,0 +1,38 @@
|
||||
function[trial_list] = get_trials_based_on_label(e, session, trial_query)
|
||||
|
||||
trial_list = [];
|
||||
if strcmp(trial_query, 'All trials')
|
||||
trial_list= 1:length(session.trials);
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
|
||||
if ~isempty(trial_query)
|
||||
|
||||
|
||||
|
||||
label_list = {};
|
||||
match_list = {};
|
||||
|
||||
ind=1;
|
||||
for t = 1:length(session.trials)
|
||||
for l = 1:length(session.trials(t).labels)
|
||||
label_list{ind} = session.trials(t).labels(l).label;
|
||||
match_list{ind} = session.trials(t).labels(l).match;
|
||||
trial_ids(ind) = t;
|
||||
ind=ind+1;
|
||||
end
|
||||
end
|
||||
|
||||
m_m = regexp(trial_query, match_list);
|
||||
m_l = regexp(trial_query, label_list);
|
||||
|
||||
matches = find(~cellfun(@isempty,m_l));
|
||||
labels = find(~cellfun(@isempty,m_l));
|
||||
|
||||
trial_list = sort([matches, labels]);
|
||||
end
|
||||
|
||||
|
||||
|
22
PDToolkit/@PDExperiment/info.m
Normal file
22
PDToolkit/@PDExperiment/info.m
Normal file
@@ -0,0 +1,22 @@
|
||||
function[text] = info(obj)
|
||||
|
||||
text{1} = sprintf('Information on PD Experiment: %s\n', obj.name);
|
||||
text{2} = repmat('-', 1, 100);
|
||||
text{3} = sprintf('Contains %2d subjects', length(obj.subjects));
|
||||
|
||||
for s = 1:length(obj.subjects)
|
||||
|
||||
subj = obj.subjects(s);
|
||||
text{end+1} = sprintf('\t*) Subject %d : %d sessions', s, length(subj.sessions));
|
||||
|
||||
for sess = 1:length(subj.sessions);
|
||||
session = subj.sessions(sess);
|
||||
text{end+1} = sprintf('\t\t*) Session %d : ', s);
|
||||
text{end+1} = sprintf('\t\t\to) - %d trials', length(session.trials));
|
||||
text{end+1} = sprintf('\t\t\to) - filename : %s', session.datafile);
|
||||
end
|
||||
end
|
||||
|
||||
if nargin == 0
|
||||
display(text)
|
||||
end
|
141
PDToolkit/@PDExperiment/information.txt
Normal file
141
PDToolkit/@PDExperiment/information.txt
Normal file
@@ -0,0 +1,141 @@
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 94 percent
|
||||
*) 2 blinks filtered ( 8 missing data events); quality : 83 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 92 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 92 percent
|
||||
*) 0 blinks filtered ( 6 missing data events); quality : 86 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 95 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 90 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 89 percent
|
||||
*) 0 blinks filtered ( 5 missing data events); quality : 88 percent
|
||||
*) 2 blinks filtered ( 5 missing data events); quality : 87 percent
|
||||
*) 0 blinks filtered ( 4 missing data events); quality : 90 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 90 percent
|
||||
*) 1 blinks filtered ( 5 missing data events); quality : 69 percent
|
||||
*) 2 blinks filtered ( 8 missing data events); quality : 83 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 94 percent
|
||||
*) 3 blinks filtered ( 6 missing data events); quality : 82 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 89 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 94 percent
|
||||
*) 1 blinks filtered ( 4 missing data events); quality : 92 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 92 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 94 percent
|
||||
*) 1 blinks filtered ( 5 missing data events); quality : 83 percent
|
||||
*) 1 blinks filtered ( 3 missing data events); quality : 93 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 89 percent
|
||||
*) 2 blinks filtered ( 5 missing data events); quality : 81 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 85 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 1 blinks filtered ( 5 missing data events); quality : 84 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 86 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 84 percent
|
||||
*) 1 blinks filtered ( 3 missing data events); quality : 55 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 88 percent
|
||||
*) 0 blinks filtered ( 5 missing data events); quality : 76 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 76 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 83 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 88 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 91 percent
|
||||
*) 1 blinks filtered ( 5 missing data events); quality : 78 percent
|
||||
*) 0 blinks filtered ( 4 missing data events); quality : 78 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 89 percent
|
||||
*) 1 blinks filtered ( 3 missing data events); quality : 91 percent
|
||||
*) 0 blinks filtered ( 4 missing data events); quality : 88 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 84 percent
|
||||
*) 1 blinks filtered ( 4 missing data events); quality : 60 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 79 percent
|
||||
*) 1 blinks filtered ( 2 missing data events); quality : 91 percent
|
||||
*) 1 blinks filtered ( 4 missing data events); quality : 81 percent
|
||||
*) 2 blinks filtered ( 4 missing data events); quality : 83 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 92 percent
|
||||
*) 1 blinks filtered ( 5 missing data events); quality : 86 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 92 percent
|
||||
*) 1 blinks filtered ( 5 missing data events); quality : 79 percent
|
||||
*) 2 blinks filtered ( 5 missing data events); quality : 63 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 84 percent
|
||||
*) 1 blinks filtered ( 2 missing data events); quality : 91 percent
|
||||
*) 1 blinks filtered ( 6 missing data events); quality : 82 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 94 percent
|
||||
*) 2 blinks filtered ( 3 missing data events); quality : 91 percent
|
||||
*) 1 blinks filtered ( 5 missing data events); quality : 85 percent
|
||||
*) 2 blinks filtered ( 4 missing data events); quality : 87 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 90 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 94 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 96 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 94 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 94 percent
|
||||
*) 1 blinks filtered ( 3 missing data events); quality : 90 percent
|
||||
*) 1 blinks filtered ( 2 missing data events); quality : 82 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 89 percent
|
||||
*) 2 blinks filtered ( 5 missing data events); quality : 79 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 94 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 92 percent
|
||||
*) 0 blinks filtered ( 4 missing data events); quality : 84 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 94 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 92 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 94 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 94 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 85 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 94 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 93 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 90 percent
|
||||
*) 2 blinks filtered ( 3 missing data events); quality : 91 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 91 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 81 percent
|
||||
*) 1 blinks filtered ( 4 missing data events); quality : 87 percent
|
||||
*) 1 blinks filtered ( 4 missing data events); quality : 72 percent
|
||||
*) 2 blinks filtered ( 5 missing data events); quality : 80 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 91 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 93 percent
|
||||
*) 1 blinks filtered ( 5 missing data events); quality : 84 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 88 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 93 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 97 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 97 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 96 percent
|
||||
*) 1 blinks filtered ( 1 missing data events); quality : 88 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 99 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 97 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 99 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 96 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 99 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 97 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 99 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 97 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 99 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 95 percent
|
||||
*) 0 blinks filtered ( 3 missing data events); quality : 95 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 2 blinks filtered ( 3 missing data events); quality : 94 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 99 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 99 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 97 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 1 blinks filtered ( 1 missing data events); quality : 96 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 97 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 97 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 96 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 100 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 96 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 2 missing data events); quality : 94 percent
|
||||
*) 1 blinks filtered ( 4 missing data events); quality : 85 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 100 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 98 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 97 percent
|
||||
*) 0 blinks filtered ( 1 missing data events); quality : 97 percent
|
||||
*) 0 blinks filtered ( 0 missing data events); quality : 97 percent
|
802
PDToolkit/@PDExperiment/multiWaitbar.m
Normal file
802
PDToolkit/@PDExperiment/multiWaitbar.m
Normal file
@@ -0,0 +1,802 @@
|
||||
function cancel = multiWaitbar( label, varargin )
|
||||
%multiWaitbar: add, remove or update an entry on the multi waitbar
|
||||
%
|
||||
% multiWaitbar(LABEL,VALUE) adds a waitbar for the specified label, or
|
||||
% if it already exists updates the value. LABEL must be a string and
|
||||
% VALUE a number between zero and one or the string 'Close' to remove the
|
||||
% entry Setting value equal to 0 or 'Reset' will cause the progress bar
|
||||
% to reset and the time estimate to be re-initialized.
|
||||
%
|
||||
% multiWaitbar(LABEL,COMMAND,VALUE,...) or
|
||||
% multiWaitbar(LABEL,VALUE,COMMAND,VALUE,...)
|
||||
% passes one or more command/value pairs for changing the named waitbar
|
||||
% entry. Possible commands include:
|
||||
% 'Value' Set the value of the named waitbar entry. The
|
||||
% corresponding value must be a number between 0 and 1.
|
||||
% 'Increment' Increment the value of the named waitbar entry. The
|
||||
% corresponding value must be a number between 0 and 1.
|
||||
% 'Color' Change the color of the named waitbar entry. The
|
||||
% value must be an RGB triple, e.g. [0.1 0.2 0.3], or a
|
||||
% single-character color name, e.g. 'r', 'b', 'm'.
|
||||
% 'Relabel' Change the label of the named waitbar entry. The
|
||||
% value must be the new name.
|
||||
% 'Reset' Set the named waitbar entry back to zero and reset its
|
||||
% timer. No value need be specified.
|
||||
% 'CanCancel' [on|off] should a "cancel" button be shown for this bar
|
||||
% (default 'off').
|
||||
% 'CancelFcn' Function to call in the event that the user cancels.
|
||||
% 'ResetCancel' Reset the "cancelled" flag for an entry (ie. if you
|
||||
% decide not to cancel).
|
||||
% 'Close' Remove the named waitbar entry.
|
||||
% 'Busy' Puts this waitbar in "busy mode" where a small bar
|
||||
% bounces back and forth. Return to normal progress display
|
||||
% using the 'Reset' command.
|
||||
%
|
||||
% cancel = multiWaitbar(LABEL,VALUE) also returns whether the user has
|
||||
% clicked the "cancel" button for this entry (true or false). Two
|
||||
% mechanisms are provided for cancelling an entry if the 'CanCancel'
|
||||
% setting is 'on'. The first is just to check the return argument and if
|
||||
% it is true abort the task. The second is to set a 'CancelFcn' that is
|
||||
% called when the user clicks the cancel button, much as is done for
|
||||
% MATLAB's built-in WAITBAR. In either case, you can use the
|
||||
% 'ResetCancel' command if you don't want to cancel after all.
|
||||
%
|
||||
% multiWaitbar('CLOSEALL') closes the waitbar window.
|
||||
%
|
||||
% Example:
|
||||
% multiWaitbar( 'CloseAll' );
|
||||
% multiWaitbar( 'Task 1', 0 );
|
||||
% multiWaitbar( 'Task 2', 0.5, 'Color', 'b' );
|
||||
% multiWaitbar( 'Task 3', 'Busy');
|
||||
% multiWaitbar( 'Task 1', 'Value', 0.1 );
|
||||
% multiWaitbar( 'Task 2', 'Increment', 0.2 );
|
||||
% multiWaitbar( 'Task 3', 'Reset' ); % Disables "busy" mode
|
||||
% multiWaitbar( 'Task 3', 'Value', 0.3 );
|
||||
% multiWaitbar( 'Task 2', 'Close' );
|
||||
% multiWaitbar( 'Task 3', 'Close' );
|
||||
% multiWaitbar( 'Task 1', 'Close' );
|
||||
%
|
||||
% Example:
|
||||
% multiWaitbar( 'Task 1', 0, 'CancelFcn', @(a,b) disp( ['Cancel ',a] ) );
|
||||
% for ii=1:100
|
||||
% abort = multiWaitbar( 'Task 1', ii/100 );
|
||||
% if abort
|
||||
% % Here we would normally ask the user if they're sure
|
||||
% break
|
||||
% else
|
||||
% pause( 1 )
|
||||
% end
|
||||
% end
|
||||
% multiWaitbar( 'Task 1', 'Close' )
|
||||
%
|
||||
% Example:
|
||||
% multiWaitbar( 'CloseAll' );
|
||||
% multiWaitbar( 'Red...', 7/7, 'Color', [0.8 0.0 0.1] );
|
||||
% multiWaitbar( 'Orange...', 6/7, 'Color', [1.0 0.4 0.0] );
|
||||
% multiWaitbar( 'Yellow...', 5/7, 'Color', [0.9 0.8 0.2] );
|
||||
% multiWaitbar( 'Green...', 4/7, 'Color', [0.2 0.9 0.3] );
|
||||
% multiWaitbar( 'Blue...', 3/7, 'Color', [0.1 0.5 0.8] );
|
||||
% multiWaitbar( 'Indigo...', 2/7, 'Color', [0.4 0.1 0.5] );
|
||||
% multiWaitbar( 'Violet...', 1/7, 'Color', [0.8 0.4 0.9] );
|
||||
%
|
||||
% Thanks to Jesse Hopkins for suggesting the "busy" mode.
|
||||
|
||||
% Author: Ben Tordoff
|
||||
% Copyright 2007-2014 The MathWorks, Inc.
|
||||
|
||||
persistent FIGH;
|
||||
cancel = false;
|
||||
|
||||
% Check basic inputs
|
||||
error( nargchk( 1, inf, nargin ) ); %#ok<NCHKN> - kept for backwards compatibility
|
||||
if ~ischar( label )
|
||||
error( 'multiWaitbar:BadArg', 'LABEL must be the name of the progress entry (i.e. a string)' );
|
||||
end
|
||||
|
||||
% Try to get hold of the figure
|
||||
if isempty( FIGH ) || ~ishandle( FIGH )
|
||||
FIGH = findall( 0, 'Type', 'figure', 'Tag', 'multiWaitbar:Figure' );
|
||||
if isempty(FIGH)
|
||||
FIGH = iCreateFig();
|
||||
else
|
||||
FIGH = handle( FIGH(1) );
|
||||
end
|
||||
end
|
||||
|
||||
% Check for close all and stop early
|
||||
if any( strcmpi( label, {'CLOSEALL','CLOSE ALL'} ) )
|
||||
iDeleteFigure(FIGH);
|
||||
return;
|
||||
end
|
||||
|
||||
% Make sure we're on-screen
|
||||
if ~strcmpi( FIGH.Visible, 'on' )
|
||||
FIGH.Visible = 'on';
|
||||
end
|
||||
|
||||
% Get the list of entries and see if this one already exists
|
||||
entries = getappdata( FIGH, 'ProgressEntries' );
|
||||
if isempty(entries)
|
||||
idx = [];
|
||||
else
|
||||
idx = find( strcmp( label, {entries.Label} ), 1, 'first' );
|
||||
end
|
||||
bgcol = getappdata( FIGH, 'DefaultProgressBarBackgroundColor' );
|
||||
|
||||
% If it doesn't exist, create it
|
||||
needs_redraw = false;
|
||||
entry_added = isempty(idx);
|
||||
if entry_added
|
||||
% Create a new entry
|
||||
defbarcolor = getappdata( FIGH, 'DefaultProgressBarColor' );
|
||||
entries = iAddEntry( FIGH, entries, label, 0, defbarcolor, bgcol );
|
||||
idx = numel( entries );
|
||||
end
|
||||
|
||||
% Check if the user requested a cancel
|
||||
if nargout
|
||||
cancel = entries(idx).Cancel;
|
||||
end
|
||||
|
||||
% Parse the inputs. We shortcut the most common case as an efficiency
|
||||
force_update = false;
|
||||
if nargin==2 && isnumeric( varargin{1} )
|
||||
entries(idx).LastValue = entries(idx).Value;
|
||||
entries(idx).Value = max( 0, min( 1, varargin{1} ) );
|
||||
entries(idx).Busy = false;
|
||||
needs_update = true;
|
||||
else
|
||||
[params,values] = iParseInputs( varargin{:} );
|
||||
|
||||
needs_update = false;
|
||||
for ii=1:numel( params )
|
||||
switch upper( params{ii} )
|
||||
case 'BUSY'
|
||||
entries(idx).Busy = true;
|
||||
needs_update = true;
|
||||
|
||||
case 'VALUE'
|
||||
entries(idx).LastValue = entries(idx).Value;
|
||||
entries(idx).Value = max( 0, min( 1, values{ii} ) );
|
||||
entries(idx).Busy = false;
|
||||
needs_update = true;
|
||||
|
||||
case {'INC','INCREMENT'}
|
||||
entries(idx).LastValue = entries(idx).Value;
|
||||
entries(idx).Value = max( 0, min( 1, entries(idx).Value + values{ii} ) );
|
||||
entries(idx).Busy = false;
|
||||
needs_update = true;
|
||||
|
||||
case {'COLOR','COLOUR'}
|
||||
entries(idx).CData = iMakeColors( values{ii}, 16 );
|
||||
needs_update = true;
|
||||
force_update = true;
|
||||
|
||||
case {'RELABEL', 'UPDATELABEL'}
|
||||
% Make sure we have a string as the value and that it
|
||||
% doesn't already appear
|
||||
if ~ischar( values{ii} )
|
||||
error( 'multiWaitbar:BadString', 'Value for ''Relabel'' must be a string.' );
|
||||
end
|
||||
if ismember( values{ii}, {entries.Label} )
|
||||
error( 'multiWaitbar:NameAlreadyExists', 'Cannot relabel an entry to a label that already exists.' );
|
||||
end
|
||||
entries(idx).Label = values{ii};
|
||||
needs_update = true;
|
||||
force_update = true;
|
||||
|
||||
case {'CANCANCEL'}
|
||||
if ~ischar( values{ii} ) || ~any( strcmpi( values{ii}, {'on','off'} ) )
|
||||
error( 'multiWaitbar:BadString', 'Parameter ''CanCancel'' must be a ''on'' or ''off''.' );
|
||||
end
|
||||
entries(idx).CanCancel = strcmpi( values{ii}, 'on' );
|
||||
entries(idx).Cancel = false;
|
||||
needs_redraw = true;
|
||||
|
||||
case {'RESETCANCEL'}
|
||||
entries(idx).Cancel = false;
|
||||
needs_redraw = true;
|
||||
|
||||
case {'CANCELFCN'}
|
||||
if ~isa( values{ii}, 'function_handle' )
|
||||
error( 'multiWaitbar:BadFunction', 'Parameter ''CancelFcn'' must be a valid function handle.' );
|
||||
end
|
||||
entries(idx).CancelFcn = values{ii};
|
||||
if ~entries(idx).CanCancel
|
||||
entries(idx).CanCancel = true;
|
||||
end
|
||||
needs_redraw = true;
|
||||
|
||||
case {'CLOSE','DONE'}
|
||||
if ~isempty(idx)
|
||||
% Remove the selected entry
|
||||
entries = iDeleteEntry( entries, idx );
|
||||
end
|
||||
if isempty( entries )
|
||||
iDeleteFigure( FIGH );
|
||||
% With the window closed, there's nothing else to do
|
||||
return;
|
||||
else
|
||||
needs_redraw = true;
|
||||
end
|
||||
% We can't continue after clearing the entry, so jump out
|
||||
break;
|
||||
|
||||
otherwise
|
||||
error( 'multiWaitbar:BadArg', 'Unrecognized command: ''%s''', params{ii} );
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% Now work out what to update/redraw
|
||||
if needs_redraw
|
||||
setappdata( FIGH, 'ProgressEntries', entries );
|
||||
iRedraw( FIGH );
|
||||
% NB: Redraw includes updating all bars, so never need to do both
|
||||
elseif needs_update
|
||||
[entries(idx),needs_redraw] = iUpdateEntry( entries(idx), force_update );
|
||||
setappdata( FIGH, 'ProgressEntries', entries );
|
||||
% NB: if anything was updated onscreen, "needs_redraw" is now true.
|
||||
end
|
||||
if entry_added || needs_redraw
|
||||
% If the shape or size has changed, do a full redraw, including events
|
||||
drawnow();
|
||||
end
|
||||
|
||||
% If we have any "busy" entries, start the timer, otherwise stop it.
|
||||
myTimer = getappdata( FIGH, 'BusyTimer' );
|
||||
if any([entries.Busy])
|
||||
if strcmpi(myTimer.Running,'off')
|
||||
start(myTimer);
|
||||
end
|
||||
else
|
||||
if strcmpi(myTimer.Running,'on')
|
||||
stop(myTimer);
|
||||
end
|
||||
end
|
||||
|
||||
end % multiWaitbar
|
||||
|
||||
|
||||
%-------------------------------------------------------------------------%
|
||||
function [params, values] = iParseInputs( varargin )
|
||||
% Parse the input arguments, extracting a list of commands and values
|
||||
idx = 1;
|
||||
params = {};
|
||||
values = {};
|
||||
if nargin==0
|
||||
return;
|
||||
end
|
||||
if isnumeric( varargin{1} )
|
||||
params{idx} = 'Value';
|
||||
values{idx} = varargin{1};
|
||||
idx = idx + 1;
|
||||
end
|
||||
|
||||
while idx <= nargin
|
||||
param = varargin{idx};
|
||||
if ~ischar( param )
|
||||
error( 'multiWaitbar:BadSyntax', 'Additional properties must be supplied as property-value pairs' );
|
||||
end
|
||||
params{end+1,1} = param; %#ok<AGROW>
|
||||
values{end+1,1} = []; %#ok<AGROW>
|
||||
switch upper( param )
|
||||
case {'DONE','CLOSE','RESETCANCEL'}
|
||||
% No value needed, and stop
|
||||
break;
|
||||
case {'BUSY'}
|
||||
% No value needed but parsing should continue
|
||||
idx = idx + 1;
|
||||
case {'RESET','ZERO','SHOW'}
|
||||
% All equivalent to saying ('Value', 0)
|
||||
params{end} = 'Value';
|
||||
values{end} = 0;
|
||||
idx = idx + 1;
|
||||
otherwise
|
||||
if idx==nargin
|
||||
error( 'multiWaitbar:BadSyntax', 'Additional properties must be supplied as property-value pairs' );
|
||||
end
|
||||
values{end,1} = varargin{idx+1};
|
||||
idx = idx + 2;
|
||||
end
|
||||
end
|
||||
if isempty( params )
|
||||
error( 'multiWaitbar:BadSyntax', 'Must specify a value or a command' );
|
||||
end
|
||||
end % iParseInputs
|
||||
|
||||
%-------------------------------------------------------------------------%
|
||||
function fobj = iCreateFig()
|
||||
% Create the progress bar group window
|
||||
bgcol = get(0,'DefaultUIControlBackgroundColor');
|
||||
f = figure( ...
|
||||
'Name', 'Progress', ...
|
||||
'Tag', 'multiWaitbar:Figure', ...
|
||||
'Color', bgcol, ...
|
||||
'MenuBar', 'none', ...
|
||||
'ToolBar', 'none', ...
|
||||
'WindowStyle', 'normal', ... % We don't want to be docked!
|
||||
'HandleVisibility', 'off', ...
|
||||
'IntegerHandle', 'off', ...
|
||||
'Visible', 'off', ...
|
||||
'NumberTitle', 'off' );
|
||||
% Resize and centre on the first screen
|
||||
screenSize = get(0,'ScreenSize');
|
||||
figSz = [360 42];
|
||||
figPos = ceil((screenSize(1,3:4)-figSz)/2);
|
||||
fobj = handle( f );
|
||||
fobj.Position = [figPos, figSz];
|
||||
setappdata( fobj, 'ProgressEntries', [] );
|
||||
% Make sure we have the image
|
||||
defbarcolor = [0.8 0.0 0.1];
|
||||
barbgcol = uint8( 255*0.75*bgcol );
|
||||
setappdata( fobj, 'DefaultProgressBarBackgroundColor', barbgcol );
|
||||
setappdata( fobj, 'DefaultProgressBarColor', defbarcolor );
|
||||
setappdata( fobj, 'DefaultProgressBarSize', [350 16] );
|
||||
% Create the timer to use for "Busy" mode, being sure to delete any
|
||||
% existing ones
|
||||
delete( timerfind('Tag', 'MultiWaitbarTimer') );
|
||||
myTimer = timer( ...
|
||||
'TimerFcn', @(src,evt) iTimerFcn(f), ...
|
||||
'Period', 0.02, ...
|
||||
'ExecutionMode', 'FixedRate', ...
|
||||
'Tag', 'MultiWaitbarTimer' );
|
||||
setappdata( fobj, 'BusyTimer', myTimer );
|
||||
|
||||
% Setup the resize function after we've finished setting up the figure to
|
||||
% avoid excessive redraws
|
||||
fobj.ResizeFcn = @iRedraw;
|
||||
fobj.CloseRequestFcn = @iCloseFigure;
|
||||
end % iCreateFig
|
||||
|
||||
%-------------------------------------------------------------------------%
|
||||
function cdata = iMakeColors( baseColor, height )
|
||||
% Creates a shiny bar from a single base color
|
||||
lightColor = [1 1 1];
|
||||
badColorErrorID = 'multiWaitbar:BadColor';
|
||||
badColorErrorMsg = 'Colors must be a three element vector [R G B] or a single character (''r'', ''g'' etc.)';
|
||||
|
||||
if ischar(baseColor)
|
||||
switch upper(baseColor)
|
||||
case 'K'
|
||||
baseColor = [0.1 0.1 0.1];
|
||||
case 'R'
|
||||
baseColor = [0.8 0 0];
|
||||
case 'G'
|
||||
baseColor = [0 0.6 0];
|
||||
case 'B'
|
||||
baseColor = [0 0 0.8];
|
||||
case 'C'
|
||||
baseColor = [0.2 0.8 0.9];
|
||||
case 'M'
|
||||
baseColor = [0.6 0 0.6];
|
||||
case 'Y'
|
||||
baseColor = [0.9 0.8 0.2];
|
||||
case 'W'
|
||||
baseColor = [0.9 0.9 0.9];
|
||||
otherwise
|
||||
error( badColorErrorID, badColorErrorMsg );
|
||||
end
|
||||
else
|
||||
if numel(baseColor) ~= 3
|
||||
error( badColorErrorID, badColorErrorMsg );
|
||||
end
|
||||
if isa( baseColor, 'uint8' )
|
||||
baseColor = double( baseColor ) / 255;
|
||||
elseif isa( baseColor, 'double' )
|
||||
if any(baseColor>1) || any(baseColor<0)
|
||||
error( 'multiWaitbar:BadColorValue', 'Color values must be in the range 0 to 1 inclusive.' );
|
||||
end
|
||||
else
|
||||
error( badColorErrorID, badColorErrorMsg );
|
||||
end
|
||||
end
|
||||
|
||||
% By this point we should have a double precision 3-element vector.
|
||||
cols = repmat( baseColor, [height, 1] );
|
||||
|
||||
breaks = max( 1, round( height * [1 25 50 75 88 100] / 100 ) );
|
||||
cols(breaks(1),:) = 0.6*baseColor;
|
||||
cols(breaks(2),:) = lightColor - 0.4*(lightColor-baseColor);
|
||||
cols(breaks(3),:) = baseColor;
|
||||
cols(breaks(4),:) = min( baseColor*1.2, 1.0 );
|
||||
cols(breaks(5),:) = min( baseColor*1.4, 0.95 ) + 0.05;
|
||||
cols(breaks(6),:) = min( baseColor*1.6, 0.9 ) + 0.1;
|
||||
|
||||
y = 1:height;
|
||||
cols(:,1) = max( 0, min( 1, interp1( breaks, cols(breaks,1), y, 'pchip' ) ) );
|
||||
cols(:,2) = max( 0, min( 1, interp1( breaks, cols(breaks,2), y, 'pchip' ) ) );
|
||||
cols(:,3) = max( 0, min( 1, interp1( breaks, cols(breaks,3), y, 'pchip' ) ) );
|
||||
cdata = uint8( 255 * cat( 3, cols(:,1), cols(:,2), cols(:,3) ) );
|
||||
end % iMakeColors
|
||||
|
||||
|
||||
%-------------------------------------------------------------------------%
|
||||
function cdata = iMakeBackground( baseColor, height )
|
||||
% Creates a shaded background
|
||||
if isa( baseColor, 'uint8' )
|
||||
baseColor = double( baseColor ) / 255;
|
||||
end
|
||||
|
||||
ratio = 1 - exp( -0.5-2*(1:height)/height )';
|
||||
cdata = uint8( 255 * cat( 3, baseColor(1)*ratio, baseColor(2)*ratio, baseColor(3)*ratio ) );
|
||||
end % iMakeBackground
|
||||
|
||||
%-------------------------------------------------------------------------%
|
||||
function entries = iAddEntry( parent, entries, label, value, color, bgcolor )
|
||||
% Add a new entry to the progress bar
|
||||
|
||||
% Create bar coloring
|
||||
psize = getappdata( parent, 'DefaultProgressBarSize' );
|
||||
cdata = iMakeColors( color, 16 );
|
||||
% Create background image
|
||||
barcdata = iMakeBackground( bgcolor, psize(2) );
|
||||
|
||||
% Work out the size in advance
|
||||
labeltext = uicontrol( 'Style', 'Text', ...
|
||||
'String', label, ...
|
||||
'Parent', parent, ...
|
||||
'HorizontalAlignment', 'Left' );
|
||||
etatext = uicontrol( 'Style', 'Text', ...
|
||||
'String', '', ...
|
||||
'Parent', parent, ...
|
||||
'HorizontalAlignment', 'Right' );
|
||||
progresswidget = uicontrol( 'Style', 'Checkbox', ...
|
||||
'String', '', ...
|
||||
'Parent', parent, ...
|
||||
'Position', [5 5 psize], ...
|
||||
'CData', barcdata );
|
||||
cancelwidget = uicontrol( 'Style', 'PushButton', ...
|
||||
'String', '', ...
|
||||
'FontWeight', 'Bold', ...
|
||||
'Parent', parent, ...
|
||||
'Position', [5 5 16 16], ...
|
||||
'CData', iMakeCross( 8 ), ...
|
||||
'Callback', @(src,evt) iCancelEntry( src, label ), ...
|
||||
'Visible', 'off' );
|
||||
mypanel = uipanel( 'Parent', parent, 'Units', 'Pixels' );
|
||||
|
||||
newentry = struct( ...
|
||||
'Label', label, ...
|
||||
'Value', value, ...
|
||||
'LastValue', inf, ...
|
||||
'Created', tic(), ...
|
||||
'LabelText', labeltext, ...
|
||||
'ETAText', etatext, ...
|
||||
'ETAString', '', ...
|
||||
'Progress', progresswidget, ...
|
||||
'ProgressSize', psize, ...
|
||||
'Panel', mypanel, ...
|
||||
'BarCData', barcdata, ...
|
||||
'CData', cdata, ...
|
||||
'BackgroundCData', barcdata, ...
|
||||
'CanCancel', false, ...
|
||||
'CancelFcn', [], ...
|
||||
'CancelButton', cancelwidget, ...
|
||||
'Cancel', false, ...
|
||||
'Busy', false );
|
||||
if isempty( entries )
|
||||
entries = newentry;
|
||||
else
|
||||
entries = [entries;newentry];
|
||||
end
|
||||
% Store in figure before the redraw
|
||||
setappdata( parent, 'ProgressEntries', entries );
|
||||
if strcmpi( get( parent, 'Visible' ), 'on' )
|
||||
iRedraw( parent, [] );
|
||||
else
|
||||
set( parent, 'Visible', 'on' );
|
||||
end
|
||||
end % iAddEntry
|
||||
|
||||
%-------------------------------------------------------------------------%
|
||||
function entries = iDeleteEntry( entries, idx )
|
||||
delete( entries(idx).LabelText );
|
||||
delete( entries(idx).ETAText );
|
||||
delete( entries(idx).CancelButton );
|
||||
delete( entries(idx).Progress );
|
||||
delete( entries(idx).Panel );
|
||||
entries(idx,:) = [];
|
||||
end % iDeleteEntry
|
||||
|
||||
%-------------------------------------------------------------------------%
|
||||
function entries = iCancelEntry( src, name )
|
||||
figh = ancestor( src, 'figure' );
|
||||
entries = getappdata( figh, 'ProgressEntries' );
|
||||
if isempty(entries)
|
||||
% The entries have been lost - nothing can be done.
|
||||
return
|
||||
end
|
||||
idx = find( strcmp( name, {entries.Label} ), 1, 'first' );
|
||||
|
||||
% Set the cancel flag so that the user is told on next update
|
||||
entries(idx).Cancel = true;
|
||||
setappdata( figh, 'ProgressEntries', entries );
|
||||
|
||||
% If a user function is supplied, call it
|
||||
if ~isempty( entries(idx).CancelFcn )
|
||||
feval( entries(idx).CancelFcn, name, 'Cancelled' );
|
||||
end
|
||||
|
||||
end % iCancelEntry
|
||||
|
||||
|
||||
%-------------------------------------------------------------------------%
|
||||
function [entry,updated] = iUpdateEntry( entry, force )
|
||||
% Update one progress bar
|
||||
|
||||
% Deal with busy entries separately
|
||||
if entry.Busy
|
||||
entry = iUpdateBusyEntry(entry);
|
||||
updated = true;
|
||||
return;
|
||||
end
|
||||
|
||||
% Some constants
|
||||
marker_weight = 0.8;
|
||||
|
||||
% Check if the label needs updating
|
||||
updated = force;
|
||||
val = entry.Value;
|
||||
lastval = entry.LastValue;
|
||||
|
||||
% Now update the bar
|
||||
psize = entry.ProgressSize;
|
||||
filled = max( 1, round( val*psize(1) ) );
|
||||
lastfilled = max( 1, round( lastval*psize(1) ) );
|
||||
|
||||
% We do some careful checking so that we only redraw what we have to. This
|
||||
% makes a small speed difference, but every little helps!
|
||||
if force || (filled<lastfilled)
|
||||
% Create the bar background
|
||||
startIdx = 1;
|
||||
bgim = entry.BackgroundCData(:,ones( 1, psize(1)-filled ),:);
|
||||
barim = iMakeBarImage(entry.CData, startIdx, filled);
|
||||
progresscdata = [barim,bgim];
|
||||
|
||||
% Add light/shadow around the markers
|
||||
markers = round( (0.1:0.1:val)*psize(1) );
|
||||
markers(markers<startIdx | markers>(filled-2)) = [];
|
||||
highlight = [marker_weight*entry.CData, 255 - marker_weight*(255-entry.CData)];
|
||||
for ii=1:numel( markers )
|
||||
progresscdata(:,markers(ii)+[-1,0],:) = highlight;
|
||||
end
|
||||
|
||||
% Set the image into the checkbox
|
||||
entry.BarCData = progresscdata;
|
||||
set( entry.Progress, 'cdata', progresscdata );
|
||||
updated = true;
|
||||
|
||||
elseif filled > lastfilled
|
||||
% Just need to update the existing data
|
||||
progresscdata = entry.BarCData;
|
||||
startIdx = max(1,lastfilled-1);
|
||||
% Repmat is the obvious way to fill the bar, but BSXFUN is often
|
||||
% faster. Indexing is obscure but faster still.
|
||||
progresscdata(:,startIdx:filled,:) = iMakeBarImage(entry.CData, startIdx, filled);
|
||||
|
||||
% Add light/shadow around the markers
|
||||
markers = round( (0.1:0.1:val)*psize(1) );
|
||||
markers(markers<startIdx | markers>(filled-2)) = [];
|
||||
highlight = [marker_weight*entry.CData, 255 - marker_weight*(255-entry.CData)];
|
||||
for ii=1:numel( markers )
|
||||
progresscdata(:,markers(ii)+[-1,0],:) = highlight;
|
||||
end
|
||||
|
||||
entry.BarCData = progresscdata;
|
||||
set( entry.Progress, 'CData', progresscdata );
|
||||
updated = true;
|
||||
end
|
||||
|
||||
% As an optimization, don't update any text if the bar didn't move and the
|
||||
% percentage hasn't changed
|
||||
decval = round( val*100 );
|
||||
lastdecval = round( lastval*100 );
|
||||
|
||||
if ~updated && (decval == lastdecval)
|
||||
return
|
||||
end
|
||||
|
||||
% Now work out the remaining time
|
||||
minTime = 3; % secs
|
||||
if val <= 0
|
||||
% Zero value, so clear the eta
|
||||
entry.Created = tic();
|
||||
elapsedtime = 0;
|
||||
etaString = '';
|
||||
else
|
||||
elapsedtime = round(toc( entry.Created )); % in seconds
|
||||
|
||||
% Only show the remaining time if we've had time to estimate
|
||||
if elapsedtime < minTime
|
||||
% Not enough time has passed since starting, so leave blank
|
||||
etaString = '';
|
||||
else
|
||||
% Calculate a rough ETA
|
||||
eta = elapsedtime * (1-val) / val;
|
||||
etaString = iGetTimeString( eta );
|
||||
end
|
||||
end
|
||||
|
||||
if ~isequal( etaString, entry.ETAString )
|
||||
set( entry.ETAText, 'String', etaString );
|
||||
entry.ETAString = etaString;
|
||||
updated = true;
|
||||
end
|
||||
|
||||
% Update the label too
|
||||
if force || elapsedtime > minTime
|
||||
if force || (decval ~= lastdecval)
|
||||
labelstr = [entry.Label, sprintf( ' (%d%%)', decval )];
|
||||
set( entry.LabelText, 'String', labelstr );
|
||||
updated = true;
|
||||
end
|
||||
end
|
||||
|
||||
end % iUpdateEntry
|
||||
|
||||
function eta = iGetTimeString( remainingtime )
|
||||
if remainingtime > 172800 % 2 days
|
||||
eta = sprintf( '%d days', round(remainingtime/86400) );
|
||||
else
|
||||
if remainingtime > 7200 % 2 hours
|
||||
eta = sprintf( '%d hours', round(remainingtime/3600) );
|
||||
else
|
||||
if remainingtime > 120 % 2 mins
|
||||
eta = sprintf( '%d mins', round(remainingtime/60) );
|
||||
else
|
||||
% Seconds
|
||||
remainingtime = round( remainingtime );
|
||||
if remainingtime > 1
|
||||
eta = sprintf( '%d secs', remainingtime );
|
||||
elseif remainingtime == 1
|
||||
eta = '1 sec';
|
||||
else
|
||||
eta = ''; % Nearly done (<1sec)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end % iGetTimeString
|
||||
|
||||
|
||||
%-------------------------------------------------------------------------%
|
||||
function entry = iUpdateBusyEntry( entry )
|
||||
% Update a "busy" progress bar
|
||||
% Make sure the widget is still OK
|
||||
if ~ishandle(entry.Progress)
|
||||
return
|
||||
end
|
||||
% Work out the new position. Since the bar is 0.1 long and needs to bounce,
|
||||
% the position varies from 0 up to 0.9 then back down again. We achieve
|
||||
% this with judicious use of "mod" with 1.8.
|
||||
entry.Value = mod(entry.Value+0.01,1.8);
|
||||
val = entry.Value;
|
||||
if val>0.9
|
||||
% Moving backwards
|
||||
val = 1.8-val;
|
||||
end
|
||||
psize = entry.ProgressSize;
|
||||
startIdx = max( 1, round( val*psize(1) ) );
|
||||
endIdx = max( 1, round( (val+0.1)*psize(1) ) );
|
||||
barLength = endIdx - startIdx + 1;
|
||||
|
||||
% Create the image
|
||||
bgim = entry.BackgroundCData(:,ones( 1, psize(1) ),:);
|
||||
barim = iMakeBarImage(entry.CData, 1, barLength);
|
||||
bgim(:,startIdx:endIdx,:) = barim;
|
||||
|
||||
% Put it into the widget
|
||||
entry.BarCData = bgim;
|
||||
set( entry.Progress, 'CData', bgim );
|
||||
end % iUpdateBusyEntry
|
||||
|
||||
|
||||
%-------------------------------------------------------------------------%
|
||||
function barim = iMakeBarImage(strip, startIdx, endIdx)
|
||||
shadow1_weight = 0.4;
|
||||
shadow2_weight = 0.7;
|
||||
barLength = endIdx - startIdx + 1;
|
||||
% Repmat is the obvious way to fill the bar, but BSXFUN is often
|
||||
% faster. Indexing is obscure but faster still.
|
||||
barim = strip(:,ones(1, barLength),:);
|
||||
% Add highlight to the start of the bar
|
||||
if startIdx <= 2 && barLength>=2
|
||||
barim(:,1,:) = 255 - shadow1_weight*(255-strip);
|
||||
barim(:,2,:) = 255 - shadow2_weight*(255-strip);
|
||||
end
|
||||
% Add shadow to the end of the bar
|
||||
if endIdx>=4 && barLength>=2
|
||||
barim(:,end,:) = shadow1_weight*strip;
|
||||
barim(:,end-1,:) = shadow2_weight*strip;
|
||||
end
|
||||
end % iMakeBarImage
|
||||
|
||||
%-------------------------------------------------------------------------%
|
||||
function iCloseFigure( fig, evt ) %#ok<INUSD>
|
||||
% Closing the figure just makes it invisible
|
||||
set( fig, 'Visible', 'off' );
|
||||
end % iCloseFigure
|
||||
|
||||
%-------------------------------------------------------------------------%
|
||||
function iDeleteFigure( fig )
|
||||
% Actually destroy the figure
|
||||
busyTimer = getappdata( fig, 'BusyTimer' );
|
||||
stop( busyTimer );
|
||||
delete( busyTimer );
|
||||
delete( fig );
|
||||
end % iDeleteFigure
|
||||
|
||||
%-------------------------------------------------------------------------%
|
||||
function iRedraw( fig, evt ) %#ok<INUSD>
|
||||
entries = getappdata( fig, 'ProgressEntries' );
|
||||
fobj = handle( fig );
|
||||
p = fobj.Position;
|
||||
% p = get( fig, 'Position' );
|
||||
border = 5;
|
||||
textheight = 16;
|
||||
barheight = 16;
|
||||
panelheight = 10;
|
||||
N = max( 1, numel( entries ) );
|
||||
|
||||
% Check the height is correct
|
||||
heightperentry = textheight+barheight+panelheight;
|
||||
requiredheight = 2*border + N*heightperentry - panelheight;
|
||||
if ~isequal( p(4), requiredheight )
|
||||
p(2) = p(2) + p(4) - requiredheight;
|
||||
p(4) = requiredheight;
|
||||
% In theory setting the position should re-trigger this callback, but
|
||||
% in practice it doesn't, probably because we aren't calling "drawnow".
|
||||
set( fig, 'Position', p )
|
||||
end
|
||||
ypos = p(4) - border;
|
||||
width = p(3) - 2*border;
|
||||
setappdata( fig, 'DefaultProgressBarSize', [width barheight] );
|
||||
|
||||
for ii=1:numel( entries )
|
||||
set( entries(ii).LabelText, 'Position', [border ypos-textheight width*0.75 textheight] );
|
||||
set( entries(ii).ETAText, 'Position', [border+width*0.75 ypos-textheight width*0.25 textheight] );
|
||||
ypos = ypos - textheight;
|
||||
if entries(ii).CanCancel
|
||||
set( entries(ii).Progress, 'Position', [border ypos-barheight width-barheight+1 barheight] );
|
||||
entries(ii).ProgressSize = [width-barheight barheight];
|
||||
set( entries(ii).CancelButton, 'Visible', 'on', 'Position', [p(3)-border-barheight ypos-barheight barheight barheight] );
|
||||
else
|
||||
set( entries(ii).Progress, 'Position', [border ypos-barheight width+1 barheight] );
|
||||
entries(ii).ProgressSize = [width barheight];
|
||||
set( entries(ii).CancelButton, 'Visible', 'off' );
|
||||
end
|
||||
ypos = ypos - barheight;
|
||||
set( entries(ii).Panel, 'Position', [-500 ypos-500-panelheight/2 p(3)+1000 500] );
|
||||
ypos = ypos - panelheight;
|
||||
entries(ii) = iUpdateEntry( entries(ii), true );
|
||||
end
|
||||
setappdata( fig, 'ProgressEntries', entries );
|
||||
end % iRedraw
|
||||
|
||||
function cdata = iMakeCross( sz )
|
||||
% Create a cross-shape icon of size sz*sz*3
|
||||
|
||||
cdata = diag(ones(sz,1),0) + diag(ones(sz-1,1),1) + diag(ones(sz-1,1),-1);
|
||||
cdata = cdata + flip(cdata,2);
|
||||
|
||||
% Convert zeros to nans (transparent) and non-zeros to zero (black)
|
||||
cdata(cdata == 0) = nan;
|
||||
cdata(~isnan(cdata)) = 0;
|
||||
|
||||
% Convert to RGB
|
||||
cdata = cat( 3, cdata, cdata, cdata );
|
||||
end % iMakeCross
|
||||
|
||||
|
||||
function iTimerFcn(fig)
|
||||
% Timer callback for updating stuff every so often
|
||||
entries = getappdata( fig, 'ProgressEntries' );
|
||||
for ii=1:numel(entries)
|
||||
if entries(ii).Busy
|
||||
entries(ii) = iUpdateBusyEntry(entries(ii));
|
||||
end
|
||||
end
|
||||
setappdata( fig, 'ProgressEntries', entries );
|
||||
end % iTimerFcn
|
41
PDToolkit/@PDExperiment/onClickPlotAxes.m
Normal file
41
PDToolkit/@PDExperiment/onClickPlotAxes.m
Normal file
@@ -0,0 +1,41 @@
|
||||
function[e] = onClickPlotAxes(varargin)
|
||||
|
||||
e = varargin{1};
|
||||
obj = varargin{2};
|
||||
handle = varargin{3};
|
||||
|
||||
location = get(obj, 'CurrentPoint');
|
||||
|
||||
previous_location = get(obj, 'UserData');
|
||||
|
||||
|
||||
subj_pop = findobj('Tag','subj_pop');
|
||||
sess_pop = findobj('Tag','sess_pop');
|
||||
|
||||
tmpsubj=get(subj_pop, 'Value');
|
||||
if (iscell(tmpsubj)), selsubj = tmpsubj{1}; else selsubj = tmpsubj;end;
|
||||
tmpsess=get(subj_pop, 'Value');
|
||||
if (iscell(tmpsubj)), selsess = tmpsess{1}; else selsess = tmpsess;end;
|
||||
if isempty(selsess) selsess = 1; end; if isempty(selsubj) selsubj = 1; end;
|
||||
e.subjects(selsubj).sessions(selsess).sampling_rate
|
||||
|
||||
sampling_rate = e.subjects(selsubj).sessions(selsess).sampling_rate;
|
||||
|
||||
new_location.x = location(1,1);
|
||||
new_location.y = location(1,2);
|
||||
|
||||
if isfield(previous_location, 'x');
|
||||
delta_t = abs(new_location.x -previous_location.x);
|
||||
units = 'ms';
|
||||
if (delta_t > 1e3)
|
||||
units = 's';
|
||||
delta_t = delta_t/1e3;
|
||||
|
||||
end
|
||||
display(sprintf('Delta time : %3.2f %s', delta_t, units));
|
||||
|
||||
end
|
||||
|
||||
previous_location = new_location;
|
||||
|
||||
set(obj, 'UserData', previous_location);
|
12
PDToolkit/@PDExperiment/onDataPointClick.m
Normal file
12
PDToolkit/@PDExperiment/onDataPointClick.m
Normal file
@@ -0,0 +1,12 @@
|
||||
function[output_text e] = onDataPointClick(e, unused, varargin)
|
||||
|
||||
varargin
|
||||
% e = varargin{1};
|
||||
% obj = varargin{2};
|
||||
% event_obj = varargin{3};
|
||||
%
|
||||
% pos = get(event_obj, 'Position')
|
||||
% display(['clicked at pos : ' pos]);
|
||||
e.
|
||||
|
||||
output_text = {'test1111'};
|
154
PDToolkit/@PDExperiment/plot.m
Normal file
154
PDToolkit/@PDExperiment/plot.m
Normal file
@@ -0,0 +1,154 @@
|
||||
function[e] = plot(e)
|
||||
|
||||
plotwindow = figure;
|
||||
set(plotwindow, 'Color', [1 1 1]);
|
||||
e.handle = plotwindow;
|
||||
|
||||
options.raw = 0;
|
||||
options.logtransformed = 0;
|
||||
options.interpolated = 0;
|
||||
options.filtered = 0;
|
||||
options.blinks = 0;
|
||||
options.markers = 0;
|
||||
options.labels = 0;
|
||||
options.baseline = 0;
|
||||
options.baseline_corrected = 0;
|
||||
options.deconvolution = 0;
|
||||
|
||||
options.drawing = options;
|
||||
options.drawing.raw = {'-', [1 0 0], 3};
|
||||
options.drawing.logtransformed = {'-', [0 0 1], 3};
|
||||
options.drawing.interpolated = {'-', [0.5 0 0], 3};
|
||||
options.drawing.filtered= {'--', [0 0.5 0], 3};
|
||||
options.drawing.markers = {'--', [0.5 0 0], 3};
|
||||
options.drawing.baseline= {'--', [0 0 1], 3};
|
||||
options.drawing.baseline_corrected= {'--', [0 0 0], 3};
|
||||
|
||||
set(plotwindow, 'UserData', options);
|
||||
|
||||
subj_pop = uicontrol('Style','popupmenu');
|
||||
sess_pop = uicontrol('Style','popupmenu');
|
||||
|
||||
subj_pop_string = ''; subj_pop_vals =[];
|
||||
sess_pop_string = ''; sess_pop_vals =[];
|
||||
|
||||
for s = 1:length(e.subjects)
|
||||
if s > 1
|
||||
subj_pop_string = [subj_pop_string '|' e.subjects(s).name];
|
||||
else
|
||||
subj_pop_string = [e.subjects(s).name];
|
||||
end
|
||||
subj_pop_vals = [subj_pop_vals s];
|
||||
end
|
||||
|
||||
set(subj_pop, 'Position', [20 20 150 20]);
|
||||
set(subj_pop, 'String', subj_pop_string);
|
||||
set(subj_pop, 'Value', 1);
|
||||
set(subj_pop, 'Callback', 'e.set_plot_subject');
|
||||
set(subj_pop, 'FontName', 'Verdana');
|
||||
set(subj_pop, 'FontWeight', 'bold');
|
||||
set(subj_pop, 'FontSize', 11);
|
||||
|
||||
sel=get(subj_pop, 'Value');
|
||||
|
||||
for s = 1:length(e.subjects(sel).sessions);
|
||||
if s > 1
|
||||
sess_pop_string = [sess_pop_string '|' e.subjects(sel).sessions(s).name];
|
||||
else
|
||||
sess_pop_string = [e.subjects(sel).sessions(s).name];
|
||||
end
|
||||
sess_pop_vals = [sess_pop_vals s];
|
||||
end
|
||||
|
||||
|
||||
set(sess_pop, 'Position', [175 20 150 20]);
|
||||
set(sess_pop, 'String', sess_pop_string);
|
||||
set(sess_pop, 'Value', 1);
|
||||
set(sess_pop, 'Callback', 'e.set_plot_sess');
|
||||
set(sess_pop, 'FontName', 'Verdana');
|
||||
set(sess_pop, 'FontWeight', 'bold');
|
||||
set(sess_pop, 'FontSize', 11);
|
||||
|
||||
selsess = get(sess_pop, 'Value');
|
||||
trial_slider = uicontrol('Style','slider');
|
||||
trial_edit = uicontrol('Style','edit');
|
||||
|
||||
set(trial_slider, 'Position', [335 20 150 20]);
|
||||
set(trial_slider, 'Min', 1);
|
||||
set(trial_slider, 'Max', length(e.subjects(sel).sessions(selsess).trials));
|
||||
set(trial_slider, 'Value', 1);
|
||||
set(trial_slider, 'Callback', 'e.set_plot_trial_slider');
|
||||
set(trial_slider, 'SliderStep',[1/length(e.subjects(sel).sessions(selsess).trials) 5/length(e.subjects(sel).sessions(selsess).trials)]);
|
||||
|
||||
set(trial_edit, 'Position', [ 495 20 60 20]);
|
||||
set(trial_edit, 'String', 1);
|
||||
set(trial_edit, 'Callback', 'e.set_plot_trial_edit');
|
||||
set(trial_edit, 'FontName', 'Verdana');
|
||||
set(trial_edit, 'FontWeight', 'bold');
|
||||
set(trial_edit, 'FontSize', 11);
|
||||
|
||||
options_toggle = uicontrol('Style', 'toggle')
|
||||
set(options_toggle, 'Position', [480 390 70 30]);
|
||||
set(options_toggle, 'String', 'Options');
|
||||
set(options_toggle', 'Callback', 'e.togglePlotOptions');
|
||||
|
||||
bl_type = e.bl_types{e.settings.BaselineCorrection};
|
||||
jList = java.util.ArrayList;
|
||||
i=0;
|
||||
|
||||
|
||||
|
||||
|
||||
jList.add(i,'<html><font name="Verdana" size=1><b>Raw trial</b></font></html>'); i = i+1;
|
||||
jList.add(i,'<html><font name="Verdana" size=1><b>Logtransformed trial</b></font></html>'); i = i+1;
|
||||
jList.add(i,'<html><font name="Verdana" size=1><b>Interpolated trial</b></font></html>'); i = i+1;
|
||||
jList.add(i,'<html><font name="Verdana" size=1><b>Filtered trial</b></font></html>');i = i+1;
|
||||
jList.add(i,'<html><font name="Verdana" size=1><b>Blinks</b></font></html>'); i = i+1;
|
||||
jList.add(i,'<html><font name="Verdana" size=1><b>Markers</b></font></html>'); i = i+1;
|
||||
jList.add(i,'<html><font name="Verdana" size=1><b>Labels</b></font></html>'); i = i+1;
|
||||
jList.add(i,['<html><font name="Verdana" size=1><b>Baseline (' bl_type ')</b></font></html>']); i = i+1;
|
||||
jList.add(i,'<html><font name="Verdana" size=1><b>Baseline corrected</b></font></html>'); i = i+1;
|
||||
jList.add(i,'<html><font name="Verdana" size=1><b>Deconvolved modelfit</b></font></html>'); i = i+1;
|
||||
|
||||
jCBList = com.mathworks.mwswing.checkboxlist.CheckBoxList(jList);
|
||||
jScrollPane = com.mathworks.mwswing.MJScrollPane(jCBList);
|
||||
posfig = get(gcf, 'Position');
|
||||
%center = [((posfig(3) /2) - 75) ((posfig(4) /2) - 100)];
|
||||
[jhCBList,hContainer] = javacomponent(jScrollPane,[400 270 150,110],gcf);
|
||||
set(jCBList, 'ValueChangedCallback', @e.setPlotOptions);
|
||||
jCBModel = jCBList.getCheckModel;
|
||||
jCBModel.uncheckAll;
|
||||
jCBModel.checkIndex(1);
|
||||
|
||||
|
||||
%% set Tags
|
||||
|
||||
plotwindow_id = get_plotwindow_id(gcf);
|
||||
set(subj_pop, 'Tag', ['subj_pop.' plotwindow_id]);
|
||||
set(sess_pop, 'Tag', ['sess_pop.' plotwindow_id]);
|
||||
set(trial_edit, 'Tag', ['trial_edit.' plotwindow_id]);
|
||||
set(trial_slider, 'Tag', ['trial_slider.' plotwindow_id]);
|
||||
|
||||
set(options_toggle, 'Tag', ['options_toggle.' plotwindow_id]);
|
||||
|
||||
plot(e.subjects(1).sessions(1).trials(1));
|
||||
|
||||
pos = get(gca, 'Position');
|
||||
set(gca, 'Position', [.1 .2 .8 .7]);
|
||||
set(gca, 'FontName', 'Verdana');
|
||||
set(gca, 'FontWeight', 'bold');
|
||||
set(gca, 'FontSize', 10);
|
||||
set(gca, 'Box', 'on');
|
||||
|
||||
|
||||
%trial_slider = uicontrol('Style', 'slider')
|
||||
%fig_pos = get(gcf,'Position');
|
||||
%set(h, 'Position', [20 20 (fig_pos(3) - 20) 20]);
|
||||
%set(h, 'Min', 1); set(h, 'Max',
|
||||
|
||||
|
||||
set(gca,'ButtonDownFcn',@e.onClickPlotAxes);
|
||||
|
||||
dcm = datacursormode(gcf);
|
||||
set(dcm, 'UpdateFcn', @e.onDataPointClick);
|
||||
datacursormode on;
|
9
PDToolkit/@PDExperiment/plot_aggregate.m
Normal file
9
PDToolkit/@PDExperiment/plot_aggregate.m
Normal file
@@ -0,0 +1,9 @@
|
||||
function[e] = plot_aggregate(e, index, highlighted)
|
||||
|
||||
|
||||
display(sprintf('plotting %d', index));
|
||||
|
||||
hold on;
|
||||
|
||||
|
||||
plot(e.aggregates(index).mean, 'LineWidth', 3, 'Color', e.aggregates(index).color);
|
28
PDToolkit/@PDExperiment/plot_aggregates.m
Normal file
28
PDToolkit/@PDExperiment/plot_aggregates.m
Normal file
@@ -0,0 +1,28 @@
|
||||
function[e] = plot_aggregates(e, table, event)
|
||||
|
||||
data = get(table, 'Data');
|
||||
|
||||
if ~isempty(event)
|
||||
|
||||
if ~isempty(event.Indices)
|
||||
selected = event.Indices(1); % selected row
|
||||
end
|
||||
end
|
||||
|
||||
e = evalin('base', 'e');
|
||||
|
||||
for a = 1:length(e.aggregates)
|
||||
|
||||
if (data{a,1})
|
||||
highlight=0;
|
||||
if ~isempty(event)
|
||||
if ~isempty(event.Indices)
|
||||
if (event.Indices(2) > 1) %% row highlighted
|
||||
highlight=1;
|
||||
end
|
||||
end
|
||||
end
|
||||
plot_aggregate(e, a, highlight);
|
||||
|
||||
end
|
||||
end
|
18
PDToolkit/@PDExperiment/preprocess.m
Normal file
18
PDToolkit/@PDExperiment/preprocess.m
Normal file
@@ -0,0 +1,18 @@
|
||||
function[obj] = preprocess(obj);
|
||||
|
||||
progressbar = waitbar(0, 'Preprocessing subjects...');
|
||||
p= get(progressbar, 'Position'); p(2)=p(2)+100;
|
||||
set(progressbar,'Position', p, 'Color', [1 1 1]);
|
||||
t = get(get(progressbar, 'Children'), 'Title');
|
||||
set(t, 'FontSize', 15, 'FontWeight', 'bold', 'FontName', 'Tahoma');
|
||||
set(progressbar,'Visible','on');
|
||||
|
||||
|
||||
for s = 1:length(obj.subjects)
|
||||
waitbar(s/length(obj.subjects), progressbar, sprintf('Preprocessing data for subject %d...', s));
|
||||
obj.subjects(s) = obj.subjects(s).preprocess(obj.settings);
|
||||
|
||||
end
|
||||
|
||||
close(progressbar);
|
||||
end
|
6
PDToolkit/@PDExperiment/removeDuplicateLabels.m
Normal file
6
PDToolkit/@PDExperiment/removeDuplicateLabels.m
Normal file
@@ -0,0 +1,6 @@
|
||||
function[obj] = removeDuplicateLabels(obj)
|
||||
|
||||
|
||||
for s = 1:length(obj.subjects)
|
||||
obj.subjects(s) = obj.subjects(s).removeDuplicateLabels;
|
||||
end
|
16
PDToolkit/@PDExperiment/remove_aggregate.m
Normal file
16
PDToolkit/@PDExperiment/remove_aggregate.m
Normal file
@@ -0,0 +1,16 @@
|
||||
function[e] = remove_aggregate(e)
|
||||
|
||||
fig = e.handle(2);
|
||||
figure(fig);
|
||||
|
||||
group_list = findobj('Tag', 'group_list');
|
||||
|
||||
selected_group = get(group_list, 'Value')
|
||||
|
||||
%e.aggregates(selected_group) = [];
|
||||
for i =selected_group+1:length(e.aggregates)
|
||||
e.aggregates(i) = e.aggregates(i-1);
|
||||
end
|
||||
e.aggregates(end) = [];
|
||||
|
||||
e.update_aggregates;
|
26
PDToolkit/@PDExperiment/select_aggregate.m
Normal file
26
PDToolkit/@PDExperiment/select_aggregate.m
Normal file
@@ -0,0 +1,26 @@
|
||||
function[e] = select_aggregate(varargin)
|
||||
|
||||
e = varargin{1};
|
||||
table = varargin{2};
|
||||
event = varargin{3};
|
||||
|
||||
data = get(table, 'Data');
|
||||
|
||||
if length(event.Indices) > 1
|
||||
|
||||
if (event.Indices(2) == 1)
|
||||
|
||||
%% checkbutton is clicked
|
||||
if isempty(data{event.Indices(1),1})
|
||||
data{event.Indices(1),1} = 0;
|
||||
end
|
||||
data{event.Indices(1),1} = logical(~data{event.Indices(1),1});
|
||||
end
|
||||
|
||||
set(table, 'Data',data);
|
||||
end
|
||||
|
||||
|
||||
e.plot_aggregates(table, event);
|
||||
|
||||
|
36
PDToolkit/@PDExperiment/setPlotOptions.m
Normal file
36
PDToolkit/@PDExperiment/setPlotOptions.m
Normal file
@@ -0,0 +1,36 @@
|
||||
function[e] = setPlotOptions(varargin)
|
||||
|
||||
plotwindow = gcf;
|
||||
plotwindow_id = get_plotwindow_id(plotwindow);
|
||||
|
||||
options = get(plotwindow, 'UserData')
|
||||
e = varargin{1};
|
||||
jEventData = varargin{2};
|
||||
hListbox = varargin{3};
|
||||
|
||||
variables = {'raw', 'logtransformed', 'interpolated', 'filtered', 'blinks', 'markers', 'labels','baseline', 'baseline_corrected', 'deconvolution'};
|
||||
items = get(jEventData, 'CheckedIndicies');
|
||||
|
||||
non_items = setdiff(0:length(variables)-1, items);
|
||||
for i = 1:length(items)
|
||||
eval(['options.' variables{items(i)+1} '=1;']);
|
||||
end
|
||||
|
||||
for i = 1:length(non_items)
|
||||
eval(['options.' variables{non_items(i)+1} '=0;']);
|
||||
end
|
||||
|
||||
set(plotwindow, 'UserData', options);
|
||||
|
||||
subj_pop = findobj('Tag',['subj_pop.' plotwindow_id]);
|
||||
sess_pop = findobj('Tag',['sess_pop.' plotwindow_id]);
|
||||
trial_edit = findobj('Tag', ['trial_edit.' plotwindow_id]);
|
||||
|
||||
tmpsubj=get(subj_pop, 'Value');
|
||||
if (iscell(tmpsubj)), selsubj = tmpsubj{1}; else selsubj = tmpsubj;end;
|
||||
tmpsess=get(sess_pop, 'Value');
|
||||
if (iscell(tmpsubj)), selsess = tmpsess{1}; else selsess = tmpsess;end;
|
||||
tmptrial=get(trial_edit, 'String');
|
||||
if (iscell(tmptrial)), seltrial = str2num(tmptrial{1}); else seltrial = str2num(tmptrial);end;
|
||||
|
||||
plot(e.subjects(selsubj).sessions(selsess).trials(seltrial), e.settings);
|
1
PDToolkit/@PDExperiment/setTrialStart.m
Normal file
1
PDToolkit/@PDExperiment/setTrialStart.m
Normal file
@@ -0,0 +1 @@
|
||||
function[obj] = setTrialStart(pattern)
|
23
PDToolkit/@PDExperiment/set_plot_sess.m
Normal file
23
PDToolkit/@PDExperiment/set_plot_sess.m
Normal file
@@ -0,0 +1,23 @@
|
||||
function[] = set_plot_sess(e)
|
||||
|
||||
plotwindow = gcf;
|
||||
plotwindow_id = get_plotwindow_id(plotwindow);
|
||||
|
||||
subj_pop = findobj('Tag', ['subj_pop.' plotwindow_id]);
|
||||
sess_pop = findobj('Tag', ['sess_pop.' plotwindow_id]);
|
||||
trial_slider = findobj('Tag', ['trial_slider.' plotwindow_id]);
|
||||
trial_edit = findobj('Tag', ['trial_edit.' plotwindow_id]);
|
||||
|
||||
trial=get(trial_slider, 'Value');
|
||||
|
||||
set(trial_edit, 'String', trial);
|
||||
|
||||
|
||||
sess = get(sess_pop, 'Value');
|
||||
subj = get(subj_pop, 'Value');
|
||||
|
||||
trial=round(get(trial_slider, 'Value'));
|
||||
set(trial_slider, 'Value', trial);
|
||||
|
||||
plot(e.subjects(subj).sessions(sess).trials(trial));
|
||||
|
22
PDToolkit/@PDExperiment/set_plot_session_trial_edit.m
Normal file
22
PDToolkit/@PDExperiment/set_plot_session_trial_edit.m
Normal file
@@ -0,0 +1,22 @@
|
||||
function[] = set_plot_trial_edit(e)
|
||||
|
||||
plotwindow = e.handle;
|
||||
|
||||
subj_pop = findobj('Tag', 'subj_pop');
|
||||
sess_pop = findobj('Tag', 'sess_pop');
|
||||
trial_slider = findobj('Tag', 'trial_slider');
|
||||
trial_edit = findobj('Tag', 'trial_edit');
|
||||
|
||||
trial=get(trial_edit, 'Value');
|
||||
|
||||
min_trial = get(trial_edit, 'Min');
|
||||
max_trial = get(trial_edit, 'Max');
|
||||
|
||||
if ((trial >= min_trial) && (trial <= max_trial))
|
||||
set(trial_slider, 'Value', trial);
|
||||
else
|
||||
display('Trial id does not exist');
|
||||
end
|
||||
|
||||
|
||||
plot(e.subjects(subj).sessions(sess).trials(trial));
|
22
PDToolkit/@PDExperiment/set_plot_subj.m
Normal file
22
PDToolkit/@PDExperiment/set_plot_subj.m
Normal file
@@ -0,0 +1,22 @@
|
||||
function[] = set_plot_subject(e)
|
||||
|
||||
plotwindow = e.handle;
|
||||
|
||||
|
||||
subj_pop = findobj('Tag', 'subj_pop');
|
||||
sess_pop = findobj('Tag', 'sess_pop');
|
||||
trial_slider = findobj('Tag', 'trial_slider');
|
||||
trial_edit = findobj('Tag', 'trial_edit');
|
||||
|
||||
sel=get(subj_pop, 'Value');
|
||||
|
||||
for s = 1:length(e.subjects(sel).sessions);
|
||||
if s > 1
|
||||
sess_pop_string = [sess_pop_string '|' e.subjects(sel).sessions(s).name];
|
||||
else
|
||||
sess_pop_string = [e.subjects(sel).sessions(s).name];
|
||||
end
|
||||
sess_pop_vals = [sess_pop_vals s];
|
||||
end
|
||||
set(sess_pop, 'Value', 1);
|
||||
|
37
PDToolkit/@PDExperiment/set_plot_subject.m
Normal file
37
PDToolkit/@PDExperiment/set_plot_subject.m
Normal file
@@ -0,0 +1,37 @@
|
||||
function[] = set_plot_subject(e)
|
||||
|
||||
plotwindow = gcf;
|
||||
plotwindow_id = get_plotwindow_id(plotwindow);
|
||||
|
||||
subj_pop = findobj('Tag', ['subj_pop.' plotwindow_id]);
|
||||
sess_pop = findobj('Tag', ['sess_pop.' plotwindow_id]);
|
||||
trial_slider = findobj('Tag', ['trial_slider.' plotwindow_id]);
|
||||
trial_edit = findobj('Tag', ['trial_edit.' plotwindow_id]);
|
||||
|
||||
tmp=get(subj_pop, 'Value');
|
||||
if (iscell(tmp))
|
||||
sel = tmp{1};
|
||||
else
|
||||
sel = tmp;
|
||||
end;
|
||||
|
||||
sess_pop_vals = []; sess_pop_string = '';
|
||||
for s = 1:length(e.subjects(sel).sessions);
|
||||
if s > 1
|
||||
sess_pop_string = [sess_pop_string '|' e.subjects(sel).sessions(s).name];
|
||||
else
|
||||
sess_pop_string = [e.subjects(sel).sessions(s).name];
|
||||
end
|
||||
sess_pop_vals = [sess_pop_vals s];
|
||||
end
|
||||
set(sess_pop, 'Value', 1);
|
||||
set(sess_pop, 'String', sess_pop_string);
|
||||
|
||||
|
||||
sess = get(sess_pop, 'Value');
|
||||
subj = get(subj_pop, 'Value');
|
||||
trial=round(get(trial_slider, 'Value'));
|
||||
|
||||
plot(e.subjects(subj).sessions(sess).trials(trial));
|
||||
|
||||
|
27
PDToolkit/@PDExperiment/set_plot_trial_edit.m
Normal file
27
PDToolkit/@PDExperiment/set_plot_trial_edit.m
Normal file
@@ -0,0 +1,27 @@
|
||||
function[] = set_plot_trial_edit(e)
|
||||
|
||||
plotwindow = gcf;
|
||||
plotwindow_id = num2str(plotwindow);
|
||||
|
||||
subj_pop = findobj('Tag', ['subj_pop.' plotwindow_id]);
|
||||
sess_pop = findobj('Tag', ['sess_pop.' plotwindow_id]);
|
||||
trial_slider = findobj('Tag', ['trial_slider.' plotwindow_id]);
|
||||
trial_edit = findobj('Tag', ['trial_edit.' plotwindow_id]);
|
||||
|
||||
trial=str2num(get(trial_edit, 'String'));
|
||||
|
||||
min_trial = get(trial_slider, 'Min');
|
||||
max_trial = get(trial_slider, 'Max');
|
||||
|
||||
if ((trial >= min_trial) && (trial <= max_trial))
|
||||
set(trial_slider, 'Value', trial);
|
||||
else
|
||||
display('Trial id does not exist');
|
||||
%set(trial_slide, 'Value', min_trial);
|
||||
end
|
||||
|
||||
sess = get(sess_pop, 'Value');
|
||||
subj = get(subj_pop, 'Value');
|
||||
|
||||
plot(e.subjects(subj).sessions(sess).trials(trial));
|
||||
|
23
PDToolkit/@PDExperiment/set_plot_trial_slider.m
Normal file
23
PDToolkit/@PDExperiment/set_plot_trial_slider.m
Normal file
@@ -0,0 +1,23 @@
|
||||
function[] = set_plot_trial_slider(e)
|
||||
|
||||
plotwindow_id = get_plotwindow_id(gcf);
|
||||
|
||||
subj_pop = findobj('Tag', ['subj_pop.' plotwindow_id]);
|
||||
sess_pop = findobj('Tag', ['sess_pop.' plotwindow_id]);
|
||||
trial_slider = findobj('Tag', ['trial_slider.' plotwindow_id]);
|
||||
trial_edit = findobj('Tag', ['trial_edit.' plotwindow_id]);
|
||||
|
||||
ts_val = get(trial_slider, 'Value');
|
||||
if iscell(ts_val)
|
||||
trial=round(ts_val{1});
|
||||
else
|
||||
trial=round(ts_val);
|
||||
end
|
||||
|
||||
set(trial_edit, 'String', trial);
|
||||
|
||||
|
||||
sess = get(sess_pop, 'Value');
|
||||
subj = get(subj_pop, 'Value');
|
||||
|
||||
plot(e.subjects(subj).sessions(sess).trials(trial));
|
47
PDToolkit/@PDExperiment/statistics.m
Normal file
47
PDToolkit/@PDExperiment/statistics.m
Normal file
@@ -0,0 +1,47 @@
|
||||
function[] = statistics(exp)
|
||||
%
|
||||
% Calculate pairwise TFCE statistics between aggregates
|
||||
% based on permutation
|
||||
%
|
||||
%
|
||||
|
||||
for a = 1:length(exp.aggregates)
|
||||
|
||||
for b = setdiff(1:length(exp.aggregates), a)
|
||||
|
||||
%% retreive matrices for aggregates of comparison
|
||||
[traces_a time_a] = exp.get_aggregate_data(a);
|
||||
[traces_b time_b] = exp.get_aggregate_data(b);
|
||||
|
||||
%% TODO: Check time_a == time_b !
|
||||
|
||||
traces = [traces_a ; traces_b];
|
||||
labels = [repmat(1, 1:size(traces_a,2)) repmat(2, 1:size(traces_b,2))];
|
||||
|
||||
%% calculate true difference:
|
||||
|
||||
true_signal = nanmean(traces_a) - nanmean(traces_b);
|
||||
|
||||
%% perform permutations
|
||||
nperm = exp.settings.Statistics.NumberOfPermutations;
|
||||
P = nan(size(traces_1,1), nperm);
|
||||
|
||||
for i = 1:nperm
|
||||
|
||||
labels_permuted = labels(randperm(length(labels)));
|
||||
a_perm = find(labels_permuted==1); b_perm = find(labels_permuted==2);
|
||||
|
||||
P(:,i) = nanmean(traces(a_perm,:)) - nanmean(traces(b_perm,:));
|
||||
end
|
||||
hmin = 0; hmax = max(max(P));
|
||||
|
||||
%% perform TFCE
|
||||
T = TFCEobj('D', P, 'hmax', hmax);
|
||||
T.TFCECalc;
|
||||
|
||||
%% store results
|
||||
exp.aggregates.statistics.TFCE(a,b).results.pvalues = T.Pvalues;
|
||||
%% threshold FWE comparison
|
||||
exp.aggregates.statistics.TFCE(a,b).results.pvalues = T.Pvalues;
|
||||
end
|
||||
end
|
10
PDToolkit/@PDExperiment/togglePlotOptions.m
Normal file
10
PDToolkit/@PDExperiment/togglePlotOptions.m
Normal file
@@ -0,0 +1,10 @@
|
||||
function[e] = togglePlotOptions(e)
|
||||
|
||||
option_list = findobj('UserData', 'com.mathworks.mwswing.MJScrollPane');
|
||||
visible = get(option_list, 'Visible');
|
||||
|
||||
if strcmp(visible, 'on')
|
||||
set(option_list, 'Visible', 'off');
|
||||
else
|
||||
set(option_list, 'Visible', 'on');
|
||||
end
|
25
PDToolkit/@PDExperiment/update_aggregates.m
Normal file
25
PDToolkit/@PDExperiment/update_aggregates.m
Normal file
@@ -0,0 +1,25 @@
|
||||
function[e] = update_aggregates(e);
|
||||
|
||||
fig = gcf;
|
||||
plotwindow_id = num2str(fig);
|
||||
|
||||
table = findobj('Tag','aggragate_table');
|
||||
agg_strings = {};
|
||||
for i = 1:length(e.aggregates)
|
||||
agg_strings{i,1} = 1;
|
||||
color_str = ['#' sprintf('%02s', dec2hex(e.aggregates(i).color(1)*255)) ...
|
||||
sprintf('%02s', dec2hex(e.aggregates(i).color(2)*255)) ...
|
||||
sprintf('%02s', dec2hex(e.aggregates(i).color(3)*255))]
|
||||
agg_strings{i,2} = ['<html><li color=' color_str '><font color=#000000>'...
|
||||
e.aggregates(i).name{1} ...
|
||||
'</font></li></html>'];
|
||||
|
||||
agg_strings{i,3} = e.aggregates(i).error.name;
|
||||
|
||||
end
|
||||
|
||||
set(table, 'Data', agg_strings);
|
||||
|
||||
|
||||
e = e.calculate_aggregates;
|
||||
e = e.plot_aggregates(table, []);
|
Reference in New Issue
Block a user