From 2414d313b3ea5d07d9d7940593bc46f0a45be8fe Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Mon, 6 Jul 2026 14:15:21 +0100 Subject: [PATCH 1/3] Do not try to write non-existing fields in eiger for NXCollection --- src/nexgen/nxs_write/nxclass_writers.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/nexgen/nxs_write/nxclass_writers.py b/src/nexgen/nxs_write/nxclass_writers.py index 4162da78..f83a14f7 100644 --- a/src/nexgen/nxs_write/nxclass_writers.py +++ b/src/nexgen/nxs_write/nxclass_writers.py @@ -781,7 +781,11 @@ def write_NXcollection( ) if "EIGER" in detector_params.description.upper() and meta: for field in DETECTOR_SPECIFIC_PARAMS: - grp[field] = h5py.ExternalLink(meta.name, detector_params.constants[field]) + if field in detector_params.constants.keys(): + # New EIGER cbor format does not have all fields in meta file + grp[field] = h5py.ExternalLink( + meta.name, detector_params.constants[field] + ) elif "TRISTAN" in detector_params.description.upper(): tick = ureg.Quantity(detector_params.constants["detector_tick"]) grp.create_dataset("detector_tick", data=tick.magnitude) From 45228a6163df0a66afc6950ad7138460a6d4bb5e Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Mon, 6 Jul 2026 16:42:23 +0100 Subject: [PATCH 2/3] Update oveload --- src/nexgen/beamlines/i19_2/eiger.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/nexgen/beamlines/i19_2/eiger.py b/src/nexgen/beamlines/i19_2/eiger.py index 69e43948..f13a9d20 100644 --- a/src/nexgen/beamlines/i19_2/eiger.py +++ b/src/nexgen/beamlines/i19_2/eiger.py @@ -151,11 +151,14 @@ def eiger_writer( source = Source("I19-2") # Define Eiger 4M params + overload = ( + 1834948 if eiger_settings.stream_format == EigerStreamFormat.CBOR else 50649 + ) eiger_params = EigerDetector( "Eiger 2X 4M", (2162, 2068), "CdTe", - 50649, + overload, -1, stream=eiger_settings.stream_format, ) From 4501e48ab50369aedea8de9299ff0f79afc7bcac Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Mon, 6 Jul 2026 17:07:32 +0100 Subject: [PATCH 3/3] Add parsing for timestamps and some more formatting options --- src/nexgen/beamlines/i19_2/parameters.py | 9 +++++++++ src/nexgen/utils.py | 3 ++- tests/beamlines/i19_2/conftest.py | 4 ---- tests/beamlines/i19_2/test_parameters.py | 14 ++++++++++++++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/nexgen/beamlines/i19_2/parameters.py b/src/nexgen/beamlines/i19_2/parameters.py index d9c2dd4c..47658a54 100644 --- a/src/nexgen/beamlines/i19_2/parameters.py +++ b/src/nexgen/beamlines/i19_2/parameters.py @@ -1,5 +1,6 @@ """Define a collection parameter model for I19-2""" +from collections.abc import Sequence from enum import StrEnum from pathlib import Path from typing import NamedTuple @@ -7,6 +8,7 @@ from pydantic import field_validator from nexgen.beamlines.beamline_utils import GeneralParams +from nexgen.utils import get_iso_timestamp # Useful axis definitions and parameters @@ -74,3 +76,10 @@ def _parse_metafile(cls, metafile: str | Path): if isinstance(metafile, str): return Path(metafile) return metafile + + @field_validator("timestamps", mode="before") + @classmethod + def _parse_timestamps(cls, timestamps: Sequence[int | None]): + start = get_iso_timestamp(timestamps[0]) if timestamps[0] else "" + end = get_iso_timestamp(timestamps[1]) if timestamps[1] else "" + return (start, end) diff --git a/src/nexgen/utils.py b/src/nexgen/utils.py index 3c6f4433..22a1999d 100644 --- a/src/nexgen/utils.py +++ b/src/nexgen/utils.py @@ -237,6 +237,7 @@ def get_iso_timestamp(ts: str | float | None) -> str: "%Y-%m-%dT%H:%M:%SZ", # ISO8601 formatted string "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S", + "%Y-%m-%d %H:%M:%S.%f", "%a %b %d %Y %H:%M:%S", "%A, %d. %B %Y %I:%M%p", ] @@ -255,7 +256,7 @@ def get_iso_timestamp(ts: str | float | None) -> str: elif isinstance(ts, str): for fmt in format_list: if _validate_timestamp_string(ts, fmt) is True: - ts_iso = datetime.strptime(ts, fmt).isoformat() + ts_iso = datetime.strptime(ts, fmt).isoformat(timespec="seconds") break if not ts_iso: raise ValueError( diff --git a/tests/beamlines/i19_2/conftest.py b/tests/beamlines/i19_2/conftest.py index 57e15006..8d55cc2c 100644 --- a/tests/beamlines/i19_2/conftest.py +++ b/tests/beamlines/i19_2/conftest.py @@ -12,7 +12,3 @@ def dummy_eiger_collection_params(): metafile="/path/to/somefile_meta.h5", detector_name=DetectorName.EIGER, ) - - -# @pytest.fixture -# def dummy_eiger_settings() diff --git a/tests/beamlines/i19_2/test_parameters.py b/tests/beamlines/i19_2/test_parameters.py index 0cc49394..aa419f54 100644 --- a/tests/beamlines/i19_2/test_parameters.py +++ b/tests/beamlines/i19_2/test_parameters.py @@ -9,3 +9,17 @@ def test_collection_parameters(dummy_eiger_collection_params: CollectionParams): assert not dummy_eiger_collection_params.axes_pos assert not dummy_eiger_collection_params.det_pos assert dummy_eiger_collection_params.tot_num_images == 10 + + +def test_collection_parameters_timestamps(): + params = CollectionParams( + exposure_time=0.01, + beam_center=(100, 200), + wavelength=0.4, + metafile="/path/to/somefile_meta.h5", + detector_name="eiger", + timestamps=("2026-07-06 17:00:21", None), + ) + + assert params.timestamps[0] == "2026-07-06T17:00:21Z" + assert params.timestamps[1] == ""