Machine or Version Specific IDL Code

QUESTION: My goal, of course, is to write machine independent or platform independent, even version indpendent, IDL code all the time. But there are times in IDL when commands work differently on different machine architectures or in different versions of IDL. In those cases, it is necessary to write machine or version specific IDL code. My question is, how is this done in IDL? In other words, how does my program know which machine or version specific code to run?

ANSWER: Machine and version specific information is stored in the IDL system variable !Version. It is easy enough to determine what the machine or version specific information is on your own machine, with the Help command. Here is what the !Version system variable looks like on a 64-bit Windows machine running IDL 8.0.

    IDL> Help, !Version, /Structure
   ** Structure !VERSION, 8 tags, length=104, data length=100:
      ARCH            STRING    'x86_64'       OS              STRING    'Win32'
      OS_FAMILY       STRING    'Windows'
      OS_NAME         STRING    'Microsoft Windows'
      RELEASE         STRING    '8.0'
      BUILD_DATE      STRING    'Jun 17 2010'
      MEMORY_BITS     INT             64       FILE_OFFSET_BITS
                      INT             64 

It is more difficult to tell what the !Version system variable looks like on machines you don't own. Here, for example, is what the !Version system variable looks like on a 64-bit LINUX machine.

    IDL> Help, !Version, /Structure
   ** Structure !VERSION, 8 tags, length=104, data length=100:
      ARCH             STRING    'x86_64'
      OS               STRING    'linux'       OS_FAMILY        STRING    'unix'
      OS_NAME          STRING    'linux'       RELEASE          STRING    '8.0'
      BUILD_DATE       STRING    'Jun 18 2010'
      MEMORY_BITS      INT             64
      FILE_OFFSET_BITS INT             64 

Here is a 32-bit LINUX machine.

    IDL> Help, !Version, /Structure
   ** Structure !VERSION, 8 tags, length=104, data length=100:
      ARCH             STRING    'x86'       OS               STRING    'linux'
      OS_FAMILY        STRING    'unix'       OS_NAME          STRING    'linux'
      RELEASE          STRING    '8.0'
      BUILD_DATE       STRING    'Jun 18 2010'
      MEMORY_BITS      INT             32
      FILE_OFFSET_BITS INT             64 

And here is a Macintosh, running the Mac OS X operating system.

   IDL> Help, !Version, /Structure
   ** Structure !VERSION, 8 tags, length=104, data length=100:
       ARCH            STRING    'x86_64'
       OS              STRING    'darwin'
       OS_FAMILY       STRING    'unix'
       OS_NAME         STRING    'Mac OS X'
       RELEASE         STRING    '7.1'
       BUILD_DATE      STRING    'Apr 21 2009'
       MEMORY_BITS     INT             64        FILE_OFFSET_BITS
                       INT             64  

The OS_NAME field of the !Version system variable on Macintosh computers used to be “MacOS” in the days (pre-2001) before the Macintosh OS X (darwin) operating system.

Naturally, when writing version specific or machine specific code, you can use anything in the !Version system variable that differs between the versions or machines you want to distinguish.

Writing IDL Version Specific Code

Occasionally, you need to write IDL version specific code. Either because a routine was added after a particular version of the software, or there was a bug in a particular version of the software that has to be worked around, and so forth. In these case, we generally use the Release field of the !Version system variable.

For example, here is how TVImage checks to see if the graphics output device supports color decomposition with the Get_Decomposed keyword, which was first introduced in IDL 5.2.

   IF Float(!Version.Release) GE 5.2 THEN Device, Get_Decomposed=theState ELSE theState = 0

Note how the string variable in !Version.Release is converted to a floating point value before doing the comparison in the boolean expression.

Often this kind of code is written in a CASE statement.

   ; Find the mean value of the 2nd dimension of the array
   thisRelease = Float(!Version.Release)    CASE 1 OF 
      (thisRelease LT 5.1): BEGIN          s = Size(array)          ysize = s[2]
         meanvalue = FltArr(ysize)          FOR j=0,ysize-1 DO BEGIN
             meanvalue = Total(array[*,j]) / N_Elements(array[*,j])
         ENDFOR          END 
      ((thisRelease GE 5.1) AND (thisRelease LT 8.0)): BEGIN
         s = Size(array)          ysize = s[2]
         meanValue = Total(array, 2) / ysize 
      (thisRelease GE 8.0): meanValue = Mean(array, 2)     ENDCASE 

Writing IDL Machine Specific Code

It is thought that the safest (that is, longest lasting) way to write machine specific code in IDL is to use the !Version.OS_Family field. This is perfect for separating, for example, code that should run on Windows machines from code that should run on UNIX machines.

     CASE StrUpCase(!Version.OS_Family) OF
      'WINDOWS': rootDir = 'C:\IDL\data'
      'UNIX':    rootDir = '/usr/david/IDL/data'    ENDCASE   
   filename = Filepath(ROOT_DIR=rootDir, 'test.dat') 

But most modern Machintosh computers are, in fact, UNIX computers, so this doesn't distinguish a Macintosh computer from a LINUX computer. There are two ways you can handle this. First, you can use some other field in the !Version system variable to branch on. For example, you could use the OS field. This is considered more dangerous, unless you know exactly which operating systems you will be running the program on.

    CASE StrUpCase(!Version.OS) OF       'WIN32':  rootDir = 'C:\IDL\data'
      'LINUX':  rootDir = '/usr/david/IDL/data'
      'DARWIN': rootDir = '/usr/idlusers/david/IDL/data'
      ELSE: Message, 'Do not recognize this operating system.'    ENDCASE   
   filename = Filepath(ROOT_DIR=rootDir, 'test.dat') 

Less dangerous is to use the !Version.OS_Family field, but then fish out the Macintosh computers from the general UNIX computers. I generally use StrPos to identify Macintosh computers, by searching for the string "Mac" or "Mac OS" in the !Version.OS_Name field.

    CASE StrUpCase(!Version.OS_Family) OF
      'WINDOWS': rootDir = 'C:\IDL\data'       'UNIX': BEGIN
        IF StrPos(!Version.OS_Name, 'Mac') GE 0 THEN BEGIN
            rootDir = '/usr/idlusers/david/IDL/data' ; Macintosh
        ENDIF ELSE BEGIN
            rootDir = '/usr/david/IDL/data' ; other UNIX.         ENDELSE
	END       ENDCASE       filename = Filepath(ROOT_DIR=rootDir, 'test.dat')

Version of IDL used to prepare this article: IDL 8.0

Google
 
Web Coyote's Guide to IDL Programming