pyTEMlib 0.2024.9.0__py3-none-any.whl → 0.2025.2.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.

@@ -0,0 +1,1120 @@
1
+ from typing import Any
2
+
3
+ import numpy as np
4
+ import os
5
+ import sys
6
+ import ipywidgets
7
+ from IPython.display import display
8
+ import plotly.graph_objects as go
9
+
10
+ import sidpy
11
+ # from pyTEMlib.microscope import microscope
12
+ from pyTEMlib import file_tools
13
+ from pyTEMlib import eels_tools
14
+ from pyTEMlib.core_loss_widget import get_core_loss_sidebar, CoreLoss
15
+ from pyTEMlib.low_loss_widget import get_low_loss_sidebar, LowLoss
16
+
17
+ def get_image_sidebar() -> Any:
18
+ side_bar = ipywidgets.GridspecLayout(14, 3, width='auto', grid_gap="0px")
19
+
20
+ side_bar[0, :2] = ipywidgets.Dropdown(
21
+ options=[('None', 0)],
22
+ value=0,
23
+ description='Main Dataset:',
24
+ disabled=False)
25
+ row = 1
26
+ side_bar[row, :3] = ipywidgets.Button(description='Image Scale',
27
+ layout=ipywidgets.Layout(width='auto', grid_area='header'),
28
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
29
+ row += 1
30
+ side_bar[row, :2] = ipywidgets.FloatText(value=7.5, description='x dim:', disabled=False, color='black',
31
+ layout=ipywidgets.Layout(width='200px'))
32
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="nm", layout=ipywidgets.Layout(width='20px'))
33
+ row += 1
34
+ side_bar[row, :2] = ipywidgets.FloatText(value=7.5, description='y dim:', disabled=False, color='black',
35
+ layout=ipywidgets.Layout(width='200px'))
36
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="nm", layout=ipywidgets.Layout(width='20px'))
37
+ row += 1
38
+
39
+ side_bar[row, :3] = ipywidgets.Button(description='Microscope',
40
+ layout=ipywidgets.Layout(width='auto', grid_area='header'),
41
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
42
+ row += 1
43
+ side_bar[row, :2] = ipywidgets.FloatText(value=-1, description='Conv.Angle:', disabled=False, color='black',
44
+ layout=ipywidgets.Layout(width='200px'))
45
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="mrad", layout=ipywidgets.Layout(width='100px'))
46
+ row += 1
47
+ side_bar[row, :2] = ipywidgets.FloatText(value=-0.1, description='Coll.Angle:', disabled=False, color='black',
48
+ layout=ipywidgets.Layout(width='200px'))
49
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="mrad", layout=ipywidgets.Layout(width='100px'))
50
+ row += 1
51
+ side_bar[row, :2] = ipywidgets.FloatText(value=.1, description='Acc Voltage:', disabled=False, color='black',
52
+ layout=ipywidgets.Layout(width='200px'))
53
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="keV", layout=ipywidgets.Layout(width='100px'))
54
+
55
+ row += 1
56
+ side_bar[row, :3] = ipywidgets.Button(description='Calibration',
57
+ layout=ipywidgets.Layout(width='auto', grid_area='header'),
58
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
59
+ row += 1
60
+ side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Pixel_Time:', disabled=False, color='black',
61
+ layout=ipywidgets.Layout(width='200px'))
62
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="μs", layout=ipywidgets.Layout(width='100px'))
63
+ row += 1
64
+ side_bar[row, :2] = ipywidgets.FloatText(value=7.5, description='Screen Curr:', disabled=False, color='black',
65
+ layout=ipywidgets.Layout(width='200px'))
66
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="pA", layout=ipywidgets.Layout(width='50px'))
67
+ row += 1
68
+
69
+ side_bar[row, 0] = ipywidgets.Button(description='FFT', disabled=True,
70
+ layout=ipywidgets.Layout(width='auto'),
71
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
72
+ side_bar[row, 1] = ipywidgets.Button(description='LR-Decon', disabled=True,
73
+ layout=ipywidgets.Layout(width='auto'),
74
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
75
+ side_bar[row, 2] = ipywidgets.Button(description='Find atoms', disabled=True,
76
+ layout=ipywidgets.Layout(width='auto'),
77
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
78
+
79
+ row += 1
80
+ side_bar[row, :3] = ipywidgets.Button(description='Image Stack',
81
+ layout=ipywidgets.Layout(width='auto', grid_area='header'),
82
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
83
+ row += 1
84
+ side_bar[row, 0] = ipywidgets.Button(description='Rig Reg.', disabled=True,
85
+ layout=ipywidgets.Layout(width='auto'),
86
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
87
+ side_bar[row, 1] = ipywidgets.Button(description='Demon', disabled=True,
88
+ layout=ipywidgets.Layout(width='auto'),
89
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
90
+ side_bar[row, 2] = ipywidgets.Button(description='Sum', disabled=True,
91
+ layout=ipywidgets.Layout(width='auto'),
92
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
93
+
94
+ side_bar[-2, 0].layout.display = "none"
95
+ for i in range(3):
96
+ side_bar[-1, i].layout.display = "none"
97
+ return side_bar
98
+
99
+
100
+ def get_info_sidebar() -> Any:
101
+ side_bar = ipywidgets.GridspecLayout(18, 3, width='auto', grid_gap="0px")
102
+
103
+ side_bar[0, :2] = ipywidgets.Dropdown(
104
+ options=[('None', 0)],
105
+ value=0,
106
+ description='Main Dataset:',
107
+ disabled=False)
108
+
109
+ row = 1
110
+ side_bar[row, :3] = ipywidgets.Button(description='Energy Scale',
111
+ layout=ipywidgets.Layout(width='auto', grid_area='header'),
112
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
113
+ row += 1
114
+ side_bar[row, :2] = ipywidgets.FloatText(value=7.5, description='Offset:', disabled=False, color='black',
115
+ layout=ipywidgets.Layout(width='200px'))
116
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='20px'))
117
+ row += 1
118
+ side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Dispersion:', disabled=False, color='black',
119
+ layout=ipywidgets.Layout(width='200px'))
120
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='20px'))
121
+ row += 1
122
+ side_bar[row, :3] = ipywidgets.Button(description='Microscope',
123
+ layout=ipywidgets.Layout(width='auto', grid_area='header'),
124
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
125
+ row += 1
126
+ side_bar[row, :2] = ipywidgets.FloatText(value=-1, description='Conv.Angle:', disabled=False, color='black',
127
+ layout=ipywidgets.Layout(width='200px'))
128
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="mrad", layout=ipywidgets.Layout(width='100px'))
129
+ row += 1
130
+ side_bar[row, :2] = ipywidgets.FloatText(value=-0.1, description='Coll.Angle:', disabled=False, color='black',
131
+ layout=ipywidgets.Layout(width='200px'))
132
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="mrad", layout=ipywidgets.Layout(width='100px'))
133
+ row += 1
134
+ side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Acc Voltage:', disabled=False, color='black',
135
+ layout=ipywidgets.Layout(width='200px'))
136
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="keV", layout=ipywidgets.Layout(width='100px'))
137
+
138
+ row += 1
139
+ side_bar[row, :3] = ipywidgets.Button(description='Calibration',
140
+ layout=ipywidgets.Layout(width='auto', grid_area='header'),
141
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
142
+ row += 1
143
+ side_bar[row, :2] = ipywidgets.Dropdown(
144
+ options=[('None', 0)],
145
+ value=0,
146
+ description='Reference:',
147
+ disabled=False)
148
+ side_bar[row, 2] = ipywidgets.ToggleButton(description='Probability',
149
+ disabled=False,
150
+ button_style='', # 'success', 'info', 'warning', 'danger' or ''
151
+ tooltip='Changes y-axis to probability if flux is given',
152
+ layout=ipywidgets.Layout(width='100px'))
153
+ row += 1
154
+ side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Exp_Time:', disabled=False, color='black',
155
+ layout=ipywidgets.Layout(width='200px'))
156
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="s", layout=ipywidgets.Layout(width='100px'))
157
+ row += 1
158
+ side_bar[row, :2] = ipywidgets.FloatText(value=7.5, description='Flux:', disabled=False, color='black',
159
+ layout=ipywidgets.Layout(width='200px'))
160
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="Mcounts", layout=ipywidgets.Layout(width='50px'))
161
+ row += 1
162
+ side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Conversion:', disabled=False, color='black',
163
+ layout=ipywidgets.Layout(width='200px'))
164
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="e⁻/counts", layout=ipywidgets.Layout(width='100px'))
165
+ row += 1
166
+ side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Current:', disabled=False, color='black',
167
+ layout=ipywidgets.Layout(width='200px'))
168
+ side_bar[row, 2] = ipywidgets.widgets.Label(value="pA", layout=ipywidgets.Layout(width='100px'))
169
+
170
+ row += 1
171
+ side_bar[row, 0] = ipywidgets.Button(description='Get Shift', disabled=True,
172
+ layout=ipywidgets.Layout(width='auto'),
173
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
174
+ side_bar[row, 1] = ipywidgets.Button(description='Shift Spec', disabled=True,
175
+ layout=ipywidgets.Layout(width='auto'),
176
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
177
+ """
178
+ side_bar[row, 2] = ipywidgets.Button(description='Res.Fct.', disabled=True,
179
+ layout=ipywidgets.Layout(width='auto'),
180
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
181
+ """
182
+
183
+ row += 1
184
+ side_bar[row, :3] = ipywidgets.Button(description='Spectrum Image',
185
+ layout=ipywidgets.Layout(width='auto', grid_area='header'),
186
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
187
+
188
+ row += 1
189
+ side_bar[row, :2] = ipywidgets.IntText(value=1, description='bin X:', disabled=False, color='black',
190
+ layout=ipywidgets.Layout(width='200px'))
191
+ row += 1
192
+ side_bar[row, :2] = ipywidgets.IntText(value=1, description='bin Y:', disabled=False, color='black',
193
+ layout=ipywidgets.Layout(width='200px'))
194
+
195
+ for i in range(15, 18):
196
+ side_bar[i, 0].layout.display = "none"
197
+ return side_bar
198
+
199
+
200
+
201
+ def get_file_widget_ui():
202
+ side_bar = ipywidgets.GridspecLayout(7, 3, height='500px', width='auto', grid_gap="0px")
203
+ row = 0
204
+ side_bar[row, :3] = ipywidgets.Dropdown(options=['None'], value='None', description='directory:', disabled=False,
205
+ button_style='', layout=ipywidgets.Layout(width='auto', grid_area='header'))
206
+ row += 1
207
+ side_bar[row, :3] = ipywidgets.Select(options=['.'], value='.', description='Select file:', disabled=False,
208
+ rows=10, layout=ipywidgets.Layout(width='auto'))
209
+ row += 1
210
+ side_bar[row, 0] = ipywidgets.Button(description='Select Main',
211
+ layout=ipywidgets.Layout(width='100px'),
212
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
213
+ side_bar[row, 1] = ipywidgets.Button(description='Add',
214
+ layout=ipywidgets.Layout(width='50px'),
215
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
216
+ side_bar[row, 2] = ipywidgets.Dropdown(options=['None'], value='None', description='loaded:', disabled=False,
217
+ button_style='')
218
+
219
+ row += 1
220
+ side_bar[row, :3] = ipywidgets.Select(options=['None'], value='None', description='Spectral:',
221
+ disabled=False, rows=3, layout=ipywidgets.Layout(width='auto'))
222
+ row += 1
223
+ side_bar[row, :3] = ipywidgets.Select(options=['Sum'], value='Sum', description='Images:',
224
+ disabled=False, rows=3, layout=ipywidgets.Layout(width='auto'))
225
+ row += 1
226
+ side_bar[row, :3] = ipywidgets.Select(options=['None'], value='None', description='Survey:',
227
+ disabled=False, rows=2, layout=ipywidgets.Layout(width='auto'))
228
+ for i in range(3, 6):
229
+ side_bar[i, 0].layout.display = "none"
230
+
231
+ row += 1
232
+ side_bar[row, 0] = ipywidgets.Button(description='Save',
233
+ layout=ipywidgets.Layout(width='100px'),
234
+ style=ipywidgets.ButtonStyle(button_color='lightblue'))
235
+ side_bar[row, 1] = ipywidgets.Text(
236
+ value='Test.hf5',
237
+ placeholder='Type something',
238
+ description='File:',
239
+ disabled=False
240
+ )
241
+ return side_bar
242
+
243
+ out = ipywidgets.Output()
244
+
245
+ class EELSBaseWidget(object):
246
+
247
+ def __init__(self, datasets=None, sidebar=None, tab_title=None):
248
+
249
+ self.datasets = datasets
250
+ self.dataset = None
251
+ self.save_path = False
252
+ self.dir_dictionary = {}
253
+ self.dir_list = ['.', '..']
254
+ self.display_list = ['.', '..']
255
+ self.dataset_list = ['None']
256
+ self.image_list = ['Sum']
257
+ self.added_spectra = {}
258
+ self.dir_name = file_tools.get_last_path()
259
+
260
+ self.key = None
261
+ self.new_info = False
262
+ self.image = 'Sum'
263
+ if 'google.colab' in sys.modules:
264
+ self.google = True
265
+ else:
266
+ self.google = False
267
+ # self.google = True
268
+
269
+ self.save_path = True
270
+
271
+ if not os.path.isdir(self.dir_name):
272
+ self.dir_name = '.'
273
+
274
+ self.get_directory(self.dir_name)
275
+ self.dir_list = ['.']
276
+ self.extensions = '*'
277
+ self.file_name = ''
278
+ self.datasets = {}
279
+ self.dataset = None
280
+ self.sd0 = 0
281
+ self.sds = 0
282
+
283
+ self.bin_x = 0
284
+ self.bin_y = 0
285
+
286
+ self.start_channel = -1
287
+ self.end_channel = -2
288
+
289
+ self.file_bar = get_file_widget_ui()
290
+ children = [self.file_bar]
291
+ titles = ['File']
292
+ if isinstance(sidebar, dict):
293
+ for sidebar_key, sidebar_gui in sidebar.items():
294
+ children.append(sidebar_gui)
295
+ titles.append(sidebar_key)
296
+ elif not isinstance(sidebar, list):
297
+ children = [self.file_bar, sidebar]
298
+ titles = ['File', 'Info']
299
+ if sidebar is None:
300
+ children = [self.file_bar]
301
+ titles = ['File']
302
+
303
+ if self.google:
304
+ self.buttons = []
305
+ for i in range(len(children)):
306
+ self.buttons.append(ipywidgets.Button(description=titles[i],
307
+ disabled=False,
308
+ button_style='', # 'success', 'info', 'warning', 'danger' or ''
309
+ layout=ipywidgets.Layout(width='800px')))
310
+
311
+
312
+ self.tab_buttons = ipywidgets.ToggleButtons(options=titles, description='', disabled=False,
313
+ layout=ipywidgets.Layout(width='auto'),
314
+ style={"button_width": "auto"})
315
+ tab = ipywidgets.VBox([self.tab_buttons, self.file_bar])
316
+ self.children = children
317
+
318
+ else:
319
+ tab = ipywidgets.Tab()
320
+ tab.children = children
321
+ tab.titles = titles
322
+
323
+
324
+
325
+ self.spectrum_plot = go.FigureWidget()
326
+ self.spectrum_plot.update_xaxes(showgrid=True, zeroline=True, showticklabels=True,
327
+ showspikes=True, spikemode='across', spikesnap='cursor', showline=False, spikedash='solid')
328
+ self.spectrum_plot['layout'].update(height=500)
329
+ self.image_plot = go.FigureWidget()
330
+ self.image_plot['layout'].update(height=500,
331
+ width=500,
332
+ autosize=True,
333
+ xaxis_showgrid=False,
334
+ yaxis_showgrid=False,
335
+ yaxis = dict(scaleanchor = 'x', autorange = "reversed"),
336
+ plot_bgcolor="white")
337
+
338
+ self.tab =tab
339
+ self.canvas_plot = ipywidgets.HBox([self.spectrum_plot])
340
+ self.canvas = ipywidgets.VBox([self.canvas_plot, out])
341
+
342
+ self.start_cursor = ipywidgets.FloatText(value=0, description='Start:', disabled=False, color='black',
343
+ layout=ipywidgets.Layout(width='200px'))
344
+ self.end_cursor = ipywidgets.FloatText(value=0, description='End:', disabled=False, color='black',
345
+ layout=ipywidgets.Layout(width='200px'))
346
+ self.statusbar = ipywidgets.Text(value='Starting',
347
+ placeholder='Type something',
348
+ description='Status:',
349
+ disabled=True,
350
+ layout=ipywidgets.Layout(width='100%'))
351
+ self.panel = ipywidgets.VBox([ipywidgets.HBox([ipywidgets.Label('', layout=ipywidgets.Layout(width='100px')),
352
+ ipywidgets.Label('Cursor:'),
353
+ self.start_cursor, ipywidgets.Label('eV'),
354
+ self.end_cursor, ipywidgets.Label('eV')]),
355
+ self.canvas,
356
+ self.statusbar])
357
+
358
+ self.app_layout = ipywidgets.AppLayout(
359
+ left_sidebar=tab,
360
+ center=self.panel,
361
+ footer=None, # message_bar,
362
+ pane_heights=[0, 10, 0],
363
+ pane_widths=[4, 10, 0],
364
+ )
365
+ # self.set_dataset()
366
+ self.change_y_scale = 1.0
367
+ self.x = 0
368
+ self.y = 0
369
+ self.bin_x = 1
370
+ self.bin_y = 1
371
+ self.count = 0
372
+ display(self.app_layout)
373
+
374
+ self.select_files = self.file_bar[1, 0]
375
+ self.path_choice = self.file_bar[0, 0]
376
+ self.set_file_options()
377
+ select_button = self.file_bar[2, 0]
378
+ add_button = self.file_bar[2, 1]
379
+ self.loaded_datasets = self.file_bar[2, 2]
380
+ self.select_files.observe(self.get_file_name, names='value')
381
+ self.path_choice.observe(self.set_dir, names='value')
382
+
383
+ select_button.on_click(self.select_main)
384
+ add_button.on_click(self.add_dataset)
385
+ self.loaded_datasets.observe(self.select_dataset, names='value')
386
+ self.file_bar[4, 0].observe(self.set_image, names='value')
387
+ self.file_bar[5, 0].observe(self.set_survey_image, names='value')
388
+
389
+ self.file_bar[6, 0].observe(self.save_datasets)
390
+
391
+ def save_datasets(self, value=0):
392
+ import warnings
393
+ file_name = self.file_bar[6, 1].value
394
+ path = self.path_choice.options[0]
395
+ with warnings.catch_warnings():
396
+ warnings.simplefilter("ignore")
397
+ h5_group = file_tools.save_dataset(self.datasets, os.path.join(path, file_name))
398
+ h5_group.file.close()
399
+ self.status_message(' File saved')
400
+
401
+ def status_message(self, out: str):
402
+ self.statusbar.value = out
403
+
404
+ def set_survey_image(self, key=None):
405
+
406
+ self.datasets['_relationship']['survey_image'] = self.file_bar[5, 0].value
407
+ # ToDo: Find boundaries of scan.
408
+
409
+ def get_image(self):
410
+ if self.file_bar[4, 0].value == 'Sum':
411
+ spec_dim = self.dataset.get_dimensions_by_type(sidpy.DimensionType.SPECTRAL)
412
+ if len(spec_dim) != 1:
413
+ raise ValueError('Only one spectral dimension')
414
+
415
+ channel_dim = self.dataset.get_dimensions_by_type(sidpy.DimensionType.CHANNEL)
416
+
417
+ if len(channel_dim) > 1:
418
+ raise ValueError('Maximal one channel dimension')
419
+
420
+ if len(channel_dim) > 0:
421
+ self.image = self.dataset.mean(axis=(spec_dim[0], channel_dim[0]))
422
+ else:
423
+ self.image = self.dataset.mean(axis=(spec_dim[0]))
424
+ image_key = 'Sum'
425
+ else:
426
+ image_key = self.file_bar[4, 0].value.split(':')[0]
427
+ self.image = self.datasets[image_key]
428
+ self.datasets['_relationship']['image'] = image_key
429
+
430
+ def set_image(self, key=None):
431
+ self.get_image()
432
+ self.plot()
433
+
434
+ def plot(self, scale=True):
435
+
436
+ spec_dims = self.dataset.get_spectral_dims(return_axis=True)
437
+ if len(spec_dims)>0:
438
+ self.energy_scale = spec_dims[0]
439
+ if self.dataset.data_type.name == 'SPECTRUM':
440
+ self.canvas_plot.children = [self.spectrum_plot]
441
+ else:
442
+ self.get_image()
443
+ self.canvas_plot.children = [self.image_plot, self.spectrum_plot]
444
+ self.plot_spectrum_image()
445
+ # self.axis = self.axes[-1]
446
+ self.spectrum = self.get_spectrum()
447
+ self.plot_spectrum()
448
+
449
+ else:
450
+ self.canvas_plot.children = [self.image_plot]
451
+ self.image = self.dataset
452
+ self.plot_image()
453
+
454
+ def plot_image(self, add_annotations=True):
455
+ image_dims = self.dataset.get_image_dims(return_axis=True)
456
+
457
+ if len(self.image_plot.data) == 0:
458
+ self.image_plot.add_trace(go.Heatmap(z=self.image.T))
459
+ else:
460
+ self.image_plot.data[0].z=np.array(self.image).T
461
+ self.image_plot.data[0].x = image_dims[0].values
462
+ self.image_plot.data[0].y = image_dims[1].values
463
+
464
+ self.image_plot.update_layout(xaxis_title = f"{image_dims[0].quantity} ({image_dims[0].units})",
465
+ yaxis_title = f"{image_dims[1].quantity} ({image_dims[1].units})")
466
+
467
+ if 'annotations' in self.dataset.metadata and add_annotations:
468
+ annotations = self.dataset.metadata['annotations']
469
+ for key in annotations:
470
+ if annotations[key]['type'] == 'spectral_image':
471
+ pos, w, h = annotations[key]['position'], annotations[key]['width'], annotations[key]['height']
472
+ self.image_plot.add_trace(go.Scatter(x= [pos[0], pos[0], pos[0]+w, pos[0]+w, pos[0]], y = [pos[1], pos[1]+h, pos[1]+h, pos[1], pos[1]], mode='lines'))
473
+ self.image_plot.add_trace(go.Scatter(x= [pos[0]], y = [pos[1]], mode='text', text=['spectrum image'],
474
+ textfont=dict(color="red"),
475
+ textposition="top right"))
476
+
477
+ elif annotations[key]['type'] == 'text':
478
+ self.image_plot.add_trace(go.Scatter(y=[annotations[key]['position'][0]], x=[annotations[key]['position'][1]],
479
+ text=[annotations[key]['label']]))
480
+ elif annotations[key]['type'] == 'circle':
481
+ [x, y] = annotations[key]['position']
482
+ r = annotations[key]['radius']
483
+ self.image_plot.add_shape(type="circle", xref="x", yref="y", x0=x-r, y0 = y-r, x1=x+r, y1=y+r,
484
+ line_color="LightSeaGreen")
485
+
486
+
487
+ def plot_spectrum(self):
488
+ if len(self.spectrum_plot.data) == 0:
489
+ self.spectrum_plot.add_trace(go.Scatter(x=self.energy_scale, y=self.spectrum, mode='markers+lines', marker_size=.1, name=self.dataset.title))
490
+ self.spectrum_plot.data = [self.spectrum_plot.data[0]]
491
+
492
+ self.xlabel = self.spectrum.labels[0]
493
+ self.ylabel = self.datasets[self.key].data_descriptor
494
+ # self.change_y_scale = 1.0
495
+ if self.y_scale != 1.:
496
+ self.ylabel = 'scattering probability (ppm/eV)'
497
+
498
+ self.spectrum_plot.update_layout(xaxis_title=self.xlabel, yaxis_title=self.ylabel)
499
+ self.spectrum_plot.data[0].y=self.spectrum
500
+ self.spectrum_plot.data[0].x=self.energy_scale
501
+ self.spectrum_plot.data[0].on_selection(self.selection_cursor)
502
+
503
+ if self.dataset.data_type.name != 'SPECTRUM':
504
+ self.spectrum_plot.data[0].name = f'spectrum {self.x}, {self.y}'
505
+
506
+ for key in self.added_spectra:
507
+ self.added_spectra[key]
508
+ spectrum = self.get_additional_spectrum(key)
509
+
510
+ self.spectrum_plot.add_trace(go.Scatter(x=self.energy_scale, y=spectrum, mode='markers+lines', marker_size=.1, name=self.added_spectra[key]))
511
+ if key == 'zero_loss':
512
+ self.low_loss.low_loss_tab[14, 1].value = np.round(np.log(self.spectrum.sum()/spectrum.sum()), 4)
513
+
514
+
515
+ def _update(self, ev=None):
516
+ self.get_spectrum()
517
+ self.plot_spectrum()
518
+
519
+ def update_tab_spectra(self):
520
+ pass
521
+
522
+ def get_spectrum(self):
523
+ if self.dataset.data_type.name == 'SPECTRUM':
524
+ self.spectrum = self.dataset.copy()
525
+ else:
526
+ image_dims = self.dataset.get_dimensions_by_type(sidpy.DimensionType.SPATIAL)
527
+ if self.x > self.dataset.shape[image_dims[0]] - self.bin_x:
528
+ self.x = self.dataset.shape[image_dims[0]] - self.bin_x
529
+ if self.y > self.dataset.shape[image_dims[1]] - self.bin_y:
530
+ self.y = self.dataset.shape[image_dims[1]] - self.bin_y
531
+ selection = []
532
+ for dim, axis in self.dataset._axes.items():
533
+ if axis.dimension_type == sidpy.DimensionType.SPATIAL:
534
+ if dim == image_dims[0]:
535
+ selection.append(slice(self.x, self.x + self.bin_x))
536
+ else:
537
+ selection.append(slice(self.y, self.y + self.bin_y))
538
+
539
+ elif axis.dimension_type == sidpy.DimensionType.SPECTRAL:
540
+ selection.append(slice(None))
541
+ elif axis.dimension_type == sidpy.DimensionType.CHANNEL:
542
+ selection.append(slice(None))
543
+ else:
544
+ selection.append(slice(0, 1))
545
+
546
+ self.spectrum = self.dataset[tuple(selection)].mean(axis=tuple(image_dims))
547
+
548
+ self.spectrum *= self.y_scale
549
+ self.spectrum.squeeze()
550
+ self.spectrum.data_type = 'spectrum'
551
+ return self.spectrum
552
+
553
+ @out.capture(clear_output=True)
554
+ def click_callback(self, trace, points, selector):
555
+ if selector.shift:
556
+ self.spectrum_plot.add_trace(go.Scatter(x=self.energy_scale,
557
+ y=self.dataset[points.point_inds[0][1], points.point_inds[0][0]],
558
+ mode='lines',
559
+ name='spectrum'+str(points.point_inds[0])))
560
+ else:
561
+ if selector.ctrl:
562
+ self.spectrum_plot.data =[self.spectrum_plot.data[0]]
563
+
564
+
565
+ self.image_plot.data[1].x = [points.point_inds[0][1]]
566
+ self.image_plot.data[1].y = [points.point_inds[0][0]]
567
+ self.x = points.point_inds[0][1]
568
+ self.y = points.point_inds[0][0]
569
+
570
+ self._update()
571
+
572
+ @out.capture(clear_output=True)
573
+ def selection_fn(self, trace,points,selector):
574
+ if selector.type == 'box':
575
+ xr = np.array(selector.xrange)
576
+ if xr[0]<0:
577
+ xr[0] = 0
578
+ yr = np.array(selector.yrange)
579
+ if yr[0]<1:
580
+ yr[0] = 0
581
+ size_sel = (int(xr[1])-int(xr[0]))*(int(yr[1])-int(yr[0]))
582
+
583
+ self.spectrum_plot.data[0].y= self.dataset[int(xr[0]):int(xr[1]), int(yr[0]):int(yr[1]),:].sum(axis=[0,1]).compute()/ size_sel
584
+ self.spectrum_plot.data[0].name = str(size_sel)+ ' spectra'
585
+ else:
586
+ print(selector)
587
+
588
+ def plot_spectrum_image(self):
589
+ if len(self.image_plot.data) == 0:
590
+ self.image_plot.add_trace(go.Heatmap(z=self.image.T))
591
+ else:
592
+ self.image_plot.data = [self.image_plot.data[0]]
593
+ self.image_plot.data[0].z=np.array(self.image).T
594
+ self.plot_spectrum()
595
+ self.image_plot.data = [self.image_plot.data[0]]
596
+ self.image_plot.add_trace(
597
+ go.Scatter(mode="markers", x=[0], y=[0], marker_symbol=[101],
598
+ marker_color="darkgray",
599
+ marker_line_width=1, marker_size=11, hovertemplate= 'x: %{x}<br>y: %{y}'))
600
+
601
+ self.image_plot.data[0].on_selection(self.selection_fn)
602
+ self.image_plot.data[0].on_click(self.click_callback)
603
+
604
+ @out.capture(clear_output=True)
605
+ def selection_cursor(self, trace, points, selector):
606
+ if selector.type == 'box':
607
+ self.start_cursor.value = np.round(selector.xrange[0], 3)
608
+ self.end_cursor.value = np.round(selector.xrange[1], 3)
609
+
610
+ energy_scale = self.dataset.get_spectral_dims(return_axis=True)[0]
611
+ self.start_channel = np.searchsorted(energy_scale, self.start_cursor.value)
612
+ self.end_channel = np.searchsorted(energy_scale, self.end_cursor.value)
613
+
614
+ def set_dataset(self, key=None):
615
+
616
+ if len(self.datasets) == 0:
617
+ data_set = sidpy.Dataset.from_array([0, 1], name='generic')
618
+ data_set.set_dimension(0, sidpy.Dimension([0, 1], 'energy_loss', units='channel', quantity='generic',
619
+ dimension_type='spectral'))
620
+ data_set.data_type = 'spectrum'
621
+ data_set.metadata = {'experiment': {'convergence_angle': 0,
622
+ 'collection_angle': 0,
623
+ 'acceleration_voltage': 0,
624
+ 'exposure_time': 0}}
625
+ self.datasets = {'Nothing': data_set}
626
+ key = 'Nothing'
627
+
628
+ dataset_key = key
629
+
630
+ self.dataset_list = []
631
+ dataset_keys = []
632
+ for key in self.datasets.keys():
633
+ if isinstance(self.datasets[key], sidpy.Dataset):
634
+ self.dataset_list.append(f'{key}: {self.datasets[key].title}')
635
+ dataset_keys.append(key)
636
+ if dataset_key not in dataset_keys:
637
+ dataset_key = dataset_keys[0]
638
+ self.key = dataset_key
639
+
640
+ self.dataset = self.datasets[self.key]
641
+
642
+ spectral_dims = self.dataset.get_spectral_dims(return_axis=True)
643
+ if len(spectral_dims) >0:
644
+ self.energy_scale = spectral_dims[0]
645
+ self.y_scale = 1.0
646
+ self.change_y_scale = 1.0
647
+ self.x = 0
648
+ self.y = 0
649
+ self.bin_x = 1
650
+ self.bin_y = 1
651
+ self.count = 0
652
+
653
+ self.update_sidebars()
654
+ #self.update_sidebar()
655
+ self.plot()
656
+
657
+ def update_sidebars(self):
658
+ pass
659
+
660
+ def select_main(self, value=0):
661
+ self.sds +=1
662
+ self.datasets = {}
663
+ # self.loaded_datasets.options = self.dataset_list
664
+
665
+ self.datasets = file_tools.open_file(self.file_name)
666
+
667
+ file_tools.save_path(self.file_name)
668
+ self.dataset_list = []
669
+ self.image_list = ['Sum']
670
+ self.survey_list = ['None']
671
+ self.spectral_list = ['None']
672
+ for key in self.datasets.keys():
673
+ if isinstance(self.datasets[key], sidpy.Dataset):
674
+ self.dataset_list.append(f'{key}: {self.datasets[key].title}')
675
+ if 'SPECTR' in self.datasets[key].data_type.name:
676
+ self.spectral_list.append(f'{key}: {self.datasets[key].title}')
677
+ if 'IMAGE' == self.datasets[key].data_type.name:
678
+ if 'survey' in self.datasets[key].title.lower():
679
+ self.survey_list.append(f'{key}: {self.datasets[key].title}')
680
+ else:
681
+ self.image_list.append(f'{key}: {self.datasets[key].title}')
682
+
683
+
684
+ self.key = self.dataset_list[0].split(':')[0]
685
+ self.dataset = self.datasets[self.key]
686
+ if len(self.image_plot.data)>0:
687
+ self.image_plot.data = [self.image_plot.data[0]]
688
+ self.spectrum_plot.data = [self.spectrum_plot.data[0]]
689
+ self.new_info = True
690
+
691
+ self.selected_dataset = self.dataset
692
+ if len(self.image_list) > 0:
693
+ self.file_bar[4, 0].options = self.image_list
694
+ self.file_bar[5, 0].options = self.survey_list
695
+ self.file_bar[4, 0].layout.display = "flex"
696
+ self.file_bar[4, 0].value = self.image_list[0]
697
+ self.file_bar[5, 0].layout.display = "flex"
698
+ self.file_bar[5, 0].value = self.survey_list[0]
699
+
700
+ self.file_bar[3, 0].options = self.dataset_list
701
+ self.loaded_datasets.options = self.dataset_list
702
+ self.loaded_datasets.value = self.dataset_list[0]
703
+ path, filename = os.path.split(self.file_name)
704
+ name, extension = os.path.splitext(filename)
705
+ self.file_bar[6, 1].value = name+'.hf5'
706
+ self.status_message(' New file loaded')
707
+
708
+ def add_dataset(self, value=0):
709
+ key = file_tools.add_dataset_from_file(self.datasets, self.file_name, 'Channel')
710
+ self.dataset_list.append(f'{key}: {self.datasets[key].title}')
711
+ self.loaded_datasets.options = self.dataset_list
712
+ self.loaded_datasets.value = self.dataset_list[-1]
713
+
714
+ if 'SPECTR' in self.datasets[key].data_type.name:
715
+ self.spectral_list.append(f'{key}: {self.datasets[key].title}')
716
+ energy = self.datasets[key].get_spectral_dims(return_axis=True)[0]
717
+ self.spectrum_plot.add_trace(go.Scatter(x=energy, y=self.datasets[key], mode='markers+lines', marker_size=.1, name=key))
718
+ if 'IMAGE' == self.datasets[key].data_type.name:
719
+ if 'survey' in self.datasets[key].title.lower():
720
+ self.survey_list.append(f'{key}: {self.datasets[key].title}')
721
+ self.file_bar[5, 0].options = self.survey_list
722
+ else:
723
+ self.image_list.append(f'{key}: {self.datasets[key].title}')
724
+ self.file_bar[4, 0].options = self.image_list
725
+ self.status_message(' image list file loaded')
726
+
727
+ def get_directory(self, directory='.'):
728
+ self.dir_name = directory
729
+ self.dir_dictionary = {}
730
+ self.dir_list = []
731
+ self.dir_list = ['.', '..'] + os.listdir(directory)
732
+
733
+ def set_dir(self, value=0):
734
+ self.dir_name = self.path_choice.value
735
+ self.select_files.index = 0
736
+ self.set_file_options()
737
+
738
+ def select_dataset(self, value=0):
739
+ key = self.loaded_datasets.value.split(':')[0]
740
+ if key != 'None':
741
+ self.selected_dataset = self.datasets[key]
742
+ self.selected_key = key
743
+ self.key = key
744
+ self.datasets['_relationship'] = {'main_dataset': self.key}
745
+
746
+ self.set_dataset()
747
+
748
+ def set_file_options(self):
749
+ self.dir_name = os.path.abspath(os.path.join(self.dir_name, self.dir_list[self.select_files.index]))
750
+ dir_list = os.listdir(self.dir_name)
751
+ file_dict = file_tools.update_directory_list(self.dir_name)
752
+
753
+ sort = np.argsort(file_dict['directory_list'])
754
+ self.dir_list = ['.', '..']
755
+ self.display_list = ['.', '..']
756
+ for j in sort:
757
+ self.display_list.append(f" * {file_dict['directory_list'][j]}")
758
+ self.dir_list.append(file_dict['directory_list'][j])
759
+
760
+ sort = np.argsort(file_dict['display_file_list'])
761
+
762
+ for i, j in enumerate(sort):
763
+ if '--' in dir_list[j]:
764
+ self.display_list.append(f" {i:3} {file_dict['display_file_list'][j]}")
765
+ else:
766
+ self.display_list.append(f" {i:3} {file_dict['display_file_list'][j]}")
767
+ self.dir_list.append(file_dict['file_list'][j])
768
+
769
+ self.dir_label = os.path.split(self.dir_name)[-1] + ':'
770
+ self.select_files.options = self.display_list
771
+
772
+ path = self.dir_name
773
+ old_path = ' '
774
+ path_list = []
775
+ while path != old_path:
776
+ path_list.append(path)
777
+ old_path = path
778
+ path = os.path.split(path)[0]
779
+ self.path_choice.options = path_list
780
+ self.path_choice.value = path_list[0]
781
+
782
+ def get_file_name(self, b):
783
+
784
+ if os.path.isdir(os.path.join(self.dir_name, self.dir_list[self.select_files.index])):
785
+ self.set_file_options()
786
+
787
+ elif os.path.isfile(os.path.join(self.dir_name, self.dir_list[self.select_files.index])):
788
+ self.file_name = os.path.join(self.dir_name, self.dir_list[self.select_files.index])
789
+
790
+ class EELSWidget(EELSBaseWidget):
791
+ def __init__(self, datasets=None):
792
+ self.lowloss_key = 'None'
793
+ self.coreloss_key = 'None'
794
+ self.info_key = 'None'
795
+ self.tabval = 0
796
+
797
+ sidebar = {'Spec.': get_info_sidebar(),
798
+ 'LowLoss': get_low_loss_sidebar(),
799
+ 'CoreLoss': get_core_loss_sidebar()}
800
+ super().__init__(datasets, sidebar)
801
+ self.info_tab = sidebar['Spec.']
802
+ self.core_loss_tab = sidebar['CoreLoss']
803
+ self.low_loss_tab = sidebar['LowLoss']
804
+ super().set_dataset()
805
+ self.info = Info(self.info_tab, self)
806
+ self.low_loss = LowLoss(self.low_loss_tab, self)
807
+ self.core_loss = CoreLoss(self.core_loss_tab, self)
808
+
809
+ self.set_action()
810
+
811
+ def set_action(self):
812
+ if self.google:
813
+ self.tab_buttons.observe(self.tab_activated)
814
+ self.tab.observe(self.tab_activated)
815
+
816
+ def tab_activated(self, val=0):
817
+ if self.google:
818
+ self.tab.children = [self.tab_buttons, self.children[self.tab_buttons.index]] # update sidebar gui
819
+ self.tabval = self.tab_buttons.index
820
+ else:
821
+ if isinstance(val.new, int):
822
+ self.tabval = val.new
823
+ # self.update_sidebars()
824
+ if self.tabval == 1:
825
+ self.info.update_dataset()
826
+ elif self.tabval == 2:
827
+ self.low_loss.update_ll_sidebar()
828
+ elif self.tabval == 3:
829
+ self.core_loss.update_cl_sidebar()
830
+
831
+ def update_tab_spectra(self):
832
+ if self.tabval == 2:
833
+ self.low_loss._update()
834
+
835
+ def update_sidebars(self):
836
+ if hasattr(self, 'info'):
837
+ self.info.update_sidebar()
838
+ #if hasattr(self, 'low_loss'):
839
+ # self.low_loss.update_ll_sidebar()
840
+ #if hasattr(self, 'core_loss'):
841
+ # self.core_loss.update_cl_sidebar()
842
+
843
+
844
+ def get_additional_spectrum(self, key):
845
+ if key not in self.datasets.keys():
846
+ return
847
+ if isinstance(self.datasets[key], np.ndarray):
848
+ return self.datasets[key]*self.y_scale
849
+
850
+ if isinstance(self.datasets[key], sidpy.Dataset):
851
+ if self.datasets[key].data_type == sidpy.DataType.SPECTRUM:
852
+ spectrum = self.datasets[key].copy()
853
+ else:
854
+ image_dims = self.datasets[key].get_dimensions_by_type(sidpy.DimensionType.SPATIAL)
855
+ selection = []
856
+ x = self.x
857
+ y = self.y
858
+ bin_x = self.bin_x
859
+ bin_y = self.bin_y
860
+ for dim, axis in self.datasets[key]._axes.items():
861
+ # print(dim, axis.dimension_type)
862
+ if axis.dimension_type == sidpy.DimensionType.SPATIAL:
863
+ if dim == image_dims[0]:
864
+ selection.append(slice(x, x + bin_x))
865
+ else:
866
+ selection.append(slice(y, y + bin_y))
867
+
868
+ elif axis.dimension_type == sidpy.DimensionType.SPECTRAL:
869
+ selection.append(slice(None))
870
+ elif axis.dimension_type == sidpy.DimensionType.CHANNEL:
871
+ selection.append(slice(None))
872
+ else:
873
+ selection.append(slice(0, 1))
874
+
875
+ spectrum = self.datasets[key][tuple(selection)].mean(axis=tuple(image_dims))
876
+ spectrum.data_type = 'spectrum'
877
+
878
+ spectrum *= self.y_scale
879
+ return spectrum.squeeze()
880
+
881
+
882
+ class Info(object):
883
+ def __init__(self, sidebar=None, parent=None):
884
+ self.parent = parent
885
+ self.info_tab = sidebar
886
+ self.key = self.parent.info_key
887
+ self.update_sidebar()
888
+ self.set_action()
889
+ self.count =0
890
+
891
+ def set_energy_scale(self, value):
892
+ self.ens = 1
893
+ self.energy_scale = self.parent.datasets[self.key].get_spectral_dims(return_axis=True)[0]
894
+ dispersion = self.parent.datasets[self.key].get_dimension_slope(self.energy_scale)
895
+ self.ens = dispersion
896
+ self.energy_scale *= (self.info_tab[3, 0].value / dispersion)
897
+ self.energy_scale += (self.info_tab[2, 0].value - self.energy_scale[0])
898
+ self.parent.plot()
899
+
900
+ def set_y_scale(self, value):
901
+ self.count += 1
902
+ self.parent.change_y_scale = 1.0 / self.parent.y_scale
903
+ if self.parent.datasets[self.parent.key].metadata['experiment']['flux_ppm'] > 1e-12:
904
+ if self.info_tab[9, 2].value:
905
+ dispersion = self.parent.datasets[self.parent.key].get_dimension_slope(self.parent.energy_scale)
906
+ self.parent.y_scale = 1 / self.parent.datasets[self.parent.key].metadata['experiment']['flux_ppm'] * dispersion
907
+ self.parent.ylabel = 'scattering probability (ppm)'
908
+ else:
909
+ self.parent.y_scale = 1.0
910
+ self.parent.ylabel = 'intensity (counts)'
911
+ self.parent.change_y_scale *= self.parent.y_scale
912
+ self.parent._update()
913
+
914
+ def set_flux(self, value):
915
+ # self.parent.datasets[self.key].metadata['experiment']['exposure_time'] = self.info_tab[10, 0].value
916
+ if self.info_tab[9, 0].value == 'None':
917
+ self.parent.datasets[self.parent.key].metadata['experiment']['flux_ppm'] = 0.
918
+ else:
919
+ ll_key = self.info_tab[9, 0].value.split(':')[0]
920
+ self.parent.datasets['_relationship']['low_loss'] = ll_key
921
+ self.parent.lowloss_key = ll_key
922
+ spectrum_dimensions = self.parent.dataset.get_spectral_dims()
923
+
924
+ number_of_pixels = 1
925
+ for index, dimension in enumerate(self.parent.dataset.shape):
926
+ if index not in spectrum_dimensions:
927
+ number_of_pixels *= dimension
928
+ if self.parent.datasets[ll_key].metadata['experiment']['exposure_time'] == 0.0:
929
+ if self.parent.datasets[ll_key].metadata['experiment']['single_exposure_time'] == 0.0:
930
+ return
931
+ else:
932
+ self.parent.datasets[ll_key].metadata['experiment']['exposure_time'] = (self.parent.datasets[ll_key].metadata['experiment']['single_exposure_time'] *
933
+ self.parent.datasets[ll_key].metadata['experiment']['number_of_frames'])
934
+
935
+ self.parent.datasets[self.parent.key].metadata['experiment']['flux_ppm'] = ((np.array(self.parent.datasets[ll_key])*1e-6).sum() /
936
+ self.parent.datasets[ll_key].metadata['experiment']['exposure_time'] /
937
+ number_of_pixels)
938
+ self.parent.datasets[self.parent.key].metadata['experiment']['flux_ppm'] *= self.parent.datasets[self.parent.key].metadata['experiment']['exposure_time']
939
+ if 'SPECT' in self.parent.datasets[ll_key].data_type.name:
940
+ self.info_tab[14, 0].disabled = False
941
+ self.info_tab[11, 0].value = np.round(self.parent.datasets[self.parent.key].metadata['experiment']['flux_ppm'], 2)
942
+
943
+ def set_microscope_parameter(self, value):
944
+ if not self.parent.new_info:
945
+ self.parent.datasets[self.key].metadata['experiment']['convergence_angle'] = self.info_tab[5, 0].value
946
+ self.parent.datasets[self.key].metadata['experiment']['collection_angle'] = self.info_tab[6, 0].value
947
+ self.parent.datasets[self.key].metadata['experiment']['acceleration_voltage'] = self.info_tab[7, 0].value*1000
948
+
949
+ def cursor2energy_scale(self, value):
950
+ self.energy_scale = self.parent.datasets[self.key].get_spectral_dims(return_axis=True)[0]
951
+ dispersion = (self.parent.end_cursor.value - self.parent.start_cursor.value) / (self.parent.end_channel - self.parent.start_channel)
952
+
953
+ self.energy_scale *= (self.info_tab[3, 0].value/dispersion)
954
+
955
+ offset = self.parent.start_cursor.value - self.parent.start_channel * dispersion
956
+ self.parent.energy_scale += (self.info_tab[2, 0].value-self.parent.energy_scale[0])
957
+ self.info_tab[2, 0].value = np.round(offset,4)
958
+ self.info_tab[3, 0].value = np.round(dispersion,4)
959
+ self.parent.plot()
960
+
961
+ def set_binning(self, value):
962
+ if 'SPECTRAL' in self.parent.dataset.data_type.name:
963
+ image_dims = self.parent.dataset.get_image_dims()
964
+
965
+ self.bin_x = int(self.info_tab[16, 0].value)
966
+ self.bin_y = int(self.info_tab[17, 0].value)
967
+ if self.bin_x < 1:
968
+ self.bin_x = 1
969
+ self.info_tab[16, 0].value = self.bin_x
970
+ if self.bin_y < 1:
971
+ self.bin_y = 1
972
+ self.info_tab[17, 0].value = self.bin_y
973
+ if self.bin_x > self.parent.dataset.shape[image_dims[0]]:
974
+ self.bin_x = self.parent.dataset.shape[image_dims[0]]
975
+ self.info_tab[16, 0].value = self.bin_x
976
+ if self.bin_y > self.parent.dataset.shape[image_dims[1]]:
977
+ self.bin_y = self.parent.dataset.shape[image_dims[1]]
978
+ self.info_tab[17, 0].value = self.bin_y
979
+ self.parent.bin_x = self.bin_x
980
+ self.parent.bin_y = self.bin_y
981
+
982
+ self.parent.datasets[self.key].metadata['experiment']['SI_bin_x'] = self.bin_x
983
+ self.parent.datasets[self.key].metadata['experiment']['SI_bin_y'] = self.bin_y
984
+ self.parent.plot()
985
+
986
+
987
+
988
+ def update_sidebar(self):
989
+ spectrum_list = ['None']
990
+ reference_list = ['None']
991
+ data_list = []
992
+
993
+ self.key = self.info_key = self.parent.info_key
994
+
995
+ spectrum_data = False
996
+ info_index= 0
997
+ for key in self.parent.datasets.keys():
998
+ if isinstance(self.parent.datasets[key], sidpy.Dataset):
999
+ if key[0] != '_' :
1000
+ data_list.append(f'{key}: {self.parent.datasets[key].title}')
1001
+ if 'SPECTR' in self.parent.datasets[key].data_type.name:
1002
+ spectrum_data = True
1003
+ spectrum_list.append(f'{key}: {self.parent.datasets[key].title}')
1004
+ if self.info_key == key:
1005
+ info_index = len(spectrum_list)-1
1006
+ reference_list.append(f'{key}: {self.parent.datasets[key].title}')
1007
+ self.info_tab[0, 0].options = spectrum_list
1008
+ self.info_tab[9, 0].options = reference_list
1009
+ self.info_tab[0, 0].value = spectrum_list[info_index]
1010
+
1011
+ if 'SPECTRUM' in self.parent.dataset.data_type.name:
1012
+ for i in range(15, 18):
1013
+ self.info_tab[i, 0].layout.display = "none"
1014
+ else:
1015
+ for i in range(15, 18):
1016
+ self.info_tab[i, 0].layout.display = "flex"
1017
+
1018
+ if 'None' not in self.key:
1019
+ self.parent.new_info = True
1020
+ energy_scale = self.parent.datasets[self.key].get_spectral_dims(return_axis=True)
1021
+ if len(energy_scale) == 0:
1022
+ return
1023
+ energy_scale = energy_scale[0]
1024
+ offset = energy_scale[0]
1025
+ # dispersion = self.parent.datasets[self.key].get_dimension_slope(energy_scale)
1026
+ dispersion = energy_scale[1] - offset
1027
+
1028
+ # self.info_tab[0,0].value = dataset_index #f'{self.key}: {self.parent.datasets[self.key].title}'
1029
+ self.info_tab[2, 0].unobserve_all()
1030
+ self.info_tab[2, 0].value = np.round(offset, 3)
1031
+ self.info_tab[3, 0].value = np.round(dispersion, 4)
1032
+ self.info_tab[5, 0].value = np.round(self.parent.datasets[self.key].metadata['experiment']['convergence_angle'], 1)
1033
+ self.info_tab[6, 0].value = np.round(self.parent.datasets[self.key].metadata['experiment']['collection_angle'], 1)
1034
+ self.info_tab[7, 0].value = np.round(self.parent.datasets[self.key].metadata['experiment']['acceleration_voltage']/1000, 1)
1035
+ self.info_tab[2, 0].observe(self.set_energy_scale, names='value')
1036
+ # print(self.parent.datasets[self.key].metadata['experiment']['acceleration_voltage'])
1037
+ self.info_tab[10, 0].value = np.round(self.parent.datasets[self.key].metadata['experiment']['exposure_time'], 4)
1038
+ if 'flux_ppm' not in self.parent.datasets[self.key].metadata['experiment']:
1039
+ self.parent.datasets[self.key].metadata['experiment']['flux_ppm'] = 0
1040
+ self.info_tab[11, 0].value = self.parent.datasets[self.key].metadata['experiment']['flux_ppm']
1041
+ if 'count_conversion' not in self.parent.datasets[self.key].metadata['experiment']:
1042
+ self.parent.datasets[self.key].metadata['experiment']['count_conversion'] = 1
1043
+ self.info_tab[12, 0].value = self.parent.datasets[self.key].metadata['experiment']['count_conversion']
1044
+ if 'beam_current' not in self.parent.datasets[self.key].metadata['experiment']:
1045
+ self.parent.datasets[self.key].metadata['experiment']['beam_current'] = 0
1046
+ self.info_tab[13, 0].value = self.parent.datasets[self.key].metadata['experiment']['beam_current']
1047
+ ll_key = 'None'
1048
+ if '_relationship' in self.parent.datasets:
1049
+ if 'low_loss' in self.parent.datasets['_relationship']:
1050
+ ll_key = self.parent.datasets['_relationship']['low_loss']
1051
+ ll_key = f'{ll_key}: {self.parent.datasets[ll_key].title}'
1052
+ self.lowloss_key = ll_key
1053
+ self.info_tab[9, 0].value = ll_key
1054
+ self.parent.new_info = False
1055
+
1056
+ def update_dataset(self, value=0):
1057
+ self.key = self.info_tab[0, 0].value.split(':')[0]
1058
+
1059
+ self.info_key = self.key
1060
+ self.parent.info_key = self.key
1061
+
1062
+ if self.info_key != 'None':
1063
+ self.parent.set_dataset(self.info_key)
1064
+ self.parent.status_message(self.key+' , '+ self.parent.info_key)
1065
+ if '_relationship' in self.parent.datasets.keys():
1066
+ self.parent.datasets['_relationship']['spectrum'] = self.info_key
1067
+ self.update_sidebar()
1068
+ self.parent._update(0)
1069
+
1070
+ def get_shift(self, value=0):
1071
+ if 'low_loss' in self.parent.datasets['_relationship']:
1072
+ low_loss = self.parent.datasets[self.parent.datasets['_relationship']['low_loss']]
1073
+
1074
+ self.parent.datasets['shifted_low_loss'] = eels_tools.align_zero_loss(low_loss)
1075
+ self.parent.datasets['shifted_low_loss'].title = self.parent.dataset.title + '_shifted'
1076
+ self.parent.datasets['_relationship']['low_loss'] = 'shifted_low_loss'
1077
+ self.update_sidebar()
1078
+
1079
+ if 'low_loss' in self.parent.datasets['_relationship']:
1080
+ if 'zero_loss' in self.parent.datasets[self.parent.datasets['_relationship']['low_loss']].metadata:
1081
+ if 'shifted' in self.parent.datasets[self.parent.datasets['_relationship']['low_loss']].metadata['zero_loss'].keys():
1082
+ self.info_tab[14, 1].disabled = False
1083
+
1084
+
1085
+ def shift_spectrum(self, value=0):
1086
+ shifts = self.parent.dataset.shape
1087
+ if 'low_loss' in self.parent.datasets['_relationship']:
1088
+ if 'zero_loss' in self.parent.datasets[self.parent.datasets['_relationship']['low_loss']].metadata:
1089
+ if 'shifted' in self.parent.datasets[self.parent.datasets['_relationship']['low_loss']].metadata['zero_loss'].keys():
1090
+ shifts = self.parent.datasets[self.parent.datasets['_relationship']['low_loss']].metadata['zero_loss']['shifted']
1091
+ shifts_new = shifts.copy()
1092
+ if 'zero_loss' in self.parent.dataset.metadata:
1093
+ if 'shifted' in self.parent.dataset.metadata['zero_loss'].keys():
1094
+ shifts_new = shifts-self.parent.dataset.metadata['zero_loss']['shifted']
1095
+ else:
1096
+ self.parent.dataset.metadata['zero_loss'] = {}
1097
+
1098
+
1099
+ self.parent.dataset = eels_tools.shift_energy(self.parent.dataset, shifts_new)
1100
+ self.parent.dataset.metadata['zero_loss']['shifted'] = shifts
1101
+ self.parent.plot()
1102
+
1103
+
1104
+ def set_action(self):
1105
+ self.info_tab[0, 0].observe(self.update_dataset, names='value')
1106
+ self.info_tab[1, 0].on_click(self.cursor2energy_scale)
1107
+ self.info_tab[2, 0].observe(self.set_energy_scale, names='value')
1108
+ self.info_tab[3, 0].observe(self.set_energy_scale, names='value')
1109
+ self.info_tab[5, 0].observe(self.set_microscope_parameter)
1110
+ self.info_tab[6, 0].observe(self.set_microscope_parameter)
1111
+ self.info_tab[7, 0].observe(self.set_microscope_parameter)
1112
+ self.info_tab[9, 0].observe(self.set_flux, names='value')
1113
+ self.info_tab[9, 2].observe(self.set_y_scale, names='value')
1114
+ self.info_tab[10, 0].observe(self.set_flux)
1115
+ self.info_tab[14, 0].on_click(self.get_shift)
1116
+ self.info_tab[14, 1].on_click(self.shift_spectrum)
1117
+ self.info_tab[14, 1].on_click(self.shift_spectrum)
1118
+
1119
+ self.info_tab[16, 0].observe(self.set_binning)
1120
+ self.info_tab[17, 0].observe(self.set_binning)