Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Analysing Low-Loss Spectra with Drude Theory

pyTEMlib : EELS_tools


Analysing Low-Loss Spectra with Drude Theory

OpenInColab

part of

pyTEMlib

a pycroscopy ecosystem package Notebook by

Gerd Duscher

Microscopy Facilities Materials Science & Engineering
Institute of Advanced Materials & Manufacturing
The University of Tennessee, Knoxville

Analyse EELS spectra and spectrum images.

Content

The main feature in a low-loss EELS spectrum is the volume plasmon peak.

This volume plasmon and all other features in the low-loss region of an EELS spectrum are described by Dielectric Theory of Electrodynamics.

The simplest theory to interprete this energy range is the Drude theory.

Another easy to observe component is the multiple scattering of this plasmon peak, which we can correct for or use for thickness determination.

See Notebook: Analysing Low-Loss Spectra with Drude Theory of the MSE672-Introduction-to-TEM Lecture in my Github account.

Load important packages

Check Installed Packages

import sys
import importlib.metadata
def test_package(package_name):
    """Test if package exists and returns version or -1"""
    try:
        version = importlib.metadata.version(package_name)
    except importlib.metadata.PackageNotFoundError:
        version = '-1'
    return version

# pyTEMlib setup ------------------
if test_package('pyTEMlib') < '0.2025.1.0':
    print('installing pyTEMlib')
    !{sys.executable} -m pip install --upgrade git+https://github.com/pycroscopy/pyTEMlib.git@main -q --upgrade
# ------------------------------
print('done')
done

Import all relevant libraries

Please note that the EELS_tools package from pyTEMlib is essential.

%matplotlib widget
import matplotlib.pyplot as plt 

import numpy as np
import sys

%load_ext autoreload
%autoreload 2

if 'google.colab' in sys.modules:
    from google.colab import output
    output.enable_custom_widget_manager()
    from google.colab import drive

sys.path.insert(0,'../../')
sys.path.insert(0,'../../../sidpy/')
import sidpy

# Import libraries from pyTEMlib
import pyTEMlib
import pyTEMlib.file_tools as ft          # File input/ output library
from pyTEMlib import eels_tools  
# import pyTEMlib.info_widget3

import pyTEMlib.kinematic_scattering as ks         # Kinematic sCattering Library
                             # Atomic form factors from Kirklands book

# For archiving reasons it is a good idea to print the version numbers out at this point
print('pyTEM version: ',pyTEMlib.__version__)
You don't have igor2 installed.     If you wish to open igor files, you will need to install it     (pip install igor2) before attempting.
You don't have gwyfile installed.     If you wish to open .gwy files, you will need to      install it (pip install gwyfile) before attempting.
Symmetry functions of spglib enabled
Using kinematic_scattering library version {_version_ }  by G.Duscher
pyTEM version:  0.2025.02.2
if 'google.colab' in sys.modules:
    drive.mount("/content/drive")
# infoWidget= pyTEMlib.info_widget3.EELSWidget()
Loading...
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:721, in Widget._lock_property(self, **properties)
    720 try:
--> 721     yield
    722 finally:

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:650, in Widget.set_state(self, sync_data)
    647 # The order of these context managers is important. Properties must
    648 # be locked when the hold_trait_notification context manager is
    649 # released and notifications are fired.
--> 650 with self._lock_property(**sync_data), self.hold_trait_notifications():
    651     for name in sync_data:

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\contextlib.py:144, in _GeneratorContextManager.__exit__(self, typ, value, traceback)
    143 try:
--> 144     next(self.gen)
    145 except StopIteration:

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1510, in HasTraits.hold_trait_notifications(self)
   1509 for change in changes:
