mirpyidl public interface

This shows the documentaiton for the mirpyidl public interface.

mirpyidl

author

Novimir Antoniuk Pablant - npablant@pppl.gov - novimir.pablant@amicitas.com

purpose

Allows for integration of IDL routines into Python.

warning

I have not been careful with generalizing the data types. At this point this will only work on 64 bit systems.

descripton

A library to call IDL (Interactive Data Language) from python. Allows trasparent wrapping of IDL routines and objects as well as arbitrary execution of IDL code.

mirpyidl is hosted at:
https://bitbucket.org/amicitas/mirpyidl
Documentation can be found at:
http://amicitas.bitbucket.io/mirpyidl
To build use the command:
python setup.py build_ext
Known Issues:

As written, this will only work if the idlrpc server is using the default ServerId.

This module includes routines to start an idlrpc server if one is not already running. This currently has some problems:

  • I don’t know a good way to check wheather the server is ready for connections. Currently I wait for the licence server to start, then wait an addition 0.5 seconds.
  • The idlrpc server is left running regardless of whether it was an existing process or started by this module. This is not really the best way to handle things.

IDL side variables

mirpyidl creates a number of variables within the IDL session to track pyidl instances and objects. These variables are then used to provide unique name spaces for different pyidl objects.

Here is a list of the persistent IDL side variables:
  • _mirpyidl_instance_counter
  • _mirpyidl_object_counter
mirpyidl.execute()
mirpyidl.ex()
mirpyidl.setVariable()
mirpyidl.set()
mirpyidl.getVariable()
mirpyidl.get()
mirpyidl.callFunction()
mirpyidl.callPro()
class mirpyidl.PyIDL

Bases: mirpyidl.PyIDLCore

Contains additional shortcut methods based on Python code.

In particular this attempts to simplify wapping of IDL routines. It also provides a workaround for structure, list and hash passing.

callFunction()

A shortcut routine to call IDL functions.

This just calls callMethod() with the options appropriate for an IDL function.

callMethod()

Call an idl subroutine or method.

result_name (string)

default = None

The name of the temporary result variable to use in the IDL function call. If None, a temporary name will be automatically generated.

return_result (bool)

default = True

If true, and function=True, then retrieve and return the result from IDL. If false, then do not return the result.

This option is used internally for object creation.

cleanup (bool)

default = True

If true the result from a function call will be deleted in the IDL session.

This object is used internally for object creation

callPro()

A shortcut routine to call IDL procedure.

This just calls callMethod() with the options appropriate for an IDL procedure.

deleteVariable()

Delete a variable from the idlrpc server.

destroyObject()

Destroy the given IDL object.

ex()

A shortcut to the execute method.

execute()

Execute a command in the IDLRPC session.

Programming Notes:

There are two issues that I need to work around:

Issue # 1

The call to IDL_ExecuteStr or IDL_RPCExecute Str does not always give me the status code that I want, which is the error number for any unrecovered error in the execute command. What is actually returned for the status code is whatever is in !ERROR_STATE.CODE at the end of the call. If an error handler is written in the way that is shown in the IDL manual, the !ERROR_STATE.CODE will in general still have the last error stored even if an error handler successfuly dealt with the error.

To get around this I add on a ” & MEASSAGE, /RESET” to the end of every call. If there is an unrecoverd error, this will not get called and the status code will be returned correctly. If the command completes, even with recoverd errors, then the status will be success.

Issue # 2

This issue is a bit more subtle. IDL has a mechanism for checking for floating point errors. The exact behavior is controled by the !EXCEPT system variable. The default setting is that IDL will check for math errors every time it returns to the main scope. If any math errors are found these will be reported in the returned status code from the execute command. This is generally the desired behavior and fine control can be implemented on either the IDL or python side.

The issue is when there are math errors on the processor floating point status register that have not otherwise been handled before the IDL execute command has been called. In this situaton IDL can pickup the math error after the command has been executed and return an error code that is actually from somewhere else.

This is probably not a common problem as I ran into it when calling both FORTRAN and IDL code from Python where an unhandled floating point error was happening in the FORTRAN code.

The expected behavior would be that IDL would only report math errors that occured within the IDL call. To ensure this I clear any accumulated math errors before calling the IDL command.

I can’t think of any time that this would not be reasonable behavior, however it does add more overhead.

get()

A shortcut to the getVariable method.

getHash()

I do not have a way to actually pass hash objects from IDL to python. In fact, without rebuilding the idl_rpc client/server I can’t even see that I am requesting an object.

This is a work around. Not particularly efficent.

warning:
This will only work if all of the hash tags are strings.
warning:
This will probably fail if the hash that is being retrieved is empty.
getIdlType()
getStructure()

I do not have a way to actually pass structures from IDL to python. In fact, without rebuilding the idl_rpc client/server I can’t even see that I am requesting a structure.

This is a work around. Not particularly efficent.

getTypeIdlFromNumpy()
getTypeNumpyFromIdl()
getVariable()

Get a varible from the idlrpc server. Check for complex types.

idlrpc
isHash()
isStructure()
newObject()

Create a new object and return a string identifier.

function
A string containing the object creation function. For example: “OBJ_NEW”
set()

A shortcut to the setVariable method.

setStructure()

Create a structure in IDL from dictionary in Python.

I cannot directly pass structures to IDL at this point since the structure definition is proprietary. The tools that IDL provides requireds that the IDL interpreter is running, which is not an option.

setVariable()
class mirpyidl.PyIDLObject

Bases: object

This is base class to use when wrapping IDL object. All python wrapper object should inherit from this class.

This class mostly just takes care of handling the mirpyidl object id so that it does not need to be delt with explicitly when wrapping.

callMethod()

Call a method of this object.

This is simply a wrapper of PyIDL, except that the object name is automaically provided.

callMethodFunction()

Call a function method of the object.

This is simply a wrapper of callMethod() but with the appropriate options for a function.

callMethodPro()

Call a procedure method of the object.

This is simply a wrapper of callMethod() but with the appropriate options for a procedure.