diff --git a/.github/workflows/plugin_test.yaml b/.github/workflows/plugin_test.yaml
index 5b7b43b7d..32fd9bbfd 100644
--- a/.github/workflows/plugin_test.yaml
+++ b/.github/workflows/plugin_test.yaml
@@ -30,10 +30,10 @@ jobs:
branch: main
tests_to_run: tests/.
- plugin: pynxtools-igor
- branch: update-definitions
+ branch: main
tests_to_run: tests/.
- plugin: pynxtools-mpes
- branch: update-definitions
+ branch: main
tests_to_run: tests/.
- plugin: pynxtools-raman
branch: main
diff --git a/CITATION.cff b/CITATION.cff
index 67d45ad01..cf46d9c00 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -4,7 +4,7 @@ message:
If you use this software, please cite it using the
metadata from this file.
type: software
-version: 0.9.3
+version: 0.10.0
authors:
- given-names: Sherjeel
family-names: Shabih
diff --git a/pyproject.toml b/pyproject.toml
index 833ae9eef..cc59d830e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -36,6 +36,7 @@ dependencies = [
"lxml>=4.9.1",
"toposort>=1.10.0",
"anytree",
+ "pint==0.17",
]
[project.urls]
diff --git a/src/pynxtools/data/NXtest.nxdl.xml b/src/pynxtools/data/NXtest.nxdl.xml
index fa2917205..329f42ef2 100644
--- a/src/pynxtools/data/NXtest.nxdl.xml
+++ b/src/pynxtools/data/NXtest.nxdl.xml
@@ -19,7 +19,7 @@
-
+
A dummy entry to test optional parent check for a required child.
@@ -27,8 +27,29 @@
A dummy entry to test optional parent check for an optional child.
-
-
+
+ A group with a (specified) name, but nameType not given explicitly.
+
+
+
+
+
+
+ A group with a name and nameType="specified".
+
+
+
+
+
+
+ A group with a name and nameType="any".
+
+
+
+
+
+
+
A dummy entry for a float value.
@@ -52,10 +73,10 @@
-
-
-
-
+
+
+
+
@@ -64,6 +85,12 @@
+
+
+
+
+
+
@@ -94,5 +121,9 @@
A required NXuser entry.
+
+
+
+
diff --git a/src/pynxtools/dataconverter/helpers.py b/src/pynxtools/dataconverter/helpers.py
index 290b4a634..ee3647414 100644
--- a/src/pynxtools/dataconverter/helpers.py
+++ b/src/pynxtools/dataconverter/helpers.py
@@ -48,24 +48,25 @@
class ValidationProblem(Enum):
UnitWithoutDocumentation = 1
InvalidEnum = 2
- MissingRequiredGroup = 3
- MissingRequiredField = 4
- MissingRequiredAttribute = 5
- InvalidType = 6
- InvalidDatetime = 7
- IsNotPosInt = 8
- ExpectedGroup = 9
- MissingDocumentation = 10
- MissingUnit = 11
- ChoiceValidationError = 12
- UnitWithoutField = 13
- AttributeForNonExistingField = 14
- BrokenLink = 15
- FailedNamefitting = 16
- NXdataMissingSignalData = 17
- NXdataMissingAxisData = 18
- NXdataAxisMismatch = 19
- KeyToBeRemoved = 20
+ OpenEnumWithNewItem = 3
+ MissingRequiredGroup = 4
+ MissingRequiredField = 5
+ MissingRequiredAttribute = 6
+ InvalidType = 7
+ InvalidDatetime = 8
+ IsNotPosInt = 9
+ ExpectedGroup = 10
+ MissingDocumentation = 11
+ MissingUnit = 12
+ ChoiceValidationError = 13
+ UnitWithoutField = 14
+ AttributeForNonExistingField = 15
+ BrokenLink = 16
+ FailedNamefitting = 17
+ NXdataMissingSignalData = 18
+ NXdataMissingAxisData = 19
+ NXdataAxisMismatch = 20
+ KeyToBeRemoved = 21
class Collector:
@@ -85,7 +86,11 @@ def _log(self, path: str, log_type: ValidationProblem, value: Optional[Any], *ar
)
elif log_type == ValidationProblem.InvalidEnum:
logger.warning(
- f"The value at {path} should be one of the following: {value}"
+ f"The value at {path} should be one of the following: {value}."
+ )
+ elif log_type == ValidationProblem.OpenEnumWithNewItem:
+ logger.info(
+ f"The value at {path} does not match with the enumerated items from the open enumeration: {value}."
)
elif log_type == ValidationProblem.MissingRequiredGroup:
logger.warning(f"The required group, {path}, hasn't been supplied.")
@@ -164,7 +169,10 @@ def collect_and_log(
if self.logging and path + str(log_type) + str(value) not in self.data:
self._log(path, log_type, value, *args, **kwargs)
# info messages should not fail validation
- if log_type not in (ValidationProblem.UnitWithoutDocumentation,):
+ if log_type not in (
+ ValidationProblem.UnitWithoutDocumentation,
+ ValidationProblem.OpenEnumWithNewItem,
+ ):
self.data.add(path + str(log_type) + str(value))
def has_validation_problems(self):
@@ -266,7 +274,7 @@ def get_all_parents_for(xml_elem: ET._Element) -> List[ET._Element]:
root = get_appdef_root(xml_elem)
inheritance_chain = []
extends = root.get("extends")
- while extends is not None and extends != "NXobject":
+ while extends is not None:
parent_xml_root, _ = get_nxdl_root_and_path(extends)
extends = parent_xml_root.get("extends")
inheritance_chain.append(parent_xml_root)
@@ -489,6 +497,15 @@ def contains_uppercase(field_name: Optional[str]) -> bool:
return any(char.isupper() for char in field_name)
+def is_variadic(name: str, name_type: str) -> bool:
+ """
+ Determine if a name is variadic based on its nameType.
+ """
+ if name:
+ return False if name_type == "specified" else True
+ return True
+
+
def convert_nexus_to_suggested_name(nexus_name):
"""Helper function to suggest a name for a group from its NeXus class."""
if contains_uppercase(nexus_name):
@@ -646,7 +663,9 @@ def convert_str_to_bool_safe(value: str) -> Optional[bool]:
raise ValueError(f"Could not interpret string '{value}' as boolean.")
-def is_valid_data_field(value: Any, nxdl_type: str, nxdl_enum: list, path: str) -> Any:
+def is_valid_data_field(
+ value: Any, nxdl_type: str, nxdl_enum: list, nxdl_enum_open: bool, path: str
+) -> Any:
# todo: Check this function and write test for it. It seems the function is not
# working as expected.
"""Checks whether a given value is valid according to the type defined in the NXDL.
@@ -688,11 +707,18 @@ def is_valid_data_field(value: Any, nxdl_type: str, nxdl_enum: list, path: str)
# Check enumeration
if nxdl_enum is not None and value not in nxdl_enum:
- collector.collect_and_log(
- path,
- ValidationProblem.InvalidEnum,
- nxdl_enum,
- )
+ if nxdl_enum_open:
+ collector.collect_and_log(
+ path,
+ ValidationProblem.OpenEnumWithNewItem,
+ nxdl_enum,
+ )
+ else:
+ collector.collect_and_log(
+ path,
+ ValidationProblem.InvalidEnum,
+ nxdl_enum,
+ )
return value
@@ -871,8 +897,8 @@ def update_and_warn(key: str, value: str):
"https://github.com/FAIRmat-NFDI/nexus_definitions/"
f"blob/{get_nexus_version_hash()}",
)
- update_and_warn("/@NeXus_version", get_nexus_version())
- update_and_warn("/@HDF5_version", ".".join(map(str, h5py.h5.get_libversion())))
+ update_and_warn("/@NeXus_release", get_nexus_version())
+ update_and_warn("/@HDF5_Version", ".".join(map(str, h5py.h5.get_libversion())))
update_and_warn("/@h5py_version", h5py.__version__)
diff --git a/src/pynxtools/dataconverter/nexus_tree.py b/src/pynxtools/dataconverter/nexus_tree.py
index 77349df49..1b721cadb 100644
--- a/src/pynxtools/dataconverter/nexus_tree.py
+++ b/src/pynxtools/dataconverter/nexus_tree.py
@@ -35,19 +35,23 @@
from anytree.node.nodemixin import NodeMixin
from pynxtools.dataconverter.helpers import (
- contains_uppercase,
get_all_parents_for,
get_nxdl_root_and_path,
+ is_variadic,
is_appdef,
remove_namespace_from_tag,
)
-from pynxtools.definitions.dev_tools.utils.nxdl_utils import get_nx_namefit
+from pynxtools.definitions.dev_tools.utils.nxdl_utils import (
+ get_nx_namefit,
+ is_name_type,
+)
NexusType = Literal[
"NX_BINARY",
"NX_BOOLEAN",
"NX_CCOMPLEX",
"NX_CHAR",
+ "NX_CHAR_OR_NUMBER",
"NX_COMPLEX",
"NX_DATE_TIME",
"NX_FLOAT",
@@ -111,6 +115,9 @@ class NexusNode(NodeMixin):
The name of the node.
type (Literal["group", "field", "attribute", "choice"]):
The type of the node, e.g., xml tag in the nxdl file.
+ name_type (Optional["specified", "any", "partial"]):
+ The nameType of the node.
+ Defaults to "specified".
optionality (Literal["required", "recommended", "optional"], optional):
The optionality of the node.
This is automatically set on init (in the respective subclasses)
@@ -118,8 +125,8 @@ class NexusNode(NodeMixin):
Defaults to "required".
variadic (bool):
True if the node name is variadic and can be matched against multiple names.
- This is set automatically on init and will be True if the name contains
- any uppercase characets and False otherwise.
+ This is set automatically on init and will be True if the `nameTYPE` is "any"
+ or "partial" and False otherwise.
Defaults to False.
inheritance (List[InstanceOf[ET._Element]]):
The inheritance chain of the node.
@@ -145,6 +152,7 @@ class NexusNode(NodeMixin):
name: str
type: Literal["group", "field", "attribute", "choice"]
+ name_type: Optional[Literal["specified", "any", "partial"]] = "specified"
optionality: Literal["required", "recommended", "optional"] = "required"
variadic: bool = False
inheritance: List[ET._Element]
@@ -177,6 +185,7 @@ def __init__(
self,
name: str,
type: Literal["group", "field", "attribute", "choice"],
+ name_type: Optional[Literal["specified", "any", "partial"]] = "specified",
optionality: Literal["required", "recommended", "optional"] = "required",
variadic: Optional[bool] = None,
parent: Optional["NexusNode"] = None,
@@ -185,8 +194,9 @@ def __init__(
super().__init__()
self.name = name
self.type = type
+ self.name_type = name_type
self.optionality = optionality
- self.variadic = contains_uppercase(self.name)
+ self.variadic = is_variadic(self.name, self.name_type)
if variadic is not None:
self.variadic = variadic
if inheritance is not None:
@@ -460,6 +470,7 @@ def _build_inheritance_chain(self, xml_elem: ET._Element) -> List[ET._Element]:
This represents the direct field or group inside the specific xml file.
"""
name = xml_elem.attrib.get("name")
+
inheritance_chain = [xml_elem]
inheritance = iter(self.inheritance)
for elem in inheritance:
@@ -483,18 +494,28 @@ def _build_inheritance_chain(self, xml_elem: ET._Element) -> List[ET._Element]:
best_group = None
best_score = -1
for group in groups:
- if name in group.attrib and not contains_uppercase(
- group.attrib["name"]
- ):
- continue
group_name = (
group.attrib.get("name")
if "name" in group.attrib
else group.attrib["type"][2:].upper()
)
- score = get_nx_namefit(name, group_name)
- if get_nx_namefit(name, group_name) >= best_score:
+ if "name" in group.attrib:
+ group_name_type = group.attrib.get("nameType", "specified")
+
+ else:
+ group_name_type = group.attrib.get("nameType", "any")
+
+ if not is_variadic(group_name, group_name_type):
+ continue
+
+ group_name_any = is_name_type(group, "any")
+ group_name_partial = is_name_type(group, "partial")
+
+ score = get_nx_namefit(
+ name, group_name, group_name_any, group_name_partial
+ )
+ if score >= best_score:
best_group = group
best_score = score
@@ -525,21 +546,31 @@ def add_node_from(self, xml_elem: ET._Element) -> Optional["NexusNode"]:
"""
default_optionality = "required" if is_appdef(xml_elem) else "optional"
tag = remove_namespace_from_tag(xml_elem.tag)
+
+ name_type = xml_elem.attrib.get("nameType", "specified")
+
if tag in ("field", "attribute"):
name = xml_elem.attrib.get("name")
+
current_elem = NexusEntity(
parent=self,
name=name,
+ name_type=name_type,
type=tag,
optionality=default_optionality,
)
elif tag == "group":
- name = xml_elem.attrib.get("name", xml_elem.attrib["type"][2:].upper())
+ name = xml_elem.attrib.get("name")
+ if not name:
+ name = xml_elem.attrib["type"][2:].upper()
+ name_type = "any"
+
inheritance_chain = self._build_inheritance_chain(xml_elem)
current_elem = NexusGroup(
parent=self,
type=tag,
name=name,
+ name_type=name_type,
nx_class=xml_elem.attrib["type"],
inheritance=inheritance_chain,
optionality=default_optionality,
@@ -548,7 +579,7 @@ def add_node_from(self, xml_elem: ET._Element) -> Optional["NexusNode"]:
current_elem = NexusChoice(
parent=self,
name=xml_elem.attrib["name"],
- variadic=contains_uppercase(xml_elem.attrib["name"]),
+ name_type=name_type,
optionality=default_optionality,
)
else:
@@ -644,6 +675,7 @@ def _check_sibling_namefit(self):
for elem in self.inheritance[1:]:
parent = elem.getparent()
+
if parent is None:
continue
siblings = parent.findall(
@@ -651,15 +683,33 @@ def _check_sibling_namefit(self):
)
for sibling in siblings:
- sibling_name = sibling.attrib.get(
- "name", sibling.attrib["type"][2:].upper()
+ sibling_name = (
+ sibling.attrib.get("name")
+ if "name" in sibling.attrib
+ else sibling.attrib["type"][2:].upper()
)
- if sibling_name == self.name or not contains_uppercase(sibling_name):
+
+ if "name" in sibling.attrib:
+ sibling_name_type = sibling.attrib.get("nameType", "specified")
+ else:
+ sibling_name_type = sibling.attrib.get("nameType", "any")
+
+ if not is_variadic(sibling_name, sibling_name_type):
continue
- if get_nx_namefit(self.name, sibling_name) < 0:
+
+ sibling_name_any = is_name_type(sibling, "any")
+ sibling_name_partial = is_name_type(sibling, "partial")
+
+ if (
+ get_nx_namefit(
+ self.name, sibling_name, sibling_name_any, sibling_name_partial
+ )
+ < 0
+ ):
continue
sibling_node = self.parent.get_child_for(sibling)
+
if sibling_node is None:
sibling_node = self.parent.add_node_from(sibling)
self.is_a.append(sibling_node)
@@ -717,9 +767,9 @@ def __init__(self, nx_class: str, **data) -> None:
self._check_sibling_namefit()
def __repr__(self) -> str:
- return (
- f"{self.nx_class[2:].upper()}[{self.name.lower()}] ({self.optionality[:3]})"
- )
+ if self.type == "attribute":
+ return f"@{self.name} ({self.optionality[:3]})"
+ return f"{self.name} ({self.optionality[:3]})"
class NexusEntity(NexusNode):
@@ -747,6 +797,10 @@ class NexusEntity(NexusNode):
Also the base classes of these entities are considered.
If there is no restriction this is set to None.
Defaults to None.
+ open_enum (bool):
+ If enumerations are used, the enumeration can be open (i.e., the value is not limited
+ to the enumeration items) or closed (i.e., the value must exactly match one of the
+ enumeration items). This is controlled by the open_enum boolean. By default, it is closed.
shape (Optional[Tuple[Optional[int], ...]]):
The shape of the entity as given by the dimensions tag.
This is set automatically on init based on the values found in the nxdl file.
@@ -761,7 +815,8 @@ class NexusEntity(NexusNode):
type: Literal["field", "attribute"]
unit: Optional[NexusUnitCategory] = None
dtype: NexusType = "NX_CHAR"
- items: Optional[List[Any]] = None
+ items: Optional[List[str]] = None
+ open_enum: bool = False
shape: Optional[Tuple[Optional[int], ...]] = None
def _set_type(self):
@@ -784,7 +839,7 @@ def _set_unit(self):
self.unit = elem.attrib["units"]
return
- def _set_items(self):
+ def _set_items_and_enum_type(self):
"""
Sets the enumeration items of the current entity
based on the values in the inheritance chain.
@@ -792,7 +847,10 @@ def _set_items(self):
"""
for elem in self.inheritance:
enum = elem.find(f"nx:enumeration", namespaces=namespaces)
+
if enum is not None:
+ if enum.attrib.get("open") == "true":
+ self.open_enum = True
self.items = []
for items in enum.findall(f"nx:item", namespaces=namespaces):
value = items.attrib["value"]
@@ -850,7 +908,7 @@ def __init__(self, **data) -> None:
self._construct_inheritance_chain_from_parent()
self._set_unit()
self._set_type()
- self._set_items()
+ self._set_items_and_enum_type()
self._set_optionality()
self._set_shape()
@@ -919,6 +977,7 @@ def add_children_to(parent: NexusNode, xml_elem: ET._Element) -> None:
name=appdef_xml_root.attrib["name"],
nx_class="NXroot",
type="group",
+ name_type="specified",
optionality="required",
variadic=False,
parent=None,
diff --git a/src/pynxtools/dataconverter/readers/example/reader.py b/src/pynxtools/dataconverter/readers/example/reader.py
index 7e368a264..0d60b335e 100644
--- a/src/pynxtools/dataconverter/readers/example/reader.py
+++ b/src/pynxtools/dataconverter/readers/example/reader.py
@@ -57,7 +57,15 @@ def read(
# The entries in the template dict should correspond with what the dataconverter
# outputs with --generate-template for a provided NXDL file
if (
- k.startswith("/ENTRY[entry]/required_group")
+ k.startswith(
+ (
+ "/ENTRY[entry]/required_group",
+ "/ENTRY[entry]/specified_group",
+ "/ENTRY[entry]/any_groupGROUP[any_groupgroup]",
+ "/ENTRY[entry]/identified_calibration",
+ "/ENTRY[entry]/named_collection",
+ )
+ )
or k
in (
"/ENTRY[entry]/optional_parent/req_group_in_opt_group",
diff --git a/src/pynxtools/dataconverter/validation.py b/src/pynxtools/dataconverter/validation.py
index 250a87bf4..f923f11bf 100644
--- a/src/pynxtools/dataconverter/validation.py
+++ b/src/pynxtools/dataconverter/validation.py
@@ -112,9 +112,9 @@ def default_to_regular_dict(d):
def split_class_and_name_of(name: str) -> Tuple[Optional[str], str]:
"""
Return the class and the name of a data dict entry of the form
- `get_class_of("ENTRY[entry]")`, which will return `("ENTRY", "entry")`.
+ `split_class_and_name_of("ENTRY[entry]")`, which will return `("ENTRY", "entry")`.
If this is a simple string it will just return this string, i.e.
- `get_class_of("entry")` will return `None, "entry"`.
+ `split_class_and_name_of("entry")` will return `None, "entry"`.
Args:
name (str): The data dict entry
@@ -161,7 +161,10 @@ def best_namefit_of(name: str, nodes: Iterable[NexusNode]) -> Optional[NexusNode
if instance_name == node.name:
return node
- score = get_nx_namefit(instance_name, node.name)
+ name_any = node.name_type == "any"
+ name_partial = node.name_type == "partial"
+
+ score = get_nx_namefit(instance_name, node.name, name_any, name_partial)
if score > -1:
best_match = node
@@ -201,11 +204,19 @@ def get_variations_of(node: NexusNode, keys: Mapping[str, Any]) -> List[str]:
return [f"{convert_nexus_to_caps(node.nx_class)}[{node.name}]"]
variations = []
+
for key in keys:
concept_name, instance_name = split_class_and_name_of(key)
if node.type == "attribute":
# Remove the starting @ from attributes
+ if concept_name:
+ concept_name = (
+ concept_name[1:]
+ if concept_name.startswith("@")
+ else concept_name
+ )
+
instance_name = (
instance_name[1:]
if instance_name.startswith("@")
@@ -215,8 +226,11 @@ def get_variations_of(node: NexusNode, keys: Mapping[str, Any]) -> List[str]:
if not concept_name or concept_name != node.name:
continue
+ name_any = node.name_type == "any"
+ name_partial = node.name_type == "partial"
+
if (
- get_nx_namefit(instance_name, node.name) >= 0
+ get_nx_namefit(instance_name, node.name, name_any, name_partial) >= 0
and key not in node.parent.get_all_direct_children_names()
):
variations.append(key)
@@ -228,8 +242,12 @@ def get_variations_of(node: NexusNode, keys: Mapping[str, Any]) -> List[str]:
return variations
def get_field_attributes(name: str, keys: Mapping[str, Any]) -> Mapping[str, Any]:
+ prefix = f"{name}@"
return {
- f"@{k.split('@')[1]}": keys[k] for k in keys if k.startswith(f"{name}@")
+ # Preserve everything after the field name, keeping '@attr[@attr]' or '@attr'
+ k[len(prefix) - 1 :]: v
+ for k, v in keys.items()
+ if k.startswith(prefix)
}
def handle_nxdata(node: NexusGroup, keys: Mapping[str, Any], prev_path: str):
@@ -350,6 +368,7 @@ def check_nxdata():
def handle_group(node: NexusGroup, keys: Mapping[str, Any], prev_path: str):
variants = get_variations_of(node, keys)
+
if node.parent_of:
for child in node.parent_of:
variants += get_variations_of(child, keys)
@@ -377,9 +396,11 @@ def handle_group(node: NexusGroup, keys: Mapping[str, Any], prev_path: str):
ValidationProblem.ExpectedGroup,
None,
)
- return
+ continue
if node.nx_class == "NXdata":
handle_nxdata(node, keys[variant], prev_path=f"{prev_path}/{variant}")
+ if node.nx_class == "NXcollection":
+ return
else:
recurse_tree(node, keys[variant], prev_path=f"{prev_path}/{variant}")
@@ -449,6 +470,7 @@ def handle_field(node: NexusNode, keys: Mapping[str, Any], prev_path: str):
mapping[f"{prev_path}/{variant}"],
node.dtype,
node.items,
+ node.open_enum,
f"{prev_path}/{variant}",
)
@@ -475,6 +497,7 @@ def handle_field(node: NexusNode, keys: Mapping[str, Any], prev_path: str):
def handle_attribute(node: NexusNode, keys: Mapping[str, Any], prev_path: str):
full_path = remove_from_not_visited(f"{prev_path}/@{node.name}")
variants = get_variations_of(node, keys)
+
if (
not variants
and node.optionality == "required"
@@ -492,6 +515,7 @@ def handle_attribute(node: NexusNode, keys: Mapping[str, Any], prev_path: str):
],
node.dtype,
node.items,
+ node.open_enum,
f"{prev_path}/{variant if variant.startswith('@') else f'@{variant}'}",
)
@@ -538,17 +562,30 @@ def add_best_matches_for(key: str, node: NexusNode) -> Optional[NexusNode]:
def is_documented(key: str, tree: NexusNode) -> bool:
if mapping.get(key) is None:
- # This value is not really set. Skip checking it's documentation.
- return True
-
- # TODO remove when nameType is implemented
- if key.endswith("/@URL"):
+ # This value is not really set. Skip checking its documentation.
return True
node = add_best_matches_for(key, tree)
+
if node is None:
+ key_path = key.replace("@", "")
+ while "/" in key_path:
+ key_path = key_path.rsplit("/", 1)[0] # Remove last segment
+ parent_node = add_best_matches_for(key_path, tree)
+ if (
+ parent_node
+ and parent_node.type == "group"
+ and parent_node.nx_class == "NXcollection"
+ ):
+ # Collection found for parents, mark as documented
+ return True
+
return False
+ if node.type == "group" and node.nx_class == "NXcollection":
+ # Collection found, mark as documented
+ return True
+
if isinstance(mapping[key], dict) and "link" in mapping[key]:
# TODO: Follow link and check consistency with current field
return True
@@ -562,7 +599,9 @@ def is_documented(key: str, tree: NexusNode) -> bool:
# We still do some further checks before returning.
# Check general validity
- mapping[key] = is_valid_data_field(mapping[key], node.dtype, node.items, key)
+ mapping[key] = is_valid_data_field(
+ mapping[key], node.dtype, node.items, node.open_enum, key
+ )
# Check main field exists for units
if (
@@ -588,6 +627,7 @@ def recurse_tree(
keys = _follow_link(keys, prev_path)
if keys is None:
return
+
handling_map.get(child.type, handle_unknown_type)(child, keys, prev_path)
def check_attributes_of_nonexisting_field(
@@ -805,12 +845,29 @@ def startswith_with_variations(
else:
# check that parent has units
node = add_best_matches_for(not_visited_key.rsplit("/", 1)[0], tree)
+
+ # Search if unit is somewhere in an NXcollection
+ if node is None:
+ key_path = not_visited_key.replace("@", "")
+ while "/" in key_path:
+ key_path = key_path.rsplit("/", 1)[0] # Remove last segment
+ parent_node = add_best_matches_for(key_path, tree)
+ if (
+ parent_node
+ and parent_node.type == "group"
+ and parent_node.nx_class == "NXcollection"
+ ):
+ # NXcollection found → break while, continue outer loop
+ break
+ continue
+
if node is None or node.type != "field" or node.unit is None:
- collector.collect_and_log(
- not_visited_key,
- ValidationProblem.UnitWithoutDocumentation,
- mapping[not_visited_key],
- )
+ if not ignore_undocumented:
+ collector.collect_and_log(
+ not_visited_key,
+ ValidationProblem.UnitWithoutDocumentation,
+ mapping[not_visited_key],
+ )
# parent key will be checked on its own if it exists, because it is in the list
continue
diff --git a/src/pynxtools/definitions b/src/pynxtools/definitions
index f7ba53f4f..a85e10cd0 160000
--- a/src/pynxtools/definitions
+++ b/src/pynxtools/definitions
@@ -1 +1 @@
-Subproject commit f7ba53f4fb409b03fde6af6ccf29146392a2c142
+Subproject commit a85e10cd0289f4e44b0fec011ff54703e6705383
diff --git a/src/pynxtools/nexus-version.txt b/src/pynxtools/nexus-version.txt
index 48133eb9b..c137d59d6 100644
--- a/src/pynxtools/nexus-version.txt
+++ b/src/pynxtools/nexus-version.txt
@@ -1 +1 @@
-v2024.02-1885-gdb54d2a0
\ No newline at end of file
+v2024.02-1913-ga85e10cd
\ No newline at end of file
diff --git a/src/pynxtools/nomad/schema.py b/src/pynxtools/nomad/schema.py
index cb0b4325e..f9fc1c4ec 100644
--- a/src/pynxtools/nomad/schema.py
+++ b/src/pynxtools/nomad/schema.py
@@ -39,6 +39,7 @@
from nomad.normalizing.common import nomad_atoms_from_ase_atoms
from nomad.normalizing.topology import add_system, add_system_info
from scipy.spatial import cKDTree
+import pint
try:
from nomad import utils
@@ -139,9 +140,7 @@ class NexusActivityStep(ActivityStep):
class AnchoredReference(EntityReference):
-
def normalize(self, archive, logger):
-
def create_Entity(lab_id, archive, f_name, qunt_name):
entitySec = Entity()
entitySec.lab_id = lab_id
@@ -197,14 +196,16 @@ def normalize(self, archive, logger):
if not (val := getattr(self, identifier)):
continue
# identifier_path = f"{self.m_def.name}_{identifier.split('__field')[0]}"
- field_n = identifier.split('__field')[0]
+ field_n = identifier.split("__field")[0]
logger.info(f"Lab id {val} to be created")
nx_id = AnchoredReference(lab_id=val, name=field_n)
nx_id.m_set_section_attribute(
- "m_nx_data_path", self.m_get_quantity_attribute(identifier, "m_nx_data_path")
+ "m_nx_data_path",
+ self.m_get_quantity_attribute(identifier, "m_nx_data_path"),
)
nx_id.m_set_section_attribute(
- "m_nx_data_file", self.m_get_quantity_attribute(identifier, "m_nx_data_file")
+ "m_nx_data_file",
+ self.m_get_quantity_attribute(identifier, "m_nx_data_file"),
)
self.AnchoredReferences.append(nx_id)
@@ -510,12 +511,12 @@ def nxdata_ensure_definition(
else:
filters = ["DATA", "AXISNAME", "FIELDNAME_errors"]
# get the reduced options
- newdefintions = {}
+ newdefinitions = {}
for dname, definition in self.m_def.all_aliases:
if dname not in filters:
- newdefintions[dname] = definition
+ newdefinitions[dname] = definition
# run the query
- definition = resolve_variadic_name(newdefintions, def_or_name, hint)
+ definition = resolve_variadic_name(newdefinitions, def_or_name, hint)
return definition
return super(current_cls, self)._ensure_definition(
def_or_name,
@@ -555,9 +556,11 @@ def __get_enumeration(xml_node: ET.Element) -> Tuple[Optional[MEnum], Optional[b
return None, None
items = enumeration.findall("nx:item", __XML_NAMESPACES)
- open = bool(enumeration.attrib["open"]) if "open" in enumeration.attrib else False
+ open_enum = (
+ bool(enumeration.attrib["open"]) if "open" in enumeration.attrib else False
+ )
- return MEnum([value.attrib["value"] for value in items]), open
+ return MEnum([value.attrib["value"] for value in items]), open_enum
def __add_common_properties(xml_node: ET.Element, definition: Definition):
@@ -765,11 +768,23 @@ def __create_field(xml_node: ET.Element, container: Section) -> Quantity:
# dimensionality
nx_dimensionality = xml_attrs.get("units", None)
if nx_dimensionality:
- if nx_dimensionality not in NXUnitSet.mapping:
- raise NotImplementedError(
- f"Unit {nx_dimensionality} is not supported for {name}."
- )
- dimensionality = NXUnitSet.mapping[nx_dimensionality]
+ dimensionality = NXUnitSet.mapping.get(nx_dimensionality)
+ if not dimensionality and nx_dimensionality != "NX_ANY":
+ try:
+ from nomad.units import ureg
+
+ quantity = 1 * ureg(nx_dimensionality)
+ if quantity.dimensionality == "dimensionless":
+ dimensionality = "1"
+ else:
+ dimensionality = str(quantity.dimensionality)
+ except (
+ pint.errors.UndefinedUnitError,
+ pint.errors.DefinitionSyntaxError,
+ ) as err:
+ raise NotImplementedError(
+ f"Unit {nx_dimensionality} is not supported for {name}."
+ ) from err
else:
dimensionality = None
diff --git a/src/pynxtools/testing/nexus_conversion.py b/src/pynxtools/testing/nexus_conversion.py
index 32c5afb0f..2f8e99241 100644
--- a/src/pynxtools/testing/nexus_conversion.py
+++ b/src/pynxtools/testing/nexus_conversion.py
@@ -20,7 +20,7 @@
import logging
import os
from glob import glob
-from typing import Dict, List, Literal, Tuple
+from typing import Dict, List, Literal, Tuple, Optional
try:
from nomad.client import parse
@@ -30,13 +30,11 @@
NOMAD_AVAILABLE = False
-from pynxtools.dataconverter.convert import get_reader, transfer_data_into_template
+from pynxtools.dataconverter.convert import get_reader, convert
from pynxtools.dataconverter.helpers import (
add_default_root_attributes,
get_nxdl_root_and_path,
)
-from pynxtools.dataconverter.validation import validate_dict_against
-from pynxtools.dataconverter.writer import Writer
from pynxtools.nexus.nexus import HandleNexus
@@ -115,7 +113,11 @@ def convert_to_nexus(
self.ref_nexus_file = [file for file in example_files if file.endswith(".nxs")][
0
]
- input_files = [file for file in example_files if not file.endswith(".nxs")]
+ input_files = [
+ file
+ for file in example_files
+ if not file.endswith((".nxs", "ref_output.txt"))
+ ]
assert self.ref_nexus_file, "Reference nexus (.nxs) file not found"
assert (
@@ -126,28 +128,40 @@ def convert_to_nexus(
nxdl_root, nxdl_file = get_nxdl_root_and_path(self.nxdl)
assert os.path.exists(nxdl_file), f"NXDL file {nxdl_file} not found"
- read_data = transfer_data_into_template(
- input_file=input_files,
- reader=self.reader_name,
- nxdl_name=self.nxdl,
- nxdl_root=nxdl_root,
- skip_verify=True,
- **self.kwargs,
- )
-
- # Clear the log of `transfer_data_into_template`
+ # Clear the log of `convert`
self.caplog.clear()
with self.caplog.at_level(caplog_level):
- _ = validate_dict_against(
- self.nxdl, read_data, ignore_undocumented=ignore_undocumented
- )[0]
- assert self.caplog.text == ""
+ _ = convert(
+ input_file=tuple(input_files),
+ reader=self.reader_name,
+ nxdl=self.nxdl,
+ skip_verify=False,
+ ignore_undocumented=ignore_undocumented,
+ output=self.created_nexus,
+ **self.kwargs,
+ )
- add_default_root_attributes(
- data=read_data, filename=os.path.basename(self.created_nexus)
- )
- Writer(read_data, nxdl_file, self.created_nexus).write()
+ test_output = self.caplog.messages
+
+ files_with_expected_output = [
+ file for file in example_files if file.endswith("ref_output.txt")
+ ]
+
+ if files_with_expected_output:
+ output_file = files_with_expected_output[0]
+ with open(output_file, "r") as file:
+ expected_messages = [line.strip() for line in file.readlines()]
+
+ for message in expected_messages:
+ if caplog_level == "WARNING":
+ if message.startswith(("WARNING", "ERROR")):
+ test_output.remove(message)
+ if caplog_level == "ERROR":
+ if message.startswith("ERROR"):
+ test_output.remove(message)
+
+ assert test_output == []
if NOMAD_AVAILABLE:
kwargs = dict(
@@ -172,7 +186,7 @@ def check_reproducibility_of_nexus(self, **kwargs):
]
IGNORE_SECTIONS: Dict[str, List[str]] = {
**reader_ignore_sections,
- "ATTRS (//@HDF5_version)": ["DEBUG - value:"],
+ "ATTRS (//@HDF5_Version)": ["DEBUG - value:"],
"ATTRS (//@file_name)": ["DEBUG - value:"],
"ATTRS (//@file_time)": ["DEBUG - value:"],
"ATTRS (//@file_update_time)": ["DEBUG - value:"],
diff --git a/tests/data/dataconverter/readers/example/testdata.json b/tests/data/dataconverter/readers/example/testdata.json
index dbcf035a3..bfeb4d1e8 100644
--- a/tests/data/dataconverter/readers/example/testdata.json
+++ b/tests/data/dataconverter/readers/example/testdata.json
@@ -15,6 +15,7 @@
"definition_version": "0.0.1",
"program_name": "Nexus Parser",
"type": "2nd type",
+ "type2": "2nd type",
"date_value": "2022-01-22T12:14:12.05018+00:00",
"date_value_units": "",
"required_child": 1,
diff --git a/tests/data/nexus/NXtest2.nxdl.xml b/tests/data/nexus/NXtest2.nxdl.xml
deleted file mode 100644
index 7b33b2165..000000000
--- a/tests/data/nexus/NXtest2.nxdl.xml
+++ /dev/null
@@ -1,455 +0,0 @@
-
-
-
-
-
-
- Characterization of a sample during a session on an electron microscope.
-
-
-
-
-
-
-
- Metadata and numerical data of the microscope and the lab in which it stands.
-
-
-
-
-
- Given name of the microscope at the hosting institution. This is an alias.
- Examples could be NionHermes, Titan, JEOL, Gemini, etc.
-
-
-
-
- Location of the lab or place where the instrument is installed.
- Using GEOREF is preferred.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- If the lens is described at least one of the fields
- voltage, current, or value should be defined.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Description of the type of the detector.
-
- Electron microscopes have typically multiple detectors.
- Different technologies are in use like CCD, scintillator,
- direct electron, CMOS, or image plate to name but a few.
-
-
-
- Instrument-specific alias/name
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A container for storing a set of NXevent_data_em instances.
-
-
-
-
-
\ No newline at end of file
diff --git a/tests/data/nexus/Ref_nexus_test.log b/tests/data/nexus/Ref_nexus_test.log
index 54541649f..7f7279708 100644
--- a/tests/data/nexus/Ref_nexus_test.log
+++ b/tests/data/nexus/Ref_nexus_test.log
@@ -32,24 +32,34 @@ DEBUG - classpath: ['NXentry']
DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY
NXentry.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY):
DEBUG -
DEBUG - documentation (NXentry.nxdl.xml:):
DEBUG -
- (**required**) :ref:`NXentry` describes the measurement.
-
- The top-level NeXus group which contains all the data and associated
- information that comprise a single measurement.
- It is mandatory that there is at least one
- group of this type in the NeXus file.
-
+ (**required**) :ref:`NXentry` describes the measurement.
+
+ The top-level NeXus group which contains all the data and associated
+ information that comprise a single measurement.
+ It is mandatory that there is at least one
+ group of this type in the NeXus file.
+DEBUG - documentation (NXobject.nxdl.xml:):
+DEBUG -
+ This is the base object of NeXus. The groups and fields contained
+ within this file are allowed to be present in any derived base class.
+
+ If nameType="partial", the placeholders (e.g., FIELDNAME or GROUPNAME)
+ can be replaced by the name of any object (field or group,
+ respectively) that exists within the same group.
+
DEBUG - ===== ATTRS (//entry@NX_class)
DEBUG - value: NXentry
DEBUG - classpath: ['NXentry']
DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY
NXentry.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - @NX_class [NX_CHAR]
DEBUG -
DEBUG - ===== FIELD (//entry/collection_time):
@@ -60,9 +70,9 @@ NXentry.nxdl.xml:/collection_time
DEBUG - <>
DEBUG - documentation (NXentry.nxdl.xml:/collection_time):
DEBUG -
- Time transpired actually collecting data i.e. taking out time when collection was
- suspended due to e.g. temperature out of range
-
+ Time transpired actually collecting data i.e. taking out time when collection was
+ suspended due to e.g. temperature out of range
+
DEBUG - ===== ATTRS (//entry/collection_time@units)
DEBUG - value: s
DEBUG - classpath: ['NXentry', 'NX_FLOAT']
@@ -74,158 +84,225 @@ DEBUG - classpath: ['NXentry', 'NXdata']
DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/DATA
NXentry.nxdl.xml:/DATA
+NXobject.nxdl.xml:/DATA
NXdata.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/DATA):
DEBUG -
DEBUG - documentation (NXentry.nxdl.xml:/DATA):
DEBUG -
- The data group
-
- .. note:: Before the NIAC2016 meeting [#]_, at least one
- :ref:`NXdata` group was required in each :ref:`NXentry` group.
- At the NIAC2016 meeting, it was decided to make :ref:`NXdata`
- an optional group in :ref:`NXentry` groups for data files that
- do not use an application definition.
- It is recommended strongly that all NeXus data files provide
- a NXdata group.
- It is permissable to omit the NXdata group only when
- defining the default plot is not practical or possible
- from the available data.
-
- For example, neutron event data may not have anything that
- makes a useful plot without extensive processing.
-
- Certain application definitions override this decision and
- require an :ref:`NXdata` group
- in the :ref:`NXentry` group. The ``minOccurs=0`` attribute
- in the application definition will indicate the
- :ref:`NXdata` group
- is optional, otherwise, it is required.
-
- .. [#] NIAC2016:
- https://www.nexusformat.org/NIAC2016.html,
- https://github.com/nexusformat/NIAC/issues/16
-
+ The data group
+
+ .. note:: Before the NIAC2016 meeting [#]_, at least one
+ :ref:`NXdata` group was required in each :ref:`NXentry` group.
+ At the NIAC2016 meeting, it was decided to make :ref:`NXdata`
+ an optional group in :ref:`NXentry` groups for data files that
+ do not use an application definition.
+ It is recommended strongly that all NeXus data files provide
+ a NXdata group.
+ It is permissible to omit the NXdata group only when
+ defining the default plot is not practical or possible
+ from the available data.
+
+ For example, neutron event data may not have anything that
+ makes a useful plot without extensive processing.
+
+ Certain application definitions override this decision and
+ require an :ref:`NXdata` group
+ in the :ref:`NXentry` group. The ``minOccurs=0`` attribute
+ in the application definition will indicate the
+ :ref:`NXdata` group
+ is optional, otherwise, it is required.
+
+ .. [#] NIAC2016:
+ https://www.nexusformat.org/NIAC2016.html,
+ https://github.com/nexusformat/NIAC/issues/16
+
+
+DEBUG - documentation (NXobject.nxdl.xml:/DATA):
+DEBUG -
DEBUG - documentation (NXdata.nxdl.xml:):
DEBUG -
- :ref:`NXdata` describes the plottable data and related dimension scales.
-
- .. index:: plotting
-
- It is strongly recommended that there is at least one :ref:`NXdata`
- group in each :ref:`NXentry` group.
- Note that the fields named ``AXISNAME`` and ``DATA``
- can be defined with different names.
- (Upper case is used to indicate that the actual name is left to the user.)
- The ``signal`` and ``axes`` attributes of the
- ``data`` group define which items
- are plottable data and which are *dimension scales*, respectively.
-
- :ref:`NXdata` is used to implement one of the basic motivations in NeXus,
- to provide a default plot for the data of this :ref:`NXentry`. The actual data
- might be stored in another group and (hard) linked to the :ref:`NXdata` group.
-
- * Each :ref:`NXdata` group will define one field as the default
- plottable data. The value of the ``signal`` attribute names this field.
- Additional fields may be used to describe the dimension scales and
- uncertainities.
- The ``auxiliary_signals`` attribute is a list of the other fields
- to be plotted with the ``signal`` data.
- * The plottable data may be of arbitrary rank up to a maximum
- of ``NX_MAXRANK=32`` (for compatibility with backend file formats).
- * The plottable data will be named as the value of
- the group ``signal`` attribute, such as::
-
- data:NXdata
- @signal = "counts"
- @axes = "mr"
- @mr_indices = 0
- counts: float[100] --> the default dependent data
- mr: float[100] --> the default independent data
-
- The field named in the ``signal`` attribute **must** exist, either
- directly as a NeXus field or defined through a link.
-
- * The group ``axes`` attribute will name the
- *dimension scale* associated with the plottable data.
-
- If available, the standard deviations of the data are to be
- stored in a data set of the same rank and dimensions, with the name ``errors``.
-
- * For each data dimension, there should be a one-dimensional array
- of the same length.
- * These one-dimensional arrays are the *dimension scales* of the
- data, *i.e*. the values of the independent variables at which the data
- is measured, such as scattering angle or energy transfer.
-
- .. index:: link
- .. index:: axes (attribute)
-
- The preferred method to associate each data dimension with
- its respective dimension scale is to specify the field name
- of each dimension scale in the group ``axes`` attribute as a string list.
- Here is an example for a 2-D data set *data* plotted
- against *time*, and *pressure*. (An additional *temperature* data set
- is provided and could be selected as an alternate for the *pressure* axis.)::
-
- data_2d:NXdata
- @signal="data"
- @axes=["time", "pressure"]
- @pressure_indices=1
- @temperature_indices=1
- @time_indices=0
- data: float[1000,20]
- pressure: float[20]
- temperature: float[20]
- time: float[1000]
-
- .. rubric:: Old methods to identify the plottable data
-
- There are two older methods of associating
- each data dimension to its respective dimension scale.
- Both are now out of date and
- should not be used when writing new data files.
- However, client software should expect to see data files
- written with any of these methods.
-
- * One method uses the ``axes``
- attribute to specify the names of each *dimension scale*.
-
- * The oldest method uses the ``axis`` attribute on each
- *dimension scale* to identify
- with an integer the axis whose value is the number of the dimension.
-
- .. index: !plot; axis label
- plot, axis units
- units
- dimension scale
-
- Each axis of the plot may be labeled with information from the
- dimension scale for that axis. The optional ``@long_name`` attribute
- is provided as the axis label default. If ``@long_name`` is not
- defined, then use the name of the dimension scale. A ``@units`` attribute,
- if available, may be added to the axis label for further description.
- See the section :ref:`Design-Units` for more information.
-
- .. index: !plot; axis title
-
- The optional ``title`` field, if available, provides a suggested
- title for the plot. If no ``title`` field is found in the :ref:`NXdata`
- group, look for a ``title`` field in the parent :ref:`NXentry` group,
- with a fallback to displaying the path to the :ref:`NXdata` group.
-
- NeXus is about how to find and annotate the data to be plotted
- but not to describe how the data is to be plotted.
- (https://www.nexusformat.org/NIAC2018Minutes.html#nxdata-plottype--attribute)
-
+ The :ref:`NXdata` class is designed to encapsulate all the information required for a set of data to be plotted.
+ NXdata groups contain plottable data (also referred to as *signals* or *dependent variables*) and their
+ associated axis coordinates (also referred to as *axes* or *independent variables*).
+
+ The actual names of the :ref:`DATA ` and :ref:`AXISNAME ` fields
+ can be chosen :ref:`freely `, as indicated by the upper case (this is a common convention in all NeXus classes).
+
+ .. note:: ``NXdata`` provides data and coordinates to be plotted but
+ does not describe how the data is to be plotted or even the dimensionality of the plot.
+ https://www.nexusformat.org/NIAC2018Minutes.html#nxdata-plottype--attribute
+
+ .. include:: data/index.rst
+ :start-line: 1
+
+ .. admonition:: Example of a simple curve plot
+
+ .. code-block::
+
+ data:NXdata
+ @signal = "data"
+ @axes = ["x"]
+ data: float[100]
+ x: float[100]
+
+ More complex cases are supported
+
+ * histogram data: ``x`` has one more value than ``data``.
+ * alternative axes: instead of a single ``x`` axis you can have several axes, one of which being the default.
+ * signals with more than one dimension: ``data`` could be 2D with axes ``x`` and ``y`` along each dimension.
+ * axes with more than one dimension: ``data`` could be 2D with axes ``x`` and ``y`` also being 2D, providing a
+ unique ``(x, y)`` coordinate for each ``data`` point.
+
+ **Signals:**
+
+ .. index:: plotting
+
+ .. admonition:: Defined by
+
+ * :ref:`DATA ` fields
+ * the :ref:`signal ` attribute
+ * the :ref:`auxiliary_signals` attribute
+
+ The :ref:`DATA ` fields contain the signal values to be plotted. The name of the field
+ to be used as the *default plot signal* is provided by the :ref:`signal ` attribute.
+ The names of the fields to be used as *secondary plot signals* are provided by the
+ :ref:`auxiliary_signals` attribute.
+
+ .. admonition:: An example with three signals, one of which being the default
+
+ .. code-block::
+
+ data:NXdata
+ @signal = "data1"
+ @auxiliary_signals = ["data2", "data3"]
+ data1: float[10,20,30] # the default signal
+ data2: float[10,20,30]
+ data3: float[10,20,30]
+
+ **Axes:**
+
+ .. index:: axes (attribute)
+ .. index:: coordinates
+
+ .. admonition:: Defined by
+
+ * :ref:`AXISNAME ` fields
+ * the :ref:`axes ` attribute
+ * :ref:`AXISNAME_indices ` attributes
+
+ The fields and attributes are defined as follows
+
+ 1. The :ref:`AXISNAME ` fields contain the axis coordinates associated with the signal values.
+
+ 2. The :ref:`axes ` attribute provides the names of the :ref:`AXISNAME `
+ fields to be used as the `default axis` for each dimension of the :ref:`DATA ` fields.
+
+ 3. The :ref:`AXISNAME_indices ` attributes describe the :ref:`DATA `
+ dimensions spanned by the corresponding :ref:`AXISNAME ` fields.
+
+ The fields and attributes have the following constraints
+
+ 1. The length of the :ref:`axes ` attribute must be equal to the rank of the :ref:`DATA `
+ fields. When a particular dimension has no default axis, the string “.” is used in that position.
+
+ 2. The number of values in :ref:`AXISNAME_indices ` must be equal to the rank of the corresponding
+ :ref:`AXISNAME ` field.
+
+ 3. When :ref:`AXISNAME_indices ` is missing for a given
+ :ref:`AXISNAME ` field, the positions of the :ref:`AXISNAME `
+ field name in the :ref:`axes ` attribute are used.
+
+ 4. When :ref:`AXISNAME_indices ` is the same as the indices of "AXISNAME" in the
+ :ref:`axes ` attribute, there is no need to provide
+ :ref:`AXISNAME_indices `.
+
+ 5. The indices of "AXISNAME" in the :ref:`axes ` attribute must be a subset of
+ :ref:`AXISNAME_indices `.
+
+ 6. The shape of an :ref:`AXISNAME ` field must correspond to the shape of the
+ :ref:`DATA ` dimensions it spans. This means that for each dimension ``i`` in ``[0, AXISNAME.ndim)``
+ spanned by axis field :ref:`AXISNAME `, the number of axis values ``AXISNAME.shape[i]``
+ along dimension ``i`` must be equal to the number of data points ``DATA.shape[AXISNAME_indices[i]]`` along dimension ``i``
+ or one more than the number of data points ``DATA.shape[AXISNAME_indices[i]]+1`` in case the
+ :ref:`AXISNAME ` field contains histogram bin edges along dimension ``i``.
+
+ Highlight consequences of these constraints
+
+ 1. An :ref:`AXISNAME ` field can have more than one dimension and can therefore span
+ more than one :ref:`DATA ` dimension. Conversely, one :ref:`DATA ` dimension
+ can be spanned by more than one :ref:`AXISNAME ` field. The default axis name (if any)
+ of each dimension can be found in the :ref:`axes ` attribute.
+
+ 2. A list of all available axes is not provided directly. All strings in the :ref:`axes ` attribute
+ (excluding the “.” string) are axis field names. In addition the prefix of an attribute ending with the string "_indices" is also
+ an axis field name.
+
+ .. admonition:: The following example covers all axes features supported (see :ref:`sphx_glr_classes_base_classes_data_plot_fscan2d.py`)
+
+ .. code-block::
+
+ data:NXdata
+ @signal = "data"
+ @axes = ["x_set", "y_set", "."] # default axes for all three dimensions
+ @x_encoder_indices = [0, 1]
+ @y_encoder_indices = 1 # or [1]
+ data: float[10,7,1024]
+ x_encoder: float[11,7] # coordinates along the first and second dimensions
+ y_encoder: float[7] # coordinates along the second dimension
+ x_set: float[10] # default coordinates along the first dimension
+ y_set: float[7] # default coordinates along the second dimension
+
+ **Uncertainties:**
+
+ .. admonition:: Defined by
+
+ * :ref:`FIELDNAME_errors ` fields
+
+ Standard deviations on data values as well as coordinates can be provided by
+ :ref:`FIELDNAME_errors ` fields where ``FIELDNAME`` is the name of a
+ :ref:`DATA ` field or an :ref:`AXISNAME ` field.
+
+ .. admonition:: An example of uncertainties on the signal, auxiliary signals and axis coordinates
+
+ .. code-block::
+
+ data:NXdata
+ @signal = "data1"
+ @auxiliary_signals = ["data2", "data3"]
+ @axes = ["x", ".", "z"]
+ data1: float[10,20,30]
+ data2: float[10,20,30]
+ data3: float[10,20,30]
+ x: float[10]
+ z: float[30]
+ data1_errors: float[10,20,30]
+ data2_errors: float[10,20,30]
+ data3_errors: float[10,20,30]
+ x_errors: float[10]
+ z_errors: float[30]
+
+
+DEBUG - documentation (NXobject.nxdl.xml:):
+DEBUG -
+ This is the base object of NeXus. The groups and fields contained
+ within this file are allowed to be present in any derived base class.
+
+ If nameType="partial", the placeholders (e.g., FIELDNAME or GROUPNAME)
+ can be replaced by the name of any object (field or group,
+ respectively) that exists within the same group.
+
DEBUG - ===== ATTRS (//entry/data@NX_class)
DEBUG - value: NXdata
DEBUG - classpath: ['NXentry', 'NXdata']
DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/DATA
NXentry.nxdl.xml:/DATA
+NXobject.nxdl.xml:/DATA
NXdata.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - @NX_class [NX_CHAR]
DEBUG -
DEBUG - ===== ATTRS (//entry/data@axes)
@@ -234,96 +311,89 @@ DEBUG - classpath: ['NXentry', 'NXdata']
DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/DATA
NXentry.nxdl.xml:/DATA
+NXobject.nxdl.xml:/DATA
NXdata.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - NXdata.nxdl.xml:@axes - [NX_CHAR]
DEBUG - <>
DEBUG - documentation (NXdata.nxdl.xml:/axes):
DEBUG -
- .. index:: plotting
-
- Array of strings holding the :ref:`names ` of
- the independent data fields used in the default plot for all of
- the dimensions of the :ref:`signal `
- as well as any :ref:`auxiliary signals `.
-
- One name is provided for every dimension in the *signal* or *auxiliary signal* fields.
-
- The *axes* values are the names of fields or links that *must* exist and be direct
- children of this NXdata group.
-
- An axis slice is specified using a field named ``AXISNAME_indices``
- as described below (where the text shown here as ``AXISNAME`` is to be
- replaced by the actual field name).
-
- When no default axis is available for a particular dimension
- of the plottable data, use a "." in that position.
- Such as::
-
- @axes=["time", ".", "."]
-
- Since there are three items in the list, the *signal* field
- must be a three-dimensional array (rank=3). The first dimension
- is described by the values of a one-dimensional array named ``time``
- while the other two dimensions have no fields to be used as dimension scales.
-
- See examples provided on the NeXus wiki:
- https://www.nexusformat.org/2014_axes_and_uncertainties.html
-
- If there are no axes at all (such as with a stack of images),
- the axes attribute can be omitted.
-
+ .. index:: plotting
+
+ The ``axes`` attribute is a list of strings which are the names of the :ref:`AXISNAME ` fields
+ to be used as the default axis along every :ref:`DATA ` dimension. As a result the length must
+ be equal to the rank of the :ref:`DATA ` fields. The string "." can be used for
+ dimensions without a default axis.
+
+ .. note:: When ``axes`` contains multiple strings, it must be saved as an actual array
+ of strings and not a single comma separated string.
+
DEBUG - ===== ATTRS (//entry/data@signal)
DEBUG - value: data
DEBUG - classpath: ['NXentry', 'NXdata']
DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/DATA
NXentry.nxdl.xml:/DATA
+NXobject.nxdl.xml:/DATA
NXdata.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - NXdata.nxdl.xml:@signal - [NX_CHAR]
DEBUG - <>
DEBUG - documentation (NXdata.nxdl.xml:/signal):
DEBUG -
- .. index:: find the default plottable data
- .. index:: plotting
- .. index:: signal attribute value
-
- Declares which NeXus field is the default.
- The value is the :ref:`name ` of the data field to be plotted.
- This field or link *must* exist and be a direct child of this NXdata group.
-
- It is recommended (as of NIAC2014) to use this attribute
- rather than adding a signal attribute to the field.
- See https://www.nexusformat.org/2014_How_to_find_default_data.html
- for a summary of the discussion.
-
+ .. index:: find the default plottable data
+ .. index:: plotting
+ .. index:: signal attribute value
+
+ The value is the :ref:`name ` of the signal that contains
+ the default plottable data. This field or link *must* exist and be a direct child
+ of this NXdata group.
+
+ It is recommended (as of NIAC2014) to use this attribute
+ rather than adding a signal attribute to the field.
+ See https://www.nexusformat.org/2014_How_to_find_default_data.html
+ for a summary of the discussion.
+
DEBUG - ===== FIELD (//entry/data/angles):
DEBUG - value: [-1.96735314 -1.91500657 -1.86266001 -1.81031344 -1.75796688 -1.70562031 ...
-DEBUG - classpath: ['NXentry', 'NXdata', 'NX_NUMBER']
+DEBUG - classpath: ['NXentry', 'NXdata', 'NX_CHAR_OR_NUMBER']
DEBUG - classes:
NXdata.nxdl.xml:/AXISNAME
DEBUG - <>
DEBUG - Dataset referenced as NXdata AXIS #0
DEBUG - documentation (NXdata.nxdl.xml:/AXISNAME):
DEBUG -
- Dimension scale defining an axis of the data.
- Client is responsible for defining the dimensions of the data.
- The name of this field may be changed to fit the circumstances.
- Standard NeXus client tools will use the attributes to determine
- how to use this field.
-
+ Coordinate values along one or more :ref:`DATA ` dimensions.
+
+ The shape of an ``AXISNAME`` field must correspond to the shape of the :ref:`DATA `
+ dimensions it spans. This means that for each ``i`` in ``[0, AXISNAME.ndim)`` the number of data points
+ ``DATA.shape[AXISNAME_indices[i]]`` must be equal to the number of coordinates ``AXISNAME.shape[i]`` or the
+ number of bin edges ``AXISNAME.shape[i]+1`` in case of histogram data.
+
+ As the upper case ``AXISNAME`` indicates, the names of the ``AXISNAME`` fields can be chosen :ref:`freely `.
+
+ Most ``AXISNAME`` fields will be sequences of numbers but if an axis is better represented using names, such as channel names,
+ an array of NX_CHAR can be provided.
+
DEBUG - ===== ATTRS (//entry/data/angles@target)
DEBUG - value: /entry/instrument/analyser/angles
-DEBUG - classpath: ['NXentry', 'NXdata', 'NX_NUMBER']
+DEBUG - classpath: ['NXentry', 'NXdata', 'NX_CHAR_OR_NUMBER']
DEBUG - classes:
NXdata.nxdl.xml:/AXISNAME
DEBUG - @target - IS NOT IN SCHEMA
DEBUG -
DEBUG - ===== ATTRS (//entry/data/angles@units)
DEBUG - value: 1/Å
-DEBUG - classpath: ['NXentry', 'NXdata', 'NX_NUMBER']
+DEBUG - classpath: ['NXentry', 'NXdata', 'NX_CHAR_OR_NUMBER']
DEBUG - classes:
NXdata.nxdl.xml:/AXISNAME
-DEBUG - NXdata.nxdl.xml:/AXISNAME@units - REQUIRED, but undefined unit category
+DEBUG - NXdata.nxdl.xml:/AXISNAME@units - [NX_CHAR]
+DEBUG - Dataset referenced as NXdata AXIS #0
+DEBUG - documentation (NXdata.nxdl.xml:/AXISNAME/units):
+DEBUG -
+ Unit in which the coordinate values are expressed.
+ See the section :ref:`Design-Units` for more information.
+
DEBUG - ===== FIELD (//entry/data/data):
DEBUG - value: [[0. 0. 0. ... 0. 0. 0.] ...
DEBUG - classpath: ['NXentry', 'NXdata', 'NX_NUMBER']
@@ -333,15 +403,15 @@ DEBUG - <>
DEBUG - Dataset referenced as NXdata SIGNAL
DEBUG - documentation (NXdata.nxdl.xml:/DATA):
DEBUG -
- .. index:: plotting
-
- This field contains the data values to be used as the
- NeXus *plottable data*.
- Client is responsible for defining the dimensions of the data.
- The name of this field may be changed to fit the circumstances.
- Standard NeXus client tools will use the attributes to determine
- how to use this field.
-
+ .. index:: plotting
+
+ Data values to be used as the NeXus *plottable data*. As the upper case ``DATA``
+ indicates, the names of the ``DATA`` fields can be chosen :ref:`freely `. The :ref:`signal attribute `
+ and :ref:`auxiliary_signals attribute` can be used to find all datasets in the ``NXdata``
+ that contain data values.
+
+ The maximum rank is ``32`` for compatibility with backend file formats.
+
DEBUG - ===== ATTRS (//entry/data/data@target)
DEBUG - value: /entry/instrument/analyser/data
DEBUG - classpath: ['NXentry', 'NXdata', 'NX_NUMBER']
@@ -357,60 +427,84 @@ NXdata.nxdl.xml:/DATA
DEBUG - NXdata.nxdl.xml:/DATA@units - REQUIRED, but undefined unit category
DEBUG - ===== FIELD (//entry/data/delays):
DEBUG - value: [-1.1 -1.08041237 -1.06082474 -1.04123711 -1.02164948 -1.00206186 ...
-DEBUG - classpath: ['NXentry', 'NXdata', 'NX_NUMBER']
+DEBUG - classpath: ['NXentry', 'NXdata', 'NX_CHAR_OR_NUMBER']
DEBUG - classes:
NXdata.nxdl.xml:/AXISNAME
DEBUG - <>
DEBUG - Dataset referenced as NXdata AXIS #2
DEBUG - documentation (NXdata.nxdl.xml:/AXISNAME):
DEBUG -
- Dimension scale defining an axis of the data.
- Client is responsible for defining the dimensions of the data.
- The name of this field may be changed to fit the circumstances.
- Standard NeXus client tools will use the attributes to determine
- how to use this field.
-
+ Coordinate values along one or more :ref:`DATA ` dimensions.
+
+ The shape of an ``AXISNAME`` field must correspond to the shape of the :ref:`DATA `
+ dimensions it spans. This means that for each ``i`` in ``[0, AXISNAME.ndim)`` the number of data points
+ ``DATA.shape[AXISNAME_indices[i]]`` must be equal to the number of coordinates ``AXISNAME.shape[i]`` or the
+ number of bin edges ``AXISNAME.shape[i]+1`` in case of histogram data.
+
+ As the upper case ``AXISNAME`` indicates, the names of the ``AXISNAME`` fields can be chosen :ref:`freely `.
+
+ Most ``AXISNAME`` fields will be sequences of numbers but if an axis is better represented using names, such as channel names,
+ an array of NX_CHAR can be provided.
+
DEBUG - ===== ATTRS (//entry/data/delays@target)
DEBUG - value: /entry/instrument/analyser/delays
-DEBUG - classpath: ['NXentry', 'NXdata', 'NX_NUMBER']
+DEBUG - classpath: ['NXentry', 'NXdata', 'NX_CHAR_OR_NUMBER']
DEBUG - classes:
NXdata.nxdl.xml:/AXISNAME
DEBUG - @target - IS NOT IN SCHEMA
DEBUG -
DEBUG - ===== ATTRS (//entry/data/delays@units)
DEBUG - value: fs
-DEBUG - classpath: ['NXentry', 'NXdata', 'NX_NUMBER']
+DEBUG - classpath: ['NXentry', 'NXdata', 'NX_CHAR_OR_NUMBER']
DEBUG - classes:
NXdata.nxdl.xml:/AXISNAME
-DEBUG - NXdata.nxdl.xml:/AXISNAME@units - REQUIRED, but undefined unit category
+DEBUG - NXdata.nxdl.xml:/AXISNAME@units - [NX_CHAR]
+DEBUG - Dataset referenced as NXdata AXIS #2
+DEBUG - documentation (NXdata.nxdl.xml:/AXISNAME/units):
+DEBUG -
+ Unit in which the coordinate values are expressed.
+ See the section :ref:`Design-Units` for more information.
+
DEBUG - ===== FIELD (//entry/data/energies):
DEBUG - value: [ 2.5 2.46917808 2.43835616 2.40753425 2.37671233 2.34589041 ...
-DEBUG - classpath: ['NXentry', 'NXdata', 'NX_NUMBER']
+DEBUG - classpath: ['NXentry', 'NXdata', 'NX_CHAR_OR_NUMBER']
DEBUG - classes:
NXdata.nxdl.xml:/AXISNAME
DEBUG - <>
DEBUG - Dataset referenced as NXdata AXIS #1
DEBUG - documentation (NXdata.nxdl.xml:/AXISNAME):
DEBUG -
- Dimension scale defining an axis of the data.
- Client is responsible for defining the dimensions of the data.
- The name of this field may be changed to fit the circumstances.
- Standard NeXus client tools will use the attributes to determine
- how to use this field.
-
+ Coordinate values along one or more :ref:`DATA ` dimensions.
+
+ The shape of an ``AXISNAME`` field must correspond to the shape of the :ref:`DATA `
+ dimensions it spans. This means that for each ``i`` in ``[0, AXISNAME.ndim)`` the number of data points
+ ``DATA.shape[AXISNAME_indices[i]]`` must be equal to the number of coordinates ``AXISNAME.shape[i]`` or the
+ number of bin edges ``AXISNAME.shape[i]+1`` in case of histogram data.
+
+ As the upper case ``AXISNAME`` indicates, the names of the ``AXISNAME`` fields can be chosen :ref:`freely `.
+
+ Most ``AXISNAME`` fields will be sequences of numbers but if an axis is better represented using names, such as channel names,
+ an array of NX_CHAR can be provided.
+
DEBUG - ===== ATTRS (//entry/data/energies@target)
DEBUG - value: /entry/instrument/analyser/energies
-DEBUG - classpath: ['NXentry', 'NXdata', 'NX_NUMBER']
+DEBUG - classpath: ['NXentry', 'NXdata', 'NX_CHAR_OR_NUMBER']
DEBUG - classes:
NXdata.nxdl.xml:/AXISNAME
DEBUG - @target - IS NOT IN SCHEMA
DEBUG -
DEBUG - ===== ATTRS (//entry/data/energies@units)
DEBUG - value: eV
-DEBUG - classpath: ['NXentry', 'NXdata', 'NX_NUMBER']
+DEBUG - classpath: ['NXentry', 'NXdata', 'NX_CHAR_OR_NUMBER']
DEBUG - classes:
NXdata.nxdl.xml:/AXISNAME
-DEBUG - NXdata.nxdl.xml:/AXISNAME@units - REQUIRED, but undefined unit category
+DEBUG - NXdata.nxdl.xml:/AXISNAME@units - [NX_CHAR]
+DEBUG - Dataset referenced as NXdata AXIS #1
+DEBUG - documentation (NXdata.nxdl.xml:/AXISNAME/units):
+DEBUG -
+ Unit in which the coordinate values are expressed.
+ See the section :ref:`Design-Units` for more information.
+
DEBUG - ===== FIELD (//entry/definition):
DEBUG - value: NXarpes
DEBUG - classpath: ['NXentry', 'NX_CHAR']
@@ -421,26 +515,24 @@ DEBUG - <>
DEBUG - enumeration (NXarpes.nxdl.xml:/ENTRY/definition):
DEBUG - -> NXarpes
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/definition):
-DEBUG -
- Official NeXus NXDL schema to which this file conforms.
-
+DEBUG - Official NeXus NXDL schema to which this file conforms.
DEBUG - documentation (NXentry.nxdl.xml:/definition):
DEBUG -
- (alternate use: see same field in :ref:`NXsubentry` for preferred)
-
- Official NeXus NXDL schema to which this entry conforms which must be
- the name of the NXDL file (case sensitive without the file extension)
- that the NXDL schema is defined in.
-
- For example the ``definition`` field for a file that conformed to the
- *NXarpes.nxdl.xml* definition must contain the string **NXarpes**.
-
- This field is provided so that :ref:`NXentry` can be the overlay position
- in a NeXus data file for an application definition and its
- set of groups, fields, and attributes.
-
- *It is advised* to use :ref:`NXsubentry`, instead, as the overlay position.
-
+ (alternate use: see same field in :ref:`NXsubentry` for preferred)
+
+ Official NeXus NXDL schema to which this entry conforms which must be
+ the name of the NXDL file (case sensitive without the file extension)
+ that the NXDL schema is defined in.
+
+ For example the ``definition`` field for a file that conformed to the
+ *NXarpes.nxdl.xml* definition must contain the string **NXarpes**.
+
+ This field is provided so that :ref:`NXentry` can be the overlay position
+ in a NeXus data file for an application definition and its
+ set of groups, fields, and attributes.
+
+ *It is advised* to use :ref:`NXsubentry`, instead, as the overlay position.
+
DEBUG - ===== FIELD (//entry/duration):
DEBUG - value: 7200
DEBUG - classpath: ['NXentry', 'NX_INT']
@@ -448,9 +540,7 @@ DEBUG - classes:
NXentry.nxdl.xml:/duration
DEBUG - <>
DEBUG - documentation (NXentry.nxdl.xml:/duration):
-DEBUG -
- Duration of measurement
-
+DEBUG - Duration of measurement
DEBUG - ===== ATTRS (//entry/duration@units)
DEBUG - value: s
DEBUG - classpath: ['NXentry', 'NX_INT']
@@ -464,25 +554,36 @@ DEBUG - classes:
NXentry.nxdl.xml:/end_time
DEBUG - <>
DEBUG - documentation (NXentry.nxdl.xml:/end_time):
-DEBUG -
- Ending time of measurement
-
+DEBUG - Ending time of measurement
DEBUG - ===== FIELD (//entry/entry_identifier):
DEBUG - value: Run 22118
-DEBUG - classpath: ['NXentry']
-DEBUG - NOT IN SCHEMA
-DEBUG -
+DEBUG - classpath: ['NXentry', 'NX_CHAR']
+DEBUG - classes:
+NXentry.nxdl.xml:/entry_identifier
+DEBUG - <>
+DEBUG - DEPRECATED - Use the field :ref:`identifier_entry ` instead.
+DEBUG - documentation (NXentry.nxdl.xml:/entry_identifier):
+DEBUG - unique identifier for the measurement, defined by the facility.
DEBUG - ===== FIELD (//entry/experiment_identifier):
DEBUG - value: F-20170538
-DEBUG - classpath: ['NXentry']
-DEBUG - NOT IN SCHEMA
+DEBUG - classpath: ['NXentry', 'NX_CHAR']
+DEBUG - classes:
+NXentry.nxdl.xml:/experiment_identifier
+DEBUG - <>
+DEBUG - DEPRECATED - Use the field :ref:`identifier_experiment ` instead.
+DEBUG - documentation (NXentry.nxdl.xml:/experiment_identifier):
DEBUG -
+ Unique identifier for the experiment,
+ defined by the facility,
+ possibly linked to the proposals
+
DEBUG - ===== GROUP (//entry/instrument [NXarpes::/NXentry/NXinstrument]):
DEBUG - classpath: ['NXentry', 'NXinstrument']
DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT
NXentry.nxdl.xml:/INSTRUMENT
NXinstrument.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT):
DEBUG -
@@ -490,15 +591,24 @@ DEBUG - documentation (NXentry.nxdl.xml:/INSTRUMENT):
DEBUG -
DEBUG - documentation (NXinstrument.nxdl.xml:):
DEBUG -
- Collection of the components of the instrument or beamline.
-
- Template of instrument descriptions comprising various beamline components.
- Each component will also be a NeXus group defined by its distance from the
- sample. Negative distances represent beamline components that are before the
- sample while positive distances represent components that are after the sample.
- This device allows the unique identification of beamline components in a way
- that is valid for both reactor and pulsed instrumentation.
-
+ Collection of the components of the instrument or beamline.
+
+ Template of instrument descriptions comprising various beamline components.
+ Each component will also be a NeXus group defined by its distance from the
+ sample. Negative distances represent beamline components that are before the
+ sample while positive distances represent components that are after the sample.
+ This device allows the unique identification of beamline components in a way
+ that is valid for both reactor and pulsed instrumentation.
+
+DEBUG - documentation (NXobject.nxdl.xml:):
+DEBUG -
+ This is the base object of NeXus. The groups and fields contained
+ within this file are allowed to be present in any derived base class.
+
+ If nameType="partial", the placeholders (e.g., FIELDNAME or GROUPNAME)
+ can be replaced by the name of any object (field or group,
+ respectively) that exists within the same group.
+
DEBUG - ===== ATTRS (//entry/instrument@NX_class)
DEBUG - value: NXinstrument
DEBUG - classpath: ['NXentry', 'NXinstrument']
@@ -506,6 +616,7 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT
NXentry.nxdl.xml:/INSTRUMENT
NXinstrument.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - @NX_class [NX_CHAR]
DEBUG -
DEBUG - ===== GROUP (//entry/instrument/analyser [NXarpes::/NXentry/NXinstrument/NXdetector]):
@@ -514,6 +625,8 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser
NXinstrument.nxdl.xml:/DETECTOR
NXdetector.nxdl.xml:
+NXcomponent.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser):
DEBUG -
@@ -521,8 +634,21 @@ DEBUG - documentation (NXinstrument.nxdl.xml:/DETECTOR):
DEBUG -
DEBUG - documentation (NXdetector.nxdl.xml:):
DEBUG -
- A detector, detector bank, or multidetector.
+ A detector, detector bank, or multidetector.
+
+DEBUG - documentation (NXcomponent.nxdl.xml:):
+DEBUG -
+ Base class for components of an instrument - real ones or simulated ones.
+DEBUG - documentation (NXobject.nxdl.xml:):
+DEBUG -
+ This is the base object of NeXus. The groups and fields contained
+ within this file are allowed to be present in any derived base class.
+
+ If nameType="partial", the placeholders (e.g., FIELDNAME or GROUPNAME)
+ can be replaced by the name of any object (field or group,
+ respectively) that exists within the same group.
+
DEBUG - ===== ATTRS (//entry/instrument/analyser@NX_class)
DEBUG - value: NXdetector
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector']
@@ -530,6 +656,8 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser
NXinstrument.nxdl.xml:/DETECTOR
NXdetector.nxdl.xml:
+NXcomponent.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - @NX_class [NX_CHAR]
DEBUG -
DEBUG - ===== FIELD (//entry/instrument/analyser/acquisition_mode):
@@ -553,19 +681,12 @@ DEBUG - -> pulse counting
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/acquisition_mode):
DEBUG -
DEBUG - documentation (NXdetector.nxdl.xml:/acquisition_mode):
-DEBUG -
- The acquisition mode of the detector.
-
+DEBUG - The acquisition mode of the detector.
DEBUG - ===== FIELD (//entry/instrument/analyser/amplifier_type):
DEBUG - value: MCP
-DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_CHAR']
-DEBUG - classes:
-NXdetector.nxdl.xml:/amplifier_type
-DEBUG - <>
-DEBUG - documentation (NXdetector.nxdl.xml:/amplifier_type):
+DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector']
+DEBUG - NOT IN SCHEMA
DEBUG -
- Type of electron amplifier, MCP, channeltron, etc.
-
DEBUG - ===== FIELD (//entry/instrument/analyser/angles):
DEBUG - value: [-1.96735314 -1.91500657 -1.86266001 -1.81031344 -1.75796688 -1.70562031 ...
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_NUMBER']
@@ -574,10 +695,10 @@ NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/angles
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/angles):
DEBUG -
- Angular axis of the analyser data
- which dimension the axis applies to is defined
- using the normal NXdata methods.
-
+ Angular axis of the analyser data
+ which dimension the axis applies to is defined
+ using the normal NXdata methods.
+
DEBUG - ===== ATTRS (//entry/instrument/analyser/angles@target)
DEBUG - value: /entry/instrument/analyser/angles
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_NUMBER']
@@ -607,29 +728,29 @@ DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/data):
DEBUG -
DEBUG - documentation (NXdetector.nxdl.xml:/data):
DEBUG -
- Data values from the detector. The rank and dimension ordering should follow a principle of
- slowest to fastest measurement axes and may be explicitly specified in application definitions.
-
- Mechanical scanning of objects (e.g. sample position/angle, incident beam energy, etc) tends to be
- the slowest part of an experiment and so any such scan axes should be allocated to the first dimensions
- of the array. Note that in some cases it may be useful to represent a 2D set of scan points as a single
- scan-axis in the data array, especially if the scan pattern doesn't fit a rectangular array nicely.
- Repetition of an experiment in a time series tends to be used similar to a slow scan axis
- and so will often be in the first dimension of the data array.
-
- The next fastest axes are typically the readout of the detector. A point detector will not add any dimensions
- (as it is just a single value per scan point) to the data array, a strip detector will add one dimension, an
- imaging detector will add two dimensions (e.g. X, Y axes) and detectors outputting higher dimensional data
- will add the corresponding number of dimensions. Note that the detector dimensions don't necessarily have to
- be written in order of the actual readout speeds - the slowest to fastest rule principle is only a guide.
-
- Finally, detectors that operate in a time-of-flight mode, such as a neutron spectrometer or a silicon drift
- detector (used for X-ray fluorescence) tend to have their dimension(s) added to the last dimensions in the data array.
-
- The type of each dimension should should follow the order of scan points, detector pixels,
- then time-of-flight (i.e. spectroscopy, spectrometry). The rank and dimension sizes (see symbol list)
- shown here are merely illustrative of coordination between related datasets.
-
+ Data values from the detector. The rank and dimension ordering should follow a principle of
+ slowest to fastest measurement axes and may be explicitly specified in application definitions.
+
+ Mechanical scanning of objects (e.g. sample position/angle, incident beam energy, etc) tends to be
+ the slowest part of an experiment and so any such scan axes should be allocated to the first dimensions
+ of the array. Note that in some cases it may be useful to represent a 2D set of scan points as a single
+ scan-axis in the data array, especially if the scan pattern doesn't fit a rectangular array nicely.
+ Repetition of an experiment in a time series tends to be used similar to a slow scan axis
+ and so will often be in the first dimension of the data array.
+
+ The next fastest axes are typically the readout of the detector. A point detector will not add any dimensions
+ (as it is just a single value per scan point) to the data array, a strip detector will add one dimension, an
+ imaging detector will add two dimensions (e.g. X, Y axes) and detectors outputting higher dimensional data
+ will add the corresponding number of dimensions. Note that the detector dimensions don't necessarily have to
+ be written in order of the actual readout speeds - the slowest to fastest rule principle is only a guide.
+
+ Finally, detectors that operate in a time-of-flight mode, such as a neutron spectrometer or a silicon drift
+ detector (used for X-ray fluorescence) tend to have their dimension(s) added to the last dimensions in the data array.
+
+ The type of each dimension should should follow the order of scan points, detector pixels,
+ then time-of-flight (i.e. spectroscopy, spectrometry). The rank and dimension sizes (see symbol list)
+ shown here are merely illustrative of coordination between related datasets.
+
DEBUG - ===== ATTRS (//entry/instrument/analyser/data@target)
DEBUG - value: /entry/instrument/analyser/data
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_NUMBER']
@@ -663,14 +784,9 @@ DEBUG - NOT IN SCHEMA
DEBUG -
DEBUG - ===== FIELD (//entry/instrument/analyser/detector_type):
DEBUG - value: DLD
-DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_CHAR']
-DEBUG - classes:
-NXdetector.nxdl.xml:/detector_type
-DEBUG - <>
-DEBUG - documentation (NXdetector.nxdl.xml:/detector_type):
+DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector']
+DEBUG - NOT IN SCHEMA
DEBUG -
- Description of the detector type, DLD, Phosphor+CCD, CMOS.
-
DEBUG - ===== FIELD (//entry/instrument/analyser/dispersion_scheme):
DEBUG - value: Time of flight
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector']
@@ -684,10 +800,10 @@ NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/energies
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/energies):
DEBUG -
- Energy axis of the analyser data
- which dimension the axis applies to is defined
- using the normal NXdata methods.
-
+ Energy axis of the analyser data
+ which dimension the axis applies to is defined
+ using the normal NXdata methods.
+
DEBUG - ===== ATTRS (//entry/instrument/analyser/energies@target)
DEBUG - value: /entry/instrument/analyser/energies
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_NUMBER']
@@ -708,9 +824,7 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/entrance_slit_setting
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/entrance_slit_setting):
-DEBUG -
- dial setting of the entrance slit
-
+DEBUG - dial setting of the entrance slit
DEBUG - ===== FIELD (//entry/instrument/analyser/entrance_slit_shape):
DEBUG - value: straight
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_CHAR']
@@ -729,9 +843,7 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/entrance_slit_size
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/entrance_slit_size):
-DEBUG -
- size of the entrance slit
-
+DEBUG - size of the entrance slit
DEBUG - ===== ATTRS (//entry/instrument/analyser/entrance_slit_size@units)
DEBUG - value: um
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_NUMBER']
@@ -775,9 +887,7 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/lens_mode
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/lens_mode):
-DEBUG -
- setting for the electron analyser lens
-
+DEBUG - setting for the electron analyser lens
DEBUG - ===== FIELD (//entry/instrument/analyser/magnification):
DEBUG - value: -1.5
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector']
@@ -790,9 +900,7 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/pass_energy
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/pass_energy):
-DEBUG -
- energy of the electrons on the mean path of the analyser
-
+DEBUG - energy of the electrons on the mean path of the analyser
DEBUG - ===== ATTRS (//entry/instrument/analyser/pass_energy@units)
DEBUG - value: eV
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_NUMBER']
@@ -811,9 +919,7 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/region_origin
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/region_origin):
-DEBUG -
- origin of rectangular region selected for readout
-
+DEBUG - origin of rectangular region selected for readout
DEBUG - ===== FIELD (//entry/instrument/analyser/region_size):
DEBUG - value: [ 80 146]
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_INT']
@@ -821,19 +927,12 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/region_size
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/region_size):
-DEBUG -
- size of rectangular region selected for readout
-
+DEBUG - size of rectangular region selected for readout
DEBUG - ===== FIELD (//entry/instrument/analyser/sensor_count):
DEBUG - value: 4
-DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_INT']
-DEBUG - classes:
-NXdetector.nxdl.xml:/sensor_count
-DEBUG - <>
-DEBUG - documentation (NXdetector.nxdl.xml:/sensor_count):
+DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector']
+DEBUG - NOT IN SCHEMA
DEBUG -
- Number of imaging sensor chips on the detector.
-
DEBUG - ===== FIELD (//entry/instrument/analyser/sensor_size):
DEBUG - value: [ 80 146]
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_INT']
@@ -841,9 +940,7 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/sensor_size
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/sensor_size):
-DEBUG -
- number of raw active elements in each dimension
-
+DEBUG - number of raw active elements in each dimension
DEBUG - ===== FIELD (//entry/instrument/analyser/time_per_channel):
DEBUG - value: 7200
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_NUMBER']
@@ -851,9 +948,7 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/time_per_channel
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/analyser/time_per_channel):
-DEBUG -
- todo: define more clearly
-
+DEBUG - todo: define more clearly
DEBUG - ===== ATTRS (//entry/instrument/analyser/time_per_channel@units)
DEBUG - value: s
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXdetector', 'NX_NUMBER']
@@ -875,33 +970,44 @@ DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXbeam']
DEBUG - classes:
NXinstrument.nxdl.xml:/BEAM
NXbeam.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - <>
DEBUG - documentation (NXinstrument.nxdl.xml:/BEAM):
DEBUG -
DEBUG - documentation (NXbeam.nxdl.xml:):
DEBUG -
- Properties of the neutron or X-ray beam at a given location.
-
- This group is intended to be referenced
- by beamline component groups within the :ref:`NXinstrument` group or by the :ref:`NXsample` group. This group is
- especially valuable in storing the results of instrument simulations in which it is useful
- to specify the beam profile, time distribution etc. at each beamline component. Otherwise,
- its most likely use is in the :ref:`NXsample` group in which it defines the results of the neutron
- scattering by the sample, e.g., energy transfer, polarizations. Finally, There are cases where the beam is
- considered as a beamline component and this group may be defined as a subgroup directly inside
- :ref:`NXinstrument`, in which case it is recommended that the position of the beam is specified by an
- :ref:`NXtransformations` group, unless the beam is at the origin (which is the sample).
-
- Note that incident_wavelength and related fields can be a scalar values or arrays, depending on the use case.
- To support these use cases, the explicit dimensionality of these fields is not specified, but it can be inferred
- by the presense of and shape of accompanying fields, such as incident_wavelength_weights for a polychromatic beam.
-
+ Properties of the neutron or X-ray beam at a given location.
+
+ This group is intended to be referenced
+ by beamline component groups within the :ref:`NXinstrument` group or by the :ref:`NXsample` group. This group is
+ especially valuable in storing the results of instrument simulations in which it is useful
+ to specify the beam profile, time distribution etc. at each beamline component. Otherwise,
+ its most likely use is in the :ref:`NXsample` group in which it defines the results of the neutron
+ scattering by the sample, e.g., energy transfer, polarizations. Finally, There are cases where the beam is
+ considered as a beamline component and this group may be defined as a subgroup directly inside
+ :ref:`NXinstrument`, in which case it is recommended that the position of the beam is specified by an
+ :ref:`NXtransformations` group, unless the beam is at the origin (which is the sample).
+
+ Note that ``incident_wavelength``, ``incident_energy``, and related fields can be a scalar values or arrays, depending on the use case.
+ To support these use cases, the explicit dimensionality of these fields is not specified, but it can be inferred
+ by the presence of and shape of accompanying fields, such as incident_wavelength_weights for a polychromatic beam.
+
+DEBUG - documentation (NXobject.nxdl.xml:):
+DEBUG -
+ This is the base object of NeXus. The groups and fields contained
+ within this file are allowed to be present in any derived base class.
+
+ If nameType="partial", the placeholders (e.g., FIELDNAME or GROUPNAME)
+ can be replaced by the name of any object (field or group,
+ respectively) that exists within the same group.
+
DEBUG - ===== ATTRS (//entry/instrument/beam_probe_0@NX_class)
DEBUG - value: NXbeam
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXbeam']
DEBUG - classes:
NXinstrument.nxdl.xml:/BEAM
NXbeam.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - @NX_class [NX_CHAR]
DEBUG -
DEBUG - ===== FIELD (//entry/instrument/beam_probe_0/distance):
@@ -911,9 +1017,7 @@ DEBUG - classes:
NXbeam.nxdl.xml:/distance
DEBUG - <>
DEBUG - documentation (NXbeam.nxdl.xml:/distance):
-DEBUG -
- Distance from sample. Note, it is recommended to use NXtransformations instead.
-
+DEBUG - Distance from sample. Note, it is recommended to use NXtransformations instead.
DEBUG - ===== ATTRS (//entry/instrument/beam_probe_0/distance@units)
DEBUG - value: cm
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXbeam', 'NX_FLOAT']
@@ -953,7 +1057,7 @@ NXbeam.nxdl.xml:/pulse_duration
DEBUG - <>
DEBUG - documentation (NXbeam.nxdl.xml:/pulse_duration):
DEBUG -
- FWHM duration of the pulses at the diagnostic point
+ FWHM duration of the pulses at the given location.
DEBUG - ===== ATTRS (//entry/instrument/beam_probe_0/pulse_duration@units)
DEBUG - value: fs
@@ -986,33 +1090,44 @@ DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXbeam']
DEBUG - classes:
NXinstrument.nxdl.xml:/BEAM
NXbeam.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - <>
DEBUG - documentation (NXinstrument.nxdl.xml:/BEAM):
DEBUG -
DEBUG - documentation (NXbeam.nxdl.xml:):
DEBUG -
- Properties of the neutron or X-ray beam at a given location.
-
- This group is intended to be referenced
- by beamline component groups within the :ref:`NXinstrument` group or by the :ref:`NXsample` group. This group is
- especially valuable in storing the results of instrument simulations in which it is useful
- to specify the beam profile, time distribution etc. at each beamline component. Otherwise,
- its most likely use is in the :ref:`NXsample` group in which it defines the results of the neutron
- scattering by the sample, e.g., energy transfer, polarizations. Finally, There are cases where the beam is
- considered as a beamline component and this group may be defined as a subgroup directly inside
- :ref:`NXinstrument`, in which case it is recommended that the position of the beam is specified by an
- :ref:`NXtransformations` group, unless the beam is at the origin (which is the sample).
-
- Note that incident_wavelength and related fields can be a scalar values or arrays, depending on the use case.
- To support these use cases, the explicit dimensionality of these fields is not specified, but it can be inferred
- by the presense of and shape of accompanying fields, such as incident_wavelength_weights for a polychromatic beam.
-
+ Properties of the neutron or X-ray beam at a given location.
+
+ This group is intended to be referenced
+ by beamline component groups within the :ref:`NXinstrument` group or by the :ref:`NXsample` group. This group is
+ especially valuable in storing the results of instrument simulations in which it is useful
+ to specify the beam profile, time distribution etc. at each beamline component. Otherwise,
+ its most likely use is in the :ref:`NXsample` group in which it defines the results of the neutron
+ scattering by the sample, e.g., energy transfer, polarizations. Finally, There are cases where the beam is
+ considered as a beamline component and this group may be defined as a subgroup directly inside
+ :ref:`NXinstrument`, in which case it is recommended that the position of the beam is specified by an
+ :ref:`NXtransformations` group, unless the beam is at the origin (which is the sample).
+
+ Note that ``incident_wavelength``, ``incident_energy``, and related fields can be a scalar values or arrays, depending on the use case.
+ To support these use cases, the explicit dimensionality of these fields is not specified, but it can be inferred
+ by the presence of and shape of accompanying fields, such as incident_wavelength_weights for a polychromatic beam.
+
+DEBUG - documentation (NXobject.nxdl.xml:):
+DEBUG -
+ This is the base object of NeXus. The groups and fields contained
+ within this file are allowed to be present in any derived base class.
+
+ If nameType="partial", the placeholders (e.g., FIELDNAME or GROUPNAME)
+ can be replaced by the name of any object (field or group,
+ respectively) that exists within the same group.
+
DEBUG - ===== ATTRS (//entry/instrument/beam_pump_0@NX_class)
DEBUG - value: NXbeam
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXbeam']
DEBUG - classes:
NXinstrument.nxdl.xml:/BEAM
NXbeam.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - @NX_class [NX_CHAR]
DEBUG -
DEBUG - ===== FIELD (//entry/instrument/beam_pump_0/average_power):
@@ -1023,7 +1138,7 @@ NXbeam.nxdl.xml:/average_power
DEBUG - <>
DEBUG - documentation (NXbeam.nxdl.xml:/average_power):
DEBUG -
- Average power at the diagnostic point
+ Average power at the at the given location.
DEBUG - ===== ATTRS (//entry/instrument/beam_pump_0/average_power@units)
DEBUG - value: uW
@@ -1048,9 +1163,7 @@ DEBUG - classes:
NXbeam.nxdl.xml:/distance
DEBUG - <>
DEBUG - documentation (NXbeam.nxdl.xml:/distance):
-DEBUG -
- Distance from sample. Note, it is recommended to use NXtransformations instead.
-
+DEBUG - Distance from sample. Note, it is recommended to use NXtransformations instead.
DEBUG - ===== ATTRS (//entry/instrument/beam_pump_0/distance@units)
DEBUG - value: cm
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXbeam', 'NX_FLOAT']
@@ -1065,14 +1178,14 @@ NXbeam.nxdl.xml:/fluence
DEBUG - <>
DEBUG - documentation (NXbeam.nxdl.xml:/fluence):
DEBUG -
- Incident fluence at the diagnostic point
+ Incident energy fluence at the given location.
DEBUG - ===== ATTRS (//entry/instrument/beam_pump_0/fluence@units)
DEBUG - value: mJ/cm^2
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXbeam', 'NX_FLOAT']
DEBUG - classes:
NXbeam.nxdl.xml:/fluence
-DEBUG - NXbeam.nxdl.xml:/fluence@units [NX_ANY]
+DEBUG - NXbeam.nxdl.xml:/fluence@units [mJ/cm^2]
DEBUG - ===== FIELD (//entry/instrument/beam_pump_0/photon_energy):
DEBUG - value: 1.55
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXbeam']
@@ -1106,7 +1219,7 @@ NXbeam.nxdl.xml:/pulse_duration
DEBUG - <>
DEBUG - documentation (NXbeam.nxdl.xml:/pulse_duration):
DEBUG -
- FWHM duration of the pulses at the diagnostic point
+ FWHM duration of the pulses at the given location.
DEBUG - ===== ATTRS (//entry/instrument/beam_pump_0/pulse_duration@units)
DEBUG - value: fs
@@ -1122,7 +1235,7 @@ NXbeam.nxdl.xml:/pulse_energy
DEBUG - <>
DEBUG - documentation (NXbeam.nxdl.xml:/pulse_energy):
DEBUG -
- Energy of a single pulse at the diagnostic point
+ Energy of a single pulse at the given location.
DEBUG - ===== ATTRS (//entry/instrument/beam_pump_0/pulse_energy@units)
DEBUG - value: nJ
@@ -1165,19 +1278,36 @@ DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXpositioner']
DEBUG - classes:
NXinstrument.nxdl.xml:/POSITIONER
NXpositioner.nxdl.xml:
+NXcomponent.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - <>
DEBUG - documentation (NXinstrument.nxdl.xml:/POSITIONER):
DEBUG -
DEBUG - documentation (NXpositioner.nxdl.xml:):
DEBUG -
- A generic positioner such as a motor or piezo-electric transducer.
+ A generic positioner such as a motor or piezo-electric transducer.
+
+DEBUG - documentation (NXcomponent.nxdl.xml:):
+DEBUG -
+ Base class for components of an instrument - real ones or simulated ones.
+DEBUG - documentation (NXobject.nxdl.xml:):
+DEBUG -
+ This is the base object of NeXus. The groups and fields contained
+ within this file are allowed to be present in any derived base class.
+
+ If nameType="partial", the placeholders (e.g., FIELDNAME or GROUPNAME)
+ can be replaced by the name of any object (field or group,
+ respectively) that exists within the same group.
+
DEBUG - ===== ATTRS (//entry/instrument/manipulator@NX_class)
DEBUG - value: NXpositioner
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXpositioner']
DEBUG - classes:
NXinstrument.nxdl.xml:/POSITIONER
NXpositioner.nxdl.xml:
+NXcomponent.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - @NX_class [NX_CHAR]
DEBUG -
DEBUG - ===== FIELD (//entry/instrument/manipulator/pos_x1):
@@ -1281,6 +1411,8 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/monochromator
NXinstrument.nxdl.xml:/MONOCHROMATOR
NXmonochromator.nxdl.xml:
+NXcomponent.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/monochromator):
DEBUG -
@@ -1288,18 +1420,32 @@ DEBUG - documentation (NXinstrument.nxdl.xml:/MONOCHROMATOR):
DEBUG -
DEBUG - documentation (NXmonochromator.nxdl.xml:):
DEBUG -
- A wavelength defining device.
-
- This is a base class for everything which
- selects a wavelength or energy, be it a
- monochromator crystal, a velocity selector,
- an undulator or whatever.
-
- The expected units are:
-
- * wavelength: angstrom
- * energy: eV
+ A wavelength defining device.
+
+ This is a base class for everything which
+ selects a wavelength or energy, be it a
+ monochromator crystal, a velocity selector,
+ an undulator or whatever.
+
+ The expected units are:
+
+ * wavelength: angstrom
+ * energy: eV
+
+
+DEBUG - documentation (NXcomponent.nxdl.xml:):
+DEBUG -
+ Base class for components of an instrument - real ones or simulated ones.
+DEBUG - documentation (NXobject.nxdl.xml:):
+DEBUG -
+ This is the base object of NeXus. The groups and fields contained
+ within this file are allowed to be present in any derived base class.
+
+ If nameType="partial", the placeholders (e.g., FIELDNAME or GROUPNAME)
+ can be replaced by the name of any object (field or group,
+ respectively) that exists within the same group.
+
DEBUG - ===== ATTRS (//entry/instrument/monochromator@NX_class)
DEBUG - value: NXmonochromator
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXmonochromator']
@@ -1307,6 +1453,8 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/monochromator
NXinstrument.nxdl.xml:/MONOCHROMATOR
NXmonochromator.nxdl.xml:
+NXcomponent.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - @NX_class [NX_CHAR]
DEBUG -
DEBUG - ===== FIELD (//entry/instrument/monochromator/energy):
@@ -1331,9 +1479,7 @@ NXmonochromator.nxdl.xml:/energy_error
DEBUG - <>
DEBUG - DEPRECATED - see https://github.com/nexusformat/definitions/issues/820
DEBUG - documentation (NXmonochromator.nxdl.xml:/energy_error):
-DEBUG -
- energy standard deviation
-
+DEBUG - energy standard deviation
DEBUG - ===== ATTRS (//entry/instrument/monochromator/energy_error@units)
DEBUG - value: eV
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXmonochromator', 'NX_FLOAT']
@@ -1366,15 +1512,15 @@ DEBUG - classes:
NXinstrument.nxdl.xml:/name
DEBUG - <>
DEBUG - documentation (NXinstrument.nxdl.xml:/name):
-DEBUG -
- Name of instrument
-
+DEBUG - Name of instrument
DEBUG - ===== GROUP (//entry/instrument/source [NXarpes::/NXentry/NXinstrument/NXsource]):
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource']
DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE
NXinstrument.nxdl.xml:/SOURCE
NXsource.nxdl.xml:
+NXcomponent.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE):
DEBUG -
@@ -1382,11 +1528,24 @@ DEBUG - documentation (NXinstrument.nxdl.xml:/SOURCE):
DEBUG -
DEBUG - documentation (NXsource.nxdl.xml:):
DEBUG -
- Radiation source emitting a beam.
-
- Examples include particle sources (electrons, neutrons, protons) or sources for electromagnetic radiation (photons).
- This base class can also be used to describe neutron or x-ray storage ring/facilities.
+ Radiation source emitting a beam.
+
+ Examples include particle sources (electrons, neutrons, protons) or sources for electromagnetic radiation (photons).
+ This base class can also be used to describe neutron or x-ray storage ring/facilities.
+
+DEBUG - documentation (NXcomponent.nxdl.xml:):
+DEBUG -
+ Base class for components of an instrument - real ones or simulated ones.
+DEBUG - documentation (NXobject.nxdl.xml:):
+DEBUG -
+ This is the base object of NeXus. The groups and fields contained
+ within this file are allowed to be present in any derived base class.
+
+ If nameType="partial", the placeholders (e.g., FIELDNAME or GROUPNAME)
+ can be replaced by the name of any object (field or group,
+ respectively) that exists within the same group.
+
DEBUG - ===== ATTRS (//entry/instrument/source@NX_class)
DEBUG - value: NXsource
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource']
@@ -1394,6 +1553,8 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE
NXinstrument.nxdl.xml:/SOURCE
NXsource.nxdl.xml:
+NXcomponent.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - @NX_class [NX_CHAR]
DEBUG -
DEBUG - ===== FIELD (//entry/instrument/source/bunch_distance):
@@ -1403,9 +1564,7 @@ DEBUG - classes:
NXsource.nxdl.xml:/bunch_distance
DEBUG - <>
DEBUG - documentation (NXsource.nxdl.xml:/bunch_distance):
-DEBUG -
- For storage rings, time between bunches
-
+DEBUG - For storage rings, time between bunches
DEBUG - ===== ATTRS (//entry/instrument/source/bunch_distance@units)
DEBUG - value: us
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource', 'NX_FLOAT']
@@ -1419,9 +1578,7 @@ DEBUG - classes:
NXsource.nxdl.xml:/bunch_length
DEBUG - <>
DEBUG - documentation (NXsource.nxdl.xml:/bunch_length):
-DEBUG -
- For storage rings, temporal length of the bunch
-
+DEBUG - For storage rings, temporal length of the bunch
DEBUG - ===== ATTRS (//entry/instrument/source/bunch_length@units)
DEBUG - value: fs
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource', 'NX_FLOAT']
@@ -1465,9 +1622,7 @@ DEBUG - classes:
NXsource.nxdl.xml:/current
DEBUG - <>
DEBUG - documentation (NXsource.nxdl.xml:/current):
-DEBUG -
- Accelerator, X-ray tube, or storage ring current
-
+DEBUG - Accelerator, X-ray tube, or storage ring current
DEBUG - ===== ATTRS (//entry/instrument/source/current@units)
DEBUG - value: uA
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource', 'NX_FLOAT']
@@ -1482,10 +1637,10 @@ NXsource.nxdl.xml:/energy
DEBUG - <>
DEBUG - documentation (NXsource.nxdl.xml:/energy):
DEBUG -
- Source energy. Typically, this would be the energy of
- the emitted beam. For storage rings, this would be
- the particle beam energy.
-
+ Source energy. Typically, this would be the energy of
+ the emitted beam. For storage rings, this would be
+ the particle beam energy.
+
DEBUG - ===== ATTRS (//entry/instrument/source/energy@units)
DEBUG - value: MeV
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource', 'NX_FLOAT']
@@ -1499,9 +1654,7 @@ DEBUG - classes:
NXsource.nxdl.xml:/frequency
DEBUG - <>
DEBUG - documentation (NXsource.nxdl.xml:/frequency):
-DEBUG -
- Frequency of pulsed source
-
+DEBUG - Frequency of pulsed source
DEBUG - ===== ATTRS (//entry/instrument/source/frequency@units)
DEBUG - value: Hz
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource', 'NX_FLOAT']
@@ -1518,21 +1671,22 @@ DEBUG - enumeration (NXsource.nxdl.xml:/mode):
DEBUG - -> Single Bunch
DEBUG - -> Multi Bunch
DEBUG - documentation (NXsource.nxdl.xml:/mode):
-DEBUG -
- source operating mode
-
+DEBUG - source operating mode
DEBUG - ===== FIELD (//entry/instrument/source/name):
DEBUG - value: FLASH
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource', 'NX_CHAR']
DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE/name
NXsource.nxdl.xml:/name
+NXcomponent.nxdl.xml:/name
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE/name):
DEBUG -
DEBUG - documentation (NXsource.nxdl.xml:/name):
+DEBUG - Name of source
+DEBUG - documentation (NXcomponent.nxdl.xml:/name):
DEBUG -
- Name of source
+ Name of the component.
DEBUG - ===== FIELD (//entry/instrument/source/number_of_bunches):
DEBUG - value: 500
@@ -1541,9 +1695,7 @@ DEBUG - classes:
NXsource.nxdl.xml:/number_of_bunches
DEBUG - <>
DEBUG - documentation (NXsource.nxdl.xml:/number_of_bunches):
-DEBUG -
- For storage rings, the number of bunches in use.
-
+DEBUG - For storage rings, the number of bunches in use.
DEBUG - ===== FIELD (//entry/instrument/source/number_of_bursts):
DEBUG - value: 1
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource']
@@ -1571,9 +1723,7 @@ DEBUG - -> proton
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE/probe):
DEBUG -
DEBUG - documentation (NXsource.nxdl.xml:/probe):
-DEBUG -
- type of radiation probe (pick one from the enumerated list and spell exactly)
-
+DEBUG - type of radiation probe (pick one from the enumerated list and spell exactly)
DEBUG - ===== FIELD (//entry/instrument/source/top_up):
DEBUG - value: True
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource', 'NX_BOOLEAN']
@@ -1581,9 +1731,7 @@ DEBUG - classes:
NXsource.nxdl.xml:/top_up
DEBUG - <>
DEBUG - documentation (NXsource.nxdl.xml:/top_up):
-DEBUG -
- Is the synchrotron operating in top_up mode?
-
+DEBUG - Is the synchrotron operating in top_up mode?
DEBUG - ===== FIELD (//entry/instrument/source/type):
DEBUG - value: Free Electron Laser
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource', 'NX_CHAR']
@@ -1606,27 +1754,26 @@ DEBUG - -> Ion Source
DEBUG - -> UV Plasma Source
DEBUG - -> Metal Jet X-ray
DEBUG - -> Laser
-DEBUG - -> Dye-Laser
+DEBUG - -> Dye Laser
DEBUG - -> Broadband Tunable Light Source
-DEBUG - -> Halogen lamp
+DEBUG - -> Halogen Lamp
DEBUG - -> LED
-DEBUG - -> Mercury Cadmium Telluride
+DEBUG - -> Mercury Cadmium Telluride Lamp
DEBUG - -> Deuterium Lamp
DEBUG - -> Xenon Lamp
DEBUG - -> Globar
-DEBUG - -> other
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE/type):
DEBUG -
DEBUG - documentation (NXsource.nxdl.xml:/type):
-DEBUG -
- type of radiation source (pick one from the enumerated list and spell exactly)
-
+DEBUG - type of radiation source (pick one from the enumerated list and spell exactly)
DEBUG - ===== GROUP (//entry/instrument/source_pump [NXarpes::/NXentry/NXinstrument/NXsource]):
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource']
DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE
NXinstrument.nxdl.xml:/SOURCE
NXsource.nxdl.xml:
+NXcomponent.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE):
DEBUG -
@@ -1634,11 +1781,24 @@ DEBUG - documentation (NXinstrument.nxdl.xml:/SOURCE):
DEBUG -
DEBUG - documentation (NXsource.nxdl.xml:):
DEBUG -
- Radiation source emitting a beam.
-
- Examples include particle sources (electrons, neutrons, protons) or sources for electromagnetic radiation (photons).
- This base class can also be used to describe neutron or x-ray storage ring/facilities.
+ Radiation source emitting a beam.
+
+ Examples include particle sources (electrons, neutrons, protons) or sources for electromagnetic radiation (photons).
+ This base class can also be used to describe neutron or x-ray storage ring/facilities.
+
+DEBUG - documentation (NXcomponent.nxdl.xml:):
+DEBUG -
+ Base class for components of an instrument - real ones or simulated ones.
+DEBUG - documentation (NXobject.nxdl.xml:):
+DEBUG -
+ This is the base object of NeXus. The groups and fields contained
+ within this file are allowed to be present in any derived base class.
+
+ If nameType="partial", the placeholders (e.g., FIELDNAME or GROUPNAME)
+ can be replaced by the name of any object (field or group,
+ respectively) that exists within the same group.
+
DEBUG - ===== ATTRS (//entry/instrument/source_pump@NX_class)
DEBUG - value: NXsource
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource']
@@ -1646,6 +1806,8 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE
NXinstrument.nxdl.xml:/SOURCE
NXsource.nxdl.xml:
+NXcomponent.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - @NX_class [NX_CHAR]
DEBUG -
DEBUG - ===== FIELD (//entry/instrument/source_pump/bunch_distance):
@@ -1655,9 +1817,7 @@ DEBUG - classes:
NXsource.nxdl.xml:/bunch_distance
DEBUG - <>
DEBUG - documentation (NXsource.nxdl.xml:/bunch_distance):
-DEBUG -
- For storage rings, time between bunches
-
+DEBUG - For storage rings, time between bunches
DEBUG - ===== ATTRS (//entry/instrument/source_pump/bunch_distance@units)
DEBUG - value: us
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource', 'NX_FLOAT']
@@ -1671,9 +1831,7 @@ DEBUG - classes:
NXsource.nxdl.xml:/bunch_length
DEBUG - <>
DEBUG - documentation (NXsource.nxdl.xml:/bunch_length):
-DEBUG -
- For storage rings, temporal length of the bunch
-
+DEBUG - For storage rings, temporal length of the bunch
DEBUG - ===== ATTRS (//entry/instrument/source_pump/bunch_length@units)
DEBUG - value: fs
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource', 'NX_FLOAT']
@@ -1707,9 +1865,7 @@ DEBUG - classes:
NXsource.nxdl.xml:/frequency
DEBUG - <>
DEBUG - documentation (NXsource.nxdl.xml:/frequency):
-DEBUG -
- Frequency of pulsed source
-
+DEBUG - Frequency of pulsed source
DEBUG - ===== ATTRS (//entry/instrument/source_pump/frequency@units)
DEBUG - value: Hz
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource', 'NX_FLOAT']
@@ -1726,21 +1882,22 @@ DEBUG - enumeration (NXsource.nxdl.xml:/mode):
DEBUG - -> Single Bunch
DEBUG - -> Multi Bunch
DEBUG - documentation (NXsource.nxdl.xml:/mode):
-DEBUG -
- source operating mode
-
+DEBUG - source operating mode
DEBUG - ===== FIELD (//entry/instrument/source_pump/name):
DEBUG - value: User Laser @ FLASH
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource', 'NX_CHAR']
DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE/name
NXsource.nxdl.xml:/name
+NXcomponent.nxdl.xml:/name
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE/name):
DEBUG -
DEBUG - documentation (NXsource.nxdl.xml:/name):
+DEBUG - Name of source
+DEBUG - documentation (NXcomponent.nxdl.xml:/name):
DEBUG -
- Name of source
+ Name of the component.
DEBUG - ===== FIELD (//entry/instrument/source_pump/number_of_bunches):
DEBUG - value: 400
@@ -1749,9 +1906,7 @@ DEBUG - classes:
NXsource.nxdl.xml:/number_of_bunches
DEBUG - <>
DEBUG - documentation (NXsource.nxdl.xml:/number_of_bunches):
-DEBUG -
- For storage rings, the number of bunches in use.
-
+DEBUG - For storage rings, the number of bunches in use.
DEBUG - ===== FIELD (//entry/instrument/source_pump/number_of_bursts):
DEBUG - value: 1
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource']
@@ -1779,9 +1934,7 @@ DEBUG - -> proton
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE/probe):
DEBUG -
DEBUG - documentation (NXsource.nxdl.xml:/probe):
-DEBUG -
- type of radiation probe (pick one from the enumerated list and spell exactly)
-
+DEBUG - type of radiation probe (pick one from the enumerated list and spell exactly)
DEBUG - ===== FIELD (//entry/instrument/source_pump/rms_jitter):
DEBUG - value: 204.68816194453154
DEBUG - classpath: ['NXentry', 'NXinstrument', 'NXsource']
@@ -1814,21 +1967,18 @@ DEBUG - -> Ion Source
DEBUG - -> UV Plasma Source
DEBUG - -> Metal Jet X-ray
DEBUG - -> Laser
-DEBUG - -> Dye-Laser
+DEBUG - -> Dye Laser
DEBUG - -> Broadband Tunable Light Source
-DEBUG - -> Halogen lamp
+DEBUG - -> Halogen Lamp
DEBUG - -> LED
-DEBUG - -> Mercury Cadmium Telluride
+DEBUG - -> Mercury Cadmium Telluride Lamp
DEBUG - -> Deuterium Lamp
DEBUG - -> Xenon Lamp
DEBUG - -> Globar
-DEBUG - -> other
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/INSTRUMENT/SOURCE/type):
DEBUG -
DEBUG - documentation (NXsource.nxdl.xml:/type):
-DEBUG -
- type of radiation source (pick one from the enumerated list and spell exactly)
-
+DEBUG - type of radiation source (pick one from the enumerated list and spell exactly)
DEBUG - ===== FIELD (//entry/instrument/spatial_resolution):
DEBUG - value: 500
DEBUG - classpath: ['NXentry', 'NXinstrument']
@@ -1856,15 +2006,15 @@ DEBUG - classes:
NXentry.nxdl.xml:/run_cycle
DEBUG - <>
DEBUG - documentation (NXentry.nxdl.xml:/run_cycle):
-DEBUG -
- Such as "2007-3". Some user facilities organize their beam time into run cycles.
-
+DEBUG - Such as "2007-3". Some user facilities organize their beam time into run cycles.
DEBUG - ===== GROUP (//entry/sample [NXarpes::/NXentry/NXsample]):
DEBUG - classpath: ['NXentry', 'NXsample']
DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/SAMPLE
NXentry.nxdl.xml:/SAMPLE
NXsample.nxdl.xml:
+NXcomponent.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/SAMPLE):
DEBUG -
@@ -1872,12 +2022,25 @@ DEBUG - documentation (NXentry.nxdl.xml:/SAMPLE):
DEBUG -
DEBUG - documentation (NXsample.nxdl.xml:):
DEBUG -
- Any information on the sample.
-
- This could include scanned variables that
- are associated with one of the data dimensions, e.g. the magnetic field, or
- logged data, e.g. monitored temperature vs elapsed time.
+ Any information on the sample.
+
+ This could include scanned variables that
+ are associated with one of the data dimensions, e.g. the magnetic field, or
+ logged data, e.g. monitored temperature vs elapsed time.
+
+DEBUG - documentation (NXcomponent.nxdl.xml:):
+DEBUG -
+ Base class for components of an instrument - real ones or simulated ones.
+DEBUG - documentation (NXobject.nxdl.xml:):
+DEBUG -
+ This is the base object of NeXus. The groups and fields contained
+ within this file are allowed to be present in any derived base class.
+
+ If nameType="partial", the placeholders (e.g., FIELDNAME or GROUPNAME)
+ can be replaced by the name of any object (field or group,
+ respectively) that exists within the same group.
+
DEBUG - ===== ATTRS (//entry/sample@NX_class)
DEBUG - value: NXsample
DEBUG - classpath: ['NXentry', 'NXsample']
@@ -1885,6 +2048,8 @@ DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/SAMPLE
NXentry.nxdl.xml:/SAMPLE
NXsample.nxdl.xml:
+NXcomponent.nxdl.xml:
+NXobject.nxdl.xml:
DEBUG - @NX_class [NX_CHAR]
DEBUG -
DEBUG - ===== FIELD (//entry/sample/bias):
@@ -1928,14 +2093,15 @@ DEBUG - classpath: ['NXentry', 'NXsample', 'NX_CHAR']
DEBUG - classes:
NXarpes.nxdl.xml:/ENTRY/SAMPLE/name
NXsample.nxdl.xml:/name
+NXcomponent.nxdl.xml:/name
DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/SAMPLE/name):
-DEBUG -
- Descriptive name of sample
-
+DEBUG - Descriptive name of sample
DEBUG - documentation (NXsample.nxdl.xml:/name):
+DEBUG - Descriptive name of sample
+DEBUG - documentation (NXcomponent.nxdl.xml:/name):
DEBUG -
- Descriptive name of sample
+ Name of the component.
DEBUG - ===== FIELD (//entry/sample/preparation_method):
DEBUG - value: in-vacuum cleave
@@ -1949,9 +2115,7 @@ DEBUG - classes:
NXsample.nxdl.xml:/pressure
DEBUG - <>
DEBUG - documentation (NXsample.nxdl.xml:/pressure):
-DEBUG -
- Applied pressure
-
+DEBUG - Applied pressure
DEBUG - ===== ATTRS (//entry/sample/pressure@units)
DEBUG - value: mbar
DEBUG - classpath: ['NXentry', 'NXsample', 'NX_FLOAT']
@@ -2001,9 +2165,7 @@ DEBUG - classes:
NXsample.nxdl.xml:/thickness
DEBUG - <>
DEBUG - documentation (NXsample.nxdl.xml:/thickness):
-DEBUG -
- sample thickness
-
+DEBUG - sample thickness
DEBUG - ===== ATTRS (//entry/sample/thickness@units)
DEBUG - value: mm
DEBUG - classpath: ['NXentry', 'NXsample', 'NX_FLOAT']
@@ -2025,9 +2187,7 @@ DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/start_time):
DEBUG -
DEBUG - documentation (NXentry.nxdl.xml:/start_time):
-DEBUG -
- Starting time of measurement
-
+DEBUG - Starting time of measurement
DEBUG - ===== FIELD (//entry/title):
DEBUG - value: Excited-state dynamics of WSe2 in the Valence Band and Core-Levels
DEBUG - classpath: ['NXentry', 'NX_CHAR']
@@ -2038,9 +2198,7 @@ DEBUG - <>
DEBUG - documentation (NXarpes.nxdl.xml:/ENTRY/title):
DEBUG -
DEBUG - documentation (NXentry.nxdl.xml:/title):
-DEBUG -
- Extended title for entry
-
+DEBUG - Extended title for entry
DEBUG - ========================
DEBUG - === Default Plotable ===
DEBUG - ========================
diff --git a/tests/dataconverter/test_helpers.py b/tests/dataconverter/test_helpers.py
index b01ba9e3c..883684012 100644
--- a/tests/dataconverter/test_helpers.py
+++ b/tests/dataconverter/test_helpers.py
@@ -175,8 +175,8 @@ def test_writing_of_root_attributes(caplog):
assert "/@file_time" in keys_added
assert "/@file_update_time" in keys_added
assert "/@NeXus_repository" in keys_added
- assert "/@NeXus_version" in keys_added
- assert "/@HDF5_version" in keys_added
+ assert "/@NeXus_release" in keys_added
+ assert "/@HDF5_Version" in keys_added
assert "/@h5py_version" in keys_added
assert "/ENTRY[entry]/definition" in keys_added
assert "/ENTRY[entry]/definition/@version" in keys_added
diff --git a/tests/dataconverter/test_validation.py b/tests/dataconverter/test_validation.py
index 6f32d64c8..80cbbb9b1 100644
--- a/tests/dataconverter/test_validation.py
+++ b/tests/dataconverter/test_validation.py
@@ -84,6 +84,40 @@ def listify_template(data_dict: Template):
TEMPLATE = Template()
+TEMPLATE["required"]["/ENTRY[my_entry]/definition"] = "NXtest" # pylint: disable=E1126
+TEMPLATE["required"]["/ENTRY[my_entry]/definition/@version"] = "2.4.6" # pylint: disable=E1126
+TEMPLATE["required"]["/ENTRY[my_entry]/program_name"] = "Testing program" # pylint: disable=E1126
+
+TEMPLATE["required"]["/ENTRY[my_entry]/OPTIONAL_group[my_group]/required_field"] = 1
+TEMPLATE["optional"]["/ENTRY[my_entry]/OPTIONAL_group[my_group]/optional_field"] = 1
+
+TEMPLATE["required"][
+ "/ENTRY[my_entry]/specified_group_with_no_name_type/specified_field_with_no_name_type"
+] = 1.0
+TEMPLATE["required"][
+ "/ENTRY[my_entry]/specified_group_with_no_name_type/specified_field_with_no_name_type/@specified_attr_in_field_with_no_name_type"
+] = "data"
+TEMPLATE["required"][
+ "/ENTRY[my_entry]/specified_group_with_no_name_type/@specified_attr_with_no_name_type"
+] = "attr"
+
+TEMPLATE["required"]["/ENTRY[my_entry]/specified_group/specified_field"] = 1.0
+TEMPLATE["required"][
+ "/ENTRY[my_entry]/specified_group/specified_field/@specified_attr_in_field"
+] = "attr"
+TEMPLATE["required"]["/ENTRY[my_entry]/specified_group/@specified_attr"] = "attr"
+
+
+TEMPLATE["required"][
+ "/ENTRY[my_entry]/any_groupGROUP[any_groupGROUP]/any_fieldFIELD[any_fieldFIELD]"
+] = 1.0
+TEMPLATE["required"][
+ "/ENTRY[my_entry]/any_groupGROUP[any_groupGROUP]/any_fieldFIELD[any_fieldFIELD]/@any_attrATTR_in_field[@any_attrATTR_in_field]"
+] = "attr"
+TEMPLATE["required"][
+ "/ENTRY[my_entry]/any_groupGROUP[any_groupGROUP]/@any_attrATTR[@any_attrATTR]"
+] = "attr"
+
TEMPLATE["optional"][
"/ENTRY[my_entry]/NXODD_name[nxodd_name]/anamethatRENAMES[anamethatichangetothis]"
] = 2
@@ -94,16 +128,15 @@ def listify_template(data_dict: Template):
TEMPLATE["optional"][
"/ENTRY[my_entry]/NXODD_name[nxodd_name]/DATA[float_value_no_attr]"
] = (2.0,)
-TEMPLATE["optional"]["/ENTRY[my_entry]/optional_parent/required_child"] = 1 # pylint: disable=E1126
-TEMPLATE["optional"]["/ENTRY[my_entry]/optional_parent/optional_child"] = 1 # pylint: disable=E1126
-TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/bool_value"] = True # pylint: disable=E1126
-TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/bool_value/@units"] = ""
-TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/int_value"] = 2 # pylint: disable=E1126
-TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/int_value/@units"] = "eV" # pylint: disable=E1126
TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/number_value"] = 2
TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/number_value/@units"] = (
"eV"
)
+TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/bool_value"] = True # pylint: disable=E1126
+TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/bool_value/@units"] = ""
+TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/int_value"] = 2 # pylint: disable=E1126
+TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/int_value/@units"] = "eV" # pylint: disable=E1126
+
TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/posint_value"] = np.array(
[1, 2, 3], # pylint: disable=E1126
dtype=np.int8,
@@ -118,8 +151,15 @@ def listify_template(data_dict: Template):
TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/@group_attribute"] = (
"data" # pylint: disable=E1126
)
+TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/date_value"] = (
+ "2022-01-22T12:14:12.05018+00:00" # pylint: disable=E1126
+)
+TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/date_value/@units"] = ""
+TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/type"] = "2nd type" # pylint: disable=E1126
+TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/type/@array"] = [0, 1, 2]
TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/@signal"] = "data"
TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/DATA[data]"] = 1 # pylint: disable=E1126
+
TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_two_name]/bool_value"] = True # pylint: disable=E1126
TEMPLATE["required"][
"/ENTRY[my_entry]/NXODD_name[nxodd_two_name]/bool_value/@units"
@@ -163,23 +203,16 @@ def listify_template(data_dict: Template):
)
TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_two_name]/@signal"] = "data"
TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_two_name]/DATA[data]"] = 1 # pylint: disable=E1126
-TEMPLATE["required"]["/ENTRY[my_entry]/OPTIONAL_group[my_group]/required_field"] = 1 # pylint: disable=E1126
-TEMPLATE["required"]["/ENTRY[my_entry]/definition"] = "NXtest" # pylint: disable=E1126
-TEMPLATE["required"]["/ENTRY[my_entry]/definition/@version"] = "2.4.6" # pylint: disable=E1126
-TEMPLATE["required"]["/ENTRY[my_entry]/program_name"] = "Testing program" # pylint: disable=E1126
-TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/type"] = "2nd type" # pylint: disable=E1126
-TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/type/@array"] = [0, 1, 2]
-TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/date_value"] = (
- "2022-01-22T12:14:12.05018+00:00" # pylint: disable=E1126
-)
-TEMPLATE["required"]["/ENTRY[my_entry]/NXODD_name[nxodd_name]/date_value/@units"] = ""
-TEMPLATE["optional"]["/ENTRY[my_entry]/OPTIONAL_group[my_group]/optional_field"] = 1
+
TEMPLATE["optional"]["/ENTRY[my_entry]/required_group/description"] = (
"An example description"
)
TEMPLATE["optional"]["/ENTRY[my_entry]/required_group2/description"] = (
"An example description"
)
+
+TEMPLATE["required"]["/ENTRY[my_entry]/optional_parent/required_child"] = 1 # pylint: disable=E1126
+TEMPLATE["optional"]["/ENTRY[my_entry]/optional_parent/optional_child"] = 1 # pylint: disable=E1126
TEMPLATE["required"][
"/ENTRY[my_entry]/optional_parent/req_group_in_opt_group/DATA[data]"
] = 1
@@ -201,6 +234,35 @@ def listify_template(data_dict: Template):
@pytest.mark.parametrize(
"data_dict,error_messages",
[
+ pytest.param(
+ alter_dict(
+ alter_dict(
+ alter_dict(
+ remove_from_dict(
+ remove_from_dict(
+ remove_from_dict(
+ TEMPLATE,
+ "/ENTRY[my_entry]/any_groupGROUP[any_groupGROUP]/any_fieldFIELD[any_fieldFIELD]",
+ "required",
+ ),
+ "/ENTRY[my_entry]/any_groupGROUP[any_groupGROUP]/any_fieldFIELD[any_fieldFIELD]/@any_attrATTR_in_field[@any_attrATTR_in_field]",
+ "required",
+ ),
+ "/ENTRY[my_entry]/any_groupGROUP[any_groupGROUP]/@any_attrATTR[@any_attrATTR]",
+ "required",
+ ),
+ "/ENTRY[my_entry]/any_groupGROUP[some_group_name]/any_fieldFIELD[some_field_name]",
+ 1.0,
+ ),
+ "/ENTRY[my_entry]/any_groupGROUP[some_group_name]/any_fieldFIELD[some_field_name]/@any_attrATTR_in_field[@some_attr_name]",
+ "new attr",
+ ),
+ "/ENTRY[my_entry]/any_groupGROUP[some_group_name]/@any_attrATTR[@some_attr_name]",
+ "new attr",
+ ),
+ [],
+ id="name-type-any",
+ ),
pytest.param(
alter_dict(
TEMPLATE,
@@ -598,13 +660,25 @@ def listify_template(data_dict: Template):
[
"The value at /ENTRY[my_entry]/NXODD_name[nxodd_name]/type should "
"be one of the following"
- ": ['1st type', '2nd type', '3rd type', '4th type']"
+ ": ['1st type', '2nd type', '3rd type', '4th type']."
],
id="wrong-enum-choice",
),
+ pytest.param(
+ alter_dict(
+ TEMPLATE,
+ "/ENTRY[my_entry]/NXODD_name[nxodd_name]/type2",
+ "a very different type",
+ ),
+ [
+ "The value at /ENTRY[my_entry]/NXODD_name[nxodd_name]/type2 does not match with the "
+ "enumerated items from the open enumeration: ['1st type open', '2nd type open']."
+ ],
+ id="open-enum-with-new-item",
+ ),
pytest.param(
set_to_none_in_dict(
- TEMPLATE, "/ENTRY[my_entry]/optional_parent/required_child", "optional"
+ TEMPLATE, "/ENTRY[my_entry]/optional_parent/required_child", "required"
),
[
"The data entry corresponding to /ENTRY[my_entry]/optional_parent/"
@@ -645,6 +719,40 @@ def listify_template(data_dict: Template):
[],
id="no-child-provided-optional-parent",
),
+ pytest.param(
+ alter_dict(
+ remove_from_dict(
+ TEMPLATE,
+ "/ENTRY[my_entry]/optional_parent/required_child",
+ "required",
+ ),
+ "/ENTRY[my_entry]/optional_parent/AXISNAME[required_child]",
+ 1,
+ ),
+ # ToDo: should not raise a warning if sibling inheritance works
+ [
+ "The data entry corresponding to /ENTRY[my_entry]/optional_parent/"
+ "required_child is required and hasn't been supplied by the reader."
+ ],
+ id="concept-name-given-for-nonvariadic-field",
+ ),
+ pytest.param(
+ alter_dict(
+ remove_from_dict(
+ TEMPLATE,
+ "/ENTRY[my_entry]/optional_parent/optional_child",
+ "optional",
+ ),
+ "/ENTRY[my_entry]/optional_parent/AXISNAME[optional_child]",
+ "test value",
+ ),
+ [
+ "The value at /ENTRY[my_entry]/optional_parent/AXISNAME[optional_child] should be "
+ "one of the following Python types: (, ), as "
+ "defined in the NXDL as NX_INT."
+ ],
+ id="concept-name-given-for-nonvariadic-field-wrong-type",
+ ),
pytest.param(TEMPLATE, "", id="valid-data-dict"),
pytest.param(
remove_from_dict(TEMPLATE, "/ENTRY[my_entry]/required_group/description"),
@@ -695,7 +803,7 @@ def listify_template(data_dict: Template):
),
[
"The value at /ENTRY[my_entry]/NXODD_name[nxodd_name]/type/@array should be one of the following Python types: (, ), as defined in the NXDL as NX_INT.",
- "The value at /ENTRY[my_entry]/NXODD_name[nxodd_name]/type/@array should be one of the following: [[0, 1, 2], [2, 3, 4]]",
+ "The value at /ENTRY[my_entry]/NXODD_name[nxodd_name]/type/@array should be one of the following: [[0, 1, 2], [2, 3, 4]].",
],
id="wrong-type-array-in-attribute",
),
@@ -704,7 +812,7 @@ def listify_template(data_dict: Template):
TEMPLATE, "/ENTRY[my_entry]/NXODD_name[nxodd_name]/type/@array", [1, 2]
),
[
- "The value at /ENTRY[my_entry]/NXODD_name[nxodd_name]/type/@array should be one of the following: [[0, 1, 2], [2, 3, 4]]"
+ "The value at /ENTRY[my_entry]/NXODD_name[nxodd_name]/type/@array should be one of the following: [[0, 1, 2], [2, 3, 4]]."
],
id="wrong-value-array-in-attribute",
),
@@ -861,6 +969,18 @@ def listify_template(data_dict: Template):
],
id="baseclass-attribute-missing-field",
),
+ pytest.param(
+ alter_dict(
+ TEMPLATE,
+ "/ENTRY[my_entry]/INSTRUMENT[my_instrument]/SOURCE[my_source]/target_material",
+ "Cu",
+ ),
+ [
+ "The value at /ENTRY[my_entry]/INSTRUMENT[my_instrument]/SOURCE[my_source]/target_material "
+ "should be one of the following: ['Ta', 'W', 'depleted_U', 'enriched_U', 'Hg', 'Pb', 'C']."
+ ],
+ id="baseclass-wrong-enum",
+ ),
pytest.param(
alter_dict(
TEMPLATE,
@@ -868,14 +988,13 @@ def listify_template(data_dict: Template):
"Wrong source type",
),
[
- "The value at /ENTRY[my_entry]/INSTRUMENT[my_instrument]/SOURCE[my_source]/type "
- "should be one of the following: ['Spallation Neutron Source', 'Pulsed Reactor Neutron Source', "
- "'Reactor Neutron Source', 'Synchrotron X-ray Source', 'Pulsed Muon Source', 'Rotating Anode X-ray', "
- "'Fixed Tube X-ray', 'UV Laser', 'Free-Electron Laser', 'Optical Laser', 'Ion Source', 'UV Plasma Source', "
- "'Metal Jet X-ray', 'Laser', 'Dye-Laser', 'Broadband Tunable Light Source', 'Halogen lamp', 'LED', "
- "'Mercury Cadmium Telluride', 'Deuterium Lamp', 'Xenon Lamp', 'Globar', 'other']"
+ "The value at /ENTRY[my_entry]/INSTRUMENT[my_instrument]/SOURCE[my_source]/type does not match with the enumerated "
+ "items from the open enumeration: ['Spallation Neutron Source', 'Pulsed Reactor Neutron Source', 'Reactor Neutron Source', "
+ "'Synchrotron X-ray Source', 'Pulsed Muon Source', 'Rotating Anode X-ray', 'Fixed Tube X-ray', 'UV Laser', 'Free-Electron Laser', "
+ "'Optical Laser', 'Ion Source', 'UV Plasma Source', 'Metal Jet X-ray', 'Laser', 'Dye Laser', 'Broadband Tunable Light Source', "
+ "'Halogen Lamp', 'LED', 'Mercury Cadmium Telluride Lamp', 'Deuterium Lamp', 'Xenon Lamp', 'Globar']."
],
- id="baseclass-wrong-enum",
+ id="baseclass-open-enum-with-new-item",
),
pytest.param(
alter_dict(
@@ -927,6 +1046,103 @@ def listify_template(data_dict: Template):
],
id="baseclass-field-with-illegal-unit",
),
+ pytest.param(
+ alter_dict(
+ TEMPLATE,
+ "/ENTRY[my_entry]/identified_calibration/identifier_1",
+ "123",
+ ),
+ [],
+ id="specified-identifier-with-type",
+ ),
+ # ToDo: reactivate if sibling inheritance works properly
+ # pytest.param(
+ # alter_dict(
+ # alter_dict(
+ # TEMPLATE,
+ # "/ENTRY[my_entry]/identified_calibration/identifier_1",
+ # "123",
+ # ),
+ # "/ENTRY[my_entry]/identified_calibration/identifier_1/@type",
+ # "ORCID",
+ # ),
+ # [],
+ # id="specified-identifier-with-type",
+ # ),
+ pytest.param(
+ alter_dict(
+ alter_dict(
+ TEMPLATE,
+ "/ENTRY[my_entry]/identifierNAME[identifier_id]",
+ "123",
+ ),
+ "/ENTRY[my_entry]/identifierNAME[identifier_id]/@type",
+ "ORCID",
+ ),
+ [],
+ id="name-fitted-identifier-with-type",
+ ),
+ pytest.param(
+ alter_dict(
+ alter_dict(
+ TEMPLATE,
+ "/ENTRY[my_entry]/identifierNAME[identifier_id]",
+ "123",
+ ),
+ "/ENTRY[my_entry]/identifierNAME[identifier_id]/@type",
+ "ORCID",
+ ),
+ [],
+ id="name-fitted-identifier-with-type",
+ ),
+ # This can be re-used later when we have proper unit checking
+ pytest.param(
+ alter_dict(
+ alter_dict(
+ TEMPLATE,
+ "/ENTRY[my_entry]/INSTRUMENT[my_instrument]/MONOCHROMATOR[monochromator]/energy_dispersion",
+ 0.5,
+ ),
+ "/ENTRY[my_entry]/INSTRUMENT[my_instrument]/MONOCHROMATOR[monochromator]/energy_dispersion/@units",
+ "J/mm",
+ ),
+ [],
+ id="baseclass-unit-example",
+ ),
+ pytest.param(
+ alter_dict(
+ alter_dict(
+ alter_dict(
+ TEMPLATE,
+ "/ENTRY[my_entry]/COLLECTION[collection]/some_field",
+ 0.5,
+ ),
+ "/ENTRY[my_entry]/COLLECTION[collection]/DATA[data]/some_field",
+ 0.5,
+ ),
+ "/ENTRY[my_entry]/COLLECTION[collection]/DATA[data]/some_field/@units",
+ "mm",
+ ),
+ [],
+ id="variadic-nxcollection",
+ ),
+ pytest.param(
+ alter_dict(
+ alter_dict(
+ alter_dict(
+ TEMPLATE,
+ "/ENTRY[my_entry]/named_collection/some_field",
+ 0.5,
+ ),
+ "/ENTRY[my_entry]/named_collection/DATA[data]/some_field",
+ 0.5,
+ ),
+ "/ENTRY[my_entry]/named_collection/DATA[data]/some_field/@units",
+ "mm",
+ ),
+ [],
+ id="nonvariadic-nxcollection",
+ ),
],
)
def test_validate_data_dict(caplog, data_dict, error_messages, request):
@@ -943,6 +1159,10 @@ def format_error_message(msg: str) -> str:
if request.node.callspec.id in (
"field-with-illegal-unit",
"baseclass-field-with-illegal-unit",
+ "open-enum-with-new-item",
+ "baseclass-open-enum-with-new-item",
+ "variadic-nxcollection",
+ "nonvariadic-nxcollection",
):
with caplog.at_level(logging.INFO):
assert validate_dict_against("NXtest", data_dict)[0]
diff --git a/tests/nexus/test_nexus.py b/tests/nexus/test_nexus.py
index 2069f4dd1..4b14b9753 100644
--- a/tests/nexus/test_nexus.py
+++ b/tests/nexus/test_nexus.py
@@ -213,77 +213,41 @@ def test_get_node_at_nxdl_path():
"""Test to verify if we receive the right XML element for a given NXDL path"""
local_dir = os.path.abspath(os.path.dirname(__file__))
nxdl_file_path = os.path.join(local_dir, "../../src/pynxtools/data/NXtest.nxdl.xml")
+
elem = ET.parse(nxdl_file_path).getroot()
+
node = get_node_at_nxdl_path("/ENTRY/NXODD_name", elem=elem)
assert node.attrib["type"] == "NXdata"
assert node.attrib["name"] == "NXODD_name"
+ node = get_node_at_nxdl_path("/ENTRY/NXODD_name/anamethatRENAMES", elem=elem)
+ assert node.attrib["type"] == "NX_INT"
+ assert node.attrib["name"] == "anamethatRENAMES"
+ assert node.attrib["nameType"] == "partial"
+ assert node.attrib["units"] == "NX_UNITLESS"
+
node = get_node_at_nxdl_path("/ENTRY/NXODD_name/float_value", elem=elem)
assert node.attrib["type"] == "NX_FLOAT"
assert node.attrib["name"] == "float_value"
+ assert not node.attrib.get("nameType")
node = get_node_at_nxdl_path("/ENTRY/NXODD_name/AXISNAME/long_name", elem=elem)
assert node.attrib["name"] == "long_name"
- nxdl_file_path = os.path.join(local_dir, "../data/nexus/NXtest2.nxdl.xml")
- elem = ET.parse(nxdl_file_path).getroot()
- node = get_node_at_nxdl_path(
- "/ENTRY/measurement/EVENT_DATA_EM/USER/affiliation", elem=elem
- )
- assert node.attrib["name"] == "affiliation"
-
- node = get_node_at_nxdl_path("/ENTRY/measurement", elem=elem)
- assert node.attrib["type"] == "NXevent_data_em_set"
-
- node = get_node_at_nxdl_path(
- "/ENTRY/measurement/EVENT_DATA_EM/SPECTRUM_SET/stack_3d", elem=elem
- )
- assert node.attrib["type"] == "NXdata"
-
- node = get_node_at_nxdl_path(
- "/ENTRY/measurement/EVENT_DATA_EM/SPECTRUM_SET/stack_3d/intensity", elem=elem
- )
- assert node.attrib["type"] == "NX_NUMBER"
+ node = get_node_at_nxdl_path("/ENTRY/NXODD_name/group_attribute", elem=elem)
+ assert node.attrib["name"] == "group_attribute"
- node = get_node_at_nxdl_path(
- "/ENTRY/measurement/EVENT_DATA_EM/SPECTRUM_SET/stack_3d/AXISNAME_indices",
- elem=elem,
- )
- assert node.attrib["name"] == "AXISNAME_indices"
-
- node = get_node_at_nxdl_path("/ENTRY/COORDINATE_SYSTEM_SET", elem=elem)
- assert node.attrib["type"] == "NXcoordinate_system_set"
+ node = get_node_at_nxdl_path("/ENTRY/optional_parent", elem=elem)
+ assert node.attrib["name"] == "optional_parent"
+ assert node.attrib["optional"] == "true"
- node = get_node_at_nxdl_path(
- "/ENTRY/COORDINATE_SYSTEM_SET/TRANSFORMATIONS", elem=elem
- )
- assert node.attrib["type"] == "NXtransformations"
+ node = get_node_at_nxdl_path("/ENTRY/optional_parent/required_child", elem=elem)
+ assert node.attrib["name"] == "required_child"
+ assert node.attrib["type"] == "NX_INT"
+ assert node.attrib["required"] == "true"
- node = get_node_at_nxdl_path(
- "/ENTRY/COORDINATE_SYSTEM_SET/TRANSFORMATIONS/AXISNAME", elem=elem
- )
- assert node.attrib["type"] == "NX_NUMBER"
-
- node = get_node_at_nxdl_path(
- "/ENTRY/COORDINATE_SYSTEM_SET/TRANSFORMATIONS/AXISNAME/transformation_type",
- elem=elem,
- )
- assert node.attrib["name"] == "transformation_type"
-
- nxdl_file_path = os.path.join(
- local_dir,
- "../../src/pynxtools/definitions/contributed_definitions/NXiv_temp.nxdl.xml",
- )
- elem = ET.parse(nxdl_file_path).getroot()
- node = get_node_at_nxdl_path(
- "/ENTRY/INSTRUMENT/ENVIRONMENT/voltage_controller", elem=elem
- )
- assert node.attrib["name"] == "voltage_controller"
-
- node = get_node_at_nxdl_path(
- "/ENTRY/INSTRUMENT/ENVIRONMENT/voltage_controller/calibration_time", elem=elem
- )
- assert node.attrib["name"] == "calibration_time"
+ node = get_node_at_nxdl_path("/ENTRY/USER/affiliation", elem=elem)
+ assert node.attrib["name"] == "affiliation"
def test_get_inherited_nodes():
@@ -297,18 +261,18 @@ def test_get_inherited_nodes():
(_, _, elist) = get_inherited_nodes(
nxdl_path="/ENTRY/INSTRUMENT/ENVIRONMENT", elem=elem
)
- assert len(elist) == 3
+ assert len(elist) == 4
(_, _, elist) = get_inherited_nodes(
nxdl_path="/ENTRY/INSTRUMENT/ENVIRONMENT/voltage_controller", elem=elem
)
- assert len(elist) == 4
+ assert len(elist) == 6
(_, _, elist) = get_inherited_nodes(
nxdl_path="/ENTRY/INSTRUMENT/ENVIRONMENT/voltage_controller",
nx_name="NXiv_temp",
)
- assert len(elist) == 4
+ assert len(elist) == 6
def test_c_option(tmp_path):
diff --git a/tests/nomad/test_parsing.py b/tests/nomad/test_parsing.py
index e050448a7..694517c98 100644
--- a/tests/nomad/test_parsing.py
+++ b/tests/nomad/test_parsing.py
@@ -57,15 +57,16 @@ def test_nexus_example():
)
# good ENUM - x-ray
assert instrument.SOURCE[0].probe__field == "x-ray"
- # wrong inherited ENUM - Burst
- assert instrument.SOURCE[0].mode__field is None
- # wrong inherited ENUM for extended field - 'Free Electron Laser'
- assert instrument.SOURCE[0].type__field is None
+ # wrong inherited ENUM - Burst (accepted for open enum)
+ assert instrument.SOURCE[0].mode__field == "Burst"
+ # wrong inherited ENUM for extended field - 'Free Electron Laser' (accepted for open enum)
+ assert instrument.SOURCE[0].type__field == "Free Electron Laser"
data = arpes_obj.ENTRY[0].DATA[0]
assert len(data.AXISNAME__field) == 3
# there is still a bug in the variadic name resolution, so skip these
- # assert data.delays__field is not None
- # assert data.angles__field.check("1/Å")
+ assert data.delays__field is not None
+ assert data.angles__field.check("1/Å")
+ # ToDo: if AXISNAME and DATA can be resolved properly, extend this!
# assert data.delays__field.check("fs")
# but the following still works
assert data.energies__field is not None
@@ -76,6 +77,16 @@ def test_nexus_example():
assert (1 * data.AXISNAME__field["angles__field"].unit).check("1/Å")
assert (1 * data.AXISNAME__field["delays__field"].unit).check("fs")
assert data.___axes == "['angles', 'energies', 'delays']"
+ # testing attributes
+ assert (
+ data.AXISNAME__field["angles__field"].attributes.get("m_nx_data_path")
+ == "/entry/data/angles"
+ )
+ assert (
+ data.m_get_quantity_attribute("angles__field", "m_nx_data_path")
+ == "/entry/data/angles"
+ )
+ assert data.m_attributes.get("m_nx_data_path") == "/entry/data"
def test_same_name_field_and_group():