pyTEMlib 0.2020.11.1__py3-none-any.whl → 0.2024.9.0__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.

Potentially problematic release.


This version of pyTEMlib might be problematic. Click here for more details.

Files changed (60) hide show
  1. pyTEMlib/__init__.py +11 -11
  2. pyTEMlib/animation.py +631 -0
  3. pyTEMlib/atom_tools.py +240 -245
  4. pyTEMlib/config_dir.py +57 -33
  5. pyTEMlib/core_loss_widget.py +658 -0
  6. pyTEMlib/crystal_tools.py +1255 -0
  7. pyTEMlib/diffraction_plot.py +756 -0
  8. pyTEMlib/dynamic_scattering.py +293 -0
  9. pyTEMlib/eds_tools.py +609 -0
  10. pyTEMlib/eels_dialog.py +749 -491
  11. pyTEMlib/{interactive_eels.py → eels_dialog_utilities.py} +1199 -1177
  12. pyTEMlib/eels_tools.py +2031 -1698
  13. pyTEMlib/file_tools.py +1276 -560
  14. pyTEMlib/file_tools_qt.py +193 -0
  15. pyTEMlib/graph_tools.py +1166 -450
  16. pyTEMlib/graph_viz.py +449 -0
  17. pyTEMlib/image_dialog.py +158 -0
  18. pyTEMlib/image_dlg.py +146 -232
  19. pyTEMlib/image_tools.py +1399 -1028
  20. pyTEMlib/info_widget.py +933 -0
  21. pyTEMlib/interactive_image.py +1 -226
  22. pyTEMlib/kinematic_scattering.py +1196 -0
  23. pyTEMlib/low_loss_widget.py +176 -0
  24. pyTEMlib/microscope.py +61 -81
  25. pyTEMlib/peak_dialog.py +1047 -410
  26. pyTEMlib/peak_dlg.py +286 -242
  27. pyTEMlib/probe_tools.py +653 -207
  28. pyTEMlib/sidpy_tools.py +153 -136
  29. pyTEMlib/simulation_tools.py +104 -87
  30. pyTEMlib/version.py +6 -3
  31. pyTEMlib/xrpa_x_sections.py +20972 -0
  32. {pyTEMlib-0.2020.11.1.dist-info → pyTEMlib-0.2024.9.0.dist-info}/LICENSE +21 -21
  33. pyTEMlib-0.2024.9.0.dist-info/METADATA +92 -0
  34. pyTEMlib-0.2024.9.0.dist-info/RECORD +37 -0
  35. {pyTEMlib-0.2020.11.1.dist-info → pyTEMlib-0.2024.9.0.dist-info}/WHEEL +5 -5
  36. {pyTEMlib-0.2020.11.1.dist-info → pyTEMlib-0.2024.9.0.dist-info}/entry_points.txt +0 -1
  37. pyTEMlib/KinsCat.py +0 -2758
  38. pyTEMlib/__version__.py +0 -2
  39. pyTEMlib/data/TEMlibrc +0 -68
  40. pyTEMlib/data/edges_db.csv +0 -189
  41. pyTEMlib/data/edges_db.pkl +0 -0
  42. pyTEMlib/data/fparam.txt +0 -103
  43. pyTEMlib/data/microscopes.csv +0 -7
  44. pyTEMlib/data/microscopes.xml +0 -167
  45. pyTEMlib/data/path.txt +0 -1
  46. pyTEMlib/defaults_parser.py +0 -90
  47. pyTEMlib/dm3_reader.py +0 -613
  48. pyTEMlib/edges_db.py +0 -76
  49. pyTEMlib/eels_dlg.py +0 -224
  50. pyTEMlib/hdf_utils.py +0 -483
  51. pyTEMlib/image_tools1.py +0 -2194
  52. pyTEMlib/info_dialog.py +0 -237
  53. pyTEMlib/info_dlg.py +0 -202
  54. pyTEMlib/nion_reader.py +0 -297
  55. pyTEMlib/nsi_reader.py +0 -170
  56. pyTEMlib/structure_tools.py +0 -316
  57. pyTEMlib/test.py +0 -2072
  58. pyTEMlib-0.2020.11.1.dist-info/METADATA +0 -20
  59. pyTEMlib-0.2020.11.1.dist-info/RECORD +0 -45
  60. {pyTEMlib-0.2020.11.1.dist-info → pyTEMlib-0.2024.9.0.dist-info}/top_level.txt +0 -0
