I have a binary 3D array of the size 1024 by 1024 by 1024. I want to use a function (convhull), which has the following input:
X is of size mpts-by-ndim, where mpts is the number of points and ndim is the dimension of the space where the points reside, 2 ≦ ndim ≦ 3
How can I reshape my array into the array X which is required by this function?
Maybe "reshape" isn't the best word, because using the "reshape" function isn't enough.
What convhull is looking for is a list of subscripts of nonzero elements in your array. Given a 3D array M:
[X,Y,Z] = ind2sub(size(M), find(M));
Then you use these in convhull:
convhull(X, Y, Z);
The lone X parameter you mention in your question is just these three column vectors concatenated:
X = [X Y Z];
convhull(X);
Related
I implemented a finite differences algorithm to solve a PDE.
The grid is a structured 2D domain of size [Nx, Nz], solved Nt times.
I pre-allocate the object containing all solutions:
sol = zeros(Nx, Nz, Nt, 'single') ;
This becomes very easily too large and I get a 'out of memory' error.
Unfortunately sparse doesn't work for N-dimensional arrays.
For the sake of the question it's not important to know the values, it goes without saying that the RAM usage grows exponentially with decreasing the grid spacing and increasing the simulation time.
I am aware that I do not need to store each time instant for the purpose of the advancement of the solution. It would be sufficient to just store the previous two time steps. However, for post-processing reasons I need to access the solution at all time-steps (or at least at a submultiple of the total number).It might help to specify that, even after the solution, the grid remains predominantly populated by zeros.
Am I fighting a lost battle or is there a more efficient way to proceed (other type of objects, vectorization...)?
Thank you.
You could store the array in sparse, linear form; that is, a column vector with length equal to the product of dimensions:
sol = sparse([], [], [], Nx*Nz*Nt, 1); % sparse column vector containing zeros
Then, instead of indexing normally,
sol(x, z, t),
you need to translate the indices x, z, t into the corresponding linear index:
For scalar indices you use
sol(x + Nx*(z-1) + Nx*Nz*(t-1))
You can define a helper function for convenience:
ind = #(sol, x, y, t) sol(x + Nx*(z-1) + Nx*Nz*(t-1))
so the indexing becomes more readable:
ind(sol, x, z, t)
For general (array) indices you need to reshape the indices along different dimensions so that implicit expansion produces the appropriate linear index:
sol(reshape(x,[],1,1) + Nx*(reshape(z,1,[],1)-1) + Nx*Nz*(reshape(t,1,1,[])-1))
which of course could also be encapsulated into a function.
Check that the conversion to linear indexing works (general case, using non-sparse array to compare with normal indexing):
Nx = 15; Nz = 18; Nt = 11;
sol = randi(9, Nx, Nz, Nt);
x = [5 6; 7 8]; z = 7; t = [4 9 1];
isequal(sol(x, z, t), ...
sol(reshape(x,[],1,1) + Nx*(reshape(z,1,[],1)-1) + Nx*Nz*(reshape(t,1,1,[])-1)))
gives
ans =
logical
1
You can create a a cell array of sparse matrices to store the results. However computations can be performed on full matrices if working with a full matrix is faster than sparse matrix and convert the full matrix to sparse matrix and place it in the cell.
A sparse matrix is a large matrix with almost all elements of the same value (typically zero). The normal representation of a sparse matrix takes up lots of memory when the useful information can be captured with much less. A possible way to represent a sparse matrix is with a cell vector whose first element is a 2-element vector representing the size of the sparse matrix. The second element is a scalar specifying the default value of the sparse matrix. Each successive element of the cell vector is a 3-element vector representing one element of the sparse matrix that has a value other than the default. The three elements are the row index, the column index and the actual value. Write a function called sparse2matrix that takes a single input of a cell vector as defined above and returns the output argument called matrix, the matrix in its traditional form.
cellvec = {[2 3], 0, [1 2 3], [2 2 -3]};
matrix = sparse2matrix(cellvec)
matrix =
0 3 0
0 -3 0
By the information in the question :
In vector cell arrays it is usually the first vector used as a sparse
matrix dimension
The second element is a scalar specifying the default value of the
sparse matrix
The other vectors are used to specify the location and the value of
the element in the sparse matrix , i.e. [i, j, x] where i,j is the location
in the matrix and x is the value of the element.
So the program is simply :
function matrix=sparse2matrix(cellvec);
matrix=zeros(cellvec{1})+cellvec{2};
for i=3:length(cellvec)
matrix(cellvec{i}(1,1),cellvec{i}(1,2))=cellvec{i}(3);
end
I have a row vector x in Matlab which contains 164372 components. I now want to group these elements in another vector y, which has to contain 52 components. The first element of the vector y must be the average of the first 164372 / 52 = 3161 elements of the vector x, the second element of y must be the average of the next 3161 elements of x, etc. This continues until I have taken all of the 52 averages of the elements in the vector x and placed them in y.
How can I implement this in Matlab? Is there some built-in function that lets me sum elements from a certain index to another index?
Thank you kindly for any help!
With reshape and mean:
x = rand(1,164372); % example data
N = 52; % block size. Assumed to divide numel(x)
result = mean(reshape(x, numel(x)/N, []), 1)
What this does is: reshape the vector into a 52-row matrix in the usual column-major order, and then compute the mean of each column.
I have a list corresponding to the matrix of a .png image without the RGB transparency information. The dimension of the matrix is 128 128 3. So I have a 128 x 128 matrix coding the red hues in each pixel; a 128 x 128 matrix coding the greens; and a 128 x 128 matrix for the blues. There is no transparency in the image, but to write this .png, I think I need to include a 128x128 matrix of 1's and tag it to my list so as to get a 128 x 128 x 4 matrix.
How can I append this matrix of ones to my list?
I have a list named compressed with these dimensions (128 128 3), and I've tried multiple single and double-bracketed ways to include something like matrix(rep(1, 128^2), nrow= 128) without success.
The idea is to eventually save it as:
require(png)
writePNG(compressed, "compressed.picture")
without doing away with color.
Here's an example depending on whether you have an array or a list of matrices currently. Looking at ?writePNG it seems you need a n x n x 4 array as the final product, so I included a conversion from list to array.
Plenty of other solutions are offered e.g. here.
n <- 4
# generate matrices
r <- matrix(runif(n^2), n, n)
g <- matrix(runif(n^2), n, n)
b <- matrix(runif(n^2), n, n)
a <- matrix(1, n, n)
# list or array format for the data you have
li <- list(r, g, b)
ar <- array(c(r, g, b), dim = c(n, n, 3))
# appending the fourth matrix
li[[4]] <- a
ar1 <- array(c(ar, a), dim = c(n, n, 4))
# alternatively for array
library(abind)
ar2 <- abind(ar, a, along = 3)
# if you have a list and need an array
sapply(li, identity, simplify = "array")
The information that i have found on the internet for this is not explained very well. I would like to know how to go about implementing a 2-D array of double-precision floating point numbers. I would like the dimensions of the array to be variable so if I say .double 100, then I am wasting a lot of memory because that may not be the size of the array e.g. could be 5 x 5. Would I have to use the stack to solve this problem? Or how else could I go about it? Also if someone could explain how to efficiently fill the array it would be much appreciated!
You can implement any rectangular 2D array as 1D array using row-major order, the only different would be is in calculating the address of the element.
For example if you have a 3×5 array of double's and you want to access the element array[x][y], you can calculate its address using the formula:
address of array[x][y] = base of array + 8 * (5 * x + y)
where base of array is the base address of array or array[0][0], 8 is the size of an element sizeof(double) and 5 is the number of columns.