From 8c909c67c495233f31dbbba3ce352bfc199c96af Mon Sep 17 00:00:00 2001 From: Dominic Oram Date: Tue, 22 Mar 2022 16:44:40 +0000 Subject: [PATCH 1/2] Added tests for various of the nexus writers --- tests/test_NxclassWriters.py | 192 +++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 tests/test_NxclassWriters.py diff --git a/tests/test_NxclassWriters.py b/tests/test_NxclassWriters.py new file mode 100644 index 00000000..f9c3f13f --- /dev/null +++ b/tests/test_NxclassWriters.py @@ -0,0 +1,192 @@ +from pathlib import Path +from nexgen.nxs_write.NXclassWriters import write_NXdata, find_scan_axis, write_NXsample +from unittest.mock import MagicMock, patch +import pytest +import tempfile +import h5py +from h5py import AttributeManager +import numpy as np +from numpy.testing import assert_array_equal + +test_goniometer_axes = { + "axes": ["omega", "sam_z", "sam_y"], + "depends": [".", "omega", "sam_z"], + "vectors": [ + -1, + 0, + 0, + 0, + -1, + 0, + -1, + 0, + 0, + ], + "types": [ + "rotation", + "translation", + "translation", + ], + "units": ["deg", "mm", "mm"], + "offsets": [0, 0, 0, 0, 0, 0, 0, 0, 0], + "starts": [0, 0, 0], + "ends": [0, 0, 0], + "increments": [1, 0, 0], +} + + +@pytest.fixture +def dummy_nexus_file(): + test_hdf_file = tempfile.TemporaryFile() + test_nexus_file = h5py.File(test_hdf_file, "w") + yield test_nexus_file + + +def test_given_no_data_files_when_write_NXdata_then_assert_error(): + mock_hdf5_file = MagicMock() + with pytest.raises(AssertionError): + write_NXdata(mock_hdf5_file, [], {}, "", "", []) + + +def test_given_no_data_type_specified_when_write_NXdata_then_exception_raised( + dummy_nexus_file, +): + with pytest.raises(SystemExit): + write_NXdata( + dummy_nexus_file, [Path("tmp")], test_goniometer_axes, "", "", [], "sam_z" + ) + + +def test_given_one_data_file_when_write_NXdata_then_data_entry_in_file( + dummy_nexus_file, +): + write_NXdata( + dummy_nexus_file, [Path("tmp")], test_goniometer_axes, "images", "", [], "sam_z" + ) + assert dummy_nexus_file["/entry/data"].attrs["NX_class"] == b"NXdata" + assert "data" in dummy_nexus_file["/entry/data"] + + +@patch("nexgen.nxs_write.NXclassWriters.find_scan_axis", return_value="sam_z") +def test_given_no_scan_axis_when_write_NXdata_then_find_scan_axis_called( + mock_find_scan_axis, dummy_nexus_file +): + write_NXdata( + dummy_nexus_file, [Path("tmp")], test_goniometer_axes, "images", "", [] + ) + mock_find_scan_axis.assert_called_once() + + +def test_given_scan_axis_when_write_NXdata_then_axis_in_data_entry_with_correct_data_and_attributes( + dummy_nexus_file, +): + test_axis = "sam_z" + test_scan_range = [0, 1, 2] + axis_entry = f"/entry/data/{test_axis}" + + write_NXdata( + dummy_nexus_file, + [Path("tmp")], + test_goniometer_axes, + "images", + "", + test_scan_range, + test_axis, + ) + + assert test_axis in dummy_nexus_file["/entry/data"] + assert_array_equal(test_scan_range, dummy_nexus_file[axis_entry][:]) + assert ( + dummy_nexus_file[axis_entry].attrs["depends_on"] + == b"/entry/sample/transformations/omega" + ) + assert dummy_nexus_file[axis_entry].attrs["transformation_type"] == b"translation" + assert dummy_nexus_file[axis_entry].attrs["units"] == b"mm" + assert_array_equal(dummy_nexus_file[axis_entry].attrs["vector"][:], [0.0, -1.0, 0]) + + +def test_given_scan_axis_when_write_NXsample_then_scan_axis_data_copied_from_data_group_as_well_as_increment_set_and_end( + dummy_nexus_file, +): + test_axis = "omega" + test_scan_range = [0, 1, 2] + axis_entry = f"/entry/sample/sample_{test_axis}/{test_axis}" + + # Doing this to write the scan axis data into the data group + write_NXdata( + dummy_nexus_file, + [Path("tmp")], + test_goniometer_axes, + "images", + "", + test_scan_range, + test_axis, + ) + + write_NXsample( + dummy_nexus_file, + test_goniometer_axes, + "", + "images", + test_axis, + test_scan_range, + ) + + assert f"sample_{test_axis}" in dummy_nexus_file["/entry/sample"] + assert_array_equal(test_scan_range, dummy_nexus_file[axis_entry][:]) + assert dummy_nexus_file[axis_entry].attrs["depends_on"] == b"." + assert dummy_nexus_file[axis_entry].attrs["transformation_type"] == b"rotation" + assert dummy_nexus_file[axis_entry].attrs["units"] == b"deg" + assert_array_equal(dummy_nexus_file[axis_entry].attrs["vector"][:], [-1, 0, 0]) + assert_array_equal(dummy_nexus_file[axis_entry + "_increment_set"][:], [1] * 3) + assert dummy_nexus_file[axis_entry + "_end"][1] == 2 + + +def test_given_no_axes_when_find_scan_axis_called_then_assert_error(): + with pytest.raises(AssertionError): + find_scan_axis([], [], [], []) + + +def test_given_one_rotation_axis_when_find_scan_axis_called_then_axis_returned(): + test_names = ["sam_x", "omega"] + test_starts = [0, 0] + test_ends = [0, 10] + test_types = ["translation", "rotation"] + scan_axis = find_scan_axis(test_names, test_starts, test_ends, test_types) + assert scan_axis == "omega" + + +def test_given_no_moving_axes_when_find_scan_axis_called_then_default_axis_returned(): + test_names = ["sam_x", "omega"] + test_starts = [0, 0] + test_ends = [0, 0] + test_types = ["rotation", "rotation"] + default_axis = "default_axis" + scan_axis = find_scan_axis( + test_names, test_starts, test_ends, test_types, default_axis + ) + assert scan_axis == default_axis + + +def test_given_one_moving_axes_when_find_scan_axis_called_then_this_axis_returned(): + test_names = ["sam_x", "omega"] + test_starts = [0, 0] + test_ends = [0, 10] + test_types = ["rotation", "rotation"] + default_axis = "default_axis" + scan_axis = find_scan_axis( + test_names, test_starts, test_ends, test_types, default_axis + ) + assert scan_axis == "omega" + + +def test_given_two_moving_axes_when_find_scan_axis_called_then_exception(): + test_names = ["sam_x", "omega"] + test_starts = [0, 0] + test_ends = [10, 10] + test_types = ["rotation", "rotation"] + default_axis = "default_axis" + with pytest.raises(SystemExit): + scan_axis = find_scan_axis( + test_names, test_starts, test_ends, test_types, default_axis + ) From c08f91f6e07d26d5f596d75e0f9d6e08b97b5cb5 Mon Sep 17 00:00:00 2001 From: Dominic Oram Date: Thu, 7 Jul 2022 09:08:20 +0100 Subject: [PATCH 2/2] Added additional unit tests for NXclassWriters --- tests/test_NXclassWriters.py | 135 +++++++++++++++++++++++- tests/test_NxclassWriters.py | 192 ----------------------------------- 2 files changed, 134 insertions(+), 193 deletions(-) delete mode 100644 tests/test_NxclassWriters.py diff --git a/tests/test_NXclassWriters.py b/tests/test_NXclassWriters.py index 404d5a6a..e51a9291 100644 --- a/tests/test_NXclassWriters.py +++ b/tests/test_NXclassWriters.py @@ -1,13 +1,48 @@ import tempfile from datetime import datetime +from unittest.mock import MagicMock import h5py import pytest +import numpy as np +from pathlib import Path +from numpy.testing import assert_array_equal -from nexgen.nxs_write.NXclassWriters import write_NXdatetime, write_NXdetector_module +from nexgen.nxs_write.NXclassWriters import ( + write_NXdatetime, + write_NXdetector_module, + write_NXdata, + write_NXsample, +) test_module = {"fast_axis": [1, 0, 0], "slow_axis": [0, 1, 0]} +test_goniometer_axes = { + "axes": ["omega", "sam_z", "sam_y"], + "depends": [".", "omega", "sam_z"], + "vectors": [ + -1, + 0, + 0, + 0, + -1, + 0, + -1, + 0, + 0, + ], + "types": [ + "rotation", + "translation", + "translation", + ], + "units": ["deg", "mm", "mm"], + "offsets": [0, 0, 0, 0, 0, 0, 0, 0, 0], + "starts": [0, 0, 0], + "ends": [90, 0, 0], + "increments": [1, 0, 0], +} + @pytest.fixture def dummy_nexus_file(): @@ -16,6 +51,104 @@ def dummy_nexus_file(): yield test_nexus_file +def test_given_no_data_files_when_write_NXdata_then_assert_error(): + mock_hdf5_file = MagicMock() + with pytest.raises(OSError): + write_NXdata(mock_hdf5_file, [], {}, "", "", []) + + +def test_given_no_data_type_specified_when_write_NXdata_then_exception_raised( + dummy_nexus_file, +): + osc_scan = {"omega": np.arange(0, 90, 1)} + with pytest.raises(ValueError): + write_NXdata( + dummy_nexus_file, + [Path("tmp")], + test_goniometer_axes, + ("", 0), + "", + osc_scan, + ) + + +def test_given_one_data_file_when_write_NXdata_then_data_in_file( + dummy_nexus_file, +): + osc_scan = {"omega": np.arange(0, 90, 1)} + write_NXdata( + dummy_nexus_file, + [Path("tmp")], + test_goniometer_axes, + ("images", 0), + "", + osc_scan, + ) + assert dummy_nexus_file["/entry/data"].attrs["NX_class"] == b"NXdata" + assert "data_000001" in dummy_nexus_file["/entry/data"] + + +def test_given_scan_axis_when_write_NXdata_then_axis_in_data_entry_with_correct_data_and_attributes( + dummy_nexus_file, +): + test_axis = "omega" + test_scan_range = np.arange(0, 90, 1) + axis_entry = f"/entry/data/{test_axis}" + osc_scan = {test_axis: test_scan_range} + + write_NXdata( + dummy_nexus_file, + [Path("tmp")], + test_goniometer_axes, + ("images", 0), + "", + osc_scan, + ) + + assert test_axis in dummy_nexus_file["/entry/data"] + assert_array_equal(test_scan_range, dummy_nexus_file[axis_entry][:]) + assert dummy_nexus_file[axis_entry].attrs["depends_on"] == b"." + assert dummy_nexus_file[axis_entry].attrs["transformation_type"] == b"rotation" + assert dummy_nexus_file[axis_entry].attrs["units"] == b"deg" + assert_array_equal(dummy_nexus_file[axis_entry].attrs["vector"][:], [-1.0, 0.0, 0]) + + +def test_given_scan_axis_when_write_NXsample_then_scan_axis_data_copied_from_data_group_as_well_as_increment_set_and_end( + dummy_nexus_file, +): + test_axis = "omega" + test_scan_range = [0, 1, 2] + axis_entry = f"/entry/sample/sample_{test_axis}/{test_axis}" + osc_scan = {test_axis: test_scan_range} + + # Doing this to write the scan axis data into the data group + write_NXdata( + dummy_nexus_file, + [Path("tmp")], + test_goniometer_axes, + ("images", 0), + "", + osc_scan, + ) + + write_NXsample( + dummy_nexus_file, + test_goniometer_axes, + "", + ("images", 0), + osc_scan, + ) + + assert f"sample_{test_axis}" in dummy_nexus_file["/entry/sample"] + assert_array_equal(test_scan_range, dummy_nexus_file[axis_entry][:]) + assert dummy_nexus_file[axis_entry].attrs["depends_on"] == b"." + assert dummy_nexus_file[axis_entry].attrs["transformation_type"] == b"rotation" + assert dummy_nexus_file[axis_entry].attrs["units"] == b"deg" + assert_array_equal(dummy_nexus_file[axis_entry].attrs["vector"][:], [-1, 0, 0]) + assert_array_equal(dummy_nexus_file[axis_entry + "_increment_set"][:], [1] * 3) + assert dummy_nexus_file[axis_entry + "_end"][1] == 2 + + def test_given_module_offset_of_1_when_write_NXdetector_module_then_fast_and_slow_axis_depends_on_module_offset( dummy_nexus_file, ): diff --git a/tests/test_NxclassWriters.py b/tests/test_NxclassWriters.py deleted file mode 100644 index f9c3f13f..00000000 --- a/tests/test_NxclassWriters.py +++ /dev/null @@ -1,192 +0,0 @@ -from pathlib import Path -from nexgen.nxs_write.NXclassWriters import write_NXdata, find_scan_axis, write_NXsample -from unittest.mock import MagicMock, patch -import pytest -import tempfile -import h5py -from h5py import AttributeManager -import numpy as np -from numpy.testing import assert_array_equal - -test_goniometer_axes = { - "axes": ["omega", "sam_z", "sam_y"], - "depends": [".", "omega", "sam_z"], - "vectors": [ - -1, - 0, - 0, - 0, - -1, - 0, - -1, - 0, - 0, - ], - "types": [ - "rotation", - "translation", - "translation", - ], - "units": ["deg", "mm", "mm"], - "offsets": [0, 0, 0, 0, 0, 0, 0, 0, 0], - "starts": [0, 0, 0], - "ends": [0, 0, 0], - "increments": [1, 0, 0], -} - - -@pytest.fixture -def dummy_nexus_file(): - test_hdf_file = tempfile.TemporaryFile() - test_nexus_file = h5py.File(test_hdf_file, "w") - yield test_nexus_file - - -def test_given_no_data_files_when_write_NXdata_then_assert_error(): - mock_hdf5_file = MagicMock() - with pytest.raises(AssertionError): - write_NXdata(mock_hdf5_file, [], {}, "", "", []) - - -def test_given_no_data_type_specified_when_write_NXdata_then_exception_raised( - dummy_nexus_file, -): - with pytest.raises(SystemExit): - write_NXdata( - dummy_nexus_file, [Path("tmp")], test_goniometer_axes, "", "", [], "sam_z" - ) - - -def test_given_one_data_file_when_write_NXdata_then_data_entry_in_file( - dummy_nexus_file, -): - write_NXdata( - dummy_nexus_file, [Path("tmp")], test_goniometer_axes, "images", "", [], "sam_z" - ) - assert dummy_nexus_file["/entry/data"].attrs["NX_class"] == b"NXdata" - assert "data" in dummy_nexus_file["/entry/data"] - - -@patch("nexgen.nxs_write.NXclassWriters.find_scan_axis", return_value="sam_z") -def test_given_no_scan_axis_when_write_NXdata_then_find_scan_axis_called( - mock_find_scan_axis, dummy_nexus_file -): - write_NXdata( - dummy_nexus_file, [Path("tmp")], test_goniometer_axes, "images", "", [] - ) - mock_find_scan_axis.assert_called_once() - - -def test_given_scan_axis_when_write_NXdata_then_axis_in_data_entry_with_correct_data_and_attributes( - dummy_nexus_file, -): - test_axis = "sam_z" - test_scan_range = [0, 1, 2] - axis_entry = f"/entry/data/{test_axis}" - - write_NXdata( - dummy_nexus_file, - [Path("tmp")], - test_goniometer_axes, - "images", - "", - test_scan_range, - test_axis, - ) - - assert test_axis in dummy_nexus_file["/entry/data"] - assert_array_equal(test_scan_range, dummy_nexus_file[axis_entry][:]) - assert ( - dummy_nexus_file[axis_entry].attrs["depends_on"] - == b"/entry/sample/transformations/omega" - ) - assert dummy_nexus_file[axis_entry].attrs["transformation_type"] == b"translation" - assert dummy_nexus_file[axis_entry].attrs["units"] == b"mm" - assert_array_equal(dummy_nexus_file[axis_entry].attrs["vector"][:], [0.0, -1.0, 0]) - - -def test_given_scan_axis_when_write_NXsample_then_scan_axis_data_copied_from_data_group_as_well_as_increment_set_and_end( - dummy_nexus_file, -): - test_axis = "omega" - test_scan_range = [0, 1, 2] - axis_entry = f"/entry/sample/sample_{test_axis}/{test_axis}" - - # Doing this to write the scan axis data into the data group - write_NXdata( - dummy_nexus_file, - [Path("tmp")], - test_goniometer_axes, - "images", - "", - test_scan_range, - test_axis, - ) - - write_NXsample( - dummy_nexus_file, - test_goniometer_axes, - "", - "images", - test_axis, - test_scan_range, - ) - - assert f"sample_{test_axis}" in dummy_nexus_file["/entry/sample"] - assert_array_equal(test_scan_range, dummy_nexus_file[axis_entry][:]) - assert dummy_nexus_file[axis_entry].attrs["depends_on"] == b"." - assert dummy_nexus_file[axis_entry].attrs["transformation_type"] == b"rotation" - assert dummy_nexus_file[axis_entry].attrs["units"] == b"deg" - assert_array_equal(dummy_nexus_file[axis_entry].attrs["vector"][:], [-1, 0, 0]) - assert_array_equal(dummy_nexus_file[axis_entry + "_increment_set"][:], [1] * 3) - assert dummy_nexus_file[axis_entry + "_end"][1] == 2 - - -def test_given_no_axes_when_find_scan_axis_called_then_assert_error(): - with pytest.raises(AssertionError): - find_scan_axis([], [], [], []) - - -def test_given_one_rotation_axis_when_find_scan_axis_called_then_axis_returned(): - test_names = ["sam_x", "omega"] - test_starts = [0, 0] - test_ends = [0, 10] - test_types = ["translation", "rotation"] - scan_axis = find_scan_axis(test_names, test_starts, test_ends, test_types) - assert scan_axis == "omega" - - -def test_given_no_moving_axes_when_find_scan_axis_called_then_default_axis_returned(): - test_names = ["sam_x", "omega"] - test_starts = [0, 0] - test_ends = [0, 0] - test_types = ["rotation", "rotation"] - default_axis = "default_axis" - scan_axis = find_scan_axis( - test_names, test_starts, test_ends, test_types, default_axis - ) - assert scan_axis == default_axis - - -def test_given_one_moving_axes_when_find_scan_axis_called_then_this_axis_returned(): - test_names = ["sam_x", "omega"] - test_starts = [0, 0] - test_ends = [0, 10] - test_types = ["rotation", "rotation"] - default_axis = "default_axis" - scan_axis = find_scan_axis( - test_names, test_starts, test_ends, test_types, default_axis - ) - assert scan_axis == "omega" - - -def test_given_two_moving_axes_when_find_scan_axis_called_then_exception(): - test_names = ["sam_x", "omega"] - test_starts = [0, 0] - test_ends = [10, 10] - test_types = ["rotation", "rotation"] - default_axis = "default_axis" - with pytest.raises(SystemExit): - scan_axis = find_scan_axis( - test_names, test_starts, test_ends, test_types, default_axis - )