There are three types of IDL programs one can write:
Here we will focus on the first two. The IDL widgets will be discussed at a later
time.
Variable names must start with a letter, but can include letters, digits, underscore
characters, or dollar signs. A variable name can have as many as 255 characters.
The size of a variable is limited only by the computer and operating system you are
using.
Valid variable names:
read6_$ file
only_8_bit
ComputerType
variable2
Invalid variable names:
name.last
third%file
4th_list
$temp
The valid data types (the name in parentheses is the name of an IDL function that
can force a variable to have that particular data type):
Undefined
Byte (Byte)
Integer (Fix)
Long Integer (Long)
Floating Point (Float)
Double Precision Floating Point (Double)
Single Precision Complex (Complex)
Double Precision Complex (DComplex)
String (String)
byte_var = 0B
integer_var = 0
long_integer = 0L
float_var = 0.0
double_var = 0.0D
complex_var = Complex(0.0, 0.0)
dcomplex_var = DComplex(0.0D, 0.0D)
string_var = ' '
Array can have up to 8 dimensions. Vectors and arrays of the different variable data
types can be set or initialized with the following built-in IDL routines:
| BytArr | Create a byte array of the specified dimensions: IDL> array = BytArr(256,256,10) |
| IntArr | Create an integer array of the specified dimensions. For example, to create an integer vector of 10 elements: IDL> vector = IntArr(10) |
| LonArr | Create a long integer array of the specified dimensions. |
| FltArr | Create a floating point array of the specified dimensions. |
| DblArr | Create a double precision floating point array of the specified dimensions. |
| ComplexArr | Create a single precision complex array of the specified dimension. |
| DComplexArr | Create a double precision complex array of the specified dimensions. |
| StrArr | Create a string array of the specified dimensions. |
IDL variables are typed dynamically, i.e., a variable will be typed to the same data
type as the assigned value. Dynamic typing means that the expression on the right
hand side of an assignment statement must be evaluated before a data type can be
assigned to the variable on the left hand side of the statement. For example, the
following will not work if you want to initialize an integer array to the value 1:
IDL> array = IntArr(10,12)
IDL> array = 1
If you print out the variable array, instead of getting a bunch of 1s, you will get
IDL> print,array
1
The reason is that when you type in array = 1, IDL thinks that the variable
array is now defined as the integer 1.
The correct way to initialize an integer array to 1 is this:
IDL> array = IntArr(10,12)
IDL> array = array + 1
In this case, the second command adds the value of 1 to each element in the variable
named array.
Another way to create an integer array with all the elements set to a value of 1
is to use the IDL Make_Array function:
IDL> array = Make_Array( 10, 12, Value=1, /Int)
In evaluating expressions, the variable data type that preserves the most precision
is maintained. For example:
IDL> value = 16/5
IDL> print,value
3
IDL> help,value
VALUE INT = 3
The expression results in value being an integer scalar with a value of 3 (integer
division). Note that you can learn the type of your variables by using the Help command.
Consider another example:
IDL> value = 16/5.
IDL> print,value
3.20000
IDL> help,value
VALUE FLOAT = 3.20000
The integer variables in IDL are short integers, i.e., they are two bytes in length.
In many programming languages, integers are four bytes in length. Short integers
sometimes surprise you in two different ways:
A counting variable exceeds the value capable of being expressed by a short integer.
For example, the integer counter goes beyond the value 32, 767.
Since most programming languages use four-byte integers, passing data back and forth
between IDL and an external program can cause your application to crash.
Always use long integers when in doubt.
Types of IDL programs
| Main Program | A main program unit consists of a sequence of IDL commands that ends in an End statement. There can be only one main program unit active in IDL at any time |
| Procedure | A procedure is a self-contained sequence of IDL commands that performs a well-defined
task. A procedure is identified by a procedure definition statement: PRO procedure_name, a1, a2, .., an To compile this procedure, type: IDL> .compile procedure_name To run this procedure, type: IDL> procedure_name, a, b, ..., |
| Function | A function is a self-contained sequence of IDL commands that performs a well-deinfed
task and returns a value to the calling program unit when it is executed. There is
always a RETURN statement in a function, and one data value (of the defined type)
is returned. A function is identified by a function definition statement: FUNCTION function_name, p1, p2, ..., pn To compile the function, type: IDL> .compile function_name To use the function, type: IDL> variable = function_name(a, b, ...) IDL> print, variable |
| Positional | PRO procedure, positional1, positional2, positional3 |
| Keyword | PRO procedure, positional1, positional2, Keyword=keyword_variable |
Parameters are passed to procedures and functions by value or by reference.
Parameters passed by value must be input parameters only, i.e., information can only
pass from the calling routine to the procedure or function. Parameters passed by
value cannot be modified in the calling routine by the called procedure or function.
Parameters passed by reference can be either input or output parameters, i.e., the
information communicated between the calling routine and the procedure and function
can be passed back and forth. Parameters passed by reference may be modified in the
colling routine by the called proceudre or function.
Determining the number of parameters used in a call
To determine the number of parameters used in a call to a procedure or function,
use the N_Params function inside the code for the routine. The function returns the
number of positional parameters used in the call:
numberOfParameters = N_Params()
Determine if a keyword is passed
To determine if a keyword was used in the call, use the N_Elements function, which
returns the number of elements contained in its argument.The key point about using
N_Elements is that it returns 0 if the argument is undefined.
For those who are familiar with C or Java, the BEGIN ... END statement blocks is
just like the brackets {}. For example:
If (something_is_true) then begin
x = 2
y = 3endif else begin
x=4
y=5endelse
Notice that BEGIN blocks are ended with different kinds of END statements. Here is
a list of the different types of END statements:
ENDCASE
ENDELSE
ENDFOR
ENDIF
ENDREPEAT
ENDWHILE
The IF ... THEN ... ELSE control statement provides logical test. The ELSE part of
the statement is optional:
IF (y eq 3) then x=2
IF (something_is_true) then x=2 else x=3
The FOR loop executes a statement, or statements, a specified number of times:
for j=0,9 do number(j) = sin(region(j)*!Pi)
It is also possible to specify the counter increment. For example, to increment the
counter by 2:
for j=0,20,2 do begin
number(j)=sin(region(j)*!Pi)
region(j)=0endfor
The WHILE loop execute a statement while a test condition remains true:
while (cnt ne 0) do begin
print,cnt
cnt = cnt - 1endwhile
A true condition in IDL is represented as:
A false condition is any condition that is not true.
The REPEAT ... UNTIL statement is similar to the WHILE statement. In this case a
statement, or statements, is repeated until the test condition is true.
REPEAT num = num + 2 UNTIL (num gt 20)
The CASE statement is used to select one, and only one, statement for execution,
depending upon the value of the test expression. The ELSE clause of the CASE statement
is optional.
CASE test OF
0: print, 'Value is 0'
1: x = test
else: y = testENDCASE
Notice that the ELSE clause, if it is used, requires a colon after it, unlike the
ELSE clause in an IF statement.
IDL allows you to use GOTO statements in your program. The GOTO statement allows
you to jump to a program label:
GOTO, Finish
...
...
Finish: RETURN
Notice that the label requires a colon after the label name.
IDL allows you to create common blocks of variables. Any program unit can gain access
to variables in the common block by declaring the common block in the program unit.
The common block is declared by specifying a common block name and the list of variables
that belong in the common block:
COMMON common_block_name, var1, var2, ..., varn
For example, to create a common block name date, with the variables day, month, and year:
COMMON date, day, month, year
To compile a user-written routine, use the .Run, .RNew, or .Compile executive commands.
IDL> .run routine.pro
IDL> .rnew routine.pro
IDL> .compile routine.pro
The filename is case sensitive on UNIX operating systems.
After a routine is compiled, it is used exactly as you use any other IDL procedure
or function.
Rules for compiling procedures and functions
The first rule to remember is that .Run doesn't run anything except a main program! And IDL runs a main program immediately after it compiles it. Any program module below a main program could not possibly get compiled in IDL.
.Compile is used to compile procedures and functions, and it doesn't run anything.
If you simply type the name of a procedure or function, and a module by that name
has not been previously compiled, IDL will automatically search for a file with the
same name as the module it is trying to resolve, following the IDL file path. If
IDL finds a file with the same name and a .pro extension, it will compile the file
until it gets to a module that has the same name as the file. At that point, it will
run the module.
If you simply type the name of a routine, IDL will only compile the file down to
the routine that has the same name as the file. Any routines below it in the file
will not be compiled. In a file that contains multiple modules, the module that will
have the same name as the file must be the last module in the file.
Also note that in case of any problem, the RETALL command will return
you to the IDL main program level.
The best way to learn to write an IDL program is to simply write one.
Here we will write a program named Plot_It that is similar to the built-in IDL command
Plot. Also, we will provide the ability to plot the data with a particular color
index that we will specify with a Color keyword. We will allow the ability to plot
the data either as a line or as plus (+) symbols. We will select the symbol drawing
method by means of a Symbol keyword.
Using your favorite text editor, create this file: plot_it.pro
We will create this program as a procedure with two input parameters and two keywords.PRO Plot_It, p1, p2, Color=color, Symbol=yes
Here, p1, p2 are the input parameters, and Color is the keyword with color as the keyword variable. Similarly, Symbol is the keyword and yes is the symbol keyword variable.
By default, when an error occurs in a program module, IDL is left in the context of the program that caused the error. To make the program to return to the main program level, use the On_Error procedure:
On_Error, 1 ; Return to the main program level.
We want this program to behave like Plot, in that we want the possibility of either specifying just the dependent data, or both the dependent and independent data together. In order to do so, we will need to know how many positional parameters were provided at runtime. We will use the function N_Parms to figure it out:
np = N_Params()
There are 4 possibilities here: (1) Plot_It was called with no parameters, (2) it was called with one parameter, (3) it was called with two parameters, or (4) it was called with more than two parameters. The program will have to check for these possibilities, and we will use the CASE statement here:case np of
0: begin
print,'Incorrect Number of Parameters'
return1: begin
dep = p1
indep = findgen(n_elements(p1))
end2: begin
dep = p2
indep = p1end
endcase
If the user specified a keyword parameter for the Color keyword, then we are all set. Else, we will have to define a default color.
if (n_elements(color) eq 0) then color = !D.N_Colors-1
We first load a color table, and use the Plot command to draw a plot without data (because we want the data line drawn in a color that may be different from the axes colors). We will overplot our data in the color we want to use with the OPlot command. Notice how we use the PSym keyword of the OPlot command to handle the input from the Symbol keyword in Plot_It. If the user of Plot_It uses the Symbol keyword, the variable yes will be defined and non-zero, in which case PSym will be set equal to 1 (+ signs). If Symbol is not used, the variable yes will be undefined in Plot_It and PSym will be set to 0 (no symbol).
loadct, 5
plot, indep, dep, /nodata
oplot, indep, dep, Color = color, PSym = Keyword_Set(yes)
PRO Plot_It, P1, P2, Color=color, Symbol = yes
On_Error, 1
np = N_Params()
CASE np OF0: begin
print,'Incorrect Number of Parameters'
return
end
1: begin
dep = p1
indep = findgen(n_elements(p1))
end
2: begin
dep = p2
indep = p1
endendcase
if (n_elements(color) eq 0) then color = !D.N_Colors-1
loadct, 5
plot, indep, dep, /nodata
oplot, indep, dep, Color = color, PSym = Keyword_Set(yes)end
Save the file and then inside IDL, compile and run the program. You will have to
first create a dataset and pass it to the program. Test and make sure it works in
all its possibilities.
Convert the steps from the first exercise into an IDL program. This program will
take in 5 arguments: the name of the input file (strings need to be placed within
quotes), the number of rows, the number of columns, the smooth window size, and a
keyword to allow the user to decide whether or not a continuum should be fitted to
the data.
The program will not need to generate a postscript plot. Generate the postscript
yourself by using the program you just wrote.
Finally, modify the program to allow you to toggle between velocity and wavelength
scale.
A sample solution is available here (after 11/16/98).