pyTEMlib 0.2024.2.2__tar.gz → 0.2024.6.0__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.

Files changed (44) hide show
  1. {pyTEMlib-0.2024.2.2/pyTEMlib.egg-info → pyTEMlib-0.2024.6.0}/PKG-INFO +1 -1
  2. pyTEMlib-0.2024.6.0/pyTEMlib/core_loss_widget.py +658 -0
  3. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/eels_dialog.py +13 -12
  4. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/eels_dialog_utilities.py +2 -3
  5. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/eels_tools.py +56 -71
  6. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/file_tools.py +7 -1
  7. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/image_tools.py +95 -23
  8. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/info_widget.py +301 -365
  9. pyTEMlib-0.2024.6.0/pyTEMlib/low_loss_widget.py +176 -0
  10. pyTEMlib-0.2024.6.0/pyTEMlib/version.py +6 -0
  11. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0/pyTEMlib.egg-info}/PKG-INFO +1 -1
  12. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib.egg-info/SOURCES.txt +2 -0
  13. pyTEMlib-0.2024.2.2/pyTEMlib/version.py +0 -6
  14. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/LICENSE +0 -0
  15. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/MANIFEST.in +0 -0
  16. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/README.rst +0 -0
  17. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/__init__.py +0 -0
  18. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/animation.py +0 -0
  19. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/atom_tools.py +0 -0
  20. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/config_dir.py +0 -0
  21. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/crystal_tools.py +0 -0
  22. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/diffraction_plot.py +0 -0
  23. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/dynamic_scattering.py +0 -0
  24. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/eds_tools.py +0 -0
  25. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/file_tools_qt.py +0 -0
  26. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/graph_tools.py +0 -0
  27. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/graph_viz.py +0 -0
  28. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/image_dialog.py +0 -0
  29. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/image_dlg.py +0 -0
  30. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/interactive_image.py +0 -0
  31. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/kinematic_scattering.py +0 -0
  32. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/microscope.py +0 -0
  33. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/peak_dialog.py +0 -0
  34. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/peak_dlg.py +0 -0
  35. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/probe_tools.py +0 -0
  36. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/sidpy_tools.py +0 -0
  37. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/simulation_tools.py +0 -0
  38. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib/xrpa_x_sections.py +0 -0
  39. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib.egg-info/dependency_links.txt +0 -0
  40. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib.egg-info/entry_points.txt +0 -0
  41. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib.egg-info/requires.txt +0 -0
  42. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/pyTEMlib.egg-info/top_level.txt +0 -0
  43. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/setup.cfg +0 -0
  44. {pyTEMlib-0.2024.2.2 → pyTEMlib-0.2024.6.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyTEMlib
3
- Version: 0.2024.2.2
3
+ Version: 0.2024.6.0
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
@@ -0,0 +1,658 @@
1
+ """
2
+ Author: Gerd Duscher
3
+ """
4
+
5
+
6
+ import numpy as np
7
+ import warnings
8
+
9
+ import ipywidgets
10
+ import IPython.display
11
+ # from IPython.display import display
12
+ import matplotlib
13
+ import matplotlib.pylab as plt
14
+ import matplotlib.patches as patches
15
+
16
+ from pyTEMlib import file_tools as ft
17
+ from pyTEMlib import eels_tools as eels
18
+ from pyTEMlib import eels_dialog_utilities
19
+
20
+ import sidpy
21
+
22
+
23
+ def get_core_loss_sidebar():
24
+ side_bar = ipywidgets.GridspecLayout(15, 3,width='auto', grid_gap="0px")
25
+
26
+ side_bar[0, :2] = ipywidgets.Dropdown(
27
+ options=[('None', 0)],
28
+ value=0,
29
+ description='Main Dataset:',
30
+ disabled=False)
31
+
32
+ row = 1
33
+ side_bar[row, :3] = ipywidgets.ToggleButton(description='Fit Area',
34
+ layout=ipywidgets.Layout(width='auto', grid_area='header'),
35
+ tooltip='Shows fit regions and regions excluded from fit',
36
+ button_style='info') #ipywidgets.ButtonStyle(button_color='lightblue'))
37
+ row += 1
38
+ side_bar[row, :2] = ipywidgets.FloatText(value=7.5,description='Fit Start:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px'))
39
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='20px'))
40
+ row += 1
41
+ side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Fit End:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px'))
42
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='20px'))
43
+
44
+ row += 1
45
+
46
+ side_bar[row, :3] = ipywidgets.Button(description='Elements',
47
+ layout=ipywidgets.Layout(width='auto', grid_area='header'),
48
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
49
+ row += 1
50
+ side_bar[row, :2] = ipywidgets.Dropdown(
51
+ options=[('Edge 1', 0), ('Edge 2', 1), ('Edge 3', 2), ('Edge 4', 3),('Add Edge', -1)],
52
+ value=0,
53
+ description='Edges:',
54
+ disabled=False,
55
+ layout=ipywidgets.Layout(width='200px'))
56
+ """side_bar[row,2] = ipywidgets.ToggleButton(
57
+ description='Regions',
58
+ disabled=False,
59
+ button_style='', # 'success', 'info', 'warning', 'danger' or ''
60
+ tooltip='Shows fit regions and regions excluded from fit',
61
+ layout=ipywidgets.Layout(width='100px')
62
+ )
63
+ """
64
+ row += 1
65
+ side_bar[row, :2] = ipywidgets.IntText(value=7.5,description='Z:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px'))
66
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="", layout=ipywidgets.Layout(width='100px'))
67
+ row += 1
68
+ side_bar[row, :2] = ipywidgets.Dropdown(
69
+ options=['K1','L3', 'M5', 'M3', 'M1', 'N7', 'N5', 'N3', 'N1'],
70
+ value='K1',
71
+ description='Symmetry:',
72
+ disabled=False,
73
+ layout=ipywidgets.Layout(width='200px'))
74
+ row += 1
75
+ side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Onset:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px'))
76
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px'))
77
+ row += 1
78
+ side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Excl.Start:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px'))
79
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px'))
80
+ row += 1
81
+ side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Excl.End:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px'))
82
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px'))
83
+ row += 1
84
+ side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Mutliplier:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px'))
85
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="a.u.", layout=ipywidgets.Layout(width='100px'))
86
+ row += 1
87
+
88
+ side_bar[row, :3] = ipywidgets.Button(description='Quantification',
89
+ layout=ipywidgets.Layout(width='auto', grid_area='header'),
90
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
91
+
92
+ row += 1
93
+ side_bar[row,0] = ipywidgets.ToggleButton(
94
+ description='Probabiity',
95
+ disabled=False,
96
+ button_style='', # 'success', 'info', 'warning', 'danger' or ''
97
+ tooltip='Changes y-axis to probability of flux is given',
98
+ layout=ipywidgets.Layout(width='100px')
99
+ )
100
+ side_bar[row,1] = ipywidgets.ToggleButton(
101
+ description='Conv.LL',
102
+ disabled=False,
103
+ button_style='', # 'success', 'info', 'warning', 'danger' or ''
104
+ tooltip='Changes y-axis to probability of flux is given',
105
+ layout=ipywidgets.Layout(width='100px')
106
+ )
107
+ side_bar[row,2] = ipywidgets.ToggleButton(
108
+ description='Show Edges',
109
+ disabled=False,
110
+ button_style='', # 'success', 'info', 'warning', 'danger' or ''
111
+ tooltip='Changes y-axis to probability of flux is given',
112
+ layout=ipywidgets.Layout(width='100px')
113
+ )
114
+
115
+ row += 1
116
+ side_bar[row,0] = ipywidgets.ToggleButton(
117
+ description='Do All',
118
+ disabled=False,
119
+ button_style='', # 'success', 'info', 'warning', 'danger' or ''
120
+ tooltip='Fits all spectra of spectrum image',
121
+ layout=ipywidgets.Layout(width='100px')
122
+ )
123
+
124
+ side_bar[row,1] = ipywidgets.IntProgress(value=0, min=0, max=10, description=' ', bar_style='', # 'success', 'info', 'warning', 'danger' or ''
125
+ style={'bar_color': 'maroon'}, orientation='horizontal')
126
+ return side_bar
127
+
128
+
129
+
130
+ class CoreLoss(object):
131
+ def __init__(self, sidebar=None, parent=None):
132
+ self.parent = parent
133
+ self.dataset = parent.dataset
134
+ self.core_loss_tab = sidebar
135
+
136
+ self.model = []
137
+ self.edges = {}
138
+ self.count = 0
139
+ self.cl_key = ''
140
+
141
+ self.periodic_table = eels_dialog_utilities.PeriodicTableWidget(self.parent.energy_scale)
142
+ self.elements_cancel_button = ipywidgets.Button(description='Cancel')
143
+ self.elements_select_button = ipywidgets.Button(description='Select')
144
+ self.elements_auto_button = ipywidgets.Button(description='Auto ID')
145
+
146
+ self.periodic_table_panel = ipywidgets.VBox([self.periodic_table.periodic_table,
147
+ ipywidgets.HBox([self.elements_cancel_button, self.elements_auto_button, self.elements_select_button])])
148
+
149
+ # self.update_cl_sidebar()
150
+ self.set_cl_action()
151
+
152
+ def update_cl_key(self, value=0):
153
+ self.cl_key = self.core_loss_tab[0, 0].value.split(':')[0]
154
+ self.parent.set_dataset(self.cl_key)
155
+
156
+ self.dataset = self.parent.dataset
157
+ print(self.cl_key, self.core_loss_tab[0, 0].value)
158
+
159
+ def update_cl_dataset(self, value=0):
160
+ if self.cl_key not in self.core_loss_tab[0, 0].options:
161
+ self.cl_key = self.core_loss_tab[0, 0].value.split(':')[0]
162
+ self.parent.set_dataset(self.cl_key)
163
+
164
+ self.dataset = self.parent.dataset
165
+
166
+ def update_cl_sidebar(self):
167
+ self.count+=1
168
+ spectrum_list = ['None '+str(self.count)]
169
+ cl_index = 0
170
+ for index, key in enumerate(self.parent.datasets.keys()):
171
+ if isinstance(self.parent.datasets[key], sidpy.Dataset):
172
+ if 'SPECTR' in self.parent.datasets[key].data_type.name:
173
+ spectrum_list.append(f'{key}: {self.parent.datasets[key].title}')
174
+ if key == self.cl_key:
175
+ cl_index = index
176
+ self.cl_key = spectrum_list[cl_index]
177
+ self.core_loss_tab[0, 0].options = spectrum_list
178
+ self.core_loss_tab[0, 0].value = spectrum_list[cl_index]
179
+
180
+
181
+
182
+ def line_select_callback(self, x_min, x_max):
183
+ self.start_cursor.value = np.round(x_min,3)
184
+ self.end_cursor.value = np.round(x_max, 3)
185
+
186
+ self.start_channel = np.searchsorted(self.datasets[self.key].energy_loss, self.start_cursor.value)
187
+ self.end_channel = np.searchsorted(self.datasets[self.key].energy_loss, self.end_cursor.value)
188
+
189
+
190
+ def plot(self, scale=True):
191
+ self.parent.dataset.metadata['edges'] = self.edges
192
+ self.parent.plot(scale=scale)
193
+ y_scale = self.parent.y_scale
194
+ spectrum = self.parent.spectrum
195
+ if len(self.model) > 1:
196
+ self.model = self.edges['model']['spectrum'].copy()
197
+ #self.parent.axis.plot(self.parent.energy_scale, (self.edges['model']['spectrum'])*y_scale, label='difference')
198
+ self.parent.axis.plot(self.parent.energy_scale, self.model*y_scale, label='model')
199
+ self.parent.axis.plot(self.parent.energy_scale, spectrum-self.model*y_scale, label='difference')
200
+ self.parent.axis.legend()
201
+ pass
202
+ if self.core_loss_tab[13, 2].value:
203
+ self.show_edges()
204
+ if self.core_loss_tab[1, 0].value:
205
+ self.plot_regions()
206
+ self.parent.figure.canvas.draw_idle()
207
+
208
+
209
+ def plot_regions(self):
210
+ axis = self.parent.figure.gca()
211
+ y_min, y_max = axis.get_ylim()
212
+ height = y_max - y_min
213
+
214
+ rect = []
215
+ if 'fit_area' in self.edges:
216
+ color = 'blue'
217
+ alpha = 0.2
218
+ x_min = self.edges['fit_area']['fit_start']
219
+ width = self.edges['fit_area']['fit_end'] - x_min
220
+ rect.append(patches.Rectangle((x_min, y_min), width, height,
221
+ edgecolor=color, alpha=alpha, facecolor=color))
222
+ axis.add_patch(rect[0])
223
+ axis.text(x_min, y_max, 'fit region', verticalalignment='top')
224
+ color = 'red'
225
+ alpha = 0.5
226
+
227
+ for key in self.edges:
228
+ if key.isdigit():
229
+ x_min = self.edges[key]['start_exclude']
230
+ width = self.edges[key]['end_exclude']-x_min
231
+ rect.append(patches.Rectangle((x_min, y_min), width, height,
232
+ edgecolor=color, alpha=alpha, facecolor=color))
233
+ axis.add_patch(rect[-1])
234
+ axis.text(x_min, y_max, f"exclude\n edge {int(key)+1}", verticalalignment='top')
235
+
236
+ def show_edges(self):
237
+ axis = self.parent.figure.gca()
238
+ x_min, x_max = axis.get_xlim()
239
+ y_min, y_max = axis.get_ylim()
240
+
241
+ for key, edge in self.edges.items():
242
+ i = 0
243
+ if key.isdigit():
244
+ element = edge['element']
245
+ for sym in edge['all_edges']:
246
+ x = edge['all_edges'][sym]['onset'] + edge['chemical_shift']
247
+ if x_min < x < x_max:
248
+ axis.text(x, y_max, '\n' * i + f"{element}-{sym}",
249
+ verticalalignment='top', color='black')
250
+ axis.axvline(x, ymin=0, ymax=1, color='gray')
251
+ i += 1
252
+
253
+
254
+ def update_element(self, z=0, index=-1):
255
+ # We check whether this element is already in the
256
+ if z == 0:
257
+ z = self.core_loss_tab[6, 0].value
258
+
259
+ zz = eels.get_z(z)
260
+ for key, edge in self.edges.items():
261
+ if key.isdigit():
262
+ if 'z' in edge:
263
+ if zz == edge['z']:
264
+ return False
265
+
266
+ major_edge = ''
267
+ minor_edge = ''
268
+ all_edges = {}
269
+ x_section = eels.get_x_sections(zz)
270
+ edge_start = 10 # int(15./ft.get_slope(self.energy_scale)+0.5)
271
+ for key in x_section:
272
+ if len(key) == 2 and key[0] in ['K', 'L', 'M', 'N', 'O'] and key[1].isdigit():
273
+ if self.parent.energy_scale[edge_start] < x_section[key]['onset'] < self.parent.energy_scale[-edge_start]:
274
+ if key in ['K1', 'L3', 'M5']:
275
+ major_edge = key
276
+ elif key in self.core_loss_tab[7, 0].options:
277
+ if minor_edge == '':
278
+ minor_edge = key
279
+ if int(key[-1]) % 2 > 0:
280
+ if int(minor_edge[-1]) % 2 == 0 or key[-1] > minor_edge[-1]:
281
+ minor_edge = key
282
+
283
+ all_edges[key] = {'onset': x_section[key]['onset']}
284
+
285
+ if major_edge != '':
286
+ key = major_edge
287
+ elif minor_edge != '':
288
+ key = minor_edge
289
+ else:
290
+ print(f'Could not find no edge of {zz} in spectrum')
291
+ return False
292
+ if index == -1:
293
+ index = self.core_loss_tab[5, 0].value
294
+ # self.ui.dialog.setWindowTitle(f'{index}, {zz}')
295
+
296
+ if str(index) not in self.edges:
297
+ self.edges[str(index)] = {}
298
+
299
+ start_exclude = x_section[key]['onset'] - x_section[key]['excl before']
300
+ end_exclude = x_section[key]['onset'] + x_section[key]['excl after']
301
+
302
+ self.edges[str(index)] = {'z': zz, 'symmetry': key, 'element': eels.elements[zz],
303
+ 'onset': x_section[key]['onset'], 'end_exclude': end_exclude,
304
+ 'start_exclude': start_exclude}
305
+ self.edges[str(index)]['all_edges'] = all_edges
306
+ self.edges[str(index)]['chemical_shift'] = 0.0
307
+ self.edges[str(index)]['areal_density'] = 0.0
308
+ self.edges[str(index)]['original_onset'] = self.edges[str(index)]['onset']
309
+ return True
310
+
311
+ def sort_elements(self):
312
+ onsets = []
313
+ for index, edge in self.edges.items():
314
+ if index.isdigit():
315
+ onsets.append(float(edge['onset']))
316
+
317
+ arg_sorted = np.argsort(onsets)
318
+ edges = self.edges.copy()
319
+ for index, i_sorted in enumerate(arg_sorted):
320
+ self.edges[str(index)] = edges[str(i_sorted)].copy()
321
+
322
+ index = 0
323
+ edge = self.edges['0']
324
+ dispersion = self.parent.energy_scale[1]-self.parent.energy_scale[0]
325
+
326
+ while str(index + 1) in self.edges:
327
+ next_edge = self.edges[str(index + 1)]
328
+ if edge['end_exclude'] > next_edge['start_exclude'] - 5 * dispersion:
329
+ edge['end_exclude'] = next_edge['start_exclude'] - 5 * dispersion
330
+ edge = next_edge
331
+ index += 1
332
+
333
+ if edge['end_exclude'] > self.parent.energy_scale[-3]:
334
+ edge['end_exclude'] = self.parent.energy_scale[-3]
335
+
336
+ def set_elements(self, value=0):
337
+ selected_elements = self.periodic_table.get_output()
338
+ edges = self.edges.copy()
339
+ to_delete = []
340
+ old_elements = []
341
+ if len(selected_elements) > 0:
342
+ for key in self.edges:
343
+ if key.isdigit():
344
+ if 'element' in self.edges[key]:
345
+ to_delete.append(key)
346
+ old_elements.append(self.edges[key]['element'])
347
+
348
+ for key in to_delete:
349
+ edges[key] = self.edges[key]
350
+ del self.edges[key]
351
+
352
+ for index, elem in enumerate(selected_elements):
353
+ if elem in old_elements:
354
+ self.edges[str(index)] = edges[str(old_elements.index(elem))]
355
+ else:
356
+ self.update_element(elem, index=index)
357
+ self.sort_elements()
358
+ self.update()
359
+ self.set_figure_pane()
360
+
361
+ def set_element(self, elem):
362
+ self.update_element(self.core_loss_tab[6, 0].value)
363
+ # self.sort_elements()
364
+ self.update()
365
+
366
+
367
+ def set_fit_start(self, value=0):
368
+ if 'edges' not in self.dataset.metadata:
369
+ self.edges = self.dataset.metadata['edges'] = {}
370
+ if 'fit_area' not in self.edges:
371
+ self.edges['fit_area'] = {'fit_start':self.parent.energy_scale[10],
372
+ 'fit_end': self.parent.energy_scale[-10]}
373
+ self.core_loss_tab[3, 0].value = str(self.edges['fit_area']['fit_end'] )
374
+ self.core_loss_tab[2, 0].value = str(self.edges['fit_area']['fit_start'] )
375
+ if self.core_loss_tab[2, 0].value < self.parent.energy_scale[0]:
376
+ self.core_loss_tab[2, 0].value = self.parent.energy_scale[10]
377
+ self.edges['fit_area']['fit_start'] = float(self.core_loss_tab[2, 0].value)
378
+ self.parent.plot()
379
+
380
+ def set_fit_end(self, value=0):
381
+ if 'edges' not in self.dataset.metadata:
382
+ self.edges = self.dataset.metadata['edges'] = {}
383
+ if 'fit_area' not in self.edges:
384
+ self.edges['fit_area'] = {'fit_start':self.parent.energy_scale[10],
385
+ 'fit_end': self.parent.energy_scale[-10]}
386
+ self.core_loss_tab[3, 0].value = str(self.edges['fit_area']['fit_end'] )
387
+ self.core_loss_tab[2, 0].value = str(self.edges['fit_area']['fit_start'] )
388
+ if self.core_loss_tab[3, 0].value > self.parent.energy_scale[-1]:
389
+ self.core_loss_tab[3, 0].value = self.parent.energy_scale[-10]
390
+ self.edges['fit_area']['fit_end'] = self.core_loss_tab[3, 0].value
391
+ self.parent.plot()
392
+ def set_fit_area(self, value=1):
393
+ if 'fit_area' not in self.edges:
394
+ self.edges['fit_area'] = {'fit_start':self.parent.energy_scale[10],
395
+ 'fit_end': self.parent.energy_scale[-10]}
396
+
397
+ fit_end = str(self.edges['fit_area']['fit_end'] )
398
+ fit_start = str(self.edges['fit_area']['fit_start'] )
399
+
400
+ if fit_end > fit_start:
401
+ fit_start = self.parent.energy_scale[10]
402
+ fit_end = self.parent.energy_scale[-10]
403
+ self.core_loss_tab[2, 0].value = fit_start
404
+ self.core_loss_tab[3, 0].value = fit_end
405
+ self.edges['fit_area']['fit_start'] = self.core_loss_tab[2, 0].value
406
+ self.edges['fit_area']['fit_end'] = self.core_loss_tab[3, 0].value
407
+
408
+ self.parent.plot()
409
+
410
+
411
+ def auto_id(self, value=0):
412
+ found_edges = eels.auto_id_edges(self.dataset)
413
+ if len(found_edges) > 0:
414
+ self.periodic_table.elements_selected = found_edges
415
+ self.periodic_table.update()
416
+
417
+ def find_elements(self, value=0):
418
+
419
+ if '0' not in self.edges:
420
+ self.edges['0'] = {}
421
+ # found_edges = eels.auto_id_edges(self.dataset)
422
+ found_edges = {}
423
+
424
+ selected_elements = []
425
+ elements = self.edges.copy()
426
+
427
+ for key in self.edges:
428
+ if key.isdigit():
429
+ if 'element' in self.edges[key]:
430
+ selected_elements.append(self.edges[key]['element'])
431
+ self.periodic_table.elements_selected = selected_elements
432
+ self.periodic_table.update()
433
+ self.parent.app_layout.center = self.periodic_table_panel # self.periodic_table.periodic_table
434
+
435
+ def set_figure_pane(self, value=0):
436
+ self.parent.app_layout.center = self.parent.panel
437
+
438
+ def update(self, index=0):
439
+ self.dataset = self.parent.dataset
440
+ index = self.core_loss_tab[5,0].value # which edge
441
+ if index < 0:
442
+ options = list(self.core_loss_tab[5, 0].options)
443
+ options.insert(-1, (f'Edge {len(self.core_loss_tab[5, 0].options)}', len(self.sidebar[4,0].options)-1))
444
+ self.core_loss_tab[5, 0].options= options
445
+ self.core_loss_tab[5, 0].value = len(self.core_loss_tab[5, 0].options)-2
446
+ if str(index) not in self.edges:
447
+ self.edges[str(index)] = {'z': 0, 'element': 'x', 'symmetry': 'K1', 'onset': 0, 'start_exclude': 0, 'end_exclude':0,
448
+ 'areal_density': 0, 'chemical_shift':0}
449
+ if 'z' not in self.edges[str(index)]:
450
+ self.edges[str(index)] = {'z': 0, 'element': 'x', 'symmetry': 'K1', 'onset': 0, 'start_exclude': 0, 'end_exclude':0,
451
+ 'areal_density': 0, 'chemical_shift':0}
452
+ edge = self.edges[str(index)]
453
+
454
+ self.core_loss_tab[6,0].value = edge['z']
455
+ self.core_loss_tab[6,2].value = edge['element']
456
+ self.core_loss_tab[7,0].value = edge['symmetry']
457
+ self.core_loss_tab[8,0].value = edge['onset']
458
+ self.core_loss_tab[9,0].value = edge['start_exclude']
459
+ self.core_loss_tab[10,0].value = edge['end_exclude']
460
+ self.core_loss_tab[13, 0].value = self.parent.info_tab[9, 2].value
461
+ if self.parent.y_scale == 1.0:
462
+ self.core_loss_tab[11, 0].value = edge['areal_density']
463
+ self.core_loss_tab[11, 2].value = 'a.u.'
464
+ else:
465
+ dispersion = self.parent.energy_scale[1]-self.parent.energy_scale[0]
466
+ self.core_loss_tab[11, 0].value = np.round(edge['areal_density']/self.dataset.metadata['experiment']['flux_ppm']*1e-6, 2)
467
+ self.core_loss_tab[11, 2].value = 'atoms/nm²'
468
+
469
+ def do_fit(self, value=0):
470
+ if 'experiment' in self.dataset.metadata:
471
+ exp = self.dataset.metadata['experiment']
472
+ if 'convergence_angle' not in exp:
473
+ raise ValueError('need a convergence_angle in experiment of metadata dictionary ')
474
+ alpha = exp['convergence_angle']
475
+ beta = exp['collection_angle']
476
+ beam_kv = exp['acceleration_voltage']
477
+
478
+ else:
479
+ raise ValueError('need a experiment parameter in metadata dictionary')
480
+
481
+ eff_beta = eels.effective_collection_angle(self.parent.energy_scale, alpha, beta, beam_kv)
482
+ self.dataset.metadata['experiment']['eff_beta'] = eff_beta
483
+ self.low_loss = None
484
+ if self.core_loss_tab[13, 1].value:
485
+ for key in self.datasets.keys():
486
+ if key != self.key:
487
+ if isinstance(self.datasets[key], sidpy.Dataset):
488
+ if self.datasets[key].data_type.name == 'SPECTRUM':
489
+ if self.datasets[key].energy_loss[0] < 0:
490
+ self.low_loss = self.datasets[key]/self.datasets[key].sum()
491
+
492
+ edges = eels.make_cross_sections(self.edges, np.array(self.parent.energy_scale), beam_kv, eff_beta, self.low_loss)
493
+ if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE:
494
+ spectrum = self.parent.get_spectrum()
495
+ else:
496
+ spectrum = self.dataset
497
+ self.edges = eels.fit_edges2(spectrum, self.parent.energy_scale, edges)
498
+ self.model = self.edges['model']['spectrum'].copy()
499
+ print('set_model', self.edges['model']['spectrum'][0], self.model[0])
500
+
501
+ areal_density = []
502
+ elements = []
503
+ for key in edges:
504
+ if key.isdigit(): # only edges have numbers in that dictionary
505
+ elements.append(edges[key]['element'])
506
+ areal_density.append(edges[key]['areal_density'])
507
+ areal_density = np.array(areal_density)
508
+ out_string = '\nRelative composition: \n'
509
+ for i, element in enumerate(elements):
510
+ out_string += f'{element}: {areal_density[i] / areal_density.sum() * 100:.1f}% '
511
+
512
+
513
+
514
+ self.update()
515
+ self.plot()
516
+
517
+ def do_all_button_click(self, value=0):
518
+ if self.sidebar[13,0].value==False:
519
+ return
520
+
521
+ if self.dataset.data_type.name != 'SPECTRAL_IMAGE':
522
+ self.do_fit()
523
+ return
524
+
525
+ if 'experiment' in self.dataset.metadata:
526
+ exp = self.dataset.metadata['experiment']
527
+ if 'convergence_angle' not in exp:
528
+ raise ValueError('need a convergence_angle in experiment of metadata dictionary ')
529
+ alpha = exp['convergence_angle']
530
+ beta = exp['collection_angle']
531
+ beam_kv = exp['acceleration_voltage']
532
+ else:
533
+ raise ValueError('need a experiment parameter in metadata dictionary')
534
+
535
+ eff_beta = eels.effective_collection_angle(self.energy_scale, alpha, beta, beam_kv)
536
+ eff_beta = beta
537
+ self.low_loss = None
538
+ if self.sidebar[12, 1].value:
539
+ for key in self.datasets.keys():
540
+ if key != self.key:
541
+ if isinstance(self.datasets[key], sidpy.Dataset):
542
+ if 'SPECTR' in self.datasets[key].data_type.name:
543
+ if self.datasets[key].energy_loss[0] < 0:
544
+ self.low_loss = self.datasets[key]/self.datasets[key].sum()
545
+
546
+ edges = eels.make_cross_sections(self.edges, np.array(self.energy_scale), beam_kv, eff_beta, self.low_loss)
547
+
548
+ view = self.parent
549
+ bin_x = view.bin_x
550
+ bin_y = view.bin_y
551
+
552
+ start_x = view.x
553
+ start_y = view.y
554
+
555
+ number_of_edges = 0
556
+ for key in self.edges:
557
+ if key.isdigit():
558
+ number_of_edges += 1
559
+
560
+ results = np.zeros([int(self.dataset.shape[0]/bin_x), int(self.dataset.shape[1]/bin_y), number_of_edges])
561
+ total_spec = int(self.dataset.shape[0]/bin_x)*int(self.dataset.shape[1]/bin_y)
562
+ self.sidebar[13,1].max = total_spec
563
+ #self.ui.progress.setMaximum(total_spec)
564
+ #self.ui.progress.setValue(0)
565
+ ind = 0
566
+ for x in range(int(self.dataset.shape[0]/bin_x)):
567
+ for y in range(int(self.dataset.shape[1]/bin_y)):
568
+ ind += 1
569
+ self.sidebar[13,1].value = ind
570
+ view.x = x*bin_x
571
+ view.y = y*bin_y
572
+ spectrum = view.get_spectrum()
573
+ with warnings.catch_warnings():
574
+ warnings.simplefilter("ignore")
575
+ edges = eels.fit_edges2(spectrum, self.energy_scale, edges)
576
+ for key, edge in edges.items():
577
+ if key.isdigit():
578
+ # element.append(edge['element'])
579
+ results[x, y, int(key)] = edge['areal_density']
580
+ edges['spectrum_image_quantification'] = results
581
+ self.sidebar[13,1].value = total_spec
582
+ view.x = start_x
583
+ view.y = start_y
584
+ self.sidebar[13,0].value = False
585
+
586
+
587
+ def modify_onset(self, value=-1):
588
+ edge_index = self.core_loss_tab[5, 0].value
589
+ edge = self.edges[str(edge_index)]
590
+ edge['onset'] = self.core_loss_tab[8,0].value
591
+ if 'original_onset' not in edge:
592
+ edge['original_onset'] = edge['onset']
593
+ edge['chemical_shift'] = edge['onset'] - edge['original_onset']
594
+ self.update()
595
+
596
+
597
+ def modify_start_exclude(self, value=-1):
598
+ edge_index = self.core_loss_tab[5, 0].value
599
+ edge = self.edges[str(edge_index)]
600
+ edge['start_exclude'] = self.core_loss_tab[9,0].value
601
+ self.plot()
602
+
603
+ def modify_end_exclude(self, value=-1):
604
+ edge_index = self.core_loss_tab[5, 0].value
605
+ edge = self.edges[str(edge_index)]
606
+ edge['end_exclude'] = self.core_loss_tab[10,0].value
607
+ self.plot()
608
+
609
+ def modify_areal_density(self, value=-1):
610
+ edge_index = self.core_loss_tab[5, 0].value
611
+ edge = self.edges[str(edge_index)]
612
+
613
+ edge['areal_density'] = self.core_loss_tab[11, 0].value
614
+ if self.parent.y_scale != 1.0:
615
+ dispersion = self.parent.energy_scale[1]-self.parent.energy_scale[0]
616
+ edge['areal_density'] = self.core_loss_tab[11, 0].value *self.dataset.metadata['experiment']['flux_ppm']/1e-6
617
+ if 'model' in self.edges:
618
+ self.model = self.edges['model']['background']
619
+ for key in self.edges:
620
+ if key.isdigit():
621
+ if 'data' in self.edges[key]:
622
+ self.model = self.model + self.edges[key]['areal_density'] * self.edges[key]['data']
623
+ self.model = self.edges['model']['background']
624
+ for key in self.edges:
625
+ if key.isdigit():
626
+ if 'data' in self.edges[key]:
627
+ self.model = self.model + self.edges[key]['areal_density'] * self.edges[key]['data']
628
+ self.plot()
629
+
630
+ def set_y_scale(self, value):
631
+ self.parent.info_tab[9, 2].value = self.core_loss_tab[13,0].value
632
+ self.update()
633
+
634
+
635
+ def set_cl_action(self):
636
+
637
+ self.core_loss_tab[0, 0].observe(self.update_cl_key, names='value')
638
+ self.core_loss_tab[2, 0].observe(self.set_fit_start, names='value')
639
+ self.core_loss_tab[3, 0].observe(self.set_fit_end, names='value')
640
+
641
+ self.core_loss_tab[4, 0].on_click(self.find_elements)
642
+ self.core_loss_tab[5, 0].observe(self.update, names='value')
643
+ self.core_loss_tab[6, 0].observe(self.set_element, names='value')
644
+
645
+ self.core_loss_tab[8, 0].observe(self.modify_onset, names='value')
646
+ self.core_loss_tab[9, 0].observe(self.modify_start_exclude, names='value')
647
+ self.core_loss_tab[10, 0].observe(self.modify_end_exclude, names='value')
648
+ self.core_loss_tab[11, 0].observe(self.modify_areal_density, names='value')
649
+
650
+ self.core_loss_tab[12, 0].on_click(self.do_fit)
651
+ self.core_loss_tab[13, 2].observe(self.plot, names='value')
652
+ self.core_loss_tab[1, 0].observe(self.plot, names='value')
653
+ self.core_loss_tab[13,0].observe(self.set_y_scale, names='value')
654
+ self.core_loss_tab[14,0].observe(self.do_all_button_click, names='value')
655
+
656
+ self.elements_cancel_button.on_click(self.set_figure_pane)
657
+ self.elements_auto_button.on_click(self.auto_id)
658
+ self.elements_select_button.on_click(self.set_elements)