When I run this piece of code:
dx = 4/(nx-1);
dy = 2/(ny-1);
phinew(2:ny-1,2:nx-1) = ((dy^2*(phiold(1:ny-2,2:nx-1)+phiold(3:ny,2:nx-1))+dx^2*(phiold(2:ny-1,1:nx-2)+phiold(2:ny-1,3:nx)))/(2*(dx^2+dy^2))-poissonf);
Within my code, the piece of code operates correctly, taking an input of an nx by ny matrix and outputting a nx by ny matrix. When I run the following code in the exact same position however:
phinew = Smoothing(phiold,poissonf,nx,ny)
Where the function "Smoothing" is defined as:
function [phinew,dx,dy] = Smoothing(phiold,poissonf,nx,ny)
dx = 4/(nx-1);
dy = 2/(ny-1);
phinew(2:ny-1,2:nx-1) = ((dy^2*(phiold(1:ny-2,2:nx-1)+phiold(3:ny,2:nx-1))+dx^2*(phiold(2:ny-1,1:nx-2)+phiold(2:ny-1,3:nx)))/(2*(dx^2+dy^2))-poissonf);
end
The function returns a nx-1 by ny-1 matrix for an nx by ny input.
I cannot wrap my head around why this is occurring at all. The output matrix is the exact same as it should be, except the last column and row are missing entirely. My code is iterative and so requires these to be of the same size, so I cannot move on until this issue is resolved.
Thank you for your time and your help. You people are life-savers.
When you run your code in the command window, phinew already exists. In your command window, do clear phinew before you pasting in those three lines, and you'll find that phinew is then nx-1 by ny-1, as you get from your function.
If you want to force your function to return nx by ny, put phinew = zeros(nx,ny); at the start of the function, or set the last column and row to whatever you want them to be.
EDIT: Responding you your comment "why [does the RHS of the main assignment output] a 48x48 matrix? Directly before the command is run phiold, phinew and poissonf are all 50x50."
I don't think poissonf is 50x50: that would lead to the error Matrix dimensions must agree, because poissonf is being added to the rest of the expression which is part of phiold, so I'll ignore poissonf in the following.
The RHS is always ny-2 by nx-2, even on the first iteration. You can see this by assigning the RHS to an intermediate variable, e.g. phipiece = ... and checking size(phipiece). The reason phinew (if created anew) is 49x49 is because it is assigned to (2:ny-1,2:nx-1), which will create a ny-1 by nx-1 matrix and leave the first row and column as zero.
If you use phinew = zeros(nx,ny); first, then the first and last rows and columns are left as zero.
Related
In Octave I defined a function in a separate file square.m
function y = square(x)
y = x^2;
endfunction
In other file script.m I have
disp("Hello World 2");
fplot( #(x) square(x),[-1 1])
And I get
error: for x^A, A must be a square matrix. Use .^ for elementwise power.
Also if I try
y = x.^2;
inside the function I get the exact same message
The reason you're getting that error is because fplot is passing the range you specified all at once as a vector, treating your function as a vectorised function, expecting a vector input and returning a vector output.
You can confirm this by turning "debug on error" to true, by doing debug_on_error(true), run the offending line, and inspect x.
Therefore, inside your function, things go wrong, because you're trying to get the square of a vector, which is an illegal operation (mathematically speaking).
Converting your function to y = x.^2 should work in this case, because you'd be converting each element of the vector to its square, which is what you want. But obviously, simply changing ^ to .^ might not work for every problem.
In general, it's better to create your own 'range' and 'outputs' and plot them directly using plot; this gives you far more control, and you can inspect the inputs and outputs first to ensure you're plotting what you think you're plotting.
Welcome to StackOverflow!
I have just tried your code on https://octave-online.net/ (no need to create an account nor even the files).
The second version works "as expected": y = x .^ 2; inside the function.
Make sure you saved the file after the modification?
I'm relatively new to Scilab and I would like to find the indices of a number in my matrix.
I have defined my number as maximal deformation (MaxEYY) and on displaying it, it is correct (I can double check in my *.csv file). However, when I want to know exactly where this number lies in my matrix using the find command, only (1,1) is returned, but I know for a fact that this number is located at (4,8).
My matrix is not huge (4x18) and I know that this number only occurs once. On opening the *.csv file, I removed the headers so there is no text.
Can anyone help me with this?
N=csvRead("file.csv",",",".",[],[],[],[],1)
EYY=N(:,8);
MaxEYY=max(EYY);
MinEYY=min(EYY);
[a,b]=find(MaxEYY);
disp([a,b]);
First, you need to understand how find() works: it looks for values of true or false in a matrix. So if you want to find a certain value in it, you should do find(value == matrix).
Then, notice that in your code, you are applying find() to MaxEYY, which is a single value, that is, a scalar, a 1-by-1 matrix. When you do that, you can only get (1,1) or [] as results.
Now, combining these two informations, this what you should've done:
[a, b] = find(EYY == MaxEYY);
Also, there is a quicker way to get this indices: max() can also return the indices of the maximum value by doing
[MaxEYY, inds] = max(EYY);
And the same goes for min().
I am to find the smallest distance between a given set of points and the origin. I have a matrix with 2 columns and 10 rows. Each row represents coordinates. One point consists of two coordinates and I would like to calculate the smallest distance between each point and to the origin. I would also like to determine which point gave this smallest distance.
In Octave, I calculate this distance by using norm and for each point in my set, I have a distance associated with them and the smallest distance is obviously the one I'm looking for. However, the code I wrote below isn't working the way it should.
function [dist,koor] = bonus4(S)
S= [-6.8667, -44.7967;
-38.0136, -35.5284;
14.4552, -27.1413;
8.4996, 31.7294;
-17.2183, 28.4815;
-37.5100, 14.1941;
-4.2664, -24.4428;
-18.6655, 26.9427;
-15.8828, 18.0170;
17.8440, -22.9164];
for i=1:size(S)
L=norm(S(i, :))
dist=norm(S(9, :));
koor=S(9, :) ;
end
i = 9 is the correct answer, but I need Octave to put that number in. How do I tell Octave that this is the number I want? Specifically:
dist=norm(S(9, :));
koor=S(9, :);
I cannot use any packages. I found the geometry package online but I am to solve the task without additional packages.
I'll work off of your original code. Firstly, you want to compute the norm of all of the points and store them as individual elements in an array. Your current code isn't doing that and is overwriting the variable L which is a single value at each iteration of the loop.
You'll want to make L an array and store the norms at each iteration of the loop. Once you do this, you'll want to find the location as well as the minimum distance itself. That can be done with one call to min where the first output gives you the minimum distance and the second output gives you the location of the minimum. You can use the second output to slice into your S array to retrieve the actual point.
Last but not least, you need to define S first before calling this function. You are defining S inside the function and that will probably give you unintended results if you want to change the input into this function at each invocation. Therefore, define S first, then call the function:
S= [-6.8667, -44.7967;
-38.0136, -35.5284;
14.4552, -27.1413;
8.4996, 31.7294;
-17.2183, 28.4815;
-37.5100, 14.1941;
-4.2664, -24.4428;
-18.6655, 26.9427;
-15.8828, 18.0170;
17.8440, -22.9164];
function [dist,koor] = bonus4(S)
%// New - Create an array to store the distances
L = zeros(size(S,1), 1);
%// Change to iterate over number of rows
for i=1:size(S,1)
L(i)=norm(S(i, :)); %// Change
end
[dist,ind] = min(L); %// Find the minimum distance
koor = S(ind,:); %// Get the actual point
end
Or, make sure you save the above function in a file called bonus4.m, then do this in the Octave command prompt:
octave:1> S= [-6.8667, -44.7967;
> -38.0136, -35.5284;
> 14.4552, -27.1413;
> 8.4996, 31.7294;
> -17.2183, 28.4815;
> -37.5100, 14.1941;
> -4.2664, -24.4428;
> -18.6655, 26.9427;
> -15.8828, 18.0170;
> 17.8440, -22.9164];
octave:2> [dist,koor] = bonus4(S);
Though this code works, I'll debate that it's slow as you're using a for loop. A faster way would be to do this completely vectorized. Because using norm for matrices is different than with vectors, you'll have to compute the distance yourself. Because you are measuring the distance from the origin, you can simply square each of the columns individually then add the columns of each row.
Therefore, you can just do this:
S= [-6.8667, -44.7967;
-38.0136, -35.5284;
14.4552, -27.1413;
8.4996, 31.7294;
-17.2183, 28.4815;
-37.5100, 14.1941;
-4.2664, -24.4428;
-18.6655, 26.9427;
-15.8828, 18.0170;
17.8440, -22.9164];
function [dist,koor] = bonus4(S)
%// New - Computes the norm of each point
L = sqrt(sum(S.^2, 2));
[dist,ind] = min(L); %// Find the minimum distance
koor = S(ind,:); %// Get the actual point
end
The function sum can be used to sum over a dimension independently. As such, by doing S.^2, you are squaring each term in the points matrix, then by using sum with the second parameter as 2, you are summing over all of the columns for each row. Taking the square root of this result computes the distance of each point to the origin, exactly the way the for loop functions. However, this (at least to me) is more readable and I daresay faster for larger sizes of points.
I am having this issue with a function that I have created in matlab. I have variables h = 0.2 and x = (0:h:1)'. 'x' is a row vector with 5 elements. I am using the following function in matlab
function d = dplus(fstring, x, h)
d=0;
end
whenever I plug the following into matlab
dplus('prob4Func',x,h)
I get this error "??? Index exceeds matrix dimensions." This makes absolutely no sense since I am not even using the vector 'x' anywhere in the function. Is there some subtlety to matlab I am missing?
I just needed to use 'clearvars dplus' to get it working. Thanks Navan!
I got this MATLAB function. When I ran it, the following error messege showed up. Can anybody give me some hint? Thank you. The code is also shown below.
[h,im_matched,theta,I,J]=im_reg_MI('keyframe1.jpg','keyframe2.jpg', 0, 1)
??? Undefined function or variable "h".
Error in ==> im_reg_MI at 74
[a, b] = max(h(:));% finding the max of MI and indecises
Below is the code.
[h,im_matched, theta,I,J]=im_reg_MI(image1, image2, angle, step)
[m,n]=size(image1);
[p,q]=size(image2);
[a,b]=size(angle);
im1=round(image1);
for k=1:b
J = rotate_image(angle(k),image2); %rotated cropped IMAGE2
image21=round(J);
[m1,n1]=size(image21);
for i=1:step:(m1-m)
for j=1:step:(n1-n)
im2=image21(i:(i+m-1),j:(j+n-1)); % selecting part of IMAGE2 matching the size of IMAHE1
im2=round(im2);
h(k,i,j)=MI2(im1,im2); % calculating MI
end
end
end
[a, b] = max(h(:));% finding the max of MI and indecises
The problem is that you aren't actually passing in image data for the image1 and image2 arguments. You're just passing character strings containing the image file names 'keyframe1.jpg' and 'keyframe2.jpg'.
You need to load the image data from the files first using IMREAD, then pass the image data to im_reg_MI. Assuming the images are in the current working directory, you would do something like this:
image1 = imread('keyframe1.jpg');
image2 = imread('keyframe2.jpg');
[h,im_matched,theta,I,J] = im_reg_MI(image1,image2,0,1);
EDIT:
There seems to be an additional error within im_reg_MI that occurs if image21 (the rotated version of image2) is the same size or smaller than image1 for one or more of its dimensions. If m1 were less than or equal to m and/or n1 were less than or equal to n, then one or both of the loops for i or j would never be entered since 1:step:(m1-m) and/or 1:step:(n1-n) would create an empty vector. Thus, the inner loop code would never be run and h would never be created.
And one extra note...
I noticed that the function im_reg_MI appears to treat the two images as 2-D, which means they must be intensity images (i.e. grayscale or binary image data). If you're dealing with indexed or RGB image data, I don't think im_reg_MI is going to handle them properly.