summaryrefslogtreecommitdiff
path: root/silx/io/nxdata
diff options
context:
space:
mode:
Diffstat (limited to 'silx/io/nxdata')
-rw-r--r--silx/io/nxdata/__init__.py4
-rw-r--r--silx/io/nxdata/_utils.py5
-rw-r--r--silx/io/nxdata/parse.py93
-rw-r--r--silx/io/nxdata/write.py5
4 files changed, 83 insertions, 24 deletions
diff --git a/silx/io/nxdata/__init__.py b/silx/io/nxdata/__init__.py
index 796810f..5bfa442 100644
--- a/silx/io/nxdata/__init__.py
+++ b/silx/io/nxdata/__init__.py
@@ -51,6 +51,8 @@ Functions
.. autofunction:: is_valid_nxdata
+.. autofunction:: is_group_with_default_NXdata
+
.. autofunction:: is_NXentry_with_default_NXdata
.. autofunction:: is_NXroot_with_default_NXdata
@@ -59,6 +61,6 @@ Functions
"""
from .parse import NXdata, get_default, is_valid_nxdata, InvalidNXdataError, \
- is_NXentry_with_default_NXdata, is_NXroot_with_default_NXdata
+ is_NXentry_with_default_NXdata, is_NXroot_with_default_NXdata, is_group_with_default_NXdata
from ._utils import get_attr_as_unicode, get_attr_as_string, nxdata_logger
from .write import save_NXdata
diff --git a/silx/io/nxdata/_utils.py b/silx/io/nxdata/_utils.py
index 077f01d..8b3474a 100644
--- a/silx/io/nxdata/_utils.py
+++ b/silx/io/nxdata/_utils.py
@@ -25,12 +25,13 @@
"""Utility functions used by NXdata validation and parsing."""
import copy
-import numpy
import logging
+import numpy
+import six
+
from silx.io import is_dataset
from silx.utils.deprecation import deprecated
-from silx.third_party import six
__authors__ = ["P. Knobel"]
diff --git a/silx/io/nxdata/parse.py b/silx/io/nxdata/parse.py
index daf1b2e..cce47ab 100644
--- a/silx/io/nxdata/parse.py
+++ b/silx/io/nxdata/parse.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2017-2018 European Synchrotron Radiation Facility
+# Copyright (c) 2017-2019 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -37,21 +37,23 @@ Other public functions:
- :func:`is_valid_nxdata`
- :func:`is_NXroot_with_default_NXdata`
- :func:`is_NXentry_with_default_NXdata`
+ - :func:`is_group_with_default_NXdata`
"""
import numpy
+import six
+
from silx.io.utils import is_group, is_file, is_dataset
from ._utils import get_attr_as_unicode, INTERPDIM, nxdata_logger, \
get_uncertainties_names, get_signal_name, \
get_auxiliary_signals_names, validate_auxiliary_signals, validate_number_of_axes
-from silx.third_party import six
__authors__ = ["P. Knobel"]
__license__ = "MIT"
-__date__ = "17/04/2018"
+__date__ = "15/02/2019"
class InvalidNXdataError(Exception):
@@ -136,7 +138,7 @@ class NXdata(object):
self.axes_names = []
# check if axis dataset defines @long_name
- for i, dsname in enumerate(self.axes_dataset_names):
+ for _, dsname in enumerate(self.axes_dataset_names):
if dsname is not None and "long_name" in self.group[dsname].attrs:
self.axes_names.append(get_attr_as_unicode(self.group[dsname], "long_name"))
else:
@@ -151,6 +153,7 @@ class NXdata(object):
raise TypeError("group must be a h5py-like group")
if get_attr_as_unicode(self.group, "NX_class") != "NXdata":
self.issues.append("Group has no attribute @NX_class='NXdata'")
+ return
signal_name = get_signal_name(self.group)
if signal_name is None:
@@ -180,8 +183,14 @@ class NXdata(object):
uncertainties_names = get_uncertainties_names(self.group, signal_name)
if uncertainties_names is not None:
if len(uncertainties_names) != len(axes_names):
- self.issues.append("@uncertainties does not define the same " +
- "number of fields than @axes")
+ if len(uncertainties_names) < len(axes_names):
+ # ignore the field to avoid index error in the axes loop
+ uncertainties_names = None
+ self.issues.append("@uncertainties does not define the same " +
+ "number of fields than @axes. Field ignored")
+ else:
+ self.issues.append("@uncertainties does not define the same " +
+ "number of fields than @axes")
# Test individual axes
is_scatter = True # true if all axes have the same size as the signal
@@ -364,7 +373,7 @@ class NXdata(object):
if not self.is_valid:
raise InvalidNXdataError("Unable to parse invalid NXdata")
- allowed_interpretations = [None, "scalar", "spectrum", "image",
+ allowed_interpretations = [None, "scaler", "scalar", "spectrum", "image",
"rgba-image", # "hsla-image", "cmyk-image"
"vertex"]
@@ -374,7 +383,7 @@ class NXdata(object):
if interpretation not in allowed_interpretations:
nxdata_logger.warning("Interpretation %s is not valid." % interpretation +
- " Valid values: " + ", ".join(allowed_interpretations))
+ " Valid values: " + ", ".join(str(s) for s in allowed_interpretations))
return interpretation
@property
@@ -737,6 +746,28 @@ class NXdata(object):
return False
return True
+ @property
+ def is_volume(self):
+ """True in the signal is exactly 3D and interpretation
+ "scalar", or nothing.
+
+ The axes length must also be consistent with the 3 dimensions
+ of the signal.
+ """
+ if not self.is_valid:
+ raise InvalidNXdataError("Unable to parse invalid NXdata")
+
+ if self.signal_ndim != 3:
+ return False
+ if self.interpretation not in [None, "scalar", "scaler"]:
+ # 'scaler' and 'scalar' for a three dimensional array indicate a scalar field in 3D
+ return False
+ volume_shape = self.signal.shape[-3:]
+ for i, axis in enumerate(self.axes[-3:]):
+ if axis is not None and len(axis) not in [volume_shape[i], 2]:
+ return False
+ return True
+
def is_valid_nxdata(group): # noqa
"""Check if a h5py group is a **valid** NX_data group.
@@ -750,20 +781,19 @@ def is_valid_nxdata(group): # noqa
return nxd.is_valid
-def is_NXentry_with_default_NXdata(group, validate=True):
- """Return True if group is a valid NXentry defining a valid default
+def is_group_with_default_NXdata(group, validate=True):
+ """Return True if group defines a valid default
NXdata.
- :param group: h5py-like object.
- :param bool validate: Set this to False if you are sure that the target group
- is valid NXdata (i.e. :func:`silx.io.nxdata.is_valid_nxdata(target_group)`
- returns True). Parameter provided for optimisation purposes."""
- if not is_group(group):
- return False
+ .. note::
- if get_attr_as_unicode(group, "NX_class") != "NXentry":
- return False
+ See https://github.com/silx-kit/silx/issues/2215
+ :param group: h5py-like object.
+ :param bool validate: Set this to skip the NXdata validation, and only
+ check the existence of the group.
+ Parameter provided for optimisation purposes, to avoid double
+ validation if the validation is already performed separately."""
default_nxdata_name = group.attrs.get("default")
if default_nxdata_name is None or default_nxdata_name not in group:
return False
@@ -779,10 +809,35 @@ def is_NXentry_with_default_NXdata(group, validate=True):
return is_valid_nxdata(default_nxdata_group)
+def is_NXentry_with_default_NXdata(group, validate=True):
+ """Return True if group is a valid NXentry defining a valid default
+ NXdata.
+
+ :param group: h5py-like object.
+ :param bool validate: Set this to skip the NXdata validation, and only
+ check the existence of the group.
+ Parameter provided for optimisation purposes, to avoid double
+ validation if the validation is already performed separately."""
+ if not is_group(group):
+ return False
+
+ if get_attr_as_unicode(group, "NX_class") != "NXentry":
+ return False
+
+ return is_group_with_default_NXdata(group, validate)
+
+
def is_NXroot_with_default_NXdata(group, validate=True):
"""Return True if group is a valid NXroot defining a default NXentry
defining a valid default NXdata.
+ .. note::
+
+ A NXroot group cannot directly define a default NXdata. If a
+ *@default* argument is present, it must point to a NXentry group.
+ This NXentry must define a valid NXdata for this function to return
+ True.
+
:param group: h5py-like object.
:param bool validate: Set this to False if you are sure that the target group
is valid NXdata (i.e. :func:`silx.io.nxdata.is_valid_nxdata(target_group)`
@@ -831,7 +886,7 @@ def get_default(group, validate=True):
if is_NXroot_with_default_NXdata(group, validate=validate):
default_entry = group[group.attrs["default"]]
default_data = default_entry[default_entry.attrs["default"]]
- elif is_NXentry_with_default_NXdata(group, validate=validate):
+ elif is_group_with_default_NXdata(group, validate=validate):
default_data = group[group.attrs["default"]]
elif not validate or is_valid_nxdata(group):
default_data = group
diff --git a/silx/io/nxdata/write.py b/silx/io/nxdata/write.py
index 05eef4d..e9ac3ac 100644
--- a/silx/io/nxdata/write.py
+++ b/silx/io/nxdata/write.py
@@ -23,11 +23,12 @@
#
# ###########################################################################*/
-import h5py
import os
import logging
+
+import h5py
import numpy
-from silx.third_party import six
+import six
__authors__ = ["P. Knobel"]
__license__ = "MIT"