"Invalid Index" error in Scilab - matlab

I'm using the following code:
for t = linspace(0,2,500)
x(t) = 1+ t^2;
y(t) = 2*t;
r(t) = sqrt((x(t))^2+(y(t))^2);
radius = 1.6
if r(t) > 0.999*radius & r(t) < 1.001*radius then
solucion = t;
end
end;
disp(solucion, "the solution is:")
Which works fine with t > 1 and different radius values.
But I get error 21: Invalid index when t takes values between 0 and 1.
I need to work with those values as well. How do I handle this?

Just so this shows up as answered in the overview:
Array indices in Scilab and MATLAB have to be positive integers (or logicals, but that is definitely not what you want here). If you need your t to vary over a range starting at 0, always write x(t+1). If you need non- integer values, still iterate over integers and compute the non-integral values from the loop index.

Related

How can I access my vectors indices when I am assigning values?

I am trying to code something in Matlab and it involves a lot of accessing elements in vectors. Below is a snippet of code that I am working on:
x(1)=1;
for i=2:18
x(i)=0;
end
for i=1:18
y(i)=1;
end
for i = 0:262124
x(i+18+1) = x(i+7+1) + mod(x(i+1),2);
y(i+18+1) = y(i+10+1) + y(i+7+1) + y(i+5+1) + mod(y(i+1), 2);
end
% n can be = 0, 1, 2,..., 262142
n = 2;
for i = 0: 262142
z(i+1) = x(mod(i+n+1, 262143)); %error: Subscript indices must either be real positive integers or logicals.
end
In the last "for" loop where I am initialising vector z(), I get an error saying: "Subscript indices must either be real positive integers or logicals." However, when I do not suppres z(i+1) by ommiting the semi colon, the program is able to run, and I can see the values of z in the workspace. Why is this?
The code I am writing in Matlab is based upon the series of instructions shown in the image below. However, I can't seem to track down my error which leads to me not being able to access the elements of x() (without not suppressing the output of z()).
I appreciate any ideas :-) Thank you!
The code breaks at that loop last iteration because , for i=262140 you get
(mod(i+n+1, 262143)) = 0
so you cant access x(0) in matlab. the first elements of any variable is x(1).
In addition, and not related to your question, this code doesn't use the advantages matlab has, instead of
for i=2:18
x(i)=0;
end
you can just write:
x(2:18)=0;
etc

Why does Matlab factorial function perceives an integer as a non-integer?

I'm trying to build a function in Matlab which generates a Taylor series around 0 for sine and the user can insert x (the value for which the sine is approximated) and a maximum error. Thus I want the function to check the maximum error and from this maximum it generates the amount of elements in the Taylor series.
I get the following error:
Error using factorial (line 20)
N must be an array of real non-negative integers.
Error in maxError (line 19)
y(x) = y(x) + (-1)^(j) * x^(2j+1)/factorial(2j+1)
Below my code.
function [n] = maxError(x,e);
%Computes number of iterations needed for a given absolute error.
n=1;
while abs(x)^(n+1)/factorial(n+1) >= e
n = n+1;
end
if mod(n,2) == 0
n=n+1;
end
y=#(x) x;
j=1;
while j<n
y(x) = y(x) + (-1)^(j) * x^(2j+1)/factorial(2j+1)
j=j+1;
end
return
I think I get the error because the factorial function can only take up integers, but the way I see it, I am feeding it an integer. Since j=1; and then gets larger by one per iteration, I don't see how Matlab can perceive this as something else than a integer.
Any help is appreciated.
You are using j as an indexing variable, which is also the complex number in Matlab, and your are forgetting a * multiply.
You can use j as a variable (not recommended!) but when you are putting a number in front of it, Matlab will stil interpret is as the complex number, and not as the variable.
Adding the multiplication symbol will solve the issue, but using i and j as variables will give you these hard to debug errors. If you had used a, the error would have been easier to understand:
>> a=10;
>> 2a+1
2a+1
↑
Error: Invalid expression. Check for missing multiplication operator, missing or
unbalanced delimiters, or other syntax error. To construct matrices, use brackets
instead of parentheses.

Convolution Kernel using a user defined function. How to deal with negative pixel values?

