Structures are one of the most useful and powerful concepts in IDL. They can simplify your programming significantly and are the most logical way to deal with large amounts of data or large numbers of variables. Although they may appear strange at first I strongly recommend you take the time to learn how to use them. The best way to learn the full power of structures is by studying other IDL programs and using them whenever you can in your own programs. In Working With FITS we will see how structures can be written out as binary FITS files.
The following analogy originates in the IDL User's Manual. Think of a structure as a house with many separate rooms. Each room can contain something irrespective of what is in the other rooms. For example, in one "room" you might have an identification number (a scalar integer), in another "room" a two-dimensional image, and in a third "room" a header. A "room" is called a field and the "house" is the data structure.
To create a structure called s type
s = {id: 0, image: fltarr(100,100), header: strarr(10)}
To find out about s type
help, s, /structure
or, equivalently,
help, s, /str
Remember in IDL you only need as many letters in a keyword to uniquely identify that keyword. We see that s has three tags: a scalar integer ID, a 100 by 100-element floating point array IMAGE, and a ten-element string array HEADER. To access the ID field type
print, s.id
To set the ID field to a different value type
s.id = 300 help, s, /str
You can see immediately how structures can simplify your programming: Instead of dealing with three separate variables (id, image, and header), everything can be carried around in a single variable, s. Structures can have an unlimited number of fields provided you do not exceed the amount of memory in RAM .
But what if you're dealing with multiple objects (for example, a catalog of stars)? Do you need an individual structure for each one? No, you can generate an array of structures analogous to an array of numbers or an array of strings. Try this:
nstar = 58
starinfo = {number: 0L, xpos: 0.0, ypos: 0.0, mag: 0.0}
starinfo = replicate(starinfo,nstar)
starinfo.number = lindgen(nstar)
The syntax 0L means make zero a long integer (as opposed to a simple integer) and is equivalent to long(0). In the first line we are (arbitrarily) specifying how many stars are in our catalog. In the second line we initialize the data structure starinfo to have four fields: an id number, an x and y position, and a magnitude. The function replicate() then makes nstar copies of starinfo. For example, try typing
print, replicate('Hello!',15)
print, replicate(14.756,3)
To examine the number field in starinfo type
print, starinfo.number
To retrieve the data on one particular star we have to find the index corresponding to that star. Try this:
indx = where(starinfo.number eq 13L,nindx) if nindx ne 0L then help, starinfo[indx], /str
There is a bit of error catching in the above bit of code that you should try to understand. To determine the number of tags (or fields) in a structure type
print, n_tags(starinfo)
To print the tag names of a structure type
print, tag_names(starinfo)
Let's work with some real data now by using the querygsc() function in the Goddard Library. This function queries the HST Guide Star Catalog (V2.2). Read the documentation on this function and then try the example below.
nearvega = querygsc('HD172167',10.0)
nfound = n_elements(nearvega)
print, "Found "+string(nfound,format='(I0)')+" stars within 10' of Vega."
help, nearvega, /str
print, nearvega.jmag
Another way to define a data structure is to use the IDL function create_struct():
mystruct = create_struct('name', 'bob', 'friend', 'joe', $
'number', 10.0, 'junk', findgen(15))
help, mystruct, /str
You can print the value of a structure field by identifying it by name or by using its index number:
print, mystruct.name, mystruct.number print, mystruct.(0), mystruct.(2)
Finally there is a set of structure manipulation routines written by David Schlegel in the idlutils library that are very useful. Consider two structures astruct and bstruct:
astruct = {a: 10.0, b: 'Hey!'}
astruct = replicate(astruct,10)
help, astruct, /str
bstruct = {c: lindgen(25,25), d: 'I need another example.'}
bstruct = replicate(bstruct,10)
help, bstruct, /str
To bring the fields in astruct and bstruct together into a new structure cstruct type
cstruct = struct_addtags(astruct,bstruct) help, cstruct, /str print, cstruct.b
Now let's say we want to append 15 more structures to astruct (for example if we added 15 more stars to our catalog):
print, n_elements(astruct)
dstruct = replicate({a: 10.0, b: 'Hey!'},15)
astruct = struct_append(astruct,dstruct)
print, n_elements(astruct)
To print a structure in a nice format type
struct_print, astruct
Finally to trim tags from a structure use struct_trimtags():
newstruct1 = struct_trimtags(bstruct,select='D') newstruct2 = struct_trimtags(bstruct,except='D') help, newstruct1, /str help, newstruct2, /str
See what the keywords select and except do by reading the documentation on struct_trimtags().
Last update 2003 November. Email J. Moustakas with questions or comments.