From 1c56202e07562024279ac08ab16595f243c203cf Mon Sep 17 00:00:00 2001 From: Simon Billinge Date: Wed, 30 Oct 2024 01:11:24 -0400 Subject: [PATCH 1/4] mask on reciprocal space is greater than not greater than equal --- src/diffpy/fourigui/fourigui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diffpy/fourigui/fourigui.py b/src/diffpy/fourigui/fourigui.py index 12e7db6..770ec1e 100755 --- a/src/diffpy/fourigui/fourigui.py +++ b/src/diffpy/fourigui/fourigui.py @@ -484,7 +484,7 @@ def applycutoff(self): r2_outer = qmax**2 i, j, k = np.meshgrid(np.arange(xdim), np.arange(ydim), np.arange(zdim)) r2 = (i - xdim // 2) ** 2 + (j - ydim // 2) ** 2 + (k - zdim // 2) ** 2 - mask = (r2 <= r2_inner) | (r2 >= r2_outer) # True if voxel is out of range + mask = (r2 < r2_inner) | (r2 > r2_outer) # True if voxel is out of range sphere[mask] = np.nan # therefore set to np.nan if out of range if self.space.get(): From d18ad47bfb323247324e6c717ea12c5b205f525f Mon Sep 17 00:00:00 2001 From: Simon Billinge Date: Wed, 30 Oct 2024 01:13:07 -0400 Subject: [PATCH 2/4] news --- news/gt.rst | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 news/gt.rst diff --git a/news/gt.rst b/news/gt.rst new file mode 100644 index 0000000..db01cae --- /dev/null +++ b/news/gt.rst @@ -0,0 +1,23 @@ +**Added:** + +* + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* qmin/qmax limits in reciprocal space grid so qmin and qmax are not excluded + +**Security:** + +* From c657f237613ef6d542ed8dc7dc55022c08f80b07 Mon Sep 17 00:00:00 2001 From: Simon Billinge Date: Sat, 9 Nov 2024 00:59:14 -0500 Subject: [PATCH 3/4] test for applycutoff in fourigui --- requirements/test.txt | 1 + src/diffpy/fourigui/fourigui.py | 4 -- tests/{unit_test.py => test_fourigui.py} | 78 ++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 4 deletions(-) rename tests/{unit_test.py => test_fourigui.py} (59%) diff --git a/requirements/test.txt b/requirements/test.txt index a727786..d9d0c8c 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -4,3 +4,4 @@ codecov coverage pytest-cov pytest-env +pytest-mock diff --git a/src/diffpy/fourigui/fourigui.py b/src/diffpy/fourigui/fourigui.py index 770ec1e..ee46dcd 100755 --- a/src/diffpy/fourigui/fourigui.py +++ b/src/diffpy/fourigui/fourigui.py @@ -291,14 +291,11 @@ def load_cube(self): self.slider.grid(row=0, column=0, padx=10, pady=10, sticky=tk.N + tk.E + tk.S + tk.W) if not self.loaded: - fig, ax = plt.subplots(figsize=(4.95, 4.95)) fig = plt.gcf() DPI = fig.get_dpi() fig.set_size_inches(500 / float(DPI), 500 / float(DPI)) - self.plane_num.set(np.shape(self.cube)[0] // 2) - if self.axis.get() == 0: self.im = plt.imshow(self.cube[self.plane_num.get(), :, :]) elif self.axis.get() == 1: @@ -319,7 +316,6 @@ def load_cube(self): self.canvas.draw() self.canvas.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH, expand=1) self.loaded = True - else: self.plot_plane() self.transformed = False diff --git a/tests/unit_test.py b/tests/test_fourigui.py similarity index 59% rename from tests/unit_test.py rename to tests/test_fourigui.py index b3b9ce3..52a556b 100644 --- a/tests/unit_test.py +++ b/tests/test_fourigui.py @@ -1,6 +1,8 @@ +import tkinter as tk import unittest import h5py +import numpy as np from diffpy.fourigui.fourigui import Gui @@ -146,5 +148,81 @@ def test_fft_111(self): self.assertTrue(self.test_gui.transformed and self.test_gui.transcutted) +def test_applycutoff(mocker): + root = tk.Tk() + fg = Gui() + # qmin of 1 and qmax of 2 is expected to leave the central pixel and corner + # pixels as NaN's + mocker.patch.object(fg.qminentry, "get", return_value=1.0) + mocker.patch.object(fg.qmaxentry, "get", return_value=2.0) + mocker.patch.object(fg, "plot_plane") # we don't want it to plot anything so intercept + fg.cutted = False + fg.cube = np.ones((5, 5, 5)) + expected_ones = np.ones((5, 5, 5)) + expected_recip = np.array( + [ + [ + [np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, 1, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + ], + [ + [np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, 1, 1, 1, np.nan], + [np.nan, 1, 1, 1, np.nan], + [np.nan, 1, 1, 1, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + ], + [ + [np.nan, np.nan, 1, np.nan, np.nan], + [np.nan, 1, 1, 1, np.nan], + [1, 1, np.nan, 1, 1], + [np.nan, 1, 1, 1, np.nan], + [np.nan, np.nan, 1, np.nan, np.nan], + ], + [ + [np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, 1, 1, 1, np.nan], + [np.nan, 1, 1, 1, np.nan], + [np.nan, 1, 1, 1, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + ], + [ + [np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, 1, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + [np.nan, np.nan, np.nan, np.nan, np.nan], + ], + ] + ) + # test the case where fg.space is 0 + fg.applycutoff() + np.testing.assert_array_equal(fg.cube_reci, expected_ones) + np.testing.assert_array_equal(fg.cube_recicut, expected_recip) + root.destroy() # Clean up Tkinter instance + + # test the case where fg.space is 1 + root = tk.Tk() + fg = Gui() + # qmin of 1 and qmax of 2 is expected to leave the central pixel and corner + # pixels as NaN's + mocker.patch.object(fg.qminentry, "get", return_value=1) + mocker.patch.object(fg.qmaxentry, "get", return_value=2) + mocker.patch.object( + fg, "fft" + ) # we don't want it to do the fft so intercept. Should be tested separately (fixme). + fg.cutted = False + fg.cube_reci = np.ones((5, 5, 5)) + fg.cube = np.ones((5, 5, 5)) + mocker.patch.object(fg.space, "get", return_value=1) + fg.applycutoff() + np.testing.assert_array_equal(fg.cube_real, expected_ones) + np.testing.assert_array_equal(fg.cube_recicut, expected_recip) + root.destroy() # Clean up Tkinter instance + + if __name__ == "__main__": unittest.main() From 5e74c0b108b83bd1a909d658475f448af4de2dd0 Mon Sep 17 00:00:00 2001 From: Simon Billinge Date: Sat, 9 Nov 2024 01:15:56 -0500 Subject: [PATCH 4/4] removed old bad test for applycutoff --- tests/integration_test.py | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/tests/integration_test.py b/tests/integration_test.py index f9cb74a..f343d5f 100644 --- a/tests/integration_test.py +++ b/tests/integration_test.py @@ -1,5 +1,4 @@ import unittest -import warnings import h5py import numpy as np @@ -98,39 +97,6 @@ def test_fft_testdataset3(self): # then self.assertTrue(np.allclose(result, self.test_gofr_cut_15to35px)) - def test_applycutoff_range1(self): - # given - self.test_gui.plot_plane = lambda *a, **b: () - self.test_gui.cube = self.test_sofq - self.test_gui.qminentry.insert(0, "10") - self.test_gui.qmaxentry.insert(0, "40") - - # when - with warnings.catch_warnings(): - warnings.simplefilter("ignore", category=RuntimeWarning) - self.test_gui.applycutoff() - result = self.test_gui.cube - - # then - self.assertTrue(np.allclose(np.nan_to_num(result), np.nan_to_num(self.test_sofq_cut_10to40px))) - - def test_applycutoff_range2(self): - # given - self.test_gui.plot_plane = lambda *a, **b: () - self.test_gui.cube = self.test_sofq - self.test_gui.qminentry.insert(0, "15") - self.test_gui.qmaxentry.insert(0, "35") - - # when - with warnings.catch_warnings(): - warnings.simplefilter("ignore", category=RuntimeWarning) - self.test_gui.applycutoff() - result = self.test_gui.cube - - # then - # with self.assertWarns(RuntimeWarning): - self.assertTrue(np.allclose(np.nan_to_num(result), np.nan_to_num(self.test_sofq_cut_15to35px))) - if __name__ == "__main__": unittest.main()