Single Colorbar for Vertical Subplots - matlab

I would like to make the following MATLAB plot have a single colorbar that extends along both subplots.
Something like this (done manually with the figure editor):
Note: This is different from the question asked here.
Thanks!

I finally figured out a solution. The colorbar can be manually positioned in code but I wanted to keep everything the original spacing. My final solution is outlined below.
Step 1. Create the plot with a single colorbar on the bottom subplot.
figure('color', 'white', 'DefaultAxesFontSize', fontSize, 'pos', posVec)
ax(1) = subplot2(2,1,1);
pcolor(x2d, t2d, dataMat1)
shading interp
ylim([0 10])
xlim([-0.3 0.3])
xticklabels({})
set(gca, 'clim', [-20 0])
colormap(flipud(gray))
set(gca,'layer','top')
axis ij
ax(2) = subplot2(2,1,2);
pcolor(x2d, t2d, dataMat2);
xlabel('x')
ylabel('y')
shading interp
ylim([0 10])
xlim([-0.3 0.3])
set(gca, 'clim', [-20 0])
yticklabels({})
cbar = colorbar;
cbar.Label.String = 'Normalized Unit';
colormap(flipud(gray))
set(gca,'layer','top')
axis ij
Step 2. Save the position vectors of the two subplots and the colorbar.
pos1 = ax(1).Position; % Position vector = [x y width height]
pos2 = ax(2).Position;
pos3 = cbar.Position;
Step 3. Update the position of the colorbar to extend to the top of the top subplot.
cbar.Position = [pos3(1:3) (pos1(2)-pos3(2))+pos1(4)];
Step 4. Update the width of the top subplot to accommodate the colorbar.
ax(1).Position = [pos1(1) pos1(2) pos2(3) pos1(4)];
Step 5. Update the width of the bottom subplot to accommodate the colorbar.
ax(2).Position = pos2;
Wait, I thought the bottom subplot already accommodated the colorbar? Actually, when setting the position of the colorbar manually (step 3), the corresponding axis no longer scales accordingly. From the documentation:
If you specify the Position property, then MATLAB changes the Location property to 'manual'. The associated axes does not resize to accommodate the colorbar when the Location property is 'manual'.
The final result:

Related

Remove border around axes but keep the grid and ticklabels [duplicate]

Is there a way to remove only the axis lines in the Matlab figure, without affecting ticks and tick labels.
I know that box toggles the upper and right axes lines and ticks and that works perfectly for me.
But my problem is that I want eliminate the bottom and left lines (only lines!) but keeping the ticks and tick labels.
Any tricks?
Yair Altman's Undocumented Matlab demonstrates a cleaner way to do this using the undocumented axes rulers:
plot(x,y);
ax1 = gca;
yruler = ax1.YRuler;
yruler.Axle.Visible = 'off';
xruler = ax1.XRuler;
xruler.Axle.Visible = 'off'; %// note you can do different formatting too such as xruler.Axle.LineWidth = 1.5;
A nice feature of this approach is that you can separately format the x and y axis lines.
Solution for Matlab versions prior to R2014b
You can introduce a new white bounding box and put it on top.
// example data
x = linspace(-4,4,100);
y = 16 - x.^2;
plot(x,y); hold on
ax1 = gca;
set(ax1,'box','off') %// here you can basically decide whether you like ticks on
%// top and on the right side or not
%// new white bounding box on top
ax2 = axes('Position', get(ax1, 'Position'),'Color','none');
set(ax2,'XTick',[],'YTick',[],'XColor','w','YColor','w','box','on','layer','top')
%// you can plot more afterwards and it doesn't effect the white box.
plot(ax1,x,-y); hold on
ylim(ax1,[-30,30])
Important is to deactivate the ticks of the second axes, to keep the ticks of the f rist one.
In Luis Mendo's solution, the plotted lines are fixed and stay at their initial position if you change the axes properties afterwards. That won't happen here, they get adjusted to the new limits. Use the correct handle for every command and there won't be much problems.
Dan's solution is easier, but does not apply for Matlab versions before R2014b.
There is another undocumented way (applicable to MATLAB R2014b and later versions) of removing the lines by changing the 'LineStyle' of rulers to 'none'.
Example:
figure;
plot(1:4,'o-'); %Plotting some data
pause(0.1); %Just to make sure that the plot is made before the next step
hAxes = gca; %Axis handle
%Changing 'LineStyle' to 'none'
hAxes.XRuler.Axle.LineStyle = 'none';
hAxes.YRuler.Axle.LineStyle = 'none';
%Default 'LineStyle': 'solid', Other possibilities: 'dashed', 'dotted', 'dashdot'
This is different from Dan's answer which uses the 'visible' property of rulers.
You could "erase" the axis lines by plotting a white line over them:
plot(1:4,1:4) %// example plot
box off %// remove outer border
hold on
a = axis; %// get axis size
plot([a(1) a(2)],[a(3) a(3)],'w'); %// plot white line over x axis
plot([a(1) a(1)],[a(3) a(4)],'w'); %// plot white line over y axis
Result:
As noted by #SardarUsama, in recent Matlab versions you may need to adjust the line width to cover the axes:
plot(1:4,1:4) %// example plot
box off %// remove outer border
hold on
a = axis; %// get axis size
plot([a(1) a(2)],[a(3) a(3)],'w', 'linewidth', 1.5); %// plot white line over x axis.
%// Set width manually
plot([a(1) a(1)],[a(3) a(4)],'w', 'linewidth', 1.5);