@@ -1,316 +0,0 @@
1
- import numpy as np
2
- from math import gcd, ceil, atan
3
- from fractions import Fraction
4
-
5
-
6
- # SIGMA_SYMBOL = u'\u03A3'
7
- UNIMODULAR_MATRIX = np.array([np.identity(3),
8
- [[1, 0, 1],
9
- [0, 1, 0],
10
- [0, 1, 1]],
11
- [[1, 0, 1],
12
- [0, 1, 0],
13
- [0, 1, -1]],
14
- [[1, 0, 1],
15
- [0, 1, 0],
16
- [-1, 1, 0]],
17
- [[1, 0, 1],
18
- [1, 1, 0],
19
- [1, 1, 1]]])
20
- STRUCTURE_MATRIX = np.array([np.identity(3),
21
- [[0.5, -0.5, 0],
22
- [0.5, 0.5, 0],
23
- [0.5, 0.5, 1]],
24
- [[0.5, 0.5, 0],
25
- [0, 0.5, 0.5],
26
- [0.5, 0, 0.5]]])
27
-
28
- # 0 is coprime only with 1
29
- def coprime(a, b):
30
- return gcd(a,b) in (0, 1)
31
-
32
-
33
- def get_cubic_sigma(hkl, m, n=1):
34
- sqsum = np.inner(hkl, hkl)
35
- sigma = m*m + n*n * sqsum
36
- while sigma != 0 and sigma % 2 == 0:
37
- sigma /= 2
38
- return (sigma if sigma > 1 else None)
39
-
40
- def get_cubic_theta(hkl, m, n=1):
41
- h,k,l = hkl
42
- sqsum = h*h + k*k + l*l
43
- assert sqsum > 0
44
- if m > 0:
45
- return 2 * atan(np.sqrt(sqsum) * n / m)
46
- else:
47
- return pi
48
-
49
-
50
- def get_theta_m_n_list(hkl, sigma, verbose=False):
51
- if sigma == 1:
52
- return [(0., 0, 0)]
53
- thetas = []
54
-
55
- # From Grimmer, Acta Cryst. (1984). A40, 108-112
56
- # S = m^2 + (u^2+v^2+w^2) n^2 (eq. 2)
57
- # S = alpha * Sigma (eq. 4)
58
- # where alpha = 1, 2 or 4.
59
- # Since (u^2+v^2+w^2) n^2 > 0,
60
- # thus alpha * Sigma > m^2 => m^2 < 4 * Sigma
61
- max_m = int(ceil(np.sqrt(4*sigma)))
62
-
63
- for m in range(max_m):
64
- for n in range(1, max_m):
65
- if not coprime(m, n):
66
- continue
67
- s = get_cubic_sigma(hkl, m, n)
68
- if s != sigma:
69
- continue
70
- theta = get_cubic_theta(hkl, m, n)
71
- if verbose:
72
- print("m=%i n=%i" % (m, n), "%.3f" % np.degrees(theta))
73
- thetas.append((theta, m, n))
74
- return np.array(thetas)
75
-
76
-
77
- def rodrigues(a, angle, verbose=False):
78
- "use Rodrigues' rotation formula to get rotation matrix"
79
- a = np.array(a, dtype=float)
80
- a /= np.sqrt(np.inner(a, a)) # make unit vector
81
- #assert abs(sin_angle - sin(acos(cos_angle))) < 1e-6
82
- if verbose:
83
- print ("rotation angle:", np.degrees(angle))
84
- print ("rotation axis:", a)
85
- omega = np.array([[ 0., -a[2], a[1]],
86
- [ a[2], 0., -a[0]],
87
- [-a[1], a[0], 0.]])
88
- rm = (np.identity(3) + omega * np.sin(angle)
89
- + np.dot(omega, omega) * (1 - np.cos(angle)))
90
- if verbose:
91
- print("rotation matrix:", rm)
92
- return rm
93
-
94
- def is_integer(a, epsilon=1e-7):
95
- "return true if numpy Float array consists off all integers"
96
- return (np.abs(a - np.round(a)) < epsilon).all()
97
-
98
- def get_smallest_multiplier(a, max_n=1000):
99
- """return the smallest positive integer n such that matrix a multiplied
100
- by n is an integer matrix
101
- """
102
- for i in range(1, max_n):
103
- if is_integer(i*a):
104
- return i
105
-
106
- def plus_minus_gen(start, end):
107
- """
108
- Generate a list of plus and minus alternating integers
109
- """
110
- for i in range(start, end):
111
- yield i
112
- yield -i
113
- def get_csl_matrix(sigma, rotate_matrix):
114
- """\
115
- Find matrix that determines the coincidence site lattice
116
- for cubic structures.
117
- Parameters:
118
- sigma: CSL sigma
119
- R: rotation matrix
120
- centering: "f" for f.c.c., "b" for b.c.c. and None for p.c.
121
- Return value:
122
- matrix, which column vectors are the unit vectors of the CSL.
123
- Based on H. Grimmer et al., Acta Cryst. (1974) A30, 197
124
- https://doi.org/10.1107/S056773947400043X
125
- """
126
-
127
- s = STRUCTURE_MATRIX[0]
128
- for u in UNIMODULAR_MATRIX:
129
- t = np.eye(3) - np.dot(np.dot(np.dot(u, np.linalg.inv(s)), np.linalg.inv(rotate_matrix)), s)
130
- if abs( np.linalg.det(t)) > 1e-6:
131
- break
132
- o_lattice = np.round( np.linalg.inv(t), 12)
133
- n = np.round(sigma / np.linalg.det(o_lattice), 6)
134
- csl_matrix = o_lattice_to_csl(o_lattice, n)
135
- return csl_matrix
136
-
137
-
138
- def o_lattice_to_csl(o_lattice, n):
139
- """
140
- The algorithm was borrowed from gosam project with slight changes.
141
- Link to the project: https://github.com/wojdyr/gosam
142
-
143
- There are two major steps: (1) Manipulate the columns of O-lattice to get
144
- an integral basis matrix for CSL: make two columns become integers and
145
- the remaining column can be multiplied by n whereby the determinant
146
- becomes sigma. (2) Simplify CSL so its vectors acquire the shortest length:
147
- decrease the integers in the matrix while keeping the determinant the same
148
- by adding other column vectors (row vectors in the following example) to a
149
- column vector. If after the addition or subtraction, the maximum value or
150
- absolute summation of added or subtracted vector is smaller than the
151
- original, then proceed the addition or subtraction.
152
- 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1
153
- 1 2 -1 -> 1 2 0 -> 1 2 0 -> 1 2 0 -> 1 2 0
154
- 1 -3 2 1 -3 2 1 -3 1 1 -3 0 2 -1 0
155
-
156
- Args:
157
- o_lattice (3x3 array): O-lattice in crystal coordinates
158
- n (int): Number of O-lattice units per CSL unit
159
-
160
- Returns:
161
- CSL matrix (3x3 array) in crystal coordinates
162
- """
163
- csl = o_lattice.copy()
164
- if n < 0:
165
- csl[0] *= -1
166
- n *= -1
167
- while True:
168
- m = [get_smallest_multiplier(i) for i in csl]
169
- m_prod = np.prod(m)
170
- if m_prod <= n:
171
- for i in range(3):
172
- csl[i] *= m[i]
173
- if m_prod < n:
174
- assert n % m_prod == 0
175
- csl[0] *= n / m_prod
176
- break
177
- else:
178
- changed = False
179
- for i in range(3):
180
- for j in range(3):
181
- if changed or i == j or m[i] == 1 or m[j] == 1:
182
- continue
183
- a, b = (i, j) if m[i] <= m[j] else (j, i)
184
- for k in plus_minus_gen(1, m[b]):
185
- handle = csl[a] + k * csl[b]
186
- if get_smallest_multiplier(handle) < m[a]:
187
- csl[a] += k * csl[b]
188
- changed = True
189
- break
190
- if not changed:
191
- # This situation rarely happens. Not sure if this solution is
192
- # legit, as det not equals to sigma. E.g. Sigma 115[113]
193
- for i in range(3):
194
- csl[i] *= m[i]
195
- break
196
- csl = csl.round().astype(int)
197
-
198
- # Reshape CSL
199
- def simplify(l1, l2):
200
- x = abs(l1 + l2)
201
- y = abs(l1)
202
- changed = False
203
- while max(x) < max(y) or (max(x) == max(y) and sum(x) < sum(y)):
204
- l1 += l2
205
- changed = True
206
- x = abs(l1 + l2)
207
- y = abs(l1)
208
- return changed
209
-
210
- while True:
211
- changed = False
212
- for i in range(3):
213
- for j in range(3):
214
- if i != j and not changed:
215
- changed = simplify(csl[i], csl[j]) or simplify(csl[i], -csl[j])
216
- if changed:
217
- break
218
- if not changed:
219
- break
220
- return csl
221
-
222
-
223
- def orthogonalize_csl(csl, axis):
224
- """
225
- (1) Set the 3rd column of csl same as the rotation axis. The algorithm was
226
- borrowed from gosam project with slight changes. Link to the project:
227
- https://github.com/wojdyr/gosam
228
- (2) Orthogonalize CSL, which is essentially a Gram-Schmidt process. At the
229
- same time, we want to make sure the column vectors of orthogonalized csl
230
- has the smallest value possible. That's why we compared two different ways.
231
- csl = [v1, v2, v3], vi is the column vector
232
- u1 = v3/||v3||, y2 = v1 - (v1 . u1)u1
233
- u2 = y2/||y2||, y3 = v3 - [(v3 . u1)u1 + (v3 . u2)u2]
234
- u3 = y3/||y3||
235
- """
236
- axis = np.array(axis)
237
- c = np.linalg.solve(csl.transpose(), axis)
238
- if not is_integer(c):
239
- mult = get_smallest_multiplier(c)
240
- c *= mult
241
- c = c.round().astype(int)
242
- ind = min([(i, v) for i, v in enumerate(c) if not np.allclose(v, 0)],
243
- key=lambda x: abs(x[1]))[0]
244
- if ind != 2:
245
- csl[ind], csl[2] = csl[2].copy(), -csl[ind]
246
- c[ind], c[2] = c[2], -c[ind]
247
-
248
- csl[2] = np.dot(c, csl)
249
- if c[2] < 0:
250
- csl[1] *= -1
251
-
252
- def get_integer(vec):
253
- # Used vec = np.array(vec, dtype=float) before, but does not work for
254
- # [5.00000000e-01, -5.00000000e-01, 2.22044605e-16] in Sigma3[112]
255
- vec = np.round(vec, 12)
256
- vec_sign = np.array([1 if abs(i) == i else -1 for i in vec])
257
- vec = list(abs(vec))
258
- new_vec = []
259
- if 0.0 in vec:
260
- zero_ind = vec.index(0)
261
- vec.pop(zero_ind)
262
- if 0.0 in vec:
263
- new_vec = [get_smallest_multiplier(vec) * i for i in vec]
264
- else:
265
- frac = Fraction(vec[0] / vec[1]).limit_denominator()
266
- new_vec = [frac.numerator, frac.denominator]
267
- new_vec.insert(zero_ind, 0)
268
- else:
269
- for i in range(len(vec) - 1):
270
- frac = Fraction(vec[i] / vec[i + 1]).limit_denominator()
271
- new_vec.extend([frac.numerator, frac.denominator])
272
- if new_vec[1] == new_vec[2]:
273
- new_vec = [new_vec[0], new_vec[1], new_vec[3]]
274
- else:
275
- new_vec = reduce_vector([new_vec[0] * new_vec[2],
276
- new_vec[1] * new_vec[2],
277
- new_vec[3] * new_vec[1]])
278
- assert is_integer(new_vec)
279
- return new_vec * vec_sign
280
-
281
- u1 = csl[2] / np.linalg.norm(csl[2])
282
- y2_1 = csl[1] - np.dot(csl[1], u1) * u1
283
- c0_1 = get_integer(y2_1)
284
- y2_2 = csl[0] - np.dot(csl[0], u1) * u1
285
- c0_2 = get_integer(y2_2)
286
- if sum(abs(c0_1)) > sum(abs(c0_2)):
287
- u2 = y2_2 / np.linalg.norm(y2_2)
288
- y3 = csl[1] - np.dot(csl[1], u1) * u1 - np.dot(csl[1], u2) * u2
289
- csl[1] = get_integer(y3)
290
- csl[0] = c0_2
291
- else:
292
- u2 = y2_1 / np.linalg.norm(y2_1)
293
- y3 = csl[0] - np.dot(csl[0], u1) * u1 - np.dot(csl[0], u2) * u2
294
- csl[1] = c0_1
295
- csl[0] = get_integer(y3)
296
- for i in range(3):
297
- for j in range(i + 1, 3):
298
- if not np.allclose(np.dot(csl[i], csl[j]), 0):
299
- raise ValueError("Non-orthogonal basis: %s" % csl)
300
- return csl.round().astype(int)
301
-
302
- def find_smallest_real_multiplier(a, max_n=1000):
303
- """return the smallest positive real f such that matrix `a' multiplied
304
- by f is an integer matrix
305
- """
306
- # |the smallest non-zero element|
307
- m = min(abs(i) for i in a if abs(i) > 1e-9)
308
- for i in range(1, max_n):
309
- t = i / float(m)
310
- if is_integer(t * a):
311
- return t
312
- raise ValueError("Sorry, we can't make this matrix integer:\n%s" % a)
313
-
314
- def scale_to_integers(v):
315
- return np.array(v * find_smallest_real_multiplier(v)).round().astype(int)
316
-