I am new to MATLAB. I am looking for a 'correct' implementation of a simple plot. I have defined an anonymous function and I want to place a point at the minimum of the function. The following code does this; but I think I am missing a more appropriate way of handling this.
f = #(t) t.^(8/3)-16*t.^(2/3);
fminbnd(f,0,5)
f(2)
fplot(f,[0 5],'Linewidth',2,'Color','g');
hold on
fplot(f,[2 2],'--or');
hold off
This is how I'd do it:
f = #(t) t.^(8/3)-16*t.^(2/3);
x1=0;
x2=5;
[x fval]=fminbnd(f,x1,x2);
fplot(f,[x1 x2],'Linewidth',2,'Color','g'); hold on
plot(x,fval,'--or'); hold off
by the way, you can also write the last line as:
plot(x,f(x),'--or');
Related
I would like to draw curves with two variables like f(x,y)=0 for example:
x^2+y^2-2ax+2by+c=0 (a,b,c are constants and x,y are variables)
Of course in the case above, it is a circle so I could write the equation above in the form of circle and calculate its center and radius. Then I can plot it out.
But next time if it is not a circle(for example there are 'xy' terms or there are 'x^3,y^3' terms), is there any way to plot it out in the x-y plane too?
I know how to draw f(x,y) in 3D plot using meshgrid, But I would like to draw f(x,y)=0 in 2D forms
Suggestion 1:
fcontour
You would use it like this:
f = #(x,y) x.^2 + y.^2
fcontour(f,[xmin xmax ymin ymax])
This was introduced in R2016a.
Suggestion 2:
you may have to determine the x- and y-values for each equation and then plot those.
You could use anonymous functions to automate this. The good thing here is that you can create a cell array of anonymous functions and loop through those.
% // Generate the x and y values
x=-2*pi:0.01:2*pi;
y=-2*pi:0.01:2*pi;
Create anonymous functions that will hold your equation. It is up to you to design these as you see fit. This particular anonymous function that I did creates a matrix where the first column hold the x values and the second hold the y-values. You will probably have different x- and y- values for each function.
a=#(x,y) ([cos(x);sin(y)].');
a1 = #(x,y) ([cos(x).^2;sin(x).^2].');
Put them in an cell array
t{1} = a;
t{2} = a1;
Then you can loop through your anonymous functions
for n=1:length(t)
f = t{n};
subplot(2,1,n)
plot(f(y,x),'LineWidth',5);
end
you can have a look at the scatterplot function: http://uk.mathworks.com/help/matlab/ref/scatter.html
[edit] or just use plot(x,y) [/edit]
I use the following example taken from the site that describes fit. Returns an
object. Is it possible to take the data that refer to the fitted surface?
load franke
sf = fit([x, y],z,'poly23')
plot(sf,[x,y],z)
Thanks!
Here is a way to do it; but there is probably a cleaner one:
After getting your sf object, you can access its methods like so:
MethodName(sf)
See here for the list of available methods
So let's say you wish to plot the surface using a handle for the plot:
hPlot = plot(sf)
Then you can fetch the XData, YData and ZData using the handles like so:
X = get(hPlot,'XData')
Y = get(hPlot,'YData')
Z = get(hPlot,'ZData')
Might be a it cumbersome but it works. Note that you can also fetch the coefficients of the fitted surface like so:
coeffvalues(sf)
and the formula used to generate it:
formula(sf)
Therefore you could generate X, Y data and create Z values using meshgrid for example and you could then modify the surface as you wish.
EDIT Here is how you could create your own surface using the coefficients and the formula. Here I create an anonymous function with two input arguments (x and y) and use it to generate z values to plot. From the data obtained using plot(sf) I used x = 1:0.01:0.01:1 and y = 500:500:3000 but you could obviously change them.
I entered the formula manually in the function handle but there has to be a better way; I'm a bit in a hurry so I did not looked further into that but you could extract every element of the formula and multiply it by the right coefficient to automatically generate the formula.
Here is the whole code:
clear
clc
close all
load franke
sf = fit([x, y],z,'poly23')
c = coeffvalues(sf)
F = formula(sf)
%// Generate x and y values.
[x,y] = meshgrid(500:100:3000,0.01:.01:1);
%// There should be a better approach than manually entering the data haha.
%// Maybe use eval or feval.
MyFun = #(x,y) (c(1) + c(2)*x + c(3)*y +c(4)*x.^2 + c(5)*x.*y + c(6)*y.^2 + c(7)*(x.^2).*y + c(8)*x.*y.^2 + c(9)*y.^3);
%// Generate z data to create a surface
z = (MyFun(x,y));
figure
subplot(1,2,1)
plot(sf)
title('Plot using sf','FontSize',18)
subplot(1,2,2)
surf(x,y,z)
title('Plot using MyFun','FontSize',18)
Output:
[I know this is many years later, but I thought I'd add this for future visitors looking for answers]
There is a much simpler way to do this - use feval, or the implicit shortcuts to it by calling the fittype object itself. It did take me a little digging to find this when I needed it, it isn't particularly obvious.
From the feval MATLAB documentation:
Standard feval syntax:
y = feval(cfun,x)
z = feval(sfun,[x,y])
z = feval(sfun,x,y)
y = feval(ffun,coeff1,coeff2,...,x)
z = feval(ffun,coeff1,coeff2,...,x,y)
You can use feval to evaluate fits, but the following simpler syntax is recommended to evaluate these objects, instead of calling feval directly. You can treat fit objects as functions and call feval indirectly using the following syntax:
y = cfun(x) % cfit objects;
z = sfun(x,y) % sfit objects
z = sfun([x, y]) % sfit objects
y = ffun(coef1,coef2,...,x) % curve fittype objects;
z = ffun(coef1,coef2,...,x,y) % surface fittype objects;
I want to plot relations like y^2=x^2(x+3) in MATLAB without using ezplot or doing algebra to find each branch of the function.
Does anyone know how I can do this? I usually create a linspace and then create a function over the linspace. For example
x=linspace(-pi,pi,1001);
f=sin(x);
plot(x,f)
Can I do something similar for the relation I have provided?
What you could do is use solve and allow MATLAB's symbolic solver to symbolically solve for an expression of y in terms of x. Once you do this, you can use subs to substitute values of x into the expression found from solve and plot all of these together. Bear in mind that you will need to cast the result of subs with double because you want the numerical result of the substitution. Not doing this will still leave the answer in MATLAB's symbolic format, and it is incompatible for use when you want to plot the final points on your graph.
Also, what you'll need to do is that given equations like what you have posted above, you may have to loop over each solution, substitute your values of x into each, then add them to the plot.
Something like the following. Here, you also have control over the domain as you have desired:
syms x y;
eqn = solve('y^2 == x^2*(x+3)', 'y'); %// Solve for y, as an expression of x
xval = linspace(-1, 1, 1000);
%// Spawn a blank figure and remember stuff as we throw it in
figure;
hold on;
%// For as many solutions as we have...
for idx = 1 : numel(eqn)
%// Substitute our values of x into each solution
yval = double(subs(eqn(idx), xval));
%// Plot the points
plot(xval, yval);
end
%// Add a grid
grid;
Take special care of how I used solve. I specified y because I want to solve for y, which will give me an expression in terms of x. x is our independent variable, and so this is important. I then specify a grid of x points from -1 to 1 - exactly 1000 points actually. I spawn a blank figure, then for as many solutions to the equation that we have, we determine the output y values for each solution we have given the x values that I made earlier. I then plot these on a graph of these points. Note that I used hold on to add more points with each invocation to plot. If I didn't do this, the figure would refresh itself and only remember the most recent call to plot. You want to put all of the points on here generated from all of the solution. For some neatness, I threw a grid in.
This is what I get:
Ok I was about to write my answer and I just saw that #rayryeng proposed a similar idea (Good job Ray!) but here it goes. The idea is also to use solve to get an expression for y, then convert the symbolic function to an anonymous function and then plot it. The code is general for any number of solutions you get from solve:
clear
clc
close all
syms x y
FunXY = y^2 == x^2*(x+3);
%//Use solve to solve for y.
Y = solve(FunXY,y);
%// Create anonymous functions, stored in a cell array.
NumSol = numel(Y); %// Number of solutions.
G = cell(1,NumSol);
for k = 1:NumSol
G{k} = matlabFunction(Y(k))
end
%// Plot the functions...
figure
hold on
for PlotCounter = 1:NumSol
fplot(G{PlotCounter},[-pi,pi])
end
hold off
The result is the following:
n = 1000;
[x y] = meshgrid(linspace(-3,3,n),linspace(-3,3,n));
z = nan(n,n);
z = (y .^ 2 <= x .^2 .* (x + 3) + .1);
z = z & (y .^ 2 >= x .^2 .* (x + 3) - .1);
contour(x,y,z)
It's probably not what you want, but I it's pretty cool!
I want to plot a function using ezplot, different values of two constants.
like
ezplot('a*x^2+b*y^2=1')
How can I plot it for different values of a and b?
Thanks everyone.
The easy way is:
first define your function with a handler, something like this:
a = 1;
b = 3;
fh = #(x,y) (a*x.^2 + b*y.^2 - 1);
Then easily use ezplot with the function:
ezplot(fh)
axis equal
If you have different values of a, and b, you can use them in a loop (or using vectorized calculation), and feed them to your function, then plot the function, and after a plot use 'hold on' command to keep the previous plot something like this:
for i=1:n
fh = #(x,y) (a(i)*x.^2 + b(i)*y.^2 - 1);
ezplot(fh);
hold on
end
That's it.
Here's one way to use multiple values for a and b: define your function separately and use function handles and anonymous function to change a and b. You can define your implicit function as two separate functions:
function y = someFun(x,a,b)
y = sqrt((1-a.*x.^2)./b);
function y = someFun2(x,a,b)
y = - sqrt((1-a.*x.^2)./b);
Then call ezplot on an anonymous function using a and b.
clear all
close all
figure
hold on
for a = 1:5
for b = 1:5
ezplot(#(x)someFun2(x,a,b));
ezplot(#(x)someFun(x,a,b));
end
end
axis([-1,1,-1,1])
ezplot will reset the axis so you'll need to set those your self after it's called.
Suppose that I want to update a plot with a new data. What method should I choose?
Set the XDataSource property to some name, update the variable, and call refreshdata
Erase the original plot, and call plot command again.
Use Set('Xdata',...')
Short answer : always use Set('Xdata',...').
Example code:
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
y = sin(x.^3);
set(h,'XData',x,'YData',y);
end
Long answer:
There are three relevant measures by which one should choose the best method.
Code clarity - How easy it is for someone to read your code?
Runtime - How quick each method performs its task?
Code portability - How fast can you re-factor your code?
Now, let's analyze the possible methods.
Method(1) - refreshdata
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
set(h,'YDataSource','y')
set(h,'XDataSource','x')
y = sin(x.^3);
refreshdata(h,'caller');
end
M-lint immediately issues a warning in the line y=sin(x.^3)
The value assigned to variable `y` might be unused
Why does it happen? refreshdata uses eval and m-lint cannot know that you will use y. Someone reading your code, might as well remove this line completely. This happened because you broke the encapsulation principle. refreshdata accesses variables from the caller workspace. Another way to take a look at this, suppose that you pass the handle of the plot to another function. The reader has no clue to why on earth you wrote y = sin(x.^3);, and how is it going to be related to the update of the plot.
Now let's discuss speed/runtime. By taking a look at refreshdata source code, you will notice two ugly for-loops, that go through all of the graphics handles variables in your space. Here is the first:
% gather up all the objects to refresh
objs = {};
for k = 1:length(h)
obj = h(k);
objfields = fields(obj);
for k2 = 1:length(objfields)
% search for properties ending in DataSource
if strncmpi(fliplr(objfields{k2}),'ecruoSataD',10)
objs = {objs{:},obj, objfields{k2}};
end
end
end
Imagine that you have not one plot, but 100 plot and you want to update only the first. This will be very slow, because for each of the plots, you attempt to find the one you need! (I am leaving as an exercise for the reader to figure out what is ecruoSataD, and how it is used.)
Even if you give the relevant plot as an argument, you still have the second loop, that runs eval several times. Not exactly efficient. I will show a time comparison in the end.
Conclusion : Hard to understand, hard to refactor, slow runtime
Method (2) - Delete and re-plot
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
set(h,'YDataSource','y')
set(h,'XDataSource','x')
y = sin(x.^3);
delete(h);
h = plot(x,y);
end
This method is quite clear for the reader. You deleted the plot, and drew a new one. However, as we will see from the time comparison in the end, that is the slowest method.
Conclusion : Easy to understand, easy to refactor, very slow runtime
Method(3) - set('XData',...,'YData')
The code is really clear. You want to modify a two properties of your plot, XData and YData. And that is exactly what you do. Also, the code runs really fast, as you can see from the comparison below.
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
y = sin(x.^3);
set(h,'XData',x,'YData',y);
end
Since the new graphics engine hg2 (R2014b and up), you can also use property syntax for specifying data if you prefer that notation:
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
y = sin(x.^3);
h.XData = x;
h.YData = y;
end
Conclusion : Easy to understand, easy to refactor, fast runtime
Here is the time comparison code
function PlotUpdateTimeCompare()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
set(h,'YDataSource','y')
set(h,'XDataSource','x')
y = sin(x.^3);
tic
for i=1:100
refreshdata(h,'caller');
end
toc
tic
for i=1:100
delete(h);
h = plot(x,y);
end
toc
tic
for i=1:100
set(h,'XData',x,'YData',y);
end
toc
end
And the results:
Elapsed time is 0.075515 seconds.
Elapsed time is 0.179954 seconds.
Elapsed time is 0.002820 seconds.
You can call the function drawnow and do something like that :
h = plot(nan);
for i = 1:n
y = ...
set(h,'YData',y);
drawnow %update the graph
end
Suppose that I want to update a plot with a new data. What method should I choose?
If you have more than one line object in the given axes then Method:
Set the XDataSource property to some name, update the variable, and call refreshdata
will generate an error in MATLAB R2012b. An appropriate example is provided in Andrey's answer.
A bug has been submitted to the Mathworks.