-> 1510     self.notify_change(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:701, in Widget.notify_change(self, change)
    700         self.send_state(key=name)
--> 701 super().notify_change(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1525, in HasTraits.notify_change(self, change)
   1524 """Notify observers of a change event"""
-> 1525 return self._notify_observers(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1568, in HasTraits._notify_observers(self, event)
   1566     c = getattr(self, c.name)
-> 1568 c(event)

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:818, in EELSWidget.tab_activated(self, val)
    817 if self.tabval == 1:
--> 818     self.info.update_dataset()
    819 elif self.tabval == 2:

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:1061, in Info.update_dataset(self, value)
   1060 self.update_sidebar()
-> 1061 self.parent._update(0)

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:514, in EELSBaseWidget._update(self, ev)
    513 self.get_spectrum()
--> 514 self.plot_spectrum()

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:492, in EELSBaseWidget.plot_spectrum(self)
    490 self.spectrum_plot.data = [self.spectrum_plot.data[0]]
--> 492 self.xlabel = self.spectrum.labels[0]
    493 self.ylabel = self.datasets[self.key].data_descriptor

IndexError: list index out of range

During handling of the above exception, another exception occurred:

IndexError                                Traceback (most recent call last)
File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:773, in Widget._handle_msg(self, msg)
    771         if 'buffer_paths' in data:
    772             _put_buffers(state, data['buffer_paths'], msg['buffers'])
--> 773         self.set_state(state)
    775 # Handle a state request.
    776 elif method == 'request_state':

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:650, in Widget.set_state(self, sync_data)
    645         self._send(msg, buffers=echo_buffers)
    647 # The order of these context managers is important. Properties must
    648 # be locked when the hold_trait_notification context manager is
    649 # released and notifications are fired.
--> 650 with self._lock_property(**sync_data), self.hold_trait_notifications():
    651     for name in sync_data:
    652         if name in self.keys:

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\contextlib.py:158, in _GeneratorContextManager.__exit__(self, typ, value, traceback)
    156     value = typ()
    157 try:
--> 158     self.gen.throw(value)
    159 except StopIteration as exc:
    160     # Suppress StopIteration *unless* it's the same exception that
    161     # was passed to throw().  This prevents a StopIteration
    162     # raised inside the "with" statement from being suppressed.
    163     return exc is not value

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:723, in Widget._lock_property(self, **properties)
    721     yield
    722 finally:
--> 723     self._property_lock = {}

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:716, in TraitType.__set__(self, obj, value)
    714 if self.read_only:
    715     raise TraitError('The "%s" trait is read-only.' % self.name)
--> 716 self.set(obj, value)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:706, in TraitType.set(self, obj, value)
    702     silent = False
    703 if silent is not True:
    704     # we explicitly compare silent to True just in case the equality
    705     # comparison above returns something other than True/False
--> 706     obj._notify_trait(self.name, old_value, new_value)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1513, in HasTraits._notify_trait(self, name, old_value, new_value)
   1512 def _notify_trait(self, name: str, old_value: t.Any, new_value: t.Any) -> None:
-> 1513     self.notify_change(
   1514         Bunch(
   1515             name=name,
   1516             old=old_value,
   1517             new=new_value,
   1518             owner=self,
   1519             type="change",
   1520         )
   1521     )

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:701, in Widget.notify_change(self, change)
    698     if name in self.keys and self._should_send_property(name, getattr(self, name)):
    699         # Send new state to front-end
    700         self.send_state(key=name)
--> 701 super().notify_change(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1525, in HasTraits.notify_change(self, change)
   1523 def notify_change(self, change: Bunch) -> None:
   1524     """Notify observers of a change event"""
-> 1525     return self._notify_observers(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1568, in HasTraits._notify_observers(self, event)
   1565 elif isinstance(c, EventHandler) and c.name is not None:
   1566     c = getattr(self, c.name)
-> 1568 c(event)

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:818, in EELSWidget.tab_activated(self, val)
    816     # self.update_sidebars()
    817 if self.tabval == 1:
--> 818     self.info.update_dataset()
    819 elif self.tabval == 2:
    820     self.low_loss.update_ll_sidebar()

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:1061, in Info.update_dataset(self, value)
   1059     self.parent.datasets['_relationship']['spectrum'] = self.info_key
   1060 self.update_sidebar()
-> 1061 self.parent._update(0)

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:514, in EELSBaseWidget._update(self, ev)
    512 def _update(self, ev=None):
    513     self.get_spectrum()
--> 514     self.plot_spectrum()

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:492, in EELSBaseWidget.plot_spectrum(self)
    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]]
--> 492 self.xlabel = self.spectrum.labels[0]
    493 self.ylabel = self.datasets[self.key].data_descriptor
    494 # self.change_y_scale = 1.0

IndexError: list index out of range
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:773, in Widget._handle_msg(self, msg)
    771         if 'buffer_paths' in data:
    772             _put_buffers(state, data['buffer_paths'], msg['buffers'])
--> 773         self.set_state(state)
    775 # Handle a state request.
    776 elif method == 'request_state':

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:650, in Widget.set_state(self, sync_data)
    645         self._send(msg, buffers=echo_buffers)
    647 # The order of these context managers is important. Properties must
    648 # be locked when the hold_trait_notification context manager is
    649 # released and notifications are fired.
--> 650 with self._lock_property(**sync_data), self.hold_trait_notifications():
    651     for name in sync_data:
    652         if name in self.keys:

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\contextlib.py:144, in _GeneratorContextManager.__exit__(self, typ, value, traceback)
    142 if typ is None:
    143     try:
--> 144         next(self.gen)
    145     except StopIteration:
    146         return False

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1510, in HasTraits.hold_trait_notifications(self)
   1508 for changes in cache.values():
   1509     for change in changes:
-> 1510         self.notify_change(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:701, in Widget.notify_change(self, change)
    698     if name in self.keys and self._should_send_property(name, getattr(self, name)):
    699         # Send new state to front-end
    700         self.send_state(key=name)
--> 701 super().notify_change(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1525, in HasTraits.notify_change(self, change)
   1523 def notify_change(self, change: Bunch) -> None:
   1524     """Notify observers of a change event"""
-> 1525     return self._notify_observers(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1568, in HasTraits._notify_observers(self, event)
   1565 elif isinstance(c, EventHandler) and c.name is not None:
   1566     c = getattr(self, c.name)
-> 1568 c(event)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget_selection.py:236, in _Selection._propagate_index(self, change)
    234     self.label = label
    235 if self.value is not value:
--> 236     self.value = value

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:716, in TraitType.__set__(self, obj, value)
    714 if self.read_only:
    715     raise TraitError('The "%s" trait is read-only.' % self.name)
--> 716 self.set(obj, value)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:706, in TraitType.set(self, obj, value)
    702     silent = False
    703 if silent is not True:
    704     # we explicitly compare silent to True just in case the equality
    705     # comparison above returns something other than True/False
--> 706     obj._notify_trait(self.name, old_value, new_value)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1513, in HasTraits._notify_trait(self, name, old_value, new_value)
   1512 def _notify_trait(self, name: str, old_value: t.Any, new_value: t.Any) -> None:
-> 1513     self.notify_change(
   1514         Bunch(
   1515             name=name,
   1516             old=old_value,
   1517             new=new_value,
   1518             owner=self,
   1519             type="change",
   1520         )
   1521     )

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:701, in Widget.notify_change(self, change)
    698     if name in self.keys and self._should_send_property(name, getattr(self, name)):
    699         # Send new state to front-end
    700         self.send_state(key=name)
--> 701 super().notify_change(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1525, in HasTraits.notify_change(self, change)
   1523 def notify_change(self, change: Bunch) -> None:
   1524     """Notify observers of a change event"""
-> 1525     return self._notify_observers(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1568, in HasTraits._notify_observers(self, event)
   1565 elif isinstance(c, EventHandler) and c.name is not None:
   1566     c = getattr(self, c.name)
-> 1568 c(event)

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:1056, in Info.update_dataset(self, value)
   1053 self.parent.info_key = self.key
   1055 if self.info_key != 'None':
-> 1056     self.parent.set_dataset(self.info_key)
   1057 self.parent.status_message(self.key+'  ,  '+ self.parent.info_key)
   1058 if '_relationship' in self.parent.datasets.keys():

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:646, in EELSBaseWidget.set_dataset(self, key)
    643 self.bin_y = 1
    644 self.count = 0
--> 646 self.update_sidebars()
    647 #self.update_sidebar()
    648 self.plot()

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:830, in EELSWidget.update_sidebars(self)
    828 def update_sidebars(self):
    829     if hasattr(self, 'info'):
--> 830         self.info.update_sidebar()

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:1024, in Info.update_sidebar(self)
   1022 self.info_tab[2, 0].unobserve_all()
   1023 self.info_tab[2, 0].value = np.round(offset, 3)
-> 1024 self.info_tab[3, 0].value = np.round(dispersion, 4)
   1025 self.info_tab[5, 0].value = np.round(self.parent.datasets[self.key].metadata['experiment']['convergence_angle'], 1)
   1026 self.info_tab[6, 0].value = np.round(self.parent.datasets[self.key].metadata['experiment']['collection_angle'], 1)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:716, in TraitType.__set__(self, obj, value)
    714 if self.read_only:
    715     raise TraitError('The "%s" trait is read-only.' % self.name)
--> 716 self.set(obj, value)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:706, in TraitType.set(self, obj, value)
    702     silent = False
    703 if silent is not True:
    704     # we explicitly compare silent to True just in case the equality
    705     # comparison above returns something other than True/False
--> 706     obj._notify_trait(self.name, old_value, new_value)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1513, in HasTraits._notify_trait(self, name, old_value, new_value)
   1512 def _notify_trait(self, name: str, old_value: t.Any, new_value: t.Any) -> None:
-> 1513     self.notify_change(
   1514         Bunch(
   1515             name=name,
   1516             old=old_value,
   1517             new=new_value,
   1518             owner=self,
   1519             type="change",
   1520         )
   1521     )

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:701, in Widget.notify_change(self, change)
    698     if name in self.keys and self._should_send_property(name, getattr(self, name)):
    699         # Send new state to front-end
    700         self.send_state(key=name)
--> 701 super().notify_change(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1525, in HasTraits.notify_change(self, change)
   1523 def notify_change(self, change: Bunch) -> None:
   1524     """Notify observers of a change event"""
-> 1525     return self._notify_observers(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1568, in HasTraits._notify_observers(self, event)
   1565 elif isinstance(c, EventHandler) and c.name is not None:
   1566     c = getattr(self, c.name)
-> 1568 c(event)

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:891, in Info.set_energy_scale(self, value)
    889 self.energy_scale *= (self.info_tab[3, 0].value / dispersion)
    890 self.energy_scale += (self.info_tab[2, 0].value - self.energy_scale[0])
--> 891 self.parent.plot()

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:444, in EELSBaseWidget.plot(self, scale)
    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()

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:588, in EELSBaseWidget.plot_spectrum_image(self)
    586     self.image_plot.data = [self.image_plot.data[0]]
    587     self.image_plot.data[0].z=np.array(self.image).T
--> 588 self.plot_spectrum()
    589 self.image_plot.add_trace(
    590             go.Scatter(mode="markers", x=[0], y=[0], marker_symbol=[101],
    591            marker_color="darkgray", 
    592            marker_line_width=1, marker_size=11, hovertemplate= 'x: %{x}<br>y: %{y}'))
    594 self.image_plot.data[0].on_selection(self.selection_fn)

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:492, in EELSBaseWidget.plot_spectrum(self)
    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]]
--> 492 self.xlabel = self.spectrum.labels[0]
    493 self.ylabel = self.datasets[self.key].data_descriptor
    494 # self.change_y_scale = 1.0

IndexError: list index out of range
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:773, in Widget._handle_msg(self, msg)
    771         if 'buffer_paths' in data:
    772             _put_buffers(state, data['buffer_paths'], msg['buffers'])
--> 773         self.set_state(state)
    775 # Handle a state request.
    776 elif method == 'request_state':

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:650, in Widget.set_state(self, sync_data)
    645         self._send(msg, buffers=echo_buffers)
    647 # The order of these context managers is important. Properties must
    648 # be locked when the hold_trait_notification context manager is
    649 # released and notifications are fired.
--> 650 with self._lock_property(**sync_data), self.hold_trait_notifications():
    651     for name in sync_data:
    652         if name in self.keys:

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\contextlib.py:144, in _GeneratorContextManager.__exit__(self, typ, value, traceback)
    142 if typ is None:
    143     try:
--> 144         next(self.gen)
    145     except StopIteration:
    146         return False

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1510, in HasTraits.hold_trait_notifications(self)
   1508 for changes in cache.values():
   1509     for change in changes:
-> 1510         self.notify_change(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:701, in Widget.notify_change(self, change)
    698     if name in self.keys and self._should_send_property(name, getattr(self, name)):
    699         # Send new state to front-end
    700         self.send_state(key=name)
--> 701 super().notify_change(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1525, in HasTraits.notify_change(self, change)
   1523 def notify_change(self, change: Bunch) -> None:
   1524     """Notify observers of a change event"""
-> 1525     return self._notify_observers(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1568, in HasTraits._notify_observers(self, event)
   1565 elif isinstance(c, EventHandler) and c.name is not None:
   1566     c = getattr(self, c.name)
-> 1568 c(event)

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:896, in Info.set_y_scale(self, value)
    894 self.count += 1
    895 self.parent.change_y_scale = 1.0 / self.parent.y_scale
--> 896 if self.parent.datasets[self.parent.key].metadata['experiment']['flux_ppm'] > 1e-12:
    897     if self.info_tab[9, 2].value:
    898         dispersion = self.parent.datasets[self.parent.key].get_dimension_slope(self.parent.energy_scale)

KeyError: 'flux_ppm'
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:773, in Widget._handle_msg(self, msg)
    771         if 'buffer_paths' in data:
    772             _put_buffers(state, data['buffer_paths'], msg['buffers'])
--> 773         self.set_state(state)
    775 # Handle a state request.
    776 elif method == 'request_state':

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:650, in Widget.set_state(self, sync_data)
    645         self._send(msg, buffers=echo_buffers)
    647 # The order of these context managers is important. Properties must
    648 # be locked when the hold_trait_notification context manager is
    649 # released and notifications are fired.
--> 650 with self._lock_property(**sync_data), self.hold_trait_notifications():
    651     for name in sync_data:
    652         if name in self.keys:

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\contextlib.py:144, in _GeneratorContextManager.__exit__(self, typ, value, traceback)
    142 if typ is None:
    143     try:
--> 144         next(self.gen)
    145     except StopIteration:
    146         return False

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1510, in HasTraits.hold_trait_notifications(self)
   1508 for changes in cache.values():
   1509     for change in changes:
-> 1510         self.notify_change(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:701, in Widget.notify_change(self, change)
    698     if name in self.keys and self._should_send_property(name, getattr(self, name)):
    699         # Send new state to front-end
    700         self.send_state(key=name)
--> 701 super().notify_change(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1525, in HasTraits.notify_change(self, change)
   1523 def notify_change(self, change: Bunch) -> None:
   1524     """Notify observers of a change event"""
-> 1525     return self._notify_observers(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1568, in HasTraits._notify_observers(self, event)
   1565 elif isinstance(c, EventHandler) and c.name is not None:
   1566     c = getattr(self, c.name)
-> 1568 c(event)

File c:\Users\gduscher\OneDrive - University of Tennessee\GitHub\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget3.py:896, in Info.set_y_scale(self, value)
    894 self.count += 1
    895 self.parent.change_y_scale = 1.0 / self.parent.y_scale
--> 896 if self.parent.datasets[self.parent.key].metadata['experiment']['flux_ppm'] > 1e-12:
    897     if self.info_tab[9, 2].value:
    898         dispersion = self.parent.datasets[self.parent.key].get_dimension_slope(self.parent.energy_scale)

KeyError: 'flux_ppm'
file_widget = ft.FileWidget3()
Loading...
Loading...
v =file_widget.selected_dataset.plot()
Loading...
dir(file_widget.dataset)
['A', 'T', '_Array__chunks', '_Array__name', '_Dataset__protected', '_Dataset__rearrange_axes', '_Dataset__reduce_dimensions', '_Dataset__validate_dim', '__abs__', '__add__', '__and__', '__array__', '__array_function__', '__array_priority__', '__array_ufunc__', '__await__', '__bool__', '__class__', '__complex__', '__dask_graph__', '__dask_keys__', '__dask_layers__', '__dask_optimize__', '__dask_postcompute__', '__dask_postpersist__', '__dask_scheduler__', '__dask_tokenize__', '__deepcopy__', '__delattr__', '__dict__', '__dir__', '__div__', '__divmod__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__iter__', '__le__', '__len__', '__long__', '__lshift__', '__lt__', '__matmul__', '__mod__', '__module__', '__mul__', '__ne__', '__neg__', '__new__', '__nonzero__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmatmul__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__setitem__', '__sizeof__', '__slots__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__weakref__', '__xor__', '_axes', '_cached_keys', '_chunks', '_closest_point', '_data_type', '_elemwise', '_griddata_transform', '_h5_dataset', '_key_array', '_meta', '_metadata', '_min_dist', '_modality', '_name', '_original_metadata', '_quantity', '_rebuild', '_repr_html_', '_reset_cache', '_scalarfunc', '_source', '_structures', '_title', '_units', '_variance', '_vindex', 'abs', 'add_provenance', 'add_structure', 'adjust_axis', 'all', 'angle', 'any', 'argmax', 'argmin', 'argtopk', 'astype', 'blocks', 'choose', 'chunks', 'chunksize', 'clip', 'compute', 'compute_chunk_sizes', 'conj', 'copy', 'cumprod', 'cumsum', 'dask', 'data_descriptor', 'data_type', 'del_dimension', 'dim_0', 'dot', 'dtype', 'energy_loss', 'fft', 'flatten', 'flatten_complex', 'fold', 'from_array', 'get_dimension_by_number', 'get_dimension_slope', 'get_dimensions_by_type', 'get_dimensions_types', 'get_extent', 'get_image_dims', 'get_spectral_dims', 'h5_dataset', 'hdf_close', 'imag', 'itemsize', 'labels', 'like_data', 'map_blocks', 'map_overlap', 'max', 'mean', 'metadata', 'min', 'modality', 'moment', 'name', 'nbytes', 'ndim', 'nonzero', 'npartitions', 'numblocks', 'original_metadata', 'partitions', 'persist', 'plot', 'point_cloud', 'prod', 'provenance', 'quantity', 'ravel', 'real', 'rechunk', 'reduce_dims', 'rename_dimension', 'repeat', 'reshape', 'round', 'set_dimension', 'set_thumbnail', 'shape', 'shuffle', 'size', 'source', 'squeeze', 'std', 'store', 'structures', 'sum', 'swapaxes', 'title', 'to_backend', 'to_dask_dataframe', 'to_delayed', 'to_hdf5', 'to_svg', 'to_tiledb', 'to_zarr', 'topk', 'trace', 'transpose', 'unfold', 'units', 'var', 'variance', 'view', 'view_metadata', 'view_original_metadata', 'vindex', 'visualize']
dataset2 = xarray.Dataset( {"spectrum": ([ "energy_scale"], np.array(file_widget.dataset))},
                           coords={"energy_scale":  np.array(file_widget.dataset.energy_loss),}
                         )
spectrum_smaller = dataset2['spectrum']/100

dataset2.attrs ={'units': 'counts', 
                 'data_type': 'spectrum',
                 'quantity': 'intensity'}

dataset2.energy_scale.attrs={'units': 'eV', 
                             'dimension_type': 'spectral',
                             'quantity': 'energy_loss'}
dataset2['energy_scale'].attrs, dataset2.energy_scale.units, list(dataset2.coords.keys()), list(dataset2.keys())
dataset2['spectrum2'] = spectrum_smaller

dataset2
Loading...
import xarray
import datetime
ds1 = xarray.Dataset({"file": file_widget.file_name })
ds1.attrs = file_widget.dataset.metadata
sidpy_tree = xarray.DataTree(name="root", dataset=ds1)
sidpy_tree.attrs = {'relationship': {'main': 'Channel_000'}}

sidpy_tree.children = {"Channel_000":  xarray.DataTree(name="spectrum", dataset=dataset2)} 
sidpy_tree['Channel_000'] -=sidpy_tree['Channel_000'].min()
#sidpy_tree['Channel_000'].coords =   sidpy_tree['Channel_000'].coords['energy_scale']+1000
d = sidpy_tree['Channel_000']/sidpy_tree['Channel_000'].max()
d.name = 'sin'
sidpy_tree['Channel_000']['other'] = np.sin(d['spectrum'].to_dataset())+666

sidpy_tree['Channel_000']['spectrum'].attrs = file_widget.dataset.original_metadata

sidpy_tree['Channel_000'].attrs ={'units': 'counts', 
                 'data_type': 'spectrum',
                 'quantity': 'intensity',
                 'provenance': {'sidpy': f"init_{sidpy.__version__}_"+str(datetime.datetime.now()).replace(' ','-')}}

print(sidpy_tree)
sidpy_tree['Channel_000'].to_dataset().attrs
<xarray.DataTree 'root'>
Group: /
│   Dimensions:  ()
│   Data variables:
│       file     <U79 316B 'C:\\Users\\gduscher\\Desktop\\drive-download-20241125...
│   Attributes:
│       relationship:  {'main': 'Channel_000'}
└── Group: /Channel_000
    │   Dimensions:       (energy_scale: 2048)
    │   Coordinates:
    │     * energy_scale  (energy_scale) float64 16kB -6.126 -6.095 ... 56.06 56.1
    │   Data variables:
    │       spectrum      (energy_scale) float64 16kB 3.205e+03 1.926e+03 ... 2.548e+04
    │       spectrum2     (energy_scale) float64 16kB 32.05 19.26 3.979 ... 261.9 254.8
    │   Attributes:
    │       units:       counts
    │       data_type:   spectrum
    │       quantity:    intensity
    │       provenance:  {'sidpy': 'init_0.12.3_2024-12-28-17:59:31.459046'}
    └── Group: /Channel_000/other
            Dimensions:       (energy_scale: 2048)
            Data variables:
                spectrum      (energy_scale) float64 16kB 666.0 666.0 666.0 ... 666.0 666.0
{'units': 'counts', 'data_type': 'spectrum', 'quantity': 'intensity', 'provenance': {'sidpy': 'init_0.12.3_2024-12-28-17:59:31.459046'}}
import xarray

import pint_xarray

from enum import Enum
class DataType(Enum):
    UNKNOWN = -1
    SPECTRUM = 1
    LINE_PLOT = 2
    LINE_PLOT_FAMILY = 3
    IMAGE = 4
    IMAGE_MAP = 5
    IMAGE_STACK = 6  # 3d
    SPECTRAL_IMAGE = 7
    IMAGE_4D = 8
    POINT_CLOUD = 9

class DimensionType(Enum):
    """
    Physical type of Dimension object. This information will be used for
    visualization and processing purposes.
    """
    UNKNOWN = -1
    SPATIAL = 1
    RECIPROCAL = 2
    SPECTRAL = 3
    TEMPORAL = 4
    CHANNEL = 5
    POINT_CLOUD = 6
    
@xarray.register_dataset_accessor("sidpy")
class SidpyAccessor:
    def __init__(self, xarray_obj):
        self._obj = xarray_obj
        self._unit = None
        self._dimensions ={} 
        self._data_type = ''
        self._units = 'counts'
        self._quantity ='intensity'
        self.provenance = {}
        print(list(self._obj.sizes.keys()))
        
        

    @property
    def units(self):
        return self._units
    
    @units.setter
    def units(self, value):
        if isinstance(value, str):
            self._units = value
        else:
            raise ValueError('units needs to be a string')
    @property
    def quantity(self):
        return self._quantity

    @quantity.setter
    def quantity(self, value):
        if isinstance(value, str):
            self._quantity = value
        else:
            raise ValueError('quantity needs to be a string')

    
    @property
    def data_type(self):
        return self._data_type

    @data_type.setter
    def data_type(self, value):
        if isinstance(value, str):
            if value.upper() in DataType._member_names_:
                self._data_type = DataType[value.upper()]
            else:
                self._data_type = DataType.UNKNOWN
                raise Warning('Supported data_types for plotting are only: ', DataType._member_names_)

        elif isinstance(value, DataType):
            self._data_type = value
        else:
            raise ValueError('data_type needs to be a string')

    
    def plot(self):
        """Plot data on a map."""
        return "plotting!"
        


#print(sidpy_tree), d['spectrum']
C:\Users\gduscher\AppData\Local\Temp\ipykernel_31260\4049633596.py:31: AccessorRegistrationWarning: registration of accessor <class '__main__.SidpyAccessor'> under name 'sidpy' for type <class 'xarray.core.dataset.Dataset'> is overriding a preexisting attribute with the same name.
  @xarray.register_dataset_accessor("sidpy")
d = sidpy_tree['Channel_000'].to_dataset()/3
dir(d.energy_scale)
['T', '_HANDLED_TYPES', '__abs__', '__add__', '__and__', '__annotations__', '__array__', '__array_priority__', '__array_ufunc__', '__array_wrap__', '__bool__', '__class__', '__complex__', '__contains__', '__copy__', '__dask_graph__', '__dask_keys__', '__dask_layers__', '__dask_optimize__', '__dask_postcompute__', '__dask_postpersist__', '__dask_scheduler__', '__dask_tokenize__', '__deepcopy__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__iadd__', '__iand__', '__ifloordiv__', '__ilshift__', '__imod__', '__imul__', '__init__', '__init_subclass__', '__int__', '__invert__', '__ior__', '__ipow__', '__irshift__', '__isub__', '__iter__', '__itruediv__', '__ixor__', '__le__', '__len__', '__lshift__', '__lt__', '__matmul__', '__mod__', '__module__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmatmul__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__setitem__', '__sizeof__', '__slots__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__weakref__', '__xor__', '_all_compat', '_attr_sources', '_binary_op', '_cache', '_calc_assign_results', '_close', '_construct_direct', '_coords', '_copy', '_copy_attrs_from', '_cum_extra_args_docstring', '_dask_finalize', '_from_temp_dataset', '_get_axis_num', '_getitem_coord', '_in_memory', '_indexes', '_inplace_binary_op', '_ipython_key_completions_', '_item_key_to_dict', '_item_sources', '_iter', '_name', '_overwrite_indexes', '_reduce_extra_args_docstring', '_reduce_method', '_reindex_callback', '_replace', '_replace_maybe_drop_dims', '_repr_html_', '_resample', '_setattr_dict', '_shuffle', '_title_for_slice', '_to_dataset_split', '_to_dataset_whole', '_to_index', '_to_temp_dataset', '_unary_op', '_variable', 'all', 'any', 'argmax', 'argmin', 'argsort', 'as_numpy', 'assign_attrs', 'assign_coords', 'astype', 'attrs', 'bfill', 'broadcast_equals', 'broadcast_like', 'chunk', 'chunks', 'chunksizes', 'clip', 'close', 'coarsen', 'combine_first', 'compute', 'conj', 'conjugate', 'convert_calendar', 'coords', 'copy', 'count', 'cumprod', 'cumsum', 'cumulative', 'cumulative_integrate', 'curvefit', 'data', 'diff', 'differentiate', 'dims', 'dot', 'drop', 'drop_attrs', 'drop_duplicates', 'drop_encoding', 'drop_indexes', 'drop_isel', 'drop_sel', 'drop_vars', 'dropna', 'dt', 'dtype', 'eV', 'encoding', 'energy_scale', 'equals', 'expand_dims', 'ffill', 'fillna', 'from_dict', 'from_iris', 'from_series', 'get_axis_num', 'get_index', 'groupby', 'groupby_bins', 'head', 'identical', 'idxmax', 'idxmin', 'imag', 'indexes', 'integrate', 'interp', 'interp_calendar', 'interp_like', 'interpolate_na', 'isel', 'isin', 'isnull', 'item', 'load', 'loc', 'map_blocks', 'max', 'mean', 'median', 'min', 'name', 'nbytes', 'ndim', 'notnull', 'pad', 'persist', 'pipe', 'plot', 'polyfit', 'prod', 'quantile', 'query', 'rank', 'real', 'reduce', 'reindex', 'reindex_like', 'rename', 'reorder_levels', 'resample', 'reset_coords', 'reset_encoding', 'reset_index', 'roll', 'rolling', 'rolling_exp', 'round', 'searchsorted', 'sel', 'set_close', 'set_index', 'set_xindex', 'shape', 'shift', 'size', 'sizes', 'sortby', 'squeeze', 'stack', 'std', 'str', 'sum', 'swap_dims', 'tail', 'thin', 'to_dask_dataframe', 'to_dataframe', 'to_dataset', 'to_dict', 'to_index', 'to_iris', 'to_masked_array', 'to_netcdf', 'to_numpy', 'to_pandas', 'to_series', 'to_unstacked_dataset', 'to_zarr', 'transpose', 'unify_chunks', 'unstack', 'values', 'var', 'variable', 'weighted', 'where', 'xindexes']
float(d['spectrum'].max())
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[268], line 1
----> 1 d.energy_scale.units()

File ~\AppData\Local\anaconda3\Lib\site-packages\xarray\core\common.py:302, in AttrAccessMixin.__getattr__(self, name)
    300         with suppress(KeyError):
    301             return source[name]
--> 302 raise AttributeError(
    303     f"{type(self).__name__!r} object has no attribute {name!r}"
    304 )

AttributeError: 'DataArray' object has no attribute 'units'
ds2 = sidpy_tree['Channel_000']['other']
ds1.sidpy.units, ds2.sidpy.units# , list(ds2.sizes.keys()), 
#ds2.sidpy.units, ds2.sidpy.dimensions={'energy_scale':  {'units': 'eV', 'quantity': 'energy_loss',  'dimension_type': 'SPECTRAL'}}
['energy_scale']
('counts', 'counts')

Load and plot a spectrum

import matplotlib.pylab as plt
plt.figure()
sidpy_tree['Channel_000'].to_dataset().plot.scatter(x ='energy_scale', y ='Channel_000')
Loading...
infoWidget.low_loss._update()
# print(infoWidget.datasets['shifted_low_loss'])
print(infoWidget.datasets['Channel_000'])
isinstance(infoWidget.datasets['Channel_000'], sidpy.Dataset)
sidpy.Dataset of type SPECTRAL_IMAGE with:
 dask.array<array, shape=(25, 10, 2048), dtype=float32, chunksize=(25, 10, 2048), chunktype=numpy.ndarray>
 data contains: intensity (counts)
 and Dimensions: 
x:  distance (µm) of size (25,)
y:  distance (µm) of size (10,)
energy_loss:  energy-loss (eV) of size (2048,)
 with metadata: ['experiment', 'annotations']
True
infoWidget.added_spectra
{}
low_loss = infoWidget.dataset

sl = eels_tools.align_zero_loss(low_loss)
print(sl)
sidpy.Dataset of type SPECTRAL_IMAGE with:
 dask.array<setitem, shape=(25, 10, 2048), dtype=float32, chunksize=(25, 10, 2048), chunktype=numpy.ndarray>
 data contains: intensity (counts)
 and Dimensions: 
x:  distance (µm) of size (25,)
y:  distance (µm) of size (10,)
energy_loss:  energy-loss (eV) of size (2048,)
 with metadata: ['experiment', 'annotations', 'zero_loss']
self = infoWidget.info
spectrum_list = ['None']
reference_list = ['None']
data_list = []
for key in self.parent.datasets.keys():
    print(key)
    if isinstance(self.parent.datasets[key], sidpy.Dataset):
        
        if key[0] != '_' :
            
            data_list.append(f'{key}: {self.parent.datasets[key].title}')
            if 'SPECTR' in self.parent.datasets[key].data_type.name:
                spectrum_data = True
                spectrum_list.append(f'{key}: {self.parent.datasets[key].title}')
                if self.info_key == key:
                    info_index = len(spectrum_list)-1
        reference_list.append(f'{key}: {self.parent.datasets[key].title}')


reference_list
Channel_000
_relationship
shifted_low_loss
['None', 'Channel_000: 11-eels']
self.parent.datasets['shifted_low_loss']
False
infoWidget.low_loss.get_drude()
infoWidget._update()
resolution_function = infoWidget.low_loss.get_additional_spectrum('zero_loss')
infoWidget.spectrum_plot.add_trace(go.Scatter(x=infoWidget.energy_scale, y=resolution_function))
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[22], line 3
      1 infoWidget._update()
      2 resolution_function = infoWidget.low_loss.get_additional_spectrum('zero_loss')
----> 3 infoWidget.spectrum_plot.add_trace(go.Scatter(x=infoWidget.energy_scale, y=resolution_function))

NameError: name 'go' is not defined
infoWidget.energy_scale[:3].values
k = infoWidget.key
infoWidget.datasets['Channel_000'].energy_loss[:3].values
infoWidget.spectrum_plot.data[1].x[1]-infoWidget.spectrum_plot.data[1].x[0]
infoWidget.canvas_plot.children = [infoWidget.image_plot]
infoWidget.canvas_plot.children
infoWidget.image_plot.data[0].x = infoWidget.datasset.
image_dims = infoWidget.dataset.get_image_dims(return_axis=True)
        
if len(infoWidget.image_plot.data) == 0:
    infoWidget.image_plot.add_trace(go.Heatmap(z=self.dataset))
else:
    infoWidget.image_plot.data[0].z=infoWidget.dataset
infoWidget.image_plot.data[0].x = image_dims[0].values
infoWidget.image_plot.data[0].y = image_dims[1].values

infoWidget.image_plot.update_layout(xaxis_title = f"{image_dims[0].quantity} ({image_dims[0].units})", 
                              yaxis_title = f"{image_dims[0].quantity} ({image_dims[0].units})")
Loading...
plasmon = eels_tools.fit_plasmon(infoWidget.dataset, 12, 20)
plasmon = np.array(plasmon)
plasmon[23,0]
array([1.47891069e+01, 5.24804751e+00, 1.59869663e+04])
res  = eels_tools.get_resolution_functions(infoWidget.dataset, startFitEnergy=-.5, endFitEnergy=.5, n_workers = 8, n_threads=32)
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
Cell In[126], line 1
----> 1 res  = eels_tools.get_resolution_functions(infoWidget.dataset, startFitEnergy=-.5, endFitEnergy=.5, n_workers = 8, n_threads=32)

File c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\eels_tools.py:494, in get_resolution_functions(dataset, startFitEnergy, endFitEnergy, n_workers, n_threads)
    490 # apply to all spectra
    491 zero_loss_fitter = SidFitter(fit_dset, zl_func, num_workers=n_workers, guess_fn=guess_function, threads=n_threads,
    492                              return_cov=False, return_fit=False, return_std=False, km_guess=False, num_fit_parms=6)
--> 494 [z_loss_params] = zero_loss_fitter.do_fit()
    495 z_loss_dset = dataset.copy()
    496 z_loss_dset *= 0.0

File c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../../../sidpy\sidpy\proc\fitter.py:279, in SidFitter.do_fit(self, **kwargs)
    273         lazy_result = dask.delayed(SidFitter.default_curve_fit)(self.fit_fn, self.dep_vec,
    274                                                                 ydata, self.num_fit_parms,
    275                                                                 return_cov=(self.return_cov or self.return_std),
    276                                                                 p0=p0, **kwargs)
    277         fit_results.append(lazy_result)
--> 279     fit_results_comp = dask.compute(*fit_results)
    280     self.client.close()
    282 else:

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\dask\base.py:661, in compute(traverse, optimize_graph, scheduler, get, *args, **kwargs)
    658     postcomputes.append(x.__dask_postcompute__())
    660 with shorten_traceback():
--> 661     results = schedule(dsk, keys, **kwargs)
    663 return repack([f(r, *a) for r, (f, a) in zip(results, postcomputes)])

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\threading.py:655, in Event.wait(self, timeout)
    653 signaled = self._flag
    654 if not signaled:
--> 655     signaled = self._cond.wait(timeout)
    656 return signaled

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\threading.py:359, in Condition.wait(self, timeout)
    357 else:
    358     if timeout > 0:
--> 359         gotit = waiter.acquire(True, timeout)
    360     else:
    361         gotit = waiter.acquire(False)

KeyboardInterrupt: 
v = res.plot()
Loading...
Loading...
par = np.array(res.metadata['zero_loss']['fit_parameter'])

for x in range(par.shape[0]):
    for y in range(par.shape[1]):
        res[x,y] = eels_tools.zl_func(res.energy_loss, *par[x,y])
res.plot()
[ 6.67765731e-02  5.41174565e+03  2.09773567e-01 -5.03759089e-02
  4.60116290e+03  1.76471738e-01]
[ 6.40790854e-02  5.42690876e+03  1.95865661e-01 -5.43761627e-02
  4.89364258e+03  1.77493041e-01]
[ 6.81077719e-02  6.43605514e+03  1.95012100e-01 -5.30016379e-02
  4.43884015e+03  1.66523164e-01]
[ 6.64093078e-02  5.75427504e+03  1.97398452e-01 -5.44820718e-02
  4.76615072e+03  1.74423078e-01]
[ 6.60569720e-02  5.51845692e+03  1.96624862e-01 -5.43996081e-02
  4.90618330e+03  1.73954089e-01]
[ 6.88292998e-02  5.83932800e+03  2.00135178e-01 -5.42389948e-02
  4.77339641e+03  1.73471449e-01]
[ 6.88602553e-02  6.40214431e+03  1.98363423e-01 -5.58406094e-02
  4.40044152e+03  1.74087986e-01]
[ 6.85837537e-02  5.50451130e+03  2.04716106e-01 -5.38545064e-02
  4.91184340e+03  1.76830016e-01]
[ 6.80843999e-02  5.92034916e+03  1.98310795e-01 -5.36603097e-02
  4.72749111e+03  1.71696664e-01]
[ 7.02924129e-02  5.79923590e+03  2.03052815e-01 -6.00875377e-02
  4.77021463e+03  1.85617368e-01]
[ 7.59351953e-02  5.74719392e+03  2.17761905e-01 -4.90964002e-02
  4.57181160e+03  1.73439777e-01]
[ 7.14214173e-02  6.42868692e+03  2.00225951e-01 -5.61403256e-02
  4.45349710e+03  1.73052011e-01]
[ 6.85377605e-02  6.03738747e+03  1.97822842e-01 -5.54147849e-02
  4.65419643e+03  1.73201414e-01]
[ 6.73344556e-02  6.21211761e+03  1.93919859e-01 -5.67820114e-02
  4.59378752e+03  1.73964356e-01]
[ 8.27238627e-02  6.45369213e+03  2.18628990e-01 -5.20886642e-02
  4.36081813e+03  1.73897061e-01]
[ 7.06435960e-02  6.36686440e+03  1.96169775e-01 -5.63710159e-02
  4.59170667e+03  1.72175490e-01]
[ 7.27963085e-02  6.55894563e+03  1.97397768e-01 -6.05839363e-02
  4.55419840e+03  1.77460246e-01]
[ 6.83713072e-02  6.45395612e+03  1.91981356e-01 -5.61672744e-02
  4.57266329e+03  1.69070320e-01]
[ 7.54707228e-02  5.14341506e+03  2.46466476e-01 -4.61403460e-02
  4.52140072e+03  1.89674132e-01]
[ 7.26078887e-02  5.75959368e+03  2.12141579e-01 -5.14107506e-02
  4.75981161e+03  1.73648064e-01]
[ 6.84163221e-02  5.74088531e+03  2.02574067e-01 -5.28523555e-02
  4.65835166e+03  1.73869145e-01]
[ 6.65971194e-02  5.77069798e+03  1.99722139e-01 -5.26893130e-02
  4.67800248e+03  1.73498950e-01]
[ 6.72157208e-02  5.92408665e+03  1.96250631e-01 -5.53627606e-02
  4.71342603e+03  1.74468412e-01]
[ 6.61735212e-02  6.39596380e+03  1.89017846e-01 -5.70988566e-02
  4.53804164e+03  1.71331806e-01]
[ 6.68025761e-02  5.63468078e+03  2.02774223e-01 -5.14165922e-02
  4.67414362e+03  1.73111664e-01]
[ 6.75920132e-02  5.96000308e+03  1.96650576e-01 -5.61433858e-02
  4.70591085e+03  1.75041706e-01]
[ 7.02985918e-02  6.39022118e+03  1.95886368e-01 -5.66922117e-02
  4.62697084e+03  1.71689098e-01]
[ 7.01250351e-02  6.33569920e+03  1.96729667e-01 -5.53759978e-02
  4.62154202e+03  1.71107272e-01]
[ 6.64675874e-02  6.50765523e+03  1.89619124e-01 -5.49894099e-02
  4.47981522e+03  1.67988504e-01]
[ 7.20129273e-02  6.20841628e+03  2.01333628e-01 -5.59094321e-02
  4.64307700e+03  1.74518796e-01]
[ 6.74800030e-02  5.29962324e+03  2.14577044e-01 -5.05834397e-02
  4.62101331e+03  1.81137746e-01]
[ 7.27224927e-02  5.74897004e+03  2.07121011e-01 -5.61475091e-02
  4.77914010e+03  1.77795688e-01]
[ 7.24757611e-02  5.47407419e+03  2.15253862e-01 -5.27279509e-02
  4.82354314e+03  1.78170799e-01]
[ 7.13477161e-02  6.05142285e+03  2.04043003e-01 -5.59095898e-02
  4.65357328e+03  1.76093187e-01]
[ 7.11669155e-02  5.86250488e+03  2.06734879e-01 -5.02780506e-02
  4.61744850e+03  1.69751817e-01]
[ 6.89522783e-02  6.43281917e+03  1.93392595e-01 -5.57871904e-02
  4.55906778e+03  1.69946641e-01]
[ 6.78458237e-02  6.66039151e+03  1.86035878e-01 -5.94598297e-02
  4.57993305e+03  1.69507571e-01]
[ 6.77096956e-02  7.65977493e+03  1.85012212e-01 -5.73856381e-02
  4.03951871e+03  1.65608309e-01]
[ 7.08814555e-02  6.29021760e+03  1.93424048e-01 -5.98209165e-02
  4.77915795e+03  1.73819512e-01]
[ 7.00859517e-02  6.46491991e+03  1.99156446e-01 -5.84047231e-02
  4.39119423e+03  1.78070478e-01]
[ 7.06292064e-02  5.45224373e+03  2.06111398e-01 -5.43028818e-02
  4.83179853e+03  1.76307660e-01]
[ 6.66900737e-02  5.61556934e+03  2.05230411e-01 -5.27893901e-02
  4.62721915e+03  1.77876480e-01]
[ 6.59869342e-02  5.90394411e+03  1.93202868e-01 -5.70168394e-02
  4.73142528e+03  1.76152518e-01]
[ 6.91387387e-02  6.35144643e+03  1.91273166e-01 -5.56624168e-02
  4.73715428e+03  1.67343119e-01]
[ 6.80138633e-02  5.95256430e+03  1.97297430e-01 -5.46779874e-02
  4.57767742e+03  1.74371633e-01]
[ 6.95208941e-02  6.36534146e+03  1.93853224e-01 -5.83178979e-02
  4.60897132e+03  1.73425950e-01]
[ 7.10639791e-02  6.52675354e+03  1.88968715e-01 -6.23933620e-02
  4.82415039e+03  1.74154100e-01]
[ 6.70775051e-02  6.58511970e+03  1.88528458e-01 -6.01088540e-02
  4.53488243e+03  1.74267170e-01]
[ 6.88841398e-02  6.51986233e+03  1.95551279e-01 -5.24628927e-02
  4.46755380e+03  1.65445476e-01]
[ 7.14861896e-02  6.34824024e+03  2.05767984e-01 -7.27602007e-02
  4.47027447e+03  2.08983426e-01]
[ 6.31795140e-02  5.03591942e+03  2.15235425e-01 -4.14925263e-02
  4.52960478e+03  1.68592966e-01]
[ 6.60352936e-02  6.31494875e+03  1.89088966e-01 -5.32457308e-02
  4.58802770e+03  1.65065264e-01]
[ 6.42608035e-02  6.10639452e+03  1.89587536e-01 -5.68037580e-02
  4.57404674e+03  1.74820643e-01]
[ 6.92104636e-02  6.30186903e+03  1.95462970e-01 -5.39385588e-02
  4.65726679e+03  1.67603141e-01]
[ 6.50354362e-02  5.32711943e+03  2.00461484e-01 -4.91218660e-02
  4.83580371e+03  1.69841823e-01]
[ 6.75996801e-02  6.73229473e+03  1.86198089e-01 -5.78660506e-02
  4.49850057e+03  1.67791499e-01]
[ 6.92084031e-02  6.96171782e+03  1.91248786e-01 -5.98826811e-02
  4.29425083e+03  1.73932510e-01]
[ 6.96971358e-02  6.60540073e+03  1.91578024e-01 -5.86298381e-02
  4.58449766e+03  1.71411968e-01]
[ 6.86357387e-02  6.53037773e+03  1.91083964e-01 -6.12751690e-02
  4.54670096e+03  1.77990299e-01]
[ 6.83529589e-02  6.59229735e+03  1.89658160e-01 -5.87710899e-02
  4.51745911e+03  1.71573881e-01]
[ 6.56597711e-02  6.72338626e+03  2.13806439e-01 -5.12216491e-02
  3.48499282e+03  1.84807458e-01]
[ 6.80277351e-02  5.68966745e+03  2.05202690e-01 -5.31191750e-02
  4.66281465e+03  1.76631524e-01]
[ 6.84217628e-02  5.79936250e+03  1.99967681e-01 -5.52690833e-02
  4.77039134e+03  1.75172229e-01]
[ 6.76028138e-02  6.29915361e+03  1.92530377e-01 -6.03973213e-02
  4.57550991e+03  1.79229410e-01]
[ 7.20094249e-02  5.61740804e+03  2.14095182e-01 -5.06940557e-02
  4.58834471e+03  1.75331664e-01]
[ 6.94449612e-02  6.39884907e+03  1.91863973e-01 -5.70096192e-02
  4.66530775e+03  1.69183065e-01]
[ 7.09248504e-02  7.29814268e+03  1.92846034e-01 -5.61491044e-02
  4.18273987e+03  1.66975209e-01]
[ 7.43447951e-02  6.60909639e+03  1.93300752e-01 -5.77601124e-02
  4.80292336e+03  1.67211477e-01]
[ 7.05282100e-02  6.53691790e+03  1.93562228e-01 -5.82143791e-02
  4.57393247e+03  1.72673537e-01]
[ 8.25789922e-02  6.30894009e+03  2.29480756e-01 -6.23772840e-02
  4.23125106e+03  1.97468337e-01]
[ 6.32390986e-02  5.06000088e+03  2.12677506e-01 -4.79246953e-02
  4.55152127e+03  1.79429283e-01]
[ 6.51738468e-02  5.71673788e+03  1.94048771e-01 -5.39475817e-02
  4.79827988e+03  1.71996033e-01]
[ 6.55109194e-02  6.21843454e+03  1.90642582e-01 -5.47139370e-02
  4.58067988e+03  1.69382855e-01]
[ 6.80000319e-02  6.24224700e+03  1.93276102e-01 -5.57100175e-02
  4.66467575e+03  1.70246915e-01]
[ 6.57226363e-02  5.01419126e+03  2.07819894e-01 -4.85739443e-02
  4.94116582e+03  1.75159255e-01]
[ 6.78396195e-02  6.49612236e+03  1.92766765e-01 -5.45112093e-02
  4.42881874e+03  1.68770081e-01]
[ 6.64915838e-02  5.92511373e+03  1.95473419e-01 -5.57630891e-02
  4.70833920e+03  1.74733843e-01]
[ 6.86710925e-02  6.19695308e+03  1.97112715e-01 -5.80219344e-02
  4.58496818e+03  1.77470099e-01]
[ 7.08991686e-02  6.39035517e+03  1.97741171e-01 -5.18675102e-02
  4.63026135e+03  1.63492213e-01]
[ 6.86272148e-02  6.46193185e+03  1.92124356e-01 -5.82374004e-02
  4.56020509e+03  1.72446721e-01]
[ 6.78998063e-02  4.89204770e+03  2.16082417e-01 -4.75957982e-02
  4.83052207e+03  1.75833386e-01]
[ 7.01922405e-02  5.27529076e+03  2.15842068e-01 -5.43489574e-02
  4.80221548e+03  1.86184512e-01]
[ 6.64744717e-02  6.29877626e+03  1.90595524e-01 -5.30355517e-02
  4.59797516e+03  1.65609424e-01]
[ 6.99276461e-02  6.45931035e+03  1.97886406e-01 -5.43755757e-02
  4.48848089e+03  1.70889444e-01]
[ 6.55687331e-02  5.67936200e+03  1.99380843e-01 -5.17950887e-02
  4.62759387e+03  1.73851117e-01]
[ 6.89090131e-02  6.14081850e+03  1.96096680e-01 -5.40550106e-02
  4.66357031e+03  1.70113432e-01]
[ 6.69297954e-02  6.57658519e+03  1.90944986e-01 -5.38256692e-02
  4.42688845e+03  1.66509149e-01]
[ 6.66268592e-02  6.31840662e+03  1.87051056e-01 -5.84196199e-02
  4.69854536e+03  1.70462983e-01]
[ 7.47530644e-02  6.27922702e+03  2.01292856e-01 -5.42117481e-02
  4.76818877e+03  1.67721298e-01]
[ 6.84607158e-02  6.40459415e+03  1.92971552e-01 -5.79513074e-02
  4.54229507e+03  1.73455914e-01]
[ 7.17223275e-02  5.36405420e+03  2.10619511e-01 -4.89687329e-02
  4.80799346e+03  1.71095951e-01]
[ 6.76977723e-02  5.90746635e+03  1.99101075e-01 -5.56079203e-02
  4.61296756e+03  1.76926346e-01]
[ 6.87809824e-02  5.72490285e+03  2.07654495e-01 -5.22544563e-02
  4.62702725e+03  1.76133143e-01]
[ 7.79338022e-02  6.48734588e+03  2.11468730e-01 -5.60960346e-02
  4.45464145e+03  1.75566909e-01]
[ 7.06625489e-02  5.56789041e+03  2.11385822e-01 -5.66078037e-02
  4.66994967e+03  1.85700012e-01]
[ 6.91130402e-02  6.41656955e+03  1.96850681e-01 -5.38908610e-02
  4.40773596e+03  1.70279793e-01]
[ 6.93167571e-02  6.41923786e+03  1.92106299e-01 -5.40455498e-02
  4.67197829e+03  1.64943038e-01]
[ 7.07843774e-02  5.55536400e+03  2.11061150e-01 -5.11208147e-02
  4.84067587e+03  1.74990352e-01]
[ 7.08848699e-02  6.57380932e+03  1.93528991e-01 -5.59929478e-02
  4.59753651e+03  1.68176176e-01]
[ 7.13016014e-02  6.48794929e+03  1.98010186e-01 -5.49411053e-02
  4.52365795e+03  1.70221475e-01]
[ 6.27014069e-02  5.17842533e+03  2.05006886e-01 -4.73110009e-02
  4.59578530e+03  1.74372819e-01]
[ 6.73982752e-02  5.67044122e+03  2.03216853e-01 -5.06371497e-02
  4.67903858e+03  1.71839377e-01]
[ 6.70349677e-02  5.57544983e+03  1.97797825e-01 -5.28015300e-02
  4.90824392e+03  1.70465891e-01]
[ 6.81203598e-02  6.27449519e+03  1.94066179e-01 -5.86671225e-02
  4.58735550e+03  1.76629163e-01]
[ 6.59545689e-02  5.73724612e+03  1.97352379e-01 -5.28783111e-02
  4.67133288e+03  1.73404634e-01]
[ 6.71547954e-02  6.16934729e+03  1.94733413e-01 -5.31929494e-02
  4.55130998e+03  1.69355340e-01]
[ 6.67107463e-02  6.09176988e+03  1.95985492e-01 -5.80258144e-02
  4.54992960e+03  1.80027858e-01]
[ 6.73604032e-02  6.58259479e+03  1.88698182e-01 -5.85105419e-02
  4.52571487e+03  1.72580554e-01]
[ 6.76337672e-02  6.42798340e+03  1.93795482e-01 -5.65714103e-02
  4.48504945e+03  1.73023023e-01]
[ 6.90159261e-02  6.19971314e+03  1.95751436e-01 -5.72228751e-02
  4.64867180e+03  1.73935019e-01]
[ 6.11260057e-02  5.03790196e+03  2.10117310e-01 -4.78493504e-02
  4.44645655e+03  1.81628158e-01]
[ 7.20556550e-02  5.84883033e+03  2.05448253e-01 -5.28697895e-02
  4.74810241e+03  1.72325825e-01]
[ 6.80240422e-02  5.55279625e+03  2.00849745e-01 -5.35456231e-02
  4.90445582e+03  1.73284814e-01]
[ 8.10165938e-02  6.58239532e+03  2.04273852e-01 -5.86714548e-02
  4.73023329e+03  1.72293689e-01]
[ 6.65355024e-02  5.44612759e+03  2.00811666e-01 -5.40579073e-02
  4.84224109e+03  1.76645521e-01]
[ 6.61856796e-02  5.77868818e+03  1.99118755e-01 -5.54895594e-02
  4.60498635e+03  1.78634638e-01]
[ 6.74058208e-02  5.86137900e+03  1.97201759e-01 -5.39572088e-02
  4.74636661e+03  1.72346774e-01]
[ 6.94703568e-02  6.35049410e+03  1.92580373e-01 -5.66825202e-02
  4.69140747e+03  1.70134815e-01]
[ 8.15472549e-02  6.34854818e+03  2.12531020e-01 -5.27694902e-02
  4.65287533e+03  1.70627424e-01]
[ 7.46136511e-02  6.82465737e+03  1.90570139e-01 -6.03374050e-02
  4.72468444e+03  1.68069340e-01]
[ 6.53272321e-02  5.16694716e+03  2.10648394e-01 -4.90759325e-02
  4.62495967e+03  1.78173080e-01]
[ 6.79889053e-02  6.38247456e+03  1.95226881e-01 -5.43182214e-02
  4.40621026e+03  1.69812726e-01]
[ 6.50445797e-02  5.61658383e+03  1.94379479e-01 -5.36735848e-02
  4.86006709e+03  1.72729522e-01]
[ 6.71643426e-02  6.42490089e+03  1.94435757e-01 -5.48060319e-02
  4.41511527e+03  1.70962194e-01]
[ 6.31431945e-02  5.60830993e+03  1.96704696e-01 -5.75166938e-02
  4.57390264e+03  1.86122788e-01]
[ 6.76300110e-02  6.15856915e+03  1.95231679e-01 -5.40067021e-02
  4.54184671e+03  1.69976297e-01]
[ 6.64897258e-02  6.11973959e+03  1.94456895e-01 -5.43714714e-02
  4.55228522e+03  1.72091972e-01]
[ 6.95622449e-02  6.46002871e+03  1.94144541e-01 -5.64840785e-02
  4.56641792e+03  1.71459880e-01]
[ 6.94738033e-02  6.51712724e+03  1.97886008e-01 -5.44272730e-02
  4.42857799e+03  1.70170819e-01]
[ 7.01329142e-02  7.59547715e+03  1.88916268e-01 -5.67432762e-02
  4.07225678e+03  1.65467238e-01]
[ 6.28544802e-02  5.11423596e+03  2.11274573e-01 -4.76060663e-02
  4.51359601e+03  1.78450365e-01]
[ 6.83760842e-02  6.16108913e+03  1.93446827e-01 -5.57890554e-02
  4.64467132e+03  1.70478710e-01]
[ 6.76158663e-02  5.45259476e+03  2.03040659e-01 -5.17696640e-02
  4.91496688e+03  1.74171798e-01]
[ 6.87041929e-02  6.33520545e+03  1.93229588e-01 -5.63715315e-02
  4.60760648e+03  1.70245785e-01]
[ 6.66804631e-02  6.16902317e+03  1.90716518e-01 -5.36180876e-02
  4.63522272e+03  1.67034305e-01]
[ 6.66141288e-02  5.82859637e+03  1.94699437e-01 -5.46926679e-02
  4.74420389e+03  1.72349028e-01]
[ 6.65690177e-02  6.50733437e+03  1.90060718e-01 -5.31312824e-02
  4.46417549e+03  1.64691276e-01]
[ 6.55180227e-02  6.14829766e+03  1.93121294e-01 -5.82297849e-02
  4.53921177e+03  1.79129502e-01]
[ 6.75438601e-02  6.42918262e+03  1.91808158e-01 -5.80760389e-02
  4.51043067e+03  1.73936347e-01]
[ 6.74908455e-02  6.42142224e+03  1.88072603e-01 -5.53410302e-02
  4.69270794e+03  1.65198669e-01]
[ 6.80929777e-02  5.45626075e+03  2.09482454e-01 -5.06805281e-02
  4.60308516e+03  1.76125004e-01]
[ 6.81188753e-02  6.43714652e+03  1.90305092e-01 -5.73847572e-02
  4.54559465e+03  1.70019205e-01]
[ 6.71106150e-02  6.13447570e+03  1.97086511e-01 -5.39414469e-02
  4.52107146e+03  1.73192084e-01]
[ 6.74073795e-02  6.49384780e+03  1.88422731e-01 -5.65396816e-02
  4.57078656e+03  1.68596679e-01]
[ 6.94192984e-02  5.35955926e+03  2.07827281e-01 -5.30397794e-02
  4.89703719e+03  1.76656121e-01]
[ 6.71502545e-02  5.50393733e+03  1.99010505e-01 -5.42068652e-02
  4.89735959e+03  1.74314024e-01]
[ 7.49144256e-02  6.26974006e+03  2.05093769e-01 -5.66842548e-02
  4.61391252e+03  1.73505978e-01]
[ 6.98343024e-02  7.32924501e+03  1.89115470e-01 -6.00473027e-02
  4.19109071e+03  1.72357228e-01]
[ 6.97690218e-02  6.13072289e+03  2.00207977e-01 -5.26772243e-02
  4.64898751e+03  1.69426425e-01]
[ 7.01525135e-02  6.22626538e+03  1.99882500e-01 -5.75795649e-02
  4.58005615e+03  1.77023149e-01]
[ 6.19899657e-02  4.85264185e+03  2.11021667e-01 -4.69958803e-02
  4.77824688e+03  1.77863253e-01]
[ 6.86590087e-02  6.37627768e+03  1.91215532e-01 -5.48850355e-02
  4.61975279e+03  1.66499832e-01]
[ 6.52153891e-02  5.75789724e+03  1.98562094e-01 -5.26411737e-02
  4.62434467e+03  1.73561140e-01]
[ 6.74287363e-02  6.13339108e+03  1.95218492e-01 -5.35038197e-02
  4.62721321e+03  1.69293487e-01]
[ 6.39138747e-02  5.64989327e+03  1.96275279e-01 -5.30286310e-02
  4.59768205e+03  1.74528394e-01]
[ 6.53077693e-02  5.29264697e+03  2.01109433e-01 -5.26551896e-02
  4.88204664e+03  1.75986527e-01]
[ 6.53010879e-02  5.35664902e+03  2.01456338e-01 -4.98447412e-02
  4.86056411e+03  1.71980210e-01]
[ 6.79404452e-02  6.36423230e+03  1.91247784e-01 -5.86077456e-02
  4.59817230e+03  1.74203105e-01]
[ 6.79406667e-02  6.40805525e+03  1.91851849e-01 -5.92671981e-02
  4.53844810e+03  1.75730582e-01]
[ 6.73612735e-02  6.45286935e+03  1.91866892e-01 -5.70179432e-02
  4.49131470e+03  1.72294985e-01]
[ 6.61441711e-02  4.85905951e+03  2.28286418e-01 -4.36170112e-02
  4.56674631e+03  1.77620859e-01]
[ 7.24758855e-02  6.09388747e+03  2.04099016e-01 -5.27858366e-02
  4.63089642e+03  1.69371805e-01]
[ 6.74634649e-02  6.02150366e+03  1.97912395e-01 -5.65196222e-02
  4.57579422e+03  1.77954654e-01]
[ 6.86130645e-02  6.14041550e+03  1.98450708e-01 -5.52042885e-02
  4.54729239e+03  1.73519304e-01]
[ 6.35926179e-02  5.25977151e+03  1.98134243e-01 -5.27086343e-02
  4.82834735e+03  1.76642214e-01]
[ 6.62231617e-02  5.47749497e+03  2.05854359e-01 -4.81054728e-02
  4.63302653e+03  1.71274231e-01]
[ 8.22183259e-02  7.87340712e+03  2.05107260e-01 -8.40056334e-02
  3.91037092e+03  2.04703333e-01]
[ 6.69693430e-02  6.47741689e+03  1.92450068e-01 -5.65659622e-02
  4.42157293e+03  1.72571151e-01]
[ 7.05177955e-02  5.82191747e+03  2.09248162e-01 -5.30113303e-02
  4.61527477e+03  1.76700577e-01]
[ 6.76118983e-02  5.90203662e+03  1.96803939e-01 -5.51106652e-02
  4.74988644e+03  1.73322632e-01]
[ 6.85513580e-02  5.31421910e+03  2.11600928e-01 -4.87395212e-02
  4.62126826e+03  1.73918710e-01]
[ 6.56663074e-02  5.49051165e+03  1.98620726e-01 -5.46820679e-02
  4.85211700e+03  1.78341831e-01]
[ 6.43771357e-02  5.74930459e+03  1.95127944e-01 -5.44050822e-02
  4.65689042e+03  1.75365196e-01]
[ 7.07325484e-02  6.09006018e+03  2.00416848e-01 -5.60656392e-02
  4.60514375e+03  1.75895878e-01]
[ 6.40547578e-02  4.89651411e+03  2.48470427e-01 -3.78183554e-02
  3.95148159e+03  1.82806597e-01]
[ 6.09633995e-02  5.46680828e+03  2.24012892e-01 -4.55267772e-02
  3.63543248e+03  1.87990107e-01]
[ 6.12890916e-02  4.56931340e+03  2.43971646e-01 -3.98568814e-02
  4.03057631e+03  1.90589131e-01]
[ 6.75625687e-02  6.13723646e+03  1.95500986e-01 -5.22638487e-02
  4.63590281e+03  1.67279720e-01]
[ 6.83062899e-02  6.12033209e+03  1.98988299e-01 -5.29302173e-02
  4.56225929e+03  1.71493911e-01]
[ 6.55227079e-02  5.51720065e+03  1.96396557e-01 -5.41821392e-02
  4.89548729e+03  1.74217393e-01]
[ 4.88824715e-02  4.83315064e+03  2.64339072e-01 -2.55110431e-02
  3.13707942e+03  1.81756048e-01]
[ 5.92862593e-02  4.72494292e+03  2.19116446e-01 -4.35271827e-02
  4.49063169e+03  1.81162528e-01]
[ 6.17100482e-02  4.97236100e+03  2.03161156e-01 -4.88621338e-02
  4.85531887e+03  1.77433206e-01]
[ 5.98215850e-02  4.65051311e+03  2.17183250e-01 -4.38209774e-02
  4.47647883e+03  1.82991891e-01]
[ 5.49587036e-02  4.47613700e+03  2.30744946e-01 -4.95239633e-02
  3.13500910e+03  2.22445533e-01]
[ 4.20987252e-02  4.29382959e+03  2.81026597e-01 -1.93471244e-02
  2.99393762e+03  1.78348657e-01]
[ 3.90424080e-02  4.25366418e+03  2.67481428e-01 -2.07010865e-02
  2.94343252e+03  1.86559981e-01]
[ 5.74270473e-02  7.05727875e+03  2.30905585e-01 -4.05108417e-02
  2.77499906e+03  1.87113693e-01]
[ 5.84887142e-02  4.77696522e+03  2.14308458e-01 -4.50424840e-02
  4.49952360e+03  1.83415871e-01]
[ 5.55715272e-02  5.50325315e+03  2.33980265e-01 -3.85144127e-02
  3.44093357e+03  1.86520272e-01]
[ 5.14990110e-02  4.11012086e+03  2.74435120e-01 -2.67742537e-02
  3.00782867e+03  1.82437678e-01]
[ 3.24334266e-02  4.20278181e+03  2.48921173e-01 -2.58516054e-02
  2.94980079e+03  2.18195050e-01]
[ 5.71802177e-02  4.72588092e+03  2.61743208e-01 -3.11795978e-02
  3.29165616e+03  1.83769594e-01]
[ 5.90765245e-02  4.41030671e+03  2.63004403e-01 -3.27722477e-02
  3.16890455e+03  1.82007473e-01]
[ 4.76327422e-02  3.99944060e+03  2.63830337e-01 -2.87103909e-02
  2.81037994e+03  1.94376835e-01]
[ 6.16864615e-02  4.51623205e+03  2.21969952e-01 -6.28028230e-02
  2.73008069e+03  2.26930146e-01]
[ 4.49690066e-02  3.81839382e+03  2.35711508e-01 -3.79473148e-02
  2.83568686e+03  2.16960162e-01]
[ 4.03109414e-02  4.27408779e+03  2.75600359e-01 -2.10619694e-02
  3.09461302e+03  1.84098150e-01]
[ 5.14757616e-02  4.38815517e+03  2.75048532e-01 -2.76837676e-02
  3.10337777e+03  1.93570909e-01]
[ 7.27693365e-02  4.46137850e+03  3.39187024e-01 -2.00739231e-02
  3.22146353e+03  1.63356101e-01]
[ 3.83970218e-02  3.75299198e+03  3.12718548e-01 -1.50738247e-02
  2.65955143e+03  1.72866744e-01]
[ 6.86584714e-02  4.32916750e+03  2.59770632e-01 -3.37763147e-02
  2.99669432e+03  1.74279223e-01]
[ 3.95956419e-02  4.07825052e+03  3.01203457e-01 -1.46396752e-02
  2.90948230e+03  1.73131334e-01]
[ 3.85228684e-02  3.85794041e+03  3.01348827e-01 -1.61295841e-02
  2.71396269e+03  1.76119786e-01]
[ 4.36078883e-02  3.67791404e+03  2.74391917e-01 -2.26160638e-02
  2.69197645e+03  1.87572265e-01]
[ 7.95807487e-02  5.40535962e+03  1.72836124e-01 -1.09466775e-01
  3.95350462e+03  2.00339957e-01]
[ 5.66891787e-02  3.72808615e+03  2.89832322e-01 -2.30327415e-02
  2.63640291e+03  1.72020047e-01]
[ 3.55672519e-02  3.89121366e+03  3.01079871e-01 -1.52257076e-02
  2.73044738e+03  1.76185718e-01]
[ 4.53117932e-02  4.05187149e+03  2.63650930e-01 -2.60322091e-02
  2.88795083e+03  1.93420845e-01]
[ 4.06603892e-02  4.00824070e+03  3.07914620e-01 -1.43323409e-02
  2.77089529e+03  1.72587035e-01]
[ 4.03202286e-02  3.54267278e+03  3.09620960e-01 -1.43560164e-02
  2.58344585e+03  1.68750165e-01]
[ 3.92918122e-02  3.59861500e+03  3.10063435e-01 -1.52342711e-02
  2.56365671e+03  1.83856587e-01]
[ 4.37984627e-02  3.75198308e+03  3.05861909e-01 -1.67356207e-02
  2.71200773e+03  1.73817829e-01]
[ 4.84826089e-02  3.65153535e+03  2.82056052e-01 -2.24691509e-02
  2.69440414e+03  1.82904807e-01]
[ 4.28457012e-02  3.87994709e+03  3.21233905e-01 -1.44219909e-02
  2.27909731e+03  1.68457580e-01]
[ 4.98419477e-02  4.29916870e+03  1.79458608e-01 -1.05671680e-01
  2.75913458e+03  2.76775599e-01]
[ 4.46354604e-02  3.37743979e+03  2.99396748e-01 -1.74288331e-02
  2.45681810e+03  1.75743450e-01]
[ 3.93076640e-02  3.74276228e+03  3.02026924e-01 -1.46634165e-02
  2.58756591e+03  1.72687605e-01]
[ 3.00156411e-02  3.58030535e+03  3.04777681e-01 -1.31494244e-02
  2.56782746e+03  1.84212403e-01]
[ 6.32018219e-02  3.94382634e+03  2.92590178e-01 -2.84021785e-02
  2.63819756e+03  1.80245025e-01]
[ 3.07268435e-02  3.24439911e+03  2.63085667e-01 -2.11473313e-02
  2.32456439e+03  2.19561621e-01]
[ 5.11327364e-02  3.55390444e+03  3.19130249e-01 -1.87187913e-02
  2.52237515e+03  1.71798319e-01]
[ 6.77751167e-02  3.56056107e+03  3.53856816e-01 -1.91533829e-02
  2.57155792e+03  1.71395988e-01]
[ 5.52526376e-02  3.64563896e+03  2.98365541e-01 -2.42463899e-02
  2.43722142e+03  1.76070527e-01]
[ 4.57592532e-02  3.54536981e+03  3.12010978e-01 -1.60119634e-02
  2.32854784e+03  1.71442057e-01]
[ 6.43110531e-02  2.93899212e+03  2.94213237e-01 -5.42155618e-02
  2.32244961e+03  2.69907579e-01]
[ 5.44617515e-02  3.16940164e+03  3.36870336e-01 -1.74343073e-02
  2.28088419e+03  1.77666041e-01]
[ 4.55986290e-02  3.47910343e+03  3.13202054e-01 -1.53647777e-02
  2.57120776e+03  1.67613896e-01]
[ 3.67587385e-02  3.42044590e+03  2.85187955e-01 -1.72873675e-02
  2.49793470e+03  1.86155001e-01]
[ 3.90702694e-02  3.53052537e+03  3.09183388e-01 -1.46606205e-02
  2.55466776e+03  1.72702961e-01]
[ 4.50571864e-02  3.41016115e+03  2.43402682e-01 -3.82871149e-02
  2.19648816e+03  2.27337248e-01]
[ 4.79847411e-02  3.41023974e+03  3.06232851e-01 -1.77373947e-02
  2.41478429e+03  1.70954724e-01]
[ 4.52086427e-02  3.44615883e+03  3.03251203e-01 -1.78517391e-02
  2.43072865e+03  1.76794409e-01]
[ 3.51354713e-02  2.78554318e+03  2.78406497e-01 -1.89318610e-02
  2.62260020e+03  1.93884693e-01]
[ 3.82350396e-02  3.17640304e+03  2.99484342e-01 -1.69094930e-02
  2.26036559e+03  1.85150782e-01]
[ 3.06479200e-02  3.00845451e+03  3.24654219e-01 -1.13989899e-02
  2.14646170e+03  1.77060504e-01]
[ 3.79865815e-02  3.15553278e+03  3.11347933e-01 -1.37329887e-02
  2.17381820e+03  1.72145281e-01]
[ 4.46953922e-02  3.24805484e+03  3.24756688e-01 -1.45324786e-02
  2.41856387e+03  1.68319156e-01]
[ 4.50063965e-02  3.35501979e+03  3.34790260e-01 -1.32011608e-02
  2.34751635e+03  1.66246685e-01]
[ 3.47932607e-02  4.45450743e+03  3.46158776e-01 -1.06126082e-02
  1.77494707e+03  1.63269847e-01]
[ 2.55044790e-02  2.93668730e+03  2.25557341e-01 -3.14044318e-02
  2.05050509e+03  2.72177204e-01]
[ 2.86772092e-02  3.03888295e+03  2.96854827e-01 -1.45988483e-02
  2.18803281e+03  1.95085785e-01]
[ 3.76314819e-02  3.43679108e+03  3.17737809e-01 -1.43514005e-02
  2.13356286e+03  1.74398180e-01]
[ 4.29946839e-02  3.12196742e+03  3.33303874e-01 -1.35932901e-02
  2.19135652e+03  1.69216099e-01]
[ 3.26110417e-02  3.01765104e+03  3.08710978e-01 -1.25171647e-02
  2.15605348e+03  1.77918117e-01]
[ 4.51750926e-02  3.05198245e+03  2.21625896e-01 -5.99106299e-02
  2.14073505e+03  2.69450412e-01]
[ 5.30518913e-02  2.98215835e+03  3.44273320e-01 -1.68104993e-02
  2.15105332e+03  1.67860039e-01]
[ 4.19531029e-02  3.14733518e+03  3.04366475e-01 -1.68133893e-02
  2.26088556e+03  1.77759014e-01]
[ 4.22684508e-02  3.12034457e+03  3.09989691e-01 -1.63226674e-02
  2.23443181e+03  1.81891089e-01]
[ 4.36801118e-02  3.22171803e+03  3.35819649e-01 -1.51221867e-02
  2.27832662e+03  1.67573166e-01]
Loading...
<Figure size 640x480 with 2 Axes>
Loading...
for dset in infoWidget.datasets.values():
    if isinstance(dset, sidpy.Dataset):
        if 'Measurement' in dset.title:
            dset.title = dset.title.split('/')[-1]

            print(dset.title)
infoWidget.low_loss.get_drude()
print(infoWidget.datasets.keys())
dat ={ 'Channel_000': infoWidget.datasets['Channel_000'], 
       '_relationship': infoWidget.datasets['_relationship'],
       'plasmon': infoWidget.datasets['plasmon']}
dict_keys(['Channel_000', '_relationship', 'shifted_low_loss', 'zero_loss', 'plasmon', 'low_loss_model'])
infoWidget.datasets['plasmon'].metadata['zero_loss'].keys()
dict_keys(['shifted', 'parameter', 'startFitEnergy', 'endFitEnergy', 'fit_parameter', 'original_low_loss', (0, 0), (20, 6), '0,0', '0,1', '0,2', '0,3', '0,4', '0,5', '0,6', '0,7', '0,8', '0,9', '1,0', '1,1', '1,2', '1,3', '1,4', '1,5', '1,6', '1,7', '1,8', '1,9', '2,0', '2,1', '2,2', '2,3', '2,4', '2,5', '2,6', '2,7', '2,8', '2,9', '3,0', '3,1', '3,2', '3,3', '3,4', '3,5', '3,6', '3,7', '3,8', '3,9', '4,0', '4,1', '4,2', '4,3', '4,4', '4,5', '4,6', '4,7', '4,8', '4,9', '5,0', '5,1', '5,2', '5,3', '5,4', '5,5', '5,6', '5,7', '5,8', '5,9', '6,0', '6,1', '6,2', '6,3', '6,4', '6,5', '6,6', '6,7', '6,8', '6,9', '7,0', '7,1', '7,2', '7,3', '7,4', '7,5', '7,6', '7,7', '7,8', '7,9', '8,0', '8,1', '8,2', '8,3', '8,4', '8,5', '8,6', '8,7', '8,8', '8,9', '9,0', '9,1', '9,2', '9,3', '9,4', '9,5', '9,6', '9,7', '9,8', '9,9', '10,0', '10,1', '10,2', '10,3', '10,4', '10,5', '10,6', '10,7', '10,8', '10,9', '11,0', '11,1', '11,2', '11,3', '11,4', '11,5', '11,6', '11,7', '11,8', '11,9', '12,0', '12,1', '12,2', '12,3', '12,4', '12,5', '12,6', '12,7', '12,8', '12,9', '13,0', '13,1', '13,2', '13,3', '13,4', '13,5', '13,6', '13,7', '13,8', '13,9', '14,0', '14,1', '14,2', '14,3', '14,4', '14,5', '14,6', '14,7', '14,8', '14,9', '15,0', '15,1', '15,2', '15,3', '15,4', '15,5', '15,6', '15,7', '15,8', '15,9', '16,0', '16,1', '16,2', '16,3', '16,4', '16,5', '16,6', '16,7', '16,8', '16,9', '17,0', '17,1', '17,2', '17,3', '17,4', '17,5', '17,6', '17,7', '17,8', '17,9', '18,0', '18,1', '18,2', '18,3', '18,4', '18,5', '18,6', '18,7', '18,8', '18,9', '19,0', '19,1', '19,2', '19,3', '19,4', '19,5', '19,6', '19,7', '19,8', '19,9', '20,0', '20,1', '20,2', '20,3', '20,4', '20,5', '20,6', '20,7', '20,8', '20,9', '21,0', '21,1', '21,2', '21,3', '21,4', '21,5', '21,6', '21,7', '21,8', '21,9', '22,0', '22,1', '22,2', '22,3', '22,4', '22,5', '22,6', '22,7', '22,8', '22,9', '23,0', '23,1', '23,2', '23,3', '23,4', '23,5', '23,6', '23,7', '23,8', '23,9', '24,0', '24,1', '24,2', '24,3', '24,4', '24,5', '24,6', '24,7', '24,8', '24,9'])
g =pyTEMlib.file_tools.save_dataset(infoWidget.datasets, '11_si.hf5')
Cannot overwrite file. Using:  11_si-1.hf5
c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\pyNSID\io\hdf_io.py:111: UserWarning: main_data_name should not contain the "-" character. Reformatted name from:11-eels to 11_eels
  warn('main_data_name should not contain the "-" character. Reformatted'
c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\pyNSID\io\hdf_utils.py:381: FutureWarning: validate_h5_dimension may be removed in a future version
  warn('validate_h5_dimension may be removed in a future version',
c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\pyNSID\io\hdf_io.py:111: UserWarning: main_data_name should not contain the "-" character. Reformatted name from:11-eels_new to 11_eels_new
  warn('main_data_name should not contain the "-" character. Reformatted'
c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../../../sidpy\sidpy\hdf\hdf_utils.py:387: UserWarning: Converted key: (0, 0) from type: <class 'tuple'> to str
  warn('Converted key: {} from type: {} to str'
c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../../../sidpy\sidpy\hdf\hdf_utils.py:387: UserWarning: Converted key: (19, 2) from type: <class 'tuple'> to str
  warn('Converted key: {} from type: {} to str'
c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\pyNSID\io\hdf_utils.py:381: FutureWarning: validate_h5_dimension may be removed in a future version
  warn('validate_h5_dimension may be removed in a future version',
c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\pyNSID\io\hdf_io.py:111: UserWarning: main_data_name should not contain the "-" character. Reformatted name from:11-eels_new_new to 11_eels_new_new
  warn('main_data_name should not contain the "-" character. Reformatted'
c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../../../sidpy\sidpy\hdf\hdf_utils.py:387: UserWarning: Converted key: (19, 2) from type: <class 'tuple'> to str
  warn('Converted key: {} from type: {} to str'
c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\pyNSID\io\hdf_utils.py:381: FutureWarning: validate_h5_dimension may be removed in a future version
  warn('validate_h5_dimension may be removed in a future version',
c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\pyNSID\io\hdf_io.py:111: UserWarning: main_data_name should not contain the "-" character. Reformatted name from:11-eels_new_new to 11_eels_new_new
  warn('main_data_name should not contain the "-" character. Reformatted'
c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../../../sidpy\sidpy\hdf\hdf_utils.py:387: UserWarning: Converted key: (0, 0) from type: <class 'tuple'> to str
  warn('Converted key: {} from type: {} to str'
c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../../../sidpy\sidpy\hdf\hdf_utils.py:387: UserWarning: Converted key: (19, 2) from type: <class 'tuple'> to str
  warn('Converted key: {} from type: {} to str'
c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\pyNSID\io\hdf_utils.py:381: FutureWarning: validate_h5_dimension may be removed in a future version
  warn('validate_h5_dimension may be removed in a future version',
c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\pyNSID\io\hdf_io.py:111: UserWarning: main_data_name should not contain the "-" character. Reformatted name from:11-eels_new_new to 11_eels_new_new
  warn('main_data_name should not contain the "-" character. Reformatted'
c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../../../sidpy\sidpy\hdf\hdf_utils.py:387: UserWarning: Converted key: (0, 0) from type: <class 'tuple'> to str
  warn('Converted key: {} from type: {} to str'
c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../../../sidpy\sidpy\hdf\hdf_utils.py:387: UserWarning: Converted key: (19, 2) from type: <class 'tuple'> to str
  warn('Converted key: {} from type: {} to str'
c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\pyNSID\io\hdf_utils.py:381: FutureWarning: validate_h5_dimension may be removed in a future version
  warn('validate_h5_dimension may be removed in a future version',
g.file.close()
dir(g)
['_MutableMapping__marker', '__abstractmethods__', '__bool__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__ne__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__setitem__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '__weakref__', '_abc_impl', '_d', '_e', '_gcpl_crt_order', '_id', '_ipython_key_completions_', '_lapl', '_lcpl', 'attrs', 'build_virtual_dataset', 'clear', 'copy', 'create_dataset', 'create_dataset_like', 'create_group', 'create_virtual_dataset', 'file', 'get', 'id', 'items', 'keys', 'move', 'name', 'parent', 'pop', 'popitem', 'ref', 'regionref', 'require_dataset', 'require_group', 'setdefault', 'update', 'values', 'visit', 'visit_links', 'visititems', 'visititems_links']
infoWidget.datasets[infoWidget.datasets['_relationship']['low_loss']].metadata
{'experiment': {'single_exposure_time': 0.1, 'number_of_frames': 1, 'collection_angle': 100.0, 'convergence_angle': 0.0, 'exposure_time': 0.1, 'microscope': '', 'acceleration_voltage': 199990.28125, 'flux_ppm': 90.36209375, 'count_conversion': 1, 'beam_current': 0}, 'annotations': {'0': {'type': 'spectral_image', 'label': '1', 'width': 0.004483174532651901, 'height': 0.04483174532651901, 'position': [0.07173079252243042, 0.0], 'Rectangle': array([ 0., 16., 10., 17.])}}, 'zero_loss': {'shifted': array([[-0.17133928, -0.20872347, -0.15697378, -0.22911345, -0.41304692, -0.27802566, -0.28852486, -0.19660906, -0.24778839, -0.29709778], [-0.17452395, -0.25264281, -0.19338031, -0.22475387, -0.3867537 , -0.26830998, -0.30173948, -0.18973434, -0.24055065, -0.27581737], [-0.18777319, -0.21813711, -0.23541803, -0.25136158, -0.37223943, -0.28151478, -0.27689985, -0.20720506, -0.20844662, -0.26624501], [-0.19766428, -0.22570338, -0.2310333 , -0.25888585, -0.36432819, -0.26848219, -0.29230228, -0.23995783, -0.25165612, -0.29044124], [-0.16309471, -0.20200637, -0.22812651, -0.24042406, -0.39094313, -0.29055997, -0.27075889, -0.18784859, -0.2146395 , -0.332887 ], [-0.18236734, -0.18087611, -0.22866335, -0.21551541, -0.36639231, -0.29861265, -0.2925165 , -0.24927491, -0.20851182, -0.28348217], [-0.19927829, -0.22898982, -0.26191095, -0.22834547, -0.36971682, -0.30889951, -0.3012673 , -0.24113467, -0.17493781, -0.32168681], [-0.1738958 , -0.1913216 , -0.21929859, -0.24915983, -0.3876799 , -0.30038999, -0.20116385, -0.26177179, -0.18331803, -0.34600463], [-0.13096981, -0.2006438 , -0.21227983, -0.21064573, -0.33160388, -0.36483439, -0.24456268, -0.26444754, -0.14945136, -0.28794927], [-0.1462392 , -0.25174427, -0.19415191, -0.25038362, -0.35794843, -0.30022434, -0.21339795, -0.23672159, -0.24448357, -0.27052469], [-0.14685874, -0.17460282, -0.16165857, -0.22823609, -0.35877969, -0.33408546, -0.24722202, -0.21119665, -0.22090627, -0.28490726], [-0.16866301, -0.15241837, -0.16493974, -0.27075112, -0.32254401, -0.31866055, -0.24792923, -0.23735904, -0.20442612, -0.30334064], [-0.16050684, -0.14049517, -0.20804801, -0.25107936, -0.35387663, -0.30954754, -0.20522215, -0.20693605, -0.21926198, -0.27534069], [-0.17034575, -0.12584347, -0.24092053, -0.31105879, -0.33426595, -0.30892898, -0.1836695 , -0.22767377, -0.2596248 , -0.24581365], [-0.22159879, -0.12982051, -0.20819836, -0.27049065, -0.34958568, -0.31558961, -0.19452586, -0.21314073, -0.24035954, -0.2328248 ], [-0.2032972 , -0.14719534, -0.19907061, -0.2462344 , -0.31856248, -0.3517771 , -0.20909715, -0.23441361, -0.25507181, -0.25137647], [-0.17083077, -0.15719943, -0.2197162 , -0.28521577, -0.31527722, -0.33289726, -0.18606309, -0.19628289, -0.25623027, -0.23231349], [-0.12688726, -0.17655356, -0.19887589, -0.29611456, -0.37989474, -0.32507459, -0.22918826, -0.21149825, -0.21018903, -0.2608516 ], [-0.18858283, -0.17266317, -0.20583162, -0.29928345, -0.3205138 , -0.34542016, -0.25208158, -0.26567733, -0.19913084, -0.2670854 ], [-0.20338365, -0.18022165, -0.22180157, -0.29435486, -0.35585983, -0.37953179, -0.17357063, -0.20438077, -0.22438605, -0.24467854], [-0.2061708 , -0.21012867, -0.24347788, -0.29475718, -0.34663862, -0.41550053, -0.18316705, -0.23659631, -0.24869219, -0.21216895], [-0.22316636, -0.21843133, -0.19459794, -0.30371964, -0.31803614, -0.36346566, -0.1827611 , -0.24550804, -0.26715442, -0.23049209], [-0.22549864, -0.20233576, -0.25172761, -0.32813819, -0.33494639, -0.41605422, -0.182917 , -0.18322456, -0.28218851, -0.22714036], [-0.22792804, -0.18826536, -0.25218583, -0.29268463, -0.32082594, -0.32751488, -0.16049068, -0.19076274, -0.2756469 , -0.23645988], [-0.17985229, -0.17842844, -0.20377253, -0.31785076, -0.34848329, -0.41367577, -0.17336046, -0.16275926, -0.30444214, -0.2085971 ]]), 'startFitEnergy': -0.5, 'endFitEnergy': 0.5, 'fit_parameter': array([-1.51221768e-02, 2.67527012e+03, 1.67573156e-01, 4.36801062e-02, 2.74369530e+03, 3.35819747e-01]), 'original_low_loss': '11-eels_new_new', '0-0': {...}, '0,0': {...}, '0,1': {...}, '0,2': {...}, '0,3': {...}, '0,4': {...}, '0,5': {...}, '0,6': {...}, '0,7': {...}, '0,8': {...}, '0,9': {...}, '1,0': {...}, '1,1': {...}, '1,2': {...}, '1,3': {...}, '1,4': {...}, '1,5': {...}, '1,6': {...}, '1,7': {...}, '1,8': {...}, '1,9': {...}, '2,0': {...}, '2,1': {...}, '2,2': {...}, '2,3': {...}, '2,4': {...}, '2,5': {...}, '2,6': {...}, '2,7': {...}, '2,8': {...}, '2,9': {...}, '3,0': {...}, '3,1': {...}, '3,2': {...}, '3,3': {...}, '3,4': {...}, '3,5': {...}, '3,6': {...}, '3,7': {...}, '3,8': {...}, '3,9': {...}, '4,0': {...}, '4,1': {...}, '4,2': {...}, '4,3': {...}, '4,4': {...}, '4,5': {...}, '4,6': {...}, '4,7': {...}, '4,8': {...}, '4,9': {...}, '5,0': {...}, '5,1': {...}, '5,2': {...}, '5,3': {...}, '5,4': {...}, '5,5': {...}, '5,6': {...}, '5,7': {...}, '5,8': {...}, '5,9': {...}, '6,0': {...}, '6,1': {...}, '6,2': {...}, '6,3': {...}, '6,4': {...}, '6,5': {...}, '6,6': {...}, '6,7': {...}, '6,8': {...}, '6,9': {...}, '7,0': {...}, '7,1': {...}, '7,2': {...}, '7,3': {...}, '7,4': {...}, '7,5': {...}, '7,6': {...}, '7,7': {...}, '7,8': {...}, '7,9': {...}, '8,0': {...}, '8,1': {...}, '8,2': {...}, '8,3': {...}, '8,4': {...}, '8,5': {...}, '8,6': {...}, '8,7': {...}, '8,8': {...}, '8,9': {...}, '9,0': {...}, '9,1': {...}, '9,2': {...}, '9,3': {...}, '9,4': {...}, '9,5': {...}, '9,6': {...}, '9,7': {...}, '9,8': {...}, '9,9': {...}, '10,0': {...}, '10,1': {...}, '10,2': {...}, '10,3': {...}, '10,4': {...}, '10,5': {...}, '10,6': {...}, '10,7': {...}, '10,8': {...}, '10,9': {...}, '11,0': {...}, '11,1': {...}, '11,2': {...}, '11,3': {...}, '11,4': {...}, '11,5': {...}, '11,6': {...}, '11,7': {...}, '11,8': {...}, '11,9': {...}, '12,0': {...}, '12,1': {...}, '12,2': {...}, '12,3': {...}, '12,4': {...}, '12,5': {...}, '12,6': {...}, '12,7': {...}, '12,8': {...}, '12,9': {...}, '13,0': {...}, '13,1': {...}, '13,2': {...}, '13,3': {...}, '13,4': {...}, '13,5': {...}, '13,6': {...}, '13,7': {...}, '13,8': {...}, '13,9': {...}, '14,0': {...}, '14,1': {...}, '14,2': {...}, '14,3': {...}, '14,4': {...}, '14,5': {...}, '14,6': {...}, '14,7': {...}, '14,8': {...}, '14,9': {...}, '15,0': {...}, '15,1': {...}, '15,2': {...}, '15,3': {...}, '15,4': {...}, '15,5': {...}, '15,6': {...}, '15,7': {...}, '15,8': {...}, '15,9': {...}, '16,0': {...}, '16,1': {...}, '16,2': {...}, '16,3': {...}, '16,4': {...}, '16,5': {...}, '16,6': {...}, '16,7': {...}, '16,8': {...}, '16,9': {...}, '17,0': {...}, '17,1': {...}, '17,2': {...}, '17,3': {...}, '17,4': {...}, '17,5': {...}, '17,6': {...}, '17,7': {...}, '17,8': {...}, '17,9': {...}, '18,0': {...}, '18,1': {...}, '18,2': {...}, '18,3': {...}, '18,4': {...}, '18,5': {...}, '18,6': {...}, '18,7': {...}, '18,8': {...}, '18,9': {...}, '19,0': {...}, '19,1': {...}, '19,2': {...}, '19,3': {...}, '19,4': {...}, '19,5': {...}, '19,6': {...}, '19,7': {...}, '19,8': {...}, '19,9': {...}, '20,0': {...}, '20,1': {...}, '20,2': {...}, '20,3': {...}, '20,4': {...}, '20,5': {...}, '20,6': {...}, '20,7': {...}, '20,8': {...}, '20,9': {...}, '21,0': {...}, '21,1': {...}, '21,2': {...}, '21,3': {...}, '21,4': {...}, '21,5': {...}, '21,6': {...}, '21,7': {...}, '21,8': {...}, '21,9': {...}, '22,0': {...}, '22,1': {...}, '22,2': {...}, '22,3': {...}, '22,4': {...}, '22,5': {...}, '22,6': {...}, '22,7': {...}, '22,8': {...}, '22,9': {...}, '23,0': {...}, '23,1': {...}, '23,2': {...}, '23,3': {...}, '23,4': {...}, '23,5': {...}, '23,6': {...}, '23,7': {...}, '23,8': {...}, '23,9': {...}, '24,0': {...}, '24,1': {...}, '24,2': {...}, '24,3': {...}, '24,4': {...}, '24,5': {...}, '24,6': {...}, '24,7': {...}, '24,8': {...}, '24,9': {...}}}
infoWidget.low_loss.get_multiple_scattering()
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
Cell In[20], line 1
----> 1 infoWidget.low_loss.get_multiple_scattering()

File c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\low_loss_widget.py:281, in get_multiple_scattering(self, value)
      0 <Error retrieving source code with stack_data see ipython/ipython#13598>

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:716, in TraitType.__set__(self, obj, value)
    714 if self.read_only:
    715     raise TraitError('The "%s" trait is read-only.' % self.name)
--> 716 self.set(obj, value)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:706, in TraitType.set(self, obj, value)
    702     silent = False
    703 if silent is not True:
    704     # we explicitly compare silent to True just in case the equality
    705     # comparison above returns something other than True/False
--> 706     obj._notify_trait(self.name, old_value, new_value)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1513, in HasTraits._notify_trait(self, name, old_value, new_value)
   1512 def _notify_trait(self, name: str, old_value: t.Any, new_value: t.Any) -> None:
-> 1513     self.notify_change(
   1514         Bunch(
   1515             name=name,
   1516             old=old_value,
   1517             new=new_value,
   1518             owner=self,
   1519             type="change",
   1520         )
   1521     )

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\ipywidgets\widgets\widget.py:687, in Widget.notify_change(self, change)
    684     if name in self.keys and self._should_send_property(name, getattr(self, name)):
    685         # Send new state to front-end
    686         self.send_state(key=name)
--> 687 super(Widget, self).notify_change(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1525, in HasTraits.notify_change(self, change)
   1523 def notify_change(self, change: Bunch) -> None:
   1524     """Notify observers of a change event"""
-> 1525     return self._notify_observers(change)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\traitlets\traitlets.py:1568, in HasTraits._notify_observers(self, event)
   1565 elif isinstance(c, EventHandler) and c.name is not None:
   1566     c = getattr(self, c.name)
-> 1568 c(event)

File c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget.py:507, in EELSBaseWidget._update(self, ev)
    505 self.axis.set_ylabel(self.ylabel)
    506 self.change_y_scale = 1.0
--> 507 self.update_tab_spectra()
    508 self.figure.canvas.draw_idle()

File c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\info_widget.py:818, in EELSWidget.update_tab_spectra(self)
    816 def update_tab_spectra(self):
    817     if self.tabval == 2:
--> 818         self.low_loss._update()

File c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\low_loss_widget.py:334, in LowLoss._update(self, ev)
    332         difference -= plasmon
    333 if self.low_loss_tab[3, 0].value + self.low_loss_tab[10, 0].value + self.low_loss_tab[15, 0].value > 0:
--> 334     self.parent.axis.plot(self.parent.energy_scale, difference, label='difference')               
    335     self.parent.axis.legend()

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\matplotlib\axes\_axes.py:1779, in Axes.plot(self, scalex, scaley, data, *args, **kwargs)
   1536 """
   1537 Plot y versus x as lines and/or markers.
   1538 
   (...)
   1776 (``'green'``) or hex strings (``'#008000'``).
   1777 """
   1778 kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
-> 1779 lines = [*self._get_lines(self, *args, data=data, **kwargs)]
   1780 for line in lines:
   1781     self.add_line(line)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\matplotlib\axes\_base.py:296, in _process_plot_var_args.__call__(self, axes, data, *args, **kwargs)
    294     this += args[0],
    295     args = args[1:]
--> 296 yield from self._plot_args(
    297     axes, this, kwargs, ambiguous_fmt_datakey=ambiguous_fmt_datakey)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\matplotlib\axes\_base.py:483, in _process_plot_var_args._plot_args(self, axes, tup, kwargs, return_kwargs, ambiguous_fmt_datakey)
    481     axes.xaxis.update_units(x)
    482 if axes.yaxis is not None:
--> 483     axes.yaxis.update_units(y)
    485 if x.shape[0] != y.shape[0]:
    486     raise ValueError(f"x and y must have same first dimension, but "
    487                      f"have shapes {x.shape} and {y.shape}")

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\matplotlib\axis.py:1750, in Axis.update_units(self, data)
   1744 def update_units(self, data):
   1745     """
   1746     Introspect *data* for units converter and update the
   1747     ``axis.converter`` instance if necessary. Return *True*
   1748     if *data* is registered for unit conversion.
   1749     """
-> 1750     converter = munits.registry.get_converter(data)
   1751     if converter is None:
   1752         return False

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\matplotlib\units.py:183, in Registry.get_converter(self, x)
    181         pass
    182 try:  # If cache lookup fails, look up based on first element...
--> 183     first = cbook._safe_first_finite(x)
    184 except (TypeError, StopIteration):
    185     pass

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\matplotlib\cbook.py:1782, in _safe_first_finite(obj)
   1780 else:
   1781     for val in obj:
-> 1782         if safe_isfinite(val):
   1783             return val
   1784     return safe_first_element(obj)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\matplotlib\cbook.py:1762, in _safe_first_finite.<locals>.safe_isfinite(val)
   1760     return False
   1761 try:
-> 1762     return math.isfinite(val)
   1763 except (TypeError, ValueError):
   1764     # if the outer object is 2d, then val is a 1d array, and
   1765     # - math.isfinite(numpy.zeros(3)) raises TypeError
   1766     # - math.isfinite(torch.zeros(3)) raises ValueError
   1767     pass

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\dask\array\core.py:1883, in Array.__float__(self)
   1882 def __float__(self):
-> 1883     return self._scalarfunc(float)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\dask\array\core.py:1875, in Array._scalarfunc(self, cast_type)
   1873     raise TypeError("Only length-1 arrays can be converted to Python scalars")
   1874 else:
-> 1875     return cast_type(self.compute().item())

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\dask\base.py:375, in DaskMethodsMixin.compute(self, **kwargs)
    351 def compute(self, **kwargs):
    352     """Compute this dask collection
    353 
    354     This turns a lazy Dask collection into its in-memory equivalent.
   (...)
    373     dask.compute
    374     """
--> 375     (result,) = compute(self, traverse=False, **kwargs)
    376     return result

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\dask\base.py:654, in compute(traverse, optimize_graph, scheduler, get, *args, **kwargs)
    646     return args
    648 schedule = get_scheduler(
    649     scheduler=scheduler,
    650     collections=collections,
    651     get=get,
    652 )
--> 654 dsk = collections_to_dsk(collections, optimize_graph, **kwargs)
    655 keys, postcomputes = [], []
    656 for x in collections:

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\dask\base.py:427, in collections_to_dsk(collections, optimize_graph, optimizations, **kwargs)
    425 for opt, val in groups.items():
    426     dsk, keys = _extract_graph_and_keys(val)
--> 427     dsk = opt(dsk, keys, **kwargs)
    429     for opt_inner in optimizations:
    430         dsk = opt_inner(dsk, keys, **kwargs)

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\dask\array\optimization.py:51, in optimize(dsk, keys, fuse_keys, fast_functions, inline_functions_fast_functions, rename_fused_keys, **kwargs)
     49 dsk = optimize_blockwise(dsk, keys=keys)
     50 dsk = fuse_roots(dsk, keys=keys)
---> 51 dsk = dsk.cull(set(keys))
     53 # Perform low-level fusion unless the user has
     54 # specified False explicitly.
     55 if config.get("optimization.fuse.active") is False:

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\dask\highlevelgraph.py:738, in HighLevelGraph.cull(self, keys)
    736 output_keys = keys_set.intersection(layer.get_output_keys())
    737 if output_keys:
--> 738     culled_layer, culled_deps = layer.cull(output_keys, all_ext_keys)
    739     # Update `keys` with all layer's external key dependencies, which
    740     # are all the layer's dependencies (`culled_deps`) excluding
    741     # the layer's output keys.
    742     external_deps = set()

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\dask\highlevelgraph.py:154, in Layer.cull(self, keys, all_hlg_keys)
    152 k = work.pop()
    153 out[k] = self[k]
--> 154 ret_deps[k] = self.get_dependencies(k, all_hlg_keys)
    155 for d in ret_deps[k]:
    156     if d not in seen:

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\dask\highlevelgraph.py:178, in Layer.get_dependencies(self, key, all_hlg_keys)
    163 def get_dependencies(self, key: Key, all_hlg_keys: Collection[Key]) -> set:
    164     """Get dependencies of `key` in the layer
    165 
    166     Parameters
   (...)
    176         A set of dependencies
    177     """
--> 178     return keys_in_tasks(all_hlg_keys, [self[key]])

File c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\dask\core.py:199, in keys_in_tasks(keys, tasks, as_list)
    197                 pass
    198     tasks = work
--> 199 return ret if as_list else set(ret)

KeyboardInterrupt: 
infoWidget.low_loss.do_all()
0 0
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
1 0
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
2 0
2 1
2 2
2 3
2 4
2 5
2 6
2 7
2 8
2 9
3 0
3 1
3 2
3 3
3 4
3 5
3 6
3 7
3 8
3 9
4 0
4 1
4 2
4 3
4 4
4 5
4 6
4 7
4 8
4 9
5 0
5 1
5 2
5 3
5 4
5 5
5 6
5 7
5 8
5 9
6 0
6 1
6 2
6 3
6 4
6 5
6 6
6 7
6 8
6 9
7 0
7 1
7 2
7 3
7 4
7 5
7 6
7 7
7 8
7 9
8 0
8 1
8 2
8 3
8 4
8 5
8 6
8 7
8 8
8 9
9 0
9 1
9 2
9 3
9 4
9 5
9 6
9 7
9 8
9 9
10 0
10 1
10 2
10 3
10 4
10 5
10 6
10 7
10 8
10 9
11 0
11 1
11 2
11 3
11 4
11 5
11 6
11 7
11 8
11 9
12 0
12 1
12 2
12 3
12 4
12 5
12 6
12 7
12 8
12 9
13 0
13 1
13 2
13 3
13 4
13 5
13 6
13 7
13 8
13 9
14 0
14 1
14 2
14 3
14 4
14 5
14 6
14 7
14 8
14 9
15 0
15 1
15 2
15 3
15 4
15 5
15 6
15 7
15 8
15 9
16 0
16 1
16 2
16 3
16 4
16 5
16 6
16 7
16 8
16 9
17 0
17 1
17 2
17 3
17 4
17 5
17 6
17 7
17 8
17 9
18 0
18 1
18 2
18 3
18 4
18 5
18 6
18 7
18 8
18 9
19 0
19 1
19 2
19 3
19 4
19 5
19 6
19 7
19 8
19 9
20 0
20 1
20 2
20 3
20 4
20 5
20 6
20 7
20 8
20 9
21 0
21 1
21 2
21 3
21 4
21 5
21 6
21 7
21 8
21 9
22 0
22 1
22 2
22 3
22 4
22 5
22 6
22 7
22 8
22 9
23 0
23 1
23 2
23 3
23 4
23 5
23 6
23 7
23 8
23 9
24 0
24 1
24 2
24 3
24 4
24 5
24 6
24 7
24 8
24 9
infoWidget.datasets['low_loss_model'].plot()
Loading...
<Figure size 640x480 with 2 Axes>
Loading...
infoWidget
Loading...
plt.figure()
for key, dset in infoWidget.datasets.items():
    if key[0] != '_': 
        print(dset.title, dset.shape)
        plt.plot(dset.energy_loss, dset)
13-without blue laser 10% (2048,)
EELS Acquire (2048,)
13-with laser (2048,)
Loading...
plt.close('all')
class EELSWidget2(pyTEMlib.info_widget.EELSBaseWidget):
    def __init__(self, datasets=None):
        
        super().__init__(datasets, sidebar=None)
        super().set_dataset()
infoWidget.low_loss.update_ll_sidebar()
Channel_000 None 0
Channel_000 None 0
infoWidget.datasets['Channel_002'].original_metadata
{'ImageData': {'Calibrations': {'Brightness': {'Origin': 0.0, 'Scale': 1.0, 'Units': ''}, 'Dimension': {'0': {'Origin': 0.0, 'Scale': 0.1487438678741455, 'Units': 'nm'}, '1': {'Origin': 0.0, 'Scale': 0.1487438678741455, 'Units': 'nm'}}, 'DisplayCalibratedUnits': 1}, 'Data': 'read', 'DataType': 11, 'Dimensions': {'0': 1024, '1': 1024}, 'PixelDepth': 4}, 'ImageTags': {'DataBar': {'Acquisition Date': '3/16/2023', 'Acquisition Time': '1:23:37 PM', 'Acquisition Time (OS)': 1.3323461017764891e+17, 'Custom elements': {}, 'Device Name': 'DigiScan', 'Exposure Number': 3960478}, 'DigiScan': {'Bitshift': 0, 'Channel': 0, 'Flip': 0, 'Flyback': 50.0, 'Horizontal DS Offset': 0.0, 'Horizontal Image Center': 512.0, 'Horizontal Perpendicular Pixel Step': -16, 'Horizontal Pixel Step': -16, 'Horizontal Spacing': 22.4, 'Integrate Frames': 0, 'Integration Percentage': 80.0, 'Number Summing Frames': 5.0, 'Recorded': 1, 'Rotation': 45.0, 'Rotation Offset': 180.0, 'Sample Time': 32.400001525878906, 'SessionID': 1678985640, 'Signal Index': 0, 'Signals': {'0': {'Acquired': 1, 'Datatype': 4, 'Selected': 1, 'Signal ID': 0}, '1': {'Acquired': 0, 'Datatype': 4, 'Selected': 0, 'Signal ID': 1}}, 'Slot': 0, 'Sum Frames': 0, 'Synchronize Lines': 1, 'TimeStamp': 'Thu Mar 16 13:23:03 2023\u2028', 'Vertical DS Offset': 0.0, 'Vertical Image Center': 512.0, 'Vertical Perpendicular Pixel Step': -16, 'Vertical Pixel Step': 16, 'Vertical Spacing': 22.4, 'Zoom factor': 0.7}, 'Microscope Info': {'Cs(mm)': 2.2, 'Emission Current (A)': 230.0, 'Field of View (m)': 0.21540414060665797, 'Formatted Indicated Mag': '249.0kx', 'Formatted Voltage': '200.0kV', 'HT Extrapolated': 0, 'Illumination Mode': 'STEM', 'Imaging Mode': 'Diffraction Mag', 'Indicated Magnification': 248993.484375, 'Items': {'0': {'Data Type': 20, 'Label': 'Specimen', 'Tag path': 'Microscope Info:Specimen', 'Value': 'TEST-Helium bubble'}, '1': {'Data Type': 20, 'Label': 'Operator', 'Tag path': 'Microscope Info:Operator', 'Value': 'Shradha'}, '2': {'Data Type': 20, 'Label': 'Microscope', 'Tag path': 'Microscope Info:Microscope', 'Value': ''}}, 'Magnification Interpolated': 0, 'Microscope': '', 'Name': 'Libra COM', 'Operation Mode': 'SCANNING', 'Operator': 'Shradha', 'Probe Current (nA)': 0.0, 'Probe Size (nm)': 0.0, 'Specimen': 'TEST-Helium bubble', 'STEM Camera Length': 1200.0000476837158, 'Voltage': 199990.28125}, 'Survey Image': {'UID': {'0': 1024205530, '1': 1461147407, '2': 52899482, '3': 519921575}}}, 'Name': '12-survey', 'UniqueID': {'0': 1024205530, '1': 1461147407, '2': 52899482, '3': 519921575}, 'DM': {'dm_version': 3, 'file_size': 4797467, 'full_file_name': 'C:\\Users\\gduscher\\Desktop\\drive-download-20241125T130908Z-001\\12-survey.dm3'}, 'original_filename': 'C:\\Users\\gduscher\\Desktop\\drive-download-20241125T130908Z-001\\12-survey.dm3', 'ApplicationBounds': [0, 0, 1343, 2152], 'DocumentObjectList': {'0': {'AnnotationGroupList': {'0': {'AnnotationType': 27, 'BackgroundColor': [-1, -1, -1], 'BackgroundMode': 2, 'Color': [-1, 0, 0], 'FillMode': 2, 'ForegroundColor': [0, -1, 0], 'HasBackground': 0, 'IsDeletable': 1, 'IsMoveable': 1, 'IsResizable': 1, 'IsSelectable': 1, 'IsTranslatable': 1, 'IsVisible': 1, 'IsVolatile': 0, 'Label': 'Beam', 'Name': 'DS_BEAM', 'ObjectTags': {}, 'Rectangle': [547.0, 769.0, 547.0, 769.0], 'SelectionStyle': 1, 'UniqueID': 13}, '1': {'AnnotationType': 23, 'BackgroundColor': [-1, -1, -1], 'BackgroundMode': 2, 'Color': [0, -1, 0], 'FillMode': 2, 'ForegroundColor': [0, -1, 0], 'HasBackground': 0, 'IsDeletable': 1, 'IsMoveable': 1, 'IsResizable': 1, 'IsSelectable': 1, 'IsTranslatable': 1, 'IsVisible': 1, 'IsVolatile': 0, 'Label': 'Spectrum Image', 'Name': 'Spectrum Image', 'ObjectTags': {}, 'Rectangle': [341.0, 15.0, 590.0, 762.0], 'SelectionStyle': 1, 'UniqueID': 10}, '2': {'AnnotationType': 31, 'BackgroundColor': [-1, -1, -1], 'BackgroundMode': 2, 'FillMode': 2, 'Font': {'Attributes': 7, 'FamilyName': 'Lucida Console', 'Size': 40}, 'ForegroundColor': [-1, -1, -1], 'HasBackground': 0, 'IsMoveable': 1, 'IsResizable': 1, 'IsSelectable': 1, 'IsTranslatable': 1, 'IsVisible': 1, 'ObjectTags': {}, 'Rectangle': [884.0, 64.0, 960.0, 544.0], 'TextOffsetH': 1.0, 'TextOffsetV': 1.0, 'TextWidth': 95.0, 'UniqueID': 9}}, 'AnnotationType': 20, 'BackgroundColor': [-1, -1, -1], 'BackgroundMode': 2, 'FillMode': 1, 'ForegroundColor': [0, -1, 0], 'HasBackground': 0, 'ImageDisplayInfo': {'BrightColor': [-1, -1, -1], 'Brightness': 0.5, 'CaptionOn': 0, 'CaptionSize': 12, 'CLUT': [[0, 0, 0], [257, 257, 257], [514, 514, 514], [771, 771, 771], [1028, 1028, 1028], [1285, 1285, 1285], [1542, 1542, 1542], [1799, 1799, 1799], [2056, 2056, 2056], [2313, 2313, 2313], [2570, 2570, 2570], [2827, 2827, 2827], [3084, 3084, 3084], [3341, 3341, 3341], [3598, 3598, 3598], [3855, 3855, 3855], [4112, 4112, 4112], [4369, 4369, 4369], [4626, 4626, 4626], [4883, 4883, 4883], [5140, 5140, 5140], [5397, 5397, 5397], [5654, 5654, 5654], [5911, 5911, 5911], [6168, 6168, 6168], [6425, 6425, 6425], [6682, 6682, 6682], [6939, 6939, 6939], [7196, 7196, 7196], [7453, 7453, 7453], [7710, 7710, 7710], [7967, 7967, 7967], [8224, 8224, 8224], [8481, 8481, 8481], [8738, 8738, 8738], [8995, 8995, 8995], [9252, 9252, 9252], [9509, 9509, 9509], [9766, 9766, 9766], [10023, 10023, 10023], [10280, 10280, 10280], [10537, 10537, 10537], [10794, 10794, 10794], [11051, 11051, 11051], [11308, 11308, 11308], [11565, 11565, 11565], [11822, 11822, 11822], [12079, 12079, 12079], [12336, 12336, 12336], [12593, 12593, 12593], [12850, 12850, 12850], [13107, 13107, 13107], [13364, 13364, 13364], [13621, 13621, 13621], [13878, 13878, 13878], [14135, 14135, 14135], [14392, 14392, 14392], [14649, 14649, 14649], [14906, 14906, 14906], [15163, 15163, 15163], [15420, 15420, 15420], [15677, 15677, 15677], [15934, 15934, 15934], [16191, 16191, 16191], [16448, 16448, 16448], [16705, 16705, 16705], [16962, 16962, 16962], [17219, 17219, 17219], [17476, 17476, 17476], [17733, 17733, 17733], [17990, 17990, 17990], [18247, 18247, 18247], [18504, 18504, 18504], [18761, 18761, 18761], [19018, 19018, 19018], [19275, 19275, 19275], [19532, 19532, 19532], [19789, 19789, 19789], [20046, 20046, 20046], [20303, 20303, 20303], [20560, 20560, 20560], [20817, 20817, 20817], [21074, 21074, 21074], [21331, 21331, 21331], [21588, 21588, 21588], [21845, 21845, 21845], [22102, 22102, 22102], [22359, 22359, 22359], [22616, 22616, 22616], [22873, 22873, 22873], [23130, 23130, 23130], [23387, 23387, 23387], [23644, 23644, 23644], [23901, 23901, 23901], [24158, 24158, 24158], [24415, 24415, 24415], [24672, 24672, 24672], [24929, 24929, 24929], [25186, 25186, 25186], [25443, 25443, 25443], [25700, 25700, 25700], [25957, 25957, 25957], [26214, 26214, 26214], [26471, 26471, 26471], [26728, 26728, 26728], [26985, 26985, 26985], [27242, 27242, 27242], [27499, 27499, 27499], [27756, 27756, 27756], [28013, 28013, 28013], [28270, 28270, 28270], [28527, 28527, 28527], [28784, 28784, 28784], [29041, 29041, 29041], [29298, 29298, 29298], [29555, 29555, 29555], [29812, 29812, 29812], [30069, 30069, 30069], [30326, 30326, 30326], [30583, 30583, 30583], [30840, 30840, 30840], [31097, 31097, 31097], [31354, 31354, 31354], [31611, 31611, 31611], [31868, 31868, 31868], [32125, 32125, 32125], [32382, 32382, 32382], [32639, 32639, 32639], [-32640, -32640, -32640], [-32383, -32383, -32383], [-32126, -32126, -32126], [-31869, -31869, -31869], [-31612, -31612, -31612], [-31355, -31355, -31355], [-31098, -31098, -31098], [-30841, -30841, -30841], [-30584, -30584, -30584], [-30327, -30327, -30327], [-30070, -30070, -30070], [-29813, -29813, -29813], [-29556, -29556, -29556], [-29299, -29299, -29299], [-29042, -29042, -29042], [-28785, -28785, -28785], [-28528, -28528, -28528], [-28271, -28271, -28271], [-28014, -28014, -28014], [-27757, -27757, -27757], [-27500, -27500, -27500], [-27243, -27243, -27243], [-26986, -26986, -26986], [-26729, -26729, -26729], [-26472, -26472, -26472], [-26215, -26215, -26215], [-25958, -25958, -25958], [-25701, -25701, -25701], [-25444, -25444, -25444], [-25187, -25187, -25187], [-24930, -24930, -24930], [-24673, -24673, -24673], [-24416, -24416, -24416], [-24159, -24159, -24159], [-23902, -23902, -23902], [-23645, -23645, -23645], [-23388, -23388, -23388], [-23131, -23131, -23131], [-22874, -22874, -22874], [-22617, -22617, -22617], [-22360, -22360, -22360], [-22103, -22103, -22103], [-21846, -21846, -21846], [-21589, -21589, -21589], [-21332, -21332, -21332], [-21075, -21075, -21075], [-20818, -20818, -20818], [-20561, -20561, -20561], [-20304, -20304, -20304], [-20047, -20047, -20047], [-19790, -19790, -19790], [-19533, -19533, -19533], [-19276, -19276, -19276], [-19019, -19019, -19019], [-18762, -18762, -18762], [-18505, -18505, -18505], [-18248, -18248, -18248], [-17991, -17991, -17991], [-17734, -17734, -17734], [-17477, -17477, -17477], [-17220, -17220, -17220], [-16963, -16963, -16963], [-16706, -16706, -16706], [-16449, -16449, -16449], [-16192, -16192, -16192], [-15935, -15935, -15935], [-15678, -15678, -15678], [-15421, -15421, -15421], [-15164, -15164, -15164], [-14907, -14907, -14907], [-14650, -14650, -14650], [-14393, -14393, -14393], [-14136, -14136, -14136], [-13879, -13879, -13879], [-13622, -13622, -13622], [-13365, -13365, -13365], [-13108, -13108, -13108], [-12851, -12851, -12851], [-12594, -12594, -12594], [-12337, -12337, -12337], [-12080, -12080, -12080], [-11823, -11823, -11823], [-11566, -11566, -11566], [-11309, -11309, -11309], [-11052, -11052, -11052], [-10795, -10795, -10795], [-10538, -10538, -10538], [-10281, -10281, -10281], [-10024, -10024, -10024], [-9767, -9767, -9767], [-9510, -9510, -9510], [-9253, -9253, -9253], [-8996, -8996, -8996], [-8739, -8739, -8739], [-8482, -8482, -8482], [-8225, -8225, -8225], [-7968, -7968, -7968], [-7711, -7711, -7711], [-7454, -7454, -7454], [-7197, -7197, -7197], [-6940, -6940, -6940], [-6683, -6683, -6683], [-6426, -6426, -6426], [-6169, -6169, -6169], [-5912, -5912, -5912], [-5655, -5655, -5655], [-5398, -5398, -5398], [-5141, -5141, -5141], [-4884, -4884, -4884], [-4627, -4627, -4627], [-4370, -4370, -4370], [-4113, -4113, -4113], [-3856, -3856, -3856], [-3599, -3599, -3599], [-3342, -3342, -3342], [-3085, -3085, -3085], [-2828, -2828, -2828], [-2571, -2571, -2571], [-2314, -2314, -2314], [-2057, -2057, -2057], [-1800, -1800, -1800], [-1543, -1543, -1543], [-1286, -1286, -1286], [-1029, -1029, -1029], [-772, -772, -772], [-515, -515, -515], [-258, -258, -258], [-1, -1, -1]], 'CLUTName': 'Greyscale', 'ComplexMode': 4, 'ComplexRange': 1000.0, 'Contrast': 0.5, 'ContrastMode': 1, 'DimensionLabels': {'0': ''}, 'DoAutoSurvey': 1, 'EstimatedMax': 156.0, 'EstimatedMaxTrimPercentage': 0.0010000000474974513, 'EstimatedMin': 808508.0, 'EstimatedMinTrimPercentage': 0.0010000000474974513, 'Gamma': 0.5, 'HighLimit': 664984.0625, 'HiLimitContrastDeltaTriggerPercentage': 0.0, 'IsInverted': 0, 'LowLimit': 1340.109375, 'LowLimitContrastDeltaTriggerPercentage': 0.0, 'MainSliceId': {'0': 0}, 'MinimumContrast': 0.0, 'RangeAdjust': 1.0, 'SparseSurvey_GridSize': 16, 'SparseSurvey_NumberPixels': 32, 'SparseSurvey_UseNumberPixels': 1, 'SurveyTechique': 1}, 'ImageDisplayType': 1, 'ImageSource': 0, 'IsMoveable': 1, 'IsResizable': 1, 'IsSelectable': 1, 'IsTranslatable': 1, 'IsVisible': 1, 'ObjectTags': {'__is_not_copy': 1, '__was_selected': 0}, 'Rectangle': [0.0, 0.0, 628.0, 628.0], 'UniqueID': 8}}, 'DocumentTags': {}, 'HasWindowPosition': 1, 'Image Behavior': {'DoIntegralZoom': 0, 'ImageDisplayBounds': [0.0, 0.0, 628.0, 628.0], 'IsZoomedToWindow': 1, 'UnscaledTransform': {'Offset': [0.0, 0.0], 'Scale': [1.0, 1.0]}, 'ViewDisplayID': 8, 'WindowRect': [0.0, 0.0, 628.0, 628.0], 'ZoomAndMoveTransform': {'Offset': [0.0, 0.0], 'Scale': [1.0, 1.0]}}, 'ImageSourceList': {'0': {'ClassName': 'ImageSource:Simple', 'Id': {'0': 0}, 'ImageRef': 1}}, 'InImageMode': 1, 'MinVersionList': {'0': {'RequiredVersion': 50659328}}, 'NextDocumentObjectID': 14, 'Page Behavior': {'DoIntegralZoom': 0, 'DrawMargins': 1, 'DrawPaper': 1, 'IsFixedInPageMode': 0, 'IsZoomedToWindow': 1, 'LayedOut': 0, 'PageTransform': {'Offset': [0.0, 0.0], 'Scale': [1.0, 1.0]}, 'RestoreImageDisplayBounds': [0.0, 0.0, 1024.0, 1024.0], 'RestoreImageDisplayID': 8, 'TargetDisplayID': 4294967295}, 'PageSetup': {'General': [1, 1000, 8500, 11000, 1000, 1000, -1000, -1000], 'Win32': b'\x04\x00\x00\x004!\x00\x00\xf8*\x00\x00M\x01\x00\x00M\x01\x00\x00\xfa\x00\x00\x00\xfa\x00\x00\x00\xe8\x03\x00\x00\xe8\x03\x00\x00\xe8\x03\x00\x00\xe8\x03\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x1b\x10', 'Win32_DevModeW': b'S\x00e\x00n\x00d\x00 \x00T\x00o\x00 \x00O\x00n\x00e\x00N\x00o\x00t\x00e\x00 \x002\x000\x001\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x04\x00\x06\xdc\x00\x0c\x03\x03\xff\x00\x00\x01\x00\x01\x00\xea\no\x08d\x00\x01\x00\x0f\x00X\x02\x02\x00\x01\x00X\x02\x02\x00\x00\x00L\x00e\x00t\x00t\x00e\x00r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00DINU"\x00\xd0\x00\x0c\x03\x00\x00\xc2\xac\x90Q\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd0\x00\x00\x00SMTJ\x00\x00\x00\x00\x10\x00\xc0\x00S\x00e\x00n\x00d\x00 \x00T\x00o\x00 \x00M\x00i\x00c\x00r\x00o\x00s\x00o\x00f\x00t\x00 \x00O\x00n\x00e\x00N\x00o\x00t\x00e\x00 \x002\x000\x001\x000\x00 \x00D\x00r\x00i\x00v\x00e\x00r\x00\x00\x00RESDLL\x00UniresDLL\x00PaperSize\x00LETTER\x00Orientation\x00PORTRAIT\x00Resolution\x00DPI600\x00ColorMode\x0024bpp\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'Win32_DevNamesW': b'\x04\x00*\x00?\x00\x00\x00S\x00e\x00n\x00d\x00 \x00T\x00o\x00 \x00M\x00i\x00c\x00r\x00o\x00s\x00o\x00f\x00t\x00 \x00O\x00n\x00e\x00N\x00o\x00t\x00e\x00 \x002\x000\x001\x000\x00 \x00D\x00r\x00i\x00v\x00e\x00r\x00\x00\x00S\x00e\x00n\x00d\x00 \x00T\x00o\x00 \x00O\x00n\x00e\x00N\x00o\x00t\x00e\x00 \x002\x000\x001\x000\x00\x00\x00n\x00u\x00l\x00:\x00\x00\x00'}, 'SentinelList': {}, 'Thumbnails': {'0': {'ImageIndex': 0, 'SourceSize_Pixels': [628, 628]}}, 'WindowPosition': [38, 9, 666, 637]}
d = infoWidget.datasets['Channel_000'].original_metadata

rect = d['DocumentObjectList']['0']['AnnotationGroupList']['2']['Rectangle']
import matplotlib.patches
plt.figure()
plt.imshow(infoWidget.datasets['Channel_000'].T)
kwargs={'edgecolor': 'red', 'facecolor': 'None'}
r = matplotlib.patches.Rectangle([rect[0], rect[2]], rect[1]-rect[0], rect[3]-rect[2], **kwargs)
plt.gca().add_artist(r)
rect
[884.0, 64.0, 960.0, 544.0]
Loading...


def read_annotation(image):
    scale_x = np.abs(image.x[1]-image.x[0])
    scale_y = np.abs(image.y[1]-image.y[0])
    rec_scale = np.array([scale_x, scale_y,scale_x, scale_y])
    if 'DocumentObjectList' not in image.original_metadata:
        return {}
    if '0' not in image.original_metadata['DocumentObjectList']:
        return {}
    annotations = {}        
    tags = image.original_metadata['DocumentObjectList']['0']     
    for key in tags:
        if 'AnnotationGroupList' in key:
            an_tags = tags[key]
            for key2 in an_tags:
                if isinstance(an_tags[key2], dict):
                    if an_tags[key2]['AnnotationType'] == 13:  #type 'text'
                        annotations[key2] = {'type': 'text'}
                        if 'Label' in an_tags:
                            annotations[key2]['label'] = an_tags['Label']
                        rect = np.array(an_tags[key2]['Rectangle']) * rec_scale
                        annotations[key2]['position'] = [rect[1],rect[0]]
                        annotations[key2]['text'] = an_tags['Text'] 
                        
                    elif an_tags[key2]['AnnotationType']==6:
                        annotations[key2] = {'type': 'circle'}
                        if 'Label' in an_tags:
                            annotations[key2]['label'] = an_tags['Label']
                        rect = np.array(an_tags[key2]['Rectangle']) * rec_scale
                    
                        annotations[key2]['radius'] =rect[3]-rect[1]
                        annotations[key2]['position'] = [rect[1],rect[0]]
        
                    elif an_tags[key2]['AnnotationType'] == 23:
                        print('1')
                        annotations[key2] = {'type':  'spectral_image'}
                        if 'Label' in an_tags[key2]:
                            annotations[key2]['label'] = an_tags[key2]['Label']
                        rect = np.array(an_tags[key2]['Rectangle']) * rec_scale
                        
                        annotations[key2]['width'] =rect[3]-rect[1]
                        annotations[key2]['height'] =rect[2]-rect[0]
                        annotations[key2]['position'] = [rect[1],rect[0]]
                        annotations[key2]['Rectangle'] = np.array(an_tags[key2]['Rectangle'])
            
    image.metadata['annotations'] = annotations                
    return annotations


dset = infoWidget.datasets['Channel_001']
read_annotation(dset)


dset.plot()
if 'annotations' in dset.metadata:
    annotations = dset.metadata['annotations']
    for key in annotations:
        if annotations[key]['type'] == 'spectral_image':
            kwargs={'edgecolor': 'red', 'facecolor': 'None'}
        
            r = matplotlib.patches.Rectangle(annotations[key]['position'], annotations[key]['width'], annotations[key]['height'], **kwargs)
            plt.gca().text(annotations[key]['position'][0], annotations[key]['position'][1], annotations[key]['label'], color='r')
            plt.gca().add_artist(r)
dset.metadata
{'image_type': 'survey image', 'experiment': {'microscope': '', 'acceleration_voltage': 199990.28125}, 'annotations': {}}
Loading...
{'AnnotationType': 23, 'BackgroundColor': [-1, -1, -1], 'BackgroundMode': 2, 'Color': [-258, 0, 0], 'FillMode': 2, 'ForegroundColor': [0, -1, 0], 'HasBackground': 0, 'IsDeletable': 1, 'IsMoveable': 1, 'IsResizable': 1, 'IsSelectable': 1, 'IsTranslatable': 1, 'IsVisible': 1, 'IsVolatile': 0, 'Label': '1', 'Name': 'SICursor', 'ObjectTags': {}, 'Rectangle': [1.0, 26.0, 10.0, 27.0], 'SelectionStyle': 1, 'UniqueID': 13}
                
            if split_keys[5] in ['AnnotationType','Text','Rectangle','Name', 'Label']:
            
        tags['annotations'] = {}
        for key in annotations:
            if annotations[key]['AnnotationType']==13: 
                if 'Label' in annotations[key]:
                    tags['annotations']['annotations_'+str(key)+'_label'] = annotations[key]['Label']
                tags['annotations']['annotations_'+str(key)+'_type'] = 'text'
                rect = np.array(annotations[key]['Rectangle'])* rec_scale
                tags['annotations']['annotations_'+str(key)+'_x'] = rect[1]
                tags['annotations']['annotations_'+str(key)+'_y'] = rect[0]
                tags['annotations']['annotations_'+str(key)+'_text'] = annotations[key]['Text']
                
            elif annotations[key]['AnnotationType']==6:
                #out_tags['annotations'][key] = {}
                if 'Label' in annotations[key]:
                    tags['annotations']['annotations_'+str(key)+'_label'] = annotations[key]['Label']
                tags['annotations']['annotations_'+str(key)+'_type'] = 'circle'
                rect = np.array(annotations[key]['Rectangle'])* rec_scale
                
                tags['annotations']['annotations_'+str(key)+'_radius'] =rect[3]-rect[1]
                tags['annotations']['annotations_'+str(key)+'_position'] = [rect[1],rect[0]]
                
            elif annotations[key]['AnnotationType']==6:
                #out_tags['annotations'][key] = {}
                if 'Label' in annotations[key]:
                    tags['annotations']['annotations_'+str(key)+'_label'] = annotations[key]['Label']
                tags['annotations']['annotations_'+str(key)+'_type'] = 'circle'
                rect = np.array(annotations[key]['Rectangle'])* rec_scale
                
                tags['annotations']['annotations_'+str(key)+'_radius'] =rect[3]-rect[1]
                tags['annotations']['annotations_'+str(key)+'_position'] = [rect[1],rect[0]]

                

            elif annotations[key]['AnnotationType']==23:
                if 'Name' in annotations[key]:
                    if annotations[key]['Name'] == 'Spectrum Image':
                        #tags['annotations'][key] = {}
                        if 'Label' in annotations[key]:
                            tags['annotations']['annotations_'+str(key)+'_label'] = annotations[key]['Label']
                        tags['annotations']['annotations_'+str(key)+'_type'] = 'spectrum image'
                        rect = np.array(annotations[key]['Rectangle'])* rec_scale
                        
                        tags['annotations']['annotations_'+str(key)+'_width'] =rect[3]-rect[1]
                        tags['annotations']['annotations_'+str(key)+'_height'] =rect[2]-rect[0]
                        tags['annotations']['annotations_'+str(key)+'_position'] = [rect[1],rect[0]]
   
  Cell In[41], line 5
    if annotations[key]['AnnotationType']==13:
                                               ^
IndentationError: expected an indented block after 'for' statement on line 4
infoWidget.tab_buttons.index = 2

infoWidget.low_loss.update_ll_sidebar()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[20], line 1
----> 1 infoWidget.tab_buttons.index = 2
      3 infoWidget.low_loss.update_ll_sidebar()

AttributeError: 'EELSWidget' object has no attribute 'tab_buttons'
infoWidget.tabval = 2
infoWidget.tab_activated()
import ipywidgets
infoWidget.tab.children = [infoWidget.tab_buttons, infoWidget.children[infoWidget.tab_buttons.index]]
infoWidget.info.update_dataset()
infoWidget.low_loss._update()
infoWidget.datasets['plasmon'].metadata
{'experiment': {'single_exposure_time': 0.1, 'exposure_time': 10.0, 'number_of_frames': 100, 'collection_angle': 100.0, 'convergence_angle': 0.0, 'microscope': 'Libra 200 MC', 'acceleration_voltage': 199990.28125, 'flux_ppm': 4875.3037109375, 'count_conversion': 1, 'beam_current': 0}, 'zero_loss': {'shifted': array([-0.14012023]), 'startFitEnergy': -0.5, 'endFitEnergy': 0.5, 'fit_parameter': array([ 3.38795373e-02, 2.04002455e+04, 2.93662064e-01, -1.63207014e-02, 2.28877644e+04, 1.92327898e-01]), 'original_low_loss': 'Squeezed_EELS90muOAonaxis3_new_new'}, 'plasmon': {'parameter': array([1.50324046e+01, 7.46074698e-01, 7.41146395e+08]), 'epsilon': array([0.00000000e+00 +0.j , 0.00000000e+00 +0.j , 0.00000000e+00 +0.j , ..., 6.23143817e+08+21041344.40887087j, 6.23269871e+08+21023350.85181732j, 6.23395723e+08+21005387.31173421j])}}
an, p = eels_tools.angle_correction(infoWidget.dataset)

plt.figure()
plt.plot(infoWidget.dataset/(an/an.max()))

plt.plot(infoWidget.dataset)
Loading...
pin = infoWidget.datasets['plasmon'].metadata['plasmon']['parameter']
pin = np.append(pin, [0.17])
print(pin)

c = eels_tools.fit_multiple_scattering(infoWidget.dataset, 5, 40, pin)
c.plot()
c.metadata
[1.60512722e+01 1.76590538e+00 3.48812177e+05 1.70000000e-01]
{'experiment': {'single_exposure_time': 0.1, 'exposure_time': 10.0, 'number_of_frames': 100, 'collection_angle': 100.0, 'convergence_angle': 0.0, 'microscope': 'Libra 200 MC', 'acceleration_voltage': 199990.28125, 'flux_ppm': 4875.3037109375, 'count_conversion': 1, 'beam_current': 0}, 'zero_loss': {'shifted': array([-0.14012023]), 'startFitEnergy': -0.5, 'endFitEnergy': 0.5, 'fit_parameter': array([ 3.38795373e-02, 2.04002455e+04, 2.93662064e-01, -1.63207014e-02, 2.28877644e+04, 1.92327898e-01]), 'original_low_loss': 'EELS90muOAonaxis3_new_new'}, 'multiple_scattering': {'parameter': array([1.50313404e+01, 7.54438111e-01, 3.50839049e+05, 2.38991855e-01])}}
Loading...

v = infoWidget.datasets['plasmon'].plot()
Loading...
def energy_loss_function(energy_scale: np.ndarray, p: np.ndarray) -> np.ndarray:
    eps = 1 - p[0]**2/(energy_scale**2+p[1]**2) + 1j * p[1] * p[0]**2/energy_scale/(energy_scale**2+p[1]**2)
    elf = (-1/eps).imag
    return elf*p[2]

def multiple_scattering(energy_scale: np.ndarray, p: list, core_loss=False)-> np.ndarray:
    p = np.abs(p)
    tmfp = p[3]
    if core_loss:
        dif = 1
    else:
        dif = 16
    LLene = np.linspace(1, 2048-1,2048)/dif
    
    SSD = energy_loss_function(LLene, p)
    ssd  = np.fft.fft(SSD)
    ssd2 = ssd.copy()
    
    ### sum contribution from each order of scattering:
    PSD = np.zeros(len(LLene))
    for order in range(15):
        # This order convoluted spectum 
        # convoluted SSD is SSD2
        SSD2 = np.fft.ifft(ssd).real
    
        # scale right (could be done better? GERD) 
        # And add this order to final spectrum
        PSD += SSD2*abs(sum(SSD)/sum(SSD2)) / scipy.special.factorial(order+1)*np.power(tmfp, (order+1))*np.exp(-tmfp) #using equation 4.1 of egerton ed2
        
        # next order convolution
        ssd = ssd * ssd2
    
    PSD /=tmfp*np.exp(-tmfp)
    BGDcoef = scipy.interpolate.splrep(LLene, PSD, s=0)    
    return scipy.interpolate.splev(energy_scale, BGDcoef)
tmfp = .17  #p[3]
p0 =[1.50312722e+01, 7.45905380e-01, 3.48811157e+05, tmfp]
x = infoWidget.dataset.energy_loss

cts = multiple_scattering(x, p0, core_loss=False)
plt.figure()
plt.plot(x,cts)
plt.plot(x, infoWidget.dataset)
plt.plot(x, infoWidget.dataset-cts)
plt.plot(x, infoWidget.datasets['plasmon'])

Loading...
multiple_scattering(energy_scale, p)


def errf_multi(p, y, x):
    elf = multiple_scattering(x, p)
    err = y - elf
    #print (p,sum(np.abs(err)))
    return np.abs(err) # /np.sqrt(y)


pin2 = np.array([9,1,.7, 1.11])
E = energy_scale = infoWidget.dataset.energy_loss
startFit =np.argmin(abs(energy_scale-6))
endFit = np.argmin(abs(energy_scale-35))
    
p2, lsq = leastsq(errf_multi, p0, args=(infoWidget.dataset[startFit:endFit], energy_scale[startFit:endFit]), maxfev=2000)

cts = multiple_scattering(x, p2, core_loss=False)
plt.figure()
plt.plot(x,cts)
plt.plot(x, infoWidget.dataset)
plt.plot(x, infoWidget.dataset-cts)
plt.plot(x, infoWidget.datasets['plasmon'])

p2, p0
(array([1.50313215e+01, 7.53493487e-01, 3.50578991e+05, 2.37203551e-01]), [15.0312722, 0.74590538, 348811.157, 0.17])
Loading...
tags = {}
tags['dispersion'] = spec.energy_loss.slope
tags['E0'] = 200 # tags['E0']#input('incident energy E0(kev) : ');
tags['collAngle'] = 30 # tags['collAngle']


def Drude( tags, e, p):
    return drude(tags,  e, p[0], p[1], p[2],  p[3])
def drude(tags, e, ep, ew, tnm, eb):
    pc = tags['dispersion']#input('ev per channel : ');
    e0 = tags['E0']#input('incident energy E0(kev) : ');
    beta = tags['collAngle']#input('collection semiangle beta(mrad) : ');
    #tnm = input('thickness(nm) : ');

    b = beta/1000.0 # %rad
    T = 1000.0*e0*(1.+e0/1022.12)/(1.0+e0/511.06)**2;# %eV # equ.5.2a or Appendix E p 427 
    tgt = 1000*e0*(1022.12 + e0)/(511.06 + e0);# %eV  Appendix E p 427 
    rk0 = 2590*(1.0+e0/511.06)*np.sqrt(2.0*T/511060);
    os = e[0]
    ewMod = eb

    eps = 1 - (ep**2-ewMod*e*1j)/(e**2+2*e*ew*1j) #Mod Drude term
    
    eps[np.nonzero(eps==0.0)]= 1e-19
    elf = np.imag(-1/eps)

    the = e/tgt; #% varies with energy loss! # Appendix E p 427 
    
    srfelf=np.imag(-4./(1.0+eps))-elf; #% for 2 surfaces
    angdep = np.arctan(b/the)/the - b/(b*b+the*the);
    srfint = angdep*srfelf/(3.1416*0.05292*rk0*T); #% probability per eV
    anglog = np.log(1.0+ b*b/the/the);
    # I0 = tags['spec'].sum()#*self.tags['counts2e']
    #print('counts2e',1/self.tags['counts2e'])
    

    # 2 * T = m_0 v**2 !!!  a_0 = 0.05292 nm
    volint = abs(tnm/(np.pi*0.05292*T*2.0)*elf*anglog); #S equ 4.26% probability per eV
    #volint = volint *I0/ epc #S probability per channel
    ssd = volint #+ srfint;

    if os <-1.0:
        xs = int(abs(-os/epc))
   
        ssd[0:xs]=0.0
        volint[0:xs]=0.0
        srfint[0:xs]=0.0
        
        #if os <0:
        Ps = np.trapz(e,srfint); #% 2 surfaces but includes negative begrenzungs contribn.
        Pv = abs(np.trapz(e,abs(volint/self.tags['spec'].sum()))); #% integrated volume probability
        Pv = (volint/I0).sum() ## our data have he same epc and the trapz formula does not include 
        lam = tnm/Pv; #% does NOT depend on free-electron approximation (no damping). 
        lamfe = 4.0*0.05292*T/ep/np.log(1+(b* tgt / ep) **2); #% Eq.(3.44) approximation
    
        #print('Ps(2surfaces+begrenzung terms) =', Ps, 'Pv=t/lambda(beta)= ',Pv,'\n');
        #print('Volume-plasmon MFP(nm) = ', lam,' Free-electron MFP(nm) = ',lamfe,'\n');
        #print('--------------------------------\n');

        """self.tags['eps'] = eps
        
        self.tags['lam'] = lam
        self.tags['lamfe'] = lamfe
        self.tags['Pv'] = Pv
        """
        
    return ssd#/np.pi
    

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[3], line 2
      1 tags = {}
----> 2 tags['dispersion'] = spec.energy_loss[1] - spec.energy_loss[10]   # input('ev per channel : ');
      3 tags['E0'] = 200 # tags['E0']#input('incident energy E0(kev) : ');
      4 tags['collAngle'] = 30 # tags['collAngle']

NameError: name 'spec' is not defined
def newDrudeBgd(energy_scale,p):
        tags = self.tags

        startB = energy_scale[0]
        endB = energy_scale[-1]
        p = np.abs(p)
       

        LLene = np.linspace(0, 2047,2048)
        SSD =  drude(LLene,p)
        ssd  = np.fft.fft(SSD)

        ssd2 = ssd.copy()
        SSD2 = SSD.copy()
        
        ### sum contribution from each order of scattering:
        PSD = np.zeros(len(LLene))
        for order in range(15):
            # This order convoluted spectum 
            PPSD = np.zeros(len(LLene))
            # convoluted SSD is SSD2
            SSD2 = np.fft.ifft(ssd).real
            
            # scale right (could be done better? GERD) 
            mult = sum(SSD)/sum(SSD2)
            SSD2 *= abs(mult)
            
            PPSD = SSD2/factorial(order+1)*np.power(tmfp,(order+1))*np.exp(-tmfp) #using equation 4.1 of egerton ed2
           # Add this order to final spectrum
            PSD += PPSD

            # next order convolution
            ssd = ssd * ssd2
            

        cts = np.zeros(len(x))
        
        if startB < 0:
            startB = 0
        BGDcoef = splrep(LLene[int(startB):int(endB)],PSD[int(startB):int(endB)],s=0)


        lin = np.zeros(len(x))

        cts =splev( x, BGDcoef)*p[1]
        
        self.cor =  self.EffectiveAngle(self.tags['E0'],x, self.tags['convAngle'], self.tags['collAngle'])  
        return cts#*self.cor
def drude_simulation(dset, e, ep, ew, tnm, eb):
    
    energy_scale = dset.get_spectral_dims(return_axis=True)[0]
    dispersion = energy_scale.slope # input('ev per channel : ');
    
    beta = dset.metadata['collection_angle'] / 1000.  # rad
    e0 = dset.metadata['acceleration_voltage'] / 1000.  # input('incident energy e0(kev) : ');

    # effective kinetic energy: T = m_o v^2/2,
    t = 1000.0 * e0 * (1. + e0 / 1022.12) / (1.0 + e0 / 511.06) ** 2  # eV # equ.5.2a or Appendix E p 427
    
    # 2 gamma T
    tgt = 1000 * e0 * (1022.12 + e0) / (511.06 + e0)  # eV  Appendix E p 427
    rk0 = 2590 * (1.0 + e0 / 511.06) * np.sqrt(2.0 * t / 511060)
    
    os = e[0]
    ew_mod = eb
    tags = dset.metadata
   
    eps = 1 - (ep ** 2 - ew_mod * e * 1j) / (e ** 2 + 2 * e * ew * 1j)  # Mod drude term
    
    eps[np.nonzero(eps == 0.0)] = 1e-19
    elf = np.imag(-1 / eps)

    the = e / tgt  # varies with energy loss! # Appendix E p 427
    # srfelf = 4..*eps2./((1+eps1).^2+eps2.^2) - elf; %equivalent
    srfelf = np.imag(-4. / (1.0 + eps)) - elf  # for 2 surfaces
    angdep = np.arctan(beta / the) / the -  beta/ (beta * beta + the * the)
    srfint = angdep * srfelf / (3.1416 * 0.05292 * rk0 * t)  # probability per eV
    anglog = np.log(1.0 + beta * beta / the / the)
    i0 = dset.sum()  # *tags['counts2e']

    # 2 * t = m_0 v**2 !!!  a_0 = 0.05292 nm
    volint = abs(tnm / (np.pi * 0.05292 * t * 2.0) * elf * anglog)  # S equ 4.26% probability per eV
    volint = volint * i0 / dispersion  # S probability per channel
    ssd = volint  # + srfint;

    if e[0] < -1.0:
        xs = int(abs(-e[0] / dispersion))

        ssd[0:xs] = 0.0
        volint[0:xs] = 0.0
        srfint[0:xs] = 0.0

        # if os <0:
        p_s = np.trapz(e, srfint)  # 2 surfaces but includes negative Begrenzung contribution.
        p_v = abs(np.trapz(e, abs(volint / tags['spec'].sum())))  # integrated volume probability
        p_v = (volint / i0).sum()  # our data have he same epc and the trapez formula does not include
        lam = tnm / p_v  # does NOT depend on free-electron approximation (no damping).
        lamfe = 4.0 * 0.05292 * t / ep / np.log(1 + (beta * tgt / ep) ** 2)  # Eq.(3.44) approximation

        tags['eps'] = eps
        tags['lam'] = lam
        tags['lamfe'] = lamfe
        tags['p_v'] = p_v

    return ssd  # /np.pi
peak_model, p = pyTEMlib.eels_tools.gaussian_mixture_model(spectrum1, p_in=None)

print(int(len(p)/3))
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[4], line 1
----> 1 peak_model, p = pyTEMlib.eels_tools.gaussian_mixture_model(spectrum1, p_in=None)
      3 print(int(len(p)/3))

NameError: name 'spectrum1' is not defined


spectrum = spectrum1.view.get_spectrum()
plt.figure()

plt.plot(spectrum, c='red')
plt.plot(peak_model, linewidth=2,c='blue')
plt.plot(spectrum-peak_model)
plt.plot((spectrum-peak_model)/np.sqrt(spectrum/20)*100)
Loading...
plt.figure()

plt.plot(spectrum.energy_loss, spectrum, c='r', label='experiment')
plt.plot(spectrum.energy_loss, peak_model, c='b',linewidth=2, label='model')
plt.plot(spectrum.energy_loss, (spectrum-peak_model)/np.sqrt(spectrum/20)*100, label='residuals')
for i in range(int(len(p)/3)):
    plt.plot(spectrum.energy_loss, pyTEMlib.eels_tools.gauss(spectrum.energy_loss, p[i*3:(i+1)*3]), label=f'Gauss {i}')

plt.legend(loc='upper right')
Loading...

peakfit

from pyTEMlib import peak_dialog

peakFitWidget = peak_dialog.PeakFitWidget(infoWidget.datasets, infoWidget.datasets['_relationship']['low_loss'])
Loading...
infoWidget.datasets['_relationship']
{'main_dataset': 'Channel_000', 'low_loss': 'Channel_000', 'resolution_functions': 'resolution_functions'}
k = peakFitWidget.dataset-np.array(peakFitWidget.model)
v =k.plot()
Loading...
peakFitWidget.smooth()
C:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\eels_tools.py:1829: RuntimeWarning: Number of calls to function has reached maxfev = 10000.
  [p, _] = leastsq(residuals3, pin, args=(x, y),maxfev = 10000)
peakFitWidget.datasets.keys()
dict_keys(['Channel_000', 'Channel_001', '_relationship', 'resolution_functions'])
peakFitWidget.fit_peaks()
C:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\peak_dialog.py:357: RuntimeWarning: Number of calls to function has reached maxfev = 11000.
  #self.model[start_channel:end_channel] = model
C:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\jupyter_client\session.py:721: UserWarning: Message serialization failed with:
Out of range float values are not JSON compliant: nan
Supporting this message is deprecated in jupyter-client 7, please make sure your message is JSON-compliant
  content = self.pack(content)
C:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\jupyter_client\session.py:721: UserWarning: Message serialization failed with:
Out of range float values are not JSON compliant: nan
Supporting this message is deprecated in jupyter-client 7, please make sure your message is JSON-compliant
  content = self.pack(content)
ff = eels_tools.gmm(energy_scale, np.array(peakFitWidget.peak_out_list).flatten())
plt.figure()
plt.plot(ff)
#peakFitWidget.dataset.plot()

np.isnan(ff).sum(), np.isinf(ff).sum()
peakFitWidget.peak_out_list = peak_model
plt.close('all')
for index, peak in peakFitWidget.peaks['peaks'].items(): # ll
    p = [peak['position'], peak['amplitude'], peak['width']]
    print(p)
    additional_spectra[f'peak {index}']= eels_tools.gauss(np.array(peakFitWidget.energy_scale), p)
[0.25, 5595090.5, 4.747764687329006]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[12], line 4
      2 p = [peak['position'], peak['amplitude'], peak['width']]
      3 print(p)
----> 4 additional_spectra[f'peak {index}']= eels_tools.gauss(np.array(peakFitWidget.energy_scale), p)

TypeError: can't unbox heterogeneous list: float64 != float32
import scipy
spectrum = peakFitWidget.dataset

energy_scale = peakFitWidget.dataset.get_spectral_dims(return_axis=True)[0].values
pin = np.array(peakFitWidget.peak_out_list[:6]).flatten()
x = np.array(spectrum)
y = energy_scale


print(x.shape)
#p = scipy.optimize.least_squares(eels_tools.residuals3, pin, args=(x,y), method='lm', verbose= 2)
print(peak_model)
energy_scale[1]-energy_scale[0]

v = eels_tools.residuals3(pin, x, y)
plt.figure()
plt.plot(v)
np.isfinite(v).sum()
(2048,)
[-4.83000000e+01  3.83246094e+03  2.80766823e+00 -2.13000000e+01
  3.34756055e+03  2.50309866e+00 -1.36424205e-11  6.00148960e+07
  1.69709218e+00  1.98000000e+01  2.50729328e+05  1.09172481e+01
  8.07000000e+01  1.41388223e+04  6.03046268e+00  9.21000000e+01
  1.34123496e+04  1.58681033e+00  1.15500000e+02  9.99801367e+03
  1.67314163e+00  1.28400000e+02  8.61218750e+03  6.05662983e+00
  1.63500000e+02  5.94440137e+03  1.55680767e+00  1.67100000e+02
  5.93256055e+03  1.67007282e+00  1.98600000e+02  4.87127148e+03
  1.65743531e+00  2.34600000e+02  3.18025830e+03  1.63774453e+00
  2.50500000e+02  3.69103735e+03  1.52271110e+00  2.55900000e+02
  3.20574658e+03  2.78972361e+00  2.67600000e+02  2.57806250e+03
  2.29663513e+00  2.81100000e+02  3.54892529e+03  1.66879714e+00
  3.07200000e+02  1.55079565e+03  1.95856399e+00  3.20400000e+02
  2.64509766e+03  1.79741244e+00  3.40800000e+02  2.07240796e+03
  2.33128935e+00  3.52500000e+02  2.45149805e+03  2.76355395e+00
  3.58500000e+02  1.76404834e+03  1.98714577e+00  4.08600000e+02
  1.12217920e+03  2.18032596e+00  4.11600000e+02  1.82581519e+03
  1.92283312e+00  4.75800000e+02  1.60657446e+03  2.27419354e+00
  4.78800000e+02  1.94508496e+03  1.82035011e+00  5.14200000e+02
  1.01093506e+03  1.92720941e+00  5.42400000e+02  1.51592969e+03
  2.27115801e+00  5.46300000e+02  1.11388831e+03  2.00918175e+00]
1847
Loading...
spectrum[spectrum<0]=10000
vv = spectrum.plot()
Loading...
import numpy as np
import matplotlib.pyplot as plt
from eels_tools import find_peaks

# Assuming peakFitWidget.dataset is your spectrum data
# Example data, replace with your actual spectrum
spectrum = peakFitWidget.dataset
peaks = peakFitWidget.dataset.metadata['peak_fit']

# Fit the peaks using the find_peaks function
peak_model, peak_out_list = find_peaks(spectrum, peaks['fit_start'], peaks['fit_end'])

# Extract the peak positions and amplitudes
peak_positions = [peak['center'] for peak in peak_out_list]
peak_amplitudes = [peak['amplitude'] for peak in peak_out_list]

# Plot the original spectrum
x = np.arange(len(spectrum))
plt.plot(x, spectrum, label='Original Spectrum', color='gray', alpha=0.5)

# Plot the identified peaks
for pos, amp in zip(peak_positions, peak_amplitudes):
    plt.axvline(pos, color='red', linestyle=':', label=f'Peak at {pos:.2f}')
    plt.plot(pos, amp, 'ro')  # Mark the peak positions

plt.xlabel('Channel')
plt.ylabel('Intensity')
plt.title('Identified Peaks in Spectrum')
plt.legend()
plt.show()

# Print the peak positions for verification
print("Identified peak positions:", peak_positions)
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[8], line 3
      1 import numpy as np
      2 import matplotlib.pyplot as plt
----> 3 from eels_tools import find_peaks
      5 # Assuming peakFitWidget.dataset is your spectrum data
      6 # Example data, replace with your actual spectrum
      7 spectrum = peakFitWidget.dataset

ModuleNotFoundError: No module named 'eels_tools'
peaks = peakFitWidget.dataset.metadata['peak_fit']

peak_model, peak_out_list = eels_tools.find_peaks(peakFitWidget.dataset,  peaks['fit_start'],  peaks['fit_end'])
C:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\numpy\core\_methods.py:206: RuntimeWarning: Degrees of freedom <= 0 for slice
  ret = _var(a, axis=axis, dtype=dtype, out=out, ddof=ddof,
C:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\numpy\core\_methods.py:163: RuntimeWarning: invalid value encountered in divide
  arrmean = um.true_divide(arrmean, div, out=arrmean,
C:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\numpy\core\_methods.py:198: RuntimeWarning: invalid value encountered in divide
  ret = ret.dtype.type(ret / rcount)
peakFitWidget.smooth()
peakFitWidget.peak_out_list
C:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\numpy\core\_methods.py:206: RuntimeWarning: Degrees of freedom <= 0 for slice
  ret = _var(a, axis=axis, dtype=dtype, out=out, ddof=ddof,
C:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\numpy\core\_methods.py:163: RuntimeWarning: invalid value encountered in divide
  arrmean = um.true_divide(arrmean, div, out=arrmean,
C:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\numpy\core\_methods.py:198: RuntimeWarning: invalid value encountered in divide
  ret = ret.dtype.type(ret / rcount)
C:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\numpy\lib\function_base.py:520: RuntimeWarning: Mean of empty slice.
  avg = a.mean(axis, **keepdims_kw)
C:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\numpy\core\_methods.py:129: RuntimeWarning: invalid value encountered in scalar divide
  ret = ret.dtype.type(ret / rcount)
array([], shape=(0, 3), dtype=float64)
infoWidget.datasets['_relationship']
da = infoWidget.datasets[infoWidget.datasets['_relationship']['low_loss']]
gg = pyTEMlib.eels_tools.find_peaks(da, -4, 40)
C:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\numpy\core\_methods.py:206: RuntimeWarning: Degrees of freedom <= 0 for slice
  ret = _var(a, axis=axis, dtype=dtype, out=out, ddof=ddof,
C:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\numpy\core\_methods.py:163: RuntimeWarning: invalid value encountered in divide
  arrmean = um.true_divide(arrmean, div, out=arrmean,
C:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\numpy\core\_methods.py:198: RuntimeWarning: invalid value encountered in divide
  ret = ret.dtype.type(ret / rcount)
dir(da.view)
['__bool__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
da = infoWidget.datasets[infoWidget.datasets['_relationship']['low_loss']]

print(da)
da.metadata['peak_fit']
sidpy.Dataset of type SPECTRAL_IMAGE with:
 dask.array<setitem, shape=(23, 28, 2048), dtype=float32, chunksize=(23, 28, 2048), chunktype=numpy.ndarray>
 data contains: intensity (counts)
 and Dimensions: 
x:  distance (µm) of size (23,)
y:  distance (µm) of size (28,)
energy_loss:  energy-loss (eV) of size (2048,)
 with metadata: ['experiment', 'peak_fit', 'zero_loss']
{'fit_start': -9.95, 'fit_end': 92.30000000000001, 'peaks': {'0': {'position': -9.95, 'amplitude': 1000.0, 'width': 1.0, 'type': 'Gauss', 'asymmetry': 0}}}
gg
(array([0., 0., 0., ..., 0., 0., 0.]), array([0.00000000e+00, 5.60210700e+06, 0.00000000e+00, 3.38997724e+00, 4.15490805e+04, 1.52867594e+00]))
shifts = pyTEMlib.eels_tools.get_zero_loss_energy(infoWidget.datasets['Channel_002'])
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
Cell In[29], line 1
----> 1 shifts = pyTEMlib.eels_tools.get_zero_loss_energy(infoWidget.datasets['Channel_002'])

File ~\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\eels_tools.py:340, in get_zero_loss_energy(dataset)
    338     for x in range(dataset.shape[0]):
    339         for y in range(dataset.shape[1]):
--> 340             _, shifts[x, y] = get_channel_zero(dataset[x, y, :], energy, width)
    341 return shifts

File ~\Documents\Github\pyTEMlib\notebooks\Spectroscopy\../..\pyTEMlib\eels_tools.py:298, in get_channel_zero(spectrum, energy, width)
    294 y = np.array(spectrum[int(zero-width):int(zero+width)]).copy()
    296 y[np.nonzero(y <= 0)] = 1e-12
--> 298 p0 = [energy[zero], spectrum.max(), .5]  # Initial guess is a normal distribution
    300 def errfunc(pp, xx, yy):
    301     return (gauss(xx, pp) - yy) / np.sqrt(yy)  # Distance to the target function

File ~\AppData\Local\anaconda3\Lib\site-packages\sidpy\sid\dataset.py:1220, in Dataset.reduce_dims.<locals>.wrapper_method(self, *args, **kwargs)
   1218 axis, keepdims = arguments.get('axis'), arguments.get('keepdims', False)
   1219 if axis is None and not keepdims:
-> 1220     return result.compute()
   1221 if axis is None:
   1222     axes = list(np.arange(self.ndim))

File ~\AppData\Local\anaconda3\Lib\site-packages\dask\base.py:375, in DaskMethodsMixin.compute(self, **kwargs)
    351 def compute(self, **kwargs):
    352     """Compute this dask collection
    353 
    354     This turns a lazy Dask collection into its in-memory equivalent.
   (...)
    373     dask.compute
    374     """
--> 375     (result,) = compute(self, traverse=False, **kwargs)
    376     return result

File ~\AppData\Local\anaconda3\Lib\site-packages\dask\base.py:661, in compute(traverse, optimize_graph, scheduler, get, *args, **kwargs)
    658     postcomputes.append(x.__dask_postcompute__())
    660 with shorten_traceback():
--> 661     results = schedule(dsk, keys, **kwargs)
    663 return repack([f(r, *a) for r, (f, a) in zip(results, postcomputes)])

File ~\AppData\Local\anaconda3\Lib\queue.py:180, in Queue.get(self, block, timeout)
    178         if remaining <= 0.0:
    179             raise Empty
--> 180         self.not_empty.wait(remaining)
    181 item = self._get()
    182 self.not_full.notify()

File ~\AppData\Local\anaconda3\Lib\threading.py:359, in Condition.wait(self, timeout)
    357 else:
    358     if timeout > 0:
--> 359         gotit = waiter.acquire(True, timeout)
    360     else:
    361         gotit = waiter.acquire(False)

KeyboardInterrupt: 
import scipy
dataset = infoWidget.datasets['Channel_002']
spectrum = dataset.sum(axis=tuple(range(dataset.ndim - 1)))
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[1], line 2
      1 import scipy
----> 2 dataset = infoWidget.datasets['Channel_002']
      3 spectrum = dataset.sum(axis=tuple(range(dataset.ndim - 1)))

NameError: name 'infoWidget' is not defined
import scipy
dataset = infoWidget.datasets['Channel_002']
spectrum = dataset.sum(axis=tuple(range(dataset.ndim - 1)))

startx = scipy.signal.find_peaks(spectrum/np.max(spectrum), height=0.98)[0][0]

end = startx + 3
start = startx - 3
for i in range(10):
    if spectrum[startx - i] < 0.3 * spectrum[startx]:
        start = startx - i
    if spectrum[startx + i] < 0.3 * spectrum[startx]:
        end = startx + i
if end - start < 7:
    end = startx + 4
    start = startx - 4


energy = dataset.get_spectral_dims(return_axis=True)[0].values

if dataset.ndim == 1:  # single spectrum
    _, shifts = pyTEMlib.eels_tools.get_channel_zero(np.array(dataset), energy, width)
    shifts = np.array([shifts])
elif dataset.ndim == 2:  # line scan
    shifts = np.zeros(dataset.shape[:1])
    for x in range(dataset.shape[0]):
        _, shifts[x] = pyTEMlib.eels_tools.get_channel_zero(dataset[x, :], energy, width)
elif dataset.ndim == 3:  # spectral image
    shifts = np.zeros(dataset.shape[:2])
    for x in range(dataset.shape[0]):
        for y in range(dataset.shape[1]):
            _, shifts[x, y] = pyTEMlib.eels_tools.get_channel_zero(dataset[x, y, :], energy, width)
shifts
210 202 8
4
array([[0.27885956, 0.27191713, 0.28913556, 0.25769037, 0.2942762 , 0.28620583, 0.33639917, 0.29324584, 0.23019431, 0.24396385, 0.28630434, 0.34782575, 0.29164501, 0.32428319, 0.31925456, 0.33853458, 0.34647511, 0.31610986, 0.38146446, 0.31699432, 0.34575115, 0.35986766, 0.33364593, 0.33229606, 0.34956855, 0.33242329, 0.3915634 , 0.35407163], [0.29500225, 0.2373293 , 0.25763805, 0.28486225, 0.31641727, 0.29900238, 0.28421314, 0.27215118, 0.25969281, 0.23715325, 0.3184073 , 0.29690798, 0.27968236, 0.32664399, 0.27429016, 0.30321827, 0.33636393, 0.33146419, 0.37165488, 0.31699942, 0.32685554, 0.37155651, 0.31661427, 0.34338988, 0.33284669, 0.31143029, 0.41046077, 0.35855505], [0.29311011, 0.22077191, 0.3060771 , 0.27921994, 0.28125945, 0.3067318 , 0.26348024, 0.25086256, 0.25962378, 0.2529393 , 0.31787102, 0.29516299, 0.28017314, 0.3592165 , 0.267943 , 0.30651435, 0.33832316, 0.31661111, 0.34534481, 0.28676643, 0.33204225, 0.35063015, 0.34971729, 0.36301199, 0.35443506, 0.34508562, 0.41291565, 0.32720252], [0.27862603, 0.2395802 , 0.27097475, 0.29844929, 0.32480325, 0.31210681, 0.30410157, 0.31895698, 0.25131819, 0.21974032, 0.26824316, 0.3026477 , 0.33016488, 0.36298262, 0.27516956, 0.32761501, 0.34910861, 0.30489061, 0.33654038, 0.27761667, 0.34485607, 0.41076118, 0.35082191, 0.41209721, 0.36572742, 0.35657333, 0.4043328 , 0.3366633 ], [0.28915177, 0.25477428, 0.25937191, 0.28322656, 0.33555691, 0.31758257, 0.27861604, 0.25593468, 0.30145909, 0.21596642, 0.27045277, 0.28342595, 0.33550093, 0.37912592, 0.27235156, 0.29138667, 0.35342075, 0.3278171 , 0.33455263, 0.29913195, 0.35593614, 0.37443954, 0.3313424 , 0.39522888, 0.34047513, 0.34615577, 0.37257263, 0.35127896], [0.26825451, 0.22317499, 0.27205782, 0.28977687, 0.31335867, 0.29903467, 0.30730622, 0.2254166 , 0.2501397 , 0.29506912, 0.29580712, 0.33147555, 0.3211084 , 0.34653584, 0.28070157, 0.29066366, 0.3425898 , 0.29964388, 0.33541241, 0.33303188, 0.32264911, 0.39229919, 0.34502718, 0.39487492, 0.36778998, 0.35605888, 0.3360836 , 0.34104887], [0.25465607, 0.24582089, 0.29155236, 0.26238632, 0.29120902, 0.28021102, 0.2754898 , 0.24523182, 0.26776028, 0.31574981, 0.28385829, 0.28627776, 0.30463114, 0.32875661, 0.30105687, 0.3067776 , 0.30641951, 0.31796401, 0.31963128, 0.32909494, 0.36074269, 0.37515573, 0.34797653, 0.39295098, 0.35302315, 0.36683995, 0.36417993, 0.35364533], [0.292511 , 0.23258882, 0.27376865, 0.2377322 , 0.28899703, 0.26824193, 0.27879703, 0.24322802, 0.27464024, 0.25538418, 0.25901674, 0.28047969, 0.29715362, 0.37488464, 0.25447685, 0.29050186, 0.30640089, 0.31729175, 0.33839128, 0.31065224, 0.37427601, 0.36502753, 0.35191241, 0.37469867, 0.34486259, 0.37088215, 0.34637744, 0.36111888], [0.25635235, 0.27019416, 0.27881258, 0.24296847, 0.2439347 , 0.26863875, 0.29996595, 0.25947241, 0.23179607, 0.25717334, 0.27921191, 0.30023848, 0.30469099, 0.31963415, 0.26250042, 0.3366933 , 0.31913805, 0.30438372, 0.35728285, 0.32887884, 0.35544641, 0.39674351, 0.34704318, 0.34718202, 0.34885386, 0.38141548, 0.36582743, 0.37162835], [0.2779227 , 0.22507787, 0.25349302, 0.2489468 , 0.2574619 , 0.24933503, 0.30956108, 0.29125198, 0.22917259, 0.2696706 , 0.26321472, 0.29098226, 0.31207799, 0.31331197, 0.25208947, 0.3258606 , 0.37896905, 0.33075093, 0.34549619, 0.3101756 , 0.38049917, 0.37980949, 0.32037619, 0.33618086, 0.35437024, 0.4081252 , 0.36734162, 0.39830539], [0.28461448, 0.23650725, 0.26976286, 0.29007012, 0.23048943, 0.28403545, 0.28856561, 0.27275457, 0.26200055, 0.3145652 , 0.28347842, 0.32009059, 0.31970605, 0.3433159 , 0.34734224, 0.32442136, 0.35281421, 0.31881861, 0.34979143, 0.32597294, 0.38637679, 0.35346344, 0.34316713, 0.37039857, 0.33056786, 0.37906996, 0.3923285 , 0.40072191], [0.25815332, 0.25105465, 0.26434024, 0.24352999, 0.23606594, 0.25148725, 0.28777328, 0.29084688, 0.25366795, 0.27467238, 0.3378339 , 0.30900469, 0.2893221 , 0.31765853, 0.29397576, 0.33832071, 0.3457589 , 0.28472426, 0.35705654, 0.32174799, 0.38509935, 0.35920384, 0.36480676, 0.34173499, 0.35504551, 0.38998532, 0.38938545, 0.39183795], [0.25616929, 0.27615618, 0.24044875, 0.27103228, 0.24235239, 0.2725113 , 0.2773447 , 0.29618213, 0.26213574, 0.2538839 , 0.33352775, 0.26730384, 0.33472612, 0.35442554, 0.26483493, 0.31008077, 0.36259978, 0.29427468, 0.33403016, 0.34279215, 0.35625539, 0.34078648, 0.3623414 , 0.38548391, 0.36306584, 0.37939006, 0.36419213, 0.40813366], [0.29477027, 0.29242067, 0.26208898, 0.22938211, 0.27008024, 0.26164282, 0.3395756 , 0.27354599, 0.24859205, 0.24623638, 0.28822334, 0.30557938, 0.29082779, 0.32814678, 0.29866092, 0.28825318, 0.31326961, 0.32114773, 0.32831089, 0.33195336, 0.33213739, 0.33702476, 0.38874667, 0.34270549, 0.35165803, 0.36284347, 0.33104932, 0.3598648 ], [0.31484983, 0.27133482, 0.2796955 , 0.22614179, 0.25680333, 0.30342777, 0.31641074, 0.26352313, 0.27141102, 0.24704663, 0.29384235, 0.30671874, 0.29041037, 0.32165614, 0.32233128, 0.27004443, 0.34106865, 0.29358258, 0.30716426, 0.32627813, 0.34667117, 0.36114773, 0.36030183, 0.36726092, 0.31770244, 0.38873846, 0.35912585, 0.3779826 ], [0.2745227 , 0.26616718, 0.23300789, 0.2661543 , 0.24198659, 0.26366613, 0.29255209, 0.26413508, 0.26059787, 0.26943424, 0.29420278, 0.29869293, 0.29239094, 0.27523946, 0.30449244, 0.26214181, 0.34524763, 0.30401337, 0.35973117, 0.33170239, 0.38205601, 0.36911811, 0.39509115, 0.35899128, 0.39090857, 0.37103475, 0.35419947, 0.36533401], [0.25355474, 0.26453087, 0.24993006, 0.26617811, 0.26285823, 0.25894022, 0.29097809, 0.23530484, 0.2826482 , 0.24949959, 0.30660538, 0.25883084, 0.33691935, 0.28690654, 0.30184456, 0.3005378 , 0.27657854, 0.32545669, 0.3350722 , 0.32765956, 0.37492385, 0.34372024, 0.37620028, 0.3605306 , 0.34733479, 0.35119791, 0.35081045, 0.36945515], [0.27058115, 0.29535405, 0.25933533, 0.24603051, 0.27246679, 0.27980309, 0.28700856, 0.22413112, 0.27118666, 0.28379198, 0.29113244, 0.28228985, 0.32547475, 0.29481563, 0.32189973, 0.29346086, 0.30910825, 0.33896943, 0.32250085, 0.35293158, 0.33332329, 0.34810451, 0.37229999, 0.37011539, 0.36788494, 0.32506948, 0.35174691, 0.39071821], [0.25202181, 0.31131463, 0.24169004, 0.26346343, 0.22033775, 0.21069325, 0.31788773, 0.24929155, 0.28026672, 0.30283353, 0.32265208, 0.29598524, 0.33788357, 0.28828424, 0.29400025, 0.32044516, 0.32719666, 0.33894647, 0.33687651, 0.34735657, 0.35248941, 0.33570986, 0.36135229, 0.33214425, 0.35519827, 0.33985382, 0.33577196, 0.39142653], [0.25719734, 0.28636417, 0.24679422, 0.25859183, 0.24966211, 0.29170404, 0.28522151, 0.23880383, 0.27825976, 0.28674107, 0.29818576, 0.26381539, 0.34813009, 0.26624489, 0.29720147, 0.30763793, 0.32224644, 0.32006327, 0.31661701, 0.38357174, 0.38138782, 0.31708329, 0.37834823, 0.34931166, 0.33390342, 0.30967558, 0.34603018, 0.38542046], [0.26717053, 0.3187942 , 0.25688932, 0.26465117, 0.23794704, 0.28813324, 0.29058177, 0.24887995, 0.2133812 , 0.2922364 , 0.3170021 , 0.27667117, 0.32899053, 0.30647512, 0.30744492, 0.30315152, 0.32894605, 0.36010006, 0.31707008, 0.34071347, 0.34518802, 0.2864612 , 0.32752686, 0.37130934, 0.33076248, 0.32663139, 0.33336231, 0.35315843], [0.3171484 , 0.32838144, 0.26763272, 0.25482452, 0.24839447, 0.22693682, 0.25846255, 0.23695833, 0.24745501, 0.28812388, 0.30393928, 0.31321126, 0.2949203 , 0.30777781, 0.34019723, 0.32201243, 0.3350535 , 0.36631547, 0.32803027, 0.35022398, 0.33984022, 0.29018393, 0.35647662, 0.34727768, 0.30282655, 0.34913906, 0.36157026, 0.38905264], [0.29772264, 0.31244 , 0.25824082, 0.2633365 , 0.29358153, 0.2853858 , 0.31198789, 0.25574126, 0.23576208, 0.33307473, 0.28249016, 0.30273328, 0.27431271, 0.31244071, 0.32128821, 0.31963668, 0.34839687, 0.35969038, 0.34473335, 0.34859848, 0.35485971, 0.3338992 , 0.35779789, 0.33342661, 0.32066506, 0.38048255, 0.35227182, 0.37892143]])
dir(infoWidget.info.shift_low_loss)
['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__func__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
import uuid
import time

# Combine UUID and timestamp
unique_id = f"{uuid.uuid4()}_{int(time.time() * 1000)}"
print(unique_id)

8aef8a91-2b7f-4834-a33b-c2c0b88d3b77_1715976165623
infoWidget.core_loss.update_cl_dataset()
infoWidget.datasets['resolution_functions'].metadata
{'experiment': {'single_exposure_time': 0.01, 'exposure_time': 0.21, 'number_of_frames': 21, 'collection_angle': 33.0, 'convergence_angle': 30.0, 'acceleration_voltage': 0.0, 'flux_ppm': 115.68867492675781, 'count_conversion': 1, 'beam_current': 0}, 'zero_loss': {'shifted': array([1.0174319]), 'startFitEnergy': -1.0, 'endFitEnergy': 1.0, 'fit_parameter': array([-1.51964411e-01, 5.09698919e+03, 1.33700815e+00, 2.38917861e-01, 5.06085447e+03, 1.72056710e+00]), 'original_low_loss': '1EELS Acquire (low-loss)_new'}}
infoWidget.datasets['Channel_000'].metadata
{'experiment': {'single_exposure_time': 3.0, 'exposure_time': 63.0, 'number_of_frames': 21, 'collection_angle': 50.0, 'convergence_angle': 30.0, 'acceleration_voltage': 60000.0, 'flux_ppm': 34706.602478027344, 'count_conversion': 1, 'beam_current': 0}, 'zero_loss': {'shifted': array([1.0174319])}, 'edges': {'fit_area': {'fit_start': 120.0, 'fit_end': 600.0}, '0': {'z': 5, 'symmetry': 'K1', 'element': 'B', 'onset': 188.0, 'end_exclude': 238.0, 'start_exclude': 185.0, 'all_edges': {'K1': {'onset': 188.0}}, 'chemical_shift': 0.0, 'areal_density': 1745395038619.995, 'original_onset': 188.0, 'data': array([5.66032845e-09, 5.61175423e-09, 5.56318001e-09, ..., 1.68366704e-10, 1.68110794e-10, 1.67854883e-10]), 'X_section_type': 'XRPA', 'X_section_source': 'pyTEMlib'}, '1': {'z': 7, 'symmetry': 'K1', 'element': 'N', 'onset': 401.6, 'end_exclude': 451.6, 'start_exclude': 396.6, 'all_edges': {'K1': {'onset': 401.6}}, 'chemical_shift': 0.0, 'areal_density': 5330240008575.439, 'original_onset': 401.6, 'data': array([2.25376447e-08, 2.23462509e-08, 2.21548571e-08, ..., 5.61435758e-10, 5.60622520e-10, 5.59809282e-10]), 'X_section_type': 'XRPA', 'X_section_source': 'pyTEMlib'}, 'model': {'background': energy_loss: energy-loss (eV) of size (2048,), 'background-poly_0': -7789207450.593016, 'background-poly_1': -92.67688006132725, 'background-poly_2': 0.07927340377406612, 'background-A': 7789231272.866521, 'background-r': -13.743081547476294, 'spectrum': energy_loss: energy-loss (eV) of size (2048,), 'blurred': array([139757.55 , 139617.84 , 139350.38 , ..., 658.92535, 628.73956, 612.56323], dtype=float32), 'mask': array([0., 0., 0., ..., 0., 0., 1.]), 'fit_parameter': array([ 7.78923127e+09, -1.37430815e+01, -7.78920745e+09, -9.26768801e+01, 7.92734038e-02, 1.74529850e+12, 5.33029998e+12]), 'fit_area_start': 120.0, 'fit_area_end': 600.0}}}
plt.close('all')
infoWidget.spectrum
Loading...
ll = infoWidget.low_loss.dataset
zero_loss_fit_width = infoWidget.low_loss.low_loss_tab[5, 0].value
print(zero_loss_fit_width)

ll.plot()
#vplt.plot(ll.energy_loss, ll)
0.3
<Figure size 640x480 with 1 Axes>
Loading...
infoWidget.datasets['resolution_functions'].metadata
{'experiment': {'single_exposure_time': 0.01, 'exposure_time': 0.21, 'number_of_frames': 21, 'collection_angle': 0.0, 'convergence_angle': 30.0, 'acceleration_voltage': 0.0, 'flux_ppm': 115.68867492675781, 'count_conversion': 1, 'beam_current': 0}, 'zero_loss': {'shifted': array([1.0174319]), 'startFitEnergy': -0.3, 'endFitEnergy': 0.3, 'fit_parameter': array([-1.49985841e-01, 2.33687317e+03, 1.33828265e+00, 2.36651224e-01, 1.09947513e+04, 1.72584231e+00]), 'original_low_loss': '1EELS Acquire (low-loss)_new'}}
s = infoWidget.low_loss.parent.dataset
energy_offset = s.get_spectral_dims(return_axis=True)[0][0]
energy_offset
view = core_loss.plot()

core_loss.metadata['zero_loss']['shifted']
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[25], line 1
----> 1 view = core_loss.plot()
      3 core_loss.metadata['zero_loss']['shifted']

NameError: name 'core_loss' is not defined
from tqdm import tqdm, trange, auto

dataset = infoWidget.selected_dataset
dataset.original_metadata.keys()
dataset_np = np.array(dataset)
for i in trange(1,len(dataset.energy_loss)-1):
    if np.abs(dataset_np[i] - dataset_np[i+1]) > 1e3  and np.abs(dataset_np[i] - dataset_np[i-1]) > 1e3:
        dataset_np[i] = (dataset_np[i-1] + dataset_np[i+1])/2
        pass
core_loss = dataset.like_data(dataset_np)

core_loss = eels_tools.shift_energy(core_loss, np.array([-0.2791726]))
view = core_loss.plot()
100%|██████████████████████████████████████████████████████████████████████████| 2046/2046 [00:00<00:00, 130983.97it/s]
Loading...
background, p = eels_tools.power_law_background(core_loss, core_loss.energy_loss, [250, 278])
spectrum = core_loss-background
spectrum.metadata = dataset.metadata.copy()
dataset.plot()
plt.gca().plot(spectrum.energy_loss, background)
plt.gca().plot(spectrum.energy_loss, spectrum)
Loading...

Everything we did in the dashboard above we do now one by one:

Fix energy scale and determine resolution function

please see Fitting the Zero-Loss Peak for details

Determine Relative Thickness

The probabaility of an low-loss function in a solid angle is then:

2P(EΩ)=teπ2a0m0v2Im[1ε(q,E)](1θ2+θE2)\frac{\partial^2 P}{(\partial E \partial \Omega) }= t* \frac{e}{\pi^2 a_0 m_0 v^2} {\rm Im} \left[ \frac{-1}{\varepsilon(q,E)} \right] \left( \frac{1}{\theta^2+\theta_E^2}\right)

See Notebook: Analysing Low-Loss Spectra with Drude Theory of the MSE672-Introduction-to-TEM Lecture in my Github account.

low_loss = eels_tools.align_zero_loss(infoWidget.selected_dataset)
zero_loss = eels_tools.get_resolution_functions(low_loss, -.5, .5)
plt.close('all')
plt.figure()
plt.plot(low_loss.energy_loss, zero_loss, label='resolution funcion')
plt.plot(low_loss.energy_loss, low_loss, label = 'spectrum')
plt.plot(low_loss.energy_loss, low_loss-zero_loss, label = 'difference')
plt.legend()
[-0.23899302] sidpy.Dataset of type SPECTRUM with:
 dask.array<array, shape=(2048,), dtype=float32, chunksize=(2048,), chunktype=numpy.ndarray>
 data contains: intensity (counts)
 and Dimensions: 
energy_loss:  energy-loss (eV) of size (2048,)
 with metadata: ['experiment']
Loading...
infoWidget.dataset.metadata
{'experiment': {'acceleration_voltage': 200000.0, 'beam_current': 0, 'collection_angle': 50.0, 'convergence_angle': 30.0, 'count_conversion': 1, 'exposure_time': 10.0, 'flux_ppm': 0.0, 'number_of_frames': 10000, 'single_exposure_time': 0.001}, 'peak_fit': {'edge_model': array([0., 0., 0., ..., 0., 0., 0.]), 'fit_end': 30.0, 'fit_start': 1.0, 'peak_model': array([0., 0., 0., ..., 0., 0., 0.]), 'peak_out_list': array([[1.14401631e+01, 2.92439760e+06, 2.45501896e+01], [7.97104419e-01, 2.89095444e+07, 1.71055819e+00]]), 'peaks': {'0': {'amplitude': 20986284.461096264, 'associated_edge': '', 'position': 0.8433632583641564, 'type': 'Gauss', 'width': 1.6347046209768021, 'asymmetry': 0.0}, '1': {'amplitude': 60297550.94024267, 'associated_edge': '', 'asymmetry': 0.0, 'position': 0.3943234078051374, 'type': 'Gauss', 'width': 0.8462042318305517}, '2': {'amplitude': 5149807.779796465, 'associated_edge': '', 'position': 4.681561552802686, 'type': 'Gauss', 'width': 3.805046085043105, 'asymmetry': 0.0}, '3': {'amplitude': 1768787.351821872, 'associated_edge': '', 'position': 15.717359457313327, 'type': 'Gauss', 'width': 5.034726824660322, 'asymmetry': 0.0}, '4': {'amplitude': 1860806.817558061, 'associated_edge': '', 'asymmetry': 0.0, 'position': 18.651735459709663, 'type': 'Gauss', 'width': 9.474450049577818}, '5': {'amplitude': 871061.5868498409, 'associated_edge': '', 'position': 27.65565717924107, 'type': 'Gauss', 'width': 11.173122920182822, 'asymmetry': 0.0}, '6': {'amplitude': 747444.1958128264, 'associated_edge': '', 'asymmetry': 0.0, 'position': 15.508181435473912, 'type': 'Gauss', 'width': 1.0964231231036516}, '7': {'amplitude': 582735.7941706154, 'associated_edge': '', 'position': 8.793443515617403, 'type': 'Gauss', 'width': 3.2503281905987924, 'asymmetry': 0.0}, '8': {'amplitude': 1490223.5949046034, 'associated_edge': '', 'asymmetry': 0.0, 'position': 5.072798469661356, 'type': 'Gauss', 'width': 0.8350422095351262}, '9': {'amplitude': 4264163.850603235, 'associated_edge': '', 'asymmetry': 0.0, 'position': 2.27260716852653, 'type': 'Gauss', 'width': 1.7783602300920873}}}, 'zero_loss': {'endFitEnergy': 0.5, 'fit_parameter': array([ 1.55362639e-01, 1.46387345e+05, 4.26253898e-01, -7.36465028e-02, 2.54673199e+05, 2.91093028e-01]), 'original_low_loss': 'EELS_0290_new', 'shifted': array([-0.2791726]), 'startFitEnergy': -0.5}}

peakfit

from pyTEMlib import peak_dialog
    
peakFitWidget = peak_dialog.PeakFitWidget({'low_loss':infoWidget.dataset})

from pyTEMlib import peak_dialog

    
peakFitWidget = peak_dialog.PeakFitWidget({'core_loss': spectrum})
Loading...
fi.metadata
{'experiment': {'single_exposure_time': 5.0, 'exposure_time': 100.0, 'number_of_frames': 20, 'collection_angle': 50.0, 'convergence_angle': 5.4, 'acceleration_voltage': 60000.0, 'flux_ppm': 1470027.5390625, 'count_conversion': 1, 'beam_current': 0}}
datasets = {'core_loss': spectrum, 'dataset': core_loss}
low_loss.metadata = infoWidget.selected_dataset.metadata
peakFitWidget = peak_dialog.PeakFitWidget(datasets)
Loading...
datasets = {'core_loss': spectrum, 'dataset': core_loss}
pyTEMlib.file_tools.save_dataset(datasets)
C:\Users\gduscher\AppData\Local\anaconda3\envs\py11\Lib\site-packages\pyNSID\io\hdf_utils.py:381: FutureWarning: validate_h5_dimension may be removed in a future version
  warn('validate_h5_dimension may be removed in a future version',
C:\Users\gduscher\AppData\Local\anaconda3\envs\py11\Lib\site-packages\pyNSID\io\hdf_utils.py:381: FutureWarning: validate_h5_dimension may be removed in a future version
  warn('validate_h5_dimension may be removed in a future version',
<HDF5 group "/Measurement_000" (2 members)>

model = spectrum.metadata['peak_fit']['peak_model'].copy()
spectrum.energy_loss -= 250
spectrum.energy_loss *= 0.05
spectrum.energy_loss += 250 

import scipy
help(eels_tools.gauss)
gauss = eels_tools.gauss(spectrum.energy_loss, [spectrum.energy_loss[1024], 1, .2])
gauss2 = eels_tools.gauss(spectrum.energy_loss, [spectrum.energy_loss[1024], 1, .1])
plt.figure()
plt.plot(gauss)
plt.plot(model)
Help on function gauss in module pyTEMlib.eels_tools:

gauss(x, p)
    Gaussian Function
    
    p[0]==mean, p[1]= amplitude p[2]==fwhm
    area = np.sqrt(2* np.pi)* p[1] * np.abs(p[2] / 2.3548)
    FWHM = 2 * np.sqrt(2 np.log(2)) * sigma = 2.3548 * sigma
    sigma = FWHM/3548
Loading...
spectrum.energy_loss.values[:4]
array([12.5 , 12.55, 12.6 , 12.65])
spectrum = infoWidget.dataset.copy()
model = spectrum.metadata['peak_fit']['peak_model']
zero_loss = np.array(np.roll(zero_loss, -np.argmax(np.array(zero_loss))))
j = np.fft.fft(model/model.sum())
z = np.fft.fft(zero_loss/zero_loss.sum()+1e-12)
#z2 = np.fft.fft(gauss2/gauss2.sum()*2)

red =(np.fft.ifft(j/z).real)#
plt.figure()
plt.plot(spectrum.energy_loss, red/red.sum(), label='deconvoluted', linewidth=3)
#plt.plot(zero_loss/zero_loss.sum())
plt.plot(spectrum.energy_loss, model/model.sum(), label='Gaussian mixing')
# plt.plot(red-model)
plt.ylim(0,.005)
plt.legend()
Loading...
for peak in spectrum.metadata['peak_fit']['peaks'].values():
    print (f"{peak['position']:.1f}, {peak['width']:.2f}, {peak['amplitude']:.0f}")
285.8, 1.15, 58843
304.8, 13.34, 77560
293.0, 2.01, 80868
292.1, 0.64, 74606
296.5, 6.59, 64373
301.8, 2.73, 12192
308.9, 2.47, 3753
287.2, 2.06, 13455
290.2, 0.99, 6659
329.1, 26.32, 40827
289.0, 1.82, 11961
peakFitWidget.fit_peaks()

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[29], line 1
----> 1 peakFitWidget.fit_peaks()

NameError: name 'peakFitWidget' is not defined
plt.close('all')
plt.figure()
plt.plot(peakFitWidget.energy_scale,peakFitWidget.peak_model, label='model')
plt.plot(peakFitWidget.energy_scale,peakFitWidget.dataset, label='spectrum')
plt.plot(peakFitWidget.energy_scale, peakFitWidget.dataset-peakFitWidget.peak_model-resolution_functions, label='dif')
plt.ylim(-4e7,1e8)
plt.legend()
Loading...
dataset = peakFitWidget.dataset
peak_model, peak_out_list = find_peaks(dataset-resolution_functions, -1,  30)
print(peak_out_list.reshape([int(len(peak_out_list)/3),3]))
plt.figure()
plt.plot(peak_model)
plt.plot(dataset-resolution_functions)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[215], line 2
      1 dataset = peakFitWidget.dataset
----> 2 peak_model, peak_out_list = find_peaks(dataset-resolution_functions, -1,  30)
      3 print(peak_out_list.reshape([int(len(peak_out_list)/3),3]))
      4 plt.figure()

ValueError: too many values to unpack (expected 2)
infoWidget.datasets['Channel_000'].metadata
{'experiment': {'single_exposure_time': 5.0, 'exposure_time': 100.0, 'number_of_frames': 20, 'collection_angle': 50.0, 'convergence_angle': 5.42, 'acceleration_voltage': 60000.0, 'flux_ppm': 1477088.59375, 'count_conversion': 1, 'beam_current': 0}, 'zero_loss': {'shifted': array([-0.2791726])}, 'peak_fit': {'fit_start': 270.05000372603536, 'fit_end': 350.3000052496791, 'peaks': {'0': {'position': 285.5328133398505, 'amplitude': 56813.851980084386, 'width': 1.1447315680844505, 'type': 'Gauss', 'associated_edge': '', 'asymmetry': 0.0}, '1': {'position': 291.8502789181616, 'amplitude': 80137.36537116366, 'width': 0.631699853337263, 'type': 'Gauss', 'associated_edge': '', 'asymmetry': 0.0}, '2': {'position': 292.68460898549887, 'amplitude': 67856.46722391486, 'width': 1.6722959462172458, 'type': 'Gauss', 'associated_edge': '', 'asymmetry': 0.0}, '3': {'position': 288.33077096412796, 'amplitude': 15200.2171172901, 'width': 4.03592603054892, 'type': 'Gauss', 'associated_edge': '', 'asymmetry': 0.0}, '4': {'position': 300.97498872546737, 'amplitude': 29204.484305388254, 'width': 2.9452493043214063, 'type': 'Gauss', 'associated_edge': '', 'asymmetry': 0.0}, '5': {'position': 431.4963301648659, 'amplitude': 62303.24268512067, 'width': 160.13636902692892, 'type': 'Gauss', 'associated_edge': '', 'asymmetry': 0.0}, '6': {'position': 297.57744196974863, 'amplitude': 82438.00185689674, 'width': 4.570549606775482, 'type': 'Gauss', 'associated_edge': '', 'asymmetry': 0.0}, '7': {'position': 306.55294236999856, 'amplitude': 64324.25014690288, 'width': 8.408828675311156, 'type': 'Gauss', 'associated_edge': '', 'asymmetry': 0.0}, '8': {'position': 327.23866847395425, 'amplitude': 24332.78308524786, 'width': 16.520135069307326, 'type': 'Gauss', 'associated_edge': '', 'asymmetry': 0.0}, '9': {'position': 302.73254089477655, 'amplitude': 30379.325543758885, 'width': 4.215055093093726, 'type': 'Gauss', 'associated_edge': '', 'asymmetry': 0.0}, '10': {'position': 313.39578279938394, 'amplitude': 13507.040368003669, 'width': 9.086317779116715, 'type': 'Gauss', 'associated_edge': '', 'asymmetry': 0.0}, '11': {'position': 293.7938526566573, 'amplitude': 56893.252049088034, 'width': 3.7967168653233117, 'type': 'Gauss', 'associated_edge': '', 'asymmetry': 0.0}}, 'edge_model': array([0., 0., 0., ..., 0., 0., 0.]), 'peak_model': array([0., 0., 0., ..., 0., 0., 0.])}}
import scipy
def residuals_ll(p, x, y, only_positive_intensity):
    """part of fit"""

    err = (y - model_ll(x, p, only_positive_intensity)) / np.sqrt(np.abs(y))
    return err

def model_ll(x, p, only_positive_intensity):
    """part of fit"""

    y = np.zeros(len(x))

    number_of_peaks = int(len(p) / 3)
    for i in range(number_of_peaks):
        if only_positive_intensity:
            p[i * 3 + 1] = abs(p[i * 3 + 1])
        p[i * 3 + 2] = abs(p[i * 3 + 2])
        if p[i * 3 + 2] > abs(p[i * 3]) * 4.29193 / 2.0:
            p[i * 3 + 2] = abs(p[i * 3]) * 4.29193 / 2.  # ## width cannot extend beyond zero, maximum is FWTM/2

        y = y + gauss(x, p[i * 3:])

    return y

def gauss(x, p):  # p[0]==mean, p[1]= amplitude p[2]==fwhm,
    """Gaussian Function

        p[0]==mean, p[1]= amplitude p[2]==fwhm
        area = np.sqrt(2* np.pi)* p[1] * np.abs(p[2] / 2.3548)
        FWHM = 2 * np.sqrt(2 np.log(2)) * sigma = 2.3548 * sigma
        sigma = FWHM/3548
    """
    if p[2] == 0:
        return x * 0.
    else:
        return p[1] * np.exp(-(x - p[0]) ** 2 / (2.0 * (p[2] / 2.3548) ** 2))

def find_peaks(dataset, fit_start, fit_end):
    energy_scale = dataset.get_spectral_dims(return_axis=True)[0].values

    start_channel = np.searchsorted(energy_scale, fit_start)
    end_channel = np.searchsorted(energy_scale, fit_end)
    spectrum = np.abs(np.array(dataset)[start_channel:end_channel])
    i_pk = scipy.signal.find_peaks_cwt(spectrum, widths=range(3, len(energy_scale) // 30)) # 
    
    p_in = np.ravel([[energy_scale[i]-fit_start, spectrum[i], .7] for i in i_pk])
    
    return p_in
    
def fit_peaks(spectrum, pin, start_fit, end_fit, only_positive_intensity=False):

    energy_scale =  spectrum.get_spectral_dims(return_axis=True)[0]
    start_fit = np.searchsorted(energy_scale, start_fit)
    end_fit = np.searchsorted(energy_scale, end_fit)
    
    fit_energy = energy_scale[start_fit:end_fit]
    spectrum = np.array(spectrum)
    fit_spectrum = spectrum[start_fit:end_fit]

    #pin_flat = [item for sublist in pin for item in sublist]
    [p_out, _] = leastsq(residuals_ll, np.array(pin), args=(fit_energy, fit_spectrum,
                                                                        only_positive_intensity))
    #p_out, pcov = curve_fit(residuals_ll, fit_energy, fit_spectrum, p0=np.array(pin))
    p = []
    for i in range(int(len(pin)/3)):
        if only_positive_intensity:
            p_out[i * 3 + 1] = abs(p_out[i * 3 + 1])
        p.append([p_out[i * 3], p_out[i * 3 + 1], abs(p_out[i * 3 + 2])])
    return p_out


fit_end = 40
peak_out_list = find_peaks(infoWidget.selected_dataset-resolution_functions, -1, fit_end)
p = fit_peaks(dataset-resolution_functions,peak_out_list,-1, fit_end)
model = model_ll(energy_scale,np.array(p), False)

print(len(peak_out_list)/3)

print(fit_end)
print(p.reshape([int(len(p)/3),3]))
print(len(p)/3)
plt.figure()
plt.plot(energy_scale, model)
plt.plot(energy_scale, dataset-resolution_functions)
plt.plot(energy_scale, dataset-resolution_functions-model)
plt.ylim(0,1e8)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[28], line 73
     69     return p_out
     72 fit_end = 40
---> 73 peak_out_list = find_peaks(infoWidget.selected_dataset-resolution_functions, -1, fit_end)
     74 p = fit_peaks(dataset-resolution_functions,peak_out_list,-1, fit_end)
     75 model = model_ll(energy_scale,np.array(p), False)

NameError: name 'resolution_functions' is not defined
peak_out_list2 = find_peaks(infoWidget.selected_dataset-resolution_functions-model, -1, fit_end)
peak_out_list = np.append(peak_out_list,peak_out_list2)
print(len(peak_out_list)/3)
p = fit_peaks(dataset-resolution_functions,peak_out_list,-1, fit_end )
model = model_ll(energy_scale,np.array(p), False)
model2 = model_ll(energy_scale,np.array(peak_out_list2), False)
print(np.std(np.array(dataset-resolution_functions)-model))
print(len(p)/3)
plt.figure()
plt.plot(energy_scale, model+resolution_functions, label='model')
plt.plot(energy_scale, model2, label='model1')
plt.plot(energy_scale, dataset, label='spectrum')
plt.plot(energy_scale, dataset-resolution_functions-model, label='difference')
plt.ylim(0,1e8)
plt.legend()
23.0
1877529801.672969
23.0
C:\Users\gduscher\AppData\Local\anaconda3\envs\py11\Lib\site-packages\scipy\optimize\_minpack_py.py:494: RuntimeWarning: Number of calls to function has reached maxfev = 14000.
  warnings.warn(errors[info][0], RuntimeWarning)
Loading...
model[:130] = 0.
model2_f = scipy.fft.fft(np.array(dataset)) #model+np.array(resolution_functions))

res_f =scipy.fft.fft(np.array(resolution_functions))
smear = gauss(energy_scale, [0,1, .2])
smear *= resolution_functions.sum()/smear.sum()
gaus_f = scipy.fft.fft(smear)  # p[0]==mean, p[1]= amplitude p[2]==fwhm,
model2 =  scipy.fft.ifft(model2_f/res_f*gaus_f).real
print(model2)
#model2 = model+np.array(resolution_functions)
print(model2.shape)
print(len(p)/3)
plt.figure()
plt.plot(energy_scale, model+resolution_functions, label='model')
plt.plot(energy_scale, model2, label='model1')
plt.plot(energy_scale, dataset, label='spectrum')
plt.plot(energy_scale, dataset-resolution_functions-model, label='difference')
plt.ylim(0,1e8)
plt.legend()
[-1198221.9850117   2628210.59194557  4581554.52393588 ...
 -2260492.70274396 -2410574.75171163 -2582093.5075449 ]
(2048,)
11.0
Loading...
plt.figure()
#plt.plot(energy_scale, model+resolution_functions)
plt.plot(energy_scale, model2)
Loading...
np.append([1,2,3], [4,5,6])
array([1, 2, 3, 4, 5, 6])
plt.close('all')




peak_model, peak_out_list = eels_tools.find_peaks(infoWidget.selected_dataset, 1,40)

new_list = np.reshape(peak_out_list, [len(peak_out_list) // 3, 3])
area = np.sqrt(2 * np.pi) * np.abs(new_list[:, 1]) * np.abs(new_list[:, 2] / np.sqrt(2 * np.log(2)))
arg_list = np.argsort(area)[::-1]
area = area[arg_list]
peak_out_list = new_list[arg_list]

number_of_peaks = np.searchsorted(area * -1, -np.average(area))

peak_model, peak_out_list[0], number_of_peaks
(array([0., 0., 0., ..., 0., 0., 0.]), array([2.03888490e+01, 6.60088441e+05, 9.51555853e+00]), 7)
peak_model, peak_out_list[0], number_of_peaks
(19, 3)
peakmodel, peak_out_list, number_of_peaks = smooth(infoWidget.selected_dataset, 1, False)
def smooth(dataset, iterations, advanced_present):
    """Gaussian mixture model (non-Bayesian)

    Fit lots of Gaussian to spectrum and let the program sort it out
    We sort the peaks by area under the Gaussians, assuming that small areas mean noise.

    """

    # TODO: add sensitivity to dialog and the two functions below
    
    # peaks = dataset.metadata['peak_fit']

    peaks ={'fit_start':1,
            'fit_end': 40}

    peak_model, peak_out_list = eels_tools.find_peaks(dataset, peaks['fit_start'], peaks['fit_end'])
    peak_out_list = [peak_out_list]

    flat_list = [item for sublist in peak_out_list for item in sublist]
    new_list = np.reshape(flat_list, [len(flat_list) // 3, 3])
    area = np.sqrt(2 * np.pi) * np.abs(new_list[:, 1]) * np.abs(new_list[:, 2] / np.sqrt(2 * np.log(2)))
    arg_list = np.argsort(area)[::-1]
    area = area[arg_list]
    peak_out_list = new_list[arg_list]

    number_of_peaks = np.searchsorted(area * -1, -np.average(area))

    return peak_model, peak_out_list, number_of_peaks
len(peakFitWidget.peak_out_list)
6
peakFitWidget.sidebar[7,0].value = 2

options = list(peakFitWidget.sidebar[7,0].options)
options.insert(-1, (f'Peak {len(options)}', len(options)-1))
len(options), options
(7, [('Peak 1', 0), ('ll', -2), ('Peak 3', 2), ('Peak 4', 3), ('Peak 5', 4), ('Peak 6', 5), ('add peak', -1)])
plt.figure()
plt.plot(resolution_functions)
plt.plot(eels_dataset)
Loading...
                                                        
view = resolution_functions.plot()
view.gca().plot(eels_dataset.energy_loss, eels_dataset)
eels_dataset.metadata
energy_shift = resolution_functions.metadata['low_loss']['shifts']
fwhm = resolution_functions.metadata['low_loss']['widths']

t_mfp = np.log(eels_dataset.sum(axis=2)/resolution_functions.sum(axis=2))

plt.figure()
ax1 = plt.subplot(131)
plt.imshow(energy_shift)
plt.colorbar()
plt.title(f' energy shift - mean: {np.mean(energy_shift):.2f}, std {np.std(energy_shift):.3f}')
ax2 = plt.subplot(132)
plt.imshow(fwhm)
plt.colorbar()
plt.title(f' peak widths - mean: {np.mean(fwhm):.2f}, std {np.std(fwhm):.3f}')
ax3 = plt.subplot(133)
plt.imshow(t_mfp)
plt.colorbar()
plt.title(f' thickness - mean: {np.mean(np.array(t_mfp)):.2f}, std {np.std(np.array(t_mfp)):.3f}')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\EELS\Analyse_Low_Loss.ipynb Cell 11 line 1
----> <a href='vscode-notebook-cell:/c%3A/Users/gduscher/Documents/Github/pyTEMlib/notebooks/EELS/Analyse_Low_Loss.ipynb#X13sZmlsZQ%3D%3D?line=0'>1</a> energy_shift = resolution_functions.metadata['low_loss']['shifts']
      <a href='vscode-notebook-cell:/c%3A/Users/gduscher/Documents/Github/pyTEMlib/notebooks/EELS/Analyse_Low_Loss.ipynb#X13sZmlsZQ%3D%3D?line=1'>2</a> fwhm = resolution_functions.metadata['low_loss']['widths']
      <a href='vscode-notebook-cell:/c%3A/Users/gduscher/Documents/Github/pyTEMlib/notebooks/EELS/Analyse_Low_Loss.ipynb#X13sZmlsZQ%3D%3D?line=3'>4</a> t_mfp = np.log(eels_dataset.sum(axis=2)/resolution_functions.sum(axis=2))

AttributeError: 'tuple' object has no attribute 'metadata'

Shift energy scale

eels_dataset.metadata['low_loss'].update(resolution_functions.metadata['low_loss'])
shifted_dataset = eels_tools.shift_on_same_scale(eels_dataset)
view = shifted_dataset.plot()
Loading...
shifted_resolution_functions = eels_tools.get_resolution_functions(shifted_dataset, zero_loss_fit_width=.9)
dif = shifted_dataset - shifted_resolution_functions
view = dif.plot()
c:\Users\gduscher\AppData\Local\anaconda3\envs\pyTEMlib\Lib\site-packages\scipy\optimize\_minpack_py.py:492: RuntimeWarning: Number of calls to function has reached maxfev = 2000.
  warnings.warn(errors[info][0], RuntimeWarning)
Loading...
datasets = fileWidget.datasets
#datasets['energy_corrected'] = shifted_dataset
#datasets['energy_corrected_resolution_function'] = shifted_resolution_functions

infoWidget= interactive_eels.InfoWidget(datasets)
c:\Users\gduscher\AppData\Local\anaconda3\envs\pyTEMlib\Lib\site-packages\jupyter_client\session.py:719: UserWarning: Message serialization failed with:
Out of range float values are not JSON compliant
Supporting this message is deprecated in jupyter-client 7, please make sure your message is JSON-compliant
  content = self.pack(content)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[8], line 5
      1 datasets = fileWidget.datasets
      2 #datasets['energy_corrected'] = shifted_dataset
      3 #datasets['energy_corrected_resolution_function'] = shifted_resolution_functions
----> 5 infoWidget= interactive_eels.InfoWidget(datasets)

File c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\EELS\../..\pyTEMlib\info_dialog.py:428, in InfoWidget.__init__(self, datasets)
    423 self.figure.canvas.toolbar_visible = True
    426 self.axis = None
--> 428 self.set_dataset()
    429 self.set_action()
    431 self.start_cursor = ipywidgets.FloatText(value=0, description='Start:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px'))

File c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\EELS\../..\pyTEMlib\info_dialog.py:527, in InfoWidget.set_dataset(self, index)
    525 self.sidebar[13,0].value = self.datasets[self.key].metadata['experiment']['beam_current']
    526 self.figure.clear()
--> 527 view = self.dataset.plot(figure=self.figure)
    528 if hasattr(self.dataset.view, 'axes'):
    529     self.axis = self.dataset.view.axes[-1]

File c:\Users\gduscher\AppData\Local\anaconda3\envs\pyTEMlib\Lib\site-packages\sidpy\sid\dataset.py:556, in Dataset.plot(self, verbose, figure, **kwargs)
    554         self.view = ComplexSpectralImageVisualizer(self, figure=figure, **kwargs)
    555     else:
--> 556         self.view = SpectralImageVisualizer(self, figure=figure, **kwargs)
    557     # plt.show()
    558 else:
    559     raise NotImplementedError('Datasets with data_type {} cannot be plotted, yet.'.format(self.data_type))

File c:\Users\gduscher\AppData\Local\anaconda3\envs\pyTEMlib\Lib\site-packages\sidpy\viz\dataset_viz.py:593, in SpectralImageVisualizer.__init__(self, dset, figure, horizontal, **kwargs)
    591 if len(self.energy_scale)!=self.spectrum.shape[0]:
    592     self.spectrum = self.spectrum.T
--> 593 self.axes[1].plot(self.energy_scale, self.spectrum.compute())
    594 self.axes[1].set_title('spectrum {}, {}'.format(self.x, self.y))
    595 self.xlabel = self.dset.labels[self.spec_dim]

File c:\Users\gduscher\AppData\Local\anaconda3\envs\pyTEMlib\Lib\site-packages\matplotlib\axes\_axes.py:1690, in Axes.plot(self, scalex, scaley, data, *args, **kwargs)
   1688 lines = [*self._get_lines(*args, data=data, **kwargs)]
   1689 for line in lines:
-> 1690     self.add_line(line)
   1691 if scalex:
   1692     self._request_autoscale_view("x")

File c:\Users\gduscher\AppData\Local\anaconda3\envs\pyTEMlib\Lib\site-packages\matplotlib\axes\_base.py:2304, in _AxesBase.add_line(self, line)
   2301 if line.get_clip_path() is None:
   2302     line.set_clip_path(self.patch)
-> 2304 self._update_line_limits(line)
   2305 if not line.get_label():
   2306     line.set_label(f'_child{len(self._children)}')

File c:\Users\gduscher\AppData\Local\anaconda3\envs\pyTEMlib\Lib\site-packages\matplotlib\axes\_base.py:2327, in _AxesBase._update_line_limits(self, line)
   2323 def _update_line_limits(self, line):
   2324     """
   2325     Figures out the data limit of the given line, updating self.dataLim.
   2326     """
-> 2327     path = line.get_path()
   2328     if path.vertices.size == 0:
   2329         return

File c:\Users\gduscher\AppData\Local\anaconda3\envs\pyTEMlib\Lib\site-packages\matplotlib\lines.py:1029, in Line2D.get_path(self)
   1027 """Return the `~matplotlib.path.Path` associated with this line."""
   1028 if self._invalidy or self._invalidx:
-> 1029     self.recache()
   1030 return self._path

File c:\Users\gduscher\AppData\Local\anaconda3\envs\pyTEMlib\Lib\site-packages\matplotlib\lines.py:681, in Line2D.recache(self, always)
    679     self._x_filled = self._x.copy()
    680     indices = np.arange(len(x))
--> 681     self._x_filled[nanmask] = np.interp(
    682         indices[nanmask], indices[~nanmask], self._x[~nanmask])
    683 else:
    684     self._x_filled = self._x

File <__array_function__ internals>:200, in interp(*args, **kwargs)

File c:\Users\gduscher\AppData\Local\anaconda3\envs\pyTEMlib\Lib\site-packages\numpy\lib\function_base.py:1595, in interp(x, xp, fp, left, right, period)
   1592     xp = np.concatenate((xp[-1:]-period, xp, xp[0:1]+period))
   1593     fp = np.concatenate((fp[-1:], fp, fp[0:1]))
-> 1595 return interp_func(x, xp, fp, left, right)

ValueError: array of sample points is empty
v = shifted_dataset.plot()
<Figure size 640x480 with 2 Axes>
Loading...
FWHM, energy_shift = eels_tools.fix_energy_scale(eels_dataset)

print(f'Zero Loss with energy resolution of {FWHM:.2f} eV at position {energy_shift:.3f} eV')
eels_dataset.energy_loss -= energy_shift

zero_loss, _ = eels_tools.resolution_function(eels_dataset.energy_loss, eels_dataset, .4)
print(zero_loss)
plt.figure()
plt.plot(eels_dataset.energy_loss, eels_dataset, label='spectrum')
plt.plot(eels_dataset.energy_loss, zero_loss, label = 'zero-loss')
plt.plot(eels_dataset.energy_loss, np.array(eels_dataset)-zero_loss , label = 'difference')

plt.title ('Lorentzian Product Fit of Zero-Loss Peak')
#plt.xlim(-5,30)
plt.legend();
Izl = zero_loss.sum()
Itotal = np.array(eels_dataset).sum()
tmfp = np.log(Itotal/Izl)
print(f'Sum of Zero-Loss: {Izl:.3f} %')
print(f'Sum of Spectrum: {Itotal:.3f} %')
print (f'thickness [IMFP]: {tmfp:.5f}')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[40], line 1
----> 1 FWHM, energy_shift = eels_tools.fix_energy_scale(eels_dataset[0,0])
      3 print(f'Zero Loss with energy resolution of {FWHM:.2f} eV at position {energy_shift:.3f} eV')
      4 eels_dataset.energy_loss -= energy_shift

File c:\Users\gduscher\Documents\Github\pyTEMlib\notebooks\EELS\../..\pyTEMlib\eels_tools.py:1116, in fix_energy_scale(spec, energy)
   1113     if not isinstance(spec, np.ndarray):
   1114         return
-> 1116 start = np.searchsorted(energy, -10)
   1117 end = np.searchsorted(energy, 10)
   1118 startx = np.argmax(spec[start:end]) + start

File <__array_function__ internals>:200, in searchsorted(*args, **kwargs)

File c:\Users\gduscher\AppData\Local\anaconda3\envs\pyTEMlib\Lib\site-packages\numpy\core\fromnumeric.py:1413, in searchsorted(a, v, side, sorter)
   1345 @array_function_dispatch(_searchsorted_dispatcher)
   1346 def searchsorted(a, v, side='left', sorter=None):
   1347     """
   1348     Find indices where elements should be inserted to maintain order.
   1349 
   (...)
   1411 
   1412     """
-> 1413     return _wrapfunc(a, 'searchsorted', v, side=side, sorter=sorter)

File c:\Users\gduscher\AppData\Local\anaconda3\envs\pyTEMlib\Lib\site-packages\numpy\core\fromnumeric.py:54, in _wrapfunc(obj, method, *args, **kwds)
     52 bound = getattr(obj, method, None)
     53 if bound is None:
---> 54     return _wrapit(obj, method, *args, **kwds)
     56 try:
     57     return bound(*args, **kwds)

File c:\Users\gduscher\AppData\Local\anaconda3\envs\pyTEMlib\Lib\site-packages\numpy\core\fromnumeric.py:43, in _wrapit(obj, method, *args, **kwds)
     41 except AttributeError:
     42     wrap = None
---> 43 result = getattr(asarray(obj), method)(*args, **kwds)
     44 if wrap:
     45     if not isinstance(result, mu.ndarray):

ValueError: object of too small depth for desired array

Fitting a Drude Function to Plasmon

The position and the width are important materials parameters and we can derive them by fitting the Drude function to the volume plasmon region.

Drude Function

Most of the inelastically scattered electron arise from interaction with outer shell electrons. These interactions, therefore, have a high intensity and are easy to obtain.

The energy-loss function FelF_{el} on the other hand is determined by the dielectric function ε\varepsilon through:

Fel=[1ε(ω)]F_{el} = \Im \left[\frac{-1}{\varepsilon(\omega)} \right]

The dielectric function in the Drude theory is given by two input parameters the position of the plasmon energy EpE_p and the width of the plasmon Γ\Gamma

ε(ω)=ε1+iε2=1+χ=1ωp2ω2+Γ2+iΓωp2ω(ω2+Γ2)ε(ω) = ε1 + iε2 = 1 + χ = 1 − \frac{\omega_p^2}{\omega^2+\Gamma^2} + \frac{i\Gamma \omega_p^2}{\omega(\omega^2+\Gamma^2)}

Here ω\omega is the angular frequency (rad/s) of forced oscillation and ωp\omega_p is the natural or resonance frequency for plasma oscillation, given by

ωp=ne2(ε0m0)ω_p = \sqrt{\frac{ne^2}{(ε_0m_0)}}

A transmitted electron represents a sudden impulse of applied electric field, containing all angular frequencies (Fourier components). Setting up a plasma oscillation of the loosely bound outer-shell electrons in a solid is equivalent to creating a pseudoparticle of energy Ep=ωpE_p = \hbar \omega_p, known as a plasmon (Pines, 1963).

from scipy.optimize import leastsq, curve_fit
eels_dataset = spec
def Drude(E,Ep,Ew, gamma=1):
    eps = 1 - Ep**2/(E**2+Ew**2) +1j* Ew* Ep**2/E/(E**2+Ew**2)
    eps = 1 - (Ep**2 - Ew * E * 1j) / (E**2 + 2 * E * gamma * 1j)  # Mod drude ter
    elf = (-1/eps).imag
    return eps,elf

def errfDrude(p, y, x):
    eps,elf = Drude(x,p[0],p[1])
    err = y - p[2]*elf
    #print (p,sum(np.abs(err)))
    return np.abs(err)#/np.sqrt(y)


pin2 = np.array([9,1,.7, 1.11])
E = energy_scale = eels_dataset.energy_loss
startFit =np.argmin(abs(energy_scale-6))
endFit = np.argmin(abs(energy_scale-15))
    
p2, lsq = leastsq(errfDrude, pin2, args=(eels_dataset[startFit:endFit], energy_scale[startFit:endFit]), maxfev=2000)

eps, elf =Drude(energy_scale,p2[0],p2[1],p2[3])
drudePSD = p2[2]* elf
plt.figure()

plt.plot(energy_scale,eels_dataset)
plt.plot(energy_scale,drudePSD)
plt.plot(energy_scale,eels_dataset-drudePSD)
plt.axhline(0, color='black')

#plt.gca().set_xlim(0,40)
#plt.gca().set_ylim(-0.01,0.2)
print(f"Drude Theory with Plamson Energy: {p2[0]:2f} eV and plasmon Width {p2[1]:.2f} eV") 
print(f"Max of Plasmon at {energy_scale[drudePSD.argmax(0)]:.2f} eV")
print(f"Amplitude of  {p2[2]:.2f} was deteremined by fit ")
p2
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[5], line 2
      1 from scipy.optimize import leastsq, curve_fit
----> 2 eels_dataset = spec
      3 def Drude(E,Ep,Ew, gamma=1):
      4     eps = 1 - Ep**2/(E**2+Ew**2) +1j* Ew* Ep**2/E/(E**2+Ew**2)

NameError: name 'spec' is not defined
plt.figure()
plt.title ('Drude Fit: Dielectric Function - Permittivity')
plt.plot(energy_scale,eps.real,label = 'Re($\epsilon)$')
plt.plot(energy_scale,eps.imag,label = 'Im($\epsilon)$')
plt.plot(energy_scale,drudePSD,label = 'loss-function$_{Drude}$')
plt.plot(energy_scale,eels_dataset,label = 'loss-function$_{exp}$')
plt.axhline(0, color='black')

plt.gca().set_xlim(0,40)
plt.gca().set_ylim(-2.5,5.3)

plt.legend();
<>:3: SyntaxWarning: invalid escape sequence '\e'
<>:4: SyntaxWarning: invalid escape sequence '\e'
<>:3: SyntaxWarning: invalid escape sequence '\e'
<>:4: SyntaxWarning: invalid escape sequence '\e'
C:\Users\gduscher\AppData\Local\Temp\ipykernel_17524\467939617.py:3: SyntaxWarning: invalid escape sequence '\e'
  plt.plot(energy_scale,eps.real,label = 'Re($\epsilon)$')
C:\Users\gduscher\AppData\Local\Temp\ipykernel_17524\467939617.py:4: SyntaxWarning: invalid escape sequence '\e'
  plt.plot(energy_scale,eps.imag,label = 'Im($\epsilon)$')
Loading...
tmfp = .3
zl2 = zero_loss
        
LLene = np.arange(1,2048)/5

zero_loss, _ = eels_tools.resolution_function(eels_dataset.energy_loss, eels_dataset, .4)

ZP = np.array(zl2).argmax(0) # zl peak position 
print(ZP)

_, SSD = Drude(LLene,15, 2 )
PSD = np.zeros(len(LLene))
FAC = 1.

ssd  = np.fft.fft(SSD)
ssd2 = ssd.copy()
SSD2 = SSD.copy()
for order in range(20):
    # This order convoluted spectum 
    PPSD = np.zeros(len(LLene))
    # convoluted SSD is SSD2
    SSD2 = np.fft.ifft(ssd).real

    # scale right (could be done better? GERD)
    mult = sum(SSD)/sum(SSD2)

    SSD2 *= mult.real/np.exp(-tmfp)
    EP = np.array(SSD2).argmax(0)
    PPSD = SSD2/FAC*np.power(tmfp,(order))*np.exp(-tmfp)*1e12
    # Add this order t0 final spectrum
    PSD += PPSD
    # Get next order factor
    FAC=FAC*(order+2.)

    # convolute next order
    ssd = ssd * ssd2




            
plt.figure()
plt.plot(SSD/SSD.max())
plt.plot(PSD/PSD.max())
173
Loading...
from scipy.interpolate import splev,splrep,splint
def MakeDrudeVL(dataset, tmfp, zero_loss, Ep, Ew, Eh):
        energy_scale = np.arange(1,2049)/5
        
        ZP = np.array(zero_loss).argmax(0) # zl peak position 
        _, PSD = Drude(energy_scale,Ep, Ew )
        PSD /= PSD.sum()
        
        FAC = 1.

        ### sum contribution from each order of scattering:
        ssd  = np.fft.fft(PSD)
        
        SSD_sum = PSD.sum()
        ssd2 = ssd.copy()
        PSD /= FAC*np.power(tmfp,(0))*np.exp(-tmfp)
        for order in range(1,15):
            FAC=FAC*(order+2.)
            ssd *= ssd2   
            # convoluted SSD is SSD2
            SSD2 = np.fft.ifft(ssd).real

            # scale right (could be done better? GERD)
            mult = SSD_sum/sum(SSD2)

            SSD2 *= mult.real/np.exp(-tmfp)
            EP = np.array(SSD2).argmax(0)
            PPSD = SSD2/FAC*np.power(tmfp,(order))*np.exp(-tmfp)
            # Add this order t0 final spectrum
            PSD += PPSD
            
            # convolute next order
        dispersion = dataset.energy_loss.slope
        
        factorZL =  Eh/dispersion*2 #, #zero_loss.sum()*(np.exp(tmfp)-1)/PSD.sum()*Eh/dispersion/4
        #print(factorZL, Eh)
        
        BGDcoef = splrep(energy_scale,PSD,s=0)
        
        cts =splev( dataset.energy_loss, BGDcoef)*factorZL #*p[1]
        
        #cts += zero_loss
        
        return cts
    
    

#zero_loss, _ = eels_tools.resolution_function(eels_dataset.energy_loss, eels_dataset, .4)
#Izl = zero_loss.sum()
#Itotal = np.array(eels_dataset).sum()
#tmfp = np.log(Itotal/Izl)
tmfp = 0.3
zero_loss = infoWidget.datasets['resolution_function']

LL = MakeDrudeVL(spec, tmfp, zero_loss, p0[0]-5,.5, p0[2])
print(LL.max(), LL.sum())
plt.figure()
plt.plot(LL, label='Multi')
plt.plot(eels_dataset, label='spec')
plt.plot(eels_dataset-LL, label='dif')
plt.legend()
#plt.ylim(-.1,.2)
229957.93374337783 45464262.67521657
Loading...

def errfDrude(p, y):
    LL = MakeDrudeVL(y, p[3], zero_loss, p[0],p[1],p[2])
    err = y - LL
    #print (p,sum(np.abs(err)))
    return np.abs(err)#/np.sqrt(y)


pin2 = np.array([15,1,.7, 0.3])
E = energy_scale = eels_dataset.energy_loss
startFit =np.argmin(abs(energy_scale-13))
endFit = np.argmin(abs(energy_scale-18))
    
p2, lsq = leastsq(errfDrude, pin2, args=(eels_dataset), maxfev=2000)

LL = MakeDrudeVL(eels_dataset, p2[3], zero_loss, p2[0],p2[1],p2[2])
plt.figure()
plt.plot(LL)
plt.plot(eels_dataset)
plt.legend()
C:\Users\gduscher\AppData\Local\Temp\ipykernel_17524\2622750204.py:19: UserWarning: No artists with labels found to put in legend.  Note that artists whose label start with an underscore are ignored when legend() is called with no argument.
  plt.legend()
Loading...
p2[3]
0.8326588466281821
np.power(0.3,(0))*np.exp(-.3)
0.7408182206817179
zero_loss.sum()
array(1.68808473)
def newDrudeBgd(x, p):
    tmfp = 500  #p[3]
    startB = x[0]
    endB = x[-1]
    p = np.abs(p)


    LLene = np.linspace(1, 2047,2048)
    eps = pyTEMlib.eels_tools.drude(LLene,p[0], p[1], p[2])
    SSD = (-1/eps).imag
    ssd  = np.fft.fft(SSD)

    ssd2 = ssd.copy()
    SSD2 = SSD.copy()

    ### sum contribution from each order of scattering:
    PSD = np.zeros(len(LLene))
    for order in range(1):
        # This order convoluted spectum 
        PPSD = np.zeros(len(LLene))
        # convoluted SSD is SSD2
        SSD2 = np.fft.ifft(ssd).real

        # scale right (could be done better? GERD) 
        print( sum(SSD)/sum(SSD2))
        mult = sum(SSD)/sum(SSD2)
        SSD2 *= abs(mult)

        PPSD = SSD2/scipy.special.factorial(order+1)*np.power(tmfp,(order+1))*np.exp(-tmfp) #using equation 4.1 of egerton ed2
       # Add this order to final spectrum
        PSD += PPSD

        # next order convolution
        ssd = ssd * ssd2


    cts = np.zeros(len(x))

    if startB < 0:
        startB = 0
    BGDcoef = scipy.interpolate.splrep(LLene[int(startB):int(endB)],PSD[int(startB):int(endB)],s=0)


    lin = np.zeros(len(x))

    cts = scipy.interpolate.splev( x, BGDcoef)*p[1]
    return cts
LLene = np.linspace(1, 2047,2048)
p = p0
eps = pyTEMlib.eels_tools.drude(LLene,p[0], p[1], p[2])
SSD = (-1/eps).imag

plt.figure()
plt.plot(SSD)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[7], line 2
      1 LLene = np.linspace(1, 2047,2048)
----> 2 p = p0
      3 eps = pyTEMlib.eels_tools.drude(LLene,p[0], p[1], p[2])
      4 SSD = (-1/eps).imag

NameError: name 'p0' is not defined
newDrudeBgd( np.array(spec.energy_loss[200:]), p0)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[8], line 1
----> 1 newDrudeBgd( np.array(spec.energy_loss[200:]), p0)

NameError: name 'spec' is not defined
def DrudeBgd(y, x, imfp, p):



        # Fit function is the spectrum - new LL bgd devided by poinson noise
        def newLL(p, y, x):
            
            err = (y - newDrudeBgd( x,p))
            #print(p, sum( err))
            return err

        # Least square fit
        pDLLBgd, lsq = scipy.optimize.leastsq(newLL, p0, args=(y, x), maxfev=2000)
        #print(sum(newLL(pZL, y, x)))
        # cts is the result of the fit
        cts=newDrudeBgd(x, abs(pDLLBgd))
        #print("new LLL background ", pZL)
        #tags['DrudeLLBgd'] = pDLLBgd
        print(pDLLBgd)
        
        
        return cts
infoWidget.datasets['plasmon'].metadata
{'experiment': {'single_exposure_time': 0.1, 'exposure_time': 10.0, 'number_of_frames': 100, 'collection_angle': 100.0, 'convergence_angle': 0.0, 'microscope': 'Libra 200 MC', 'acceleration_voltage': 199990.28125, 'flux_ppm': 4875.3037109375, 'count_conversion': 1, 'beam_current': 0}, 'zero_loss': {'shifted': array([-0.14012023]), 'startFitEnergy': -0.5, 'endFitEnergy': 0.5, 'fit_parameter': array([-1.63207010e-02, 2.06835590e+04, 1.92327897e-01, 3.38795374e-02, 2.25742582e+04, 2.93662067e-01]), 'original_low_loss': 'EELS90muOAonaxis3_new_new'}, 'plasmon': {'parameter': array([1.50312722e+01, 7.45905381e-01, 3.48811157e+05]), 'epsilon': array([ 0. +0.j , 0. +0.j , 0. +0.j , ..., 293283.07757369+9900.8221703j , 293342.39439935+9892.35528781j, 293401.61631948+9883.90252999j])}}
import scipy
p0 = np.zeros(4)
#if 'Drude P Pos' in tags:
p0[:3] = [1.50312722e+01, 7.45905381e-01, 3.48811157e+05]
#p0[0] = tags['Drude P Pos']
#p0[1] = tags['Drude P Width']
#p0[2] = tags['Drude P thick']
p0[3] = 17. #tags['Drude P Assym']
spec = infoWidget.dataset
spec.energy_loss[200]

cts = DrudeBgd(np.array(spec[200:]), np.array(spec.energy_loss[200:]), .15, p0)

plt.figure()
plt.plot(cts)
1.0000000000000007
1.0000000000000007
1.0000000000000007
0.9999999999999997
1.0
0.9999999999999997
1.0000000000000007
1.0000000000000007
[1.50312722e+01 7.45905381e-01 3.48811157e+05 1.70000000e+01]
Loading...
def PMFP(ssdLL, energy_scale):
        # Calculate plasmon mean free paths using a free-electron formula Eq.(3.58)
        # with m = m0 and assuming small width of the plasmon peak.
        # Equally good for calculating total-inelastic MFP using a value of
        # Em in Eq.(5.38) or a more approximate value using Eq.(5.2).
        # Probe convergence alpha incorporated using Scheinfein & Isaacson formula.
        # Above values assume dipole conditions (beta* < Bethe-ridge angle).
        # The program also estimates a total-inelastic MFP by using dipole formula
        # with effective collection angle bstar = Bethe-ridge angle.
        # To obtain this value, enter alarge value (~ 100 mrad) for alpha or beta.
        E0 = 200000            #Incident-electron energy E0 (keV): ');
        Ep = energy_scale[0]+ssdLL.argmax(0)*(energy_scale[1]-energy_scale[0]) #'Plasmon energy of mean energy loss (eV): ');
        print(Ep, ssdLL.argmax(0))
        alpha = 10 #'Convergence semiangle (mrad) [can be 0]: ');
        beta  = 30 #'Collection semiangle (mrad): ');
        
        F = (1.0+E0/1022.0)/(1.0+E0/511.0)**2;
        Fg = (1.0+E0/1022.0)/(1.0+E0/511.0);
        T = E0*F; #keV
        tgt = 2.0*Fg*E0;
        a0 = 0.0529;  #nm
        #print('2.gamma.T = ',tgt);

        # calculation of convergence correction
        #tgt=2.*E0.*(1.+E0./1022.)./(1.+E0./511.); % keV
        thetae=(Ep+1e-6)/tgt;          # in mrad, avoid NaN for e=0
        a2=alpha*alpha*1e-6 + 1e-10;  #radians^2, avoiding inf for alpha=0
        b2=beta*beta*1e-6;            #radians^2
        t2=thetae*thetae*1e-6;        #radians^2
        eta1=np.sqrt((a2+b2+t2)**2-4*a2*b2)-a2-b2-t2;
        eta2=2*b2*np.log(0.5/t2*(np.sqrt((a2+t2-b2)**2+4*b2*t2)+a2+t2-b2));
        eta3=2*a2*np.log(0.5/t2*(np.sqrt((b2+t2-a2)**2+4*a2*t2)+b2+t2-a2));
        eta=(eta1+eta2+eta3)/a2/np.log(4/t2);
        f1=(eta1+eta2+eta3)/2/a2/np.log(1+b2/t2);
        f2=f1;
        if(alpha/beta>1):
            f2=f1*a2/b2;

        bstar=thetae*np.sqrt(np.exp(f2*np.log(1+b2/t2))-1); #% mrad
        #print('effective semiangle beta* = %g mrad\n',bstar);
        bstar = 40
        
        thetabr = 1000 * (Ep/E0/1000.0)**0.5;
        print('Bethe Ridge Angle', thetabr)
        #print('Bethe-ridge angle(mrad) = ',tags['Bethe Ridge Angle'],'nm\n')

        pmfp = 0.0
        imfp = 0.0
        if (bstar < thetabr):
            pmfp = 4000*a0*T/Ep/np.log(1+bstar**2/thetae**2);
            imfp = 106*F*E0/Ep/np.log(2.0*bstar*E0/Ep);
            #print('Free-electron   MFP(nm) = %g nm\n',pmfp);
            #print('Using Eq.(5.2), MFP(nm) = %g nm\n',imfp);
            
        else:
            #print('Dipole range is exceeded\n');
            imfp = 4000*a0*T/Ep/np.log(1+thetabr**2/thetae**2);
            #print('total-inelastic MFP(nm) = %g nm\n',imfp);
        

        return pmfp, imfp
Ep = np.array(eels_dataset.energy_loss)[0]+np.array(ssdLL).argmax(0)*(np.array(eels_dataset.energy_loss)[1]-np.array(eels_dataset.energy_loss)[0])
Ep,  np.array(ssdLL).argmax(0)
(15.040794864773837, 920)
PMFP(np.array(ssdLL), np.array(eels_dataset.energy_loss))
15.040794864773837 920
Bethe Ridge Angle 0.27423343035426806
(0.0, 219.06514501302627)
# Use resolution Function as ZL if existing
# print len(LLSpec)
LLSpec = eels_dataset
zero_loss, _ = eels_tools.resolution_function(eels_dataset.energy_loss, eels_dataset, .4)

j = np.fft.fft(eels_dataset)
z = np.fft.fft(zero_loss)
j1 = z*np.log(j/z)
ssdLL =np.fft.ifft(j1).real#,'fourier-log deconvolution')

#parent.text2.append('\n Single Scattering Deconvolution, Done')
if np.array(eels_dataset).sum() > 0.0:          
    tmfp = np.log(np.array(eels_dataset).sum()/zero_loss.sum())
else:
    tmfp = 0.0
Ep = np.array(eels_dataset.energy_loss)[0]+np.array(ssdLL).argmax(0)*(np.array(eels_dataset.energy_loss)[1]-np.array(eels_dataset.energy_loss)[0])

print(tmfp)
plt.figure()
plt.plot(ssdLL)
0.17584541453708571
Loading...
def drude(dataset,  ep, ew, tnm, eb, verbose=False):
       
    
    e0 = 200
    beta = 30
    e = dataset.energy_loss
    epc = e[1]-e[0]

    b = beta/1000.0 # %rad
    T = 1000.0*e0*(1.+e0/1022.12)/(1.0+e0/511.06)**2;# %eV # equ.5.2a or Appendix E p 427 
    tgt = 1000*e0*(1022.12 + e0)/(511.06 + e0);# %eV  Appendix E p 427 
    rk0 = 2590*(1.0+e0/511.06)*np.sqrt(2.0*T/511060);
    os = e[0]
    ewMod = eb
    eps = 1 - (ep**2-ewMod*e*1j)/(e**2+2*e*ew*1j) #Mod Drude term
    eps[np.nonzero(eps==0.0)]= 1e-19
    elf = np.imag(-1/eps)

    the = e/tgt; #% varies with energy loss! # Appendix E p 427 
    srfelf=np.imag(-4./(1.0+eps))-elf; #% for 2 surfaces
    angdep = np.arctan(b/the)/the - b/(b*b+the*the);
    srfint = angdep*srfelf/(3.1416*0.05292*rk0*T); #% probability per eV
    anglog = np.log(1.0+ b*b/the/the);
    I0 = eels_dataset.sum() *1     
    volint = abs(tnm/(np.pi*0.05292*T*2)*elf*anglog); #S equ 4.26% probability per eV
    volint = (volint+srfint) *I0  *epc #S probability per channel
    ssd = volint #+ srfint;
    if os <-1.0:
        xs = int(abs(-os/epc))

        ssd[0:xs]=0.0
        volint[0:xs]=0.0
        srfint[0:xs]=0.0
        
        Ps = np.trapz(e,srfint); #% 2 surfaces but includes negative begrenzungs contribn.
        Pv = abs(np.trapz(e,abs(volint/np.array(eels_dataset)))); #% integrated volume probability
        Pv = (volint/I0).sum() ## our data have he same epc and the trapz formula does not include 
        lam = tnm/Pv; #% does NOT depend on free-electron approximation (no damping). 
        lamfe = 4.0*0.05292*T/ep/np.log(1+(b* tgt / ep) **2); #% Eq.(3.44) approximation
    if verbose:
        print('Ps(2surfaces+begrenzung terms) =', Ps, 'Pv=t/lambda(beta)= ',Pv,'\n');
        print('Volume-plasmon MFP(nm) = ', lam,' Free-electron MFP(nm) = ',lamfe,'\n');
        print('--------------------------------\n');

            
    return ssd#/np.pi
ssd = drude(eels_dataset,  15, .5, 3, 1)
plt.figure()
plt.plot(eels_dataset.energy_loss, ssd)
Loading...
def doSSD(LLSpec):
        
        # Use resolution Function as ZL if existing
        # print len(LLSpec)
        extract_zero_loss(LLSpec)
        
        j = np.fft.fft(LLSpec)
        z = np.fft.fft(tags['zero_loss'])
        z2 = z ## Could be a zl extracted from Spectrum
        j1 = z2*np.log(j/z)
        ssdLL =np.fft.ifft(j1).real#,'fourier-log deconvolution')
        tags['ssdLL']=ssdLL.copy()
        
        
        #parent.text2.append('\n Single Scattering Deconvolution, Done')
        if np.array(LLSpec).sum() > 0.0:          
            tmfp = np.log(np.array(LLSpec).sum()/tags['zero_loss'].sum())
        else:
            tmfp = 0.0

        # Use resolution function if available, use ZL otherwise
        zl2 = tags['zero_loss']
        
        
        #####################
        ####### for SSD convoluted Spectra
        #####################
        startE = (6.0-tags['offset'])/tags['dispersion']
        SSD = ssdLL.copy()
        SSD2 = SSD.copy()
        SSD2[0:startE]=0.0
        EP = np.array(SSD2).argmax(0) # plasmon peak position
        ZP = np.array(zl2).argmax(0) # zl peak position 
        #print ('\n EP: ',EP,startE, tags['offset']+EP*tags['dispersion'])


        guess = [tags['offset']+EP*tags['dispersion'], 10000.0, 6.0, 0.98]
        pin = np.array(guess)

        def errfct(p, y, x):
            err = (y - Lorentzian(x,p))
            return err

        def Lorentzian(x,p):
            y = ((0.5 *  p[1]* p[2]/3.14)/((x- p[0])**2+(( p[2]/2)**2)))
            return y

        p, lsq = leastsq(errfct, pin, args=(SSD, tags['ene']), maxfev=2000)
        tags['PLpos'] = p[0]
        tags['PLwidth'] = p[2]
        tags['PLarea'] = p[1]
        #parent.text2.insertPlainText('\n Position 1  Amplitude 1,  Width 1,  \n')
        #parent.text2.insertPlainText(str(p[0:3]))
        PL1 =  Lorentzian(tags['ene'],p)

        pmfp, imfp = PMFP()
        startxE = tags['Drude Fit Start']
        endxE = tags['Drude Fit End']
        startx = (startxE-tags['offset'])/tags['dispersion']
        endx = (endxE-tags['offset'])/tags['dispersion']

        if p[0] < startxE:
            p[0] = startxE
        if p[0] > endxE:
            p[0] = endxE
        if p[2] > (endxE-startxE)/2.0:
            p[2] = (endxE-startxE)/2.0
        
        
        guess = [p[0],p[2],tmfp*imfp,0.1,1.0]
        guess = [22,10,50,0.1,1.0]
        pin2 = np.array(guess)

        
        def errfDrude(p, y, x):
            p = abs(p)
            if p[0] < startxE:
                p[0] = startxE
            if p[0] > endxE:
                p[0] = endxE
            if p[1] > endxE-startxE/3.0:
                p[1] = endxE-startxE/3.0
            if p[2] > 200:
                p[2] = 200
            if p[2]<0:
                p[2] =0
            if p[3] > 10:
                p[3] = 10
            if p[3]<0:
                p[3] =0
            if not tags['Drude Fit Asymm'] :
                p[3] = 0
            
            err = (y - drude(x,p[0],p[1],p[2],abs(p[3])))

            y[np.nonzero(y<=0)] = 1e-12
            return np.abs(err)/np.sqrt(y)
        
        

        
        p2, lsq = leastsq(errfDrude, pin2, args=(tags['spec'][startx:endx], tags['ene'][startx:endx]), maxfev=2000)
        p2[3] = abs(p2[3])
        drudePSD = drude(tags['ene'],p2[0],p2[1],p2[2],abs(p2[3]))
        tags['Drude SSD'] = drudePSD
        
        tags['Drude P Pos'] = p2[0]
        tags['Drude P Width'] = p2[1]
        tags['Drude P thick'] = p2[2]
        tags['Drude P Assym'] = abs(p2[3])
        Pv = drudePSD.sum()/tags['spec'].sum()
        tags['Drude P Probab'] = Pv
        tags['Drude P IMFP'] =  p2[2]/Pv #(Wave vs. intensity)
        #tags['Drude P/LL IMFP',p2[2]/tmfp,'nm')
        tags['LLthick'] = tmfp

        e = 1.60217646E-19; #% electron charge in Coulomb
        eps0 =  8.854187817*1e-12 # vacuum permittivity
        mel = 9.109e-31; #% REST electron mass in kg
        h = 4.135667516*1e-15; #% Planck's constant
        hbar = h/2.0/np.pi;

        tags['Drude e- density']= np.sqrt( (p2[0]/hbar)**2/e**2*eps0*mel)*1e-7 #gerd true? /nm^2

        tags['Drude VL'] = MakeDrudeVL()
        
        
        return tmfp

Surface Plasmon

Spectra from thin specimen show the excitations of the surface plasmons on each side of the specimen. For any normal specimen these surface plasmons do interact, but this is not true for extremely thick specimen (>>10>> 10nm). The surface plasmon frequency ωS\omega_S for thin specimen is related to the bulk plasmon frequency ωP\omega_P by Ritchie [Ritchie-PR1957]:

ωS=ωP[1±exp(qst)1+ε]1/2\omega_S=\omega_P\left[ \frac{1\pm \exp(-q_st) }{1+\varepsilon} \right]^{1/2}

The symmetric mode, where like charges face one another, corresponds to the higher angular frequency qsq_s. Please note, that this relationship does only apply for large qsq_s

The differential probability for surface excitation at both surfaces of a sample with thickness tt can be expressed (normal incident, no retardation effects) by:

d2PsdΩdE=2π2γa0m02μ3θ(θ2+θE2)2[(εaεb)2εa2εb]\frac{d^2 P_s}{d\Omega d E}=\frac{2\hbar}{\pi^2 \gamma a_0 m_0^2 \mu^3}\frac{\theta}{(\theta^2+\theta^2_E)^2} \Im\left[ \frac{(\varepsilon_a - \varepsilon_b)^2 } {\varepsilon_a^2 \varepsilon_b}\right]

with $$ R_c = \frac{\varepsilon_a \sin^2(tE/2\hbar\mu)}{\varepsilon_b + \varepsilon_z }\tanh (q_s t/2)

  • \frac{\varepsilon_a \cos^2(tE/2\hbar\mu)}{\varepsilon_b + \varepsilon_a} \coth (q_s t/2) $and and \varepsilon_aand and \varepsilon_b$ are the permitivities of the two surfaces.

A secondary effect of the surface excitation is the reduced intensity of the bulk plasmon peak. The effect is usually smaller than 1%, but can be larger for spectra with small collection angle, because the preferred scattering of surfuce losses into small angles. The correction for surface plasmon will be discussed in the Kramers--Kronig Analysis.

Summary

The beauty of Low--Loss spectroscopy is its derivation of the dielectric function to high energies without prior knowledge of the composition. The signal is strong and the acquisition time is mostly restricted by the dynamic range of the spectrum.

Think of low-loss spectroscopy as Electrodynamics

The advantages of EELS is the derivation of these values spatially resolved. And from a linescan across an Si/SiO2_2 interface the dielectric function per pixel can be obtained. From that we can calculate the dielectric polarizability αe(E)\alpha_e (E), which may be a measure of the dielectric strength.

We obtain more or less easily:

  • relative thickness

  • absolute thickness

  • inelastic mean free path

  • plasmon frequency

  • plasmon width

  • band gap

  • dielectric function

  • reflectivity

  • absorption

  • effective number of electrons per atoms

The analysis of the optical data requires the exact knowledge of the zero-loss peak. Because of the weighting in the Fourier Analysis, the low energy part contributes heavily to the dielectric function. Therefore, energy resolution is critical for an exact determination of all the optical values from EELS. The new monochromated TEMs are now able to achieve an energy resolution of 10 meV (one is at the oak Ridge National Laboratory), which allows for a sharper zero-loss peak. Such a sharp zero-loss peak will enable us to extract this low energy data more accurately. The dielectric function and the parameters derived from it, can be more precisely determined from such EELS spectra.