How to prevent colorbar overlapping in the right y axis (matlab)

First, I am new in matlab.
I have a scattered graphic having two y axes.
I wanted to use a colorbar at the east side of the figure, however, the colorbar is overlapping on the right y axis and label.
FigHandle = figure('Position', [1, 1, 1200, 1200]);
h1 = scatter(x,y1,30,z);![enter image description here][1]
ax1 = gca;
grid on
hold(ax1, 'all');
ax2 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','top',...
'YAxisLocation','right',...
'Color','none',...
'XColor','k','YColor','k', 'fontsize',20);
hold(ax2, 'all');
h2 = scatter(x,y2,30,z,'Parent',ax2);
t = colorbar('peer',gca);
colorbar('location','eastoutside')
1) I tried to reduce the width of the plot screen (not figure) so that I may have some space for the colorbar but it didnot work.
2) I tried to increase the width of all figure screen, but the plot screen is also increased, so nothing changed.
I tried several position adjustment codes but I fail to figure out the concept.
In summary, I want to find out a way out to reduce the width of the plot screen, so that there is sufficent space for colorbar.
Many thanks in advance.
You can try to manually adjust the length of your X-axis with axis([XMIN XMAX YMIN YMAX]) or xlim([XMIN XMAX]), and expand XMAX until the overlap is gone.
Otherwise here is bit of code that will do the thing you want:
currentLimit=get(gca,'Xlim') %Get the X limit from your current (gca) axis
set(gca, 'XLim', [CurrentLimit(1),CurrentLimit(2)+0.1*CurrentLimit(2)]) %Set a new Xlimit for the current axis
Hope that works!

How can I combine multipe x-axis while using the same y-axis?

I am trying to plot the wake velocity deficient behind an object at different streamwise positions (pos.1, 2 and 3) behind the object.
A rough sketch of how the graph should look like is shown below. The x-axis represents velocity and the y-axis is the coordinate normal to the flow.
How can I restart the x-axis such that the data of each position is plotted in it's own space, resembling it's actual position in the flow.
Easiest solution I think is to create all plots you need in horizontally arranged subplots, and then "beautify" according to your level of perfectionism ^_^
The "beautifications" I did in this case are:
For the axes in each subplot, switch the 'box' option off
Set the ytick to [] and color the y-axes white, of every y-axis except the leftmost one
create another axes object in the background without any axes labels, so that it appears that the subplots are really one plot
Here's the code:
%// Some bogus data
y = 0:0.1:4*pi;
x1 = sin(y);
x2 = sin(3*y);
x3 = sin(2*y).*sin(5*y);
%// Initialize figure window
figure(1), clf, hold on
%// Plot each plot on its own axes
subplot(1,3,3), hold on
plot(x3,y)
set(gca,...
'ytick' , [],...
'ycolor', 'w',...
'box' , 'off');
subplot(1,3,2)
plot(x2,y)
set(gca,...
'ytick' , [],...
'ycolor', 'w',...
'box' , 'off')
subplot(1,3,1)
plot(x1,y)
set(gca,...
'box', 'off') %// NOTE: don't kill these axes
%// Background axes
P = axes('parent', 1, 'xtick', [], 'ytick', []);
uistack(P, 'down', 10)
You could consider plotting your data on a single x-axis with an offset and changing the label of the x-axis ticks.
Consider your x-vector to be x_pos1 for the first position, your second and third would be similar but with an addition of an offset. E.g. offset = 15; x_pos2 = x_pos1+offset;
You can obtain and change your x-axis tick label by:
get(gca, 'xticklabel')
set(gca, 'xticklabel', yourLabelHere)

