essdiffraction 23.12.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ess/diffraction/__init__.py +56 -0
- ess/diffraction/correction.py +125 -0
- ess/diffraction/external/__init__.py +141 -0
- ess/diffraction/external/powgen/__init__.py +23 -0
- ess/diffraction/external/powgen/beamline.py +65 -0
- ess/diffraction/external/powgen/data.py +159 -0
- ess/diffraction/external/powgen/instrument_view.py +42 -0
- ess/diffraction/external/powgen/types.py +19 -0
- ess/diffraction/filtering.py +126 -0
- ess/diffraction/grouping.py +81 -0
- ess/diffraction/logging.py +15 -0
- ess/diffraction/powder/__init__.py +14 -0
- ess/diffraction/powder/conversion.py +157 -0
- ess/diffraction/powder/correction.py +46 -0
- ess/diffraction/py.typed +0 -0
- ess/diffraction/smoothing.py +87 -0
- ess/diffraction/types.py +117 -0
- ess/diffraction/uncertainty.py +18 -0
- ess/dream/__init__.py +23 -0
- ess/dream/data.py +34 -0
- ess/dream/io.py +133 -0
- essdiffraction-23.12.0.dist-info/LICENSE +29 -0
- essdiffraction-23.12.0.dist-info/METADATA +77 -0
- essdiffraction-23.12.0.dist-info/RECORD +26 -0
- essdiffraction-23.12.0.dist-info/WHEEL +5 -0
- essdiffraction-23.12.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Components for diffraction experiments (powder and single crystal).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import importlib.metadata
|
|
9
|
+
|
|
10
|
+
from . import uncertainty
|
|
11
|
+
from .correction import (
|
|
12
|
+
normalize_by_monitor,
|
|
13
|
+
normalize_by_proton_charge,
|
|
14
|
+
normalize_by_vanadium,
|
|
15
|
+
)
|
|
16
|
+
from .correction import providers as correction_providers
|
|
17
|
+
from .filtering import crop_tof, filter_events
|
|
18
|
+
from .filtering import providers as filtering_providers
|
|
19
|
+
from .filtering import remove_bad_pulses
|
|
20
|
+
from .grouping import finalize_histogram, group_by_two_theta, merge_all_pixels
|
|
21
|
+
from .grouping import providers as grouping_providers
|
|
22
|
+
from .smoothing import lowpass
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
__version__ = importlib.metadata.version(__package__ or __name__)
|
|
26
|
+
except importlib.metadata.PackageNotFoundError:
|
|
27
|
+
__version__ = "0.0.0"
|
|
28
|
+
|
|
29
|
+
del importlib
|
|
30
|
+
|
|
31
|
+
providers = (
|
|
32
|
+
*correction_providers,
|
|
33
|
+
*filtering_providers,
|
|
34
|
+
*grouping_providers,
|
|
35
|
+
*uncertainty.providers,
|
|
36
|
+
)
|
|
37
|
+
"""Sciline providers for setting up a diffraction pipeline.
|
|
38
|
+
|
|
39
|
+
These implement basic diffraction data-reduction functionality and need to be
|
|
40
|
+
extended with instrument-specific and sub-technique-specific providers.
|
|
41
|
+
"""
|
|
42
|
+
del correction_providers, filtering_providers, grouping_providers
|
|
43
|
+
|
|
44
|
+
__all__ = [
|
|
45
|
+
'crop_tof',
|
|
46
|
+
'filter_events',
|
|
47
|
+
'finalize_histogram',
|
|
48
|
+
'group_by_two_theta',
|
|
49
|
+
'lowpass',
|
|
50
|
+
'merge_all_pixels',
|
|
51
|
+
'normalize_by_monitor',
|
|
52
|
+
'normalize_by_proton_charge',
|
|
53
|
+
'normalize_by_vanadium',
|
|
54
|
+
'remove_bad_pulses',
|
|
55
|
+
'uncertainty',
|
|
56
|
+
]
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
|
|
5
|
+
import scipp as sc
|
|
6
|
+
from scippneutron.conversion.graph import beamline, tof
|
|
7
|
+
|
|
8
|
+
from .logging import get_logger
|
|
9
|
+
from .smoothing import lowpass
|
|
10
|
+
from .types import (
|
|
11
|
+
AccumulatedProtonCharge,
|
|
12
|
+
DspacingBins,
|
|
13
|
+
FilteredData,
|
|
14
|
+
FocussedData,
|
|
15
|
+
NormalizedByProtonCharge,
|
|
16
|
+
NormalizedByVanadium,
|
|
17
|
+
RunType,
|
|
18
|
+
SampleRun,
|
|
19
|
+
VanadiumRun,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def normalize_by_monitor(
|
|
24
|
+
data: sc.DataArray,
|
|
25
|
+
*,
|
|
26
|
+
monitor: sc.DataArray,
|
|
27
|
+
wavelength_edges: Optional[sc.Variable] = None,
|
|
28
|
+
smooth_args: Optional[Dict[str, Any]] = None,
|
|
29
|
+
) -> sc.DataArray:
|
|
30
|
+
"""
|
|
31
|
+
Normalize event data by a monitor.
|
|
32
|
+
|
|
33
|
+
The input is converted to wavelength if it does not already contain wavelengths.
|
|
34
|
+
|
|
35
|
+
Parameters
|
|
36
|
+
----------
|
|
37
|
+
data:
|
|
38
|
+
Input event data.
|
|
39
|
+
monitor:
|
|
40
|
+
A histogrammed monitor.
|
|
41
|
+
wavelength_edges:
|
|
42
|
+
If given, rebin the monitor with these edges.
|
|
43
|
+
smooth_args:
|
|
44
|
+
If given, the monitor histogram is smoothed with
|
|
45
|
+
:func:`ess.diffraction.lowpass` before dividing into `data`.
|
|
46
|
+
`smooth_args` is passed as keyword arguments to
|
|
47
|
+
:func:`ess.diffraction.lowpass`. If ``None``, the monitor is not smoothed.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
:
|
|
52
|
+
`data` normalized by a monitor.
|
|
53
|
+
"""
|
|
54
|
+
if 'wavelength' not in monitor.coords:
|
|
55
|
+
monitor = monitor.transform_coords(
|
|
56
|
+
'wavelength',
|
|
57
|
+
graph={**beamline.beamline(scatter=False), **tof.elastic("tof")},
|
|
58
|
+
keep_inputs=False,
|
|
59
|
+
keep_intermediate=False,
|
|
60
|
+
keep_aliases=False,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
if wavelength_edges is not None:
|
|
64
|
+
monitor = monitor.rebin(wavelength=wavelength_edges)
|
|
65
|
+
if smooth_args is not None:
|
|
66
|
+
get_logger().info(
|
|
67
|
+
"Smoothing monitor for normalization using "
|
|
68
|
+
"ess.diffraction.smoothing.lowpass with %s.",
|
|
69
|
+
smooth_args,
|
|
70
|
+
)
|
|
71
|
+
monitor = lowpass(monitor, dim='wavelength', **smooth_args)
|
|
72
|
+
return data.bins / sc.lookup(func=monitor, dim='wavelength')
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def normalize_by_vanadium(
|
|
76
|
+
data: FocussedData[SampleRun],
|
|
77
|
+
vanadium: FocussedData[VanadiumRun],
|
|
78
|
+
edges: DspacingBins,
|
|
79
|
+
) -> NormalizedByVanadium:
|
|
80
|
+
"""
|
|
81
|
+
Normalize sample data by a vanadium measurement.
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
data:
|
|
86
|
+
Sample data.
|
|
87
|
+
vanadium:
|
|
88
|
+
Vanadium data.
|
|
89
|
+
edges:
|
|
90
|
+
`vanadium` is histogrammed into these bins before dividing the data by it.
|
|
91
|
+
|
|
92
|
+
Returns
|
|
93
|
+
-------
|
|
94
|
+
:
|
|
95
|
+
`data` normalized by `vanadium`.
|
|
96
|
+
"""
|
|
97
|
+
norm = sc.lookup(vanadium.hist({edges.dim: edges}), dim=edges.dim)
|
|
98
|
+
# Converting to unit 'one' because the division might produce a unit
|
|
99
|
+
# with a large scale if the proton charges in data and vanadium were
|
|
100
|
+
# measured with different units.
|
|
101
|
+
return (data.bins / norm).to(unit='one', copy=False)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def normalize_by_proton_charge(
|
|
105
|
+
data: FilteredData[RunType], proton_charge: AccumulatedProtonCharge[RunType]
|
|
106
|
+
) -> NormalizedByProtonCharge[RunType]:
|
|
107
|
+
"""Normalize data by an accumulated proton charge.
|
|
108
|
+
|
|
109
|
+
Parameters
|
|
110
|
+
----------
|
|
111
|
+
data:
|
|
112
|
+
Un-normalized data array as events or a histogram.
|
|
113
|
+
proton_charge:
|
|
114
|
+
Accumulated proton charge over the entire run.
|
|
115
|
+
|
|
116
|
+
Returns
|
|
117
|
+
-------
|
|
118
|
+
:
|
|
119
|
+
``data / proton_charge``
|
|
120
|
+
"""
|
|
121
|
+
return NormalizedByProtonCharge[RunType](data / proton_charge)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
providers = (normalize_by_proton_charge, normalize_by_vanadium)
|
|
125
|
+
"""Sciline providers for diffraction corrections."""
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
|
|
3
|
+
"""
|
|
4
|
+
Components for non-ESS diffraction experiments.
|
|
5
|
+
|
|
6
|
+
WARNING This package will be removed in the future!
|
|
7
|
+
It only serves as helpers to develop workflows until it is determined,
|
|
8
|
+
which mechanisms and interfaces will be used at ESS.
|
|
9
|
+
"""
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Dict, Optional, Union
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
import scipp as sc
|
|
15
|
+
import scippneutron as scn
|
|
16
|
+
|
|
17
|
+
from ..logging import get_logger
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _as_boolean_mask(var: sc.Variable) -> sc.Variable:
|
|
21
|
+
if var.dtype in ('float32', 'float64'):
|
|
22
|
+
if sc.any(var != var.to(dtype='int64')).value:
|
|
23
|
+
raise ValueError(
|
|
24
|
+
'Cannot construct boolean mask, the input mask has fractional values.'
|
|
25
|
+
)
|
|
26
|
+
return var.to(dtype=bool)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _parse_calibration_instrument_args(
|
|
30
|
+
filename: Union[str, Path],
|
|
31
|
+
*,
|
|
32
|
+
instrument_filename: Optional[str] = None,
|
|
33
|
+
instrument_name: Optional[str] = None,
|
|
34
|
+
) -> Dict[str, str]:
|
|
35
|
+
if instrument_filename is not None:
|
|
36
|
+
if instrument_name is not None:
|
|
37
|
+
raise ValueError(
|
|
38
|
+
'Only one argument of `instrument_name` and '
|
|
39
|
+
'`instrument_filename` is allowed, got both.'
|
|
40
|
+
)
|
|
41
|
+
instrument_arg = {'InstrumentFilename': instrument_filename}
|
|
42
|
+
instrument_message = f'with instrument file {instrument_filename}'
|
|
43
|
+
else:
|
|
44
|
+
if instrument_name is None:
|
|
45
|
+
raise ValueError(
|
|
46
|
+
'Need one argument of `instrument_name` and '
|
|
47
|
+
'`instrument_filename` is allowed, got neither.'
|
|
48
|
+
)
|
|
49
|
+
instrument_arg = {'InstrumentName': instrument_name}
|
|
50
|
+
instrument_message = f'with instrument {instrument_name}'
|
|
51
|
+
|
|
52
|
+
get_logger().info(
|
|
53
|
+
'Loading calibration from file %s %s', filename, instrument_message
|
|
54
|
+
)
|
|
55
|
+
return instrument_arg
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def load_calibration(
|
|
59
|
+
filename: Union[str, Path],
|
|
60
|
+
*,
|
|
61
|
+
instrument_filename: Optional[str] = None,
|
|
62
|
+
instrument_name: Optional[str] = None,
|
|
63
|
+
mantid_args: Optional[dict] = None,
|
|
64
|
+
) -> sc.Dataset:
|
|
65
|
+
"""
|
|
66
|
+
Load and return calibration data.
|
|
67
|
+
|
|
68
|
+
Warning
|
|
69
|
+
-------
|
|
70
|
+
This function is designed to work with calibration files used by Mantid,
|
|
71
|
+
specifically for POWGEN. It does not represent the interface used at ESS
|
|
72
|
+
and will be removed in the future.
|
|
73
|
+
|
|
74
|
+
Uses the Mantid algorithm `LoadDiffCal
|
|
75
|
+
<https://docs.mantidproject.org/nightly/algorithms/LoadDiffCal-v1.html>`_
|
|
76
|
+
and stores the data in a :class:`scipp.Dataset`
|
|
77
|
+
|
|
78
|
+
Note that this function requires mantid to be installed and available in
|
|
79
|
+
the same Python environment as ess.
|
|
80
|
+
|
|
81
|
+
Parameters
|
|
82
|
+
----------
|
|
83
|
+
filename:
|
|
84
|
+
The name of the calibration file to load.
|
|
85
|
+
instrument_filename:
|
|
86
|
+
Instrument definition file.
|
|
87
|
+
instrument_name:
|
|
88
|
+
Name of the instrument.
|
|
89
|
+
mantid_args:
|
|
90
|
+
Dictionary with additional arguments for the
|
|
91
|
+
`LoadDiffCal` Mantid algorithm.
|
|
92
|
+
|
|
93
|
+
Returns
|
|
94
|
+
-------
|
|
95
|
+
:
|
|
96
|
+
A Dataset containing the calibration data and masking.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
mantid_args = {} if mantid_args is None else mantid_args
|
|
100
|
+
mantid_args.update(
|
|
101
|
+
_parse_calibration_instrument_args(
|
|
102
|
+
filename,
|
|
103
|
+
instrument_filename=instrument_filename,
|
|
104
|
+
instrument_name=instrument_name,
|
|
105
|
+
)
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
with scn.mantid.run_mantid_alg(
|
|
109
|
+
'LoadDiffCal',
|
|
110
|
+
Filename=str(filename),
|
|
111
|
+
MakeGroupingWorkspace=False,
|
|
112
|
+
**mantid_args,
|
|
113
|
+
) as ws:
|
|
114
|
+
ds = scn.from_mantid(ws.OutputCalWorkspace)
|
|
115
|
+
mask_ws = ws.OutputMaskWorkspace
|
|
116
|
+
rows = mask_ws.getNumberHistograms()
|
|
117
|
+
mask = sc.array(
|
|
118
|
+
dims=['row'],
|
|
119
|
+
values=np.fromiter(
|
|
120
|
+
(mask_ws.readY(i)[0] for i in range(rows)), count=rows, dtype=np.bool_
|
|
121
|
+
),
|
|
122
|
+
unit=None,
|
|
123
|
+
)
|
|
124
|
+
# This is deliberately not stored as a mask since that would make
|
|
125
|
+
# subsequent handling, e.g., with groupby, more complicated. The mask
|
|
126
|
+
# is conceptually not masking rows in this table, i.e., it is not
|
|
127
|
+
# marking invalid rows, but rather describes masking for other data.
|
|
128
|
+
ds["mask"] = _as_boolean_mask(mask)
|
|
129
|
+
|
|
130
|
+
# The file does not define units
|
|
131
|
+
# TODO why those units? Can we verify?
|
|
132
|
+
ds["difc"].unit = 'us / angstrom'
|
|
133
|
+
ds["difa"].unit = 'us / angstrom**2'
|
|
134
|
+
ds["tzero"].unit = 'us'
|
|
135
|
+
|
|
136
|
+
ds = ds.rename_dims({'row': 'detector'})
|
|
137
|
+
ds.coords['detector'] = ds['detid'].data
|
|
138
|
+
ds.coords['detector'].unit = None
|
|
139
|
+
del ds['detid']
|
|
140
|
+
|
|
141
|
+
return ds
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
|
|
3
|
+
"""
|
|
4
|
+
Functions and classes for the POWGEN instrument.
|
|
5
|
+
|
|
6
|
+
Note that this module is temporary and will be removed in favor of
|
|
7
|
+
the ``dream`` module when that is available.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from . import beamline, data
|
|
11
|
+
from .instrument_view import instrument_view
|
|
12
|
+
|
|
13
|
+
providers = (
|
|
14
|
+
*beamline.providers,
|
|
15
|
+
*data.providers,
|
|
16
|
+
)
|
|
17
|
+
"""Sciline Providers for POWGEN-specific functionality."""
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
'beamline',
|
|
21
|
+
'data',
|
|
22
|
+
'instrument_view',
|
|
23
|
+
]
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
|
|
3
|
+
"""
|
|
4
|
+
Beamline parameters and utilities for POWGEN.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import scipp as sc
|
|
8
|
+
|
|
9
|
+
from ...types import CalibrationData, RawCalibrationData
|
|
10
|
+
from .types import DetectorInfo
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def map_detector_to_spectrum(
|
|
14
|
+
data: sc.Dataset, *, detector_info: sc.Dataset
|
|
15
|
+
) -> sc.Dataset:
|
|
16
|
+
"""
|
|
17
|
+
Transform 'detector' coords to 'spectrum'.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
data:
|
|
22
|
+
Input data whose 'detector' coord is transformed.
|
|
23
|
+
detector_info:
|
|
24
|
+
Defines mapping from detector numbers to spectra.
|
|
25
|
+
|
|
26
|
+
Returns
|
|
27
|
+
-------
|
|
28
|
+
:
|
|
29
|
+
`data` with 'detector' coord and dim replaced by 'spectrum'.
|
|
30
|
+
"""
|
|
31
|
+
if not sc.identical(
|
|
32
|
+
data.coords['detector'].to(
|
|
33
|
+
dtype=detector_info.coords['detector'].dtype, copy=False
|
|
34
|
+
),
|
|
35
|
+
detector_info.coords['detector'],
|
|
36
|
+
):
|
|
37
|
+
raise sc.CoordError(
|
|
38
|
+
"The 'detector' coords of `data` and `detector_info` do not match."
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
out = data.copy(deep=False)
|
|
42
|
+
del out.coords['detector']
|
|
43
|
+
# Add 1 because spectrum numbers in the data start at 1 but
|
|
44
|
+
# detector_info contains spectrum indices which start at 0.
|
|
45
|
+
out.coords['spectrum'] = detector_info.coords['spectrum'] + sc.index(
|
|
46
|
+
1, dtype=detector_info.coords['spectrum'].dtype
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
return out.rename_dims({'detector': 'spectrum'})
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def preprocess_calibration_data(
|
|
53
|
+
data: RawCalibrationData, detector_info: DetectorInfo
|
|
54
|
+
) -> CalibrationData:
|
|
55
|
+
"""Convert calibration data to a format that can be used by Scipp.
|
|
56
|
+
|
|
57
|
+
The raw calibration data is encoded in terms of a `'detector'` coordinate.
|
|
58
|
+
This needs to be converted to a `'spectrum'` coordinate to align
|
|
59
|
+
if with sample data.
|
|
60
|
+
"""
|
|
61
|
+
return CalibrationData(map_detector_to_spectrum(data, detector_info=detector_info))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
providers = (preprocess_calibration_data,)
|
|
65
|
+
"""Sciline providers for POWGEN beamline processing."""
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
|
|
3
|
+
|
|
4
|
+
"""Utilities for loading example data for POWGEN."""
|
|
5
|
+
|
|
6
|
+
import scipp as sc
|
|
7
|
+
|
|
8
|
+
from ...types import (
|
|
9
|
+
AccumulatedProtonCharge,
|
|
10
|
+
CalibrationFilename,
|
|
11
|
+
Filename,
|
|
12
|
+
ProtonCharge,
|
|
13
|
+
RawCalibrationData,
|
|
14
|
+
RawData,
|
|
15
|
+
RawDataAndMetadata,
|
|
16
|
+
RawDataWithVariances,
|
|
17
|
+
RunType,
|
|
18
|
+
SampleRun,
|
|
19
|
+
VanadiumRun,
|
|
20
|
+
)
|
|
21
|
+
from .types import DetectorInfo
|
|
22
|
+
|
|
23
|
+
_version = '1'
|
|
24
|
+
|
|
25
|
+
__all__ = ['get_path']
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _make_pooch():
|
|
29
|
+
import pooch
|
|
30
|
+
|
|
31
|
+
return pooch.create(
|
|
32
|
+
path=pooch.os_cache('ess/powgen'),
|
|
33
|
+
env='ESS_DATA_DIR',
|
|
34
|
+
base_url='https://public.esss.dk/groups/scipp/ess/powgen/{version}/',
|
|
35
|
+
version=_version,
|
|
36
|
+
registry={
|
|
37
|
+
# Files loadable with Mantid
|
|
38
|
+
'PG3_4844_event.nxs': 'md5:d5ae38871d0a09a28ae01f85d969de1e',
|
|
39
|
+
'PG3_4866_event.nxs': 'md5:3d543bc6a646e622b3f4542bc3435e7e',
|
|
40
|
+
'PG3_5226_event.nxs': 'md5:58b386ebdfeb728d34fd3ba00a2d4f1e',
|
|
41
|
+
'PG3_FERNS_d4832_2011_08_24.cal': 'md5:c181221ebef9fcf30114954268c7a6b6',
|
|
42
|
+
# Zipped Scipp HDF5 files
|
|
43
|
+
'PG3_4844_event.zip': 'md5:a644c74f5e740385469b67431b690a3e',
|
|
44
|
+
'PG3_4866_event.zip': 'md5:5bc49def987f0faeb212a406b92b548e',
|
|
45
|
+
'PG3_FERNS_d4832_2011_08_24.zip': 'md5:0fef4ed5f61465eaaa3f87a18f5bb80d',
|
|
46
|
+
},
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
_pooch = _make_pooch()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def get_path(name: str, unzip: bool = False) -> str:
|
|
54
|
+
"""
|
|
55
|
+
Return the path to a data file bundled with scippneutron.
|
|
56
|
+
|
|
57
|
+
This function only works with example data and cannot handle
|
|
58
|
+
paths to custom files.
|
|
59
|
+
"""
|
|
60
|
+
import pooch
|
|
61
|
+
|
|
62
|
+
return _pooch.fetch(name, processor=pooch.Unzip() if unzip else None)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def mantid_sample_file() -> str:
|
|
66
|
+
return get_path('PG3_4844_event.nxs')
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def mantid_vanadium_file() -> str:
|
|
70
|
+
return get_path('PG3_4866_event.nxs')
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def mantid_empty_instrument_file() -> str:
|
|
74
|
+
return get_path('PG3_5226_event.nxs')
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def mantid_calibration_file() -> str:
|
|
78
|
+
return get_path('PG3_FERNS_d4832_2011_08_24.cal')
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def sample_file() -> str:
|
|
82
|
+
(path,) = get_path('PG3_4844_event.zip', unzip=True)
|
|
83
|
+
return path
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def vanadium_file() -> str:
|
|
87
|
+
(path,) = get_path('PG3_4866_event.zip', unzip=True)
|
|
88
|
+
return path
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def calibration_file() -> str:
|
|
92
|
+
(path,) = get_path('PG3_FERNS_d4832_2011_08_24.zip', unzip=True)
|
|
93
|
+
return path
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def pooch_load(filename: Filename[RunType]) -> RawDataAndMetadata[RunType]:
|
|
97
|
+
"""Load a file with pooch.
|
|
98
|
+
|
|
99
|
+
If the file is a zip archive, it is extracted and a path to the contained
|
|
100
|
+
file is returned.
|
|
101
|
+
|
|
102
|
+
The loaded data holds both the events and any metadata from the file.
|
|
103
|
+
"""
|
|
104
|
+
if filename.endswith('.zip'):
|
|
105
|
+
(path,) = get_path(filename, unzip=True)
|
|
106
|
+
else:
|
|
107
|
+
path = get_path(filename)
|
|
108
|
+
return RawDataAndMetadata[RunType](sc.io.load_hdf5(path))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def pooch_load_calibration(filename: CalibrationFilename) -> RawCalibrationData:
|
|
112
|
+
"""Load the calibration data for the POWGEN test data."""
|
|
113
|
+
if filename.endswith('.zip'):
|
|
114
|
+
(path,) = get_path(filename, unzip=True)
|
|
115
|
+
else:
|
|
116
|
+
path = get_path(filename)
|
|
117
|
+
return RawCalibrationData(sc.io.load_hdf5(path))
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
# This can be generalized with https://github.com/scipp/sciline/issues/69.
|
|
121
|
+
def extract_raw_data_sample(dg: RawDataAndMetadata[SampleRun]) -> RawData[SampleRun]:
|
|
122
|
+
"""Return the events from a loaded data group."""
|
|
123
|
+
return RawData[SampleRun](dg['data'])
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def extract_raw_data_vanadium(
|
|
127
|
+
dg: RawDataAndMetadata[VanadiumRun],
|
|
128
|
+
) -> RawDataWithVariances[VanadiumRun]:
|
|
129
|
+
"""Return the events from a loaded data group."""
|
|
130
|
+
return RawDataWithVariances[VanadiumRun](dg['data'])
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def extract_detector_info(dg: RawDataAndMetadata[SampleRun]) -> DetectorInfo:
|
|
134
|
+
"""Return the detector info from a loaded data group."""
|
|
135
|
+
return DetectorInfo(dg['detector_info'])
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def extract_proton_charge(dg: RawDataAndMetadata[RunType]) -> ProtonCharge[RunType]:
|
|
139
|
+
"""Return the proton charge from a loaded data group."""
|
|
140
|
+
return ProtonCharge[RunType](dg['proton_charge'])
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def extract_accumulated_proton_charge(
|
|
144
|
+
data: RawData[RunType],
|
|
145
|
+
) -> AccumulatedProtonCharge[RunType]:
|
|
146
|
+
"""Return the stored accumulated proton charge from a loaded data group."""
|
|
147
|
+
return AccumulatedProtonCharge[RunType](data.coords['gd_prtn_chrg'])
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
providers = (
|
|
151
|
+
pooch_load,
|
|
152
|
+
pooch_load_calibration,
|
|
153
|
+
extract_accumulated_proton_charge,
|
|
154
|
+
extract_detector_info,
|
|
155
|
+
extract_proton_charge,
|
|
156
|
+
extract_raw_data_sample,
|
|
157
|
+
extract_raw_data_vanadium,
|
|
158
|
+
)
|
|
159
|
+
"""Sciline Providers for loading POWGEN data."""
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import scipp as sc
|
|
6
|
+
import scippneutron as scn
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def instrument_view(
|
|
10
|
+
da: sc.DataArray,
|
|
11
|
+
positions: str = "position",
|
|
12
|
+
pixel_size: Optional[float] = None,
|
|
13
|
+
components: Optional[dict] = None,
|
|
14
|
+
**kwargs,
|
|
15
|
+
):
|
|
16
|
+
"""
|
|
17
|
+
Instrument view for the POWGEN instrument, with adjusted default arguments.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
positions:
|
|
22
|
+
Key for coord holding positions to use for pixels
|
|
23
|
+
pixel_size:
|
|
24
|
+
Custom pixel size to use for detector pixels
|
|
25
|
+
components:
|
|
26
|
+
Dictionary containing display names and corresponding
|
|
27
|
+
settings (also a Dictionary) for additional components to display
|
|
28
|
+
items with known positions to be shown
|
|
29
|
+
kwargs:
|
|
30
|
+
See :func:`scippneutron.instrument_view`
|
|
31
|
+
"""
|
|
32
|
+
# TODO: the camera argument does not work with the Plopp instrument view
|
|
33
|
+
# if 'camera' not in kwargs:
|
|
34
|
+
# kwargs = {
|
|
35
|
+
# **kwargs, 'camera': {
|
|
36
|
+
# 'position': sc.vector(value=[-3, 3, 3],
|
|
37
|
+
# unit=da.coords[positions].unit)
|
|
38
|
+
# }
|
|
39
|
+
# }
|
|
40
|
+
return scn.instrument_view(
|
|
41
|
+
da, positions=positions, components=components, pixel_size=pixel_size, **kwargs
|
|
42
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
|
|
3
|
+
|
|
4
|
+
"""This module defines the domain types used by POWGEN.
|
|
5
|
+
|
|
6
|
+
The domain types are used to define parameters and to request results from a Sciline
|
|
7
|
+
pipeline.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import NewType
|
|
11
|
+
|
|
12
|
+
import scipp as sc
|
|
13
|
+
|
|
14
|
+
# This is Mantid-specific and can probably be removed when the POWGEN
|
|
15
|
+
# workflow is removed.
|
|
16
|
+
DetectorInfo = NewType('DetectorInfo', sc.Dataset)
|
|
17
|
+
"""Mapping between detector numbers and spectra."""
|
|
18
|
+
|
|
19
|
+
del sc, NewType
|