pyTEMlib 0.2025.4.1__py3-none-any.whl → 0.2025.9.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.

Potentially problematic release.


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

Files changed (94) hide show
  1. build/lib/pyTEMlib/__init__.py +33 -0
  2. build/lib/pyTEMlib/animation.py +640 -0
  3. build/lib/pyTEMlib/atom_tools.py +238 -0
  4. build/lib/pyTEMlib/config_dir.py +31 -0
  5. build/lib/pyTEMlib/crystal_tools.py +1219 -0
  6. build/lib/pyTEMlib/diffraction_plot.py +756 -0
  7. build/lib/pyTEMlib/dynamic_scattering.py +293 -0
  8. build/lib/pyTEMlib/eds_tools.py +826 -0
  9. build/lib/pyTEMlib/eds_xsections.py +432 -0
  10. build/lib/pyTEMlib/eels_tools/__init__.py +44 -0
  11. build/lib/pyTEMlib/eels_tools/core_loss_tools.py +751 -0
  12. build/lib/pyTEMlib/eels_tools/eels_database.py +134 -0
  13. build/lib/pyTEMlib/eels_tools/low_loss_tools.py +655 -0
  14. build/lib/pyTEMlib/eels_tools/peak_fit_tools.py +175 -0
  15. build/lib/pyTEMlib/eels_tools/zero_loss_tools.py +264 -0
  16. build/lib/pyTEMlib/file_reader.py +274 -0
  17. build/lib/pyTEMlib/file_tools.py +811 -0
  18. build/lib/pyTEMlib/get_bote_salvat.py +69 -0
  19. build/lib/pyTEMlib/graph_tools.py +1153 -0
  20. build/lib/pyTEMlib/graph_viz.py +599 -0
  21. build/lib/pyTEMlib/image/__init__.py +37 -0
  22. build/lib/pyTEMlib/image/image_atoms.py +270 -0
  23. build/lib/pyTEMlib/image/image_clean.py +197 -0
  24. build/lib/pyTEMlib/image/image_distortion.py +299 -0
  25. build/lib/pyTEMlib/image/image_fft.py +277 -0
  26. build/lib/pyTEMlib/image/image_graph.py +926 -0
  27. build/lib/pyTEMlib/image/image_registration.py +316 -0
  28. build/lib/pyTEMlib/image/image_utilities.py +309 -0
  29. build/lib/pyTEMlib/image/image_window.py +421 -0
  30. build/lib/pyTEMlib/image_tools.py +699 -0
  31. build/lib/pyTEMlib/interactive_image.py +1 -0
  32. build/lib/pyTEMlib/kinematic_scattering.py +1196 -0
  33. build/lib/pyTEMlib/microscope.py +61 -0
  34. build/lib/pyTEMlib/probe_tools.py +906 -0
  35. build/lib/pyTEMlib/sidpy_tools.py +153 -0
  36. build/lib/pyTEMlib/simulation_tools.py +104 -0
  37. build/lib/pyTEMlib/test.py +437 -0
  38. build/lib/pyTEMlib/utilities.py +314 -0
  39. build/lib/pyTEMlib/version.py +5 -0
  40. build/lib/pyTEMlib/xrpa_x_sections.py +20976 -0
  41. pyTEMlib/__init__.py +25 -3
  42. pyTEMlib/animation.py +31 -22
  43. pyTEMlib/atom_tools.py +29 -34
  44. pyTEMlib/config_dir.py +2 -28
  45. pyTEMlib/crystal_tools.py +129 -165
  46. pyTEMlib/eds_tools.py +559 -342
  47. pyTEMlib/eds_xsections.py +432 -0
  48. pyTEMlib/eels_tools/__init__.py +44 -0
  49. pyTEMlib/eels_tools/core_loss_tools.py +751 -0
  50. pyTEMlib/eels_tools/eels_database.py +134 -0
  51. pyTEMlib/eels_tools/low_loss_tools.py +655 -0
  52. pyTEMlib/eels_tools/peak_fit_tools.py +175 -0
  53. pyTEMlib/eels_tools/zero_loss_tools.py +264 -0
  54. pyTEMlib/file_reader.py +274 -0
  55. pyTEMlib/file_tools.py +260 -1130
  56. pyTEMlib/get_bote_salvat.py +69 -0
  57. pyTEMlib/graph_tools.py +101 -174
  58. pyTEMlib/graph_viz.py +150 -0
  59. pyTEMlib/image/__init__.py +37 -0
  60. pyTEMlib/image/image_atoms.py +270 -0
  61. pyTEMlib/image/image_clean.py +197 -0
  62. pyTEMlib/image/image_distortion.py +299 -0
  63. pyTEMlib/image/image_fft.py +277 -0
  64. pyTEMlib/image/image_graph.py +926 -0
  65. pyTEMlib/image/image_registration.py +316 -0
  66. pyTEMlib/image/image_utilities.py +309 -0
  67. pyTEMlib/image/image_window.py +421 -0
  68. pyTEMlib/image_tools.py +154 -915
  69. pyTEMlib/kinematic_scattering.py +1 -1
  70. pyTEMlib/probe_tools.py +1 -1
  71. pyTEMlib/test.py +437 -0
  72. pyTEMlib/utilities.py +314 -0
  73. pyTEMlib/version.py +2 -3
  74. pyTEMlib/xrpa_x_sections.py +14 -10
  75. {pytemlib-0.2025.4.1.dist-info → pytemlib-0.2025.9.1.dist-info}/METADATA +13 -16
  76. pytemlib-0.2025.9.1.dist-info/RECORD +86 -0
  77. {pytemlib-0.2025.4.1.dist-info → pytemlib-0.2025.9.1.dist-info}/WHEEL +1 -1
  78. pytemlib-0.2025.9.1.dist-info/top_level.txt +6 -0
  79. pyTEMlib/core_loss_widget.py +0 -721
  80. pyTEMlib/eels_dialog.py +0 -754
  81. pyTEMlib/eels_dialog_utilities.py +0 -1199
  82. pyTEMlib/eels_tools.py +0 -2359
  83. pyTEMlib/file_tools_qt.py +0 -193
  84. pyTEMlib/image_dialog.py +0 -158
  85. pyTEMlib/image_dlg.py +0 -146
  86. pyTEMlib/info_widget.py +0 -1086
  87. pyTEMlib/info_widget3.py +0 -1120
  88. pyTEMlib/low_loss_widget.py +0 -479
  89. pyTEMlib/peak_dialog.py +0 -1129
  90. pyTEMlib/peak_dlg.py +0 -286
  91. pytemlib-0.2025.4.1.dist-info/RECORD +0 -38
  92. pytemlib-0.2025.4.1.dist-info/top_level.txt +0 -1
  93. {pytemlib-0.2025.4.1.dist-info → pytemlib-0.2025.9.1.dist-info}/entry_points.txt +0 -0
  94. {pytemlib-0.2025.4.1.dist-info → pytemlib-0.2025.9.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,238 @@
1
+ """ Atom detection
2
+
3
+ All atom detection is done here
4
+ Everything is in unit of pixel!!
5
+
6
+ Author: Gerd Duscher
7
+
8
+ part of pyTEMlib
9
+
10
+
11
+ a pycroscopy package
12
+ """
13
+
14
+ import numpy as np
15
+
16
+ import skimage.feature
17
+ import sklearn.cluster
18
+ import scipy.spatial
19
+ import scipy.optimize
20
+
21
+ from tqdm.auto import trange
22
+
23
+ import sidpy
24
+ import pyTEMlib
25
+
26
+ def find_atoms(image, atom_size=0.1, threshold=0.):
27
+ """ Find atoms is a simple wrapper for blob_log in skimage.feature
28
+
29
+ Parameters
30
+ ----------
31
+ image: sidpy.Dataset
32
+ the image to find atoms
33
+ atom_size: float
34
+ visible size of atom blob diameter in nm gives minimal distance between found blobs
35
+ threshold: float
36
+ threshold for blob finder; (usually between 0.001 and 1.0)
37
+ for threshold <= 0 we use the RMS contrast
38
+
39
+ Returns
40
+ -------
41
+ atoms: numpy array(Nx3)
42
+ atoms positions and radius of blob
43
+ """
44
+
45
+ if not isinstance(image, sidpy.Dataset):
46
+ raise TypeError('We need a sidpy.Dataset')
47
+ if image.data_type.name != 'IMAGE':
48
+ raise TypeError('We need sidpy.Dataset of sidpy.Datatype: IMAGE')
49
+ if not isinstance(atom_size, (float, int)):
50
+ raise TypeError('atom_size parameter has to be a number')
51
+ if not isinstance(threshold, float):
52
+ raise TypeError('threshold parameter has to be a float number')
53
+
54
+ scale_x = np.unique(np.gradient(image.dim_0.values))[0]
55
+ im = np.array(image-image.min())
56
+ im = im/im.max()
57
+ if threshold <= 0.:
58
+ threshold = np.std(im)
59
+ atoms = skimage.feature.blob_log(im, max_sigma=atom_size/scale_x, threshold=threshold)
60
+ return atoms
61
+
62
+
63
+ def atoms_clustering(atoms, mid_atoms, number_of_clusters=3, nearest_neighbours=7):
64
+ """ A wrapper for sklearn.cluster kmeans clustering of atoms.
65
+
66
+ Parameters
67
+ ----------
68
+ atoms: list or np.array (Nx2)
69
+ list of all atoms
70
+ mid_atoms: list or np.array (Nx2)
71
+ atoms to be evaluated
72
+ number_of_clusters: int
73
+ number of clusters to sort (ini=3)
74
+ nearest_neighbours: int
75
+ number of nearest neighbours evaluated
76
+
77
+ Returns
78
+ -------
79
+ clusters, distances, indices: numpy arrays
80
+ """
81
+
82
+ # get distances
83
+ nn_tree = scipy.spatial.KDTree(np.array(atoms)[:, 0:2])
84
+
85
+ distances, indices = nn_tree.query(np.array(mid_atoms)[:, 0:2], nearest_neighbours)
86
+
87
+ # Clustering with fixed RNG in kmeans
88
+ k_means = sklearn.cluster.KMeans(n_clusters=number_of_clusters, random_state=0)
89
+ k_means.fit(distances)
90
+ clusters = k_means.predict(distances)
91
+
92
+ return clusters, distances, indices
93
+
94
+
95
+ def gauss_difference(params, area):
96
+ """
97
+ Difference between part of an image and a Gaussian
98
+ This function is used int he atom refine function of pyTEMlib
99
+
100
+ Parameters
101
+ ----------
102
+ params: list
103
+ list of Gaussian parameters [width, position_x, position_y, intensity]
104
+ area: numpy array
105
+ 2D matrix = part of an image
106
+
107
+ Returns
108
+ -------
109
+ numpy array: flattened array of difference
110
+
111
+ """
112
+ gauss = pyTEMlib.probe_tools.make_gauss(area.shape[0], area.shape[1],
113
+ width=params[0], x0=params[1],
114
+ y0=params[2], intensity=params[3])
115
+ return (area - gauss).flatten()
116
+
117
+
118
+ def atom_refine(image, atoms, radius, max_int=0, min_int=0, max_dist=4):
119
+ """Fits a Gaussian in a blob of an image
120
+
121
+ Parameters
122
+ ----------
123
+ image: np.array or sidpy Dataset
124
+ atoms: list or np.array
125
+ positions of atoms
126
+ radius: float
127
+ radius of circular mask to define fitting of Gaussian
128
+ max_int: float
129
+ optional - maximum intensity to be considered for fitting
130
+ (to exclude contaminated areas for example)
131
+ min_int: float
132
+ optional - minimum intensity to be considered for fitting
133
+ (to exclude contaminated holes for example)
134
+ max_dist: float
135
+ optional - maximum distance of movement of Gaussian during fitting
136
+
137
+ Returns
138
+ -------
139
+ sym: dict
140
+ dictionary containing new atom positions and other output
141
+ """
142
+ rr = int(radius + 0.5) # atom radius
143
+
144
+ pixels = np.linspace(0, 2 * rr, 2 * rr + 1) - rr
145
+ x, y = np.meshgrid(pixels, pixels)
146
+ mask = (x ** 2 + y ** 2) < rr ** 2
147
+
148
+ guess = [rr * 2, 0.0, 0.0, 1]
149
+
150
+ sym = {'number_of_atoms': len(atoms)}
151
+
152
+ volume = []
153
+ position = []
154
+ intensities = []
155
+ maximum_area = []
156
+ new_atoms = []
157
+ gauss_width = []
158
+ gauss_amplitude = []
159
+ gauss_intensity = []
160
+
161
+ for i in range(len(atoms)):
162
+ x, y = atoms[i][0:2]
163
+ x = int(x)
164
+ y = int(y)
165
+
166
+ area = image[x - rr:x + rr + 1, y - rr:y + rr + 1]
167
+
168
+ append = False
169
+
170
+ if x-rr < 0 or y-rr < 0 or x+rr+1 > image.shape[0] or y+rr+1 > image.shape[1]:
171
+ position.append(-1)
172
+ intensities.append(-1.)
173
+ maximum_area.append(-1.)
174
+ else: # atom found
175
+ position.append(1)
176
+ intensities.append((area * mask).sum())
177
+ maximum_area.append((area * mask).max())
178
+
179
+ if max_int > 0:
180
+ if area.sum() < max_int:
181
+ if area.sum() > min_int:
182
+ append = True
183
+ elif area.sum() > min_int:
184
+ append = True
185
+
186
+ pout = [0, 0, 0, 0]
187
+ if append:
188
+ if x-rr < 0 or y-rr < 0 or x+rr+1 > image.shape[0] or y+rr+1 > image.shape[1]:
189
+ pass
190
+ else:
191
+ [pout, _] = scipy.optimize.leastsq(gauss_difference, guess, args=area)
192
+ if (abs(pout[1]) > max_dist) or (abs(pout[2]) > max_dist):
193
+ pout = [0, 0, 0, 0]
194
+
195
+ volume.append(2 * np.pi * pout[3] * pout[0] * pout[0])
196
+
197
+ new_atoms.append([x + pout[1], y + pout[2]]) # ,pout[0], volume)) #,pout[3]))
198
+ if all(v == 0 for v in pout):
199
+ gauss_intensity.append(0.)
200
+ else:
201
+ gauss = pyTEMlib.probe_tools.make_gauss(area.shape[0], area.shape[1], width=pout[0],
202
+ x0=pout[1], y0=pout[2], intensity=pout[3])
203
+ gauss_intensity.append((gauss * mask).sum())
204
+ gauss_width.append(pout[0])
205
+ gauss_amplitude.append(pout[3])
206
+
207
+ sym['inside'] = position
208
+ sym['intensity_area'] = intensities
209
+ sym['maximum_area'] = maximum_area
210
+ sym['atoms'] = new_atoms
211
+ sym['gauss_width'] = gauss_width
212
+ sym['gauss_amplitude'] = gauss_amplitude
213
+ sym['gauss_intensity'] = gauss_intensity
214
+ sym['gauss_volume'] = volume
215
+
216
+ return sym
217
+
218
+
219
+ def intensity_area(image, atoms, radius):
220
+ """
221
+ integrated intensity of atoms in an image with a mask around each atom of radius radius
222
+ """
223
+ rr = int(radius + 0.5) # atom radius
224
+ print('using radius ', rr, 'pixels')
225
+
226
+ pixels = np.linspace(0, 2 * rr, 2 * rr + 1) - rr
227
+ x, y = np.meshgrid(pixels, pixels)
228
+ mask = np.array((x ** 2 + y ** 2) < rr ** 2)
229
+ intensities = []
230
+ for atom in atoms:
231
+ x = int(atom[1])
232
+ y = int(atom[0])
233
+ area = image[x - rr:x + rr + 1, y - rr:y + rr + 1]
234
+ if area.shape == mask.shape:
235
+ intensities.append((area * mask).sum())
236
+ else:
237
+ intensities.append(-1)
238
+ return intensities
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+ # part of pyTEMlib
3
+ # 2022/08 Changed this to be hopefully compatible with conda-forge
4
+ #
5
+ #
6
+ """
7
+ config_dir: setup of directory ~/.pyTEMlib for custom sources and database
8
+ """
9
+ import os
10
+
11
+ # import wget
12
+ if os.name in ['nt', 'dos', 'posix']:
13
+ config_path = os.path.join(os.path.expanduser('~'), '.pyTEMlib')
14
+ else:
15
+ config_path = '.'
16
+
17
+ if os.path.isdir(config_path) is False:
18
+ # messages.information("Creating config directory: %s" % config_path)
19
+ os.mkdir(config_path)
20
+
21
+ lines = ['Microscope,E0,alpha,beta,pppc,correlation_factor,VOA_conv,EELS_b1,EELS_b2,EELS_b100,MADF_offset,MADF_slope,'
22
+ 'HADF_offset,HADF_slope,BF_offset,BF_slope',
23
+ 'Libra 200,2.00E+05,10,15,1,1,6241509.647,0.0634,0.0634,0.0634,0,0,0,0,0,0',
24
+ 'UltraSTEM 60,6.00E+04,30,50,1,1,1.79E+07,0.2,0.45,0.9,0.001383,4.04E-06,0,0,0,0',
25
+ 'UltraSTEM 100,1.00E+05,30,50,1,1,6.24E+06,0.45,1,2,0,0,0,0,0,0',
26
+ 'UltraSTEM 200,2.00E+05,30,50,1,1,6.24E+06,0.45,1,2,0,0,0,0,0,0']
27
+
28
+ config_file = os.path.join(config_path, 'microscopes.csv')
29
+ if os.path.isfile(config_file) is False: # Do not overwrite users microscopy files
30
+ with open(config_file, 'w', encoding='utf-8') as f:
31
+ f.write('\n'.join(lines))