pyTEMlib 0.2024.6.0__tar.gz → 0.2024.8.4__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.
Potentially problematic release.
This version of pyTEMlib might be problematic. Click here for more details.
- {pyTEMlib-0.2024.6.0/pyTEMlib.egg-info → pytemlib-0.2024.8.4}/PKG-INFO +18 -3
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/eds_tools.py +218 -167
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/image_tools.py +8 -4
- pytemlib-0.2024.8.4/pyTEMlib/version.py +6 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/xrpa_x_sections.py +140 -54
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4/pyTEMlib.egg-info}/PKG-INFO +18 -3
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib.egg-info/entry_points.txt +0 -1
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib.egg-info/requires.txt +1 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/setup.py +2 -1
- pyTEMlib-0.2024.6.0/pyTEMlib/version.py +0 -6
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/LICENSE +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/MANIFEST.in +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/README.rst +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/__init__.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/animation.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/atom_tools.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/config_dir.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/core_loss_widget.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/crystal_tools.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/diffraction_plot.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/dynamic_scattering.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/eels_dialog.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/eels_dialog_utilities.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/eels_tools.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/file_tools.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/file_tools_qt.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/graph_tools.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/graph_viz.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/image_dialog.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/image_dlg.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/info_widget.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/interactive_image.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/kinematic_scattering.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/low_loss_widget.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/microscope.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/peak_dialog.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/peak_dlg.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/probe_tools.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/sidpy_tools.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib/simulation_tools.py +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib.egg-info/SOURCES.txt +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib.egg-info/dependency_links.txt +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/pyTEMlib.egg-info/top_level.txt +0 -0
- {pyTEMlib-0.2024.6.0 → pytemlib-0.2024.8.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyTEMlib
|
|
3
|
-
Version: 0.2024.
|
|
3
|
+
Version: 0.2024.8.4
|
|
4
4
|
Summary: pyTEM: TEM Data Quantification library through a model-based approach
|
|
5
5
|
Home-page: https://pycroscopy.github.io/pyTEMlib/about.html
|
|
6
6
|
Author: Gerd Duscher
|
|
@@ -25,6 +25,23 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
25
25
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
26
26
|
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
27
27
|
License-File: LICENSE
|
|
28
|
+
Requires-Dist: scipy
|
|
29
|
+
Requires-Dist: numpy
|
|
30
|
+
Requires-Dist: pillow
|
|
31
|
+
Requires-Dist: ase
|
|
32
|
+
Requires-Dist: tqdm
|
|
33
|
+
Requires-Dist: plotly
|
|
34
|
+
Requires-Dist: pandas
|
|
35
|
+
Requires-Dist: requests
|
|
36
|
+
Requires-Dist: lxml
|
|
37
|
+
Requires-Dist: ipympl
|
|
38
|
+
Requires-Dist: build
|
|
39
|
+
Requires-Dist: spglib
|
|
40
|
+
Requires-Dist: scikit-image
|
|
41
|
+
Requires-Dist: scikit-learn
|
|
42
|
+
Requires-Dist: pyNSID>=0.0.7
|
|
43
|
+
Requires-Dist: sidpy>=0.12.1
|
|
44
|
+
Requires-Dist: SciFiReaders>=0.0.8
|
|
28
45
|
|
|
29
46
|
pyTEMlib
|
|
30
47
|
========
|
|
@@ -74,5 +91,3 @@ or via conda:
|
|
|
74
91
|
``conda install pyTEMlib -c conda-forge``
|
|
75
92
|
|
|
76
93
|
These installation options are also available in the `example notebooks <https://github.com/pycroscopy/pyTEMlib/notebooks>`_
|
|
77
|
-
|
|
78
|
-
|
|
@@ -56,7 +56,6 @@ shell_occupancy = {'K1': 2, 'L1': 2, 'L2': 2, 'L3': 4, 'M1': 2, 'M2': 2, 'M3': 4
|
|
|
56
56
|
def detector_response(dataset):
|
|
57
57
|
tags = dataset.metadata['experiment']
|
|
58
58
|
|
|
59
|
-
tags['acceleration_voltage_V'] = tags['microscope']['acceleration_voltage_V']
|
|
60
59
|
energy_scale = dataset.get_spectral_dims(return_axis=True)[0]
|
|
61
60
|
if 'start_channel' not in tags['detector']:
|
|
62
61
|
tags['detector']['start_channel'] = np.searchsorted(energy_scale, 100)
|
|
@@ -88,7 +87,7 @@ def get_detector_response(detector_definition, energy_scale):
|
|
|
88
87
|
-------
|
|
89
88
|
|
|
90
89
|
tags ={}
|
|
91
|
-
tags['
|
|
90
|
+
tags['acceleration_voltage'] = 200000
|
|
92
91
|
|
|
93
92
|
tags['detector'] ={}
|
|
94
93
|
|
|
@@ -182,19 +181,13 @@ def find_elements(spectrum, minor_peaks):
|
|
|
182
181
|
found = False
|
|
183
182
|
for element in range(3,82):
|
|
184
183
|
if 'lines' in x_sections[str(element)]:
|
|
185
|
-
if 'K-
|
|
186
|
-
if abs(x_sections[str(element)]['lines']['K-
|
|
184
|
+
if 'K-L2' in x_sections[str(element)]['lines']:
|
|
185
|
+
if abs(x_sections[str(element)]['lines']['K-L2']['position']- energy_scale[peak]) <10:
|
|
187
186
|
found = True
|
|
188
187
|
if x_sections[str(element)]['name'] not in elements:
|
|
189
188
|
elements.append( x_sections[str(element)]['name'])
|
|
190
189
|
if not found:
|
|
191
|
-
if '
|
|
192
|
-
if abs(x_sections[str(element)]['lines']['K-L2']['position']- energy_scale[peak]) <10:
|
|
193
|
-
found = True
|
|
194
|
-
if x_sections[str(element)]['name'] not in elements:
|
|
195
|
-
elements.append( x_sections[str(element)]['name'])
|
|
196
|
-
if not found:
|
|
197
|
-
if 'L3-M5' in x_sections[str(element)]['lines']:
|
|
190
|
+
if 'L3-M3' in x_sections[str(element)]['lines']:
|
|
198
191
|
if abs(x_sections[str(element)]['lines']['L3-M5']['position']- energy_scale[peak]) <30:
|
|
199
192
|
if x_sections[str(element)]['name'] not in elements:
|
|
200
193
|
elements.append( x_sections[str(element)]['name'])
|
|
@@ -212,87 +205,71 @@ def get_x_ray_lines(spectrum, elements):
|
|
|
212
205
|
# omega_K = Z**4/(alpha_K+Z**4)
|
|
213
206
|
# omega_L = Z**4/(alpha_L+Z**4)
|
|
214
207
|
# omega_M = Z**4/(alpha_M+Z**4)
|
|
215
|
-
energy_scale = spectrum.get_spectral_dims(return_axis=True)[0]
|
|
208
|
+
energy_scale = np.array(spectrum.get_spectral_dims(return_axis=True)[0].values)
|
|
216
209
|
for element in elements:
|
|
217
|
-
atomic_number = elements_list.index(element)
|
|
210
|
+
atomic_number = pyTEMlib.eds_tools.elements_list.index(element)
|
|
218
211
|
out_tags[element] ={'Z': atomic_number}
|
|
212
|
+
lines = x_sections[str(atomic_number)]['lines']
|
|
213
|
+
K_weight = 0
|
|
214
|
+
K_main = 'None'
|
|
215
|
+
K_lines = []
|
|
216
|
+
L_weight = 0
|
|
217
|
+
L_main = 'None'
|
|
218
|
+
L_lines = []
|
|
219
|
+
M_weight = 0
|
|
220
|
+
M_main = 'None'
|
|
221
|
+
M_lines = []
|
|
222
|
+
|
|
223
|
+
for key, line in lines.items():
|
|
224
|
+
if 'K' == key[0]:
|
|
225
|
+
if line['position'] < energy_scale[-1]:
|
|
226
|
+
K_lines.append(key)
|
|
227
|
+
if line['weight'] > K_weight:
|
|
228
|
+
K_weight = line['weight']
|
|
229
|
+
K_main = key
|
|
230
|
+
if 'L' == key[0]:
|
|
231
|
+
if line['position'] < energy_scale[-1]:
|
|
232
|
+
L_lines.append(key)
|
|
233
|
+
if line['weight'] > L_weight:
|
|
234
|
+
L_weight = line['weight']
|
|
235
|
+
L_main = key
|
|
236
|
+
if 'M' == key[0]:
|
|
237
|
+
if line['position'] < energy_scale[-1]:
|
|
238
|
+
M_lines.append(key)
|
|
239
|
+
if line['weight'] > M_weight:
|
|
240
|
+
M_weight = line['weight']
|
|
241
|
+
M_main = key
|
|
242
|
+
|
|
243
|
+
if K_weight > 0:
|
|
244
|
+
out_tags[element]['K-family'] = {'main': K_main, 'weight': K_weight, 'lines': K_lines}
|
|
245
|
+
height = spectrum[np.searchsorted(energy_scale, x_sections[str(atomic_number)]['lines'][K_main]['position'] )].compute()
|
|
246
|
+
out_tags[element]['K-family']['height'] = height/K_weight
|
|
247
|
+
for key in K_lines:
|
|
248
|
+
out_tags[element]['K-family'][key] = x_sections[str(atomic_number)]['lines'][key]
|
|
249
|
+
if L_weight > 0:
|
|
250
|
+
out_tags[element]['L-family'] = {'main': L_main, 'weight': L_weight, 'lines': L_lines}
|
|
251
|
+
height = spectrum[np.searchsorted(energy_scale, x_sections[str(atomic_number)]['lines'][L_main]['position'] )].compute()
|
|
252
|
+
out_tags[element]['L-family']['height'] = height/L_weight
|
|
253
|
+
for key in L_lines:
|
|
254
|
+
out_tags[element]['L-family'][key] = x_sections[str(atomic_number)]['lines'][key]
|
|
255
|
+
if M_weight > 0:
|
|
256
|
+
out_tags[element]['M-family'] = {'main': M_main, 'weight': M_weight, 'lines': M_lines}
|
|
257
|
+
height = spectrum[np.searchsorted(energy_scale, x_sections[str(atomic_number)]['lines'][M_main]['position'] )].compute()
|
|
258
|
+
out_tags[element]['M-family']['height'] = height/M_weight
|
|
259
|
+
for key in M_lines:
|
|
260
|
+
out_tags[element]['M-family'][key] = x_sections[str(atomic_number)]['lines'][key]
|
|
219
261
|
|
|
220
|
-
if 'K-L3' in x_sections[str(atomic_number)]['lines']:
|
|
221
|
-
if x_sections[str(atomic_number)]['lines']['K-L3']['position'] < energy_scale[-1]:
|
|
222
|
-
height = spectrum[np.searchsorted(energy_scale, x_sections[str(atomic_number)]['lines']['K-L3']['position'] )].compute()
|
|
223
|
-
out_tags[element]['K-family'] = {'height': height}
|
|
224
|
-
if 'K' in x_sections[str(atomic_number)]['fluorescent_yield']:
|
|
225
|
-
out_tags[element]['K-family']['yield'] = x_sections[str(atomic_number)]['fluorescent_yield']['K']
|
|
226
|
-
else:
|
|
227
|
-
out_tags[element]['K-family']['yield'] = atomic_number**4/(alpha_K+atomic_number**4)/4/1.4
|
|
228
|
-
|
|
229
|
-
if 'L3-M5' in x_sections[str(atomic_number)]['lines']:
|
|
230
|
-
if x_sections[str(atomic_number)]['lines']['L3-M5']['position'] < energy_scale[-1]:
|
|
231
|
-
height = spectrum[np.searchsorted(energy_scale, x_sections[str(atomic_number)]['lines']['L3-M5']['position'] )].compute()
|
|
232
|
-
out_tags[element]['L-family'] = {'height': height}
|
|
233
|
-
if 'L' in x_sections[str(atomic_number)]['fluorescent_yield']:
|
|
234
|
-
out_tags[element]['L-family']['yield'] = x_sections[str(atomic_number)]['fluorescent_yield']['L']
|
|
235
|
-
else:
|
|
236
|
-
out_tags[element]['L-family']['yield'] = (atomic_number**4/(alpha_L+atomic_number**4))**2
|
|
237
|
-
|
|
238
|
-
if 'M5-N6' in x_sections[str(atomic_number)]['lines']:
|
|
239
|
-
if x_sections[str(atomic_number)]['lines']['M5-N6']['position'] < energy_scale[-1]:
|
|
240
|
-
height = spectrum[np.searchsorted(energy_scale, x_sections[str(atomic_number)]['lines']['M5-N6']['position'] )].compute()
|
|
241
|
-
out_tags[element]['M-family'] = {'height': height}
|
|
242
|
-
if 'M' in x_sections[str(atomic_number)]['fluorescent_yield']:
|
|
243
|
-
out_tags[element]['M-family']['yield'] = x_sections[str(atomic_number)]['fluorescent_yield']['M']
|
|
244
|
-
else:
|
|
245
|
-
out_tags[element]['M-family']['yield'] = (atomic_number**4/(alpha_M+atomic_number**4))**2
|
|
246
|
-
|
|
247
|
-
for key, line in x_sections[str(atomic_number)]['lines'].items():
|
|
248
|
-
other = True
|
|
249
|
-
if line['weight'] > 0.01 and line['position'] < 3e4:
|
|
250
|
-
if 'K-family' in out_tags[element]:
|
|
251
|
-
if key[0] == 'K':
|
|
252
|
-
other = False
|
|
253
|
-
out_tags[element]['K-family'][key]=line
|
|
254
|
-
if 'L-family' in out_tags[element]:
|
|
255
|
-
if key[:2] in ['L2', 'L3']:
|
|
256
|
-
other = False
|
|
257
|
-
out_tags[element]['L-family'][key]=line
|
|
258
|
-
if 'M-family' in out_tags[element]:
|
|
259
|
-
if key[:2] in ['M5', 'M4']:
|
|
260
|
-
other = False
|
|
261
|
-
out_tags[element]['M-family'][key]=line
|
|
262
|
-
if other:
|
|
263
|
-
if 'other' not in out_tags[element]:
|
|
264
|
-
out_tags[element]['other'] = {}
|
|
265
|
-
height = spectrum[np.searchsorted(energy_scale, x_sections[str(atomic_number)]['lines'][key]['position'] )].compute()
|
|
266
|
-
out_tags[element]['other'][key]=line
|
|
267
|
-
out_tags[element]['other'][key]['height'] = height
|
|
268
|
-
|
|
269
262
|
xs = get_eds_cross_sections(atomic_number)
|
|
270
263
|
if 'K' in xs and 'K-family' in out_tags[element]:
|
|
271
|
-
out_tags[element]['K-family']['
|
|
264
|
+
out_tags[element]['K-family']['probability'] = xs['K']
|
|
272
265
|
if 'L' in xs and 'L-family' in out_tags[element]:
|
|
273
|
-
out_tags[element]['L-family']['
|
|
266
|
+
out_tags[element]['L-family']['probability'] = xs['L']
|
|
274
267
|
if 'M' in xs and 'M-family' in out_tags[element]:
|
|
275
|
-
out_tags[element]['M-family']['
|
|
268
|
+
out_tags[element]['M-family']['probability'] = xs['M']
|
|
276
269
|
|
|
277
|
-
"""
|
|
278
|
-
We really should use the sum of the family
|
|
279
|
-
for key, x_lines in out_tags.items():
|
|
280
|
-
if 'K-family' in x_lines:
|
|
281
|
-
xs = pyTEMlib.eels_tools.xsec_xrpa(np.arange(100)+x_sections[str(x_lines['Z'])]['K1']['onset'], 200,x_lines['Z'], 100).sum()
|
|
282
|
-
|
|
283
|
-
x_lines['K-family']['ionization_x_section'] = xs
|
|
284
|
-
|
|
285
|
-
if 'L-family' in x_lines:
|
|
286
|
-
xs = pyTEMlib.eels_tools.xsec_xrpa(np.arange(100)+x_sections[str(x_lines['Z'])]['L3']['onset'], 200,x_lines['Z'], 100).sum()
|
|
287
|
-
x_lines['L-family']['ionization_x_section'] = xs
|
|
288
|
-
if 'M-family' in x_lines:
|
|
289
|
-
xs = pyTEMlib.eels_tools.xsec_xrpa(np.arange(100)+x_sections[str(x_lines['Z'])]['M5']['onset'], 200,x_lines['Z'], 100).sum()
|
|
290
|
-
x_lines['M-family']['ionization_x_section'] = xs
|
|
291
|
-
"""
|
|
292
270
|
if 'EDS' not in spectrum.metadata:
|
|
293
271
|
spectrum.metadata['EDS'] = {}
|
|
294
|
-
|
|
295
|
-
spectrum.metadata['EDS']['lines'] = out_tags
|
|
272
|
+
spectrum.metadata['EDS'].update(out_tags)
|
|
296
273
|
return out_tags
|
|
297
274
|
|
|
298
275
|
|
|
@@ -313,7 +290,7 @@ def get_peak(E, energy_scale):
|
|
|
313
290
|
|
|
314
291
|
|
|
315
292
|
def initial_model_parameter(spectrum):
|
|
316
|
-
tags = spectrum.metadata['EDS']
|
|
293
|
+
tags = spectrum.metadata['EDS']
|
|
317
294
|
energy_scale = spectrum.get_spectral_dims(return_axis=True)[0]
|
|
318
295
|
p = []
|
|
319
296
|
peaks = []
|
|
@@ -324,9 +301,9 @@ def initial_model_parameter(spectrum):
|
|
|
324
301
|
for line, info in lines['K-family'].items():
|
|
325
302
|
if line[0] == 'K':
|
|
326
303
|
model += get_peak(info['position'], energy_scale)*info['weight']
|
|
327
|
-
lines['K-family']['peaks'] = model/model.sum()
|
|
328
|
-
|
|
329
|
-
p.append(lines['K-family']['height'])
|
|
304
|
+
lines['K-family']['peaks'] = model /model.sum() # *lines['K-family']['probability']
|
|
305
|
+
|
|
306
|
+
p.append(lines['K-family']['height'] / lines['K-family']['peaks'].max())
|
|
330
307
|
peaks.append(lines['K-family']['peaks'])
|
|
331
308
|
keys.append(element+':K-family')
|
|
332
309
|
if 'L-family' in lines:
|
|
@@ -334,9 +311,8 @@ def initial_model_parameter(spectrum):
|
|
|
334
311
|
for line, info in lines['L-family'].items():
|
|
335
312
|
if line[0] == 'L':
|
|
336
313
|
model += get_peak(info['position'], energy_scale)*info['weight']
|
|
337
|
-
lines['L-family']['peaks'] = model/model.sum()
|
|
338
|
-
lines['L-family']['height']
|
|
339
|
-
p.append(lines['L-family']['height'])
|
|
314
|
+
lines['L-family']['peaks'] = model /model.sum() # *lines['L-family']['probability']
|
|
315
|
+
p.append(lines['L-family']['height'] / lines['L-family']['peaks'].max())
|
|
340
316
|
peaks.append(lines['L-family']['peaks'])
|
|
341
317
|
keys.append(element+':L-family')
|
|
342
318
|
if 'M-family' in lines:
|
|
@@ -344,18 +320,11 @@ def initial_model_parameter(spectrum):
|
|
|
344
320
|
for line, info in lines['M-family'].items():
|
|
345
321
|
if line[0] == 'M':
|
|
346
322
|
model += get_peak(info['position'], energy_scale)*info['weight']
|
|
347
|
-
lines['M-family']['peaks'] = model/model.sum()
|
|
348
|
-
lines['M-family']['height']
|
|
349
|
-
p.append(lines['M-family']['height'])
|
|
323
|
+
lines['M-family']['peaks'] = model /model.sum()*lines['M-family']['probability']
|
|
324
|
+
p.append(lines['M-family']['height'] / lines['M-family']['peaks'].max())
|
|
350
325
|
peaks.append(lines['M-family']['peaks'])
|
|
351
326
|
keys.append(element+':M-family')
|
|
352
|
-
|
|
353
|
-
if 'other' in lines:
|
|
354
|
-
for line, info in lines['other'].items():
|
|
355
|
-
info['peak'] = get_peak(info['position'], energy_scale)
|
|
356
|
-
peaks.append(info['peak'])
|
|
357
|
-
p.append(info['height'])
|
|
358
|
-
keys.append(element+':other:'+line)
|
|
327
|
+
|
|
359
328
|
|
|
360
329
|
#p.extend([300, 10, 1.e-04])
|
|
361
330
|
# p.extend([1, 300, -.02])
|
|
@@ -363,22 +332,23 @@ def initial_model_parameter(spectrum):
|
|
|
363
332
|
return np.array(peaks), np.array(p), keys
|
|
364
333
|
|
|
365
334
|
def get_model(spectrum, start=100):
|
|
366
|
-
|
|
367
|
-
peaks, pp, keys = initial_model_parameter(spectrum)
|
|
368
335
|
model = np.zeros(len(spectrum))
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
336
|
+
for key in spectrum.metadata['EDS']:
|
|
337
|
+
for family in spectrum.metadata['EDS'][key]:
|
|
338
|
+
if isinstance(spectrum.metadata['EDS'][key][family], dict):
|
|
339
|
+
intensity = spectrum.metadata['EDS'][key][family]['areal_density']
|
|
340
|
+
peaks = spectrum.metadata['EDS'][key][family]['peaks']
|
|
341
|
+
model += peaks * intensity
|
|
342
|
+
|
|
343
|
+
if 'detector_efficiency' in spectrum.metadata['EDS']['detector'].keys():
|
|
344
|
+
detector_efficiency = spectrum.metadata['EDS']['detector']['detector_efficiency']
|
|
375
345
|
else:
|
|
376
346
|
detector_efficiency = None
|
|
377
|
-
E_0 = spectrum.metadata['experiment']['
|
|
347
|
+
E_0 = spectrum.metadata['experiment']['acceleration_voltage']
|
|
378
348
|
|
|
379
|
-
if detector_efficiency is not None:
|
|
380
|
-
|
|
381
|
-
|
|
349
|
+
# if detector_efficiency is not None:
|
|
350
|
+
# model[start:] += detector_efficiency[start:] * (pp[-3] + pp[-2] * (E_0 - energy_scale) / energy_scale +
|
|
351
|
+
# pp[-1] * (E_0 - energy_scale) ** 2 / energy_scale)
|
|
382
352
|
|
|
383
353
|
return model
|
|
384
354
|
|
|
@@ -386,22 +356,22 @@ def fit_model(spectrum, elements, use_detector_efficiency=False):
|
|
|
386
356
|
out_tags = get_x_ray_lines(spectrum, elements)
|
|
387
357
|
peaks, pin, keys = initial_model_parameter(spectrum)
|
|
388
358
|
energy_scale = spectrum.get_spectral_dims(return_axis=True)[0].values
|
|
389
|
-
|
|
390
|
-
if 'detector' in spectrum.metadata['
|
|
391
|
-
if 'start_channel' not in spectrum.metadata['
|
|
392
|
-
spectrum.metadata['
|
|
393
|
-
if 'detector_efficiency' in spectrum.metadata['
|
|
359
|
+
|
|
360
|
+
if 'detector' in spectrum.metadata['EDS'].keys():
|
|
361
|
+
if 'start_channel' not in spectrum.metadata['EDS']['detector']:
|
|
362
|
+
spectrum.metadata['EDS']['detector']['start_channel'] = np.searchsorted(energy_scale, 100)
|
|
363
|
+
if 'detector_efficiency' in spectrum.metadata['EDS']['detector'].keys():
|
|
394
364
|
if use_detector_efficiency:
|
|
395
|
-
detector_efficiency = spectrum.metadata['
|
|
365
|
+
detector_efficiency = spectrum.metadata['EDS']['detector']['detector_efficiency']
|
|
396
366
|
else:
|
|
397
367
|
use_detector_efficiency = False
|
|
398
368
|
else:
|
|
399
369
|
print('need detector information to fit spectrum')
|
|
400
370
|
return
|
|
401
|
-
start = spectrum.metadata['
|
|
371
|
+
start = spectrum.metadata['EDS']['detector']['start_channel']
|
|
402
372
|
energy_scale = energy_scale[start:]
|
|
403
373
|
|
|
404
|
-
E_0= spectrum.metadata['experiment']['
|
|
374
|
+
E_0= spectrum.metadata['experiment']['acceleration_voltage']
|
|
405
375
|
|
|
406
376
|
def residuals(pp, yy):
|
|
407
377
|
#get_model(peaks, pp, detector_efficiency=None)
|
|
@@ -426,33 +396,31 @@ def fit_model(spectrum, elements, use_detector_efficiency=False):
|
|
|
426
396
|
|
|
427
397
|
# print(pin[-6:], p[-6:])
|
|
428
398
|
|
|
429
|
-
update_fit_values(out_tags, p)
|
|
399
|
+
update_fit_values(out_tags, peaks, p)
|
|
430
400
|
|
|
431
401
|
|
|
432
402
|
if 'EDS' not in spectrum.metadata:
|
|
433
403
|
spectrum.metadata['EDS'] = {}
|
|
434
|
-
spectrum.metadata['EDS']
|
|
404
|
+
spectrum.metadata['EDS'].update(out_tags)
|
|
435
405
|
|
|
436
406
|
return np.array(peaks), np.array(p)
|
|
437
407
|
|
|
438
408
|
|
|
439
|
-
def update_fit_values(out_tags, p):
|
|
409
|
+
def update_fit_values(out_tags, peaks, p):
|
|
440
410
|
index = 0
|
|
441
411
|
for element, lines in out_tags.items():
|
|
442
412
|
if 'K-family' in lines:
|
|
443
|
-
lines['K-family']['
|
|
413
|
+
lines['K-family']['areal_density'] = p[index]
|
|
414
|
+
lines['K-family']['peaks'] = peaks[index]
|
|
444
415
|
index += 1
|
|
445
416
|
if 'L-family' in lines:
|
|
446
|
-
lines['L-family']['
|
|
417
|
+
lines['L-family']['areal_density'] = p[index]
|
|
418
|
+
lines['L-family']['peaks'] = peaks[index]
|
|
447
419
|
index += 1
|
|
448
420
|
if 'M-family' in lines:
|
|
449
|
-
lines['M-family']['
|
|
421
|
+
lines['M-family']['areal_density'] =p[index]
|
|
422
|
+
lines['M-family']['peaks'] = peaks[index]
|
|
450
423
|
index += 1
|
|
451
|
-
if 'other' in lines:
|
|
452
|
-
for line, info in lines['other'].items():
|
|
453
|
-
info['height'] = p[index]
|
|
454
|
-
index += 1
|
|
455
|
-
|
|
456
424
|
|
|
457
425
|
def get_eds_xsection(Xsection, energy_scale, start_bgd, end_bgd):
|
|
458
426
|
background = pyTEMlib.eels_tools.power_law_background(Xsection, energy_scale, [start_bgd, end_bgd], verbose=False)
|
|
@@ -462,44 +430,97 @@ def get_eds_xsection(Xsection, energy_scale, start_bgd, end_bgd):
|
|
|
462
430
|
return cross_section_core
|
|
463
431
|
|
|
464
432
|
|
|
465
|
-
def get_eds_cross_sections(z):
|
|
466
|
-
energy_scale = np.arange(
|
|
467
|
-
Xsection = pyTEMlib.eels_tools.xsec_xrpa(energy_scale,
|
|
433
|
+
def get_eds_cross_sections(z, acceleration_voltage=200000):
|
|
434
|
+
energy_scale = np.arange(1,20000)
|
|
435
|
+
Xsection = pyTEMlib.eels_tools.xsec_xrpa(energy_scale, acceleration_voltage/1000., z, 400.)
|
|
468
436
|
edge_info = pyTEMlib.eels_tools.get_x_sections(z)
|
|
437
|
+
|
|
438
|
+
|
|
469
439
|
eds_cross_sections = {}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
start_bgd
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
440
|
+
Xyield = edge_info['total_fluorescent_yield']
|
|
441
|
+
if 'K' in Xyield:
|
|
442
|
+
start_bgd = edge_info['K1']['onset'] * 0.8
|
|
443
|
+
end_bgd = edge_info['K1']['onset'] - 5
|
|
444
|
+
if start_bgd > end_bgd:
|
|
445
|
+
start_bgd = end_bgd-100
|
|
446
|
+
if start_bgd > energy_scale[0] and end_bgd< energy_scale[-1]-100:
|
|
447
|
+
eds_xsection = get_eds_xsection(Xsection, energy_scale, start_bgd, end_bgd)
|
|
448
|
+
eds_xsection[eds_xsection<0] = 0.
|
|
449
|
+
start_sum = np.searchsorted(energy_scale, edge_info['K1']['onset'])
|
|
450
|
+
end_sum = start_sum+600
|
|
451
|
+
if end_sum> len(Xsection):
|
|
452
|
+
end_sum = len(Xsection)-1
|
|
453
|
+
eds_cross_sections['K1'] = eds_xsection[start_sum:end_sum].sum()
|
|
454
|
+
eds_cross_sections['K'] = eds_xsection[start_sum:end_sum].sum() * Xyield['K']
|
|
455
|
+
|
|
456
|
+
if 'L3' in Xyield:
|
|
457
|
+
start_bgd = edge_info['L3']['onset'] * 0.8
|
|
458
|
+
end_bgd = edge_info['L3']['onset'] - 5
|
|
459
|
+
if start_bgd > end_bgd:
|
|
460
|
+
start_bgd = end_bgd-100
|
|
461
|
+
if start_bgd > energy_scale[0] and end_bgd< energy_scale[-1]-100:
|
|
462
|
+
eds_xsection = get_eds_xsection(Xsection, energy_scale, start_bgd, end_bgd)
|
|
463
|
+
eds_xsection[eds_xsection<0] = 0.
|
|
464
|
+
start_sum = np.searchsorted(energy_scale, edge_info['L3']['onset'])
|
|
465
|
+
end_sum = start_sum+600
|
|
466
|
+
if end_sum> len(Xsection):
|
|
467
|
+
end_sum = len(Xsection)-1
|
|
468
|
+
if end_sum >np.searchsorted(energy_scale, edge_info['K1']['onset'])-10:
|
|
469
|
+
end_sum = np.searchsorted(energy_scale, edge_info['K1']['onset'])-10
|
|
470
|
+
eds_cross_sections['L'] = eds_xsection[start_sum:end_sum].sum()
|
|
471
|
+
L1_channel = np.searchsorted(energy_scale, edge_info['L1']['onset'])
|
|
472
|
+
m_start = start_sum-100
|
|
473
|
+
if m_start < 2:
|
|
474
|
+
m_start = start_sum-20
|
|
475
|
+
l3_rise = np.max(Xsection[m_start: L1_channel-10])-np.min(Xsection[m_start: L1_channel-10])
|
|
476
|
+
l1_rise = np.max(Xsection[L1_channel-10: L1_channel+100])-np.min(Xsection[L1_channel-10: L1_channel+100])
|
|
477
|
+
l1_ratio = l1_rise/l3_rise
|
|
478
|
+
|
|
479
|
+
eds_cross_sections['L1'] = l1_ratio * eds_cross_sections['L']
|
|
480
|
+
eds_cross_sections['L2'] = eds_cross_sections['L']*(1-l1_ratio)*1/3
|
|
481
|
+
eds_cross_sections['L3'] = eds_cross_sections['L']*(1-l1_ratio)*2/3
|
|
482
|
+
eds_cross_sections['yield_L1'] = Xyield['L1']
|
|
483
|
+
eds_cross_sections['yield_L2'] = Xyield['L2']
|
|
484
|
+
eds_cross_sections['yield_L3'] = Xyield['L3']
|
|
485
|
+
|
|
486
|
+
eds_cross_sections['L'] = eds_cross_sections['L1']*Xyield['L1']+eds_cross_sections['L2']*Xyield['L2']+eds_cross_sections['L3']*Xyield['L3']
|
|
487
|
+
# eds_cross_sections['L'] /= 8
|
|
488
|
+
if 'M5' in Xyield:
|
|
489
|
+
start_bgd = edge_info['M5']['onset'] * 0.8
|
|
490
|
+
end_bgd = edge_info['M5']['onset'] - 5
|
|
491
|
+
if start_bgd > end_bgd:
|
|
492
|
+
start_bgd = end_bgd-100
|
|
493
|
+
if start_bgd > energy_scale[0] and end_bgd< energy_scale[-1]-100:
|
|
494
|
+
eds_xsection = get_eds_xsection(Xsection, energy_scale, start_bgd, end_bgd)
|
|
495
|
+
eds_xsection[eds_xsection<0] = 0.
|
|
496
|
+
start_sum = np.searchsorted(energy_scale, edge_info['M5']['onset'])
|
|
497
|
+
end_sum = start_sum+600
|
|
498
|
+
if end_sum > np.searchsorted(energy_scale, edge_info['L3']['onset'])-10:
|
|
499
|
+
end_sum = np.searchsorted(energy_scale, edge_info['L3']['onset'])-10
|
|
500
|
+
eds_cross_sections['M'] = eds_xsection[start_sum:end_sum].sum()
|
|
501
|
+
#print(edge_info['M5']['onset'] - edge_info['M1']['onset'])
|
|
502
|
+
M3_channel = np.searchsorted(energy_scale, edge_info['M3']['onset'])
|
|
503
|
+
M1_channel = np.searchsorted(energy_scale, edge_info['M1']['onset'])
|
|
504
|
+
m5_rise = np.max(Xsection[start_sum-100: M3_channel-10])-np.min(Xsection[start_sum-100: M3_channel-10])
|
|
505
|
+
m3_rise = np.max(Xsection[M3_channel-10: M1_channel-10])-np.min(Xsection[M3_channel-10: M1_channel-10])
|
|
506
|
+
m1_rise = np.max(Xsection[M1_channel-10: M1_channel+100])-np.min(Xsection[M1_channel-10: M1_channel+100])
|
|
507
|
+
m1_ratio = m1_rise/m5_rise
|
|
508
|
+
m3_ratio = m3_rise/m5_rise
|
|
509
|
+
m5_ratio = 1-(m1_ratio+m3_ratio)
|
|
510
|
+
#print(m1_ratio, m3_ratio, 1-(m1_ratio+m3_ratio))
|
|
511
|
+
eds_cross_sections['M1'] = m1_ratio * eds_cross_sections['M']
|
|
512
|
+
eds_cross_sections['M2'] = m3_ratio * eds_cross_sections['M']*1/3
|
|
513
|
+
eds_cross_sections['M3'] = m3_ratio * eds_cross_sections['M']*2/3
|
|
514
|
+
eds_cross_sections['M4'] = m5_ratio * eds_cross_sections['M']*2/5
|
|
515
|
+
eds_cross_sections['M5'] = m5_ratio * eds_cross_sections['M']*3/5
|
|
516
|
+
eds_cross_sections['yield_M1'] = Xyield['M1']
|
|
517
|
+
eds_cross_sections['yield_M2'] = Xyield['M2']
|
|
518
|
+
eds_cross_sections['yield_M3'] = Xyield['M3']
|
|
519
|
+
eds_cross_sections['yield_M4'] = Xyield['M4']
|
|
520
|
+
eds_cross_sections['yield_M5'] = Xyield['M5']
|
|
521
|
+
eds_cross_sections['M'] = eds_cross_sections['M1']*Xyield['M1']+eds_cross_sections['M2']*Xyield['M2']+eds_cross_sections['M3']*Xyield['M3'] \
|
|
522
|
+
+eds_cross_sections['M4']*Xyield['M4']+eds_cross_sections['M5']*Xyield['M5']
|
|
523
|
+
#eds_cross_sections['M'] /= 18
|
|
503
524
|
return eds_cross_sections
|
|
504
525
|
|
|
505
526
|
|
|
@@ -555,4 +576,34 @@ def plot_phases(dataset, image=None, survey_image=None):
|
|
|
555
576
|
plt.legend()
|
|
556
577
|
plt.tight_layout()
|
|
557
578
|
plt.show()
|
|
558
|
-
return fig
|
|
579
|
+
return fig
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
def plot_lines(eds_quantification: dict, axis: plt.Axes):
|
|
583
|
+
for key, lines in eds_quantification.items():
|
|
584
|
+
if 'K-family' in lines:
|
|
585
|
+
intensity = lines['K-family']['height']
|
|
586
|
+
for line in lines['K-family']:
|
|
587
|
+
if line[0] == 'K':
|
|
588
|
+
pos = lines['K-family'][line]['position']
|
|
589
|
+
axis.plot([pos,pos], [0, intensity*lines['K-family'][line]['weight']], color='blue')
|
|
590
|
+
if line == lines['K-family']['main']:
|
|
591
|
+
axis.text(pos,0, key+'\n'+line, verticalalignment='top')
|
|
592
|
+
|
|
593
|
+
if 'L-family' in lines:
|
|
594
|
+
intensity = lines['L-family']['height']
|
|
595
|
+
for line in lines['L-family']:
|
|
596
|
+
if line[0] == 'L':
|
|
597
|
+
pos = lines['L-family'][line]['position']
|
|
598
|
+
axis.plot([pos,pos], [0, intensity*lines['L-family'][line]['weight']], color='black')
|
|
599
|
+
if line in [lines['L-family']['main'], 'L3-M5', 'L3-N5', 'L1-M3']:
|
|
600
|
+
axis.text(pos,0, key+'\n'+line, verticalalignment='top')
|
|
601
|
+
|
|
602
|
+
if 'M-family' in lines:
|
|
603
|
+
intensity = lines['M-family']['height']
|
|
604
|
+
for line in lines['M-family']:
|
|
605
|
+
if line[0] == 'M':
|
|
606
|
+
pos = lines['M-family'][line]['position']
|
|
607
|
+
axis.plot([pos,pos], [0, intensity*lines['M-family'][line]['weight']], color='green')
|
|
608
|
+
if line in [lines['M-family']['main'], 'M5-N7', 'M4-N6']:
|
|
609
|
+
axis.text(pos,0, key+'\n'+line, verticalalignment='top')
|
|
@@ -601,8 +601,12 @@ def rigid_registration(dataset, sub_pixel=True):
|
|
|
601
601
|
rig_reg, drift = rig_reg_drift(dataset, relative_drift)
|
|
602
602
|
crop_reg, input_crop = crop_image_stack(rig_reg, drift)
|
|
603
603
|
|
|
604
|
-
rigid_registered =
|
|
605
|
-
|
|
604
|
+
rigid_registered = sidpy.Dataset.from_array(crop_reg,
|
|
605
|
+
title='Rigid Registration',
|
|
606
|
+
data_type='IMAGE_STACK',
|
|
607
|
+
quantity=dataset.quantity,
|
|
608
|
+
units=dataset.units)
|
|
609
|
+
rigid_registered.title = 'Rigid_Registration'
|
|
606
610
|
rigid_registered.source = dataset.title
|
|
607
611
|
rigid_registered.metadata = {'analysis': 'rigid sub-pixel registration', 'drift': drift,
|
|
608
612
|
'input_crop': input_crop, 'input_shape': dataset.shape[1:]}
|
|
@@ -664,9 +668,9 @@ def rig_reg_drift(dset, rel_drift):
|
|
|
664
668
|
# absolute drift
|
|
665
669
|
print(rel_drift)
|
|
666
670
|
drift = np.array(rel_drift).copy()
|
|
667
|
-
|
|
671
|
+
|
|
668
672
|
drift[0] = [0, 0]
|
|
669
|
-
for i in range(drift.shape[0]):
|
|
673
|
+
for i in range(1, drift.shape[0]):
|
|
670
674
|
drift[i] = drift[i - 1] + rel_drift[i]
|
|
671
675
|
center_drift = drift[int(drift.shape[0] / 2)]
|
|
672
676
|
drift = drift - center_drift
|