Plotting a subplot on top of another plot in Matlab

I need to plot several plots along a sloped line at different positions.
For example, if I:
plot(0:200,'k');
plotpts = 5:5:200;
I would like to be able to plot a smaller plot at each of my plotpts on top of the original 0:200 line.
I know you can use hold on and plot over top that way, but I need to change my origin each time. Does anyone have any suggestions? I would really like to stay in matlab. Thanks!
Here is a flexible way I usually do it:
plot(1:10, 'k')
plotpts = 2:2:8;
mainbox = get(gca, 'Position');
xlims = get(gca, 'XLim');
ylims = get(gca, 'Ylim');
for i=1:length(plotpts)
originx = mainbox(1) + (plotpts(i) - xlims(1)) * (mainbox(3)) / (xlims(2) - xlims(1));
originy = mainbox(2) + (plotpts(i) - ylims(1)) * (mainbox(4)) / (ylims(2) - ylims(1));
axes('position', [originx originy 0.1 0.1], 'Color', 'none')
% Do some plotting here...
end
It's quite a bit of work, but you probably want to use the axes command. A figure window can host any number of axes, where each axes has it's own position, data, annotations, color etc.
The most difficult thing for the application you describe is that each axis position needs to be defined in the coordinate frame of the underlying figure, which means that some math may be required to create the illusion that the axis is correctly positioned within a parent axes/
For example, if you first create a simple plot
figure(1234); clf;
plot(1:10, rand(1,10),'.k-','linewidth',5);
xlim([1 10]);
ylim([0 1]);
set(gca,'color','y'); %This just helps demonstrate the next steps
You can place another axis directly on top of the first, and then
ha = axes('position',[.2 .3 .1 .1])
plot(linspace(0,2*pi,100), sin(linspace(0,2*pi,100)), 'b-')
xlim([0 2*pi])
You can adjust the the properties of the inset axis to suit your particular needs, for example
set(ha,'color','none'); %A transparent axis
set(ha,'xtick',[],'ytick',[]); %Remove tick labels
title(ha,'This is an inset plot')
Is the command subplot not what you're looking for?

Minor grid with solid lines & grey-color

