Skip to content
Merged
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
28 changes: 23 additions & 5 deletions packages/essinstruments/src/ess/instruments/loki/bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"""

from collections.abc import Mapping
from functools import reduce
from functools import cache, reduce
from operator import or_
from pathlib import Path
from typing import Any
Expand Down Expand Up @@ -79,9 +79,27 @@
"""The name of the mask of the angle ranges of a record."""


@cache
def _base_workflow() -> sciline.Pipeline:
"""The workflow of esssans, built once per process since that takes about 0.7 s.

Requests must not change it, but change a copy, see :func:`_workflow`.
"""
# sciline inserts each generic key as a node of a networkx graph, about 1000
# here, and rebuilds the graph at each assignment. Sharing one workflow is only
# worth it while that holds: measure the constructor when sciline handles
# generics another way, and build a workflow per request if it is cheap.
return LokiAtLarmorWorkflow()


def _workflow() -> sciline.Pipeline:
"""A copy of the workflow of esssans, for one request to change."""
return _base_workflow().copy()


def _run_workflow(run: Path) -> sciline.Pipeline:
"""The workflow of the detector of one run, with no beam-centre correction."""
workflow = LokiAtLarmorWorkflow()
workflow = _workflow()
workflow[Filename[SampleRun]] = str(run)
workflow[BeamCenter] = _NO_CORRECTION
return workflow
Expand Down Expand Up @@ -111,7 +129,7 @@ def compute_masks(params: MasksParams) -> MasksOutputs:
raise ValueError(f'mask files with the same name: {sorted(names)}')
masks: dict[str, sc.Variable] = {}
if params.mask_files:
workflow = LokiAtLarmorWorkflow()
workflow = _workflow()
workflow[DetectorIDs] = params.detector.counts.coords['detector_number']
# esssans names each mask by the path of its file, which differs by host.
by_path = sans.with_pixel_mask_filenames(
Expand All @@ -126,7 +144,7 @@ def find_beam_centre(params: BeamCentreParams) -> BeamCentreOutputs:
# The finder raises its cutoff until pixels are left, so without any it never ends.
if not counts.sum().value > 0:
raise ValueError('no counts outside the masks to find a beam centre from')
workflow = LokiAtLarmorWorkflow()
workflow = _workflow()
workflow[Position[snx.NXsample, SampleRun]] = counts.coords['sample_position']
workflow[Position[snx.NXsource, SampleRun]] = counts.coords['source_position']
# The finder sums the dimensions that the positions lack, and else expects events.
Expand Down Expand Up @@ -205,7 +223,7 @@ def _transmission(


def _iofq_pipeline(fixed: Mapping[str, Any]) -> sciline.Pipeline:
pipeline = LokiAtLarmorWorkflow()
pipeline = _workflow()
for provider in (
_detector_masks,
_beam_center,
Expand Down
Loading