[Scipy-svn] r6651 - in trunk/scipy/io: . tests

scipy-svn at scipy.org scipy-svn at scipy.org
Wed Aug 18 17:23:13 EDT 2010


Author: matthew.brett at gmail.com
Date: 2010-08-18 16:23:13 -0500 (Wed, 18 Aug 2010)
New Revision: 6651

Added:
   trunk/scipy/io/idl.py
Removed:
   trunk/scipy/io/idlsave.py
Modified:
   trunk/scipy/io/__init__.py
   trunk/scipy/io/tests/test_idlsave.py
Log:
RF - move idlsave to idl, rename read to readsav

Modified: trunk/scipy/io/__init__.py
===================================================================
--- trunk/scipy/io/__init__.py	2010-08-18 21:23:07 UTC (rev 6650)
+++ trunk/scipy/io/__init__.py	2010-08-18 21:23:13 UTC (rev 6651)
@@ -17,7 +17,7 @@
 import matlab.byteordercodes as byteordercodes
 from data_store import save_as_module
 from mmio import mminfo, mmread, mmwrite
-import idlsave
+from idl import readsav
 
 __all__ = filter(lambda s:not s.startswith('_'),dir())
 from numpy.testing import Tester

Copied: trunk/scipy/io/idl.py (from rev 6650, trunk/scipy/io/idlsave.py)
===================================================================
--- trunk/scipy/io/idl.py	                        (rev 0)
+++ trunk/scipy/io/idl.py	2010-08-18 21:23:13 UTC (rev 6651)
@@ -0,0 +1,779 @@
+# IDLSave - a python module to read IDL 'save' files
+# Copyright (c) 2010 Thomas P. Robitaille
+
+# Many thanks to Craig Markwardt for publishing the Unofficial Format
+# Specification for IDL .sav files, without which this Python module would not
+# exist (http://cow.physics.wisc.edu/~craigm/idl/savefmt).
+
+# This code was developed by with permission from ITT Visual Information
+# Systems. IDL(r) is a registered trademark of ITT Visual Information Systems,
+# Inc. for their Interactive Data Language software.
+
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+import struct
+import numpy as np
+import tempfile
+import zlib
+import warnings
+
+# Define the different data types that can be found in an IDL save file
+DTYPE_DICT = {}
+DTYPE_DICT[1] = '>u1'
+DTYPE_DICT[2] = '>i2'
+DTYPE_DICT[3] = '>i4'
+DTYPE_DICT[4] = '>f4'
+DTYPE_DICT[5] = '>f8'
+DTYPE_DICT[6] = '>c8'
+DTYPE_DICT[7] = '|O'
+DTYPE_DICT[8] = '|O'
+DTYPE_DICT[9] = '>c16'
+DTYPE_DICT[12] = '>u2'
+DTYPE_DICT[13] = '>u4'
+DTYPE_DICT[14] = '>i8'
+DTYPE_DICT[15] = '>u8'
+
+# Define the different record types that can be found in an IDL save file
+RECTYPE_DICT = {}
+RECTYPE_DICT[0] = "START_MARKER"
+RECTYPE_DICT[1] = "COMMON_VARIABLE"
+RECTYPE_DICT[2] = "VARIABLE"
+RECTYPE_DICT[3] = "SYSTEM_VARIABLE"
+RECTYPE_DICT[6] = "END_MARKER"
+RECTYPE_DICT[10] = "TIMESTAMP"
+RECTYPE_DICT[12] = "COMPILED"
+RECTYPE_DICT[13] = "IDENTIFICATION"
+RECTYPE_DICT[14] = "VERSION"
+RECTYPE_DICT[15] = "HEAP_HEADER"
+RECTYPE_DICT[16] = "HEAP_DATA"
+RECTYPE_DICT[17] = "PROMOTE64"
+RECTYPE_DICT[19] = "NOTICE"
+
+# Define a dictionary to contain structure definitions
+STRUCT_DICT = {}
+
+
+def _align_32(f):
+    '''Align to the next 32-bit position in a file'''
+
+    pos = f.tell()
+    if pos % 4 <> 0:
+        f.seek(pos + 4 - pos % 4)
+    return
+
+
+def _skip_bytes(f, n):
+    '''Skip `n` bytes'''
+    f.read(n)
+    return
+
+
+def _read_bytes(f, n):
+    '''Read the next `n` bytes'''
+    return f.read(n)
+
+
+def _read_byte(f):
+    '''Read a single byte'''
+    return np.uint8(struct.unpack('>B', f.read(4)[0])[0])
+
+
+def _read_long(f):
+    '''Read a signed 32-bit integer'''
+    return np.int32(struct.unpack('>l', f.read(4))[0])
+
+
+def _read_int16(f):
+    '''Read a signed 16-bit integer'''
+    return np.int16(struct.unpack('>h', f.read(4)[2:4])[0])
+
+
+def _read_int32(f):
+    '''Read a signed 32-bit integer'''
+    return np.int32(struct.unpack('>i', f.read(4))[0])
+
+
+def _read_int64(f):
+    '''Read a signed 64-bit integer'''
+    return np.int64(struct.unpack('>q', f.read(8))[0])
+
+
+def _read_uint16(f):
+    '''Read an unsigned 16-bit integer'''
+    return np.uint16(struct.unpack('>H', f.read(4)[2:4])[0])
+
+
+def _read_uint32(f):
+    '''Read an unsigned 32-bit integer'''
+    return np.uint32(struct.unpack('>I', f.read(4))[0])
+
+
+def _read_uint64(f):
+    '''Read an unsigned 64-bit integer'''
+    return np.uint64(struct.unpack('>Q', f.read(8))[0])
+
+
+def _read_float32(f):
+    '''Read a 32-bit float'''
+    return np.float32(struct.unpack('>f', f.read(4))[0])
+
+
+def _read_float64(f):
+    '''Read a 64-bit float'''
+    return np.float64(struct.unpack('>d', f.read(8))[0])
+
+
+class Pointer(object):
+    '''Class used to define pointers'''
+
+    def __init__(self, index):
+        self.index = index
+        return
+
+
+def _read_string(f):
+    '''Read a string'''
+    length = _read_long(f)
+    if length > 0:
+        chars = _read_bytes(f, length)
+        _align_32(f)
+    else:
+        chars = None
+    return np.str(chars)
+
+
+def _read_string_data(f):
+    '''Read a data string (length is specified twice)'''
+    length = _read_long(f)
+    if length > 0:
+        length = _read_long(f)
+        string = _read_bytes(f, length)
+        _align_32(f)
+    else:
+        string = None
+    return np.str(string)
+
+
+def _read_data(f, dtype):
+    '''Read a variable with a specified data type'''
+    if dtype==1:
+        if _read_int32(f) <> 1:
+            raise Exception("Error occured while reading byte variable")
+        return _read_byte(f)
+    elif dtype==2:
+        return _read_int16(f)
+    elif dtype==3:
+        return _read_int32(f)
+    elif dtype==4:
+        return _read_float32(f)
+    elif dtype==5:
+        return _read_float64(f)
+    elif dtype==6:
+        real = _read_float32(f)
+        imag = _read_float32(f)
+        return np.complex64(real + imag * 1j)
+    elif dtype==7:
+        return _read_string_data(f)
+    elif dtype==8:
+        raise Exception("Should not be here - please report this")
+    elif dtype==9:
+        real = _read_float64(f)
+        imag = _read_float64(f)
+        return np.complex128(real + imag * 1j)
+    elif dtype==10:
+        return Pointer(_read_int32(f))
+    elif dtype==11:
+        raise Exception("Object reference type not implemented")
+    elif dtype==12:
+        return _read_uint16(f)
+    elif dtype==13:
+        return _read_uint32(f)
+    elif dtype==14:
+        return _read_int64(f)
+    elif dtype==15:
+        return _read_uint64(f)
+    else:
+        raise Exception("Unknown IDL type: %i - please report this" % dtype)
+
+
+def _read_structure(f, array_desc, struct_desc):
+    '''
+    Read a structure, with the array and structure descriptors given as
+    `array_desc` and `structure_desc` respectively.
+    '''
+
+    nrows = array_desc['nelements']
+    ncols = struct_desc['ntags']
+    columns = struct_desc['tagtable']
+
+    dtype = []
+    for col in columns:
+        if col['structure'] or col['array']:
+            dtype.append(((col['name'].lower(), col['name']), np.object_))
+        else:
+            if col['typecode'] in DTYPE_DICT:
+                dtype.append(((col['name'].lower(), col['name']),
+                                    DTYPE_DICT[col['typecode']]))
+            else:
+                raise Exception("Variable type %i not implemented" %
+                                                            col['typecode'])
+
+    structure = np.recarray((nrows, ), dtype=dtype)
+
+    for i in range(nrows):
+        for col in columns:
+            dtype = col['typecode']
+            if col['structure']:
+                structure[col['name']][i] = _read_structure(f, \
+                                      struct_desc['arrtable'][col['name']], \
+                                      struct_desc['structtable'][col['name']])
+            elif col['array']:
+                structure[col['name']][i] = _read_array(f, dtype, \
+                                      struct_desc['arrtable'][col['name']])
+            else:
+                structure[col['name']][i] = _read_data(f, dtype)
+
+    return structure
+
+
+def _read_array(f, typecode, array_desc):
+    '''
+    Read an array of type `typecode`, with the array descriptor given as
+    `array_desc`.
+    '''
+
+    if typecode in [1, 3, 4, 5, 6, 9, 13, 14, 15]:
+
+        if typecode == 1:
+            nbytes = _read_int32(f)
+            if nbytes <> array_desc['nbytes']:
+                raise Exception("Error occured while reading byte array")
+
+        # Read bytes as numpy array
+        array = np.fromstring(f.read(array_desc['nbytes']), \
+                                dtype=DTYPE_DICT[typecode])
+
+    elif typecode in [2, 12]:
+
+        # These are 2 byte types, need to skip every two as they are not packed
+
+        array = np.fromstring(f.read(array_desc['nbytes']*2), \
+                                dtype=DTYPE_DICT[typecode])[1::2]
+
+    else:
+
+        # Read bytes into list
+        array = []
+        for i in range(array_desc['nelements']):
+            dtype = typecode
+            data = _read_data(f, dtype)
+            array.append(data)
+
+        array = np.array(array, dtype=np.object_)
+
+    # Reshape array if needed
+    if array_desc['ndims'] > 1:
+        dims = array_desc['dims'][:array_desc['ndims']]
+        dims.reverse()
+        array = array.reshape(dims)
+
+    # Go to next alignment position
+    _align_32(f)
+
+    return array
+
+
+def _read_record(f):
+    '''Function to read in a full record'''
+
+    record = {}
+
+    recpos = f.tell()
+    record['rectype'] = _read_long(f)
+
+    nextrec = _read_uint32(f)
+    nextrec += _read_uint32(f) * 2**32
+
+    _skip_bytes(f, 4)
+
+    if not record['rectype'] in RECTYPE_DICT:
+        raise Exception("Unknown RECTYPE: %i" % record['rectype'])
+
+    record['rectype'] = RECTYPE_DICT[record['rectype']]
+
+    if record['rectype'] in ["VARIABLE", "HEAP_DATA"]:
+
+        if record['rectype'] == "VARIABLE":
+            record['varname'] = _read_string(f)
+        else:
+            record['heap_index'] = _read_long(f)
+            _skip_bytes(f, 4)
+
+        rectypedesc = _read_typedesc(f)
+
+        varstart = _read_long(f)
+        if varstart <> 7:
+            raise Exception("VARSTART is not 7")
+
+        if rectypedesc['structure']:
+            record['data'] = _read_structure(f, rectypedesc['array_desc'], \
+                                          rectypedesc['struct_desc'])
+        elif rectypedesc['array']:
+            record['data'] = _read_array(f, rectypedesc['typecode'], \
+                                      rectypedesc['array_desc'])
+        else:
+            dtype = rectypedesc['typecode']
+            record['data'] = _read_data(f, dtype)
+
+    elif record['rectype'] == "TIMESTAMP":
+
+        _skip_bytes(f, 4*256)
+        record['date'] = _read_string(f)
+        record['user'] = _read_string(f)
+        record['host'] = _read_string(f)
+
+    elif record['rectype'] == "VERSION":
+
+        record['format'] = _read_long(f)
+        record['arch'] = _read_string(f)
+        record['os'] = _read_string(f)
+        record['release'] = _read_string(f)
+
+    elif record['rectype'] == "IDENTIFICATON":
+
+        record['author'] = _read_string(f)
+        record['title'] = _read_string(f)
+        record['idcode'] = _read_string(f)
+
+    elif record['rectype'] == "NOTICE":
+
+        record['notice'] = _read_string(f)
+
+    elif record['rectype'] == "HEAP_HEADER":
+
+        record['nvalues'] = _read_long(f)
+        record['indices'] = []
+        for i in range(record['nvalues']):
+            record['indices'].append(_read_long(f))
+
+    elif record['rectype'] == "COMMONBLOCK":
+
+        record['nvars'] = _read_long(f)
+        record['name'] = _read_string(f)
+        record['varnames'] = []
+        for i in range(record['nvars']):
+            record['varnames'].append(_read_string(f))
+
+    elif record['rectype'] == "END_MARKER":
+
+        record['end'] = True
+
+    elif record['rectype'] == "UNKNOWN":
+
+        warnings.warn("Skipping UNKNOWN record")
+
+    elif record['rectype'] == "SYSTEM_VARIABLE":
+
+        warnings.warn("Skipping SYSTEM_VARIABLE record")
+
+    else:
+
+        raise Exception("record['rectype']=%s not implemented" % \
+                                                            record['rectype'])
+
+    f.seek(nextrec)
+
+    return record
+
+
+def _read_typedesc(f):
+    '''Function to read in a type descriptor'''
+
+    typedesc = {}
+
+    typedesc['typecode'] = _read_long(f)
+    typedesc['varflags'] = _read_long(f)
+
+    if typedesc['varflags'] & 2 == 2:
+        raise Exception("System variables not implemented")
+
+    typedesc['array'] = typedesc['varflags'] & 4 == 4
+    typedesc['structure'] = typedesc['varflags'] & 32 == 32
+
+    if typedesc['structure']:
+        typedesc['array_desc'] = _read_arraydesc(f)
+        typedesc['struct_desc'] = _read_structdesc(f)
+    elif typedesc['array']:
+        typedesc['array_desc'] = _read_arraydesc(f)
+
+    return typedesc
+
+
+def _read_arraydesc(f):
+    '''Function to read in an array descriptor'''
+
+    arraydesc = {}
+
+    arraydesc['arrstart'] = _read_long(f)
+
+    if arraydesc['arrstart'] == 8:
+
+        _skip_bytes(f, 4)
+
+        arraydesc['nbytes'] = _read_long(f)
+        arraydesc['nelements'] = _read_long(f)
+        arraydesc['ndims'] = _read_long(f)
+
+        _skip_bytes(f, 8)
+
+        arraydesc['nmax'] = _read_long(f)
+
+        arraydesc['dims'] = []
+        for d in range(arraydesc['nmax']):
+            arraydesc['dims'].append(_read_long(f))
+
+    elif arraydesc['arrstart'] == 18:
+
+        warnings.warn("Using experimental 64-bit array read")
+
+        _skip_bytes(f, 8)
+
+        arraydesc['nbytes'] = _read_uint64(f)
+        arraydesc['nelements'] = _read_uint64(f)
+        arraydesc['ndims'] = _read_long(f)
+
+        _skip_bytes(f, 8)
+
+        arraydesc['nmax'] = 8
+
+        arraydesc['dims'] = []
+        for d in range(arraydesc['nmax']):
+            v = _read_long(f)
+            if v <> 0:
+                raise Exception("Expected a zero in ARRAY_DESC")
+            arraydesc['dims'].append(_read_long(f))
+
+    else:
+
+        raise Exception("Unknown ARRSTART: %i" % arraydesc['arrstart'])
+
+    return arraydesc
+
+
+def _read_structdesc(f):
+    '''Function to read in a structure descriptor'''
+
+    structdesc = {}
+
+    structstart = _read_long(f)
+    if structstart <> 9:
+        raise Exception("STRUCTSTART should be 9")
+
+    structdesc['name'] = _read_string(f)
+    structdesc['predef'] = _read_long(f)
+    structdesc['ntags'] = _read_long(f)
+    structdesc['nbytes'] = _read_long(f)
+
+    if structdesc['predef'] & 1 == 0:
+
+        structdesc['tagtable'] = []
+        for t in range(structdesc['ntags']):
+            structdesc['tagtable'].append(_read_tagdesc(f))
+
+        for tag in structdesc['tagtable']:
+            tag['name'] = _read_string(f)
+
+        structdesc['arrtable'] = {}
+        for tag in structdesc['tagtable']:
+            if tag['array']:
+                structdesc['arrtable'][tag['name']] = _read_arraydesc(f)
+
+        structdesc['structtable'] = {}
+        for tag in structdesc['tagtable']:
+            if tag['structure']:
+                structdesc['structtable'][tag['name']] = _read_structdesc(f)
+
+        STRUCT_DICT[structdesc['name']] = (structdesc['tagtable'], \
+                                           structdesc['arrtable'], \
+                                           structdesc['structtable'])
+
+    else:
+
+        if not structdesc['name'] in STRUCT_DICT:
+            raise Exception("PREDEF=1 but can't find definition")
+
+        structdesc['tagtable'], \
+        structdesc['arrtable'], \
+        structdesc['structtable'] = STRUCT_DICT[structdesc['name']]
+
+    return structdesc
+
+
+def _read_tagdesc(f):
+    '''Function to read in a tag descriptor'''
+
+    tagdesc = {}
+
+    tagdesc['offset'] = _read_long(f)
+
+    if tagdesc['offset'] == -1:
+        tagdesc['offset'] = _read_uint64(f)
+
+    tagdesc['typecode'] = _read_long(f)
+    tagflags = _read_long(f)
+
+    tagdesc['array'] = tagflags & 4 == 4
+    tagdesc['structure'] = tagflags & 32 == 32
+    tagdesc['scalar'] = tagdesc['typecode'] in DTYPE_DICT
+    # Assume '10'x is scalar
+
+    return tagdesc
+
+
+class AttrDict(dict):
+    '''
+    A case-insensitive dictionary with access via item, attribute, and call
+    notations:
+
+        >>> d = AttrDict()
+        >>> d['Variable'] = 123
+        >>> d['Variable']
+        123
+        >>> d.Variable
+        123
+        >>> d.variable
+        123
+        >>> d('VARIABLE')
+        123
+    '''
+
+    def __init__(self, init={}):
+        dict.__init__(self, init)
+
+    def __getitem__(self, name):
+        return super(AttrDict, self).__getitem__(name.lower())
+
+    def __setitem__(self, key, value):
+        return super(AttrDict, self).__setitem__(key.lower(), value)
+
+    __getattr__ = __getitem__
+    __setattr__ = __setitem__
+    __call__ = __getitem__
+
+
+def readsav(file_name, idict=None, python_dict=False,
+            uncompressed_file_name=None, verbose=False):
+    '''
+    Read an IDL .sav file
+
+    Parameters
+    ----------
+    file_name : str
+        Name of the IDL save file.
+    idict : dict, optional
+        Dictionary in which to insert .sav file variables
+    python_dict: bool, optional
+        By default, the object return is not a Python dictionary, but a
+        case-insensitive dictionary with item, attribute, and call access
+        to variables. To get a standard Python dictionary, set this option
+        to True.
+    uncompressed_file_name : str, optional
+        This option only has an effect for .sav files written with the
+        /compress option. If a file name is specified, compressed .sav
+        files are uncompressed to this file. Otherwise, readsav will use
+        the `tempfile` module to determine a temporary filename
+        automatically, and will remove the temporary file upon successfully
+        reading it in.
+    verbose : bool, optional
+        Whether to print out information about the save file, including
+        the records read, and available variables.
+
+    Returns
+    ----------
+    idl_dict : AttrDict or dict
+        If `python_dict` is set to False (default), this function returns a
+        case-insensitive dictionary with item, attribute, and call access
+        to variables. If `python_dict` is set to True, this function
+        returns a Python dictionary with all variable names in lowercase.
+        If `idict` was specified, then variables are written to the
+        dictionary specified, and the updated dictionary is returned.
+    '''
+
+    # Initialize record and variable holders
+    records = []
+    if python_dict or idict:
+        variables = {}
+    else:
+        variables = AttrDict()
+
+    # Open the IDL file
+    f = file(file_name, 'rb')
+
+    # Read the signature, which should be 'SR'
+    signature = _read_bytes(f, 2)
+    if signature <> 'SR':
+        raise Exception("Invalid SIGNATURE: %s" % signature)
+
+    # Next, the record format, which is '\x00\x04' for normal .sav
+    # files, and '\x00\x06' for compressed .sav files.
+    recfmt = _read_bytes(f, 2)
+
+    if recfmt == '\x00\x04':
+        pass
+
+    elif recfmt == '\x00\x06':
+
+        if verbose:
+            print "IDL Save file is compressed"
+
+        if uncompressed_file_name:
+            fout = file(uncompressed_file_name, 'w+b')
+        else:
+            fout = tempfile.NamedTemporaryFile(suffix='.sav')
+
+        if verbose:
+            print " -> expanding to %s" % fout.name
+
+        # Write header
+        fout.write('SR\x00\x04')
+
+        # Cycle through records
+        while True:
+
+            # Read record type
+            rectype = _read_long(f)
+            fout.write(struct.pack('>l', rectype))
+
+            # Read position of next record and return as int
+            nextrec = _read_uint32(f)
+            nextrec += _read_uint32(f) * 2**32
+
+            # Read the unknown 4 bytes
+            unknown = f.read(4)
+
+            # Check if the end of the file has been reached
+            if RECTYPE_DICT[rectype] == 'END_MARKER':
+                fout.write(struct.pack('>I', int(nextrec) % 2**32))
+                fout.write(struct.pack('>I', int((nextrec - (nextrec % 2**32)) / 2**32)))
+                fout.write(unknown)
+                break
+
+            # Find current position
+            pos = f.tell()
+
+            # Decompress record
+            string = zlib.decompress(f.read(nextrec-pos))
+
+            # Find new position of next record
+            nextrec = fout.tell() + len(string) + 12
+
+            # Write out record
+            fout.write(struct.pack('>I', int(nextrec % 2**32)))
+            fout.write(struct.pack('>I', int((nextrec - (nextrec % 2**32)) / 2**32)))
+            fout.write(unknown)
+            fout.write(string)
+
+        # Close the original compressed file
+        f.close()
+
+        # Set f to be the decompressed file, and skip the first four bytes
+        f = fout
+        f.seek(4)
+
+    else:
+        raise Exception("Invalid RECFMT: %s" % recfmt)
+
+    # Loop through records, and add them to the list
+    while True:
+        r = _read_record(f)
+        records.append(r)
+        if 'end' in r:
+            if r['end']:
+                break
+
+    # Close the file
+    f.close()
+
+    # Find heap data variables
+    heap = {}
+    for r in records:
+        if r['rectype'] == "HEAP_DATA":
+            heap[r['heap_index']] = r['data']
+
+    # Find all variables
+    for r in records:
+        if r['rectype'] == "VARIABLE":
+            while isinstance(r['data'], Pointer):
+                r['data'] = heap[r['data'].index]
+            variables[r['varname'].lower()] = r['data']
+
+    if verbose:
+
+        # Print out timestamp info about the file
+        for record in records:
+            if record['rectype'] == "TIMESTAMP":
+                print "-"*50
+                print "Date: %s" % record['date']
+                print "User: %s" % record['user']
+                print "Host: %s" % record['host']
+                break
+
+        # Print out version info about the file
+        for record in records:
+            if record['rectype'] == "VERSION":
+                print "-"*50
+                print "Format: %s" % record['format']
+                print "Architecture: %s" % record['arch']
+                print "Operating System: %s" % record['os']
+                print "IDL Version: %s" % record['release']
+                break
+
+        # Print out identification info about the file
+        for record in records:
+            if record['rectype'] == "IDENTIFICATON":
+                print "-"*50
+                print "Author: %s" % record['author']
+                print "Title: %s" % record['title']
+                print "ID Code: %s" % record['idcode']
+                break
+
+        print "-"*50
+        print "Successfully read %i records of which:" % \
+                                            (len(records))
+
+        # Create convenience list of record types
+        rectypes = [r['rectype'] for r in records]
+
+        for rt in set(rectypes):
+            if rt <> 'END_MARKER':
+                print " - %i are of type %s" % (rectypes.count(rt), rt)
+        print "-"*50
+
+        if 'VARIABLE' in rectypes:
+            print "Available variables:"
+            for var in variables:
+                print " - %s [%s]" % (var, type(variables[var]))
+            print "-"*50
+
+    if idict:
+        for var in variables:
+            idict[var] = variables[var]
+        return idict
+    else:
+        return variables

