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

scipy-svn@scip... scipy-svn@scip...
Mon Dec 8 13:46:55 CST 2008


Author: matthew.brett@gmail.com
Date: 2008-12-08 13:46:52 -0600 (Mon, 08 Dec 2008)
New Revision: 5237

Modified:
   trunk/scipy/io/matlab/mio.py
   trunk/scipy/io/matlab/mio5.py
   trunk/scipy/io/matlab/miobase.py
   trunk/scipy/io/matlab/tests/test_mio.py
Log:
Committed nice patch to allow option for long field names, from Lee Kamentsky via Vebjorn Ljosa

Modified: trunk/scipy/io/matlab/mio.py
===================================================================
--- trunk/scipy/io/matlab/mio.py	2008-12-08 00:08:23 UTC (rev 5236)
+++ trunk/scipy/io/matlab/mio.py	2008-12-08 19:46:52 UTC (rev 5237)
@@ -116,7 +116,7 @@
     return mdict
 
 @filldoc
-def savemat(file_name, mdict, appendmat=True, format='5'):
+def savemat(file_name, mdict, appendmat=True, format='5', long_field_names=False):
     """Save a dictionary of names and arrays into the MATLAB-style .mat file.
 
     This saves the arrayobjects in the given dictionary to a matlab
@@ -130,7 +130,8 @@
     %(append_arg)s
     format : {'5', '4'} string, optional
         '5' for matlab 5 (up to matlab 7.2)
-        '4' for matlab 4 mat files,
+        '4' for matlab 4 mat files
+    %(long_fields)s
     """
     file_is_string = isinstance(file_name, basestring)
     if file_is_string:
@@ -146,9 +147,13 @@
         file_stream = file_name
 
     if format == '4':
+        if long_field_names:
+            raise ValueError("Long field names are not available for version 4 files")
         MW = MatFile4Writer(file_stream)
     elif format == '5':
-        MW = MatFile5Writer(file_stream, unicode_strings=True)
+        MW = MatFile5Writer(file_stream,
+                            unicode_strings=True,
+                            long_field_names=long_field_names)
     else:
         raise ValueError("Format should be '4' or '5'")
     MW.put_variables(mdict)

Modified: trunk/scipy/io/matlab/mio5.py
===================================================================
--- trunk/scipy/io/matlab/mio5.py	2008-12-08 00:08:23 UTC (rev 5236)
+++ trunk/scipy/io/matlab/mio5.py	2008-12-08 19:46:52 UTC (rev 5237)
@@ -631,10 +631,12 @@
                  arr,
                  name,
                  is_global=False,
-                 unicode_strings=False):
+                 unicode_strings=False,
+                 long_field_names=False):
         super(Mat5MatrixWriter, self).__init__(file_stream, arr, name)
         self.is_global = is_global
         self.unicode_strings = unicode_strings
+        self.long_field_names = long_field_names
 
     def write_dtype(self, arr):
         self.file_stream.write(arr.tostring())
@@ -815,9 +817,10 @@
         # write fieldnames
         fieldnames = [f[0] for f in self.arr.dtype.descr]
         length = max([len(fieldname) for fieldname in fieldnames])+1
-        if length > 32:
+        max_length = (self.long_field_names and 64) or 32
+        if length > max_length:
             raise ValueError(
-                "Field names are restricted to 64 characters in Matlab")
+                "Field names are restricted to %d characters in Matlab"%(max_length-1))
         self.write_element(np.array([length], dtype='i4'))
         self.write_element(
             np.array(fieldnames, dtype='S%d'%(length)),
@@ -842,9 +845,10 @@
 
 class Mat5WriterGetter(object):
     ''' Wraps stream and options, provides methods for getting Writer objects '''
-    def __init__(self, stream, unicode_strings):
+    def __init__(self, stream, unicode_strings, long_field_names=False):
         self.stream = stream
         self.unicode_strings = unicode_strings
+        self.long_field_names = long_field_names
 
     def rewind(self):
         self.stream.seek(0)
@@ -871,7 +875,12 @@
             # No interesting conversion possible
             raise TypeError('Could not convert %s (type %s) to array'
                             % (arr, type(arr)))
-        args = (self.stream, narr, name, is_global, self.unicode_strings)
+        args = (self.stream, 
+                narr, 
+                name, 
+                is_global, 
+                self.unicode_strings, 
+                self.long_field_names)
         if isinstance(narr, MatlabFunction):
             return Mat5FunctionWriter(*args)
         if isinstance(narr, MatlabObject):
@@ -895,7 +904,8 @@
     def __init__(self, file_stream,
                  do_compression=False,
                  unicode_strings=False,
-                 global_vars=None):
+                 global_vars=None,
+                 long_field_names=False):
         super(MatFile5Writer, self).__init__(file_stream)
         self.do_compression = do_compression
         if global_vars:
@@ -904,7 +914,8 @@
             self.global_vars = []
         self.writer_getter = Mat5WriterGetter(
             StringIO(),
-            unicode_strings)
+            unicode_strings,
+            long_field_names)
         # write header
         import os, time
         hdr =  np.zeros((), mdtypes_template['file_header'])
@@ -923,6 +934,15 @@
                                None,
                                'get/set unicode strings property')
 
+    def get_long_field_names(self):
+        return self.write_getter.long_field_names
+    def set_long_field_names(self, long_field_names):
+        self.writer_getter.long_field_names = long_field_names
+    long_field_names = property(get_long_field_names,
+                                set_long_field_names,
+                                None,
+                                'enable writing 32-63 character field names for Matlab 7.6+')
+
     def put_variables(self, mdict):
         for name, var in mdict.items():
             if name[0] == '_':

Modified: trunk/scipy/io/matlab/miobase.py
===================================================================
--- trunk/scipy/io/matlab/miobase.py	2008-12-08 00:08:23 UTC (rev 5236)
+++ trunk/scipy/io/matlab/miobase.py	2008-12-08 19:46:52 UTC (rev 5237)
@@ -57,7 +57,13 @@
         Note that non-record arrays cannot be exported via savemat.''',
     'matstream_arg':
     '''mat_stream : file-like
-        object with file API, open for reading'''}
+        object with file API, open for reading''',
+    'long_fields':
+    '''long_field_names : boolean, optional, default=False
+        False - maximum field name length in a structure is 31 characters
+                which is the documented maximum length
+        True  - maximum field name length in a structure is 63 characters
+                which works for Matlab 7.6'''}
     func.__doc__ = func.__doc__ % doc_dict
     return func
 

Modified: trunk/scipy/io/matlab/tests/test_mio.py
===================================================================
--- trunk/scipy/io/matlab/tests/test_mio.py	2008-12-08 00:08:23 UTC (rev 5236)
+++ trunk/scipy/io/matlab/tests/test_mio.py	2008-12-08 19:46:52 UTC (rev 5237)
@@ -338,6 +338,7 @@
     """Regression test for #653."""
     assert_raises(TypeError, savemat, StringIO(), {'d':{1:2}}, format='5')
 
+
 def test_structname_len():
     # Test limit for length of field names in structs
     lim = 31
@@ -349,3 +350,23 @@
     st1 = np.zeros((1,1), dtype=[(fldname, object)])
     assert_raises(ValueError, savemat, StringIO(),
                   {'longstruct': st1}, format='5')
+
+
+def test_4_and_long_field_names_incompatible():
+    # Long field names option not supported in 4
+    my_struct = np.zeros((1,1),dtype=[('my_fieldname',object)])
+    assert_raises(ValueError, savemat, StringIO(),
+                  {'my_struct':my_struct}, format='4', long_field_names=True)
+
+
+def test_long_field_names():
+    # Test limit for length of field names in structs
+    lim = 63
+    fldname = 'a' * lim
+    st1 = np.zeros((1,1), dtype=[(fldname, object)])
+    mat_stream = StringIO()
+    savemat(StringIO(), {'longstruct': st1}, format='5',long_field_names=True)
+    fldname = 'a' * (lim+1)
+    st1 = np.zeros((1,1), dtype=[(fldname, object)])
+    assert_raises(ValueError, savemat, StringIO(),
+                  {'longstruct': st1}, format='5',long_field_names=True)



More information about the Scipy-svn mailing list