MATLAB fill area between lines - matlab

I'm trying to do something similar to what's outlined in this post:
MATLAB, Filling in the area between two sets of data, lines in one figure
but running into a roadblock. I'm trying to shade the area of a graph that represents the mean +/- standard deviation. The variable definitions are a bit complicated but it boils down to this code, and when plotted without shading, I get the screenshot below:
x = linspace(0, 100, 101)';
mean = torqueRnormMean(:,1);
meanPlusSTD = torqueRnormMean(:,1) + torqueRnormStd(:,1);
meanMinusSTD = torqueRnormMean(:,1) - torqueRnormStd(:,1);
plot(x, mean, 'k', 'LineWidth', 2)
plot(x, meanPlusSTD, 'k--')
plot(x, meanMinusSTD, 'k--')
But when I try to implement shading just on the lower half of the graph (between mean and meanMinusSTD) by adding the code below, I get a plot that looks like this:
fill( [x fliplr(x)], [mean fliplr(meanMinusSTD)], 'y', 'LineStyle','--');
It's obviously not shading the correct area of the graph, and new near-horizontal lines are being created close to 0 that are messing with the shading.
Any thoughts? I'm stumped.

You may be getting a problem with using mean as a variable, since it's also a reserved MATLAB command. Try clearing the variable space and then using a unique variable name.
As for the second problem, you want
fill( [x fliplr(x)], [meanUniqueName fliplr(meanMinusSTD)], 'y', 'LineStyle','--');
You also don't need to do this in two steps, but can do it all at once. A code snippet from a script I'm currently working on does the exact same thing and contains the lines:
avar = allan(DATA, tau);
xFill = [avar.tau1 fliplr(avar.tau1)];
yFill = [avar.sig2+avar.sig2err fliplr(avar.sig2-avar.sig2err)];
figure(2);
fill(xFill,yFill,'y','LineStyle','--')
line(avar.tau1,avar.sig2);
So I fill the area between the two error lines, and then draw the data line on top.

It turned out to be a column vs row vector issue. For some reason using the fill method above with flipud with the original column vectors doesn't work, but transposing the original variables then using fliplr does. Go figure. Here's the code in case it helps someone else:
x = linspace(0,100, 101);
mean = torqueRnormMean(:,DOF)';
meanPlusSTD = torqueRnormMean(:,DOF)' + torqueRnormStd(:,DOF)';
meanMinusSTD = torqueRnormMean(:,DOF)' - torqueRnormStd(:,DOF)';
fill( [x fliplr(x)], [meanPlusSTD fliplr(meanMinusSTD)], 'k');
alpha(.25);
plot(x, mean, 'k', 'LineWidth', 2)
plot(x, meanPlusSTD, 'k')
plot(x, meanMinusSTD, 'k')
Note that I removed the dotted line and just used thin vs. thick lines to denote standard deviation and mean. I did this because the line style was inconsistent. This code is in a loop where DOF runs from 1:9, and in some of the subplots both std curves would be dashed and in some just the top or bottom. It didn't matter enough to me to have them dashed so I kept it simple. Now this is an example of the graph I get:

One thing that you appear to be doing wrong is that you're applying fliplr to column vectors. That will have no effect. The example you cited uses row vectors. You also concatenate them into a matrix instead of into a single vector like the example. I think that the equivalent with column vectors would be:
fill( [x;flipud(x)], [mean;flipud(meanMinusSTD)], 'y');

Another possibility:
x = 1:1000; % example x values
y_upper = 5+sin(2*pi/200*x); % example upper curve
y_lower = 2+sin(2*pi/230*x); % example lower curve
bar(x, y_upper, 1, 'b', 'edgecolor', 'b');
hold on
bar(x, y_lower, 1, 'w', 'edgecolor', 'w');
axis([0 1000 0 7])
It uses bar (with unit width and same-color edges) to fill the upper curve, and then a second bar to "remove" (plot in white) the lower part.

Related

Colormap and colorbar for 3d trajectory. (Matlab) [duplicate]

