%************************************************************************** % % 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. % % Output: % [hBar hErrorbar] = barwitherr(..) returns a vector of handles to the % barseries (hBar) and error bar (hErrorbar) objects % % Symmetric Example: % y = randn(3,4); % random y values (3 groups of 4 parameters) % errY = 0.1.*y; % 10% error % h = 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') % set(h(1),'FaceColor','k'); % % % 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 % 14/06/2013 Martina F. Callaghan Returning handle as recommended by % Eric (see submission comments) % 08/07/2013 Martina F. Callaghan Only return handle if requested. % 18/07/2013 Martina F. Callaghan Bug fix for single group data that % allows assymetric errors. % Also removed dot from display as % per Charles Colin comment. The % handle can be returned to control % appearance. % 27/08/2013 Martina F. Callaghan Ensuring errors are always stored % as lowerErrors and upperErrors even % if symmetric. % %************************************************************************** function varargout = 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 isscalar(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{:}, 'EdgeColor', 'none'); % standard implementation of bar fn hold on hBar = handles.bar; if nRows > 1 hErrorbar = zeros(1,nCols); for col = 1:nCols % Extract the x location data needed for the errorbar plots: x = get(get(handles.bar(col),'children'),'xdata'); % 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: hErrorbar(col) = errorbar(mean(x,1), values(xOrder,col), lowerErrors(xOrder,col), upperErrors(xOrder, col), '.k'); set(hErrorbar(col), 'marker', 'none') end else x = get(get(handles.bar,'children'),'xdata'); hErrorbar = errorbar(mean(x,1), values, lowerErrors, upperErrors, '.k'); set(hErrorbar, 'marker', 'none') end hold off switch nargout case 1 varargout{1} = hBar; case 2 varargout{1} = hBar; varargout{2} = hErrorbar; end