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
48 changes: 24 additions & 24 deletions src/ess/reduce/nexus/_nexus_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@

from ..logging import get_logger
from .types import (
Filename,
NeXusDetector,
AnyNeXusMonitorName,
AnyRunAnyNeXusMonitor,
AnyRunFilename,
AnyRunNeXusDetector,
AnyRunNeXusSample,
AnyRunNeXusSource,
NeXusDetectorName,
NeXusEntryName,
NeXusGroup,
NeXusLocationSpec,
NeXusMonitor,
NeXusMonitorName,
NeXusSample,
NeXusSource,
NeXusSourceName,
RawDetectorData,
RawMonitorData,
Expand All @@ -36,13 +36,13 @@ class NoNewDefinitionsType: ...


def load_detector(
file_path: Filename,
file_path: AnyRunFilename,
selection=(),
*,
detector_name: NeXusDetectorName,
entry_name: NeXusEntryName | None = None,
definitions: Mapping | None | NoNewDefinitionsType = NoNewDefinitions,
) -> NeXusDetector:
) -> AnyRunNeXusDetector:
"""Load a single detector (bank) from a NeXus file.

The detector positions are computed automatically from NeXus transformations,
Expand Down Expand Up @@ -74,7 +74,7 @@ def load_detector(
A data group containing the detector events or histogram
and any auxiliary data stored in the same NeXus group.
"""
return NeXusDetector(
return AnyRunNeXusDetector(
load_component(
NeXusLocationSpec(
filename=file_path,
Expand All @@ -89,13 +89,13 @@ def load_detector(


def load_monitor(
file_path: Filename,
file_path: AnyRunFilename,
selection=(),
*,
monitor_name: NeXusMonitorName,
monitor_name: AnyNeXusMonitorName,
entry_name: NeXusEntryName | None = None,
definitions: Mapping | None | NoNewDefinitionsType = NoNewDefinitions,
) -> NeXusMonitor:
) -> AnyRunAnyNeXusMonitor:
"""Load a single monitor from a NeXus file.

The monitor position is computed automatically from NeXus transformations,
Expand Down Expand Up @@ -127,7 +127,7 @@ def load_monitor(
A data group containing the monitor events or histogram
and any auxiliary data stored in the same NeXus group.
"""
return NeXusMonitor(
return AnyRunAnyNeXusMonitor(
load_component(
NeXusLocationSpec(
filename=file_path,
Expand All @@ -142,12 +142,12 @@ def load_monitor(


def load_source(
file_path: Filename,
file_path: AnyRunFilename,
*,
source_name: NeXusSourceName | None = None,
entry_name: NeXusEntryName | None = None,
definitions: Mapping | None | NoNewDefinitionsType = NoNewDefinitions,
) -> NeXusSource:
) -> AnyRunNeXusSource:
"""Load a source from a NeXus file.

The source position is computed automatically from NeXus transformations,
Expand Down Expand Up @@ -181,7 +181,7 @@ def load_source(
A data group containing all data stored in
the source NeXus group.
"""
return NeXusSource(
return AnyRunNeXusSource(
load_component(
NeXusLocationSpec(
filename=file_path, component_name=source_name, entry_name=entry_name
Expand All @@ -193,10 +193,10 @@ def load_source(


def load_sample(
file_path: Filename,
file_path: AnyRunFilename,
entry_name: NeXusEntryName | None = None,
definitions: Mapping | None | NoNewDefinitionsType = NoNewDefinitions,
) -> NeXusSample:
) -> AnyRunNeXusSample:
"""Load a sample from a NeXus file.

The sample is located based on its NeXus class.
Expand Down Expand Up @@ -226,7 +226,7 @@ def load_sample(
A data group containing all data stored in
the sample NeXus group.
"""
return NeXusSample(
return AnyRunNeXusSample(
load_component(
NeXusLocationSpec(filename=file_path, entry_name=entry_name),
nx_class=snx.NXsample,
Expand Down Expand Up @@ -274,7 +274,7 @@ def load_component(


def _open_nexus_file(
file_path: Filename,
file_path: AnyRunFilename,
definitions: Mapping | None | NoNewDefinitionsType = NoNewDefinitions,
) -> ContextManager:
if isinstance(file_path, getattr(NeXusGroup, '__supertype__', type(None))):
Expand Down Expand Up @@ -310,7 +310,7 @@ def _unique_child_group(
return next(iter(children.values())) # type: ignore[return-value]


def extract_detector_data(detector: NeXusDetector) -> RawDetectorData:
def extract_detector_data(detector: AnyRunNeXusDetector) -> RawDetectorData:
"""Get and return the events or histogram from a detector loaded from NeXus.

This function looks for a data array in the detector group and returns that.
Expand Down Expand Up @@ -339,7 +339,7 @@ def extract_detector_data(detector: NeXusDetector) -> RawDetectorData:
return RawDetectorData(_extract_events_or_histogram(detector))


def extract_monitor_data(monitor: NeXusMonitor) -> RawMonitorData:
def extract_monitor_data(monitor: AnyRunAnyNeXusMonitor) -> RawMonitorData:
"""Get and return the events or histogram from a monitor loaded from NeXus.

This function looks for a data array in the monitor group and returns that.
Expand Down Expand Up @@ -413,7 +413,7 @@ def _select_unique_array(


def load_event_data(
file_path: Filename,
file_path: AnyRunFilename,
selection=(),
*,
entry_name: NeXusEntryName | None = None,
Expand Down Expand Up @@ -629,7 +629,7 @@ def _parse_monitor(group: snx.Group) -> NeXusMonitorInfo:
)


def read_nexus_file_info(file_path: Filename) -> NeXusFileInfo:
def read_nexus_file_info(file_path: AnyRunFilename) -> NeXusFileInfo:
"""Opens and inspects a NeXus file, returning a summary of its contents."""
with _open_nexus_file(file_path) as f:
entry = _unique_child_group(f, snx.NXentry, None)
Expand Down
7 changes: 4 additions & 3 deletions src/ess/reduce/nexus/generic_types.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"""Domain types for use with Sciline, parametrized by run- and monitor-type."""

from dataclasses import dataclass
from pathlib import Path
from typing import Generic, NewType, TypeVar

import sciline
import scipp as sc
import scippnexus as snx

from .types import FilePath, NeXusFile, NeXusGroup, NeXusLocationSpec
from .types import Component, FilePath, NeXusFile, NeXusGroup, NeXusLocationSpec

# 1 TypeVars used to parametrize the generic parts of the workflow

Expand Down Expand Up @@ -148,11 +149,11 @@ class MonitorData(
"""Calibrated monitor merged with neutron event data."""


Component = TypeVar('Component', bound=snx.NXobject)
class Filename(sciline.Scope[RunType, Path], Path): ...
Copy link
Member

Choose a reason for hiding this comment

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

With this, there are now to Filename types. The other one is in types.py. This seems confusing.

Copy link
Member Author

Choose a reason for hiding this comment

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

Please see #75 (comment), this is the case for about 20 or so types.

Copy link
Member

Choose a reason for hiding this comment

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

See me new comment



@dataclass
class Filename(Generic[RunType]):
class NeXusFileSpec(Generic[RunType]):
value: FilePath | NeXusFile | NeXusGroup


Expand Down
26 changes: 17 additions & 9 deletions src/ess/reduce/nexus/generic_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
from .types import DetectorBankSizes, GravityVector, NeXusDetectorName, PulseSelection


def file_path_to_file_spec(filename: gt.Filename[RunType]) -> gt.NeXusFileSpec[RunType]:
return gt.NeXusFileSpec[RunType](filename)


def no_monitor_position_offset() -> gt.MonitorPositionOffset[RunType, MonitorType]:
return gt.MonitorPositionOffset[RunType, MonitorType](workflow.no_offset)

Expand All @@ -29,34 +33,38 @@ def no_detector_position_offset() -> gt.DetectorPositionOffset[RunType]:


def unique_sample_spec(
filename: gt.Filename[RunType],
filename: gt.NeXusFileSpec[RunType],
) -> gt.NeXusComponentLocationSpec[snx.NXsample, RunType]:
return gt.NeXusComponentLocationSpec[snx.NXsample, RunType](filename=filename)
return gt.NeXusComponentLocationSpec[snx.NXsample, RunType](filename=filename.value)


def unique_source_spec(
filename: gt.Filename[RunType],
filename: gt.NeXusFileSpec[RunType],
) -> gt.NeXusComponentLocationSpec[snx.NXsource, RunType]:
return gt.NeXusComponentLocationSpec[snx.NXsource, RunType](filename=filename)
return gt.NeXusComponentLocationSpec[snx.NXsource, RunType](filename=filename.value)


def monitor_by_name(
filename: gt.Filename[RunType],
filename: gt.NeXusFileSpec[RunType],
name: gt.NeXusMonitorName[MonitorType],
selection: PulseSelection,
) -> gt.NeXusMonitorLocationSpec[RunType, MonitorType]:
return gt.NeXusMonitorLocationSpec[RunType, MonitorType](
filename=filename, component_name=name, selection={'event_time_zero': selection}
filename=filename.value,
component_name=name,
selection={'event_time_zero': selection},
)


def detector_by_name(
filename: gt.Filename[RunType],
filename: gt.NeXusFileSpec[RunType],
name: NeXusDetectorName,
selection: PulseSelection,
) -> gt.NeXusComponentLocationSpec[snx.NXdetector, RunType]:
return gt.NeXusComponentLocationSpec[snx.NXdetector, RunType](
filename=filename, component_name=name, selection={'event_time_zero': selection}
filename=filename.value,
component_name=name,
selection={'event_time_zero': selection},
)


Expand Down Expand Up @@ -174,7 +182,7 @@ def assemble_monitor_data(
assemble_monitor_data.__doc__ = workflow.assemble_monitor_data.__doc__


_common_providers = (workflow.gravity_vector_neg_y,)
_common_providers = (workflow.gravity_vector_neg_y, file_path_to_file_spec)

_monitor_providers = (
no_monitor_position_offset,
Expand Down
34 changes: 17 additions & 17 deletions src/ess/reduce/nexus/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"""Name of a detector (bank) in a NeXus file."""
NeXusEntryName = NewType('NeXusEntryName', str)
"""Name of an entry in a NeXus file."""
NeXusMonitorName = NewType('NeXusMonitorName', str)
AnyNeXusMonitorName = NewType('AnyNeXusMonitorName', str)
"""Name of a monitor in a NeXus file."""
NeXusSourceName = NewType('NeXusSourceName', str)
"""Name of a source in a NeXus file."""
Expand All @@ -35,47 +35,47 @@
RawMonitorData = NewType('RawMonitorData', sc.DataArray)
"""Data extracted from a RawMonitor."""

NeXusDetector = NewType('NeXusDetector', sc.DataGroup)
AnyRunNeXusDetector = NewType('AnyRunNeXusDetector', sc.DataGroup)
"""Full raw data from a NeXus detector."""
NeXusMonitor = NewType('NeXusMonitor', sc.DataGroup)
AnyRunAnyNeXusMonitor = NewType('AnyRunAnyNeXusMonitor', sc.DataGroup)
"""Full raw data from a NeXus monitor."""
NeXusSample = NewType('NeXusSample', sc.DataGroup)
AnyRunNeXusSample = NewType('AnyRunNeXusSample', sc.DataGroup)
"""Raw data from a NeXus sample."""
NeXusSource = NewType('NeXusSource', sc.DataGroup)
AnyRunNeXusSource = NewType('AnyRunNeXusSource', sc.DataGroup)
"""Raw data from a NeXus source."""
NeXusDetectorEventData = NewType('NeXusDetectorEventData', sc.DataArray)
AnyRunNeXusDetectorEventData = NewType('AnyRunNeXusDetectorEventData', sc.DataArray)
"""Data array loaded from a NeXus NXevent_data group within an NXdetector."""
NeXusMonitorEventData = NewType('NeXusMonitorEventData', sc.DataArray)
AnyRunAnyNeXusMonitorEventData = NewType('AnyRunAnyNeXusMonitorEventData', sc.DataArray)
"""Data array loaded from a NeXus NXevent_data group within an NXmonitor."""

SourcePosition = NewType('SourcePosition', sc.Variable)
AnyRunSourcePosition = NewType('AnyRunSourcePosition', sc.Variable)
"""Position of the neutron source."""

SamplePosition = NewType('SamplePosition', sc.Variable)
AnyRunSamplePosition = NewType('AnyRunSamplePosition', sc.Variable)
"""Position of the sample."""

DetectorPositionOffset = NewType('DetectorPositionOffset', sc.Variable)
AnyRunDetectorPositionOffset = NewType('AnyRunDetectorPositionOffset', sc.Variable)
"""Offset for the detector position, added to base position."""

MonitorPositionOffset = NewType('MonitorPositionOffset', sc.Variable)
AnyRunAnyMonitorPositionOffset = NewType('AnyRunAnyMonitorPositionOffset', sc.Variable)
"""Offset for the monitor position, added to base position."""


DetectorBankSizes = NewType("DetectorBankSizes", dict[str, dict[str, int | Any]])

CalibratedDetector = NewType('CalibratedDetector', sc.DataArray)
CalibratedMonitor = NewType('CalibratedMonitor', sc.DataArray)
AnyRunCalibratedDetector = NewType('AnyRunCalibratedDetector', sc.DataArray)
AnyRunAnyCalibratedMonitor = NewType('AnyRunAnyCalibratedMonitor', sc.DataArray)

DetectorData = NewType('DetectorData', sc.DataArray)
MonitorData = NewType('MonitorData', sc.DataArray)
AnyRunDetectorData = NewType('AnyRunDetectorData', sc.DataArray)
AnyRunAnyMonitorData = NewType('AnyRunAnyMonitorData', sc.DataArray)

PulseSelection = NewType('PulseSelection', slice)

GravityVector = NewType('GravityVector', sc.Variable)

Component = TypeVar('Component', bound=snx.NXobject)

Filename = FilePath | NeXusFile | NeXusGroup
AnyRunFilename = FilePath | NeXusFile | NeXusGroup


@dataclass
Expand All @@ -84,7 +84,7 @@ class NeXusLocationSpec(Generic[Component]):
NeXus filename and optional parameters to identify (parts of) a component to load.
"""

filename: Filename
filename: AnyRunFilename
entry_name: NeXusEntryName | None = None
component_name: str | None = None
selection: snx.typing.ScippIndex = ()
Loading