Primeros pasos in IDL

2. Programming Fundamentals

2.1. Operators

EXAMPLES:

IDL>;Set A equal to 3.
IDL>A = 5 < 3 & print,A
IDL>;Set A equal to -6.
IDL>A = 5 < (-6) & print,A
IDL>;Syntax Error. IDL attempts to perform a subtraction operation if
IDL>;the "-6" is not enclosed in parentheses.
IDL>A = 5 < -6

IDL>;Set all points in array A that are smaller than 5 to 5.
IDL>A=[1,2,3] & print, A
IDL>A = A > 5 &  print, A

IDL>;A 3-column by 2-row array:
IDL>array1 = [ [1, 2, 1], [2, -1, 2] ]
IDL>;A 2-column by 3-row array:
IDL>array2 = [ [1, 3], [0, 1], [1, 1] ]
IDL>print,'A 1:'
IDL>print,array1
IDL>print,'A 2:'
IDL>print,array2
IDL>PRINT, array1#array2
IDL>PRINT, array1##array2

IDL>;Assign the value of 9 modulo 5 (4) to A.
IDL>A = 9 MOD 5
IDL>print,A
 

2.2. Procedures and Functions

Functions and procedures are self-contained modules that can be regarded as new IDL commands and constitute the building blocks of a larger IDL program.  Due to the fact that they are reusable, simplify and minimize considerably the amount of new code required for each application.

The syntax of a PROCEDURE is as follows:

PRO Name, Parameter1, ..., Parametern, Key1=value1,..., Keyn=valuen
   ;Statements defining procedure.
   Statement1
   Statement2
   ...
END ;End of procedure definition.

Positional parameters are identified by their position. If a set of statements of the procedure makes use of Parameter1 and a second set of statements requires Parameter2 and these parameters are variables of different types (e.g., strings versus integers) and you exchange their position the procedure breaks and an error message is generated at the execution. A good practise is to use the positional parameters for required parameters and keyword parameters for optional parameters.

Keyword parameters do not depend on their positions, but they are defined according to their names. Keyword abreviations are allowed but not recommended.

The syntax of a FUNCTION is as follows:

FUNCTION Name, Parameter1, ..., Parametern, Key1=Value1,..., Keyn=Valuen
    Statement1
    Statement2
    ...
    RETURN, Expression
END

Note that the only differences between Procedures and Functions is in their starting line of definition (PRO versus FUNCTION) and that FUNCTION returns a single specific IDL variable of any type.

Procedures and Functions are invoked in the following way:

Name_of_Procedure,Parameter1, ..., Parametern, Key1=Value1,..., Keyn=Valuen

Result=Name_of_Function(Parameter1, ..., Parametern, Key1=Value1,..., Keyn=Valuen)

Procedures are compiled either automatically when invoked or using the executive commands (to be typed at the IDL command prompt, but never in program statements) such as:

.RUN procedure_name
.RNEW procedure_name
.COMPILE procedure_name

If you are in idlde click on RUN in the main menu to see the executive commands. For example, click on COMPILE and then on RUN to compile and execute a procedure respectively.
 

EXAMPLES:

IDL>;Edit a file and call it "arrayaverage" and save it:
>FUNCTION arrayaverage, a
>av=TOTAL(a) / N_ELEMENTS(a)
>; TOTAL function returns the sum of the elements of Array,
>;N_ELEMENTS function returns the number of elements contained in an expression or variable.
>RETURN,av
>END

IDL>;Edit a second file and call it "arraymult" and save it:
>FUNCTION arraymult, a,b,NUMELEM=numberelements
>c=a##b
>numberelements=N_ELEMENTS(c)
>RETURN,c
>END

IDL>;Edit a third file and call it "myarrays_game.pro" and save it:
>PRO myarrays_game
>a=[ [1., 2., 3.], [4., 5., 6.] ,[7., 8., 9.]]
>result=arrayaverage(a)
>print,'The average of my first array is: ',result
>b=[ [1., 1., 1.], [1., 1., 1.], [1., 1., 1.]]
>result2=arraymult(a,NUMELEM=newarrayelements,b)
>;Note that the keywords can go in between the positional parameters
>print,'This is the new array: ' & print,result2
>print,'This is the number of elements of the new array: ',newarrayelements
>END
IDL>;Type in the IDL command line:
IDL>.compile arrayaverage, arraymult
IDL>.myarrays_game
 

