I am trying to plot two sequences of bars, using the same y-axis. One of the sequences goes on the bottom, the other goes on top (from top to bottom), and the y axis is split into two (half for the bottom bars and half for the top bars). The bottom bars use one color, like green, and the top bars use another color, red, and the y axis uses the respective colors on each half on the axis.
Example:
Question: How can I split the y-axis in the way represented in the figure above?
Thanks for helping! =D
You could create this effect by layering three axes and adjusting their properties accordingly. For example:
% The larger left axes:
hLeft = axes('Position', [0.1 0.1 0.8 0.8], ... % Normalized position
'XLim', [0 11], 'YLim', [0 3], ... % Set desired limits
'Box', 'off'); % Turn off outline
hLeft.XLabel.String = 'Time'; % Add an x label
hLeft.YLabel.String = 'Line'; % Add a y label
hLeft.Title.String = 'Bar-bar-plot'; % Add a title
hLine = line(hLeft, 1:10, rand(1,10)+1, 'Color', 'k'); % Plot a sample line
% The lower right axes:
hLower = axes('Position', [0.1 0.1 0.8 0.4], ... % Position over bottom half
'XLim', [0 11], 'YLim', [0 1.5], ... % Set desired limits
'YColor', [0 0.5 0], 'Color', 'none', ... % Change colors
'YAxisLocation', 'right'); % Position y axis
hLower.XAxis.Visible = 'off'; % Turn of x axis
hLower.YLabel.String = 'Bar 1'; % Add a y label
hold on;
hBarLower = bar(hLower, 1:10, rand(1,10), ... % A sample bar plot
'FaceColor', 'none', 'EdgeColor', [0 0.5 0]);
% The upper right axes:
hUpper = axes('Position', [0.1 0.5 0.8 0.4], ... % Position over top half
'XLim', [0 11], 'YLim', [0 1.5], ... % Set desired limits
'YColor', [1 0 0], 'Color', 'none', ... % Change colors
'YAxisLocation', 'right', ... % Position y axis
'YDir', 'reverse'); % Reverse y axis
hUpper.XAxis.Visible = 'off'; % Turn off x axis
hUpper.YLabel.String = 'Bar 2'; % Add a y label
hold on;
hBarUpper = bar(hUpper, 1:10, rand(1,10), ... % A sample bar plot
'FaceColor', 'none', 'EdgeColor', [1 0 0]);
% Add a legend:
hLegend = legend(hUpper, [hLine hBarLower hBarUpper], ...
{'line', 'bar 1', 'bar 2'}, 'Color', 'w');
And here's the plot:
You can reposition the legend as needed by left clicking on it and dragging it to the best spot.
Related
I would like to plot the grouped bar chart for the comparison of three methods. I tried the following code and it is displayed as stacked bar chart.can you please help
dice =[0, 3, 5];
no_of_region=[42, 12, 5];
figure;
bar(dice',.2,'grouped','FaceColor',[0 .5 .5],'EdgeColor',[0 .9 .9],'LineWidth',1.5)
ylabel('Dice Similarity index')
yyaxis right
bar(no_of_region, .2,'grouped','EdgeColor', 'r', 'LineWidth', 2);
legend('Dice Similarity Index','Number of regions')
legend('Location','northwest')
XTickLabel={'a' ; 'b';'c'};
XTick=[1 2 3]
set(gca, 'XTick',XTick);
set(gca, 'XTickLabel', XTickLabel);
set(gca, 'XTickLabelRotation', 45);
xlabel('Different Methods', 'Fontsize', 16)
ylabel('Number of Regions', 'Fontsize', 16)
title('Comparison of Algorithms', 'fontsize', 20);
set(gcf,'color','w');
OUTPUT I GOT AS:
One easy solution is to shift the bars left and right by half of their width (or more if you would like space between them). Here is the new code, which is also cleaned a bit stylistically:
% parameters
dice = [0, 3, 5];
no_of_region = [42, 12, 5];
X = [1, 2, 3]; % common x values for plot
bar_width = 0.2; % width of bars
% initialize figure
figure;
% left plot
bar(X.' - bar_width/2, dice', bar_width, 'grouped', ...
'FaceColor', [0 .5 .5], ...
'EdgeColor', [0 .9 .9], ...
'LineWidth', 1.5);
ylabel('Dice Similarity index');
% right plot
yyaxis right;
bar(X.' + bar_width/2, no_of_region, bar_width, 'grouped', ...
'EdgeColor', 'r', ...
'LineWidth', 2);
% plot formatting
legend({'Dice Similarity Index', 'Number of regions'}, ...
'Location', 'northwest');
XTickLabel = {'a' ; 'b'; 'c'};
XTick = X;
set(gca, ...
'XTick', XTick, ...
'XTickLabel', XTickLabel, ...
'XTickLabelRotation', 45);
xlabel('Different Methods', 'FontSize', 16);
ylabel('Number of Regions', 'FontSize', 16);
title('Comparison of Algorithms', 'FontSize', 20);
set(gcf, 'color', 'w');
Depending on desired behavior, you also might consider replacing figure; by clf;, which clears the existing figure or opens a new figure window if there is not already one open.
I would like to have vertical/horizontal grid lines across spacing of figures in Matlab 2015b.
I know that you can have a background image that can be a network of gridlines by background, something partial about it at How do I add a background image to my GUI or figure window?
However, I think gridlines without a picture would be a better choice
Example code
data=randi(513,513);
D=mat2gray(pdist(data, 'correlation'));
ax2 = axes('OuterPosition', [0.51 0.5 0.5 0.5]);
plot(D, 'Parent', ax2);
set(ax2, 'XLim', [0, size(D,1)])
axis(ax2, 'square');
title('Corr pdist');
cbar2 = colorbar();
set(ax2, 'XLim', [0 size(D,2)]);
set(cbar2, 'Visible', 'off')
grid minor;
% Force a draw event to have the axes determine where the
labelconverter = #(x)sprintf('%.2g', x); % https://stackoverflow.com/a/35780915/54964
callback = #(varargin)set(ax2, 'xticklabels', arrayfun(labelconverter, get(ax2, 'xtick'), 'uniform', 0));
set(hFig, 'SizeChangedFcn', callback);
callback(); % necessary for the original small window and its scientific numbering
D_square=squareform(D, 'tomatrix');
ax4 = axes('OuterPosition', [0.51 0 0.5 0.5]);
imshow( D_square );
colormap('parula'); colorbar;
axis(ax4, 'square');
title('Square Corr pdist');
where the system is based on relative positions, rather than subplot as described in the answer here about Tight subplot with colorbars and subplot's 3rd parameter in Matlab?
Hypothetical methods
have master figure which has grid lines; embed those two figures there as parent positions; not sure if possible
assign gridlines function to the function background
have a separate background image which has static gridlines
Function about Suever's script
function [ hFig ] = init_background_grid(thickness)
%% Background
hFig=figure;
backax = axes('Parent', hFig);
% Ensure that this is below other objects
uistack(backax, 'bottom');
% Span the whole figure
set(backax, 'Position', [0 0 1 1]);
grid(backax, 'on')
% Make it invisible except for the grid and
% ensure it isn't able to be interacted with
set(backax, 'HitTest', 'off', ...
'HandleVisibility', 'off', ...
'GridLineStyle', '-', ...
'Color', 'none', ...
'XColor', 'none', ...
'YColor', 'none')
% Determine grid spacing with x/y ticks
% Increase nLines for a finer grid
nLines = thickness; % 30 default
set(backax, 'XTick', linspace(0, 1, nLines), ...
'YTick', linspace(0, 1, nLines));
end
How can you have grid lines in the background i.e. in the spacing between figures?
I would probably just setup an axes that spans your entire figure, then turn on the grid lines, then set the color of the axes to 'none'. A full example is shown below.
fig = figure();
backax = axes('Parent', fig);
% Ensure that this is below other objects
uistack(backax, 'bottom');
% Span the whole figure
set(backax, 'Position', [0 0 1 1]);
grid(backax, 'on')
% Make it invisible except for the grid and
% ensure it isn't able to be interacted with
set(backax, 'HitTest', 'off', ...
'HandleVisibility', 'off', ...
'GridLineStyle', '-', ...
'Color', 'none', ...
'XColor', 'none', ...
'YColor', 'none')
% Determine grid spacing with x/y ticks
% Increase nLines for a finer grid
nLines = 20;
set(backax, 'XTick', linspace(0, 1, nLines), ...
'YTick', linspace(0, 1, nLines));
You can then add any plots, uicontrols, etc. on top of this and it should work just fine. It will also handle the case where you decide that you want a different figure color.
I get the following figure with a bar plot :
I would like to remove the XTick with red circles but keep Xtick for the middle of each group of bars (i.e 1024, 10240, 102400, 1024000, 10240000).
I generate this image with the Matlab script below :
x = load('performances.txt');
% Get Runtimes
for i = 1:6
time_seq(1:5,i) = x((i-1)*5+1:i*5,3);
time_gpu(1:5,i) = x((i-1)*5+1:i*5,4);
speedup(1:5,i) = time_seq(1:5,i)./time_gpu(1:5,i);
end
% X axis
sizeArray = [1024 10240 102400 1024000 10240000 102400000]
figure(1);
% Get Histogram
h = bar(log10(sizeArray),log10(speedup(1:5,:)')); % get histogram
% Log10 for x-axis and xtick
set(gca,'Xtick',log10(1024):1:log10(1.024*10^8))
set(gca,'Xticklabel',10.^get(gca,'Xtick'));
set(h(1),'facecolor',[0.5 0.5 1]);
set(h(2),'facecolor',[1 0.5 0.5]);
set(h(3),'facecolor',[0.5 1 0.5]);
set(h(4),'facecolor',[0.5 0.5 0.5]);
set(h(5),'facecolor',[1 0.5 1]);
hPatch = findobj(h,'Type','patch');
set(hPatch,'facealpha',1);
grid on;
title('Benchmark GPU vs CPU');
% Size of WorkGroup
h = legend('N=16','N=32','N=64','N=128','N=256');
v = get(h,'title');
set(v,'string','WorkGroup size');
% Place legend
rect = [0.6,0.25,0.2,0.2];
set(h,'Position',rect,'color','w');
hPatch = findobj(h,'Type','patch');
set(hPatch,'facealpha',1);
xlabel('log(Array size)');
ylabel('log(Speedup)');
% Make right y-axis visible
ax1 = gca;
ax2 = axes('Position', get(ax1, 'Position'));
set(ax2, 'YAxisLocation', 'right', 'Color', 'none', 'XTickLabel', []);
set(ax2, 'YLim', get(ax1, 'YLim'));
I tried different things but couldn't make them disappear, anyone would have an idea or a clue ?
Thanks
It happens because of the last 3 lines in your code where you add the Y-axis from the right side. You need to add the following line at the end:
set(ax2,'XTick',[]);
Here is my result (with fake data):
Here is my code
clear all;clc
x = linspace(0, 10, 100);
axes('Position', [.075,.075,.9,.2], ...
'XColor', 'k', ...
'YColor', [0 0 0]);
fill(x, circshift(sin(x), 50), 'red', 'EdgeColor','None');
ylabel('Fancy Sine', 'FontSize', 11);
% Adding this the upper vanishes and the y axes is on left not right side
axes('Position', [.075,.075,.9,.2], ...
'XColor', 'k', ...
'YAxisLocation', 'Right', ...
'Color', 'none');
plot(x, x, 'Color', [.2 .4 .8]);
ylabel('Line Graph', 'FontSize', 11);
xlabel('X', 'FontSize', 11);
The single axis works fine
But when I want to add the second axis, the first disappears and the new axis is not on the right, but left side..
But both plots should be in one axis and the second y axis should be on the right side.
How to achieve this?
plot automatically sets the axis properties to the default. Use hold to stop this or specify the axis properties after your plot call.
An example of the former:
clear all;clc
x = linspace(0, 10, 100);
ax1 = axes('Position', [.075,.075,.9,.2], ...
'XColor', 'k', ...
'YColor', [0 0 0]);
p1 = fill(x, circshift(sin(x), 50), 'red', 'EdgeColor','None','Parent',ax1);
ylabel('Fancy Sine', 'FontSize', 11);
% Adding this the upper vanishes and the y axes is on left not right side
ax2 = axes('Position', [.075,.075,.9,.2], ...
'XColor', 'k', ...
'YAxisLocation', 'Right', ...
'Color', 'none');
hold on
p2 = plot(ax2,x, x, 'Color', [.2 .4 .8]);
hold off
ylabel('Line Graph', 'FontSize', 11);
xlabel('X', 'FontSize', 11);
Edit1: The reason you don't need to do this for your fill call is because it creates a patch object in your axes and does not invoke a plot command.
with help of the community in this thread: Minor grid with solid lines & grey-color
I got it to work to set minor grid lines as solid and coloured style. But when adding a second y-axes it just messes up the y-ticks on the right axis! heres the example code:
x = linspace(0, 10, 11);
y1 = x.^3+1;
y2 = x+1;
y3 = y1./y2+5;
% plotte: http://www.mathworks.com/help/techdoc/ref/linespec.html
myfig = figure('Position', [500 500 445 356]); %[left, bottom, width, height]:
ax1 = axes('Position',[0.13 0.18 0.75 0.75]);
hold on
p1 = plot(x,y1,'x--r');
p2 = plot(x,y2,'*-b');
xlim([0 max(x)]);
ylim([0 max([max(y1) max(y2)])]);
col=.85*[1 1 1];
%# create a second transparent axis, same position/extents, same ticks and labels
ax2 = axes('Position',get(ax1,'Position'), ...
'Color','none', 'Box','on', ...
'XTickLabel',get(ax1,'XTickLabel'), 'YTickLabel',get(ax1,'YTickLabel'), ...
'XTick',get(ax1,'XTick'), 'YTick',get(ax1,'YTick'), ...
'XLim',get(ax1,'XLim'), 'YLim',get(ax1,'YLim'));
%# show grid-lines of first axis, give them desired color, but hide text labels
set(ax1, 'XColor',col, 'YColor',col, ...
'XMinorGrid','on', 'YMinorGrid','on', ...
'MinorGridLineStyle','-', ...
'XTickLabel',[], 'YTickLabel',[]);
%# link the two axes to share the same limits on pan/zoom
linkaxes([ax1 ax2],'xy');
ax3 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','top',...
'YAxisLocation','right',...
'Color','none',...
'XTickLabel', [],...
'XColor','k','YColor','k');
%# link the two axes to share the same limits on pan/zoom
linkaxes([ax1 ax2 ax3], 'x');
ylabel(ax3, 'Speedup []');
ylim(ax3, [0 max(y3)]);
hold on
p3 = plot(x,y3,'s-.m','Parent',ax3);
hleg = legend([p1 p2 p3], {'CPU', 'GPU', 'Speedup'}, 'Location', 'NorthWest');
xlabel(ax2, 'N_{Funcs}');
ylabel(ax2, 't [s]');
set(hleg, 'FontAngle', 'italic')
and how it looks like:
Its simpler than you think: when you create the second axis ax2, set the 'Box' property to 'off' instead of 'on'.
Even more, you can simplify that part and create it as:
ax2 = copyobj(ax1,myfig);
delete( get(ax2,'Children') )
set(ax2, 'Color','none', 'Box','off')
The 2nd y-axis is "messed up" because the automatically generated YTick from y3 does not agree with the YTick from y1 and y2.
If this view is final (meaning you don't have to zoom in/zoom out or move the plot), you can manually define the YTick of ax3 to match those of ax1
ax3 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','top',...
'YAxisLocation','right',...
'Color','none',...
'XTickLabel', [],...
'YTick', [0:max(y3)/5:max(y3)], ... %% Define 6 YTick (including 0) like ax1
'XColor','k','YColor','k');