Interactive Data Language (IDL) - Course by R.K.

1. Introduction, Language Elements and Syntax

1.1. Introduction

IDL stands for 'Interactive Data Language'. Do not confuse it with the 'Interface Description Language', which bears the same acronym but is an entirely different thing.

It is an interpreted, but interactively compilable, programming language with integrated graphical facilities. Arrays are first class elements in IDL, which makes it quite similar to F90.

The great advantage of IDL is the convenience of program development, which usually is more rapid and requires less training than other languages. The danger that comes with it is that inexperienced programmers write slow and inefficient codes.

IDL is multi platform, being available on a wide set of hardware architectures, programs in IDL hence should run on any machine that has an IDL port. Behavior can however be different, were operating system access is made (graphics!).

All IDL programs, interactive or not, require a license. There is no way to 'compile' an application so it would later run without an IDL installation or license.

For heavy numerical work there are better choices than IDL, because possibilities of optimization are limited and IDL can not parallelize processes on multi processor machines.

The IAC in the moment has 20 floating licenses, meaning that 20 users can simultaneously use IDL at any machine at the IAC installations (including the observatories at the Roque de los Muchachos and Izaña as well as the Department of Astrophysics of the University). There are another 6 licences attached to the machine 'dino', a six processor SGI Power Challenge that should be used for long running processes.

DO NOT BLOCK LICENSES WHILE NOT ACTUALLY WORKING WITH IDL.

The license manager of IDL grants multiple sessions by one and the same user on one and the same machine with the same output terminal for one license (up to 10 sessions). This course is current with version 5.1 of IDL.

IDL in the Internet:

1.2 Invoking IDL

You can start IDL in command line mode by just typing

idl

or start it in a developers environment with

idlde

This actually is a sophisticated tool that integrates facilities like editing and debugging. I highly recommend to use this tool, but this course will not detail about it.

To get help in general, type the interrogation sign ?, which gets you into IDL hypertext help system. Information about local libraries can be obtained by the command widget_olh. The command 'help' in IDL gives information about a specific variable or all variables of the current program segment.

To terminate an IDL session type

exit

IDL is not case sensitive.

1.3. Data Types

IDL variables have names up to 128 characters long. They have to start with a character and may contain characters, numbers and some special characters like '$' and '_'. There are about 35 reserved names that can not be used for variables, such as 'if', 'do', 'end' etc.

IDL provides the following data types:

Type Bytes Range Conversion Routine Name 
Byte 1 0-255 byte 
String 0-32767 Text string 
Integer 2 -32768 -- +32767 fix 
Long 4 2x +/- 109 long 
Float 4 +/- 1038 float 
Double Precision 8 +/- 10308 double 
Complex 8 (pair of reals) complex 
Double Precision Complex 16 (pair of double precision reals) dcomplex 
Structure unlimited arbitrary set of variables

There is no logical data type. Any data type can be used to signal logical true or false with a scalar value. If the data is byte, integer or long integer, all even values represent false and all odd values true. In all other types 0 stands for false and a nonzero value for true. Note that it will not cause an error if you test strings for a logical condition. You can write quiete confusing code with this:

IDL> false='true'
IDL> if false then print,'true'
true

Type assignment by IDL is usually implicit, which means that you should spend great care on controlling data types. The default assignment to integers is 2 Bytes, exceeding the limits is quite easy and does not result in error messages. Example:

IDL> a=20000
IDL> b=20000
IDL> print,a+b
    -25536

It is possible to change the type of a variable in the course of an IDL program, which is an additional source of error.

IDL> a=40000.
IDL> a=fix(a)
IDL> print,a
     -25536

Although IDL does not require it, it is save and good practise to define explicitly all data used in a program and never change types.

IDL> a=long(20000)
IDL> b=long(20000)
IDL> print,a+b
     40000

1.3.1. Arrays

All data types can be expanded to arrays of up to eight dimensions. Arrays can be created and initialized either all elements to zero, or with elements corresponding to the index number of the subscript.

Data Type Initialize to 0 Initialize to index number 
Byte bytarr bindgen 
Integer intarr indgen 
Long Integer lonarr lindgen 
Float fltarr findgen 
Double Precision Float dblarr dindgen 
Complex complexarr cindgen 
Double Precision Complex dcomplexarr dcindgen 
String strarr sindgen 

There is also a generic array creator make_array that can be used to dynamically allocate arrays of any given type.

Array boundaries go from 0 to dim-1, like C and unlike Fortran. a=findgen(2,2)creates a two dimensional array with elements a[0,0],a[1,0],a[0,1] and a[1,1].

Array subscripts may be written in round '( )' or square '[ ]' brackets. It is advisable to use square brackets in order to distinguish between subscripts and function calls. This will make programs more easily readable.

IDL is row major, like Fortran. Arrays in memory are ordered by rows: A[0,0],A[1,0],A[2,0]... A[0,1],A[1,1] ....
It is extremely important to take this into account in nested loops. The innermost loop should always act on the first index.

Sub-arrays are extracted by referencing a subscript range explicitly or by an asterisk and indicates all elements of one dimension.

IDL> a=findgen(5,2)
IDL> b=a[0:1,*]
IDL> print,b
     0.00000      1.00000    
     5.00000      6.00000

1.3.2. Structures

A structure combines several data to a logical unit. Structures elements are referenced as structure_name.element. To define a structure, use

structure={structure_name,element_1:definition_1,element_2:definition_2,....}

