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.
@@ -0,0 +1,126 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+ # Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
3
+ # @author Jan-Lukas Wynen
4
+ """
5
+ Prototype for event filtering.
6
+
7
+ IMPORTANT Will be moved to a different place and potentially modified.
8
+ """
9
+ from contextlib import contextmanager
10
+ from numbers import Real
11
+
12
+ import scipp as sc
13
+
14
+ from .types import FilteredData, RawData, RunType, TofCroppedData, ValidTofRange
15
+
16
+
17
+ def _equivalent_bin_indices(a, b) -> bool:
18
+ a_begin = a.bins.constituents['begin'].flatten(to='')
19
+ a_end = a.bins.constituents['end'].flatten(to='')
20
+ b_begin = b.bins.constituents['begin'].flatten(to='')
21
+ b_end = b.bins.constituents['end'].flatten(to='')
22
+ non_empty = a_begin != a_end
23
+ return (
24
+ sc.all((a_begin == b_begin)[non_empty]).value
25
+ and sc.all((a_end == b_end)[non_empty]).value
26
+ )
27
+
28
+
29
+ @contextmanager
30
+ def _temporary_bin_coord(data: sc.DataArray, name: str, coord: sc.Variable) -> None:
31
+ if not _equivalent_bin_indices(data, coord):
32
+ raise ValueError("data and coord do not have equivalent bin indices")
33
+ coord = sc.bins(
34
+ data=coord.bins.constituents['data'],
35
+ begin=data.bins.coords['pulse_time'].bins.constituents['begin'],
36
+ end=data.bins.coords['pulse_time'].bins.constituents['end'],
37
+ dim=coord.bins.constituents['dim'],
38
+ )
39
+ data.bins.coords[name] = coord
40
+ yield
41
+ del data.bins.coords[name]
42
+
43
+
44
+ # TODO non-monotonic proton charge -> raise?
45
+ def _with_pulse_time_edges(da: sc.DataArray, dim: str) -> sc.DataArray:
46
+ pulse_time = da.coords[dim]
47
+ one = sc.scalar(1, dtype='int64', unit=pulse_time.unit)
48
+ lo = pulse_time[0] - one
49
+ hi = pulse_time[-1] + one
50
+ mid = sc.midpoints(pulse_time)
51
+ da.coords[dim] = sc.concat([lo, mid, hi], dim)
52
+ return da
53
+
54
+
55
+ def remove_bad_pulses(
56
+ data: sc.DataArray, *, proton_charge: sc.DataArray, threshold_factor: Real
57
+ ) -> sc.DataArray:
58
+ """
59
+ assumes that there are bad pulses
60
+ """
61
+ min_charge = proton_charge.data.mean() * threshold_factor
62
+ good_pulse = _with_pulse_time_edges(proton_charge >= min_charge, proton_charge.dim)
63
+ with _temporary_bin_coord(
64
+ data,
65
+ 'good_pulse',
66
+ sc.lookup(good_pulse, good_pulse.dim)[data.bins.coords[good_pulse.dim]],
67
+ ):
68
+ filtered = data.group(sc.array(dims=['good_pulse'], values=[True]))
69
+ filtered = filtered.squeeze('good_pulse').copy(deep=False)
70
+ del filtered.coords['good_pulse']
71
+ return filtered
72
+
73
+
74
+ def crop_tof(
75
+ data: RawData[RunType], tof_range: ValidTofRange
76
+ ) -> TofCroppedData[RunType]:
77
+ """Remove events outside the specified TOF range.
78
+
79
+ Parameters
80
+ ----------
81
+ data:
82
+ Data to be cropped.
83
+ Expected to have a coordinate called `'tof'`.
84
+ tof_range:
85
+ 1d, len-2 variable containing the lower and upper bounds for
86
+ time-of-flight.
87
+
88
+ Returns
89
+ -------
90
+ :
91
+ Cropped data.
92
+ """
93
+ return TofCroppedData[RunType](
94
+ data.bin(tof=tof_range.to(unit=data.coords['tof'].unit))
95
+ )
96
+
97
+
98
+ def filter_events(data: TofCroppedData[RunType]) -> FilteredData[RunType]:
99
+ """Remove bad events.
100
+
101
+ Attention
102
+ ---------
103
+ This function currently does nothing because it is unclear how to filter
104
+ events at ESS.
105
+ In the future, this function will filter out events that
106
+ cannot be used for analysis.
107
+
108
+ Parameters
109
+ ----------
110
+ data:
111
+ Input events to be filtered.
112
+
113
+ Returns
114
+ -------
115
+ :
116
+ `data` with bad events removed.
117
+ """
118
+ # TODO this needs to filter by proton charge once we know how
119
+ return FilteredData[RunType](data)
120
+
121
+
122
+ providers = (
123
+ crop_tof,
124
+ filter_events,
125
+ )
126
+ """Sciline providers for event filtering."""
@@ -0,0 +1,81 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+ # Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
3
+
4
+ from scippneutron.conversion.graph import beamline
5
+
6
+ from .types import (
7
+ DspacingBins,
8
+ DspacingData,
9
+ DspacingHistogram,
10
+ FocussedData,
11
+ NormalizedByVanadium,
12
+ RunType,
13
+ TwoThetaBins,
14
+ )
15
+
16
+
17
+ def group_by_two_theta(
18
+ data: DspacingData[RunType], edges: TwoThetaBins
19
+ ) -> FocussedData[RunType]:
20
+ """
21
+ Group data into two_theta bins.
22
+
23
+ Parameters
24
+ ----------
25
+ data:
26
+ Input data array with events. Must contain a coord called 'two_theta'
27
+ or coords that can be used to compute it.
28
+ edges:
29
+ Bin edges in two_theta. `data` is grouped into those bins.
30
+
31
+ Returns
32
+ -------
33
+ :
34
+ `data` grouped into two_theta bins.
35
+ """
36
+ out = data.transform_coords('two_theta', graph=beamline.beamline(scatter=True))
37
+ return FocussedData[RunType](
38
+ out.bin(two_theta=edges.to(unit=out.coords['two_theta'].unit, copy=False))
39
+ )
40
+
41
+
42
+ def merge_all_pixels(data: DspacingData[RunType]) -> FocussedData[RunType]:
43
+ """Combine all pixels (spectra) of the detector.
44
+
45
+ Parameters
46
+ ----------
47
+ data:
48
+ Input data with a `'spectrum'` dimension.
49
+
50
+ Returns
51
+ -------
52
+ :
53
+ The input without a `'spectrum'` dimension.
54
+ """
55
+ return FocussedData(data.bins.concat('spectrum'))
56
+
57
+
58
+ def finalize_histogram(
59
+ data: NormalizedByVanadium, edges: DspacingBins
60
+ ) -> DspacingHistogram:
61
+ """Finalize the d-spacing histogram.
62
+
63
+ Histograms the input data into the given d-spacing bins.
64
+
65
+ Parameters
66
+ ----------
67
+ data:
68
+ Data to be histogrammed.
69
+ edges:
70
+ Bin edges in d-spacing.
71
+
72
+ Returns
73
+ -------
74
+ :
75
+ Histogrammed data.
76
+ """
77
+ return DspacingHistogram(data.hist(dspacing=edges))
78
+
79
+
80
+ providers = (merge_all_pixels, finalize_histogram)
81
+ """Sciline providers for grouping pixels."""
@@ -0,0 +1,15 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+ # Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
3
+
4
+ import logging
5
+
6
+
7
+ def get_logger() -> logging.Logger:
8
+ """Return the logger for ess.diffraction.
9
+
10
+ Returns
11
+ -------
12
+ :
13
+ The requested logger.
14
+ """
15
+ return logging.getLogger('scipp.ess.diffraction')
@@ -0,0 +1,14 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+ # Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
3
+ """
4
+ Components for powder diffraction experiments.
5
+ """
6
+ from .conversion import providers as conversion_providers
7
+ from .conversion import to_dspacing_with_calibration
8
+ from .correction import merge_calibration
9
+
10
+ providers = (*conversion_providers,)
11
+ """Sciline providers for powder diffraction."""
12
+ del conversion_providers
13
+
14
+ __all__ = ['merge_calibration', 'to_dspacing_with_calibration']
@@ -0,0 +1,157 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+ # Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
3
+ """
4
+ Coordinate transformations for powder diffraction.
5
+ """
6
+
7
+ import uuid
8
+ from typing import Optional
9
+
10
+ import scipp as sc
11
+
12
+ from ..logging import get_logger
13
+ from ..types import CalibrationData, DspacingData, NormalizedByProtonCharge, RunType
14
+ from .correction import merge_calibration
15
+
16
+
17
+ def _dspacing_from_diff_calibration_generic_impl(t, t0, a, c):
18
+ """
19
+ This function implements the solution to
20
+ t = a * d^2 + c * d + t0
21
+ for a != 0.
22
+ It uses the following way of expressing the solution with an order of operations
23
+ that is optimized for low memory usage.
24
+ d = (sqrt([x-t0+t] / x) - 1) * c / (2a)
25
+ x = c^2 / (4a)
26
+ """
27
+ x = c**2 / (4 * a)
28
+ out = (x - t0) + t
29
+ out /= x
30
+ del x
31
+ sc.sqrt(out, out=out)
32
+ out -= 1
33
+ out *= c / (2 * a)
34
+ return out
35
+
36
+
37
+ def _dspacing_from_diff_calibration_a0_impl(t, t0, c):
38
+ """
39
+ This function implements the solution to
40
+ t = a * d^2 + c * d + t0
41
+ for a == 0.
42
+ """
43
+ out = t - t0
44
+ out /= c
45
+ return out
46
+
47
+
48
+ def dspacing_from_diff_calibration(
49
+ tof: sc.Variable,
50
+ tzero: sc.Variable,
51
+ difa: sc.Variable,
52
+ difc: sc.Variable,
53
+ _tag_positions_consumed: sc.Variable,
54
+ ) -> sc.Variable:
55
+ r"""
56
+ Compute d-spacing from calibration parameters.
57
+
58
+ d-spacing is the positive solution of
59
+
60
+ .. math:: \mathsf{tof} = \mathsf{DIFA} * d^2 + \mathsf{DIFC} * d + t_0
61
+
62
+ This function can be used with :func:`scipp.transform_coords`.
63
+
64
+ See Also
65
+ --------
66
+ ess.diffraction.conversions.to_dspacing_with_calibration
67
+ """
68
+ if sc.all(difa == sc.scalar(0.0, unit=difa.unit)).value:
69
+ return _dspacing_from_diff_calibration_a0_impl(tof, tzero, difc)
70
+ return _dspacing_from_diff_calibration_generic_impl(tof, tzero, difa, difc)
71
+
72
+
73
+ def _restore_tof_if_in_wavelength(data: sc.DataArray) -> sc.DataArray:
74
+ if 'wavelength' not in data.dims:
75
+ return data
76
+
77
+ get_logger().info("Discarding coordinate 'wavelength' in favor of 'tof'.")
78
+ temp_name = uuid.uuid4().hex
79
+ aux = data.transform_coords(
80
+ temp_name,
81
+ {temp_name: lambda wavelength, tof: tof},
82
+ keep_inputs=False,
83
+ quiet=True,
84
+ )
85
+ return aux.transform_coords(
86
+ 'tof', {'tof': temp_name}, keep_inputs=False, quiet=True
87
+ )
88
+
89
+
90
+ def _consume_positions(position, sample_position, source_position):
91
+ _ = position
92
+ _ = sample_position
93
+ _ = source_position
94
+ return sc.scalar(0)
95
+
96
+
97
+ def to_dspacing_with_calibration(
98
+ data: NormalizedByProtonCharge[RunType],
99
+ calibration: Optional[CalibrationData] = None,
100
+ ) -> DspacingData[RunType]:
101
+ """
102
+ Transform coordinates to d-spacing from calibration parameters.
103
+
104
+ Computes d-spacing from time-of-flight stored in `data`.
105
+
106
+ Attention
107
+ ---------
108
+ `data` may have a wavelength coordinate and dimension,
109
+ but those are discarded.
110
+ Only the stored time-of-flight is used, that is, any modifications to
111
+ the wavelength coordinate after it was computed from time-of-flight are lost.
112
+
113
+ Raises
114
+ ------
115
+ KeyError
116
+ If `data` does not contain a 'tof' coordinate.
117
+
118
+ Parameters
119
+ ----------
120
+ data:
121
+ Input data in tof or wavelength dimension.
122
+ Must have a tof coordinate.
123
+ calibration:
124
+ Calibration data. If given, use it for the conversion.
125
+ Otherwise, the calibration data must be stored in `data`.
126
+
127
+ Returns
128
+ -------
129
+ :
130
+ A DataArray with the same data as the input and a 'dspacing' coordinate.
131
+
132
+ See Also
133
+ --------
134
+ ess.diffraction.conversions.dspacing_from_diff_calibration
135
+ """
136
+ if calibration is not None:
137
+ out = merge_calibration(into=data, calibration=calibration)
138
+ else:
139
+ out = data
140
+
141
+ out = _restore_tof_if_in_wavelength(out)
142
+ graph = {
143
+ 'dspacing': dspacing_from_diff_calibration,
144
+ }
145
+
146
+ if 'position' in out.coords:
147
+ graph['_tag_positions_consumed'] = _consume_positions
148
+ else:
149
+ out.coords['_tag_positions_consumed'] = sc.scalar(0)
150
+
151
+ out = out.transform_coords('dspacing', graph=graph, keep_intermediate=False)
152
+ out.coords.pop('_tag_positions_consumed', None)
153
+ return DspacingData[RunType](out)
154
+
155
+
156
+ providers = (to_dspacing_with_calibration,)
157
+ """Sciline providers for coordinate transformations."""
@@ -0,0 +1,46 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+ # Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
3
+ import scipp as sc
4
+
5
+
6
+ def merge_calibration(*, into: sc.DataArray, calibration: sc.Dataset) -> sc.DataArray:
7
+ """
8
+ Return a scipp.DataArray containing calibration metadata as coordinates.
9
+
10
+ Parameters
11
+ ----------
12
+ into:
13
+ Base data and metadata for the returned object.
14
+ calibration:
15
+ Calibration parameters.
16
+
17
+ Returns
18
+ -------
19
+ :
20
+ Copy of `into` with additional coordinates and masks
21
+ from `calibration`.
22
+
23
+ See Also
24
+ --------
25
+ ess.diffraction.load_calibration
26
+ """
27
+ dim = calibration.dim
28
+ if not sc.identical(into.coords[dim], calibration.coords[dim]):
29
+ raise ValueError(
30
+ f'Coordinate {dim} of calibration and target dataset do not agree.'
31
+ )
32
+ out = into.copy(deep=False)
33
+ for name in ('difa', 'difc', 'tzero'):
34
+ if name in out.coords:
35
+ raise ValueError(
36
+ f"Cannot add calibration parameter '{name}' to data, "
37
+ "there already is metadata with the same name."
38
+ )
39
+ out.coords[name] = calibration[name].data
40
+ if 'calibration' in out.masks:
41
+ raise ValueError(
42
+ "Cannot add calibration mask 'calibration' tp data, "
43
+ "there already is a mask with the same name."
44
+ )
45
+ out.masks['calibration'] = calibration['mask'].data
46
+ return out
File without changes
@@ -0,0 +1,87 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+ # Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
3
+ """
4
+ Smoothing arrays data.
5
+ """
6
+
7
+ from typing import Optional
8
+
9
+ import scipp as sc
10
+ from scipp.scipy.signal import butter
11
+
12
+ from .logging import get_logger
13
+
14
+
15
+ def _ensure_no_variances(var: sc.DataArray) -> sc.DataArray:
16
+ if var.variances is not None:
17
+ get_logger().warning(
18
+ 'Tried to smoothen data with uncertainties. '
19
+ 'This is not supported because the results would be highly correlated.\n'
20
+ 'Instead, the variances are ignored and the output '
21
+ 'will be returned without any!'
22
+ '\n--------------------------------------------------\n'
23
+ 'If you know a good solution for handling uncertainties in such a case, '
24
+ 'please contact the scipp developers! (e.g. via https://github.com/scipp)'
25
+ '\n--------------------------------------------------\n'
26
+ )
27
+ return sc.values(var)
28
+ return var
29
+
30
+
31
+ def lowpass(
32
+ da: sc.DataArray, *, dim: str, N: int, Wn: sc.Variable, coord: Optional[str] = None
33
+ ) -> sc.DataArray:
34
+ """
35
+ Smooth data using a lowpass frequency filter.
36
+
37
+ Applies a lowpass Butterworth filter to `da.data` based on the sampling rate
38
+ defined by `coord`.
39
+ See :py:func:`scipp.signal.butter` for information on filter design.
40
+
41
+ Important
42
+ ---------
43
+ If `coord` is bin-edges, it is first converted to bin-centers using
44
+ :func:`scipp.midpoints`.
45
+ This is only valid for linearly-spaced edges.
46
+
47
+ Parameters
48
+ ----------
49
+ da:
50
+ Data to smoothen.
51
+ dim:
52
+ Dimension along which to smooth.
53
+ coord:
54
+ Name of the coordinate that defines the sampling frequency.
55
+ Defaults to `dim`.
56
+ N:
57
+ Order of the lowpass filter.
58
+ Wn:
59
+ Critical frequency of the filter.
60
+
61
+ Returns
62
+ -------
63
+ :
64
+ Smoothed `da`.
65
+
66
+ See Also
67
+ --------
68
+ scipp.signal.butter scipp.signal.sosfiltfilt
69
+
70
+ Examples
71
+ --------
72
+
73
+ >>> from ess.diffraction import lowpass
74
+ >>> x = sc.linspace(dim='x', start=1.1, stop=4.0, num=1000, unit='m')
75
+ >>> y = sc.sin(x * sc.scalar(1.0, unit='rad/m'))
76
+ >>> y += sc.sin(x * sc.scalar(400.0, unit='rad/m'))
77
+ >>> noisy = sc.DataArray(data=y, coords={'x': x})
78
+ >>> smooth = lowpass(noisy, dim='x', N=4, Wn=20 / x.unit)
79
+ """
80
+ da = _ensure_no_variances(da)
81
+ coord = dim if coord is None else coord
82
+
83
+ if da.coords[coord].sizes[dim] == da.sizes[dim] + 1:
84
+ da = da.copy(deep=False)
85
+ da.coords[coord] = sc.midpoints(da.coords[coord], dim)
86
+
87
+ return butter(da.coords[coord], N=N, Wn=Wn).filtfilt(da, dim)
@@ -0,0 +1,117 @@
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 in ess.diffraction.
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, TypeVar
11
+
12
+ import sciline
13
+ import scipp as sc
14
+
15
+ # 1 TypeVars used to parametrize the generic parts of the workflow
16
+
17
+ # 1.1 Run types
18
+ EmptyInstrumentRun = NewType('EmptyInstrumentRun', int)
19
+ """Empty instrument run."""
20
+ SampleRun = NewType('SampleRun', int)
21
+ """Sample run."""
22
+ VanadiumRun = NewType('VanadiumRun', int)
23
+ """Vanadium run."""
24
+ RunType = TypeVar('RunType', EmptyInstrumentRun, SampleRun, VanadiumRun)
25
+ """TypeVar used for specifying the run."""
26
+
27
+
28
+ # 2 Workflow parameters
29
+
30
+ CalibrationFilename = NewType('CalibrationFilename', str)
31
+ """Filename of the instrument calibration file."""
32
+
33
+ DspacingBins = NewType('DSpacingBins', sc.Variable)
34
+ """Bin edges for d-spacing."""
35
+
36
+
37
+ class Filename(sciline.Scope[RunType, str], str):
38
+ """Filename of a run."""
39
+
40
+
41
+ OutFilename = NewType('OutFilename', str)
42
+ """Filename of the output."""
43
+
44
+ TwoThetaBins = NewType('TwoThetaBins', sc.Variable)
45
+ """Bin edges for grouping in 2theta.
46
+
47
+ This is used by an alternative focussing step that groups detector
48
+ pixels by scattering angle into bins given by these edges.
49
+ """
50
+
51
+ ValidTofRange = NewType('ValidTofRange', sc.Variable)
52
+ """Min and max tof value of the instrument."""
53
+
54
+ # 3 Workflow (intermediate) results
55
+
56
+
57
+ class AccumulatedProtonCharge(sciline.Scope[RunType, sc.Variable], sc.Variable):
58
+ """Total proton charge."""
59
+
60
+
61
+ CalibrationData = NewType('CalibrationData', sc.Dataset)
62
+ """Detector calibration data."""
63
+
64
+
65
+ class DspacingData(sciline.Scope[RunType, sc.DataArray], sc.DataArray):
66
+ """Data converted to d-spacing."""
67
+
68
+
69
+ class DspacingDataWithoutVariances(sciline.Scope[RunType, sc.DataArray], sc.DataArray):
70
+ """Data converted to d-spacing where variances where removed."""
71
+
72
+
73
+ DspacingHistogram = NewType('DspacingHistogram', sc.DataArray)
74
+ """Histogrammed intensity vs d-spacing."""
75
+
76
+
77
+ class FilteredData(sciline.Scope[RunType, sc.DataArray], sc.DataArray):
78
+ """Raw data without invalid events."""
79
+
80
+
81
+ class FocussedData(sciline.Scope[RunType, sc.DataArray], sc.DataArray):
82
+ """Intensity vs d-spacing after focussing pixels."""
83
+
84
+
85
+ class NormalizedByProtonCharge(sciline.Scope[RunType, sc.DataArray], sc.DataArray):
86
+ """Data that has been normalized by proton charge."""
87
+
88
+
89
+ NormalizedByVanadium = NewType('NormalizedByVanadium', sc.DataArray)
90
+ """Data that has been normalized by a vanadium run."""
91
+
92
+
93
+ class ProtonCharge(sciline.Scope[RunType, sc.DataArray], sc.DataArray):
94
+ """Time-dependent proton charge."""
95
+
96
+
97
+ RawCalibrationData = NewType('RawCalibrationData', sc.Dataset)
98
+ """Calibration data as loaded from file, needs preprocessing before using."""
99
+
100
+
101
+ class RawData(sciline.Scope[RunType, sc.DataArray], sc.DataArray):
102
+ """Raw data."""
103
+
104
+
105
+ class RawDataWithVariances(sciline.Scope[RunType, sc.DataArray], sc.DataArray):
106
+ """Raw data that has variances which need special handling."""
107
+
108
+
109
+ class RawDataAndMetadata(sciline.Scope[RunType, sc.DataGroup], sc.DataGroup):
110
+ """Raw data and associated metadata."""
111
+
112
+
113
+ class TofCroppedData(sciline.Scope[RunType, sc.DataArray], sc.DataArray):
114
+ """Raw data cropped to the valid TOF range."""
115
+
116
+
117
+ del sc, sciline, NewType, TypeVar
@@ -0,0 +1,18 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+ # Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
3
+ """Tools for handling statistical uncertainties."""
4
+
5
+ from .types import RawData, RawDataWithVariances, VanadiumRun
6
+
7
+
8
+ def drop_variances(data: RawDataWithVariances[VanadiumRun]) -> RawData[VanadiumRun]:
9
+ res = data.copy(deep=False)
10
+ if res.bins is not None:
11
+ res.bins.constituents['data'].variances = None
12
+ else:
13
+ res.variances = None
14
+ return RawData[VanadiumRun](res)
15
+
16
+
17
+ providers = (drop_variances,)
18
+ """Sciline providers for handling statistical uncertainties."""
ess/dream/__init__.py ADDED
@@ -0,0 +1,23 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+ # Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
3
+
4
+ """
5
+ Components for DREAM
6
+ """
7
+ import importlib.metadata
8
+
9
+ from . import data
10
+ from .io import fold_nexus_detectors, load_nexus
11
+
12
+ try:
13
+ __version__ = importlib.metadata.version(__package__ or __name__)
14
+ except importlib.metadata.PackageNotFoundError:
15
+ __version__ = "0.0.0"
16
+
17
+ del importlib
18
+
19
+ __all__ = [
20
+ "data",
21
+ "fold_nexus_detectors",
22
+ "load_nexus",
23
+ ]