2.3. Program control statements

2.3.1 Conditional statements

¤ Simple conditional statements:
IF condition THEN statement [ ELSE statement]

or

IF condition THEN BEGIN
   statements
ENDIF [ ELSE BEGIN
   statements
ENDELSE ]

EXAMPLES:

IDL>a='hellon'
IDL>IF a EQ 'hello' THEN print,'say hello' ELSE print,'say bye'

>a=3
>IF a EQ 2 THEN BEGIN
>   b=a*2
>   c=b
>   print,a
>   print,b
>   print,'c equal to',c
>ENDIF ELSE BEGIN
>  print,'a is not two'
>   print,'c is not two'
>ENDELSE

  ¤ Multiple conditional statements:
 

The CASE statement is used where a condition can evaluate to a number of differenent solutions and when a CASE is true IDL goes to the next step after the CASE statement. Its syntax is:

             CASE expression OF
              expression: statement
                ...
              expression: statement
              [ELSE: statement]
              ENDCASE

The SWITCH statement is used to select one statement for execution from several choices, depending upon the value of the expression following the word SWITCH. Its syntax is:
 

SWITCH expression OF
      expression: statement
      ...
      expression: statement
ELSE: statement
ENDSWITCH
Whereas CASE executes at most one statement within the CASE block, SWITCH executes the first matching choice and then continue executing the remaining choices in the SWITCH block.  For this reason, the BREAK statement is commonly used within SWITCH statements to force an immediate exit from the SWITCH block.

EXAMPLES:

;you can type the following sentences within a procedure(s) and execute it.

>football='Madrid'
>CASE football OF
> 'Madrid':  BEGIN
>                        print, 'I am not a fan'
>                        print, 'I want them to loose'
>                   END
>   'Barcelona':   print, 'I am a fan'
>   'Tenerife':   print, 'I am a fan'
>ELSE: print, 'I love the place'
>ENDCASE

>football='Madrid'
>print,'Here is my new answer'
>SWITCH football OF
>   'Madrid':  BEGIN
>                        print, 'I am not a fan'
>                        print, 'I want them to loose'
>                    END
>   'Barcelona':   print, 'I am a fan'
>   'Tenerife':   print, 'I am a fan'
>ELSE: print, 'I love the place'
>ENDSWITCH

>print,'Here is my new new answer'
>football='Madrid'
>SWITCH football OF
>   'Madrid':  BEGIN
>               print, 'I am not a fan'
>                print, 'I want them to loose'
>               BREAK & END
>  'Barcelona':  BEGIN print, 'I am a fan'
>    BREAK & END
>   'Tenerife':   BEGIN print, 'I am a fan'
>    BREAK & END
>ELSE: BEGIN print, 'I love the place'
>BREAK & END
>ENDSWITCH
 

2.3.2. Loops

The FOR statement is used to execute one or more statements repeatedly, while incrementing or decrementing a variable with each repetition, until a condition is met. The syntax is:

FOR Variable = Expression, Expression DO Statement

WHILE...DO loops are used to execute a statement or a number of statements repeatedly while a test condition remains true.  The syntax of the WHILE...DO statement is as follows:

WHILE expression DO statement

or

WHILE expression DO BEGIN
   statements
ENDWHILE

REPEAT...UNTIL loops are used to repetitively execute a a number of statement until a condition is met. This loop is similar to the WHILE loop, except that the test condition is evaluated at the end of the loop rather than at the begining. Its syntax is:

REPEAT statement UNTIL expression

or

REPEAT  BEGIN
   statements
ENDREP  UNTIL expression
 

EXAMPLES:

IDL> a=0
IDL> FOR a=0,3 DO print,a*10

>a=0
>WHILE a le 3 DO BEGIN
>  print,a*10
>   a=a+1
>ENDWHILE

>a=0
>REPEAT  BEGIN
>   print,a*10
>   a=a+1
>ENDREP  UNTIL a gt 3
 

2.3.4. Common statement

Common blocks are useful when there are variables that need to be accessed by several IDL procedures or when the value of a variable within a procedure must be preserved across calls. Unlike local variables common blocks variables are not destroyed when a procedure is exited. The syntaxis is as follows:

COMMON Block_Name, Variable1, Variable2, ..., Variablen

