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
7 changes: 4 additions & 3 deletions docs/user-guide/dream/dream-data-reduction.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,10 @@
"metadata": {},
"outputs": [],
"source": [
"intermediates[MaskedData[SampleRun]].bins.concat().hist(\n",
" two_theta=300, wavelength=300\n",
").plot(norm=\"log\")"
"two_theta = sc.linspace(\"two_theta\", 0.8, 2.4, 301, unit=\"rad\")\n",
Copy link
Member

Choose a reason for hiding this comment

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

Why the explicit limits? Does this really matter so much for performance?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because we have some voxels with NaN positions, and get an exception otherwise.

"intermediates[MaskedData[SampleRun]].hist(two_theta=two_theta, wavelength=300).plot(\n",
" norm=\"log\"\n",
")"
]
},
{
Expand Down
5 changes: 0 additions & 5 deletions docs/user-guide/dream/dream-instrument-view.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@
"\n",
"# Extract the events from nested data groups\n",
"dg = sc.DataGroup({key: detector[\"events\"] for key, detector in dg.items()})\n",
"\n",
"# Construct the pixel positions from event positions\n",
"for da in dg.values():\n",
" da.coords[\"position\"] = da.bins.coords[\"position\"].bins.mean()\n",
"\n",
"dg"
]
},
Expand Down
23 changes: 11 additions & 12 deletions src/ess/dream/io/geant4.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,10 @@ def _group(detectors: Dict[str, sc.DataArray]) -> Dict[str, sc.DataGroup]:
def group(key: str, da: sc.DataArray) -> sc.DataArray:
if key in ["high_resolution", "sans"]:
# Only the HR and SANS detectors have sectors.
return da.group("sector", *elements)
res = da.group(*elements)
res = da.group("sector", *elements)
else:
res = da.group(*elements)
res.coords['position'] = res.bins.coords.pop('position').bins.mean()
Copy link
Member

Choose a reason for hiding this comment

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

Did you check whether this changes the final result?

Copy link
Member Author

Choose a reason for hiding this comment

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

I was hoping there are tests for that...?

Copy link
Member

@jl-wynen jl-wynen Jun 26, 2024

Choose a reason for hiding this comment

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

There are no tests for the complete $I(d)$. We only test a subset of properties of the output.

The problem is that the workflow is incomplete. Most updates in the near future will break regression tests.

res.bins.coords.pop("sector", None)
return res

