Changeset 204

Show
Ignore:
Timestamp:
05/30/08 17:49:16 (6 months ago)
Author:
edsuom
Message:

Made pybywire.pack more flexible; use whatever array dimensions and dtype you want

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • projects/Twisted-Goodies/trunk/twisted_goodies/pybywire/pack.py

    r109 r204  
    3939class Packer(object): 
    4040    """ 
    41     I pack up SciPY arrays of one or two dimensions, and Python floats. 
     41    I pack up SciPY arrays of any number of dimensions, and Python floats. 
    4242 
    4343    You can supply one or more such arrays to my constructor, or use my 
     
    4545    a compact binary representation (a string) of the entire package of 
    4646    packed-up arrays. 
     47 
     48    The binary format is:: 
     49 
     50        Data Item   Type    Description 
     51        ----------------------------------------------------------------------- 
     52        N_arrays    B       Number of arrays included 
     53        dtype0      -       Array 0 dtype (char format) 
     54        dims0       H       Array 0 number of dimensions 
     55        dim00       H       Array 0, first dimension 
     56        ...         ...     ... 
     57        dim0n       H       Array 0, last dimension 
     58        len0        I       Length of string containing array data 
     59        data0       -       Array 0, raveled, string format 
     60        ... 
     61     
    4762    """ 
    4863    __slots__ = ['dataList'] 
     
    5469 
    5570    def append(self, X): 
    56         dims = len(s.shape(X)) 
    57         if dims == 1: 
    58             X = s.array(X).reshape((len(X), 1)) 
    59         elif dims == 0: 
    60             X = [[X]] 
    61         rows, cols = s.shape(X) 
    62         formatString = "d" * cols 
    63         dataStrings = [struct.pack("ii", rows, cols)] 
    64         for row in X: 
    65             dataStrings.append(struct.pack(formatString, *row)) 
     71        shape = s.shape(X) 
     72        if not shape: 
     73            X = s.array(X) 
     74        X = X.ravel() 
     75        # Header: dtype (1 char), dims, dim_0, ..., dim_n, len 
     76        dataStrings = [ 
     77            X.dtype.char[:1], 
     78            struct.pack("H"*(len(shape)+1), len(shape), *shape), 
     79            None, 
     80            X.tostring()] 
     81        dataStrings[2] = struct.pack("I", len(dataStrings[3])) 
    6682        self.dataList.append("".join(dataStrings)) 
    6783     
     
    7591class Unpacker(object): 
    7692    """ 
    77     I unpack SciPY 1-D arrays, 2-D arrays, and Python floats from a binary 
    78     representation supplied to my constructor as a string. Call the constructed 
    79     instance of me once for each thing to unpack. 
    80  
     93    I unpack SciPY arrays and Python floats from a binary representation 
     94    supplied to my constructor as a string. Call the constructed instance of me 
     95    once for each thing to unpack. 
    8196    """ 
    8297    __slots__ = ['dataString', 'k', 'count', 'N'] 
     
    103118        return self() 
    104119 
     120    def _getValues(self, fmt, N): 
     121        bytes = struct.calcsize(fmt) * N 
     122        result = struct.unpack( 
     123            fmt*N, self.dataString[self.k:self.k+bytes]) 
     124        self.k += bytes 
     125        if N == 1: 
     126            return result[0] 
     127        return result 
     128     
    105129    def __call__(self): 
    106         rows, cols = struct.unpack("ii", self.dataString[self.k:self.k+8]) 
    107         self.k += 8 
    108         Z = s.empty((rows, cols), s.float64) 
    109         formatString = "d" * cols 
    110         for k in xrange(rows): 
    111             rowString = self.dataString[self.k:self.k+8*cols] 
    112             self.k += 8*cols 
    113             Z[k, :] = struct.unpack(formatString, rowString) 
    114         if cols > 1: 
    115             return Z 
    116         if rows > 1: 
    117             return Z[:,0] 
    118         return Z[0][0] 
     130        dtype = self.dataString[self.k] 
     131        self.k += 1 
     132        dims = self._getValues('H', 1) 
     133        shape = self._getValues('H', dims) 
     134        lenData = self._getValues('I', 1) 
     135        Z = s.fromstring(self.dataString[self.k:self.k+lenData], dtype=dtype) 
     136        self.k += lenData 
     137        if dims == 0: 
     138            return Z[0] 
     139        return Z.reshape(shape) 
    119140     
    120141