Axis labels are cut off when saving MATLAB figure - matlab

Consider the following MWE with produces a figure:
clear
close all
fig1 = figure(1);
set(gca,'xscale','log')
set(gca,'yscale','log')
xlabel('Frequency (Hz)')
ylabel('Amplitude (dB)')
set(gca,'FontUnits','points',...
'FontWeight','normal',...
'FontSize',10,...
'FontName','Times',...
'Units','normalized');
PaperW = 16;
PaperH = 7.5;
fig1.Units = 'centimeters';
fig1.Position = [20 10 PaperW PaperH];
fig1.PaperUnits = 'centimeters';
fig1.PaperPosition = [0 0 PaperW PaperH];
print(fig1,'fig1.png','-dpng','-r300')
I'm trying to save this as a .png file using print. Additionally, I want the saved image to be 16cm by 7.5cm. I specified this using PaperW and PaperH (the width and height).
The problem is, the bottom of the xlabel text is cut off. Why is this happening? And how can I solve this problem?
Zoomed in on the xlabel. Notice how the bottom of the q and y are cut off.

You can tinker around the position of the axis as follows,
% get axis position, move up the y co-ordinate by just little bit and offset the height by the same amount
pos = get(gca, 'Position');
set(gca, 'Position', [pos(1) pos(2)+0.05 pos(3) pos(4)-0.05]);

Related

How to make 2 circles rotate/spin like a wheel in Matlab

I've plotted two circles and filled them with the colormap 'jet'. However, every time I try to rotate the circles using rotate function or even the spin function of colormap to make the colour jet spin inside the circle - It changes the plot entirely - Rotating only 1 circle, filling up the screen, and rotating it at an angle.
Can someone please explain how I can rotate those 2 circles, as though they are wheels of a car?
The code is as follows: (I commented out my attempt at rotating and spin)
%First Circle
r1 = linspace(0,1,10);
theta1 = linspace(0, 2*pi, 100);
[rg, thg] = meshgrid(r1,theta1);
[x1,y1] = pol2cart(thg,rg);
circ1 = pcolor(x1,y1,thg);
colormap(jet);
ylim([-2 2]);
hold on
%Second Circle
r2 = linspace(0,1,10);
theta2 = linspace(0, 2*pi, 100);
[rg, thg] = meshgrid(r2,theta2);
[x2,y2] = pol2cart(thg,rg);
circ2 = pcolor(x2+2.5,y2,thg);
%colormap(jet);
%for ang=1:360
% rotate(circ2,[0 1 1],-1);
% drawnow;
%end
%spinmap(5,1); %Spins colorjet map
view ([0 90]);
shading interp;
axis equal;
grid off;
hold off
Change your plotting to:
for ang=1:360
cla; hold on
circ1 = pcolor(x1,y1,thg);
circ2 = pcolor(x2,y2,thg);
rotate(circ2,[0 0 1],-ang);
rotate(circ1,[0 0 1],-ang);
set(circ1,'XData',get(circ1,'Xdata')+2.5); %change circ1 position
view ([0 90]);
shading interp;
axis equal;
grid off;
hold off
drawnow;
end
The problem with rotate is that rotates the whole figure, so once one circle is rotating on place, if you apply rotate again the other one will rotate around the first one. To solve that, create both circles in the same place, rotate both, and then put one in a different position

area() plot covers plot axis