This question already has answers here:
Change color of 2D plot line depending on 3rd value
(5 answers)
Closed 6 months ago.
I'm looking to do something similar to the below image (source) in Matlab. Ignore the vectors and the shaded cone; I just want to
plot a trajectory on the unit sphere, given by a function m(x) (whose values are points on the sphere),
color it according to parameter x (running from -inf to +inf),
display a color bar which explains the mapping from x-value to color.
I can plot the sphere easily with the help of built-in functions sphere and mesh, and I can draw the trajectory with plot3. To generate the x-values I can use something like
x = tan((-1:0.01:1)*pi/2);
which gives a distribution of points fitting for the types of functions m(x) will be (most of the action will be around x = 0).
The tricky part is the color. I have looked at the colormap and colorbar built-ins, but both seem to pertain to meshes and surfaces rather than curves, so I don't see an obvious way to adapt it to my use case.
Does anyone have any ideas for how I might proceed?
When using plot it is not possible for one line to be multicoloured. In order to make one line multicoloured, you must plot each individual segment and then colour them individually. For example:
% make some dummy data
% note that this is in the form of 1 x N row vectors
t = -.99:0.01:0.99;
x = cos(t * pi/2);
y = sin(t * pi/2);
z = t;
% reorder data in order to plot individual line segments
indices = [1:length(x) - 1; 2:length(x)];
figure;
p = plot3(x(indices), y(indices), z(indices), 'LineWidth', 2);
set(p, {'Color'}, num2cell(parula(length(x) - 1), 2)); % see what happens when you comment out this line
You can change the colormap you want by changing the parula keyword above. You can use any of the supplied colormaps, or create your own (in the form of an M x 3 RGB triple matrix).
You can then add the colorbar (note that these are dummy values).
c = colorbar;
caxis([-6 6]);
set(c, 'Ticks', [-6, -4, -2, -1, 0, 1, 2, 4, 6]);
set(c, 'TickLabels', {'-\infty', '-4', '-2', '-1', '0', '1', '2', '4', '\infty'});
You can achieve a somewhat similar, but different, effect using scatter3(). It is similar to plot3() but will allow you to set color (and size, if you wish) for each data point that it plots. If the aesthetics suit you, it is a simple and versatile approach.

Plotting a phase portrait with multiple colors with MATLAB

I want to add something to make my phase portrait more understandable. Nevertheless, I can't find anything (I found this
https://se.mathworks.com/help/matlab/ref/colorspec.html
https://se.mathworks.com/matlabcentral/fileexchange/11611-linear-2d-plot-with-rainbow-color
https://se.mathworks.com/help/symbolic/mupad_ref/linecolortype.html
) but it is not what I need.
I would really like to see the color of the line of the phase portrait changing depending of if it is at the beginning or at the end of the simulation.
I found this idea which seems great :
I don't understand at all what he has done (the code is I suppose written here:
https://blogs.mathworks.com/pick/2008/08/15/colors-for-your-multi-line-plots/ )
but It would be great if I can plot a one line function which color varies depending of the time. If moreover, like on the picture, I can have have a scale on the right: it would be awesome.
So for now, I have that :
data = readtable('test.txt');
figure('Name','Phase' , 'units','normalized','outerposition',[(8/100) (0.3- 16/100) 0.5 0.7]);
hold on
plot(data{:,2},data{:,3}, 'k.', 'LineWidth',1.5 );
plot(data{:,4},data{:,5}, 'r.', 'LineWidth',1.5 );
xL = xlim;
yL = ylim;
line([0 0], yL); %x-axis
line(xL, [0 0]); %y-axis
title(['Phase portrait'])
xlabel('f')
ylabel('f '' ')
hold off
I read the values of the function in a .txt file, and then I plot the 2nd/3rd columns and 4/5th columns. The first column is the time evoluting.
Do you have any idea :)?
Thank you!
There are several ways to go about this to be honest.
However it makes a bit easier if you let us know what your time data is.
Do you plot your time data on the x (or y) axis or is it a different additional data set. Should it be an additional data set then you can consider it like z-data, plotted on the Z-axis or/and as a color.
Below is an example of what you can do by making a 3D plot but displaying it in 2D, this allows you to add the colorbar without too many problems.
x=0:5;
y=0:5;
z=rand(1,6); %random data to simulate your time
xx=[x' x']; %this allows you to plot the data using surf in 3d
yy=[y' y']; %same as for xx
z1=zeros(size(xx)); % we don't need z-data so we're making it a matrix of zeros
zc=[z' z']; %input here your time data values, if x/y then you can just use those instead of z
hs=surf(xx,yy,z1,zc,'EdgeColor','interp') %// color binded to "z" values, choose interp for interpolated/gradual color changes, flat makes it sudden
colormap('hsv') %choose your colormap or make it yourself
view(2) %// view(0,90)
hcb=colorbar; %add a colorbar
I found this, thanks to another user on stackoverflaw.
data = readtable('4ressorspendule.txt');
n = numel(data.Var1);
c = size(data,2);
figure('Name','Phase' , 'units','normalized','outerposition',[(8/100) (0.3 - 16/100) 0.5 0.7]);
for i=1:n
hold on
plot(data{i,2},data{i,3},'.','Color',[1 (1-i/n) 0] ,'MarkerSize',4);
plot(data{i,4},data{i,5},'.','Color',[0 (i/n) (1-i/n)],'MarkerSize',4);
end
xL = xlim;
yL = ylim;
line([0 0], yL); %x-axis
line(xL, [0 0]); %y-axis
title(['Phase portrait'])
xlabel('f')
ylabel('f '' ')
hold off

