Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions docs/learn/multi-format-reader.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def read(
) -> dict:
self.kwargs = kwargs
self.config_file = self.kwargs.get("config_file", self.config_file)
self.overwrite_keys = self.kwargs.get("overwrite_keys", self.overwrite_keys)
self.overwrite_keys = self.kwargs.get("overwrite_keys", self.overwrite_keys)
```

## Template initialization and processing order
Expand Down Expand Up @@ -142,10 +142,10 @@ Next up, we can make use of the config file, which is a JSON file that tells the

```json
{
"/ENTRY/title": "@attrs:metadata/title",
"/ENTRY/title": "@attrs:metadata/title",
"/ENTRY/USER[user]": {
"name": "my_name",
},
},
"/ENTRY/INSTRUMENT[instrument]": {
"name":"@eln",
"temperature_sensor": {
Expand All @@ -157,7 +157,7 @@ Next up, we can make use of the config file, which is a JSON file that tells the
"temperature_env": {
"temperature_sensor": "@link:/entry/instrument/temperature_sensor"
}
},
},
"/ENTRY/data": {
"@axes": "@data:dims",
"AXISNAME_indices[@*_indices]": "@data:*.index",
Expand Down Expand Up @@ -263,16 +263,16 @@ Here, `key` is the config dict key (e.g., `"/ENTRY[my-entry]/data/data"`) and pa
```
that allows filling multiple fields of the same type from a list of dimensions. This can be particularly helpful for writing `DATA` and `AXISNAME` fields that are all stored under similar paths in the read-in data.
For this, the `get_data_dims` method needs to be implemented. For a given path, it should return a list of all data axes available to replace the wildcard.

The same wildcard notation can also be used within a name to repeat entries with different names (e.g., field_*{my, name, etc} is converted into three keys with * replaced by my, name, etc, respectively). As an example, for multiple lenses and their voltage readouts, one could write:
```json
"LENS_EM[lens_*{A,B,Foc}]": {
"ELECTROMAGNETIC_LENS[lens_*{A,B,Foc}]": {
"name": "*",
"voltage": "@attrs:metadata/file/Lens:*:V",
"voltage/@units": "V"
},
```
which would write `NXlens_em` instances named `lens_A`, `lens_B`, and `lens_Foc`.
which would write `NXelectromagnetic_lens` instances named `lens_A`, `lens_B`, and `lens_Foc`.

- **Required fields in optional groups**: There will sometimes be the situation that there is an optional NeXus group in an application definition, that (if implemented) requires some sub-element. As an example, for the instrument's energy resolution, the only value expected to come from a data source is the `resolution`, whereas other fields are hardcoded.
```json
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ dev = [
"types-requests",
"pre-commit",
]
dev-nomad = [
"urllib3==1.26.20",
"filelock==3.3.1",
"platformdirs==4.3.7"
]
convert = [
"pynxtools[apm,ellips,em,igor,mpes,raman,spm,xps,xrd]",
]
Expand Down
17 changes: 14 additions & 3 deletions src/pynxtools/dataconverter/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
DEBUG_VALIDATION = False

import copy
import re
from collections import defaultdict
Expand All @@ -24,6 +26,8 @@
from operator import getitem
from typing import Any, Literal, Optional, Union

if DEBUG_VALIDATION:
import debugpy # will connect to debugger if in debug mode
import h5py
import lxml.etree as ET
import numpy as np
Expand All @@ -42,7 +46,12 @@
generate_tree_from,
)
from pynxtools.definitions.dev_tools.utils.nxdl_utils import get_nx_namefit
from pynxtools.units import NXUnitSet, ureg
from pynxtools.units import NXUnitSet

if DEBUG_VALIDATION:
debugpy.debug_this_thread()
# set break points like this
# debugpy.breakpoint()


def validate_hdf_group_against(appdef: str, data: h5py.Group):
Expand Down Expand Up @@ -599,8 +608,10 @@ def handle_field(node: NexusNode, keys: Mapping[str, Any], prev_path: str):
for variant in variants:
variant_path = f"{prev_path}/{variant}"

if isinstance(keys[variant], Mapping) and not all(
k.startswith("@") for k in keys[variant]
if (
isinstance(keys[variant], Mapping)
and not all(k.startswith("@") for k in keys[variant])
and not list(keys[variant].keys()) == ["compress", "strength"]
):
# A field should not have a dict of keys that are _not_ all attributes,
# i.e. no sub-fields or sub-groups.
Expand Down
2 changes: 1 addition & 1 deletion src/pynxtools/definitions
Submodule definitions updated 350 files
2 changes: 1 addition & 1 deletion src/pynxtools/nexus-version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v2024.02-1986-g1e8c4331
v2024.02-2041-g870edd9a
19 changes: 10 additions & 9 deletions src/pynxtools/testing/nexus_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import logging
import os
from glob import glob
from typing import Literal, Optional
from typing import Literal

try:
from nomad.client import parse
Expand All @@ -31,10 +31,7 @@


from pynxtools.dataconverter.convert import convert, get_reader
from pynxtools.dataconverter.helpers import (
add_default_root_attributes,
get_nxdl_root_and_path,
)
from pynxtools.dataconverter.helpers import get_nxdl_root_and_path
from pynxtools.nexus.nexus import HandleNexus


Expand Down Expand Up @@ -110,15 +107,17 @@ def convert_to_nexus(
example_files = self.files_or_dir
else:
example_files = sorted(glob(os.path.join(self.files_or_dir, "*")))
self.ref_nexus_file = [file for file in example_files if file.endswith(".nxs")][
0
]
# dbg, assumes that this always exists
# 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", "ref_output.txt"))
]
assert self.ref_nexus_file, "Reference nexus (.nxs) file not found"
# dbg
# assert self.ref_nexus_file, "Reference nexus (.nxs) file not found"

assert (
self.nxdl in self.reader.supported_nxdls
Expand All @@ -143,6 +142,8 @@ def convert_to_nexus(
)

test_output = self.caplog.messages
# dbg
return

files_with_expected_output = [
file for file in example_files if file.endswith("ref_output.txt")
Expand Down