Deleted: trunk/scipy/io/idlsave.py
===================================================================
--- trunk/scipy/io/idlsave.py	2010-08-18 21:23:07 UTC (rev 6650)
+++ trunk/scipy/io/idlsave.py	2010-08-18 21:23:13 UTC (rev 6651)
@@ -1,779 +0,0 @@
-# IDLSave - a python module to read IDL 'save' files
-# Copyright (c) 2010 Thomas P. Robitaille
-
-# Many thanks to Craig Markwardt for publishing the Unofficial Format
-# Specification for IDL .sav files, without which this Python module would not
-# exist (http://cow.physics.wisc.edu/~craigm/idl/savefmt).
-
-# This code was developed by with permission from ITT Visual Information
-# Systems. IDL(r) is a registered trademark of ITT Visual Information Systems,
-# Inc. for their Interactive Data Language software.
-
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import struct
-import numpy as np
-import tempfile
-import zlib
-import warnings
-
-# Define the different data types that can be found in an IDL save file
-DTYPE_DICT = {}
-DTYPE_DICT[1] = '>u1'
-DTYPE_DICT[2] = '>i2'
-DTYPE_DICT[3] = '>i4'
-DTYPE_DICT[4] = '>f4'
-DTYPE_DICT[5] = '>f8'
-DTYPE_DICT[6] = '>c8'
-DTYPE_DICT[7] = '|O'
-DTYPE_DICT[8] = '|O'
-DTYPE_DICT[9] = '>c16'
-DTYPE_DICT[12] = '>u2'
-DTYPE_DICT[13] = '>u4'
-DTYPE_DICT[14] = '>i8'
-DTYPE_DICT[15] = '>u8'
-
-# Define the different record types that can be found in an IDL save file
-RECTYPE_DICT = {}
-RECTYPE_DICT[0] = "START_MARKER"
-RECTYPE_DICT[1] = "COMMON_VARIABLE"
-RECTYPE_DICT[2] = "VARIABLE"
-RECTYPE_DICT[3] = "SYSTEM_VARIABLE"
-RECTYPE_DICT[6] = "END_MARKER"
-RECTYPE_DICT[10] = "TIMESTAMP"
-RECTYPE_DICT[12] = "COMPILED"
-RECTYPE_DICT[13] = "IDENTIFICATION"
-RECTYPE_DICT[14] = "VERSION"
-RECTYPE_DICT[15] = "HEAP_HEADER"
-RECTYPE_DICT[16] = "HEAP_DATA"
-RECTYPE_DICT[17] = "PROMOTE64"
-RECTYPE_DICT[19] = "NOTICE"
-
-# Define a dictionary to contain structure definitions
-STRUCT_DICT = {}
-
-
-def _align_32(f):
-    '''Align to the next 32-bit position in a file'''
-
-    pos = f.tell()
-    if pos % 4 <> 0:
-        f.seek(pos + 4 - pos % 4)
-    return
-
-
-def _skip_bytes(f, n):
-    '''Skip `n` bytes'''
-    f.read(n)
-    return
-
-
-def _read_bytes(f, n):
-    '''Read the next `n` bytes'''
-    return f.read(n)
-
-
-def _read_byte(f):
-    '''Read a single byte'''
-    return np.uint8(struct.unpack('>B', f.read(4)[0])[0])
-
-
-def _read_long(f):
-    '''Read a signed 32-bit integer'''
-    return np.int32(struct.unpack('>l', f.read(4))[0])
-
-
-def _read_int16(f):
-    '''Read a signed 16-bit integer'''
-    return np.int16(struct.unpack('>h', f.read(4)[2:4])[0])
-
-
-def _read_int32(f):
-    '''Read a signed 32-bit integer'''
-    return np.int32(struct.unpack('>i', f.read(4))[0])
-
-
-def _read_int64(f):
-    '''Read a signed 64-bit integer'''
-    return np.int64(struct.unpack('>q', f.read(8))[0])
-
-
-def _read_uint16(f):
-    '''Read an unsigned 16-bit integer'''
-    return np.uint16(struct.unpack('>H', f.read(4)[2:4])[0])
-
-
-def _read_uint32(f):
-    '''Read an unsigned 32-bit integer'''
-    return np.uint32(struct.unpack('>I', f.read(4))[0])
-
-
-def _read_uint64(f):
-    '''Read an unsigned 64-bit integer'''
-    return np.uint64(struct.unpack('>Q', f.read(8))[0])
-
-
-def _read_float32(f):
-    '''Read a 32-bit float'''
-    return np.float32(struct.unpack('>f', f.read(4))[0])
-
-
-def _read_float64(f):
-    '''Read a 64-bit float'''
-    return np.float64(struct.unpack('>d', f.read(8))[0])
-
-
-class Pointer(object):
-    '''Class used to define pointers'''
-
-    def __init__(self, index):
-        self.index = index
-        return
-
-
-def _read_string(f):
-    '''Read a string'''
-    length = _read_long(f)
-    if length > 0:
-        chars = _read_bytes(f, length)
-        _align_32(f)
-    else:
-        chars = None
-    return np.str(chars)
-
-
-def _read_string_data(f):
-    '''Read a data string (length is specified twice)'''
-    length = _read_long(f)
-    if length > 0:
-        length = _read_long(f)
-        string = _read_bytes(f, length)
-        _align_32(f)
-    else:
-        string = None
-    return np.str(string)
-
-
-def _read_data(f, dtype):
-    '''Read a variable with a specified data type'''
-    if dtype==1:
-        if _read_int32(f) <> 1:
-            raise Exception("Error occured while reading byte variable")
-        return _read_byte(f)
-    elif dtype==2:
-        return _read_int16(f)
-    elif dtype==3:
-        return _read_int32(f)
-    elif dtype==4:
-        return _read_float32(f)
-    elif dtype==5:
-        return _read_float64(f)
-    elif dtype==6:
-        real = _read_float32(f)
-        imag = _read_float32(f)
-        return np.complex64(real + imag * 1j)
-    elif dtype==7:
-        return _read_string_data(f)
-    elif dtype==8:
-        raise Exception("Should not be here - please report this")
-    elif dtype==9:
-        real = _read_float64(f)
-        imag = _read_float64(f)
-        return np.complex128(real + imag * 1j)
-    elif dtype==10:
-        return Pointer(_read_int32(f))
-    elif dtype==11:
-        raise Exception("Object reference type not implemented")
-    elif dtype==12:
-        return _read_uint16(f)
-    elif dtype==13:
-        return _read_uint32(f)
-    elif dtype==14:
-        return _read_int64(f)
-    elif dtype==15:
-        return _read_uint64(f)
-    else:
-        raise Exception("Unknown IDL type: %i - please report this" % dtype)
-
-
-def _read_structure(f, array_desc, struct_desc):
-    '''
-    Read a structure, with the array and structure descriptors given as
-    `array_desc` and `structure_desc` respectively.
-    '''
-
-    nrows = array_desc['nelements']
-    ncols = struct_desc['ntags']
-    columns = struct_desc['tagtable']
-
-    dtype = []
-    for col in columns:
-        if col['structure'] or col['array']:
-            dtype.append(((col['name'].lower(), col['name']), np.object_))
-        else:
-            if col['typecode'] in DTYPE_DICT:
-                dtype.append(((col['name'].lower(), col['name']),
-                                    DTYPE_DICT[col['typecode']]))
-            else:
-                raise Exception("Variable type %i not implemented" %
-                                                            col['typecode'])
-
-    structure = np.recarray((nrows, ), dtype=dtype)
-
-    for i in range(nrows):
-        for col in columns:
-            dtype = col['typecode']
-            if col['structure']:
-                structure[col['name']][i] = _read_structure(f, \
-                                      struct_desc['arrtable'][col['name']], \
-                                      struct_desc['structtable'][col['name']])
-            elif col['array']:
-                structure[col['name']][i] = _read_array(f, dtype, \
-                                      struct_desc['arrtable'][col['name']])
-            else:
-                structure[col['name']][i] = _read_data(f, dtype)
-
-    return structure
-
-
-def _read_array(f, typecode, array_desc):
-    '''
-    Read an array of type `typecode`, with the array descriptor given as
-    `array_desc`.
-    '''
-
-    if typecode in [1, 3, 4, 5, 6, 9, 13, 14, 15]:
-
-        if typecode == 1:
-            nbytes = _read_int32(f)
-            if nbytes <> array_desc['nbytes']:
-                raise Exception("Error occured while reading byte array")
-
-        # Read bytes as numpy array
-        array = np.fromstring(f.read(array_desc['nbytes']), \
-                                dtype=DTYPE_DICT[typecode])
-
-    elif typecode in [2, 12]:
-
-        # These are 2 byte types, need to skip every two as they are not packed
-
-        array = np.fromstring(f.read(array_desc['nbytes']*2), \
-                                dtype=DTYPE_DICT[typecode])[1::2]
-
-    else:
-
-        # Read bytes into list
-        array = []
-        for i in range(array_desc['nelements']):
-            dtype = typecode
-            data = _read_data(f, dtype)
-            array.append(data)
-
-        array = np.array(array, dtype=np.object_)
-
-    # Reshape array if needed
-    if array_desc['ndims'] > 1:
-        dims = array_desc['dims'][:array_desc['ndims']]
-        dims.reverse()
-        array = array.reshape(dims)
-
-    # Go to next alignment position
-    _align_32(f)
-
-    return array
-
-
-def _read_record(f):
-    '''Function to read in a full record'''
-
-    record = {}
-
-    recpos = f.tell()
-    record['rectype'] = _read_long(f)
-
-    nextrec = _read_uint32(f)
-    nextrec += _read_uint32(f) * 2**32
-
-    _skip_bytes(f, 4)
-
-    if not record['rectype'] in RECTYPE_DICT:
-        raise Exception("Unknown RECTYPE: %i" % record['rectype'])
-
-    record['rectype'] = RECTYPE_DICT[record['rectype']]
-
-    if record['rectype'] in ["VARIABLE", "HEAP_DATA"]:
-
-        if record['rectype'] == "VARIABLE":
-            record['varname'] = _read_string(f)
-        else:
-            record['heap_index'] = _read_long(f)
-            _skip_bytes(f, 4)
-
-        rectypedesc = _read_typedesc(f)
-
-        varstart = _read_long(f)
-        if varstart <> 7:
-            raise Exception("VARSTART is not 7")
-
-        if rectypedesc['structure']:
-            record['data'] = _read_structure(f, rectypedesc['array_desc'], \
-                                          rectypedesc['struct_desc'])
-        elif rectypedesc['array']:
-            record['data'] = _read_array(f, rectypedesc['typecode'], \
-                                      rectypedesc['array_desc'])
-        else:
-            dtype = rectypedesc['typecode']
-            record['data'] = _read_data(f, dtype)
-
-    elif record['rectype'] == "TIMESTAMP":
-
-        _skip_bytes(f, 4*256)
-        record['date'] = _read_string(f)
-        record['user'] = _read_string(f)
-        record['host'] = _read_string(f)
-
-    elif record['rectype'] == "VERSION":
-
-        record['format'] = _read_long(f)
-        record['arch'] = _read_string(f)
-        record['os'] = _read_string(f)
-        record['release'] = _read_string(f)
-
-    elif record['rectype'] == "IDENTIFICATON":
-
-        record['author'] = _read_string(f)
-        record['title'] = _read_string(f)
-        record['idcode'] = _read_string(f)
-
-    elif record['rectype'] == "NOTICE":
-
-        record['notice'] = _read_string(f)
-
-    elif record['rectype'] == "HEAP_HEADER":
-
-        record['nvalues'] = _read_long(f)
-        record['indices'] = []
-        for i in range(record['nvalues']):
-            record['indices'].append(_read_long(f))
-
-    elif record['rectype'] == "COMMONBLOCK":
-
-        record['nvars'] = _read_long(f)
-        record['name'] = _read_string(f)
-        record['varnames'] = []
-        for i in range(record['nvars']):
-            record['varnames'].append(_read_string(f))
-
-    elif record['rectype'] == "END_MARKER":
-
-        record['end'] = True
-
-    elif record['rectype'] == "UNKNOWN":
-
-        warnings.warn("Skipping UNKNOWN record")
-
-    elif record['rectype'] == "SYSTEM_VARIABLE":
-
-        warnings.warn("Skipping SYSTEM_VARIABLE record")
-
-    else:
-
-        raise Exception("record['rectype']=%s not implemented" % \
-                                                            record['rectype'])
-
-    f.seek(nextrec)
-
-    return record
-
-
-def _read_typedesc(f):
-    '''Function to read in a type descriptor'''
-
-    typedesc = {}
-
-    typedesc['typecode'] = _read_long(f)
-    typedesc['varflags'] = _read_long(f)
-
-    if typedesc['varflags'] & 2 == 2:
-        raise Exception("System variables not implemented")
-
-    typedesc['array'] = typedesc['varflags'] & 4 == 4
-    typedesc['structure'] = typedesc['varflags'] & 32 == 32
-
-    if typedesc['structure']:
-        typedesc['array_desc'] = _read_arraydesc(f)
-        typedesc['struct_desc'] = _read_structdesc(f)
-    elif typedesc['array']:
-        typedesc['array_desc'] = _read_arraydesc(f)
-
-    return typedesc
-
-
-def _read_arraydesc(f):
-    '''Function to read in an array descriptor'''
-
-    arraydesc = {}
-
-    arraydesc['arrstart'] = _read_long(f)
-
-    if arraydesc['arrstart'] == 8:
-
-        _skip_bytes(f, 4)
-
-        arraydesc['nbytes'] = _read_long(f)
-        arraydesc['nelements'] = _read_long(f)
-        arraydesc['ndims'] = _read_long(f)
-
-        _skip_bytes(f, 8)
-
-        arraydesc['nmax'] = _read_long(f)
-
-        arraydesc['dims'] = []
-        for d in range(arraydesc['nmax']):
-            arraydesc['dims'].append(_read_long(f))
-
-    elif arraydesc['arrstart'] == 18:
-
-        warnings.warn("Using experimental 64-bit array read")
-
-        _skip_bytes(f, 8)
-
-        arraydesc['nbytes'] = _read_uint64(f)
-        arraydesc['nelements'] = _read_uint64(f)
-        arraydesc['ndims'] = _read_long(f)
-
-        _skip_bytes(f, 8)
-
-        arraydesc['nmax'] = 8
-
-        arraydesc['dims'] = []
-        for d in range(arraydesc['nmax']):
-            v = _read_long(f)
-            if v <> 0:
-                raise Exception("Expected a zero in ARRAY_DESC")
-            arraydesc['dims'].append(_read_long(f))
-
-    else:
-
-        raise Exception("Unknown ARRSTART: %i" % arraydesc['arrstart'])
-
-    return arraydesc
-
-
-def _read_structdesc(f):
-    '''Function to read in a structure descriptor'''
-
-    structdesc = {}
-
-    structstart = _read_long(f)
-    if structstart <> 9:
-        raise Exception("STRUCTSTART should be 9")
-
-    structdesc['name'] = _read_string(f)
-    structdesc['predef'] = _read_long(f)
-    structdesc['ntags'] = _read_long(f)
-    structdesc['nbytes'] = _read_long(f)
-
-    if structdesc['predef'] & 1 == 0:
-
-        structdesc['tagtable'] = []
-        for t in range(structdesc['ntags']):
-            structdesc['tagtable'].append(_read_tagdesc(f))
-
-        for tag in structdesc['tagtable']:
-            tag['name'] = _read_string(f)
-
-        structdesc['arrtable'] = {}
-        for tag in structdesc['tagtable']:
-            if tag['array']:
-                structdesc['arrtable'][tag['name']] = _read_arraydesc(f)
-
-        structdesc['structtable'] = {}
-        for tag in structdesc['tagtable']:
-            if tag['structure']:
-                structdesc['structtable'][tag['name']] = _read_structdesc(f)
-
-        STRUCT_DICT[structdesc['name']] = (structdesc['tagtable'], \
-                                           structdesc['arrtable'], \
-                                           structdesc['structtable'])
-
-    else:
-
-        if not structdesc['name'] in STRUCT_DICT:
-            raise Exception("PREDEF=1 but can't find definition")
-
-        structdesc['tagtable'], \
-        structdesc['arrtable'], \
-        structdesc['structtable'] = STRUCT_DICT[structdesc['name']]
-
-    return structdesc
-
-
-def _read_tagdesc(f):
-    '''Function to read in a tag descriptor'''
-
-    tagdesc = {}
-
-    tagdesc['offset'] = _read_long(f)
-
-    if tagdesc['offset'] == -1:
-        tagdesc['offset'] = _read_uint64(f)
-
-    tagdesc['typecode'] = _read_long(f)
-    tagflags = _read_long(f)
-
-    tagdesc['array'] = tagflags & 4 == 4
-    tagdesc['structure'] = tagflags & 32 == 32
-    tagdesc['scalar'] = tagdesc['typecode'] in DTYPE_DICT
-    # Assume '10'x is scalar
-
-    return tagdesc
-
-
-class AttrDict(dict):
-    '''
-    A case-insensitive dictionary with access via item, attribute, and call
-    notations:
-
-        >>> d = AttrDict()
-        >>> d['Variable'] = 123
-        >>> d['Variable']
-        123
-        >>> d.Variable
-        123
-        >>> d.variable
-        123
-        >>> d('VARIABLE')
-        123
-    '''
-
-    def __init__(self, init={}):
-        dict.__init__(self, init)
-
-    def __getitem__(self, name):
-        return super(AttrDict, self).__getitem__(name.lower())
-
-    def __setitem__(self, key, value):
-        return super(AttrDict, self).__setitem__(key.lower(), value)
-
-    __getattr__ = __getitem__
-    __setattr__ = __setitem__
-    __call__ = __getitem__
-
-
-def read(file_name, idict=None, python_dict=False,
-         uncompressed_file_name=None, verbose=False):
-    '''
-    Read an IDL .sav file
-
-    Parameters
-    ----------
-    file_name : str
-        Name of the IDL save file.
-    idict : dict, optional
-        Dictionary in which to insert .sav file variables
-    python_dict: bool, optional
-        By default, the object return is not a Python dictionary, but a
-        case-insensitive dictionary with item, attribute, and call access
-        to variables. To get a standard Python dictionary, set this option
-        to True.
-    uncompressed_file_name : str, optional
-        This option only has an effect for .sav files written with the
-        /compress option. If a file name is specified, compressed .sav
-        files are uncompressed to this file. Otherwise, idlsave will use
-        the `tempfile` module to determine a temporary filename
-        automatically, and will remove the temporary file upon successfully
-        reading it in.
-    verbose : bool, optional
-        Whether to print out information about the save file, including
-        the records read, and available variables.
-
-    Returns
-    ----------
-    idl_dict : AttrDict or dict
-        If `python_dict` is set to False (default), this function returns a
-        case-insensitive dictionary with item, attribute, and call access
-        to variables. If `python_dict` is set to True, this function
-        returns a Python dictionary with all variable names in lowercase.
-        If `idict` was specified, then variables are written to the
-        dictionary specified, and the updated dictionary is returned.
-    '''
-
-    # Initialize record and variable holders
-    records = []
-    if python_dict or idict:
-        variables = {}
-    else:
-        variables = AttrDict()
-
-    # Open the IDL file
-    f = file(file_name, 'rb')
-
-    # Read the signature, which should be 'SR'
-    signature = _read_bytes(f, 2)
-    if signature <> 'SR':
-        raise Exception("Invalid SIGNATURE: %s" % signature)
-
-    # Next, the record format, which is '\x00\x04' for normal .sav
-    # files, and '\x00\x06' for compressed .sav files.
-    recfmt = _read_bytes(f, 2)
-
-    if recfmt == '\x00\x04':
-        pass
-
-    elif recfmt == '\x00\x06':
-
-        if verbose:
-            print "IDL Save file is compressed"
-
-        if uncompressed_file_name:
-            fout = file(uncompressed_file_name, 'w+b')
-        else:
-            fout = tempfile.NamedTemporaryFile(suffix='.sav')
-
-        if verbose:
-            print " -> expanding to %s" % fout.name
-
-        # Write header
-        fout.write('SR\x00\x04')
-
-        # Cycle through records
-        while True:
-
-            # Read record type
-            rectype = _read_long(f)
-            fout.write(struct.pack('>l', rectype))
-
-            # Read position of next record and return as int
-            nextrec = _read_uint32(f)
-            nextrec += _read_uint32(f) * 2**32
-
-            # Read the unknown 4 bytes
-            unknown = f.read(4)
-
-            # Check if the end of the file has been reached
-            if RECTYPE_DICT[rectype] == 'END_MARKER':
-                fout.write(struct.pack('>I', int(nextrec) % 2**32))
-                fout.write(struct.pack('>I', int((nextrec - (nextrec % 2**32)) / 2**32)))
-                fout.write(unknown)
-                break
-
-            # Find current position
-            pos = f.tell()
-
-            # Decompress record
-            string = zlib.decompress(f.read(nextrec-pos))
-
-            # Find new position of next record
-            nextrec = fout.tell() + len(string) + 12
-
-            # Write out record
-            fout.write(struct.pack('>I', int(nextrec % 2**32)))
-            fout.write(struct.pack('>I', int((nextrec - (nextrec % 2**32)) / 2**32)))
-            fout.write(unknown)
-            fout.write(string)
-
-        # Close the original compressed file
-        f.close()
-
-        # Set f to be the decompressed file, and skip the first four bytes
-        f = fout
-        f.seek(4)
-
-    else:
-        raise Exception("Invalid RECFMT: %s" % recfmt)
-
-    # Loop through records, and add them to the list
-    while True:
-        r = _read_record(f)
-        records.append(r)
-        if 'end' in r:
-            if r['end']:
-                break
-
-    # Close the file
-    f.close()
-
-    # Find heap data variables
-    heap = {}
-    for r in records:
-        if r['rectype'] == "HEAP_DATA":
-            heap[r['heap_index']] = r['data']
-
-    # Find all variables
-    for r in records:
-        if r['rectype'] == "VARIABLE":
-            while isinstance(r['data'], Pointer):
-                r['data'] = heap[r['data'].index]
-            variables[r['varname'].lower()] = r['data']
-
-    if verbose:
-
-        # Print out timestamp info about the file
-        for record in records:
-            if record['rectype'] == "TIMESTAMP":
-                print "-"*50
-                print "Date: %s" % record['date']
-                print "User: %s" % record['user']
-                print "Host: %s" % record['host']
-                break
-
-        # Print out version info about the file
-        for record in records:
-            if record['rectype'] == "VERSION":
-                print "-"*50
-                print "Format: %s" % record['format']
-                print "Architecture: %s" % record['arch']
-                print "Operating System: %s" % record['os']
-                print "IDL Version: %s" % record['release']
-                break
-
-        # Print out identification info about the file
-        for record in records:
-            if record['rectype'] == "IDENTIFICATON":
-                print "-"*50
-                print "Author: %s" % record['author']
-                print "Title: %s" % record['title']
-                print "ID Code: %s" % record['idcode']
-                break
-
-        print "-"*50
-        print "Successfully read %i records of which:" % \
-                                            (len(records))
-
-        # Create convenience list of record types
-        rectypes = [r['rectype'] for r in records]
-
-        for rt in set(rectypes):
-            if rt <> 'END_MARKER':
-                print " - %i are of type %s" % (rectypes.count(rt), rt)
-        print "-"*50
-
-        if 'VARIABLE' in rectypes:
-            print "Available variables:"
-            for var in variables:
-                print " - %s [%s]" % (var, type(variables[var]))
-            print "-"*50
-
-    if idict:
-        for var in variables:
-            idict[var] = variables[var]
-        return idict
-    else:
-        return variables

