-
Notifications
You must be signed in to change notification settings - Fork 1
/
barwitherr.m
127 lines (117 loc) · 4.63 KB
/
barwitherr.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
%**************************************************************************
%
% This is a simple extension of the bar plot to include error bars. It
% is called in exactly the same way as bar but with an extra input
% parameter "errors" passed first.
%
% Parameters:
% errors - the errors to be plotted (extra dimension used if assymetric)
% varargin - parameters as passed to conventional bar plot
% See bar and errorbar documentation for more details.
%
% Symmetric Example:
% y = randn(3,4); % random y values (3 groups of 4 parameters)
% errY = 0.1.*y; % 10% error
% barwitherr(errY, y); % Plot with errorbars
%
% set(gca,'XTickLabel',{'Group A','Group B','Group C'})
% legend('Parameter 1','Parameter 2','Parameter 3','Parameter 4')
% ylabel('Y Value')
%
%
% Asymmetric Example:
% y = randn(3,4); % random y values (3 groups of 4 parameters)
% errY = zeros(3,4,2);
% errY(:,:,1) = 0.1.*y; % 10% lower error
% errY(:,:,2) = 0.2.*y; % 20% upper error
% barwitherr(errY, y); % Plot with errorbars
%
% set(gca,'XTickLabel',{'Group A','Group B','Group C'})
% legend('Parameter 1','Parameter 2','Parameter 3','Parameter 4')
% ylabel('Y Value')
%
%
% Notes:
% Ideally used for group plots with non-overlapping bars because it
% will always plot in bar centre (so can look odd for over-lapping bars)
% and for stacked plots the errorbars will be at the original y value is
% not the stacked value so again odd appearance as is.
%
% The data may not be in ascending order. Only an issue if x-values are
% passed to the fn in which case their order must be determined to
% correctly position the errorbars.
%
%
% 24/02/2011 Martina F. Callaghan Created
% 12/08/2011 Martina F. Callaghan Updated for random x-values
% 24/10/2011 Martina F. Callaghan Updated for asymmetric errors
% 15/11/2011 Martina F. Callaghan Fixed bug for assymetric errors &
% vector plots
%
%**************************************************************************
function handles = barwitherr(errors,varargin)
% Check how the function has been called based on requirements for "bar"
if nargin < 3
% This is the same as calling bar(y)
values = varargin{1};
xOrder = 1:size(values,1);
else
% This means extra parameters have been specified
if ishandle(varargin{2}) || ischar(varargin{2})
% It is a width / property so the y values are still varargin{1}
values = varargin{1};
xOrder = 1:size(values,1);
else
% x-values have been specified so the y values are varargin{2}
% If x-values have been specified, they could be in a random order,
% get their indices in ascending order for use with the bar
% locations which will be in ascending order:
values = varargin{2};
[tmp xOrder] = sort(varargin{1});
end
end
% If an extra dimension is supplied for the errors then they are
% assymetric split out into upper and lower:
if ndims(errors) == ndims(values)+1
lowerErrors = errors(:,:,1);
upperErrors = errors(:,:,2);
elseif isvector(values)~=isvector(errors)
lowerErrors = errors(:,1);
upperErrors = errors(:,2);
else
lowerErrors = errors;
upperErrors = errors;
end
% Check that the size of "errors" corresponsds to the size of the y-values.
% Arbitrarily using lower errors as indicative.
if any(size(values) ~= size(lowerErrors))
error('The values and errors have to be the same length')
end
[nRows nCols] = size(values);
handles.bar = bar(varargin{:}); % standard implementation of bar fn
hold on
if nRows > 1
for col = 1:nCols
% Extract the x location data needed for the errorbar plots:
% this was the old code, worked with previous versions of matlab:
if verLessThan('matlab', '8.5')
x = get(get(handles.bar(col),'children'),'xdata');
% but now (v2015a) bar works differently, I found a hidden XOffset property!
else
x = get(handles.bar(col),'xdata') + get(handles.bar(col),'xoffset');
end
% Use the mean x values to call the standard errorbar fn; the
% errorbars will now be centred on each bar; these are in ascending
% order so use xOrder to ensure y values and errors are too:
errorbar(mean(x,1),values(xOrder,col),lowerErrors(xOrder,col), upperErrors(xOrder, col), '.k')
end
else
%same update here:
if verLessThan('matlab','8.5')
x = get(get(handles.bar,'children'),'xdata');
else
x = get(handles.bar,'xdata') + get(handles.bar,'xoffset');
end
errorbar(mean(x,1),values,errors,'.k')
end
hold off