Matlab: How to show sigma and mu on normal curve - matlab

I am plotting a normal curve by using y = normpdf(x,mu,sigma); in Matlab.
This draws for me a normal curve. But, I need additional information to be shown on the curve, like having vertical lines on the curve to show the mu and the sigma. Similar to this one:
Is there any Matlab function to draw such vertical lines on the curve?
Thanks,
Aida

There are no built-in function for this, but we can do it easily by the hands:
Create normal curve and plot it:
x = -2:0.05:2;
mu = 0; sigma = 0.5;
y = normpdf(x,mu,sigma);
plot(x,y)
Add lines for sigmas:
hold on;
plot( [mu - sigma mu - sigma],[0 max(y)],'--')
plot( [mu + sigma mu + sigma],[0 max(y)],'--')
You can change it to any sigma you need (2sigma 3sigma).
How to add the text? This way:
text(0.1,-0.05,'mu + sigma');
or if you want it look really beautiful:
text(-0.65,-0.05,'\mu - \sigma')
Result:

The easiest way to draw lines in Matlab is probably using simply plot. The following code segment draws a line from [x1, y1] to [x2, y2]:
plot([x1,y1], [x2,y2], plotoptions)
To make sure that this line is also visible on your current figure use hold on. This results in a code like the following:
y = normpdf(x,mu,sigma)
figure(1)
hold on
plot(x,y) % Your normal distribution
plot([mu,startY], [mu, stopY], plotoptions) % Plot the line at position mu.
% The startY and stopY indicate the bottom and top of your graph.
hold off
The Mathworks documentation page of plot can be a great reference, with a lot of examples and different plot options. For example how to make a dashed or colored line:
http://www.mathworks.com/help/matlab/ref/plot.html?searchHighlight=plot%20line

Related

Matlab how to make smooth contour plot?

I want to represent data with 2 variables in 2D format. The value is represented by color and the 2 variables as the 2 axis. I am using the contourf function to plot my data:
clc; clear;
load('dataM.mat')
cMap=jet(256); %set the colomap using the "jet" scale
F2=figure(1);
[c,h]=contourf(xrow,ycol,BDmatrix,50);
set(h, 'edgecolor','none');
xlim([0.0352 0.3872]);
ylim([0.0352 0.3872]);
colormap(cMap);
cb=colorbar;
caxis([0.7 0.96]);
% box on;
hold on;
Both xrow and ycol are 6x6 matrices representing the coordinates. BDmatrix is the 6x6 matrix representing the corresponding data. However, what I get is this:
The following is the xrow and yrow matices:
The following is the BDmatrix matices:
Would it be possible for the contour color to vary smoothly rather than appearing as straight lines joining the data points? The problem of this figure is the coarse-granularity which is not appealing. I have tried to replace contourf with imagec but it seems not working. I am using MATLAB R2015b.
You can interpolate your data.
newpoints = 100;
[xq,yq] = meshgrid(...
linspace(min(min(xrow,[],2)),max(max(xrow,[],2)),newpoints ),...
linspace(min(min(ycol,[],1)),max(max(ycol,[],1)),newpoints )...
);
BDmatrixq = interp2(xrow,ycol,BDmatrix,xq,yq,'cubic');
[c,h]=contourf(xq,yq,BDmatrixq);
Choose the "smoothness" of the new plot via the parameter newpoints.
To reduce the Color edges, you can increase the number of value-steps. By default this is 10. The following code increases the number of value-steps to 50:
[c,h]=contourf(xq,yq,BDmatrixq,50);
A 3D-surf plot would be more suitable for very smooth color-shading. Just rotate it to a top-down view. The surf plot is also much faster than the contour plot with a lot of value-steps.
f = figure;
ax = axes('Parent',f);
h = surf(xq,yq,BDmatrixq,'Parent',ax);
set(h, 'edgecolor','none');
view(ax,[0,90]);
colormap(Jet);
colorbar;
Note 1: Cubic interpolation is not shape-preserving. That means, the interpolated shape can have maxima which are greater than the maximum values of the original BDmatrix (and minima which are less). If BDmatrix has noisy values, the interpolation might be bad.
Note 2: If you generated xrow and yrow by yourself (and know the limits), than you do not need that min-max-extraction what I did.
Note 3: After adding screenshots of your data matrices to your original posting, one can see, that xrow and ycol come from an ndgrid generator. So we also must use this here in order to be consistent. Since interp2 needs meshgrid we have to switch to griddedInterpolant:
[xq,yq] = ndgrid(...
linspace(min(min(xrow,[],1)),max(max(xrow,[],1)),newpoints ),...
linspace(min(min(ycol,[],2)),max(max(ycol,[],2)),newpoints )...
);
F = griddedInterpolant(xrow,ycol,BDmatrix,'cubic');
BDmatrixq = F(xq,yq);

