spurious lines using fimplicit on a modular function - matlab

I want to plot collections of repeating circular arcs and am having trouble with spurious lines showing up in the plots. For example, one of the plots I want is given by
a = #(x,y) ((mod(x,1) + 0.5).^2 + (mod(y,1) - 0.5).^2 - 1)
fimplicit(a,[-1,1],'MeshDensity',500)
but the output is incorrect as far as I can tell:
The implicit function is decidedly not zero on the verticle lines. I assume something funny is happening with the fimplicit algorithm and modular arithmetic. Any ideas how to get around this? Thanks!

That probably happens because your function is discontinuous at the lines x = k with k integer, as a surface plot reveals:
fsurf(a, [-2 2])
To verify that the discontinuity is the likely reason, consider the simpler example
f = #(x,y) (2*(x>=0)-1).*(2*(y>=0)-1);
This function is discontinuous at x = 0 and at y = 0. It jumps from 1 to −1 at x = 0 and at y = 0, but it never equals 0.
fsurf(f, [-2 2])
It can be seen that fimplicit is confused by the discontinuity, and thinks the function is 0 there:
fimplicit(f,[-2,2],'MeshDensity',500)
Looking at the source code of fimplicit, the actual work is seen to be done (on R2017b at least) by the class matlab.graphics.function.ImplicitFunctionLine in the second to last line. That class is a .p file, and is thus obfuscated, which means that unfortunately its source code cannot be seen.

Related

Integral of an integral

Why does the error message of this code return: "Subscript indices must either be real positive integers or logicals.", when I am using ceil for every subscript?
A=1:1:100;
B=1:1:100;
C=1;
D=1:1:100;
E=2;
F=1:1:100;
G=1:1:100;
H=0.1:0.1:10;
fun_1=#(t)integral(#(ti)G(ceil(ti)).*H(ceil(t-ti)),0.1,t-1);
fun_2=#(t)integral(#(ti)G(ceil(ti)).*B(ceil(ti)).*(C.*D(t).^E)./F(t).*...
exp(-integral(#(x)(C.*D(ceil(x)).^E)./F(ceil(x)),ti,5)-K.*(t-ti)),0.1,t-
1,'ArrayValued',true);
I=500;
J=1000;
K=2;
fun_3=#(t)I*integral(#(ti)min(fun_2(ceil(ti)),J).*exp(-(K+I).*(t-ti)),0.1,t-
1);
t=1:1:5;
figure(1)
fplot(fun_1,t);
figure(2)
fplot(fun_2,t);
figure(3)
fplot(fun_3,t);
fplot see documentation Called as fplot(f,xinterval) evaluates your function handle f over the interval xinterval. IT will evaluate f at automatically determined steps along that given interval.
From the docs:
xinterval — Interval for x [–5 5] (default) | two-element vector of
form [xmin xmax]
You seem to be trying to specify exactly where you want your functions evaluated
t=1:1:5;
...
fplot(fun_1,t);
But it doesn't work that way. What is happening is that fplot is evaluating the function from 1 to 2 (the first 2 elements of t). So for example it might feed values of t = 1, 1.05, 1.1,... ,2 into your fun_# functions.
You can tell this because you first function which does work actually plots over the x-range of 1 to 2.
The reason you are getting a subscript indices error is because in fun_2 you have this ...(C.*D(t).^E)./F(t).*... Since fplot is feeding in values for t which are spaced between 1 and 2 (ex. 1.1) that is not a valid index.
If you really just want the values of your functions at t = 1:1:5 The you probably do not want to use fplot and just want evaluate the functions at those times and plot it.
y = feval(fun_1,t);
plot(t,y)
EDIT: The above code doesn't work
You will need to do something like the code below. This is because the 2nd & 3rd trems to the intergral function need to be scalar (1x1). If you feed them an array for t then they crash. So evaluate at each t not all at once.
figure(1)
y_1 = arrayfun(fun_1,t);
plot(t,y_1);
figure(2)
y_2 = arrayfun(fun_2,t);
plot(t,y_2);
figure(3)
y_3 = arrayfun(fun_3,t);
plot(t,y_3);
Note: the Third function still errors ... and I'm not 100% sure why. I didn't really look at it.

interval spacing on matlab