I'm using the following to display the minor grid in my plot:
grid(gca,'minor')
set(gca,'MinorGridLineStyle','-')
but I'd like to change the color of the grid lines to a nice greyscale. I can't find any option 'grid color' in matlab... Do you know any or any workaround?
I found this: http://www.mathworks.com/matlabcentral/fileexchange/9815-gridcolor but as I read of the comments, it doesn't work very well and further it only changes gridcolor, not the color of the minor grid...
Thanks!
EDIT:
Problem with semilogx as posting here now:
x = [1e-9 1e-8 1e-7 1e-6 1e-5 1e-4 1e-3 1e-2]';
y1 = linspace(20, 90, 8);
y2 = y1.^2;
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]:
p1 = semilogx(x,y1,'x--r',x,y2,'*-b');
ax1 = gca;
set(ax1, 'Position',[0.13 0.18 0.75 0.75]);
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'),...
'XScale', 'log');
%# 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',[],'XScale', 'log');
%# link the two axes to share the same limits on pan/zoom
linkaxes([ax1 ax2],'xy');
Displaying like this:
EDIT2: A problem occurs when adding a second y-axes as in the following picture, look at the ticks of the right y-axes:
this will be discussed here to have a better overview!
Matlab: Problem with ticks when setting minor grid style and two y-axis
Set the 'XColor','YColor' axes properties. Note that these properties determine the color of the axis lines, tick marks, tick mark labels, and the axis grid lines, so AFAIK you can't assign those different colors than that of the entire axis..
Example:
plot(rand(10,1))
set(gca, 'XMinorGrid','on', 'YMinorGrid','on', 'XColor','r', 'YColor','g')
EDIT1:
You can always create a second transparent axis with the desired grid colors, but with no ticks or labels, stacked on top of the current axis. Here is an example:
%# create plot as usual
plot(rand(10,1))
hAx1 = gca;
%# create a second axis, same position/extents, no tick or labels, colored grid-lines
hAx2 = axes('Position',get(hAx1,'Position'), ...
'Color','none', 'TickLength',[1e-100 1e-100], ...
'XMinorGrid','on', 'YMinorGrid','on', ...
'Box','off', 'XColor','g', 'YColor','r', ...
'XTickLabel',[], 'YTickLabel',[], ...
'XTick',get(hAx1,'XTick'), 'YTick',get(hAx1,'YTick'), ...
'XLim',get(hAx1,'XLim'), 'YLim',get(hAx1,'YLim'));
%# position it on top
%#uistack(hAx2,'top')
%# redraw the enclosing box in the original axis colors
x = get(hAx1,'XLim');
y = get(hAx1,'YLim');
line([x([1 2]) nan x([2 1])],[y([1 1]) nan y([2 2])],'Color',get(hAx1,'XColor'))
line([x([1 1]) nan x([2 2])],[y([1 2]) nan y([2 1])],'Color',get(hAx1,'YColor'))
The only problem is that the grid lines are drawn on top of your plot, which might get in the way if the grid-lines are thick :)
EDIT2:
Seems like #yoda had a similar idea to the above. Here is a slightly improved version inspired by his solution:
%# create plot as usual
plot(11:20, rand(10,1)*5)
hAx1 = gca; %# get a handle to first axis
%# create a second transparent axis, same position/extents, same ticks and labels
hAx2 = axes('Position',get(hAx1,'Position'), ...
'Color','none', 'Box','on', ...
'XTickLabel',get(hAx1,'XTickLabel'), 'YTickLabel',get(hAx1,'YTickLabel'), ...
'XTick',get(hAx1,'XTick'), 'YTick',get(hAx1,'YTick'), ...
'XLim',get(hAx1,'XLim'), 'YLim',get(hAx1,'YLim'));
%# show grid-lines of first axis, give them desired color, but hide text labels
set(hAx1, 'XColor','g', 'YColor','r', ...
'XMinorGrid','on', 'YMinorGrid','on', ...
'XTickLabel',[], 'YTickLabel',[]);
%# link the two axes to share the same limits on pan/zoom
linkaxes([hAx1 hAx2],'xy');
%# lets create a legend, and some titles
legend(hAx1, 'text')
title('title'), xlabel('x'), ylabel('y')
EDIT3 (take 2):
Here is the same example but with a log-scale x-axis. Note how instead of creating a second axis and manually setting its properties to match the first, I simply copyobj the axis, and delete its children.
%# create a plot as usual (x-axis is in the log-scale)
semilogx(logspace(0,5,100), cumsum(rand(100,1)-0.5))
xlabel('x'), ylabel('y'), title('text')
legend('plot')
%# capture handle to current figure and axis
hFig = gcf;
hAx1 = gca;
%# create a second transparent axis, as a copy of the first
hAx2 = copyobj(hAx1,hFig);
delete( get(hAx2,'Children') )
set(hAx2, 'Color','none', 'Box','on', ...
'XGrid','off', 'YGrid','off')
%# show grid-lines of first axis, style them as desired,
%# but hide its tick marks and axis labels
set(hAx1, 'XColor',[0.9 0.9 0.9], 'YColor',[0.9 0.9 0.9], ...
'XMinorGrid','on', 'YMinorGrid','on', 'MinorGridLineStyle','-', ...
'XTickLabel',[], 'YTickLabel',[]);
xlabel(hAx1, ''), ylabel(hAx1, ''), title(hAx1, '')
%# link the two axes to share the same limits on pan/zoom
linkaxes([hAx1 hAx2], 'xy');
%# Note that `gca==hAx1` from this point on...
%# If you want to change the axis labels, explicitly use hAx2 as parameter.
You should get the correct plot in your example with this code. However I think the x variable values you choose might be too close in the current figure size to show all the vertical lines (simply maximize the figure to see what I mean)...
To get a better idea of what each axis contains, here is a divided view where the plot on the left contains only the graphics rendered by hAx1, while the plot on right contains only the hAx2 components. Those two views are basically overlayed on top of each other in the final figure shown before.
Unfortunately, while the trick of over- or under-laying a second, gridded axes mostly works, Matlab does not render it properly when you save to a PDF file. This is because Matlab does not support transparency in PDFs.
One workaround is to simply use line to draw in the grid lines one by one:
for dir='XY';
ticks = get(gca, [dir 'Tick']);
lim = get(gca, [dir 'lim']);
for ii=1:length(ticks)
coord = ticks(ii);
for jj=1:9,
if jj==1 % major grid properties
color = [1 1 1]*0.9;
weight = 2;
else % minor grid properties
color = [1 1 1]*0.9;
weight = 1;
end
if jj*coord > lim(2)
continue
end
if dir=='X'
L = line((jj*coord)*[1 1], get(gca, 'ylim'), ...
'color', color, 'linewidth', weight);
else
L = line(get(gca, 'xlim'), (jj*coord)*[1 1], ...
'color', color, 'linewidth', weight);
end
uistack(L, 'bottom');
end
end
end
One downside of this approach is that it overwrites the tick marks and plot boundary box. A solution to this is to combine this approach with the trick of under-laying a second axes. Draw the fake grid on the underlying axes. This IS rendered properly in PDF:
While Amro is right that the minor grid's color is the same as that of the axis labels, you can always turn off the axis labels and overlay a second axes with transparent filling and set the labels on that in a different color. Here's a small example showing how:
plot(rand(10,1))
xTicks=get(gca,'xTick');
yTicks=get(gca,'ytick');
set(gca, 'XMinorGrid','on', 'YMinorGrid','on',...
'XColor','r', 'YColor','g','xticklabel',[],'yticklabel',[],...
'box','off')
h2=axes;
set(h2,'color','none','xtick',linspace(0,1,numel(xTicks)),'xticklabel',xTicks,...
'ytick',linspace(0,1,numel(yTicks)),'yticklabel',yTicks)
This lets you set independent colors for major and minor X and Y grid lines, without overwriting the outer box. Even better, subsequent legend() commands will pick up the plot lines, not the manually drawn grid lines.
The trick is to make copies of the axes, then reverse their order in the figure's drawing hierarchy. Each copy of the axes can then draw its own set of grid colors and styles.
This strategy is compatible with subplot() and print().
function gridcolor(majorX, majorY, minorX, minorY)
ax1 = gca; %# get a handle to first axis
%# create a second transparent axis, same position/extents, same ticks and labels
ax2 = copyobj(ax1,gcf);
ax3 = copyobj(ax1,gcf);
delete(get(ax2,'Children'));
delete(get(ax3,'Children'));
set(ax2, 'Color','none', 'Box','off','YTickLabel',[],'YTickLabel',[],...
'GridLineStyle', '-',...
'XGrid','on','YGrid','on',...
'XMinorGrid','off','YMinorGrid','off',...
'XColor',majorX,'YColor',majorY);
set(ax3,'Box','off','YTickLabel',[],'YTickLabel',[],...
'MinorGridLineStyle','-',...
'XGrid','off','YGrid','off',...
'XMinorGrid','on','YMinorGrid','on',...
'XColor',minorX,'YColor',minorY);
set(ax1, 'Color','none', 'Box','on')
handles = [ax3; ax2; ax1];
c = get(gcf,'Children');
for i=1:length(handles)
c = c(find(c ~= handles(i)));
end
set(gcf,'Children',[c; flipud(handles)]);
linkaxes([ax1 ax2 ax3]);
end
subplot(211);semilogx([1:4000]);gridcolor('r','g','c','b');
subplot(212);semilogx(([1:4000]).^-1);gridcolor('r','g','c','b');