I am creating a graph in MATLAB and then shading the background of the graph to highlight regions. An example of this is as follows:
clc; clear all;
hFig = figure;
y = [0:0.1:2*pi];
x = sin(y);
plot(y,x);
hold on
h(1) = area([0 (2*pi)/2], [1 1],-1);
set(h(1),'FaceColor',[1.0 0.8 0.6],'EdgeColor',[1.0 0.8 0.6]);
h(2) = area([(2*pi)/2 2*pi], [1 1],-1);
set(h(2),'FaceColor',[1.0 0.5 0.5],'EdgeColor',[1.0 0.5 0.5]);
axis tight
set(gca,'children',flipud(get(gca,'children')));
%# centimeters units
X = 14.0; %# paper size
Y = 12.0; %# paper size
xMargin = 1; %# left/right margins from page borders
yMargin = 1; %# bottom/top margins from page borders
xSize = X - 2*xMargin; %# figure size on paper (widht & hieght)
ySize = Y - 2*yMargin; %# figure size on paper (widht & hieght)
set(hFig, 'PaperUnits','centimeters')
set(hFig, 'PaperSize',[X Y])
set(hFig, 'PaperPosition',[xMargin yMargin xSize ySize])
set(hFig, 'PaperOrientation','portrait')
print('example','-dpdf','-r0');
In MATLAB the plot looks like this:
But the generated pdf file looks as follows:
Is there a command to force the axis lines back on top of the shaded areas as it is in the MATLAB plot?
Thanks
When I run the script (R2012b) also the in the "figure" the axis are masked by the two areas (and in the ".pdf" as well).
It seem the problem is related to the plotting rather than the conversion to ".pdf".
In particular the problem seems due to a coupling effect of the defined areas size and "axis tight" setting.
So I've sligthly reduced the areas size, replaced "axis tight" with the explicit defintion of "xlim" and "ylim".
Also, I've increased the axis "linewidth".
clc; clear all;
hFig = figure;
y = [0:0.1:2*pi];
x = sin(y);
plot(y,x);
hold on
% Modified area extend
% h(1) = area([0 (2*pi)/2], [1 1],-1);
h(1) = area([0.02 (2*pi)/2], [.99 .99],-.995);
set(h(1),'FaceColor',[1.0 0.8 0.6],'EdgeColor',[1.0 0.8 0.6]);
% Modified area extend
% h(2) = area([(2*pi)/2 2*pi], [1 1],-1);
h(2) = area([(2*pi)/2 2*pi-.01], [.99 .99],-.995);
set(h(2),'FaceColor',[1.0 0.5 0.5],'EdgeColor',[1.0 0.5 0.5]);
% Replaced "axis tight with explicit "xlim" and "ylim"
% axis tight
set(gca,'xlim',[0 2*pi],'ylim',[-1 1])
% Increased axis "linewidth" (notr strictly necessary
set(gca,'linewidth',1)
set(gca,'children',flipud(get(gca,'children')));
%# centimeters units
X = 14.0; %# paper size
Y = 12.0; %# paper size
xMargin = 1; %# left/right margins from page borders
yMargin = 1; %# bottom/top margins from page borders
xSize = X - 2*xMargin; %# figure size on paper (widht & hieght)
ySize = Y - 2*yMargin; %# figure size on paper (widht & hieght)
set(hFig, 'PaperUnits','centimeters')
set(hFig, 'PaperSize',[X Y])
set(hFig, 'PaperPosition',[xMargin yMargin xSize ySize])
set(hFig, 'PaperOrientation','portrait')
print('example','-dpdf','-r0');
Hope this helps.
The fix was simple, just had to add
set(gca,'layer','top');
to force the axis ontop of the boxes.

Zoom region within a plot in Matlab

I'm using Matlab to produce figures, and I'm wondering if there is a way to plot a zoomed region in a figure of the overall data?
I have scatter data plotted over one week, with the x-axis in hours, and I want to zoom into the first 3 hours, and display them within the main figure with the x-axis label of minutes.
The plotting code I have so far is as follows:
allvalsx = marabint(:,2)
allvalsy = marabint(:,5)
subvalsx = marabint(1:7,2);
subvalsy = marabint(1:7,2);
%% Plots the scatter chart.
sizemarker = 135
handle = scatter(allvalsx, allvalsy, sizemarker, '.')
figure(1)
axes('Position',[.2 .2 .2 .2])
handle2 = scatter(subvalsx, subvalsy, '.r')
title(plotTitle)
xlabel('Time since treatment (hours)')
ylabel('Contact angle (deg)')
% Axis scales x1, x2, y1, y2
axis([0, marabint(length(marabint),2) + 10, 0, 120]);
% This adds a red horizontal line indicating the untreated angle of the
% sample.
untreatedLine = line('XData', [0 marabint(length(marabint),2) + 10], 'YData', [untreatedAngle untreatedAngle], 'LineStyle', '-', ...
'LineWidth', 1, 'Color','r');
% Adding a legend to the graph
legendInfo = horzcat('Untreated angle of ', untreatedString)
hleg1 = legend(untreatedLine, legendInfo);
% This encases the plot in a box
a = gca;
% set box property to off and remove background color
set(a,'box','off','color','none')
% create new, empty axes with box but without ticks
b = axes('Position',get(a,'Position'),'box','on','xtick',[],'ytick',[]);
% set original axes as active
axes(a)
% link axes in case of zooming
linkaxes([a b])
set(gcf,'PaperUnits','inches');
set(gcf,'PaperSize', [8.267 5.25]);
set(gcf,'PaperPosition',[0 0.2625 8.267 4.75]);
set(gcf,'PaperPositionMode','Manual');
set(handle,'Marker','.');
print(gcf, '-dpdf', '-r150', horzcat('markertest4.pdf'));
This produces the following
Can anyone help me out with this?
yeah, I think I know what you need. Try this:
zoomStart = 0;
zoomStop = 3;
set(gca, 'XLim', [zoomStart zoomStop])
Let me know if that doesn't do what you need, and I'll give you a different way.

Resize figure to Axes Position in Matlab

I have a figure with a bar plot in it, I have removed all ticks and titles, so now only the bars themselves are shown. I'd like to have the figure shrink to the size of the bar plot.
I've tried the following:
set(gca,'Units', 'Pixels');
set(gca,'XLim', [0.5 10.5],'YLim', [0 1],'Units', 'Pixels');
a=get(gca, 'Position');
set(gcf, 'Units', 'Pixels');
b=get(gcf,'Position');
set(gca, 'DataAspectRatioMode', 'manual', 'XLimMode', 'manual','YLimMode', 'manual')
set(gca, 'Position', [5,5,a(3),a(4)]);
set(gcf, 'Position', [10,10, a(3)+10,a(4)+10]);
This however doesn't work. after some investigations I found that the main problem is that the axes don't snap to the axis size.
Any way to solve this without calculating the size of every plot in the figure?
I want to decrease the blank areas around the plot below:
this is the figure after running my code, still a lot of space remains, this is because this is the size of the axes:
Thanks
edit: The problem stems from axes size as illustrated by the image below, upper picture is with DataAspectRatio set to [1 1 1] and lower picture without (automatic mode). note that the axes size doesn't change (noted by black squares)
*there is some change due to opening plot tools, which docks the figure.
Does it help?
f = figure;
% generate bar
y = [75.995,91.972,105.711,123.203,131.669,...
150.697,179.323,203.212,226.505,249.633,281.422];
bar(y);
% end of graph
axis tight;
allAx = findall(f,'type','axes');
pa = get(gca, 'Position');
pf = get(f, 'Position');
% change shape of the figure to match
% xsize(figure)/yszie(figure) = xsize(axis)/ysize(axis)
pf(4) = ((pf(3)-pf(1))*pa(4)+pa(2)*(pf(1)-pf(3))+pf(2)*pa(3)-pa(1)*pf(2))/(pa(3)-pa(1));
set(allAx, 'Units', 'Normalized', 'Position', [0, 0, 1, 1]);
set(f, 'Position', pf);

how to draw three graphics on the same figure?

That's how I draw two graphics (thanks for guys who helped me to do that):
clear
logsFolder = 'C:\logs\';
stocks = {'log'};
for stock = stocks
filename = [logsFolder stock{1} '.log'];
fLog = fopen(filename);
data = textscan(fLog, '%f:%f:%f:%f %f %f %f');
fclose(fLog);
% hh:min:sec:millisec
secvec = [60*60 60 1 1e-3];
x = [data{1:4}] * secvec';
y = data{5};
yPrice = data{6};
xindays = x / (24*60*60);
figure;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
set(AX(1),'xtick',[]);
lo1 = min(y);
hi1 = max(y);
lo2 = min(yPrice);
hi2 = max(yPrice);
if (hi2/lo2 > hi1/lo1)
ylim(AX(1),[lo1 hi2/lo2 * lo1]);
ylim(AX(2),[lo2 hi2]);
else
ylim(AX(1),[lo1 hi1]);
ylim(AX(2),[lo2 hi1/lo1 * lo2]);
end
ticklabelformat(AX(2),'y','%g')
ticklabelformat(AX(2),'x',{#tick2datestr,'x','HH:MM:SS'})
title(stock);
% iNeedToDrawThat = data{7}
end
Input file example is available here As you can see my file contains the last column which I also want to display. The range should be from 0 (at the bottom of figure) to the maximum value (at the up of the graph). So I need to draw three graphics somehow. It's ok to omit axis with labels for the third graph as I already have two axis and I have no place to add third one. However it's ok to "overlap" two axis if possible.
I have no idea how to do that so I'm looking for your help.
I've tried that but it doesn't work:
figure;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
hold on;
volume = data{7};
plot(xindays, volume);
hold off;
I have already mentioned a similar question in the comments, it should give you plenty of ideas...
Anyway, I've put together a solution to plot multiple y axes. Right now the code is a bit involved, but it should be possible to refactor a re-usable function out of it (like the addaxis function on the File Exchange).
The idea is to first plot each curve in a separate axis (all superimposed), and make them transparent (except the bottom one). Next we create copies of this set of axes and shift them along the x-direction. We also make those copies transparent, but now we can show the tick-marks along the y-axis of each. Finally we give them correct z-order, and link the x and y limits so that we can use the pan and zoom functionality.
%# read and parse data from file
fid = fopen('log.log','rt');
C = textscan(fid, '%s %f %f %f', 'CollectOutput',true);
fclose(fid);
dt = datenum(C{1}, 'HH:MM:SS:FFF');
data = C{2};
NUM = size(data,2);
%# create a wider figure
hFig = figure('Position',get(0,'DefaultFigurePosition').*[1 1 1.7 1]);
%# some properties
clr = lines(NUM);
bgClr = get(0,'DefaultFigureColor');
pos = get(0,'DefaultAxesPosition');
pp = 0.1; % shift in normalized units: pos(1)
%# create plot axes (make axis invisible)
hAx = zeros(NUM,1);
for i=1:NUM
hAx(i) = axes('Parent',hFig, 'Color','none', ...
'XColor',bgClr, 'YColor',bgClr, ...
'Units','normalized', 'Position',pos+[(NUM-1)*pp 0 -(NUM-1)*pp 0]);
line(dt, data(:,i), 'Color',clr(i,:), 'Parent',hAx(i))
end
axis(hAx, 'tight') %# tight x/y limits
%# create shifted copies of axes to show y-ticks
hAxx = zeros(size(hAx));
for i=1:NUM
hAxx(i) = copyobj(hAx(i), hFig);
delete(get(hAxx(i),'Children')); %# keep only axis
set(hAxx(i), 'YColor',clr(i,:), ...
'Units','normalized', 'Position',pos+[(NUM-i)*pp 0 -(NUM-i)*pp 0]);
ylabel(hAxx(i), sprintf('Axis %d',i))
end
xlabel(hAxx(1), 'datetime')
title(hAxx(1), 'Log')
datetick(hAxx(1), 'x', 'HH:MM', 'keeplimits')
%# set 1st axis copy as current axis
set(hFig, 'CurrentAxes',hAxx(1))
%# adjust ticks of axes
set(hAx(1), 'Color','w') %# give white bg to 1st axis
set(hAxx(1), 'XColor','k') %# show xticks of 1st axis copy
set(hAxx(2:end), 'XTick',[], 'XTickLabel',[])
set(hAx, 'XTick',[], 'XTickLabel',[], 'YTick',[], 'YTickLabel',[])
%# fix z-order
for i=3:-1:1, uistack(hAxx(i),'top'), end
uistack(hAx(1), 'bottom')
%# link x/y limits so that panning/zooming works
lh = cell(NUM+1,1);
for i=1:NUM
lh{i} = linkprop([hAxx(i);hAx(i)], 'YLim');
end
lh{end} = linkprop([hAxx;hAx], 'XLim');
The result:
The panning/zooming is a bit funny, you have to initiate them by starting to drag from the side (the shifted colored axes). This is because the first one (corresponding to the blue line) is the one on top, thus catches all mouse clicks.
Note: I see you are using a custom function ticklabelformat, which I haven't tested in combination with the above code. I will leave that part to you..
HTH
sample use of hold on
figure;
plot(x1,y1);
hold on
plot(x2,y2);
plot(x3,y3);
hold off
do "figure" and "hold on" only once outside the loop. then plot all the graphs you need
figure;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
hold on;
volume = data{7};
plot(xindays, volume);
hold off;
if you do it the way you suggested using hold on, i.e. use plotyy() first then the axes won't adjust so if you 3rd series is out of the range of your first set of axes then it won't appear. Try just flipping them and see if that produces a result?
volume = data{7};
plot(xindays, volume);
hold on;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
This way the axes should adjust
For example:
t = 1:10;
x = t*2;
y = t*-2;
z = x + 1000;
Now compare
plot(t,z, 'r')
hold on
plotyy(t,x, t,y)
to
plotyy(t,x, t,y)
hold on
plot(t,z, 'r')