Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 49 additions & 22 deletions nxs/napi.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ class NeXus(object):
# ==== File ====
nxlib.nxiopen_.restype = c_int
nxlib.nxiopen_.argtypes = [c_char_p, c_int, c_void_pp]
def __init__(self, filename, mode='r'):
def __init__(self, filename, mode='r', encoding='UTF-8'):
"""
Open the NeXus file returning a handle.

Expand All @@ -367,17 +367,19 @@ def __init__(self, filename, mode='r'):
if mode not in _nxopen_mode.values():
raise ValueError("Invalid open mode %s" % str(mode))

self.filename, self.mode = filename, mode
self.encoding = encoding
self.filename = self._str2bytes(filename)
self.mode = mode
self.handle = c_void_p(None)
self._path = []
self._indata = False
status = nxlib.nxiopen_(filename,mode,_ref(self.handle))
status = nxlib.nxiopen_(self.filename,mode,_ref(self.handle))
if status == ERROR:
if mode in [ACC_READ, ACC_RDWR]:
op = 'open'
else:
op = 'create'
raise NeXusError("Could not %s %s" % (op,filename))
raise NeXusError("Could not %s %s" % (op,self.filename))
self.isopen = True

def _getpath(self):
Expand All @@ -391,6 +393,16 @@ def _getlongpath(self):
longpath = property(_getlongpath, doc="Unix-style path including " \
+ "nxclass to the node")

def _str2bytes(self, s):
if isinstance(s, str):
s = s.encode(self.encoding)
return s

def _bytes2str(self, b):
if isinstance(b, bytes):
b = b.decode(self.encoding)
return b

def __del__(self):
"""
Be sure to close the file before deleting the last reference.
Expand Down Expand Up @@ -469,7 +481,7 @@ def setnumberformat(self,type,format):
Corresponds to NXsetnumberformat(&handle,type,format)
"""
type = _nxtype_code[type]
status = nxlib.nxisetnumberformat_(self.handle,type,format)
status = nxlib.nxisetnumberformat_(self.handle,type,self._str2bytes(format))
if status == ERROR:
raise ValueError("Could not set %s to %s in %s" %
(type, format, self.filename))
Expand All @@ -486,7 +498,8 @@ def makegroup(self, name, nxclass):
Corresponds to NXmakegroup(handle, name, nxclass)
"""
# print("makegroup", self._loc(), name, nxclass)
status = nxlib.nximakegroup_(self.handle, name, nxclass)
status = nxlib.nximakegroup_(self.handle, self._str2bytes(name),
self._str2bytes(nxclass))
if status == ERROR:
raise NeXusError("Could not create %s:%s in %s" %
(nxclass, name, self._loc()))
Expand All @@ -507,7 +520,7 @@ def openpath(self, path):

Corresponds to NXopenpath(handle, path)
"""
self._openpath(path, opendata=True)
self._openpath(self._str2bytes(path), opendata=True)

def _openpath(self, path, opendata=True):
"""helper function: open relative path and maybe data"""
Expand Down Expand Up @@ -610,7 +623,7 @@ def opengrouppath(self, path):

Corresponds to NXopengrouppath(handle, path)
"""
self._openpath(path,opendata=False)
self._openpath(self._str2bytes(path),opendata=False)

nxlib.nxiopengroup_.restype = c_int
nxlib.nxiopengroup_.argtypes = [c_void_p, c_char_p, c_char_p]
Expand All @@ -626,7 +639,8 @@ def opengroup(self, name, nxclass=None):
# print("opengroup", self._loc(), name, nxclass)
if nxclass is None:
nxclass = self.__getnxclass(name)
status = nxlib.nxiopengroup_(self.handle, name, nxclass)
status = nxlib.nxiopengroup_(self.handle, self._str2bytes(name),
self._str2bytes(nxclass))
if status == ERROR:
raise ValueError("Could not open %s:%s in %s" %
(nxclass, name, self._loc()))
Expand Down Expand Up @@ -670,6 +684,8 @@ def getgroupinfo(self):
nxclass = ctypes.create_string_buffer(MAXNAMELEN)
n = c_int(0)
status = nxlib.nxigetgroupinfo_(self.handle,_ref(n),path,nxclass)
path = self._bytes2str(path)
nxclass = self._bytes2str(nxclass)
if status == ERROR:
raise ValueError("Could not get group info: %s" % (self._loc()))
# print("getgroupinfo", self._loc(), nxclass.value, name.value, n.value)
Expand Down Expand Up @@ -723,7 +739,7 @@ def getnextentry(self):
# if nxclass == 'SDS':
# dtype = _pytype_code(storage.value)
# print("nextentry", nxclass.value, name.value, storage.value)
return name.value,nxclass.value
return self._bytes2str(name.value), self._bytes2str(nxclass.value)

