[Scipy-svn] r2202 - trunk/Lib/io
scipy-svn at scipy.org
scipy-svn at scipy.org
Tue Sep 19 11:17:26 EDT 2006
Author: matthew.brett at gmail.com
Date: 2006-09-19 10:16:02 -0500 (Tue, 19 Sep 2006)
New Revision: 2202
Modified:
trunk/Lib/io/mio.py
trunk/Lib/io/mio4.py
trunk/Lib/io/miobase.py
Log:
Fix to permission error on test; fixes to byte swapping on save; refactoring for Mat4 save routines; minor bugfixes to (untested) original dtype recasting
Modified: trunk/Lib/io/mio.py
===================================================================
--- trunk/Lib/io/mio.py 2006-09-19 12:44:07 UTC (rev 2201)
+++ trunk/Lib/io/mio.py 2006-09-19 15:16:02 UTC (rev 2202)
@@ -52,7 +52,7 @@
if full_name is None:
raise IOError, "%s not found on the path." % file_name
- byte_stream = ByteStream(memmap(full_name))
+ byte_stream = ByteStream(memmap(full_name, mode='r'))
MR = MatFile4Reader(byte_stream)
if MR.format_looks_right():
return MR
Modified: trunk/Lib/io/mio4.py
===================================================================
--- trunk/Lib/io/mio4.py 2006-09-19 12:44:07 UTC (rev 2201)
+++ trunk/Lib/io/mio4.py 2006-09-19 15:16:02 UTC (rev 2202)
@@ -38,7 +38,7 @@
'u1': miUINT8,
'S1': miUINT8,
}
-
+
# matrix classes
mxFULL_CLASS = 0
mxCHAR_CLASS = 1
@@ -134,13 +134,14 @@
class Mat4FullGetter(Mat4MatrixGetter):
def get_raw_array(self):
self.header.is_numeric = True
- self.header.original_dtype = dtype(float64)
if self.header.is_complex:
+ self.header.original_dtype = dtype(complex128)
# avoid array copy to save memory
res = self.read_hdr_array(copy=False)
res_j = self.read_hdr_array(copy=False)
return res + (res_j * 1j)
else:
+ self.header.original_dtype = dtype(float64)
return self.read_hdr_array()
@@ -162,13 +163,15 @@
where N is the number of non-zero values. Column 1 values [0:N]
are the (1-based) row indices of the each non-zero value, column 2
[0:N] are the column indices, column 3 [0:N] are the (real)
- values. The last values [-1:0:2] of the rows, column indices are
+ values. The last values [-1,0:2] of the rows, column indices are
shape[0] and shape[1] respectively of the output matrix. The last
value for the values column is a padding 0. mrows and ncols values
from the header give the shape of the stored matrix, here [N+1,
3]. Complex data is saved as a 4 column matrix, where the fourth
column contains the imaginary component of the data; the last
- value is again 0
+ value is again 0. Complex sparse data do _not_ have the header
+ imagf field set to True; the fact that the data are complex is
+ only detectable because there are 4 storage columns
'''
def get_raw_array(self):
self.header.original_dtype = dtype(float64)
@@ -219,62 +222,94 @@
return ByteOrder.native_code
-class MatFile4Writer(MatFileWriter):
- codec = 'ascii'
-
- def arr_to_matrix(self, arr):
- ''' Convert numeric array to matlab format '''
- dts = arr.dtype.str[1:]
- if not dts in np_to_mtypes:
- arr = arr.astype('f8')
- return atleast_2d(arr)
-
- def matrix_header(self, var, name):
- ''' Return header for matrix array '''
+class Mat4MatrixWriter(MatStreamWriter):
+
+ def write_header(self, P, T, dims, imagf):
+ ''' Write header for data type, matrix class, dims, complex flag '''
header = empty((), mdtypes_template['header'])
- dt = var.dtype.str[1:]
M = not ByteOrder.little_endian
O = 0
- P = np_to_mtypes[dt]
- T = dt == 'S1' # could also be sparse -> 2
- header['mopt'] = M*1000+O*100+P*10+T
- dims = var.shape
+ header['mopt'] = (M * 1000 +
+ O * 100 +
+ P * 10 +
+ T)
header['mrows'] = dims[0]
header['ncols'] = dims[1]
- header['imagf'] = var.dtype.kind == 'c'
- header['namlen'] = len(name) + 1
- return header
-
- def put_variable(self, var, name):
- arr = array(var)
- if arr.dtype.hasobject:
- raise TypeError, 'Cannot save object arrays in Mat4'
- if have_sparse:
- if scipy.sparse.issparse(arr):
- raise TypeError, 'Cannot save sparse arrays yet'
- if arr.dtype.kind in ('U', 'S'):
- arr = self.str_to_chars(arr)
- else:
- arr = self.arr_to_matrix(arr)
- dims = arr.shape
+ header['imagf'] = imagf
+ header['namlen'] = len(self.name) + 1
+ self.write_bytes(header)
+ self.write_string(self.name + '\0')
+
+ def arr_to_2d(self):
+ self.arr = atleast_2d(self.arr)
+ dims = self.arr.shape
if len(dims) > 2:
dims = [product(dims[:-1]), dims[-1]]
- arr = reshape(arr, dims)
- if arr.dtype.kind == 'U':
+ self.arr = reshape(self.arr, dims)
+
+ def write(self):
+ assert False, 'Not implemented'
+
+
+class Mat4NumericWriter(Mat4MatrixWriter):
+
+ def write(self):
+ self.arr_to_2d()
+ imagf = self.arr.dtype.kind == 'c'
+ try:
+ P = np_to_mtypes[self.arr.dtype.str[1:]]
+ except KeyError:
+ if imagf:
+ self.arr = self.arr.astype('c128')
+ else:
+ self.arr = self.arr.astype('f8')
+ P = miDOUBLE
+ self.write_header(P, 0, self.arr.shape, imagf)
+ if imagf:
+ self.write_bytes(self.arr.real)
+ self.write_bytes(self.arr.imag)
+ else:
+ self.write_bytes(self.arr)
+
+
+class Mat4CharWriter(Mat4MatrixWriter):
+
+ def write(self):
+ self.arr_to_chars()
+ self.arr_to_2d()
+ dims = self.arr.shape
+ self.write_header(miUINT8, 1, dims, 0)
+ if self.arr.dtype.kind == 'U':
# Recode unicode to ascii
- dt = 'U' + str(product(dims))
- st_arr = ndarray(shape=(), dtype=dt, buffer=arr)
+ n_chars = product(dims)
+ st_arr = ndarray(shape=(),
+ dtype=self.arr_dtype_number(n_chars),
+ buffer=self.arr)
st = st_arr.item().encode('ascii')
- arr = ndarray(shape=dims, dtype='S1', buffer=st)
- header = self.matrix_header(arr, name)
- self.write_bytes(header)
- self.write_string(name + '\0')
- if header['imagf']:
- self.write_bytes(arr.real)
- self.write_bytes(arr.imag)
- else:
- self.write_bytes(arr)
-
+ self.arr = ndarray(shape=dims, dtype='S1', buffer=st)
+ self.write_bytes(self.arr)
+
+
+def matrix_writer_factory(stream, arr, name):
+ ''' Factory function to return matrix writer given variable to write
+ @stream - file or file-like stream to write to
+ @arr - array to write
+ @name - name in matlab workspace
+ '''
+ arr = array(arr)
+ if arr.dtype.hasobject:
+ raise TypeError, 'Cannot save object arrays in Mat4'
+ if have_sparse:
+ if scipy.sparse.issparse(arr):
+ raise TypeError, 'Cannot save sparse arrays yet'
+ if arr.dtype.kind in ('U', 'S'):
+ return Mat4CharWriter(stream, arr, name)
+ else:
+ return Mat4NumericWriter(stream, arr, name)
+
+
+class MatFile4Writer(MatFileWriter):
+
def put_variables(self, mdict):
for name, var in mdict.items():
- self.put_variable(var, name)
+ matrix_writer_factory(self.file_stream, var, name).write()
Modified: trunk/Lib/io/miobase.py
===================================================================
--- trunk/Lib/io/miobase.py 2006-09-19 12:44:07 UTC (rev 2201)
+++ trunk/Lib/io/miobase.py 2006-09-19 15:16:02 UTC (rev 2202)
@@ -257,7 +257,8 @@
b = self.read_bytes(1)
self.mat_stream.seek(-1,1)
return len(b) == 0
-
+
+
class MatMatrixGetter(MatStreamAgent):
""" Base class for matrix getters
@@ -315,25 +316,38 @@
assert False, 'Not implemented'
-class MatFileWriter(object):
- ''' Base type for writing mat files '''
- def __init__(self, file_stream):
+class MatStreamWriter(object):
+ ''' Base object for writing to mat files '''
+ def __init__(self, file_stream, arr, name):
self.file_stream = file_stream
+ self.arr = arr
+ dt = self.arr.dtype
+ if not dt.isnative:
+ self.arr = self.arr.astype(dt.newbyteorder('='))
+ self.name = name
+
+ def arr_dtype_number(self, num):
+ ''' Return dtype for given number of items per element'''
+ return dtype(self.arr.dtype.str[:2] + str(num))
- def str_to_chars(self, arr):
+ def arr_to_chars(self):
''' Converts string array to matlab char array '''
- dims = list(arr.shape)
+ dims = list(self.arr.shape)
if not dims:
dims = [1]
- dims.append(int(arr.dtype.str[2:]))
- num_els = product(dims)
- dt = dtype(arr.dtype.kind + '1')
- return ndarray(shape=dims, dtype=dt, buffer=arr)
+ dims.append(int(self.arr.dtype.str[2:]))
+ self.arr = ndarray(shape=dims,
+ dtype=self.arr_dtype_number(1),
+ buffer=self.arr)
def write_bytes(self, arr):
- arr.dtype.newbyteorder(ByteOrder.native_code)
- s = arr.tostring(order='F')
- self.file_stream.write(s)
+ self.file_stream.write(arr.tostring(order='F'))
def write_string(self, s):
self.file_stream.write(s)
+
+
+class MatFileWriter(object):
+ ''' Base class for Mat file writers '''
+ def __init__(self, file_stream):
+ self.file_stream = file_stream
More information about the Scipy-svn
mailing list