Related
Here is a sample of a strange problem. I'd like to plot curves with multiple y axes and I use a fairly common method in MATLAB.
function plot_test()
clear;
savefile = 1;
scrsz = get(0,'ScreenSize');
figure('Position',[1 1 0.9 * scrsz(3) 0.9 * scrsz(4)]);
hold on;
box on;
x = 0:1:10;
h1 = plot(x, x.^2 , 'r', 'LineWidth', 2.5);
%Axis label
xlabel('XLabel', 'FontSize', 20, 'Interpreter', 'latex');
ylabel('YLabel', 'FontSize', 20, 'Interpreter', 'latex');
set(gca, 'FontSize', 20, 'LineWidth', 3);
ax1 = gca;
ax2 = axes('Position',get(ax1,'Position'),'XAxisLocation','top','YAxisLocation','right','Color','none','XColor','none','YColor','k');
linkaxes([ax1 ax2],'x');
hold on
box on;
h2 = plot(x, x, 'b', 'Parent', ax2, 'LineWidth', 2.5);
ylabel('Second YLabel', 'FontSize', 20, 'Interpreter', 'latex');
set(gca, 'FontSize', 20, 'LineWidth', 3);
hl=legend([h1 h2],{'First Line','Second Line'});
set(hl,'FontSize',15,'Location','Northwest', 'Orientation','Vertical')
%Save pdf
if savefile
% Backup previous settings
prePaperType = get(gcf,'PaperType');
prePaperUnits = get(gcf,'PaperUnits');
preUnits = get(gcf,'Units');
prePaperPosition = get(gcf,'PaperPosition');
prePaperSize = get(gcf,'PaperSize');
% Make changing paper type possible
set(gcf,'PaperType','<custom>');
% Set units to all be the same
set(gcf,'PaperUnits','inches');
set(gcf,'Units','inches');
% Save the pdf
print -dpdf Test.pdf;
% Restore the previous settings
set(gcf,'PaperType',prePaperType);
set(gcf,'PaperUnits',prePaperUnits);
set(gcf,'Units',preUnits);
set(gcf,'PaperPosition',prePaperPosition);
set(gcf,'PaperSize',prePaperSize);
end
The objective is to print a PDF of the figure and save it in the same folder as Test.pdf. This is accomplished but the axes are misaligned. On my Windows machine it looks horrible while on a Mac it looks almost okay (but if you look closely, the y-axes are indeed misaligned at the bottom).
This only happens when I use a second axis. Without that, all this runs perfectly. Any idea why?
Okay, so I found a way: The trick is to use plotyy. Sample code below
function plot_test2()
clear;
savefile = 1;
scrsz = get(0,'ScreenSize');
figure('Position',[1 1 0.9 * scrsz(3) 0.9 * scrsz(4)]);
hold on;
box on;
x=(0:1:10);
y1=x;
y2=x.^2;
[hAx, hLine1, hLine2] = plotyy(x,y1,x,y2);
%Axis label
xlabel(hAx(1),'XLabel', 'FontSize', 20, 'Interpreter', 'latex', 'Color', 'k');
ylabel(hAx(1),'YLabel', 'FontSize', 20, 'Interpreter', 'latex', 'Color', 'k');
ylabel(hAx(2),'Second YLabel', 'FontSize', 20, 'Interpreter', 'latex');
set(hAx,{'ycolor'},{'k';'k'})
set(hAx,{'FontSize'},{20;20}, {'LineWidth'}, {3;3})
set(hLine1,'LineWidth', 3)
set(hLine2,'LineWidth', 3)
set(hLine1,'Color', 'r')
set(hLine2,'Color', 'b')
hl=legend([hLine1 hLine2],{'First Line','Second Line'});
set(hl,'FontSize',15,'Location','Northwest', 'Orientation','Vertical')
%Save pdf
if savefile
% Backup previous settings
prePaperType = get(gcf,'PaperType');
prePaperUnits = get(gcf,'PaperUnits');
preUnits = get(gcf,'Units');
prePaperPosition = get(gcf,'PaperPosition');
prePaperSize = get(gcf,'PaperSize');
% Make changing paper type possible
set(gcf,'PaperType','<custom>');
% Set units to all be the same
set(gcf,'PaperUnits','inches');
set(gcf,'Units','inches');
% Save the pdf
print -dpdf Test.pdf;
% Restore the previous settings
set(gcf,'PaperType',prePaperType);
set(gcf,'PaperUnits',prePaperUnits);
set(gcf,'Units',preUnits);
set(gcf,'PaperPosition',prePaperPosition);
set(gcf,'PaperSize',prePaperSize);
end
I run into the problem where Matlab 2015b expands the labels of new Xticks when the x-axis gets bigger by using incomplete label, zeros, in the thread No Gap Next to Axis Label in Matlab?
The dynamic expansion of incomplete labels of xticks is not possible because there is always cases of insufficient space but only one symbol is needed to mark half between two values.
The situation is problematic with zeros because I have several calibration points and several systems where the extra zeros are errorprone.
I would like to have there another symbol.
Example code how to create those incomplete labels of xticks
labels = arrayfun(#(x)sprintf('%.2g', x), xticks, 'uniform', 0);
ax2 = axes('OuterPosition', [0.51 0.5 0.5 0.5]); % anything here
xticks = get(ax2, 'xtick'); % https://stackoverflow.com/a/35776785/54964
set(ax2, 'xticklabels', labels); % here the point!
Without those incomplete labels of xticks but broader labelling which is worser
labels = arrayfun(#(x)sprintf('%.2g', x), xticks, 'uniform', 0);
ax2 = axes('OuterPosition', [0.51 0.5 0.5 0.5]);
xticks = get(ax2, 'xtick'); % https://stackoverflow.com/a/35776785/54964
set(ax2, 'xtick', xticks, 'xticklabels', labels);
Output of Suever's answer
Beautiful Small window in the original size with scientific numbering because of callback(); at the end of the code following
Medium window
Code
hFig=figure;
data=randi(513,513);
D=mat2gray(pdist(data, 'correlation'));
ax2 = axes('OuterPosition', [0.51 0.5 0.5 0.5]);
plot(D, 'Parent', ax2);
axis(ax2, 'square');
title('Corr pdist');
cbar2 = colorbar();
set(ax2, 'XLim', [0 size(D,2)]);
set(cbar2, 'Visible', 'off')
grid minor;
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 small window
How can you have another symbol for the incomplete labels of xticks in Matlab?
As I said in the other question, if you want the labels to be updated automatically when you resize things, you'll want to do the following.
fig = figure;
% Set large xlimits to demonstrate the issue at hand
ax2 = axes('xlim', [0 1e9]);
% Force a draw event to have the axes determine where the
labelconverter = #(x)sprintf('%.2g', x);
callback = #(varargin)set(ax2, 'xticklabels', arrayfun(labelconverter, get(ax2, 'xtick'), 'uniform', 0));
set(fig, 'SizeChangedFcn', callback);
% Be sure to execute the callback to get new labels prior to figure resize.
callback();
As you change the size of your figure, the labels will be changed automatically and the positions will be updated.
Small Window
Medium Window
Large Window
Note: Test this code in isolation to verify that it works, then adapt the idea to your solution. It seems like you're ending up with a lot of complications because your namespace is polluted (for example your examples don't even run because labels isn't defined).
I am plotting two maps next to each other using subplot. However, now, the image is turning out like this:
Is there any way to make the map part of the image larger? I would like to plot the maps side by side, by in this image, the resolution is low and the size is small.
%% Graph one site at a time
nFrames = 6240; % Number of frames.
for k = 94:nFrames
h11 = subplot(1,2,1); % PM2.5
% Map of conterminous US
ax = figure(1);
set(ax, 'visible', 'off', 'units','normalized','outerposition',[0 0 1 1]);
ax = usamap('conus');
set(ax,'Position',get(h11,'Position'));
delete(h11);
states = shaperead('usastatelo', 'UseGeoCoords', true,...
'Selector',...
{#(name) ~any(strcmp(name,{'Alaska','Hawaii'})), 'Name'});
faceColors = makesymbolspec('Polygon',...
{'INDEX', [1 numel(states)], 'FaceColor', 'none'}); % NOTE - colors are random
geoshow(ax, states, 'DisplayType', 'polygon', ...
'SymbolSpec', faceColors)
framem off; gridm off; mlabel off; plabel off
hold on
% Plot data
scatterm(ax,str2double(Lat_PM25{k})', str2double(Lon_PM25{k})', 25, str2double(data_PM25{k})', 'filled');
% Colorbar
caxis([5 30]);
h = colorbar;
ylabel(h,'ug/m3');
% Title
title(['PM2.5 24-hr Concentration ', datestr(cell2mat(date_PM25(k)), 'mmm dd yyyy')]);
%%%%
h22 = subplot(1,2,2); % O3
% Map of conterminous US
ax2 = usamap('conus');
set(ax2,'Position',get(h22,'Position'));
delete(h22);
states = shaperead('usastatelo', 'UseGeoCoords', true,...
'Selector',...
{#(name) ~any(strcmp(name,{'Alaska','Hawaii'})), 'Name'});
faceColors = makesymbolspec('Polygon',...
{'INDEX', [1 numel(states)], 'FaceColor', 'none'}); % NOTE - colors are random
geoshow(ax2, states, 'DisplayType', 'polygon', ...
'SymbolSpec', faceColors)
framem off; gridm off; mlabel off; plabel off
hold on
% Plot data
scatterm(ax2,str2double(Lat_O3{k})', str2double(Lon_O3{k})', 25, str2double(data_O3{k})'*1000, 'filled');
hold on
% Colorbar
caxis([10 90]);
h = colorbar;
ylabel(h,'ppb');
% Title
title(['O3 MDA8 Concentration ', datestr(cell2mat(date_O3(k)), 'mmm dd yyyy')]); % Title changes every daytitle(str);
% Capture the frame
mov(k) = getframe(gcf); % Makes figure window pop up
% Save as jpg
eval(['print -djpeg map_US_' datestr(cell2mat(date_PM25(k)),'yyyy_mm_dd') '_PM25_24hr_O3_MDA8.jpg']);
clf
end
close(gcf)
To change the amount of space the data occupies in the figure, you can use this command:
set(gca,'Position',[0.1 .1 0.75 0.85])
You'll have to play with the numbers a bit, to get things look nice. Note that Matlab rescales everything when you resize the figure window, so the optimal numbers depend on the window size you want to use.
On the other hand, you want to make the map bigger in comparison to the colorbar. You cannot make it without changing your window size, because your maps are already as high as the color bars. I would suggest to:
Set caxis to the same range in both plots.
Remove the colorbar on the left one.
Increase the height of your figure window to make the maps occupy as much width as possible.
Put the two images nicelye side by side using the command above.
For more information, see Matlab Documentation on Axes Properties.
Example:
% Default dimenstions
figure
x = 1:.1:4;
y = x;
[X, Y] = meshgrid(x,y);
subplot(1,2,1)
h = pcolor(X, Y, sin(X).*cos(Y)*2);
set(h, 'EdgeAlpha', 0);
axis square
colorbar
subplot(1,2,2)
h = pcolor(X, Y, sin(Y).*cos(X));
set(h, 'EdgeAlpha', 0);
axis square
colorbar
% adjust dimensions
subplot(1,2,1)
set(gca, 'Position', [0.1 0.1 0.3 0.85])
subplot(1,2,2)
set(gca, 'Position', [0.55 0.1 0.3 0.85])
This blog post has many great examples of FileExchange scripts dealing with size of subplots.
subplot_tight works very well and makes the subplots larger. Instead of writing in subplot(1,2,1), use subplot_tight(1,2,1)
My problem was similar -> scaling subplots in a figure a bit more up. Important for me though, was to maintain the aspect ratio that I've set before.
Enhancing the answer from #texnic in order to not have to set the values manually, one might use the following:
scale = 1.1; % Subplot scale
subplot(1,2,1)
% Your plotting here ...
pos = get(gca, 'Position'); % Get positions of the subplot [left bottom width height]
set(gca, 'Position', [pos(1) pos(2) pos(3)*scale pos(4)*scale]); % Scale width and height
Understanding this, one can also easily implement a parametric move of the subplot.
Somehow, the title, xlabel, ylabel, ylim and xlim does not stay fixed in the script below, how do I fix this?
x = 0:0.01:1;
figure
p1 = subplot(2,1,1);
xlabel(p1, '$x$','Interpreter','LaTex', 'Fontsize', 16);
ylabel(p1, '$\sin(x+t)$','Interpreter','LaTex', 'Fontsize', 16);
title(p1, 'Sine','Interpreter','LaTex', 'Fontsize', 20);
ylim(p1, [-1 2])
xlim(p1, [0 1])
p2 = subplot(2,1,2);
xlabel(p2, '$x$','Interpreter','LaTex', 'Fontsize', 16);
ylabel(p2, '$\cos(x+t)$','Interpreter','LaTex', 'Fontsize', 16);
title(p2, 'Cosine','Interpreter','LaTex', 'Fontsize', 20);
ylim(p2, [-2 1])
xlim(p2, [0 1])
for t = 0:0.1:2
plot(p1, x, sin(x+t))
plot(p2, x, cos(x+t))
pause(0.1)
end
By default, since you haven't got hold on or hold all, when you replot in the loop everything is reset. Since you only want to change one set of values in each graph, you can use set rather than plot here to get around the issue.
First, after each subplot is called, plot the initial graph and take a handle for it:
p1 = subplot(2,1,1);
h1 = plot(p1,x,sin(x);
Then continue on setting up the labels, etc, as you already do.
In the loop, to replace the data in your existing graph:
for t = 0.1:0.1:2
set(h1,'Ydata',sin(x+t))
set(h2,'Ydata',cos(x+t))
pause(0.1)
end
I want to plot something like this:
x = 0:0.01:10;
f = #(x) 50* 1.6.^(-x-5);
g = #(x) 50* 1.6.^(+x-10);
plot(x, f(x));
hold on
plot(x, g(x));
I can't manage to get axes similar to the ones in this figure:
I know I can remove the top and right lines like in this question, but I don't know how to get the arrows on the edges.
I don't need the additional annotations, but I would like to remove the ticks on the axes. I know how to do this when the axes are "normal", but I'm not sure if it must be done in another way when the axes are already manipulated.
Does anyone know how to do this?
Well, don't say I didn't warn you :)
% Some bogus functions
f = #(x) 50* 1.6.^(-x-5);
g = #(x) 50* 1.6.^(+x-10);
% Point where they meet
xE = 2.5;
yE = f(xE);
% Plot the bogus functions
figure(1), clf, hold on
x = 0:0.2:5;
plot(x,f(x),'r', x,g(x),'b', 'linewidth', 2)
% get rid of standard axes decorations
set(gca, 'Xtick', [], 'Ytick', [], 'box', 'off')
% Fix the axes sizes
axis([0 5 0 5])
% the equilibrium point
plot(xE, yE, 'k.', 'markersize', 20)
% the dashed lines
line([xE 0; xE xE], [0 yE; yE yE], 'linestyle', '--', 'color', 'k')
% the arrows
xO = 0.2;
yO = 0.1;
patch(...
[5-xO -yO; 5-xO +yO; 5.0 0.0], ...
[yO 5-xO; -yO 5-xO; 0 5], 'k', 'clipping', 'off')
% the squishy wiggly line pointing to the "equilibrium" text
h = #(x)0.5*(x+0.2) + 0.1*sin((x+0.2)*14);
x = 2.7:0.01:3.5;
plot(x, h(x), 'k', 'linewidth', 2)
% the static texts
text(xE-yO, -0.2, 'Q^*', 'fontweight', 'bold')
text(-2*yO, yE, 'P^*', 'fontweight', 'bold')
text(-2*yO, 4, 'Price', 'rotation', 90, 'fontsize', 14)
text( 4, -0.2, 'Quantity', 'fontsize', 14)
text( .5, 4.2, 'Demand', 'fontsize', 14, 'rotation', -55)
text( 4.0, 3.3, 'Supply', 'fontsize', 14, 'rotation', +55)
text( 3.6, 2.1, 'Equilibrium', 'fontsize', 14)
Result:
The symbolic math toolbox has provisions for making these arrows, but without that toolbox you are stuck with drawing the arrows yourself. The following code should be useful for this purpose:
% determine position of the axes
axp = get(gca,'Position');
% determine startpoint and endpoint for the arrows
xs=axp(1);
xe=axp(1)+axp(3)+0.04;
ys=axp(2);
ye=axp(2)+axp(4)+0.05;
% make the arrows
annotation('arrow', [xs xe],[ys ys]);
annotation('arrow', [xs xs],[ys ye]);
% remove old box and axes
box off
set(gca,'YTick',[])
set(gca,'XTick',[])
set(gca,'YColor',get(gca,'Color'))
set(gca,'XColor',get(gca,'Color'))
The only drawback is that for some figure window sizes you will have a 1-pixel white border below the arrows, and setting the LineWidth property of the axes to a ridiculous small value does not help.
But for printing, the small white border should not be relevant.