def getentries(self):
"""
Expand Down Expand Up @@ -879,7 +895,7 @@ def opendata(self, name):
if self._indata:
status = ERROR
else:
status = nxlib.nxiopendata_(self.handle, name)
status = nxlib.nxiopendata_(self.handle, self._str2bytes(name))
if status == ERROR:
raise ValueError("Could not open data %s: %s" % (name, self._loc()))
self._path.append((name,"SDS"))
Expand Down Expand Up @@ -924,7 +940,7 @@ def makedata(self, name, dtype=None, shape=None):
# print("makedata", self._loc(), name, shape, dtype)
storage = _nxtype_code[str(dtype)]
shape = numpy.asarray(shape,'int64')
status = nxlib.nximakedata64_(self.handle,name,storage,len(shape),
status = nxlib.nximakedata64_(self.handle,self._str2bytes(name),storage,len(shape),
shape.ctypes.data_as(c_int64_p))
if status == ERROR:
raise ValueError("Could not create data %s: %s" %
Expand Down Expand Up @@ -958,7 +974,9 @@ def compmakedata(self, name, dtype=None, shape=None, mode='lzw',
chunks[-1] = shape[-1]
else:
chunks = numpy.array(chunks,'int64')
status = nxlib.nxicompmakedata64_(self.handle,name,storage,len(dims),
status = nxlib.nxicompmakedata64_(self.handle,
self._str2bytes(name),
storage,len(dims),
dims.ctypes.data_as(c_int64_p),
_compression_code[mode],
chunks.ctypes.data_as(c_int64_p))
Expand Down Expand Up @@ -1123,7 +1141,7 @@ def getnextattr(self):
raise NeXusError("Could not get next attr: %s" % (self._loc()))
dtype = _pytype_code[storage.value]
# print("getnextattr", name.value, length.value, dtype)
return name.value, length.value, dtype
return self._bytes2str(name.value), length.value, dtype

# TODO: Resolve discrepency between NeXus API documentation and
# TODO: apparent behaviour for getattr/putattr length.
Expand All @@ -1142,7 +1160,8 @@ def getattr(self, name, length, dtype):
storage = c_int(_nxtype_code[str(dtype)])
# print("getattr", self._loc(), name, length, size, dtype)
size = c_int(size)
status = nxlib.nxigetattr_(self.handle,name,pdata,_ref(size),_ref(storage))
status = nxlib.nxigetattr_(self.handle,self._str2bytes(name),
pdata,_ref(size),_ref(storage))
if status == ERROR:
raise ValueError("Could not read attr %s: %s" % (name, self._loc()))
# print("getattr", self._loc(), name, datafn())
Expand Down Expand Up @@ -1194,7 +1213,8 @@ def putattr(self, name, value, dtype = None):

# Perform the call
storage = c_int(_nxtype_code[dtype])
status = nxlib.nxiputattr_(self.handle,name,data,length,storage)
status = nxlib.nxiputattr_(self.handle,self._str2bytes(name),
data,length,storage)
if status == ERROR:
raise NeXusError("Could not write attr %s: %s" %
(name, self._loc()))
Expand Down Expand Up @@ -1289,7 +1309,8 @@ def makenamedlink(self,name,ID):

Corresponds to NXmakenamedlink(handle,name,&ID)
"""
status = nxlib.nximakenamedlink_(self.handle,name,_ref(ID))
status = nxlib.nximakenamedlink_(self.handle,self._str2bytes(name),
_ref(ID))
if status == ERROR:
raise NeXusError("Could not make link %s: %s" % (name, self._loc()))

Expand Down Expand Up @@ -1364,7 +1385,7 @@ def inquirefile(self, maxnamelen=MAXPATHLEN):
status = nxlib.nxiinquirefile_(self.handle,filename,maxnamelen)
if status == ERROR:
raise NeXusError("Could not determine filename: %s" % (self._loc()))
return filename.value
return self._bytes2str(filename.value)

nxlib.nxilinkexternal_.restype = c_int
nxlib.nxilinkexternal_.argtyps = [c_void_p, c_char_p,
Expand All @@ -1378,7 +1399,10 @@ def linkexternal(self, name, nxclass, url):

Corresponds to NXisexternalgroup(&handle,name,nxclass,file,len)
"""
status = nxlib.nxilinkexternal_(self.handle,name,nxclass,url)
status = nxlib.nxilinkexternal_(self.handle,
self._str2bytes(name),
self._str2bytes(nxclass),
self._str2bytes(url))
if status == ERROR:
raise NeXusError("Could not link %s to %s: %s" %
(name, url, self._loc()))
Expand All @@ -1394,12 +1418,15 @@ def isexternalgroup(self, name, nxclass, maxnamelen=MAXPATHLEN):
Corresponds to NXisexternalgroup(&handle,name,nxclass,file,len)
"""
url = ctypes.create_string_buffer(maxnamelen)
status = nxlib.nxiisexternalgroup_(self.handle,name,nxclass,
url,maxnamelen)
status = nxlib.nxiisexternalgroup_(self.handle,
self._str2bytes(name),
self._str2bytes(nxclass),
url,
maxnamelen)
if status == ERROR:
return None
else:
return url.value
return self._bytes2str(url.value)

# ==== Utility functions ====
def _loc(self):
Expand Down