Draw a line with non-Cartesian coordinates in MATLAB

MATLAB's surf command allows you to pass it optional X and Y data that specify non-cartesian x-y components. (they essentially change the basis vectors). I desire to pass similar arguments to a function that will draw a line.
How do I plot a line using a non-cartesian coordinate system?
My apologies if my terminology is a little off. This still might technically be a cartesian space but it wouldn't be square in the sense that one unit in the x-direction is orthogonal to one unit in the y-direction. If you can correct my terminology, I would really appreciate it!
EDIT:
Below better demonstrates what I mean:
The commands:
datA=1:10;
datB=1:10;
X=cosd(8*datA)'*datB;
Y=datA'*log10(datB*3);
Z=ones(size(datA'))*cosd(datB);
XX=X./(1+Z);
YY=Y./(1+Z);
surf(XX,YY,eye(10)); view([0 0 1])
produces the following graph:
Here, the X and Y dimensions are not orthogonal nor equi-spaced. One unit in x could correspond to 5 cm in the x direction but the next one unit in x could correspond to 2 cm in the x direction + 1 cm in the y direction. I desire to replicate this functionality but drawing a line instead of a surf For instance, I'm looking for a function where:
straightLine=[(1:10)' (1:10)'];
my_line(XX,YY,straightLine(:,1),straightLine(:,2))
would produce a line that traced the red squares on the surf graph.
I'm still not certain of what your input data are about, and what you want to plot. However, from how you want to plot it, I can help.
When you call
surf(XX,YY,eye(10)); view([0 0 1]);
and want to get only the "red parts", i.e. the maxima of the function, you are essentially selecting a subset of the XX, YY matrices using the diagonal matrix as indicator. So you could select those points manually, and use plot to plot them as a line:
Xplot = diag(XX);
Yplot = diag(YY);
plot(Xplot,Yplot,'r.-');
The call to diag(XX) will take the diagonal elements of the matrix XX, which is exactly where you'll get the red patches when you use surf with the z data according to eye().
Result:
Also, if you're just trying to do what your example states, then there's no need to use matrices just to take out the diagonal eventually. Here's the same result, using elementwise operations on your input vectors:
datA = 1:10;
datB = 1:10;
X2 = cosd(8*datA).*datB;
Y2 = datA.*log10(datB*3);
Z2 = cosd(datB);
XX2 = X2./(1+Z2);
YY2 = Y2./(1+Z2);
plot(Xplot,Yplot,'rs-',XX2,YY2,'bo--','linewidth',2,'markersize',10);
legend('original','vector')
Result:
Matlab has many built-in function to assist you.
In 2D the easiest way to do this is polar that allows you to make a graph using theta and rho vectors:
theta = linspace(0,2*pi,100);
r = sin(2*theta);
figure(1)
polar(theta, r), grid on
So, you would get this.
There also is pol2cart function that would convert your data into x and y format:
[x,y] = pol2cart(theta,r);
figure(2)
plot(x, y), grid on
This would look slightly different
Then, if we extend this to 3D, you are only left with plot3. So, If you have data like:
theta = linspace(0,10*pi,500);
r = ones(size(theta));
z = linspace(-10,10,500);
you need to use pol2cart with 3 arguments to produce this:
[x,y,z] = pol2cart(theta,r,z);
figure(3)
plot3(x,y,z),grid on
Finally, if you have spherical data, you have sph2cart:
theta = linspace(0,2*pi,100);
phi = linspace(-pi/2,pi/2,100);
rho = sin(2*theta - phi);
[x,y,z] = sph2cart(theta, phi, rho);
figure(4)
plot3(x,y,z),grid on
view([-150 70])
That would look this way

Plot gradient in matlab and nothing but blank appears

I'm trying to plot the gradient of the real part of a complex function, however what I get is a blank figure. I do not understand what I am doing wrong since the code works with other functions (such as the imaginary part)
% Set up
x = -3:0.2:3;
y1 = (-3:0.2:3);
y = (-3:0.2:3)*1i;
[X, Y]= meshgrid(x,y);
% Complex variable s
s = X + Y;
% Complex function f(z)
z = s + 1./s;
figure
subplot(1,2,1);
[Dx, Dy] = gradient(real(z),.2,.5);
quiver(x,y1,Dx,Dy)
title('u(x,y) gradient, vector field');
%%Imaginary part
subplot(1,2,2)
contour(x,y1,imag(z),linspace(-10,10,100)); title('Contour of Im(f)');
xlabel('x'); ylabel('y'); %clabel(C3);
title('Imaginary part');
Here below is the image I get
I tried to rescale and resize the picture, the domain etc... but couldn't get the gradient to display (the arrows). What am I doing wrong here?
EDIT:
I found out it displays blank perhaps because there are some Inf and -Inf values in the Dy and Dx variables, is there an option to ignore these values or set them to 0?
It looks to me like it works, but the line width of your arrows is too small for you to see.
You can increase it by assigning a handle to the quiver plot like so:
hQuiver = quiver(x,y1,Dx,Dy);
And then, after the plot is created, change any of its many properties like so:
set(hQuiver,'LineWidth',4)
or do it all in the call to quiver:
hQuiver = quiver(x,y1,Dx,Dy,'LineWidth',4);
In this case it gives the following:
EDIT:
To answer your secondary question, you can set elements that are equal to +Inf or -Inf to any value you want using isinf:
Dx(isinf(Dx)) = 0;
and
Dy(isinf(Dy)) = 0;
It is not blank. You've plotted the quiver diagram (usually used in optical flow diagrams). It is giving an inward pointing arrow at each of the locations formed by the grid with points in x and y1.

How to connect pick points of a histogram by a curve in Matlab?

I am beginner in Matlab.
I have a histogram of a set of data I need to do 2 things.
1) I need the vertical axes to be normalized.
2) To curve a fit that passes through all the pick points of my Histogram bars.
Thank you
You can do it along these lines:
data = randn(1,1000); %// example data
num_bars = 15; %// specify number of bars
[n x] = hist(data,num_bars); %// use two-output version of hist to get values
n_normalized = n/numel(data)/(x(2)-x(1)); %// normalize to unit area
bar(x, n_normalized, 1); %// plot histogram (with unit-width bars)
hold on
plot(x, n_normalized, 'r'); %// plot line, in red (or change color)
For (1) try axis([xmin xmax ymin ymax])
For (2) try first drawing the histogram, then call hold on, then use the plot command.

