Description
The user function must comply the following interface:
result = myUserFunction(mode, couples, fast).
Two calling modes are distinguished:
1. Info call
The function should return the number of required figures when
called with mode = 'info'.
nFigures = myUserFunction('info', couples);
This number will be used to arrange the custom figures
properly and to prepare figure saving for the report.
2. Normal call
With mode = 'normal', the function should apply the custom plot.
Output arguments are not required and will be ignored.
myUserFunction('normal', couples, fast, overwrite);
The second argument, couples, is a struct, where
where couples(i).stimuli(j).xForFit(:,k)
will return the trajectory of the k-th dynamic variable of couple i and
stimulus j at all experimentally sampled time points.
Similar, couples(i).stimuli(j).yDataForFit(:,k) contains the observed
values and couples(i).stimuli(j).zForFit(:,k) the derived variables.
For calculations based on the integrated trajectories, e.g. to accurately
determine the maximum of a curve, xFine etc. can be used.
The third argument, fast, will be true if e.g. a slider is changed in the
equalizer or a fitting process is running. Then, the user function should
avoid time-consuming steps like drawing a legend or a title.
Argument four, 'overwrite', is usually set to true. If false,
old trajectories should not be overwritten, which is useful to compare
e.g. different parameter settings in the same figure.
% IDs
couples(i).modelID
couples(i).dataID
couples(i).kIDs
couples(i).sIDs
couples(i).uIDs
couples(i).xIDs
couples(i).yIDs
couples(i).zIDs
couples(i).aIDs
% Parameters and start values
couples(i).k
couples(i).s
couples(i).x0
% Visibility (as set in the equalizer)
couples(i).plotting.visible.a.indices
couples(i).plotting.visible.u.indices
couples(i).plotting.visible.x.indices
couples(i).plotting.visible.y.indices
couples(i).plotting.visible.z.indices
couples(i).plotting.visible.stimuli.indices
% Trajectories for fine sampling (Fine) or experimental sampling (ForFit)
% for each stimulus couples(i).stimuli(j):
tForFit Sampling of experiment
tFine Fine sampling (n may be changed in config.plotting.nFine)
xForFit Dynamic variable x given by model at sampling time points
xFine Dynamic variable x given by model for fine sampling
yForFit Observable y given by model at sampling time points
yDataForFit Externally given data - the measurements
yDataStdForFit Standard deviation of the external data
yFine Observable y given by model for fine sampling
y0 Mean value of external data for first time point
zForFit Derived variable z
zFine
uForFit Driving input u
uFine
u0 Value of driving input u at first time point
Notes
Please do not use the 'figure' command to change
the current figure inside your code. Instead use
set(0,'CurrentFigure', gcf+1);
to switch to the next figure. The first figure will already be selected
by PottersWheel.
If the function is called without arguments, the current
user defined plotting function name is returned.
The name of the plotting function is saved in the configuration at:
config.plotting.userFunction
The function can be changed any time, also without calling pwCombine.
This is different for pwSetOptimizationUserFunction, which has
to be set before pwCombine is called.
Macros
PW_Macro_Custom_Plotting_01
Examples
1. Plot the sum of Erk_obs over all couples:
pwSetPlottingUserFunction(@myUserFunction1)
where myUserFunction1.m reads:
function result = myUserFunction1(mode, couples, fast, overwrite)
result = [];
if strcmpi(mode, 'info')
result = 1; % only one additional figure
return
elseif ~strcmpi(mode, 'normal')
error('Unknown mode: %s', mode)
end
% We assume that all couples have the same number of stimuli
% and that Erk is the 3rd observable (iErk = 3)
for j=1:length(couples(1).stimuli)
ySum = couples(1).stimuli(j).yForFit(:,iErk);
for i=2:length(couples)
ySum = ySum + couples(i).stimuli(j).yForFit(:,iErk);
end
plot(couples(1).tForFit, ySum);
hold on
end
2. Sum plot for x and y over all couples for stimulus 1 and
pay attention to 'fast' and 'overwrite' arguments
function result = pwUserFunctionPlotSum(mode, couples, fast, overwrite)
result = 2;
if strcmp(mode, 'info')
return
elseif ~strcmp(mode, 'normal')
error('Unknown mode: %s', mode);
end
xSum = couples(1).stimuli(1).xForFit;
ySum = couples(1).stimuli(1).yForFit;
for i=2:length(couples)
xSum = xSum + couples(i).stimuli(1).xForFit;
ySum = ySum + couples(i).stimuli(1).yForFit;
end
% Overwrite?
if overwrite == true
hold off
else
hold on
end
% Fast or slow plotting?
if fast == true
plot(couples(1).stimuli(1).tForFit, xSum, '-');
set(0, 'CurrentFigure', gcf+1);
% Overwrite?
if overwrite == true
hold off
else
hold on
end
plot(couples(1).stimuli(1).tForFit, ySum, '-');
else
plot(couples(1).stimuli(1).tForFit, xSum, '.-');
title('Sum for x over all couples')
h = legend(couples(1).xIDs);
set(h, 'Interpreter', 'none');
set(0, 'CurrentFigure', gcf+1);
% Overwrite?
if overwrite == true
hold off
else
hold on
end
plot(couples(1).stimuli(1).tForFit, ySum, '.-');
title('Sum for y over all couples')
h = legend(couples(1).yIDs);
set(h, 'Interpreter', 'none');
end
3. Phase space diagram for x variables 1 and 2
function result = phaseSpace(mode, couples, fast, overwrite)
% Custom function plotting x1 against x2.
%% Return number of created figures if mode == 'info'
result = [];
if strcmpi(mode, 'info')
result = 1; % only one additional figure
return
elseif ~strcmpi(mode, 'normal')
error('Unknown mode: %s', mode)
end
%% Get data
x1 = couples(1).stimuli(1).xFine(:,1);
x2 = couples(1).stimuli(1).xFine(:,2);
%% Overwrite?
if overwrite == true
hold off
else
hold on
end
%% Plot
plot(x1, x2, 'b-');
hold on
plot(x1(1), x2(1), 'ko');
%% Labels
title('Phase space diagram', 'FontSize', 14);
xlabel(couples(1).xIDs{1});
ylabel(couples(1).xIDs{2});
Keywords: set plotting user function
See also