Color-coded representation of data in a 2-D plot (in MATLAB)

I have several 4 x 4 matrices with data that I would like to represent in a 2-D plot. The plot is supposed to show how the results of a simulation change with varying parameters.
On the y-axis I would like to have the possible values of parameter A (in this case, [10,20,30,40]) and on the x-axis I want to have the possible values of parameter B (in this case, [2,3,4,5]). C is a 4 x 4 matrix with the evaluation value for running the simulation with the corresponding parameter combination.
Example: The evaluation value for the parameter combination A = 10, B = 2 equals 12 dB. I would like to plot it at the cross section A and B (I hope you understand what I mean by this) and code the value by a fat colored dot (e.g. red means high values, blue means low values).
How can I do this? I would basically like to have something like mesh without lines.
I'm sorry for my imperfect English! I hope you understood what I would like to achieve, thank you in advance!
You can do this with the mesh command (and the built-in colormaps you can choose from can be found here, or you could even make your own):
[A, B] = meshgrid(10:10:40, 2:5); % Grids of parameter values
C = rand(4); % Random sample data
hMesh = mesh(A, B, C); % Plot a mesh
set(hMesh, 'Marker', '.', ... % Circular marker
'MarkerSize', 60, ... % Make marker bigger
'FaceColor', 'none', ... % Don't color the faces
'LineStyle', 'none'); % Don't render lines
colormap(jet); % Change the color map
view(0, 90); % Change the view to look from above
axis([5 45 1.5 5.5]); % Expand the axes limits a bit
colorbar; % Add colorbar
And here's the plot:

Xtick marks and Xtick labels on heatmap in Matlab

