Skip to content
Merged
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
34 changes: 32 additions & 2 deletions src/chexus/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def validate(self, node: Dataset | Group) -> Violation | None:
if name not in start.children:
return Violation(node.name, f"depends_on target {target} is missing")
start = start.children[name]
if not is_transformation(start):
if not is_complete_transformation(start):
return Violation(
node.name, f"depends_on target {target} is not a transformation"
)
Expand Down Expand Up @@ -217,6 +217,15 @@ def is_transformation(node: Dataset | Group) -> bool:
return "transformation_type" in node.attrs and "vector" in node.attrs


def is_complete_transformation(node: Dataset | Group) -> bool:
return (
is_transformation(node)
and "depends_on" in node.attrs
# Check that the transformation is type NX_NUMBER
and (isinstance(node, Dataset) or node.attrs.get('NX_class') == 'NXlog')
)


class transformation_offset_units_missing(Validator):
def __init__(self) -> None:
super().__init__(
Expand Down Expand Up @@ -378,7 +387,7 @@ def validate(self, node: Dataset | Group) -> Violation | None:
if not np.isin(event_ids, detector_numbers).all():
diff = np.setdiff1d(event_ids, detector_numbers)
return Violation(
node.name, 'event_id:s that are not in detector_number: ' f'{diff}'
node.name, f'event_id:s that are not in detector_number: {diff}'
)


Expand Down Expand Up @@ -533,6 +542,26 @@ def validate(self, node: Group | Dataset) -> Violation | None:
return Violation(node.name, "NXevent_data must have event dataset(s)")


class children_of_nxtransformations_are_nxnumber(Validator):
def __init__(self) -> None:
super().__init__(
"NXtransformations_child_not_NX_NUMBER",
"children of NXtransformations must be NX_NUMBER",
)

def applies_to(self, node: Dataset | Group) -> bool:
return (
node.parent is not None
and node.parent.attrs.get("NX_class") == "NXtransformations"
)

def validate(self, node: Dataset | Group) -> Violation | None:
if not (isinstance(node, Dataset) or node.attrs.get("NX_class") == "NXlog"):
return Violation(
node.name, "child of NXtransformation is not NXlog or dataset"
)


def base_validators(*, has_scipp=True):
validators = [
depends_on_missing(),
Expand All @@ -554,6 +583,7 @@ def base_validators(*, has_scipp=True):
NXdetector_pixel_offsets_are_unambiguous(),
event_index_is_eight_bytes(),
event_data_group_has_event_datasets(),
children_of_nxtransformations_are_nxnumber(),
]
if has_scipp:
validators += [
Expand Down
53 changes: 53 additions & 0 deletions tests/validators_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,30 @@ def test_depends_on_target_missing():
assert result.name == "x/transform"


def test_depends_on_target_requires_depends_on_attribute():
group = chexus.Group(name="x", attrs={"NX_class": "NXdetector"})
depends_on = chexus.Dataset(
name="x/depends_on", value="transform", shape=None, dtype=str, parent=group
)
transform = chexus.Dataset(
name="x/transform",
value=None,
shape=None,
dtype=float,
parent=group,
attrs={
"transformation_type": "translation",
"vector": [1.0, 0.0, 0.0],
},
)
group.children = {"depends_on": depends_on, "transform": transform}

result = chexus.validators.depends_on_target_missing().validate(depends_on)

assert isinstance(result, chexus.Violation)
assert result.name == "x/depends_on"


def test_float_dataset_units_missing():
good = chexus.Dataset(
name="x",
Expand Down Expand Up @@ -905,3 +929,32 @@ def test_event_data_has_event_datasets_bad_empty() -> None:
chexus.validators.event_data_group_has_event_datasets().validate(parent),
chexus.Violation,
)


def test_children_of_nxtransformations_are_nxnumber() -> None:
parent = chexus.Group(
name="transformations", attrs={"NX_class": "NXtransformations"}
)
dataset = chexus.Dataset(
name="transformations/dataset",
value=1.0,
shape=None,
dtype=float,
parent=parent,
)
good = chexus.Group(
name="transformations/good", attrs={"NX_class": "NXlog"}, parent=parent
)
bad = chexus.Group(
name="transformations/bad", attrs={"NX_class": "NXcollection"}, parent=parent
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing good and bad datasets?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a good dataset test, but there is no bad dataset case for this validator because we don't check dtype.


validator = chexus.validators.children_of_nxtransformations_are_nxnumber()

assert not validator.applies_to(parent)
assert validator.applies_to(dataset)
assert validator.validate(dataset) is None
assert validator.applies_to(good)
assert validator.validate(good) is None
assert validator.applies_to(bad)
assert isinstance(validator.validate(bad), chexus.Violation)
Loading