# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2025 Scipp contributors (https://github.com/scipp)
from multiprocessing.pool import ThreadPool
import scipp as sc
from ess.reduce.data import make_registry
from ..reflectometry.types import Filename, ReferenceRun, SampleRun
_registry = make_registry(
"ess/estia",
version="1",
files={
"218610_tof_detector_list.p.x.y.t.L.sx.sy": "md5:65145a26c36d12954a97d27d6e7f4ed9", # noqa: E501
"218611_tof_detector_list.p.x.y.t.L.sx.sy": "md5:4599e938568f3b73a72d6d48fe5160e7", # noqa: E501
"218612_tof_detector_list.p.x.y.t.L.sx.sy": "md5:6bacd1e4d922007c7f574f20378b28f2", # noqa: E501
"218613_tof_detector_list.p.x.y.t.L.sx.sy": "md5:7c17cb8a2fe38f4f0976de1254295636", # noqa: E501
"218614_tof_detector_list.p.x.y.t.L.sx.sy": "md5:78cf399dcedea2a2d4178e11b95c53f2", # noqa: E501
# McStas runs for the samples in the Estia McStas model at various angles
"examples/220573/mccode.h5": "md5:2f1ba298bd8a1a67082a41d2c3957fc7",
"examples/220574/mccode.h5": "md5:ecfcf72e936dd5345c1aededa7e9388b",
"examples/220575/mccode.h5": "md5:efb206cf7cf87bf587bca31dca5da39d",
"examples/220576/mccode.h5": "md5:f63664809a15331d055ab9746f7f7259",
"examples/220577/mccode.h5": "md5:e0915c1271ae1800deba7e8c4b7cbf3e",
"examples/220578/mccode.h5": "md5:c456c1bf7e30c09d3ab36f0a87721d49",
"examples/220579/mccode.h5": "md5:3fd9ce4eab6c54346ce7086055695552",
"examples/220580/mccode.h5": "md5:36ff5b178fef6eb5f3be97089c493574",
"examples/220581/mccode.h5": "md5:736aa90d3570a104ab1ca0f4090ea94e",
"examples/220582/mccode.h5": "md5:d01a1fa2e98f0086b3bc0e5dbc323bde",
"examples/220583/mccode.h5": "md5:4f243df1b2dac2cf6da408ee6afb9a37",
"examples/220584/mccode.h5": "md5:5d82b18156c3675a986ec2c02d96a45c",
"examples/220585/mccode.h5": "md5:09540bd8ccea696232b1fdaac978cb29",
# Ground truth reflectivity curves
"examples/NiTiML.ref": "md5:9769b884dfa09d34b6ae449b640463a1",
"examples/Si-SiO2.ref": "md5:436e2312e137b63bf31cc39064d28864",
"examples/Si-Ni.ref": "md5:76fcfc655635086060387163c9175ab4",
# Spin flip example from McStas simulation.
# All runs have the same sample rotation angle but different samples.
# Each sample is measured using all four flipper setting.
"spin_flip_example/ground_truth_spin_down_reflectivity.h5": "md5:1b3f4c70be6e2d5bae35836c378a0762", # noqa: E501
"spin_flip_example/ground_truth_spin_up_reflectivity.h5": "md5:77ded33407a5004587e475ede0312424", # noqa: E501
"spin_flip_example/spin_flip_sample_onon.h5": "md5:da3a075869d4b5525f58c317c914059d", # noqa: E501
"spin_flip_example/spin_flip_sample_offon.h5": "md5:7382118990012204c6f1d0419b23c68b", # noqa: E501
"spin_flip_example/magnetic_supermirror_2_offoff.h5": "md5:c2176171d227e58dc0fbf2e81385b1cc", # noqa: E501
"spin_flip_example/magnetic_supermirror_onon.h5": "md5:bdc4beaca386acda53afdae361a815d9", # noqa: E501
"spin_flip_example/supermirror_offon.h5": "md5:88caf8839cc3ea06589a41a63847dc1e", # noqa: E501
"spin_flip_example/magnetic_supermirror_onoff.h5": "md5:3e2dda52e536f1a00c7a26f30d0ed63f", # noqa: E501
"spin_flip_example/magnetic_supermirror_2_onon.h5": "md5:670df3ed849239208f2b47512c9f6fa1", # noqa: E501
"spin_flip_example/magnetic_supermirror_2_offon.h5": "md5:6017dc15ed7ab37265d1376aec4fa76e", # noqa: E501
"spin_flip_example/magnetic_supermirror_offoff.h5": "md5:1a992b7e74d5e5be3267674ea22f5b1c", # noqa: E501
"spin_flip_example/supermirror_onon.h5": "md5:05929e088691601210a5fdc068375b59",
"spin_flip_example/spin_flip_sample_offoff.h5": "md5:249024737f59c83e28efe9633a3b6b73", # noqa: E501
"spin_flip_example/spin_flip_sample_onoff.h5": "md5:897ce7e94c748a2bb9eb44b4dc9f023a", # noqa: E501
"spin_flip_example/magnetic_supermirror_2_onoff.h5": "md5:11dcd560b1d90b0dde699a55b2998d15", # noqa: E501
"spin_flip_example/magnetic_supermirror_offon.h5": "md5:f2e06c989c347e8e1f32e3f2a48580ce", # noqa: E501
"spin_flip_example/supermirror_onoff.h5": "md5:3ae9863d13d79c24e29017948bd383ab", # noqa: E501
"spin_flip_example/supermirror_offoff.h5": "md5:22bc20099b2f456e459391189ee60977", # noqa: E501
"estia-tof-lookup-table-pulse-stride-1.h5": "md5:696953c772209fadc9c4a2ca619cf04d", # noqa: E501
},
)
[docs]
def estia_mcstas_reference_run() -> Filename[ReferenceRun]:
return Filename[ReferenceRun](
_registry.get_path("218610_tof_detector_list.p.x.y.t.L.sx.sy")
)
[docs]
def estia_mcstas_sample_run(number: int | str) -> Filename[SampleRun]:
return Filename[SampleRun](
_registry.get_path(f"2186{int(number):02d}_tof_detector_list.p.x.y.t.L.sx.sy")
)
[docs]
def estia_mcstas_example(name):
"""Returns a list of McStas files associated with the sample."""
if name == 'reference':
return _registry.get_path("examples/220573/mccode.h5")
elif name == 'Ni/Ti-multilayer':
return list(
map(
_registry.get_path,
[f"examples/2205{i}/mccode.h5" for i in range(74, 78)],
)
)
elif name == 'Ni-film on silicon':
return list(
map(
_registry.get_path,
[f"examples/2205{i}/mccode.h5" for i in range(78, 82)],
)
)
elif name == 'Natural SiO2 on silicon':
return list(
map(
_registry.get_path,
[f"examples/2205{i}/mccode.h5" for i in range(82, 86)],
)
)
raise ValueError(f'"{name}" is not a valid sample name')
[docs]
def estia_mcstas_groundtruth(name):
"""Returns the ground truth reflectivity curve for the sample."""
def parse(fname):
ds = sc.io.load_csv(fname, sep=' ')
if len(ds.keys()) == 3:
_, Qcol, Rcol = ds.keys()
else:
Qcol, Rcol = ds.keys()
return sc.DataArray(
sc.array(dims='Q', values=ds[Rcol].values),
coords={
'Q': sc.array(dims='Q', values=[0, *ds[Qcol].values], unit='1/angstrom')
},
)
if name == 'Ni/Ti-multilayer':
return parse(_registry.get_path("examples/NiTiML.ref"))
elif name == 'Ni-film on silicon':
return parse(_registry.get_path("examples/Si-Ni.ref"))
elif name == 'Natural SiO2 on silicon':
return parse(_registry.get_path("examples/Si-SiO2.ref"))
raise ValueError(f'"{name}" is not a valid sample name')
[docs]
def estia_mcstas_spin_flip_example(sample, flipper_setting):
return _registry.get_path(f'spin_flip_example/{sample}_{flipper_setting}.h5')
[docs]
def estia_mcstas_spin_flip_example_groundtruth(up_or_down):
if up_or_down == 'down':
return _registry.get_path(
'spin_flip_example/ground_truth_spin_down_reflectivity.h5'
)
if up_or_down == 'up':
return _registry.get_path(
'spin_flip_example/ground_truth_spin_up_reflectivity.h5'
)
raise ValueError(f'Ground truth curve for spin state "{up_or_down}" does not exist')
def _refresh_cache(args):
estia_mcstas_spin_flip_example(*args)
[docs]
def estia_mcstas_spin_flip_example_download_all_to_cache():
# Run once to create the folder structure without conflicts
_refresh_cache(('supermirror', 'offoff'))
with ThreadPool(20) as pool:
for _ in pool.map(
_refresh_cache,
[
(sample, setting)
for sample in (
'supermirror',
'magnetic_supermirror',
'magnetic_supermirror_2',
'spin_flip_sample',
)
for setting in ('offoff', 'offon', 'onoff', 'onon')
],
):
pass
[docs]
def estia_tof_lookup_table():
return _registry.get_path('estia-tof-lookup-table-pulse-stride-1.h5')
__all__ = [
"estia_mcstas_example",
"estia_mcstas_reference_run",
"estia_mcstas_sample_run",
"estia_mcstas_spin_flip_example",
"estia_mcstas_spin_flip_example_download_all_to_cache",
"estia_mcstas_spin_flip_example_groundtruth",
]