Some notes on the IDL path, IDL batch files, and xterms under Linux

Sometimes getting the IDL path right can be a bit of a problem, especially if doing some indirect IDL jobs. This page will discuss some of the issues. This is not meant to be the final word on this topic, but the techniques seem to work on my system so may be of some value.

Jump to brief summary.


The IDL command is really a script file for Linux

When IDL is run at the command line what really happens is that a shell script is run, which sets up some environmental variables, and then executes the IDL program. To see this do which idl which will give something like /usr/local/bin/idl. Do more /usr/local/bin/idl to see the script file. The part of this script file of interest here is:
if [ "$IDL_PATH" = "" ]; then
        IDL_PATH="+$IDL_DIR/lib:+$IDL_DIR/examples"
else
    IDL_PATH=\+$IDL_PATH:\+$IDL_DIR/lib:\+$IDL_DIR/examples
fi
IDL_DIR was defined just before in the script file. IDL_PATH may or may not be defined. If it is defined then a couple additional standard IDL locations are added after it in the path.


Examples of the IDL script file updating IDL_PATH

Turn off any IDL startup file.
Set IDL_PATH to /common/idl_libs/idlusr:
setenv IDL_PATH /common/idl_libs/idlusr
Note: this library contains the most basic local IDL routines, ones that might be used in the IDL startup file.
Get into IDL and do print,getenv('IDL_PATH')
The result is:
+/common/idl_libs/idlusr:+/usr/local/rsi/idl_5.6/lib:+/usr/local/rsi/idl_5.6/examples
This is just what is expected from the IDL shell script.

As a minor variation, make an IDL batch file to list this. Name it pcheck.pro and give it a single line:
print,' IDL_PATH = '+getenv('IDL_PATH')
To run it do:
idl pcheck   giving (as expected):

IDL_PATH = +/common/idl_libs/idlusr:+/usr/local/rsi/idl_5.6/lib:+/usr/local/rsi/idl_5.6/examples


xterms inherit environmental variables

Try echo $TEST
You should get TEST: Undefined variable.
Now do setenv TEST "This is a test" (chs or tsch syntax)
echo $TEST
This is a test
If you create a new xterm it will have TEST defined:
xterm &
Then in that xterm try echo $TEST, which will show that it is defined. So xterms will inherit any environmental variables that exist when they are created. This includes IDL_PATH.

An xterm can be created and a command executed in it:
xterm -e idl pcheck
where -e means execute the command that follows, any arguments follow the command.
Doing the above will give the same result as idl pcheck, but in a new xterm.

Now a problem comes up. An xterm may be spawned from within IDL:
Inside idl do: spawn,'xterm -e idl pcheck' giving:

IDL_PATH = ++/common/idl_libs/idlusr:+/usr/local/rsi/idl_5.6/lib:+/usr/local/rsi/idl_5.6/examples:+/usr/local/rsi/idl_5.6/lib:+/usr/local/rsi/idl_5.6/examples
Not only are the added IDL items duplicated, but worse, the leading item now has a double +, making it invalid. Now none of the routines from that library are available. This happens because the IDL script is too simple, it does not check if the contents of IDL_PATH already include the added items, so they are added again. There is a workaround, but first it must be explained wwhy anybody would ever care.


Why does it matter?

xterms spawned from IDL and running IDL routines can be very useful in some cases. The xterms are quite flexible, they can have their size and position set, and even their background and text color. They can be told what commands to run in them. So a single IDL batch file could set up multiple xterms, each running their own IDL code. Then the original IDL batch file could exit. One local application sets up 7 different xterms. The first intializes several items and also checks if conditions are good to continue. If not it signals that the rest of the setup should be aborted.

Below the IDL path problem workaround will be given, and then some examples on controlling xterms.


Setting the IDL path

Make sure there is no IDL_PATH environmental variable defined.

The IDL path can be controlled using the IDL startup file. The IDL startup file is an IDL batch file. That means all commands in it must be as if they were typed at the IDL prompt. So no gotos are allowed and all commands must be contained in single statements. The statements may be compound and even on multiple lines as will be shown in examples.

In the IDL startup file add the desired library near the front:

!path = '/common/idl_libs/idlusr:'+!path
Now any routines in that library are available for use in the startup file. A very useful routine related to the IDL path is called path, do path,/help for details.