to create a structure to hold all informations from a fits file, e.g.

a=bytarr(36,80)
b=fltarr(1024,1024)
fitsim={fits, header:a, data:b}

to extract the first header line you may use a command like this:

line1=string(fitsim.header(0,*))

to divide all data by a common factor:

fitsim.data=fitsim.data/factor

1.4. Operators

IDL provides much the same operators than any other language. As arrays are first class elements, this operators work directly on arrays.

IDL> a=findgen(2)
IDL> print,a+10
     10.0000      11.0000

IDL specific operators include "#" for matrix multiplication, "<" and " >" for minimum and maximum, respectively. There also are the logical operators not, eq, ne, le, lt, ge, gt, and, or and xor. The result of a logical operator is a byte (or byte array) where the value 0 indicates false and 1 true.

IDL> a=indgen(5)
IDL> b=(a-2)^2
IDL> print,a
       0       1       2       3       4
IDL> print,b
       4       1       0       1       4
IDL> print, a > b
       4       1       2       3       4
IDL> print,a gt b
   0   0   1   1   0

1.5. Statements

An IDL statement consist of an optional statement label (not recommended) terminated by a colon, the statement itself and a comment separated by semicolon.

Groups of statements bracketed by an BEGIN and END statement are called a block.

1.5.1 Assignment Statements

variable=expression

a=1. ; assign value 1.0 to real variable a

Remember that arrays are first class elements and can be used in assignment statements without restriction.

IDL> a=findgen(2)
IDL> a=a+10
IDL> print,a
     10.0000      11.0000

1.5.2. Common Block Statement

The Common Block statement defines a set of variables known to every program unit where it appears. Works exactly like Fortran.

COMMON Block_Name, Variable_1, Variable_2, ...

1.5.3. Case Statement

With the CASE statement you can branch according to a set of conditions:

CASE Expression OF
Expression_1: Statement
Expression_2: Statement
....
ELSE: Statement
ENDCASE

Statement of course can be a block surrounded by BEGIN and END

case n of
n gt 0: begin
        print,' greater than zero'
        print,n
        end
n eq 0: print,' equal zero'
else:   print,' negative'
endcase

1.5.4 For Statement

The FOR statement, like the Fortran DO, increments or decrements a loop variable and cycles a loop until the end condition is met.

FOR variable=initial,end,inc DO statement

if inc is not specified, an increment of one is used. Although no restrictions apply to the type of the loop variable, it its strongly recommended to use only integer (long) variables.

If instead of a single Statement a block is passed, it has to be closed by an ENDFOR.

a=findgen(10)
n=0
for i=0,9 do begin
     if ( a[i] gt 5. ) then n=n+1
     endfor
     print, n, ' elements greater than 5.'

1.5.5 IF Statement

Branches according to a condition.

IF condition THEN Statement [ELSE Statement]

Close blocks of statements by ENDIF or ENDELSE statements, respectively. Note that statement may be another if.

Be careful with logical ifs or you may have some unexpected results:

IDL> i=0
IDL> if (i eq 0) then print, 'true' else print, 'false'
true
IDL> if (i = 0)  then print, 'true' else print, 'false'
false
IDL> if (i)      then print, 'true' else print, 'false'
false

or look at this one:

IDL> for i=0,5 do if (i>1) then print,'greater' else print,'smaller'
greater
greater
smaller
greater
smaller
greater

1.5.6. Repeat Statement

Another form of a loop statements

REPEAT Statement UNTIL condition

Statement blocks have to be closed by ENDREP

1.5.7 While Statement

WHILE condition DO Statements

Use ENDWHILE to close statement blocks.

1.5.8. Logical Branches Overview

FOR variable=begin,end,inc DO Statement 
IF expression THEN Statement 
ELSE Statement 
REPEAT Statement UNTIL endcondition 
WHILE expression DO Statement 
CASE expression OF 
Expression_1: Statement 
Expression_2: .... 
.... 
ELSE Statement 
ENDCASE

1.6. Save and Restore

An efficient way to interrupt and resume work with IDL is by using the save and restore commands.

save, /all, file=<filename>

will save all variables (including system variables) and active procedures. To resume a session at that point just do an

restore, file=<filename>

1.7. Journaling

You can force IDL to log (or journal) all your interactive commands to a file. This is sometimes useful if you want to convert your interactive work later into a program.

To start journaling, use the command

journal, <filename>

All commands are no logged in the specified file. When journaling is active,

journal, <string>

writes the specified string to the journal file. To end journaling, issue the journal command without arguments.

1.8. Operating system access

Within the IDL command interpreter you can send commands to the operating system by preceding them with a dollar ("$") sign. Here are some Unix examples. Remember that in other operating systems these may not work or produce different results.

$pwd

gives you the name of the current work directory. Observe however, that with

$cd dir

you can NOT change the current work directory, since there is no feedback from the Operating system to IDL (the the command cd, 'directory' to perform this action.

If the result of an operating system call has to used within IDL the call to the Operating System has to be issued with the

spawn, com, result

command. The command has to be put in the string variable com. result is an optional output variable which holds the result of the command, if any was produced.

spawn,'ls -ls $HOME | wc -l',res
print,'number of files in your home directory is : ',res 
number of files in your home directory is :        73

IDL can catch the value of environment variables with the

result=getenv(variable_name)

command.

 print, getenv('SHELL')
 /usr/local/bin/tcsh