>;edit a file and call it "callerproc.pro"
>;this is the caller procedure
>pro callerproc
>COMMON acom, a
>a=1
>proc1,result1
>proc2,result2
>print,'result1:',a,result1
>print,'result2:',a,result2
>end
;
>;this is the first procedure which needs a
>pro proc1,result1
>COMMON acom, a
>result1=a*2
>end
;
>;this is the second procedure which needs a
>pro proc2,result2
>COMMON acom, a
>result2=a*3
>end

2.3.5. Jump statements


EXAMPLES:

>for i=0,5 do begin
>    if i le 2 then CONTINUE ;it will go to the next loop value without executing the next statement
>    print,'I do want loop values larger than 2, current value is',i
>endfor

>for i=0,5 do begin
>    if i gt 2 then CONTINUE
>    print,'I do not want loop values larger than 2, current value is',i
>endfor

>for i=0,5 do begin
>    print,'i value is',i
>    if i gt 2 then GOTO, goout
>endfor
>goout: print,'i got to be larger than 2: bye bye'
 

2.4. Accessing the operating system and external routines

The most simple way to access the operative system is by using $ as explained above. $ can only be used interactively. There is an alternative command  SPAWN, which can be used interactively or in IDL programs. It is very easy to use:

SPAWN, command, result

IDL execution suspends until the spawned process terminates.

EXAMPLES:

IDL>$pwd    ;it will let you know your current directory

IDL>SPAWN,'ls *.pro',numberprocs
IDL>print,'Total number of IDL procedures is:',n_elements(numberprocs)
IDL>print,'The names of my IDL procedures are:',numberprocs
 

 ;Edit from outside IDL the following fortran77 code and call it "add_to_a.f"
       program add_to_a
      character*50 file_i,file_o
      integer i
      real*4 a_i,value
      write(*,*)'name input file, value to add, name output file?'
      read(*,*)file_i,value,file_o
      open(99,file=file_i,status='old')
      open(98,file=file_o,status='new')
      do i=1,999999
          read(99,*,end=12)a_i
          write(98,*)a_i+value
      enddo
12  close(99)
      close(98)
      end
;Compile this fortran code outside from IDL, i.e., type "f77 add_to_a.f"
IDL> openw,1,"file_in"
IDL> for i=0.,3. do printf,1,i
IDL> close,1
IDL> SPAWN,'echo file_in 10. file_out  | a.out'
IDL> openr,1,"file_out"
IDL> data=fltarr(4)
IDL> readf,1,data
IDL> close,1
IDL> print,data
 

There is a more sophisticated approach by means of using CALL_EXTERNAL function, which loads and calls routines contained in shareable object libraries. IDL and the called routine share the same process address space. CALL_EXTERNAL avoids the overhead of process creation of the SPAWN routine. In addition, the shareable object library is only loaded the first time it is referenced, saving overhead on succeeding calls. The compilation process depend on the platform used. See the manual for details.
 

2.5. Errors

There are a number of error handling control statements that could be useful. We describe some of the most commonly used in IDL.

ON_IOERROR,label

It works as a GOTO statement. It allows you to specify a label (string) with some explanations about input output errors when these occur. This command might be placed in a section of the code before a data file is read. When writing the label use color ":" after it (as in GOTO).

Another useful command to be written at the begining of a procedure is

ON_ERROR,n

where n is a number from 0 to 3.  By default this number is 0, which means that the program stops inmediatly in the module that caused the error. If you choose n to be 1,  the program stops and return you to the command line. When n is 2, the program stops and return to the program module that called the module causing error. Finally, when n is 3 the program stops and return to the program module that registered the ON_ERROR condition, which might not be the current module.

Errors are reported via the !ERROR_STATE system variable. If you type

help,!ERROR_STATE, /structure

In this structure variable is contained for example the error message and the error code. You can also type:

print,!ERROR_STATE.code
print,!ERROR_STATE.msg

Note: it is a good practise to type RETALL if you wish to return to the IDL command line with all your variables recovered after a crash.
 

EXAMPLES:

>pro testerror
>;ON_ERROR,0
>galaxy=filepath('galaxy.dat',SUBDIRECTORY=['examples','data'])
>g=intarr(256,256) ;it should be defined as bytarr
>ON_IOERROR,iolabel
>openr,lun,galaxy,/get_lun
>readu,lun,g
>free_lun,lun
>iolabel:'this is a reading error'
>window,xsize=256,ysize=256
>device,decomposed=0
>erase
>tvscl,g
>end