I am trying to add a grey shaded area between two user-defined vertical lines. I need this gray shaded area to appear beneath my already plotted data. I have tried using the fill and area functions, but haven't been able to successfully create a bounded area to appear underneath the Matlab plot. I need the shaded area plot to extend from the x-axis at vertical lines created at 5.5 and 19 and extend up to the y-axis at 900 (left y-axis) and at 1 (right y-axis). See here: https://www.dropbox.com/s/qyzkuhw17yxn8p5/sample.png
I suppose the problem does not lie in generating the shaded area, but in making it appear below other elements of the plot even though it gets plotted later. You can achieve that by locating it "deeper", i.e. at a smaller z-value. Here is an example, building on the code by randomatlabuser:
x = linspace(0, 24, 100);
plot(x, 450 - 400 * cos(x / 12 * pi), 'k.-')
hold all
x = [5.5 5.5 19 19 5.5];
y = [0 900 900 0 0];
patch(x, y, -1 * ones(size(x)), [0.9 0.9 0.9], 'LineStyle', 'none')
patch is essentially the same as fill, but has a version that supports a third coordinate, the z-value.
From what I understand you want to do this:
h1 = plot((0:24), (0:700/24:700), '-b', 'LineWidth', 10); % some function
hold on
h2 = plot((0:24), 1.5 * (0:24) .^2, '-r', 'LineWidth', 10); % some other function
x = [5.5 5.5 19 19 5.5]; y = [0 900 900 0 0]; % define edges of area
h3 = fill(x, y, [0.9 0.9 0.9], 'LineStyle', 'none'); % fill area
set(gca, 'Children', [h1 h2 h3]) % h3 in the background, then h2 and finally h1 upfront
If not, you need to explain better what you are after.
% Add shaded area to plot
% Line 1
hl1 = line(x1,y1,'Color','b');
x = [5.5 5.5 19 19]; y = [0 900 900 0]; % define edges of shaded area
% Locations for 5:30am and 19:00pm with the left y-axis ranging from 0-900
hl2=fill([x(1) x(2) x(3) x(4)], [y(1) y(2) y(3) y(4)],'Color','r','EdgeColor','none','LineStyle','none');
hl1 = line(x1,y1,'Color','b'); % Replot line 1 over shaded area
hold on;
% Continue adding more shaded areas using the fill function or add lines directly...
Related
I followed the solution to the question "How to insert two X axis in a Matlab plot" to create a graph with two x-axes, one on top of the other.
I am now trying to create a vertical line between the two x-axes at specific x values. For example, let's say I have a figure like the one in the linked question. How would I draw a vertical line at the value x = 2 m/s between the two x-axes?
Here is an image of what I am looking for. The red line is what I am trying to draw in MATLAB. The two x-axes both have the same scale.
this is doable, but tricky. I used annotation but you need to map from the figure units to the axes units. here goes:
% experimental data
M(:,1) = [ 0, 1, 2, 3, 4, 5];
M(:,3) = [12, 10, 15, 12, 11, 13];
% get bounds
xmaxa = max(M(:,1))*3.6; % km/h
xmaxb = max(M(:,1)); % m/s
figure;
% axis for m/s
b=axes('Position',[.1 .1 .8 eps]);
set(b,'Units','normalized');
set(b,'Color','none');
% axis for km/h with stem-plot
a=axes('Position',[.1 .2 .8 .7]);
set(a,'Units','normalized');
stem(a,M(:,1).*3.6, M(:,3));
% set limits and labels
set(a,'xlim',[0 xmaxa]);
set(b,'xlim',[0 xmaxb]);
xlabel(a,'Speed (km/h)')
xlabel(b,'Speed (m/s)')
ylabel(a,'Samples');
title(a,'Double x-axis plot');
% this where the trick happens
pos = get(b, 'Position') ;
x_normalized = #(x0) (x0 - min(b.XLim))/diff(b.XLim) * pos(3) + pos(1);
xl = [x_normalized(2) x_normalized(2)]; % because you wanted x=2 m/s
yl = [0.1 0.2];
annotation('line',xl,yl,'Color',[1 0 0])
I have the following code, which plots a 'map' using imagesc, and provides a legend, see output attached.
I am trying to replace the lines in the legend with solid squares. My attamps to far leave the lines and ad hollow squares (including a random square in the top left corner of the figure)
figure(6)
imagesc(lut)
title('Ditribution of Land use Types')
ylabel('Longitude')
xlabel('Latitude')
caxis([0, 7])
myColorMap = jet(6);
imagesc(lut, 'AlphaData', ~isnan(lut))
colormap(myColorMap);
L = line(ones(6), ones(6));
set(L, {'Color'}, num2cell(myColorMap, 2))
legend(L, {'Forest','Shrubland','Savanna','Grassland','Agricultural','Barron'})
set(L(:),'Marker','s')
grid on
ax = gca
ax.GridAlpha = .2
ax.XTick = [5 10 15 20 25 30 35 40];
ax.YTick = [5 10 15 20 25 30];
ax.XTickLabel = {'118^{o}E','123^{o}E','128^{o}E', '133^{o}E', '138^{o}E', '143^{o}E','148^{o}E', '153^{o}E'};
ax.YTickLabel = {'13^{o}S','18^{o}S','23^{o}S','28^{o}S','33^{o}S','38^{o}S'};
ax.TickLength =[0.0 0.0]
Use nan to create invisible data (thanks #matlatbgui), and set L with all needed properties for no line and filled square markers:
% some arbitrary data:
N = 30;
lut = diag(1:N)*ones(N)+(diag(1:N)*ones(N)).';
% coloring settings:
caxis([0, 7])
myColorMap = jet(6);
% plotting:
imagesc(lut, 'AlphaData', ~isnan(lut))
colormap(myColorMap);
% Setting the legend:
L = line(nan(6), nan(6),'LineStyle','none'); % 'nan' creates 'invisible' data
set(L, {'MarkerEdgeColor'}, num2cell(myColorMap, 2),...
{'MarkerFaceColor'},num2cell(myColorMap, 2),... % setting the markers to filled squares
'Marker','s');
legend(L, {'Forest','Shrubland','Savanna','Grassland','Agricultural','Barron'})
and you don't need your line:
set(L(:),'Marker','s')
The square on the upper-left corner is obviously due to set(L(:),'Marker','s') which draws a square at the start and end points of the lines, at [1, 1]. Instead of changing the 'Marker', if you increase the 'LineWidth', you get much better results with:
L = line(ones(6), ones(6));
legend(L, {'Forest','Shrubland','Savanna','Grassland','Agricultural','Barron'})
set(L(:), 'LineWidth', 10)
With this output:
So if you are not restricted to make squares, I believe wide rectangles are better flags for color.
The legend of this boxplot comes with the same color! How can I fix this? How can I move the x-axis lable a little bit lower ?Thanks for your help.
close all
clc;clear;
f=figure;
Temp_O=[-0.234115422389688;-0.153751688636750;3.03158128172032;-0.746185319551222;0.491616009046725;1.17490826218458;0.495331079652895;0.757394580248284;1.28467417069223;0.710444835069366;-0.979521722186138;-0.216850422633648;0.0596632891728577;-0.525362330358090;0.681608181821661;-0.995216710339821;-0.706416688978551;-0.147700048468633;-0.145946504735073;0.355209739265580;1.25860455564176;0.970569089382961;3.99404165520844;0.433235373567272;1.37023527554759;1.45032207715449;2.00968917969203;0.840884198707613;2.08558564237223;2.05435556980046;-15.5517060656394;3.18991806590028;1.28277879106186;2.15931490153483;3.19647581545030;2.97877640768595;0.0857405478541730;-1.59362648933500;-2.18109410889313;0.751077088333943;0.795072796032814;4.18896005388773;-0.591461781602054;-0.229818549439720];
position_O = 5:5:25;
position_O=position_O';
g = [ones(10,1); 2*ones(10,1); 3*ones(10,1) ;4*ones(10,1);5*ones(4,1)];
box_O = boxplot(Temp_O,g,'colors','b','positions',position_O,'width',0.8);
h=findobj(gca,'tag','Outliers');
delete(h)
set(gca,'XTickLabel',{' '})
hold on
Temp_S=[-0.234069549668875;-0.0803021151079149;0.166729084507040;-0.991371043478263;0.320651878289472;0.118699258741257;-0.190944834558825;0.540367970198674;1.02556298920863;0.112849364285713;-0.395341229166667;0.382362326388889;-1.40591456976744;0.247202120000001;-1.33262568333333;-1.27793610544218;0.0400995141843974;-1.32333150653595;-1.84221947163121;0.407607340136054;0.264276120300749;-0.337747273809525;1.03841878571429;-1.41048786507936;0.901727821428570;-1.03012908482143;2.69786876785714;-0.691010535714286;1.66913088345865;0.684260974489794;-10.3923539047619;1.04994314285714;2.13557031632653;3.87736348701299;7.38705700000000;0.0451628482142860;-3.69094742857143;-1.14071104081633;-3.15830153968254;-4.41399970408163;6.09908001655629;0.0267684861111112;-2.67854298170732;0.925146217948717;];
position_S = 6.8:5:26.8;
position_S=position_S';
box_S = boxplot(Temp_S,g,'colors','r','positions',position_S,'width',0.8);
h=findobj(gca,'tag','Outliers');
delete(h)
legend(findobj(gca,'Tag','Box'),'Group1','Group2')
set(gca,'XTickLabel',{' '}) ;
hold off
text('Position',[5,-11],'String','S')
text('Position',[10,-11],'String','M')
text('Position',[15,-11],'String','L')
text('Position',[20,-11],'String','V')
text('Position',[25,-11],'String','C')
xlabel('Types','FontSize',10);
% set(get(gca, 'XLabel'), 'Position', [0 .2 0]); %
ylim([-10.5 7.8]);
The issue is that you're only displaying the legend for the first two boxes (yours has a total of 10 boxes) and both of these are red. The first 5 boxes that are found are red and the last 5 are blue. Instead you could use the first and last box.
%// Create the box plot
box_S = boxplot(Temp_S, g, 'colors', 'r', 'positions', position_S, 'width', 0.8);
%// Get all of the box plot objects
boxes = findobj(gca, 'Tag', 'Box');
legend(boxes([end 1]), 'Group1', 'Group2')
You could do this more robustly though with the following:
boxes = findobj(gca, 'Tag', 'box');
%// Sort by xposition
[~, ind] = sort(cellfun(#mean, get(boxes, 'XData')));
%// Apply legends to one red and one blue one.
legend(boxes(ind(1:2)), 'Group1', 'Group2');
And to move the xlabel a little lower, you can simply adjust it's Position property.
yrange = diff(get(gca, 'YLim'));
XL = get(gca, 'XLabel');
original = get(XL, 'Position');
%// Add an extra 1% padding
set(XL, 'Position', original - [0 0.01*yrange 0])
Here is a small example (I only kept the necessary stuff):
x1 = randn(44,1);
x2 = randn(44,1);
pos1 = (5:5:25)';
pos2 = (6.8:5:26.8)';
g = repelem([1 2 3 4 5], [10 10 10 10 4]);
h1 = boxplot(x1, g, 'Colors','b', 'Positions',pos1, 'Width',0.8);
hold on
h2 = boxplot(x2, g, 'Colors','r', 'Positions',pos2, 'Width',0.8);
hold off
legend([h1(5,1),h2(5,1)], {'Group1','Group2'})
To quote help boxplot:
% H = BOXPLOT(...) returns the handle H to the lines in the box plot.
% H has one column per box, consisting of the handles for the various
% parts of the box. For the traditional plotstyle, the rows correspond
% to: upper whisker, lower whisker, upper adjacent value, lower adjacent
% value, box, median, and outliers. For the compact plotstyle, the rows
% correspond to: whiskers, box, median outer, median inner, and outliers.
% If median comparison intervals are indicated with markers, H will have
% two more rows for notch lo and notch hi. If medianstyle or boxstyle
% have been set explicitly, the meaning of the rows will adjust
% accordingly.
I was trying to produce the following figure:
as similar as possible. I was having difficulties because I wasn't sure how to plot the unit circle. How does one do that? I tried using the polar function but I couldn't then make it also plot the blue crosses and red crosses. Anyone has an idea?
Edited answer
Here is a part of the code:
% --- Plot everything on the same axes
hold on
% --- Plot the unit circle:
theta = linspace(0, 2*pi, 360);
plot(cos(theta), sin(theta), 'k--');
% --- Plot the blue points
x = [0.2 0.4 0.4 0.8];
y = [0.4 0.2 0.8 0.4];
scatter(x, y, 'bs');
% --- Plot the red points:
x = [0.4 0.8];
y = [0.4 0.8];
scatter(x, y, 'ro');
There are still many modifications to do to get the final plots, but at least this is a starting point.
Second edit
To answer your question about the intersection of a line and a circle, you have to start with the maths behind. Line and circle are defined by the following equations:
y = a.x + b % Cartesian definition of a line
(x-x0)² + (y-y0)² = r² % Cartesian definition of a circle
If you combine the two, you realize that finding the intersection is similar to finding the solution of:
(a²+1).x² + 2(a(b-y0)-x0).x + x0²+(b-y0)²-r² = 0
i.e. the roots of a polynom. As this is a trinom, there are 3 possibilities: 0 solution (no intersection), 1 solution (line is tangent to the circle) and 2 solutions (line crossing the circle).
So, in practice you have to:
Get the parameters a, b, x0, y0 and r of your problem
Find the roots of the polynom (for instance, with the function roots)
Decide what to do based on the number of roots.
Hope this helps,
%% Construct polar grid (put inside another function)
range = 0.2:0.2:1;
n = 50;
for i=1:length(range)
ro = ones(1,n);
ro = ro.*range(i);
th = linspace(0,pi*2,n);
[xx,yy] = pol2cart(th,ro);
plot(xx,yy, 'color',[.9 .9 .9]), grid on, hold on
n = round(n * 1.5);
end
%% Plot like normal
x1 = [.2 .4 .4 .8];
y1 = [.4 .2 .8 .4];
x2 = [.4 .8];
y2 = [.4 .8];
plot(x1,y1, 'bx',...
x2,y2, 'ro');
xlim([-.05 1]);
ylim([-.05 1]);
I am trying to use either the contourf or colormap functions to plot filled ellipses with colors according to their arcsin(b/a) value (a=major axis, b=minor axis).
clearvars -except data colheaders
close all
clc
data(:,9)=data(:,9)*pi/180; % Convers Column 9 (angle of rotation) in rad
data(:,6)=1196-data(:,6); % Reset the Y coordinate axis to bottom left
theta = 0 : 0.01 : 2*pi; % Converts phi in rad
imax=29;
% Define colors
cvalues=asin(data(1:imax,8)./data(1:imax,7))./asin(1);
cm = colormap; % returns the current color map
% Sort and get their index to access the color array
[~,idx] = sort(cvalues);
% Create colormap
%ColorMap=jet;
for i=1:imax
x = data(i,7)/2 * cos(theta) * cos(data(i,9)) - data(i,8)/2 * sin(theta) * sin(data(i,9)) + data(i,5);
y = data(i,8)/2 * sin(theta) * cos(data(i,9)) + data(i,7)/2 * cos(theta) * sin(data(i,9)) + data(i,6);
colorID = max(1, sum(cvalues(i) > [0:1/length(cm(:,1)):1]));
ColorMap(i,:) = cm(colorID, :); % returns your color
hold on
% Columns (5,6) are the centre (x,y) of the ellipse
% Columns (7,8) are the major and minor axes (a,b)
% Column 9 is the rotation angle with the x axis
%% TRYING A FASTER WAY OF PLOTTING
%A(:,i)=x';
%B(:,i)=y';
%%
fill(x,y,ColorMap(i,:),'EdgeColor', 'None')
text(data(i,5),data(i,6),[num2str(asin(1)*180*cvalues(i)/pi)]) % Assigns number to each ellipse
end
%%
%fill(A,B,ColorMap(1:200,3)','EdgeColor', 'None')
%%
% Adds colorbar to plot
colorbar('SouthOutside')
caxis([0 90])
axis equal;
%xlim([0 7649]);
%ylim([0 15927]);
grid on;
I get a picture that looks like this which I think works well:
Instead of adding numbers in the ellipses, I have added the angle I obtained (90 for circles, 0 for very long ellipse). Now is my real experiment i will have to plot several thousands ellipses, and we found out that it takes quite alot of time to plot them, you'll see we tried another method to basically record the data and plot all in one go. But we haven't succeeded so far if you have any advice :)
Here is a way using built-in colormaps in Matlab (look here for a complete list).
The trick is to create a n x 3 array where n is the number of colors you wish to represent. Here it's the number of ellipses.
You can create a colormap like so:
MyColorMap = jet(n)); %// jet or anything listed in the link above. You can also create your own colormap.
So that's what we're going to do in the following code. In order to get the order right, we need to sort the values of asin(b/a) and fetch each index for the right ellipse. The code is commented so it's quite easy to follow. I added 4 ellipses in the plot to see the difference in color better:
clear
clc
close all
%// Define dummy data
data = zeros(8,9);
data(:,5) = [3;5;12;8;2;7;4;6]; % Centre location X
data(:,6) = [1; -5 ;-2; 4;2;-3;9;5]; % Centre location Y
data(:,7) = [6 ;7;8;6;1;4;2;5]; % Major Axis a
data(:,8) = [2;5;4;2;2;5;3;7]; % Minor axis b
data(:,9) = [10;40;45;90;35;70;85;110]; % Angle of rotation phi
data(:,9)=data(:,9)*pi/180; % Converts phi in rads
theta = 0 : 0.01 : 2*pi;
%// Define colors here
cvalues = asin(data(:,8)./data(:,7));
%// Sort and get their index to access the color array
[~,idx] = sort(cvalues);
%// Create colormap with the "jet" colors
ColorMap = jet(numel(cvalues));
This is the array containing the "colors". It looks like this:
ColorMap =
0 0 1
0 0.5 1
0 1 1
0.5 1 0.5
1 1 0
1 0.5 0
1 0 0
0.5 0 0
So each row represents a combination of red, blue and green (RGB) and there are as many rows as there are ellipses to plot. Now filling the ellipses:
hold all
for i=1:numel(idx)
k = idx(i);
x = data(k,8)/2 * cos(theta) * cos(data(k,9)) - data(k,7)/2 * sin(theta) * sin(data(k,9)) + data(k,5);
y = data(k,7)/2 * sin(theta) * cos(data(k,9)) + data(k,8)/2 * cos(theta) * sin(data(k,9)) + data(k,6);
fill(x,y,ColorMap(i,:))
plot(x, y, 'LineWidth', 1);
% Label each ellipse with a number
text(data(i,5),data(i,6),num2str(i),'Color','k','FontSize',12)
end
axis equal;
grid on;
Output with the jet colormap: blue is the first ellipse plotted and red is the last. You can add a colorbar if you want (add colorbar)
Using another colormap, the bone colormap, gives the following:
Hope that helps!