Source code for ewokscore.persistence.nexus
from pathlib import Path
from typing import Any
from typing import List
from typing import Mapping
import h5py
from silx.io import h5py_utils
from silx.io.dictdump import dicttonx
from silx.io.dictdump import nxtodict
from silx.utils.proxy import docstring
from . import atomic
from .file import FileProxy
# @h5py_utils.retry(retry_period=1)
[docs]
def h5_item_exists(path, item):
try:
with h5py_utils.File(path) as f:
return item in f
except Exception:
return False
[docs]
class NexusProxy(FileProxy):
SCHEME = "nexus"
EXTENSIONS = [".nx", "nxs", ".h5", ".hdf5", ".nexus"]
ALLOW_PATH_IN_FILE = True
[docs]
@docstring(FileProxy)
def exists(self) -> bool:
if not super().exists():
return False
return h5_item_exists(self.path, self.path_in_file)
def _dump(self, path: Path, data: Any, update_mode: str = "add", **_) -> None:
if isinstance(data, Mapping):
h5group = self.path_in_file
else:
h5group = self.path_in_file_parent
h5name = self.path_in_file_name
if h5name:
data = {h5name: data}
elif not isinstance(data, Mapping):
raise TypeError("'data' must be a dictionary")
with atomic.atomic_write_hdf5(path, h5group) as (h5file, h5group):
dicttonx(
treedict=data,
h5file=h5file,
h5path=h5group,
update_mode=update_mode,
add_nx_class=True,
)
self._set_nx_classes(h5file, self.path_in_file_parts())
@staticmethod
def _set_nx_classes(h5file, parts: List[str]):
h5file.attrs["NX_class"] = "NXroot"
h5group = h5file
for i, name in enumerate(parts):
h5group = h5group[name]
if not isinstance(h5group, h5py.Group):
break
if i == 0:
NX_class = "NXentry"
elif i == 1:
NX_class = "NXprocess"
else:
NX_class = "NXcollection"
h5group.attrs["NX_class"] = NX_class
def _load(self, path: Path, **kw) -> Any:
h5group = self.path_in_file_parent
h5name = self.path_in_file_name
adict = nxtodict(h5file=str(path), path=h5group, **kw)
if h5name:
return adict[h5name]
return adict