From a9c01f0f9dda8eec009d7016fb90418f00047d96 Mon Sep 17 00:00:00 2001 From: Chris Meyer <34664+cmeyer@users.noreply.github.com> Date: Tue, 15 Jul 2025 16:54:59 -0700 Subject: [PATCH] Fix FFT calibration for odd dimensions. Test. Fixes #70. --- CHANGES.rst | 4 ++++ nion/data/Core.py | 4 +++- nion/data/test/Core_test.py | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 4bfa2d4..df7fafc 100755 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,10 @@ Changelog (niondata) ==================== +UNRELEASED +---------- +- Fix FFT calibration for odd dimensions. + 15.9.0 (2025-06-25) ------------------- - Add rectangle mask generation functions. diff --git a/nion/data/Core.py b/nion/data/Core.py index cab1dbe..5efc011 100755 --- a/nion/data/Core.py +++ b/nion/data/Core.py @@ -181,8 +181,10 @@ def calculate_data() -> _ImageDataType: assert len(src_dimensional_calibrations) == len(Image.dimensional_shape_from_shape_and_dtype(data_shape, data_dtype) or ()) + # zero_frequency_position = numpy.array((numpy.array(data_shape) // 2)) + 0.5 + dimensional_calibrations = [ - Calibration.Calibration((-0.5 - 0.5 * data_shape_n) / (dimensional_calibration.scale * data_shape_n), + Calibration.Calibration((-0.5 - data_shape_n // 2) / (dimensional_calibration.scale * data_shape_n), 1.0 / (dimensional_calibration.scale * data_shape_n), "1/" + dimensional_calibration.units) for dimensional_calibration, data_shape_n in zip(src_dimensional_calibrations, data_shape)] diff --git a/nion/data/test/Core_test.py b/nion/data/test/Core_test.py index a2297f8..5106973 100755 --- a/nion/data/test/Core_test.py +++ b/nion/data/test/Core_test.py @@ -1319,6 +1319,23 @@ def test_rectangular_mask_generation_out_of_bounds_completely(self) -> None: mask = mask_xdata.data self.assertTrue(numpy.all(mask == 0)) + def test_fft_zero_component_calibration(self) -> None: + dimensional_calibrations = (Calibration.Calibration(0, 1, "S"), Calibration.Calibration(0, 1, "S")) + xdata = DataAndMetadata.new_data_and_metadata(data=numpy.ones((16, 8)), dimensional_calibrations=dimensional_calibrations) + result = Core.function_fft(xdata) + self.assertAlmostEqual(0.0, result.dimensional_calibrations[0].convert_to_calibrated_value(8.5)) + self.assertAlmostEqual(0.0, result.dimensional_calibrations[1].convert_to_calibrated_value(4.5)) + xdata2 = DataAndMetadata.new_data_and_metadata(data=numpy.ones((15, 9)), dimensional_calibrations=dimensional_calibrations) + result2 = Core.function_fft(xdata2) + self.assertAlmostEqual(0.0, result2.dimensional_calibrations[0].convert_to_calibrated_value(7.5)) + self.assertAlmostEqual(0.0, result2.dimensional_calibrations[1].convert_to_calibrated_value(4.5)) + xdata3 = DataAndMetadata.new_data_and_metadata(data=numpy.ones((16,)), dimensional_calibrations=dimensional_calibrations[0:1]) + result3 = Core.function_fft(xdata3) + self.assertAlmostEqual(0.0, result3.dimensional_calibrations[0].convert_to_calibrated_value(8.5)) + xdata4 = DataAndMetadata.new_data_and_metadata(data=numpy.ones((15,)), dimensional_calibrations=dimensional_calibrations[0:1]) + result4 = Core.function_fft(xdata4) + self.assertAlmostEqual(0.0, result4.dimensional_calibrations[0].convert_to_calibrated_value(7.5)) + if __name__ == '__main__': logging.getLogger().setLevel(logging.DEBUG)