Skip to content

Commit 68e0952

Browse files
authored
Merge pull request #183 from pycroscopy/use_dict3
infoWidget with plotly
2 parents 180b44b + 4b05f98 commit 68e0952

File tree

9 files changed

+4391
-196
lines changed

9 files changed

+4391
-196
lines changed

notebooks/0_pyTEMlib.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
"name": "python",
6464
"nbconvert_exporter": "python",
6565
"pygments_lexer": "ipython3",
66-
"version": "3.11.7"
66+
"version": "3.13.0"
6767
},
6868
"toc": {
6969
"base_numbering": "1",

notebooks/Spectroscopy/Analyse_Low_Loss.ipynb

Lines changed: 2774 additions & 24 deletions
Large diffs are not rendered by default.

notebooks/Spectroscopy/EDS.ipynb

Lines changed: 53 additions & 65 deletions
Large diffs are not rendered by default.

pyTEMlib/core_loss_widget.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,16 @@ def update_cl_sidebar(self):
191191
cl_index = index+1
192192
self.core_loss_tab[0, 0].options = spectrum_list
193193
self.core_loss_tab[0, 0].value = spectrum_list[cl_index]
194-
self.update_cl_dataset()
195-
self.set_fit_start()
196-
self.parent.plot()
194+
if '_relationship' in self.parent.datasets.keys():
195+
self.update_cl_dataset()
196+
self.set_fit_start()
197+
self.parent.plot()
197198

198199
def update_cl_dataset(self, value=0):
199200
self.cl_key = self.core_loss_tab[0, 0].value.split(':')[0]
200201
self.parent.coreloss_key = self.cl_key
201-
self.parent.datasets['_relationship']['core_loss'] = self.cl_key
202+
if '_relationship' in self.parent.datasets.keys():
203+
self.parent.datasets['_relationship']['core_loss'] = self.cl_key
202204

203205
if 'None' in self.cl_key:
204206
return

pyTEMlib/eels_tools.py

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,15 @@ def align_zero_loss(dataset: sidpy.Dataset) -> sidpy.Dataset:
395395
new_si.metadata.update({'zero_loss': {'shifted': shifts}})
396396
return new_si
397397

398+
from numba import jit
399+
400+
def get_zero_losses(energy, z_loss_params):
401+
z_loss_dset = np.zeros((z_loss_params.shape[0], z_loss_params.shape[1], energy.shape[0]))
402+
for x in range(z_loss_params.shape[0]):
403+
for y in range(z_loss_params.shape[1]):
404+
z_loss_dset[x, y] += zl_func(energy, *z_loss_params[x, y])
405+
return z_loss_dset
406+
398407

399408

400409

@@ -488,11 +497,12 @@ def guess_function(xvec, yvec):
488497
z_loss_dset = dataset.copy()
489498
z_loss_dset *= 0.0
490499

491-
energy_grid = np.broadcast_to(energy.reshape((1, 1, -1)), (z_loss_dset.shape[0],
492-
z_loss_dset.shape[1], energy.shape[0]))
493-
z_loss_peaks = zl_func(energy_grid, *z_loss_params)
494-
z_loss_dset += z_loss_peaks
495-
500+
#energy_grid = np.broadcast_to(energy.reshape((1, 1, -1)), (z_loss_dset.shape[0],
501+
# z_loss_dset.shape[1], energy.shape[0]))
502+
#z_loss_peaks = zl_func(energy_grid, *z_loss_params)
503+
z_loss_params = np.array(z_loss_params)
504+
z_loss_dset += get_zero_losses(np.array(energy), np.array(z_loss_params))
505+
496506
shifts = z_loss_params[:, :, 0] * z_loss_params[:, :, 3]
497507
widths = z_loss_params[:, :, 2] * z_loss_params[:, :, 5]
498508

@@ -522,7 +532,15 @@ def drude_lorentz(eps_inf, leng, ep, eb, gamma, e, amplitude):
522532
return eps
523533

524534

525-
def fit_plasmon(dataset: Union[sidpy.Dataset, np.ndarray], startFitEnergy: float, endFitEnergy: float, plot_result: bool = False, number_workers: int = 4, number_threads: int = 8) -> Union[sidpy.Dataset, np.ndarray]:
535+
def get_plasmon_losses(energy, params):
536+
dset = np.zeros((params.shape[0], params.shape[1], energy.shape[0]))
537+
for x in range(params.shape[0]):
538+
for y in range(params.shape[1]):
539+
dset[x, y] += energy_loss_function(energy, params[x, y])
540+
return dset
541+
542+
543+
def fit_plasmon(dataset: Union[sidpy.Dataset, np.ndarray], startFitEnergy: float, endFitEnergy: float, number_workers: int = 4, number_threads: int = 8) -> Union[sidpy.Dataset, np.ndarray]:
526544
"""
527545
Fit plasmon peak positions and widths in a TEM dataset using a Drude model.
528546
@@ -567,8 +585,6 @@ def energy_loss_function(E: np.ndarray, Ep: float, Ew: float, A: float) -> np.nd
567585
elf = (-1/eps).imag
568586
return A*elf
569587

570-
571-
572588
# define window for fitting
573589
energy = dataset.get_spectral_dims(return_axis=True)[0].values
574590
start_fit_pixel = np.searchsorted(energy, startFitEnergy)
@@ -589,37 +605,46 @@ def energy_loss_function(E: np.ndarray, Ep: float, Ew: float, A: float) -> np.nd
589605
guess_pos = energy[guess_pos]
590606
if guess_width >8:
591607
guess_width=8
592-
popt, pcov = curve_fit(energy_loss_function, energy[start_fit_pixel:end_fit_pixel], fit_dset,
593-
p0=[guess_pos, guess_width, guess_amplitude])
608+
try:
609+
popt, pcov = curve_fit(energy_loss_function, energy[start_fit_pixel:end_fit_pixel], fit_dset,
610+
p0=[guess_pos, guess_width, guess_amplitude])
611+
except:
612+
end_fit_pixel = np.searchsorted(energy, 30)
613+
fit_dset = np.array(dataset[start_fit_pixel:end_fit_pixel]/ anglog[start_fit_pixel:end_fit_pixel])
614+
try:
615+
popt, pcov = curve_fit(energy_loss_function, energy[start_fit_pixel:end_fit_pixel], fit_dset,
616+
p0=[guess_pos, guess_width, guess_amplitude])
617+
except:
618+
popt=[0,0,0]
594619

595620
plasmon = dataset.like_data(energy_loss_function(energy, popt[0], popt[1], popt[2]))
596621
plasmon *= anglog
597622
start_plasmon = np.searchsorted(energy, 0)+1
598-
599-
600623
plasmon[:start_plasmon] = 0.
624+
601625
epsilon = drude(energy, popt[0], popt[1], 1) * popt[2]
602626
epsilon[:start_plasmon] = 0.
603-
627+
604628
plasmon.metadata['plasmon'] = {'parameter': popt, 'epsilon':epsilon}
605629
return plasmon
606630

607631
# if it can be parallelized:
608632
fitter = SidFitter(fit_dset, energy_loss_function, num_workers=number_workers,
609633
threads=number_threads, return_cov=False, return_fit=False, return_std=False,
610634
km_guess=False, num_fit_parms=3)
611-
[fitted_dataset] = fitter.do_fit()
635+
[fit_parameter] = fitter.do_fit()
636+
637+
plasmon_dset = dataset * 0.0
638+
fit_parameter = np.array(fit_parameter)
639+
plasmon_dset += get_plasmon_losses(np.array(energy), fit_parameter)
640+
if 'plasmon' not in plasmon_dset.metadata:
641+
plasmon_dset.metadata['plasmon'] = {}
642+
plasmon_dset.metadata['plasmon'].update({'startFitEnergy': startFitEnergy,
643+
'endFitEnergy': endFitEnergy,
644+
'fit_parameter': fit_parameter,
645+
'original_low_loss': dataset.title})
612646

613-
if plot_result:
614-
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, sharex=True, sharey=True)
615-
ax1.imshow(fitted_dataset[:, :, 0], cmap='jet')
616-
ax1.set_title('Ep - Peak Position')
617-
ax2.imshow(fitted_dataset[:, :, 1], cmap='jet')
618-
ax2.set_title('Ew - Peak Width')
619-
ax3.imshow(fitted_dataset[:, :, 2], cmap='jet')
620-
ax3.set_title('A - Amplitude')
621-
plt.show()
622-
return fitted_dataset
647+
return plasmon_dset
623648

624649

625650
def angle_correction(spectrum):
@@ -722,8 +747,11 @@ def multiple_scattering(energy_scale: np.ndarray, p: list, core_loss=False)-> np
722747
ssd = ssd * ssd2
723748

724749
PSD /=tmfp*np.exp(-tmfp)
725-
BGDcoef = scipy.interpolate.splrep(LLene, PSD, s=0)
726-
return scipy.interpolate.splev(energy_scale, BGDcoef)
750+
BGDcoef = scipy.interpolate.splrep(LLene, PSD, s=0)
751+
msd = scipy.interpolate.splev(energy_scale, BGDcoef)
752+
start_plasmon = np.searchsorted(energy_scale, 0)+1
753+
msd[:start_plasmon] = 0.
754+
return msd
727755

728756
def fit_multiple_scattering(dataset: Union[sidpy.Dataset, np.ndarray], startFitEnergy: float, endFitEnergy: float,pin=None, number_workers: int = 4, number_threads: int = 8) -> Union[sidpy.Dataset, np.ndarray]:
729757
"""

pyTEMlib/file_tools.py

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,55 @@ def h5_group_to_dict(group, group_dict={}):
787787
return group_dict
788788

789789

790+
def read_annotation(image):
791+
if 'MAGE' not in image.data_type.name:
792+
return {}
793+
scale_x = np.abs(image.x[1]-image.x[0])
794+
scale_y = np.abs(image.y[1]-image.y[0])
795+
rec_scale = np.array([scale_x, scale_y,scale_x, scale_y])
796+
if 'DocumentObjectList' not in image.original_metadata:
797+
return {}
798+
if '0' not in image.original_metadata['DocumentObjectList']:
799+
return {}
800+
annotations = {}
801+
tags = image.original_metadata['DocumentObjectList']['0']
802+
for key in tags:
803+
if 'AnnotationGroupList' in key:
804+
an_tags = tags[key]
805+
for key2 in an_tags:
806+
if isinstance(an_tags[key2], dict):
807+
if an_tags[key2]['AnnotationType'] == 13: #type 'text'
808+
annotations[key2] = {'type': 'text'}
809+
if 'Label' in an_tags:
810+
annotations[key2]['label'] = an_tags['Label']
811+
rect = np.array(an_tags[key2]['Rectangle']) * rec_scale
812+
annotations[key2]['position'] = [rect[1],rect[0]]
813+
annotations[key2]['text'] = an_tags['Text']
814+
815+
elif an_tags[key2]['AnnotationType']==6:
816+
annotations[key2] = {'type': 'circle'}
817+
if 'Label' in an_tags:
818+
annotations[key2]['label'] = an_tags['Label']
819+
rect = np.array(an_tags[key2]['Rectangle']) * rec_scale
820+
821+
annotations[key2]['radius'] =rect[3]-rect[1]
822+
annotations[key2]['position'] = [rect[1],rect[0]]
823+
824+
elif an_tags[key2]['AnnotationType'] == 23:
825+
annotations[key2] = {'type': 'spectral_image'}
826+
if 'Label' in an_tags[key2]:
827+
annotations[key2]['label'] = an_tags[key2]['Label']
828+
rect = np.array(an_tags[key2]['Rectangle']) * rec_scale
829+
830+
annotations[key2]['width'] =rect[3]-rect[1]
831+
annotations[key2]['height'] =rect[2]-rect[0]
832+
annotations[key2]['position'] = [rect[1],rect[0]]
833+
annotations[key2]['Rectangle'] = np.array(an_tags[key2]['Rectangle'])
834+
if len(annotations)>0:
835+
image.metadata['annotations'] = annotations
836+
return annotations
837+
838+
790839
def open_file(filename=None, h5_group=None, write_hdf_file=False, sum_frames=False): # save_file=False,
791840
"""Opens a file if the extension is .emd, .mrc, .hf5, .ndata, .dm3 or .dm4
792841
@@ -850,11 +899,16 @@ def open_file(filename=None, h5_group=None, write_hdf_file=False, sum_frames=Fa
850899
dataset_dict[key] = h5_group_to_dict(master_group[key])
851900
if not write_hdf_file:
852901
file.close()
902+
for dset in dataset_dict.values():
903+
if isinstance(dset, sidpy.Dataset):
904+
if 'Measurement' in dset.title:
905+
dset.title = dset.title.split('/')[-1]
853906
return dataset_dict
854907
elif extension in ['.dm3', '.dm4', '.ndata', '.ndata1', '.h5', '.emd', '.emi', '.edaxh5', '.mrc']:
855908
# tags = open_file(filename)
856909
if extension in ['.dm3', '.dm4']:
857910
reader = SciFiReaders.DMReader(filename)
911+
858912
elif extension in ['.emi']:
859913
try:
860914
import hyperspy.api as hs
@@ -903,8 +957,10 @@ def open_file(filename=None, h5_group=None, write_hdf_file=False, sum_frames=Fa
903957
if not isinstance(dset, dict):
904958
print('Please use new SciFiReaders Package for full functionality')
905959
if isinstance(dset, sidpy.Dataset):
906-
dset = [dset]
907-
960+
dset = {'Channel_000': dset}
961+
for key in dset:
962+
read_annotation(dset[key])
963+
908964
if isinstance(dset, dict):
909965
dataset_dict = dset
910966

0 commit comments

Comments
 (0)