Ignore:
Timestamp:
08/04/09 01:07:17 (3 years ago)
Author:
Paul Kienzle
Message:

fix python string issue. Refs #173.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/bindings/python/nxs/napi.py

    r1203 r1221  
    419419        Corresponds to NXmakegroup(handle, name, nxclass) 
    420420        """ 
     421        #print "makegroup",self._loc(),name,nxclass 
    421422        status = nxlib.nximakegroup_(self.handle, name, nxclass) 
    422423        if status == ERROR: 
     
    556557        Corresponds to NXopengroup(handle, name, nxclass) 
    557558        """ 
    558         #print "open group",nxclass,name 
     559        #print "opengroup",self._loc(),name,nxclass 
    559560        if nxclass is None: 
    560561            nxclass = self.__getnxclass(name) 
     
    575576        Corresponds to NXclosegroup(handle) 
    576577        """ 
    577         #print "close group" 
     578        #print "closegroup" 
    578579        status = nxlib.nxiclosegroup_(self.handle) 
    579580        if status == ERROR: 
     
    603604        if status == ERROR: 
    604605            raise ValueError, "Could not get group info: %s"%(self._loc()) 
    605         #print "group info",nxclass.value,name.value,n.value 
     606        #print "getgroupinfo",self._loc(),nxclass.value,name.value,n.value 
    606607        name = path.value.split('/')[-1]  # Protect against HDF5 returning path 
    607608        return n.value,name,nxclass.value 
     
    655656        #if nxclass == 'SDS': 
    656657        #    dtype = _pytype_code(storage.value) 
    657         #print "group next",nxclass.value, name.value, storage.value 
     658        #print "nextentry",nxclass.value, name.value, storage.value 
    658659        return name.value,nxclass.value 
    659660 
     
    728729 
    729730    # ==== Data ==== 
    730     nxlib.nxigetinfo_.restype = c_int 
    731     nxlib.nxigetinfo_.argtypes = [c_void_p, c_int_p, c_void_p, c_int_p] 
    732     def getinfo(self): 
     731    nxlib.nxigetrawinfo_.restype = c_int 
     732    nxlib.nxigetrawinfo_.argtypes = [c_void_p, c_int_p, c_void_p, c_int_p] 
     733    def getrawinfo(self): 
    733734        """ 
    734735        Returns the tuple dimensions,type for the currently open dataset. 
     
    740741        complex values. 
    741742 
     743        Unlike getinfo(), the size of the string storage area is 
     744        returned rather than the length of the stored string. 
     745 
     746        Raises NeXusError if this fails. 
     747 
     748        Corresponds to NXgetrawinfo(handle, &rank, dims, &storage), 
     749        but with storage converted from HDF values to numpy compatible 
     750        strings, and rank implicit in the length of the returned dimensions. 
     751        """ 
     752        rank = c_int(0) 
     753        shape = numpy.zeros(MAXRANK, 'i') 
     754        storage = c_int(0) 
     755        status = nxlib.nxigetrawinfo_(self.handle, _ref(rank), shape.ctypes.data, 
     756                                     _ref(storage)) 
     757        if status == ERROR: 
     758            raise NeXusError, "Could not get data info: %s"%(self._loc()) 
     759        shape = shape[:rank.value]+0 
     760        dtype = _pytype_code[storage.value] 
     761        #print "getrawinfo",self._loc(),"->",shape,dtype 
     762        return shape,dtype 
     763 
     764    nxlib.nxigetinfo_.restype = c_int 
     765    nxlib.nxigetinfo_.argtypes = [c_void_p, c_int_p, c_void_p, c_int_p] 
     766    def getinfo(self): 
     767        """ 
     768        Returns the tuple dimensions,type for the currently open dataset. 
     769        Dimensions is an integer array whose length corresponds to the rank 
     770        of the dataset and whose elements are the size of the individual 
     771        dimensions.  Storage type is returned as a string, with 'char' for 
     772        a stored string, '[u]int[8|16|32]' for various integer values or 
     773        'float[32|64]' for floating point values.  No support for 
     774        complex values. 
     775 
     776        Unlike getrawinfo(), the length of the stored string is 
     777        returned rather than the size of the string storage area. 
     778 
    742779        Raises NeXusError if this fails. 
    743780 
     
    758795        shape = shape[:rank.value]+0 
    759796        dtype = _pytype_code[storage.value] 
    760         #print "data info",shape,dtype 
     797        #print "getinfo",self._loc(),"->",shape,dtype 
    761798        return shape,dtype 
    762799 
     
    771808        Corresponds to NXopendata(handle, name) 
    772809        """ 
    773         #print "opening data",name 
     810        #print "opendata",self._loc(),name 
    774811        status = nxlib.nxiopendata_(self.handle, name) 
    775812        if status == ERROR: 
     
    789826        Corresponds to NXclosedata(handle) 
    790827        """ 
    791         #print "closing data" 
     828        #print "closedata" 
    792829        status = nxlib.nxiclosedata_(self.handle) 
    793830        if status == ERROR: 
     
    815852        # TODO: With keywords for value and attr, this can be used for 
    816853        # TODO: makedata, opendata, putdata, putattr, putattr, ..., closedata 
    817         #print "Data",name,dtype,shape 
     854        #print "makedata",self._loc(),name,shape,dtype 
    818855        storage = _nxtype_code[str(dtype)] 
    819856        shape = numpy.array(shape,'i') 
     
    865902        Return the data.  If data is a string (1-D char array), a python 
    866903        string is returned.  If data is a scalar (1-D numeric array of 
    867         length 1), a python numeric scalar is returned. 
     904        length 1), a python scalar is returned.  If data is a string  
     905        array, a numpy array of type 'S#' where # is the maximum string 
     906        length is returned.  If data is a numeric array, a numpy array 
     907        is returned. 
    868908 
    869909        Raises ValueError if this fails. 
     
    873913        # TODO: consider accepting preallocated data so we don't thrash memory 
    874914        shape,dtype = self.getinfo() 
    875         datafn,pdata,size = self._poutput(dtype,shape) 
     915        data,pdata,size,datafn = self._poutput(dtype,shape) 
    876916        status = nxlib.nxigetdata_(self.handle,pdata) 
    877917        if status == ERROR: 
    878918            raise ValueError, "Could not read data: %s"%(self._loc()) 
    879         #print "data",ret() 
     919        #print "getdata",self._loc(),shape,dtype 
    880920        return datafn() 
    881921 
     
    894934        """ 
    895935        # TODO: consider accepting preallocated data so we don't thrash memory 
    896         shape,dtype = self.getinfo() 
    897         datafn,pdata,size = self._poutput(dtype,slab_shape) 
     936        shape,dtype = self.getrawinfo() 
     937        data,pdata,size,datafn = self._poutput(dtype,slab_shape) 
    898938        slab_offset = numpy.array(slab_offset,'i') 
    899939        slab_shape = numpy.array(slab_shape,'i') 
     
    916956        Corresponds to NXputdata(handle, data) 
    917957        """ 
    918         shape,dtype = self.getinfo() 
     958        shape,dtype = self.getrawinfo() 
     959        #print "putdata",self._loc(),shape,dtype 
    919960        data,pdata = self._pinput(data,dtype,shape) 
    920961        status = nxlib.nxiputdata_(self.handle,pdata) 
     
    935976        Corresponds to NXputslab(handle,data,offset,shape) 
    936977        """ 
    937         shape,dtype = self.getinfo() 
     978        shape,dtype = self.getrawinfo() 
    938979        data,pdata = self._pinput(data,dtype,slab_shape) 
    939980        slab_offset = numpy.array(slab_offset,'i') 
     
    10111052            raise NeXusError, "Could not get next attr: %s"%(self._loc()) 
    10121053        dtype = _pytype_code[storage.value] 
    1013         #print "next attr",name.value,length.value,dtype 
     1054        #print "getnextattr",name.value,length.value,dtype 
    10141055        return name.value, length.value, dtype 
    10151056 
     
    10271068        """ 
    10281069        if dtype is 'char': length += 1  # HDF4 needs zero-terminator 
    1029         datafn,pdata,size = self._poutput(str(dtype),[length]) 
     1070        data,pdata,size,datafn = self._poutput(str(dtype),[length]) 
    10301071        storage = c_int(_nxtype_code[str(dtype)]) 
    1031         #print "retrieving",name,length,dtype,size 
     1072        #print "getattr",self._loc(),name,length,size,dtype 
    10321073        size = c_int(size) 
    10331074        status = nxlib.nxigetattr_(self.handle,name,pdata,_ref(size),_ref(storage)) 
    10341075        if status == ERROR: 
    10351076            raise ValueError, "Could not read attr %s: %s" % (name,self._loc()) 
    1036         #print "attr",name,datafn(),size 
     1077        #print "getattr",self._loc(),name,datafn() 
    10371078        return datafn() 
    10381079 
     
    13041345        """ 
    13051346        Build space to collect a nexus data element. 
    1306         Returns datafn,data,size where 
    1307         - datafn is a lamba expression to extract the value out of the element. 
    1308         - pdata is the value to pass to C (effectively a void *) 
     1347        Returns data,pdata,size,datafn where 
     1348        - data is a python type to hold the returned data 
     1349        - pdata is the pointer to the start of the data 
    13091350        - size is the number of bytes in the data block 
    1310         Note that ret can return a string, a scalar or an array depending 
     1351        - datafn is a lamba expression to extract the return value from data 
     1352        Note that datafn can return a string, a scalar or an array depending 
    13111353        on the data type and shape of the data group. 
    13121354        """ 
     
    13141356            # string - use ctypes allocator 
    13151357            size = int(shape[0]) 
    1316             pdata = ctypes.create_string_buffer(size) 
    1317             datafn = lambda: pdata.value 
     1358            data = ctypes.create_string_buffer(size) 
     1359            pdata = data 
     1360            datafn = lambda: data.value 
    13181361        else: 
    1319             # numeric - use numpy array 
    1320             if dtype=='char': dtype = 'uint8' 
    1321             data = numpy.zeros(shape,dtype) 
     1362            # scalar, array or string list - use numpy array 
     1363            if dtype=='char':  
     1364                data = numpy.zeros(shape[:-1], dtype='S%i'%shape[-1]) 
     1365            else: 
     1366                data = numpy.zeros(shape, dtype) 
    13221367            if len(shape) == 1 and shape[0] == 1: 
    13231368                datafn = lambda: data[0] 
     
    13261371            pdata = data.ctypes.data 
    13271372            size = data.nbytes 
    1328         return datafn,pdata,size 
     1373        return data,pdata,size,datafn 
    13291374 
    13301375    def _pinput(self, data, dtype, shape): 
    13311376        """ 
    1332         Convert an input array to a C pointer to a dense array.  This may 
    1333         require conversion of the array, so the new array is returned along 
    1334         with its pointer. 
     1377        Convert an input array to a C pointer to a dense array. 
     1378 
     1379        Returns data, pdata where  
     1380        - data is a possibly new copy of the array 
     1381        - pdata is a pointer to the beginning of the array.   
     1382        Note that you must hold a reference to data for as long  
     1383        as you need pdata to keep the memory from being released to the heap. 
    13351384        """ 
    13361385        if dtype == "char": 
    1337             # Character data - pad with zeros to the right length 
    1338             if not _is_string_like(data): 
    1339                 raise ValueError,"Expected character data: %s"%(self._loc()) 
    1340             if len(data) < shape[0]: 
    1341                 data += '\000'*(shape[0]-len(data)) 
     1386            data = numpy.asarray(data, dtype='S%d'%(shape[-1])) 
    13421387        else: 
    13431388            # Convert scalars to vectors of length one 
    13441389            if numpy.prod(shape) == 1 and not hasattr(data,'shape'): 
    1345                 data = numpy.array([data],dtype=dtype) 
     1390                data = numpy.array([data], dtype=dtype) 
    13461391            # Check that dimensions match 
    13471392            # Ick! need to exclude dimensions of length 1 in order to catch 
     
    13491394            input_shape = numpy.array([i for i in data.shape if i != 1]) 
    13501395            target_shape = numpy.array([i for i in shape if i != 1]) 
    1351             if len(input_shape) != len(target_shape) or (input_shape != target_shape).any(): 
     1396            if len(input_shape) != len(target_shape) \ 
     1397                    or (input_shape != target_shape).any(): 
    13521398                raise ValueError,\ 
    1353                     "Shape mismatch %s!=%s: %s"%(data.shape,shape,self.filename) 
     1399                    "Shape mismatch %s!=%s: %s"%(data_shape,shape,self._loc()) 
     1400            # Check data type 
    13541401            if str(data.dtype) != dtype: 
    13551402                raise ValueError,\ 
    13561403                    "Type mismatch %s!=%s: %s"%(dtype,data.dtype,self._loc()) 
    13571404 
    1358         if dtype == 'char': 
    1359             # String: hand it over as usual for strings.  Assumes the string 
    1360             # is the correct length for the storage area. 
    1361             pdata = data 
    1362         else: 
    1363             # Vector: assume it is of the correct storage class and size 
    1364             data = numpy.ascontiguousarray(data) 
    1365             pdata = data.ctypes.data 
    1366  
     1405        data = numpy.ascontiguousarray(data) 
     1406        pdata = data.ctypes.data 
     1407             
    13671408        return data,pdata 
    13681409 
Note: See TracChangeset for help on using the changeset viewer.