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
Copyright © 2010 David W. Fanning
Last Updated 26 October 2010