Source code for ewoksxrdct.tests.test_regrid_data

import numpy as np
import pytest

from ..tasks.regrid_data import RegridData


def _run_regrid(
    translation_values,
    rotation_angles,
    integration_intensity_values,
    translation_grid_params,
    rotation_grid_params,
    integration_radial_axis="2theta",
    integration_radial_axis_values=None,
):
    if integration_radial_axis_values is None:
        integration_radial_axis_values = np.array([0.1])

    task = RegridData(
        inputs={
            "translation_values": np.asarray(translation_values, dtype=float),
            "translation_grid_params": translation_grid_params,
            "rotation_angles": np.asarray(rotation_angles, dtype=float),
            "rotation_grid_params": rotation_grid_params,
            "integration_intensity_values": np.asarray(
                integration_intensity_values, dtype=float
            ),
            "integration_radial_axis": integration_radial_axis,
            "integration_radial_axis_values": integration_radial_axis_values,
        }
    )
    task.execute()
    return task


[docs] def test_compute_bin_edges_centered_multiple_bins(): """Edges are offset by half the grid spacing so bins center on grid points.""" task = RegridData( inputs={ "translation_values": np.array([0, 0, 0, 10, 10, 10]), "translation_grid_params": (0, 10, 2), "rotation_angles": np.array([0, 5, 10, 0, 5, 10]), "rotation_grid_params": (0, 10, 3), "integration_intensity_values": np.zeros((6, 1)), "integration_radial_axis_values": np.array([0.1]), } ) edges = task.compute_bin_edges_centered(0, 10, 3) np.testing.assert_allclose(edges, [-2.5, 2.5, 7.5, 12.5])
[docs] def test_compute_bin_edges_centered_single_bin_raises(): """A single-bin grid has no spacing to compute a bin from, so it raises a ValueError.""" task = RegridData( inputs={ "translation_values": np.array([0, 0, 10, 10]), "translation_grid_params": (0, 10, 2), "rotation_angles": np.array([0, 10, 0, 10]), "rotation_grid_params": (0, 10, 2), "integration_intensity_values": np.zeros((4, 1)), "integration_radial_axis_values": np.array([0.1]), } ) with pytest.raises(ValueError, match="n_bins must be at least 2"): task.compute_bin_edges_centered(5, 5, 1)
[docs] def test_run_averages_points_that_fall_in_same_bin(): """When two readings land in the same bin the regridded value is their average, and a bin with no readings is zero rather than NaN.""" # n_trans=3, n_rot=2, but the (10, 0) bin got two readings and (20, 10) got none. translation_values = [0, 0, 10, 10, 10, 20] rotation_angles = [0, 10, 0, 0, 10, 0] intensity = [[1], [2], [10], [20], [4], [5]] task = _run_regrid( translation_values=translation_values, rotation_angles=rotation_angles, integration_intensity_values=intensity, translation_grid_params=(0, 20, 3), rotation_grid_params=(0, 10, 2), ) expected = np.array([[[1], [2]], [[15], [4]], [[5], [0]]]) np.testing.assert_allclose(task.outputs.integration_intensity_values, expected)
[docs] def test_run_handles_descending_grid_params(): """A grid given as (high, low, count) -- e.g. a motor scanning from a high position down to a low one -- must regrid correctly and produce ascending output grids, not silently drop every point.""" # A full raster following the physical scan direction: translation sweeps # 20 -> 10 -> 0, and at each stop rotation sweeps 10 -> 0. translation_values = [20, 20, 10, 10, 0, 0] rotation_angles = [10, 0, 10, 0, 10, 0] intensity = [[1], [2], [3], [4], [5], [6]] task = _run_regrid( translation_values=translation_values, rotation_angles=rotation_angles, integration_intensity_values=intensity, translation_grid_params=(20, 0, 3), # descending rotation_grid_params=(10, 0, 2), # descending ) expected = np.array([[[6], [5]], [[4], [3]], [[2], [1]]]) np.testing.assert_allclose(task.outputs.integration_intensity_values, expected) np.testing.assert_allclose(task.outputs.translation_values, [0, 10, 20]) np.testing.assert_allclose(task.outputs.rotation_angles, [0, 10])
[docs] def test_run_drops_points_outside_grid_range(): """A motor readback beyond the nominal scan range is excluded from the regridded output instead of raising or corrupting a bin.""" translation_values = [0, 0, 10, 10, 20, 20] rotation_angles = [0, 10, 0, 10, 0, 500] # last point overshoots intensity = [[1], [2], [3], [4], [5], [999]] task = _run_regrid( translation_values=translation_values, rotation_angles=rotation_angles, integration_intensity_values=intensity, translation_grid_params=(0, 20, 3), rotation_grid_params=(0, 10, 2), ) expected = np.array([[[1], [2]], [[3], [4]], [[5], [0]]]) np.testing.assert_allclose(task.outputs.integration_intensity_values, expected)
[docs] def test_run_handles_integer_intensity_values(): """Integer intensity input handled in regrid_histogram.""" task = RegridData( inputs={ "translation_values": np.array([0, 0, 10, 10]), "translation_grid_params": (0, 10, 2), "rotation_angles": np.array([0, 0, 0, 0]), "rotation_grid_params": (0, 10, 2), "integration_intensity_values": np.array( [[1], [2], [3], [4]], dtype=np.int32 ), "integration_radial_axis_values": np.array([0.1]), } ) task.execute() expected = np.array([[[1.5], [0]], [[3.5], [0]]]) np.testing.assert_allclose(task.outputs.integration_intensity_values, expected)
[docs] def test_run_passes_through_radial_axis_metadata(): """The radial axis name and edge values are forwarded unchanged.""" radial_axis_edges = np.array([0.1, 0.2, 0.3]) # Both grids are (0, 10, 2) -> grid points [0, 10], covering all 2*2=4 # combinations. task = _run_regrid( translation_values=[0, 0, 10, 10], rotation_angles=[0, 10, 0, 10], integration_intensity_values=[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]], translation_grid_params=(0, 10, 2), rotation_grid_params=(0, 10, 2), integration_radial_axis="2theta", integration_radial_axis_values=radial_axis_edges, ) assert task.outputs.integration_radial_axis == "2theta" np.testing.assert_array_equal( task.outputs.integration_radial_axis_values, radial_axis_edges )