Is there a way to rotate 3D arrays in Julia? - arrays

I am trying to rotate a 3D array in julia as if it represents a physical object in 3D space. Essentially, I want to know if there is a way to rotate an array by increments of 90 degrees along the x-, y-, and/or the z-axis.
In 2D it would be something like this if I were to rotate counter-clockwise...
1 2 3 3 6 9
4 5 6 -----> 2 5 8
7 8 9 1 4 7
I would want the same logic to apply in 3D as well.
Any help is appreciated.

For two-dimensional Matrices you have functions such as rotl90, rotr90 and rot180. Those can be combined with mapslices to get the desired effect. For an example below is a rotation over dimensions 1 and 2 for each cut of array in the dimension 3.
julia> A=collect(reshape(1:27,3,3,3))
3×3×3 Array{Int64,3}:
[:, :, 1] =
1 4 7
2 5 8
3 6 9
[:, :, 2] =
10 13 16
11 14 17
12 15 18
[:, :, 3] =
19 22 25
20 23 26
21 24 27
julia> mapslices(rotr90,A,dims=[1,2])
3×3×3 Array{Int64,3}:
[:, :, 1] =
3 2 1
6 5 4
9 8 7
[:, :, 2] =
12 11 10
15 14 13
18 17 16
[:, :, 3] =
21 20 19
24 23 22
27 26 25

Related

Matlab: repeat and concatenate rows and cols into new array

I have two 4-by-4 arrays:
a1 = [ 1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16 ]
a2 = [ 17 18 19 20; 21 22 23 24; 25 26 27 28; 29 30 31 32 ]
I need to create 16-by-8 array C:
1 2 3 4 17 18 19 20
1 2 3 4 21 22 23 24
1 2 3 4 25 26 27 28
1 2 3 4 29 30 31 32
5 6 7 8 17 18 19 20
5 6 7 8 21 22 23 24
5 6 7 8 25 26 27 28
5 6 7 8 29 30 31 32
9 10 11 12 17 18 19 20
9 10 11 12 21 22 23 24
9 10 11 12 25 26 27 28
9 10 11 12 29 30 31 32
13 14 15 16 17 18 19 20
13 14 15 16 21 22 23 24
13 14 15 16 25 26 27 28
13 14 15 16 29 30 31 32
The left half (from 1st to 4th column) of the result array C should repeat 4 times i-th row of the array a1, the right half (from 5th to 8th column) should repeat 4 times the array a2.
Below is my code.
p=4
n=4
for i=1:n
b=n*i;
a=n*(i-1)+1;
for j=1:p
for k=a:b
C(k,j)=a1(i,j);
end;
end;
end;
for i=1:n
b=n*i;
a=n*(i-1)+1;
for j=p+1:2*p
l=1;
for k=a:b
C(k,j)=a2(l,j-p);
l=l+1;
end;
end;
end;
C;
size_C=size(C)
Question. Is it possible to create result array C without for-loop? Which functions can I use?
Yes it's possible.
One way of doing it is by using kron and repmat
C = [ kron(a1, ones(4,1)) repmat(a2, 4, 1)]
Perhaps the 4 should be derived from the size of one of the matrixes
You can use ndgrid to generate the row indices and then concatenate:
[ii, jj] = ndgrid(1:size(a2,1), 1:size(a1,1));
C = [a1(jj,:) a2(ii,:)];
With focus on performance, here's one using reshape and repmat -
% Store sizes
M = size(a1,1);
N = size(a2,1);
% Get the replicated version for a1 and a2 separately
parte1 = reshape(repmat(reshape(a1,1,M,[]),[N,1,1]),M*N,[])
parte2 = repmat(a2,[M,1]);
% Do columnar concatenatation for final output
out = [parte1 parte2]
Sample run on a generic case -
a1 = % 3 x 4 array
5 2 6 9
7 4 7 6
9 8 6 1
a2 = % 2 x 5 array
7 7 1 9 2
6 8 8 7 9
out =
5 2 6 9 7 7 1 9 2
5 2 6 9 6 8 8 7 9
7 4 7 6 7 7 1 9 2
7 4 7 6 6 8 8 7 9
9 8 6 1 7 7 1 9 2
9 8 6 1 6 8 8 7 9

