orGUI 1.0.1__py3-none-any.whl

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 (83) hide show
  1. orGUI-1.0.1.dist-info/LICENSE +21 -0
  2. orGUI-1.0.1.dist-info/METADATA +147 -0
  3. orGUI-1.0.1.dist-info/RECORD +83 -0
  4. orGUI-1.0.1.dist-info/WHEEL +5 -0
  5. orGUI-1.0.1.dist-info/entry_points.txt +2 -0
  6. orGUI-1.0.1.dist-info/top_level.txt +1 -0
  7. orgui/__init__.py +36 -0
  8. orgui/app/ArrayTableDialog.py +433 -0
  9. orgui/app/QReflectionSelector.py +538 -0
  10. orgui/app/QScanSelector.py +692 -0
  11. orgui/app/QUBCalculator.py +1210 -0
  12. orgui/app/__init__.py +36 -0
  13. orgui/app/database.py +487 -0
  14. orgui/app/orGUI.py +2613 -0
  15. orgui/app/qutils.py +51 -0
  16. orgui/backend/__init__.py +32 -0
  17. orgui/backend/backends.py +157 -0
  18. orgui/backend/beamline/ID31DiffractLinTilt.py +77 -0
  19. orgui/backend/beamline/P212_tools.py +577 -0
  20. orgui/backend/beamline/__init__.py +36 -0
  21. orgui/backend/beamline/fio_reader.py +110 -0
  22. orgui/backend/beamline/id31_tools.py +651 -0
  23. orgui/backend/scans.py +95 -0
  24. orgui/backend/udefaults.py +163 -0
  25. orgui/backend/universalScanLoader.py +105 -0
  26. orgui/datautils/__init__.py +32 -0
  27. orgui/datautils/util.py +705 -0
  28. orgui/datautils/xrayutils/CTRcalc.py +3022 -0
  29. orgui/datautils/xrayutils/CTRopt.py +623 -0
  30. orgui/datautils/xrayutils/CTRplotutil.py +904 -0
  31. orgui/datautils/xrayutils/DetectorCalibration.py +685 -0
  32. orgui/datautils/xrayutils/HKLVlieg.py +1360 -0
  33. orgui/datautils/xrayutils/ReciprocalNavigation.py +401 -0
  34. orgui/datautils/xrayutils/_CTRcalc_accel.py +181 -0
  35. orgui/datautils/xrayutils/__init__.py +46 -0
  36. orgui/datautils/xrayutils/element_data.py +213 -0
  37. orgui/datautils/xrayutils/test/__init__.py +57 -0
  38. orgui/datautils/xrayutils/test/test_CTRcalc.py +152 -0
  39. orgui/datautils/xrayutils/test/test_DetectorCalibration.py +336 -0
  40. orgui/datautils/xrayutils/test/test_HKLcalc.py +88 -0
  41. orgui/datautils/xrayutils/unitcells/Fe3O4(100).bul +59 -0
  42. orgui/datautils/xrayutils/unitcells/Pt100.bul +7 -0
  43. orgui/datautils/xrayutils/unitcells/Pt100_small.bul +5 -0
  44. orgui/datautils/xrayutils/unitcells/Pt110.bul +5 -0
  45. orgui/datautils/xrayutils/unitcells/Pt111.bul +6 -0
  46. orgui/datautils/xrayutils/unitcells/Pt310.bul +13 -0
  47. orgui/datautils/xrayutils/unitcells/Pt3O4(100).bul +19 -0
  48. orgui/datautils/xrayutils/unitcells/PtO(001).bul +9 -0
  49. orgui/datautils/xrayutils/unitcells/PtO(010).bul +9 -0
  50. orgui/datautils/xrayutils/unitcells/PtO(100).bul +9 -0
  51. orgui/datautils/xrayutils/unitcells/__init__.py +67 -0
  52. orgui/datautils/xrayutils/unitcells/a-PtO2(0001).bul +6 -0
  53. orgui/main.py +101 -0
  54. orgui/resources/__init__.py +40 -0
  55. orgui/resources/icons/alpha.png +0 -0
  56. orgui/resources/icons/alpha.svg +67 -0
  57. orgui/resources/icons/diffractometer_v3.png +0 -0
  58. orgui/resources/icons/disable-image.png +0 -0
  59. orgui/resources/icons/disable-image.svg +68 -0
  60. orgui/resources/icons/document-nx-open.png +0 -0
  61. orgui/resources/icons/document-nx-open.svg +152 -0
  62. orgui/resources/icons/document-nx-save.png +0 -0
  63. orgui/resources/icons/document-nx-save.svg +73 -0
  64. orgui/resources/icons/logo.png +0 -0
  65. orgui/resources/icons/logo.svg +808 -0
  66. orgui/resources/icons/max_image.png +0 -0
  67. orgui/resources/icons/max_image.svg +77 -0
  68. orgui/resources/icons/max_image2.png +0 -0
  69. orgui/resources/icons/max_image2.svg +83 -0
  70. orgui/resources/icons/search-image.png +0 -0
  71. orgui/resources/icons/search-image.svg +94 -0
  72. orgui/resources/icons/search-reflection.png +0 -0
  73. orgui/resources/icons/search-reflection.svg +126 -0
  74. orgui/resources/icons/search.png +0 -0
  75. orgui/resources/icons/search.svg +91 -0
  76. orgui/resources/icons/select-image.png +0 -0
  77. orgui/resources/icons/select-image.svg +60 -0
  78. orgui/resources/icons/set-reflection.png +0 -0
  79. orgui/resources/icons/set-reflection.svg +91 -0
  80. orgui/resources/icons/sum_image.png +0 -0
  81. orgui/resources/icons/sum_image.svg +63 -0
  82. orgui/resources/icons/sum_image2.png +0 -0
  83. orgui/resources/icons/sum_image2.svg +75 -0