I've declared a function that will be used to calculate the convolution of an image using an arbitrary 3x3 kernel. I also created a script that will prompt the user to select both an image as well as enter the convolution kernel of their choice. However, I do not know how to go about dealing with negative pixel values that will arise for various kernels. How would I implement a condition into my script that will deal with these negative values?
This is my function:
function y = convul(x,m,H,W)
y=zeros(H,W);
for i=2:(H-1)
for j=2:(W-1)
Z1=(x(i-1,j-1))*(m(1,1));
Z2=(x(i-1,j))*(m(1,2));
Z3=(x(i-1,j+1))*(m(1,3));
Z4=(x(i,j-1))*(m(2,1));
Z5=(x(i,j))*(m(2,2));
Z6=(x(i,j+1))*(m(2,3));
Z7=(x(i+1,j-1))*(m(3,1));
Z8=(x(i+1,j))*(m(3,2));
Z9=(x(i+1,j+1))*(m(3,3));
y(i,j)=Z1+Z2+Z3+Z4+Z5+Z6+Z7+Z8+Z9;
end
end
And this is the script that I've written that prompts the user to enter an image and select a kernel of their choice:
[file,path]=uigetfile('*.bmp');
x = imread(fullfile(path,file));
x_info=imfinfo(fullfile(path,file));
W=x_info.Width;
H=x_info.Height;
L=x_info.NumColormapEntries;
prompt='Enter a convulation kernel m: ';
m=input(prompt)/9;
y=convul(x,m,H,W);
imshow(y,[0,(L-1)]);
I've tried to use the absolute value of the convolution, as well as attempting to locate negatives in the output image, but nothing worked.
This is the original image:
This is the image I get when I use the kernel [-1 -1 -1;-1 9 -1; -1 -1 -1]:
I don't know what I'm doing wrong.
MATLAB is rather unique in how it handles operations between different data types. If x is uint8 (as it likely is in this case), and m is double (as it likely is in this case), then this operation:
Z1=(x(i-1,j-1))*(m(1,1));
returns a uint8 value, not a double. Arithmetic in MATLAB always takes the type of the non-double argument. (And you cannot do arithmetic between two different types unless one of them is double.)
MATLAB does integer arithmetic with saturation. That means that uint8(5) * -1 gives 0, not -5, because uint8 cannot represent a negative value.
So all your Z1..Z9 are uint8 values, negative results have been set to 0. Now you add all of these, again with saturation, leading to a value of at most 255. This value is assigned to the output (a double). So it looks like you are doing your computations correctly and outputting a double array, but you are still clamping your result in an odd way.
A Correct implementation would cast each of the values of x to double before multiplying by a potentially negative number. For example:
for i = 2:H-1
for j = 2:W-1
s = 0;
s = s + double(x(i-1,j-1))*m(1,1);
s = s + double(x(i-1,j))*m(1,2);
s = s + double(x(i-1,j+1))*m(1,3);
s = s + double(x(i,j-1))*m(2,1);
s = s + double(x(i,j))*m(2,2);
s = s + double(x(i,j+1))*m(2,3);
s = s + double(x(i+1,j-1))*m(3,1);
s = s + double(x(i+1,j))*m(3,2);
s = s + double(x(i+1,j+1))*m(3,3);
y(i,j) = s;
end
end
(Note that I removed your use of 9 different variables, I think this is cleaner, and I also removed a lot of your unnecessary brackets!)
A simpler implementation would be:
for i = 2:H-1
for j = 2:W-1
s = double(x(i-1:i+1,j-1:j+1)) .* m;
y(i,j) = sum(s(:));
end
end

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.

Matlab, graphing functions

I have a homework problem, I think I did it correctly but need to make sure 100%. Can anyone check for me, before I hand it in?
Thank you.
Question:
Plot the function given by f (x) = 2 sin(2x) − 3 cos(x/2) over the in-
terval [0, 2π] using steps of length .001 (How?). Use the commands max and min to estimate the maximum and minimum points. Include the maximum and minimum points as tick marks on the x-axis and the maximum and minimum values as tick marks on the y-axis.
My code:
x=linspace(0,2*pi,6280);
f=#(x)...
2.*sin(2.*x)-3.*cos(x./2);
%f = #(x)2.*sin(2.*x)-3.*cos(x./2)
g=#(x)...
-1*(2.*sin(2.*x)-3.*cos(x./2));
%g = #(x)-1*(2.*sin(2.*x)-3.*cos(x./2))
[x3,y5]=fminbnd(g,0,2*pi);
%x3 = 4.0968
%y3 = -3.2647
[x2,y4]=fminbnd(f,0,2*pi);
%x2 =2.1864
%y2 = -3.2647
y2=max(f(x));
y3=min(f(x));
plot(x,f(x));
set(gca,'XTick',[x2 x3]);
set(gca,'YTick',[y2 y3]);
(*after I paste this code here, it appeared not as nice as I had it in my program, don't know why)
To create a vector with certain step do
x=0:0.001:2*pi;
Why do you have g(x) function and why are you using fminbind? Use MIN and MAX, return index of those values and find related x values.
[ymin, minindex] = min(f(x));
xmin = x(minindex);
For general case if you have multiple min/max values, index will contain only the first occurrence. Instead you can do:
minindex = find(y==ymin);
Or for real values to avoid precision error:
minindex = find(abs(y-ymin)<=eps);
Also your last statement returns error Values must be monotonically increasing. To avoid it sort your tick values.
set(gca,'XTick',sort([xmin xmax]));
set(gca,'YTick',sort([ymin ymax]));