Repository navigation
feat: patch NeXus files on the fly while loading - #839
Draft
SimonHeybrock wants to merge 2 commits into
Draft
SimonHeybrock wants to merge 2 commits into
SimonHeybrock wants to merge 2 commits into
Conversation
Add `ess.reduce.nexus.patch`, a read-only view of an HDF5 file with a list of operations applied (set/delete attributes, remove, move, set dataset). ScippNexus reads through this view, so workflows see the fixed structure without copying or modifying the file. Data is read from the original datasets. Patches are opt-in via the `NeXusFilePatch[RunType]` workflow parameter, which defaults to an empty patch. Patches can be loaded from TOML files and, being plain lists, amended in memory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Motion NXlogs of beamstop axes and the detector carriage were configured with a "TODO-" source prefix and are empty, while the motor readback was written to `<component>/value`. The patch makes these files loadable with the standard workflows. It is also the first example of a tracked NeXus patch file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Some raw files have defects that break the standard workflows, e.g., an empty transformation NXlog. #785 added failsafe loaders for inspecting such files, but their output cannot be used by workflows. This PR adds a way to fix known defects while loading, without rewriting the file.
What it does
A patch is a list of operations, stored in a TOML file:
Operations are
set_attrs,delete_attrs,remove,move,set_dataset, applied in order. Patching is opt-in per run:A patch is a plain list, so a tracked patch file can be amended in memory with extra fixes.
How it works
patch.PatchedH5Filewraps anh5py.Fileand implements the small part of the h5py interface that ScippNexus uses (ScippNexus is duck-typed against h5py). ScippNexus reads through this view, so:name,parent, andfilereport paths in the patched tree, sodepends_onchains resolve in the patched file,Operations fail if the file does not match the patch (e.g., removing a path that does not exist), so a patch applied to the wrong file fails when the file is opened instead of silently doing nothing.
The patch travels through the workflow as
PatchedFilePathin place of the file path, soPreopenNeXusFile=Falsekeeps re-opening the file per access as before.No ScippNexus changes are needed. Two places in ScippNexus are less duck-typed than its
H5Groupprotocol suggests, and both are handled here:snx.Fileonly wraps objects that passisinstance(..., h5py.File | h5py.Group).PatchedNeXusFiletherefore subclassessnx.Groupand adds the context-manager andclose()behavior ofsnx.File.snx.Attrscallsattrs.get_id(name).get_type().get_cset()to find the encoding of string attributes. Patched attributes are therefore stored in an in-memory HDF5 file, so they have real h5py IDs.A possible follow-up in ScippNexus: let
snx.Fileaccept any h5py-like group, optionally taking ownership, which would makePatchedNeXusFileunnecessary. The protocols inscippnexus/typing.pycould also be updated: they omititems,get, andattrs.get_id, which ScippNexus uses, but listcreate_dataset,create_group, andvisititems, which reading does not need.Discarded alternatives
BytesIOor the HDF5coredriver) and patching with h5py: reads the whole file into memory, not viable for large event files.ExternalLinkreport.file/.parent/.nameof the original file, so absolutedepends_onpaths resolve in the unpatched tree.Groupobjects after construction: requires touching cached private state.Example patch
ess/loki/nexus_patches/todo_motion_sources.tomlfixes the LoKI file used asloki_broken_filein the tests: motion NXlogs of the beamstop axes and the detector carriage have aTODO-source and are empty, while the motor readback was written to<component>/value. With the patch,GenericNeXusWorkflowcomputes detector and monitor positions for that file.Not in this PR
h5py.Filedirectly (some reflectometry, NMX, and spectroscopy loaders) does not see patches.🤖 Generated with Claude Code