Environment: Windows 7 64 bit, Matlab 2014a
Objective:
To draw a heatmap of errors for two parameters to be optimized.
To put proper tick marks and tick values
Draw the grid lines in the correct place
Problem: Arranging the X and Y tick positions and values. When the last ("end") value of the vectors in x and y axes are the same, the code I use puts the ticks and values properly. However, when the end values are different it does not, and produces something really weird.
Below I have included the code which I have modified so that you can run it without the need of adding anything. Of course in my case the error vector are the error values, not random numbers. To see the problem of "end value" use the second b vector.
fontsize = 20
k = [2^-5, 2^-3, 2^-1, 2^0, 2^1, 2^3, 2^5, 2^7, 2^9, 2^11, 2^13, 2^15]
b = [2^-5, 2^-3, 2^-1, 2^0, 2^1, 2^3, 2^5, 2^7, 2^8, 2^9, 2^10, 2^11, 2^13, 2^15]
% b = [2^-5, 2^-3, 2^-1, 2^0, 2^1, 2^3, 2^5, 2^7, 2^8, 2^9, 2^10, 2^11, 2^13, 2^19]
errorVector = randi(20, 1, length(b)*length(k))'
figure
% Create a matrix from error vector (size of error vector is [length(k)*length(b),1])
B = reshape(errorVector, [length(b), length(k)])
B = flipud(B)
% imagesc(x,y,C)
imagesc(b, k, B)
title('Heatmap Parameters Percent Error', 'FontSize', fontsize);
% Set colorbar limits
caxis([0 15])
colorbar;
ax1 = gca;
xTickLabel = (k)'
xTick = linspace(k(1), k(end), numel(xTickLabel))';
set(ax1, 'XTick', xTick, 'XTickLabel', xTickLabel)
xlabel('k parameter', 'FontSize', fontsize)
yTickLabel = (b)'
yTick = linspace(b(1), b(end), numel(yTickLabel))';
set(ax1, 'YTick', yTick, 'YTickLabel', flipud(yTickLabel(:)))
ylabel('b parameter', 'FontSize', fontsize)
set(ax1,'FontSize', fontsize)
Here, change any of the end values of b or k vectors, and the program will output a graph where the X and Y ticks are totally wrong.
Also, I would like to draw grid lines. When I use "grid on" it draws grid lines right on the tick marks which is not correct in the case of heatmap. Because tick marks will be in the center of the columns -or rows- but the grid lines should be at the boundaries between the columns -or rows.
By the way if you know a better way to plot a heatmap in Matlab, please do tell.
Please help me solve this problem. Any help is appreciated,
Ilyas
First of all - you don't need to flipud the B matrix - by default imagesc plots the y-data inversed, but you can fix this with the following statement:
set(gca,'ydir','normal');
This also means you don't have to mess around with flipping the tick-labels. You can get the labels right by doing the following:
% replace the imagesc call with:
imagesc(B);
set(gca,'ydir','normal');
% formatting stuff
...
% replace the set commands with:
set(ax1, 'XTick', 1:length(k), 'XTickLabel', k)
set(ax1, 'YTick', 1:length(b), 'YTickLabel', b)
By default, if you don't provide x and y data to the imagesc command, it will number them linearly (1,2,3...). Basically what we've done here is make sure that it has ticks for each of the elements of b and k, and then set the labels to the values of the respective vectors.
Unfortunately, I'm not sure if there is a way to get the grid spacing right with imagesc or not. You could try using pcolor instead, which has it's own set of issues, but allows you to get grid lines (of sorts) between the elements. It also allows you to use an interpolated shading mode, which will make your plot look more like a typical heat map.
To use pcolor instead, you just have to replace imagesc:
% imagesc(B);
% set(gca,'ydir','normal');
pcolor(B);
% this uses a smoother shading method, for a more 'heatmap' like output
% shading interp
Everything else should work as intended, I believe.

draw a line of best fit through data with shaded region for error

I have the following data:
dat = [9.3,0.6,0.4,0.7;...
3.2,1.2,0.7,1.9;...
3.9,1.8,0.7,1.9;...
1.0,7.4,5.6,10.7;...
4.7,1.0,0.5,1.3;...
2.2,2.6,1.2,2.7;...
7.2,1.0,0.5,1.1;...
1.0,4.8,7.5,10.3;...
2.7,1.8,1.7,4.0;...
8.2,0.8,0.4,0.9;...
1.0,4.9,5.7,8.2;...
12.9,1.3,0.6,1.6;...
7.7,0.8,0.5,1.3;...
5.8,0.9,0.6,1.9;...
1.1,4.5,6.2,12.1;...
1.1,4.5,2.8,4.8;...
16.4,0.3,0.3,0.5;...
10.4,0.6,0.3,0.7;...
2.2,3.1,2.2,4.6];
where the first column shows the observed values the second column shows the modeled values and the third and fourth columns show the min and max respectively.
I can plot the relationship between observed and modeled by
scatter(d(:,1),d(:,2))
Next, I would like to draw a smooth line through these points to show the relationship. How can this be done? Obviously a simple straight line would not be much use here.
Secondly, I would like to use the min and max (3rd and 4th columns respectively) to draw a shaded region around the modeled values in order to show the associated error.
I would eventually like to have something that looks like
http://www.giss.nasa.gov/research/briefs/rosenzweig_03/figure2.gif
Something like this?
%// Rename and sort your data
[x,I] = sort(dat(:,1));
y = dat(I,2);
mins = dat(I,3);
maxs = dat(I,4);
%// Assume a model of the form y = A + B/x. Solve for A and B
%// using least squares
P = [ones(size(x)) 1./x] \ y;
%// Initialize figure
figure(1), clf, hold on
set(1, 'Renderer', 'OpenGl');
%// Plot "shaded" areas
fill([x; flipud(x)], [mins; flipud(maxs)], 'y',...
'FaceAlpha', 0.2,...
'EdgeColor', 'r');
%// Plot data and fit
legendEntry(1) = plot(x, P(1) + P(2)./x, 'b',...
'LineWidth', 2);
legendEntry(2) = plot(dat(:,1), dat(:,2), 'r.',...
'Markersize', 15);