pyTEMlib 0.2025.4.2__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 -928
  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.2.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.2.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.2.dist-info/RECORD +0 -38
  92. pytemlib-0.2025.4.2.dist-info/top_level.txt +0 -1
  93. {pytemlib-0.2025.4.2.dist-info → pytemlib-0.2025.9.1.dist-info}/entry_points.txt +0 -0
  94. {pytemlib-0.2025.4.2.dist-info → pytemlib-0.2025.9.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,479 +0,0 @@
1
- from typing import Any
2
-
3
- import numpy as np
4
- import os
5
- import ipywidgets
6
- import matplotlib.pylab as plt
7
- import matplotlib
8
- from IPython.display import display
9
-
10
- import sidpy
11
- # from pyTEMlib.microscope import microscope
12
- from pyTEMlib import file_tools
13
- from pyTEMlib import eels_tools
14
-
15
-
16
- def get_low_loss_sidebar() -> Any:
17
- side_bar = ipywidgets.GridspecLayout(17, 3, width='auto', grid_gap="0px")
18
-
19
- side_bar[0, :2] = ipywidgets.Dropdown(
20
- options=[('None', 0)],
21
- value=0,
22
- description='Low-Loss:',
23
- disabled=False)
24
-
25
- row = 1
26
-
27
- side_bar[row, :3] = ipywidgets.Button(description='Resolution Function',
28
- layout=ipywidgets.Layout(width='auto', grid_area='header'),
29
- style=ipywidgets.ButtonStyle(button_color='lightblue'))
30
- row += 1
31
- side_bar[row, :2] = ipywidgets.FloatText(value=7.5, description='fit width:', disabled=False, color='black',
32
- layout=ipywidgets.Layout(width='200px'))
33
- side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px'))
34
- row +=1
35
- side_bar[row, 0] = ipywidgets.ToggleButton(description='Plot Res.Fct.',
36
- disabled=False,
37
- button_style='', # 'success', 'info', 'warning', 'danger' or ''
38
- tooltip='Plots resolution function on right',
39
- layout=ipywidgets.Layout(width='100px'))
40
-
41
- side_bar[row, 2] = ipywidgets.ToggleButton(description='Probability',
42
- disabled=False,
43
- button_style='', # 'success', 'info', 'warning', 'danger' or ''
44
- tooltip='Changes y-axis to probability if flux is given',
45
- layout=ipywidgets.Layout(width='100px'))
46
-
47
-
48
- row += 1
49
- side_bar[row, :3] = ipywidgets.Button(description='Drude',
50
- layout=ipywidgets.Layout(width='auto', grid_area='header'),
51
- style=ipywidgets.ButtonStyle(button_color='lightblue'))
52
- row += 1
53
- side_bar[row, :2] = ipywidgets.FloatText(value=5, description='Start Fit:', disabled=False, color='black',
54
- layout=ipywidgets.Layout(width='200px'))
55
- side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px'))
56
- row += 1
57
- side_bar[row, :2] = ipywidgets.FloatText(value=25, description='End Fit:', disabled=False, color='black',
58
- layout=ipywidgets.Layout(width='200px'))
59
- side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='50px'))
60
- row += 1
61
- side_bar[row, :2] = ipywidgets.FloatText(value=5, description='Energy:', disabled=False, color='black',
62
- layout=ipywidgets.Layout(width='200px'))
63
- side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px'))
64
- row += 1
65
- side_bar[row, :2] = ipywidgets.FloatText(value=25, description='Width:', disabled=False, color='black',
66
- layout=ipywidgets.Layout(width='200px'))
67
- side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='50px'))
68
- row += 1
69
- side_bar[row, :2] = ipywidgets.FloatText(value=25, description='Amplitude:', disabled=False, color='black',
70
- layout=ipywidgets.Layout(width='200px'))
71
- side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='50px'))
72
- row +=1
73
- side_bar[row, 0] = ipywidgets.ToggleButton(description='Plot Drude',
74
- disabled=False,
75
- button_style='', # 'success', 'info', 'warning', 'danger' or ''
76
- tooltip='Plots resolution function on right',
77
- layout=ipywidgets.Layout(width='100px'))
78
-
79
- side_bar[row, 2] = ipywidgets.ToggleButton(description='Plot Diel.Fct.',
80
- disabled=False,
81
- button_style='', # 'success', 'info', 'warning', 'danger' or ''
82
- tooltip='Changes y-axis to probability if flux is given',
83
- layout=ipywidgets.Layout(width='100px'))
84
- side_bar[row, 1] = ipywidgets.ToggleButton(description='Do All',
85
- disabled=False,
86
- button_style='', # 'success', 'info', 'warning', 'danger' or ''
87
- tooltip='Changes y-axis to probability if flux is given',
88
- layout=ipywidgets.Layout(width='100px'))
89
- row += 1
90
- side_bar[row, :3] = ipywidgets.Button(description='Multiple Scattering',
91
- layout=ipywidgets.Layout(width='auto', grid_area='header'),
92
- style=ipywidgets.ButtonStyle(button_color='lightblue'))
93
- row += 1
94
- side_bar[row, :2] = ipywidgets.FloatText(value=5, description='Start Fit:', disabled=False, color='black',
95
- layout=ipywidgets.Layout(width='200px'))
96
- side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px'))
97
- row += 1
98
- side_bar[row, :2] = ipywidgets.FloatText(value=-1, description='End Fit:', disabled=False, color='black',
99
- layout=ipywidgets.Layout(width='200px'))
100
- side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='50px'))
101
- row +=1
102
- side_bar[row, :2] = ipywidgets.FloatText(value=25, description='thickness:', disabled=False, color='black',
103
- layout=ipywidgets.Layout(width='200px'))
104
- side_bar[row, 2] = ipywidgets.widgets.Label(value="* iMFP", layout=ipywidgets.Layout(width='50px'))
105
-
106
- row +=1
107
- side_bar[row, 0] = ipywidgets.ToggleButton(description='Plot LowLoss',
108
- disabled=False,
109
- button_style='', # 'success', 'info', 'warning', 'danger' or ''
110
- tooltip='Plots resolution function on right',
111
- layout=ipywidgets.Layout(width='100px'))
112
-
113
-
114
- side_bar[row, 1:3] = ipywidgets.IntProgress(value=0, min=0, max=10, description=' ', bar_style='', # 'success', 'info', 'warning', 'danger' or ''
115
- style={'bar_color': 'maroon'}, orientation='horizontal')
116
- return side_bar
117
-
118
- class LowLoss(object):
119
- def __init__(self, sidebar=None, parent=None):
120
- self.parent = parent
121
- self.dataset = parent.dataset
122
- self.low_loss_tab = sidebar
123
- self.set_ll_action()
124
- self.ll_key = ''
125
- self.update_ll_sidebar()
126
-
127
- def update_ll_sidebar(self):
128
- spectrum_list = ['None']
129
- ll_index = 0
130
- self.ll_key = self.parent.lowloss_key
131
- for index, key in enumerate(self.parent.datasets.keys()):
132
- if isinstance(self.parent.datasets[key], sidpy.Dataset):
133
- if 'SPECTR' in self.parent.datasets[key].data_type.name:
134
- energy_offset = self.parent.datasets[key].get_spectral_dims(return_axis=True)[0][0]
135
- if energy_offset < 0:
136
- spectrum_list.append(f'{key}: {self.parent.datasets[key].title}')
137
- if key == self.ll_key:
138
- ll_index = index-1
139
-
140
- if ll_index >len(spectrum_list) - 1:
141
- ll_index = len(spectrum_list) - 1
142
-
143
- self.low_loss_tab[0, 0].options = spectrum_list
144
- self.low_loss_tab[0, 0].value = spectrum_list[ll_index]
145
-
146
- self.update_ll_dataset()
147
-
148
- def update_ll_dataset(self, value=0):
149
- self.ll_key = self.low_loss_tab[0, 0].value.split(':')[0]
150
- self.parent.lowloss_key = self.ll_key
151
- if 'None' in self.ll_key:
152
- return
153
- self.parent.set_dataset(self.ll_key)
154
- self.dataset = self.parent.dataset
155
- if self.low_loss_tab[13, 0].value < 0:
156
- energy_scale = self.dataset.get_spectral_dims(return_axis=True)[0]
157
- self.low_loss_tab[13, 0].value = np.round(self.dataset.get_spectral_dims(return_axis=True)[0][-2], 3)
158
-
159
-
160
- def get_resolution_function(self, value=0):
161
-
162
- zero_loss_fit_width=self.low_loss_tab[2, 0].value
163
- spectrum = self.parent.spectrum
164
- if 'zero_loss' not in self.parent.datasets.keys():
165
- self.parent.datasets['zero_loss'] = self.parent.dataset.copy()*0
166
- # if 'zero_loss' not in self.parent.datasets['zero_loss'].metadata.keys():
167
- self.parent.datasets['zero_loss'].metadata['zero_loss']={}
168
- self.parent.datasets['zero_loss'].metadata['zero_loss']['parameter'] = np.zeros([self.dataset.shape[0], self.dataset.shape[1], 6])
169
-
170
-
171
- res = eels_tools.get_resolution_functions(spectrum, startFitEnergy=-zero_loss_fit_width, endFitEnergy=zero_loss_fit_width)
172
- if len(self.parent.datasets['zero_loss'].shape) > 2:
173
- self.parent.datasets['zero_loss'][self.parent.x, self.parent.y] = np.array(res)
174
- self.parent.datasets['zero_loss'].metadata['zero_loss'][self.parent.x, self.parent.y] = res.metadata['zero_loss']['fit_parameter']
175
- else:
176
- self.parent.datasets['zero_loss'] = res
177
- self.parent.datasets['zero_loss'].metadata['zero_loss'].update(res.metadata['zero_loss'])
178
-
179
- self.parent.datasets['_relationship']['resolution_function'] = 'zero_loss'
180
-
181
- self.parent.dataset.metadata['zero_loss'].update(self.parent.datasets['zero_loss'].metadata['zero_loss'])
182
-
183
- if self.low_loss_tab[3, 0].value:
184
- self.parent._update()
185
- else:
186
- self.low_loss_tab[3, 0].value = True
187
- self.low_loss_tab[14, 1].value = np.round(np.log(self.parent.spectrum.sum()/res.sum()), 4)
188
- self.parent.status_message('Fitted zero-loss peak')
189
-
190
- def get_drude(self, value=0):
191
- self.low_loss_tab[8, 0].value = False
192
- fit_start = self.low_loss_tab[5, 0].value
193
- fit_end = self.low_loss_tab[6, 0].value
194
- if 'plasmon' not in self.parent.datasets.keys():
195
- self.parent.datasets['plasmon'] = self.parent.dataset.copy()*0
196
- if 'plasmon' not in self.parent.datasets['plasmon'].metadata.keys():
197
- self.parent.datasets['plasmon'].metadata['plasmon'] = {}
198
- if 'fit_parameter' not in self.parent.datasets['plasmon'].metadata['plasmon'].keys():
199
- if len(self.dataset.shape) > 2:
200
- self.parent.datasets['plasmon'].metadata['plasmon']['fit_parameter'] = np.zeros([self.dataset.shape[0], self.dataset.shape[1], 4])
201
- self.parent.datasets['plasmon'].metadata['plasmon']['IMFP'] = np.zeros([self.dataset.shape[0], self.dataset.shape[1]])
202
-
203
- if 'low_loss_model' not in self.parent.datasets.keys():
204
- self.parent.datasets['low_loss_model'] = self.parent.dataset.copy()*0
205
- self.parent.status_message(str(self.parent.x))
206
- plasmon = eels_tools.fit_plasmon(self.parent.spectrum, fit_start, fit_end)
207
-
208
- p = plasmon.metadata['plasmon']['parameter']
209
- p = list(np.abs(p))
210
- p.append(self.low_loss_tab[14, 0].value)
211
-
212
-
213
- anglog, _, _ = eels_tools.angle_correction(self.parent.spectrum)
214
-
215
- low_loss = eels_tools.multiple_scattering(self.parent.energy_scale, p) * anglog
216
-
217
-
218
- if len(self.parent.datasets['plasmon'].shape) > 2:
219
- self.parent.datasets['plasmon'][self.parent.x, self.parent.y] = np.array(plasmon)
220
- self.parent.datasets['low_loss_model'][self.parent.x, self.parent.y] = np.array(low_loss)
221
- self.parent.datasets['plasmon'].metadata['plasmon']['fit_parameter'][self.parent.x, self.parent.y] = p
222
-
223
- if 'zero_loss' in self.parent.datasets:
224
- res = self.parent.datasets['zero_loss'][self.parent.x, self.parent.y]
225
-
226
- else:
227
- self.parent.datasets['plasmon'] = plasmon
228
- self.parent.datasets['low_loss_model'] = low_loss
229
- if 'zero_loss' in self.parent.datasets:
230
- res = self.parent.datasets['zero_loss']
231
- self.parent.datasets['_relationship']['plasmon'] = 'plasmon'
232
- self.parent.datasets['_relationship']['low_loss_model'] = 'low_loss_model'
233
-
234
- #self.dataset.metadata['plasmon'].update(self.parent.datasets['plasmon'].metadata['zero_loss'])
235
- if self.low_loss_tab[10, 0].value:
236
- self.parent._update()
237
- self._update()
238
- else:
239
- self.low_loss_tab[10, 0].value = True
240
-
241
- self.low_loss_tab[7, 0].value = np.round(np.abs(p[0]),3)
242
- self.low_loss_tab[8, 0].value = np.round(p[1],3)
243
- self.low_loss_tab[9, 0].value = np.round(p[2],1)
244
-
245
- _, dsdo, _ = eels_tools.angle_correction(self.parent.spectrum)
246
-
247
- if 'zero_loss' in self.parent.datasets:
248
- I0 = res.sum() + p[2]
249
- else:
250
- I0 = self.parent.spectrum.sum()
251
- # I0 = self.parent.spectrum.sum()
252
- # print(I0)
253
- # T = m_0 v**2 !!! a_0 = 0.05292 nm p[2] = S(E)/elf
254
- t_nm = p[2]/I0*dsdo #Egerton equ 4.26% probability per eV
255
- relative_thickness = self.low_loss_tab[14, 0].value
256
- imfp, _ = eels_tools.inelatic_mean_free_path(p[0], self.parent.spectrum)
257
- t_nm = float(relative_thickness * imfp)
258
- # print(t_nm, relative_thickness, imfp)
259
- self.parent.status_message(f'Fitted plasmon peak: thickness :{t_nm:.1f} nm and IMFP: {t_nm/relative_thickness:.1f} nm in free electron approximation')
260
-
261
- if self.dataset.ndim>1:
262
- # self.parent.datasets['plasmon'].metadata['plasmon'][self.parent.x, self.parent.y]['thickness'] = t_nm
263
- # self.parent.datasets['plasmon'].metadata['plasmon'][self.parent.x, self.parent.y]['relative_thickness'] = relative_thickness
264
- self.parent.datasets['plasmon'].metadata['plasmon']['IMFP'][self.parent.x, self.parent.y] = t_nm/relative_thickness
265
-
266
- else:
267
- self.parent.datasets['plasmon'].metadata['plasmon']['thickness'] = t_nm
268
- self.parent.datasets['plasmon'].metadata['plasmon']['relative_thickness'] = relative_thickness
269
- self.parent.datasets['plasmon'].metadata['plasmon']['IMFP'] = t_nm/relative_thickness
270
-
271
-
272
- def multiple_scattering(self, value=0):
273
- if self.dataset.ndim >1:
274
- anglog, dsdo, _ = eels_tools.angle_correction(self.parent.spectrum)
275
- par = np.array(self.parent.datasets['plasmon'].metadata['plasmon']['fit_parameter'])
276
- for x in range(self.parent.dataset.shape[0]):
277
- for y in range(self.parent.dataset.shape[1]):
278
- self.parent.datasets['low_loss_model'][x, y] = eels_tools.multiple_scattering(self.parent.energy_scale, par[x, y]) * anglog
279
-
280
-
281
- def do_all(self, value=0):
282
- if len(self.parent.dataset.shape) < 3:
283
- return
284
-
285
- zero_loss_fit_width=self.low_loss_tab[2, 0].value
286
- fit_start = self.low_loss_tab[5, 0].value
287
- fit_end = self.low_loss_tab[6, 0].value
288
-
289
-
290
- if 'low_loss_model' not in self.parent.datasets.keys():
291
- self.parent.datasets['low_loss_model'] = self.parent.dataset.copy()*0
292
- self.parent.datasets['low_loss_model'].title = self.parent.dataset.title + ' low_loss_model'
293
-
294
- self.low_loss_tab[15,1].max = self.parent.dataset.shape[0]*self.parent.dataset.shape[1]
295
-
296
- self.parent.datasets['zero_loss'] = eels_tools.get_resolution_functions(self.dataset, startFitEnergy=-zero_loss_fit_width, endFitEnergy=zero_loss_fit_width)
297
- self.parent.datasets['zero_loss'].title = self.parent.dataset.title + ' zero_loss'
298
- self.parent.status_message('Fitted zero-loss peak')
299
-
300
- self.parent.datasets['plasmon'] = eels_tools.fit_plasmon(self.dataset, fit_start, fit_end)
301
- self.parent.datasets['plasmon'].title = self.parent.dataset.title + ' plasmon'
302
-
303
- self.parent.status_message('Fitted zero-loss + plasmon peak')
304
-
305
-
306
- """
307
- anglog, _, _ = eels_tools.angle_correction(self.parent.spectrum)
308
- i = 0
309
- for x in range(self.parent.dataset.shape[0]):
310
- for y in range(self.parent.dataset.shape[1]):
311
- self.low_loss_tab[15,1].value = i
312
- i+= 1
313
-
314
- spectrum = self.parent.dataset[x, y]
315
-
316
- plasmon = eels_tools.fit_plasmon(spectrum, fit_start, fit_end)
317
- p =np.abs(plasmon.metadata['plasmon']['parameter'])
318
- p = list(np.abs(p))
319
-
320
- p.append(np.log(spectrum.sum()/self.parent.datasets['zero_loss'][x,y].sum()))
321
- if p[-1] is np.nan:
322
- p[-1] = 0
323
- low_loss = eels_tools.multiple_scattering(self.parent.energy_scale, p) * anglog
324
- self.parent.datasets['plasmon'][x, y] = np.array(plasmon.compute())
325
- self.parent.datasets['low_loss_model'][x, y] = np.array(low_loss)
326
- drude_p[x, y, :] = np.array(p)
327
-
328
-
329
-
330
- self.parent.datasets['plasmon'].metadata['plasmon'].update({'parameter': drude_p})
331
- self.parent.datasets['low_loss_model'].metadata['low_loss'] = ({'parameter': drude_p})
332
- """
333
-
334
- imfp = np.log(self.parent.dataset.sum(axis=2)/self.parent.datasets['zero_loss'].sum(axis=2))
335
- self.parent.datasets['plasmon'].metadata['plasmon']['fit_parameter'] = np.append(self.parent.datasets['plasmon'].metadata['plasmon']['fit_parameter'], imfp[..., np.newaxis], axis=2)
336
- E_p = self.parent.datasets['plasmon'].metadata['plasmon']['fit_parameter'][:,:,0]
337
- self.parent.datasets['plasmon'].metadata['plasmon']['IMFP'], _ = eels_tools.inelatic_mean_free_path(E_p, self.parent.spectrum)
338
- self.parent.datasets['_relationship']['zero_loss'] = 'zero_loss'
339
- self.parent.datasets['_relationship']['plasmon'] = 'plasmon'
340
- self.multiple_scattering()
341
- self.parent.datasets['_relationship']['low_loss_model'] = 'low_loss_model'
342
-
343
- self.low_loss_tab[10, 1].value = False
344
-
345
- def get_multiple_scattering(self, value=0):
346
- self.low_loss_tab[15, 0].value = False
347
- fit_start = self.low_loss_tab[12, 0].value
348
- fit_end = self.low_loss_tab[13, 0].value
349
-
350
- p = [self.low_loss_tab[7, 0].value, self.low_loss_tab[8, 0].value, self.low_loss_tab[9, 0].value, self.low_loss_tab[14, 0].value]
351
- low_loss = eels_tools.fit_multiple_scattering(self.parent.spectrum, fit_start, fit_end, pin=p)
352
-
353
-
354
- self.parent.datasets['multiple_scattering'] = low_loss
355
- self.parent.datasets['_relationship']['multiple_scattering'] = 'multiple_scattering'
356
- self.low_loss_tab[10, 0].value = False
357
- self.low_loss_tab[15, 0].value = True
358
- p = low_loss.metadata['multiple_scattering']['parameter']
359
- self.low_loss_tab[14, 0].value = np.round(p[3],3)
360
-
361
- self.parent.status_message('Fitted multiple scattering')
362
-
363
-
364
- return low_loss
365
-
366
- def set_ll_action(self):
367
- self.low_loss_tab[0, 0].observe(self.update_ll_dataset)
368
- #self.low_loss_tab[1, 0].on_click(self.fix_energy_scale)
369
- #self.low_loss_tab[2, 0].observe(self.set_energy_scale, names='value')
370
- #self.low_loss_tab[3, 0].observe(self.set_energy_scale, names='value')
371
- self.low_loss_tab[1, 0].on_click(self.get_resolution_function)
372
- self.low_loss_tab[3, 2].observe(self.parent.info.set_y_scale, names='value')
373
- self.low_loss_tab[3, 0].observe(self._update, names='value')
374
- self.low_loss_tab[4, 0].on_click(self.get_drude)
375
- self.low_loss_tab[10, 0].observe(self._update, names='value')
376
- self.low_loss_tab[10, 1].observe(self.do_all, names='value')
377
- self.low_loss_tab[10, 2].observe(self._update, names='value')
378
- self.low_loss_tab[11, 0].on_click(self.get_multiple_scattering)
379
- self.low_loss_tab[15, 0].observe(self._update, names='value')
380
-
381
-
382
- def _update(self, ev=0):
383
- low_loss = None
384
- plasmon = None
385
- resolution_function = None
386
- if 'zero_loss' in self.parent.added_spectra.keys():
387
- del self.parent.added_spectra['zero_loss']
388
- if 'plasmon' in self.parent.added_spectra.keys():
389
- del self.parent.added_spectra['plasmon']
390
- if 'low_loss_model' in self.parent.added_spectra.keys():
391
- del self.parent.added_spectra['low_loss_model']
392
-
393
- if self .low_loss_tab[3, 0].value:
394
- if 'zero_loss' in self.parent.datasets.keys():
395
- resolution_function = np.array(self.parent.get_additional_spectrum('zero_loss'))
396
- self.parent.added_spectra.update({'zero_loss': 'resolution'})
397
- if self.low_loss_tab[10, 0].value:
398
- if 'plasmon' in self.parent.datasets.keys():
399
- plasmon = self.parent.get_additional_spectrum('plasmon')
400
- if len(self.dataset.shape) > 1:
401
- p = np.round(plasmon.metadata['plasmon']['fit_parameter'][self.parent.x, self.parent.y], 3)
402
- imfp = np.array(plasmon.metadata['plasmon']['IMFP'][self.parent.x, self.parent.y])
403
- else:
404
- p = np.round(plasmon.metadata['plasmon']['fit_parameter'], 3)
405
- imfp = plasmon.metadata['plasmon']['IMFP']
406
-
407
- self.parent.added_spectra.update({'plasmon': 'plasmon'})
408
- self.low_loss_tab[7, 1].value =p[0]
409
- self.low_loss_tab[8, 1].value = p[1]
410
- self.low_loss_tab[8, 1].value = p[2]
411
-
412
- self.low_loss_tab[14, 1].value =p[-1]
413
- t_nm = float(p[-1] * imfp)
414
- # print(t_nm, p[-1], imfp)
415
- self.parent.status_message(f'Fitted plasmon peak: thickness :{t_nm:.1f} nm and IMFP: {imfp:.1f} nm in free electron approximation')
416
-
417
- if self.low_loss_tab[15, 0].value:
418
- low_loss = np.array(self.parent.get_additional_spectrum('low_loss_model'))
419
- self.parent.added_spectra.update({'low_loss': 'low_loss'})
420
-
421
- if self.low_loss_tab[3, 0].value + self.low_loss_tab[10, 0].value + self.low_loss_tab[15, 0].value > 0:
422
- self.parent.datasets['_difference'] = np.array(self.parent.spectrum)
423
- if resolution_function is not None:
424
- self.parent.datasets['_difference'] -= resolution_function
425
- if low_loss is not None:
426
- self.parent.datasets['_difference'] -= low_loss
427
- else:
428
- if plasmon is not None:
429
- self.parent.datasets['_difference'] -= np.array(plasmon)
430
- self.parent.added_spectra.update({'_difference': 'difference'})
431
- else:
432
- if '_difference' in self.parent.datasets.keys():
433
- del self.parent.datasets['_difference']
434
- self.parent._update()
435
-
436
- def get_additional_spectrum(self, key):
437
- if key not in self.parent.datasets.keys():
438
- return
439
-
440
- if self.parent.datasets[key].data_type == sidpy.DataType.SPECTRUM:
441
- spectrum = self.parent.datasets[key].copy()
442
- else:
443
- image_dims = self.parent.datasets[key].get_dimensions_by_type(sidpy.DimensionType.SPATIAL)
444
- selection = []
445
- x = self.parent.x
446
- y = self.parent.y
447
- bin_x = self.parent.bin_x
448
- bin_y = self.parent.bin_y
449
- for dim, axis in self.parent.datasets[key]._axes.items():
450
- # print(dim, axis.dimension_type)
451
- if axis.dimension_type == sidpy.DimensionType.SPATIAL:
452
- if dim == image_dims[0]:
453
- selection.append(slice(x, x + bin_x))
454
- else:
455
- selection.append(slice(y, y + bin_y))
456
-
457
- elif axis.dimension_type == sidpy.DimensionType.SPECTRAL:
458
- selection.append(slice(None))
459
- elif axis.dimension_type == sidpy.DimensionType.CHANNEL:
460
- selection.append(slice(None))
461
- else:
462
- selection.append(slice(0, 1))
463
-
464
- spectrum = self.parent.datasets[key][tuple(selection)].mean(axis=tuple(image_dims))
465
-
466
- spectrum *= self.parent.y_scale
467
-
468
- return spectrum.squeeze()
469
-
470
-
471
-
472
-
473
- def set_binning(self, value):
474
- if 'SPECTRAL' in self.dataset.data_type.name:
475
- bin_x = self.info_tab[15, 0].value
476
- bin_y = self.info_tab[16, 0].value
477
- self.dataset.view.set_bin([bin_x, bin_y])
478
- self.datasets[self.key].metadata['experiment']['SI_bin_x'] = bin_x
479
- self.datasets[self.key].metadata['experiment']['SI_bin_y'] = bin_y