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:
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.
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
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
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
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
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.
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
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, ...
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
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.'
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
Another form of a loop statements
REPEAT Statement UNTIL condition
Statement blocks have to be closed by ENDREP
WHILE condition DO Statements
Use ENDWHILE to close statement blocks.
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 |
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>
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.
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