Modified: trunk/scipy/io/tests/test_idlsave.py
===================================================================
--- trunk/scipy/io/tests/test_idlsave.py	2010-08-18 21:23:07 UTC (rev 6650)
+++ trunk/scipy/io/tests/test_idlsave.py	2010-08-18 21:23:13 UTC (rev 6651)
@@ -7,7 +7,7 @@
 from numpy.testing import assert_equal, assert_array_equal, run_module_suite
 from nose.tools import assert_true
 
-from scipy.io import idlsave
+from scipy.io.idl import readsav
 
 
 def object_array(*args):
@@ -39,7 +39,7 @@
     def test_idict(self):
         custom_dict = {'a': np.int16(999)}
         original_id = id(custom_dict)
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_byte.sav'), idict=custom_dict, verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_byte.sav'), idict=custom_dict, verbose=False)
         assert_equal(original_id, id(s))
         assert_true('a' in s)
         assert_identical(s['a'], np.int16(999))
@@ -50,38 +50,38 @@
     '''Test that scalar values are read in with the correct value and type'''
 
     def test_byte(self):
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_byte.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_byte.sav'), verbose=False)
         assert_identical(s.i8u, np.uint8(234))
 
     def test_int16(self):
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_int16.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_int16.sav'), verbose=False)
         assert_identical(s.i16s, np.int16(-23456))
 
     def test_int32(self):
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_int32.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_int32.sav'), verbose=False)
         assert_identical(s.i32s, np.int32(-1234567890))
 
     def test_float32(self):
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_float32.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_float32.sav'), verbose=False)
         assert_identical(s.f32, np.float32(-3.1234567e+37))
 
     def test_float64(self):
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_float64.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_float64.sav'), verbose=False)
         assert_identical(s.f64, np.float64(-1.1976931348623157e+307))
 
     def test_complex32(self):
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_complex32.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_complex32.sav'), verbose=False)
         assert_identical(s.c32, np.complex64(3.124442e13-2.312442e31j))
 
     def test_string(self):
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_string.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_string.sav'), verbose=False)
         assert_identical(s.s, np.str("The quick brown fox jumps over the lazy python"))
 
     def test_structure(self):
         pass
 
     def test_complex64(self):
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_complex64.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_complex64.sav'), verbose=False)
         assert_identical(s.c64, np.complex128(1.1987253647623157e+112-5.1987258887729157e+307j))
 
     def test_heap_pointer(self):
