There are a few options I'm aware of:
Of the following, #1 is the closest to what you requested, but I believe that #3 offers the best blend of usability for your mentioned goal, speed, and compatibility with different versions of IDL.
1) Using scope_varfetch
with the /enter
keyword:
pro foo, G
for k = 1, 216 do begin
varname = 'atom' + strtrim(k, 1)
(scope_varfetch(varname, level=-1, /enter)) = G[*, 0:*:(215 + k)]
endfor
end
This creates variables named atom1
through atom216
in the calling routine, or in $MAIN$
if executed interactively. I think this is the closest to what you requested. You can also access those variables directly from the calling function by name using syntax either like print, atom5
or like:
for k = 1, 216 do begin
varname = 'atom' + strtrim(k, 1)
print, scope_varfetch(varname)
endfor
2) Using an IDL 8.0+ List object:
atom = list(length=216)
for k = 0, 215 do atom[k] = G[*, 0:*:(216 + k)]
Note that the list is 0-indexed, meaning that the first element is zero, instead of one. Use atom[0]
to access the first atom, and so on. To access the first index of the first atom, surround with parentheses and use an additional set of brackets to index: (atom[0])[0, 0]
. The parentheses are necessary due to IDL's unusual order of operations.
3) Using a pointer array:
atom = ptrarr(216)
for k = 0, 215 do atom[k] = ptr_new(G[*, 0:*:(216 + k)])
Or with slightly different syntax:
atom = ptrarr(216, /allocate_heap)
for k = 0, 215 do *atom[k] = ptr_new(G[*, 0:*:(216 + k)])
This is the most efficient and highly compatible way to do it. Pointers and the associated ptrarr
and ptr_new
functions have been around since IDL 5.0, and they are much more efficient than lists, hashes, or scope_varfetch
.
Note that like the list, this is 0-indexed. Also, to access these values you have to "deference" them with a *
, as in print, *atom[0]
to print the first atom array, or print, (*atom[0])[0, 0]
to print the first element of the first array and so on. The parentheses are required for the same reason as with the list. Setting values is also possible with syntax like (*atom[0])[1, 15] = new_values
.
4) Using an IDL 8.0+ hash:
atoms = hash()
for k = 1, 216 do begin
name = 'atom' + strtrim(k, 1)
atoms[name] = G[*, 0:*:(215 + k)]
endfor
These can be referenced like atoms['atom0']
. I don't think this is probably the best option in this case, since an array is more efficient, but it is very useful if there are additional string names you need to use, or if the data indexes are sparse.
5) Building a structure with create_struct
:
atoms = !null
for k = 1, 216 do begin
tagname = 'atom' + strtrim(k, 1)
atoms = create_struct(atoms, tagname, G[*, 0:*:(215 + k)])
endfor
This is very slow, but relatively easy to understand once it's done. Get each array like atoms.atom1
and get an element like atoms.atom1[0, 0]
.