Mechanism for Passing Parameters


  • All scalar values are passed to and from Python by value, meaning a copy of the variable is made, and changes to the variable on one side will not affect the other side's value.
  • String arrays, lists, tuples, and dictionaries are passed to and from by value.
  • Numeric arrays are passed by reference when they are used as arguments or keywords to Python methods.
  • Numeric arrays are passed by value when they are passed from IDL to the Python __main__ level and when Python returns a result to IDL. In other words, a copy of the entire array is made. This is due to two reasons. First, unlike Python, IDL has no concept of slices (multiple views into the same array), and could become confused if multiple references to the same array were returned. Second, Python has no simple way to notify when all references to a variable are gone, and therefore IDL does not know when it is safe to delete a variable.

Datatype Conversion


When variables are passed from IDL to Python or Python to IDL (as arguments, keywords, or __main__ variables), the following datatype conversions take place in both directions:

IDL Datatype

Python Type

!NULL (0)

None

Byte (1)

numpy.uint8

Int (2)

numpy.int16

Long (3)

numpy.int32

Float (4)

numpy.float32

Double (5)

numpy.float64, float

Complex (6)

numpy.complex64

String (7)

str, unicode

Structure (8)

see tables below

Double Complex (9)

numpy.complex128

Pointer (10)

not allowed

Objref (11)

see tables below

Uint (12)

numpy.uint16

Ulong (13)

numpy.uint32

Long64 (14)

numpy.int64

Ulong64 (15)

numpy.uint64

The following datatypes are used when converting from IDL to Python:

IDL Datatype

Python Type

Structure (8)

collections.OrderedDict

String array

list

List object

list

Hash, Dictionary object

dict

OrderedHash object

collections.OrderedDict

IDL PYTHON object

corresponding Python object

Other IDL class

Python idlpy.IDL object

The following datatypes are used when converting from Python to IDL:

Python Type

IDL Type

bool, numpy.bool_

Byte (1), with boolean flag

int, long

Long (3) or Long64 (14), depending upon value

float

Double (5)

complex

Double Complex (9)

bytes, bytearray

String (7)

unicode

String (7)

numpy string/unicode array

String array

list

List object

dict

Hash object

collections.OrderedDict

OrderedHash object

tuple

List object

other Python object

IDL PYTHON object that wraps the Python object

Python IDL object

corresponding IDL PYTHON object

Array Dimensions and Array Majority


In IDL the data within a multi-dimensional array is organized as "column major," while in Python the data is organized as "row major."

Column Major Versus Row Major

In IDL, for a two-dimensional array the first dimension represents the "columns" of that array, while the second dimension represents the "rows". In terms of memory layout, the first dimension varies the "fastest", and has a stride equal to the size of the datatype in bytes. The second dimension varies the "slowest" and has a stride equal to the number of columns multiplied by the datatype size in bytes. For example, for a 16-bit integer array each column is separated by two bytes while each row is separated by 6 bytes:

IDL> x = INDGEN(3,2)+1  ; 3 columns by 2 rows
IDL> PRINT, x
  1  2  3
  4  5  6
IDL> PRINT, x[2,1]  ; value in column 2, row 1
  6
IDL> PRINT, BYTE(x, 0, 6*2) ; print the byte representation
  1  0  2  0  3  0  4  0  5  0  6  0

In Python, for a two-dimensional array the first dimension represents the "rows" of that array, while the second dimension represents the "columns". In terms of memory layout, the first dimension varies the "slowest", and has a stride equal to the number of columns multiplied by the datatype size in bytes. The second dimension varies the "fastest" and has a stride equal to the size of the datatype in bytes. For example, for a 16-bit integer array each column is separated by two bytes while each row is separated by 6 bytes:

>>> import numpy as np
>>> x = np.array([[1, 2, 3], [4, 5, 6]], np.int16)
>>> x.shape
  (2L, 3L)
>>> x.strides
  (6L, 2L)
>>> x[1,2]  # value in row 1, column 2
  6
>>> x.tobytes()
  '\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00'

Notice that in both Python and IDL the bytes are organized the same in memory; it is only the way that the dimensions are reported and the indexing order that is different.

Array Conversion

When IDL passes an array to Python, or when Python passes an array back to IDL, the bytes within the data array remain unchanged. Instead, the order of the dimensions is reversed. For example, if we create an array in IDL that has dimensions [3, 640, 480], then in Python the dimensions will be reported as [480, 640, 3]:

IDL> x = BYTARR(3, 640, 480)
IDL> HELP, x
X                       BYTE       = Array[3, 640, 480]
IDL> Python.x = x  ; transfer array to Python
IDL> Python.Run('x.shape')
(480, 640, 3)

In most cases this will be the desired behavior. However, in some cases you may need to transpose your actual data values. For example, you might read in the data from a file in IDL, and then run the data through a Python algorithm that expects a certain order. In IDL you can use the TRANSPOSE function to re-order the values within an array before sending it to Python, while in Python you can use numpy.transpose.

Version History


8.5

Introduced

8.6

Handle numpy string/unicode arrays; handle IDL structures, OrderedHash; handle Python collections.OrderedDict

8.6.1

For variables passed from Python to IDL, change from pass-by-reference to pass-by-value.

See Also


Python Bridge