Julia : Cartesian product of multiple arrays

I would like to compute a product iterator using Iterators.jl.
Let's say I have an array of UnitRanges tab with a priori unknown size.
I would like to compute the cartesian product of the elements of tab.
For example if tab length is 2 and tab[1] = a and tab[2] = b I want to compute product(a,b) from Iterators.jl.
I want to make a generic function that compute the cartesian product of every component in tab.
I tried something like this
prod = tab[1]
for i in tab[2:end]
prod = product(prod,i)
end
However if tab is length 3, components a,b and c, I obtain in prod elements under the form (1,(3,2)) and not (1,3,2). With 1 element of c, 3 element of b and 2 element of a.
In v0.5, there is now Base.product, which is much better than Iterators.product.
It can handle as many arrays as needed, and it even has a shape:
julia> collect(Base.product([1, 2], [3, 4]))
2×2 Array{Tuple{Int64,Int64},2}:
(1,3) (1,4)
(2,3) (2,4)
julia> collect(Base.product(1:5, 1:3, 1:2, 1:2))
5×3×2×2 Array{NTuple{4,Int64},4}:
[:, :, 1, 1] =
(1,1,1,1) (1,2,1,1) (1,3,1,1)
(2,1,1,1) (2,2,1,1) (2,3,1,1)
(3,1,1,1) (3,2,1,1) (3,3,1,1)
(4,1,1,1) (4,2,1,1) (4,3,1,1)
(5,1,1,1) (5,2,1,1) (5,3,1,1)
[:, :, 2, 1] =
(1,1,2,1) (1,2,2,1) (1,3,2,1)
(2,1,2,1) (2,2,2,1) (2,3,2,1)
(3,1,2,1) (3,2,2,1) (3,3,2,1)
(4,1,2,1) (4,2,2,1) (4,3,2,1)
(5,1,2,1) (5,2,2,1) (5,3,2,1)
[:, :, 1, 2] =
(1,1,1,2) (1,2,1,2) (1,3,1,2)
(2,1,1,2) (2,2,1,2) (2,3,1,2)
(3,1,1,2) (3,2,1,2) (3,3,1,2)
(4,1,1,2) (4,2,1,2) (4,3,1,2)
(5,1,1,2) (5,2,1,2) (5,3,1,2)
[:, :, 2, 2] =
(1,1,2,2) (1,2,2,2) (1,3,2,2)
(2,1,2,2) (2,2,2,2) (2,3,2,2)
(3,1,2,2) (3,2,2,2) (3,3,2,2)
(4,1,2,2) (4,2,2,2) (4,3,2,2)
(5,1,2,2) (5,2,2,2) (5,3,2,2)
The shape is extremely useful for map. For instance, here's how to create a multiplication table using Base.product:
julia> map(prod, Base.product(1:9, 1:9))
9×9 Array{Int64,2}:
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
Of course, if you don't need the shape, then you are free to ignore it — it will still iterate properly.
And Base.product is fast too!

How to fill an array by row in Julia

I would like to fill an Array object by row in the Julia language.
The reshape function wants to fill by column (Julia is column major).
julia> reshape(1:15, 3,5)
3x5 Array{Int64,2}:
1 4 7 10 13
2 5 8 11 14
3 6 9 12 15
Is there a way to persuade it to fill by row? It feels like there should be an obvious answer, but I've not found one.
One suggestion:
julia> reshape(1:15, 5, 3) |> transpose
3x5 Array{Int64,2}:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
With array comprehension:
julia> [i+5*j for j=0:2,i=1:5]
3x5 Array{Int64,2}:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
Ah, it's just more than 10x times faster than other suggestion (actually, an embarrassing 100x on my initial benchmark).
permutedims is another choice when dealing with more general multi-way arrays.
julia> permutedims(reshape(1:24, 2,3,4), [2,1,3])
3x2x4 Array{Int64,3}:
[:, :, 1] =
1 2
3 4
5 6
[:, :, 2] =
7 8
9 10
11 12
[:, :, 3] =
13 14
15 16
17 18
[:, :, 4] =
19 20
21 22
23 24
however, it's slowest among other suggestions in your specific case.