How do I display an arrow positioned at a specific angle in MATLAB?

I am working in MATLAB and I'm stuck on a very simple problem: I've got an object defined by its position (x,y) and theta (an angle, in degrees). I would like to plot the point and add an arrow, starting from the point and pointing toward the direction defined by the angle. It actually doesn't even have to be an arrow, anything graphically showing the value of the angle will do!
Here's a picture showing the kind of thing I'm trying to draw:
removed dead ImageShack link
The quiver() plotting function plots arrows like this. Take your theta value and convert it to (x,y) cartesian coordinates representing the vector you want to plot as an arrow and use those as the (u,v) parameters to quiver().
theta = pi/9;
r = 3; % magnitude (length) of arrow to plot
x = 4; y = 5;
u = r * cos(theta); % convert polar (theta,r) to cartesian
v = r * sin(theta);
h = quiver(x,y,u,v);
set(gca, 'XLim', [1 10], 'YLim', [1 10]);
Take a look through online the Matlab documentation to see other plot types; there's a lot, including several radial plots. They're in the MATLAB > Functions > Graphics > Specialized Plotting section. Do "doc quiver" at the command line and browse around.
If you want to try and make something that looks like the image you linked to, here's some code to help you do it (NOTE: you would first have to download the submission arrow.m by Erik Johnson on the MathWorks File Exchange, which I always like to use for generating arrows of any shape and size):
x = 1; % X coordinate of arrow start
y = 2; % Y coordinate of arrow start
theta = pi/4; % Angle of arrow, from x-axis
L = 2; % Length of arrow
xEnd = x+L*cos(theta); % X coordinate of arrow end
yEnd = y+L*sin(theta); % Y coordinate of arrow end
points = linspace(0, theta); % 100 points from 0 to theta
xCurve = x+(L/2).*cos(points); % X coordinates of curve
yCurve = y+(L/2).*sin(points); % Y coordinates of curve
plot(x+[-L L], [y y], '--k'); % Plot dashed line
hold on; % Add subsequent plots to the current axes
axis([x+[-L L] y+[-L L]]); % Set axis limits
axis equal; % Make tick increments of each axis equal
arrow([x y], [xEnd yEnd]); % Plot arrow
plot(xCurve, yCurve, '-k'); % Plot curve
plot(x, y, 'o', 'MarkerEdgeColor', 'k', 'MarkerFaceColor', 'w'); % Plot point
And here's what it would look like:
You can then add text to the plot (for the angle and the coordinate values) using the text function.
Here's a partial answer, I expect you can figure out the rest. I fired up the Figures editor and opened the plot tools. I dragged an arrow from the palette onto my figure. Then I generated an m-file. This included the line:
annotation(figure1,'arrow',[0.1489 0.2945],[0.5793 0.6481]);
So, the first pair of coordinates is the start of the arrow. You're going to have to figure out the pointy end (second pair of coordinates) using a little bit of trigonometry. You might even be able to get the little arc if you do some more fiddling around with plot tools.
Let us know if the trig defeats you. Oh, and I forgot to plot the point, but I guess you can figure that out ?