Skip to content
Open
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
9 changes: 6 additions & 3 deletions packages/essdiffraction/src/ess/dream/io/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ def prepare_reduced_data(da: sc.DataArray) -> sc.DataArray:
hist = da.hist() if da.is_binned else da.copy(deep=False)
hist.coords[hist.dim] = sc.midpoints(hist.coords[hist.dim])

if hist.masks:
if (mask := irreducible_mask(hist.masks, hist.dim)) is not None:
# No file format we use here supports masks, so the next
# best thing is to zero out masked data:
hist.data = hist.data.copy()
hist.values *= irreducible_mask(hist.masks, hist.dim).values
if hist.variances is not None:
replacement = sc.scalar(0.0, variance=0.0, unit=hist.unit, dtype=hist.dtype)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I guess this is the usual question: should the variance be 0, and thus being a very tight constraint on fits?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think I would nan the masked values instead of 0. Makes them easier to distinguish from real zeros

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good point. I tried that and easydiffraction doesn't like it. It raises

TypeError: Value mismatch for <reduced_tof.data.1.intensity_meas>. Provided nan outside [0, inf]. Keeping current 0.0.

Judging by that error message, inf would be valid.

@AndrewSazonov How do we best encode masked data? In this case, it is masked because the vanadium measurement has a 0 in a bin.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Inf feels like it would just be a workaround/hack. Would make more sense if NaN was accepted downstream.

else:
replacement = sc.scalar(0.0, unit=hist.unit, dtype=hist.dtype)
hist.data = sc.where(mask, replacement, hist.data)
hist.masks.clear()

return hist
48 changes: 46 additions & 2 deletions packages/essdiffraction/tests/dream/io/cif_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import io

import ess.dream.io.cif
import numpy as np
import pytest
import scipp as sc
import scipp.testing
from ess.powder.calibration import OutputCalibrationData
from ess.powder.types import (
Beamline,
Expand All @@ -23,8 +25,11 @@
def ioftof() -> IntensityTof:
return IntensityTof(
sc.DataArray(
sc.array(dims=['tof'], values=[2.1, 3.2], variances=[0.3, 0.4]),
coords={'tof': sc.linspace('tof', 0.1, 1.2, 3, unit='us')},
sc.array(dims=['tof'], values=[2.1, 3.2, 1.6], variances=[0.3, 0.4, 0.1]),
coords={
'tof': sc.array(dims=['tof'], values=[0.1, 0.3, 0.5, 0.7], unit='us')
},
masks={'bad': sc.array(dims=['tof'], values=[False, True, False])},
)
)

Expand Down Expand Up @@ -95,3 +100,42 @@ def test_save_reduced_tof(ioftof: IntensityTof, cal: OutputCalibrationData) -> N
_pd_proc.intensity_norm_su
"""
assert loop_header in result


def test_save_reduced_tof_writes_excpected_data(
ioftof: IntensityTof, cal: OutputCalibrationData
) -> None:
cif_ = ess.dream.io.cif.prepare_reduced_tof_cif(
ioftof,
authors=CIFAuthors([]),
beamline=Beamline(
name="DREAM",
),
source=ESS_SOURCE,
measurement=Measurement(
title="Test measurement",
),
reducers=ReducerSoftware([]),
calibration=cal,
)
result = save_reduced_tof_to_str(cif_)

loop_header = """loop_
_pd_data.point_id
_pd_meas.time_of_flight
_pd_proc.intensity_norm
_pd_proc.intensity_norm_su
"""
data_table = result[result.index(loop_header) + len(loop_header) :]
_, tof, val, std = np.loadtxt(io.StringIO(data_table), delimiter=' ').T
loaded = sc.DataArray(
sc.array(dims=['tof'], values=val, variances=std**2),
coords={'tof': sc.array(dims=['tof'], values=tof, unit='us')},
)

expected = sc.DataArray(
sc.array(dims=['tof'], values=[2.1, 0.0, 1.6], variances=[0.3, 0.0, 0.1]),
coords={'tof': sc.array(dims=['tof'], values=[0.2, 0.4, 0.6], unit='us')},
)
# Can't be identical because of conversion to standard deviations
sc.testing.assert_allclose(loaded, expected)
Loading