Search code examples
matlabsampling

Custom subarray of a multidimensional array


I have an array A which has a size [N1 N2 N3 3 3]. Array A can be considered as a rectangular box in three dimensions that for each of its element, an array of size [3 3] is defined, and here I call it B. In other words, B with size [3 3] is defined for each point in the domain.

I am trying to subdivide the rectangular box into small cubes of size d×d×d, where d is an even number. Also, there should be 50% overlap between adjacent cubes and . For example, let's say:

A; % size(A) = [14 16 20 3 3];
d = 4;

With the above example, the sampling will be as follows. The cubes along with with first dimension of A, i.e., 1:14 will include the following elements of A:

cube1: 1, 2, 3, 4
cube2: 3, 4, 5, 6
cube3: 5, 6, 7, 8
cube4: 7, 8, 9, 10
cube5: 9, 10,11,12
cube6: 11,12,13,14

along the second dimension of A, i.e., 1:16, we have:

cube1: 1, 2, 3, 4
cube2: 3, 4, 5, 6
cube3: 5, 6, 7, 8
cube4: 7, 8, 9, 10
cube5: 9, 10,11,12
cube6: 11,12,13,14
cube7: 13,14,15,16

And finally along the third dimension of A, i.e., 1:20:

cube1: 1, 2, 3, 4
cube2: 3, 4, 5, 6
cube3: 5, 6, 7, 8
cube4: 7, 8, 9, 10
cube5: 9, 10,11,12
cube6: 11,12,13,14
cube7: 13,14,15,16
cube8: 15,16,17,18
cube9: 17,18,19,20

Now Anew will have a size [6 7 9 3 3] and the value at each of its element will be the summation of each element of B over all the element of A that are in each cube. For example, Anew(1, 4, 9, 1, 1) is actually:

A(elements of cube1, elements of cube4, elements of cube9, 1, 1)

or in other words, A(1:4, 7:10, 17:20). Therefore:

Anew(1, 4, 9, 1, 1) = 0;
for i = 1:4           % cube1 along with first dimension uses 1, 2, 3, 4
    for j = 7:10      % cube4 along with the second dimension uses 7, 8, 9, 10
        for k = 17:20 % cube9 along with the third dimension uses 17, 18, 19, 20
            Anew(1, 4, 9, 1, 1) = Anew(1, 4, 9, 1, 1) + A(i, j, k, 1, 1);
        end
    end
end

In the above for loop, A(i, j, k, 1, 1) is B(1, 1) at point (i, j, k) in the original domain. Could someone help me how I should approach in a vectorize fashion?


Solution

  • The rows of cube1,2,etccan be given by 2*n-1:2*n+2 where n is the row number. this will be stored as an anonymous function to simplify the later code...

    ind = @(n) 2*n-1 : 2*n+2
    

    Vectorising the loop in the question, for point(ii,jj,kk) the value of B(ll,mm) a possible solution is as follows:

    sum(reshape(A(ind(ii),ind(jj),ind(kk),ll,mm),1,[]))
    

    where the above code gets all required elements, reshapes into a column and then sums


    To generate values for all ii,jj,kk,ll,mm combinations

    sA=size(A);
    nii=sA(1)/2-1; njj=sA(2)/2-1; nkk=sA(3)/2-1; nll=sA(4); nmm=sA(5) %Sizes for grid
    
    [ii,jj,kk,ll,mm]=ndgrid(1:nii,1:njj,1:nkk,1:nll,1:nmm);  %Creates grid
    
    Anew=arrayfun(@(ii,jj,kk,ll,mm)sum(reshape(A(ind(ii),ind(jj),ind(kk),ll,mm),...
          1,[])),ii,jj,kk,ll,mm);                            %Apply function to grid