Here is an example IDL startup file:

;=======================================================
;
;       idlstartup.pro = executed each time IDL starts
;
;=======================================================

;------  Add initial library  -------------------
!path = '/common/idl_libs/idlusr:'+!path

;------  X windows visual class  ----------
device, true_color=24           ; This works in linux.

;------- Window retain control  --------------
device,retain=2                 ; IDL restores windows when uncovered.

;-------  Set some system variables  ---------
!quiet = 1              ; Turn off compile messages.
!edit_input = 1000      ; Set line recall.
host = getenv('HOST')
p = strmid(host,0,1)
!prompt = p+'_idl> '    ; Host sensitive prompt.

print,' HOST = ',host

;------  Set up a timer object  --------------
tm = obj_new('timer')
print,' tm is a timer object (do tm->help for instructions).'

;------  Add libraries to IDL path  ----------
HOME = getenv('HOME')
path,'/common/idl_libs/goddard_astrolib/pro'  ; FITS lib.
path,HOME+'/idl/libs/idlmessenger'      ; Messenger lib.
path,'/common/idl_libs/idldid'          ; Digital cam lib.
path,'/common/idl_libs/idlusr2'         ; Secondary lib.
path,'/common/idl_libs/idlspec'         ; Group specific routines.
path,'/common/idl_libs/idldoc'          ; Librarian.
path,'/common/idl_libs/idltape'         ; Tape lib.
path,'/common/idl_libs/idlnoaa'         ; NOAA lib.
path,'/common/idl_libs/idlsat'          ; Sat lib.
path,front='idlusr$'                    ; Move main lib to front.

path,remove='/examples/'		; Drop some libs.
path,remove='/idl_.../examples$'
The main points are that the library with the path routine is added first, then path is used to add other libraries, move them, or drop them.

The IDL script file still messes up IDL_PATH, but it doesn't matter now. The local library to be aded is not in IDL_PATH at all, so doesn't get the ++ in front. The replicated IDL libraries also still work. The one at the front becomes invalid but is repeated later so is still there. The ones that are valid but replicated don't seem to hurt anything and are weeded out when setting the !path system variable. The local library is added after all this happens, in the IDL startup file. So spawned xterms now work as they should.


Some notes on controlling xterms

The main idea here is that a single IDL routine can be used to set up multiple xterms and run an IDL routine in each. The startup routine can then exit. Here is a simple example:
cmd0 = 'xterm -geometry 60x8+0+0 -bg "#775555" -fg "#ffffff" -title "Initialize" -e idl do_init'

cmd1 = 'xterm -geometry 60x8+0+0 -bg "#eeffff" -fg "#000000" -title "TLM Logging" -e idl do_tlm_log &'
cmd2 = 'xterm -geometry 60x8+0+135 -bg "#ffffee" -fg "#000000" -title "Sphere Logging" -e idl do_sph_log &'
cmd3 = 'xterm -geometry 60x8+0+270 -bg "#eeffee" -fg "#000000" -title "Global Logging" -e idl do_global_log &'

spawn, cmd0
excode = getfile('status.tmp')
file_delete, 'status.tmp'
excode = excode(0)

if excode eq '1' then exit

spawn, cmd1
spawn, cmd2
spawn, cmd3

exit
In the above example, cmd0 does an initialization. It runs the IDL batch file called do_init.pro. All these IDL batch files may be wrapper files, they may simply call another ordinary IDL routine.
Note the last character in the command strings above. All but cmd0 end in &. The & means don't wait after spawning the command, return right away. That allows any number of spawned commands to be active at the same time. cmd0 is different, it checks conditions and sets a status, passed through the text file status.tmp. After that command completes the status is checked (and deleted). The other commands are then run if ok, else everything is terminated. In either case, this startup file exits.

The first xterm command is:

xterm -geometry 60x8+0+0 -bg "#775555" -fg "#ffffff" -title "Initialize" -e idl do_init
The control items are as follows: There are many more xterm items that may be controlled, see man xterm for lots more details.


Summary

  • Make sure no IDL_PATH environmental variable is defined.

  • Add intial library to !path in the IDL startup file:
    !path = '/common/idl_libs/idlusr:'+!path

  • Use path in the IDL startup file to add more libraries.