@@ -91,19 +91,19 @@
         pass
 
     def test_uint16(self):
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_uint16.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_uint16.sav'), verbose=False)
         assert_identical(s.i16u, np.uint16(65511))
 
     def test_uint32(self):
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_uint32.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_uint32.sav'), verbose=False)
         assert_identical(s.i32u, np.uint32(4294967233))
 
     def test_int64(self):
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_int64.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_int64.sav'), verbose=False)
         assert_identical(s.i64s, np.int64(-9223372036854774567))
 
     def test_uint64(self):
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_uint64.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_uint64.sav'), verbose=False)
         assert_identical(s.i64u, np.uint64(18446744073709529285))
 
 
@@ -111,7 +111,7 @@
     '''Test that compressed .sav files can be read in'''
 
     def test_compressed(self):
-        s = idlsave.read(path.join(DATA_PATH, 'various_compressed.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'various_compressed.sav'), verbose=False)
         assert_identical(s.i8u, np.uint8(234))
         assert_identical(s.f32, np.float32(-3.1234567e+37))
         assert_identical(s.c64, np.complex128(1.1987253647623157e+112-5.1987258887729157e+307j))
@@ -126,35 +126,35 @@
     '''Test that multi-dimensional arrays are read in with the correct dimensions'''
 
     def test_1d(self):
-        s = idlsave.read(path.join(DATA_PATH, 'array_float32_1d.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'array_float32_1d.sav'), verbose=False)
         assert_equal(s.array1d.shape, (123, ))
 
     def test_2d(self):
-        s = idlsave.read(path.join(DATA_PATH, 'array_float32_2d.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'array_float32_2d.sav'), verbose=False)
         assert_equal(s.array2d.shape, (22, 12))
 
     def test_3d(self):
-        s = idlsave.read(path.join(DATA_PATH, 'array_float32_3d.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'array_float32_3d.sav'), verbose=False)
         assert_equal(s.array3d.shape, (11, 22, 12))
 
     def test_4d(self):
-        s = idlsave.read(path.join(DATA_PATH, 'array_float32_4d.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'array_float32_4d.sav'), verbose=False)
         assert_equal(s.array4d.shape, (4, 5, 8, 7))
 
     def test_5d(self):
-        s = idlsave.read(path.join(DATA_PATH, 'array_float32_5d.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'array_float32_5d.sav'), verbose=False)
         assert_equal(s.array5d.shape, (4, 3, 4, 6, 5))
 
     def test_6d(self):
-        s = idlsave.read(path.join(DATA_PATH, 'array_float32_6d.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'array_float32_6d.sav'), verbose=False)
         assert_equal(s.array6d.shape, (3, 6, 4, 5, 3, 4))
 
     def test_7d(self):
-        s = idlsave.read(path.join(DATA_PATH, 'array_float32_7d.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'array_float32_7d.sav'), verbose=False)
         assert_equal(s.array7d.shape, (2, 1, 2, 3, 4, 3, 2))
 
     def test_8d(self):
-        s = idlsave.read(path.join(DATA_PATH, 'array_float32_8d.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'array_float32_8d.sav'), verbose=False)
         assert_equal(s.array8d.shape, (4, 3, 2, 1, 2, 3, 5, 4))
 
 
@@ -162,7 +162,7 @@
     '''Test that structures are correctly read in'''
 
     def test_scalars(self):
-        s = idlsave.read(path.join(DATA_PATH, 'struct_scalars.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'struct_scalars.sav'), verbose=False)
         assert_identical(s.scalars.a, np.array(np.int16(1)))
         assert_identical(s.scalars.b, np.array(np.int32(2)))
         assert_identical(s.scalars.c, np.array(np.float32(3.)))
@@ -171,7 +171,7 @@
         assert_identical(s.scalars.f, np.array(np.complex64(-1.+3j)))
 
     def test_scalars_replicated(self):
-        s = idlsave.read(path.join(DATA_PATH, 'struct_scalars_replicated.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'struct_scalars_replicated.sav'), verbose=False)
         assert_identical(s.scalars_rep.a, np.repeat(np.int16(1), 5))
         assert_identical(s.scalars_rep.b, np.repeat(np.int32(2), 5))
         assert_identical(s.scalars_rep.c, np.repeat(np.float32(3.), 5))
@@ -180,7 +180,7 @@
         assert_identical(s.scalars_rep.f, np.repeat(np.complex64(-1.+3j), 5))
 
     def test_arrays(self):
-        s = idlsave.read(path.join(DATA_PATH, 'struct_arrays.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'struct_arrays.sav'), verbose=False)
         assert_array_identical(s.arrays.a[0], np.array([1, 2, 3], dtype=np.int16))
         assert_array_identical(s.arrays.b[0], np.array([4., 5., 6., 7.], dtype=np.float32))
         assert_array_identical(s.arrays.c[0], np.array([np.complex64(1+2j), np.complex64(7+8j)]))
@@ -188,7 +188,7 @@
 
     def test_arrays_replicated(self):
 
-        s = idlsave.read(path.join(DATA_PATH, 'struct_arrays_replicated.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'struct_arrays_replicated.sav'), verbose=False)
 
         # Check column types
         assert_true(s.arrays_rep.a.dtype.type is np.object_)
@@ -214,7 +214,7 @@
     '''Check that pointers in .sav files produce references to the same object in Python'''
 
     def test_pointers(self):
-        s = idlsave.read(path.join(DATA_PATH, 'scalar_heap_pointer.sav'), verbose=False)
+        s = readsav(path.join(DATA_PATH, 'scalar_heap_pointer.sav'), verbose=False)
         assert_identical(s.c64_pointer1, np.complex128(1.1987253647623157e+112-5.1987258887729157e+307j))
         assert_identical(s.c64_pointer2, np.complex128(1.1987253647623157e+112-5.1987258887729157e+307j))
         assert_true(s.c64_pointer1 is s.c64_pointer2)




More information about the Scipy-svn mailing list