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.
Related
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]);
Data Plot
%% Data
% Imports the array data (x and y) to the workspace by loading Excel data
% that has been imported and converted to *.mat format.
load('900day_r') % y data.
load('x_degreesb'); % x axis data
%% Remove non linear trends
opol = 0;% Degree of filtering on original profile
[p,s,mu] = polyfit(x_degreesb,x900day_r,opol);
f_y = polyval(p,x_degreesb,[],mu);
x900day_r = x900day_r - f_y;
max_x = max(x900day_r);% Find maximum in array
x900day_r = x900day_r/max_x;% Normalize height to max
min_x = min(x900day_r);% Find minimum in array
x900day_r = x900day_r - min_x;% Shift profile (lowest value in array = 0)
%% Find Peaks & Valleys
[pks, locs] = findpeaks(x900day_r); % returns peaks & locations
x900day_r_Inv = max(x900day_r)-x900day_r; % invert y data
vlys = max(vlys)-vlys; % invert data for valley markers
%% Plot Profile
% Plot profile and markers for peaks
plot(x_degreesb,x900day_r,'b',x_degreesb(locs),pks+0.04,'v','markersize',5,'markerfacecolor','b','linewidth',1);
hold on
% Plot profile and markers for valleys
plot(x_degreesb(min_locs),vlys-0.04,'^','markersize',5,'markerfacecolor','b','linewidth',1);
% Plot characteristics
axis('tight') % Makes the graph fill the figure.
grid on % Turns the grid on (major not minor).
% Sets up the figure (fig) for display
fig = gca;
set(fig,'fontname','Bodoni 72','fontsize',20);
% Set y limits to auto. Set x limits and x tick marks
ylim('auto'); % Sets the y limits
xlim([0, 360]); % Sets the x limits from 0 to 360
set (fig, 'XTick', [0, 45, 90, 135, 180, 225, 270, 315, 360]) % Sets x axis tick marks
% Set fig for presentation appearance
x = xlabel('$Location On Cylinder Perimiter {[degrees]}$'); % x label.
y = ylabel('$Curve Height {[mm]}$'); % y label.
t = title('$900 Days Cylinder$ r'); % Title (presentation fraction).
% Set vertical lines at quadrant boundaries
hold on
x1 = 90;
x2 = 180;
x3 = 270;
x4 = 360;
y1 = get(gca, 'ylim');
plot ([x1 x1],y1,'k')%Caudal Medial(0:90)
plot ([x2 x2],y1,'k')%Cranial Medial(90:180)
plot ([x3 x3],y1,'k')%Cranial Lateral(180:270)
plot ([x4 x4],y1,'k')%Cadual Lateral(270:360)
hold on
% Interpretation of text characters for presentation
set(t,'Interpreter','Latex');
set(x,'Interpreter','Latex');
set(y,'Interpreter','Latex');
%% Isolate Cranial Medial & Lateral Section of Profile
x = x_degreesb;% Quadrant data
y = x900day_r;% Profile data
indx = (x >= 90) & (x <= 270);% Index section
[pks, locs, widths, proms] = findpeaks(y(indx));% Find peaks in section
Rmax = max(pks);% Find maximum peak
Rmin = min(y(indx));% Find minimum in section
CL = (Rmax + Rmin)/2;% Center line of sectioned profile
%% Plot Center Line
hold on
x1 = 90;
x2 = 270;
y1 = CL;
plot ([x1 x2],[y1 y1],'r','linewidth',1.5);
%% Plot Rmax
hold on
x1 = 90;
x2 = 270;
y1 = Rmax;
plot ([x1 x2],[y1 y1],'k','linewidth',1.5);
%% Plot Rmin
hold on
x1 = 90;
x2 = 270;
y1 = Rmin;
plot ([x1 x2],[y1 y1],'k','linewidth', 1.5);
%% Highlight Region of Interest
%subplot(2,1,2)
x = x_degreesb;% Quadrant data
y = x900day_r;% Profile data
indx = (x >= 90) & (x <= 270);% Index section
plot(x(indx),y(indx),'k','linewidth',2)% Plot 90:270 curve in black
level = CL;% set the centerline as the level for area shading
% Shade the area of the curve in the indexed section grey [.7 .7 .7] above the level CL
area(x(indx), max(y(indx), level),level, 'EdgeColor', 'none', 'FaceColor',[.7 .7 .7],'showbaseline', 'off');
% Shade the area of the curve in the indexed section dark grey below the level CL
area(x(indx), min(y(indx), level),level, 'EdgeColor', 'none', 'FaceColor',[.5 .5 .5],'showbaseline','off');
Does anyone know how I can find the area above (light grey) and below (dark grey) the centerline (red) for the specific range between 90:270 using MATLAB? I have been trying to use trapz, setting the level (red line in Data Plot picture) but can't seem to get trapz to calculate just the highlighted areas. I posted the code, but not the data, as its a rather large set of data that makes up the curve. Any help would be greatly appreciated!
RP
#Some Guy: Thanks for the quick responses. Here is an example script that you can run. You can change the ratio of blue area to grey area by changing the level value. In pic 1 with level set to 2 they should be equal. In pic 2 blue should be more than grey with level set to 1.6. Thats what I was trying to do. Any thoughts?
%% Example
x = 0:.01:4*pi;% x data
y = sin(x)+2;% y data
level = 1.6;% level
plot(x, y)
hold on
x_interest = 0:.01:x(length(y));
y_interest = sin(x_interest)+2;
xlim ([0 x(length(y))])
% Shaded area above level
area(x_interest, max(y_interest, level), level, ...
'EdgeColor', 'none', 'FaceColor', [.6 .7 .8], ...
'ShowBaseLine', 'off');
% Shaded area below level
area(x_interest, min(y_interest, level), level, ...
'EdgeColor', 'none', 'FaceColor', [.5 .5 .5], ...
'ShowBaseLine', 'off');
y_above = max(y_interest - level,0); % Take only the part of curve above y_split
y_below = max(-y_above,0); % Take the part below y_split
A_above = trapz(y_above)
A_below = trapz(y_below)
If I had data in a vector y and a scalar y_split at which I wanted to split I would do:
y_above = y - y_split;
y_below = max(-y_above,0); % Take the part below y_split
y_above = max(y_above,0); % Take the part above y_split
A_above = trapz(y_above);
A_below = trapz(y_below);
You can plot y_above and y_below to make sure you are integrating as you intend to.
EDIT: With OPs example script the areas with level = 2 is:
A_above =
399.9997
A_below =
399.9976
And level = 1.6 is
A_above =
683.5241
A_below =
181.1221
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.
I am using the following code for Pi approximation, using the rejection sampling method.
% DISPLAY A CIRCLE INSCRIBED IN A SQUARE
figure;
a = 0:.01:2*pi;
x = cos(a); y = sin(a);
hold on
plot(x,y,'k','Linewidth',2)
t = text(0.5, 0.05,'r');
l = line([0 1],[0 0],'Linewidth',2);
axis equal
box on
xlim([-1 1])
ylim([-1 1])
title('Unit Circle Inscribed in a Square')
pause;
rand('seed',12345)
randn('seed',12345)
delete(l); delete(t);
% DRAW SAMPLES FROM PROPOSAL DISTRIBUTION
samples = 2*rand(2,100000) - 1;
% REJECTION
reject = sum(samples.^2) > 1;
% DISPLAY REJECTION CRITERION
scatter(samples(1,~reject),samples(2,~reject),'b.')
scatter(samples(1,reject),samples(2,reject),'rx')
hold off
xlim([-1 1])
ylim([-1 1])
The expected result should be a blue circle inside of a red square. When I run the code the red point for building the square are displayed, but the blue point not.
The expected result should be as the picture found at this Link
But I get the following result:
Does anybody know what I can possibly do in order to visualize the blue points as well? Thanks in advance.
The scatter function is probably not the best choice for such huge number of points. Try this instead:
t = 0:.01:2*pi;
x = cos(t); y = sin(t);
samples = 2*rand(2,100000) - 1;
reject = sum(samples.^2) > 1;
props = {'LineStyle','none', 'Marker','.', 'MarkerSize',1};
line(x, y, 'Color','k', 'LineWidth',2)
line(samples(1,~reject), samples(2,~reject), props{:}, 'Color','b')
line(samples(1,reject), samples(2,reject), props{:}, 'Color','r')
axis equal; axis([-1 1 -1 1])
box on
How to plot something outside the axis with MATLAB? I had like to plot something similar to this figure;
Thank you.
Here is one possible trick by using two axes:
%# plot data as usual
x = randn(1000,1);
[count bin] = hist(x,50);
figure, bar(bin,count,'hist')
hAx1 = gca;
%# create a second axis as copy of first (without its content),
%# reduce its size, and set limits accordingly
hAx2 = copyobj(hAx1,gcf);
set(hAx2, 'Position',get(hAx1,'Position').*[1 1 1 0.9], ...
'XLimMode','manual', 'YLimMode','manual', ...
'YLim',get(hAx1,'YLim').*[1 0.9])
delete(get(hAx2,'Children'))
%# hide first axis, and adjust Z-order
axis(hAx1,'off')
uistack(hAx1,'top')
%# add title and labels
title(hAx2,'Title')
xlabel(hAx2, 'Frequency'), ylabel(hAx2, 'Mag')
and here is the plot before and after:
You can display one axis with the scale you want, then plot your data on another axis which is invisible and large enough to hold the data you need:
f = figure;
% some fake data
x = 0:20;
y = 23-x;
a_max = 20;
b_max = 23;
a_height = .7;
%% axes you'll see
a = axes('Position', [.1 .1 .8 a_height]);
xlim([0 20]);
ylim([0 20]);
%% axes you'll use
scale = b_max/a_max;
a2 = axes('Position', [.1 .1 .8 scale*a_height]);
p = plot(x, y);
xlim([0 20]);
ylim([0 b_max]);
set(a2, 'Color', 'none', 'Visible', 'off');
I had similar problem and I've solved it thanks to this answer. In case of bar series the code is as follows:
[a,b] = hist(randn(1000,1)); % generate random data and histogram
h = bar(b,a); % plot bar series
ylim([0 70]) % set limits
set(get(h,'children'),'clipping','off')% turn off clippings