@@ -0,0 +1,336 @@
1
+ # -*- coding: utf-8 -*-
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2020-2024 Timo Fuchs
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+ __author__ = "Timo Fuchs"
26
+ __copyright__ = "Copyright 2020-2024 Timo Fuchs"
27
+ __license__ = "MIT License"
28
+ __version__ = "1.0.0"
29
+ __maintainer__ = "Timo Fuchs"
30
+ __email__ = "fuchs@physik.uni-kiel.de"
31
+
32
+ import unittest
33
+
34
+ from .. import DetectorCalibration
35
+ import pyFAI
36
+
37
+ import numpy as np
38
+ import os
39
+ import warnings
40
+
41
+ try:
42
+ from silx.io import dictdump
43
+ silx_avail = True
44
+ except:
45
+ silx_avail = False
46
+
47
+
48
+ class TestRWDetector2D_SXRD(unittest.TestCase):
49
+
50
+ def setUp(self):
51
+ self.sxrddet = DetectorCalibration.Detector2D_SXRD()
52
+ self.sxrddet.detector = pyFAI.detector_factory('Pilatus 2M CdTe')
53
+ self.sxrddet.poni1 = 0.1
54
+ self.sxrddet.poni2 = 0.1
55
+ self.sxrddet.rot1 = np.pi/20
56
+ self.sxrddet.rot2 = -np.pi/20
57
+ self.sxrddet.rot3 = 0
58
+ self.sxrddet.dist = 1.5
59
+ self.sxrddet.setAzimuthalReference(np.deg2rad(90.))
60
+ self.sxrddet.setPolarization(np.deg2rad(90.), 0.75)
61
+
62
+ def test_from_to_dict(self):
63
+ nxdict = self.sxrddet.toNXdict()
64
+ othersxrddet = DetectorCalibration.Detector2D_SXRD()
65
+ othersxrddet.fromNXdict(nxdict)
66
+ self.check_sxrd_equal(othersxrddet)
67
+
68
+ def check_sxrd_equal(self, other):
69
+ self.assertDictEqual(self.sxrddet.getPyFAI(), other.getPyFAI())
70
+ self.assertEqual(self.sxrddet._polFactor, other._polFactor)
71
+ self.assertEqual(self.sxrddet._polAxis, other._polAxis)
72
+ self.assertEqual(self.sxrddet._deltaChi, other._deltaChi)
73
+
74
+ @unittest.skipUnless(silx_avail, "silx not available")
75
+ def test_write_nx(self):
76
+ self._nxfilename = "./detcal_test.nx"
77
+ self.addCleanup(self._destruct_file, self._nxfilename)
78
+
79
+ nxdict = self.sxrddet.toNXdict()
80
+ dictdump.dicttonx(nxdict, self._nxfilename)
81
+ self.assertTrue(os.path.isfile(self._nxfilename))
82
+ os.remove(self._nxfilename)
83
+
84
+ @unittest.skipUnless(silx_avail, "silx not available")
85
+ def test_read_write_nx(self):
86
+ self._nxfilename = "./detcal_test.nx"
87
+ self.addCleanup(self._destruct_file, self._nxfilename)
88
+
89
+ nxdict = self.sxrddet.toNXdict()
90
+ dictdump.dicttonx(nxdict, self._nxfilename)
91
+
92
+ read_dict = dictdump.nxtodict(self._nxfilename)
93
+ othersxrddet = DetectorCalibration.Detector2D_SXRD()
94
+ othersxrddet.fromNXdict(read_dict)
95
+ self.check_sxrd_equal(othersxrddet)
96
+
97
+ othersxrddet = DetectorCalibration.loadNXdict(read_dict)
98
+ self.check_sxrd_equal(othersxrddet)
99
+
100
+ os.remove(self._nxfilename)
101
+
102
+
103
+ def _destruct_file(self, filename):
104
+ if os.path.exists(filename):
105
+ os.remove(self._nxfilename)
106
+
107
+
108
+ class TestAnglePixelConversion(unittest.TestCase):
109
+
110
+ def setUp(self):
111
+ self.sxrddet = DetectorCalibration.Detector2D_SXRD()
112
+ self.sxrddet.detector = pyFAI.detector_factory('Pilatus 2M CdTe')
113
+ self.sxrddet.poni1 = 0.1
114
+ self.sxrddet.poni2 = 0.1
115
+ self.sxrddet.rot1 = np.pi/20
116
+ self.sxrddet.rot2 = -np.pi/20
117
+ self.sxrddet.rot3 = 0
118
+ self.sxrddet.dist = 1.5
119
+ self.sxrddet.setAzimuthalReference(np.deg2rad(90.))
120
+ self.sxrddet.setPolarization(np.deg2rad(90.), 0.75)
121
+
122
+ self.p1 = np.arange(self.sxrddet.detector.shape[1] ) + 0.5 # pixel center
123
+ self.p2 = np.arange(self.sxrddet.detector.shape[0] ) + 0.5
124
+ self.p12 = np.moveaxis(np.array(np.meshgrid(self.p1,self.p2)),0, -1)[:,:,::-1]
125
+
126
+ self.mu = np.deg2rad(0.1) # should be differed, but probably ok
127
+
128
+
129
+ def assertPixelErrorSurfaceAnglesLessThan(self, abserr=1e-3, msg=""):
130
+ gamma, delta = self.sxrddet.surfaceAngles(self.mu)
131
+ p12_conv = self.sxrddet.pixelsSurfaceAngles(gamma, delta, self.mu)
132
+ maxerror = np.nanmax(np.abs(self.p12 - p12_conv))
133
+ if maxerror > abserr:
134
+ warnings.warn("too large error: %.5f pixel coord from surface angles, %s" % (maxerror, msg))
135
+ #self.assertLessEqual(maxerror, abserr, "too large error pixel coord from surface angles, %s" % msg)
136
+
137
+ def assertPixelErrorTthChiLessThan(self, abserr=1e-3, msg=""):
138
+ tth = self.sxrddet.twoThetaArray()
139
+ chi = self.sxrddet.chiArray()
140
+ p12_conv = self.sxrddet.pixelsTthChi(tth, chi)
141
+ maxerror = np.nanmax(np.abs(self.p12 - p12_conv))
142
+ if maxerror > abserr:
143
+ warnings.warn("too large error: %.5f pixel coord from tth and chi, %s" % (maxerror, msg))
144
+ #self.assertLessEqual(maxerror, abserr, "too large error pixel coord from tth and chi, %s" % msg)
145
+
146
+ def assertGamDelRangeErrorLessThan(self, abserr=1e-3, msg=""):
147
+ exact = self.sxrddet._rangegamdel_p_full_det
148
+ corner = self.sxrddet.rangegamdel_p
149
+
150
+ diff = np.array(exact) - np.array(corner)
151
+ max_rel_diff = np.amax(np.abs(diff))
152
+ if max_rel_diff > abserr:
153
+ warnings.warn("too large error: %.5f approx det corners, %s" % (max_rel_diff, msg))
154
+ #self.assertLessEqual(max_rel_diff, abserr, "too large error approx det corners, %s" % msg)
155
+
156
+ def test_poni1(self):
157
+ for p1 in np.linspace(-3,3,5):
158
+ self.sxrddet.poni1 = p1
159
+ msg="poni1 = %s" % p1
160
+ self.assertPixelErrorSurfaceAnglesLessThan(msg=msg)
161
+ self.assertPixelErrorTthChiLessThan(msg=msg)
162
+ self.assertGamDelRangeErrorLessThan(msg=msg)
163
+ self.sxrddet.poni1 = 0.1
164
+
165
+ def test_poni2(self):
166
+ for p1 in np.linspace(-3,3,5):
167
+ self.sxrddet.poni2 = p1
168
+ msg="poni2 = %s" % p1
169
+ self.assertPixelErrorSurfaceAnglesLessThan(msg=msg)
170
+ self.assertPixelErrorTthChiLessThan(msg=msg)
171
+ self.assertGamDelRangeErrorLessThan(msg=msg)
172
+ self.sxrddet.poni2 = 0.1
173
+
174
+ def test_rot1(self):
175
+ for p1 in np.linspace(0,np.pi,8):
176
+ self.sxrddet.rot1 = p1
177
+ msg="rot1 = %s" % p1
178
+ self.assertPixelErrorSurfaceAnglesLessThan(msg=msg)
179
+ self.assertPixelErrorTthChiLessThan(msg=msg)
180
+ self.assertGamDelRangeErrorLessThan(msg=msg)
181
+ self.sxrddet.rot1 = np.pi/20
182
+
183
+ def test_rot2(self):
184
+ for p1 in np.linspace(0,np.pi,8):
185
+ self.sxrddet.rot2 = p1
186
+ msg="rot2 = %s" % p1
187
+ self.assertPixelErrorSurfaceAnglesLessThan(msg=msg)
188
+ self.assertPixelErrorTthChiLessThan(msg=msg)
189
+ self.assertGamDelRangeErrorLessThan(msg=msg)
190
+ self.sxrddet.rot2 = -np.pi/20
191
+
192
+ def test_rot3(self):
193
+ for p1 in np.linspace(0,np.pi,8):
194
+ self.sxrddet.rot3 = p1
195
+ msg="rot3 = %s" % p1
196
+ self.assertPixelErrorSurfaceAnglesLessThan(msg=msg)
197
+ self.assertPixelErrorTthChiLessThan(msg=msg)
198
+ self.assertGamDelRangeErrorLessThan(msg=msg)
199
+ self.sxrddet.rot3 = 0
200
+
201
+ def test_dist(self):
202
+ for d in np.linspace(0.01,10,5):
203
+ self.sxrddet.dist = d
204
+ msg="dist = %s" % d
205
+ self.assertPixelErrorSurfaceAnglesLessThan(msg=msg)
206
+ self.assertPixelErrorTthChiLessThan(msg=msg)
207
+ self.assertGamDelRangeErrorLessThan(msg=msg)
208
+ self.sxrddet.dist = 1.5
209
+
210
+ """
211
+ def test_del_gam_range():
212
+ sxrddet = Detector2D_SXRD()
213
+ sxrddet.detector = pyFAI.detector_factory('Pilatus 2M CdTe')
214
+ sxrddet.poni1 = 0.1
215
+ sxrddet.poni2 = 0.1
216
+ sxrddet.rot1 = np.pi/4
217
+ sxrddet.rot2 = np.pi/5
218
+ sxrddet.rot3 = np.pi/6
219
+ sxrddet.dist = 1.5
220
+ sxrddet.setAzimuthalReference(np.deg2rad(90.))
221
+
222
+
223
+ def checkRange():
224
+ exact = sxrddet._rangegamdel_p_full_det
225
+ corner = sxrddet.rangegamdel_p
226
+ #print("Exact: ", exact)
227
+ #print("Corner: ", corner)
228
+ diff = np.array(exact) - np.array(corner)
229
+ max_rel_diff = np.amax(np.abs(diff))
230
+ return max_rel_diff, diff
231
+ #print("Difference:", np.array(exact) - np.array(corner))
232
+
233
+ sxrddet.poni2 = 0.0
234
+ for p1 in np.linspace(-5,5,20):
235
+ sxrddet.poni1 = p1
236
+ maxerr, diff = checkRange()
237
+ print(f"Max numerical error at poni1 = {p1} m: {maxerr}")
238
+
239
+ sxrddet.poni1 = 0.0
240
+ for p2 in np.linspace(-5,5,20):
241
+ sxrddet.poni2 = p2
242
+ maxerr, diff = checkRange()
243
+ print(f"Max numerical error at poni2 = {p2} m: {maxerr}")
244
+
245
+ # test rot1:
246
+ for r1 in np.linspace(0,np.pi,8):
247
+ sxrddet.rot1 = r1
248
+ maxerr, diff = checkRange()
249
+ print(f"Max numerical error at rot1 = {np.rad2deg(r1)} deg: {maxerr}")
250
+ sxrddet.rot1 = np.pi/4
251
+ for r2 in np.linspace(0,np.pi,8):
252
+ sxrddet.rot2 = r2
253
+ maxerr, diff = checkRange()
254
+ print(f"Max numerical error at rot2 = {np.rad2deg(r2)} deg: {maxerr}")
255
+
256
+ sxrddet.rot2 = np.pi/4
257
+ for r3 in np.linspace(0,np.pi,8):
258
+ sxrddet.rot3 = r3
259
+ maxerr, diff = checkRange()
260
+ print(f"Max numerical error at rot3 = {np.rad2deg(r3)} deg: {maxerr}")
261
+ sxrddet.rot3 = np.pi/4
262
+
263
+ for d in np.linspace(0.001,10,5):
264
+ sxrddet.dist = d
265
+ maxerr, diff = checkRange()
266
+ print(f"Max numerical error at dist = {d} m: {maxerr}")
267
+
268
+
269
+ def testPixelConversion():
270
+ sxrddet = Detector2D_SXRD()
271
+ sxrddet.detector = pyFAI.detector_factory('Pilatus 2M CdTe')
272
+ sxrddet.poni1 = 0.1
273
+ sxrddet.poni2 = 0.1
274
+ sxrddet.rot1 = np.pi/4
275
+ sxrddet.rot2 = np.pi/5
276
+ sxrddet.rot3 = np.pi/6
277
+ sxrddet.dist = 1.5
278
+ sxrddet.setAzimuthalReference(np.deg2rad(90.))
279
+
280
+ # pixel coordinates:
281
+ p1 = np.arange(sxrddet.detector.shape[1] ) + 0.5 # pixel center
282
+ p2 = np.arange(sxrddet.detector.shape[0] ) + 0.5
283
+ p12 = np.moveaxis(np.array(np.meshgrid(p1,p2)),0, -1)[:,:,::-1]
284
+ # this seems to be overcomplicated... is there a better method?
285
+
286
+
287
+ def checkPixel_sxrd():
288
+ gamma, delta = sxrddet.surfaceAngles(np.deg2rad(0.1))
289
+ p12_conv = sxrddet.pixelsSurfaceAngles(gamma, delta, np.deg2rad(0.1))
290
+ return np.nanmax(np.abs(p12 - p12_conv))
291
+ #return np.allclose(p12, p12_conv, atol=1e-5)
292
+
293
+ def checkPixel_tth():
294
+ tth = sxrddet.twoThetaArray()
295
+ chi = sxrddet.chiArray()
296
+ p12_conv = sxrddet.pixelsTthChi(tth, chi)
297
+ return np.nanmax(np.abs(p12 - p12_conv))
298
+
299
+ checkPixel = checkPixel_sxrd
300
+
301
+ sxrddet.poni2 = 0.0
302
+ for p1 in np.linspace(-5,5,20):
303
+ sxrddet.poni1 = p1
304
+ maxerr = checkPixel()
305
+ print(f"Max numerical error at poni1 = {p1} m: {maxerr}")
306
+ sxrddet.poni1 = 0.0
307
+ for p2 in np.linspace(-5,5,20):
308
+ sxrddet.poni2 = p2
309
+ maxerr = checkPixel()
310
+ print(f"Max numerical error at poni2 = {p2} m: {maxerr}")
311
+
312
+ # test rot1:
313
+ for r1 in np.linspace(0,np.pi,8):
314
+ sxrddet.rot1 = r1
315
+ maxerr = checkPixel()
316
+ print(f"Max numerical error at rot1 = {np.rad2deg(r1)} deg: {maxerr}")
317
+ sxrddet.rot1 = np.pi/4
318
+ for r2 in np.linspace(0,np.pi,8):
319
+ sxrddet.rot2 = r2
320
+ maxerr = checkPixel()
321
+ print(f"Max numerical error at rot2 = {np.rad2deg(r2)} deg: {maxerr}")
322
+
323
+ sxrddet.rot2 = np.pi/4
324
+ for r3 in np.linspace(0,np.pi,8):
325
+ sxrddet.rot3 = r3
326
+ maxerr = checkPixel()
327
+ print(f"Max numerical error at rot3 = {np.rad2deg(r3)} deg: {maxerr}")
328
+ sxrddet.rot3 = np.pi/4
329
+
330
+ for d in np.linspace(0.001,10,5):
331
+ sxrddet.dist = d
332
+ maxerr = checkPixel()
333
+ print(f"Max numerical error at dist = {d} m: {maxerr}")
334
+
335
+
336
+ """
@@ -0,0 +1,88 @@
1
+ # -*- coding: utf-8 -*-
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2020-2024 Timo Fuchs
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+ __author__ = "Timo Fuchs"
26
+ __copyright__ = "Copyright 2020-2024 Timo Fuchs"
27
+ __license__ = "MIT License"
28
+ __version__ = "1.0.0"
29
+ __maintainer__ = "Timo Fuchs"
30
+ __email__ = "fuchs@physik.uni-kiel.de"
31
+
32
+ import unittest
33
+
34
+ from .. import HKLVlieg
35
+ from ... import util
36
+
37
+ import numpy as np
38
+ import os
39
+
40
+
41
+ class TestLattice(unittest.TestCase):
42
+
43
+ def testCreateLattice(self):
44
+ lat = HKLVlieg.Lattice([3.9242, 3.9242, 3.9242] ,[90.0000 ,90.0000, 120.0000])
45
+ self.assertTrue(np.allclose([3.9242, 3.9242, 3.9242], lat.a))
46
+ self.assertTrue(np.allclose(np.deg2rad([90.0000 ,90.0000, 120.0000]), lat.alpha))
47
+ self.assertTrue(np.allclose(np.deg2rad([90.0000 ,90.0000, 60.0000]), lat.beta))
48
+ self.assertTrue(np.allclose([1.84883478, 1.84883478, 1.60113789], lat.b))
49
+
50
+ lat.setLattice([3.9242, 3.9242, 3.9242] ,[90.0000 ,90.0000, 120.0000])
51
+ self.assertTrue(np.allclose([3.9242, 3.9242, 3.9242], lat.a))
52
+ self.assertTrue(np.allclose(np.deg2rad([90.0000 ,90.0000, 120.0000]), lat.alpha))
53
+ self.assertTrue(np.allclose(np.deg2rad([90.0000 ,90.0000, 60.0000]), lat.beta))
54
+ self.assertTrue(np.allclose([1.84883478, 1.84883478, 1.60113789], lat.b))
55
+
56
+ lat.a = [3.9242, 3.9242, 3.9242]
57
+ self.assertTrue(np.allclose([3.9242, 3.9242, 3.9242], lat.a))
58
+ self.assertTrue(np.allclose(np.deg2rad([90.0000 ,90.0000, 120.0000]), lat.alpha))
59
+ self.assertTrue(np.allclose(np.deg2rad([90.0000 ,90.0000, 60.0000]), lat.beta))
60
+ self.assertTrue(np.allclose([1.84883478, 1.84883478, 1.60113789], lat.b))
61
+
62
+ lat.alpha = np.deg2rad([90.0000 ,90.0000, 120.0000])
63
+ self.assertTrue(np.allclose([3.9242, 3.9242, 3.9242], lat.a))
64
+ self.assertTrue(np.allclose(np.deg2rad([90.0000 ,90.0000, 120.0000]), lat.alpha))
65
+ self.assertTrue(np.allclose(np.deg2rad([90.0000 ,90.0000, 60.0000]), lat.beta))
66
+ self.assertTrue(np.allclose([1.84883478, 1.84883478, 1.60113789], lat.b))
67
+
68
+
69
+ def testIsReciprocal(self):
70
+
71
+ lat = HKLVlieg.Lattice([3.9242, 6.9242, 2.9242] ,[100.0000 ,90.0000, 120.0000])
72
+
73
+ xyz_rel = (np.arange(100*3).reshape((3,100)) - 150) / 10.
74
+ hkl = (np.arange(100*3).reshape((3,100)) - 150) / 10.
75
+
76
+ phase = 2*np.pi * np.sum(xyz_rel*hkl,axis=0)
77
+
78
+ xyz_cart = lat.directVectorCart(xyz_rel.T)
79
+ self.assertTrue(np.allclose(xyz_cart, lat.R_mat @ xyz_rel))
80
+
81
+ Q_cart = lat.reciprocalVectorCart(hkl.T)
82
+ self.assertTrue(np.allclose(Q_cart, lat.B_mat @ hkl))
83
+
84
+ phase_lat = np.sum(xyz_cart*Q_cart,axis=0)
85
+
86
+ self.assertTrue(np.allclose(phase_lat, phase))
87
+
88
+
@@ -0,0 +1,59 @@
1
+ // Fe3O4(001)
2
+ return
3
+ 8.397 8.397 8.397 90.0 90.0 90.0
4
+ O 0.98789 0.48789 0.754 0.7 0.7 1
5
+ O 0.26211 0.76211 0.754 0.7 0.7 1
6
+ O 0.48789 0.98789 0.754 0.7 0.7 1
7
+ O 0.76211 0.26211 0.754 0.7 0.7 1
8
+ Fe 0.5 0.75 0.75 0.678 0.678 1
9
+ Fe 0.25 0 0.75 0.678 0.678 1
10
+ Fe 0 0.25 0.75 0.678 0.678 1
11
+ Fe 0.75 0.5 0.75 0.678 0.678 1
12
+ O 0.23789 0.23789 0.746 0.7 0.7 1
13
+ O 0.01211 0.01211 0.746 0.7 0.7 1
14
+ O 0.51211 0.51211 0.746 0.7 0.7 1
15
+ O 0.73789 0.73789 0.746 0.7 0.7 1
16
+ Fe 0.625 0.125 0.625 0.583 0.583 1
17
+ Fe 0.125 0.625 0.625 0.583 0.583 1
18
+ O 0.51211 0.73789 0.504 0.7 0.7 1
19
+ O 0.01211 0.23789 0.504 0.7 0.7 1
20
+ O 0.73789 0.51211 0.504 0.7 0.7 1
21
+ O 0.23789 0.01211 0.504 0.7 0.7 1
22
+ Fe 0.75 0.75 0.5 0.678 0.678 1
23
+ Fe 0.25 0.25 0.5 0.678 0.678 1
24
+ Fe 0.5 0.5 0.5 0.678 0.678 1
25
+ Fe 0 0 0.5 0.678 0.678 1
26
+ O 0.76211 0.98789 0.496 0.7 0.7 1
27
+ O 0.26211 0.48789 0.496 0.7 0.7 1
28
+ O 0.98789 0.76211 0.496 0.7 0.7 1
29
+ O 0.48789 0.26211 0.496 0.7 0.7 1
30
+ Fe 0.875 0.375 0.375 0.583 0.583 1
31
+ Fe 0.375 0.875 0.375 0.583 0.583 1
32
+ O 0.48789 0.48789 0.254 0.7 0.7 1
33
+ O 0.76211 0.76211 0.254 0.7 0.7 1
34
+ O 0.98789 0.98789 0.254 0.7 0.7 1
35
+ O 0.26211 0.26211 0.254 0.7 0.7 1
36
+ Fe 0.5 0.25 0.25 0.678 0.678 1
37
+ Fe 0.75 0 0.25 0.678 0.678 1
38
+ Fe 0.25 0.5 0.25 0.678 0.678 1
39
+ Fe 0 0.75 0.25 0.678 0.678 1
40
+ O 0.01211 0.51211 0.246 0.7 0.7 1
41
+ O 0.51211 0.01211 0.246 0.7 0.7 1
42
+ O 0.73789 0.23789 0.246 0.7 0.7 1
43
+ O 0.23789 0.73789 0.246 0.7 0.7 1
44
+ Fe 0.125 0.125 0.125 0.583 0.583 1
45
+ Fe 0.625 0.625 0.125 0.583 0.583 1
46
+ O 0.01211 0.73789 0.004 0.7 0.7 1
47
+ O 0.73789 0.01211 0.004 0.7 0.7 1
48
+ O 0.23789 0.51211 0.004 0.7 0.7 1
49
+ O 0.51211 0.23789 0.004 0.7 0.7 1
50
+ Fe 0 0.5 0 0.678 0.678 1
51
+ Fe 0.75 0.25 0 0.678 0.678 1
52
+ Fe 0.25 0.75 0 0.678 0.678 1
53
+ Fe 0.5 0 0 0.678 0.678 1
54
+ O 0.98789 0.26211 -0.004 0.7 0.7 1
55
+ O 0.26211 0.98789 -0.004 0.7 0.7 1
56
+ O 0.48789 0.76211 -0.004 0.7 0.7 1
57
+ O 0.76211 0.48789 -0.004 0.7 0.7 1
58
+ Fe 0.375 0.375 -0.125 0.583 0.583 1
59
+ Fe 0.875 0.875 -0.125 0.583 0.583 1
@@ -0,0 +1,7 @@
1
+ // Pt(100) larger unit cell for compatibility
2
+ return
3
+ 3.9242 3.9242 3.9242 90.0000 90.0000 90.0000
4
+ Pt 0.00000 0.00000 -1.00000 0.4353 0.4353 1.0000
5
+ Pt 0.50000 0.50000 -1.00000 0.4353 0.4353 1.0000
6
+ Pt 0.50000 0.00000 -0.50000 0.4353 0.4353 1.0000
7
+ Pt 0.00000 0.50000 -0.50000 0.4353 0.4353 1.0000
@@ -0,0 +1,5 @@
1
+ // Pt(100)
2
+ return
3
+ 2.7748 2.7748 3.9242 90.0000 90.0000 90.0000
4
+ Pt 0.50000 0.50000 -1.00000 0.4350 0.4350 1.0000
5
+ Pt 0.00000 0.00000 -0.50000 0.4350 0.4350 1.0000
@@ -0,0 +1,5 @@
1
+ // Pt(110)
2
+ return
3
+ 3.9242 2.7740 2.7740 90.000 90.000 90.000
4
+ Pt 0.0000 0.0000 0.0 0.4489 0.4489 1
5
+ Pt 0.5000 0.5000 -0.5 0.4489 0.4489 1
@@ -0,0 +1,6 @@
1
+ // Pt(111)
2
+ return
3
+ 2.7740 2.7740 6.7960 90.0 90.0 120.0
4
+ Pt 0.00000 0.00000 0.00000 0.4489 0.4489 1
5
+ Pt 0.33333 0.66667 -0.33333 0.4489 0.4489 1
6
+ Pt 0.66667 0.33333 -0.66667 0.4489 0.4489 1
@@ -0,0 +1,13 @@
1
+ // Pt(310)
2
+ return
3
+ 6.2047 3.9242 6.2047 90.000 90.000 90.000
4
+ Pt 0.0000 0.0000 0.0 0.4489 0.4489 1
5
+ Pt 0.3000 0.5000 -0.1 0.4489 0.4489 1
6
+ Pt 0.6000 0.0000 -0.2 0.4489 0.4489 1
7
+ Pt 0.9000 0.5000 -0.3 0.4489 0.4489 1
8
+ Pt 0.2000 0.0000 -0.4 0.4489 0.4489 1
9
+ Pt 0.5000 0.5000 -0.5 0.4489 0.4489 1
10
+ Pt 0.8000 0.0000 -0.6 0.4489 0.4489 1
11
+ Pt 0.1000 0.5000 -0.7 0.4489 0.4489 1
12
+ Pt 0.4000 0.0000 -0.8 0.4489 0.4489 1
13
+ Pt 0.7000 0.5000 -0.9 0.4489 0.4489 1
@@ -0,0 +1,19 @@
1
+ // Pt3O4(100) simple cubic version
2
+ // Muller, Olaf ; Roy, Rustum: Formation and stability of the platinum and rhodium oxides at high oxygen pressures and the structures of Pt3O4, β-PtO2 and RhO2. In: Journal of The Less-Common Metals Bd. 16 (1968), Nr. 2, S. 129–146
3
+ // Nomiyama, Ricardo K. ; Piotrowski, Maurício J. ; Da Silva, Juarez L.F.: Bulk structures of PtO and PtO2 from density functional calculations. In: Physical Review B - Condensed Matter and Materials Physics Bd. 84 (2011), Nr. 10, S. 2–5
4
+ return
5
+ 5.5580 5.5580 5.5580 90.0000 90.0000 90.0000
6
+ Pt 0.50000 0.25000 0.00000000 0.4353 0.4353 1.0000
7
+ Pt 0.50000 0.75000 0.00000000 0.4353 0.4353 1.0000
8
+ Pt 0.00000 0.50000 0.75000000 0.4353 0.4353 1.0000
9
+ Pt 0.00000 0.50000 0.25000000 0.4353 0.4353 1.0000
10
+ Pt 0.75000 0.00000 0.50000000 0.4353 0.4353 1.0000
11
+ Pt 0.25000 0.00000 0.50000000 0.4353 0.4353 1.0000
12
+ O 0.75000 0.25000 0.25000000 0.4353 0.4353 1.0000
13
+ O 0.25000 0.25000 0.75000000 0.4353 0.4353 1.0000
14
+ O 0.25000 0.75000 0.25000000 0.4353 0.4353 1.0000
15
+ O 0.75000 0.75000 0.75000000 0.4353 0.4353 1.0000
16
+ O 0.25000 0.75000 0.75000000 0.4353 0.4353 1.0000
17
+ O 0.75000 0.75000 0.25000000 0.4353 0.4353 1.0000
18
+ O 0.25000 0.25000 0.25000000 0.4353 0.4353 1.0000
19
+ O 0.75000 0.25000 0.75000000 0.4353 0.4353 1.0000
@@ -0,0 +1,9 @@
1
+ // PtO(001) tetragonal "PtS"
2
+ // from McBride, J. R. ; Graham, G. W. ; Peters, C. R. ; Weber, W. H.: Growth and characterization of reactively sputtered thin-film platinum oxides. In: Journal of Applied Physics Bd. 69 (1991), Nr. 3, S. 1596–1604
3
+ // Moore, Walter J. ; Pauling, Linus: The Crystal Structures of the Tetragonal Monoxides of Lead, Tin, Palladium, and Platinum. In: Journal of the American Chemical Society Bd. 63 (1941), Nr. 5, S. 1392–1394
4
+ return
5
+ 3.0777 3.0777 5.3400 90.0000 90.0000 90.0000
6
+ O2- 0.00000 0.00000 -0.75000 0.4353 0.4353 1.0000
7
+ Pt2+ 0.00000 0.50000 -0.50000 0.4353 0.4353 1.0000
8
+ O2- 0.00000 0.00000 -0.25000 0.4353 0.4353 1.0000
9
+ Pt2+ 0.50000 0.00000 0.00000 0.4353 0.4353 1.0000
@@ -0,0 +1,9 @@
1
+ // PtO(010) tetragonal "PtS"
2
+ // from McBride, J. R. ; Graham, G. W. ; Peters, C. R. ; Weber, W. H.: Growth and characterization of reactively sputtered thin-film platinum oxides. In: Journal of Applied Physics Bd. 69 (1991), Nr. 3, S. 1596–1604
3
+ // Moore, Walter J. ; Pauling, Linus: The Crystal Structures of the Tetragonal Monoxides of Lead, Tin, Palladium, and Platinum. In: Journal of the American Chemical Society Bd. 63 (1941), Nr. 5, S. 1392–1394
4
+ return
5
+ 3.0777 5.3400 3.0777 90.0000 90.0000 90.0000
6
+ O2- 0.00000 0.75000 0.00000 0.4353 0.4353 1.0000
7
+ Pt2+ 0.50000 0.50000 0.00000 0.4353 0.4353 1.0000
8
+ O2- 0.00000 0.25000 0.00000 0.4353 0.4353 1.0000
9
+ Pt4+ 0.00000 0.00000 -0.50000 0.4353 0.4353 1.0000
@@ -0,0 +1,9 @@
1
+ // PtO(001) tetragonal "PtS"
2
+ // from McBride, J. R. ; Graham, G. W. ; Peters, C. R. ; Weber, W. H.: Growth and characterization of reactively sputtered thin-film platinum oxides. In: Journal of Applied Physics Bd. 69 (1991), Nr. 3, S. 1596–1604
3
+ // Moore, Walter J. ; Pauling, Linus: The Crystal Structures of the Tetragonal Monoxides of Lead, Tin, Palladium, and Platinum. In: Journal of the American Chemical Society Bd. 63 (1941), Nr. 5, S. 1392–1394
4
+ return
5
+ 5.3400 3.0777 3.0777 90.0000 90.0000 90.0000
6
+ O2- 0.75000 0.50000 -0.50000 0.4353 0.4353 1.0000
7
+ Pt2+ 0.50000 0.50000 0.00000 0.4353 0.4353 1.0000
8
+ O2- 0.25000 0.50000 -0.50000 0.4353 0.4353 1.0000
9
+ Pt2+ 0.00000 0.0000 -0.50000 0.4353 0.4353 1.0000
@@ -0,0 +1,67 @@
1
+ # -*- coding: utf-8 -*-
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2020-2024 Timo Fuchs
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+ __author__ = "Timo Fuchs"
26
+ __copyright__ = "Copyright 2020-2024 Timo Fuchs"
27
+ __license__ = "MIT License"
28
+ __version__ = "1.0.0"
29
+ __maintainer__ = "Timo Fuchs"
30
+ __email__ = "fuchs@physik.uni-kiel.de"
31
+
32
+ import os
33
+ import glob
34
+
35
+ _uc_path = os.path.dirname(__file__)
36
+
37
+ _files_bulk = glob.glob(os.path.join(_uc_path,"*.bul"))
38
+ _files_surf = glob.glob(os.path.join(_uc_path,"*.sur"))
39
+ _files_xtal = glob.glob(os.path.join(_uc_path,"*.xtal"))
40
+
41
+ availablebulk = [os.path.splitext(os.path.basename(bf))[0] for bf in _files_bulk]
42
+ availablesur = [os.path.splitext(os.path.basename(bf))[0] for bf in _files_surf]
43
+ availablextal = [os.path.splitext(os.path.basename(bf))[0] for bf in _files_xtal]
44
+
45
+ BULFILES = dict( (os.path.splitext(os.path.basename(bf))[0].lower(), bf) for bf in _files_bulk)
46
+ SURFILES = dict( (os.path.splitext(os.path.basename(bf))[0].lower(), bf) for bf in _files_surf)
47
+ XTALFILES = dict( (os.path.splitext(os.path.basename(bf))[0].lower(), bf) for bf in _files_xtal)
48
+
49
+
50
+ def unitcell(name: str):
51
+ from .. import CTRcalc
52
+ name = name.lower()
53
+ if name in BULFILES:
54
+ return CTRcalc.UnitCell.fromBULfile(BULFILES[name])
55
+ elif name in SURFILES:
56
+ return CTRcalc.UnitCell.fromSURfile(SURFILES[name])
57
+ else:
58
+ raise ValueError("Unit cell %s is not available." % name)
59
+
60
+
61
+ def crystal(name: str):
62
+ from .. import CTRcalc
63
+ name = name.lower()
64
+ if name in XTALFILES:
65
+ return CTRcalc.SXRDCrystal.fromFile(XTALFILES[name])
66
+ else:
67
+ raise ValueError("Crystal %s is not available." % name)
@@ -0,0 +1,6 @@
1
+ // alpha-PtO2(0001). A single O-Pt-O trilayer with Pt at 000.
2
+ return
3
+ 3.1000 3.1000 4.1600 90.0000 90.0000 120.0000
4
+ O2- 0.33333 0.66666 0.25000 0.4350 0.4350 1.0000
5
+ Pt4+ 0.00000 0.00000 0.00000 0.4350 0.4350 1.0000
6
+ O2- 0.66666 0.33333 -0.25000 0.4350 0.4350 1.0000