pyTEMlib 0.2023.8.0__py2.py3-none-any.whl → 0.2024.2.0__py2.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.
- pyTEMlib/config_dir.py +0 -1
- pyTEMlib/crystal_tools.py +22 -26
- pyTEMlib/eds_tools.py +499 -46
- pyTEMlib/eels_dialog.py +284 -899
- pyTEMlib/eels_dialog_utilities.py +218 -341
- pyTEMlib/eels_tools.py +1526 -1583
- pyTEMlib/file_tools.py +52 -48
- pyTEMlib/graph_tools.py +3 -4
- pyTEMlib/image_tools.py +171 -41
- pyTEMlib/info_widget.py +618 -276
- pyTEMlib/kinematic_scattering.py +77 -512
- pyTEMlib/peak_dialog.py +162 -288
- pyTEMlib/version.py +2 -2
- pyTEMlib/xrpa_x_sections.py +173 -97
- {pyTEMlib-0.2023.8.0.dist-info → pyTEMlib-0.2024.2.0.dist-info}/LICENSE +1 -1
- {pyTEMlib-0.2023.8.0.dist-info → pyTEMlib-0.2024.2.0.dist-info}/METADATA +2 -2
- pyTEMlib-0.2024.2.0.dist-info/RECORD +35 -0
- {pyTEMlib-0.2023.8.0.dist-info → pyTEMlib-0.2024.2.0.dist-info}/WHEEL +1 -1
- pyTEMlib/eels_dlg.py +0 -252
- pyTEMlib/info_dialog.py +0 -665
- pyTEMlib/info_dlg.py +0 -239
- pyTEMlib/interactive_eels.py +0 -35
- pyTEMlib/viz.py +0 -481
- pyTEMlib-0.2023.8.0.dist-info/RECORD +0 -40
- {pyTEMlib-0.2023.8.0.dist-info → pyTEMlib-0.2024.2.0.dist-info}/entry_points.txt +0 -0
- {pyTEMlib-0.2023.8.0.dist-info → pyTEMlib-0.2024.2.0.dist-info}/top_level.txt +0 -0
pyTEMlib/eels_dialog.py
CHANGED
|
@@ -3,813 +3,98 @@ QT dialog window for EELS compositional analysis
|
|
|
3
3
|
|
|
4
4
|
Author: Gerd Duscher
|
|
5
5
|
"""
|
|
6
|
-
Qt_available = True
|
|
7
|
-
try:
|
|
8
|
-
from PyQt5 import QtCore, QtWidgets
|
|
9
|
-
except:
|
|
10
|
-
Qt_available = False
|
|
11
|
-
# print('Qt dialogs are not available')
|
|
12
6
|
|
|
13
7
|
|
|
14
8
|
import numpy as np
|
|
9
|
+
import warnings
|
|
15
10
|
|
|
16
11
|
import ipywidgets
|
|
17
12
|
import IPython.display
|
|
13
|
+
# from IPython.display import display
|
|
18
14
|
import matplotlib
|
|
19
15
|
import matplotlib.pylab as plt
|
|
20
16
|
import matplotlib.patches as patches
|
|
21
17
|
|
|
22
18
|
from pyTEMlib import file_tools as ft
|
|
23
19
|
from pyTEMlib import eels_tools as eels
|
|
20
|
+
from pyTEMlib import eels_dialog_utilities
|
|
24
21
|
|
|
25
22
|
import sidpy
|
|
26
23
|
|
|
27
|
-
if Qt_available:
|
|
28
|
-
from pyTEMlib import eels_dlg
|
|
29
|
-
from pyTEMlib import eels_dialog_utilities
|
|
30
|
-
|
|
31
|
-
class EELSDialog(QtWidgets.QDialog):
|
|
32
|
-
"""
|
|
33
|
-
EELS Input Dialog for Chemical Analysis
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
|
-
def __init__(self, datasets=None):
|
|
37
|
-
super().__init__(None, QtCore.Qt.WindowStaysOnTopHint)
|
|
38
|
-
# Create an instance of the GUI
|
|
39
|
-
if datasets is None:
|
|
40
|
-
# make a dummy dataset
|
|
41
|
-
datasets = {'Channel_000':ft.make_dummy_dataset(sidpy.DataType.SPECTRUM)}
|
|
42
|
-
elif isinstance(datasets, sidpy.Dataset):
|
|
43
|
-
datasets = {'Channel_000': datasets}
|
|
44
|
-
elif isinstance(datasets, dict):
|
|
45
|
-
pass
|
|
46
|
-
else:
|
|
47
|
-
raise TypeError('dataset or first item inhas to be a sidpy dataset')
|
|
48
|
-
self.datasets = datasets
|
|
49
|
-
self.dataset = datasets[list(datasets)[0]]
|
|
50
|
-
|
|
51
|
-
if not isinstance(self.dataset, sidpy.Dataset):
|
|
52
|
-
raise TypeError('dataset or first item inhas to be a sidpy dataset')
|
|
53
|
-
|
|
54
|
-
self.spec_dim = ft.get_dimensions_by_type('spectral', self.dataset)
|
|
55
|
-
if len(self.spec_dim) != 1:
|
|
56
|
-
raise TypeError('We need exactly one SPECTRAL dimension')
|
|
57
|
-
self.spec_dim = self.spec_dim[0]
|
|
58
|
-
|
|
59
|
-
self.ui = eels_dlg.UiDialog(self)
|
|
60
|
-
# Run the .setup_ui() method to show the GUI
|
|
61
|
-
# self.ui.setup_ui(self)
|
|
62
|
-
|
|
63
|
-
self.set_action()
|
|
64
|
-
|
|
65
|
-
self.energy_scale = np.array([])
|
|
66
|
-
self.model = np.array([])
|
|
67
|
-
self.y_scale = 1.0
|
|
68
|
-
self.change_y_scale = 1.0
|
|
69
|
-
self.spectrum_ll = None
|
|
70
|
-
self.low_loss_key = None
|
|
71
|
-
|
|
72
|
-
self.edges = {}
|
|
73
|
-
|
|
74
|
-
self.show_regions = False
|
|
75
|
-
self.show()
|
|
76
|
-
|
|
77
|
-
self.set_dataset(self.dataset)
|
|
78
|
-
initial_elements = []
|
|
79
|
-
|
|
80
|
-
for key in self.edges:
|
|
81
|
-
if key.isdigit():
|
|
82
|
-
if 'element' in self.edges[key]:
|
|
83
|
-
initial_elements.append(self.edges[key]['element'])
|
|
84
|
-
|
|
85
|
-
self.pt_dialog = eels_dialog_utilities.PeriodicTableDialog(energy_scale=self.energy_scale,
|
|
86
|
-
initial_elements=initial_elements)
|
|
87
|
-
self.pt_dialog.signal_selected[list].connect(self.set_elements)
|
|
88
|
-
|
|
89
|
-
self.dataset.plot()
|
|
90
|
-
|
|
91
|
-
if hasattr(self.dataset.view, 'axes'):
|
|
92
|
-
self.axis = self.dataset.view.axes[-1]
|
|
93
|
-
elif hasattr(self.dataset.view, 'axis'):
|
|
94
|
-
self.axis = self.dataset.view.axis
|
|
95
|
-
|
|
96
|
-
self.figure = self.axis.figure
|
|
97
|
-
self.updY = 0
|
|
98
|
-
self.figure.canvas.mpl_connect('button_press_event', self.plot)
|
|
99
|
-
|
|
100
|
-
self.ui.do_fit_button.setFocus()
|
|
101
|
-
self.plot()
|
|
102
|
-
self.ui.do_fit_button.setFocus()
|
|
103
|
-
|
|
104
|
-
def set_dataset(self, dataset):
|
|
105
|
-
|
|
106
|
-
self.dataset = dataset
|
|
107
|
-
if 'edges' not in self.dataset.metadata or self.dataset.metadata['edges'] == {}:
|
|
108
|
-
self.dataset.metadata['edges'] = {'0': {}, 'model': {}, 'use_low_loss': False}
|
|
109
|
-
self.edges = self.dataset.metadata['edges']
|
|
110
|
-
|
|
111
|
-
spec_dim = ft.get_dimensions_by_type('spectral', dataset)[0]
|
|
112
|
-
|
|
113
|
-
if len(spec_dim) == 0:
|
|
114
|
-
raise TypeError('We need at least one SPECTRAL dimension')
|
|
115
|
-
|
|
116
|
-
self.spec_dim = spec_dim[0]
|
|
117
|
-
self.energy_scale = dataset._axes[self.spec_dim].values
|
|
118
|
-
self.ui.edit2.setText(f"{self.energy_scale[-2]:.3f}")
|
|
119
|
-
|
|
120
|
-
if 'fit_area' not in self.edges:
|
|
121
|
-
self.edges['fit_area'] = {}
|
|
122
|
-
if 'fit_start' not in self.edges['fit_area']:
|
|
123
|
-
self.ui.edit1.setText(f"{self.energy_scale[50]:.3f}")
|
|
124
|
-
self.edges['fit_area']['fit_start'] = float(self.ui.edit1.displayText())
|
|
125
|
-
else:
|
|
126
|
-
self.ui.edit1.setText(f"{self.edges['fit_area']['fit_start']:.3f}")
|
|
127
|
-
if 'fit_end' not in self.edges['fit_area']:
|
|
128
|
-
self.ui.edit2.setText(f"{self.energy_scale[-2]:.3f}")
|
|
129
|
-
self.edges['fit_area']['fit_end'] = float(self.ui.edit2.displayText())
|
|
130
|
-
else:
|
|
131
|
-
self.ui.edit2.setText(f"{self.edges['fit_area']['fit_end']:.3f}")
|
|
132
|
-
|
|
133
|
-
if self.dataset.data_type.name == 'SPECTRAL_IMAGE':
|
|
134
|
-
if 'SI_bin_x' not in self.dataset.metadata['experiment']:
|
|
135
|
-
self.dataset.metadata['experiment']['SI_bin_x'] = 1
|
|
136
|
-
self.dataset.metadata['experiment']['SI_bin_y'] = 1
|
|
137
|
-
|
|
138
|
-
bin_x = self.dataset.metadata['experiment']['SI_bin_x']
|
|
139
|
-
bin_y = self.dataset.metadata['experiment']['SI_bin_y']
|
|
140
|
-
self.dataset.view.set_bin([bin_x, bin_y])
|
|
141
|
-
self.update()
|
|
142
|
-
|
|
143
|
-
def update(self):
|
|
144
|
-
index = self.ui.list3.currentIndex() # which edge
|
|
145
|
-
edge = self.edges[str(index)]
|
|
146
|
-
|
|
147
|
-
if 'z' in edge:
|
|
148
|
-
self.ui.list5.setCurrentIndex(self.ui.edge_sym.index(edge['symmetry']))
|
|
149
|
-
self.ui.edit4.setText(str(edge['z']))
|
|
150
|
-
self.ui.unit4.setText(edge['element'])
|
|
151
|
-
self.ui.edit6.setText(f"{edge['onset']:.2f}")
|
|
152
|
-
self.ui.edit7.setText(f"{edge['start_exclude']:.2f}")
|
|
153
|
-
self.ui.edit8.setText(f"{edge['end_exclude']:.2f}")
|
|
154
|
-
if self.y_scale == 1.0:
|
|
155
|
-
self.ui.edit9.setText(f"{edge['areal_density']:.2e}")
|
|
156
|
-
self.ui.unit9.setText('a.u.')
|
|
157
|
-
else:
|
|
158
|
-
dispersion = self.energy_scale[1]-self.energy_scale[0]
|
|
159
|
-
self.ui.edit9.setText(f"{edge['areal_density']*self.y_scale*1e-6/dispersion:.2f}")
|
|
160
|
-
self.ui.unit9.setText('atoms/nm²')
|
|
161
|
-
else:
|
|
162
|
-
self.ui.list3.setCurrentIndex(0)
|
|
163
|
-
self.ui.edit4.setText(str(0))
|
|
164
|
-
self.ui.unit4.setText(' ')
|
|
165
|
-
self.ui.edit6.setText(f"{0:.2f}")
|
|
166
|
-
self.ui.edit7.setText(f"{0:.2f}")
|
|
167
|
-
self.ui.edit8.setText(f"{0:.2f}")
|
|
168
|
-
self.ui.edit9.setText(f"{0:.2e}")
|
|
169
|
-
|
|
170
|
-
def update_element(self, z):
|
|
171
|
-
# We check whether this element is already in the
|
|
172
|
-
zz = eels.get_z(z)
|
|
173
|
-
for key, edge in self.edges.items():
|
|
174
|
-
if key.isdigit():
|
|
175
|
-
if 'z' in edge:
|
|
176
|
-
if zz == edge['z']:
|
|
177
|
-
return False
|
|
178
|
-
|
|
179
|
-
major_edge = ''
|
|
180
|
-
minor_edge = ''
|
|
181
|
-
all_edges = {}
|
|
182
|
-
x_section = eels.get_x_sections(zz)
|
|
183
|
-
edge_start = 10 # int(15./ft.get_slope(self.energy_scale)+0.5)
|
|
184
|
-
for key in x_section:
|
|
185
|
-
if len(key) == 2 and key[0] in ['K', 'L', 'M', 'N', 'O'] and key[1].isdigit():
|
|
186
|
-
if self.energy_scale[edge_start] < x_section[key]['onset'] < self.energy_scale[-edge_start]:
|
|
187
|
-
if key in ['K1', 'L3', 'M5']:
|
|
188
|
-
major_edge = key
|
|
189
|
-
elif key in self.ui.edge_sym:
|
|
190
|
-
if minor_edge == '':
|
|
191
|
-
minor_edge = key
|
|
192
|
-
if int(key[-1]) % 2 > 0:
|
|
193
|
-
if int(minor_edge[-1]) % 2 == 0 or key[-1] > minor_edge[-1]:
|
|
194
|
-
minor_edge = key
|
|
195
|
-
|
|
196
|
-
all_edges[key] = {'onset': x_section[key]['onset']}
|
|
197
|
-
|
|
198
|
-
if major_edge != '':
|
|
199
|
-
key = major_edge
|
|
200
|
-
elif minor_edge != '':
|
|
201
|
-
key = minor_edge
|
|
202
|
-
else:
|
|
203
|
-
print(f'Could not find no edge of {zz} in spectrum')
|
|
204
|
-
return False
|
|
205
|
-
|
|
206
|
-
index = self.ui.list3.currentIndex()
|
|
207
|
-
# self.ui.dialog.setWindowTitle(f'{index}, {zz}')
|
|
208
|
-
|
|
209
|
-
if str(index) not in self.edges:
|
|
210
|
-
self.edges[str(index)] = {}
|
|
211
|
-
|
|
212
|
-
start_exclude = x_section[key]['onset'] - x_section[key]['excl before']
|
|
213
|
-
end_exclude = x_section[key]['onset'] + x_section[key]['excl after']
|
|
214
|
-
|
|
215
|
-
self.edges[str(index)] = {'z': zz, 'symmetry': key, 'element': eels.elements[zz],
|
|
216
|
-
'onset': x_section[key]['onset'], 'end_exclude': end_exclude,
|
|
217
|
-
'start_exclude': start_exclude}
|
|
218
|
-
self.edges[str(index)]['all_edges'] = all_edges
|
|
219
|
-
self.edges[str(index)]['chemical_shift'] = 0.0
|
|
220
|
-
self.edges[str(index)]['areal_density'] = 0.0
|
|
221
|
-
self.edges[str(index)]['original_onset'] = self.edges[str(index)]['onset']
|
|
222
|
-
return True
|
|
223
|
-
|
|
224
|
-
def on_enter(self):
|
|
225
|
-
sender = self.sender()
|
|
226
|
-
edge_list = self.ui.list3
|
|
227
|
-
# self.ui.dialog.setWindowTitle(f"{sender.objectName()}")
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if sender.objectName() == 'fit_start_edit':
|
|
231
|
-
value = float(str(sender.displayText()).strip())
|
|
232
|
-
if value < self.energy_scale[0]:
|
|
233
|
-
value = self.energy_scale[0]
|
|
234
|
-
if value > self.energy_scale[-5]:
|
|
235
|
-
value = self.energy_scale[-5]
|
|
236
|
-
self.edges['fit_area']['fit_start'] = value
|
|
237
|
-
sender.setText(str(self.edges['fit_area']['fit_start']))
|
|
238
|
-
elif sender.objectName() == 'fit_end_edit':
|
|
239
|
-
value = float(str(sender.displayText()).strip())
|
|
240
|
-
if value < self.energy_scale[5]:
|
|
241
|
-
value = self.energy_scale[5]
|
|
242
|
-
if value > self.energy_scale[-1]:
|
|
243
|
-
value = self.energy_scale[-1]
|
|
244
|
-
self.edges['fit_area']['fit_end'] = value
|
|
245
|
-
sender.setText(str(self.edges['fit_area']['fit_end']))
|
|
246
|
-
elif sender.objectName() == 'element_edit':
|
|
247
|
-
if str(sender.displayText()).strip() == '0':
|
|
248
|
-
# sender.setText('PT')
|
|
249
|
-
self.pt_dialog.energy_scale = self.energy_scale
|
|
250
|
-
self.pt_dialog.show()
|
|
251
|
-
pass
|
|
252
|
-
else:
|
|
253
|
-
self.update_element(str(sender.displayText()).strip())
|
|
254
|
-
self.update()
|
|
255
|
-
elif sender.objectName() in ['onset_edit', 'excl_start_edit', 'excl_end_edit']:
|
|
256
|
-
self.check_area_consistency()
|
|
257
|
-
|
|
258
|
-
elif sender.objectName() == 'multiplier_edit':
|
|
259
|
-
index = edge_list.currentIndex()
|
|
260
|
-
self.edges[str(index)]['areal_density'] = float(self.ui.edit9.displayText())
|
|
261
|
-
if self.y_scale != 1.0:
|
|
262
|
-
dispersion = self.energy_scale[1]-self.energy_scale[0]
|
|
263
|
-
self.edges[str(index)]['areal_density'] /= self.y_scale * 1e-6 *dispersion
|
|
264
|
-
if 'background' not in self.edges['model']:
|
|
265
|
-
print(' no background')
|
|
266
|
-
return
|
|
267
|
-
self.model = self.edges['model']['background']
|
|
268
|
-
for key in self.edges:
|
|
269
|
-
if key.isdigit():
|
|
270
|
-
self.model = self.model + self.edges[key]['areal_density'] * self.edges[key]['data']
|
|
271
|
-
self.plot()
|
|
272
|
-
else:
|
|
273
|
-
return
|
|
274
|
-
if self.show_regions:
|
|
275
|
-
self.plot()
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
def sort_elements(self):
|
|
280
|
-
onsets = []
|
|
281
|
-
for index, edge in self.edges.items():
|
|
282
|
-
if index.isdigit():
|
|
283
|
-
onsets.append(float(edge['onset']))
|
|
284
|
-
|
|
285
|
-
arg_sorted = np.argsort(onsets)
|
|
286
|
-
edges = self.edges.copy()
|
|
287
|
-
for index, i_sorted in enumerate(arg_sorted):
|
|
288
|
-
self.edges[str(index)] = edges[str(i_sorted)].copy()
|
|
289
|
-
|
|
290
|
-
index = 0
|
|
291
|
-
edge = self.edges['0']
|
|
292
|
-
dispersion = self.energy_scale[1]-self.energy_scale[0]
|
|
293
|
-
|
|
294
|
-
while str(index + 1) in self.edges:
|
|
295
|
-
next_edge = self.edges[str(index + 1)]
|
|
296
|
-
if edge['end_exclude'] > next_edge['start_exclude'] - 5 * dispersion:
|
|
297
|
-
edge['end_exclude'] = next_edge['start_exclude'] - 5 * dispersion
|
|
298
|
-
edge = next_edge
|
|
299
|
-
index += 1
|
|
300
|
-
|
|
301
|
-
if edge['end_exclude'] > self.energy_scale[-3]:
|
|
302
|
-
edge['end_exclude'] = self.energy_scale[-3]
|
|
303
|
-
|
|
304
|
-
def set_elements(self, selected_elements):
|
|
305
|
-
edge_list = self.ui.list3
|
|
306
|
-
|
|
307
|
-
for index, elem in enumerate(selected_elements):
|
|
308
|
-
edge_list.setCurrentIndex(index)
|
|
309
|
-
self.update_element(elem)
|
|
310
|
-
|
|
311
|
-
self.sort_elements()
|
|
312
|
-
self.update()
|
|
313
|
-
|
|
314
|
-
def plot(self, event=None):
|
|
315
|
-
self.energy_scale = self.dataset._axes[self.spec_dim].values
|
|
316
|
-
if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE:
|
|
317
|
-
spectrum = self.dataset.view.get_spectrum()
|
|
318
|
-
self.axis = self.dataset.view.axes[1]
|
|
319
|
-
else:
|
|
320
|
-
spectrum = np.array(self.dataset)
|
|
321
|
-
self.axis = self.dataset.view.axis
|
|
322
|
-
|
|
323
|
-
if self.ui.select10.isChecked():
|
|
324
|
-
if 'experiment' in self.dataset.metadata:
|
|
325
|
-
exp = self.dataset.metadata['experiment']
|
|
326
|
-
if 'convergence_angle' not in exp:
|
|
327
|
-
raise ValueError('need a convergence_angle in experiment of metadata dictionary ')
|
|
328
|
-
alpha = exp['convergence_angle']
|
|
329
|
-
beta = exp['collection_angle']
|
|
330
|
-
beam_kv = exp['acceleration_voltage']
|
|
331
|
-
|
|
332
|
-
eff_beta = eels.effective_collection_angle(self.energy_scale, alpha, beta, beam_kv)
|
|
333
|
-
edges = eels.make_cross_sections(self.edges, np.array(self.energy_scale), beam_kv, eff_beta)
|
|
334
|
-
self.edges = eels.fit_edges2(spectrum, self.energy_scale, edges)
|
|
335
|
-
areal_density = []
|
|
336
|
-
elements = []
|
|
337
|
-
for key in edges:
|
|
338
|
-
if key.isdigit(): # only edges have numbers in that dictionary
|
|
339
|
-
elements.append(edges[key]['element'])
|
|
340
|
-
areal_density.append(edges[key]['areal_density'])
|
|
341
|
-
areal_density = np.array(areal_density)
|
|
342
|
-
out_string = '\nRelative composition: \n'
|
|
343
|
-
for i, element in enumerate(elements):
|
|
344
|
-
out_string += f'{element}: {areal_density[i] / areal_density.sum() * 100:.1f}% '
|
|
345
|
-
|
|
346
|
-
self.model = self.edges['model']['spectrum']
|
|
347
|
-
self.update()
|
|
348
|
-
|
|
349
|
-
x_limit = self.axis.get_xlim()
|
|
350
|
-
y_limit = np.array(self.axis.get_ylim())*self.change_y_scale
|
|
351
|
-
self.change_y_scale = 1.0
|
|
352
|
-
|
|
353
|
-
self.axis.clear()
|
|
354
|
-
|
|
355
|
-
line1, = self.axis.plot(self.energy_scale, spectrum*self.y_scale, label='spectrum')
|
|
356
|
-
lines = [line1]
|
|
357
|
-
|
|
358
|
-
def onpick(event):
|
|
359
|
-
# on the pick event, find the orig line corresponding to the
|
|
360
|
-
# legend proxy line, and toggle the visibility
|
|
361
|
-
leg_line = event.artist
|
|
362
|
-
orig_line = lined[legline]
|
|
363
|
-
vis = not origline.get_visible()
|
|
364
|
-
orig_line.set_visible(vis)
|
|
365
|
-
# Change the alpha on the line in the legend, so we can see what lines
|
|
366
|
-
# have been toggled
|
|
367
|
-
if vis:
|
|
368
|
-
leg_line.set_alpha(1.0)
|
|
369
|
-
else:
|
|
370
|
-
leg_line.set_alpha(0.2)
|
|
371
|
-
self.figure.canvas.draw()
|
|
372
|
-
|
|
373
|
-
if len(self.model) > 1:
|
|
374
|
-
line2, = self.axis.plot(self.energy_scale, self.model*self.y_scale, label='model')
|
|
375
|
-
line3, = self.axis.plot(self.energy_scale, (spectrum - self.model)*self.y_scale, label='difference')
|
|
376
|
-
line4, = self.axis.plot(self.energy_scale, (spectrum - self.model) / np.sqrt(spectrum)*self.y_scale, label='Poisson')
|
|
377
|
-
lines = [line1, line2, line3, line4]
|
|
378
|
-
lined = dict()
|
|
379
|
-
|
|
380
|
-
legend = self.axis.legend(loc='upper right', fancybox=True, shadow=True)
|
|
381
|
-
|
|
382
|
-
legend.get_frame().set_alpha(0.4)
|
|
383
|
-
for legline, origline in zip(legend.get_lines(), lines):
|
|
384
|
-
legline.set_picker(5) # 5 pts tolerance
|
|
385
|
-
lined[legline] = origline
|
|
386
|
-
self.figure.canvas.mpl_connect('pick_event', onpick)
|
|
387
|
-
self.axis.set_xlim(x_limit)
|
|
388
|
-
self.axis.set_ylim(y_limit)
|
|
389
|
-
|
|
390
|
-
if self.y_scale != 1.:
|
|
391
|
-
self.axis.set_ylabel('scattering intensity (ppm)')
|
|
392
|
-
else:
|
|
393
|
-
self.axis.set_ylabel('intensity (counts)')
|
|
394
|
-
self.axis.set_xlabel('energy_loss (eV)')
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
if self.ui.show_edges.isChecked():
|
|
398
|
-
self.show_edges()
|
|
399
|
-
if self.show_regions:
|
|
400
|
-
self.plot_regions()
|
|
401
|
-
self.figure.canvas.draw_idle()
|
|
402
|
-
|
|
403
|
-
def plot_regions(self):
|
|
404
|
-
y_min, y_max = self.axis.get_ylim()
|
|
405
|
-
height = y_max - y_min
|
|
406
|
-
|
|
407
|
-
rect = []
|
|
408
|
-
if 'fit_area' in self.edges:
|
|
409
|
-
color = 'blue'
|
|
410
|
-
alpha = 0.2
|
|
411
|
-
x_min = self.edges['fit_area']['fit_start']
|
|
412
|
-
width = self.edges['fit_area']['fit_end'] - x_min
|
|
413
|
-
rect.append(patches.Rectangle((x_min, y_min), width, height,
|
|
414
|
-
edgecolor=color, alpha=alpha, facecolor=color))
|
|
415
|
-
self.axis.add_patch(rect[0])
|
|
416
|
-
self.axis.text(x_min, y_max, 'fit region', verticalalignment='top')
|
|
417
|
-
color = 'red'
|
|
418
|
-
alpha = 0.5
|
|
419
|
-
for key in self.edges:
|
|
420
|
-
if key.isdigit():
|
|
421
|
-
x_min = self.edges[key]['start_exclude']
|
|
422
|
-
width = self.edges[key]['end_exclude']-x_min
|
|
423
|
-
rect.append(patches.Rectangle((x_min, y_min), width, height,
|
|
424
|
-
edgecolor=color, alpha=alpha, facecolor=color))
|
|
425
|
-
self.axis.add_patch(rect[-1])
|
|
426
|
-
self.axis.text(x_min, y_max, f"exclude\n edge {int(key)+1}", verticalalignment='top')
|
|
427
|
-
|
|
428
|
-
def show_edges(self):
|
|
429
|
-
x_min, x_max = self.axis.get_xlim()
|
|
430
|
-
y_min, y_max = self.axis.get_ylim()
|
|
431
|
-
|
|
432
|
-
for key, edge in self.edges.items():
|
|
433
|
-
i = 0
|
|
434
|
-
if key.isdigit():
|
|
435
|
-
element = edge['element']
|
|
436
|
-
for sym in edge['all_edges']:
|
|
437
|
-
x = edge['all_edges'][sym]['onset'] + edge['chemical_shift']
|
|
438
|
-
if x_min < x < x_max:
|
|
439
|
-
self.axis.text(x, y_max, '\n' * i + f"{element}-{sym}",
|
|
440
|
-
verticalalignment='top', color='black')
|
|
441
|
-
self.axis.axvline(x, ymin=0, ymax=1, color='gray')
|
|
442
|
-
i += 1
|
|
443
|
-
|
|
444
|
-
def check_area_consistency(self):
|
|
445
|
-
if self.dataset is None:
|
|
446
|
-
return
|
|
447
|
-
onset = float(self.ui.edit6.displayText())
|
|
448
|
-
excl_start = float(self.ui.edit7.displayText())
|
|
449
|
-
excl_end = float(self.ui.edit8.displayText())
|
|
450
|
-
if onset < self.energy_scale[2]:
|
|
451
|
-
onset = self.energy_scale[2]
|
|
452
|
-
excl_start = self.energy_scale[2]
|
|
453
|
-
if onset > self.energy_scale[-2]:
|
|
454
|
-
onset = self.energy_scale[-2]
|
|
455
|
-
excl_end = self.energy_scale[-2]
|
|
456
|
-
if excl_start > onset:
|
|
457
|
-
excl_start = onset
|
|
458
|
-
if excl_end < onset:
|
|
459
|
-
excl_end = onset
|
|
460
|
-
|
|
461
|
-
index = self.ui.list3.currentIndex()
|
|
462
|
-
self.edges[str(index)]['chemical_shift'] = onset - self.edges[str(index)]['original_onset']
|
|
463
|
-
self.edges[str(index)]['onset'] = onset
|
|
464
|
-
self.edges[str(index)]['end_exclude'] = excl_end
|
|
465
|
-
self.edges[str(index)]['start_exclude'] = excl_start
|
|
466
|
-
|
|
467
|
-
self.update()
|
|
468
|
-
|
|
469
|
-
def on_list_enter(self):
|
|
470
|
-
sender = self.sender()
|
|
471
|
-
# self.ui.dialog.setWindowTitle(f"on list eneter {sender.objectName()}")
|
|
472
|
-
|
|
473
|
-
if sender.objectName() == 'edge_list':
|
|
474
|
-
index = self.ui.list3.currentIndex()
|
|
475
|
-
|
|
476
|
-
number_of_edges = 0
|
|
477
|
-
for key in self.edges:
|
|
478
|
-
if key.isdigit():
|
|
479
|
-
if int(key) > number_of_edges:
|
|
480
|
-
number_of_edges = int(key)
|
|
481
|
-
number_of_edges += 1
|
|
482
|
-
if index > number_of_edges:
|
|
483
|
-
index = number_of_edges
|
|
484
|
-
self.ui.list3.setCurrentIndex(index)
|
|
485
|
-
if str(index) not in self.edges:
|
|
486
|
-
self.edges[str(index)] = {'z': 0, 'symmetry': 'K1', 'element': 'H', 'onset': 0, 'end_exclude': 0,
|
|
487
|
-
'start_exclude': 0, 'areal_density': 0}
|
|
488
|
-
|
|
489
|
-
self.update()
|
|
490
|
-
elif sender.objectName() == 'symmetry_list':
|
|
491
|
-
sym = self.ui.list5.currentText()
|
|
492
|
-
index = self.ui.list3.currentIndex()
|
|
493
|
-
zz = self.edges[str(index)]['z']
|
|
494
|
-
if zz > 1:
|
|
495
|
-
x_section = eels.get_x_sections(zz)
|
|
496
|
-
if sym in x_section:
|
|
497
|
-
start_exclude = x_section[sym]['onset'] - x_section[sym]['excl before']
|
|
498
|
-
end_exclude = x_section[sym]['onset'] + x_section[sym]['excl after']
|
|
499
|
-
self.edges[str(index)].update({'symmetry': sym, 'onset': x_section[sym]['onset'],
|
|
500
|
-
'end_exclude': end_exclude, 'start_exclude': start_exclude})
|
|
501
|
-
self.edges[str(index)]['chemical_shift'] = 0.0
|
|
502
|
-
self.edges[str(index)]['areal_density'] = 0.0
|
|
503
|
-
self.edges[str(index)]['original_onset'] = self.edges[index]['onset']
|
|
504
|
-
self.update()
|
|
505
|
-
elif sender.objectName() == 'symmetry_method':
|
|
506
|
-
self.ui.select5.setCurrentIndex(0)
|
|
507
|
-
|
|
508
|
-
def on_check(self):
|
|
509
|
-
sender = self.sender()
|
|
510
|
-
# self.ui.dialog.setWindowTitle(f"on_check {sender.objectName()}")
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
if sender.objectName() == 'edge_check':
|
|
514
|
-
self.show_regions = sender.isChecked()
|
|
515
|
-
elif sender.objectName() == 'conv_ll':
|
|
516
|
-
self.edges['use_low_loss'] = self.ui.check10.isChecked()
|
|
517
|
-
if self.ui.check10.isChecked():
|
|
518
|
-
self.low_loss()
|
|
519
|
-
elif sender.objectName() == 'probability':
|
|
520
|
-
dispersion = self.energy_scale[1]-self.energy_scale[0]
|
|
521
|
-
old_y_scale = self.y_scale *1.
|
|
522
|
-
if sender.isChecked():
|
|
523
|
-
flux_key = None
|
|
524
|
-
spectrum_key = None
|
|
525
|
-
|
|
526
|
-
for key in self.datasets.keys():
|
|
527
|
-
if 'Reference' in key:
|
|
528
|
-
if self.datasets[key].data_type.name == 'IMAGE': # Prefer Ronchigrams
|
|
529
|
-
flux_key = key
|
|
530
|
-
self.dataset.metadata['experiment']['flux_reference_key'] = flux_key
|
|
531
|
-
elif self.datasets[key].data_type.name == 'SPECTRUM':
|
|
532
|
-
spectrum_key = key
|
|
533
|
-
self.dataset.metadata['experiment']['low_loss_key'] = spectrum_key
|
|
534
|
-
if flux_key is None:
|
|
535
|
-
flux_key = spectrum_key
|
|
536
|
-
|
|
537
|
-
# self.ui.dialog.setWindowTitle(f"2nd {self.dataset.metadata['experiment']['flux_ppm']:.2f}")
|
|
538
|
-
if self.dataset.metadata['experiment']['flux_ppm'] > 0:
|
|
539
|
-
# self.ui.dialog.setWindowTitle(f"3rD {self.dataset.metadata['experiment']['flux_ppm']:.2f}")
|
|
540
|
-
self.y_scale = 1/self.dataset.metadata['experiment']['flux_ppm']*dispersion
|
|
541
|
-
elif flux_key is not None:
|
|
542
|
-
self.dataset.metadata['experiment']['flux_ppm'] = (np.array(self.datasets[flux_key])/1e6).sum()
|
|
543
|
-
self.dataset.metadata['experiment']['flux_ppm'] /= self.datasets[flux_key].metadata['experiment']['exposure_time']
|
|
544
|
-
self.dataset.metadata['experiment']['flux_ppm'] *= self.dataset.metadata['experiment']['exposure_time']
|
|
545
|
-
self.y_scale = 1/self.dataset.metadata['experiment']['flux_ppm']*dispersion
|
|
546
|
-
else:
|
|
547
|
-
self.y_scale = 1.0
|
|
548
|
-
else:
|
|
549
|
-
self.y_scale = 1.0
|
|
550
|
-
|
|
551
|
-
self.change_y_scale = self.y_scale/old_y_scale
|
|
552
|
-
self.update()
|
|
553
|
-
self.plot()
|
|
554
|
-
|
|
555
|
-
def low_loss(self):
|
|
556
|
-
self.edges['use_low_loss'] = self.ui.check10.isChecked()
|
|
557
|
-
if self.low_loss_key is None:
|
|
558
|
-
for key in self.datasets.keys():
|
|
559
|
-
if 'Reference' in key:
|
|
560
|
-
if self.datasets[key].data_type.name == 'SPECTRUM':
|
|
561
|
-
self.low_loss_key = key
|
|
562
|
-
self.dataset.metadata['experiment']['low_loss_key'] = self.low_loss_key
|
|
563
|
-
|
|
564
|
-
if self.low_loss_key is None:
|
|
565
|
-
self.low_loss_key = ft.add_dataset_from_file(self.datasets, key_name='Reference')
|
|
566
|
-
self.spectrum_ll = self.datasets[self.low_loss_key]
|
|
567
|
-
if self.spectrum_ll.data_type.name != 'SPECTRUM':
|
|
568
|
-
self.spectrum_ll = None
|
|
569
|
-
self.low_loss_key = None
|
|
570
|
-
|
|
571
|
-
if self.low_loss_key is not None:
|
|
572
|
-
self.spectrum_ll = self.datasets[self.low_loss_key]
|
|
573
|
-
if 'number_of_frames' in self.spectrum_ll.metadata['experiment']:
|
|
574
|
-
self.spectrum_ll.metadata['experiment']['exposure_time'] = \
|
|
575
|
-
self.spectrum_ll.metadata['experiment']['single_exposure_time'] * \
|
|
576
|
-
self.spectrum_ll.metadata['experiment']['number_of_frames']
|
|
577
|
-
|
|
578
|
-
def do_all_button_click(self):
|
|
579
|
-
|
|
580
|
-
if self.dataset.data_type.name != 'SPECTRAL_IMAGE':
|
|
581
|
-
self.do_fit_button_click()
|
|
582
|
-
return
|
|
583
|
-
|
|
584
|
-
if 'experiment' in self.dataset.metadata:
|
|
585
|
-
exp = self.dataset.metadata['experiment']
|
|
586
|
-
if 'convergence_angle' not in exp:
|
|
587
|
-
raise ValueError('need a convergence_angle in experiment of metadata dictionary ')
|
|
588
|
-
alpha = exp['convergence_angle']
|
|
589
|
-
beta = exp['collection_angle']
|
|
590
|
-
beam_kv = exp['acceleration_voltage']
|
|
591
|
-
else:
|
|
592
|
-
raise ValueError('need a experiment parameter in metadata dictionary')
|
|
593
24
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
if self.edges['use_low_loss']:
|
|
597
|
-
low_loss = np.array(self.spectrum_ll)/self.spectrum_ll.sum()
|
|
598
|
-
else:
|
|
599
|
-
low_loss = None
|
|
600
|
-
|
|
601
|
-
edges = eels.make_cross_sections(self.edges, np.array(self.energy_scale), beam_kv, eff_beta,
|
|
602
|
-
low_loss=low_loss)
|
|
25
|
+
class CurveVisualizer(object):
|
|
26
|
+
"""Plots a sidpy.Dataset with spectral dimension-type
|
|
603
27
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
number_of_edges += 1
|
|
615
|
-
|
|
616
|
-
results = np.zeros([int(self.dataset.shape[0]/bin_x), int(self.dataset.shape[1]/bin_y), number_of_edges])
|
|
617
|
-
total_spec = int(self.dataset.shape[0]/bin_x)*int(self.dataset.shape[1]/bin_y)
|
|
618
|
-
self.ui.progress.setMaximum(total_spec)
|
|
619
|
-
self.ui.progress.setValue(0)
|
|
620
|
-
ind = 0
|
|
621
|
-
for x in range(int(self.dataset.shape[0]/bin_x)):
|
|
622
|
-
|
|
623
|
-
for y in range(int(self.dataset.shape[1]/bin_y)):
|
|
624
|
-
ind += 1
|
|
625
|
-
self.ui.progress.setValue(ind)
|
|
626
|
-
view.x = x*bin_x
|
|
627
|
-
view.y = y*bin_y
|
|
628
|
-
spectrum = view.get_spectrum()
|
|
629
|
-
|
|
630
|
-
edges = eels.fit_edges2(spectrum, self.energy_scale, edges)
|
|
631
|
-
for key, edge in edges.items():
|
|
632
|
-
if key.isdigit():
|
|
633
|
-
# element.append(edge['element'])
|
|
634
|
-
results[x, y, int(key)] = edge['areal_density']
|
|
635
|
-
edges['spectrum_image_quantification'] = results
|
|
636
|
-
self.ui.progress.setValue(total_spec)
|
|
637
|
-
view.x = start_x
|
|
638
|
-
view.y = start_y
|
|
639
|
-
|
|
640
|
-
def do_fit_button_click(self):
|
|
641
|
-
if 'experiment' in self.dataset.metadata:
|
|
642
|
-
exp = self.dataset.metadata['experiment']
|
|
643
|
-
if 'convergence_angle' not in exp:
|
|
644
|
-
raise ValueError('need a convergence_angle in experiment of metadata dictionary ')
|
|
645
|
-
alpha = exp['convergence_angle']
|
|
646
|
-
beta = exp['collection_angle']
|
|
647
|
-
beam_kv = exp['acceleration_voltage']
|
|
648
|
-
|
|
649
|
-
else:
|
|
650
|
-
raise ValueError('need a experiment parameter in metadata dictionary')
|
|
651
|
-
self.energy_scale = self.dataset._axes[self.spec_dim].values
|
|
652
|
-
eff_beta = eels.effective_collection_angle(self.energy_scale, alpha, beta, beam_kv)
|
|
653
|
-
|
|
654
|
-
if self.edges['use_low_loss']:
|
|
655
|
-
low_loss = self.spectrum_ll / self.spectrum_ll.sum()
|
|
656
|
-
else:
|
|
657
|
-
low_loss = None
|
|
658
|
-
edges = eels.make_cross_sections(self.edges, np.array(self.energy_scale), beam_kv, eff_beta, low_loss)
|
|
28
|
+
"""
|
|
29
|
+
def __init__(self, dset, spectrum_number=None, axis=None, leg=None, **kwargs):
|
|
30
|
+
if not isinstance(dset, sidpy.Dataset):
|
|
31
|
+
raise TypeError('dset should be a sidpy.Dataset object')
|
|
32
|
+
if axis is None:
|
|
33
|
+
self.fig = plt.figure()
|
|
34
|
+
self.axis = self.fig.add_subplot(1, 1, 1)
|
|
35
|
+
else:
|
|
36
|
+
self.axis = axis
|
|
37
|
+
self.fig = axis.figure
|
|
659
38
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
spectrum = self.dataset
|
|
664
|
-
self.edges = eels.fit_edges2(spectrum, self.energy_scale, edges)
|
|
665
|
-
areal_density = []
|
|
666
|
-
elements = []
|
|
667
|
-
for key in edges:
|
|
668
|
-
if key.isdigit(): # only edges have numbers in that dictionary
|
|
669
|
-
elements.append(edges[key]['element'])
|
|
670
|
-
areal_density.append(edges[key]['areal_density'])
|
|
671
|
-
areal_density = np.array(areal_density)
|
|
672
|
-
out_string = '\nRelative composition: \n'
|
|
673
|
-
for i, element in enumerate(elements):
|
|
674
|
-
out_string += f'{element}: {areal_density[i] / areal_density.sum() * 100:.1f}% '
|
|
675
|
-
|
|
676
|
-
self.model = self.edges['model']['spectrum']
|
|
677
|
-
self.update()
|
|
678
|
-
self.plot()
|
|
679
|
-
|
|
680
|
-
def do_auto_id_button_click(self):
|
|
681
|
-
# self.ui.dialog.setWindowTitle(f"auto id ")
|
|
682
|
-
self.ui.do_fit_button.setFocus()
|
|
683
|
-
|
|
684
|
-
if '0' not in self.edges:
|
|
685
|
-
self.edges['0'] ={}
|
|
686
|
-
found_edges = eels.auto_id_edges(self.dataset)
|
|
687
|
-
|
|
688
|
-
to_delete = []
|
|
689
|
-
if len(found_edges) >0:
|
|
690
|
-
for key in self.edges:
|
|
691
|
-
if key.isdigit():
|
|
692
|
-
to_delete.append(key)
|
|
693
|
-
for key in to_delete:
|
|
694
|
-
del self.edges[key]
|
|
695
|
-
if len(to_delete) == 0:
|
|
696
|
-
self.edges['0'] = {}
|
|
697
|
-
|
|
698
|
-
selected_elements = []
|
|
699
|
-
for key in found_edges:
|
|
700
|
-
selected_elements.append(key)
|
|
701
|
-
self.set_elements(selected_elements)
|
|
702
|
-
|
|
703
|
-
for button in self.pt_dialog.button:
|
|
704
|
-
if button.text() in selected_elements:
|
|
705
|
-
button.setChecked(True)
|
|
706
|
-
else:
|
|
707
|
-
button.setChecked(False)
|
|
708
|
-
self.update()
|
|
709
|
-
|
|
710
|
-
def do_select_button_click(self):
|
|
711
|
-
self.pt_dialog.energy_scale = self.energy_scale
|
|
712
|
-
self.pt_dialog.show()
|
|
713
|
-
self.update()
|
|
714
|
-
|
|
715
|
-
def set_action(self):
|
|
716
|
-
self.ui.edit1.editingFinished.connect(self.on_enter)
|
|
717
|
-
self.ui.edit2.editingFinished.connect(self.on_enter)
|
|
718
|
-
self.ui.list3.activated[str].connect(self.on_list_enter)
|
|
719
|
-
self.ui.check3.clicked.connect(self.on_check)
|
|
720
|
-
self.ui.edit4.editingFinished.connect(self.on_enter)
|
|
721
|
-
self.ui.list5.activated[str].connect(self.on_list_enter)
|
|
722
|
-
self.ui.select5.activated[str].connect(self.on_list_enter)
|
|
723
|
-
|
|
724
|
-
self.ui.edit6.editingFinished.connect(self.on_enter)
|
|
725
|
-
self.ui.edit7.editingFinished.connect(self.on_enter)
|
|
726
|
-
self.ui.edit8.editingFinished.connect(self.on_enter)
|
|
727
|
-
self.ui.edit9.editingFinished.connect(self.on_enter)
|
|
728
|
-
|
|
729
|
-
self.ui.check10.clicked.connect(self.on_check)
|
|
730
|
-
self.ui.select10.clicked.connect(self.on_check)
|
|
731
|
-
self.ui.show_edges.clicked.connect(self.on_check)
|
|
732
|
-
self.ui.check_probability.clicked.connect(self.on_check)
|
|
733
|
-
|
|
734
|
-
self.ui.do_all_button.clicked.connect(self.do_all_button_click)
|
|
735
|
-
self.ui.do_fit_button.clicked.connect(self.do_fit_button_click)
|
|
736
|
-
self.ui.auto_id_button.clicked.connect(self.do_auto_id_button_click)
|
|
737
|
-
self.ui.select_button.clicked.connect(self.do_select_button_click)
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
class CurveVisualizer(object):
|
|
741
|
-
"""Plots a sidpy.Dataset with spectral dimension-type
|
|
742
|
-
|
|
743
|
-
"""
|
|
744
|
-
def __init__(self, dset, spectrum_number=None, axis=None, leg=None, **kwargs):
|
|
745
|
-
if not isinstance(dset, sidpy.Dataset):
|
|
746
|
-
raise TypeError('dset should be a sidpy.Dataset object')
|
|
747
|
-
if axis is None:
|
|
748
|
-
self.fig = plt.figure()
|
|
749
|
-
self.axis = self.fig.add_subplot(1, 1, 1)
|
|
750
|
-
else:
|
|
751
|
-
self.axis = axis
|
|
752
|
-
self.fig = axis.figure
|
|
39
|
+
self.dset = dset
|
|
40
|
+
self.selection = []
|
|
41
|
+
[self.spec_dim, self.energy_scale] = ft.get_dimensions_by_type('spectral', self.dset)[0]
|
|
753
42
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
[self.spec_dim, self.energy_scale] = ft.get_dimensions_by_type('spectral', self.dset)[0]
|
|
43
|
+
self.lined = dict()
|
|
44
|
+
self.plot(**kwargs)
|
|
757
45
|
|
|
758
|
-
|
|
759
|
-
|
|
46
|
+
def plot(self, **kwargs):
|
|
47
|
+
if self.dset.data_type.name == 'IMAGE_STACK':
|
|
48
|
+
line1, = self.axis.plot(self.energy_scale.values, self.dset[0, 0], label='spectrum', **kwargs)
|
|
49
|
+
else:
|
|
50
|
+
line1, = self.axis.plot(self.energy_scale.values, self.dset, label='spectrum', **kwargs)
|
|
51
|
+
lines = [line1]
|
|
52
|
+
if 'add2plot' in self.dset.metadata:
|
|
53
|
+
data = self.dset.metadata['add2plot']
|
|
54
|
+
for key, line in data.items():
|
|
55
|
+
line_add, = self.axis.plot(self.energy_scale.values, line['data'], label=line['legend'])
|
|
56
|
+
lines.append(line_add)
|
|
57
|
+
|
|
58
|
+
legend = self.axis.legend(loc='upper right', fancybox=True, shadow=True)
|
|
59
|
+
legend.get_frame().set_alpha(0.4)
|
|
60
|
+
|
|
61
|
+
for legline, origline in zip(legend.get_lines(), lines):
|
|
62
|
+
legline.set_picker(True)
|
|
63
|
+
legline.set_pickradius(5) # 5 pts tolerance
|
|
64
|
+
self.lined[legline] = origline
|
|
65
|
+
self.fig.canvas.mpl_connect('pick_event', self.onpick)
|
|
66
|
+
|
|
67
|
+
self.axis.axhline(0, color='gray', alpha=0.6)
|
|
68
|
+
self.axis.set_xlabel(self.dset.labels[0])
|
|
69
|
+
self.axis.set_ylabel(self.dset.data_descriptor)
|
|
70
|
+
self.axis.ticklabel_format(style='sci', scilimits=(-2, 3))
|
|
71
|
+
self.fig.canvas.draw_idle()
|
|
760
72
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
self.axis.set_xlabel(self.dset.labels[0])
|
|
784
|
-
self.axis.set_ylabel(self.dset.data_descriptor)
|
|
785
|
-
self.axis.ticklabel_format(style='sci', scilimits=(-2, 3))
|
|
786
|
-
self.fig.canvas.draw_idle()
|
|
787
|
-
|
|
788
|
-
def update(self, **kwargs):
|
|
789
|
-
x_limit = self.axis.get_xlim()
|
|
790
|
-
y_limit = self.axis.get_ylim()
|
|
791
|
-
self.axis.clear()
|
|
792
|
-
self.plot(**kwargs)
|
|
793
|
-
self.axis.set_xlim(x_limit)
|
|
794
|
-
self.axis.set_ylim(y_limit)
|
|
795
|
-
|
|
796
|
-
def onpick(self, event):
|
|
797
|
-
# on the pick event, find the orig line corresponding to the
|
|
798
|
-
# legend proxy line, and toggle the visibility
|
|
799
|
-
legline = event.artist
|
|
800
|
-
origline = self.lined[legline]
|
|
801
|
-
vis = not origline.get_visible()
|
|
802
|
-
origline.set_visible(vis)
|
|
803
|
-
# Change the alpha on the line in the legend, so we can see what lines
|
|
804
|
-
# have been toggled
|
|
805
|
-
if vis:
|
|
806
|
-
legline.set_alpha(1.0)
|
|
807
|
-
else:
|
|
808
|
-
legline.set_alpha(0.2)
|
|
809
|
-
self.fig.canvas.draw()
|
|
73
|
+
def update(self, **kwargs):
|
|
74
|
+
x_limit = self.axis.get_xlim()
|
|
75
|
+
y_limit = self.axis.get_ylim()
|
|
76
|
+
self.axis.clear()
|
|
77
|
+
self.plot(**kwargs)
|
|
78
|
+
self.axis.set_xlim(x_limit)
|
|
79
|
+
self.axis.set_ylim(y_limit)
|
|
80
|
+
|
|
81
|
+
def onpick(self, event):
|
|
82
|
+
# on the pick event, find the orig line corresponding to the
|
|
83
|
+
# legend proxy line, and toggle the visibility
|
|
84
|
+
legline = event.artist
|
|
85
|
+
origline = self.lined[legline]
|
|
86
|
+
vis = not origline.get_visible()
|
|
87
|
+
origline.set_visible(vis)
|
|
88
|
+
# Change the alpha on the line in the legend, so we can see what lines
|
|
89
|
+
# have been toggled
|
|
90
|
+
if vis:
|
|
91
|
+
legline.set_alpha(1.0)
|
|
92
|
+
else:
|
|
93
|
+
legline.set_alpha(0.2)
|
|
94
|
+
self.fig.canvas.draw()
|
|
810
95
|
|
|
811
96
|
def get_sidebar():
|
|
812
|
-
side_bar = ipywidgets.GridspecLayout(
|
|
97
|
+
side_bar = ipywidgets.GridspecLayout(14, 3,width='auto', grid_gap="0px")
|
|
813
98
|
|
|
814
99
|
|
|
815
100
|
row = 0
|
|
@@ -894,111 +179,88 @@ def get_sidebar():
|
|
|
894
179
|
tooltip='Changes y-axis to probability of flux is given',
|
|
895
180
|
layout=ipywidgets.Layout(width='100px')
|
|
896
181
|
)
|
|
182
|
+
|
|
183
|
+
row += 1
|
|
184
|
+
side_bar[row,0] = ipywidgets.ToggleButton(
|
|
185
|
+
description='Do All',
|
|
186
|
+
disabled=False,
|
|
187
|
+
button_style='', # 'success', 'info', 'warning', 'danger' or ''
|
|
188
|
+
tooltip='Fits all spectra of spectrum image',
|
|
189
|
+
layout=ipywidgets.Layout(width='100px')
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
side_bar[row,1] = ipywidgets.IntProgress(value=0, min=0, max=10, description=' ', bar_style='', # 'success', 'info', 'warning', 'danger' or ''
|
|
193
|
+
style={'bar_color': 'maroon'}, orientation='horizontal')
|
|
897
194
|
return side_bar
|
|
898
195
|
|
|
899
196
|
|
|
900
197
|
class CompositionWidget(object):
|
|
901
|
-
def __init__(self, datasets=None):
|
|
902
|
-
|
|
198
|
+
def __init__(self, datasets=None, key=None):
|
|
199
|
+
|
|
903
200
|
if not isinstance(datasets, dict):
|
|
904
|
-
raise TypeError('dataset or first item
|
|
905
|
-
|
|
201
|
+
raise TypeError('dataset or first item has to be a sidpy dataset')
|
|
202
|
+
self.datasets = datasets
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
self.model = []
|
|
906
206
|
self.sidebar = get_sidebar()
|
|
907
|
-
self.dataset = datasets[list(datasets)[0]]
|
|
908
|
-
if not isinstance(self.dataset, sidpy.Dataset):
|
|
909
|
-
raise TypeError('dataset or first item inhas to be a sidpy dataset')
|
|
910
|
-
self.spec_dim = ft.get_dimensions_by_type('spectral', self.dataset)
|
|
911
|
-
if len(self.spec_dim) != 1:
|
|
912
|
-
raise TypeError('We need exactly one SPECTRAL dimension')
|
|
913
|
-
self.spec_dim = self.spec_dim[0]
|
|
914
|
-
#self.energy_scale = self.dataset._axes[self.spec_dim]
|
|
915
207
|
|
|
916
|
-
self.
|
|
917
|
-
|
|
918
|
-
self.
|
|
919
|
-
self.
|
|
920
|
-
self.
|
|
921
|
-
self.
|
|
922
|
-
|
|
923
|
-
self.
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
with plt.ioff():
|
|
928
|
-
self.fig = plt.figure()
|
|
929
|
-
self.fig.canvas.toolbar_position = 'right'
|
|
930
|
-
self.fig.canvas.toolbar_visible = True
|
|
931
|
-
self.key = list(self.datasets.keys())[0]
|
|
932
|
-
self.set_dataset()
|
|
933
|
-
self.set_action()
|
|
934
|
-
self.y_scale = 1.0
|
|
935
|
-
self.change_y_scale = 1.0
|
|
936
|
-
self.plot(scale=False)
|
|
937
|
-
self.selector = matplotlib.widgets.SpanSelector(self.fig.gca(), self.line_select_callback,
|
|
938
|
-
direction="horizontal",
|
|
939
|
-
interactive=True,
|
|
940
|
-
props=dict(facecolor='blue', alpha=0.2))
|
|
941
|
-
self.start_cursor = ipywidgets.FloatText(value=0, description='Start:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px'))
|
|
942
|
-
self.end_cursor = ipywidgets.FloatText(value=0, description='End:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px'))
|
|
943
|
-
self.panel = ipywidgets.VBox([ipywidgets.HBox([ipywidgets.Label('',layout=ipywidgets.Layout(width='100px')), ipywidgets.Label('Cursor:'),
|
|
944
|
-
self.start_cursor,ipywidgets.Label('eV'),
|
|
945
|
-
self.end_cursor, ipywidgets.Label('eV')]),
|
|
946
|
-
self.fig.canvas])
|
|
208
|
+
self.set_dataset(key)
|
|
209
|
+
|
|
210
|
+
self.periodic_table = eels_dialog_utilities.PeriodicTableWidget(self.energy_scale)
|
|
211
|
+
self.elements_cancel_button = ipywidgets.Button(description='Cancel')
|
|
212
|
+
self.elements_select_button = ipywidgets.Button(description='Select')
|
|
213
|
+
self.elements_auto_button = ipywidgets.Button(description='Auto ID')
|
|
214
|
+
|
|
215
|
+
self.periodic_table_panel = ipywidgets.VBox([self.periodic_table.periodic_table,
|
|
216
|
+
ipywidgets.HBox([self.elements_cancel_button, self.elements_auto_button, self.elements_select_button])])
|
|
217
|
+
|
|
947
218
|
|
|
948
219
|
self.app_layout = ipywidgets.AppLayout(
|
|
949
220
|
left_sidebar=self.sidebar,
|
|
950
|
-
center=self.panel,
|
|
221
|
+
center=self.view.panel,
|
|
951
222
|
footer=None,#message_bar,
|
|
952
223
|
pane_heights=[0, 10, 0],
|
|
953
224
|
pane_widths=[4, 10, 0],
|
|
954
225
|
)
|
|
226
|
+
self.set_action()
|
|
955
227
|
IPython.display.display(self.app_layout)
|
|
228
|
+
|
|
956
229
|
|
|
957
230
|
def line_select_callback(self, x_min, x_max):
|
|
958
231
|
self.start_cursor.value = np.round(x_min,3)
|
|
959
232
|
self.end_cursor.value = np.round(x_max, 3)
|
|
233
|
+
|
|
960
234
|
self.start_channel = np.searchsorted(self.datasets[self.key].energy_loss, self.start_cursor.value)
|
|
961
235
|
self.end_channel = np.searchsorted(self.datasets[self.key].energy_loss, self.end_cursor.value)
|
|
236
|
+
|
|
962
237
|
|
|
963
238
|
def plot(self, scale=True):
|
|
239
|
+
self.view.change_y_scale = self.change_y_scale
|
|
240
|
+
self.view.y_scale = self.y_scale
|
|
241
|
+
self.energy_scale = self.dataset.energy_loss.values
|
|
964
242
|
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
ax.plot(self.energy_scale, self.datasets[self.key]*self.y_scale, label=self.datasets[self.key].title)
|
|
970
|
-
|
|
971
|
-
ax.set_xlabel(self.datasets[self.key].labels[0])
|
|
972
|
-
ax.set_ylabel(self.datasets[self.key].data_descriptor)
|
|
973
|
-
ax.ticklabel_format(style='sci', scilimits=(-2, 3))
|
|
974
|
-
if scale:
|
|
975
|
-
ax.set_ylim(np.array(ylim)*self.change_y_scale)
|
|
976
|
-
self.change_y_scale = 1.0
|
|
977
|
-
if self.y_scale != 1.:
|
|
978
|
-
ax.set_ylabel('scattering probability (ppm/eV)')
|
|
979
|
-
self.selector = matplotlib.widgets.SpanSelector(self.fig.gca(), self.line_select_callback,
|
|
980
|
-
direction="horizontal",
|
|
981
|
-
interactive=True,
|
|
982
|
-
props=dict(facecolor='blue', alpha=0.2))
|
|
983
|
-
|
|
243
|
+
if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE:
|
|
244
|
+
spectrum = self.view.get_spectrum()
|
|
245
|
+
else:
|
|
246
|
+
spectrum = self.dataset
|
|
984
247
|
if len(self.model) > 1:
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
248
|
+
additional_spectra = {'model': self.model,
|
|
249
|
+
'difference': spectrum-self.model}
|
|
250
|
+
else:
|
|
251
|
+
additional_spectra = None
|
|
252
|
+
self.view.plot(scale=True, additional_spectra=additional_spectra )
|
|
253
|
+
self.change_y_scale = 1.
|
|
254
|
+
|
|
993
255
|
if self.sidebar[12, 2].value:
|
|
994
|
-
|
|
256
|
+
self.show_edges()
|
|
995
257
|
if self.sidebar[0, 0].value:
|
|
996
258
|
self.plot_regions()
|
|
997
|
-
self.
|
|
259
|
+
self.view.figure.canvas.draw_idle()
|
|
998
260
|
|
|
999
261
|
|
|
1000
262
|
def plot_regions(self):
|
|
1001
|
-
axis = self.
|
|
263
|
+
axis = self.view.figure.gca()
|
|
1002
264
|
y_min, y_max = axis.get_ylim()
|
|
1003
265
|
height = y_max - y_min
|
|
1004
266
|
|
|
@@ -1025,7 +287,7 @@ class CompositionWidget(object):
|
|
|
1025
287
|
axis.text(x_min, y_max, f"exclude\n edge {int(key)+1}", verticalalignment='top')
|
|
1026
288
|
|
|
1027
289
|
def show_edges(self):
|
|
1028
|
-
axis = self.
|
|
290
|
+
axis = self.view.figure.gca()
|
|
1029
291
|
x_min, x_max = axis.get_xlim()
|
|
1030
292
|
y_min, y_max = axis.get_ylim()
|
|
1031
293
|
|
|
@@ -1044,7 +306,30 @@ class CompositionWidget(object):
|
|
|
1044
306
|
|
|
1045
307
|
|
|
1046
308
|
|
|
1047
|
-
def set_dataset(self,
|
|
309
|
+
def set_dataset(self, set_key):
|
|
310
|
+
spectrum_list = []
|
|
311
|
+
self.spectrum_keys_list = []
|
|
312
|
+
reference_list =[('None', -1)]
|
|
313
|
+
|
|
314
|
+
for index, key in enumerate(self.datasets.keys()):
|
|
315
|
+
if 'Reference' not in key:
|
|
316
|
+
if 'SPECTR' in self.datasets[key].data_type.name:
|
|
317
|
+
spectrum_list.append((f'{key}: {self.datasets[key].title}', index))
|
|
318
|
+
self.spectrum_keys_list.append(key)
|
|
319
|
+
reference_list.append((f'{key}: {self.datasets[key].title}', index))
|
|
320
|
+
|
|
321
|
+
if set_key in self.spectrum_keys_list:
|
|
322
|
+
self.key = set_key
|
|
323
|
+
else:
|
|
324
|
+
self.key = self.spectrum_keys_list[-1]
|
|
325
|
+
self.dataset = self.datasets[self.key]
|
|
326
|
+
|
|
327
|
+
spec_dim = self.dataset.get_dimensions_by_type(sidpy.DimensionType.SPECTRAL)
|
|
328
|
+
self.spec_dim = self.dataset._axes[spec_dim[0]]
|
|
329
|
+
|
|
330
|
+
self.energy_scale = self.spec_dim.values
|
|
331
|
+
self.dataset.metadata['experiment']['offset'] = self.energy_scale[0]
|
|
332
|
+
self.dataset.metadata['experiment']['dispersion'] = self.energy_scale[1] - self.energy_scale[0]
|
|
1048
333
|
if 'edges' not in self.dataset.metadata or self.dataset.metadata['edges'] == {}:
|
|
1049
334
|
self.dataset.metadata['edges'] = {'0': {}, 'model': {}, 'use_low_loss': False}
|
|
1050
335
|
|
|
@@ -1073,6 +358,13 @@ class CompositionWidget(object):
|
|
|
1073
358
|
bin_x = self.dataset.metadata['experiment']['SI_bin_x']
|
|
1074
359
|
bin_y = self.dataset.metadata['experiment']['SI_bin_y']
|
|
1075
360
|
# self.dataset.view.set_bin([bin_x, bin_y])
|
|
361
|
+
if self.dataset.data_type.name =='SPECTRAL_IMAGE':
|
|
362
|
+
self.view = eels_dialog_utilities.SIPlot(self.dataset)
|
|
363
|
+
else:
|
|
364
|
+
self.view = eels_dialog_utilities.SpectrumPlot(self.dataset)
|
|
365
|
+
self.y_scale = 1.0
|
|
366
|
+
self.change_y_scale = 1.0
|
|
367
|
+
|
|
1076
368
|
self.update()
|
|
1077
369
|
|
|
1078
370
|
def update_element(self, z=0, index=-1):
|
|
@@ -1131,8 +423,6 @@ class CompositionWidget(object):
|
|
|
1131
423
|
self.edges[str(index)]['areal_density'] = 0.0
|
|
1132
424
|
self.edges[str(index)]['original_onset'] = self.edges[str(index)]['onset']
|
|
1133
425
|
return True
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
426
|
|
|
1137
427
|
def sort_elements(self):
|
|
1138
428
|
onsets = []
|
|
@@ -1159,24 +449,36 @@ class CompositionWidget(object):
|
|
|
1159
449
|
if edge['end_exclude'] > self.energy_scale[-3]:
|
|
1160
450
|
edge['end_exclude'] = self.energy_scale[-3]
|
|
1161
451
|
|
|
1162
|
-
def set_elements(self,
|
|
452
|
+
def set_elements(self, value=0):
|
|
453
|
+
selected_elements = self.periodic_table.get_output()
|
|
454
|
+
edges = self.edges.copy()
|
|
455
|
+
to_delete = []
|
|
456
|
+
old_elements = []
|
|
457
|
+
if len(selected_elements) > 0:
|
|
458
|
+
for key in self.edges:
|
|
459
|
+
if key.isdigit():
|
|
460
|
+
to_delete.append(key)
|
|
461
|
+
old_elements.append(self.edges[key]['element'])
|
|
1163
462
|
|
|
463
|
+
for key in to_delete:
|
|
464
|
+
edges[key] = self.edges[key]
|
|
465
|
+
del self.edges[key]
|
|
466
|
+
|
|
1164
467
|
for index, elem in enumerate(selected_elements):
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
468
|
+
if elem in old_elements:
|
|
469
|
+
self.edges[str(index)] = edges[str(old_elements.index(elem))]
|
|
470
|
+
else:
|
|
471
|
+
self.update_element(elem, index=index)
|
|
472
|
+
self.sort_elements()
|
|
1169
473
|
self.update()
|
|
1170
|
-
|
|
474
|
+
self.set_figure_pane()
|
|
1171
475
|
|
|
1172
|
-
|
|
1173
476
|
def set_element(self, elem):
|
|
1174
477
|
self.update_element(self.sidebar[5, 0].value)
|
|
1175
478
|
# self.sort_elements()
|
|
1176
479
|
self.update()
|
|
1177
480
|
|
|
1178
481
|
def cursor2energy_scale(self, value):
|
|
1179
|
-
|
|
1180
482
|
dispersion = (self.end_cursor.value - self.start_cursor.value) / (self.end_channel - self.start_channel)
|
|
1181
483
|
self.datasets[self.key].energy_loss *= (self.sidebar[3, 0].value/dispersion)
|
|
1182
484
|
self.sidebar[3, 0].value = dispersion
|
|
@@ -1199,38 +501,43 @@ class CompositionWidget(object):
|
|
|
1199
501
|
|
|
1200
502
|
def set_y_scale(self, value):
|
|
1201
503
|
self.change_y_scale = 1/self.y_scale
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
504
|
+
self.y_scale = 1.0
|
|
505
|
+
if self.dataset.metadata['experiment']['flux_ppm'] > 0:
|
|
506
|
+
if self.sidebar[12, 0].value:
|
|
507
|
+
dispersion = self.energy_scale[1] - self.energy_scale[0]
|
|
508
|
+
self.y_scale = 1/self.dataset.metadata['experiment']['flux_ppm'] * dispersion
|
|
1207
509
|
|
|
1208
510
|
self.change_y_scale *= self.y_scale
|
|
1209
511
|
self.update()
|
|
1210
512
|
self.plot()
|
|
513
|
+
|
|
514
|
+
def auto_id(self, value=0):
|
|
515
|
+
found_edges = eels.auto_id_edges(self.dataset)
|
|
516
|
+
if len(found_edges) > 0:
|
|
517
|
+
self.periodic_table.elements_selected = found_edges
|
|
518
|
+
self.periodic_table.update()
|
|
1211
519
|
|
|
1212
520
|
def find_elements(self, value=0):
|
|
1213
521
|
|
|
1214
522
|
if '0' not in self.edges:
|
|
1215
|
-
self.edges['0'] ={}
|
|
1216
|
-
found_edges = eels.auto_id_edges(self.dataset)
|
|
1217
|
-
|
|
1218
|
-
to_delete = []
|
|
1219
|
-
if len(found_edges) >0:
|
|
1220
|
-
for key in self.edges:
|
|
1221
|
-
if key.isdigit():
|
|
1222
|
-
to_delete.append(key)
|
|
1223
|
-
for key in to_delete:
|
|
1224
|
-
del self.edges[key]
|
|
1225
|
-
if len(to_delete) > 0:
|
|
1226
523
|
self.edges['0'] = {}
|
|
524
|
+
# found_edges = eels.auto_id_edges(self.dataset)
|
|
525
|
+
found_edges = {}
|
|
1227
526
|
|
|
1228
527
|
selected_elements = []
|
|
1229
|
-
|
|
1230
|
-
selected_elements.append(key)
|
|
1231
|
-
self.set_elements(selected_elements)
|
|
528
|
+
elements = self.edges.copy()
|
|
1232
529
|
|
|
1233
|
-
self.
|
|
530
|
+
for key in self.edges:
|
|
531
|
+
if key.isdigit():
|
|
532
|
+
if 'element' in self.edges[key]:
|
|
533
|
+
selected_elements.append(self.edges[key]['element'])
|
|
534
|
+
self.periodic_table.elements_selected = selected_elements
|
|
535
|
+
self.periodic_table.update()
|
|
536
|
+
self.app_layout.center = self.periodic_table_panel # self.periodic_table.periodic_table
|
|
537
|
+
|
|
538
|
+
def set_figure_pane(self, value=0):
|
|
539
|
+
|
|
540
|
+
self.app_layout.center = self.view.panel
|
|
1234
541
|
|
|
1235
542
|
def update(self, index=0):
|
|
1236
543
|
|
|
@@ -1242,10 +549,10 @@ class CompositionWidget(object):
|
|
|
1242
549
|
self.sidebar[4,0].value = len(self.sidebar[4,0].options)-2
|
|
1243
550
|
if str(index) not in self.edges:
|
|
1244
551
|
self.edges[str(index)] = {'z': 0, 'element': 'x', 'symmetry': 'K1', 'onset': 0, 'start_exclude': 0, 'end_exclude':0,
|
|
1245
|
-
'areal_density': 0}
|
|
552
|
+
'areal_density': 0, 'chemical_shift':0}
|
|
1246
553
|
if 'z' not in self.edges[str(index)]:
|
|
1247
554
|
self.edges[str(index)] = {'z': 0, 'element': 'x', 'symmetry': 'K1', 'onset': 0, 'start_exclude': 0, 'end_exclude':0,
|
|
1248
|
-
'areal_density': 0}
|
|
555
|
+
'areal_density': 0, 'chemical_shift':0}
|
|
1249
556
|
edge = self.edges[str(index)]
|
|
1250
557
|
|
|
1251
558
|
self.sidebar[5,0].value = edge['z']
|
|
@@ -1289,7 +596,7 @@ class CompositionWidget(object):
|
|
|
1289
596
|
edges = eels.make_cross_sections(self.edges, np.array(self.energy_scale), beam_kv, eff_beta, self.low_loss)
|
|
1290
597
|
|
|
1291
598
|
if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE:
|
|
1292
|
-
spectrum = self.
|
|
599
|
+
spectrum = self.view.get_spectrum()
|
|
1293
600
|
else:
|
|
1294
601
|
spectrum = self.dataset
|
|
1295
602
|
self.edges = eels.fit_edges2(spectrum, self.energy_scale, edges)
|
|
@@ -1307,11 +614,83 @@ class CompositionWidget(object):
|
|
|
1307
614
|
self.model = self.edges['model']['spectrum']
|
|
1308
615
|
self.update()
|
|
1309
616
|
self.plot()
|
|
617
|
+
|
|
618
|
+
def do_all_button_click(self, value=0):
|
|
619
|
+
if self.sidebar[13,0].value==False:
|
|
620
|
+
return
|
|
621
|
+
|
|
622
|
+
if self.dataset.data_type.name != 'SPECTRAL_IMAGE':
|
|
623
|
+
self.do_fit()
|
|
624
|
+
return
|
|
625
|
+
|
|
626
|
+
if 'experiment' in self.dataset.metadata:
|
|
627
|
+
exp = self.dataset.metadata['experiment']
|
|
628
|
+
if 'convergence_angle' not in exp:
|
|
629
|
+
raise ValueError('need a convergence_angle in experiment of metadata dictionary ')
|
|
630
|
+
alpha = exp['convergence_angle']
|
|
631
|
+
beta = exp['collection_angle']
|
|
632
|
+
beam_kv = exp['acceleration_voltage']
|
|
633
|
+
else:
|
|
634
|
+
raise ValueError('need a experiment parameter in metadata dictionary')
|
|
635
|
+
|
|
636
|
+
eff_beta = eels.effective_collection_angle(self.energy_scale, alpha, beta, beam_kv)
|
|
637
|
+
|
|
638
|
+
self.low_loss = None
|
|
639
|
+
if self.sidebar[12, 1].value:
|
|
640
|
+
for key in self.datasets.keys():
|
|
641
|
+
if key != self.key:
|
|
642
|
+
if isinstance(self.datasets[key], sidpy.Dataset):
|
|
643
|
+
if 'SPECTR' in self.datasets[key].data_type.name:
|
|
644
|
+
if self.datasets[key].energy_loss[0] < 0:
|
|
645
|
+
self.low_loss = self.datasets[key]/self.datasets[key].sum()
|
|
646
|
+
|
|
647
|
+
edges = eels.make_cross_sections(self.edges, np.array(self.energy_scale), beam_kv, eff_beta, self.low_loss)
|
|
648
|
+
|
|
649
|
+
view = self.view
|
|
650
|
+
bin_x = view.bin_x
|
|
651
|
+
bin_y = view.bin_y
|
|
652
|
+
|
|
653
|
+
start_x = view.x
|
|
654
|
+
start_y = view.y
|
|
655
|
+
|
|
656
|
+
number_of_edges = 0
|
|
657
|
+
for key in self.edges:
|
|
658
|
+
if key.isdigit():
|
|
659
|
+
number_of_edges += 1
|
|
660
|
+
|
|
661
|
+
results = np.zeros([int(self.dataset.shape[0]/bin_x), int(self.dataset.shape[1]/bin_y), number_of_edges])
|
|
662
|
+
total_spec = int(self.dataset.shape[0]/bin_x)*int(self.dataset.shape[1]/bin_y)
|
|
663
|
+
self.sidebar[13,1].max = total_spec
|
|
664
|
+
#self.ui.progress.setMaximum(total_spec)
|
|
665
|
+
#self.ui.progress.setValue(0)
|
|
666
|
+
ind = 0
|
|
667
|
+
for x in range(int(self.dataset.shape[0]/bin_x)):
|
|
668
|
+
for y in range(int(self.dataset.shape[1]/bin_y)):
|
|
669
|
+
ind += 1
|
|
670
|
+
self.sidebar[13,1].value = ind
|
|
671
|
+
view.x = x*bin_x
|
|
672
|
+
view.y = y*bin_y
|
|
673
|
+
spectrum = view.get_spectrum()
|
|
674
|
+
with warnings.catch_warnings():
|
|
675
|
+
warnings.simplefilter("ignore")
|
|
676
|
+
edges = eels.fit_edges2(spectrum, self.energy_scale, edges)
|
|
677
|
+
for key, edge in edges.items():
|
|
678
|
+
if key.isdigit():
|
|
679
|
+
# element.append(edge['element'])
|
|
680
|
+
results[x, y, int(key)] = edge['areal_density']
|
|
681
|
+
edges['spectrum_image_quantification'] = results
|
|
682
|
+
self.sidebar[13,1].value = total_spec
|
|
683
|
+
view.x = start_x
|
|
684
|
+
view.y = start_y
|
|
685
|
+
self.sidebar[13,0].value = False
|
|
686
|
+
|
|
1310
687
|
|
|
1311
688
|
def modify_onset(self, value=-1):
|
|
1312
689
|
edge_index = self.sidebar[4, 0].value
|
|
1313
690
|
edge = self.edges[str(edge_index)]
|
|
1314
691
|
edge['onset'] = self.sidebar[7,0].value
|
|
692
|
+
if 'original_onset' not in edge:
|
|
693
|
+
edge['original_onset'] = edge['onset']
|
|
1315
694
|
edge['chemical_shift'] = edge['onset'] - edge['original_onset']
|
|
1316
695
|
self.update()
|
|
1317
696
|
|
|
@@ -1340,7 +719,9 @@ class CompositionWidget(object):
|
|
|
1340
719
|
self.model = self.edges['model']['background']
|
|
1341
720
|
for key in self.edges:
|
|
1342
721
|
if key.isdigit():
|
|
1343
|
-
|
|
722
|
+
if 'data' in self.edges[key]:
|
|
723
|
+
|
|
724
|
+
self.model = self.model + self.edges[key]['areal_density'] * self.edges[key]['data']
|
|
1344
725
|
self.plot()
|
|
1345
726
|
|
|
1346
727
|
def set_action(self):
|
|
@@ -1348,7 +729,7 @@ class CompositionWidget(object):
|
|
|
1348
729
|
self.sidebar[2, 0].observe(self.set_fit_area, names='value')
|
|
1349
730
|
|
|
1350
731
|
self.sidebar[3, 0].on_click(self.find_elements)
|
|
1351
|
-
self.sidebar[4, 0].observe(self.update)
|
|
732
|
+
self.sidebar[4, 0].observe(self.update, names='value')
|
|
1352
733
|
self.sidebar[5, 0].observe(self.set_element, names='value')
|
|
1353
734
|
|
|
1354
735
|
self.sidebar[7, 0].observe(self.modify_onset, names='value')
|
|
@@ -1357,7 +738,11 @@ class CompositionWidget(object):
|
|
|
1357
738
|
self.sidebar[10, 0].observe(self.modify_areal_density, names='value')
|
|
1358
739
|
|
|
1359
740
|
self.sidebar[11, 0].on_click(self.do_fit)
|
|
1360
|
-
self.sidebar[12, 2].observe(self.plot)
|
|
1361
|
-
self.sidebar[0, 0].observe(self.plot)
|
|
1362
|
-
|
|
1363
|
-
self.sidebar[
|
|
741
|
+
self.sidebar[12, 2].observe(self.plot, names='value')
|
|
742
|
+
self.sidebar[0, 0].observe(self.plot, names='value')
|
|
743
|
+
self.sidebar[12,0].observe(self.set_y_scale, names='value')
|
|
744
|
+
self.sidebar[13,0].observe(self.do_all_button_click, names='value')
|
|
745
|
+
|
|
746
|
+
self.elements_cancel_button.on_click(self.set_figure_pane)
|
|
747
|
+
self.elements_auto_button.on_click(self.auto_id)
|
|
748
|
+
self.elements_select_button.on_click(self.set_elements)
|