Search code examples
matlabrandomcell

Add random number to cell of matrices


I have a cell, A of size 1 by 625. i.e.

A = { A1, A2, ..., A625},

where each of the 625 elements of the cell A are 3D matrices of the same size, 42 by 42 by 3.


Problem 1

Since the entries of my matrices represent concentration of red blood cells which are of very small values and I cannot simply work with randn.

For each of the matrix, I try with this command, e.g.:

A1 = A1 .*(1 + randn(42,42,3)/100)

I try with dividing by 100 to minimize the possibility of very negative number (e.g. 1.234e-6) but I cannot eliminate this possibility.

Also, is there any quick way to add different randn(42,42,3) to different 625 matrices. A + randn(42,42,3) won't work because it is adding the same set of random numbers.


Problem 2

I want to make 30 copies of the cell A by adding random numbers to each of entries of the 625 matrices. That is, I want to obtain a cell, Patients which is a cell of 1 by 30 and each of the cell element is another cell element of 625 matrices.

Patients = A % Initialization. I have 30 patients.

for i = 1 : 30;
   Patients = { Patients, Patients + `method from problem 1`};
end

I have tried to make my problems clear. I appreciate so much for your help.


Solution

  • Problem 1:

    % optional: initialize the random number generator to the current time. T
    rng('shuffle');
    A = cell(625);
    A = cellfun( @(x) rand(42,42,3), A ,'UniformOutput', false)
    

    note the differences between 'rand', 'randn', 'rng'

    from the MATLAB documentation:

    rng('shuffle') seeds the random number generator based on the current time. Thus, rand, randi, and randn produce a different sequence of numbers after each time you call rng.

    rand = Uniformly distributed random numbers -> no negative values [0, 1]

    randn = Normally distributed random numbers

    If you want to generate numbers in a special interval (from the MATLAB documentation):

    In general, you can generate N random numbers in the interval [a,b] with the formula r = a + (b-a).*rand(N,1).

    Problem 2:

    I highly recommend you to build a struct with your 30 cells. This will facilitate the indexing/looping later significantly! You can name the struct fields after your patients, so you will have less trouble keeping track of them.

    You can also build an cell-array. This is the easiest way for indexing.

    In both cases: do preallocation of the memmory! (MATLAB stores variables coherent in your memory. If the variable grows, MATLAB might have to relocate the variable...)

    % for preallocation + initialization in one step:
    A = cell(625);
    Patients.Peter = cellfun( @(x) rand(42,42,3), A ,'UniformOutput', false);
    Patients.Tom = cellfun( @(x) rand(42,42,3), A ,'UniformOutput', false);
    
    % loop through the struct like this
    FldNms = fieldnames( Patients );
    for i = 0:length(Patients)
         Patients.(FldNms{i}) = % do whatever you like
    end
    

    If you prefer an array:

    % preallocation:
    arry = cell(30);
    for i = 1:length(array)
         arry(i) = { cellfun( @(x) rand(42,42,3), A ,'UniformOutput', false) };
    end
    

    This is a lot of wild indexing and you will get a lot of trouble by using (),{} and [] for indexing.

    Think again if you need a cell array in the first place. An array of 625 matrices might suit you as well. Data structure can significantly affect the performance, the readability and your coding time!