how do I combine only the vectors - Matlab

How do I combine all the vectors in small subsets of vectors in Matlab?
a= [5 6 7] b = [8 9 10] c=[11 12 13] d=[14 15 16] e=[17 18 19]
a combine with b and c:
Outcome:
M1= [ 5 6 7 8 9 10 11 12 13]
a with b and d:
M2 = [5 6 7 8 9 10 14 15 16]
and so on .....
This answer covers the case for an arbitrary number of vectors. The vectors are assumed to be row vectors of equal length.
Let your example data be defined as
a = [5 6 7]; b = [8 9 10]; c = [11 12 13]; d = [14 15 16]; e = [17 18 19];
vectors = {a, b, c, d, e}; %// cell array with any number of row vectors of equal size
n = 3; %// desired subset size
Then: generate all combinations of indices, use that to index into vectors, concatenate into one big row vector, and reshape that to obtain the desired result:
combs = nchoosek(1:numel(vectors), n);
result = reshape([vectors{combs.'}], numel(vectors{1})*n, []).';
This gives a matrix whose first row is your M1, second row is M2 etc:
result =
5 6 7 8 9 10 11 12 13
5 6 7 8 9 10 14 15 16
5 6 7 8 9 10 17 18 19
5 6 7 11 12 13 14 15 16
5 6 7 11 12 13 17 18 19
5 6 7 14 15 16 17 18 19
8 9 10 11 12 13 14 15 16
8 9 10 11 12 13 17 18 19
8 9 10 14 15 16 17 18 19
11 12 13 14 15 16 17 18 19
You can use the cat function:
res = cat(2,a,b,c);
or simply the [] syntax:
res = [a b c];
In both cases, res will contain [5 6 7 8 9 10 11 12 13].
Best,
Use nchoosek.
a = [5 6 7]; b = [8 9]; c = [11 12 13]; d = [14 15 16]; e = [17 18 19];
N = 3;
x = {a,b,c,d,e};
y = nchoosek(x,N);
And you have all the combination of your arrays taken N at a time in a cell array. Each row i of the cell x is a combination, so to have it back as a row vector just do
horzcat(y{i,:})
Or, if you want to get them all and put them in a cell array of size n_combs
n_combs = size(y,1);
out = cell(0,n_combs);
for i = 1 : n_combs
out{i} = horzcat(1, y{i,:});
end
There is no constraint on the size of the arrays that you want to combine, e.g., you can combine
a = [5 7]; b = [8 9]; c = [11]; d = [20 14 15 16]; e = [17 18 19];
However, if you must put together all the combination in a matrix, then the arrays have to be of the same size. In this case Luis Mendo's answer does the job.
Finally, if repetitions are allowed use nmultichoosek instead of nchoosek.

What is the meaning of the addition at the end of this array declaration?

I'm tasked with implementing an algorithm which was supplied as Matlab (which none of us have any experience with) into our c++ application.
There is an array declared as such:
encrypted = [18 10 20 13 6 25 21 13 17;
2 26 4 29 22 9 5 29 1;
19 11 21 12 7 24 20 12 16;
% ... many rows like this ...
13 21 11 18 25 6 10 18 14]+1;
What is the semantic meaning of the +1 at the end of the array declaration?
Simply adding 1 to each entry:
>> [1 2 3; 4 5 6]
ans =
1 2 3
4 5 6
>> [1 2 3; 4 5 6] + 1
ans =
2 3 4
5 6 7
If you have MATLAB around, you could have figured that out by just trying. If you do not, I hope you have a very clear picture of what the code is doing and write a good test suite, since you won't be able to compare your new code's output to the MATLAB one.
The +1 means that all elements of the written matrix will be increased by one.
Example
out = [1 2;
3 4] + 1;
disp(out)
2 3
4 5

Resources