Skip to content

Commit dfc8bbd

Browse files
authored
Merge pull request #63 from sbillinge/gt2
Test for correct applycutoff
2 parents d4c91b2 + fae69cf commit dfc8bbd

File tree

5 files changed

+103
-45
lines changed

5 files changed

+103
-45
lines changed

Diff for: news/gt.rst

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
**Added:**
2+
3+
* <news item>
4+
5+
**Changed:**
6+
7+
* <news item>
8+
9+
**Deprecated:**
10+
11+
* <news item>
12+
13+
**Removed:**
14+
15+
* <news item>
16+
17+
**Fixed:**
18+
19+
* qmin/qmax limits in reciprocal space grid so qmin and qmax are not excluded
20+
21+
**Security:**
22+
23+
* <news item>

Diff for: requirements/test.txt

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ codecov
44
coverage
55
pytest-cov
66
pytest-env
7+
pytest-mock

Diff for: src/diffpy/fourigui/fourigui.py

+1-5
Original file line numberDiff line numberDiff line change
@@ -291,14 +291,11 @@ def load_cube(self):
291291
self.slider.grid(row=0, column=0, padx=10, pady=10, sticky=tk.N + tk.E + tk.S + tk.W)
292292

293293
if not self.loaded:
294-
295294
fig, ax = plt.subplots(figsize=(4.95, 4.95))
296295
fig = plt.gcf()
297296
DPI = fig.get_dpi()
298297
fig.set_size_inches(500 / float(DPI), 500 / float(DPI))
299-
300298
self.plane_num.set(np.shape(self.cube)[0] // 2)
301-
302299
if self.axis.get() == 0:
303300
self.im = plt.imshow(self.cube[self.plane_num.get(), :, :])
304301
elif self.axis.get() == 1:
@@ -319,7 +316,6 @@ def load_cube(self):
319316
self.canvas.draw()
320317
self.canvas.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
321318
self.loaded = True
322-
323319
else:
324320
self.plot_plane()
325321
self.transformed = False
@@ -485,7 +481,7 @@ def applycutoff(self):
485481
r2_outer = qmax**2
486482
i, j, k = np.meshgrid(np.arange(xdim), np.arange(ydim), np.arange(zdim))
487483
r2 = (i - xdim // 2) ** 2 + (j - ydim // 2) ** 2 + (k - zdim // 2) ** 2
488-
mask = (r2 <= r2_inner) | (r2 >= r2_outer) # True if voxel is out of range
484+
mask = (r2 < r2_inner) | (r2 > r2_outer) # True if voxel is out of range
489485
sphere[mask] = np.nan # therefore set to np.nan if out of range
490486

491487
if self.space.get():

Diff for: tests/integration_test.py

-40
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import unittest
2-
import warnings
32

43
import h5py
54
import numpy as np
@@ -98,45 +97,6 @@ def test_fft_testdataset3(self):
9897
# then
9998
self.assertTrue(np.allclose(result, self.test_gofr_cut_15to35px))
10099

101-
def test_applycutoff_range1(self):
102-
# given
103-
self.test_gui.plot_plane = lambda *a, **b: ()
104-
self.test_gui.cube = self.test_sofq
105-
self.test_gui.qminentry.insert(0, "10")
106-
self.test_gui.qmaxentry.insert(0, "40")
107-
108-
# Desired behavior is nans in the arrays below qmin and above qmax. As a result, np.nanmax will generate
109-
# runtimewarnings when it # encounters slices that are all nans. capture these so tests pass cleanly
110-
# without warnings
111-
with warnings.catch_warnings():
112-
warnings.simplefilter("ignore", category=RuntimeWarning)
113-
# when
114-
self.test_gui.applycutoff()
115-
result = self.test_gui.cube
116-
117-
# then
118-
self.assertTrue(np.allclose(np.nan_to_num(result), np.nan_to_num(self.test_sofq_cut_10to40px)))
119-
120-
def test_applycutoff_range2(self):
121-
# given
122-
self.test_gui.plot_plane = lambda *a, **b: ()
123-
self.test_gui.cube = self.test_sofq
124-
self.test_gui.qminentry.insert(0, "15")
125-
self.test_gui.qmaxentry.insert(0, "35")
126-
127-
# Desired behavior is nans in the arrays below qmin and above qmax. As a result, np.nanmax will generate
128-
# runtimewarnings when it # encounters slices that are all nans. capture these so tests pass cleanly
129-
# without warnings
130-
with warnings.catch_warnings():
131-
warnings.simplefilter("ignore", category=RuntimeWarning)
132-
# when
133-
self.test_gui.applycutoff()
134-
result = self.test_gui.cube
135-
136-
# then
137-
# with self.assertWarns(RuntimeWarning):
138-
self.assertTrue(np.allclose(np.nan_to_num(result), np.nan_to_num(self.test_sofq_cut_15to35px)))
139-
140100

141101
if __name__ == "__main__":
142102
unittest.main()

Diff for: tests/unit_test.py renamed to tests/test_fourigui.py

+78
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import tkinter as tk
12
import unittest
23

34
import h5py
5+
import numpy as np
46

57
from diffpy.fourigui.fourigui import Gui
68

@@ -146,5 +148,81 @@ def test_fft_111(self):
146148
self.assertTrue(self.test_gui.transformed and self.test_gui.transcutted)
147149

148150

151+
def test_applycutoff(mocker):
152+
root = tk.Tk()
153+
fg = Gui()
154+
# qmin of 1 and qmax of 2 is expected to leave the central pixel and corner
155+
# pixels as NaN's
156+
mocker.patch.object(fg.qminentry, "get", return_value=1.0)
157+
mocker.patch.object(fg.qmaxentry, "get", return_value=2.0)
158+
mocker.patch.object(fg, "plot_plane") # we don't want it to plot anything so intercept
159+
fg.cutted = False
160+
fg.cube = np.ones((5, 5, 5))
161+
expected_ones = np.ones((5, 5, 5))
162+
expected_recip = np.array(
163+
[
164+
[
165+
[np.nan, np.nan, np.nan, np.nan, np.nan],
166+
[np.nan, np.nan, np.nan, np.nan, np.nan],
167+
[np.nan, np.nan, 1, np.nan, np.nan],
168+
[np.nan, np.nan, np.nan, np.nan, np.nan],
169+
[np.nan, np.nan, np.nan, np.nan, np.nan],
170+
],
171+
[
172+
[np.nan, np.nan, np.nan, np.nan, np.nan],
173+
[np.nan, 1, 1, 1, np.nan],
174+
[np.nan, 1, 1, 1, np.nan],
175+
[np.nan, 1, 1, 1, np.nan],
176+
[np.nan, np.nan, np.nan, np.nan, np.nan],
177+
],
178+
[
179+
[np.nan, np.nan, 1, np.nan, np.nan],
180+
[np.nan, 1, 1, 1, np.nan],
181+
[1, 1, np.nan, 1, 1],
182+
[np.nan, 1, 1, 1, np.nan],
183+
[np.nan, np.nan, 1, np.nan, np.nan],
184+
],
185+
[
186+
[np.nan, np.nan, np.nan, np.nan, np.nan],
187+
[np.nan, 1, 1, 1, np.nan],
188+
[np.nan, 1, 1, 1, np.nan],
189+
[np.nan, 1, 1, 1, np.nan],
190+
[np.nan, np.nan, np.nan, np.nan, np.nan],
191+
],
192+
[
193+
[np.nan, np.nan, np.nan, np.nan, np.nan],
194+
[np.nan, np.nan, np.nan, np.nan, np.nan],
195+
[np.nan, np.nan, 1, np.nan, np.nan],
196+
[np.nan, np.nan, np.nan, np.nan, np.nan],
197+
[np.nan, np.nan, np.nan, np.nan, np.nan],
198+
],
199+
]
200+
)
201+
# test the case where fg.space is 0
202+
fg.applycutoff()
203+
np.testing.assert_array_equal(fg.cube_reci, expected_ones)
204+
np.testing.assert_array_equal(fg.cube_recicut, expected_recip)
205+
root.destroy() # Clean up Tkinter instance
206+
207+
# test the case where fg.space is 1
208+
root = tk.Tk()
209+
fg = Gui()
210+
# qmin of 1 and qmax of 2 is expected to leave the central pixel and corner
211+
# pixels as NaN's
212+
mocker.patch.object(fg.qminentry, "get", return_value=1)
213+
mocker.patch.object(fg.qmaxentry, "get", return_value=2)
214+
mocker.patch.object(
215+
fg, "fft"
216+
) # we don't want it to do the fft so intercept. Should be tested separately (fixme).
217+
fg.cutted = False
218+
fg.cube_reci = np.ones((5, 5, 5))
219+
fg.cube = np.ones((5, 5, 5))
220+
mocker.patch.object(fg.space, "get", return_value=1)
221+
fg.applycutoff()
222+
np.testing.assert_array_equal(fg.cube_real, expected_ones)
223+
np.testing.assert_array_equal(fg.cube_recicut, expected_recip)
224+
root.destroy() # Clean up Tkinter instance
225+
226+
149227
if __name__ == "__main__":
150228
unittest.main()

0 commit comments

Comments
 (0)