So you have a robust and well-tested program someone gave you that runs in ITT’s IDL programming environment, and you don’t want to rewrite it in Python so you can use Python. Don’t worry, you can use Python to run IDL programs (and probably the other way ’round, too).
Yes, you can have your cake and eat it too. There are actually multiple ways to do this, including two different Python modules (pyIDL and pIDLy), using python’s os.system() to run an IDL script that outputs to a file, then reading in that file with Python, and so on…
I’m going to show off pIDLy. There’s a nice page here that explains it all, but here’s a quick summary:
pIDLy requires numpy and Pexpect to run.
pip install pidly pexpect
Now you set it up in your program:
import pidly ... idl = pidly.IDL('/Applications/itt/idl706/bin/idl')
IDL seems to preferentially installs itself by adding a bunch of aliases and $shell_variables to your .bashrc or .tcshrc file, so the IDL executable is actually not in your $PATH like executables really ought to be. That means you have to give pIDLy the full path to your IDL executable (check your .bashrc or .tcshrc)
Now, to use it: pIDLy works by creating an IDL session within your Python session (I called my session ‘idl’) ; you can pass it commands to execute, and retrieve results.
I’m sending the IDL procedure some of my python variables, but ultimately whatever’s in those parentheses has to follow IDL syntax. You’ll get all the printed messages the IDL program would normally produce, and if something crashes here, you’ll end up at the interactive IDL prompt. Next time you run IDL itself you’ll find all of the commands pIDLy sent to IDL in the scrollback buffer. Also, notice one big difference between IDL procedures and Python programs: In Python, you get results from a procedures by setting the program equal to its output.
outputs = program(inputs)
In IDL, you get results from a procedure by creating a variable, passing it to a function that fills it, and then using the results. (I THINK what’s happening is that IDL is using the argument list to say “this data object has this variable name inside the subroutine, and this other variable name outside the subroutine” – this page supports that theory)
outputs = dblarr(datalen) program(inputs,outputs)
In my above example, r_of_t, phi_of_t, z_of_t, and time_t are created within the ‘kinematics’ subroutine, but they had to exist in some in the main program so IDL would make their values accessible outside of the ‘kinematics’ subroutine. Because they CANNOT exist beforehand in Python, I put their names in strings.
Now, getting results out is easy. Once the IDL session is done running its command, Python resumes on the next line. The IDL session keeps running, though, which allows you to pull out the results.
r_t[i] = idl.r_of_t phi_t[i] = idl.phi_of_t z_t[i] = idl.z_of_t time_t = idl.time_t
They are returned as numpy datatypes, and pIDLy’s developer claims nearly everything works, if a little slowly. The same IDL session can run multiple programs, so you don’t need to close and reopen IDL sessions every time you go through a loop.
Closing the IDL session is easy: