diffpy.fourigui 0.1.0rc0__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. {diffpy_fourigui-0.1.0rc0/src/diffpy.fourigui.egg-info → diffpy_fourigui-0.2.0}/PKG-INFO +26 -16
  2. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/README.rst +23 -12
  3. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/pyproject.toml +10 -2
  4. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/requirements/conda.txt +0 -1
  5. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/requirements/pip.txt +0 -1
  6. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/requirements/test.txt +1 -0
  7. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/src/diffpy/fourigui/fourigui.py +43 -33
  8. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0/src/diffpy.fourigui.egg-info}/PKG-INFO +26 -16
  9. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/src/diffpy.fourigui.egg-info/SOURCES.txt +2 -1
  10. diffpy_fourigui-0.2.0/src/diffpy.fourigui.egg-info/entry_points.txt +2 -0
  11. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/src/diffpy.fourigui.egg-info/requires.txt +0 -1
  12. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/integration_test.py +0 -28
  13. diffpy_fourigui-0.1.0rc0/tests/unit_test.py → diffpy_fourigui-0.2.0/tests/test_fourigui.py +78 -0
  14. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/AUTHORS.rst +0 -0
  15. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/LICENSE.rst +0 -0
  16. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/MANIFEST.in +0 -0
  17. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/requirements/build.txt +0 -0
  18. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/requirements/docs.txt +0 -0
  19. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/setup.cfg +0 -0
  20. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/src/diffpy/__init__.py +0 -0
  21. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/src/diffpy/fourigui/__init__.py +0 -0
  22. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/src/diffpy/fourigui/version.py +0 -0
  23. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/src/diffpy.fourigui.egg-info/dependency_links.txt +0 -0
  24. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/src/diffpy.fourigui.egg-info/top_level.txt +0 -0
  25. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/conftest.py +0 -0
  26. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/test_version.py +0 -0
  27. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/testdata/__init__.py +0 -0
  28. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/testdata/dummydata.h5 +0 -0
  29. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/testdata/gofr.h5 +0 -0
  30. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/testdata/gofr_.h5 +0 -0
  31. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/testdata/gofr_cut.h5 +0 -0
  32. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/testdata/gofr_from_sofq_cut_10to40px.h5 +0 -0
  33. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/testdata/gofr_from_sofq_cut_15to35px.h5 +0 -0
  34. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/testdata/make_testdata.py +0 -0
  35. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/testdata/sofq.h5 +0 -0
  36. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/testdata/sofq_cut_10to40px.h5 +0 -0
  37. {diffpy_fourigui-0.1.0rc0 → diffpy_fourigui-0.2.0}/tests/testdata/sofq_cut_15to35px.h5 +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: diffpy.fourigui
3
- Version: 0.1.0rc0
3
+ Version: 0.2.0
4
4
  Summary: Tool for visualizing 3D diffraction and PDF Images.
5
5
  Author-email: "Simon J.L. Billinge group" <simon.billinge@gmail.com>
6
6
  Maintainer-email: "Simon J.L. Billinge group" <simon.billinge@gmail.com>
@@ -16,17 +16,16 @@ Classifier: Operating System :: MacOS :: MacOS X
16
16
  Classifier: Operating System :: Microsoft :: Windows
17
17
  Classifier: Operating System :: POSIX
18
18
  Classifier: Operating System :: Unix
19
- Classifier: Programming Language :: Python :: 3.10
20
19
  Classifier: Programming Language :: Python :: 3.11
21
20
  Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
22
  Classifier: Topic :: Scientific/Engineering :: Physics
23
23
  Classifier: Topic :: Scientific/Engineering :: Chemistry
24
- Requires-Python: >=3.10
24
+ Requires-Python: <3.14,>=3.11
25
25
  Description-Content-Type: text/x-rst
26
26
  License-File: LICENSE.rst
27
27
  License-File: AUTHORS.rst
28
28
  Requires-Dist: h5py
29
- Requires-Dist: time
30
29
  Requires-Dist: tk
31
30
  Requires-Dist: matplotlib
32
31
  Requires-Dist: numpy
@@ -70,7 +69,13 @@ Requires-Dist: numpy
70
69
 
71
70
  Tool for visualizing 3D diffraction and PDF Images.
72
71
 
73
- * LONGER DESCRIPTION HERE
72
+ Diffpy.fourigui is a tool to visualize and process 3D data sets written with the Python programming language.
73
+ Diffpy.fourigui always displays one slice perpendicular to one axis and allows scrolling through the 3D data set along
74
+ the given axis with a slider. It shows feedback values such as global and local maxima, minima or NAN ratios.
75
+ The matplotlib panel e.g. for zooming and saving figures is featured. Diffpy.fourigui is designed for the processing of 3D
76
+ atomic pair distribution functions (PDFs). One can load a 3D reciprocal space scattering volume which can be Fourier
77
+ transformed to the 3D PDF. Thereby, one can apply cut off frequencies beyond and below given Q values, compare the
78
+ results and switch between the scattering volume in reciprocal space and 3D PDF in real space.
74
79
 
75
80
  For more information about the diffpy.fourigui library, please consult our `online documentation <https://diffpy.github.io/diffpy.fourigui>`_.
76
81
 
@@ -79,7 +84,9 @@ Citation
79
84
 
80
85
  If you use diffpy.fourigui in a scientific publication, we would like you to cite this package as
81
86
 
82
- diffpy.fourigui Package, https://github.com/diffpy/diffpy.fourigui
87
+ S. Y. Harouna-Mayer, S. Tao, Z. Gong, M. V. Zimmermann, D. Koziej, A.-C. Dippel, and S. J. L. Billinge,
88
+ `Real-Space Texture and Pole-Figure Analysis Using the 3D Pair Distribution
89
+ Function on a Platinum Thin Film <https://doi.org/10.1107/S2052252522006674>`_. *IUCrJ* **9 (5)**, 594–603 (2022).
83
90
 
84
91
  Installation
85
92
  ------------
@@ -95,20 +102,18 @@ To add "conda-forge" to the conda channels, run the following in a terminal. ::
95
102
  We want to install our packages in a suitable conda environment.
96
103
  The following creates and activates a new environment named ``diffpy.fourigui_env`` ::
97
104
 
98
- conda create -n diffpy.fourigui_env python=3
105
+ conda create -n diffpy.fourigui_env diffpy.fourigui
99
106
  conda activate diffpy.fourigui_env
100
107
 
101
- Then, to fully install ``diffpy.fourigui`` in our active environment, run ::
108
+ To confirm that the installation was successful, type ::
102
109
 
103
- conda install diffpy.fourigui
110
+ python -c "import diffpy.fourigui; print(diffpy.fourigui.__version__)"
104
111
 
105
- Another option is to use ``pip`` to download and install the latest release from
106
- `Python Package Index <https://pypi.python.org>`_.
107
- To install using ``pip`` into your ``diffpy.fourigui_env`` environment, we will also have to install dependencies ::
108
-
109
- pip install -r https://raw.githubusercontent.com/diffpy/diffpy.fourigui/main/requirements/run.txt
112
+ The output should print the latest version displayed on the badges above.
110
113
 
111
- and then install the package ::
114
+ If the above does not work, you can use ``pip`` to download and install the latest release from
115
+ `Python Package Index <https://pypi.python.org>`_.
116
+ To install using ``pip`` into your ``diffpy.fourigui_env`` environment, type ::
112
117
 
113
118
  pip install diffpy.fourigui
114
119
 
@@ -118,6 +123,11 @@ and run the following ::
118
123
 
119
124
  pip install .
120
125
 
126
+ Getting Started
127
+ ---------------
128
+
129
+ You may consult our `online documentation <https://diffpy.github.io/diffpy.fourigui>`_ for tutorials and API references.
130
+
121
131
  Support and Contribute
122
132
  ----------------------
123
133
 
@@ -146,7 +156,7 @@ trying to commit again.
146
156
 
147
157
  Improvements and fixes are always appreciated.
148
158
 
149
- Before contribuing, please read our `Code of Conduct <https://github.com/diffpy/diffpy.fourigui/blob/main/CODE_OF_CONDUCT.rst>`_.
159
+ Before contributing, please read our `Code of Conduct <https://github.com/diffpy/diffpy.fourigui/blob/main/CODE_OF_CONDUCT.rst>`_.
150
160
 
151
161
  Contact
152
162
  -------
@@ -37,7 +37,13 @@
37
37
 
38
38
  Tool for visualizing 3D diffraction and PDF Images.
39
39
 
40
- * LONGER DESCRIPTION HERE
40
+ Diffpy.fourigui is a tool to visualize and process 3D data sets written with the Python programming language.
41
+ Diffpy.fourigui always displays one slice perpendicular to one axis and allows scrolling through the 3D data set along
42
+ the given axis with a slider. It shows feedback values such as global and local maxima, minima or NAN ratios.
43
+ The matplotlib panel e.g. for zooming and saving figures is featured. Diffpy.fourigui is designed for the processing of 3D
44
+ atomic pair distribution functions (PDFs). One can load a 3D reciprocal space scattering volume which can be Fourier
45
+ transformed to the 3D PDF. Thereby, one can apply cut off frequencies beyond and below given Q values, compare the
46
+ results and switch between the scattering volume in reciprocal space and 3D PDF in real space.
41
47
 
42
48
  For more information about the diffpy.fourigui library, please consult our `online documentation <https://diffpy.github.io/diffpy.fourigui>`_.
43
49
 
@@ -46,7 +52,9 @@ Citation
46
52
 
47
53
  If you use diffpy.fourigui in a scientific publication, we would like you to cite this package as
48
54
 
49
- diffpy.fourigui Package, https://github.com/diffpy/diffpy.fourigui
55
+ S. Y. Harouna-Mayer, S. Tao, Z. Gong, M. V. Zimmermann, D. Koziej, A.-C. Dippel, and S. J. L. Billinge,
56
+ `Real-Space Texture and Pole-Figure Analysis Using the 3D Pair Distribution
57
+ Function on a Platinum Thin Film <https://doi.org/10.1107/S2052252522006674>`_. *IUCrJ* **9 (5)**, 594–603 (2022).
50
58
 
51
59
  Installation
52
60
  ------------
@@ -62,20 +70,18 @@ To add "conda-forge" to the conda channels, run the following in a terminal. ::
62
70
  We want to install our packages in a suitable conda environment.
63
71
  The following creates and activates a new environment named ``diffpy.fourigui_env`` ::
64
72
 
65
- conda create -n diffpy.fourigui_env python=3
73
+ conda create -n diffpy.fourigui_env diffpy.fourigui
66
74
  conda activate diffpy.fourigui_env
67
75
 
68
- Then, to fully install ``diffpy.fourigui`` in our active environment, run ::
76
+ To confirm that the installation was successful, type ::
69
77
 
70
- conda install diffpy.fourigui
78
+ python -c "import diffpy.fourigui; print(diffpy.fourigui.__version__)"
71
79
 
72
- Another option is to use ``pip`` to download and install the latest release from
73
- `Python Package Index <https://pypi.python.org>`_.
74
- To install using ``pip`` into your ``diffpy.fourigui_env`` environment, we will also have to install dependencies ::
75
-
76
- pip install -r https://raw.githubusercontent.com/diffpy/diffpy.fourigui/main/requirements/run.txt
80
+ The output should print the latest version displayed on the badges above.
77
81
 
78
- and then install the package ::
82
+ If the above does not work, you can use ``pip`` to download and install the latest release from
83
+ `Python Package Index <https://pypi.python.org>`_.
84
+ To install using ``pip`` into your ``diffpy.fourigui_env`` environment, type ::
79
85
 
80
86
  pip install diffpy.fourigui
81
87
 
@@ -85,6 +91,11 @@ and run the following ::
85
91
 
86
92
  pip install .
87
93
 
94
+ Getting Started
95
+ ---------------
96
+
97
+ You may consult our `online documentation <https://diffpy.github.io/diffpy.fourigui>`_ for tutorials and API references.
98
+
88
99
  Support and Contribute
89
100
  ----------------------
90
101
 
@@ -113,7 +124,7 @@ trying to commit again.
113
124
 
114
125
  Improvements and fixes are always appreciated.
115
126
 
116
- Before contribuing, please read our `Code of Conduct <https://github.com/diffpy/diffpy.fourigui/blob/main/CODE_OF_CONDUCT.rst>`_.
127
+ Before contributing, please read our `Code of Conduct <https://github.com/diffpy/diffpy.fourigui/blob/main/CODE_OF_CONDUCT.rst>`_.
117
128
 
118
129
  Contact
119
130
  -------
@@ -14,7 +14,7 @@ maintainers = [
14
14
  description = "Tool for visualizing 3D diffraction and PDF Images."
15
15
  keywords = ['diffraction', 'pdf', 'pair distribution function', 'gui']
16
16
  readme = "README.rst"
17
- requires-python = ">=3.10"
17
+ requires-python = ">=3.11, <3.14"
18
18
  classifiers = [
19
19
  'Development Status :: 5 - Production/Stable',
20
20
  'Environment :: Console',
@@ -25,13 +25,16 @@ classifiers = [
25
25
  'Operating System :: Microsoft :: Windows',
26
26
  'Operating System :: POSIX',
27
27
  'Operating System :: Unix',
28
- 'Programming Language :: Python :: 3.10',
29
28
  'Programming Language :: Python :: 3.11',
30
29
  'Programming Language :: Python :: 3.12',
30
+ 'Programming Language :: Python :: 3.13',
31
31
  'Topic :: Scientific/Engineering :: Physics',
32
32
  'Topic :: Scientific/Engineering :: Chemistry',
33
33
  ]
34
34
 
35
+ [project.scripts]
36
+ fourigui = "diffpy.fourigui.fourigui:main"
37
+
35
38
  [project.urls]
36
39
  Homepage = "https://github.com/diffpy/diffpy.fourigui/"
37
40
  Issues = "https://github.com/diffpy/diffpy.fourigui/issues/"
@@ -51,6 +54,11 @@ namespaces = false # to disable scanning PEP 420 namespaces (true by default)
51
54
  [tool.setuptools.dynamic]
52
55
  dependencies = {file = ["requirements/pip.txt"]}
53
56
 
57
+ [tool.codespell]
58
+ exclude-file = ".codespell/ignore_lines.txt"
59
+ ignore-words = ".codespell/ignore_words.txt"
60
+ skip = "*.cif,*.dat"
61
+
54
62
  [tool.black]
55
63
  line-length = 115
56
64
  include = '\.pyi?$'
@@ -1,5 +1,4 @@
1
1
  h5py
2
- time
3
2
  tk
4
3
  matplotlib-base
5
4
  numpy
@@ -1,5 +1,4 @@
1
1
  h5py
2
- time
3
2
  tk
4
3
  matplotlib
5
4
  numpy
@@ -4,3 +4,4 @@ codecov
4
4
  coverage
5
5
  pytest-cov
6
6
  pytest-env
7
+ pytest-mock
@@ -1,4 +1,3 @@
1
- import time
2
1
  import tkinter as tk
3
2
  from tkinter.ttk import Button
4
3
 
@@ -22,6 +21,7 @@ class Gui(tk.Frame):
22
21
  self.initUI()
23
22
 
24
23
  def initUI(self):
24
+ """Initialize the GUI for fourigui"""
25
25
 
26
26
  self.loaded = False # denotes whether a dataset is loaded
27
27
  self.transformed = False # denotes whether dataset is Fourier transformed
@@ -155,10 +155,10 @@ class Gui(tk.Frame):
155
155
  anibutton.grid(row=8, column=4)
156
156
 
157
157
  # row 10-12 Fourier transformation
158
- seperator = tk.Label(
158
+ separator = tk.Label(
159
159
  frame00, text=" "
160
160
  ) # __________________________________________________________________")
161
- seperator.grid(row=9, column=0, columnspan=5)
161
+ separator.grid(row=9, column=0, columnspan=5)
162
162
  cutofflabel = tk.Label(frame00, text="cutoff frequency")
163
163
  cutofflabel.grid(row=10, column=2, columnspan=2)
164
164
  qminlabel = tk.Label(frame00, text="qmin [px]:")
@@ -291,14 +291,11 @@ class Gui(tk.Frame):
291
291
  self.slider.grid(row=0, column=0, padx=10, pady=10, sticky=tk.N + tk.E + tk.S + tk.W)
292
292
 
293
293
  if not self.loaded:
294
-
295
294
  fig, ax = plt.subplots(figsize=(4.95, 4.95))
296
295
  fig = plt.gcf()
297
296
  DPI = fig.get_dpi()
298
297
  fig.set_size_inches(500 / float(DPI), 500 / float(DPI))
299
-
300
298
  self.plane_num.set(np.shape(self.cube)[0] // 2)
301
-
302
299
  if self.axis.get() == 0:
303
300
  self.im = plt.imshow(self.cube[self.plane_num.get(), :, :])
304
301
  elif self.axis.get() == 1:
@@ -319,7 +316,6 @@ class Gui(tk.Frame):
319
316
  self.canvas.draw()
320
317
  self.canvas.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
321
318
  self.loaded = True
322
-
323
319
  else:
324
320
  self.plot_plane()
325
321
  self.transformed = False
@@ -371,18 +367,18 @@ class Gui(tk.Frame):
371
367
  elif self.axis.get() == 2:
372
368
  plane = self.cube[:, :, self.plane_num.get()]
373
369
  nan_ratio = np.count_nonzero(np.isnan(plane)) / plane.size
374
- self.localmax["text"] = "{}".format(np.format_float_scientific(np.nanmax(plane), 1))
375
- self.localmin["text"] = "{}".format(np.format_float_scientific(np.nanmin(plane), 1))
376
- self.localsum["text"] = "{}".format(np.format_float_scientific(np.nansum(plane), 1))
377
- self.localnanratio["text"] = "{}".format(round(nan_ratio, 2))
370
+ self.localmax["text"] = f"{np.format_float_scientific(np.nanmax(plane), 1)}"
371
+ self.localmin["text"] = f"{np.format_float_scientific(np.nanmin(plane), 1)}"
372
+ self.localsum["text"] = f"{np.format_float_scientific(np.nansum(plane), 1)}"
373
+ self.localnanratio["text"] = f"{round(nan_ratio, 2)}"
378
374
 
379
375
  def intensity_upd_global(self):
380
- """show global intensity minimum, maximum and sum of 3D array"""
376
+ """Load global intensity minimum, maximum and sum of 3D array"""
381
377
  self.intensity_upd_local()
382
378
  nan_ratio = np.count_nonzero(np.isnan(self.cube)) / self.cube.size
383
- self.globalmax["text"] = "{}".format(np.format_float_scientific(np.nanmax(self.cube), 1))
384
- self.globalmin["text"] = "{}".format(np.format_float_scientific(np.nanmin(self.cube), 1))
385
- self.globalsum["text"] = "{}".format(np.format_float_scientific(np.nansum(self.cube), 1))
379
+ self.globalmax["text"] = f"{np.format_float_scientific(np.nanmax(self.cube), 1)}"
380
+ self.globalmin["text"] = f"{np.format_float_scientific(np.nanmin(self.cube), 1)}"
381
+ self.globalsum["text"] = f"{np.format_float_scientific(np.nansum(self.cube), 1)}"
386
382
  self.globalnanratio["text"] = "{}".format(round(nan_ratio, 2))
387
383
 
388
384
  def fft(self):
@@ -392,15 +388,13 @@ class Gui(tk.Frame):
392
388
  """
393
389
 
394
390
  def perform_fft(fftholder):
395
- time0 = time.time()
396
391
  fftholder = np.nan_to_num(fftholder)
397
392
  size = list(fftholder.shape)
393
+ axes = list(range(fftholder.ndim))
398
394
  fftholder = np.fft.ifftshift(fftholder)
399
- fftholder = np.fft.fftn(fftholder, s=size, norm="ortho")
395
+ fftholder = np.fft.fftn(fftholder, s=size, axes=axes, norm="ortho")
400
396
  fftholder = np.fft.fftshift(fftholder)
401
397
  fftholder = fftholder.real
402
- fftdur = time.time() - time0
403
- print("- FFT performed in {} sec.".format(round(fftdur, 4)))
404
398
  return fftholder
405
399
 
406
400
  if not self.transformed and not self.transcutted: # no fft at all yet
@@ -462,33 +456,38 @@ class Gui(tk.Frame):
462
456
 
463
457
  def applycutoff(self):
464
458
  """
459
+ shape the reciprocal-space array
460
+
465
461
  reassign all voxels with distance smaller than qmin and greater than qmax
466
- from the central voxel to 0.0
462
+ to np.nan.
463
+
464
+ parameters:
465
+ -----------
467
466
  qmin, qmax is loaded from the qmin, qmax input panel
468
- currently opperates in units of pixels
467
+ currently operates in units of pixels
468
+
469
+ Returns:
470
+ --------
471
+ nothing
469
472
  """
470
473
  if not self.cutted:
471
-
472
- time0 = time.time()
473
- X, Y, Z = self.cube.shape
474
- sphere = np.ones((X, Y, Z))
474
+ xdim, ydim, zdim = self.cube.shape
475
+ sphere = np.ones((xdim, ydim, zdim))
475
476
  qmin = float(self.qminentry.get())
476
477
  qmax = float(self.qmaxentry.get())
477
478
  # convert qmin to pixels
478
479
  # convert qmax to pixels
479
480
  r2_inner = qmin**2
480
481
  r2_outer = qmax**2
481
- XS, YS, ZS = np.meshgrid(np.arange(X), np.arange(Y), np.arange(Z))
482
- R2 = (XS - X // 2) ** 2 + (YS - Y // 2) ** 2 + (ZS - Z // 2) ** 2
483
- mask = (R2 <= r2_inner) | (R2 >= r2_outer)
484
- sphere[mask] = np.nan
485
- cutdur = time.time() - time0
482
+ i, j, k = np.meshgrid(np.arange(xdim), np.arange(ydim), np.arange(zdim))
483
+ r2 = (i - xdim // 2) ** 2 + (j - ydim // 2) ** 2 + (k - zdim // 2) ** 2
484
+ mask = (r2 < r2_inner) | (r2 > r2_outer) # True if voxel is out of range
485
+ sphere[mask] = np.nan # therefore set to np.nan if out of range
486
486
 
487
487
  if self.space.get():
488
488
  self.cube_real = self.cube
489
489
  self.cube = self.cube_reci * sphere
490
490
  self.cube_recicut = self.cube
491
- print("- Cutoff below {} and beyond {} in {} sec.".format(qmin, qmax, round(cutdur, 4)))
492
491
  self.fft()
493
492
  else:
494
493
  self.cube_reci = self.cube
@@ -496,7 +495,6 @@ class Gui(tk.Frame):
496
495
  self.cube_recicut = self.cube
497
496
  self.plot_plane()
498
497
  self.intensity_upd_global()
499
- print("- Cutoff below {} and beyond {} in {} sec.".format(qmin, qmax, round(cutdur, 4)))
500
498
 
501
499
  self.cutted = True
502
500
 
@@ -509,6 +507,9 @@ class Gui(tk.Frame):
509
507
  self.intensity_upd_global()
510
508
 
511
509
  def redocutuff(self):
510
+ """
511
+ Redo the cutoff operation depending on the current space (real or reciprocal).
512
+ """
512
513
  if self.space.get(): # in real space
513
514
  self.cube_realcut = self.cube
514
515
  if not self.transformed:
@@ -521,6 +522,9 @@ class Gui(tk.Frame):
521
522
  self.intensity_upd_global()
522
523
 
523
524
  def newcutoff(self):
525
+ """
526
+ Apply a new cutoff based on the current space and cutoff settings.
527
+ """
524
528
  if self.cutoff.get():
525
529
  if self.space.get() and self.transformed:
526
530
  self.cube = self.cube_real
@@ -531,6 +535,9 @@ class Gui(tk.Frame):
531
535
  self.applycutoff()
532
536
 
533
537
  def plot_next_plane(self):
538
+ """
539
+ Plot the next plane in the dataset, looping back to the first if at the end.
540
+ """
534
541
  n = self.plane_num.get()
535
542
  if n == len(self.cube[self.axis.get()]) - 1:
536
543
  n = 0
@@ -541,7 +548,7 @@ class Gui(tk.Frame):
541
548
 
542
549
  def animation(self):
543
550
  """
544
- slices through the 3D array along the selcted axis
551
+ slices through the 3D array along the selected axis
545
552
  """
546
553
  try:
547
554
  if not self.anientry.get():
@@ -556,6 +563,9 @@ class Gui(tk.Frame):
556
563
  self.plot_next_plane()
557
564
 
558
565
  def multiple_funcs(*funcs):
566
+ """
567
+ Executes multiple functions passed as arguments in sequence.
568
+ """
559
569
  for func in funcs:
560
570
  func
561
571
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: diffpy.fourigui
3
- Version: 0.1.0rc0
3
+ Version: 0.2.0
4
4
  Summary: Tool for visualizing 3D diffraction and PDF Images.
5
5
  Author-email: "Simon J.L. Billinge group" <simon.billinge@gmail.com>
6
6
  Maintainer-email: "Simon J.L. Billinge group" <simon.billinge@gmail.com>
@@ -16,17 +16,16 @@ Classifier: Operating System :: MacOS :: MacOS X
16
16
  Classifier: Operating System :: Microsoft :: Windows
17
17
  Classifier: Operating System :: POSIX
18
18
  Classifier: Operating System :: Unix
19
- Classifier: Programming Language :: Python :: 3.10
20
19
  Classifier: Programming Language :: Python :: 3.11
21
20
  Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
22
  Classifier: Topic :: Scientific/Engineering :: Physics
23
23
  Classifier: Topic :: Scientific/Engineering :: Chemistry
24
- Requires-Python: >=3.10
24
+ Requires-Python: <3.14,>=3.11
25
25
  Description-Content-Type: text/x-rst
26
26
  License-File: LICENSE.rst
27
27
  License-File: AUTHORS.rst
28
28
  Requires-Dist: h5py
29
- Requires-Dist: time
30
29
  Requires-Dist: tk
31
30
  Requires-Dist: matplotlib
32
31
  Requires-Dist: numpy
@@ -70,7 +69,13 @@ Requires-Dist: numpy
70
69
 
71
70
  Tool for visualizing 3D diffraction and PDF Images.
72
71
 
73
- * LONGER DESCRIPTION HERE
72
+ Diffpy.fourigui is a tool to visualize and process 3D data sets written with the Python programming language.
73
+ Diffpy.fourigui always displays one slice perpendicular to one axis and allows scrolling through the 3D data set along
74
+ the given axis with a slider. It shows feedback values such as global and local maxima, minima or NAN ratios.
75
+ The matplotlib panel e.g. for zooming and saving figures is featured. Diffpy.fourigui is designed for the processing of 3D
76
+ atomic pair distribution functions (PDFs). One can load a 3D reciprocal space scattering volume which can be Fourier
77
+ transformed to the 3D PDF. Thereby, one can apply cut off frequencies beyond and below given Q values, compare the
78
+ results and switch between the scattering volume in reciprocal space and 3D PDF in real space.
74
79
 
75
80
  For more information about the diffpy.fourigui library, please consult our `online documentation <https://diffpy.github.io/diffpy.fourigui>`_.
76
81
 
@@ -79,7 +84,9 @@ Citation
79
84
 
80
85
  If you use diffpy.fourigui in a scientific publication, we would like you to cite this package as
81
86
 
82
- diffpy.fourigui Package, https://github.com/diffpy/diffpy.fourigui
87
+ S. Y. Harouna-Mayer, S. Tao, Z. Gong, M. V. Zimmermann, D. Koziej, A.-C. Dippel, and S. J. L. Billinge,
88
+ `Real-Space Texture and Pole-Figure Analysis Using the 3D Pair Distribution
89
+ Function on a Platinum Thin Film <https://doi.org/10.1107/S2052252522006674>`_. *IUCrJ* **9 (5)**, 594–603 (2022).
83
90
 
84
91
  Installation
85
92
  ------------
@@ -95,20 +102,18 @@ To add "conda-forge" to the conda channels, run the following in a terminal. ::
95
102
  We want to install our packages in a suitable conda environment.
96
103
  The following creates and activates a new environment named ``diffpy.fourigui_env`` ::
97
104
 
98
- conda create -n diffpy.fourigui_env python=3
105
+ conda create -n diffpy.fourigui_env diffpy.fourigui
99
106
  conda activate diffpy.fourigui_env
100
107
 
101
- Then, to fully install ``diffpy.fourigui`` in our active environment, run ::
108
+ To confirm that the installation was successful, type ::
102
109
 
103
- conda install diffpy.fourigui
110
+ python -c "import diffpy.fourigui; print(diffpy.fourigui.__version__)"
104
111
 
105
- Another option is to use ``pip`` to download and install the latest release from
106
- `Python Package Index <https://pypi.python.org>`_.
107
- To install using ``pip`` into your ``diffpy.fourigui_env`` environment, we will also have to install dependencies ::
108
-
109
- pip install -r https://raw.githubusercontent.com/diffpy/diffpy.fourigui/main/requirements/run.txt
112
+ The output should print the latest version displayed on the badges above.
110
113
 
111
- and then install the package ::
114
+ If the above does not work, you can use ``pip`` to download and install the latest release from
115
+ `Python Package Index <https://pypi.python.org>`_.
116
+ To install using ``pip`` into your ``diffpy.fourigui_env`` environment, type ::
112
117
 
113
118
  pip install diffpy.fourigui
114
119
 
@@ -118,6 +123,11 @@ and run the following ::
118
123
 
119
124
  pip install .
120
125
 
126
+ Getting Started
127
+ ---------------
128
+
129
+ You may consult our `online documentation <https://diffpy.github.io/diffpy.fourigui>`_ for tutorials and API references.
130
+
121
131
  Support and Contribute
122
132
  ----------------------
123
133
 
@@ -146,7 +156,7 @@ trying to commit again.
146
156
 
147
157
  Improvements and fixes are always appreciated.
148
158
 
149
- Before contribuing, please read our `Code of Conduct <https://github.com/diffpy/diffpy.fourigui/blob/main/CODE_OF_CONDUCT.rst>`_.
159
+ Before contributing, please read our `Code of Conduct <https://github.com/diffpy/diffpy.fourigui/blob/main/CODE_OF_CONDUCT.rst>`_.
150
160
 
151
161
  Contact
152
162
  -------
@@ -12,6 +12,7 @@ src/diffpy/__init__.py
12
12
  src/diffpy.fourigui.egg-info/PKG-INFO
13
13
  src/diffpy.fourigui.egg-info/SOURCES.txt
14
14
  src/diffpy.fourigui.egg-info/dependency_links.txt
15
+ src/diffpy.fourigui.egg-info/entry_points.txt
15
16
  src/diffpy.fourigui.egg-info/requires.txt
16
17
  src/diffpy.fourigui.egg-info/top_level.txt
17
18
  src/diffpy/fourigui/__init__.py
@@ -19,8 +20,8 @@ src/diffpy/fourigui/fourigui.py
19
20
  src/diffpy/fourigui/version.py
20
21
  tests/conftest.py
21
22
  tests/integration_test.py
23
+ tests/test_fourigui.py
22
24
  tests/test_version.py
23
- tests/unit_test.py
24
25
  tests/testdata/__init__.py
25
26
  tests/testdata/dummydata.h5
26
27
  tests/testdata/gofr.h5
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ fourigui = diffpy.fourigui.fourigui:main
@@ -97,34 +97,6 @@ class TestGui(unittest.TestCase):
97
97
  # then
98
98
  self.assertTrue(np.allclose(result, self.test_gofr_cut_15to35px))
99
99
 
100
- def test_applycutoff_range1(self):
101
- # given
102
- self.test_gui.plot_plane = lambda *a, **b: ()
103
- self.test_gui.cube = self.test_sofq
104
- self.test_gui.qminentry.insert(0, "10")
105
- self.test_gui.qmaxentry.insert(0, "40")
106
-
107
- # when
108
- self.test_gui.applycutoff()
109
- result = self.test_gui.cube
110
-
111
- # then
112
- self.assertTrue(np.allclose(np.nan_to_num(result), np.nan_to_num(self.test_sofq_cut_10to40px)))
113
-
114
- def test_applycutoff_range2(self):
115
- # given
116
- self.test_gui.plot_plane = lambda *a, **b: ()
117
- self.test_gui.cube = self.test_sofq
118
- self.test_gui.qminentry.insert(0, "15")
119
- self.test_gui.qmaxentry.insert(0, "35")
120
-
121
- # when
122
- self.test_gui.applycutoff()
123
- result = self.test_gui.cube
124
-
125
- # then
126
- self.assertTrue(np.allclose(np.nan_to_num(result), np.nan_to_num(self.test_sofq_cut_15to35px)))
127
-
128
100
 
129
101
  if __name__ == "__main__":
130
102
  unittest.main()
@@ -1,6 +1,8 @@
1
+ import tkinter as tk
1
2
  import unittest
2
3
 
3
4
  import h5py
5
+ import numpy as np
4
6
 
5
7
  from diffpy.fourigui.fourigui import Gui
6
8
 
@@ -146,5 +148,81 @@ class TestGui(unittest.TestCase):
146
148
  self.assertTrue(self.test_gui.transformed and self.test_gui.transcutted)
147
149
 
148
150
 
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
+
149
227
  if __name__ == "__main__":
150
228
  unittest.main()