Hi I'm new to matlab and programming in general and I was wondering if anyone could tell me whats wrong with my code.
These were my instructions and values
Complete the implementation of the dampedOsc function, which evaluates and plots a graph showing the function y=e-0.8xcos 3x at a
set of points spaced at intervals of 0.1 and ranging from 0 to 3π.
The curve should be displayed using a magenta dotted line with
'pentagram' markers.
and my code:
function y = dampedOsc(x)
fplot(#(x) (exp(-0.8*x)*cos(3*x)),[0 3*pi()],'mp:')
end
All tests passed except this one:
Test 1 (Test that function has been plotted):
Actual value does not have correct size:
expectedSize =
1 95
actualSize =
1 98
Test failed.
I honestly have no idea whats gone wrong, I thought it was because of the lack
of point spaced intervals but I have no idea how to input it.
This is an interesting question, so I'll give it a stab. I would probably do something like this.
function z = dampedOsc(x)
if isvector(x) == 0
return
else
z = zeros(1,length(x));
for n = 1 : length(x)
y = exp(-0.8 .* x(n)) .* cos(3 .* x(n));
z(1,n) = y;
end
end
z
end
Then, calling that dampedOsc function from another script, should give the figure.
plot([0 : 0.1 : (3*pi)],dampedOsc(x),'mp:')
I don't have MATLAB in front of me right now, but I think this should work. If it doesn't, I can fix it. Good luck with your project!

integers can only be combined with integers of same class or scalar doubles error

I do not know what this error means or how to fix it. I am trying to perform an image rotation in a separate space of coordinates. When defining the reference space of the matrix to be at zero, I am getting the error that integers can only be comibined with integers of the same class or scalar doubles. the line is
WZcentered = WZ - [x0;yo]*ones(1,Ncols);
WZ is classified as a 400x299x3 unit 8, in the workspace. It is an image. x0 and y0 are set to 0 when the function is called. How can I fix this issue/what exactly is happening here?
Also, when I do the same thing yet make WZ to be equal to double(WZ) I get the error that 'matrix dimensions must agree.' I am not sure what the double function does however. Here is the whole code.
function [out_flag, WZout, x_final, y_final] = adopted_moveWZ(WZ, x0, y0);
%Initial Test of plot
[Nrows,Ncols]=size(WZ);
if Nrows ~= 2
if Ncols ==2
WZ=transpose(WZ); %take transpose
[Nrows,Ncols]=size(WZ); %reset the number of rows and columns
else
fprintf('ERROR: Input file should have 2-vectors for the input points.\n');
end
end
plot(WZ(1,:),WZ(2,:),'.')
title('These are the original points in the image');
pause(2.0)
%WZorig = WZ;
%centering
WZcentered = WZ - ([x0;y0] * ones(1,Ncols));
FigScale=400;
axis([-FigScale 2*FigScale -FigScale 2*FigScale])
disp('Hit any key to start the animation');
pause;
SceneCenter = zeros(Nrows,Ncols);
WZnew = WZcentered;
for ii=0:20
%rotate
R = [cos(pi/ii) -sin(pi/ii) 0; sin(pi/ii) cos(pi/ii) 0; 0 0 1];
WZnew = R * WZnew;
plot(WZnew(1,:),WZnew(2,:),'.')
%place WZnew at a different place in the scene
SceneCenter = (ii*[30;40])*ones(1,Ncols);
plot(SceneCenter(1,:) + WZnew(1,:), SceneCenter(2,:) + WZnew(2,:),'.')
axis([-FigScale 2*FigScale -FigScale 2*FigScale])
pause(1.0);
end
%Set final values for output at end of program
x_final = SceneCenter(1,1);
y_final = SceneCenter(2,1);
PPout = PPnew + SceneCenter;
This happens due to WZ and ([x0;y0] * ones(1,Ncols)) being of different data types. You might think MATLAB is loosely typed, and hence should do the right thing when you have a floating point type operated with an integer type, but this rule breaks every once in a while. A simpler example to demonstrate this is here:
X = uint8(magic(5))
Y = zeros(5)
X - Y
This breaks with the same error that you are reporting. One way to fix this is to force cast one of the operands to the other, typically up-casted to make sure the math works. When you do this, both the numbers you are working on are floating point (double precision), and so they are represented in the same byte formatting sequence in memory. This way, the '-' sign is valid, in the same way that you can say 3 apples + 4 apples = 7 apples, but 3 oranges (uint8) + 4 apples (double) = ?. The double(X) makes it clear that you really mean to use double precision arithmetic, and hence fixes the error. This is how it looks now:
double(X) - Y
After having identified this, the new error is 'matrix dimensions do not match'. This means exactly what it says. WZ is a 400x299x3 matrix, and the right hand side matrix is 2xnCols. Now can you subtract a 2D matrix from a 3D matrix of different sizes meaningfully?
Depending on what your code is really intending to do, you can pad the RHS matrix, or find out other ways to make the sizes equal.
All of this is why MATLAB includes routines to do image rotation, namely http://www.mathworks.com/help/images/ref/imrotate.html . This is part of the Image Processing Toolbox, though.

octave plot does not work properly

CODE DELETED
Hi, the code above is my (slightly modified) rooo.m file.
I'm just trying to plot the function by typing into (octave) terminal
x = 1:1:40;
plot(x, rooo(x), '+');
But this will only print the graph of y=1.
I believe it's because of the y = 1; in the first line (btw the function itself returns the right value, say when I type rooo(3)).
When I change it to some other number (say b), the graph will show y =b.
Does anyone have an idea why this is happening??
I think it's not working because if you type rooo(x) at the command line, it will return a scalar result of 1, instead of a vector. The 1 < n logical condition doesn't work as you intended to when n is a vector.
Here is a suggestion to make it work (maybe not the most elegant but it seems to work):
CODE DELETED
Which, when called as in your question, gives the following plot
The results seem to be different from the ones reported in MATLAB though.
An alternative, if you don't want to modify your function, is to change the way you call it:
>> x = 1:1:40;
>> y = ones(size(x));
>> for k=1:length(x)
y(k) = rooo(x(k));
end
>> plot(x,y,'+')
This gives the same result as the above suggestion.
It's not working because you never enter the while loop with x starting at 1. Since
1 < n == 1 < x is false at the very beginning, the function returns.
However when you call rooo(3) or actually rooo(Anything > 1) it does work. With x = 1.1:1:40 the plot looks like this ( I made it with Matlab) :

Sampling and DTFT in Matlab

I need to produce a signal x=-2*cos(100*pi*n)+2*cos(140*pi*n)+cos(200*pi*n)
So I put it like this :
N=1024;
for n=1:N
x=-2*cos(100*pi*n)+2*cos(140*pi*n)+cos(200*pi*n);
end
But What I get is that the result keeps giving out 1
I tried to test each values according to each n, and I get the same results for any n
For example -2*cos(100*pi*n) with n=1 has to be -1.393310473. Instead of that, Matlab gave the result -2 for it and it always gave -2 for any n
I don't know how to fix it, so I hope someone could help me out! Thank you!
Not sure where you get the idea that -2*cos(100*pi) should be anything other than -2. Maybe you are not aware that Matlab works in radians?
Look at your expression. Each term can be factored to contain 2*pi*(an integer). And you should know that cos(2*pi*(an integer)) = 1.
So the results are exactly as expected.
What you are seeing is basically what happens when you under-sample a waveform. You may know that the Nyquist criterion says that you need to have a sampling rate that is at least two times greater than the highest frequency component present; but in your case, you are sampling one point every 50, 70, 100 complete cycles. So you are "far beyond Nyquist". And that can only be solved by sampling more closely.
For example, you could do:
t = linspace(0, 1, 1024); % sample the waveform 1024 times between 0 and 1
f1 = 50;
f2 = 70;
f3 = 100;
signal = -2*cos(2*pi*f1*t) + 2*cos(2*pi*f2*t) + cos(2*pi*f3*t);
figure; plot(t, signal)
I think you are using degrees when you are doing your calculations, so do this:
n = 1:1024
x=-2*cosd(100*pi*n)+2*cosd(140*pi*n)+cosd(200*pi*n);
cosd uses degrees instead of radians. Radians is the default for cos so matlab has a separate function when degree input is used. For me this gave:
-2*cosd(100*pi*1) = -1.3933
The first term that I got using:
x=-2*cosd(100*pi*1)+2*cosd(140*pi*1)+cosd(200*pi*1)
x = -1.0693
Also notice that I defined n as n = 1:1024; this will give all integers from 1,2,...,1024,
there is no need to use a for loop since many of Matlab's built in functions are vectorized. Meaning you can just input a vector and it will calculate the function for every element in the vector.