Expand Down Expand Up @@ -167,15 +169,11 @@ def _extract_detector(
return events


def get_source_position(
raw_source: RawSource[RunType],
) -> SourcePosition[RunType]:
def get_source_position(raw_source: RawSource[RunType]) -> SourcePosition[RunType]:
return SourcePosition[RunType](raw_source["position"])


def get_sample_position(
raw_sample: RawSample[RunType],
) -> SamplePosition[RunType]:
def get_sample_position(raw_sample: RawSample[RunType]) -> SamplePosition[RunType]:
return SamplePosition[RunType](raw_sample["position"])


Expand All @@ -184,10 +182,11 @@ def patch_detector_data(
source_position: SourcePosition[RunType],
sample_position: SamplePosition[RunType],
) -> ReducibleDetectorData[RunType]:
out = detector_data.copy(deep=False)
out.coords["source_position"] = source_position
out.coords["sample_position"] = sample_position
return ReducibleDetectorData[RunType](out)
return ReducibleDetectorData[RunType](
detector_data.assign_coords(
source_position=source_position, sample_position=sample_position
)
)


def geant4_detector_dimensions(
Expand Down
12 changes: 7 additions & 5 deletions src/ess/powder/conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,13 @@ def convert_to_dspacing(
) -> DspacingData[RunType]:
if calibration is None:
out = data.transform_coords(["dspacing"], graph=graph, keep_intermediate=False)
return DspacingData[RunType](out)
out = to_dspacing_with_calibration(data, calibration=calibration)
for key in ('wavelength', 'two_theta'):
if key in out.coords.keys():
out.coords.set_aligned(key, False)
else:
out = to_dspacing_with_calibration(data, calibration=calibration)
for key in ('wavelength', 'two_theta'):
if key in out.coords.keys():
out.coords.set_aligned(key, False)
out.bins.coords.pop('tof', None)
out.bins.coords.pop('wavelength', None)
return DspacingData[RunType](out)


Expand Down
36 changes: 28 additions & 8 deletions src/ess/powder/grouping.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
"""Grouping and merging of pixels / voxels."""

import scipp as sc

from .types import (
DspacingBins,
DspacingData,
Expand All @@ -12,23 +14,41 @@
)


def _drop_grouping_and_bin(
data: sc.DataArray, *, dims_to_reduce: tuple[str, ...] | None = None, edges: dict
) -> sc.DataArray:
all_pixels = data if dims_to_reduce == () else data.bins.concat(dims_to_reduce)
Comment on lines +17 to +20
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def _drop_grouping_and_bin(
data: sc.DataArray, *, dims_to_reduce: tuple[str, ...] | None = None, edges: dict
) -> sc.DataArray:
all_pixels = data if dims_to_reduce == () else data.bins.concat(dims_to_reduce)
def _drop_grouping_and_bin(
data: sc.DataArray, *, edges: dict
) -> sc.DataArray:
all_pixels = data.bins.concat(dims_to_reduce)

because dims_to_reduce is never used.

Copy link
Member Author

Choose a reason for hiding this comment

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

I was using it for the two-theta case, but then refactored. Since I wanted to consider moving this to ESSreduce I thought I'd keep it.

# all_pixels may just have a single bin now, which currently yields
# inferior performance when binning (no/bad multi-threading?).
# We operate on the content buffer for better multi-threaded performance.
if all_pixels.ndim == 0:
return (
all_pixels.value.bin(**edges)
.assign_coords(all_pixels.coords)
.assign_masks(all_pixels.masks)
)
else:
return all_pixels.bin(**edges)


def focus_data_dspacing(
data: DspacingData[RunType],
dspacing_bins: DspacingBins,
data: DspacingData[RunType], dspacing_bins: DspacingBins
) -> FocussedDataDspacing[RunType]:
out = data.bins.concat().bin({dspacing_bins.dim: dspacing_bins})
return FocussedDataDspacing[RunType](out)
return FocussedDataDspacing[RunType](
_drop_grouping_and_bin(data, edges={dspacing_bins.dim: dspacing_bins})
)


def focus_data_dspacing_and_two_theta(
data: DspacingData[RunType],
dspacing_bins: DspacingBins,
twotheta_bins: TwoThetaBins,
) -> FocussedDataDspacingTwoTheta[RunType]:
bins = {twotheta_bins.dim: twotheta_bins, dspacing_bins.dim: dspacing_bins}
if "two_theta" in data.bins.coords:
data = data.bins.concat()
return FocussedDataDspacingTwoTheta[RunType](data.bin(**bins))
return FocussedDataDspacingTwoTheta[RunType](
data.bin({twotheta_bins.dim: twotheta_bins}).bin(
{dspacing_bins.dim: dspacing_bins}
)
)


providers = (focus_data_dspacing, focus_data_dspacing_and_two_theta)
Expand Down
2 changes: 1 addition & 1 deletion tests/dream/geant4_reduction_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def test_pipeline_two_theta_masking(providers, params):
pipeline = sciline.Pipeline(providers, params=params)
pipeline = powder.with_pixel_mask_filenames(pipeline, [])
masked_sample = pipeline.compute(MaskedData[SampleRun])
assert 'two_theta' in masked_sample.bins.masks
assert 'two_theta' in masked_sample.masks
sum_in_masked_region = (
masked_sample.bin(two_theta=sc.concat([tmin, tmax], dim='two_theta')).sum().data
)
Expand Down
10 changes: 5 additions & 5 deletions tests/dream/io/geant4_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def test_load_geant4_csv_mantle_has_expected_coords(file):
assert "sector" not in mantle.bins.coords
assert "tof" in mantle.bins.coords
assert "wavelength" in mantle.bins.coords
assert "position" in mantle.bins.coords
assert "position" in mantle.coords


def test_load_geant4_csv_endcap_backward_has_expected_coords(file):
Expand All @@ -128,7 +128,7 @@ def test_load_geant4_csv_endcap_backward_has_expected_coords(file):
assert "sector" not in endcap.bins.coords
assert "tof" in endcap.bins.coords
assert "wavelength" in endcap.bins.coords
assert "position" in endcap.bins.coords
assert "position" in endcap.coords


def test_load_geant4_csv_endcap_forward_has_expected_coords(file):
Expand All @@ -143,7 +143,7 @@ def test_load_geant4_csv_endcap_forward_has_expected_coords(file):
assert "sector" not in endcap.bins.coords
assert "tof" in endcap.bins.coords
assert "wavelength" in endcap.bins.coords
assert "position" in endcap.bins.coords
assert "position" in endcap.coords


def test_load_geant4_csv_high_resolution_has_expected_coords(file):
Expand All @@ -157,7 +157,7 @@ def test_load_geant4_csv_high_resolution_has_expected_coords(file):

assert "tof" in hr.bins.coords
assert "wavelength" in hr.bins.coords
assert "position" in hr.bins.coords
assert "position" in hr.coords


def test_load_geant4_csv_sans_has_expected_coords(file):
Expand All @@ -174,7 +174,7 @@ def test_load_geant4_csv_sans_has_expected_coords(file):

assert "tof" in sans.bins.coords
assert "wavelength" in sans.bins.coords
assert "position" in sans.bins.coords
assert "position" in sans.coords


def test_geant4_in_pipeline(file_path, file):
Expand Down