Error when creating a tensor from a for loop
4 views (last 30 days)
Show older comments
I want to write a function that stores calculated values depending on the position in x1, x2 and x3 in a tensor (3D array). My current code works with a regular spacing of 1 between the array values:
F_array = zeros(27, 27, 27);
for x1 = -13:1:13
for x2 = -13:1:13
for x3 = -13:1:13
% F = f(x1, x2, x3);
F_array(x1+14, x2+14, x3+14) = F;
end
end
end
To get more accurate result, I tried to reduce the spacing between the array values to 0.5:
F_array = zeros(53, 53, 53);
for x1 = -13:0.5:13
for x2 = -13:0.5:13
for x3 = -13:0.5:13
% F = f(x1, x2, x3);
F_array(x1+27, x2+27, x3+27) = F;
end
end
end
However, now I get the following error message:
"Index in position 3 is invalid. Array indices must be positive integers or logical values."
I don't see any overall difference in the codes. Can anyone tell me what is causing this problem?
0 Comments
Accepted Answer
Stephen23
on 2 Jan 2025
Edited: Stephen23
on 2 Jan 2025
"Can anyone tell me what is causing this problem?"
Explanation
Look at the values that you are using as indices. For the 1st code using integer steps, e.g.:
x1 = -13:1:13;
x1+14
For the 2nd code using steps of 0.5:
x1 = -13:0.5:13;
x1+27
Are MATLAB indices allowed to contain fractional parts? (hint: no). Is 14.5 a valid index?(hint: no).
"I don't see any overall difference in the codes."
Your computer does not care what you "see" or imagine or want or hope or believe your code is doing. To debug code you need to look at what it actually is doing. Usually the first step is to display the relevant values, to see if they make sense.
Error messages are also very important.
Solution
In general with MATLAB it is much easier and more reliable to loop over indices, not over data values. Once you learn to do this, your code will be more robust and much more generalised. In your specific case, do NOT fiddle around with offsets and scaling: this is a dead-end approach that forces you to awkwardly modify all of your code every time you want to change any step size or start point. Ugh, bad code design! It forces you into writing code that makes you do more work.
However you can easily write code that works for any data vector (including data vectors with e.g. unequal step sizes or real-world sampled data):
V1 = -13:0.5:13; % the step size here is irrelevant
V2 = -13:0.5:13; % the step size here is irrelevant
V3 = -13:0.5:13; % the step size here is irrelevant
N1 = numel(V1);
N2 = numel(V2);
N3 = numel(V3);
F_array = nan(N1,N2,N3); % automatically adjust the output array size
for k1 = 1:N1
for k2 = 1:N2
for k3 = 1:N3
F = f(V1(k1),V2(k2),V3(k3));
F_array(k1,k2,k3) = F;
end
end
end
Now you can change the step size or start value and it will work automatically adjust the output array size and the indices and how many iterations without you needing to make any other changes... this is how you write generalised code.
Do NOT fiddle around with offsets & scaling, unless you really want fragile code that is painful to modify and maintain.
More Answers (1)
Sameer
on 2 Jan 2025
Hi @Bruce
The issue arises because the indices in MATLAB must be positive integers. When you change the spacing between the values to 0.5, the indices "x1+27", "x2+27", and "x3+27" become non-integers, which is not allowed for indexing.
To fix this, you need to convert the indices to integers. One way to do this is by scaling the indices appropriately.
You can do this by multiplying the indices by 2 to account for the 0.5 spacing and then adding an offset.
Here's how you can modify your code:
F_array = zeros(53, 53, 53);
for x1 = -13:0.5:13
for x2 = -13:0.5:13
for x3 = -13:0.5:13
% F = f(x1, x2, x3);
idx1 = round((x1 + 13) * 2 + 1);
idx2 = round((x2 + 13) * 2 + 1);
idx3 = round((x3 + 13) * 2 + 1);
F_array(idx1, idx2, idx3) = F;
end
end
end
Hope this helps!
See Also
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!