Introduction to IDL

This chapter introduces some of the main concepts in IDL without a full discussion of the details. Later chapters provide more extensive explanations.

Getting starting with IDL

Variables can be created at any time interactively or anywhere in a program simply by assigning a value to a variable name. For instance, the following creates the variable s (or redefines it if it already existed), makes it a scalar string, and assigns “Hello world!” as its value:

In [0]:
s = 'Hello world!'

There is no declaration of variables in IDL—just assign to them and they pop into existence or are recreated if they already existed.

IDL has an extensive library of routines for data access, analysis, and visualization. Here, we use the print routine to print the value of a variable (starting in IDL 8.3, an implied print is done for variables or expressions simply listed on the command line, i.e., IDL> s):

In [1]:
print, s
Hello world!

Procedures (those routines which do not return a value) have the somewhat odd syntax of requiring a comma between their name and any arguments passed to them. IDL is case-insensitive; the following is equivalent to the above statement:

In [2]:
PRINT, S
Hello world!

The help routine is another procedure which can provide some information about a variable:

In [3]:
help, s
S               STRING    = 'Hello world!'

There are several other routines like size, n_elements, and others that provide even more detailed information about a variable. More information about these routines is provided in Section 3.7, "Variable Information".

The next example creates a simple line plot of a sine curve. We begin by creating another variable, this one to hold the x values of the sine curve:

In [4]:
x = findgen(361) * !dtor   ; 0 < x < 2 pi

There are several new concepts demonstrated on this line. First, the text after the ; is a comment, ignored by IDL. There are no multi-line comments in IDL, so to write a paragraph of comments place a semi-colon at the beginning of each line. Next, findgen is a function; the syntax for calling functions uses parentheses around the arguments to the function. The return value of a function cannot be ignored like in some other languages—here the return value of findgen is part of an expression that is eventually assigned to x. The findgen function (standing for “Floating point INDex GENerator”) is one of a family of index-generating functions which produce arrays whose values are equal to their indices (IDL starts arrays at index 0):

In [5]:
print, findgen(6)
      0.00000      1.00000      2.00000      3.00000      4.00000      5.00000

The assignment to x also shows an array operation—each value of the array findgen(360) is multiplied by the scalar system variable !dtor, a global variable specifying the factor needed to convert degrees to radians. Array operations are fast and efficient ways to operate on each element of an array. In IDL, array operations are preferred to looping over the individual elements of an array. All the arithmetic operators such as *, /, +, -, and most others are capable of using arrays as their operands. The variable !dtor belongs to a class of global variables, called system variables, which are identified with names beginning with !. Many of IDL’s library routines are also array based, accepting arguments which can be arrays. The sin function performs the sine operation on an array of values at once:

In [6]:
y = sin(x)

Of course, sin can also compute the sine of a single value—it recognizes the type and size of its argument and returns an appropriate result.

Arrays can be indexed using a simple notation to access subsets of the array. For example, to retrieve a single array value, just use square brackets around a zero-based index value:

In [7]:
print, y[0]
      0.00000

It is possible to use parentheses, but I recommend against it. See Section 5.10, "The compile_opt statement" for details about this. A range of values can also be selected. To retrieve the first 10 values of the array, use the following:

In [8]:
print, y[0:9]
      0.00000    0.0174524    0.0348995    0.0523360    0.0697565    0.0871557     0.104528     0.121869     0.139173     0.156434

Non-adjacent values can also be accessed. For instance, here we access y at indices 0, 90, 180, and 270:

In [9]:
print, y[[0, 90, 180, 270]]
      0.00000      1.00000 -8.74228e-08     -1.00000

Note that -8.74228e-08 is zero within the tolerance floating point precision. See Section 3.4, "Arrays" for more details about arrays and more syntax for indexing them.

Now that we have x and y values, the plot procedure will produce a simple line plot using many reasonable defaults:

In [9]:
plot, x, y
% Program caused arithmetic error: Floating illegal operand

The plot defaults can be changed by specifying keywords in the plot call. These keywords are named parameters, as opposed to the positional parameters like x and y. For example, to change the thickness of the line representing the sine curve to 4 times thicker than its standard width, set the thick keyword to 4:

In [10]:
window, /free
plot, x, y, thick=4, psym=4

Keywords can appear in any order when calling a routine, but positional parameters are distinguished by their relative order amongst the other positional parameters. Keyword names can be abbreviated, making them more convenient to type:

In [11]:
window, /free
plot, x, y, th=4

But if shortened too much, the desired keyword cannot be determined, e.g., there are several keywords starting with "t":

In [12]:
plot, x, y, t=4
% Ambiguous keyword abbreviation: T.
% Execution halted at: $MAIN$          

Abbreviating keywords can save time when using IDL interactively, but should be avoided when writing programs. The IDL help system describes all the keywords accepted by each routine. For example, to look up the online help for the print procedure, use

In [13]:
?print

This gives information about the purpose of the routine, return value, positional parameters, keywords, examples, changes to the routine by IDL version, and other related routines and help topics.

Another special notation for keywords concerns a special class of keywords which are either on or off, i.e., boolean keywords. For example, the isotropic keyword will make sure the x- and y-axes have the same scaling if it is set:

In [14]:
window, /free
plot, x, y, thick=4, isotropic=1

These boolean keywords have a special notation using a / before their name to indicate when they are set. The following is exactly equivalent to the above:

In [15]:
window, /free
plot, x, y, thick=4, /isotropic

Remember to not use an = if using this notation—use either isotropic=1 or /isotropic, not both. There is no special notation for when a boolean keyword is off since not using the keyword in the call is usually equivalent to setting it to 0. See Section 6.4, "Line plots" for more information about the plot procedure’s extensive set of options.

For a bit more practical example of using the plot procedure, read a simple data file and plot a few columns in it:

In [16]:
data = read_ascii(file_which('plot.txt'), data_start=2)

The syntax of function calls allows them to be nested; here the return value of file_which is passed as an argument to read_ascii. The data_start keyword indicates that there are two header lines above the start of the data. The file_which function searches our IDL installation (and outside of it in our !path, but we’ll talk about that later) for a file named plot.txt which is provided as an example data file. The help procedure again tells us about the variable we have just created, this time we are using the structures keyword to provide more information about this structure variable (see Section 3.5, "Structures" for more information about structures):

In [17]:
help, data, /structures
** Structure <7096508>, 1 tags, length=108, data length=108, refs=1:
   FIELD1          FLOAT     Array[3, 9]

This indicates that data is a structure with a single field that is a 3 by 9 array of floating point values. In IDL’s convention, 3 by 9 indicates a 3 column by 9 row array. Plot the first column against the second column:

In [18]:
window, /free
plot, data.field1[0, *], data.field1[1, *], xstyle=9, ystyle=8
In [ ]: