Search code examples
idl-programming-language

How can I save float arrays in a multiple dimension array in IDL?


I am trying to save many float arrays in a multiple dimsensional array. Each float array belongs to a specific index in the dimensional array.

The array size of the float arrays are [128, 128].

What did I try?

(I made it simple, right now I am not using the [128, 128] size.)

multiple_array = MAKE_ARRAY(5, 3, /FLOAT)
> multiple_array
  0.00000000      0.00000000      0.00000000      0.00000000      0.00000000
  0.00000000      0.00000000      0.00000000      0.00000000      0.00000000
  0.00000000      0.00000000      0.00000000      0.00000000      0.00000000

float_array = FLTARR(3, 3)
;skipped setting some simple values

> float_array
   1.0000000       2.0000000       3.0000000
   4.0000000       5.0000000       6.0000000
   7.0000000       8.0000000       9.0000000

multiple_array[0, 0] = float_array
   1.0000000       2.0000000       3.0000000      0.00000000      0.00000000
   4.0000000       5.0000000       6.0000000      0.00000000      0.00000000
   7.0000000       8.0000000       9.0000000      0.00000000      0.00000000

And that is actually not what I want! My float_array should not overwrite the other indexes from my multiple array, but only the very first index (multiple_array[0, 0])

What do I want:

I was thinking something like this:

(Let's say this code would work like in other programming languages)

multiple_array[0, 0] = float_array
   FIRST_FLOAT_ARRAY       0.0000000       0.0000000      0.00000000      0.00000000
   0.0000000               0.0000000       0.0000000      0.00000000      0.00000000
   0.0000000               0.0000000       0.0000000      0.00000000      0.00000000

And later my multiple_array should look like this:

> multiple_array
   FIRST_FLOAT_ARRAY       SECOND_FLOAT_ARRAY       THIRD_FLOAT_ARRAY      FOURTH_FLOAT_ARRAY      FIFTH_FLOAT_ARRAY
   SIXTH_FLOAT_ARRAY       0.0000000                0.0000000              0.00000000              0.00000000
   0.0000000               0.0000000                0.0000000              0.00000000              0.00000000

... and so on

What am doing with this later?

Later I want to get these values like this:

current_float_array = multiple_array[0, 0]
> help, current_float_array
CURRENT_FLOAT_ARRAY               FLOAT     = Array[3, 3]

> current_float_array
   1.0000000       2.0000000       3.0000000
   4.0000000       5.0000000       6.0000000
   7.0000000       8.0000000       9.0000000

Is this even possible? For me it actually doesn't matter, if my multiple_array would end in a PTRARR or anything else, as long as I have the result like current_float_array I would be happy with it.

Thanks in advance for any help! I am looking forward for any suggestions.


Solution

  • You did a great job of answering your own very nicely framed question. :-) I can add some more options.

    In the case where your subarrays are the same size (128x128), a common approach in IDL is to use a higher-dimensional array to contain several of them. In this case, where you want a (5x3) array of the subarrays, you could create:

    multidim_array = FltArr(128, 128, 5, 3)
    

    To access one 128x128 subarray, use, for example:

    current_float_array = multidim_array[*, *, 0, 0]
    help, current_float_array
    CURRENT_FLOAT_ARRAY               FLOAT     = Array[128, 128]
    

    Note that IDL drops trailing dimensions if they have length 1, so we get Array[128, 128] rather than Array[128, 128, 1, 1].

    One note for efficiency: when you are loading data into this array, rather than addressing the 128x128 subarray, if you indicate the starting element only, IDL will do the assignment much more quickly. So, use:

    multidim_array[0, 0, 0, 0] = float_array
    

    rather than:

    multidim_array[*, *, 0, 0] = float_array
    

    (The general rule is that, behind the scenes, IDL takes any "*" items and expands them into a set of indices that are used to move each data element one by one. If you just give the starting element, the whole array can be copied as a block.)

    Note that this is exactly what you inadvertently did in your first test above (multiple_array[0, 0] = float_array), which was not what you wanted at the time.

    The multidim_array approach and your PtrArr approach will each have pros and cons when arrays are very large, where memory size and processing time may have trade-offs, but in small applications, either approach is reasonable.

    Yet another way to do this (since IDL 8.1 at least) is with the LIST data type, which would allow the subarrays to have different sizes. In fact, an element of a list can be anything at all (like your subarrays), and you can access those entries (and even index into the subarrays) with simple array-indexing syntax. Here's a sample of what you can do, creating a as a list of lists:

    IDL> a=list(list(indgen(2,3),indgen(3,4)), list(indgen(2,4)))
    IDL> a
    [
        [
            [[0, 1], [2, 3], [4, 5]],
            [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
        ],
        [
            [[0, 1], [2, 3], [4, 5], [6, 7]]
        ]
    ]
    IDL> a[0]
    [
        [[0, 1], [2, 3], [4, 5]],
        [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
    ]
    IDL> a[0,1]
           0       1       2
           3       4       5
           6       7       8
           9      10      11
    

    You would load your data into the list of lists like this, within a loop (sorry, not tested, but believed correct):

    multiple_list = List()
    FOR rowI = 0, 3 DO BEGIN
       row_list = List
       FOR columnI = 0, 5 DO $
          row_list.Add, GetYourFloatArrayHerePossiblyUsing(columnI, rowI)
       multiple_list.Add, row_list
    ENDFOR ; rowI over all rows
    

    and you could access the first array as:

    multiple_list[0, 0]
    

    and also:

    multiple_list[0, 0, 0, 0]     ; first element of first array
    multiple_list[2, 4, 127, 127] ; last element of last array
    

    I hope this is helpful!