diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 00000000..9f6ae4c6 --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 868fb72c95ded13c8d8a087307de155c +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.doctrees/_autosummary/pyTEMlib.animation.InteractiveAberration.doctree b/.doctrees/_autosummary/pyTEMlib.animation.InteractiveAberration.doctree new file mode 100644 index 00000000..644ff57d Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.animation.InteractiveAberration.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.animation.InteractiveRonchigramMagnification.doctree b/.doctrees/_autosummary/pyTEMlib.animation.InteractiveRonchigramMagnification.doctree new file mode 100644 index 00000000..02d064c0 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.animation.InteractiveRonchigramMagnification.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.animation.add_aperture.doctree b/.doctrees/_autosummary/pyTEMlib.animation.add_aperture.doctree new file mode 100644 index 00000000..cb949d3e Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.animation.add_aperture.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.animation.add_lens.doctree b/.doctrees/_autosummary/pyTEMlib.animation.add_lens.doctree new file mode 100644 index 00000000..92ab6650 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.animation.add_lens.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.animation.deficient_holz_line.doctree b/.doctrees/_autosummary/pyTEMlib.animation.deficient_holz_line.doctree new file mode 100644 index 00000000..9d6ec786 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.animation.deficient_holz_line.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.animation.deficient_kikuchi_line.doctree b/.doctrees/_autosummary/pyTEMlib.animation.deficient_kikuchi_line.doctree new file mode 100644 index 00000000..227fdc71 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.animation.deficient_kikuchi_line.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.animation.doctree b/.doctrees/_autosummary/pyTEMlib.animation.doctree new file mode 100644 index 00000000..6856f32c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.animation.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.animation.geometric_ray_diagram.doctree b/.doctrees/_autosummary/pyTEMlib.animation.geometric_ray_diagram.doctree new file mode 100644 index 00000000..6041342a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.animation.geometric_ray_diagram.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.animation.propagate_beam.doctree b/.doctrees/_autosummary/pyTEMlib.animation.propagate_beam.doctree new file mode 100644 index 00000000..a62698ac Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.animation.propagate_beam.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.atom_tools.atom_refine.doctree b/.doctrees/_autosummary/pyTEMlib.atom_tools.atom_refine.doctree new file mode 100644 index 00000000..934366b2 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.atom_tools.atom_refine.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.atom_tools.atoms_clustering.doctree b/.doctrees/_autosummary/pyTEMlib.atom_tools.atoms_clustering.doctree new file mode 100644 index 00000000..54fcb0f7 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.atom_tools.atoms_clustering.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.atom_tools.doctree b/.doctrees/_autosummary/pyTEMlib.atom_tools.doctree new file mode 100644 index 00000000..3d259f0f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.atom_tools.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.atom_tools.find_atoms.doctree b/.doctrees/_autosummary/pyTEMlib.atom_tools.find_atoms.doctree new file mode 100644 index 00000000..5ae021d3 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.atom_tools.find_atoms.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.atom_tools.gauss_difference.doctree b/.doctrees/_autosummary/pyTEMlib.atom_tools.gauss_difference.doctree new file mode 100644 index 00000000..3c5f8714 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.atom_tools.gauss_difference.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.atom_tools.intensity_area.doctree b/.doctrees/_autosummary/pyTEMlib.atom_tools.intensity_area.doctree new file mode 100644 index 00000000..fa64d916 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.atom_tools.intensity_area.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.config_dir.doctree b/.doctrees/_autosummary/pyTEMlib.config_dir.doctree new file mode 100644 index 00000000..34e47d0d Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.config_dir.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.crystal_tools.atoms_from_dictionary.doctree b/.doctrees/_autosummary/pyTEMlib.crystal_tools.atoms_from_dictionary.doctree new file mode 100644 index 00000000..81ad3f84 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.crystal_tools.atoms_from_dictionary.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.crystal_tools.ball_and_stick.doctree b/.doctrees/_autosummary/pyTEMlib.crystal_tools.ball_and_stick.doctree new file mode 100644 index 00000000..b5deb95e Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.crystal_tools.ball_and_stick.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.crystal_tools.doctree b/.doctrees/_autosummary/pyTEMlib.crystal_tools.doctree new file mode 100644 index 00000000..3bdda619 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.crystal_tools.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.crystal_tools.get_dictionary.doctree b/.doctrees/_autosummary/pyTEMlib.crystal_tools.get_dictionary.doctree new file mode 100644 index 00000000..16164035 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.crystal_tools.get_dictionary.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.crystal_tools.get_projection.doctree b/.doctrees/_autosummary/pyTEMlib.crystal_tools.get_projection.doctree new file mode 100644 index 00000000..59f699db Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.crystal_tools.get_projection.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.crystal_tools.get_symmetry.doctree b/.doctrees/_autosummary/pyTEMlib.crystal_tools.get_symmetry.doctree new file mode 100644 index 00000000..e6c9b49f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.crystal_tools.get_symmetry.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.crystal_tools.jmol_viewer.doctree b/.doctrees/_autosummary/pyTEMlib.crystal_tools.jmol_viewer.doctree new file mode 100644 index 00000000..80c32dfe Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.crystal_tools.jmol_viewer.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.crystal_tools.plot_super_cell.doctree b/.doctrees/_autosummary/pyTEMlib.crystal_tools.plot_super_cell.doctree new file mode 100644 index 00000000..9be91b3f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.crystal_tools.plot_super_cell.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.crystal_tools.plot_unit_cell.doctree b/.doctrees/_autosummary/pyTEMlib.crystal_tools.plot_unit_cell.doctree new file mode 100644 index 00000000..3d955d70 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.crystal_tools.plot_unit_cell.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.crystal_tools.set_bond_radii.doctree b/.doctrees/_autosummary/pyTEMlib.crystal_tools.set_bond_radii.doctree new file mode 100644 index 00000000..0890cdad Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.crystal_tools.set_bond_radii.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.crystal_tools.structure_by_name.doctree b/.doctrees/_autosummary/pyTEMlib.crystal_tools.structure_by_name.doctree new file mode 100644 index 00000000..0564eaa5 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.crystal_tools.structure_by_name.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.diffraction_plot.cartesian2polar.doctree b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.cartesian2polar.doctree new file mode 100644 index 00000000..efac893b Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.cartesian2polar.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.diffraction_plot.circles.doctree b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.circles.doctree new file mode 100644 index 00000000..28856cbd Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.circles.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.diffraction_plot.doctree b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.doctree new file mode 100644 index 00000000..5c5f591d Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plotCBED_parameter.doctree b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plotCBED_parameter.doctree new file mode 100644 index 00000000..1e79879a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plotCBED_parameter.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plotHOLZ_parameter.doctree b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plotHOLZ_parameter.doctree new file mode 100644 index 00000000..f892a722 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plotHOLZ_parameter.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plotKikuchi.doctree b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plotKikuchi.doctree new file mode 100644 index 00000000..21c0833e Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plotKikuchi.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plotSAED_parameter.doctree b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plotSAED_parameter.doctree new file mode 100644 index 00000000..779c6593 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plotSAED_parameter.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plot_diffraction_pattern.doctree b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plot_diffraction_pattern.doctree new file mode 100644 index 00000000..81382d58 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plot_diffraction_pattern.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D.doctree b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D.doctree new file mode 100644 index 00000000..42d5ea5c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plot_ring_pattern.doctree b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plot_ring_pattern.doctree new file mode 100644 index 00000000..f5bfcb32 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.plot_ring_pattern.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.diffraction_plot.topolar.doctree b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.topolar.doctree new file mode 100644 index 00000000..246fbe8d Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.topolar.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.diffraction_plot.warp.doctree b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.warp.doctree new file mode 100644 index 00000000..ed218c2a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.diffraction_plot.warp.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.doctree b/.doctrees/_autosummary/pyTEMlib.doctree new file mode 100644 index 00000000..c4a92931 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.doctree b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.doctree new file mode 100644 index 00000000..d930821f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.get_propagator.doctree b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.get_propagator.doctree new file mode 100644 index 00000000..0a95de60 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.get_propagator.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.get_transmission.doctree b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.get_transmission.doctree new file mode 100644 index 00000000..5f7d4973 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.get_transmission.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.interaction_parameter.doctree b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.interaction_parameter.doctree new file mode 100644 index 00000000..2392b82d Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.interaction_parameter.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.make_chi.doctree b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.make_chi.doctree new file mode 100644 index 00000000..d0449232 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.make_chi.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.multi_slice.doctree b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.multi_slice.doctree new file mode 100644 index 00000000..575b8cfb Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.multi_slice.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.objective_lens_function.doctree b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.objective_lens_function.doctree new file mode 100644 index 00000000..9503bdfe Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.objective_lens_function.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.potential_1dim.doctree b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.potential_1dim.doctree new file mode 100644 index 00000000..aacdb6b0 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.potential_1dim.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.potential_2dim.doctree b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.potential_2dim.doctree new file mode 100644 index 00000000..797cbb9a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.dynamic_scattering.potential_2dim.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eds_tools.detect_peaks.doctree b/.doctrees/_autosummary/pyTEMlib.eds_tools.detect_peaks.doctree new file mode 100644 index 00000000..768f9f27 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eds_tools.detect_peaks.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eds_tools.detector_response.doctree b/.doctrees/_autosummary/pyTEMlib.eds_tools.detector_response.doctree new file mode 100644 index 00000000..cfb8c4d2 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eds_tools.detector_response.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eds_tools.doctree b/.doctrees/_autosummary/pyTEMlib.eds_tools.doctree new file mode 100644 index 00000000..ff2095bb Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eds_tools.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eds_tools.find_elements.doctree b/.doctrees/_autosummary/pyTEMlib.eds_tools.find_elements.doctree new file mode 100644 index 00000000..b95540ab Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eds_tools.find_elements.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eds_tools.fit_model.doctree b/.doctrees/_autosummary/pyTEMlib.eds_tools.fit_model.doctree new file mode 100644 index 00000000..0372d2e9 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eds_tools.fit_model.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eds_tools.gaussian.doctree b/.doctrees/_autosummary/pyTEMlib.eds_tools.gaussian.doctree new file mode 100644 index 00000000..91d034ea Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eds_tools.gaussian.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eds_tools.getFWHM.doctree b/.doctrees/_autosummary/pyTEMlib.eds_tools.getFWHM.doctree new file mode 100644 index 00000000..18ebcb81 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eds_tools.getFWHM.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eds_tools.get_eds_cross_sections.doctree b/.doctrees/_autosummary/pyTEMlib.eds_tools.get_eds_cross_sections.doctree new file mode 100644 index 00000000..9c9d66e7 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eds_tools.get_eds_cross_sections.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eds_tools.get_eds_xsection.doctree b/.doctrees/_autosummary/pyTEMlib.eds_tools.get_eds_xsection.doctree new file mode 100644 index 00000000..acef400f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eds_tools.get_eds_xsection.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eds_tools.get_model.doctree b/.doctrees/_autosummary/pyTEMlib.eds_tools.get_model.doctree new file mode 100644 index 00000000..8cb27473 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eds_tools.get_model.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eds_tools.get_peak.doctree b/.doctrees/_autosummary/pyTEMlib.eds_tools.get_peak.doctree new file mode 100644 index 00000000..318363bb Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eds_tools.get_peak.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eds_tools.get_x_ray_lines.doctree b/.doctrees/_autosummary/pyTEMlib.eds_tools.get_x_ray_lines.doctree new file mode 100644 index 00000000..78da9f64 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eds_tools.get_x_ray_lines.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eds_tools.update_fit_values.doctree b/.doctrees/_autosummary/pyTEMlib.eds_tools.update_fit_values.doctree new file mode 100644 index 00000000..ff55ae8e Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eds_tools.update_fit_values.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog.CompositionWidget.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog.CompositionWidget.doctree new file mode 100644 index 00000000..c2cce5dc Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog.CompositionWidget.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog.doctree new file mode 100644 index 00000000..cfa9cbd8 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog.get_sidebar.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog.get_sidebar.doctree new file mode 100644 index 00000000..fa461537 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog.get_sidebar.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.EdgesAtCursor.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.EdgesAtCursor.doctree new file mode 100644 index 00000000..bf5420f1 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.EdgesAtCursor.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.ElementalEdges.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.ElementalEdges.doctree new file mode 100644 index 00000000..c9f3131c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.ElementalEdges.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage.doctree new file mode 100644 index 00000000..a8e3c781 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.PeriodicTableWidget.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.PeriodicTableWidget.doctree new file mode 100644 index 00000000..b4bf174c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.PeriodicTableWidget.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.RangeSelector.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.RangeSelector.doctree new file mode 100644 index 00000000..5d503033 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.RangeSelector.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.RegionSelector.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.RegionSelector.doctree new file mode 100644 index 00000000..6c4c3e21 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.RegionSelector.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.SIPlot.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.SIPlot.doctree new file mode 100644 index 00000000..351ca0a7 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.SIPlot.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.SpectrumPlot.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.SpectrumPlot.doctree new file mode 100644 index 00000000..7522a705 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.SpectrumPlot.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.doctree new file mode 100644 index 00000000..9cf61cdf Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.get_likely_edges.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.get_likely_edges.doctree new file mode 100644 index 00000000..a85db278 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.get_likely_edges.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_info.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_info.doctree new file mode 100644 index 00000000..17d1d8c8 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_info.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_widget.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_widget.doctree new file mode 100644 index 00000000..c480beb0 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_widget.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.make_box_layout.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.make_box_layout.doctree new file mode 100644 index 00000000..166ead4a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.make_box_layout.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.plot_EELS.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.plot_EELS.doctree new file mode 100644 index 00000000..3d3edb57 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dialog_utilities.plot_EELS.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_dlg.doctree b/.doctrees/_autosummary/pyTEMlib.eels_dlg.doctree new file mode 100644 index 00000000..83da9f2c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_dlg.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.add_element_to_dataset.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.add_element_to_dataset.doctree new file mode 100644 index 00000000..44994a33 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.add_element_to_dataset.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.add_peaks.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.add_peaks.doctree new file mode 100644 index 00000000..8542aaba Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.add_peaks.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.assign_likely_edges.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.assign_likely_edges.doctree new file mode 100644 index 00000000..85af3a47 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.assign_likely_edges.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.auto_chemical_composition.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.auto_chemical_composition.doctree new file mode 100644 index 00000000..8cfcba94 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.auto_chemical_composition.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.auto_id_edges.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.auto_id_edges.doctree new file mode 100644 index 00000000..0d6cd2e6 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.auto_id_edges.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.cl_model.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.cl_model.doctree new file mode 100644 index 00000000..b4337166 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.cl_model.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.doctree new file mode 100644 index 00000000..5a2053da Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.drude.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.drude.doctree new file mode 100644 index 00000000..a35283ed Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.drude.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.drude2.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.drude2.doctree new file mode 100644 index 00000000..28ceb30f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.drude2.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.drude_lorentz.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.drude_lorentz.doctree new file mode 100644 index 00000000..6f9d1ea9 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.drude_lorentz.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.drude_simulation.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.drude_simulation.doctree new file mode 100644 index 00000000..b72b8091 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.drude_simulation.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.effective_collection_angle.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.effective_collection_angle.doctree new file mode 100644 index 00000000..72527ef5 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.effective_collection_angle.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.find_all_edges.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_all_edges.doctree new file mode 100644 index 00000000..41cf7b91 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_all_edges.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.find_associated_edges.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_associated_edges.doctree new file mode 100644 index 00000000..02d615c8 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_associated_edges.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.find_edges.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_edges.doctree new file mode 100644 index 00000000..73182d36 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_edges.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.find_major_edges.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_major_edges.doctree new file mode 100644 index 00000000..4f753530 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_major_edges.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.find_maxima.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_maxima.doctree new file mode 100644 index 00000000..18142861 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_maxima.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.find_peaks.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_peaks.doctree new file mode 100644 index 00000000..87c6da8f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_peaks.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.find_white_lines.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_white_lines.doctree new file mode 100644 index 00000000..c26d347f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.find_white_lines.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_dataset.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_dataset.doctree new file mode 100644 index 00000000..69f1b75c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_dataset.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_edges.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_edges.doctree new file mode 100644 index 00000000..dd9fbb41 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_edges.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_edges2.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_edges2.doctree new file mode 100644 index 00000000..e2606d81 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_edges2.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_model.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_model.doctree new file mode 100644 index 00000000..5059b7a9 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_model.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_peaks.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_peaks.doctree new file mode 100644 index 00000000..bb8674db Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.fit_peaks.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.fix_energy_scale.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.fix_energy_scale.doctree new file mode 100644 index 00000000..ecb1db57 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.fix_energy_scale.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.gauss.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.gauss.doctree new file mode 100644 index 00000000..805c7eb4 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.gauss.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.get_energy_shifts.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.get_energy_shifts.doctree new file mode 100644 index 00000000..168162c3 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.get_energy_shifts.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.get_resolution_functions.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.get_resolution_functions.doctree new file mode 100644 index 00000000..b5d1ebb3 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.get_resolution_functions.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.get_spectrum_eels_db.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.get_spectrum_eels_db.doctree new file mode 100644 index 00000000..942d3843 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.get_spectrum_eels_db.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.get_wave_length.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.get_wave_length.doctree new file mode 100644 index 00000000..0626cb1a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.get_wave_length.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.get_x_sections.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.get_x_sections.doctree new file mode 100644 index 00000000..0b77c8b2 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.get_x_sections.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.get_z.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.get_z.doctree new file mode 100644 index 00000000..007b05ae Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.get_z.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.identify_edges.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.identify_edges.doctree new file mode 100644 index 00000000..528a3079 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.identify_edges.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.kroeger_core.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.kroeger_core.doctree new file mode 100644 index 00000000..a50e7eaa Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.kroeger_core.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.kroeger_core2.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.kroeger_core2.doctree new file mode 100644 index 00000000..e2c3ea36 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.kroeger_core2.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.list_all_edges.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.list_all_edges.doctree new file mode 100644 index 00000000..3cea71fb Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.list_all_edges.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.lorentz.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.lorentz.doctree new file mode 100644 index 00000000..ab774366 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.lorentz.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.make_cross_sections.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.make_cross_sections.doctree new file mode 100644 index 00000000..8b976102 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.make_cross_sections.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.make_edges.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.make_edges.doctree new file mode 100644 index 00000000..3256d853 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.make_edges.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.model3.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.model3.doctree new file mode 100644 index 00000000..9656fdf2 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.model3.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.model_ll.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.model_ll.doctree new file mode 100644 index 00000000..28f0076a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.model_ll.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.model_smooth.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.model_smooth.doctree new file mode 100644 index 00000000..e910f131 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.model_smooth.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.plot_dispersion.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.plot_dispersion.doctree new file mode 100644 index 00000000..5be0d7cd Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.plot_dispersion.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.power_law.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.power_law.doctree new file mode 100644 index 00000000..3bbc7f63 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.power_law.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.power_law_background.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.power_law_background.doctree new file mode 100644 index 00000000..3f105904 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.power_law_background.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.read_msa.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.read_msa.doctree new file mode 100644 index 00000000..e7753df2 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.read_msa.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.residuals_ll.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.residuals_ll.doctree new file mode 100644 index 00000000..19f3c34e Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.residuals_ll.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.residuals_ll2.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.residuals_ll2.doctree new file mode 100644 index 00000000..b051124c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.residuals_ll2.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.residuals_smooth.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.residuals_smooth.doctree new file mode 100644 index 00000000..64d3769f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.residuals_smooth.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.resolution_function.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.resolution_function.doctree new file mode 100644 index 00000000..ffc43ccf Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.resolution_function.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.resolution_function2.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.resolution_function2.doctree new file mode 100644 index 00000000..c1d68cde Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.resolution_function2.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.second_derivative.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.second_derivative.doctree new file mode 100644 index 00000000..53414d05 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.second_derivative.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.set_previous_quantification.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.set_previous_quantification.doctree new file mode 100644 index 00000000..e806ac04 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.set_previous_quantification.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.shift_on_same_scale.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.shift_on_same_scale.doctree new file mode 100644 index 00000000..10b1cb13 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.shift_on_same_scale.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.sort_peaks.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.sort_peaks.doctree new file mode 100644 index 00000000..597391f4 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.sort_peaks.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.xsec_xrpa.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.xsec_xrpa.doctree new file mode 100644 index 00000000..effe12d1 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.xsec_xrpa.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.zl.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.zl.doctree new file mode 100644 index 00000000..490b054d Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.zl.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.eels_tools.zl_func.doctree b/.doctrees/_autosummary/pyTEMlib.eels_tools.zl_func.doctree new file mode 100644 index 00000000..50c9c112 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.eels_tools.zl_func.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.ChooseDataset.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.ChooseDataset.doctree new file mode 100644 index 00000000..0f36888a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.ChooseDataset.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.FileWidget.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.FileWidget.doctree new file mode 100644 index 00000000..5392afd1 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.FileWidget.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.add_dataset_from_file.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.add_dataset_from_file.doctree new file mode 100644 index 00000000..10500391 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.add_dataset_from_file.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.add_to_dict.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.add_to_dict.doctree new file mode 100644 index 00000000..f116638e Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.add_to_dict.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.doctree new file mode 100644 index 00000000..90c08772 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.get_h5_filename.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.get_h5_filename.doctree new file mode 100644 index 00000000..fd7b1cbc Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.get_h5_filename.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.get_last_path.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.get_last_path.doctree new file mode 100644 index 00000000..6a800ab8 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.get_last_path.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.get_main_channel.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.get_main_channel.doctree new file mode 100644 index 00000000..9ccdadef Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.get_main_channel.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.get_start_channel.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.get_start_channel.doctree new file mode 100644 index 00000000..4b4a6fc9 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.get_start_channel.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.h5_add_crystal_structure.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.h5_add_crystal_structure.doctree new file mode 100644 index 00000000..1fe489db Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.h5_add_crystal_structure.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.h5_add_to_structure.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.h5_add_to_structure.doctree new file mode 100644 index 00000000..08216abb Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.h5_add_to_structure.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.h5_get_crystal_structure.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.h5_get_crystal_structure.doctree new file mode 100644 index 00000000..0fb23a8c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.h5_get_crystal_structure.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.h5_group_to_dict.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.h5_group_to_dict.doctree new file mode 100644 index 00000000..5fe6b9b1 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.h5_group_to_dict.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.h5_tree.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.h5_tree.doctree new file mode 100644 index 00000000..5d1dfee0 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.h5_tree.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.log_results.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.log_results.doctree new file mode 100644 index 00000000..c48374b0 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.log_results.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.open_file.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.open_file.doctree new file mode 100644 index 00000000..7480296b Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.open_file.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.open_file_dialog_qt.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.open_file_dialog_qt.doctree new file mode 100644 index 00000000..19c9121a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.open_file_dialog_qt.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.read_cif.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.read_cif.doctree new file mode 100644 index 00000000..d57349cf Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.read_cif.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.read_dm3_info.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.read_dm3_info.doctree new file mode 100644 index 00000000..1c2881f9 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.read_dm3_info.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.read_essential_metadata.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.read_essential_metadata.doctree new file mode 100644 index 00000000..468bf5e1 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.read_essential_metadata.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.read_nion_image_info.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.read_nion_image_info.doctree new file mode 100644 index 00000000..3fc9c4ae Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.read_nion_image_info.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.read_old_h5group.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.read_old_h5group.doctree new file mode 100644 index 00000000..4518cc0e Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.read_old_h5group.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.read_poscar.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.read_poscar.doctree new file mode 100644 index 00000000..5bfb2f8c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.read_poscar.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.save_dataset.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.save_dataset.doctree new file mode 100644 index 00000000..36f09635 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.save_dataset.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.save_dataset_dictionary.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.save_dataset_dictionary.doctree new file mode 100644 index 00000000..655101bb Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.save_dataset_dictionary.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.save_file_dialog_qt.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.save_file_dialog_qt.doctree new file mode 100644 index 00000000..a9a09f85 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.save_file_dialog_qt.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.save_path.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.save_path.doctree new file mode 100644 index 00000000..c1d3bccc Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.save_path.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.save_single_dataset.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.save_single_dataset.doctree new file mode 100644 index 00000000..9131c964 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.save_single_dataset.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.set_dimensions.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.set_dimensions.doctree new file mode 100644 index 00000000..57de13a8 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.set_dimensions.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools.update_directory_list.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools.update_directory_list.doctree new file mode 100644 index 00000000..1ebbad39 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools.update_directory_list.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.file_tools_qt.doctree b/.doctrees/_autosummary/pyTEMlib.file_tools_qt.doctree new file mode 100644 index 00000000..3b331019 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.file_tools_qt.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.breadth_first_search.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.breadth_first_search.doctree new file mode 100644 index 00000000..3f3869ff Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.breadth_first_search.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.circum_center.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.circum_center.doctree new file mode 100644 index 00000000..9b5f72f2 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.circum_center.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.doctree new file mode 100644 index 00000000..18cf5d4e Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.find_interstitial_clusters.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.find_interstitial_clusters.doctree new file mode 100644 index 00000000..abb48015 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.find_interstitial_clusters.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.find_overlapping_spheres.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.find_overlapping_spheres.doctree new file mode 100644 index 00000000..12945b8f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.find_overlapping_spheres.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.find_polyhedra.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.find_polyhedra.doctree new file mode 100644 index 00000000..467c3eaf Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.find_polyhedra.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.get_bond_radii.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_bond_radii.doctree new file mode 100644 index 00000000..5cc94467 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_bond_radii.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.get_bonds.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_bonds.doctree new file mode 100644 index 00000000..dd07a978 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_bonds.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.get_connectivity_matrix.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_connectivity_matrix.doctree new file mode 100644 index 00000000..485ff5fc Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_connectivity_matrix.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.get_distortion_matrix.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_distortion_matrix.doctree new file mode 100644 index 00000000..87b08d68 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_distortion_matrix.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.get_maximum_view.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_maximum_view.doctree new file mode 100644 index 00000000..67a03137 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_maximum_view.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.get_non_periodic_supercell.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_non_periodic_supercell.doctree new file mode 100644 index 00000000..06f01056 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_non_periodic_supercell.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.get_polygons.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_polygons.doctree new file mode 100644 index 00000000..e6d16cb0 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_polygons.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.get_significant_vertices.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_significant_vertices.doctree new file mode 100644 index 00000000..01df77ba Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_significant_vertices.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.get_voronoi.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_voronoi.doctree new file mode 100644 index 00000000..0f2e6250 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.get_voronoi.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.interstitial_sphere_center.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.interstitial_sphere_center.doctree new file mode 100644 index 00000000..6cdcacf2 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.interstitial_sphere_center.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.make_polygons.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.make_polygons.doctree new file mode 100644 index 00000000..62481ef1 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.make_polygons.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.make_polyhedrons.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.make_polyhedrons.doctree new file mode 100644 index 00000000..57bd9199 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.make_polyhedrons.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.plot_atoms.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.plot_atoms.doctree new file mode 100644 index 00000000..273c9ee1 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.plot_atoms.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.polygon_sort.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.polygon_sort.doctree new file mode 100644 index 00000000..7b4762e6 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.polygon_sort.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.set_bond_radii.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.set_bond_radii.doctree new file mode 100644 index 00000000..b7e2556e Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.set_bond_radii.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.sort_polyhedra_by_vertices.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.sort_polyhedra_by_vertices.doctree new file mode 100644 index 00000000..a362e176 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.sort_polyhedra_by_vertices.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.transform_voronoi.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.transform_voronoi.doctree new file mode 100644 index 00000000..4f3d5c12 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.transform_voronoi.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.undistort.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.undistort.doctree new file mode 100644 index 00000000..2b9d13f8 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.undistort.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.undistort_sitk.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.undistort_sitk.doctree new file mode 100644 index 00000000..6aff9234 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.undistort_sitk.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.undistort_stack.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.undistort_stack.doctree new file mode 100644 index 00000000..6bb1312b Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.undistort_stack.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.undistort_stack_sitk.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.undistort_stack_sitk.doctree new file mode 100644 index 00000000..39d3cae0 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.undistort_stack_sitk.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_tools.voronoi_volumes.doctree b/.doctrees/_autosummary/pyTEMlib.graph_tools.voronoi_volumes.doctree new file mode 100644 index 00000000..5a5fcacb Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_tools.voronoi_volumes.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_viz.doctree b/.doctrees/_autosummary/pyTEMlib.graph_viz.doctree new file mode 100644 index 00000000..0596c5cb Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_viz.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_viz.get_boundary_polyhedra.doctree b/.doctrees/_autosummary/pyTEMlib.graph_viz.get_boundary_polyhedra.doctree new file mode 100644 index 00000000..da2d1782 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_viz.get_boundary_polyhedra.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_bonds.doctree b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_bonds.doctree new file mode 100644 index 00000000..a63cda15 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_bonds.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_polyhedron.doctree b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_polyhedron.doctree new file mode 100644 index 00000000..ed3e4c54 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_polyhedron.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_super_cell.doctree b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_super_cell.doctree new file mode 100644 index 00000000..f4a56699 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_super_cell.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_supercell.doctree b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_supercell.doctree new file mode 100644 index 00000000..9481b8ec Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_supercell.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_supercell_bonds.doctree b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_supercell_bonds.doctree new file mode 100644 index 00000000..579a1977 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_supercell_bonds.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_supercell_polyhedra.doctree b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_supercell_polyhedra.doctree new file mode 100644 index 00000000..a389a68f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_supercell_polyhedra.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_with_polyhedra.doctree b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_with_polyhedra.doctree new file mode 100644 index 00000000..23efa68b Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_viz.plot_with_polyhedra.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.graph_viz.show_polyhedra.doctree b/.doctrees/_autosummary/pyTEMlib.graph_viz.show_polyhedra.doctree new file mode 100644 index 00000000..c31f9f9c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.graph_viz.show_polyhedra.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_dialog.doctree b/.doctrees/_autosummary/pyTEMlib.image_dialog.doctree new file mode 100644 index 00000000..00b35de4 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_dialog.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_dlg.doctree b/.doctrees/_autosummary/pyTEMlib.image_dlg.doctree new file mode 100644 index 00000000..edb80cbc Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_dlg.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.ImageWithLineProfile.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.ImageWithLineProfile.doctree new file mode 100644 index 00000000..f6a4ede2 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.ImageWithLineProfile.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.adaptive_fourier_filter.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.adaptive_fourier_filter.doctree new file mode 100644 index 00000000..1f8c8177 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.adaptive_fourier_filter.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.align_crystal_reflections.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.align_crystal_reflections.doctree new file mode 100644 index 00000000..d3641de4 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.align_crystal_reflections.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.calculate_ctf.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.calculate_ctf.doctree new file mode 100644 index 00000000..cbbd1e6e Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.calculate_ctf.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.calculate_scherzer.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.calculate_scherzer.doctree new file mode 100644 index 00000000..5bfbf4ec Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.calculate_scherzer.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.calibrate_image_scale.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.calibrate_image_scale.doctree new file mode 100644 index 00000000..93c11d5b Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.calibrate_image_scale.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.cart2pol.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.cart2pol.doctree new file mode 100644 index 00000000..7804dc2c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.cart2pol.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.cartesian2polar.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.cartesian2polar.doctree new file mode 100644 index 00000000..a68aefa3 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.cartesian2polar.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.clean_svd.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.clean_svd.doctree new file mode 100644 index 00000000..c6290a0e Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.clean_svd.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.complete_registration.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.complete_registration.doctree new file mode 100644 index 00000000..fb0d0752 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.complete_registration.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.crop_image_stack.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.crop_image_stack.doctree new file mode 100644 index 00000000..663959aa Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.crop_image_stack.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.decon_lr.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.decon_lr.doctree new file mode 100644 index 00000000..f2b63dc4 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.decon_lr.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.demon_registration.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.demon_registration.doctree new file mode 100644 index 00000000..249a9440 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.demon_registration.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.diffractogram_spots.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.diffractogram_spots.doctree new file mode 100644 index 00000000..9fd06c6a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.diffractogram_spots.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.doctree new file mode 100644 index 00000000..ae946dac Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.fourier_transform.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.fourier_transform.doctree new file mode 100644 index 00000000..7b0c4e1d Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.fourier_transform.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.get_rotation.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.get_rotation.doctree new file mode 100644 index 00000000..334eefe1 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.get_rotation.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.get_wavelength.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.get_wavelength.doctree new file mode 100644 index 00000000..e0d48fa5 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.get_wavelength.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.histogram_plot.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.histogram_plot.doctree new file mode 100644 index 00000000..94cee16b Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.histogram_plot.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.pol2cart.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.pol2cart.doctree new file mode 100644 index 00000000..c0c96a3a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.pol2cart.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.power_spectrum.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.power_spectrum.doctree new file mode 100644 index 00000000..9cec8195 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.power_spectrum.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.rebin.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.rebin.doctree new file mode 100644 index 00000000..277f3b3e Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.rebin.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.rig_reg_drift.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.rig_reg_drift.doctree new file mode 100644 index 00000000..c0114bd0 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.rig_reg_drift.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.rigid_registration.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.rigid_registration.doctree new file mode 100644 index 00000000..e519062a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.rigid_registration.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.rotational_symmetry_diffractogram.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.rotational_symmetry_diffractogram.doctree new file mode 100644 index 00000000..3b37f901 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.rotational_symmetry_diffractogram.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.warp.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.warp.doctree new file mode 100644 index 00000000..0703d7a8 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.warp.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.image_tools.xy2polar.doctree b/.doctrees/_autosummary/pyTEMlib.image_tools.xy2polar.doctree new file mode 100644 index 00000000..1fc54407 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.image_tools.xy2polar.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.info_dialog.InfoWidget.doctree b/.doctrees/_autosummary/pyTEMlib.info_dialog.InfoWidget.doctree new file mode 100644 index 00000000..34174f72 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.info_dialog.InfoWidget.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.info_dialog.doctree b/.doctrees/_autosummary/pyTEMlib.info_dialog.doctree new file mode 100644 index 00000000..764e832b Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.info_dialog.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.info_dialog.get_sidebar.doctree b/.doctrees/_autosummary/pyTEMlib.info_dialog.get_sidebar.doctree new file mode 100644 index 00000000..62302d99 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.info_dialog.get_sidebar.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.info_dlg.doctree b/.doctrees/_autosummary/pyTEMlib.info_dlg.doctree new file mode 100644 index 00000000..39764bee Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.info_dlg.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.info_widget.EELSWidget.doctree b/.doctrees/_autosummary/pyTEMlib.info_widget.EELSWidget.doctree new file mode 100644 index 00000000..0c673cae Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.info_widget.EELSWidget.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.info_widget.InfoWidget.doctree b/.doctrees/_autosummary/pyTEMlib.info_widget.InfoWidget.doctree new file mode 100644 index 00000000..b7081063 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.info_widget.InfoWidget.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.info_widget.LowLossWidget.doctree b/.doctrees/_autosummary/pyTEMlib.info_widget.LowLossWidget.doctree new file mode 100644 index 00000000..11c1c631 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.info_widget.LowLossWidget.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.info_widget.doctree b/.doctrees/_autosummary/pyTEMlib.info_widget.doctree new file mode 100644 index 00000000..b67127ca Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.info_widget.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.info_widget.get_info_sidebar.doctree b/.doctrees/_autosummary/pyTEMlib.info_widget.get_info_sidebar.doctree new file mode 100644 index 00000000..7a10a7f5 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.info_widget.get_info_sidebar.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.info_widget.get_low_loss_sidebar.doctree b/.doctrees/_autosummary/pyTEMlib.info_widget.get_low_loss_sidebar.doctree new file mode 100644 index 00000000..d2f4c8c3 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.info_widget.get_low_loss_sidebar.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.interactive_eels.doctree b/.doctrees/_autosummary/pyTEMlib.interactive_eels.doctree new file mode 100644 index 00000000..d260eed2 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.interactive_eels.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.interactive_image.doctree b/.doctrees/_autosummary/pyTEMlib.interactive_image.doctree new file mode 100644 index 00000000..bd33e9c6 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.interactive_image.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.Zuo_fig_3_18.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.Zuo_fig_3_18.doctree new file mode 100644 index 00000000..45857006 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.Zuo_fig_3_18.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.check_sanity.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.check_sanity.doctree new file mode 100644 index 00000000..e261afc3 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.check_sanity.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.doctree new file mode 100644 index 00000000..1cbe947a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.example.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.example.doctree new file mode 100644 index 00000000..9fdb1666 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.example.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.feq.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.feq.doctree new file mode 100644 index 00000000..ad58fb97 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.feq.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.find_angles.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.find_angles.doctree new file mode 100644 index 00000000..62dd5358 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.find_angles.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.find_nearest_zone_axis.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.find_nearest_zone_axis.doctree new file mode 100644 index 00000000..a114ee7c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.find_nearest_zone_axis.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.get_dynamically_allowed.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.get_dynamically_allowed.doctree new file mode 100644 index 00000000..0fa1dae2 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.get_dynamically_allowed.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.get_metric_tensor.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.get_metric_tensor.doctree new file mode 100644 index 00000000..5a2a3029 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.get_metric_tensor.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.get_rotation_matrix.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.get_rotation_matrix.doctree new file mode 100644 index 00000000..4ff67e0c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.get_rotation_matrix.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.get_wavelength.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.get_wavelength.doctree new file mode 100644 index 00000000..6466c33a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.get_wavelength.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering.doctree new file mode 100644 index 00000000..e100d303 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering2.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering2.doctree new file mode 100644 index 00000000..4020d89c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering2.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.make_pretty_labels.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.make_pretty_labels.doctree new file mode 100644 index 00000000..ed41dba3 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.make_pretty_labels.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.read_poscar.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.read_poscar.doctree new file mode 100644 index 00000000..15be214a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.read_poscar.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.ring_pattern_calculation.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.ring_pattern_calculation.doctree new file mode 100644 index 00000000..c29d32c7 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.ring_pattern_calculation.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.scattering_matrix.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.scattering_matrix.doctree new file mode 100644 index 00000000..5fbd96ed Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.scattering_matrix.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.stage_rotation_matrix.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.stage_rotation_matrix.doctree new file mode 100644 index 00000000..6a892662 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.stage_rotation_matrix.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.vector_norm.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.vector_norm.doctree new file mode 100644 index 00000000..367ff00d Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.vector_norm.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.zone_mistilt.doctree b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.zone_mistilt.doctree new file mode 100644 index 00000000..ae009fd8 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.kinematic_scattering.zone_mistilt.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.microscope.Microscope.doctree b/.doctrees/_autosummary/pyTEMlib.microscope.Microscope.doctree new file mode 100644 index 00000000..f6f9dbf4 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.microscope.Microscope.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.microscope.doctree b/.doctrees/_autosummary/pyTEMlib.microscope.doctree new file mode 100644 index 00000000..62298f1a Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.microscope.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.peak_dialog.PeakFitWidget.doctree b/.doctrees/_autosummary/pyTEMlib.peak_dialog.PeakFitWidget.doctree new file mode 100644 index 00000000..591b77a2 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.peak_dialog.PeakFitWidget.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.peak_dialog.doctree b/.doctrees/_autosummary/pyTEMlib.peak_dialog.doctree new file mode 100644 index 00000000..1ee6bbaf Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.peak_dialog.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.peak_dialog.get_sidebar.doctree b/.doctrees/_autosummary/pyTEMlib.peak_dialog.get_sidebar.doctree new file mode 100644 index 00000000..17a57093 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.peak_dialog.get_sidebar.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.peak_dialog.smooth.doctree b/.doctrees/_autosummary/pyTEMlib.peak_dialog.smooth.doctree new file mode 100644 index 00000000..5e64c8e0 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.peak_dialog.smooth.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.peak_dlg.doctree b/.doctrees/_autosummary/pyTEMlib.peak_dlg.doctree new file mode 100644 index 00000000..ba215e61 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.peak_dlg.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.doctree new file mode 100644 index 00000000..ff83de43 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.get_chi.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_chi.doctree new file mode 100644 index 00000000..063965e1 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_chi.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.get_chi_2.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_chi_2.doctree new file mode 100644 index 00000000..1157e793 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_chi_2.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.get_d2chidu2.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_d2chidu2.doctree new file mode 100644 index 00000000..01303ba9 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_d2chidu2.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.get_d2chidudv.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_d2chidudv.doctree new file mode 100644 index 00000000..7f58bcfb Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_d2chidudv.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.get_d2chidv2.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_d2chidv2.doctree new file mode 100644 index 00000000..3c3e6ea4 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_d2chidv2.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.get_ronchigram.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_ronchigram.doctree new file mode 100644 index 00000000..c4f8e775 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_ronchigram.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.get_ronchigram_2.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_ronchigram_2.doctree new file mode 100644 index 00000000..44e78263 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_ronchigram_2.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.get_source_energy_spread.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_source_energy_spread.doctree new file mode 100644 index 00000000..538e4de2 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_source_energy_spread.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.get_target_aberrations.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_target_aberrations.doctree new file mode 100644 index 00000000..c050b5b3 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.get_target_aberrations.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.make_chi.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.make_chi.doctree new file mode 100644 index 00000000..7ba04bd8 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.make_chi.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.make_chi1.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.make_chi1.doctree new file mode 100644 index 00000000..af840516 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.make_chi1.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.make_gauss.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.make_gauss.doctree new file mode 100644 index 00000000..e0b8f246 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.make_gauss.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.make_lorentz.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.make_lorentz.doctree new file mode 100644 index 00000000..d26eca06 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.make_lorentz.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.print_aberrations.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.print_aberrations.doctree new file mode 100644 index 00000000..3e44c8c1 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.print_aberrations.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.probe2.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.probe2.doctree new file mode 100644 index 00000000..fd5936bd Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.probe2.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.probe_tools.zero_loss_peak_weight.doctree b/.doctrees/_autosummary/pyTEMlib.probe_tools.zero_loss_peak_weight.doctree new file mode 100644 index 00000000..c244bbd1 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.probe_tools.zero_loss_peak_weight.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.sidpy_tools.ChooseDataset.doctree b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.ChooseDataset.doctree new file mode 100644 index 00000000..f4a866c7 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.ChooseDataset.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.sidpy_tools.doctree b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.doctree new file mode 100644 index 00000000..01e85845 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_order.doctree b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_order.doctree new file mode 100644 index 00000000..568611ed Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_order.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_type.doctree b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_type.doctree new file mode 100644 index 00000000..59c0d01f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_type.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.sidpy_tools.get_extent.doctree b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.get_extent.doctree new file mode 100644 index 00000000..922a6e5d Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.get_extent.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.sidpy_tools.get_image_dims.doctree b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.get_image_dims.doctree new file mode 100644 index 00000000..564756b9 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.get_image_dims.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.sidpy_tools.make_dummy_dataset.doctree b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.make_dummy_dataset.doctree new file mode 100644 index 00000000..df4e9908 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.make_dummy_dataset.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.sidpy_tools.plot.doctree b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.plot.doctree new file mode 100644 index 00000000..556e8174 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.sidpy_tools.plot.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.simulation_tools.doctree b/.doctrees/_autosummary/pyTEMlib.simulation_tools.doctree new file mode 100644 index 00000000..438a34aa Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.simulation_tools.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.simulation_tools.exciting_get_spectra.doctree b/.doctrees/_autosummary/pyTEMlib.simulation_tools.exciting_get_spectra.doctree new file mode 100644 index 00000000..2d7798c7 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.simulation_tools.exciting_get_spectra.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.simulation_tools.final_state_broadening.doctree b/.doctrees/_autosummary/pyTEMlib.simulation_tools.final_state_broadening.doctree new file mode 100644 index 00000000..0d1ed23f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.simulation_tools.final_state_broadening.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.version.doctree b/.doctrees/_autosummary/pyTEMlib.version.doctree new file mode 100644 index 00000000..f77ad0b7 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.version.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.viz.CurveVisualizer.doctree b/.doctrees/_autosummary/pyTEMlib.viz.CurveVisualizer.doctree new file mode 100644 index 00000000..7f120bb8 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.viz.CurveVisualizer.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.viz.SpectrumView.doctree b/.doctrees/_autosummary/pyTEMlib.viz.SpectrumView.doctree new file mode 100644 index 00000000..7df64c4f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.viz.SpectrumView.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.viz.doctree b/.doctrees/_autosummary/pyTEMlib.viz.doctree new file mode 100644 index 00000000..0e08b07c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.viz.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.viz.find_edge_names.doctree b/.doctrees/_autosummary/pyTEMlib.viz.find_edge_names.doctree new file mode 100644 index 00000000..d37d1417 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.viz.find_edge_names.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.viz.plot.doctree b/.doctrees/_autosummary/pyTEMlib.viz.plot.doctree new file mode 100644 index 00000000..266a3f39 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.viz.plot.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.viz.plot_image.doctree b/.doctrees/_autosummary/pyTEMlib.viz.plot_image.doctree new file mode 100644 index 00000000..474a549c Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.viz.plot_image.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.viz.plot_spectrum.doctree b/.doctrees/_autosummary/pyTEMlib.viz.plot_spectrum.doctree new file mode 100644 index 00000000..7668f83b Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.viz.plot_spectrum.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.viz.plot_stack.doctree b/.doctrees/_autosummary/pyTEMlib.viz.plot_stack.doctree new file mode 100644 index 00000000..1f318e51 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.viz.plot_stack.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.viz.spectrum_view_plotly.doctree b/.doctrees/_autosummary/pyTEMlib.viz.spectrum_view_plotly.doctree new file mode 100644 index 00000000..117be2fc Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.viz.spectrum_view_plotly.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.viz.verify_spectrum_dataset.doctree b/.doctrees/_autosummary/pyTEMlib.viz.verify_spectrum_dataset.doctree new file mode 100644 index 00000000..26169790 Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.viz.verify_spectrum_dataset.doctree differ diff --git a/.doctrees/_autosummary/pyTEMlib.xrpa_x_sections.doctree b/.doctrees/_autosummary/pyTEMlib.xrpa_x_sections.doctree new file mode 100644 index 00000000..e51ec23f Binary files /dev/null and b/.doctrees/_autosummary/pyTEMlib.xrpa_x_sections.doctree differ diff --git a/.doctrees/about.doctree b/.doctrees/about.doctree new file mode 100644 index 00000000..ffc3ee00 Binary files /dev/null and b/.doctrees/about.doctree differ diff --git a/.doctrees/contact.doctree b/.doctrees/contact.doctree new file mode 100644 index 00000000..61647eed Binary files /dev/null and b/.doctrees/contact.doctree differ diff --git a/.doctrees/credits.doctree b/.doctrees/credits.doctree new file mode 100644 index 00000000..52431803 Binary files /dev/null and b/.doctrees/credits.doctree differ diff --git a/.doctrees/environment.pickle b/.doctrees/environment.pickle new file mode 100644 index 00000000..b2a8ddc6 Binary files /dev/null and b/.doctrees/environment.pickle differ diff --git a/.doctrees/index.doctree b/.doctrees/index.doctree new file mode 100644 index 00000000..3b859ba9 Binary files /dev/null and b/.doctrees/index.doctree differ diff --git a/.doctrees/install.doctree b/.doctrees/install.doctree new file mode 100644 index 00000000..f5d0267d Binary files /dev/null and b/.doctrees/install.doctree differ diff --git a/.doctrees/notebooks/EELS/index.doctree b/.doctrees/notebooks/EELS/index.doctree new file mode 100644 index 00000000..ab844dbc Binary files /dev/null and b/.doctrees/notebooks/EELS/index.doctree differ diff --git a/.doctrees/notebooks/Imaging/index.doctree b/.doctrees/notebooks/Imaging/index.doctree new file mode 100644 index 00000000..1be4ac86 Binary files /dev/null and b/.doctrees/notebooks/Imaging/index.doctree differ diff --git a/.doctrees/revisions.doctree b/.doctrees/revisions.doctree new file mode 100644 index 00000000..5ad1f49e Binary files /dev/null and b/.doctrees/revisions.doctree differ diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/_autosummary/pyTEMlib.animation.InteractiveAberration.html b/_autosummary/pyTEMlib.animation.InteractiveAberration.html new file mode 100644 index 00000000..c692e257 --- /dev/null +++ b/_autosummary/pyTEMlib.animation.InteractiveAberration.html @@ -0,0 +1,136 @@ + + + + + + + pyTEMlib.animation.InteractiveAberration — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.animation.InteractiveAberration

+
+
+class pyTEMlib.animation.InteractiveAberration(horizontal=True)[source]
+

Bases: object

+

### Interactive explanation of aberrations

+

Methods

+ + + + + + + + + +

on_button_clicked

update

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.animation.InteractiveRonchigramMagnification.html b/_autosummary/pyTEMlib.animation.InteractiveRonchigramMagnification.html new file mode 100644 index 00000000..91c3a279 --- /dev/null +++ b/_autosummary/pyTEMlib.animation.InteractiveRonchigramMagnification.html @@ -0,0 +1,136 @@ + + + + + + + pyTEMlib.animation.InteractiveRonchigramMagnification — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.animation.InteractiveRonchigramMagnification

+
+
+class pyTEMlib.animation.InteractiveRonchigramMagnification(horizontal=True)[source]
+

Bases: object

+

### Interactive explanation of magnification

+

Methods

+ + + + + + + + + +

on_button_clicked

update

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.animation.add_aperture.html b/_autosummary/pyTEMlib.animation.add_aperture.html new file mode 100644 index 00000000..ee589a53 --- /dev/null +++ b/_autosummary/pyTEMlib.animation.add_aperture.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.animation.add_aperture — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.animation.add_aperture

+
+
+pyTEMlib.animation.add_aperture(z, diam, radius, lens_labels)[source]
+

add aperture to propagate beam plot

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.animation.add_lens.html b/_autosummary/pyTEMlib.animation.add_lens.html new file mode 100644 index 00000000..fd069de2 --- /dev/null +++ b/_autosummary/pyTEMlib.animation.add_lens.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.animation.add_lens — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.animation.add_lens

+
+
+pyTEMlib.animation.add_lens(z, f, diam, lens_labels)[source]
+

add lens to propagate beam plot

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.animation.deficient_holz_line.html b/_autosummary/pyTEMlib.animation.deficient_holz_line.html new file mode 100644 index 00000000..8ce8c727 --- /dev/null +++ b/_autosummary/pyTEMlib.animation.deficient_holz_line.html @@ -0,0 +1,137 @@ + + + + + + + pyTEMlib.animation.deficient_holz_line — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.animation.deficient_holz_line

+
+
+pyTEMlib.animation.deficient_holz_line(exact_bragg=False, shift=False, laue_zone=1, color='black')[source]
+

Ewald sphere construction to explain Laue Circle and deficient HOLZ lines

+

Parameters: +exact_bragg: boolean

+
+

whether to tilt into exact Bragg condition or along zone axis

+
+
+
shift: boolean

whether to shift exact Bragg-condition onto zone axis origin

+
+
laue_zone: int

first or second Laue zone only

+
+
color: string

color of wave vectors and Ewald sphere

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.animation.deficient_kikuchi_line.html b/_autosummary/pyTEMlib.animation.deficient_kikuchi_line.html new file mode 100644 index 00000000..42a90793 --- /dev/null +++ b/_autosummary/pyTEMlib.animation.deficient_kikuchi_line.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.animation.deficient_kikuchi_line — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.animation.deficient_kikuchi_line

+
+
+pyTEMlib.animation.deficient_kikuchi_line(s_g=0.0, color_b='black')[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.animation.geometric_ray_diagram.html b/_autosummary/pyTEMlib.animation.geometric_ray_diagram.html new file mode 100644 index 00000000..cc07be34 --- /dev/null +++ b/_autosummary/pyTEMlib.animation.geometric_ray_diagram.html @@ -0,0 +1,135 @@ + + + + + + + pyTEMlib.animation.geometric_ray_diagram — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.animation.geometric_ray_diagram

+
+
+pyTEMlib.animation.geometric_ray_diagram(focal_length=1.0, magnification=False)[source]
+

Sketch of geometric ray diagram od one lens

+
+
Parameters:
+
    +
  • focal_length (float) – focal length of lens

  • +
  • magnification (boolean) – draw magnification on the side

  • +
+
+
Return type:
+

matplotlib figure

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.animation.html b/_autosummary/pyTEMlib.animation.html new file mode 100644 index 00000000..372fae82 --- /dev/null +++ b/_autosummary/pyTEMlib.animation.html @@ -0,0 +1,157 @@ + + + + + + + pyTEMlib.animation — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.animation

+

Figures and Animations for TEM in jupyter notebooks +part of MSE 672 course at UTK

+

Author: Gerd Duscher +revision: 01/11/2021 +03/17/2021 added Aberration Animation

+

Functions

+ + + + + + + + + + + + + + + + + + + + + +

add_aperture

add aperture to propagate beam plot

add_lens

add lens to propagate beam plot

deficient_holz_line

Ewald sphere construction to explain Laue Circle and deficient HOLZ lines

deficient_kikuchi_line

geometric_ray_diagram

Sketch of geometric ray diagram od one lens

propagate_beam

geometrical propagation of light rays from given source

+

Classes

+ + + + + + + + + +

InteractiveAberration

### Interactive explanation of aberrations

InteractiveRonchigramMagnification

### Interactive explanation of magnification

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.animation.propagate_beam.html b/_autosummary/pyTEMlib.animation.propagate_beam.html new file mode 100644 index 00000000..5fd8c225 --- /dev/null +++ b/_autosummary/pyTEMlib.animation.propagate_beam.html @@ -0,0 +1,137 @@ + + + + + + + pyTEMlib.animation.propagate_beam — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.animation.propagate_beam

+
+
+pyTEMlib.animation.propagate_beam(source_position, numerical_aperture, number_of_rays, lens_positions, focal_lengths, lens_labels='', color='b')[source]
+

geometrical propagation of light rays from given source

+
+
Parameters:
+
    +
  • source_position (list) – location of the source (z0, x0) along and off axis (in mm)

  • +
  • numerical_aperture (float) – numerical aperture of the beam (in degrees)

  • +
  • number_of_rays (int) – number of rays to trace

  • +
  • lens_positions (numpy array) – array with the location of the lenses

  • +
  • focal_lengths (numpy array) – array with the focal length of lenses

  • +
  • lens_labels (list of string) – label for the nature of lenses

  • +
  • color (str) – color of the rays on plot

  • +
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.atom_tools.atom_refine.html b/_autosummary/pyTEMlib.atom_tools.atom_refine.html new file mode 100644 index 00000000..e1b0a23f --- /dev/null +++ b/_autosummary/pyTEMlib.atom_tools.atom_refine.html @@ -0,0 +1,142 @@ + + + + + + + pyTEMlib.atom_tools.atom_refine — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.atom_tools.atom_refine

+
+
+pyTEMlib.atom_tools.atom_refine(image, atoms, radius, max_int=0, min_int=0, max_dist=4)[source]
+

Fits a Gaussian in a blob of an image

+
+
Parameters:
+
    +
  • image (np.array or sidpy Dataset) –

  • +
  • atoms (list or np.array) – positions of atoms

  • +
  • radius (float) – radius of circular mask to define fitting of Gaussian

  • +
  • max_int (float) – optional - maximum intensity to be considered for fitting (to exclude contaminated areas for example)

  • +
  • min_int (float) – optional - minimum intensity to be considered for fitting (to exclude contaminated holes for example)

  • +
  • max_dist (float) – optional - maximum distance of movement of Gaussian during fitting

  • +
+
+
Returns:
+

sym – dictionary containing new atom positions and other output such as intensity of the fitted Gaussian

+
+
Return type:
+

dict

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.atom_tools.atoms_clustering.html b/_autosummary/pyTEMlib.atom_tools.atoms_clustering.html new file mode 100644 index 00000000..5df92d42 --- /dev/null +++ b/_autosummary/pyTEMlib.atom_tools.atoms_clustering.html @@ -0,0 +1,140 @@ + + + + + + + pyTEMlib.atom_tools.atoms_clustering — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.atom_tools.atoms_clustering

+
+
+pyTEMlib.atom_tools.atoms_clustering(atoms, mid_atoms, number_of_clusters=3, nearest_neighbours=7)[source]
+

A wrapper for sklearn.cluster kmeans clustering of atoms.

+
+
Parameters:
+
    +
  • atoms (list or np.array (Nx2)) – list of all atoms

  • +
  • mid_atoms (list or np.array (Nx2)) – atoms to be evaluated

  • +
  • number_of_clusters (int) – number of clusters to sort (ini=3)

  • +
  • nearest_neighbours (int) – number of nearest neighbours evaluated

  • +
+
+
Returns:
+

clusters, distances, indices

+
+
Return type:
+

numpy arrays

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.atom_tools.find_atoms.html b/_autosummary/pyTEMlib.atom_tools.find_atoms.html new file mode 100644 index 00000000..800e639b --- /dev/null +++ b/_autosummary/pyTEMlib.atom_tools.find_atoms.html @@ -0,0 +1,139 @@ + + + + + + + pyTEMlib.atom_tools.find_atoms — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.atom_tools.find_atoms

+
+
+pyTEMlib.atom_tools.find_atoms(image, atom_size=0.1, threshold=0.0)[source]
+

Find atoms is a simple wrapper for blob_log in skimage.feature

+
+
Parameters:
+
    +
  • image (sidpy.Dataset) – the image to find atoms

  • +
  • atom_size (float) – visible size of atom blob diameter in nm gives minimal distance between found blobs

  • +
  • threshold (float) – threshold for blob finder; (usually between 0.001 and 1.0) for threshold <= 0 we use the RMS contrast

  • +
+
+
Returns:
+

atoms – atoms positions and radius of blob

+
+
Return type:
+

numpy array(Nx3)

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.atom_tools.gauss_difference.html b/_autosummary/pyTEMlib.atom_tools.gauss_difference.html new file mode 100644 index 00000000..4c99e662 --- /dev/null +++ b/_autosummary/pyTEMlib.atom_tools.gauss_difference.html @@ -0,0 +1,139 @@ + + + + + + + pyTEMlib.atom_tools.gauss_difference — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.atom_tools.gauss_difference

+
+
+pyTEMlib.atom_tools.gauss_difference(params, area)[source]
+

Difference between part of an image and a Gaussian +This function is used int he atom refine function of pyTEMlib

+
+
Parameters:
+
    +
  • params (list) – list of Gaussian parameters [width, position_x, position_y, intensity]

  • +
  • area (numpy array) – 2D matrix = part of an image

  • +
+
+
Returns:
+

numpy array

+
+
Return type:
+

flattened array of difference

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.atom_tools.html b/_autosummary/pyTEMlib.atom_tools.html new file mode 100644 index 00000000..fbbda110 --- /dev/null +++ b/_autosummary/pyTEMlib.atom_tools.html @@ -0,0 +1,144 @@ + + + + + + + pyTEMlib.atom_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.atom_tools

+

Atom detection

+

All atom detection is done here +Everything is in unit of pixel!!

+

Author: Gerd Duscher

+

part of pyTEMlib

+

a pycroscopy package

+

Functions

+ + + + + + + + + + + + + + + + + + +

atom_refine

Fits a Gaussian in a blob of an image

atoms_clustering

A wrapper for sklearn.cluster kmeans clustering of atoms.

find_atoms

Find atoms is a simple wrapper for blob_log in skimage.feature

gauss_difference

Difference between part of an image and a Gaussian This function is used int he atom refine function of pyTEMlib

intensity_area

integrated intensity of atoms in an image with a mask around each atom of radius radius

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.atom_tools.intensity_area.html b/_autosummary/pyTEMlib.atom_tools.intensity_area.html new file mode 100644 index 00000000..bbe37c71 --- /dev/null +++ b/_autosummary/pyTEMlib.atom_tools.intensity_area.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.atom_tools.intensity_area — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.atom_tools.intensity_area

+
+
+pyTEMlib.atom_tools.intensity_area(image, atoms, radius)[source]
+

integrated intensity of atoms in an image with a mask around each atom of radius radius

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.config_dir.html b/_autosummary/pyTEMlib.config_dir.html new file mode 100644 index 00000000..f0a726f9 --- /dev/null +++ b/_autosummary/pyTEMlib.config_dir.html @@ -0,0 +1,119 @@ + + + + + + + pyTEMlib.config_dir — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.config_dir

+

config_dir: setup of directory ~/.pyTEMlib for custom sources and database

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.crystal_tools.atoms_from_dictionary.html b/_autosummary/pyTEMlib.crystal_tools.atoms_from_dictionary.html new file mode 100644 index 00000000..0c4381d6 --- /dev/null +++ b/_autosummary/pyTEMlib.crystal_tools.atoms_from_dictionary.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.crystal_tools.atoms_from_dictionary — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.crystal_tools.atoms_from_dictionary

+
+
+pyTEMlib.crystal_tools.atoms_from_dictionary(tags)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.crystal_tools.ball_and_stick.html b/_autosummary/pyTEMlib.crystal_tools.ball_and_stick.html new file mode 100644 index 00000000..0f14bf2f --- /dev/null +++ b/_autosummary/pyTEMlib.crystal_tools.ball_and_stick.html @@ -0,0 +1,145 @@ + + + + + + + pyTEMlib.crystal_tools.ball_and_stick — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.crystal_tools.ball_and_stick

+
+
+pyTEMlib.crystal_tools.ball_and_stick(atoms, extend=1, max_bond_length=0.0)[source]
+

Calculates the data to plot a ball and stick model

+
+
Parameters:
+
    +
  • atoms (ase.Atoms object) – object containing the structural information like ‘cell’, ‘positions’, and ‘symbols’ .

  • +
  • extend (integer or list f 3 integers) – The extend argument scales the effective cell in which atoms +will be included. It must either be a list of three integers or a single +integer scaling all 3 directions. By setting this value to one, +all corner and edge atoms will be included in the returned cell. +This will of cause make the returned cell non-repeatable, but this is +very useful for visualisation.

  • +
  • max_bond_length (1 float) – The max_bond_length argument defines the distance for which a bond will be shown. +If max_bond_length is zero, the tabulated atom radii will be used.

  • +
+
+
Returns:
+

super_cell – structure with additional information in info dictionary

+
+
Return type:
+

ase.Atoms object

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.crystal_tools.get_dictionary.html b/_autosummary/pyTEMlib.crystal_tools.get_dictionary.html new file mode 100644 index 00000000..187197aa --- /dev/null +++ b/_autosummary/pyTEMlib.crystal_tools.get_dictionary.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.crystal_tools.get_dictionary — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.crystal_tools.get_dictionary

+
+
+pyTEMlib.crystal_tools.get_dictionary(atoms)[source]
+

structure dictionary from ase.Atoms object

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.crystal_tools.get_projection.html b/_autosummary/pyTEMlib.crystal_tools.get_projection.html new file mode 100644 index 00000000..3e285451 --- /dev/null +++ b/_autosummary/pyTEMlib.crystal_tools.get_projection.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.crystal_tools.get_projection — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.crystal_tools.get_projection

+
+
+pyTEMlib.crystal_tools.get_projection(crystal, layers=1)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.crystal_tools.get_symmetry.html b/_autosummary/pyTEMlib.crystal_tools.get_symmetry.html new file mode 100644 index 00000000..6e66f881 --- /dev/null +++ b/_autosummary/pyTEMlib.crystal_tools.get_symmetry.html @@ -0,0 +1,133 @@ + + + + + + + pyTEMlib.crystal_tools.get_symmetry — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.crystal_tools.get_symmetry

+
+
+pyTEMlib.crystal_tools.get_symmetry(atoms, verbose=True)[source]
+

Symmetry analysis with spglib

+

spglib must be installed

+
+
Parameters:
+
    +
  • atoms (ase.Atoms object) – crystal structure

  • +
  • verbose (bool) –

  • +
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.crystal_tools.html b/_autosummary/pyTEMlib.crystal_tools.html new file mode 100644 index 00000000..fbc2672f --- /dev/null +++ b/_autosummary/pyTEMlib.crystal_tools.html @@ -0,0 +1,165 @@ + + + + + + + pyTEMlib.crystal_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.crystal_tools

+

crystal_tools

+

part of pyTEMlib

+

Author: Gerd Duscher

+

Provides convenient functions to make most regular crystal structures

+

Contains also a dictionary of crystal structures and atomic form factors

+
+
Units:

everything is in SI units, except length is given in nm. +angles are assumed to be in degree but will be internally converted to rad

+
+
Usage:

See the notebooks for examples of these routines

+
+
+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

atoms_from_dictionary

ball_and_stick

Calculates the data to plot a ball and stick model

get_dictionary

structure dictionary from ase.Atoms object

get_projection

get_symmetry

Symmetry analysis with spglib

jmol_viewer

jmol viewer of ase .Atoms object requires jupyter-jsmol to be installed (available through conda or pip)

plot_super_cell

make a super_cell to plot with extra atoms at periodic boundaries

plot_unit_cell

Simple plot of unit cell

set_bond_radii

structure_by_name

Provides crystal structure in ase.Atoms format.

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.crystal_tools.jmol_viewer.html b/_autosummary/pyTEMlib.crystal_tools.jmol_viewer.html new file mode 100644 index 00000000..dd86fd95 --- /dev/null +++ b/_autosummary/pyTEMlib.crystal_tools.jmol_viewer.html @@ -0,0 +1,155 @@ + + + + + + + pyTEMlib.crystal_tools.jmol_viewer — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.crystal_tools.jmol_viewer

+
+
+pyTEMlib.crystal_tools.jmol_viewer(atoms, size=2)[source]
+

jmol viewer of ase .Atoms object +requires jupyter-jsmol to be installed (available through conda or pip)

+
+

Parameter

+
+
atoms: ase.Atoms

structure info

+
+
size: int, list, or np.array of size 3; default 1

size of unit_cell; maximum = 8

+
+
+
+
returns:
+

view

+
+
rtype:
+

JsmolView object

+
+
+

Example

+

from jupyter_jsmol import JsmolView +import ase +import ase.build +import itertools +import numpy as np +atoms = ase.build.bulk(‘Cu’, ‘fcc’, a=5.76911, cubic=True) +for pos in list(itertools.product([0.25, .75], repeat=3)):

+
+

atoms += ase.Atom(‘Al’, al2cu.cell.lengths()*pos)

+
+

view = plot_ase(atoms, size = 8) +display(view)

+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.crystal_tools.plot_super_cell.html b/_autosummary/pyTEMlib.crystal_tools.plot_super_cell.html new file mode 100644 index 00000000..e40be477 --- /dev/null +++ b/_autosummary/pyTEMlib.crystal_tools.plot_super_cell.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.crystal_tools.plot_super_cell — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.crystal_tools.plot_super_cell

+
+
+pyTEMlib.crystal_tools.plot_super_cell(super_cell, shift_x=0.0)[source]
+

make a super_cell to plot with extra atoms at periodic boundaries

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.crystal_tools.plot_unit_cell.html b/_autosummary/pyTEMlib.crystal_tools.plot_unit_cell.html new file mode 100644 index 00000000..85a8a538 --- /dev/null +++ b/_autosummary/pyTEMlib.crystal_tools.plot_unit_cell.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.crystal_tools.plot_unit_cell — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.crystal_tools.plot_unit_cell

+
+
+pyTEMlib.crystal_tools.plot_unit_cell(atoms, extend=1, max_bond_length=1.0, ax=None)[source]
+

Simple plot of unit cell

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.crystal_tools.set_bond_radii.html b/_autosummary/pyTEMlib.crystal_tools.set_bond_radii.html new file mode 100644 index 00000000..6c23c78b --- /dev/null +++ b/_autosummary/pyTEMlib.crystal_tools.set_bond_radii.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.crystal_tools.set_bond_radii — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.crystal_tools.set_bond_radii

+
+
+pyTEMlib.crystal_tools.set_bond_radii(atoms)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.crystal_tools.structure_by_name.html b/_autosummary/pyTEMlib.crystal_tools.structure_by_name.html new file mode 100644 index 00000000..7c55622a --- /dev/null +++ b/_autosummary/pyTEMlib.crystal_tools.structure_by_name.html @@ -0,0 +1,148 @@ + + + + + + + pyTEMlib.crystal_tools.structure_by_name — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.crystal_tools.structure_by_name

+
+
+pyTEMlib.crystal_tools.structure_by_name(crystal_name)[source]
+

Provides crystal structure in ase.Atoms format. +Additional information is stored in the info attribute as a dictionary

+
+

Parameter

+
+
crystal_name: str

Please note that the chemical expressions are not case-sensitive.

+
+
+
+
returns:
+

atoms – structure

+
+
rtype:
+

ase.Atoms

+
+
+

Example

+

>> # for a list of pre-defined crystal structures +>> import pyTEMlib.crystal_tools +>> print(pyTEMlib.crystal_tools.crystal_data_base.keys()) +>> +>> atoms = pyTEMlib.crystal_tools.structure_by_name(‘Silicon’) +>> print(atoms) +>> print(atoms.info)

+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.diffraction_plot.cartesian2polar.html b/_autosummary/pyTEMlib.diffraction_plot.cartesian2polar.html new file mode 100644 index 00000000..c34fd3e6 --- /dev/null +++ b/_autosummary/pyTEMlib.diffraction_plot.cartesian2polar.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.diffraction_plot.cartesian2polar — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.diffraction_plot.cartesian2polar

+
+
+pyTEMlib.diffraction_plot.cartesian2polar(x, y, grid, r, t, order=3)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.diffraction_plot.circles.html b/_autosummary/pyTEMlib.diffraction_plot.circles.html new file mode 100644 index 00000000..643df83e --- /dev/null +++ b/_autosummary/pyTEMlib.diffraction_plot.circles.html @@ -0,0 +1,168 @@ + + + + + + + pyTEMlib.diffraction_plot.circles — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.diffraction_plot.circles

+
+
+pyTEMlib.diffraction_plot.circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs)[source]
+

Make a scatter plot of circles. +Similar to plt.scatter, but the size of circles are in data scale. +:param x: Input data +:type x: scalar or array_like, shape (n, ) +:param y: Input data +:type y: scalar or array_like, shape (n, ) +:param s: Radius of circles. +:type s: scalar or array_like, shape (n, ) +:param c: c can be a single color format string, or a sequence of color

+
+

specifications of length N, or a sequence of N numbers to be +mapped to colors using the cmap and norm specified via kwargs. +Note that c should not be a single numeric RGB or RGBA sequence +because that is indistinguishable from an array of values +to be colormapped. (If you insist, use color instead.) +c can be a 2-D array in which the rows are RGB or RGBA, however.

+
+
+
Parameters:
+
    +
  • vmin (scalar, optional, default: None) – vmin and vmax are used in conjunction with norm to normalize +luminance data. If either are None, the min and max of the +color array is used.

  • +
  • vmax (scalar, optional, default: None) – vmin and vmax are used in conjunction with norm to normalize +luminance data. If either are None, the min and max of the +color array is used.

  • +
  • kwargs (~matplotlib.collections.Collection properties) – Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), linestyle(ls), +norm, cmap, transform, etc.

  • +
+
+
Returns:
+

paths

+
+
Return type:
+

~matplotlib.collections.PathCollection

+
+
+

Examples

+

a = np.arange(11) +circles(a, a, s=a*0.2, c=a, alpha=0.5, ec=’none’) +plt.colorbar() +License +——– +This code is under [The BSD 3-Clause License] +(http://opensource.org/licenses/BSD-3-Clause)

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.diffraction_plot.html b/_autosummary/pyTEMlib.diffraction_plot.html new file mode 100644 index 00000000..93bef6b2 --- /dev/null +++ b/_autosummary/pyTEMlib.diffraction_plot.html @@ -0,0 +1,156 @@ + + + + + + + pyTEMlib.diffraction_plot — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.diffraction_plot

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

cartesian2polar

circles

Make a scatter plot of circles. Similar to plt.scatter, but the size of circles are in data scale. :param x: Input data :type x: scalar or array_like, shape (n, ) :param y: Input data :type y: scalar or array_like, shape (n, ) :param s: Radius of circles. :type s: scalar or array_like, shape (n, ) :param c: c can be a single color format string, or a sequence of color specifications of length N, or a sequence of N numbers to be mapped to colors using the cmap and norm specified via kwargs. Note that c should not be a single numeric RGB or RGBA sequence because that is indistinguishable from an array of values to be colormapped. (If you insist, use color instead.) c can be a 2-D array in which the rows are RGB or RGBA, however. :type c: color or sequence of color, optional, default : 'b' :param vmin: vmin and vmax are used in conjunction with norm to normalize luminance data. If either are None, the min and max of the color array is used. :type vmin: scalar, optional, default: None :param vmax: vmin and vmax are used in conjunction with norm to normalize luminance data. If either are None, the min and max of the color array is used. :type vmax: scalar, optional, default: None :param kwargs: Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), linestyle(ls), norm, cmap, transform, etc. :type kwargs: ~matplotlib.collections.Collection properties.

plotCBED_parameter

plotHOLZ_parameter

plotKikuchi

plotSAED_parameter

plot_diffraction_pattern

Plot of spot diffraction pattern with matplotlib Plot of spot diffraction pattern with matplotlib

plot_reciprocal_unit_cell_2D

Plot # unit cell in reciprocal space in 2D

plot_ring_pattern

Plot of ring diffraction pattern with matplotlib

topolar

Transform img to its polar coordinate representation.

warp

Define original polar grid

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.diffraction_plot.plotCBED_parameter.html b/_autosummary/pyTEMlib.diffraction_plot.plotCBED_parameter.html new file mode 100644 index 00000000..6b512e6e --- /dev/null +++ b/_autosummary/pyTEMlib.diffraction_plot.plotCBED_parameter.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.diffraction_plot.plotCBED_parameter — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.diffraction_plot.plotCBED_parameter

+
+
+pyTEMlib.diffraction_plot.plotCBED_parameter()[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.diffraction_plot.plotHOLZ_parameter.html b/_autosummary/pyTEMlib.diffraction_plot.plotHOLZ_parameter.html new file mode 100644 index 00000000..4e6c07f3 --- /dev/null +++ b/_autosummary/pyTEMlib.diffraction_plot.plotHOLZ_parameter.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.diffraction_plot.plotHOLZ_parameter — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.diffraction_plot.plotHOLZ_parameter

+
+
+pyTEMlib.diffraction_plot.plotHOLZ_parameter(grey=False)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.diffraction_plot.plotKikuchi.html b/_autosummary/pyTEMlib.diffraction_plot.plotKikuchi.html new file mode 100644 index 00000000..569f4c89 --- /dev/null +++ b/_autosummary/pyTEMlib.diffraction_plot.plotKikuchi.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.diffraction_plot.plotKikuchi — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.diffraction_plot.plotKikuchi

+
+
+pyTEMlib.diffraction_plot.plotKikuchi(grey=False)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.diffraction_plot.plotSAED_parameter.html b/_autosummary/pyTEMlib.diffraction_plot.plotSAED_parameter.html new file mode 100644 index 00000000..c1f57203 --- /dev/null +++ b/_autosummary/pyTEMlib.diffraction_plot.plotSAED_parameter.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.diffraction_plot.plotSAED_parameter — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.diffraction_plot.plotSAED_parameter

+
+
+pyTEMlib.diffraction_plot.plotSAED_parameter(gray=False)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.diffraction_plot.plot_diffraction_pattern.html b/_autosummary/pyTEMlib.diffraction_plot.plot_diffraction_pattern.html new file mode 100644 index 00000000..28c6bbc7 --- /dev/null +++ b/_autosummary/pyTEMlib.diffraction_plot.plot_diffraction_pattern.html @@ -0,0 +1,140 @@ + + + + + + + pyTEMlib.diffraction_plot.plot_diffraction_pattern — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.diffraction_plot.plot_diffraction_pattern

+
+
+pyTEMlib.diffraction_plot.plot_diffraction_pattern(atoms, diffraction_pattern=None, grey=False)[source]
+

Plot of spot diffraction pattern with matplotlib +Plot of spot diffraction pattern with matplotlib

+
+
Parameters:
+
    +
  • atoms (dictionary or ase.Atoms object) – information stored as dictionary either directly or in info attribute of ase.Atoms object

  • +
  • diffraction_pattern (None or sidpy.Dataset) – diffraction pattern in background

  • +
  • grey (bool) – plotting in greyscale if True

  • +
+
+
Returns:
+

fig – reference to matplotlib figure

+
+
Return type:
+

matplotlib figure

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D.html b/_autosummary/pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D.html new file mode 100644 index 00000000..8253f4bc --- /dev/null +++ b/_autosummary/pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • + View page source +
  • +
+
+
+
+
+ +
+

pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D

+
+
+pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D(atoms)[source]
+

Plot # unit cell in reciprocal space in 2D

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.diffraction_plot.plot_ring_pattern.html b/_autosummary/pyTEMlib.diffraction_plot.plot_ring_pattern.html new file mode 100644 index 00000000..f48dd776 --- /dev/null +++ b/_autosummary/pyTEMlib.diffraction_plot.plot_ring_pattern.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.diffraction_plot.plot_ring_pattern — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.diffraction_plot.plot_ring_pattern

+
+
+pyTEMlib.diffraction_plot.plot_ring_pattern(atoms, diffraction_pattern=None, grey=False)[source]
+

Plot of ring diffraction pattern with matplotlib

+
+
Parameters:
+
    +
  • atoms (dictionary or sidpy.Dataset) – information stored as dictionary either directly or in metadata attribute of sidpy.Dataset

  • +
  • grey (bool) – plotting in greyscale if True

  • +
+
+
Returns:
+

fig – reference to matplotlib figure

+
+
Return type:
+

matplotlib figure

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.diffraction_plot.topolar.html b/_autosummary/pyTEMlib.diffraction_plot.topolar.html new file mode 100644 index 00000000..203a681e --- /dev/null +++ b/_autosummary/pyTEMlib.diffraction_plot.topolar.html @@ -0,0 +1,129 @@ + + + + + + + pyTEMlib.diffraction_plot.topolar — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.diffraction_plot.topolar

+
+
+pyTEMlib.diffraction_plot.topolar(img, order=1)[source]
+

Transform img to its polar coordinate representation.

+
+
order: int, default 1

Specify the spline interpolation order. +High orders may be slow for large images.

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.diffraction_plot.warp.html b/_autosummary/pyTEMlib.diffraction_plot.warp.html new file mode 100644 index 00000000..6e382193 --- /dev/null +++ b/_autosummary/pyTEMlib.diffraction_plot.warp.html @@ -0,0 +1,137 @@ + + + + + + + pyTEMlib.diffraction_plot.warp — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.diffraction_plot.warp

+
+
+pyTEMlib.diffraction_plot.warp(diff, center)[source]
+

Define original polar grid

+
+

Parameter:

+
+
diff: sidpy object or numpy ndarray of

diffraction pattern

+
+
center: list or numpy array of length 2

coordinates of center in pixel

+
+
+
+
+

Return:

+

numpy array of diffraction pattern in polar coordinates

+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.dynamic_scattering.get_propagator.html b/_autosummary/pyTEMlib.dynamic_scattering.get_propagator.html new file mode 100644 index 00000000..659cc1a3 --- /dev/null +++ b/_autosummary/pyTEMlib.dynamic_scattering.get_propagator.html @@ -0,0 +1,150 @@ + + + + + + + pyTEMlib.dynamic_scattering.get_propagator — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.dynamic_scattering.get_propagator

+
+
+pyTEMlib.dynamic_scattering.get_propagator(size_in_pixel, delta_z, number_layers, wavelength, field_of_view, bandwidth_factor, verbose=True)[source]
+

Get propagator function

+

has to be convoluted with wave function after transmission

+
+

Parameter

+
+
size_in_pixel: int

number of pixels of one axis in square image

+
+
delta_z: float

distance between layers

+
+
number_layers: int

number of layers to make a propagator

+
+
wavelength: float

wavelength of incident electrons

+
+
field_of_view: float

field of view of image

+
+
bandwidth_factor: float

relative bandwidth to avoid anti-aliasing

+
+
+
+
returns:
+

propagator

+
+
rtype:
+

complex numpy array (layers x size_in_pixel x size_in_pixel)

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.dynamic_scattering.get_transmission.html b/_autosummary/pyTEMlib.dynamic_scattering.get_transmission.html new file mode 100644 index 00000000..1c183a78 --- /dev/null +++ b/_autosummary/pyTEMlib.dynamic_scattering.get_transmission.html @@ -0,0 +1,139 @@ + + + + + + + pyTEMlib.dynamic_scattering.get_transmission — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.dynamic_scattering.get_transmission

+
+
+pyTEMlib.dynamic_scattering.get_transmission(potential, acceleration_voltage)[source]
+

Get transmission function

+

has to be multiplied in real space with wave function

+
+

Parameter

+
+
potential: numpy array (nxn)

potential of a layer

+
+
acceleration_voltage: float

acceleration voltage in V

+
+
+
+
rtype:
+

complex numpy array (nxn)

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.dynamic_scattering.html b/_autosummary/pyTEMlib.dynamic_scattering.html new file mode 100644 index 00000000..f4809913 --- /dev/null +++ b/_autosummary/pyTEMlib.dynamic_scattering.html @@ -0,0 +1,150 @@ + + + + + + + pyTEMlib.dynamic_scattering — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.dynamic_scattering

+

Dynamic Scattering Library for Multi-Slice Calculations

+

author: Gerd Duscher

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

get_propagator

Get propagator function

get_transmission

Get transmission function

interaction_parameter

Calculates interaction parameter sigma

make_chi

###

+

multi_slice

Multi-Slice Calculation

objective_lens_function

Objective len function to be convoluted with exit wave to derive image function

potential_1dim

Calculates the projected potential of an atom of element

potential_2dim

Make a super-cell with potentials

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.dynamic_scattering.interaction_parameter.html b/_autosummary/pyTEMlib.dynamic_scattering.interaction_parameter.html new file mode 100644 index 00000000..7e065abc --- /dev/null +++ b/_autosummary/pyTEMlib.dynamic_scattering.interaction_parameter.html @@ -0,0 +1,139 @@ + + + + + + + pyTEMlib.dynamic_scattering.interaction_parameter — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.dynamic_scattering.interaction_parameter

+
+
+pyTEMlib.dynamic_scattering.interaction_parameter(acceleration_voltage)[source]
+

Calculates interaction parameter sigma

+
+

Parameter

+
+
acceleration_voltage: float

acceleration voltage in volt

+
+
+
+
returns:
+

interaction parameter – interaction parameter (dimensionless)

+
+
rtype:
+

float

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.dynamic_scattering.make_chi.html b/_autosummary/pyTEMlib.dynamic_scattering.make_chi.html new file mode 100644 index 00000000..23c5f00d --- /dev/null +++ b/_autosummary/pyTEMlib.dynamic_scattering.make_chi.html @@ -0,0 +1,129 @@ + + + + + + + pyTEMlib.dynamic_scattering.make_chi — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.dynamic_scattering.make_chi

+
+
+pyTEMlib.dynamic_scattering.make_chi(theta, phi, aberrations)[source]
+

### +# Aberration function chi +### +phi and theta are meshgrids of the angles in polar coordinates. +aberrations is a dictionary with the aberrations coefficients +Attention: an empty aberration dictionary will give you a perfect aberration

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.dynamic_scattering.multi_slice.html b/_autosummary/pyTEMlib.dynamic_scattering.multi_slice.html new file mode 100644 index 00000000..8ce8632b --- /dev/null +++ b/_autosummary/pyTEMlib.dynamic_scattering.multi_slice.html @@ -0,0 +1,139 @@ + + + + + + + pyTEMlib.dynamic_scattering.multi_slice — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.dynamic_scattering.multi_slice

+
+
+pyTEMlib.dynamic_scattering.multi_slice(wave, number_of_unit_cell_z, number_layers, transmission, propagator)[source]
+

Multi-Slice Calculation

+

The wave function will be changed iteratively

+
+
Parameters:
+
    +
  • wave (complex numpy array (nxn)) – starting wave function

  • +
  • number_of_unit_cell_z (int) – this gives the thickness in multiples of c lattice parameter

  • +
  • number_layers (int) – number of layers per unit cell

  • +
  • transmission (complex numpy array) – transmission function

  • +
  • propagator (complex numpy array) – propagator function

  • +
+
+
Return type:
+

complex numpy array

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.dynamic_scattering.objective_lens_function.html b/_autosummary/pyTEMlib.dynamic_scattering.objective_lens_function.html new file mode 100644 index 00000000..c691a979 --- /dev/null +++ b/_autosummary/pyTEMlib.dynamic_scattering.objective_lens_function.html @@ -0,0 +1,146 @@ + + + + + + + pyTEMlib.dynamic_scattering.objective_lens_function — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.dynamic_scattering.objective_lens_function

+
+
+pyTEMlib.dynamic_scattering.objective_lens_function(ab, nx, ny, field_of_view, aperture_size=10)[source]
+

Objective len function to be convoluted with exit wave to derive image function

+
+

Parameter:

+
+
ab: dict

aberrations in nm should at least contain defocus (C10), and spherical aberration (C30)

+
+
nx: int

number of pixel in x direction

+
+
ny: int

number of pixel in y direction

+
+
field_of_view: float

field of view of potential

+
+
wavelength: float

wavelength in nm

+
+
aperture_size: float

aperture size in 1/nm

+
+
+
+
+

Returns:

+

object function: numpy array (nx x ny) +extent: list

+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.dynamic_scattering.potential_1dim.html b/_autosummary/pyTEMlib.dynamic_scattering.potential_1dim.html new file mode 100644 index 00000000..c0d648ef --- /dev/null +++ b/_autosummary/pyTEMlib.dynamic_scattering.potential_1dim.html @@ -0,0 +1,145 @@ + + + + + + + pyTEMlib.dynamic_scattering.potential_1dim — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.dynamic_scattering.potential_1dim

+
+
+pyTEMlib.dynamic_scattering.potential_1dim(element, r)[source]
+

Calculates the projected potential of an atom of element

+

The projected potential will be in units of V nm^2, +however, internally we will use Angstrom instead of nm! +The basis for these calculations are the atomic form factors of Kirkland 2𝑛𝑑 edition +following the equation in Appendix C page 252.

+
+

Parameter

+
+
element: str

name of ‘element

+
+
r: numpy array [nxn]

impact parameters (distances from atom position) in nm

+
+
+
+
returns:
+

projected potential in units of V nm^2

+
+
rtype:
+

numpy array (nxn)

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.dynamic_scattering.potential_2dim.html b/_autosummary/pyTEMlib.dynamic_scattering.potential_2dim.html new file mode 100644 index 00000000..15982e1c --- /dev/null +++ b/_autosummary/pyTEMlib.dynamic_scattering.potential_2dim.html @@ -0,0 +1,125 @@ + + + + + + + pyTEMlib.dynamic_scattering.potential_2dim — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.dynamic_scattering.potential_2dim

+
+
+pyTEMlib.dynamic_scattering.potential_2dim(element, nx, ny, n_cell_x, n_cell_y, lattice_parameter, base)[source]
+

Make a super-cell with potentials

+

Limitation is that we only place atom potential with single pixel resolution

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eds_tools.detect_peaks.html b/_autosummary/pyTEMlib.eds_tools.detect_peaks.html new file mode 100644 index 00000000..8faea36d --- /dev/null +++ b/_autosummary/pyTEMlib.eds_tools.detect_peaks.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eds_tools.detect_peaks — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eds_tools.detect_peaks

+
+
+pyTEMlib.eds_tools.detect_peaks(dataset, minimum_number_of_peaks=30)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eds_tools.detector_response.html b/_autosummary/pyTEMlib.eds_tools.detector_response.html new file mode 100644 index 00000000..0ae5b756 --- /dev/null +++ b/_autosummary/pyTEMlib.eds_tools.detector_response.html @@ -0,0 +1,144 @@ + + + + + + + pyTEMlib.eds_tools.detector_response — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eds_tools.detector_response

+
+
+pyTEMlib.eds_tools.detector_response(detector_definition, energy_scale)[source]
+

Example

+

tags = {}

+

tags[‘acceleration_voltage_V’] = 30000

+

tags[‘detector’] ={} +tags[‘detector’][‘layers’] ={}

+

## layer thicknesses of commen materials in EDS detectors in m +tags[‘detector’][‘layers’][‘alLayer’] = {} +tags[‘detector’][‘layers’][‘alLayer’][‘thickness’] = 30 *1e-9 # in m +tags[‘detector’][‘layers’][‘alLayer’][‘Z’] = 13

+

tags[‘detector’][‘layers’][‘deadLayer’] = {} +tags[‘detector’][‘layers’][‘deadLayer’][‘thickness’] = 100 *1e-9 # in m +tags[‘detector’][‘layers’][‘deadLayer’][‘Z’] = 14

+

tags[‘detector’][‘layers’][‘window’] = {} +tags[‘detector’][‘layers’][‘window’][‘thickness’] = 100 *1e-9 # in m +tags[‘detector’][‘layers’][‘window’][‘Z’] = 6

+

tags[‘detector’][‘detector’] = {} +tags[‘detector’][‘detector’][‘thickness’] = 45 * 1e-3 # in m +tags[‘detector’][‘detector’][‘Z’] = 14 +tags[‘detector’][‘detector’][‘area’] = 30 * 1e-6 #in m2

+

energy_scale = np.linspace(.1,60,1199)*1000 i eV +detector_response(tags, energy_scale)

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eds_tools.find_elements.html b/_autosummary/pyTEMlib.eds_tools.find_elements.html new file mode 100644 index 00000000..3356a6f4 --- /dev/null +++ b/_autosummary/pyTEMlib.eds_tools.find_elements.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eds_tools.find_elements — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eds_tools.find_elements

+
+
+pyTEMlib.eds_tools.find_elements(spectrum, minor_peaks)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eds_tools.fit_model.html b/_autosummary/pyTEMlib.eds_tools.fit_model.html new file mode 100644 index 00000000..2c97e9c5 --- /dev/null +++ b/_autosummary/pyTEMlib.eds_tools.fit_model.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eds_tools.fit_model — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eds_tools.fit_model

+
+
+pyTEMlib.eds_tools.fit_model(spectrum, elements)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eds_tools.gaussian.html b/_autosummary/pyTEMlib.eds_tools.gaussian.html new file mode 100644 index 00000000..633af7b4 --- /dev/null +++ b/_autosummary/pyTEMlib.eds_tools.gaussian.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eds_tools.gaussian — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eds_tools.gaussian

+
+
+pyTEMlib.eds_tools.gaussian(enrgy_scale, mu, FWHM)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eds_tools.getFWHM.html b/_autosummary/pyTEMlib.eds_tools.getFWHM.html new file mode 100644 index 00000000..25d907de --- /dev/null +++ b/_autosummary/pyTEMlib.eds_tools.getFWHM.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eds_tools.getFWHM — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eds_tools.getFWHM

+
+
+pyTEMlib.eds_tools.getFWHM(E, E_ref, FWHM_ref)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eds_tools.get_eds_cross_sections.html b/_autosummary/pyTEMlib.eds_tools.get_eds_cross_sections.html new file mode 100644 index 00000000..24f6f59a --- /dev/null +++ b/_autosummary/pyTEMlib.eds_tools.get_eds_cross_sections.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eds_tools.get_eds_cross_sections — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eds_tools.get_eds_cross_sections

+
+
+pyTEMlib.eds_tools.get_eds_cross_sections(z)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eds_tools.get_eds_xsection.html b/_autosummary/pyTEMlib.eds_tools.get_eds_xsection.html new file mode 100644 index 00000000..35d4c383 --- /dev/null +++ b/_autosummary/pyTEMlib.eds_tools.get_eds_xsection.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eds_tools.get_eds_xsection — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eds_tools.get_eds_xsection

+
+
+pyTEMlib.eds_tools.get_eds_xsection(Xsection, energy_scale, start_bgd, end_bgd)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eds_tools.get_model.html b/_autosummary/pyTEMlib.eds_tools.get_model.html new file mode 100644 index 00000000..4aa89dfc --- /dev/null +++ b/_autosummary/pyTEMlib.eds_tools.get_model.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eds_tools.get_model — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eds_tools.get_model

+
+
+pyTEMlib.eds_tools.get_model(tags, spectrum)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eds_tools.get_peak.html b/_autosummary/pyTEMlib.eds_tools.get_peak.html new file mode 100644 index 00000000..3ce22583 --- /dev/null +++ b/_autosummary/pyTEMlib.eds_tools.get_peak.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eds_tools.get_peak — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eds_tools.get_peak

+
+
+pyTEMlib.eds_tools.get_peak(E, energy_scale)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eds_tools.get_x_ray_lines.html b/_autosummary/pyTEMlib.eds_tools.get_x_ray_lines.html new file mode 100644 index 00000000..c59c5485 --- /dev/null +++ b/_autosummary/pyTEMlib.eds_tools.get_x_ray_lines.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eds_tools.get_x_ray_lines — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eds_tools.get_x_ray_lines

+
+
+pyTEMlib.eds_tools.get_x_ray_lines(spectrum, elements)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eds_tools.html b/_autosummary/pyTEMlib.eds_tools.html new file mode 100644 index 00000000..4a41ffdc --- /dev/null +++ b/_autosummary/pyTEMlib.eds_tools.html @@ -0,0 +1,174 @@ + + + + + + + pyTEMlib.eds_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eds_tools

+

eds_tools +Model based quantification of energy-dispersive X-ray spectroscopy data +Copyright by Gerd Duscher

+

The University of Tennessee, Knoxville +Department of Materials Science & Engineering

+

Sources:

+
+
Units:

everything is in SI units, except length is given in nm and angles in mrad.

+
+
Usage:

See the notebooks for examples of these routines

+
+
+

All the input and output is done through a dictionary which is to be found in the meta_data +attribute of the sidpy.Dataset

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

detect_peaks

detector_response

Example

+

find_elements

fit_model

gaussian

getFWHM

get_eds_cross_sections

get_eds_xsection

get_model

get_peak

get_x_ray_lines

update_fit_values

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eds_tools.update_fit_values.html b/_autosummary/pyTEMlib.eds_tools.update_fit_values.html new file mode 100644 index 00000000..8e5690fe --- /dev/null +++ b/_autosummary/pyTEMlib.eds_tools.update_fit_values.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eds_tools.update_fit_values — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eds_tools.update_fit_values

+
+
+pyTEMlib.eds_tools.update_fit_values(out_tags, p)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog.CompositionWidget.html b/_autosummary/pyTEMlib.eels_dialog.CompositionWidget.html new file mode 100644 index 00000000..590eb137 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog.CompositionWidget.html @@ -0,0 +1,195 @@ + + + + + + + pyTEMlib.eels_dialog.CompositionWidget — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog.CompositionWidget

+
+
+class pyTEMlib.eels_dialog.CompositionWidget(datasets=None, index=0)[source]
+

Bases: object

+

Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

auto_id

cursor2energy_scale

do_fit

find_elements

line_select_callback

modify_areal_density

modify_end_exclude

modify_onset

modify_start_exclude

plot

plot_regions

set_action

set_dataset

set_element

set_elements

set_figure_pane

set_fit_area

set_y_scale

show_edges

sort_elements

update

update_element

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog.get_sidebar.html b/_autosummary/pyTEMlib.eels_dialog.get_sidebar.html new file mode 100644 index 00000000..d883ff9d --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog.get_sidebar.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eels_dialog.get_sidebar — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog.get_sidebar

+
+
+pyTEMlib.eels_dialog.get_sidebar()[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog.html b/_autosummary/pyTEMlib.eels_dialog.html new file mode 100644 index 00000000..271c11d6 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog.html @@ -0,0 +1,136 @@ + + + + + + + pyTEMlib.eels_dialog — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog

+

QT dialog window for EELS compositional analysis

+

Author: Gerd Duscher

+

Functions

+ + + + + + +

get_sidebar

+

Classes

+ + + + + + +

CompositionWidget

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.EdgesAtCursor.html b/_autosummary/pyTEMlib.eels_dialog_utilities.EdgesAtCursor.html new file mode 100644 index 00000000..04c6ecb0 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.EdgesAtCursor.html @@ -0,0 +1,192 @@ + + + + + + + pyTEMlib.eels_dialog_utilities.EdgesAtCursor — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities.EdgesAtCursor

+
+
+class pyTEMlib.eels_dialog_utilities.EdgesAtCursor(ax, x, y, maximal_chemical_shift=5)[source]
+

Bases: object

+

Adds a Cursor to a plot, which plots all major (possible) ionization edges at +the cursor location if left (right) mouse button is clicked.

+
+
+ax
+
+
Type:
+

matplotlib axis

+
+
+
+ +
+
+x
+

energy_scale of spectrum

+
+
Type:
+

numpy array

+
+
+
+ +
+
+y
+

intensities of spectrum

+
+
Type:
+

numpy array

+
+
+
+ +
+
+maximal_chemical_shift
+

optional parameter maximum_chemical_shift which allows to change the energy range in which the edges +are searched.

+
+
Type:
+

float

+
+
+
+ +

Example

+

fig, ax = plt.subplots() +ax.plot(energy_scale, spectrum) +cursor = EdgesAtCursor(ax, energy_scale, spectrum)

+

see Chapter4 ‘CH4-Working_with_X-Sections’ notebook

+

Methods

+ + + + + + + + + + + + + + + +

click

del_edges

disconnect

mouse_move

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.ElementalEdges.html b/_autosummary/pyTEMlib.eels_dialog_utilities.ElementalEdges.html new file mode 100644 index 00000000..8c446633 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.ElementalEdges.html @@ -0,0 +1,158 @@ + + + + + + + pyTEMlib.eels_dialog_utilities.ElementalEdges — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities.ElementalEdges

+
+
+class pyTEMlib.eels_dialog_utilities.ElementalEdges(ax, z)[source]
+

Bases: object

+

Adds ionization edges of element z to plot with axis ax

+

There is an optional parameter maximum_chemical_shift which allows to change +the energy range in which the edges are searched.

+

available functions: +- update(): updates the drawing of ionization edges +- set_edge(Z) : changes atomic number and updates everything accordingly +- disconnect: makes everything invisible and stops drawing +- reconnect: undo of disconnect

+

usage: +>> fig, ax = plt.subplots() +>> ax.plot(energy_scale, spectrum) +>> Z= 42 +>> cursor = ElementalEdges(ax, Z)

+

see Chapter4 ‘CH4-Working_with_X-Sections’ notebook

+

Methods

+ + + + + + + + + + + + + + + + + + +

disconnect

onresize

reconnect

set_edge

update

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage.html b/_autosummary/pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage.html new file mode 100644 index 00000000..739e2315 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage.html @@ -0,0 +1,201 @@ + + + + + + + pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • + View page source +
  • +
+
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage

+
+
+class pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage(data_source, horizontal=True)[source]
+

Bases: object

+

Interactive spectrum imaging plot

+
+

Attributes:

+
+
dictionary with a minimum of the following keys:

[‘image’]: displayed image +[‘data’]: data cube +[‘intensity_scale_ppm’]: intensity scale +[‘ylabel’]: intensity label +[‘spectra’] dictionary which contains dictionaries for each spectrum style [‘1-2’]:

+
+

[‘spectrum’] = tags[‘cube’][y,x,:] +[‘spectra’][f’{x}-{y}’][‘energy_scale’] = tags[‘energy_scale’] +[‘intensity_scale’] = 1/tags[‘cube’][y,x,:].sum()*1e6

+
+
+
+

Please note the possibility to load any image for the selection of the spectrum +Also there is the possibility to display the survey image.

+
+
For analysis, we have the following options:

‘fix_energy’: set zero-loss peak maximum to zero !! Low loss spectra only!! +‘fit_zero_loss’: fit zero-loss peak with model function !! Low loss spectra only!! +‘fit_low_loss’: fit low-loss spectrum with model peaks !! Low loss spectra only!!

+

‘fit_composition’: fit core-loss spectrum with background and cross-sections!! Core loss spectra only!! +‘fit_ELNES’: fit core-loss edge with model peaks !! Core loss spectra only!!

+
+
+

Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

do_all

fit_quantification

fit_zero_loss

fix_energy

get_current_spectrum

get_xy

on_button_clicked

onclick

overlay_data

overlay_z_contrast_image

set_legend

set_survey_image

set_tags

set_z_contrast_image

update

+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.PeriodicTableWidget.html b/_autosummary/pyTEMlib.eels_dialog_utilities.PeriodicTableWidget.html new file mode 100644 index 00000000..ccc38eca --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.PeriodicTableWidget.html @@ -0,0 +1,151 @@ + + + + + + + pyTEMlib.eels_dialog_utilities.PeriodicTableWidget — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities.PeriodicTableWidget

+
+
+class pyTEMlib.eels_dialog_utilities.PeriodicTableWidget(initial_elements=None, energy_scale=None)[source]
+

Bases: object

+

ipywidget to get a selection of elements.

+

Elements that are not having a valid cross-sections are disabled.

+
+
Parameters:
+
    +
  • initial_elements (list of str) – the elements that are already selected

  • +
  • energy_scale (list or numpy array) – energy-scale of spectrum/spectra to determine likely edges

  • +
+
+
Returns:
+

list of strings – use get_output() function

+
+
Return type:
+

elements.

+
+
+

Methods

+ + + + + + + + + +

get_output

update

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.RangeSelector.html b/_autosummary/pyTEMlib.eels_dialog_utilities.RangeSelector.html new file mode 100644 index 00000000..0159969e --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.RangeSelector.html @@ -0,0 +1,444 @@ + + + + + + + pyTEMlib.eels_dialog_utilities.RangeSelector — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities.RangeSelector

+
+
+class pyTEMlib.eels_dialog_utilities.RangeSelector(ax, on_select)[source]
+

Bases: RectangleSelector

+

Select ranges of edge fitting interactively

+

Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

add_state

Add a state to define the widget's behavior.

clear

Clear the selection and set the selector ready to make a new one.

connect_default_events

Connect the major canvas events to methods.

connect_event

Connect a callback function with an event.

disconnect_events

Disconnect all events created by this widget.

draw_shape

get_active

Get whether the widget is active.

get_visible

Get the visibility of the selector artists.

ignore

Return whether event should be ignored.

on_key_press

Key press event handler and validator for all selection widgets.

on_key_release

Key release event handler and validator.

on_scroll

Mouse scroll event handler and validator.

onmove

Cursor move event handler and validator.

press

Button press handler and validator.

release

Button release event handler and validator.

remove_state

Remove a state to define the widget's behavior.

set_active

Set whether the widget is active.

set_handle_props

Set the properties of the handles selector artist.

set_props

Set the properties of the selector artist.

set_visible

Set the visibility of the selector artists.

update

Draw using blit() or draw_idle(), depending on self.useblit.

update_background

Force an update of the background.

+

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

active

Is the widget active?

artists

Tuple of the artists of the selector.

center

Center of rectangle in data coordinates.

corners

Corners of rectangle in data coordinates from lower left, moving clockwise.

drawon

edge_centers

Midpoint of rectangle edges in data coordinates from left, moving anti-clockwise.

eventson

extents

Return (xmin, xmax, ymin, ymax) in data coordinates as defined by the bounding box before rotation.

geometry

Return an array of shape (2, 5) containing the x (RectangleSelector.geometry[1, :]) and y (RectangleSelector.geometry[0, :]) data coordinates of the four corners of the rectangle starting and ending in the top left corner.

rotation

Rotation in degree in interval [-45°, 45°].

state_modifier_keys

visible

+
+
+property active
+

Is the widget active?

+
+ +
+
+add_state(state)
+

Add a state to define the widget’s behavior. See the +state_modifier_keys parameters for details.

+
+
Parameters:
+

state (str) – Must be a supported state of the selector. See the +state_modifier_keys parameters for details.

+
+
Raises:
+

ValueError – When the state is not supported by the selector.

+
+
+
+ +
+
+property artists
+

Tuple of the artists of the selector.

+
+ +
+
+property center
+

Center of rectangle in data coordinates.

+
+ +
+
+clear()
+

Clear the selection and set the selector ready to make a new one.

+
+ +
+
+connect_default_events()
+

Connect the major canvas events to methods.

+
+ +
+
+connect_event(event, callback)
+

Connect a callback function with an event.

+

This should be used in lieu of figure.canvas.mpl_connect since this +function stores callback ids for later clean up.

+
+ +
+
+property corners
+

Corners of rectangle in data coordinates from lower left, +moving clockwise.

+
+ +
+
+disconnect_events()
+

Disconnect all events created by this widget.

+
+ +
+
+property edge_centers
+

Midpoint of rectangle edges in data coordinates from left, +moving anti-clockwise.

+
+ +
+
+property extents
+

Return (xmin, xmax, ymin, ymax) in data coordinates as defined by the +bounding box before rotation.

+
+ +
+
+property geometry
+

Return an array of shape (2, 5) containing the +x (RectangleSelector.geometry[1, :]) and +y (RectangleSelector.geometry[0, :]) data coordinates of the four +corners of the rectangle starting and ending in the top left corner.

+
+ +
+
+get_active()
+

Get whether the widget is active.

+
+ +
+
+get_visible()
+

Get the visibility of the selector artists.

+
+ +
+
+ignore(event)
+

Return whether event should be ignored.

+

This method should be called at the beginning of any event callback.

+
+ +
+
+on_key_press(event)
+

Key press event handler and validator for all selection widgets.

+
+ +
+
+on_key_release(event)
+

Key release event handler and validator.

+
+ +
+
+on_scroll(event)
+

Mouse scroll event handler and validator.

+
+ +
+
+onmove(event)
+

Cursor move event handler and validator.

+
+ +
+
+press(event)
+

Button press handler and validator.

+
+ +
+
+release(event)
+

Button release event handler and validator.

+
+ +
+
+remove_state(state)
+

Remove a state to define the widget’s behavior. See the +state_modifier_keys parameters for details.

+
+
Parameters:
+

state (str) – Must be a supported state of the selector. See the +state_modifier_keys parameters for details.

+
+
Raises:
+

ValueError – When the state is not supported by the selector.

+
+
+
+ +
+
+property rotation
+

Rotation in degree in interval [-45°, 45°]. The rotation is limited in +range to keep the implementation simple.

+
+ +
+
+set_active(active)
+

Set whether the widget is active.

+
+ +
+
+set_handle_props(**handle_props)
+

Set the properties of the handles selector artist. See the +handle_props argument in the selector docstring to know which +properties are supported.

+
+ +
+
+set_props(**props)
+

Set the properties of the selector artist. See the props argument +in the selector docstring to know which properties are supported.

+
+ +
+
+set_visible(visible)
+

Set the visibility of the selector artists.

+
+ +
+
+update()
+

Draw using blit() or draw_idle(), depending on self.useblit.

+
+ +
+
+update_background(event)
+

Force an update of the background.

+
+ +
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.RegionSelector.html b/_autosummary/pyTEMlib.eels_dialog_utilities.RegionSelector.html new file mode 100644 index 00000000..6e5a9dd9 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.RegionSelector.html @@ -0,0 +1,157 @@ + + + + + + + pyTEMlib.eels_dialog_utilities.RegionSelector — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities.RegionSelector

+
+
+class pyTEMlib.eels_dialog_utilities.RegionSelector(ax)[source]
+

Bases: object

+

Selects fitting region and the regions that are excluded for each edge.

+

Select a region with a spanSelector and then type ‘a’ for all the fitting region or a number for the edge +you want to define the region excluded from the fit (solid state effects).

+

see Chapter4 ‘CH4-Working_with_X-Sections,ipynb’ notebook

+

Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

click

delete_region

disconnect

get_regions

on_select1

onresize

set_regions

update

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.SIPlot.html b/_autosummary/pyTEMlib.eels_dialog_utilities.SIPlot.html new file mode 100644 index 00000000..d2e344e7 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.SIPlot.html @@ -0,0 +1,147 @@ + + + + + + + pyTEMlib.eels_dialog_utilities.SIPlot — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities.SIPlot

+
+
+class pyTEMlib.eels_dialog_utilities.SIPlot(dset, figure=None, horizontal=True, **kwargs)[source]
+

Bases: SpectralImageVisualizer

+

Methods

+ + + + + + + + + + + + + + + + + + + + + +

get_spectrum

get_xy

line_select_callback

plot

set_bin

set_legend

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.SpectrumPlot.html b/_autosummary/pyTEMlib.eels_dialog_utilities.SpectrumPlot.html new file mode 100644 index 00000000..268fefce --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.SpectrumPlot.html @@ -0,0 +1,135 @@ + + + + + + + pyTEMlib.eels_dialog_utilities.SpectrumPlot — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities.SpectrumPlot

+
+
+class pyTEMlib.eels_dialog_utilities.SpectrumPlot(dset, spectrum_number=0, figure=None, **kwargs)[source]
+

Bases: CurveVisualizer

+

Methods

+ + + + + + + + + +

line_select_callback

plot

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.get_likely_edges.html b/_autosummary/pyTEMlib.eels_dialog_utilities.get_likely_edges.html new file mode 100644 index 00000000..f96bdbdc --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.get_likely_edges.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_dialog_utilities.get_likely_edges — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities.get_likely_edges

+
+
+pyTEMlib.eels_dialog_utilities.get_likely_edges(energy_scale)[source]
+

get likely ionization edges within energy_scale

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_info.html b/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_info.html new file mode 100644 index 00000000..6e6cc0e9 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_info.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_dialog_utilities.get_periodic_table_info — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • + View page source +
  • +
+
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities.get_periodic_table_info

+
+
+pyTEMlib.eels_dialog_utilities.get_periodic_table_info()[source]
+

Info for periodic table dialog

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_widget.html b/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_widget.html new file mode 100644 index 00000000..ddf966d0 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_widget.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eels_dialog_utilities.get_periodic_table_widget — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • + View page source +
  • +
+
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities.get_periodic_table_widget

+
+
+pyTEMlib.eels_dialog_utilities.get_periodic_table_widget(energy_scale=None)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.html b/_autosummary/pyTEMlib.eels_dialog_utilities.html new file mode 100644 index 00000000..3d4ad8d8 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.html @@ -0,0 +1,170 @@ + + + + + + + pyTEMlib.eels_dialog_utilities — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities

+

Interactive routines for EELS analysis

+

this file provides additional dialogs for EELS quantification

+

Author: Gerd Duscher

+

Functions

+ + + + + + + + + + + + + + + +

get_likely_edges

get likely ionization edges within energy_scale

get_periodic_table_info

Info for periodic table dialog

get_periodic_table_widget

make_box_layout

+

Classes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

EdgesAtCursor

Adds a Cursor to a plot, which plots all major (possible) ionization edges at the cursor location if left (right) mouse button is clicked.

ElementalEdges

Adds ionization edges of element z to plot with axis ax

InteractiveSpectrumImage

Interactive spectrum imaging plot

PeriodicTableWidget

ipywidget to get a selection of elements.

RangeSelector

Select ranges of edge fitting interactively

RegionSelector

Selects fitting region and the regions that are excluded for each edge.

SIPlot

SpectrumPlot

plot_EELS

Public constructor

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.make_box_layout.html b/_autosummary/pyTEMlib.eels_dialog_utilities.make_box_layout.html new file mode 100644 index 00000000..4e6f41d9 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.make_box_layout.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eels_dialog_utilities.make_box_layout — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities.make_box_layout

+
+
+pyTEMlib.eels_dialog_utilities.make_box_layout()[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dialog_utilities.plot_EELS.html b/_autosummary/pyTEMlib.eels_dialog_utilities.plot_EELS.html new file mode 100644 index 00000000..984f5a54 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dialog_utilities.plot_EELS.html @@ -0,0 +1,768 @@ + + + + + + + pyTEMlib.eels_dialog_utilities.plot_EELS — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dialog_utilities.plot_EELS

+
+
+class pyTEMlib.eels_dialog_utilities.plot_EELS(**kwargs: Any)[source]
+

Bases: HBox

+

Public constructor

+

Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

add_class

Adds a class to the top level element of the widget.

add_traits

Dynamically add trait attributes to the Widget.

blur

Blur the widget.

class_own_trait_events

Get a dict of all event handlers defined on this class, not a parent.

class_own_traits

Get a dict of all the traitlets defined on this class, not a parent.

class_trait_names

Get a list of all the names of this class' traits.

class_traits

Get a dict of all the traits of this class.

close

Close method.

close_all

focus

Focus on the widget.

get_manager_state

Returns the full state for a widget manager for embedding

get_state

Gets the widget state, or a piece of it.

get_view_spec

handle_comm_opened

Static method, called when a widget is constructed.

handle_control_comm_opened

Class method, called when the comm-open message on the "jupyter.widget.control" comm channel is received

has_trait

Returns True if the object has a trait with the specified name.

hold_sync

Hold syncing any state until the outermost context manager exits

hold_trait_notifications

Context manager for bundling trait change notifications and cross validation.

line_color

notify_change

Called when a property has changed.

observe

Setup a handler to be called when a trait changes.

on_legend_pick

on_msg

(Un)Register a custom msg receive callback.

on_trait_change

DEPRECATED: Setup a handler to be called when a trait changes.

on_widget_constructed

Registers a callback to be called when a widget is constructed.

open

Open a comm to the frontend if one isn't already open.

remove_class

Removes a class from the top level element of the widget.

send

Sends a custom msg to the widget model in the front-end.

send_state

Sends the widget state, or a piece of it, to the front-end, if it exists.

set_dimension

set_state

Called when a state is received from the front-end.

set_trait

Forcibly sets trait attribute, including read-only attributes.

setup_instance

This is called before self.__init__ is called.

trait_defaults

Return a trait's default value or a dictionary of them

trait_events

Get a dict of all the event handlers of this class.

trait_has_value

Returns True if the specified trait has a value.

trait_metadata

Get metadata values for trait by key.

trait_names

Get a list of all the names of this class' traits.

trait_values

A dict of trait names and their values.

traits

Get a dict of all the traits of this class.

unobserve

Remove a trait change handler.

unobserve_all

Remove trait change handlers of any type for the specified name.

update

Draw line in plot

update_exposure

update_ylabel

+

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

box_style

Use a predefined styling for the box.

children

List of widget children

comm

A trait which allows any value.

cross_validation_lock

A contextmanager for running a block with our cross validation lock set to True.

keys

The traits which are synced.

layout

An instance trait which coerces a dict to an instance.

log

A trait whose value must be an instance of a specified class.

model_id

Gets the model id of this widget.

tabbable

Is widget tabbable?

tooltip

A tooltip caption.

widget_types

widgets

+
+
+__del__()
+

Object disposal

+
+ +
+
+add_class(className)
+

Adds a class to the top level element of the widget.

+

Doesn’t add the class if it already exists.

+
+ +
+
+add_traits(**traits)
+

Dynamically add trait attributes to the Widget.

+
+ +
+
+blur()
+

Blur the widget.

+
+ +
+
+box_style
+

Use a predefined styling for the box.

+
+ +
+
+children
+

List of widget children

+
+ +
+
+classmethod class_own_trait_events(name)
+

Get a dict of all event handlers defined on this class, not a parent.

+

Works like event_handlers, except for excluding traits from parents.

+
+ +
+
+classmethod class_own_traits(**metadata)
+

Get a dict of all the traitlets defined on this class, not a parent.

+

Works like class_traits, except for excluding traits from parents.

+
+ +
+
+classmethod class_trait_names(**metadata)
+

Get a list of all the names of this class’ traits.

+

This method is just like the trait_names() method, +but is unbound.

+
+ +
+
+classmethod class_traits(**metadata)
+

Get a dict of all the traits of this class. The dictionary +is keyed on the name and the values are the TraitType objects.

+

This method is just like the traits() method, but is unbound.

+

The TraitTypes returned don’t know anything about the values +that the various HasTrait’s instances are holding.

+

The metadata kwargs allow functions to be passed in which +filter traits based on metadata values. The functions should +take a single value as an argument and return a boolean. If +any function returns False, then the trait is not included in +the output. If a metadata key doesn’t exist, None will be passed +to the function.

+
+ +
+
+close()
+

Close method.

+

Closes the underlying comm. +When the comm is closed, all of the widget views are automatically +removed from the front-end.

+
+ +
+
+property cross_validation_lock
+

A contextmanager for running a block with our cross validation lock set +to True.

+

At the end of the block, the lock’s value is restored to its value +prior to entering the block.

+
+ +
+
+focus()
+

Focus on the widget.

+
+ +
+
+static get_manager_state(drop_defaults=False, widgets=None)
+

Returns the full state for a widget manager for embedding

+
+
Parameters:
+
    +
  • drop_defaults – when True, it will not include default value

  • +
  • widgets – list with widgets to include in the state (or all widgets when None)

  • +
+
+
Returns:
+

+
+
+
+ +
+
+get_state(key=None, drop_defaults=False)
+

Gets the widget state, or a piece of it.

+
+
Parameters:
+

key (unicode or iterable (optional)) – A single property’s name or iterable of property names to get.

+
+
Returns:
+

    +
  • state (dict of states)

  • +
  • metadata (dict) – metadata for each field: {key: metadata}

  • +
+

+
+
+
+ +
+
+static handle_comm_opened(comm, msg)
+

Static method, called when a widget is constructed.

+
+ +
+
+classmethod handle_control_comm_opened(comm, msg)
+

Class method, called when the comm-open message on the +“jupyter.widget.control” comm channel is received

+
+ +
+
+has_trait(name)
+

Returns True if the object has a trait with the specified name.

+
+ +
+
+hold_sync()
+

Hold syncing any state until the outermost context manager exits

+
+ +
+
+hold_trait_notifications()
+

Context manager for bundling trait change notifications and cross +validation.

+

Use this when doing multiple trait assignments (init, config), to avoid +race conditions in trait notifiers requesting other trait values. +All trait notifications will fire after all values have been assigned.

+
+ +
+
+keys
+

The traits which are synced.

+
+ +
+
+property model_id
+

Gets the model id of this widget.

+

If a Comm doesn’t exist yet, a Comm will be created automagically.

+
+ +
+
+notify_change(change)
+

Called when a property has changed.

+
+ +
+
+observe(handler: t.Callable[..., t.Any], names: Sentinel | str | t.Iterable[Sentinel | str] = traitlets.All, type: Sentinel | str = 'change') None
+

Setup a handler to be called when a trait changes.

+

This is used to setup dynamic notifications of trait changes.

+
+
Parameters:
+
    +
  • handler (callable) – A callable that is called when a trait changes. Its +signature should be handler(change), where change is a +dictionary. The change dictionary at least holds a ‘type’ key. +* type: the type of notification. +Other keys may be passed depending on the value of ‘type’. In the +case where type is ‘change’, we also have the following keys: +* owner : the HasTraits instance +* old : the old value of the modified trait attribute +* new : the new value of the modified trait attribute +* name : the name of the modified trait attribute.

  • +
  • names (list, str, All) – If names is All, the handler will apply to all traits. If a list +of str, handler will apply to all names in the list. If a +str, the handler will apply just to that name.

  • +
  • type (str, All (default: 'change')) – The type of notification to filter by. If equal to All, then all +notifications are passed to the observe handler.

  • +
+
+
+
+ +
+
+on_msg(callback, remove=False)
+

(Un)Register a custom msg receive callback.

+
+
Parameters:
+
    +
  • callback (callable) –

    callback will be passed three arguments when a message arrives:

    +
    callback(widget, content, buffers)
    +
    +
    +

  • +
  • remove (bool) – True if the callback should be unregistered.

  • +
+
+
+
+ +
+
+on_trait_change(handler=None, name=None, remove=False)
+

DEPRECATED: Setup a handler to be called when a trait changes.

+

This is used to setup dynamic notifications of trait changes.

+

Static handlers can be created by creating methods on a HasTraits +subclass with the naming convention ‘_[traitname]_changed’. Thus, +to create static handler for the trait ‘a’, create the method +_a_changed(self, name, old, new) (fewer arguments can be used, see +below).

+

If remove is True and handler is not specified, all change +handlers for the specified name are uninstalled.

+
+
Parameters:
+
    +
  • handler (callable, None) – A callable that is called when a trait changes. Its +signature can be handler(), handler(name), handler(name, new), +handler(name, old, new), or handler(name, old, new, self).

  • +
  • name (list, str, None) – If None, the handler will apply to all traits. If a list +of str, handler will apply to all names in the list. If a +str, the handler will apply just to that name.

  • +
  • remove (bool) – If False (the default), then install the handler. If True +then unintall it.

  • +
+
+
+
+ +
+
+static on_widget_constructed(callback)
+

Registers a callback to be called when a widget is constructed.

+

The callback must have the following signature: +callback(widget)

+
+ +
+
+open()
+

Open a comm to the frontend if one isn’t already open.

+
+ +
+
+remove_class(className)
+

Removes a class from the top level element of the widget.

+

Doesn’t remove the class if it doesn’t exist.

+
+ +
+
+send(content, buffers=None)
+

Sends a custom msg to the widget model in the front-end.

+
+
Parameters:
+
    +
  • content (dict) – Content of the message to send.

  • +
  • buffers (list of binary buffers) – Binary buffers to send with message

  • +
+
+
+
+ +
+
+send_state(key=None)
+

Sends the widget state, or a piece of it, to the front-end, if it exists.

+
+
Parameters:
+

key (unicode, or iterable (optional)) – A single property’s name or iterable of property names to sync with the front-end.

+
+
+
+ +
+
+set_state(sync_data)
+

Called when a state is received from the front-end.

+
+ +
+
+set_trait(name, value)
+

Forcibly sets trait attribute, including read-only attributes.

+
+ +
+
+setup_instance(**kwargs)
+

This is called before self.__init__ is called.

+
+ +
+
+tabbable
+

Is widget tabbable?

+
+ +
+
+tooltip
+

A tooltip caption.

+
+ +
+
+trait_defaults(*names, **metadata)
+

Return a trait’s default value or a dictionary of them

+

Notes

+

Dynamically generated default values may +depend on the current state of the object.

+
+ +
+
+classmethod trait_events(name=None)
+

Get a dict of all the event handlers of this class.

+
+
Parameters:
+

name (str (default: None)) – The name of a trait of this class. If name is None then all +the event handlers of this class will be returned instead.

+
+
Return type:
+

The event handlers associated with a trait name, or all event handlers.

+
+
+
+ +
+
+trait_has_value(name)
+

Returns True if the specified trait has a value.

+

This will return false even if getattr would return a +dynamically generated default value. These default values +will be recognized as existing only after they have been +generated.

+

Example

+
class MyClass(HasTraits):
+    i = Int()
+
+mc = MyClass()
+assert not mc.trait_has_value("i")
+mc.i # generates a default value
+assert mc.trait_has_value("i")
+
+
+
+ +
+
+trait_metadata(traitname, key, default=None)
+

Get metadata values for trait by key.

+
+ +
+
+trait_names(**metadata)
+

Get a list of all the names of this class’ traits.

+
+ +
+
+trait_values(**metadata)
+

A dict of trait names and their values.

+

The metadata kwargs allow functions to be passed in which +filter traits based on metadata values. The functions should +take a single value as an argument and return a boolean. If +any function returns False, then the trait is not included in +the output. If a metadata key doesn’t exist, None will be passed +to the function.

+
+
Return type:
+

A dict of trait names and their values.

+
+
+

Notes

+

Trait values are retrieved via getattr, any exceptions raised +by traits or the operations they may trigger will result in the +absence of a trait value in the result dict.

+
+ +
+
+traits(**metadata)
+

Get a dict of all the traits of this class. The dictionary +is keyed on the name and the values are the TraitType objects.

+

The TraitTypes returned don’t know anything about the values +that the various HasTrait’s instances are holding.

+

The metadata kwargs allow functions to be passed in which +filter traits based on metadata values. The functions should +take a single value as an argument and return a boolean. If +any function returns False, then the trait is not included in +the output. If a metadata key doesn’t exist, None will be passed +to the function.

+
+ +
+
+unobserve(handler: t.Callable[..., t.Any], names: Sentinel | str | t.Iterable[Sentinel | str] = traitlets.All, type: Sentinel | str = 'change') None
+

Remove a trait change handler.

+

This is used to unregister handlers to trait change notifications.

+
+
Parameters:
+
    +
  • handler (callable) – The callable called when a trait attribute changes.

  • +
  • names (list, str, All (default: All)) – The names of the traits for which the specified handler should be +uninstalled. If names is All, the specified handler is uninstalled +from the list of notifiers corresponding to all changes.

  • +
  • type (str or All (default: 'change')) – The type of notification to filter by. If All, the specified handler +is uninstalled from the list of notifiers corresponding to all types.

  • +
+
+
+
+ +
+
+unobserve_all(name: str | t.Any = traitlets.All) None
+

Remove trait change handlers of any type for the specified name. +If name is not specified, removes all trait notifiers.

+
+ +
+
+update()[source]
+

Draw line in plot

+
+ +
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_dlg.html b/_autosummary/pyTEMlib.eels_dlg.html new file mode 100644 index 00000000..c69aa4b4 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_dlg.html @@ -0,0 +1,119 @@ + + + + + + + pyTEMlib.eels_dlg — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_dlg

+

GUI definitions for EEELS_dialog

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.add_element_to_dataset.html b/_autosummary/pyTEMlib.eels_tools.add_element_to_dataset.html new file mode 100644 index 00000000..2c5691dc --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.add_element_to_dataset.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eels_tools.add_element_to_dataset — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.add_element_to_dataset

+
+
+pyTEMlib.eels_tools.add_element_to_dataset(dataset, z)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.add_peaks.html b/_autosummary/pyTEMlib.eels_tools.add_peaks.html new file mode 100644 index 00000000..02bb8596 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.add_peaks.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.add_peaks — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.add_peaks

+
+
+pyTEMlib.eels_tools.add_peaks(x, y, peaks, pin_in=None, peak_shape_in=None, shape='Gaussian')[source]
+

add peaks to fitting parameters

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.assign_likely_edges.html b/_autosummary/pyTEMlib.eels_tools.assign_likely_edges.html new file mode 100644 index 00000000..c3e4b77b --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.assign_likely_edges.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eels_tools.assign_likely_edges — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.assign_likely_edges

+
+
+pyTEMlib.eels_tools.assign_likely_edges(edge_channels, energy_scale)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.auto_chemical_composition.html b/_autosummary/pyTEMlib.eels_tools.auto_chemical_composition.html new file mode 100644 index 00000000..24093207 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.auto_chemical_composition.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eels_tools.auto_chemical_composition — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.auto_chemical_composition

+
+
+pyTEMlib.eels_tools.auto_chemical_composition(dataset)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.auto_id_edges.html b/_autosummary/pyTEMlib.eels_tools.auto_id_edges.html new file mode 100644 index 00000000..97203c2a --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.auto_id_edges.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eels_tools.auto_id_edges — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.auto_id_edges

+
+
+pyTEMlib.eels_tools.auto_id_edges(dataset)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.cl_model.html b/_autosummary/pyTEMlib.eels_tools.cl_model.html new file mode 100644 index 00000000..36d20e11 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.cl_model.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.cl_model — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.cl_model

+
+
+pyTEMlib.eels_tools.cl_model(x, p, number_of_edges, xsec)[source]
+

core loss model for fitting

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.drude.html b/_autosummary/pyTEMlib.eels_tools.drude.html new file mode 100644 index 00000000..ec364741 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.drude.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.drude — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.drude

+
+
+pyTEMlib.eels_tools.drude(peak_position, peak_width, gamma, energy_scale)[source]
+

dielectric function according to Drude theory

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.drude2.html b/_autosummary/pyTEMlib.eels_tools.drude2.html new file mode 100644 index 00000000..8b655860 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.drude2.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.drude2 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.drude2

+
+
+pyTEMlib.eels_tools.drude2(tags, e, p)[source]
+

dielectric function according to Drude theory for fitting

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.drude_lorentz.html b/_autosummary/pyTEMlib.eels_tools.drude_lorentz.html new file mode 100644 index 00000000..11fc460b --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.drude_lorentz.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.drude_lorentz — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.drude_lorentz

+
+
+pyTEMlib.eels_tools.drude_lorentz(eps_inf, leng, ep, eb, gamma, e, amplitude)[source]
+

dielectric function according to Drude-Lorentz theory

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.drude_simulation.html b/_autosummary/pyTEMlib.eels_tools.drude_simulation.html new file mode 100644 index 00000000..d37fb9d2 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.drude_simulation.html @@ -0,0 +1,166 @@ + + + + + + + pyTEMlib.eels_tools.drude_simulation — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.drude_simulation

+
+
+pyTEMlib.eels_tools.drude_simulation(dset, e, ep, ew, tnm, eb)[source]
+

probabilities of dielectric function eps relative to zero-loss integral (i0 = 1)

+

Gives probabilities of dielectric function eps relative to zero-loss integral (i0 = 1) per eV +Details in R.F.Egerton: EELS in the Electron Microscope, 3rd edition, Springer 2011

+

# function drude(ep,ew,eb,epc,e0,beta,nn,tnm) +# Given the plasmon energy (ep), plasmon fwhm (ew) and binding energy(eb), +# this program generates: +# EPS1, EPS2 from modified Eq. (3.40), ELF=Im(-1/EPS) from Eq. (3.42), +# single scattering from Eq. (4.26) and SRFINT from Eq. (4.31) +# The output is e, ssd into the file drude.ssd (for use in Flog etc.) +# and e,eps1 ,eps2 into drude.eps (for use in Kroeger etc.) +# Gives probabilities relative to zero-loss integral (i0 = 1) per eV +# Details in R.F.Egerton: EELS in the Electron Microscope, 3rd edition, Springer 2011 +# Version 10.11.26

+

b.7 drude Simulation of a Low-Loss Spectrum +The program DRUDE calculates a single-scattering plasmon-loss spectrum for +a specimen of a given thickness tnm (in nm), recorded with electrons of a +specified incident energy e0 by a spectrometer that accepts scattering up to a +specified collection semi-angle beta. It is based on the extended drude model +(Section 3.3.2), with a volume energy-loss function elf in accord with Eq. (3.64) and +a surface-scattering energy-loss function srelf as in Eq. (4.31). Retardation effects +and coupling between the two surface modes are not included. The surface term can +be made negligible by entering a large specimen thickness (tnm > 1000). +Surface intensity srfint and volume intensity volint are calculated from +Eqs. (4.31) and (4.26), respectively. The total spectral intensity ssd is written to +the file DRUDE.SSD, which can be used as input for KRAKRO. These intensities are +all divided by i0, to give relative probabilities (per eV). The real and imaginary parts +of the dielectric function are written to DRUDE.EPS and can be used for comparison +with the results of Kramers–Kronig analysis (KRAKRO.DAT). +Written output includes the surface-loss probability Ps, obtained by integrating +srfint (a value that relates to two surfaces but includes the negative begrenzungs +term), for comparison with the analytical integration represented by Eq. (3.77). The +volume-loss probability p_v is obtained by integrating volint and is used to calculate +the volume plasmon mean free path (lam = tnm/p_v). The latter is listed and +compared with the MFP obtained from Eq. (3.44), which represents analytical integration +assuming a zero-width plasmon peak. The total probability (Pt = p_v+Ps) is +calculated and used to evaluate the thickness (lam.Pt) that would be given by the formula +t/λ = ln(It/i0), ignoring the surface-loss probability. Note that p_v will exceed +1 for thicker specimens (t/λ > 1), since it represents the probability of plasmon +scattering relative to that of no inelastic scattering. +The command-line usage is drude(ep,ew,eb,epc,beta,e0,tnm,nn), where ep is the +plasmon energy, ew the plasmon width, eb the binding energy of the electrons (0 for +a metal), and nn is the number of channels in the output spectrum. An example of +the output is shown in Fig. b.1a,b.

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.effective_collection_angle.html b/_autosummary/pyTEMlib.eels_tools.effective_collection_angle.html new file mode 100644 index 00000000..779e433c --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.effective_collection_angle.html @@ -0,0 +1,190 @@ + + + + + + + pyTEMlib.eels_tools.effective_collection_angle — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.effective_collection_angle

+
+
+pyTEMlib.eels_tools.effective_collection_angle(energy_scale, alpha, beta, beam_kv)[source]
+

Calculates the effective collection angle in mrad:

+

Translate from original Fortran program +Calculates the effective collection angle in mrad: +Parameter +——— +energy_scale: numpy array

+
+

first and last energy loss of spectrum in eV

+
+
+
alpha: float

convergence angle in mrad

+
+
beta: float

collection angle in mrad

+
+
beamKV: float

acceleration voltage in V

+
+
+
+
Returns:
+

    +
  • eff_beta (float) – effective collection angle in mrad

  • +
  • # function y = effbeta(ene, alpha, beta, beam_kv)

  • +
  • #

  • +
  • # This program computes etha(alpha,beta), that is the collection

  • +
  • # efficiency associated to the following geometry

  • +
  • #

  • +
  • # alpha = half angle of illumination (0 -> pi/2)

  • +
  • # beta = half angle of collection (0 -> pi/2)

  • +
  • # (pi/2 = 1570.795 mrad)

  • +
  • #

  • +
  • # A constant angular distribution of incident electrons is assumed

  • +
  • # for any incident angle (-alpha,alpha). These electrons imping the

  • +
  • # target and a single energy-loss event occurs, with a characteristic

  • +
  • # angle theta-e (relativistic). The angular distribution of the

  • +
  • # electrons after the target is analytically derived.

  • +
  • # This program integrates this distribution from theta=0 up to

  • +
  • # theta=beta with an adjustable angular step.

  • +
  • # This program also computes beta which is the theoretical*

  • +
  • # collection angle which would give the same value of etha(alpha,beta)

  • +
  • # with a parallel incident beam.

  • +
  • #

  • +
  • # subroutines and function subprograms required

  • +
  • # ———————————————

  • +
  • # none

  • +
  • #

  • +
  • # comments

  • +
  • # ——–

  • +
  • #

  • +
  • # The following parameters are asked as input

  • +
  • # accelerating voltage (kV), energy loss range (eV) for the study,

  • +
  • # energy loss step (eV) in this range, alpha (mrad), beta (mrad).

  • +
  • # The program returns for each energy loss step

  • +
  • # alpha (mrad), beta (mrad), theta-e (relativistic) (mrad),

  • +
  • # energy loss (eV), etha (#), beta * (mrad)

  • +
  • #

  • +
  • # author

  • +
  • # ——–

  • +
  • # Pierre TREBBIA

  • +
  • # US 41 (“Microscopie Electronique Analytique Quantitative”)

  • +
  • # Laboratoire de Physique des Solides, Bat. 510

  • +
  • # Universite Paris-Sud, F91405 ORSAY Cedex

  • +
  • # Phone ((33-1) 69 41 53 68)

  • +
  • #

  • +
+

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.find_all_edges.html b/_autosummary/pyTEMlib.eels_tools.find_all_edges.html new file mode 100644 index 00000000..419f8179 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.find_all_edges.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.eels_tools.find_all_edges — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.find_all_edges

+
+
+pyTEMlib.eels_tools.find_all_edges(edge_onset, maximal_chemical_shift=5)[source]
+

Find all (major and minor) edges within an energy range

+
+
Parameters:
+
    +
  • edge_onset (float) – approximate energy of ionization edge

  • +
  • maximal_chemical_shift (float) – optional, range of energy window around edge_onset to look for major edges

  • +
+
+
Returns:
+

text – string with all edges in energy range

+
+
Return type:
+

str

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.find_associated_edges.html b/_autosummary/pyTEMlib.eels_tools.find_associated_edges.html new file mode 100644 index 00000000..3a96ee65 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.find_associated_edges.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eels_tools.find_associated_edges — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.find_associated_edges

+
+
+pyTEMlib.eels_tools.find_associated_edges(dataset)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.find_edges.html b/_autosummary/pyTEMlib.eels_tools.find_edges.html new file mode 100644 index 00000000..69c98d0a --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.find_edges.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.find_edges — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.find_edges

+
+
+pyTEMlib.eels_tools.find_edges(dataset, sensitivity=2.5)[source]
+

find edges within a sidpy.Dataset

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.find_major_edges.html b/_autosummary/pyTEMlib.eels_tools.find_major_edges.html new file mode 100644 index 00000000..e476f633 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.find_major_edges.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.eels_tools.find_major_edges — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.find_major_edges

+
+
+pyTEMlib.eels_tools.find_major_edges(edge_onset, maximal_chemical_shift=5.0)[source]
+

Find all major edges within an energy range

+
+
Parameters:
+
    +
  • edge_onset (float) – approximate energy of ionization edge

  • +
  • maximal_chemical_shift (float) – optional, range of energy window around edge_onset to look for major edges

  • +
+
+
Returns:
+

text – string with all major edges in energy range

+
+
Return type:
+

str

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.find_maxima.html b/_autosummary/pyTEMlib.eels_tools.find_maxima.html new file mode 100644 index 00000000..347a0812 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.find_maxima.html @@ -0,0 +1,139 @@ + + + + + + + pyTEMlib.eels_tools.find_maxima — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.find_maxima

+
+
+pyTEMlib.eels_tools.find_maxima(y, number_of_peaks)[source]
+

find the first most prominent peaks

+

peaks are then sorted by energy

+
+
Parameters:
+
    +
  • y (numpy array) – (part) of spectrum

  • +
  • number_of_peaks (int) –

  • +
+
+
Returns:
+

indices of peaks

+
+
Return type:
+

numpy array

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.find_peaks.html b/_autosummary/pyTEMlib.eels_tools.find_peaks.html new file mode 100644 index 00000000..e98aec52 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.find_peaks.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.find_peaks — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.find_peaks

+
+
+pyTEMlib.eels_tools.find_peaks(dataset, fit_start, fit_end, sensitivity=2)[source]
+

find peaks in spectrum

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.find_white_lines.html b/_autosummary/pyTEMlib.eels_tools.find_white_lines.html new file mode 100644 index 00000000..edeabc3f --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.find_white_lines.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eels_tools.find_white_lines — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.find_white_lines

+
+
+pyTEMlib.eels_tools.find_white_lines(dataset)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.fit_dataset.html b/_autosummary/pyTEMlib.eels_tools.fit_dataset.html new file mode 100644 index 00000000..ee0571c6 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.fit_dataset.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eels_tools.fit_dataset — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.fit_dataset

+
+
+pyTEMlib.eels_tools.fit_dataset(dataset)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.fit_edges.html b/_autosummary/pyTEMlib.eels_tools.fit_edges.html new file mode 100644 index 00000000..f9c4b4cf --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.fit_edges.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.fit_edges — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.fit_edges

+
+
+pyTEMlib.eels_tools.fit_edges(spectrum, energy_scale, region_tags, edges)[source]
+

fit edges for quantification

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.fit_edges2.html b/_autosummary/pyTEMlib.eels_tools.fit_edges2.html new file mode 100644 index 00000000..e3e2d5d2 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.fit_edges2.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.fit_edges2 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.fit_edges2

+
+
+pyTEMlib.eels_tools.fit_edges2(spectrum, energy_scale, edges)[source]
+

fit edges for quantification

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.fit_model.html b/_autosummary/pyTEMlib.eels_tools.fit_model.html new file mode 100644 index 00000000..6a8b81ef --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.fit_model.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.fit_model — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.fit_model

+
+
+pyTEMlib.eels_tools.fit_model(x, y, pin, number_of_peaks, peak_shape, p_zl, restrict_pos=0, restrict_width=0)[source]
+

model for fitting low-loss spectrum

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.fit_peaks.html b/_autosummary/pyTEMlib.eels_tools.fit_peaks.html new file mode 100644 index 00000000..7d9eeb23 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.fit_peaks.html @@ -0,0 +1,142 @@ + + + + + + + pyTEMlib.eels_tools.fit_peaks — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.fit_peaks

+
+
+pyTEMlib.eels_tools.fit_peaks(spectrum, energy_scale, pin, start_fit, end_fit, only_positive_intensity=False)[source]
+

fit peaks to spectrum

+
+
Parameters:
+
    +
  • spectrum (numpy array) – spectrum to be fitted

  • +
  • energy_scale (numpy array) – energy scale of spectrum

  • +
  • pin (list of float) – intial guess of peaks position amplitude width

  • +
  • start_fit (int) – channel where fit starts

  • +
  • end_fit (int) – channel where fit starts

  • +
  • only_positive_intensity (boolean) – allows only for positive amplitudes if True; default = False

  • +
+
+
Returns:
+

p – fitting parameters

+
+
Return type:
+

list of float

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.fix_energy_scale.html b/_autosummary/pyTEMlib.eels_tools.fix_energy_scale.html new file mode 100644 index 00000000..59f15cd2 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.fix_energy_scale.html @@ -0,0 +1,125 @@ + + + + + + + pyTEMlib.eels_tools.fix_energy_scale — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.fix_energy_scale

+
+
+pyTEMlib.eels_tools.fix_energy_scale(spec, energy=None)[source]
+

Shift energy scale according to zero-loss peak position

+

This function assumes that the fzero loss peak is the maximum of the spectrum.

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.gauss.html b/_autosummary/pyTEMlib.eels_tools.gauss.html new file mode 100644 index 00000000..123726b2 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.gauss.html @@ -0,0 +1,128 @@ + + + + + + + pyTEMlib.eels_tools.gauss — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.gauss

+
+
+pyTEMlib.eels_tools.gauss(x, p)[source]
+

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

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.get_energy_shifts.html b/_autosummary/pyTEMlib.eels_tools.get_energy_shifts.html new file mode 100644 index 00000000..0e11af0f --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.get_energy_shifts.html @@ -0,0 +1,125 @@ + + + + + + + pyTEMlib.eels_tools.get_energy_shifts — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.get_energy_shifts

+
+
+pyTEMlib.eels_tools.get_energy_shifts(spectrum_image, energy_scale=None, zero_loss_fit_width=0.3)[source]
+

get shift of spectrum from zero-loss peak position +better to use get resolution_functions

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.get_resolution_functions.html b/_autosummary/pyTEMlib.eels_tools.get_resolution_functions.html new file mode 100644 index 00000000..9f01c7d7 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.get_resolution_functions.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.get_resolution_functions — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.get_resolution_functions

+
+
+pyTEMlib.eels_tools.get_resolution_functions(spectrum_image, energy_scale=None, zero_loss_fit_width=0.3)[source]
+

get resolution_function and shift of spectra form zero-loss peak position

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.get_spectrum_eels_db.html b/_autosummary/pyTEMlib.eels_tools.get_spectrum_eels_db.html new file mode 100644 index 00000000..f6927970 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.get_spectrum_eels_db.html @@ -0,0 +1,126 @@ + + + + + + + pyTEMlib.eels_tools.get_spectrum_eels_db — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.get_spectrum_eels_db

+
+
+pyTEMlib.eels_tools.get_spectrum_eels_db(formula=None, edge=None, title=None, element=None)[source]
+

get spectra from EELS database +chemical formula and edge is accepted. +Could expose more of the search parameters

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.get_wave_length.html b/_autosummary/pyTEMlib.eels_tools.get_wave_length.html new file mode 100644 index 00000000..423ec57d --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.get_wave_length.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.get_wave_length — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.get_wave_length

+
+
+pyTEMlib.eels_tools.get_wave_length(e0)[source]
+

get deBroglie wavelength of electron accelerated by energy (in eV) e0

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.get_x_sections.html b/_autosummary/pyTEMlib.eels_tools.get_x_sections.html new file mode 100644 index 00000000..963cffc9 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.get_x_sections.html @@ -0,0 +1,135 @@ + + + + + + + pyTEMlib.eels_tools.get_x_sections — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.get_x_sections

+
+
+pyTEMlib.eels_tools.get_x_sections(z=0)[source]
+

Reads X-ray fluorescent cross-sections from a pickle file.

+
+
Parameters:
+

z (int) – atomic number if zero all cross-sections will be returned

+
+
Returns:
+

cross-section of an element or of all elements if z = 0

+
+
Return type:
+

dictionary

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.get_z.html b/_autosummary/pyTEMlib.eels_tools.get_z.html new file mode 100644 index 00000000..a5a616af --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.get_z.html @@ -0,0 +1,131 @@ + + + + + + + pyTEMlib.eels_tools.get_z — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.get_z

+
+
+pyTEMlib.eels_tools.get_z(z)[source]
+

Returns the atomic number independent of input as a string or number

+
+

Parameter

+
+
z: int, str

atomic number of chemical symbol (0 if not valid)

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.html b/_autosummary/pyTEMlib.eels_tools.html new file mode 100644 index 00000000..d6c747ef --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.html @@ -0,0 +1,311 @@ + + + + + + + pyTEMlib.eels_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools

+

eels_tools +Model based quantification of electron energy-loss data +Copyright by Gerd Duscher

+

The University of Tennessee, Knoxville +Department of Materials Science & Engineering

+
+
Sources:
    +
  1. Tian et al.

  2. +
+
+
Units:

everything is in SI units, except length is given in nm and angles in mrad.

+
+
Usage:

See the notebooks for examples of these routines

+
+
+

All the input and output is done through a dictionary which is to be found in the meta_data +attribute of the sidpy.Dataset

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

add_element_to_dataset

add_peaks

add peaks to fitting parameters

assign_likely_edges

auto_chemical_composition

auto_id_edges

cl_model

core loss model for fitting

drude

dielectric function according to Drude theory

drude2

dielectric function according to Drude theory for fitting

drude_lorentz

dielectric function according to Drude-Lorentz theory

drude_simulation

probabilities of dielectric function eps relative to zero-loss integral (i0 = 1)

effective_collection_angle

Calculates the effective collection angle in mrad:

find_all_edges

Find all (major and minor) edges within an energy range

find_associated_edges

find_edges

find edges within a sidpy.Dataset

find_major_edges

Find all major edges within an energy range

find_maxima

find the first most prominent peaks

find_peaks

find peaks in spectrum

find_white_lines

fit_dataset

fit_edges

fit edges for quantification

fit_edges2

fit edges for quantification

fit_model

model for fitting low-loss spectrum

fit_peaks

fit peaks to spectrum

fix_energy_scale

Shift energy scale according to zero-loss peak position

gauss

Gaussian Function

get_energy_shifts

get shift of spectrum from zero-loss peak position better to use get resolution_functions

get_resolution_functions

get resolution_function and shift of spectra form zero-loss peak position

get_spectrum_eels_db

get spectra from EELS database chemical formula and edge is accepted.

get_wave_length

get deBroglie wavelength of electron accelerated by energy (in eV) e0

get_x_sections

Reads X-ray fluorescent cross-sections from a pickle file.

get_z

Returns the atomic number independent of input as a string or number

identify_edges

Using first derivative to determine edge onsets Any peak in first derivative higher than noise_level times standard deviation will be considered

kroeger_core

This function calculates the differential scattering probability

kroeger_core2

This function calculates the differential scattering probability

list_all_edges

List all ionization edges of an element with atomic number z

lorentz

lorentzian function

make_cross_sections

Updates the edges dictionary with collection angle-integrated X-ray photo-absorption cross-sections

make_edges

Makes the edges dictionary for quantification

model3

model for fitting low-loss spectrum

model_ll

part of fit

model_smooth

part of fit

plot_dispersion

Plot loss function

power_law

power law for power_law_background

power_law_background

fit of power law to spectrum

read_msa

read msa formated file

residuals_ll

part of fit

residuals_ll2

part of fit

residuals_smooth

part of fit

resolution_function

get resolution function (zero-loss peak shape) from low-loss spectrum

resolution_function2

second_derivative

Calculates second derivative of a sidpy.dataset

set_previous_quantification

Set previous quantification from a sidpy.Dataset

shift_on_same_scale

shift spectrum in energy

sort_peaks

sort fitting parameters by peak position

xsec_xrpa

Calculate momentum-integrated cross-section for EELS from X-ray photo-absorption cross-sections.

zl

zero-loss function

zl_func

zero-loss peak function

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.identify_edges.html b/_autosummary/pyTEMlib.eels_tools.identify_edges.html new file mode 100644 index 00000000..33bd4a1b --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.identify_edges.html @@ -0,0 +1,139 @@ + + + + + + + pyTEMlib.eels_tools.identify_edges — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.identify_edges

+
+
+pyTEMlib.eels_tools.identify_edges(dataset, noise_level=2.0)[source]
+

Using first derivative to determine edge onsets +Any peak in first derivative higher than noise_level times standard deviation will be considered

+
+
Parameters:
+
    +
  • dataset (sidpy.Dataset) – the spectrum

  • +
  • noise_level (float) – ths number times standard deviation in first derivative decides on whether an edge onset is significant

  • +
+
+
Returns:
+

edge_channel

+
+
Return type:
+

numpy.ndarray

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.kroeger_core.html b/_autosummary/pyTEMlib.eels_tools.kroeger_core.html new file mode 100644 index 00000000..5ffdae6c --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.kroeger_core.html @@ -0,0 +1,149 @@ + + + + + + + pyTEMlib.eels_tools.kroeger_core — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.kroeger_core

+
+
+pyTEMlib.eels_tools.kroeger_core(e_data, a_data, eps_data, ee, thick, relativistic=True)[source]
+

This function calculates the differential scattering probability

+
+
+\[\frac{d^2P}{d \Omega d_e}\]
+
+

of the low-loss region for total loss and volume plasmon loss

+
+
Parameters:
+
    +
  • e_data (array) – energy scale [eV]

  • +
  • a_data (array) – angle or momentum range [rad]

  • +
  • eps_data (array) – dielectric function data

  • +
  • ee (float) – acceleration voltage [keV]

  • +
  • thick (float) – thickness in m

  • +
  • relativistic – boolean include relativistic corrections

  • +
+
+
Returns:
+

total loss probability +p_vol (numpy array 2d): volume loss probability

+
+
Return type:
+

P (numpy array 2d)

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.kroeger_core2.html b/_autosummary/pyTEMlib.eels_tools.kroeger_core2.html new file mode 100644 index 00000000..1c27ba55 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.kroeger_core2.html @@ -0,0 +1,151 @@ + + + + + + + pyTEMlib.eels_tools.kroeger_core2 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.kroeger_core2

+
+
+pyTEMlib.eels_tools.kroeger_core2(e_data, a_data, eps_data, acceleration_voltage_kev, thickness, relativistic=True)[source]
+

This function calculates the differential scattering probability

+
+
+\[\frac{d^2P}{d \Omega d_e}\]
+
+

of the low-loss region for total loss and volume plasmon loss

+
+
Parameters:
+
    +
  • e_data (array) – energy scale [eV]

  • +
  • a_data (array) – angle or momentum range [rad]

  • +
  • eps_data (array) –

  • +
  • acceleration_voltage_kev (float) – acceleration voltage [keV]

  • +
  • thickness (float) – thickness in nm

  • +
  • relativistic (boolean) – relativistic correction

  • +
+
+
Returns:
+

total loss probability +p_vol (numpy array 2d): volume loss probability

+

return P, P*scale*1e2,p_vol*1e2, p_simple*1e2

+

+
+
Return type:
+

P (numpy array 2d)

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.list_all_edges.html b/_autosummary/pyTEMlib.eels_tools.list_all_edges.html new file mode 100644 index 00000000..325ac456 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.list_all_edges.html @@ -0,0 +1,135 @@ + + + + + + + pyTEMlib.eels_tools.list_all_edges — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.list_all_edges

+
+
+pyTEMlib.eels_tools.list_all_edges(z, verbose=False)[source]
+

List all ionization edges of an element with atomic number z

+
+
Parameters:
+

z (int) – atomic number

+
+
Returns:
+

out_string – string with all major edges in energy range

+
+
Return type:
+

str

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.lorentz.html b/_autosummary/pyTEMlib.eels_tools.lorentz.html new file mode 100644 index 00000000..4520eeb7 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.lorentz.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.lorentz — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.lorentz

+
+
+pyTEMlib.eels_tools.lorentz(x, p)[source]
+

lorentzian function

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.make_cross_sections.html b/_autosummary/pyTEMlib.eels_tools.make_cross_sections.html new file mode 100644 index 00000000..acd099ec --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.make_cross_sections.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.make_cross_sections — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.make_cross_sections

+
+
+pyTEMlib.eels_tools.make_cross_sections(edges, energy_scale, e_0, coll_angle, low_loss=None)[source]
+

Updates the edges dictionary with collection angle-integrated X-ray photo-absorption cross-sections

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.make_edges.html b/_autosummary/pyTEMlib.eels_tools.make_edges.html new file mode 100644 index 00000000..2478bde0 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.make_edges.html @@ -0,0 +1,141 @@ + + + + + + + pyTEMlib.eels_tools.make_edges — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.make_edges

+
+
+pyTEMlib.eels_tools.make_edges(edges_present, energy_scale, e_0, coll_angle, low_loss=None)[source]
+

Makes the edges dictionary for quantification

+
+
Parameters:
+
    +
  • edges_present (list) – list of edges

  • +
  • energy_scale (numpy array) – energy scale on which to make cross-section

  • +
  • e_0 (float) – acceleration voltage (in V)

  • +
  • coll_angle (float) – collection angle in mrad

  • +
  • low_loss (numpy array with same length as energy_scale) – low_less spectrum with which to convolve the cross-section (default=None)

  • +
+
+
Returns:
+

edges – dictionary with all information on cross-section

+
+
Return type:
+

dict

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.model3.html b/_autosummary/pyTEMlib.eels_tools.model3.html new file mode 100644 index 00000000..9bdbff81 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.model3.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.model3 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.model3

+
+
+pyTEMlib.eels_tools.model3(x, p, number_of_peaks, peak_shape, p_zl, pin=None, restrict_pos=0, restrict_width=0)[source]
+

model for fitting low-loss spectrum

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.model_ll.html b/_autosummary/pyTEMlib.eels_tools.model_ll.html new file mode 100644 index 00000000..5cc79fb1 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.model_ll.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.model_ll — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.model_ll

+
+
+pyTEMlib.eels_tools.model_ll(x, p, only_positive_intensity)[source]
+

part of fit

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.model_smooth.html b/_autosummary/pyTEMlib.eels_tools.model_smooth.html new file mode 100644 index 00000000..8311e49c --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.model_smooth.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.model_smooth — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.model_smooth

+
+
+pyTEMlib.eels_tools.model_smooth(x, p, only_positive_intensity=False)[source]
+

part of fit

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.plot_dispersion.html b/_autosummary/pyTEMlib.eels_tools.plot_dispersion.html new file mode 100644 index 00000000..cdc6be8a --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.plot_dispersion.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.plot_dispersion — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.plot_dispersion

+
+
+pyTEMlib.eels_tools.plot_dispersion(plotdata, units, a_data, e_data, title, max_p, ee, ef=4.0, ep=16.8, es=0, ibt=[])[source]
+

Plot loss function

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.power_law.html b/_autosummary/pyTEMlib.eels_tools.power_law.html new file mode 100644 index 00000000..23830a3b --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.power_law.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.power_law — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.power_law

+
+
+pyTEMlib.eels_tools.power_law(energy, a, r)[source]
+

power law for power_law_background

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.power_law_background.html b/_autosummary/pyTEMlib.eels_tools.power_law_background.html new file mode 100644 index 00000000..3c461373 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.power_law_background.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.power_law_background — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.power_law_background

+
+
+pyTEMlib.eels_tools.power_law_background(spectrum, energy_scale, fit_area, verbose=False)[source]
+

fit of power law to spectrum

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.read_msa.html b/_autosummary/pyTEMlib.eels_tools.read_msa.html new file mode 100644 index 00000000..c52d7398 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.read_msa.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.read_msa — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.read_msa

+
+
+pyTEMlib.eels_tools.read_msa(msa_string)[source]
+

read msa formated file

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.residuals_ll.html b/_autosummary/pyTEMlib.eels_tools.residuals_ll.html new file mode 100644 index 00000000..d9861296 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.residuals_ll.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.residuals_ll — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.residuals_ll

+
+
+pyTEMlib.eels_tools.residuals_ll(p, x, y, only_positive_intensity)[source]
+

part of fit

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.residuals_ll2.html b/_autosummary/pyTEMlib.eels_tools.residuals_ll2.html new file mode 100644 index 00000000..896e5a96 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.residuals_ll2.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.residuals_ll2 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.residuals_ll2

+
+
+pyTEMlib.eels_tools.residuals_ll2(p, x, y, only_positive_intensity)[source]
+

part of fit

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.residuals_smooth.html b/_autosummary/pyTEMlib.eels_tools.residuals_smooth.html new file mode 100644 index 00000000..77be3700 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.residuals_smooth.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.residuals_smooth — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.residuals_smooth

+
+
+pyTEMlib.eels_tools.residuals_smooth(p, x, y, only_positive_intensity)[source]
+

part of fit

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.resolution_function.html b/_autosummary/pyTEMlib.eels_tools.resolution_function.html new file mode 100644 index 00000000..1bc5685a --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.resolution_function.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.resolution_function — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.resolution_function

+
+
+pyTEMlib.eels_tools.resolution_function(energy_scale, spectrum, width, verbose=False)[source]
+

get resolution function (zero-loss peak shape) from low-loss spectrum

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.resolution_function2.html b/_autosummary/pyTEMlib.eels_tools.resolution_function2.html new file mode 100644 index 00000000..3e7973db --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.resolution_function2.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.eels_tools.resolution_function2 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.resolution_function2

+
+
+pyTEMlib.eels_tools.resolution_function2(dataset, width=0.3)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.second_derivative.html b/_autosummary/pyTEMlib.eels_tools.second_derivative.html new file mode 100644 index 00000000..e40f9a4e --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.second_derivative.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.second_derivative — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.second_derivative

+
+
+pyTEMlib.eels_tools.second_derivative(dataset, sensitivity)[source]
+

Calculates second derivative of a sidpy.dataset

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.set_previous_quantification.html b/_autosummary/pyTEMlib.eels_tools.set_previous_quantification.html new file mode 100644 index 00000000..a405038c --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.set_previous_quantification.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.set_previous_quantification — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.set_previous_quantification

+
+
+pyTEMlib.eels_tools.set_previous_quantification(current_dataset)[source]
+

Set previous quantification from a sidpy.Dataset

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.shift_on_same_scale.html b/_autosummary/pyTEMlib.eels_tools.shift_on_same_scale.html new file mode 100644 index 00000000..ce266f57 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.shift_on_same_scale.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.shift_on_same_scale — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.shift_on_same_scale

+
+
+pyTEMlib.eels_tools.shift_on_same_scale(spectrum_image, shifts=None, energy_scale=None, master_energy_scale=None)[source]
+

shift spectrum in energy

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.sort_peaks.html b/_autosummary/pyTEMlib.eels_tools.sort_peaks.html new file mode 100644 index 00000000..286a7669 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.sort_peaks.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.sort_peaks — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.sort_peaks

+
+
+pyTEMlib.eels_tools.sort_peaks(p, peak_shape)[source]
+

sort fitting parameters by peak position

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.xsec_xrpa.html b/_autosummary/pyTEMlib.eels_tools.xsec_xrpa.html new file mode 100644 index 00000000..0de4da65 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.xsec_xrpa.html @@ -0,0 +1,137 @@ + + + + + + + pyTEMlib.eels_tools.xsec_xrpa — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.xsec_xrpa

+
+
+pyTEMlib.eels_tools.xsec_xrpa(energy_scale, e0, z, beta, shift=0)[source]
+

Calculate momentum-integrated cross-section for EELS from X-ray photo-absorption cross-sections.

+

X-ray photo-absorption cross-sections from NIST. +Momentum-integrated cross-section for EELS according to Egerton Ultramicroscopy 50 (1993) 13-28 equation (4)

+
+
Parameters:
+
    +
  • energy_scale (numpy array) – energy scale of spectrum to be analyzed

  • +
  • e0 (float) – acceleration voltage in keV

  • +
  • z (int) – atomic number of element

  • +
  • beta (float) – effective collection angle in mrad

  • +
  • shift (float) – chemical shift of edge in eV

  • +
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.zl.html b/_autosummary/pyTEMlib.eels_tools.zl.html new file mode 100644 index 00000000..4a714ae3 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.zl.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.zl — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.zl

+
+
+pyTEMlib.eels_tools.zl(x, p, p_zl)[source]
+

zero-loss function

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.eels_tools.zl_func.html b/_autosummary/pyTEMlib.eels_tools.zl_func.html new file mode 100644 index 00000000..20f69474 --- /dev/null +++ b/_autosummary/pyTEMlib.eels_tools.zl_func.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.eels_tools.zl_func — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.eels_tools.zl_func

+
+
+pyTEMlib.eels_tools.zl_func(p, x)[source]
+

zero-loss peak function

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.ChooseDataset.html b/_autosummary/pyTEMlib.file_tools.ChooseDataset.html new file mode 100644 index 00000000..9d1c2530 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.ChooseDataset.html @@ -0,0 +1,142 @@ + + + + + + + pyTEMlib.file_tools.ChooseDataset — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.ChooseDataset

+
+
+class pyTEMlib.file_tools.ChooseDataset(input_object, show_dialog=True)[source]
+

Bases: object

+

Widget to select dataset object

+

Methods

+ + + + + + + + + +

get_dataset_list

Get by Log number sorted list of datasets

set_dataset

+
+
+get_dataset_list()[source]
+

Get by Log number sorted list of datasets

+
+ +
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.FileWidget.html b/_autosummary/pyTEMlib.file_tools.FileWidget.html new file mode 100644 index 00000000..b9f1f5a9 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.FileWidget.html @@ -0,0 +1,197 @@ + + + + + + + pyTEMlib.file_tools.FileWidget — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.FileWidget

+
+
+class pyTEMlib.file_tools.FileWidget(dir_name=None, extension=['*'])[source]
+

Bases: object

+

Widget to select directories or widgets from a list

+

Works in google colab. +The widget converts the name of the nion file to the one in Nion’s swift software, +because it is otherwise incomprehensible

+
+
+dir_name
+

name of starting directory

+
+
Type:
+

str

+
+
+
+ +
+
+extension
+

extensions of files to be listed in widget

+
+
Type:
+

list of str

+
+
+
+ +
+
+get_directory()[source]
+
+ +
+
+set_options()[source]
+
+ +
+
+get_file_name()[source]
+
+ +

Example

+

>>from google.colab import drive +>>drive.mount(“/content/drive”) +>>file_list = pyTEMlib.file_tools.FileWidget() +next code cell: +>>dataset = pyTEMlib.file_tools.open_file(file_list.file_name)

+

Methods

+ + + + + + + + + + + + + + + + + + + + + + + + +

add_dataset

get_directory

get_file_name

select_main

selected_dataset

set_dir

set_options

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.add_dataset_from_file.html b/_autosummary/pyTEMlib.file_tools.add_dataset_from_file.html new file mode 100644 index 00000000..854ff1d0 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.add_dataset_from_file.html @@ -0,0 +1,139 @@ + + + + + + + pyTEMlib.file_tools.add_dataset_from_file — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.add_dataset_from_file

+
+
+pyTEMlib.file_tools.add_dataset_from_file(datasets, filename=None, key_name='Log', single_dataset=True)[source]
+

Add dataset to datasets dictionary

+
+
Parameters:
+
    +
  • dataset (dict) – dictionary to write to file

  • +
  • filename (str, default: None,) – name of file to open, if None, adialog will appear

  • +
  • key_name (str, default: 'Log') – name for key in dictionary with running number being added

  • +
+
+
Returns:
+

key_name – actual last used name of dictionary key

+
+
Return type:
+

str

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.add_to_dict.html b/_autosummary/pyTEMlib.file_tools.add_to_dict.html new file mode 100644 index 00000000..f6b492e2 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.add_to_dict.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.file_tools.add_to_dict — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.add_to_dict

+
+
+pyTEMlib.file_tools.add_to_dict(file_dict, name)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.get_h5_filename.html b/_autosummary/pyTEMlib.file_tools.get_h5_filename.html new file mode 100644 index 00000000..50d8bf66 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.get_h5_filename.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.file_tools.get_h5_filename — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.get_h5_filename

+
+
+pyTEMlib.file_tools.get_h5_filename(fname)[source]
+

Determines file name of hdf5 file for newly converted data file

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.get_last_path.html b/_autosummary/pyTEMlib.file_tools.get_last_path.html new file mode 100644 index 00000000..dd326968 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.get_last_path.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.file_tools.get_last_path — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.get_last_path

+
+
+pyTEMlib.file_tools.get_last_path()[source]
+

Returns the path of the file last opened

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.get_main_channel.html b/_autosummary/pyTEMlib.file_tools.get_main_channel.html new file mode 100644 index 00000000..813be40e --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.get_main_channel.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.file_tools.get_main_channel — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.get_main_channel

+
+
+pyTEMlib.file_tools.get_main_channel(h5_file)[source]
+

Returns name of first channel group in hdf5-file

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.get_start_channel.html b/_autosummary/pyTEMlib.file_tools.get_start_channel.html new file mode 100644 index 00000000..d36abd8a --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.get_start_channel.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.file_tools.get_start_channel — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.get_start_channel

+
+
+pyTEMlib.file_tools.get_start_channel(h5_file)[source]
+

Legacy for get start channel

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.h5_add_crystal_structure.html b/_autosummary/pyTEMlib.file_tools.h5_add_crystal_structure.html new file mode 100644 index 00000000..b2e84570 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.h5_add_crystal_structure.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.file_tools.h5_add_crystal_structure — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.h5_add_crystal_structure

+
+
+pyTEMlib.file_tools.h5_add_crystal_structure(h5_file, input_structure, name=None)[source]
+

Write crystal structure to NSID file

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.h5_add_to_structure.html b/_autosummary/pyTEMlib.file_tools.h5_add_to_structure.html new file mode 100644 index 00000000..d92f87bf --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.h5_add_to_structure.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.file_tools.h5_add_to_structure — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.h5_add_to_structure

+
+
+pyTEMlib.file_tools.h5_add_to_structure(structure_group, crystal_tags)[source]
+

add dictionary as structure group

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.h5_get_crystal_structure.html b/_autosummary/pyTEMlib.file_tools.h5_get_crystal_structure.html new file mode 100644 index 00000000..c5fdd805 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.h5_get_crystal_structure.html @@ -0,0 +1,136 @@ + + + + + + + pyTEMlib.file_tools.h5_get_crystal_structure — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.h5_get_crystal_structure

+
+
+pyTEMlib.file_tools.h5_get_crystal_structure(structure_group)[source]
+

Read crystal structure from NSID file +Any additional information will be read as dictionary into the info attribute of the ase.Atoms object

+
+
Parameters:
+

structure_group (h5py.Group) – location in hdf5 file to where the structure information is stored

+
+
Returns:
+

atoms – crystal structure in ase format

+
+
Return type:
+

ase.Atoms object

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.h5_group_to_dict.html b/_autosummary/pyTEMlib.file_tools.h5_group_to_dict.html new file mode 100644 index 00000000..284c4f3f --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.h5_group_to_dict.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.file_tools.h5_group_to_dict — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.h5_group_to_dict

+
+
+pyTEMlib.file_tools.h5_group_to_dict(group, group_dict={})[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.h5_tree.html b/_autosummary/pyTEMlib.file_tools.h5_tree.html new file mode 100644 index 00000000..72b15462 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.h5_tree.html @@ -0,0 +1,125 @@ + + + + + + + pyTEMlib.file_tools.h5_tree — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.h5_tree

+
+
+pyTEMlib.file_tools.h5_tree(input_object)[source]
+

Just a wrapper for the sidpy function print_tree,

+

so that sidpy does not have to be loaded in notebook

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.html b/_autosummary/pyTEMlib.file_tools.html new file mode 100644 index 00000000..0e2fc3c7 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.html @@ -0,0 +1,223 @@ + + + + + + + pyTEMlib.file_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools

+

file_tools: All tools to load and save data

+
+
+

2018 01 31 Included Nion Swift files to be opened +major revision 2020 09 to include sidpy and pyNSID data formats +2022 change to ase format for structures: this changed the default unit of length to Angstrom!!!

+
+
+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

add_dataset_from_file

Add dataset to datasets dictionary

add_to_dict

get_h5_filename

Determines file name of hdf5 file for newly converted data file

get_last_path

Returns the path of the file last opened

get_main_channel

Returns name of first channel group in hdf5-file

get_start_channel

Legacy for get start channel

h5_add_crystal_structure

Write crystal structure to NSID file

h5_add_to_structure

add dictionary as structure group

h5_get_crystal_structure

Read crystal structure from NSID file Any additional information will be read as dictionary into the info attribute of the ase.Atoms object

h5_group_to_dict

h5_tree

Just a wrapper for the sidpy function print_tree,

log_results

Log Results in hdf5-file

open_file

Opens a file if the extension is .hf5, .ndata, .dm3 or .dm4

open_file_dialog_qt

Opens a File dialog which is used in open_file() function

read_cif

Open a cif file If no file name is provided an open file dialog to select a cif file appears

read_dm3_info

Read essential parameter from original_metadata originating from a dm3 file

read_essential_metadata

Updates dataset.metadata['experiment'] with essential information read from original metadata

read_nion_image_info

Read essential parameter from original_metadata originating from a dm3 file

read_old_h5group

Make a sidpy.Dataset from pyUSID style hdf5 group

read_poscar

Open a POSCAR file from Vasp If no file name is provided an open file dialog to select a POSCAR file appears

save_dataset

Saves a dataset to a file in pyNSID format :param dataset: the data :type dataset: sidpy.Dataset :param filename: name of file to be opened, if filename is None, a QT file dialog will try to open :type filename: str :param h5_group: not used yet :type h5_group: hd5py.Group

save_dataset_dictionary

save_file_dialog_qt

Opens a File dialog which is used in open_file() function

save_path

Save path of last opened file

save_single_dataset

set_dimensions

Attaches correct dimension from old pyTEMlib style.

update_directory_list

+

Classes

+ + + + + + + + + +

ChooseDataset

Widget to select dataset object

FileWidget

Widget to select directories or widgets from a list

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.log_results.html b/_autosummary/pyTEMlib.file_tools.log_results.html new file mode 100644 index 00000000..f1072100 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.log_results.html @@ -0,0 +1,142 @@ + + + + + + + pyTEMlib.file_tools.log_results — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.log_results

+
+
+pyTEMlib.file_tools.log_results(h5_group, dataset=None, attributes=None)[source]
+

Log Results in hdf5-file

+

Saves either a sidpy.Dataset or dictionary in a hdf5-file. +The group for the result will consist of ‘Log_’ and a running index. +That group will be placed in h5_group.

+
+
Parameters:
+
    +
  • h5_group (hd5py.Group, or sidpy.Dataset) – groups where result group are to be stored

  • +
  • dataset (sidpy.Dataset or None) – sidpy dataset to be stored

  • +
  • attributes (dict) – dictionary containing results that are not based on a sidpy.Dataset

  • +
+
+
Returns:
+

log_group – group in hdf5 file with results.

+
+
Return type:
+

hd5py.Group

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.open_file.html b/_autosummary/pyTEMlib.file_tools.open_file.html new file mode 100644 index 00000000..507196d9 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.open_file.html @@ -0,0 +1,155 @@ + + + + + + + pyTEMlib.file_tools.open_file — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.open_file

+
+
+pyTEMlib.file_tools.open_file(filename=None, h5_group=None, write_hdf_file=False)[source]
+

Opens a file if the extension is .hf5, .ndata, .dm3 or .dm4

+

If no filename is provided the QT open_file windows opens (if QT_available==True) +Everything will be stored in a NSID style hf5 file. +Subroutines used:

+
+
    +
  • NSIDReader

  • +
  • +
    nsid.write_
      +
    • get_main_tags

    • +
    • get_additional tags

    • +
    +
    +
    +
  • +
+
+
+
Parameters:
+
    +
  • filename (str) – name of file to be opened, if filename is None, a QT file dialog will try to open

  • +
  • h5_group (hd5py.Group) – not used yet #TODO: provide hook for usage of external chosen group

  • +
  • write_hdf_file (bool) – set to false so that sidpy dataset will not be written to hf5-file automatically

  • +
+
+
Returns:
+

sidpy dataset with location of hdf5 dataset as attribute

+
+
Return type:
+

sidpy.Dataset

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.open_file_dialog_qt.html b/_autosummary/pyTEMlib.file_tools.open_file_dialog_qt.html new file mode 100644 index 00000000..02d48d1f --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.open_file_dialog_qt.html @@ -0,0 +1,143 @@ + + + + + + + pyTEMlib.file_tools.open_file_dialog_qt — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.open_file_dialog_qt

+
+
+pyTEMlib.file_tools.open_file_dialog_qt(file_types=None)[source]
+

Opens a File dialog which is used in open_file() function

+

This function uses pyQt5. +The app of the Gui has to be running for QT. Tkinter does not run on Macs at this point in time. +In jupyter notebooks use %gui Qt early in the notebook.

+

The file looks first for a path.txt file for the last directory you used.

+
+
Parameters:
+

file_types (string) – file type filter in the form of ‘*.hf5’

+
+
Returns:
+

filename – full filename with absolute path and extension as a string

+
+
Return type:
+

string

+
+
+

Example

+

>> import file_tools as ft +>> filename = ft.openfile_dialog() +>> print(filename)

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.read_cif.html b/_autosummary/pyTEMlib.file_tools.read_cif.html new file mode 100644 index 00000000..10badc11 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.read_cif.html @@ -0,0 +1,139 @@ + + + + + + + pyTEMlib.file_tools.read_cif — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.read_cif

+
+
+pyTEMlib.file_tools.read_cif(file_name=None, verbose=False)[source]
+

Open a cif file +If no file name is provided an open file dialog to select a cif file appears

+
+
Parameters:
+
    +
  • file_name (str) – if None is provided an open file dialog will appear

  • +
  • verbose (bool) –

  • +
+
+
Returns:
+

crystal – crystal structure in ase format

+
+
Return type:
+

ase.Atoms

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.read_dm3_info.html b/_autosummary/pyTEMlib.file_tools.read_dm3_info.html new file mode 100644 index 00000000..30413755 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.read_dm3_info.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.file_tools.read_dm3_info — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.read_dm3_info

+
+
+pyTEMlib.file_tools.read_dm3_info(original_metadata)[source]
+

Read essential parameter from original_metadata originating from a dm3 file

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.read_essential_metadata.html b/_autosummary/pyTEMlib.file_tools.read_essential_metadata.html new file mode 100644 index 00000000..c78562d3 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.read_essential_metadata.html @@ -0,0 +1,125 @@ + + + + + + + pyTEMlib.file_tools.read_essential_metadata — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.read_essential_metadata

+
+
+pyTEMlib.file_tools.read_essential_metadata(dataset)[source]
+

Updates dataset.metadata[‘experiment’] with essential information read from original metadata

+

This depends on whether it is originally a nion or a dm3 file

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.read_nion_image_info.html b/_autosummary/pyTEMlib.file_tools.read_nion_image_info.html new file mode 100644 index 00000000..b3956336 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.read_nion_image_info.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.file_tools.read_nion_image_info — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.read_nion_image_info

+
+
+pyTEMlib.file_tools.read_nion_image_info(original_metadata)[source]
+

Read essential parameter from original_metadata originating from a dm3 file

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.read_old_h5group.html b/_autosummary/pyTEMlib.file_tools.read_old_h5group.html new file mode 100644 index 00000000..5e3d06fb --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.read_old_h5group.html @@ -0,0 +1,132 @@ + + + + + + + pyTEMlib.file_tools.read_old_h5group — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.read_old_h5group

+
+
+pyTEMlib.file_tools.read_old_h5group(current_channel)[source]
+

Make a sidpy.Dataset from pyUSID style hdf5 group

+
+
Parameters:
+

current_channel (h5_group) –

+
+
Return type:
+

sidpy.Dataset

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.read_poscar.html b/_autosummary/pyTEMlib.file_tools.read_poscar.html new file mode 100644 index 00000000..a6571c58 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.read_poscar.html @@ -0,0 +1,136 @@ + + + + + + + pyTEMlib.file_tools.read_poscar — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.read_poscar

+
+
+pyTEMlib.file_tools.read_poscar(file_name=None)[source]
+

Open a POSCAR file from Vasp +If no file name is provided an open file dialog to select a POSCAR file appears

+
+
Parameters:
+

file_name (str) – if None is provided an open file dialog will appear

+
+
Returns:
+

crystal – crystal structure in ase format

+
+
Return type:
+

ase.Atoms

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.save_dataset.html b/_autosummary/pyTEMlib.file_tools.save_dataset.html new file mode 100644 index 00000000..ffbba66c --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.save_dataset.html @@ -0,0 +1,130 @@ + + + + + + + pyTEMlib.file_tools.save_dataset — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.save_dataset

+
+
+pyTEMlib.file_tools.save_dataset(dataset, filename=None, h5_group=None)[source]
+

Saves a dataset to a file in pyNSID format +:param dataset: the data +:type dataset: sidpy.Dataset +:param filename: name of file to be opened, if filename is None, a QT file dialog will try to open +:type filename: str +:param h5_group: not used yet +:type h5_group: hd5py.Group

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.save_dataset_dictionary.html b/_autosummary/pyTEMlib.file_tools.save_dataset_dictionary.html new file mode 100644 index 00000000..ea8a6470 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.save_dataset_dictionary.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.file_tools.save_dataset_dictionary — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.save_dataset_dictionary

+
+
+pyTEMlib.file_tools.save_dataset_dictionary(h5_file, datasets)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.save_file_dialog_qt.html b/_autosummary/pyTEMlib.file_tools.save_file_dialog_qt.html new file mode 100644 index 00000000..4cd02ccf --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.save_file_dialog_qt.html @@ -0,0 +1,143 @@ + + + + + + + pyTEMlib.file_tools.save_file_dialog_qt — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.save_file_dialog_qt

+
+
+pyTEMlib.file_tools.save_file_dialog_qt(file_types=None)[source]
+

Opens a File dialog which is used in open_file() function

+

This function uses pyQt5. +The app of the Gui has to be running for QT. Tkinter does not run on Macs at this point in time. +In jupyter notebooks use %gui Qt early in the notebook.

+

The file looks first for a path.txt file for the last directory you used.

+
+
Parameters:
+

file_types (string) – file type filter in the form of ‘*.hf5’

+
+
Returns:
+

filename – full filename with absolute path and extension as a string

+
+
Return type:
+

string

+
+
+

Example

+

>> import file_tools as ft +>> filename = ft.openfile_dialog() +>> print(filename)

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.save_path.html b/_autosummary/pyTEMlib.file_tools.save_path.html new file mode 100644 index 00000000..3e318de4 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.save_path.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.file_tools.save_path — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.save_path

+
+
+pyTEMlib.file_tools.save_path(filename)[source]
+

Save path of last opened file

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.save_single_dataset.html b/_autosummary/pyTEMlib.file_tools.save_single_dataset.html new file mode 100644 index 00000000..17bbec27 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.save_single_dataset.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.file_tools.save_single_dataset — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.save_single_dataset

+
+
+pyTEMlib.file_tools.save_single_dataset(h5_file, dataset, h5_group=None)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.set_dimensions.html b/_autosummary/pyTEMlib.file_tools.set_dimensions.html new file mode 100644 index 00000000..9de50252 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.set_dimensions.html @@ -0,0 +1,132 @@ + + + + + + + pyTEMlib.file_tools.set_dimensions — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.set_dimensions

+
+
+pyTEMlib.file_tools.set_dimensions(dset, current_channel)[source]
+

Attaches correct dimension from old pyTEMlib style.

+
+
Parameters:
+
    +
  • dset (sidpy.Dataset) –

  • +
  • current_channel (hdf5.Group) –

  • +
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools.update_directory_list.html b/_autosummary/pyTEMlib.file_tools.update_directory_list.html new file mode 100644 index 00000000..b73ac954 --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools.update_directory_list.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.file_tools.update_directory_list — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools.update_directory_list

+
+
+pyTEMlib.file_tools.update_directory_list(directory_name)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.file_tools_qt.html b/_autosummary/pyTEMlib.file_tools_qt.html new file mode 100644 index 00000000..642ff76c --- /dev/null +++ b/_autosummary/pyTEMlib.file_tools_qt.html @@ -0,0 +1,118 @@ + + + + + + + pyTEMlib.file_tools_qt — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.file_tools_qt

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.breadth_first_search.html b/_autosummary/pyTEMlib.graph_tools.breadth_first_search.html new file mode 100644 index 00000000..26bf8984 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.breadth_first_search.html @@ -0,0 +1,142 @@ + + + + + + + pyTEMlib.graph_tools.breadth_first_search — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ + + + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.circum_center.html b/_autosummary/pyTEMlib.graph_tools.circum_center.html new file mode 100644 index 00000000..352db275 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.circum_center.html @@ -0,0 +1,144 @@ + + + + + + + pyTEMlib.graph_tools.circum_center — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.circum_center

+
+
+pyTEMlib.graph_tools.circum_center(vertex_pos, tol=0.0001)[source]
+

Function finds the center and the radius of the circumsphere of every simplex. +Reference: +Fiedler, Miroslav. Matrices and graphs in geometry. No. 139. Cambridge University Press, 2011. +(p.29 bottom: example 2.1.11) +Code started from https://github.com/spatala/gbpy +with help of https://codereview.stackexchange.com/questions/77593/calculating-the-volume-of-a-tetrahedron

+
+
Parameters:
+
    +
  • vertex_pos (numpy array) – The position of vertices of a tetrahedron

  • +
  • tol (float) – Tolerance defined to identify co-planar tetrahedrons

  • +
+
+
Returns:
+

    +
  • circum_center (numpy array) – The center of the circumsphere

  • +
  • circum_radius (float) – The radius of the circumsphere

  • +
+

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.find_interstitial_clusters.html b/_autosummary/pyTEMlib.graph_tools.find_interstitial_clusters.html new file mode 100644 index 00000000..15763553 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.find_interstitial_clusters.html @@ -0,0 +1,125 @@ + + + + + + + pyTEMlib.graph_tools.find_interstitial_clusters — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.find_interstitial_clusters

+
+
+pyTEMlib.graph_tools.find_interstitial_clusters(overlapping_pairs)[source]
+

Make clusters +Breadth first search to go through the list of overlapping spheres or circles to determine clusters

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.find_overlapping_spheres.html b/_autosummary/pyTEMlib.graph_tools.find_overlapping_spheres.html new file mode 100644 index 00000000..66a9d2b5 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.find_overlapping_spheres.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.graph_tools.find_overlapping_spheres — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.find_overlapping_spheres

+
+
+pyTEMlib.graph_tools.find_overlapping_spheres(voronoi_vertices, r_vv, r_a, cheat=1.0)[source]
+

Find overlapping spheres

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.find_polyhedra.html b/_autosummary/pyTEMlib.graph_tools.find_polyhedra.html new file mode 100644 index 00000000..d4466cd4 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.find_polyhedra.html @@ -0,0 +1,149 @@ + + + + + + + pyTEMlib.graph_tools.find_polyhedra — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.find_polyhedra

+
+
+pyTEMlib.graph_tools.find_polyhedra(atoms, optimize=True, cheat=1.0, bond_radii=None)[source]
+

get polyhedra information from an ase.Atoms object

+

This is following the method of Banadaki and Patala +http://dx.doi.org/10.1038/s41524-017-0016-0

+
+
We are using the bond radius according to Kirkland, which is tabulated in
    +
  • pyTEMlib.crystal_tools.electronFF[atoms.symbols[vert]][‘bond_length’][1]

  • +
+
+
+
+

Parameter

+
+
atoms: ase.Atoms object

the structural information

+
+
cheat: float

does not exist

+
+
+
+
returns:
+

polyhedra – dictionary with all information of polyhedra

+
+
rtype:
+

dict

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.get_bond_radii.html b/_autosummary/pyTEMlib.graph_tools.get_bond_radii.html new file mode 100644 index 00000000..d0d25ae2 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.get_bond_radii.html @@ -0,0 +1,134 @@ + + + + + + + pyTEMlib.graph_tools.get_bond_radii — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.get_bond_radii

+
+
+pyTEMlib.graph_tools.get_bond_radii(atoms, bond_type='bond')[source]
+

get all bond radii from Kirkland +Parameter: +———- +atoms ase.Atoms object

+
+

structure information in ase format

+
+
+
type: str

type of bond ‘covalent’ or ‘metallic’

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.get_bonds.html b/_autosummary/pyTEMlib.graph_tools.get_bonds.html new file mode 100644 index 00000000..a318cd87 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.get_bonds.html @@ -0,0 +1,131 @@ + + + + + + + pyTEMlib.graph_tools.get_bonds — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.get_bonds

+
+
+pyTEMlib.graph_tools.get_bonds(crystal, shift=0.0, verbose=False, cheat=1.0)[source]
+

Get polyhedra, and bonds from and edges and lengths of edges for each polyhedron and store it in info dictionary of new ase.Atoms object

+
+

Parameter:

+
+
crystal: ase.atoms_object

information on all polyhedra

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.get_connectivity_matrix.html b/_autosummary/pyTEMlib.graph_tools.get_connectivity_matrix.html new file mode 100644 index 00000000..32e89073 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.get_connectivity_matrix.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.graph_tools.get_connectivity_matrix — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.get_connectivity_matrix

+
+
+pyTEMlib.graph_tools.get_connectivity_matrix(crystal, atoms, polyhedra)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.get_distortion_matrix.html b/_autosummary/pyTEMlib.graph_tools.get_distortion_matrix.html new file mode 100644 index 00000000..052b1993 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.get_distortion_matrix.html @@ -0,0 +1,125 @@ + + + + + + + pyTEMlib.graph_tools.get_distortion_matrix — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.get_distortion_matrix

+
+
+pyTEMlib.graph_tools.get_distortion_matrix(atoms, ideal_lattice)[source]
+

Calculates distortion matrix

+

Calculates the distortion matrix by comparing ideal and distorted Voronoi tiles

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.get_maximum_view.html b/_autosummary/pyTEMlib.graph_tools.get_maximum_view.html new file mode 100644 index 00000000..63d8b005 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.get_maximum_view.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.graph_tools.get_maximum_view — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.get_maximum_view

+
+
+pyTEMlib.graph_tools.get_maximum_view(distortion_matrix)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.get_non_periodic_supercell.html b/_autosummary/pyTEMlib.graph_tools.get_non_periodic_supercell.html new file mode 100644 index 00000000..49d188d0 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.get_non_periodic_supercell.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.graph_tools.get_non_periodic_supercell — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.get_non_periodic_supercell

+
+
+pyTEMlib.graph_tools.get_non_periodic_supercell(super_cell)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.get_polygons.html b/_autosummary/pyTEMlib.graph_tools.get_polygons.html new file mode 100644 index 00000000..ffa73d26 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.get_polygons.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.graph_tools.get_polygons — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.get_polygons

+
+
+pyTEMlib.graph_tools.get_polygons(atoms, clusters, voronoi_tetrahedrons)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.get_significant_vertices.html b/_autosummary/pyTEMlib.graph_tools.get_significant_vertices.html new file mode 100644 index 00000000..7860c7d4 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.get_significant_vertices.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.graph_tools.get_significant_vertices — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.get_significant_vertices

+
+
+pyTEMlib.graph_tools.get_significant_vertices(vertices, distance=3)[source]
+

Calculate average for all points that are closer than distance apart, otherwise leave the points alone

+
+
Parameters:
+
    +
  • vertices (numpy array (n,2)) – list of points

  • +
  • distance (float) – (in same scale as points )

  • +
+
+
Returns:
+

ideal_vertices – list of points that are all a minimum of 3 apart.

+
+
Return type:
+

list of floats

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.get_voronoi.html b/_autosummary/pyTEMlib.graph_tools.get_voronoi.html new file mode 100644 index 00000000..d27bde95 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.get_voronoi.html @@ -0,0 +1,142 @@ + + + + + + + pyTEMlib.graph_tools.get_voronoi — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.get_voronoi

+
+
+pyTEMlib.graph_tools.get_voronoi(tetrahedra, atoms, bond_radii=None, optimize=True)[source]
+

Find Voronoi vertices and keep track of associated tetrahedrons and interstitial radii

+

Used in find_polyhedra function

+
+
Parameters:
+
    +
  • tetrahedra (scipy.spatial.Delaunay object) – Delaunay tesselation

  • +
  • atoms (ase.Atoms object) – the structural information

  • +
  • optimize (boolean) – whether to use different atom radii or not

  • +
+
+
Returns:
+

    +
  • voronoi_vertices (list) – list of positions of voronoi vertices

  • +
  • voronoi_tetrahedra – list of indices of associated vertices of tetrahedra

  • +
  • r_vv (list of float) – list of all interstitial sizes

  • +
+

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.html b/_autosummary/pyTEMlib.graph_tools.html new file mode 100644 index 00000000..52b6299e --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.html @@ -0,0 +1,204 @@ + + + + + + + pyTEMlib.graph_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

breadth_first_search

breadth first search of atoms viewed as a graph

circum_center

Function finds the center and the radius of the circumsphere of every simplex.

find_interstitial_clusters

Make clusters Breadth first search to go through the list of overlapping spheres or circles to determine clusters

find_overlapping_spheres

Find overlapping spheres

find_polyhedra

get polyhedra information from an ase.Atoms object

get_bond_radii

get all bond radii from Kirkland Parameter: ---------- atoms ase.Atoms object structure information in ase format type: str type of bond 'covalent' or 'metallic'

get_bonds

Get polyhedra, and bonds from and edges and lengths of edges for each polyhedron and store it in info dictionary of new ase.Atoms object

get_connectivity_matrix

get_distortion_matrix

Calculates distortion matrix

get_maximum_view

get_non_periodic_supercell

get_polygons

get_significant_vertices

Calculate average for all points that are closer than distance apart, otherwise leave the points alone

get_voronoi

Find Voronoi vertices and keep track of associated tetrahedrons and interstitial radii

interstitial_sphere_center

Function finds center and radius of the largest interstitial sphere of a simplex.

make_polygons

make polygons from convex hulls of vertices around interstitial positions

make_polyhedrons

collect output data and make dictionary

plot_atoms

Plot structure in a ase.Atoms object with plotly

polygon_sort

set_bond_radii

set certain or all bond-radii taken from Kirkland

sort_polyhedra_by_vertices

transform_voronoi

find transformation matrix A between a polygon and a perfect one

undistort

Undistort image according to distortion matrix

undistort_sitk

use simple ITK to undistort image

undistort_stack

Undistort stack with distortion matrix

undistort_stack_sitk

use simple ITK to undistort stack of image input: image: numpy array with size NxM distortion_matrix: h5 Dataset or numpy array with size 2 x P x Q with P, Q >= M, N output: image M, N

voronoi_volumes

Volumes of voronoi cells from https://stackoverflow.com/questions/19634993/volume-of-voronoi-cell-python

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.interstitial_sphere_center.html b/_autosummary/pyTEMlib.graph_tools.interstitial_sphere_center.html new file mode 100644 index 00000000..1cc8c3dd --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.interstitial_sphere_center.html @@ -0,0 +1,143 @@ + + + + + + + pyTEMlib.graph_tools.interstitial_sphere_center — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.interstitial_sphere_center

+
+
+pyTEMlib.graph_tools.interstitial_sphere_center(vertex_pos, atom_radii, optimize=True)[source]
+

Function finds center and radius of the largest interstitial sphere of a simplex. +Which is the center of the cirumsphere if all atoms have the same radius, +but differs for differently sized atoms. +In the last case, the circumsphere center is used as starting point for refinement.

+
+
Parameters:
+
    +
  • vertex_pos (numpy array) – The position of vertices of a tetrahedron

  • +
  • atom_radii (float) – bond radii of atoms

  • +
  • optimize (boolean) – whether atom bond lengths are optimized or not

  • +
+
+
Returns:
+

    +
  • new_center (numpy array) – The center of the largest interstitial sphere

  • +
  • radius (float) – The radius of the largest interstitial sphere

  • +
+

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.make_polygons.html b/_autosummary/pyTEMlib.graph_tools.make_polygons.html new file mode 100644 index 00000000..afb79022 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.make_polygons.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.graph_tools.make_polygons — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.make_polygons

+
+
+pyTEMlib.graph_tools.make_polygons(atoms, voronoi_vertices, voronoi_tetrahedrons, clusters, visited_all)[source]
+

make polygons from convex hulls of vertices around interstitial positions

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.make_polyhedrons.html b/_autosummary/pyTEMlib.graph_tools.make_polyhedrons.html new file mode 100644 index 00000000..d92e7bf7 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.make_polyhedrons.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.graph_tools.make_polyhedrons — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.make_polyhedrons

+
+
+pyTEMlib.graph_tools.make_polyhedrons(atoms, voronoi_vertices, voronoi_tetrahedrons, clusters, visited_all)[source]
+

collect output data and make dictionary

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.plot_atoms.html b/_autosummary/pyTEMlib.graph_tools.plot_atoms.html new file mode 100644 index 00000000..9a3b2a34 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.plot_atoms.html @@ -0,0 +1,143 @@ + + + + + + + pyTEMlib.graph_tools.plot_atoms — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.plot_atoms

+
+
+pyTEMlib.graph_tools.plot_atoms(atoms: Atoms, polyhedra_indices=None, plot_bonds=False, color='', template=None, atom_size=None, max_size=35) Figure[source]
+

Plot structure in a ase.Atoms object with plotly

+

If the info dictionary of the atoms object contains bond or polyedra information, these can be set tobe plotted

+
+

Partameter:

+
+
atoms: ase.Atoms object

structure of supercell

+
+
polyhedra_indices: list of integers

indices of polyhedra to be plotted

+
+
plot_bonds: boolean

whether to plot bonds or not

+
+
+
+
+

Returns:

+
+
fig: plotly figure object

handle to figure needed to modify appearance

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.polygon_sort.html b/_autosummary/pyTEMlib.graph_tools.polygon_sort.html new file mode 100644 index 00000000..218c9c3b --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.polygon_sort.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.graph_tools.polygon_sort — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.polygon_sort

+
+
+pyTEMlib.graph_tools.polygon_sort(corners)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.set_bond_radii.html b/_autosummary/pyTEMlib.graph_tools.set_bond_radii.html new file mode 100644 index 00000000..a3f91aa0 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.set_bond_radii.html @@ -0,0 +1,141 @@ + + + + + + + pyTEMlib.graph_tools.set_bond_radii — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.set_bond_radii

+
+
+pyTEMlib.graph_tools.set_bond_radii(atoms, bond_type='bond')[source]
+

set certain or all bond-radii taken from Kirkland

+

Bond_radii are also stored in atoms.info

+
+

Parameter:

+
+
atoms ase.Atoms object

structure information in ase format

+
+
type: str

type of bond ‘covalent’ or ‘metallic’

+
+
+
+
+

Return:

+
+
r_a: list

list of atomic bond-radii

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.sort_polyhedra_by_vertices.html b/_autosummary/pyTEMlib.graph_tools.sort_polyhedra_by_vertices.html new file mode 100644 index 00000000..66cadf41 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.sort_polyhedra_by_vertices.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.graph_tools.sort_polyhedra_by_vertices — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.sort_polyhedra_by_vertices

+
+
+pyTEMlib.graph_tools.sort_polyhedra_by_vertices(polyhedra, visible=range(4, 100), z_lim=[0, 100], verbose=False)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.transform_voronoi.html b/_autosummary/pyTEMlib.graph_tools.transform_voronoi.html new file mode 100644 index 00000000..c5b6c22c --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.transform_voronoi.html @@ -0,0 +1,128 @@ + + + + + + + pyTEMlib.graph_tools.transform_voronoi — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.transform_voronoi

+
+
+pyTEMlib.graph_tools.transform_voronoi(vertices, ideal_voronoi)[source]
+

find transformation matrix A between a polygon and a perfect one

+

returns: +list of points: all points on a grid within original polygon +list of points: coordinates of these points where pixel have to move to +2x2 matrix aa: transformation matrix

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.undistort.html b/_autosummary/pyTEMlib.graph_tools.undistort.html new file mode 100644 index 00000000..8336c875 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.undistort.html @@ -0,0 +1,141 @@ + + + + + + + pyTEMlib.graph_tools.undistort — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.undistort

+
+
+pyTEMlib.graph_tools.undistort(distortion_matrix, image_data)[source]
+

Undistort image according to distortion matrix

+

Uses the griddata interpolation of scipy to apply distortion matrix to image. +The distortion matrix contains in origin and target pixel coordinates +target is where the pixel has to be moved (floats)

+
+
Parameters:
+
    +
  • distortion_matrix (numpy array (Nx2)) – distortion matrix (format N x 2)

  • +
  • image_data (numpy array or sidpy.Dataset) – image

  • +
+
+
Returns:
+

interpolated – undistorted image

+
+
Return type:
+

numpy array

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.undistort_sitk.html b/_autosummary/pyTEMlib.graph_tools.undistort_sitk.html new file mode 100644 index 00000000..adf87176 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.undistort_sitk.html @@ -0,0 +1,141 @@ + + + + + + + pyTEMlib.graph_tools.undistort_sitk — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.undistort_sitk

+
+
+pyTEMlib.graph_tools.undistort_sitk(image_data, distortion_matrix)[source]
+

use simple ITK to undistort image

+
+
Parameters:
+
    +
  • image_data (numpy array with size NxM) –

  • +
  • distortion_matrix (sidpy.Dataset or numpy array with size 2 x P x Q) –

  • +
  • P (with) –

  • +
  • M (Q >=) –

  • +
  • N

  • +
+
+
Returns:
+

image

+
+
Return type:
+

numpy array MXN

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.undistort_stack.html b/_autosummary/pyTEMlib.graph_tools.undistort_stack.html new file mode 100644 index 00000000..390a4971 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.undistort_stack.html @@ -0,0 +1,134 @@ + + + + + + + pyTEMlib.graph_tools.undistort_stack — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.undistort_stack

+
+
+pyTEMlib.graph_tools.undistort_stack(distortion_matrix, data)[source]
+

Undistort stack with distortion matrix

+

Use the griddata interpolation of scipy to apply distortion matrix to image +The distortion matrix contains in each pixel where the pixel has to be moved (floats)

+
+
Parameters:
+
    +
  • distortion_matrix (numpy array) – distortion matrix to undistort image (format image.shape[0], image.shape[2], 2)

  • +
  • data (numpy array or sidpy.Dataset) – image

  • +
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.undistort_stack_sitk.html b/_autosummary/pyTEMlib.graph_tools.undistort_stack_sitk.html new file mode 100644 index 00000000..7dcbbfb5 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.undistort_stack_sitk.html @@ -0,0 +1,130 @@ + + + + + + + pyTEMlib.graph_tools.undistort_stack_sitk — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.undistort_stack_sitk

+
+
+pyTEMlib.graph_tools.undistort_stack_sitk(distortion_matrix, image_stack)[source]
+

use simple ITK to undistort stack of image +input: +image: numpy array with size NxM +distortion_matrix: h5 Dataset or numpy array with size 2 x P x Q +with P, Q >= M, N +output: +image M, N

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_tools.voronoi_volumes.html b/_autosummary/pyTEMlib.graph_tools.voronoi_volumes.html new file mode 100644 index 00000000..29513825 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_tools.voronoi_volumes.html @@ -0,0 +1,125 @@ + + + + + + + pyTEMlib.graph_tools.voronoi_volumes — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_tools.voronoi_volumes

+
+
+pyTEMlib.graph_tools.voronoi_volumes(atoms)[source]
+

Volumes of voronoi cells from +https://stackoverflow.com/questions/19634993/volume-of-voronoi-cell-python

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_viz.get_boundary_polyhedra.html b/_autosummary/pyTEMlib.graph_viz.get_boundary_polyhedra.html new file mode 100644 index 00000000..4cc3b207 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_viz.get_boundary_polyhedra.html @@ -0,0 +1,147 @@ + + + + + + + pyTEMlib.graph_viz.get_boundary_polyhedra — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_viz.get_boundary_polyhedra

+
+
+pyTEMlib.graph_viz.get_boundary_polyhedra(polyhedra, boundary_x=0, boundary_width=0.5, verbose=True, z_lim=[0, 100])[source]
+

get indices of polyhedra at boundary (assumed to be parallel to x-axis)

+
+

Parameter

+
+
polyhedra: dict

dictionary of all polyhedra

+
+
boundary_x: float

position of boundary in Angstrom

+
+
boundary_width: float

width of boundary where center of polyhedra are considered in Angstrom

+
+
verbose: boolean

optional

+
+
z_lim: list

upper and lower limit of polyhedra to plot

+
+
+
+
returns:
+

boundary_polyhedra – list of polyhedra at boundary

+
+
rtype:
+

list

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_viz.html b/_autosummary/pyTEMlib.graph_viz.html new file mode 100644 index 00000000..10bdaae3 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_viz.html @@ -0,0 +1,157 @@ + + + + + + + pyTEMlib.graph_viz — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_viz

+
+

# plotting functions for graph_tools

+

part of pyTEMlib +a pycrosccopy package

+

Author: Gerd Duscher +First Version: 2022-01-08

+
+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

get_boundary_polyhedra

get indices of polyhedra at boundary (assumed to be parallel to x-axis)

plot_bonds

Information to plot bonds with plotly

plot_polyhedron

Information to plot polyhedra with plotly

plot_super_cell

make a super_cell to plot with extra atoms at periodic boundaries

plot_supercell

plot supercell with plotly

plot_supercell_bonds

plot atoms and bonds with plotly

plot_supercell_polyhedra

plot atoms and polyhedra with plotly

plot_with_polyhedra

plot atoms and polyhedra with plotly

show_polyhedra

plot polyhedra and atoms of vertices with plotly

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_viz.plot_bonds.html b/_autosummary/pyTEMlib.graph_viz.plot_bonds.html new file mode 100644 index 00000000..9dfb4922 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_viz.plot_bonds.html @@ -0,0 +1,139 @@ + + + + + + + pyTEMlib.graph_viz.plot_bonds — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_viz.plot_bonds

+
+
+pyTEMlib.graph_viz.plot_bonds(polyhedra)[source]
+

Information to plot bonds with plotly

+
+

Parameter

+
+
polyhedra: dict

dictionary of all polyhedra

+
+
+
+
returns:
+

data – instructions to plot for plotly

+
+
rtype:
+

dict

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_viz.plot_polyhedron.html b/_autosummary/pyTEMlib.graph_viz.plot_polyhedron.html new file mode 100644 index 00000000..5fc4c6e6 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_viz.plot_polyhedron.html @@ -0,0 +1,143 @@ + + + + + + + pyTEMlib.graph_viz.plot_polyhedron — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_viz.plot_polyhedron

+
+
+pyTEMlib.graph_viz.plot_polyhedron(polyhedra, indices, center=False)[source]
+

Information to plot polyhedra with plotly

+
+

Parameter

+
+
polyhedra: dict

dictionary of all polyhedra

+
+
indices: list or integer

list or index of polyhedron to plot.

+
+
center: boolean

whether to center polyhedra on origin

+
+
+
+
returns:
+

data – instructions to plot for plotly

+
+
rtype:
+

dict

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_viz.plot_super_cell.html b/_autosummary/pyTEMlib.graph_viz.plot_super_cell.html new file mode 100644 index 00000000..d80b9f0e --- /dev/null +++ b/_autosummary/pyTEMlib.graph_viz.plot_super_cell.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.graph_viz.plot_super_cell — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_viz.plot_super_cell

+
+
+pyTEMlib.graph_viz.plot_super_cell(super_cell, shift_x=0.0)[source]
+

make a super_cell to plot with extra atoms at periodic boundaries

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_viz.plot_supercell.html b/_autosummary/pyTEMlib.graph_viz.plot_supercell.html new file mode 100644 index 00000000..ed28ef21 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_viz.plot_supercell.html @@ -0,0 +1,143 @@ + + + + + + + pyTEMlib.graph_viz.plot_supercell — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_viz.plot_supercell

+
+
+pyTEMlib.graph_viz.plot_supercell(supercell, size=(1, 1, 1), shift_x=0.25, title='')[source]
+

plot supercell with plotly

+
+

Parameter

+
+
supercell: ase.Atoms

optional structure info to plot atoms (with correct color)

+
+
shift_x: float

amount of shift in x direction of supercell

+
+
title: str

title of plot

+
+
+
+
returns:
+

fig – plotly figure instance

+
+
rtype:
+

plotly.figure

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_viz.plot_supercell_bonds.html b/_autosummary/pyTEMlib.graph_viz.plot_supercell_bonds.html new file mode 100644 index 00000000..48cf3ee5 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_viz.plot_supercell_bonds.html @@ -0,0 +1,147 @@ + + + + + + + pyTEMlib.graph_viz.plot_supercell_bonds — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_viz.plot_supercell_bonds

+
+
+pyTEMlib.graph_viz.plot_supercell_bonds(polyhedra, atoms, volumes=None, atom_size=15, title='')[source]
+

plot atoms and bonds with plotly

+
+

Parameter

+
+
polyhedra: dict

dictionary of all polyhedra

+
+
atoms: ase.Atoms

optional structure info to plot atoms (with correct color)

+
+
volumes: list

list of volumes, optional structure

+
+
atoms_size: float

sie of atoms to plot

+
+
title: str

title of plot

+
+
+
+
returns:
+

fig – plotly figure instance

+
+
rtype:
+

plotly.figure

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_viz.plot_supercell_polyhedra.html b/_autosummary/pyTEMlib.graph_viz.plot_supercell_polyhedra.html new file mode 100644 index 00000000..8553997e --- /dev/null +++ b/_autosummary/pyTEMlib.graph_viz.plot_supercell_polyhedra.html @@ -0,0 +1,147 @@ + + + + + + + pyTEMlib.graph_viz.plot_supercell_polyhedra — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_viz.plot_supercell_polyhedra

+
+
+pyTEMlib.graph_viz.plot_supercell_polyhedra(polyhedra, indices, atoms, volumes=None, title='')[source]
+

plot atoms and polyhedra with plotly

+
+

Parameter

+
+
polyhedra: dict

dictionary of all polyhedra

+
+
indices: list

list of indices of polyhedra to plot

+
+
atoms: ase.Atoms

optional structure info to plot atoms (with correct color)

+
+
volumes: list

list of volumes, optional structure

+
+
title: str

title of plot

+
+
+
+
returns:
+

fig – plotly figure instance

+
+
rtype:
+

plotly.figure

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_viz.plot_with_polyhedra.html b/_autosummary/pyTEMlib.graph_viz.plot_with_polyhedra.html new file mode 100644 index 00000000..be5dfa0b --- /dev/null +++ b/_autosummary/pyTEMlib.graph_viz.plot_with_polyhedra.html @@ -0,0 +1,143 @@ + + + + + + + pyTEMlib.graph_viz.plot_with_polyhedra — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_viz.plot_with_polyhedra

+
+
+pyTEMlib.graph_viz.plot_with_polyhedra(polyhedra, indices, atoms=None, title='')[source]
+

plot atoms and polyhedra with plotly

+
+

Parameter

+
+
polyhedra: dict

dictionary of all polyhedra

+
+
indices: list or integer

list or index of polyhedron to plot.

+
+
atoms: ase.Atoms

optional structure info to plot atoms (with correct color)

+
+
+
+
returns:
+

fig – plotly figure instance

+
+
rtype:
+

plotly.figure

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.graph_viz.show_polyhedra.html b/_autosummary/pyTEMlib.graph_viz.show_polyhedra.html new file mode 100644 index 00000000..e7f77980 --- /dev/null +++ b/_autosummary/pyTEMlib.graph_viz.show_polyhedra.html @@ -0,0 +1,147 @@ + + + + + + + pyTEMlib.graph_viz.show_polyhedra — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.graph_viz.show_polyhedra

+
+
+pyTEMlib.graph_viz.show_polyhedra(polyhedra, boundary_polyhedra, atoms, volumes=None, title='')[source]
+

plot polyhedra and atoms of vertices with plotly

+
+

Parameter

+
+
polyhedra: dict

dictionary of all polyhedra

+
+
boundary_polyhedra: list

list of indices of polyhedra to plot

+
+
atoms: ase.Atoms

optional structure info to plot atoms (with correct color)

+
+
volumes: list

list of volumes, optional structure

+
+
title: str

title of plot

+
+
+
+
returns:
+

fig – plotly figure instance

+
+
rtype:
+

plotly.figure

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.html b/_autosummary/pyTEMlib.html new file mode 100644 index 00000000..0292d5a8 --- /dev/null +++ b/_autosummary/pyTEMlib.html @@ -0,0 +1,228 @@ + + + + + + + pyTEMlib — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib

+

Created on Sat Jan 19 10:07:35 2019

+

@author: gduscher

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

pyTEMlib.animation

Figures and Animations for TEM in jupyter notebooks part of MSE 672 course at UTK

pyTEMlib.atom_tools

Atom detection

pyTEMlib.config_dir

config_dir: setup of directory ~/.pyTEMlib for custom sources and database

pyTEMlib.crystal_tools

crystal_tools

pyTEMlib.diffraction_plot

pyTEMlib.dynamic_scattering

Dynamic Scattering Library for Multi-Slice Calculations

pyTEMlib.eds_tools

eds_tools Model based quantification of energy-dispersive X-ray spectroscopy data Copyright by Gerd Duscher

pyTEMlib.eels_dialog

QT dialog window for EELS compositional analysis

pyTEMlib.eels_dialog_utilities

Interactive routines for EELS analysis

pyTEMlib.eels_dlg

GUI definitions for EEELS_dialog

pyTEMlib.eels_tools

eels_tools Model based quantification of electron energy-loss data Copyright by Gerd Duscher

pyTEMlib.file_tools

file_tools: All tools to load and save data

pyTEMlib.file_tools_qt

pyTEMlib.graph_tools

pyTEMlib.graph_viz

# plotting functions for graph_tools

pyTEMlib.image_dialog

Input Dialog for Image Analysis

pyTEMlib.image_dlg

Gui for image_dialog

pyTEMlib.image_tools

image_tools.py by Gerd Duscher, UTK part of pyTEMlib MIT license except where stated differently

pyTEMlib.info_dialog

Input Dialog for EELS Analysis

pyTEMlib.info_dlg

Gui for info_dialog

pyTEMlib.info_widget

pyTEMlib.interactive_eels

Interactive routines for EELS analysis

pyTEMlib.interactive_image

pyTEMlib.kinematic_scattering

kinematic_scattering Copyright by Gerd Duscher

pyTEMlib.microscope

default microscope parameters from config file

pyTEMlib.peak_dialog

EELS Input Dialog for ELNES Analysis

pyTEMlib.peak_dlg

GUI definitions for peak_fit_dialog

pyTEMlib.probe_tools

Functions to calculate electron probe

pyTEMlib.sidpy_tools

utility functions for sidpy; will move to sidpy

pyTEMlib.simulation_tools

dft simulations tools

pyTEMlib.version

version

pyTEMlib.viz

plotting of sidpy Datasets with bokeh for google colab

pyTEMlib.xrpa_x_sections

X-ray photo-absorption cross-sections for inelastic scattering from NIST The cross sections are given in atoms/nm^3 not barns!! See xsec_xrpa function in eels_tools for usage.

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_dialog.html b/_autosummary/pyTEMlib.image_dialog.html new file mode 100644 index 00000000..38e6587f --- /dev/null +++ b/_autosummary/pyTEMlib.image_dialog.html @@ -0,0 +1,120 @@ + + + + + + + pyTEMlib.image_dialog — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_dialog

+

Input Dialog for Image Analysis

+

Author: Gerd Duscher

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_dlg.html b/_autosummary/pyTEMlib.image_dlg.html new file mode 100644 index 00000000..f6c80df3 --- /dev/null +++ b/_autosummary/pyTEMlib.image_dlg.html @@ -0,0 +1,120 @@ + + + + + + + pyTEMlib.image_dlg — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_dlg

+

Gui for image_dialog

+

Author: Gerd Duscher

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.ImageWithLineProfile.html b/_autosummary/pyTEMlib.image_tools.ImageWithLineProfile.html new file mode 100644 index 00000000..d86922db --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.ImageWithLineProfile.html @@ -0,0 +1,139 @@ + + + + + + + pyTEMlib.image_tools.ImageWithLineProfile — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.ImageWithLineProfile

+
+
+class pyTEMlib.image_tools.ImageWithLineProfile(data, extent, title='')[source]
+

Bases: object

+

Image with line profile

+

Methods

+ + + + + + +

update

+
+
+__call__(event)[source]
+

Call self as a function.

+
+ +
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.adaptive_fourier_filter.html b/_autosummary/pyTEMlib.image_tools.adaptive_fourier_filter.html new file mode 100644 index 00000000..d8942d2d --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.adaptive_fourier_filter.html @@ -0,0 +1,143 @@ + + + + + + + pyTEMlib.image_tools.adaptive_fourier_filter — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.adaptive_fourier_filter

+
+
+pyTEMlib.image_tools.adaptive_fourier_filter(dset, spots, low_pass=3, reflection_radius=0.3)[source]
+

Use spots in diffractogram for a Fourier Filter

+
+

Parameters:

+
+
dset: sidpy.Dataset

image to be filtered

+
+
spots: np.ndarray(N,2)

sorted spots in diffractogram in 1/nm

+
+
low_pass: float

low pass filter in center of diffractogram in 1/nm

+
+
reflection_radius: float

radius of masked reflections in 1/nm

+
+
+
+
+

Output:

+
+

Fourier filtered image

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.align_crystal_reflections.html b/_autosummary/pyTEMlib.image_tools.align_crystal_reflections.html new file mode 100644 index 00000000..21dbc733 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.align_crystal_reflections.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.image_tools.align_crystal_reflections — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.align_crystal_reflections

+
+
+pyTEMlib.image_tools.align_crystal_reflections(spots, crystals)[source]
+

Depreciated - use diffraction spots

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.calculate_ctf.html b/_autosummary/pyTEMlib.image_tools.calculate_ctf.html new file mode 100644 index 00000000..5210cf6a --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.calculate_ctf.html @@ -0,0 +1,141 @@ + + + + + + + pyTEMlib.image_tools.calculate_ctf — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.calculate_ctf

+
+
+pyTEMlib.image_tools.calculate_ctf(wavelength, cs, defocus, k)[source]
+

Calculate Contrast Transfer Function

+

everything in nm

+
+
Parameters:
+
    +
  • wavelength (float) – deBroglie wavelength of electrons

  • +
  • cs (float) – spherical aberration coefficient

  • +
  • defocus (float) – defocus

  • +
  • k (numpy array) – reciprocal scale

  • +
+
+
Returns:
+

ctf – contrast transfer function

+
+
Return type:
+

numpy array

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.calculate_scherzer.html b/_autosummary/pyTEMlib.image_tools.calculate_scherzer.html new file mode 100644 index 00000000..6c2a8226 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.calculate_scherzer.html @@ -0,0 +1,125 @@ + + + + + + + pyTEMlib.image_tools.calculate_scherzer — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.calculate_scherzer

+
+
+pyTEMlib.image_tools.calculate_scherzer(wavelength, cs)[source]
+

Calculate the Scherzer defocus. Cs is in mm, lambda is in nm

+

# Input and output in nm

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.calibrate_image_scale.html b/_autosummary/pyTEMlib.image_tools.calibrate_image_scale.html new file mode 100644 index 00000000..c620b743 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.calibrate_image_scale.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.image_tools.calibrate_image_scale — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.calibrate_image_scale

+
+
+pyTEMlib.image_tools.calibrate_image_scale(fft_tags, spots_reference, spots_experiment)[source]
+

depreciated get change of scale from comparison of spots to Bragg angles

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.cart2pol.html b/_autosummary/pyTEMlib.image_tools.cart2pol.html new file mode 100644 index 00000000..de6762c3 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.cart2pol.html @@ -0,0 +1,136 @@ + + + + + + + pyTEMlib.image_tools.cart2pol — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.cart2pol

+
+
+pyTEMlib.image_tools.cart2pol(points)[source]
+

Cartesian to polar coordinate conversion

+
+
Parameters:
+

points (float or numpy array) – points to be converted (Nx2)

+
+
Returns:
+

    +
  • rho (float or numpy array) – distance

  • +
  • phi (float or numpy array) – angle

  • +
+

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.cartesian2polar.html b/_autosummary/pyTEMlib.image_tools.cartesian2polar.html new file mode 100644 index 00000000..a1644836 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.cartesian2polar.html @@ -0,0 +1,125 @@ + + + + + + + pyTEMlib.image_tools.cartesian2polar — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.cartesian2polar

+
+
+pyTEMlib.image_tools.cartesian2polar(x, y, grid, r, t, order=3)[source]
+

Transform cartesian grid to polar grid

+

Used by warp

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.clean_svd.html b/_autosummary/pyTEMlib.image_tools.clean_svd.html new file mode 100644 index 00000000..8b62d2cf --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.clean_svd.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.image_tools.clean_svd — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.clean_svd

+
+
+pyTEMlib.image_tools.clean_svd(im, pixel_size=1, source_size=5)[source]
+

De-noising of image by using first component of single value decomposition

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.complete_registration.html b/_autosummary/pyTEMlib.image_tools.complete_registration.html new file mode 100644 index 00000000..fd8cfe6d --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.complete_registration.html @@ -0,0 +1,142 @@ + + + + + + + pyTEMlib.image_tools.complete_registration — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.complete_registration

+
+
+pyTEMlib.image_tools.complete_registration(main_dataset, storage_channel=None)[source]
+

Rigid and then non-rigid (demon) registration

+

Performs rigid and then non-rigid registration, please see individual functions: +- rigid_registration +- demon_registration

+
+
Parameters:
+
    +
  • main_dataset (sidpy.Dataset) – dataset of data_type ‘IMAGE_STACK’ to be registered

  • +
  • storage_channel (h5py.Group) – optional - location in hdf5 file to store datasets

  • +
+
+
Returns:
+

    +
  • non_rigid_registered (sidpy.Dataset)

  • +
  • rigid_registered_dataset (sidpy.Dataset)

  • +
+

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.crop_image_stack.html b/_autosummary/pyTEMlib.image_tools.crop_image_stack.html new file mode 100644 index 00000000..16df6fb1 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.crop_image_stack.html @@ -0,0 +1,136 @@ + + + + + + + pyTEMlib.image_tools.crop_image_stack — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.crop_image_stack

+
+
+pyTEMlib.image_tools.crop_image_stack(rig_reg, drift)[source]
+

Crop images in stack according to drift

+

This function is used by rigid_registration routine

+
+
Parameters:
+
    +
  • rig_reg (numpy array (N,x,y)) –

  • +
  • drift (list (2,B)) –

  • +
+
+
Return type:
+

numpy array

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.decon_lr.html b/_autosummary/pyTEMlib.image_tools.decon_lr.html new file mode 100644 index 00000000..159fb53b --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.decon_lr.html @@ -0,0 +1,146 @@ + + + + + + + pyTEMlib.image_tools.decon_lr — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.decon_lr

+
+
+pyTEMlib.image_tools.decon_lr(o_image, probe, verbose=False)[source]
+

# This task generates a restored image from an input image and point spread function (PSF) using +# the algorithm developed independently by Lucy (1974, Astron. J. 79, 745) and Richardson +# (1972, J. Opt. Soc. Am. 62, 55) and adapted for HST imagery by Snyder +# (1990, in Restoration of HST Images and Spectra, ST ScI Workshop Proceedings; see also +# Snyder, Hammoud, & White, JOSA, v. 10, no. 5, May 1993, in press). +# Additional options developed by Rick White (STScI) are also included. +# +# The Lucy-Richardson method can be derived from the maximum likelihood expression for data +# with a Poisson noise distribution. Thus, it naturally applies to optical imaging data such as HST. +# The method forces the restored image to be positive, in accord with photon-counting statistics. +# +# The Lucy-Richardson algorithm generates a restored image through an iterative method. The essence +# of the iteration is as follows: the (n+1)th estimate of the restored image is given by the nth estimate +# of the restored image multiplied by a correction image. That is, +# +# original data +# image = image ————— * reflect(PSF) +# n+1 n image * PSF +# n

+

# where the *’s represent convolution operators and reflect(PSF) is the reflection of the PSF, i.e. +# reflect((PSF)(x,y)) = PSF(-x,-y). When the convolutions are carried out using fast Fourier transforms +# (FFTs), one can use the fact that FFT(reflect(PSF)) = conj(FFT(PSF)), where conj is the complex conjugate +# operator.

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.demon_registration.html b/_autosummary/pyTEMlib.image_tools.demon_registration.html new file mode 100644 index 00000000..e277a541 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.demon_registration.html @@ -0,0 +1,148 @@ + + + + + + + pyTEMlib.image_tools.demon_registration — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.demon_registration

+
+
+pyTEMlib.image_tools.demon_registration(dataset, verbose=False)[source]
+

Diffeomorphic Demon Non-Rigid Registration

+
+
Depends on:

simpleITK and numpy

+
+
+

Please Cite: http://www.simpleitk.org/SimpleITK/project/parti.html +and T. Vercauteren, X. Pennec, A. Perchant and N. Ayache +Diffeomorphic Demons Using ITK’s Finite Difference Solver Hierarchy +The Insight Journal, http://hdl.handle.net/1926/510 2007

+
+
Parameters:
+
    +
  • dataset (sidpy.Dataset) – stack of image after rigid registration and cropping

  • +
  • verbose (boolean) – optional for increased output

  • +
+
+
Returns:
+

dem_reg

+
+
Return type:
+

stack of images with non-rigid registration

+
+
+

Example

+

dem_reg = demon_reg(stack_dataset, verbose=False)

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.diffractogram_spots.html b/_autosummary/pyTEMlib.image_tools.diffractogram_spots.html new file mode 100644 index 00000000..358dbff2 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.diffractogram_spots.html @@ -0,0 +1,139 @@ + + + + + + + pyTEMlib.image_tools.diffractogram_spots — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.diffractogram_spots

+
+
+pyTEMlib.image_tools.diffractogram_spots(dset, spot_threshold, return_center=True, eps=0.1)[source]
+

Find spots in diffractogram and sort them by distance from center

+

Uses blob_log from scipy.spatial

+
+
Parameters:
+
    +
  • dset (sidpy.Dataset) – diffractogram

  • +
  • spot_threshold (float) – threshold for blob finder

  • +
+
+
Returns:
+

spots – sorted position (x,y) and radius (r) of all spots

+
+
Return type:
+

numpy array

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.fourier_transform.html b/_autosummary/pyTEMlib.image_tools.fourier_transform.html new file mode 100644 index 00000000..47474a92 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.fourier_transform.html @@ -0,0 +1,141 @@ + + + + + + + pyTEMlib.image_tools.fourier_transform — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.fourier_transform

+
+
+pyTEMlib.image_tools.fourier_transform(dset)[source]
+

Reads information into dictionary ‘tags’, performs ‘FFT’, and provides a smoothed FT and reciprocal +and intensity limits for visualization.

+
+
Parameters:
+

dset (sidpy.Dataset) – image

+
+
Returns:
+

fft_dset – Fourier transform with correct dimensions

+
+
Return type:
+

sidpy.Dataset

+
+
+

Example

+
>>> fft_dataset = fourier_transform(sidpy_dataset)
+>>> fft_dataset.plot()
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.get_rotation.html b/_autosummary/pyTEMlib.image_tools.get_rotation.html new file mode 100644 index 00000000..2192962f --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.get_rotation.html @@ -0,0 +1,133 @@ + + + + + + + pyTEMlib.image_tools.get_rotation — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.get_rotation

+
+
+pyTEMlib.image_tools.get_rotation(experiment_spots, crystal_spots)[source]
+

Get rotation by comparing spots in diffractogram to diffraction Bragg spots

+
+

Parameter

+
+
experiment_spots: numpy array (nx2)

positions (in 1/nm) of spots in diffractogram

+
+
crystal_spots: numpy array (nx2)

positions (in 1/nm) of Bragg spots according to kinematic scattering theory

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.get_wavelength.html b/_autosummary/pyTEMlib.image_tools.get_wavelength.html new file mode 100644 index 00000000..1792b102 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.get_wavelength.html @@ -0,0 +1,132 @@ + + + + + + + pyTEMlib.image_tools.get_wavelength — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.get_wavelength

+
+
+pyTEMlib.image_tools.get_wavelength(e0)[source]
+

Calculates the relativistic corrected de Broglie wave length of an electron

+
+
Parameters:
+

e0 (float) – acceleration voltage in volt

+
+
Return type:
+

wave length in 1/nm

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.histogram_plot.html b/_autosummary/pyTEMlib.image_tools.histogram_plot.html new file mode 100644 index 00000000..538a617d --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.histogram_plot.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.image_tools.histogram_plot — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.histogram_plot

+
+
+pyTEMlib.image_tools.histogram_plot(image_tags)[source]
+

interactive histogram

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.html b/_autosummary/pyTEMlib.image_tools.html new file mode 100644 index 00000000..a75f7701 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.html @@ -0,0 +1,210 @@ + + + + + + + pyTEMlib.image_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools

+

image_tools.py +by Gerd Duscher, UTK +part of pyTEMlib +MIT license except where stated differently

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

adaptive_fourier_filter

Use spots in diffractogram for a Fourier Filter

align_crystal_reflections

Depreciated - use diffraction spots

calculate_ctf

Calculate Contrast Transfer Function

calculate_scherzer

Calculate the Scherzer defocus.

calibrate_image_scale

depreciated get change of scale from comparison of spots to Bragg angles

cart2pol

Cartesian to polar coordinate conversion

cartesian2polar

Transform cartesian grid to polar grid

clean_svd

De-noising of image by using first component of single value decomposition

complete_registration

Rigid and then non-rigid (demon) registration

crop_image_stack

Crop images in stack according to drift

decon_lr

# This task generates a restored image from an input image and point spread function (PSF) using # the algorithm developed independently by Lucy (1974, Astron.

demon_registration

Diffeomorphic Demon Non-Rigid Registration

diffractogram_spots

Find spots in diffractogram and sort them by distance from center

fourier_transform

Reads information into dictionary 'tags', performs 'FFT', and provides a smoothed FT and reciprocal and intensity limits for visualization.

get_rotation

Get rotation by comparing spots in diffractogram to diffraction Bragg spots

get_wavelength

Calculates the relativistic corrected de Broglie wave length of an electron

histogram_plot

interactive histogram

pol2cart

Polar to Cartesian coordinate conversion

power_spectrum

Calculate power spectrum

rebin

rebin an image by the number of pixels in x and y direction given by binning

rig_reg_drift

Shifting images on top of each other

rigid_registration

Rigid registration of image stack with pixel accuracy

rotational_symmetry_diffractogram

Test rotational symmetry of diffraction spots

warp

Takes a centered diffraction pattern (as a sidpy dataset)and warps it to a polar grid

xy2polar

Conversion from carthesian to polar coordinates

+

Classes

+ + + + + + +

ImageWithLineProfile

Image with line profile

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.pol2cart.html b/_autosummary/pyTEMlib.image_tools.pol2cart.html new file mode 100644 index 00000000..ab59ba75 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.pol2cart.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.image_tools.pol2cart — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.pol2cart

+
+
+pyTEMlib.image_tools.pol2cart(rho, phi)[source]
+

Polar to Cartesian coordinate conversion

+
+
Parameters:
+
    +
  • rho (float or numpy array) – distance

  • +
  • phi (float or numpy array) – angle

  • +
+
+
Returns:
+

x – x coordinates of converted points(Nx2)

+
+
Return type:
+

float or numpy array

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.power_spectrum.html b/_autosummary/pyTEMlib.image_tools.power_spectrum.html new file mode 100644 index 00000000..9054ba3d --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.power_spectrum.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.image_tools.power_spectrum — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.power_spectrum

+
+
+pyTEMlib.image_tools.power_spectrum(dset, smoothing=3)[source]
+

Calculate power spectrum

+
+
Parameters:
+
    +
  • dset (sidpy.Dataset) – image

  • +
  • smoothing (int) – Gaussian smoothing

  • +
+
+
Returns:
+

power_spec – power spectrum with correct dimensions

+
+
Return type:
+

sidpy.Dataset

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.rebin.html b/_autosummary/pyTEMlib.image_tools.rebin.html new file mode 100644 index 00000000..3067dda6 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.rebin.html @@ -0,0 +1,133 @@ + + + + + + + pyTEMlib.image_tools.rebin — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.rebin

+
+
+pyTEMlib.image_tools.rebin(im, binning=2)[source]
+

rebin an image by the number of pixels in x and y direction given by binning

+
+

Parameter

+

image: numpy array in 2 dimensions

+
+
rtype:
+

binned image as numpy array

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.rig_reg_drift.html b/_autosummary/pyTEMlib.image_tools.rig_reg_drift.html new file mode 100644 index 00000000..33104e12 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.rig_reg_drift.html @@ -0,0 +1,143 @@ + + + + + + + pyTEMlib.image_tools.rig_reg_drift — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.rig_reg_drift

+
+
+pyTEMlib.image_tools.rig_reg_drift(dset, rel_drift)[source]
+

Shifting images on top of each other

+

Uses relative drift to shift images on top of each other, +with center image as reference. +Shifting is done with shift routine of ndimage from scipy. +This function is used by rigid_registration routine

+
+
Parameters:
+
    +
  • dset (sidpy.Dataset) – dataset with image_stack

  • +
  • rel_drift – relative_drift from image to image as list of [shiftx, shifty]

  • +
+
+
Returns:
+

    +
  • stack (numpy array)

  • +
  • drift (list of drift in pixel)

  • +
+

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.rigid_registration.html b/_autosummary/pyTEMlib.image_tools.rigid_registration.html new file mode 100644 index 00000000..7f4bfa2d --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.rigid_registration.html @@ -0,0 +1,137 @@ + + + + + + + pyTEMlib.image_tools.rigid_registration — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.rigid_registration

+
+
+pyTEMlib.image_tools.rigid_registration(dataset)[source]
+

Rigid registration of image stack with pixel accuracy

+

Uses simple cross_correlation +(we determine drift from one image to next)

+
+
Parameters:
+

dataset (sidpy.Dataset) – sidpy dataset with image_stack dataset

+
+
Returns:
+

rigid_registered – Registered Stack and drift (with respect to center image)

+
+
Return type:
+

sidpy.Dataset

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.rotational_symmetry_diffractogram.html b/_autosummary/pyTEMlib.image_tools.rotational_symmetry_diffractogram.html new file mode 100644 index 00000000..8764b59c --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.rotational_symmetry_diffractogram.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.image_tools.rotational_symmetry_diffractogram — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • + View page source +
  • +
+
+
+
+
+ +
+

pyTEMlib.image_tools.rotational_symmetry_diffractogram

+
+
+pyTEMlib.image_tools.rotational_symmetry_diffractogram(spots)[source]
+

Test rotational symmetry of diffraction spots

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.warp.html b/_autosummary/pyTEMlib.image_tools.warp.html new file mode 100644 index 00000000..3cc671d5 --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.warp.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.image_tools.warp — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.warp

+
+
+pyTEMlib.image_tools.warp(diff)[source]
+

Takes a centered diffraction pattern (as a sidpy dataset)and warps it to a polar grid

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.image_tools.xy2polar.html b/_autosummary/pyTEMlib.image_tools.xy2polar.html new file mode 100644 index 00000000..94e7237b --- /dev/null +++ b/_autosummary/pyTEMlib.image_tools.xy2polar.html @@ -0,0 +1,137 @@ + + + + + + + pyTEMlib.image_tools.xy2polar — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.image_tools.xy2polar

+
+
+pyTEMlib.image_tools.xy2polar(points, rounding=0.001)[source]
+

Conversion from carthesian to polar coordinates

+

the angles and distances are sorted by r and then phi +The indices of this sort is also returned

+
+
Parameters:
+
    +
  • points (numpy array) – number of points in axis 0 first two elements in axis 1 are x and y

  • +
  • rounding (int) – optional rounding in significant digits

  • +
+
+
Return type:
+

r, phi, sorted_indices

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.info_dialog.InfoWidget.html b/_autosummary/pyTEMlib.info_dialog.InfoWidget.html new file mode 100644 index 00000000..2a12096d --- /dev/null +++ b/_autosummary/pyTEMlib.info_dialog.InfoWidget.html @@ -0,0 +1,159 @@ + + + + + + + pyTEMlib.info_dialog.InfoWidget — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.info_dialog.InfoWidget

+
+
+class pyTEMlib.info_dialog.InfoWidget(datasets=None)[source]
+

Bases: object

+

Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

cursor2energy_scale

get_spectrum

plot

set_action

set_binning

set_dataset

set_energy_scale

set_flux

set_microscope_parameter

set_y_scale

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.info_dialog.get_sidebar.html b/_autosummary/pyTEMlib.info_dialog.get_sidebar.html new file mode 100644 index 00000000..9f1f5356 --- /dev/null +++ b/_autosummary/pyTEMlib.info_dialog.get_sidebar.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.info_dialog.get_sidebar — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.info_dialog.get_sidebar

+
+
+pyTEMlib.info_dialog.get_sidebar()[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.info_dialog.html b/_autosummary/pyTEMlib.info_dialog.html new file mode 100644 index 00000000..8abd11cc --- /dev/null +++ b/_autosummary/pyTEMlib.info_dialog.html @@ -0,0 +1,136 @@ + + + + + + + pyTEMlib.info_dialog — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.info_dialog

+

Input Dialog for EELS Analysis

+

Author: Gerd Duscher

+

Functions

+ + + + + + +

get_sidebar

+

Classes

+ + + + + + +

InfoWidget

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.info_dlg.html b/_autosummary/pyTEMlib.info_dlg.html new file mode 100644 index 00000000..ef2a6119 --- /dev/null +++ b/_autosummary/pyTEMlib.info_dlg.html @@ -0,0 +1,120 @@ + + + + + + + pyTEMlib.info_dlg — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.info_dlg

+

Gui for info_dialog

+

Author: Gerd Duscher

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.info_widget.EELSWidget.html b/_autosummary/pyTEMlib.info_widget.EELSWidget.html new file mode 100644 index 00000000..c10deb39 --- /dev/null +++ b/_autosummary/pyTEMlib.info_widget.EELSWidget.html @@ -0,0 +1,153 @@ + + + + + + + pyTEMlib.info_widget.EELSWidget — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.info_widget.EELSWidget

+
+
+class pyTEMlib.info_widget.EELSWidget(datasets, sidebar, tab_title=None)[source]
+

Bases: object

+

Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

get_spectrum

line_select_callback

plot

plot_spectrum

plot_spectrum_image

set_dataset

set_energy_scale

set_y_scale

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.info_widget.InfoWidget.html b/_autosummary/pyTEMlib.info_widget.InfoWidget.html new file mode 100644 index 00000000..1ba24ec4 --- /dev/null +++ b/_autosummary/pyTEMlib.info_widget.InfoWidget.html @@ -0,0 +1,171 @@ + + + + + + + pyTEMlib.info_widget.InfoWidget — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.info_widget.InfoWidget

+
+
+class pyTEMlib.info_widget.InfoWidget(datasets)[source]
+

Bases: EELSWidget

+

Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

cursor2energy_scale

get_spectrum

line_select_callback

plot

plot_spectrum

plot_spectrum_image

set_action

set_binning

set_dataset

set_energy_scale

set_flux

set_microscope_parameter

set_y_scale

update_dataset

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.info_widget.LowLossWidget.html b/_autosummary/pyTEMlib.info_widget.LowLossWidget.html new file mode 100644 index 00000000..be1abff8 --- /dev/null +++ b/_autosummary/pyTEMlib.info_widget.LowLossWidget.html @@ -0,0 +1,171 @@ + + + + + + + pyTEMlib.info_widget.LowLossWidget — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.info_widget.LowLossWidget

+
+
+class pyTEMlib.info_widget.LowLossWidget(datasets)[source]
+

Bases: EELSWidget

+

Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

fix_energy_scale

get_additional_spectrum

get_resolution_function

get_spectrum

line_select_callback

plot

plot_spectrum

plot_spectrum_image

set_action

set_binning

set_dataset

set_energy_scale

set_y_scale

update_dataset

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.info_widget.get_info_sidebar.html b/_autosummary/pyTEMlib.info_widget.get_info_sidebar.html new file mode 100644 index 00000000..15e493e8 --- /dev/null +++ b/_autosummary/pyTEMlib.info_widget.get_info_sidebar.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.info_widget.get_info_sidebar — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.info_widget.get_info_sidebar

+
+
+pyTEMlib.info_widget.get_info_sidebar()[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.info_widget.get_low_loss_sidebar.html b/_autosummary/pyTEMlib.info_widget.get_low_loss_sidebar.html new file mode 100644 index 00000000..bde16a43 --- /dev/null +++ b/_autosummary/pyTEMlib.info_widget.get_low_loss_sidebar.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.info_widget.get_low_loss_sidebar — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.info_widget.get_low_loss_sidebar

+
+
+pyTEMlib.info_widget.get_low_loss_sidebar()[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.info_widget.html b/_autosummary/pyTEMlib.info_widget.html new file mode 100644 index 00000000..0a027344 --- /dev/null +++ b/_autosummary/pyTEMlib.info_widget.html @@ -0,0 +1,143 @@ + + + + + + + pyTEMlib.info_widget — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.info_widget

+

Functions

+ + + + + + + + + +

get_info_sidebar

get_low_loss_sidebar

+

Classes

+ + + + + + + + + + + + +

EELSWidget

InfoWidget

LowLossWidget

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.interactive_eels.html b/_autosummary/pyTEMlib.interactive_eels.html new file mode 100644 index 00000000..eb7758c5 --- /dev/null +++ b/_autosummary/pyTEMlib.interactive_eels.html @@ -0,0 +1,121 @@ + + + + + + + pyTEMlib.interactive_eels — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.interactive_eels

+

Interactive routines for EELS analysis

+

this file provides additional dialogs for EELS quantification

+

Author: Gerd Duscher

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.interactive_image.html b/_autosummary/pyTEMlib.interactive_image.html new file mode 100644 index 00000000..3e209be6 --- /dev/null +++ b/_autosummary/pyTEMlib.interactive_image.html @@ -0,0 +1,118 @@ + + + + + + + pyTEMlib.interactive_image — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.interactive_image

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.Zuo_fig_3_18.html b/_autosummary/pyTEMlib.kinematic_scattering.Zuo_fig_3_18.html new file mode 100644 index 00000000..a8f7e0ac --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.Zuo_fig_3_18.html @@ -0,0 +1,143 @@ + + + + + + + pyTEMlib.kinematic_scattering.Zuo_fig_3_18 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.Zuo_fig_3_18

+
+
+pyTEMlib.kinematic_scattering.Zuo_fig_3_18(verbose=True)[source]
+

Input for Figure 3.18 in Zuo and Spence “Advanced TEM”, 2017

+

This input acts as an example as well as a reference

+
+

Parameters:

+
+
verbose: boolean:

optional to see output

+
+
+
+
+

Returns:

+
+
+
atoms: ase.Atoms

Silicon crystal structure

+
+
+

e +dictionary: tags is the dictionary of all input and output parameter needed to reproduce that figure.

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.check_sanity.html b/_autosummary/pyTEMlib.kinematic_scattering.check_sanity.html new file mode 100644 index 00000000..3adf5e1f --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.check_sanity.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.kinematic_scattering.check_sanity — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.check_sanity

+
+
+pyTEMlib.kinematic_scattering.check_sanity(atoms, verbose_level=0)[source]
+

Check sanity of input parameters

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.example.html b/_autosummary/pyTEMlib.kinematic_scattering.example.html new file mode 100644 index 00000000..0889a00d --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.example.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.kinematic_scattering.example — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.example

+
+
+pyTEMlib.kinematic_scattering.example(verbose=True)[source]
+

same as Zuo_fig_3_18

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.feq.html b/_autosummary/pyTEMlib.kinematic_scattering.feq.html new file mode 100644 index 00000000..b77dffed --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.feq.html @@ -0,0 +1,142 @@ + + + + + + + pyTEMlib.kinematic_scattering.feq — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.feq

+
+
+pyTEMlib.kinematic_scattering.feq(element, q)[source]
+

Atomic form factor parametrized in 1/Angstrom but converted to 1/Angstrom

+

The atomic form factor is from Kirkland: Advanced Computing in Electron Microscopy 2nd edition, Appendix C. +From Appendix C of Kirkland, “Advanced Computing in Electron Microscopy”, 3Ard ed. +Calculation of electron form factor for specific q: +Using equation Kirkland C.15

+
+
Parameters:
+
    +
  • element (string) – element name

  • +
  • q (float) – magnitude of scattering vector in 1/Angstrom – (=> exp(-i*g.r), physics negative convention)

  • +
+
+
Returns:
+

fL+fG – atomic scattering vector

+
+
Return type:
+

float

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.find_angles.html b/_autosummary/pyTEMlib.kinematic_scattering.find_angles.html new file mode 100644 index 00000000..cde35f59 --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.find_angles.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.kinematic_scattering.find_angles — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.find_angles

+
+
+pyTEMlib.kinematic_scattering.find_angles(zone)[source]
+

Microscope stage coordinates of zone

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.find_nearest_zone_axis.html b/_autosummary/pyTEMlib.kinematic_scattering.find_nearest_zone_axis.html new file mode 100644 index 00000000..1d138564 --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.find_nearest_zone_axis.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.kinematic_scattering.find_nearest_zone_axis — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.find_nearest_zone_axis

+
+
+pyTEMlib.kinematic_scattering.find_nearest_zone_axis(tags)[source]
+

Test all zone axis up to a maximum of hkl_max

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.get_dynamically_allowed.html b/_autosummary/pyTEMlib.kinematic_scattering.get_dynamically_allowed.html new file mode 100644 index 00000000..3bacaeaa --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.get_dynamically_allowed.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.kinematic_scattering.get_dynamically_allowed — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.get_dynamically_allowed

+
+
+pyTEMlib.kinematic_scattering.get_dynamically_allowed(atoms, verbose=False)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.get_metric_tensor.html b/_autosummary/pyTEMlib.kinematic_scattering.get_metric_tensor.html new file mode 100644 index 00000000..d1aa591b --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.get_metric_tensor.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.kinematic_scattering.get_metric_tensor — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.get_metric_tensor

+
+
+pyTEMlib.kinematic_scattering.get_metric_tensor(matrix)[source]
+

The metric tensor of the lattice.

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.get_rotation_matrix.html b/_autosummary/pyTEMlib.kinematic_scattering.get_rotation_matrix.html new file mode 100644 index 00000000..52ae888b --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.get_rotation_matrix.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.kinematic_scattering.get_rotation_matrix — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.get_rotation_matrix

+
+
+pyTEMlib.kinematic_scattering.get_rotation_matrix(tags)[source]
+

zone axis in global coordinate system

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.get_wavelength.html b/_autosummary/pyTEMlib.kinematic_scattering.get_wavelength.html new file mode 100644 index 00000000..69f95921 --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.get_wavelength.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.kinematic_scattering.get_wavelength — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.get_wavelength

+
+
+pyTEMlib.kinematic_scattering.get_wavelength(acceleration_voltage)[source]
+

Calculates the relativistic corrected de Broglie wavelength of an electron in Angstrom

+
+

Parameter:

+
+
acceleration_voltage: float

acceleration voltage in volt

+
+
+
+
+

Returns:

+
+
wavelength: float

wave length in Angstrom

+
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.html b/_autosummary/pyTEMlib.kinematic_scattering.html new file mode 100644 index 00000000..f2c7d432 --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.html @@ -0,0 +1,200 @@ + + + + + + + pyTEMlib.kinematic_scattering — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering

+

kinematic_scattering +Copyright by Gerd Duscher

+

The University of Tennessee, Knoxville +Department of Materials Science & Engineering

+
+
Sources:

Scattering Theory: +Zuo and Spence, “Advanced TEM”, 2017

+

Spence and Zuo, Electron Microdiffraction, Plenum 1992

+
+
Atomic Form Factor:

Kirkland: Advanced Computing in Electron Microscopy 2nd edition +Appendix C

+
+
+
+
Units:

everything is in SI units, except length which is given in Angstrom.

+
+
Usage:

See the notebooks for examples of these routines

+
+
+

All the input and output is done through a ase.Atoms object and the dictionary in the info attribute

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Zuo_fig_3_18

Input for Figure 3.18 in Zuo and Spence "Advanced TEM", 2017

check_sanity

Check sanity of input parameters

example

same as Zuo_fig_3_18

feq

Atomic form factor parametrized in 1/Angstrom but converted to 1/Angstrom

find_angles

Microscope stage coordinates of zone

find_nearest_zone_axis

Test all zone axis up to a maximum of hkl_max

get_dynamically_allowed

get_metric_tensor

The metric tensor of the lattice.

get_rotation_matrix

zone axis in global coordinate system

get_wavelength

Calculates the relativistic corrected de Broglie wavelength of an electron in Angstrom

kinematic_scattering

All kinematic scattering calculation

kinematic_scattering2

All kinematic scattering calculation

make_pretty_labels

Make pretty labels

read_poscar

ring_pattern_calculation

Calculate the ring diffraction pattern of a crystal structure

scattering_matrix

Scattering matrix

stage_rotation_matrix

Microscope stage coordinate system

vector_norm

Length of vector

zone_mistilt

Rotation of zone axis by mistilt

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering.html b/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering.html new file mode 100644 index 00000000..dcb42436 --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering.html @@ -0,0 +1,162 @@ + + + + + + + pyTEMlib.kinematic_scattering.kinematic_scattering — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.kinematic_scattering

+
+
+pyTEMlib.kinematic_scattering.kinematic_scattering(atoms, verbose=False)[source]
+

All kinematic scattering calculation

+

Calculates Bragg spots, Kikuchi lines, excess, and deficient HOLZ lines

+
+
Parameters:
+
    +
  • atoms (ase.Atoms) – object with crystal structure: +and with experimental parameters in info attribute: +‘acceleration_voltage_V’, ‘zone_hkl’, ‘Sg_max’, ‘hkl_max’ +Optional parameters are: +‘mistilt’, convergence_angle_mrad’, and ‘crystal_name’ +verbose = True will give extended output of the calculation

  • +
  • verbose (boolean) – default is False

  • +
+
+
Returns:
+

There are three sub_dictionaries in info attribute: +[‘allowed’], [‘forbidden’], and [‘HOLZ’] +[‘allowed’] and [‘forbidden’] dictionaries contain:

+
+

[‘Sg’], [‘hkl’], [‘g’], [‘structure factor’], [‘intensities’], +[‘ZOLZ’], [‘FOLZ’], [‘SOLZ’], [‘HOLZ’], [‘HHOLZ’], [‘label’], and [‘Laue_zone’]

+
+
+
the [‘HOLZ’] dictionary contains:

[‘slope’], [‘distance’], [‘theta’], [‘g_deficient’], [‘g_excess’], [‘hkl’], [‘intensities’], +[‘ZOLZ’], [‘FOLZ’], [‘SOLZ’], [‘HOLZ’], and [‘HHOLZ’]

+
+
+

Please note that the Kikuchi lines are the HOLZ lines of ZOLZ

+
+
There are also a few parameters stored in the main dictionary:

[‘wave_length_nm’], [‘reciprocal_unit_cell’], [‘inner_potential_V’], [‘incident_wave_vector’], +[‘volume’], [‘theta’], [‘phi’], and [‘incident_wave_vector_vacuum’]

+
+
+

+
+
Return type:
+

atoms

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering2.html b/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering2.html new file mode 100644 index 00000000..8a862eda --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering2.html @@ -0,0 +1,162 @@ + + + + + + + pyTEMlib.kinematic_scattering.kinematic_scattering2 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.kinematic_scattering2

+
+
+pyTEMlib.kinematic_scattering.kinematic_scattering2(atoms, verbose=False)[source]
+

All kinematic scattering calculation

+

Calculates Bragg spots, Kikuchi lines, excess, and deficient HOLZ lines

+
+
Parameters:
+
    +
  • atoms (ase.Atoms) – object with crystal structure: +and with experimental parameters in info attribute: +‘acceleration_voltage_V’, ‘zone_hkl’, ‘Sg_max’, ‘hkl_max’ +Optional parameters are: +‘mistilt’, convergence_angle_mrad’, and ‘crystal_name’ +verbose = True will give extended output of the calculation

  • +
  • verbose (boolean) – default is False

  • +
+
+
Returns:
+

There are three sub_dictionaries in info attribute: +[‘allowed’], [‘forbidden’], and [‘HOLZ’] +[‘allowed’] and [‘forbidden’] dictionaries contain:

+
+

[‘Sg’], [‘hkl’], [‘g’], [‘structure factor’], [‘intensities’], +[‘ZOLZ’], [‘FOLZ’], [‘SOLZ’], [‘HOLZ’], [‘HHOLZ’], [‘label’], and [‘Laue_zone’]

+
+
+
the [‘HOLZ’] dictionary contains:

[‘slope’], [‘distance’], [‘theta’], [‘g_deficient’], [‘g_excess’], [‘hkl’], [‘intensities’], +[‘ZOLZ’], [‘FOLZ’], [‘SOLZ’], [‘HOLZ’], and [‘HHOLZ’]

+
+
+

Please note that the Kikuchi lines are the HOLZ lines of ZOLZ

+
+
There are also a few parameters stored in the main dictionary:

[‘wave_length_nm’], [‘reciprocal_unit_cell’], [‘inner_potential_V’], [‘incident_wave_vector’], +[‘volume’], [‘theta’], [‘phi’], and [‘incident_wave_vector_vacuum’]

+
+
+

+
+
Return type:
+

ato,s

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.make_pretty_labels.html b/_autosummary/pyTEMlib.kinematic_scattering.make_pretty_labels.html new file mode 100644 index 00000000..d21dd84c --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.make_pretty_labels.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.kinematic_scattering.make_pretty_labels — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.make_pretty_labels

+
+
+pyTEMlib.kinematic_scattering.make_pretty_labels(hkls, hex_label=False)[source]
+

Make pretty labels

+
+
Parameters:
+
    +
  • hkls (np.ndarray) – a numpy array with all the Miller indices to be labeled

  • +
  • hex_label (boolean - optional) – if True this will make for Miller indices.

  • +
+
+
Returns:
+

hkl_label – list of labels in Latex format

+
+
Return type:
+

list

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.read_poscar.html b/_autosummary/pyTEMlib.kinematic_scattering.read_poscar.html new file mode 100644 index 00000000..56dea72f --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.read_poscar.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.kinematic_scattering.read_poscar — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.read_poscar

+
+
+pyTEMlib.kinematic_scattering.read_poscar(filename)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.ring_pattern_calculation.html b/_autosummary/pyTEMlib.kinematic_scattering.ring_pattern_calculation.html new file mode 100644 index 00000000..7e76d885 --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.ring_pattern_calculation.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.kinematic_scattering.ring_pattern_calculation — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • + View page source +
  • +
+
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.ring_pattern_calculation

+
+
+pyTEMlib.kinematic_scattering.ring_pattern_calculation(atoms, verbose=False)[source]
+

Calculate the ring diffraction pattern of a crystal structure

+
+
Parameters:
+
    +
  • atoms (Crystal) – crystal structure

  • +
  • verbose (verbose print-outs) – set to False

  • +
+
+
Returns:
+

tags – dictionary with diffraction information added

+
+
Return type:
+

dict

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.scattering_matrix.html b/_autosummary/pyTEMlib.kinematic_scattering.scattering_matrix.html new file mode 100644 index 00000000..41a0a625 --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.scattering_matrix.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.kinematic_scattering.scattering_matrix — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.scattering_matrix

+
+
+pyTEMlib.kinematic_scattering.scattering_matrix(tags, verbose_level=1)[source]
+

Scattering matrix

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.stage_rotation_matrix.html b/_autosummary/pyTEMlib.kinematic_scattering.stage_rotation_matrix.html new file mode 100644 index 00000000..a04d084e --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.stage_rotation_matrix.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.kinematic_scattering.stage_rotation_matrix — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.stage_rotation_matrix

+
+
+pyTEMlib.kinematic_scattering.stage_rotation_matrix(alpha, beta)[source]
+

Microscope stage coordinate system

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.vector_norm.html b/_autosummary/pyTEMlib.kinematic_scattering.vector_norm.html new file mode 100644 index 00000000..8a5262b6 --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.vector_norm.html @@ -0,0 +1,125 @@ + + + + + + + pyTEMlib.kinematic_scattering.vector_norm — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.vector_norm

+
+
+pyTEMlib.kinematic_scattering.vector_norm(g)[source]
+

Length of vector

+

depreciated - use np.linalg.norm

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.kinematic_scattering.zone_mistilt.html b/_autosummary/pyTEMlib.kinematic_scattering.zone_mistilt.html new file mode 100644 index 00000000..6e2916d1 --- /dev/null +++ b/_autosummary/pyTEMlib.kinematic_scattering.zone_mistilt.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.kinematic_scattering.zone_mistilt — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.kinematic_scattering.zone_mistilt

+
+
+pyTEMlib.kinematic_scattering.zone_mistilt(zone, angles)[source]
+

Rotation of zone axis by mistilt

+
+
Parameters:
+
    +
  • zone (list or numpy array of int) – zone axis in Miller indices

  • +
  • angles (ist or numpy array of float) – list of mistilt angles in degree

  • +
+
+
Returns:
+

new_zone_axis – new tilted zone axis

+
+
Return type:
+

np.ndarray (3)

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.microscope.Microscope.html b/_autosummary/pyTEMlib.microscope.Microscope.html new file mode 100644 index 00000000..9a84d55b --- /dev/null +++ b/_autosummary/pyTEMlib.microscope.Microscope.html @@ -0,0 +1,165 @@ + + + + + + + pyTEMlib.microscope.Microscope — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.microscope.Microscope

+
+
+class pyTEMlib.microscope.Microscope[source]
+

Bases: object

+

Class to read configuration file and provide microscope information

+

Methods

+ + + + + + + + + + + + +

get_available_microscope_names

load_microscopes

set_microscope

+

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + +

E0

alpha

beta

correlation_factor

microscopes

name

pppc

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.microscope.html b/_autosummary/pyTEMlib.microscope.html new file mode 100644 index 00000000..71852388 --- /dev/null +++ b/_autosummary/pyTEMlib.microscope.html @@ -0,0 +1,131 @@ + + + + + + + pyTEMlib.microscope — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.microscope

+

default microscope parameters from config file

+

Read microscope CSV file

+

for pyTEMLib by Gerd

+

copyright 2012, Gerd Duscher +updated 2021

+

Classes

+ + + + + + +

Microscope

Class to read configuration file and provide microscope information

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.peak_dialog.PeakFitWidget.html b/_autosummary/pyTEMlib.peak_dialog.PeakFitWidget.html new file mode 100644 index 00000000..a03db129 --- /dev/null +++ b/_autosummary/pyTEMlib.peak_dialog.PeakFitWidget.html @@ -0,0 +1,190 @@ + + + + + + + pyTEMlib.peak_dialog.PeakFitWidget — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.peak_dialog.PeakFitWidget

+
+
+class pyTEMlib.peak_dialog.PeakFitWidget(datasets=None)[source]
+

Bases: object

+

Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

find_peaks

find_white_lines

fit_peaks

Fit spectrum with peaks given in peaks dictionary

line_select_callback

make_model

modify_peak_amplitude

modify_peak_position

modify_peak_width

plot

set_action

set_dataset

set_fit_area

set_peak_list

set_y_scale

smooth

Fit lots of Gaussian to spectrum and let the program sort it out

update

+
+
+fit_peaks(value=0)[source]
+

Fit spectrum with peaks given in peaks dictionary

+
+ +
+
+smooth(value=0)[source]
+

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.

+
+ +
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.peak_dialog.get_sidebar.html b/_autosummary/pyTEMlib.peak_dialog.get_sidebar.html new file mode 100644 index 00000000..9f095578 --- /dev/null +++ b/_autosummary/pyTEMlib.peak_dialog.get_sidebar.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.peak_dialog.get_sidebar — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.peak_dialog.get_sidebar

+
+
+pyTEMlib.peak_dialog.get_sidebar()[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.peak_dialog.html b/_autosummary/pyTEMlib.peak_dialog.html new file mode 100644 index 00000000..e06728a3 --- /dev/null +++ b/_autosummary/pyTEMlib.peak_dialog.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.peak_dialog — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.peak_dialog

+

EELS Input Dialog for ELNES Analysis

+

Functions

+ + + + + + + + + +

get_sidebar

smooth

Gaussian mixture model (non-Bayesian)

+

Classes

+ + + + + + +

PeakFitWidget

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.peak_dialog.smooth.html b/_autosummary/pyTEMlib.peak_dialog.smooth.html new file mode 100644 index 00000000..07c2aff4 --- /dev/null +++ b/_autosummary/pyTEMlib.peak_dialog.smooth.html @@ -0,0 +1,126 @@ + + + + + + + pyTEMlib.peak_dialog.smooth — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.peak_dialog.smooth

+
+
+pyTEMlib.peak_dialog.smooth(dataset, iterations, advanced_present)[source]
+

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.

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.peak_dlg.html b/_autosummary/pyTEMlib.peak_dlg.html new file mode 100644 index 00000000..dd832b30 --- /dev/null +++ b/_autosummary/pyTEMlib.peak_dlg.html @@ -0,0 +1,119 @@ + + + + + + + pyTEMlib.peak_dlg — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.peak_dlg

+

GUI definitions for peak_fit_dialog

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.get_chi.html b/_autosummary/pyTEMlib.probe_tools.get_chi.html new file mode 100644 index 00000000..fe4a1984 --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.get_chi.html @@ -0,0 +1,127 @@ + + + + + + + pyTEMlib.probe_tools.get_chi — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.get_chi

+
+
+pyTEMlib.probe_tools.get_chi(ab, size_x, size_y, verbose=False)[source]
+

Get aberration function chi without defocus spread

+

# Internally reciprocal lattice vectors in 1/nm or rad. +# All calculations of chi in angles. +# All aberration coefficients in nm

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.get_chi_2.html b/_autosummary/pyTEMlib.probe_tools.get_chi_2.html new file mode 100644 index 00000000..bdd0b542 --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.get_chi_2.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.probe_tools.get_chi_2 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.get_chi_2

+
+
+pyTEMlib.probe_tools.get_chi_2(ab, u, v)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.get_d2chidu2.html b/_autosummary/pyTEMlib.probe_tools.get_d2chidu2.html new file mode 100644 index 00000000..ff0477c8 --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.get_d2chidu2.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.probe_tools.get_d2chidu2 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.get_d2chidu2

+
+
+pyTEMlib.probe_tools.get_d2chidu2(ab, u, v)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.get_d2chidudv.html b/_autosummary/pyTEMlib.probe_tools.get_d2chidudv.html new file mode 100644 index 00000000..a8666e7e --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.get_d2chidudv.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.probe_tools.get_d2chidudv — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.get_d2chidudv

+
+
+pyTEMlib.probe_tools.get_d2chidudv(ab, u, v)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.get_d2chidv2.html b/_autosummary/pyTEMlib.probe_tools.get_d2chidv2.html new file mode 100644 index 00000000..59443d66 --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.get_d2chidv2.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.probe_tools.get_d2chidv2 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.get_d2chidv2

+
+
+pyTEMlib.probe_tools.get_d2chidv2(ab, u, v)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.get_ronchigram.html b/_autosummary/pyTEMlib.probe_tools.get_ronchigram.html new file mode 100644 index 00000000..103c976c --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.get_ronchigram.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.probe_tools.get_ronchigram — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.get_ronchigram

+
+
+pyTEMlib.probe_tools.get_ronchigram(size, ab, scale='mrad')[source]
+

Get Ronchigram

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.get_ronchigram_2.html b/_autosummary/pyTEMlib.probe_tools.get_ronchigram_2.html new file mode 100644 index 00000000..f07d81fd --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.get_ronchigram_2.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.probe_tools.get_ronchigram_2 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.get_ronchigram_2

+
+
+pyTEMlib.probe_tools.get_ronchigram_2(size, ab, scale='mrad', threshold=3)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.get_source_energy_spread.html b/_autosummary/pyTEMlib.probe_tools.get_source_energy_spread.html new file mode 100644 index 00000000..9350e897 --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.get_source_energy_spread.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.probe_tools.get_source_energy_spread — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.get_source_energy_spread

+
+
+pyTEMlib.probe_tools.get_source_energy_spread()[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.get_target_aberrations.html b/_autosummary/pyTEMlib.probe_tools.get_target_aberrations.html new file mode 100644 index 00000000..04adfa43 --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.get_target_aberrations.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.probe_tools.get_target_aberrations — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.get_target_aberrations

+
+
+pyTEMlib.probe_tools.get_target_aberrations(TEM_name, acceleration_voltage)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.html b/_autosummary/pyTEMlib.probe_tools.html new file mode 100644 index 00000000..9ef928ad --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.html @@ -0,0 +1,175 @@ + + + + + + + pyTEMlib.probe_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools

+

Functions to calculate electron probe

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

get_chi

Get aberration function chi without defocus spread

get_chi_2

get_d2chidu2

get_d2chidudv

get_d2chidv2

get_ronchigram

Get Ronchigram

get_ronchigram_2

get_source_energy_spread

get_target_aberrations

make_chi

make_chi1

# ## # Aberration function chi without defocus # ##

make_gauss

Make a Gaussian shaped probe

make_lorentz

Make a Lorentzian shaped probe

print_aberrations

probe2

    +
  • This function creates an incident STEM probe

  • +
+

zero_loss_peak_weight

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.make_chi.html b/_autosummary/pyTEMlib.probe_tools.make_chi.html new file mode 100644 index 00000000..e9e0fbc6 --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.make_chi.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.probe_tools.make_chi — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.make_chi

+
+
+pyTEMlib.probe_tools.make_chi(phi, theta, aberrations)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.make_chi1.html b/_autosummary/pyTEMlib.probe_tools.make_chi1.html new file mode 100644 index 00000000..ad885725 --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.make_chi1.html @@ -0,0 +1,126 @@ + + + + + + + pyTEMlib.probe_tools.make_chi1 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.make_chi1

+
+
+pyTEMlib.probe_tools.make_chi1(phi, theta, wavelength, ab, c1_include)[source]
+

# ## +# Aberration function chi without defocus +# ##

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.make_gauss.html b/_autosummary/pyTEMlib.probe_tools.make_gauss.html new file mode 100644 index 00000000..9fa3f907 --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.make_gauss.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.probe_tools.make_gauss — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.make_gauss

+
+
+pyTEMlib.probe_tools.make_gauss(size_x, size_y, width=1.0, x0=0.0, y0=0.0, intensity=1.0)[source]
+

Make a Gaussian shaped probe

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.make_lorentz.html b/_autosummary/pyTEMlib.probe_tools.make_lorentz.html new file mode 100644 index 00000000..b9fc5b8c --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.make_lorentz.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.probe_tools.make_lorentz — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.make_lorentz

+
+
+pyTEMlib.probe_tools.make_lorentz(size_x, size_y, gamma=1.0, x0=0.0, y0=0.0, intensity=1.0)[source]
+

Make a Lorentzian shaped probe

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.print_aberrations.html b/_autosummary/pyTEMlib.probe_tools.print_aberrations.html new file mode 100644 index 00000000..5d69d6a0 --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.print_aberrations.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.probe_tools.print_aberrations — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.print_aberrations

+
+
+pyTEMlib.probe_tools.print_aberrations(ab)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.probe2.html b/_autosummary/pyTEMlib.probe_tools.probe2.html new file mode 100644 index 00000000..f7b5cbba --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.probe2.html @@ -0,0 +1,161 @@ + + + + + + + pyTEMlib.probe_tools.probe2 — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.probe2

+
+
+pyTEMlib.probe_tools.probe2(ab, size_x, size_y, tags, verbose=False)[source]
+
    +
  • This function creates an incident STEM probe

  • +
  • at position (0,0)

  • +
  • with parameters given in ab dictionary

  • +
  • +
  • The following Aberration functions are being used:

  • +
    1. +
    2. ddf = Cc*de/E but not + Cc2*(de/E)^2,

    3. +
    +
  • +
  • Cc, Cc2 = chrom. Aber. (1st, 2nd order) [1]

  • +
    1. +
    2. chi(qx,qy) = (2*pi/lambda)*{0.5*C1*(qx^2+qy^2)+

    3. +
    +
  • +
  • 0.5*C12a*(qx^2-qy^2)+

  • +
  • C12b*qx*qy+

  • +
  • C21a/3*qx*(qx^2+qy^2)+

  • +
  • +
  • +0.5*C3*(qx^2+qy^2)^2

  • +
  • +0.125*C5*(qx^2+qy^2)^3

  • +
  • … (need to finish)

  • +
  • +
  • +
  • qx = acos(k_x/K), qy = acos(k_y/K)

  • +
  • +
  • References:

  • +
  • [1] J. Zach, M. Haider,

  • +
  • “Correction of spherical and Chromatic Aberration

  • +
  • in a low Voltage SEM”, Optik 98 (3), 112-118 (1995)

  • +
  • [2] O.L. Krivanek, N. Delby, A.R. Lupini,

  • +
  • “Towards sub-Angstrom Electron Beams”,

  • +
  • Ultramicroscopy 78, 1-11 (1999)

  • +
  • +
+

# Internally reciprocal lattice vectors in 1/nm or rad. +# All calculations of chi in angles. +# All aberration coefficients in nm

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.probe_tools.zero_loss_peak_weight.html b/_autosummary/pyTEMlib.probe_tools.zero_loss_peak_weight.html new file mode 100644 index 00000000..03d12cb0 --- /dev/null +++ b/_autosummary/pyTEMlib.probe_tools.zero_loss_peak_weight.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.probe_tools.zero_loss_peak_weight — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.probe_tools.zero_loss_peak_weight

+
+
+pyTEMlib.probe_tools.zero_loss_peak_weight()[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.sidpy_tools.ChooseDataset.html b/_autosummary/pyTEMlib.sidpy_tools.ChooseDataset.html new file mode 100644 index 00000000..fedde848 --- /dev/null +++ b/_autosummary/pyTEMlib.sidpy_tools.ChooseDataset.html @@ -0,0 +1,142 @@ + + + + + + + pyTEMlib.sidpy_tools.ChooseDataset — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.sidpy_tools.ChooseDataset

+
+
+class pyTEMlib.sidpy_tools.ChooseDataset(input_object, show_dialog=True)[source]
+

Bases: object

+

Widget to select dataset object

+

Methods

+ + + + + + + + + +

get_dataset_list

Get by Log number sorted list of datasets

set_dataset

+
+
+get_dataset_list()[source]
+

Get by Log number sorted list of datasets

+
+ +
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_order.html b/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_order.html new file mode 100644 index 00000000..74dfd3be --- /dev/null +++ b/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_order.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.sidpy_tools.get_dimensions_by_order — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.sidpy_tools.get_dimensions_by_order

+
+
+pyTEMlib.sidpy_tools.get_dimensions_by_order(dims_in, dataset)[source]
+

get dimension

+
+
Parameters:
+
    +
  • dims_in (int or list of int) – the dimensions by numerical order

  • +
  • dataset (sidpy.Dataset) –

  • +
+
+
Returns:
+

dims_out

+
+
Return type:
+

list of dimensions

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_type.html b/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_type.html new file mode 100644 index 00000000..c66d9b9b --- /dev/null +++ b/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_type.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.sidpy_tools.get_dimensions_by_type — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.sidpy_tools.get_dimensions_by_type

+
+
+pyTEMlib.sidpy_tools.get_dimensions_by_type(dims_in, dataset)[source]
+

get dimension by dimension_type name

+
+
Parameters:
+
    +
  • dims_in (dimension_type or list of dimension_types) – the dimensions by numerical order

  • +
  • dataset (sidpy.Dataset) –

  • +
+
+
Returns:
+

dims_out

+
+
Return type:
+

list of dimensions

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.sidpy_tools.get_extent.html b/_autosummary/pyTEMlib.sidpy_tools.get_extent.html new file mode 100644 index 00000000..536a9a97 --- /dev/null +++ b/_autosummary/pyTEMlib.sidpy_tools.get_extent.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.sidpy_tools.get_extent — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.sidpy_tools.get_extent

+
+
+pyTEMlib.sidpy_tools.get_extent(dataset)[source]
+

get extent to plot with matplotlib

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.sidpy_tools.get_image_dims.html b/_autosummary/pyTEMlib.sidpy_tools.get_image_dims.html new file mode 100644 index 00000000..1a2160f7 --- /dev/null +++ b/_autosummary/pyTEMlib.sidpy_tools.get_image_dims.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.sidpy_tools.get_image_dims — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.sidpy_tools.get_image_dims

+
+
+pyTEMlib.sidpy_tools.get_image_dims(dataset)[source]
+

Get all spatial dimensions

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.sidpy_tools.html b/_autosummary/pyTEMlib.sidpy_tools.html new file mode 100644 index 00000000..76ad6c01 --- /dev/null +++ b/_autosummary/pyTEMlib.sidpy_tools.html @@ -0,0 +1,150 @@ + + + + + + + pyTEMlib.sidpy_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.sidpy_tools

+

utility functions for sidpy; will move to sidpy

+

Functions

+ + + + + + + + + + + + + + + + + + + + + +

get_dimensions_by_order

get dimension

get_dimensions_by_type

get dimension by dimension_type name

get_extent

get extent to plot with matplotlib

get_image_dims

Get all spatial dimensions

make_dummy_dataset

Make a dummy sidpy.Dataset

plot

+

Classes

+ + + + + + +

ChooseDataset

Widget to select dataset object

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.sidpy_tools.make_dummy_dataset.html b/_autosummary/pyTEMlib.sidpy_tools.make_dummy_dataset.html new file mode 100644 index 00000000..68756eee --- /dev/null +++ b/_autosummary/pyTEMlib.sidpy_tools.make_dummy_dataset.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.sidpy_tools.make_dummy_dataset — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.sidpy_tools.make_dummy_dataset

+
+
+pyTEMlib.sidpy_tools.make_dummy_dataset(value_type)[source]
+

Make a dummy sidpy.Dataset

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.sidpy_tools.plot.html b/_autosummary/pyTEMlib.sidpy_tools.plot.html new file mode 100644 index 00000000..64876bdd --- /dev/null +++ b/_autosummary/pyTEMlib.sidpy_tools.plot.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.sidpy_tools.plot — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.sidpy_tools.plot

+
+
+pyTEMlib.sidpy_tools.plot(dataset)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.simulation_tools.exciting_get_spectra.html b/_autosummary/pyTEMlib.simulation_tools.exciting_get_spectra.html new file mode 100644 index 00000000..c4ec7c4d --- /dev/null +++ b/_autosummary/pyTEMlib.simulation_tools.exciting_get_spectra.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.simulation_tools.exciting_get_spectra — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.simulation_tools.exciting_get_spectra

+
+
+pyTEMlib.simulation_tools.exciting_get_spectra(file)[source]
+

get EELS spectra from exciting calculation

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.simulation_tools.final_state_broadening.html b/_autosummary/pyTEMlib.simulation_tools.final_state_broadening.html new file mode 100644 index 00000000..6fda066b --- /dev/null +++ b/_autosummary/pyTEMlib.simulation_tools.final_state_broadening.html @@ -0,0 +1,140 @@ + + + + + + + pyTEMlib.simulation_tools.final_state_broadening — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.simulation_tools.final_state_broadening

+
+
+pyTEMlib.simulation_tools.final_state_broadening(x, y, start, instrument)[source]
+

Final state smearing of ELNES edges

+
+
Parameters:
+
    +
  • x (numpy array) – x or energy loss axis of density of states

  • +
  • y (numpy array) – y or intensity axis of density of states

  • +
  • start (float) – start energy of edge

  • +
  • instrument (float) – instrument broadening

  • +
+
+
Returns:
+

out_data – smeared intensity according to final state and instrument broadening

+
+
Return type:
+

numpy array

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.simulation_tools.html b/_autosummary/pyTEMlib.simulation_tools.html new file mode 100644 index 00000000..3e4c190f --- /dev/null +++ b/_autosummary/pyTEMlib.simulation_tools.html @@ -0,0 +1,138 @@ + + + + + + + pyTEMlib.simulation_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.simulation_tools

+

dft simulations tools

+

Part of pyTEMlib +by Gerd Duscher +created 10/29/2020

+

Supports the conversion of DFT data to simulated EELS spectra

+
    +
  • exciting_get_spectra: importing dielectric function from the exciting program

  • +
  • final_state_broadening: apply final state broadening to loss-spectra

  • +
+

Functions

+ + + + + + + + + +

exciting_get_spectra

get EELS spectra from exciting calculation

final_state_broadening

Final state smearing of ELNES edges

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.version.html b/_autosummary/pyTEMlib.version.html new file mode 100644 index 00000000..4512977b --- /dev/null +++ b/_autosummary/pyTEMlib.version.html @@ -0,0 +1,119 @@ + + + + + + + pyTEMlib.version — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.version

+

version

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.viz.CurveVisualizer.html b/_autosummary/pyTEMlib.viz.CurveVisualizer.html new file mode 100644 index 00000000..4a7b6e44 --- /dev/null +++ b/_autosummary/pyTEMlib.viz.CurveVisualizer.html @@ -0,0 +1,139 @@ + + + + + + + pyTEMlib.viz.CurveVisualizer — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.viz.CurveVisualizer

+
+
+class pyTEMlib.viz.CurveVisualizer(dset, spectrum_number=None, axis=None, leg=None, **kwargs)[source]
+

Bases: object

+

Plots a sidpy.Dataset with spectral dimension

+

Methods

+ + + + + + + + + + + + +

onpick

plot

update

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.viz.SpectrumView.html b/_autosummary/pyTEMlib.viz.SpectrumView.html new file mode 100644 index 00000000..a6557bbe --- /dev/null +++ b/_autosummary/pyTEMlib.viz.SpectrumView.html @@ -0,0 +1,151 @@ + + + + + + + pyTEMlib.viz.SpectrumView — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.viz.SpectrumView

+
+
+class pyTEMlib.viz.SpectrumView(datasets, figure=None, **kwargs)[source]
+

Bases: object

+

Methods

+ + + + + + + + + + + + + + + + + + +

add_region

identify_edges

initialize_edge

Intitalizes edge cursor Should be run first so that edge cursor is first

regions_visibility

update_region

+
+
+initialize_edge()[source]
+

Intitalizes edge cursor +Should be run first so that edge cursor is first

+
+ +
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.viz.find_edge_names.html b/_autosummary/pyTEMlib.viz.find_edge_names.html new file mode 100644 index 00000000..9e97c175 --- /dev/null +++ b/_autosummary/pyTEMlib.viz.find_edge_names.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.viz.find_edge_names — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.viz.find_edge_names

+
+
+pyTEMlib.viz.find_edge_names(energy_value)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.viz.html b/_autosummary/pyTEMlib.viz.html new file mode 100644 index 00000000..c2317caa --- /dev/null +++ b/_autosummary/pyTEMlib.viz.html @@ -0,0 +1,156 @@ + + + + + + + pyTEMlib.viz — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.viz

+

plotting of sidpy Datasets with bokeh for google colab

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + +

find_edge_names

plot

plot according to data_type

plot_image

Plotting an image

plot_spectrum

Plot spectrum

plot_stack

Plotting a stack of images

spectrum_view_plotly

verify_spectrum_dataset

+

Classes

+ + + + + + + + + +

CurveVisualizer

Plots a sidpy.Dataset with spectral dimension

SpectrumView

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.viz.plot.html b/_autosummary/pyTEMlib.viz.plot.html new file mode 100644 index 00000000..0c2fb5e0 --- /dev/null +++ b/_autosummary/pyTEMlib.viz.plot.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.viz.plot — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.viz.plot

+
+
+pyTEMlib.viz.plot(dataset, palette='Viridis256')[source]
+

plot according to data_type

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.viz.plot_image.html b/_autosummary/pyTEMlib.viz.plot_image.html new file mode 100644 index 00000000..8a887d67 --- /dev/null +++ b/_autosummary/pyTEMlib.viz.plot_image.html @@ -0,0 +1,145 @@ + + + + + + + pyTEMlib.viz.plot_image — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.viz.plot_image

+
+
+pyTEMlib.viz.plot_image(dataset, palette='Viridis256')[source]
+

Plotting an image

+

Plotting an image contained in a sidpy.Dataset.

+
+
Parameters:
+
    +
  • dataset (sidpy.Dataset) – sidpy dataset with data_type ‘IMAGE_STACK’

  • +
  • palette (bokeh palette) – palette is optional

  • +
+
+
Returns:
+

p

+
+
Return type:
+

bokeh plot

+
+
+

Example

+

>> import pyTEMlib +>> from bokeh.plotting import figure, show, output_notebook +>> output_notebook() +>> p = pyTEMlib.viz(dataset) +>> p.show(p)

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.viz.plot_spectrum.html b/_autosummary/pyTEMlib.viz.plot_spectrum.html new file mode 100644 index 00000000..8e1edce1 --- /dev/null +++ b/_autosummary/pyTEMlib.viz.plot_spectrum.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.viz.plot_spectrum — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.viz.plot_spectrum

+
+
+pyTEMlib.viz.plot_spectrum(dataset, selected_range, palette=None)[source]
+

Plot spectrum

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.viz.plot_stack.html b/_autosummary/pyTEMlib.viz.plot_stack.html new file mode 100644 index 00000000..43c7431d --- /dev/null +++ b/_autosummary/pyTEMlib.viz.plot_stack.html @@ -0,0 +1,146 @@ + + + + + + + pyTEMlib.viz.plot_stack — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.viz.plot_stack

+
+
+pyTEMlib.viz.plot_stack(dataset, palette='Viridis256')[source]
+

Plotting a stack of images

+

Plotting a stack of images contained in a sidpy.Dataset. +The images can be scrolled through with a slider widget.

+
+
Parameters:
+
    +
  • dataset (sidpy.Dataset) – sidpy dataset with data_type ‘IMAGE_STACK’

  • +
  • palette (bokeh palette) – palette is optional

  • +
+
+
Returns:
+

p

+
+
Return type:
+

bokeh plot

+
+
+

Example

+

>> import pyTEMlib +>> from bokeh.plotting import figure, show, output_notebook +>> output_notebook() +>> p = pyTEMlib.viz(dataset) +>> p.show(p)

+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.viz.spectrum_view_plotly.html b/_autosummary/pyTEMlib.viz.spectrum_view_plotly.html new file mode 100644 index 00000000..194bc6c9 --- /dev/null +++ b/_autosummary/pyTEMlib.viz.spectrum_view_plotly.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.viz.spectrum_view_plotly — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.viz.spectrum_view_plotly

+
+
+pyTEMlib.viz.spectrum_view_plotly(datasets, figure=None, show=False)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.viz.verify_spectrum_dataset.html b/_autosummary/pyTEMlib.viz.verify_spectrum_dataset.html new file mode 100644 index 00000000..6a416dc3 --- /dev/null +++ b/_autosummary/pyTEMlib.viz.verify_spectrum_dataset.html @@ -0,0 +1,123 @@ + + + + + + + pyTEMlib.viz.verify_spectrum_dataset — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.viz.verify_spectrum_dataset

+
+
+pyTEMlib.viz.verify_spectrum_dataset(datasets)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_autosummary/pyTEMlib.xrpa_x_sections.html b/_autosummary/pyTEMlib.xrpa_x_sections.html new file mode 100644 index 00000000..263c7053 --- /dev/null +++ b/_autosummary/pyTEMlib.xrpa_x_sections.html @@ -0,0 +1,124 @@ + + + + + + + pyTEMlib.xrpa_x_sections — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib.xrpa_x_sections

+

X-ray photo-absorption cross-sections for inelastic scattering from NIST +The cross sections are given in atoms/nm^3 not barns!! +See xsec_xrpa function in eels_tools for usage.

+

for pyTEMLib by Gerd

+

copyright 2022, Gerd Duscher

+

extended to larger energy scales 01/20/2023

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/index.html b/_modules/index.html new file mode 100644 index 00000000..23589e76 --- /dev/null +++ b/_modules/index.html @@ -0,0 +1,136 @@ + + + + + + Overview: module code — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ + +
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/animation.html b/_modules/pyTEMlib/animation.html new file mode 100644 index 00000000..82915a07 --- /dev/null +++ b/_modules/pyTEMlib/animation.html @@ -0,0 +1,746 @@ + + + + + + pyTEMlib.animation — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.animation

+"""Figures and Animations for TEM in jupyter notebooks
+part of MSE 672 course at UTK
+
+Author: Gerd Duscher
+revision: 01/11/2021
+03/17/2021 added Aberration Animation
+ """
+
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.patches as patches
+
+from ipywidgets import widgets
+from IPython.display import display
+
+import pyTEMlib.kinematic_scattering as ks
+
+
+
[docs]def geometric_ray_diagram(focal_length=1., magnification=False): + """ Sketch of geometric ray diagram od one lens + + Parameters + ---------- + focal_length: float + focal length of lens + magnification: boolean + draw magnification on the side + + Returns + ------- + matplotlib figure + """ + + f = focal_length + + u = 1.5 + v = 1 / (1 / f - 1 / u) + m = v / u + if magnification: + line_strong = .5 + else: + line_strong = 2 + + x = 0.4 + + fig, ax = plt.subplots() + + # add an ellipse + ellipse = patches.Ellipse((0.0, 0.0), 3.4, 0.3, alpha=0.3, color='blue') + ax.add_patch(ellipse) + ax.plot([1.5, -1.5], [0, 0], '--', color='black') + ax.plot([0, 0], [u, -v], '--', color='black') + single_prop = dict(arrowstyle="->", shrinkA=0, shrinkB=0) + double_prop = dict(arrowstyle="<->", shrinkA=0, shrinkB=0) + + if magnification: + ax.annotate("", xy=(-x, u), xytext=(x, u), arrowprops=single_prop) + ax.annotate("", xy=(x * m, -v), xytext=(-x * m, -v), arrowprops=single_prop) + + else: + ax.annotate("", xy=(-x, u), xytext=(0, u), arrowprops=single_prop) + ax.annotate("", xy=(x * m, -v), xytext=(0, -v), arrowprops=single_prop) + + ax.text(x + 0.1, u, 'object plane', va='center') + ax.plot([1, -1], [-f, -f], '--', color='black') + ax.text(1.1, -f, 'back focal\n plane', va='center') + ax.text(x * m + 0.1, -v, 'image plane', va='center') + + ax.annotate("", xy=(-.9, 0), xytext=(-.9, -f), arrowprops=double_prop) + ax.text(-1, -f / 2, 'f') + if magnification: + ax.annotate("", xy=(-1.8, 0), xytext=(-1.8, -v), arrowprops=double_prop) + ax.text(-1.7, -v / 2, 'v') + ax.annotate("", xy=(-1.8, 0), xytext=(-1.8, u), arrowprops=double_prop) + ax.text(-1.7, u / 2, 'u') + + ax.plot([-x, x * m], [u, -v], color='black', linewidth=line_strong) + ax.plot([-x, -x], [u, 0], color='black', linewidth=line_strong) + ax.plot([-x, x * m], [0, -v], color='black', linewidth=line_strong) + + ax.plot([-x, -2 * x], [u, 0], color='black', linewidth=0.5) + ax.plot([-2 * x, x * m], [0, -v], color='black', linewidth=0.5) + if magnification: + ax.plot([x, -x * m], [u, -v], color='black', linewidth=0.5) + ax.plot([x, x], [u, 0], color='black', linewidth=0.5) + ax.plot([x, -x * m], [0, -v], color='black', linewidth=0.5) + + ax.plot([x, 2 * x], [u, 0], color='black', linewidth=0.5) + ax.plot([2 * x, -x * m], [0, -v], color='black', linewidth=0.5) + else: + ax.plot([-x, x * m], [u, 0], color='black', linewidth=0.5) + ax.plot([x * m, x * m], [0, -v], color='black', linewidth=0.5) + + ax.set_xlim(-2, 3) + ax.set_ylim(-3.5, 2) + ax.set_aspect('equal')
+ + +# ---------------------------------------------------------------- +# Modified from Michael Fairchild :simply draws a thin-lens at the provided location parameters: +# - z: location along the optical axis (in mm) +# - f: focal length (in mm, can be negative if div. lens) +# - diam: lens diameter in mm +# - lens_labels: label to identify the lens on the drawing +# ---------------------------------------------------------------- +
[docs]def add_lens(z, f, diam, lens_labels): + """add lens to propagate beam plot""" + ww, tw, rad = diam / 10.0, diam / 3.0, diam / 2.0 + plt.plot([z, z], [-rad, rad], 'k', linewidth=2) + plt.plot([z, z + tw], [-rad, -rad + np.sign(f) * ww], 'k', linewidth=2) + plt.plot([z, z - tw], [-rad, -rad + np.sign(f) * ww], 'k', linewidth=2) + plt.plot([z, z + tw], [rad, rad - np.sign(f) * ww], 'k', linewidth=2) + plt.plot([z, z - tw], [rad, rad - np.sign(f) * ww], 'k', linewidth=2) + plt.plot([z + f, z + f], [-ww, ww], 'k', linewidth=2) + plt.plot([z - f, z - f], [-ww, ww], 'k', linewidth=2) + plt.text(z, rad + 5.0, lens_labels, fontsize=12) + plt.text(z, rad + 2.0, 'f=' + str(int(f)), fontsize=10)
+ + +
[docs]def add_aperture(z, diam, radius, lens_labels): + """add aperture to propagate beam plot""" + + ww, tw, rad = diam / 10.0, diam / 3.0, diam / 2.0 + radius = radius / 2 + plt.plot([z, z], [-rad, -radius], 'k', linewidth=2) + plt.plot([z, z], [rad, radius], 'k', linewidth=2) + plt.text(z, -rad - 2.0, lens_labels, fontsize=12)
+ + +
[docs]def propagate_beam(source_position, numerical_aperture, number_of_rays, lens_positions, focal_lengths, + lens_labels='', color='b'): + """geometrical propagation of light rays from given source + + Parameters + ---------- + source_position: list + location of the source (z0, x0) along and off axis (in mm) + numerical_aperture: float + numerical aperture of the beam (in degrees) + number_of_rays: int + number of rays to trace + lens_positions: numpy array + array with the location of the lenses + focal_lengths: numpy array + array with the focal length of lenses + lens_labels: list of string + label for the nature of lenses + color: str + color of the rays on plot + """ + + plt.figure() + z_max = 1600. + + # aperture (maximum angle) in radians + apa = numerical_aperture * np.pi / 180.0 + + for i in range(np.size(lens_positions)): + add_lens(lens_positions[i], focal_lengths[i], 25, lens_labels[i]) + + add_aperture(840, 25, 7, 'CA') + + # position of source is z0,x0 + z0 = source_position[0] + if np.size(source_position) == 2: + x0 = source_position[1] + else: + x0 = 0.0 + + # list of lens positions + zl1, ff1 = lens_positions[(z0 < lens_positions)], focal_lengths[(z0 < lens_positions)] + nl = np.size(zl1) # number of lenses + + zz, xx, tani = np.zeros(nl + 2), np.zeros(nl + 2), np.zeros(nl + 2) + tan0 = np.tan(apa / 2.0) - np.tan(apa) * np.arange(number_of_rays) / (number_of_rays - 1) + + for i in range(number_of_rays): + tani[0] = tan0[i] # initial incidence angle + zz[0], xx[0] = z0, x0 + for j in range(nl): + zz[j + 1] = zl1[j] + xx[j + 1] = xx[j] + (zz[j + 1] - zz[j]) * tani[j] + tani[j + 1] = tani[j] - xx[j + 1] / ff1[j] + + zz[nl + 1] = z_max + xx[nl + 1] = xx[nl] + (zz[nl + 1] - zz[nl]) * tani[nl] + plt.plot(zz, xx, color) + plt.axis([-20, z_max, -20, 20])
+ + +
[docs]def deficient_holz_line(exact_bragg=False, shift=False, laue_zone=1, color='black'): + """ + Ewald sphere construction to explain Laue Circle and deficient HOLZ lines + + Parameters: + exact_bragg: boolean + whether to tilt into exact Bragg condition or along zone axis + shift: boolean + whether to shift exact Bragg-condition onto zone axis origin + laue_zone: int + first or second Laue zone only + color: string + color of wave vectors and Ewald sphere + """ + + k_0 = [0, 1 / ks.get_wavelength(600)] + + d = 5. # lattice parameter in nm + + if laue_zone == 0: + s_g = 1 / d + 0.06 + else: + s_g = .1 + + g = np.linspace(-5, 6, 12) * 1 / d + g_d = np.array([5. / d + laue_zone * 1 / d / 2, laue_zone * 1 / d]) + g_sg = g_d.copy() + g_sg[1] = g_d[1] + s_g # point on Ewald sphere + + # reciprocal lattice + plt.scatter(g[:-1], [0] * 11, color='red') + plt.scatter(g - 1 / d / 2, [1 / d] * 12, color='blue') + + shift_x = shift_y = 0. + d_theta = d_theta1 = d_theta2 = 0 + + if exact_bragg: + + d_theta1 = np.arctan((1 / d * laue_zone + s_g) / g_d[0]) + d_theta2 = np.arctan((1 / d * laue_zone) / g_d[0]) + d_theta = -(d_theta1 - d_theta2) + s_g = 0 + s = np.sin(d_theta) + c = np.cos(d_theta) + k_0 = [-s * k_0[1], c * k_0[1]] + if shift: + shift_x = -k_0[0] + shift_y = np.linalg.norm(k_0) - k_0[1] + d_theta = np.degrees(d_theta) + + k_0[0] += shift_x + k_0[1] += shift_y + + # Ewald Sphere + ewald_sphere = patches.Circle((k_0[0], k_0[1]), radius=np.linalg.norm(k_0), clip_on=False, zorder=10, linewidth=1, + edgecolor=color, fill=False) + plt.gca().add_artist(ewald_sphere) + + plt.gca().arrow(g[-1] + .1 / d / 4, 1 / d / 2, 0, 1 / d / 2, head_width=0.03, head_length=0.04, fc='k', ec='k', + length_includes_head=True) + plt.gca().arrow(g[-1] + .1 / d / 4, 1 / d / 2, 0, -1 / d / 2, head_width=0.03, head_length=0.04, fc='k', ec='k', + length_includes_head=True) + plt.gca().annotate("$|g_{HOLZ}|$", xytext=(g[-1] + .1 / d / 3, 1 / d / 3), xy=(g[-1] + 1 / d / 3, 1 / d / 3)) + + # k_0 + plt.scatter(k_0[0], k_0[1]) + plt.gca().arrow(k_0[0], k_0[1], -k_0[0] + shift_x, -k_0[1] + shift_y, head_width=0.03, head_length=0.04, fc=color, + ec=color, length_includes_head=True) + plt.gca().annotate("K$_0$", xytext=(k_0[0] / 2, k_0[1] / 3), xy=(k_0[0] / 2, k_0[1] / 2)) + + # K_d Bragg of HOLZ reflection + plt.gca().arrow(k_0[0], k_0[1], -k_0[0] + g_d[0] + shift_x, -k_0[1] + g_d[1] + s_g + shift_y, head_width=0.03, + head_length=0.04, fc=color, + ec=color, length_includes_head=True) + plt.gca().annotate("K$_d$", xytext=(k_0[0] + (g_d[0] - k_0[0]) / 2, k_0[1] / 2), xy=(6.5 / d / 2, k_0[1] / 2)) + + # s_g excitation Error of HOLZ reflection + if s_g > 0: + plt.gca().arrow(g_d[0], g_d[1], 0, s_g, head_width=0.03, head_length=0.04, fc='k', + ec='k', length_includes_head=True) + plt.gca().annotate("s$_g$", xytext=(g_d[0] * 1.01, g_d[1] + s_g / 3), xy=(g_d[0] * 1.01, g_d[1] + s_g / 3)) + + # Bragg angle + g_sg = g_d + g_sg[1] = g_d[1] + s_g + plt.plot([0 + shift_x, g_sg[0] + shift_x], [0 + shift_y, g_d[1] + shift_y], color=color, linewidth=1, alpha=0.5, + linestyle='--') + plt.plot([k_0[0], g_sg[0] / 2 + shift_x], [k_0[1], g_sg[1] / 2 + shift_y], color=color, linewidth=1, alpha=0.5, + linestyle='--') + # d_theta = np.degrees(np.arctan(k_0[0]/k_0[1])) + bragg_angle = patches.Arc((k_0[0], k_0[1]), width=k_0[1], height=k_0[1], theta1=-90 + d_theta, + theta2=-90 + d_theta + np.degrees(np.arcsin(np.linalg.norm(g_sg / 2) / k_0[1])), fc=color, + ec=color) + + plt.gca().annotate(r"$\theta $", xytext=(k_0[0] / 1.3, k_0[1] / 1.5), xy=(k_0[0] / 2 + g_d[0] / 4, k_0[1] / 2)) + plt.gca().add_patch(bragg_angle) + + # deviation/tilt angle + if np.abs(d_theta) > 0: + if shift: + deviation_angle = patches.Arc((k_0[0], k_0[1]), width=k_0[1] * 1.5, height=k_0[1] * 1.5, + theta1=-90 + d_theta, + theta2=-90, + fc=color, ec=color, linewidth=3) + plt.gca().annotate(r"$d \theta $", xytext=(k_0[0] - .13, k_0[1] / 3.7), + xy=(k_0[0] + g_d[0] / 4, k_0[1] / 2)) + plt.gca().arrow(shift_x, -.2, 0, .2, head_width=0.05, head_length=0.06, fc=color, ec='black', + length_includes_head=True, linewidth=3) + plt.gca().annotate("deficient line", xytext=(shift_x * 2, -.2), xy=(shift_x, 0)) + else: + deviation_angle = patches.Arc((0, 0), width=k_0[1], height=k_0[1], + theta1=np.degrees(d_theta2), + theta2=np.degrees(d_theta1), + fc=color, ec=color, linewidth=3) + plt.gca().annotate(r"$d \theta $", xytext=(g_d[0] * .8, 1 / d / 3), xy=(g_d[0], 1 / d)) + + plt.gca().add_patch(deviation_angle) + plt.gca().set_aspect('equal') + plt.gca().set_ylim(-.5, 2.2) + plt.gca().set_xlim(-1.1, 1.6)
+ + +
[docs]def deficient_kikuchi_line(s_g=0., color_b='black'): + k_len = 1 / ks.get_wavelength(20) + d = 2 # lattice parameter in nm + + g = np.linspace(-2, 2, 5) * 1 / d + g_d = np.array([1 / d, 0]) + + # reciprocal lattice + plt.scatter(g, [0] * 5, color='blue') + + alpha = -np.arctan(s_g / g_d[0]) + theta = -np.arcsin(g_d[0] / 2 / k_len) + + k_0 = np.array([-np.sin(theta - alpha) * k_len, np.cos(theta - alpha) * k_len]) + k_d = np.array([-np.sin(-theta - alpha) * k_len, np.cos(-theta - alpha) * k_len]) + k_i = np.array([-np.sin(theta - alpha) * 1., np.cos(theta - alpha) * 1.]) + k_i_t = np.array([-np.sin(-alpha), np.cos(-alpha)]) + + kk_e = np.array([-np.sin(-theta) * k_len, np.cos(-theta) * k_len]) + kk_d = np.array([-np.sin(theta) * k_len, np.cos(theta) * k_len]) + + # Ewald Sphere + ewald_sphere = patches.Circle((k_0[0], k_0[1]), radius=np.linalg.norm(k_0), clip_on=False, zorder=10, linewidth=1, + edgecolor=color_b, fill=False) + plt.gca().add_artist(ewald_sphere) + + # K_0 + plt.plot([k_0[0], k_0[0]], [k_0[1], k_0[1] + .4], color='gray', linestyle='-', alpha=0.3) + + plt.gca().arrow(k_0[0] + k_i[0], k_0[1] + k_i[1], -k_i[0], -k_i[1], head_width=0.01, head_length=0.015, fc=color_b, + ec=color_b, length_includes_head=True) + plt.plot([k_0[0] + k_i_t[0], k_0[0] - k_i_t[0]], [k_0[1] + k_i_t[1], k_0[1] - k_i_t[1]], color='black', + linestyle='--', alpha=0.5) + plt.scatter(k_0[0], k_0[1], color='black') + plt.gca().arrow(k_0[0], k_0[1], -k_0[0], -k_0[1], head_width=0.01, head_length=0.015, fc=color_b, + ec=color_b, length_includes_head=True) + plt.gca().annotate("K$_0$", xytext=(-k_0[0] / 2, 0), xy=(k_0[0] / 2, 0)) + + plt.gca().arrow(k_0[0], k_0[1], -k_d[0], -k_d[1], head_width=0.01, head_length=0.015, fc=color_b, + ec=color_b, length_includes_head=True) + # K_e excess line + plt.gca().arrow(k_0[0], k_0[1], -kk_e[0], -kk_e[1], head_width=0.01, head_length=0.015, fc='red', + ec='red', length_includes_head=True) + plt.gca().annotate("excess", xytext=(k_0[0] - kk_e[0], -1), xy=(-kk_e[0] + k_0[0], 0)) + plt.plot([k_0[0] - kk_e[0], k_0[0] - kk_e[0]], [-.1, .1], color='red') + + # k_d deficient line + plt.gca().arrow(k_0[0], k_0[1], -kk_d[0], -kk_d[1], head_width=0.01, head_length=0.015, fc='blue', + ec='blue', length_includes_head=True) + plt.plot([k_0[0] - kk_d[0], k_0[0] - kk_d[0]], [-.1, .1], color='blue') + plt.gca().annotate("deficient", xytext=(k_0[0] - kk_d[0], -1), xy=(k_0[0] - kk_d[0], 0)) + + # s_g excitation Error of HOLZ reflection + plt.gca().arrow(g_d[0], g_d[1], 0, s_g, head_width=0.01, head_length=0.015, fc='k', + ec='k', length_includes_head=True) + plt.gca().annotate("s$_g$", xytext=(g_d[0] * 1.01, g_d[1] + s_g / 3), xy=(g_d[0] * 1.01, g_d[1] + s_g / 3)) + + theta = np.degrees(theta) + alpha = np.degrees(alpha) + + bragg_angle = patches.Arc((k_0[0], k_0[1]), width=.55, height=.55, + theta1=90 + theta - alpha, theta2=90 - alpha, fc='black', ec='black') + if alpha > 0: + deviation_angle = patches.Arc((k_0[0], k_0[1]), width=.6, height=.6, + theta1=90 - alpha, theta2=90, fc='black', ec='red') + else: + deviation_angle = patches.Arc((k_0[0], k_0[1]), width=.6, height=.6, + theta1=90, theta2=90 - alpha, fc='black', ec='red') + + plt.gca().annotate(r"$\theta$", xytext=(k_0[0] + k_i_t[0] / 20, k_0[1] + .2), xy=(k_0[0] + k_i_t[0], k_0[1] + .2)) + plt.gca().annotate(r"$\alpha$", xytext=(k_0[0] + k_i_t[0] / 10, k_0[1] + .3), xy=(k_0[0] + k_i_t[0], k_0[1] + .3), + color='red') + plt.gca().add_patch(bragg_angle) + plt.gca().add_patch(deviation_angle) + + plt.gca().set_aspect('equal') + plt.gca().set_xlabel('angle (1/$\AA$)') + plt.gca().set_ylim(-.1, k_0[1] * 2.2) + plt.gca().set_xlim(-.2, 1.03)
+ + +
[docs]class InteractiveAberration(object): + """ + ### Interactive explanation of aberrations + + """ + + def __init__(self, horizontal=True): + + box_layout = widgets.Layout(display='flex', + flex_flow='row', + align_items='stretch', + width='100%') + + self.words = ['ideal rays', 'aberrated rays', 'aberrated wavefront', 'aberration function'] + + self.buttons = [widgets.ToggleButton(value=False, description=word, disabled=False) for word in self.words] + box = widgets.Box(children=self.buttons, layout=box_layout) + display(box) + + # Button(description='edge_quantification') + for button in self.buttons: + button.observe(self.on_button_clicked, 'value') # on_click(self.on_button_clicked) + + self.figure = plt.figure() + self.ax = plt.gca() + self.horizontal = horizontal + self.ax.set_aspect('equal') + self.analysis = [] + self.update() + # self.cid = self.figure.canvas.mpl_connect('button_press_event', self.onclick) + + def on_button_clicked(self, b): + # print(b['owner'].description) + selection = b['owner'].description + if selection in self.analysis: + self.analysis.remove(selection) + else: + self.analysis.append(selection) + self.update() + + def update(self): + ax = self.ax + ax.clear() + selection = self.analysis + ax.plot([0, 15], [0, 0], color='black') + ax.plot([9, 9], [-.3, .3], color='black') + lens = patches.Ellipse((2, 0), + width=.4, + height=7, + facecolor='gray') + ax.add_patch(lens) + ax.set_ylim(-6.5, 6.5) + ax.set_aspect('equal') + + if self.words[0] in selection: + color = 'gray' + ax.plot([0, 2], [1, 1], color=color) + ax.plot([0, 2], [-1, -1], color=color) + ax.plot([2, 9], [1, 0], color=color) + ax.plot([2, 9], [-1, 0], color=color) + + gauss = patches.Ellipse((9, 0), + width=12, + height=12, + fill=False) + ax.add_patch(gauss) + + if self.words[1] in selection: + color = 'blue' + ax.plot([0, 2], [2, 2], color=color) + ax.plot([0, 2], [-2, -2], color=color) + ax.plot([2, 7], [2, 0], color=color) + ax.plot([2, 7], [-2, 0], color=color) + gauss2 = patches.Ellipse((7, 0), + width=8, + height=8, + fill=False, + color=color, linestyle='--') + plt.gca().add_patch(gauss2) + + if self.words[2] in selection: + color = 'red' + ax.plot([0, 2], [2, 2], color=color) + ax.plot([0, 2], [-2, -2], color=color) + ax.plot([2, 7], [2, 0], color=color) + ax.plot([2, 7], [-2, 0], color=color) + ax.plot([0, 2], [1, 1], color=color) + ax.plot([0, 2], [-1, -1], color=color) + ax.plot([2, 9], [1, 0], color=color) + ax.plot([2, 9], [-1, 0], color=color) + gauss3 = patches.Ellipse((9, 0), + width=12, + height=9.7, + fill=False, + color=color) + plt.gca().add_patch(gauss3) + + if self.words[3] in selection: + color = 'green' + x = np.arange(100) / 100 - 6 + x2 = np.arange(100) / 100 * 1.5 - 6 + b = 4.8 + a = 6 + y = np.sqrt(a ** 2 - x ** 2) + y2 = b / a * np.sqrt(a ** 2 - x2 ** 2) + + x = np.append(x[::-1], x[1:]) + y = np.append(y[::-1], -y[1:]) + x2 = np.append(x2[::-1], x2[1:]) + y2 = np.append(y2[::-1], -y2[1:]) + + dif = y2 - y + + x = np.append(x[::-1], x2) + y = np.append(y[::-1], y2) + aberration = patches.Polygon(np.array([x + 9, y]).T, + fill=True, + color=color, alpha=.5) + + aberration2 = patches.Polygon(np.array( + [np.append(np.abs(dif), [0, 0]) * 2 + 2.5, np.append(np.linspace(-3.3, 3.3, len(dif)), [3.3, -3.3])]).T, + fill=True, + color=color, alpha=.9) + + plt.gca().add_patch(aberration) + plt.gca().add_patch(aberration2)
+ + +
[docs]class InteractiveRonchigramMagnification(object): + """ + ### Interactive explanation of magnification + + """ + + def __init__(self, horizontal=True): + + box_layout = widgets.Layout(display='flex', + flex_flow='row', + align_items='stretch', + width='100%') + + self.words = ['ideal rays', 'radial circle rays', 'axial circle rays', 'over-focused rays'] + + self.buttons = [widgets.ToggleButton(value=False, description=word, disabled=False) for word in self.words] + box = widgets.Box(children=self.buttons, layout=box_layout) + display(box) + + # Button(description='edge_quantification') + for button in self.buttons: + button.observe(self.on_button_clicked, 'value') # on_click(self.on_button_clicked) + + self.figure = plt.figure() + self.ax = plt.gca() + self.horizontal = horizontal + self.ax.set_aspect('equal') + self.analysis = [] + self.update() + # self.cid = self.figure.canvas.mpl_connect('button_press_event', self.onclick) + + def on_button_clicked(self, b): + # print(b['owner'].description) + selection = b['owner'].description + if selection in self.analysis: + self.analysis.remove(selection) + else: + self.analysis.append(selection) + self.update() + + def update(self): + ax = self.ax + ax.clear() + selection = self.analysis + ax.plot([0, 24], [0, 0], color='black') + ax.plot([14, 14], [-.3, .3], color='black') + ax.text(14, 1, s='f') + lens = patches.Ellipse((4, 0), + width=.8, + height=14, + facecolor='gray') + ax.add_patch(lens) + ax.text(4, 8, s='lens') + sample = patches.Rectangle((10, -2), + width=.2, + height=4, + facecolor='gray') + + ax.add_patch(sample) + ax.text(9, 3, s='sample') + ax.set_ylim(-10, 10) + ax.set_aspect('equal') + + if self.words[0] in selection: + color = 'gray' + ax.plot([0, 4], [1, 1], color=color) + ax.plot([0, 4], [-1, -1], color=color) + ax.plot([4, 24], [1, -1], color=color) + ax.plot([4, 24], [-1, 1], color=color) + + circle1 = patches.Ellipse((24, 0), width=.2, height=2, fill=False, color=color) + ax.add_patch(circle1) + + if self.words[1] in selection: + color = 'red' + ax.plot([0, 4], [3, 3], color=color) + ax.plot([0, 4], [-3, -3], color=color) + ax.plot([4, 24], [3, -4], color=color) + ax.plot([4, 24], [-3, 4], color=color) + ax.plot([0, 4], [2.5, 2.5], color=color) + ax.plot([0, 4], [-2.50, -2.5], color=color) + ax.plot([4, 24], [2.5, -2.8], color=color) + ax.plot([4, 24], [-2.5, 2.8], color=color) + + circle2 = patches.Ellipse((24, 0), width=.9, height=8, fill=False, color=color) + ax.add_patch(circle2) + circle3 = patches.Ellipse((24, 0), width=.6, height=5.6, fill=False, color=color) + ax.add_patch(circle3) + circle3 = patches.Ellipse((24, 0), width=.7, height=7.3, fill=False, color=color, linewidth=5, alpha=.5) + ax.add_patch(circle3) + + if self.words[2] in selection: + color = 'orange' + ax.plot([0, 4], [4, 4], color=color) + ax.plot([0, 4], [-4, -4], color=color) + ax.plot([4, 24], [4, -9.25], color=color) + ax.plot([4, 24], [-4, 9.25], color=color) + + circle4 = patches.Ellipse((24, 0), width=2, height=18.5, fill=False, color=color) + plt.gca().add_patch(circle4) + + if self.words[3] in selection: + color = 'green' + ax.plot([0, 4], [5, 5], color=color, linestyle='--') + ax.plot([0, 4], [-5, -5], color=color, linestyle='--') + ax.plot([4, 24], [5, -13], color=color, linestyle='--') + ax.plot([4, 24], [-5, 13], color=color, linestyle='--') + + circle6 = patches.Ellipse((24, 0), width=4, height=26, fill=False, color=color, linestyle='--') + plt.gca().add_patch(circle6)
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/atom_tools.html b/_modules/pyTEMlib/atom_tools.html new file mode 100644 index 00000000..3016b459 --- /dev/null +++ b/_modules/pyTEMlib/atom_tools.html @@ -0,0 +1,355 @@ + + + + + + pyTEMlib.atom_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.atom_tools

+""" Atom detection
+
+All atom detection is done here
+Everything is in unit of pixel!!
+
+Author: Gerd Duscher
+
+part of pyTEMlib
+
+a pycroscopy package
+"""
+
+import numpy as np
+import sys
+
+# from skimage.feature import peak_local_max
+from skimage.feature import blob_log
+
+from sklearn.cluster import KMeans
+from scipy.spatial import cKDTree
+import scipy.optimize as optimization
+
+import pyTEMlib.probe_tools as probe_tools
+import pyTEMlib.file_tools as ft
+import sidpy
+from tqdm.auto import trange
+
+
+
[docs]def find_atoms(image, atom_size=0.1, threshold=0.): + """ Find atoms is a simple wrapper for blob_log in skimage.feature + + Parameters + ---------- + image: sidpy.Dataset + the image to find atoms + atom_size: float + visible size of atom blob diameter in nm gives minimal distance between found blobs + threshold: float + threshold for blob finder; (usually between 0.001 and 1.0) for threshold <= 0 we use the RMS contrast + + Returns + ------- + atoms: numpy array(Nx3) + atoms positions and radius of blob + """ + + if not isinstance(image, sidpy.Dataset): + raise TypeError('We need a sidpy.Dataset') + if image.data_type.name != 'IMAGE': + raise TypeError('We need sidpy.Dataset of sidpy.Datatype: IMAGE') + if not isinstance(atom_size, (float, int)): + raise TypeError('atom_size parameter has to be a number') + if not isinstance(threshold, float): + raise TypeError('threshold parameter has to be a float number') + + scale_x = ft.get_slope(image.dim_0) + im = np.array(image-image.min()) + im = im/im.max() + if threshold <= 0.: + threshold = np.std(im) + atoms = blob_log(im, max_sigma=atom_size/scale_x, threshold=threshold) + + return atoms
+ + +
[docs]def atoms_clustering(atoms, mid_atoms, number_of_clusters=3, nearest_neighbours=7): + """ A wrapper for sklearn.cluster kmeans clustering of atoms. + + Parameters + ---------- + atoms: list or np.array (Nx2) + list of all atoms + mid_atoms: list or np.array (Nx2) + atoms to be evaluated + number_of_clusters: int + number of clusters to sort (ini=3) + nearest_neighbours: int + number of nearest neighbours evaluated + + Returns + ------- + clusters, distances, indices: numpy arrays + """ + + # get distances + nn_tree = cKDTree(np.array(atoms)[:, 0:2]) + + distances, indices = nn_tree.query(np.array(mid_atoms)[:, 0:2], nearest_neighbours) + + # Clustering + k_means = KMeans(n_clusters=number_of_clusters, random_state=0) # Fixing the RNG in kmeans + k_means.fit(distances) + clusters = k_means.predict(distances) + + return clusters, distances, indices
+ + +
[docs]def gauss_difference(params, area): + """ + Difference between part of an image and a Gaussian + This function is used int he atom refine function of pyTEMlib + + Parameters + ---------- + params: list + list of Gaussian parameters [width, position_x, position_y, intensity] + area: numpy array + 2D matrix = part of an image + + Returns + ------- + numpy array: flattened array of difference + + """ + gauss = probe_tools.make_gauss(area.shape[0], area.shape[1], width=params[0], x0=params[1], y0=params[2], + intensity=params[3]) + return (area - gauss).flatten()
+ + +
[docs]def atom_refine(image, atoms, radius, max_int=0, min_int=0, max_dist=4): + """Fits a Gaussian in a blob of an image + + Parameters + ---------- + image: np.array or sidpy Dataset + atoms: list or np.array + positions of atoms + radius: float + radius of circular mask to define fitting of Gaussian + max_int: float + optional - maximum intensity to be considered for fitting (to exclude contaminated areas for example) + min_int: float + optional - minimum intensity to be considered for fitting (to exclude contaminated holes for example) + max_dist: float + optional - maximum distance of movement of Gaussian during fitting + + Returns + ------- + sym: dict + dictionary containing new atom positions and other output such as intensity of the fitted Gaussian + """ + rr = int(radius + 0.5) # atom radius + print('using radius ', rr, 'pixels') + + pixels = np.linspace(0, 2 * rr, 2 * rr + 1) - rr + x, y = np.meshgrid(pixels, pixels) + mask = (x ** 2 + y ** 2) < rr ** 2 + + guess = [rr * 2, 0.0, 0.0, 1] + + sym = {'number_of_atoms': len(atoms)} + + volume = [] + position = [] + intensities = [] + maximum_area = [] + new_atoms = [] + gauss_width = [] + gauss_amplitude = [] + gauss_intensity = [] + + for i in trange(len(atoms)): + x, y = atoms[i][0:2] + x = int(x) + y = int(y) + + area = image[x - rr:x + rr + 1, y - rr:y + rr + 1] + + append = False + + if (x - rr) < 0 or y - rr < 0 or x + rr + 1 > image.shape[0] or y + rr + 1 > image.shape[1]: # atom not found + position.append(-1) + intensities.append(-1.) + maximum_area.append(-1.) + else: # atom found + position.append(1) + intensities.append((area * mask).sum()) + maximum_area.append((area * mask).max()) + + if max_int > 0: + if area.sum() < max_int: + if area.sum() > min_int: + append = True + elif area.sum() > min_int: + append = True + + pout = [0, 0, 0, 0] + if append: + if (x - rr) < 0 or y - rr < 0 or x + rr + 1 > image.shape[0] or y + rr + 1 > image.shape[1]: + pass + else: + [pout, _] = optimization.leastsq(gauss_difference, guess, args=area) + + if (abs(pout[1]) > max_dist) or (abs(pout[2]) > max_dist): + pout = [0, 0, 0, 0] + + volume.append(2 * np.pi * pout[3] * pout[0] * pout[0]) + + new_atoms.append([x + pout[1], y + pout[2]]) # ,pout[0], volume)) #,pout[3])) + if all(v == 0 for v in pout): + gauss_intensity.append(0.) + else: + gauss = probe_tools.make_gauss(area.shape[0], area.shape[1], width=pout[0], x0=pout[1], y0=pout[2], + intensity=pout[3]) + gauss_intensity.append((gauss * mask).sum()) + gauss_width.append(pout[0]) + gauss_amplitude.append(pout[3]) + + sym['inside'] = position + sym['intensity_area'] = intensities + sym['maximum_area'] = maximum_area + sym['atoms'] = new_atoms + sym['gauss_width'] = gauss_width + sym['gauss_amplitude'] = gauss_amplitude + sym['gauss_intensity'] = gauss_intensity + sym['gauss_volume'] = volume + + return sym
+ + +
[docs]def intensity_area(image, atoms, radius): + """ + integrated intensity of atoms in an image with a mask around each atom of radius radius + """ + rr = int(radius + 0.5) # atom radius + print('using radius ', rr, 'pixels') + + pixels = np.linspace(0, 2 * rr, 2 * rr + 1) - rr + x, y = np.meshgrid(pixels, pixels) + mask = np.array((x ** 2 + y ** 2) < rr ** 2) + intensities = [] + for i in range(len(atoms)): + x = int(atoms[i][1]) + y = int(atoms[i][0]) + area = image[x - rr:x + rr + 1, y - rr:y + rr + 1] + if area.shape == mask.shape: + intensities.append((area * mask).sum()) + else: + intensities.append(-1) + return intensities
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/crystal_tools.html b/_modules/pyTEMlib/crystal_tools.html new file mode 100644 index 00000000..54b0125e --- /dev/null +++ b/_modules/pyTEMlib/crystal_tools.html @@ -0,0 +1,1374 @@ + + + + + + pyTEMlib.crystal_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.crystal_tools

+"""
+crystal_tools
+
+part of pyTEMlib
+
+Author: Gerd Duscher
+
+Provides convenient functions to make most regular crystal structures
+
+Contains also a dictionary of crystal structures and atomic form factors
+
+Units:
+    everything is in SI units, except length is given in nm.
+    angles are assumed to be in degree but will be internally converted to rad
+
+Usage:
+    See the notebooks for examples of these routines
+
+"""
+
+import numpy as np
+import itertools
+import ase
+import ase.spacegroup
+import ase.build
+import ase.data.colors
+
+import matplotlib.pylab as plt  # basic plotting
+from scipy.spatial import cKDTree
+_spglib_present = True
+try:
+    import spglib
+except ModuleNotFoundError:
+    _spglib_present = False
+
+if _spglib_present:
+    print('Symmetry functions of spglib enabled')
+else:
+    print('spglib not installed; Symmetry functions of spglib disabled')
+
+
+# from mpl_toolkits.mplot3d import Axes3D  # 3D plotting
+# from matplotlib.patches import Circle  # , Ellipse, Rectangle
+# from matplotlib.collections import PatchCollection
+
+
+
[docs]def get_dictionary(atoms): + """ + structure dictionary from ase.Atoms object + """ + tags = {'unit_cell': atoms.cell.array, + 'elements': atoms.get_chemical_formula(), + 'base': atoms.get_scaled_positions(), + 'metadata': atoms.info} + + return tags
+ + +
[docs]def atoms_from_dictionary(tags): + atoms = ase.Atoms(cell=tags['unit_cell'], + symbols=tags['elements'], + scaled_positions=tags['base']) + if 'metadata' in tags: + atoms.info = tags['metadata'] + return atoms
+ + +
[docs]def get_symmetry(atoms, verbose=True): + """ + Symmetry analysis with spglib + + spglib must be installed + + Parameters + ---------- + atoms: ase.Atoms object + crystal structure + verbose: bool + + Returns + ------- + + """ + if _spglib_present: + if verbose: + print('#####################') + print('# Symmetry Analysis #') + print('#####################') + + base = atoms.get_scaled_positions() + for i, atom in enumerate(atoms): + if verbose: + print(f'{i + 1}: {atom.number} = {2} : [{base[i][0]:.2f}, {base[i][1]:.2f}, {base[i][2]:.2f}]') + + lattice = (atoms.cell, atoms.get_scaled_positions(), atoms.numbers) + spgroup = spglib.get_spacegroup(lattice, symprec=1e-2) + sym = spglib.get_symmetry(lattice) + + if verbose: + print(" Spacegroup is %s." % spgroup) + print(' Crystal has {0} symmetry operation'.format(sym['rotations'].shape[0])) + + p_lattice, p_positions, p_numbers = spglib.find_primitive(lattice, symprec=1e-5) + print("\n########################\n #Basis vectors of primitive Cell:") + for i in range(3): + print('[{0:.4f}, {1:.4f}, {2:.4f}]'.format(p_lattice[i][0], p_lattice[i][1], p_lattice[i][2])) + + print('There {0} atoms and {1} species in primitive unit cell:'.format(len(p_positions), p_numbers)) + else: + print('spglib is not installed') + + return True
+ + +
[docs]def set_bond_radii(atoms): + bond_radii = np.ones(len(atoms)) + for i in range(len(atoms)): + bond_radii[i] = electronFF[atoms.symbols[i]]['bond_length'][1] + atoms.info['bond_radii'] = bond_radii
+ + +
[docs]def get_projection(crystal, layers=1): + zone_axis = crystal.info['experimental']['zone_axis'] + angle = crystal.info['experimental']['angle'] + projected_crystal = ase.build.surface(crystal, zone_axis, vacuum=.0, layers=layers) + + element_tree = cKDTree(projected_crystal.positions[:, 0:2]) + done = [] + projected = [] + for atom in projected_crystal: + if atom.index not in done: + near = element_tree.query_ball_point(atom.position[:2], 0.05) + projected.append(near) + done.extend(near) + print('projected atomic numbers') + atomic_numbers = [] + for pro in projected: + atomic_numbers.append(projected_crystal.get_atomic_numbers()[pro].sum()) + + projected_crystal.rotate(np.degrees(angle)%360, 'z', rotate_cell=True) + + near_base = np.array([projected_crystal.cell[0,:2], -projected_crystal.cell[0,:2], + projected_crystal.cell[1,:2], -projected_crystal.cell[1,:2], + projected_crystal.cell[0,:2] + projected_crystal.cell[1,:2], + -(projected_crystal.cell[0,:2] + projected_crystal.cell[1,:2])]) + lines = np.array( [[[0, near_base[0,0]],[0, near_base[0,1]]], + [[0, near_base[2,0]],[0, near_base[2,1]]], + [[near_base[0,0], near_base[4,0]],[near_base[0,1], near_base[4,1]]], + [[near_base[2,0], near_base[4,0]],[near_base[2,1], near_base[4,1]]]]) + projected_atoms = [] + for index in projected: + projected_atoms.append(index[0]) + + projected_crystal.info['projection']={'indices': projected, + 'projected': projected_atoms, + 'projected_Z': atomic_numbers, + 'angle': np.degrees(angle)+180%360, + 'near_base': near_base, + 'lines': lines} + return projected_crystal
+ + +
[docs]def jmol_viewer(atoms, size=2): + """ + jmol viewer of ase .Atoms object + requires jupyter-jsmol to be installed (available through conda or pip) + + Parameter + --------- + atoms: ase.Atoms + structure info + size: int, list, or np.array of size 3; default 1 + size of unit_cell; maximum = 8 + + Returns + ------- + view: JsmolView object + + Example + ------- + from jupyter_jsmol import JsmolView + import ase + import ase.build + import itertools + import numpy as np + atoms = ase.build.bulk('Cu', 'fcc', a=5.76911, cubic=True) + for pos in list(itertools.product([0.25, .75], repeat=3)): + atoms += ase.Atom('Al', al2cu.cell.lengths()*pos) + + view = plot_ase(atoms, size = 8) + display(view) + """ + try: + from jupyter_jsmol import JsmolView + from IPython.display import display + except ImportError: + print('this function is based on jupyter-jsmol, please install with: \n ' + 'conda install -c conda-forge jupyter-jsmol') + return + + if isinstance(size, int): + size = [size] * 3 + + [a, b, c] = atoms.cell.lengths() + [alpha, beta, gamma] = atoms.cell.angles() + + view = JsmolView.from_ase(atoms, f"{{{size[0]} {size[1]} {size[2]}}}" + f" unitcell {{{a:.3f} {b:.3f} {c:.3f} {alpha:.3f} {beta:.3f} {gamma:.3f}}}") + + display(view) + + return view
+ + +
[docs]def plot_super_cell(super_cell, shift_x=0.): + """ make a super_cell to plot with extra atoms at periodic boundaries""" + + if not isinstance(super_cell, ase.Atoms): + raise TypeError('Need an ase Atoms object') + + super_cell2plot = super_cell * (2, 2, 2) + super_cell2plot.positions[:, 0] = super_cell2plot.positions[:, 0] - super_cell2plot.cell[0, 0] * shift_x + + del super_cell2plot[super_cell2plot.positions[:, 2] > super_cell.cell[2, 2] + 0.1] + del super_cell2plot[super_cell2plot.positions[:, 1] > super_cell.cell[1, 1] + 0.1] + del super_cell2plot[super_cell2plot.positions[:, 0] > super_cell.cell[0, 0] + 0.1] + del super_cell2plot[super_cell2plot.positions[:, 0] < -0.1] + super_cell2plot.cell = super_cell.cell * (1, 1, 1) + + return super_cell2plot
+ + +
[docs]def ball_and_stick(atoms, extend=1, max_bond_length=0.): + """Calculates the data to plot a ball and stick model + + Parameters + ---------- + atoms: ase.Atoms object + object containing the structural information like 'cell', 'positions', and 'symbols' . + + extend: integer or list f 3 integers + The *extend* argument scales the effective cell in which atoms + will be included. It must either be a list of three integers or a single + integer scaling all 3 directions. By setting this value to one, + all corner and edge atoms will be included in the returned cell. + This will of cause make the returned cell non-repeatable, but this is + very useful for visualisation. + + max_bond_length: 1 float + The max_bond_length argument defines the distance for which a bond will be shown. + If max_bond_length is zero, the tabulated atom radii will be used. + + Returns + ------- + super_cell: ase.Atoms object + structure with additional information in info dictionary + """ + + if not isinstance(atoms, ase.Atoms): + raise TypeError('Need an ase Atoms object') + + from ase import neighborlist + from scipy import sparse + from scipy.sparse import dok_matrix + + super_cell = plot_super_cell(atoms*extend) + cell = super_cell.cell.array + # Corners and Outline of unit cell + h = (0, 1) + corner_vectors = np.dot(np.array(list(itertools.product(h, h, h))), cell) + corner_matrix = dok_matrix((8, 8), dtype=bool) + trace = [[0, 1], [1, 3], [2, 3], [0, 2], [0, 4], [4, 5], [5, 7], [6, 7], [4, 6], [1, 5], [2, 6], [3, 7]] + for s, e in trace: + corner_matrix[s, e] = True + + # List of bond lengths taken from electronFF database below + bond_lengths = [] + for atom in super_cell: + bond_lengths.append(electronFF[atom.symbol]['bond_length'][1]) + + super_cell.set_cell(cell*2, scale_atoms=False) # otherwise, corner atoms have distance 0 + neighbor_list = neighborlist.NeighborList(bond_lengths, self_interaction=False, bothways=False) + neighbor_list.update(super_cell) + bond_matrix = neighbor_list.get_connectivity_matrix() + + del_double = [] + for (k, s) in bond_matrix.keys(): + if k > s: + del_double.append((k, s)) + for key in del_double: + bond_matrix.pop(key) + + if super_cell.info is None: + super_cell.info = {} + super_cell.info['plot_cell'] = {'bond_matrix': bond_matrix, 'corner_vectors': corner_vectors, + 'bond_length': bond_lengths, 'corner_matrix': corner_matrix} + super_cell.set_cell(cell/2, scale_atoms=False) + return super_cell
+ + +
[docs]def plot_unit_cell(atoms, extend=1, max_bond_length=1.0, ax = None): + """ + Simple plot of unit cell + """ + + super_cell = ball_and_stick(atoms, extend=extend, max_bond_length=max_bond_length) + + corners = super_cell.info['plot_cell']['corner_vectors'] + positions = super_cell.positions - super_cell.cell.lengths()/2 + + if ax is None: + fig = plt.figure() + ax = fig.add_subplot(111, projection='3d') + # draw unit_cell + + for line in super_cell.info['plot_cell']['corner_matrix'].keys(): + ax.plot3D(corners[line, 0], corners[line, 1], corners[line, 2], color="blue") + + # draw bonds + bond_matrix = super_cell.info['plot_cell']['bond_matrix'] + for bond in super_cell.info['plot_cell']['bond_matrix'].keys(): + ax.plot3D(positions[bond, 0], positions[bond, 1], positions[bond, 2], color="black", linewidth=4) + # , tube_radius=0.02) + + # draw atoms + ax.scatter(super_cell.positions[:, 0], super_cell.positions[:, 1], super_cell.positions[:, 2], + color=tuple(jmol_colors[super_cell.get_atomic_numbers()]), alpha=1.0, s=50) + maximum_position = super_cell.positions.max()*1.05 + ax.set_proj_type('ortho') + + ax.set_zlim(-maximum_position/2, maximum_position/2) + ax.set_ylim(-maximum_position/2, maximum_position/2) + ax.set_xlim(-maximum_position/2, maximum_position/2) + + if 'name' in super_cell.info: + ax.set_title(super_cell.info['name']) + + ax.set_xlabel('x [Å]') + ax.set_ylabel('y [Å]') + ax.set_zlabel('z [Å]') + return ax.get_figure()
+ + +# Jmol colors. See: http://jmol.sourceforge.net/jscolors/#color_U +jmol_colors = ase.data.colors.jmol_colors + + +
[docs]def structure_by_name(crystal_name): + """ + Provides crystal structure in ase.Atoms format. + Additional information is stored in the info attribute as a dictionary + + + Parameter + --------- + crystal_name: str + Please note that the chemical expressions are not case-sensitive. + + Returns + ------- + atoms: ase.Atoms + structure + + Example + ------- + >> # for a list of pre-defined crystal structures + >> import pyTEMlib.crystal_tools + >> print(pyTEMlib.crystal_tools.crystal_data_base.keys()) + >> + >> atoms = pyTEMlib.crystal_tools.structure_by_name('Silicon') + >> print(atoms) + >> print(atoms.info) + + """ + + # Check whether name is in the crystal_data_base + import ase + import ase.build + + if crystal_name.lower() in cdb: + tags = cdb[crystal_name.lower()].copy() + else: + print(f'Crystal name {crystal_name.lower()} not defined') + return + + if 'symmetry' in tags: + if tags['symmetry'].lower() == 'fcc': + atoms = ase.build.bulk(tags['elements'], 'fcc', a=tags['a'], cubic=True) + + elif tags['symmetry'].lower() == 'bcc': + atoms = ase.build.bulk(tags['elements'], 'bcc', a=tags['a'], cubic=True) + + elif tags['symmetry'].lower() == 'diamond': + import ase.lattice.cubic + atoms = ase.lattice.cubic.Diamond(tags['elements'], latticeconstant=tags['a']) + + elif 'rocksalt' in tags['symmetry']: # B1 + import ase.lattice.compounds + atoms = ase.lattice.compounds.Rocksalt(tags['elements'], latticeconstant=tags['a']) + + elif 'zincblende' in tags['symmetry']: + import ase.lattice.compounds + atoms = ase.lattice.compounds.B3(tags['elements'], latticeconstant=tags['a']) + + elif 'B2' in tags['symmetry']: + import ase.lattice.compounds + atoms = ase.lattice.compounds.B2(tags['elements'], latticeconstant=tags['a']) + + elif 'graphite' in tags['symmetry']: + base = [(0, 0, 0), (0, 0, 1/2), (2/3, 1/3, 0), (1/3, 2/3, 1/2)] + structure_matrix = np.array([[tags['a'], 0., 0.], + [np.cos(np.pi/3*2)*tags['a'], np.sin(np.pi/3*2)*tags['a'], 0.], + [0., 0., tags['c']]]) + + atoms = ase.Atoms(tags['elements'], cell=structure_matrix, scaled_positions=base) + + elif 'perovskite' in tags['symmetry']: + import ase.spacegroup + atom_positions = [(0.0, 0.0, 0.0), (0.5, 0.5, 0.5), (0.5, 0.5, 0.0)] + atoms = ase.spacegroup.crystal(tags['elements'], atom_positions, spacegroup=221, cellpar=tags['a']) + + elif 'wurzite' in tags['symmetry']: + import ase.spacegroup + atom_positions = [(1/3, 2/3, 0.0), (1/3, 2/3, tags['u'])] + atoms = ase.spacegroup.crystal(tags['elements'], atom_positions, spacegroup=186, + cellpar=[tags['a'], tags['a'], tags['c'], 90, 90, 120]) + + elif 'rutile' in tags['symmetry']: + import ase.spacegroup + atoms = ase.spacegroup.crystal(tags['elements'], basis=[(0, 0, 0), (0.3, 0.3, 0.0)], + spacegroup=136, cellpar=[tags['a'], tags['a'], tags['c'], 90, 90, 90]) + elif 'dichalcogenide' in tags['symmetry']: + import ase.spacegroup + + u = tags['u'] + base = [(1 / 3., 2 / 3., 1 / 4.), (2 / 3., 1 / 3., 3 / 4.), + (2 / 3., 1 / 3., 1 / 4. + u), (2 / 3., 1 / 3., 1 / 4. - u), + (1 / 3., 2 / 3., 3 / 4. + u), (1 / 3., 2 / 3., 3 / 4. - u)] + atoms = ase.spacegroup.crystal(tags['elements'][0] * 2 + tags['elements'][1] * 4, base, spacegroup=194, + cellpar=[tags['a'], tags['a'], tags['c'], 90, 90, 120]) + + elif tags['symmetry'].lower() in ['primitive', 'hexagonal']: + atoms = ase.Atoms(tags['elements'], cell=tags['unit_cell'], scaled_positions=tags['base']) + + else: + print(' symmetry of structure is wrong') + + atoms.info = {'structure': {'reference': tags['reference'], 'link': tags['link']}, + 'title': tags['crystal_name']} + return atoms
+ + +# crystal data base cbd +cdb = {'aluminum': {'crystal_name': 'aluminum', + 'symmetry': 'FCC', + 'elements': 'Al', + 'a': 4.05, # Angstrom + 'reference': 'W. Witt, Z. Naturforsch. A, 1967, 22A, 92', + 'link': 'http://doi.org/10.1515/zna-1967-0115'}} +cdb['al'] = cdb['aluminium'] = cdb['aluminum'] + +cdb['gold'] = {'crystal_name': 'gold', + 'symmetry': 'FCC', + 'elements': 'Au', + 'a': 4.0782, # Angstrom + 'reference': '', + 'link': ''} +cdb['au'] = cdb['gold'] + +cdb['silver'] = {'crystal_name': 'silver', + 'symmetry': 'FCC', + 'elements': 'Ag', + 'a': 4.0853, # Angstrom + 'reference': '', 'link': ''} +cdb['ag'] = cdb['silver'] + +cdb['copper'] = {'crystal_name': 'copper', + 'symmetry': 'FCC', + 'elements': 'Cu', + 'a': 4.0853, # Angstrom + 'reference': '', 'link': ''} +cdb['cu'] = cdb['copper'] + +cdb['diamond'] = {'crystal_name': 'diamond', + 'symmetry': 'diamond', + 'elements': 'C', + 'a': 3.5668, # Angstrom + 'reference': '', 'link': ''} + +cdb['germanium'] = {'crystal_name': 'germanium', + 'symmetry': 'diamond', + 'elements': 'Ge', + 'a': 5.66806348, # Angstrom for 300K + 'reference': 'H. P. Singh, Acta Crystallogr., 1968, 24A, 469', + 'link': 'https://doi.org/10.1107/S056773946800094X'} +cdb['ge'] = cdb['germanium'] + +cdb['silicon'] = {'crystal_name': 'silicon', + 'symmetry': 'diamond', + 'elements': 'Si', + 'a': 5.430880, # Angstrom for 300K + 'reference': 'C. R. Hubbard, H. E. Swanson, and F. A. Mauer, J. Appl. Crystallogr., 1975, 8, 45', + 'link': 'https://doi.org/10.1107/S0021889875009508'} +cdb['si'] = cdb['silicon'] + +cdb['gaas'] = {'crystal_name': 'GaAs', + 'symmetry': 'zincblende(B3)', + 'elements': ['Ga', 'As'], + 'a': 5.65325, # Angstrom for 300K + 'reference': 'J.F.C. Baker, M. Hart, M.A.G. Halliwell, R. Heckingbottom, Solid-State Electronics, 19, ' + '1976, 331-334,', + 'link': 'https://doi.org/10.1016/0038-1101(76)90031-9'} + +cdb['fcc fe'] = {'crystal_name': 'FCC Fe', + 'symmetry': 'FCC', + 'elements': 'Fe', + 'a': 3.3571, # Angstrom + 'reference': 'R. Kohlhaas, P. Donner, and N. Schmitz-Pranghe, Z. Angew. Phys., 1967, 23, 245', + 'link': ''} + +cdb['iron'] = {'crystal_name': 'BCC Fe', + 'symmetry': 'BCC', + 'elements': 'Fe', + 'a': 2.866, # Angstrom + 'reference': 'Z. S. Basinski, W. Hume-Rothery and A. L. Sutton, Proceedings of the Royal Society of ' + 'London. Series A, Mathematical and Physical Sciences Vol. 229, No. 1179 ' + '(May 24, 1955), pp. 459-467', + 'link': 'http://www.jstor.org/stable/99693'} +cdb['bcc fe'] = cdb['alpha iron'] = cdb['iron'] + +cdb['srtio3'] = {'crystal_name': 'SrTiO3', + 'symmetry': 'perovskite', + 'elements': ['Sr', 'Ti', 'O'], + 'a': 3.905268, # Angstrom + 'reference': 'M. Schmidbauer, A. Kwasniewski and J. Schwarzkopf, Acta Cryst. (2012). B68, 8-14', + 'link': 'http://doi.org/10.1107/S0108768111046738'} +cdb['strontium titanate'] = cdb['srtio3'] + +cdb['graphite'] = {'crystal_name': 'graphite', + 'symmetry': 'graphite hexagonal', + 'elements': 'C4', + 'a': 2.46772414, + 'c': 6.711, + 'reference': 'P. Trucano and R. Chen, Nature, 1975, 258, 136', + 'link': 'https://doi.org/10.1038/258136a0'} + +cdb['cscl'] = {'crystal_name': 'CsCl', + 'symmetry': 'CsCl (B2)', + 'a': 4.209, # Angstrom + 'elements': ['Cs', 'Cl'], + 'reference': '', 'link': ''} +cdb['cesium chlorid'] = cdb['cscl'] + +cdb['mgo'] = {'crystal_name': 'MgO', + 'symmetry': 'rocksalt (B1)', + 'elements': ['Mg', 'O'], + 'a': 4.256483, # Angstrom + 'reference': '', 'link': ''} + +cdb['titanium nitride'] = {'crystal_name': 'TiN', + 'symmetry': 'rocksalt (B1)', + 'elements': ['Ti', 'N'], + 'a': 4.25353445, # Angstrom + 'reference': '', 'link': '', + 'space_group': 225, + 'symmetry_name': 'Fm-3m'} + +cdb['zno wurzite'] = {'crystal_name': 'ZnO Wurzite', + 'symmetry': 'wurzite', + 'elements': ['Zn', 'O'], + 'a': 3.278, # Angstrom + 'c': 5.292, # Angstrom + 'u': 0.382, + 'reference': '', 'link': ''} +cdb['zno'] = cdb['wzno'] = cdb['zno wurzite'] + +cdb['gan'] = {'crystal_name': 'GaN Wurzite', + 'symmetry': 'wurzite', + 'elements': ['Ga', 'N'], + 'a': 3.186, # Angstrom + 'c': 5.186, # Angstrom + 'u': 0.376393, + 'reference': '', 'link': ''} +cdb['gan wurzite'] = cdb['wgan'] = cdb['gallium nitride'] = cdb['gan'] + + +cdb['tio2'] = {'crystal_name': 'TiO2 rutile', + 'symmetry': 'rutile', + 'elements': ['Ti', 'O'], + 'a': 4.6, # Angstrom + 'c': 2.95, # Angstrom + 'reference': '', 'link': ''} + +cdb['mos2'] = {'crystal_name': 'MoS2', + 'symmetry': 'dichalcogenide', + 'elements': ['Mo', 'S'], + 'a': 3.19031573, # Angstrom + 'c': 14.87900430, # Angstrom + 'u': 0.105174, + 'reference': '', 'link': ''} + +cdb['ws2'] = {'crystal_name': 'WS2', + 'symmetry': 'dichalcogenide', + 'elements': ['W', 'S'], + 'a': 3.19073051, # Angstrom + 'c': 14.20240204, # Angstrom + 'u': 0.110759, + 'reference': '', 'link': ''} + +cdb['wse2'] = {'crystal_name': 'WSe2', + 'symmetry': 'dichalcogenide', + 'elements': ['W', 'Se'], + 'a': 3.32706918, # Angstrom + 'c': 15.06895072, # Angstrom + 'u': 0.111569, + 'reference': '', 'link': ''} + +cdb['mose2'] = {'crystal_name': 'MoSe2', + 'symmetry': 'dichalcogenide', + 'elements': ['Mo', 'Se'], + 'a': 3.32694913, # Angstrom + 'c': 15.45142322, # Angstrom + 'u': 0.108249, + 'reference': '', 'link': ''} +a_l = 0.3336 +c_l = 0.4754 +base_l = [(2. / 3., 1. / 3., .5), (1. / 3., 2. / 3., 0.), (2. / 3., 1. / 3., 0.), (1. / 3., 2. / 3., .5)] + +cdb['zno hexagonal'] = {'crystal_name': 'ZnO hexagonal', + 'symmetry': 'hexagonal', + 'a': a_l, # nm + 'c': c_l, # not np.sqrt(8/3)*1 + 'elements': ['Zn', 'Zn', 'O', 'O'], + 'unit_cell': [[a_l, 0., 0.], + [np.cos(120 / 180 * np.pi) * a_l, np.sin(120 / 180 * np.pi) * a_l, 0.], + [0., 0., c_l]], + 'base': np.array(base_l), + 'reference': '', 'link': ''} + +cdb['pdse2'] = {'crystal_name': 'PdSe2', + 'symmetry': 'primitive', + 'unit_cell': (np.identity(3) * (.579441832, 0.594542204, 0.858506072)), + 'elements': ['Pd'] * 4 + ['Se'] * 8, + 'base': np.array([[.5, .0, .0], [.0, 0.5, 0.0], + [.5, 0.5, 0.5], [.0, 0.5, 0.5], + [0.611300, 0.119356, 0.585891], + [0.111300, 0.380644, 0.414109], + [0.388700, 0.619356, 0.914109], + [0.888700, 0.880644, 0.085891], + [0.111300, 0.119356, 0.914109], + [0.611300, 0.380644, 0.085891], + [0.888700, 0.619356, 0.585891], + [0.388700, 0.880644, 0.414109]]), + 'reference': '', 'link': ''} + +crystal_data_base = cdb + +# From Appendix C of Kirkland, "Advanced Computing in Electron Microscopy", 2nd ed. +electronFF = { + # form factor coefficients + # Z= 6, chisq= 0.143335 + # a1 b1 a2 b2 + # a3 b3 c1 d1 + # c2 d2 c3 d3 + + # name of the file: feKirkland.txt + # converted with program sortFF.py + # form factor parametrized in 1/Angstrom + # bond_length as a list of atom Sizes, bond radii, angle radii, H-bond radii + + 'H': {'Z': 1, 'chisq': 0.170190, + 'bond_length': [0.98, 0.78, 1.20, 0], + 'fa': [4.20298324e-003, 6.27762505e-002, 3.00907347e-002], + 'fb': [2.25350888e-001, 2.25366950e-001, 2.25331756e-001], + 'fc': [6.77756695e-002, 3.56609237e-003, 2.76135815e-002], + 'fd': [4.38854001e+000, 4.03884823e-001, 1.44490166e+000]}, + 'He': {'Z': 2, 'chisq': 0.396634, + 'bond_length': [1.45, 1.25, 1.40, 0], + 'fa': [1.87543704e-005, 4.10595800e-004, 1.96300059e-001], + 'fb': [2.12427997e-001, 3.32212279e-001, 5.17325152e-001], + 'fc': [8.36015738e-003, 2.95102022e-002, 4.65928982e-007], + 'fd': [3.66668239e-001, 1.37171827e+000, 3.75768025e+004]}, + 'Li': {'Z': 3, 'chisq': 0.286232, + 'bond_length': [1.76, 1.56, 1.82, 0], + 'fa': [7.45843816e-002, 7.15382250e-002, 1.45315229e-001], + 'fb': [8.81151424e-001, 4.59142904e-002, 8.81301714e-001], + 'fc': [1.12125769e+000, 2.51736525e-003, 3.58434971e-001], + 'fd': [1.88483665e+001, 1.59189995e-001, 6.12371000e+000]}, + 'Be': {'Z': 4, 'chisq': 0.195442, + 'bond_length': [1.33, 1.13, 1.70, 0], + 'fa': [6.11642897e-002, 1.25755034e-001, 2.00831548e-001], + 'fb': [9.90182132e-002, 9.90272412e-002, 1.87392509e+000], + 'fc': [7.87242876e-001, 1.58847850e-003, 2.73962031e-001], + 'fd': [9.32794929e+000, 8.91900236e-002, 3.20687658e+000]}, + 'B': {'Z': 5, 'chisq': 0.146989, + 'bond_length': [1.18, 0.98, 2.08, 0], + 'fa': [1.25716066e-001, 1.73314452e-001, 1.84774811e-001], + 'fb': [1.48258830e-001, 1.48257216e-001, 3.34227311e+000], + 'fc': [1.95250221e-001, 5.29642075e-001, 1.08230500e-003], + 'fd': [1.97339463e+000, 5.70035553e+000, 5.64857237e-002]}, + 'C': {'Z': 6, 'chisq': 0.102440, + 'bond_length': [1.12, 0.92, 1.95, 0], + 'fa': [2.12080767e-001, 1.99811865e-001, 1.68254385e-001], + 'fb': [2.08605417e-001, 2.08610186e-001, 5.57870773e+000], + 'fc': [1.42048360e-001, 3.63830672e-001, 8.35012044e-004], + 'fd': [1.33311887e+000, 3.80800263e+000, 4.03982620e-002]}, + 'N': {'Z': 7, 'chisq': 0.060249, + 'bond_length': [1.08, 0.88, 1.85, 1.30], + 'fa': [5.33015554e-001, 5.29008883e-002, 9.24159648e-002], + 'fb': [2.90952515e-001, 1.03547896e+001, 1.03540028e+001], + 'fc': [2.61799101e-001, 8.80262108e-004, 1.10166555e-001], + 'fd': [2.76252723e+000, 3.47681236e-002, 9.93421736e-001]}, + 'O': {'Z': 8, 'chisq': 0.039944, + 'bond_length': [1.09, 0.89, 1.70, 1.40], + 'fa': [3.39969204e-001, 3.07570172e-001, 1.30369072e-001], + 'fb': [3.81570280e-001, 3.81571436e-001, 1.91919745e+001], + 'fc': [8.83326058e-002, 1.96586700e-001, 9.96220028e-004], + 'fd': [7.60635525e-001, 2.07401094e+000, 3.03266869e-002]}, + 'F': {'Z': 9, 'chisq': 0.027866, + 'bond_length': [1.30, 1.10, 1.73, 0], + 'fa': [2.30560593e-001, 5.26889648e-001, 1.24346755e-001], + 'fb': [4.80754213e-001, 4.80763895e-001, 3.95306720e+001], + 'fc': [1.24616894e-003, 7.20452555e-002, 1.53075777e-001], + 'fd': [2.62181803e-002, 5.92495593e-001, 1.59127671e+000]}, + 'Ne': {'Z': 10, 'chisq': 0.021836, + 'bond_length': [1.50, 1.30, 1.54, 0], + 'fa': [4.08371771e-001, 4.54418858e-001, 1.44564923e-001], + 'fb': [5.88228627e-001, 5.88288655e-001, 1.21246013e+002], + 'fc': [5.91531395e-002, 1.24003718e-001, 1.64986037e-003], + 'fd': [4.63963540e-001, 1.23413025e+000, 2.05869217e-002]}, + 'Na': {'Z': 11, 'chisq': 0.064136, + 'bond_length': [2.10, 1.91, 2.27, 0], + 'fa': [1.36471662e-001, 7.70677865e-001, 1.56862014e-001], + 'fb': [4.99965301e-002, 8.81899664e-001, 1.61768579e+001], + 'fc': [9.96821513e-001, 3.80304670e-002, 1.27685089e-001], + 'fd': [2.00132610e+001, 2.60516254e-001, 6.99559329e-001]}, + 'Mg': {'Z': 12, 'chisq': 0.051303, + 'bond_length': [1.80, 1.60, 1.73, 0], + 'fa': [3.04384121e-001, 7.56270563e-001, 1.01164809e-001], + 'fb': [8.42014377e-002, 1.64065598e+000, 2.97142975e+001], + 'fc': [3.45203403e-002, 9.71751327e-001, 1.20593012e-001], + 'fd': [2.16596094e-001, 1.21236852e+001, 5.60865838e-001]}, + 'Al': {'Z': 13, 'chisq': 0.049529, + 'bond_length': [1.60, 1.43, 2.05, 0], + 'fa': [7.77419424e-001, 5.78312036e-002, 4.26386499e-001], + 'fb': [2.71058227e+000, 7.17532098e+001, 9.13331555e-002], + 'fc': [1.13407220e-001, 7.90114035e-001, 3.23293496e-002], + 'fd': [4.48867451e-001, 8.66366718e+000, 1.78503463e-001]}, + 'Si': {'Z': 14, 'chisq': 0.071667, + 'bond_length': [1.52, 1.32, 2.10, 0], + 'fa': [1.06543892e+000, 1.20143691e-001, 1.80915263e-001], + 'fb': [1.04118455e+000, 6.87113368e+001, 8.87533926e-002], + 'fc': [1.12065620e+000, 3.05452816e-002, 1.59963502e+000], + 'fd': [3.70062619e+000, 2.14097897e-001, 9.99096638e+000]}, + 'P': {'Z': 15, 'chisq': 0.047673, + 'bond_length': [1.48, 1.28, 2.08, 0], + 'fa': [1.05284447e+000, 2.99440284e-001, 1.17460748e-001], + 'fb': [1.31962590e+000, 1.28460520e-001, 1.02190163e+002], + 'fc': [9.60643452e-001, 2.63555748e-002, 1.38059330e+000], + 'fd': [2.87477555e+000, 1.82076844e-001, 7.49165526e+000]}, + 'S': {'Z': 16, 'chisq': 0.033482, + 'bond_length': [1.47, 1.27, 2.00, 0], + 'fa': [1.01646916e+000, 4.41766748e-001, 1.21503863e-001], + 'fb': [1.69181965e+000, 1.74180288e-001, 1.67011091e+002], + 'fc': [8.27966670e-001, 2.33022533e-002, 1.18302846e+000], + 'fd': [2.30342810e+000, 1.56954150e-001, 5.85782891e+000]}, + 'Cl': {'Z': 17, 'chisq': 0.206186, + 'bond_length': [1.70, 1.50, 1.97, 0], + 'fa': [9.44221116e-001, 4.37322049e-001, 2.54547926e-001], + 'fb': [2.40052374e-001, 9.30510439e+000, 9.30486346e+000], + 'fc': [5.47763323e-002, 8.00087488e-001, 1.07488641e-002], + 'fd': [1.68655688e-001, 2.97849774e+000, 6.84240646e-002]}, + 'Ar': {'Z': 18, 'chisq': 0.263904, + 'bond_length': [2.00, 1.80, 1.88, 0], + 'fa': [1.06983288e+000, 4.24631786e-001, 2.43897949e-001], + 'fb': [2.87791022e-001, 1.24156957e+001, 1.24158868e+001], + 'fc': [4.79446296e-002, 7.64958952e-001, 8.23128431e-003], + 'fd': [1.36979796e-001, 2.43940729e+000, 5.27258749e-002]}, + 'K': {'Z': 19, 'chisq': 0.161900, + 'bond_length': [2.58, 2.38, 2.75, 0], + 'fa': [6.92717865e-001, 9.65161085e-001, 1.48466588e-001], + 'fb': [7.10849990e+000, 3.57532901e-001, 3.93763275e-002], + 'fc': [2.64645027e-002, 1.80883768e+000, 5.43900018e-001], + 'fd': [1.03591321e-001, 3.22845199e+001, 1.67791374e+000]}, + 'Ca': {'Z': 20, 'chisq': 0.085209, + 'bond_length': [2.17, 1.97, 1.97, 0], + 'fa': [3.66902871e-001, 8.66378999e-001, 6.67203300e-001], + 'fb': [6.14274129e-002, 5.70881727e-001, 7.82965639e+000], + 'fc': [4.87743636e-001, 1.82406314e+000, 2.20248453e-002], + 'fd': [1.32531318e+000, 2.10056032e+001, 9.11853450e-002]}, + 'Sc': {'Z': 21, 'chisq': 0.052352, + 'bond_length': [1.84, 1.64, 1.70, 0], + 'fa': [3.78871777e-001, 9.00022505e-001, 7.15288914e-001], + 'fb': [6.98910162e-002, 5.21061541e-001, 7.87707920e+000], + 'fc': [1.88640973e-002, 4.07945949e-001, 1.61786540e+000], + 'fd': [8.17512708e-002, 1.11141388e+000, 1.80840759e+001]}, + 'Ti': {'Z': 22, 'chisq': 0.035298, + 'bond_length': [1.66, 1.46, 1.70, 0], + 'fa': [3.62383267e-001, 9.84232966e-001, 7.41715642e-001], + 'fb': [7.54707114e-002, 4.97757309e-001, 8.17659391e+000], + 'fc': [3.62555269e-001, 1.49159390e+000, 1.61659509e-002], + 'fd': [9.55524906e-001, 1.62221677e+001, 7.33140839e-002]}, + 'V': {'Z': 23, 'chisq': 0.030745, + 'bond_length': [1.55, 1.35, 1.70, 0], + 'fa': [3.52961378e-001, 7.46791014e-001, 1.08364068e+000], + 'fb': [8.19204103e-002, 8.81189511e+000, 5.10646075e-001], + 'fc': [1.39013610e+000, 3.31273356e-001, 1.40422612e-002], + 'fd': [1.48901841e+001, 8.38543079e-001, 6.57432678e-002]}, + 'Cr': {'Z': 24, 'chisq': 0.015287, + 'bond_length': [1.56, 1.36, 1.70, 0], + 'fa': [1.34348379e+000, 5.07040328e-001, 4.26358955e-001], + 'fb': [1.25814353e+000, 1.15042811e+001, 8.53660389e-002], + 'fc': [1.17241826e-002, 5.11966516e-001, 3.38285828e-001], + 'fd': [6.00177061e-002, 1.53772451e+000, 6.62418319e-001]}, + 'Mn': {'Z': 25, 'chisq': 0.031274, + 'bond_length': [1.54, 1.30, 1.70, 0], + 'fa': [3.26697613e-001, 7.17297000e-001, 1.33212464e+000], + 'fb': [8.88813083e-002, 1.11300198e+001, 5.82141104e-001], + 'fc': [2.80801702e-001, 1.15499241e+000, 1.11984488e-002], + 'fd': [6.71583145e-001, 1.26825395e+001, 5.32334467e-002]}, + 'Fe': {'Z': 26, 'chisq': 0.031315, + 'bond_length': [1.47, 1.27, 1.70, 0], + 'fa': [3.13454847e-001, 6.89290016e-001, 1.47141531e+000], + 'fb': [8.99325756e-002, 1.30366038e+001, 6.33345291e-001], + 'fc': [1.03298688e+000, 2.58280285e-001, 1.03460690e-002], + 'fd': [1.16783425e+001, 6.09116446e-001, 4.81610627e-002]}, + 'Co': {'Z': 27, 'chisq': 0.031643, + 'bond_length': [1.45, 1.25, 1.70, 0], + 'fa': [3.15878278e-001, 1.60139005e+000, 6.56394338e-001], + 'fb': [9.46683246e-002, 6.99436449e-001, 1.56954403e+001], + 'fc': [9.36746624e-001, 9.77562646e-003, 2.38378578e-001], + 'fd': [1.09392410e+001, 4.37446816e-002, 5.56286483e-001]}, + 'Ni': {'Z': 28, 'chisq': 0.032245, + 'bond_length': [1.45, 1.25, 1.63, 0], + 'fa': [1.72254630e+000, 3.29543044e-001, 6.23007200e-001], + 'fb': [7.76606908e-001, 1.02262360e-001, 1.94156207e+001], + 'fc': [9.43496513e-003, 8.54063515e-001, 2.21073515e-001], + 'fd': [3.98684596e-002, 1.04078166e+001, 5.10869330e-001]}, + 'Cu': {'Z': 29, 'chisq': 0.010467, + 'bond_length': [1.48, 1.28, 1.40, 0], + 'fa': [3.58774531e-001, 1.76181348e+000, 6.36905053e-001], + 'fb': [1.06153463e-001, 1.01640995e+000, 1.53659093e+001], + 'fc': [7.44930667e-003, 1.89002347e-001, 2.29619589e-001], + 'fd': [3.85345989e-002, 3.98427790e-001, 9.01419843e-001]}, + 'Zn': {'Z': 30, 'chisq': 0.026698, + 'bond_length': [1.59, 1.39, 1.39, 0], + 'fa': [5.70893973e-001, 1.98908856e+000, 3.06060585e-001], + 'fb': [1.26534614e-001, 2.17781965e+000, 3.78619003e+001], + 'fc': [2.35600223e-001, 3.97061102e-001, 6.85657228e-003], + 'fd': [3.67019041e-001, 8.66419596e-001, 3.35778823e-002]}, + 'Ga': {'Z': 31, 'chisq': 0.008110, + 'bond_length': [1.61, 1.41, 1.87, 0], + 'fa': [6.25528464e-001, 2.05302901e+000, 2.89608120e-001], + 'fb': [1.10005650e-001, 2.41095786e+000, 4.78685736e+001], + 'fc': [2.07910594e-001, 3.45079617e-001, 6.55634298e-003], + 'fd': [3.27807224e-001, 7.43139061e-001, 3.09411369e-002]}, + 'Ge': {'Z': 32, 'chisq': 0.032198, + 'bond_length': [1.57, 1.37, 1.70, 0], + 'fa': [5.90952690e-001, 5.39980660e-001, 2.00626188e+000], + 'fb': [1.18375976e-001, 7.18937433e+001, 1.39304889e+000], + 'fc': [7.49705041e-001, 1.83581347e-001, 9.52190743e-003], + 'fd': [6.89943350e+000, 3.64667232e-001, 2.69888650e-002]}, + 'As': {'Z': 33, 'chisq': 0.034014, + 'bond_length': [1.59, 1.39, 1.85, 0], + 'fa': [7.77875218e-001, 5.93848150e-001, 1.95918751e+000], + 'fb': [1.50733157e-001, 1.42882209e+002, 1.74750339e+000], + 'fc': [1.79880226e-001, 8.63267222e-001, 9.59053427e-003], + 'fd': [3.31800852e-001, 5.85490274e+000, 2.33777569e-002]}, + 'Se': {'Z': 34, 'chisq': 0.035703, + 'bond_length': [1.60, 1.40, 1.90, 0], + 'fa': [9.58390681e-001, 6.03851342e-001, 1.90828931e+000], + 'fb': [1.83775557e-001, 1.96819224e+002, 2.15082053e+000], + 'fc': [1.73885956e-001, 9.35265145e-001, 8.62254658e-003], + 'fd': [3.00006024e-001, 4.92471215e+000, 2.12308108e-002]}, + 'Br': {'Z': 35, 'chisq': 0.039250, + 'bond_length': [1.80, 1.60, 2.10, 0], + 'fa': [1.14136170e+000, 5.18118737e-001, 1.85731975e+000], + 'fb': [2.18708710e-001, 1.93916682e+002, 2.65755396e+000], + 'fc': [1.68217399e-001, 9.75705606e-001, 7.24187871e-003], + 'fd': [2.71719918e-001, 4.19482500e+000, 1.99325718e-002]}, + 'Kr': {'Z': 36, 'chisq': 0.045421, + 'bond_length': [2.10, 1.90, 2.02, 0], + 'fa': [3.24386970e-001, 1.31732163e+000, 1.79912614e+000], + 'fb': [6.31317973e+001, 2.54706036e-001, 3.23668394e+000], + 'fc': [4.29961425e-003, 1.00429433e+000, 1.62188197e-001], + 'fd': [1.98965610e-002, 3.61094513e+000, 2.45583672e-001]}, + 'Rb': {'Z': 37, 'chisq': 0.130044, + 'bond_length': [2.75, 2.55, 1.70, 0], + 'fa': [2.90445351e-001, 2.44201329e+000, 7.69435449e-001], + 'fb': [3.68420227e-002, 1.16013332e+000, 1.69591472e+001], + 'fc': [1.58687000e+000, 2.81617593e-003, 1.28663830e-001], + 'fd': [2.53082574e+000, 1.88577417e-002, 2.10753969e-001]}, + 'Sr': {'Z': 38, 'chisq': 0.188055, + 'bond_length': [2.35, 2.15, 1.70, 0], + 'fa': [1.37373086e-002, 1.97548672e+000, 1.59261029e+000], + 'fb': [1.87469061e-002, 6.36079230e+000, 2.21992482e-001], + 'fc': [1.73263882e-001, 4.66280378e+000, 1.61265063e-003], + 'fd': [2.01624958e-001, 2.53027803e+001, 1.53610568e-002]}, + 'Y': {'Z': 39, 'chisq': 0.174927, + 'bond_length': [2.00, 1.80, 1.70, 0], + 'fa': [6.75302747e-001, 4.70286720e-001, 2.63497677e+000], + 'fb': [6.54331847e-002, 1.06108709e+002, 2.06643540e+000], + 'fc': [1.09621746e-001, 9.60348773e-001, 5.28921555e-003], + 'fd': [1.93131925e-001, 1.63310938e+000, 1.66083821e-002]}, + 'Zr': {'Z': 40, 'chisq': 0.072078, + 'bond_length': [1.80, 1.60, 1.70, 0], + 'fa': [2.64365505e+000, 5.54225147e-001, 7.61376625e-001], + 'fb': [2.20202699e+000, 1.78260107e+002, 7.67218745e-002], + 'fc': [6.02946891e-003, 9.91630530e-002, 9.56782020e-001], + 'fd': [1.55143296e-002, 1.76175995e-001, 1.54330682e+000]}, + 'Nb': {'Z': 41, 'chisq': 0.011800, + 'bond_length': [1.67, 1.47, 1.70, 0], + 'fa': [6.59532875e-001, 1.84545854e+000, 1.25584405e+000], + 'fb': [8.66145490e-002, 5.94774398e+000, 6.40851475e-001], + 'fc': [1.22253422e-001, 7.06638328e-001, 2.62381591e-003], + 'fd': [1.66646050e-001, 1.62853268e+000, 8.26257859e-003]}, + 'Mo': {'Z': 42, 'chisq': 0.008976, + 'bond_length': [1.60, 1.40, 1.70, 0], + 'fa': [6.10160120e-001, 1.26544000e+000, 1.97428762e+000], + 'fb': [9.11628054e-002, 5.06776025e-001, 5.89590381e+000], + 'fc': [6.48028962e-001, 2.60380817e-003, 1.13887493e-001], + 'fd': [1.46634108e+000, 7.84336311e-003, 1.55114340e-001]}, + 'Tc': {'Z': 43, 'chisq': 0.023771, + 'bond_length': [1.56, 1.36, 1.70, 0], + 'fa': [8.55189183e-001, 1.66219641e+000, 1.45575475e+000], + 'fb': [1.02962151e-001, 7.64907000e+000, 1.01639987e+000], + 'fc': [1.05445664e-001, 7.71657112e-001, 2.20992635e-003], + 'fd': [1.42303338e-001, 1.34659349e+000, 7.90358976e-003]}, + 'Ru': {'Z': 44, 'chisq': 0.010613, + 'bond_length': [1.54, 1.34, 1.70, 0], + 'fa': [4.70847093e-001, 1.58180781e+000, 2.02419818e+000], + 'fb': [9.33029874e-002, 4.52831347e-001, 7.11489023e+000], + 'fc': [1.97036257e-003, 6.26912639e-001, 1.02641320e-001], + 'fd': [7.56181595e-003, 1.25399858e+000, 1.33786087e-001]}, + 'Rh': {'Z': 45, 'chisq': 0.012895, + 'bond_length': [1.54, 1.34, 1.70, 0], + 'fa': [4.20051553e-001, 1.76266507e+000, 2.02735641e+000], + 'fb': [9.38882628e-002, 4.64441687e-001, 8.19346046e+000], + 'fc': [1.45487176e-003, 6.22809600e-001, 9.91529915e-002], + 'fd': [7.82704517e-003, 1.17194153e+000, 1.24532839e-001]}, + 'Pd': {'Z': 46, 'chisq': 0.009172, + 'bond_length': [1.58, 1.38, 1.63, 0], + 'fa': [2.10475155e+000, 2.03884487e+000, 1.82067264e-001], + 'fb': [8.68606470e+000, 3.78924449e-001, 1.42921634e-001], + 'fc': [9.52040948e-002, 5.91445248e-001, 1.13328676e-003], + 'fd': [1.17125900e-001, 1.07843808e+000, 7.80252092e-003]}, + 'Ag': {'Z': 47, 'chisq': 0.006648, + 'bond_length': [1.64, 1.44, 1.72, 0], + 'fa': [2.07981390e+000, 4.43170726e-001, 1.96515215e+000], + 'fb': [9.92540297e+000, 1.04920104e-001, 6.40103839e-001], + 'fc': [5.96130591e-001, 4.78016333e-001, 9.46458470e-002], + 'fd': [8.89594790e-001, 1.98509407e+000, 1.12744464e-001]}, + 'Cd': {'Z': 48, 'chisq': 0.005588, + 'bond_length': [1.77, 1.57, 1.58, 0], + 'fa': [1.63657549e+000, 2.17927989e+000, 7.71300690e-001], + 'fb': [1.24540381e+001, 1.45134660e+000, 1.26695757e-001], + 'fc': [6.64193880e-001, 7.64563285e-001, 8.61126689e-002], + 'fd': [7.77659202e-001, 1.66075210e+000, 1.05728357e-001]}, + 'In': {'Z': 49, 'chisq': 0.002569, + 'bond_length': [1.86, 1.66, 1.93, 0], + 'fa': [2.24820632e+000, 1.64706864e+000, 7.88679265e-001], + 'fb': [1.51913507e+000, 1.30113424e+001, 1.06128184e-001], + 'fc': [8.12579069e-002, 6.68280346e-001, 6.38467475e-001], + 'fd': [9.94045620e-002, 1.49742063e+000, 7.18422635e-001]}, + 'Sn': {'Z': 50, 'chisq': 0.005051, + 'bond_length': [1.82, 1.62, 2.17, 0], + 'fa': [2.16644620e+000, 6.88691021e-001, 1.92431751e+000], + 'fb': [1.13174909e+001, 1.10131285e-001, 6.74464853e-001], + 'fc': [5.65359888e-001, 9.18683861e-001, 7.80542213e-002], + 'fd': [7.33564610e-001, 1.02310312e+001, 9.31104308e-002]}, + 'Sb': {'Z': 51, 'chisq': 0.004383, + 'bond_length': [1.79, 1.59, 2.20, 0], + 'fa': [1.73662114e+000, 9.99871380e-001, 2.13972409e+000], + 'fb': [8.84334719e-001, 1.38462121e-001, 1.19666432e+001], + 'fc': [5.60566526e-001, 9.93772747e-001, 7.37374982e-002], + 'fd': [6.72672880e-001, 8.72330411e+000, 8.78577715e-002]}, + 'Te': {'Z': 52, 'chisq': 0.004105, + 'bond_length': [1.80, 1.60, 2.06, 0], + 'fa': [2.09383882e+000, 1.56940519e+000, 1.30941993e+000], + 'fb': [1.26856869e+001, 1.21236537e+000, 1.66633292e-001], + 'fc': [6.98067804e-002, 1.04969537e+000, 5.55594354e-001], + 'fd': [8.30817576e-002, 7.43147857e+000, 6.17487676e-001]}, + 'I': {'Z': 53, 'chisq': 0.004068, + 'bond_length': [1.90, 1.70, 2.15, 0], + 'fa': [1.60186925e+000, 1.98510264e+000, 1.48226200e+000], + 'fb': [1.95031538e-001, 1.36976183e+001, 1.80304795e+000], + 'fc': [5.53807199e-001, 1.11728722e+000, 6.60720847e-002], + 'fd': [5.67912340e-001, 6.40879878e+000, 7.86615429e-002]}, + 'Xe': {'Z': 54, 'chisq': 0.004381, + 'bond_length': [2.30, 2.10, 2.16, 0], + 'fa': [1.60015487e+000, 1.71644581e+000, 1.84968351e+000], + 'fb': [2.92913354e+000, 1.55882990e+001, 2.22525983e-001], + 'fc': [6.23813648e-002, 1.21387555e+000, 5.54051946e-001], + 'fd': [7.45581223e-002, 5.56013271e+000, 5.21994521e-001]}, + 'Cs': {'Z': 55, 'chisq': 0.042676, + 'bond_length': [2.93, 2.73, 1.70, 0], + 'fa': [2.95236854e+000, 4.28105721e-001, 1.89599233e+000], + 'fb': [6.01461952e+000, 4.64151246e+001, 1.80109756e-001], + 'fc': [5.48012938e-002, 4.70838600e+000, 5.90356719e-001], + 'fd': [7.12799633e-002, 4.56702799e+001, 4.70236310e-001]}, + 'Ba': {'Z': 56, 'chisq': 0.043267, + 'bond_length': [2.44, 2.24, 1.70, 0], + 'fa': [3.19434243e+000, 1.98289586e+000, 1.55121052e-001], + 'fb': [9.27352241e+000, 2.28741632e-001, 3.82000231e-002], + 'fc': [6.73222354e-002, 4.48474211e+000, 5.42674414e-001], + 'fd': [7.30961745e-002, 2.95703565e+001, 4.08647015e-001]}, + 'La': {'Z': 57, 'chisq': 0.033249, + 'bond_length': [2.08, 1.88, 1.70, 0], + 'fa': [2.05036425e+000, 1.42114311e-001, 3.23538151e+000], + 'fb': [2.20348417e-001, 3.96438056e-002, 9.56979169e+000], + 'fc': [6.34683429e-002, 3.97960586e+000, 5.20116711e-001], + 'fd': [6.92443091e-002, 2.53178406e+001, 3.83614098e-001]}, + 'Ce': {'Z': 58, 'chisq': 0.029355, + 'bond_length': [2.02, 1.82, 1.70, 0], + 'fa': [3.22990759e+000, 1.57618307e-001, 2.13477838e+000], + 'fb': [9.94660135e+000, 4.15378676e-002, 2.40480572e-001], + 'fc': [5.01907609e-001, 3.80889010e+000, 5.96625028e-002], + 'fd': [3.66252019e-001, 2.43275968e+001, 6.59653503e-002]}, + 'Pr': {'Z': 59, 'chisq': 0.029725, + 'bond_length': [2.03, 1.83, 1.70, 0], + 'fa': [1.58189324e-001, 3.18141995e+000, 2.27622140e+000], + 'fb': [3.91309056e-002, 1.04139545e+001, 2.81671757e-001], + 'fc': [3.97705472e+000, 5.58448277e-002, 4.85207954e-001], + 'fd': [2.61872978e+001, 6.30921695e-002, 3.54234369e-001]}, + 'Nd': {'Z': 60, 'chisq': 0.027597, + 'bond_length': [2.02, 1.82, 1.70, 0], + 'fa': [1.81379417e-001, 3.17616396e+000, 2.35221519e+000], + 'fb': [4.37324793e-002, 1.07842572e+001, 3.05571833e-001], + 'fc': [3.83125763e+000, 5.25889976e-002, 4.70090742e-001], + 'fd': [2.54745408e+001, 6.02676073e-002, 3.39017003e-001]}, + 'Pm': {'Z': 61, 'chisq': 0.025208, + 'bond_length': [2.01, 1.81, 1.70, 0], + 'fa': [1.92986811e-001, 2.43756023e+000, 3.17248504e+000], + 'fb': [4.37785970e-002, 3.29336996e-001, 1.11259996e+001], + 'fc': [3.58105414e+000, 4.56529394e-001, 4.94812177e-002], + 'fd': [2.46709586e+001, 3.24990282e-001, 5.76553100e-002]}, + 'Sm': {'Z': 62, 'chisq': 0.023540, + 'bond_length': [2.00, 1.80, 1.70, 0], + 'fa': [2.12002595e-001, 3.16891754e+000, 2.51503494e+000], + 'fb': [4.57703608e-002, 1.14536599e+001, 3.55561054e-001], + 'fc': [4.44080845e-001, 3.36742101e+000, 4.65652543e-002], + 'fd': [3.11953363e-001, 2.40291435e+001, 5.52266819e-002]}, + 'Eu': {'Z': 63, 'chisq': 0.022204, + 'bond_length': [2.24, 2.04, 1.70, 0], + 'fa': [2.59355002e+000, 3.16557522e+000, 2.29402652e-001], + 'fb': [3.82452612e-001, 1.17675155e+001, 4.76642249e-002], + 'fc': [4.32257780e-001, 3.17261920e+000, 4.37958317e-002], + 'fd': [2.99719833e-001, 2.34462738e+001, 5.29440680e-002]}, + 'Gd': {'Z': 64, 'chisq': 0.017492, + 'bond_length': [2.00, 1.80, 1.70, 0], + 'fa': [3.19144939e+000, 2.55766431e+000, 3.32681934e-001], + 'fb': [1.20224655e+001, 4.08338876e-001, 5.85819814e-002], + 'fc': [4.14243130e-002, 2.61036728e+000, 4.20526863e-001], + 'fd': [5.06771477e-002, 1.99344244e+001, 2.85686240e-001]}, + 'Tb': {'Z': 65, 'chisq': 0.020036, + 'bond_length': [1.98, 1.78, 1.70, 0], + 'fa': [2.59407462e-001, 3.16177855e+000, 2.75095751e+000], + 'fb': [5.04689354e-002, 1.23140183e+001, 4.38337626e-001], + 'fc': [2.79247686e+000, 3.85931001e-002, 4.10881708e-001], + 'fd': [2.23797309e+001, 4.87920992e-002, 2.77622892e-001]}, + 'Dy': {'Z': 66, 'chisq': 0.019351, + 'bond_length': [1.97, 1.77, 1.70, 0], + 'fa': [3.16055396e+000, 2.82751709e+000, 2.75140255e-001], + 'fb': [1.25470414e+001, 4.67899094e-001, 5.23226982e-002], + 'fc': [4.00967160e-001, 2.63110834e+000, 3.61333817e-002], + 'fd': [2.67614884e-001, 2.19498166e+001, 4.68871497e-002]}, + 'Ho': {'Z': 67, 'chisq': 0.018720, + 'bond_length': [1.98, 1.78, 1.70, 0], + 'fa': [2.88642467e-001, 2.90567296e+000, 3.15960159e+000], + 'fb': [5.40507687e-002, 4.97581077e-001, 1.27599505e+001], + 'fc': [3.91280259e-001, 2.48596038e+000, 3.37664478e-002], + 'fd': [2.58151831e-001, 2.15400972e+001, 4.50664323e-002]}, + 'Er': {'Z': 68, 'chisq': 0.018677, + 'bond_length': [1.96, 1.76, 1.70, 0], + 'fa': [3.15573213e+000, 3.11519560e-001, 2.97722406e+000], + 'fb': [1.29729009e+001, 5.81399387e-002, 5.31213394e-001], + 'fc': [3.81563854e-001, 2.40247532e+000, 3.15224214e-002], + 'fd': [2.49195776e-001, 2.13627616e+001, 4.33253257e-002]}, + 'Tm': {'Z': 69, 'chisq': 0.018176, + 'bond_length': [1.95, 1.75, 1.70, 0], + 'fa': [3.15591970e+000, 3.22544710e-001, 3.05569053e+000], + 'fb': [1.31232407e+001, 5.97223323e-002, 5.61876773e-001], + 'fc': [2.92845100e-002, 3.72487205e-001, 2.27833695e+000], + 'fd': [4.16534255e-002, 2.40821967e-001, 2.10034185e+001]}, + 'Yb': {'Z': 70, 'chisq': 0.018460, + 'bond_length': [2.10, 1.90, 1.70, 0], + 'fa': [3.10794704e+000, 3.14091221e+000, 3.75660454e-001], + 'fb': [6.06347847e-001, 1.33705269e+001, 7.29814740e-002], + 'fc': [3.61901097e-001, 2.45409082e+000, 2.72383990e-002], + 'fd': [2.32652051e-001, 2.12695209e+001, 3.99969597e-002]}, + 'Lu': {'Z': 71, 'chisq': 0.015021, + 'bond_length': [1.93, 1.73, 1.70, 0], + 'fa': [3.11446863e+000, 5.39634353e-001, 3.06460915e+000], + 'fb': [1.38968881e+001, 8.91708508e-002, 6.79919563e-001], + 'fc': [2.58563745e-002, 2.13983556e+000, 3.47788231e-001], + 'fd': [3.82808522e-002, 1.80078788e+001, 2.22706591e-001]}, + 'Hf': {'Z': 72, 'chisq': 0.012070, + 'bond_length': [1.78, 1.58, 1.70, 0], + 'fa': [3.01166899e+000, 3.16284788e+000, 6.33421771e-001], + 'fb': [7.10401889e-001, 1.38262192e+001, 9.48486572e-002], + 'fc': [3.41417198e-001, 1.53566013e+000, 2.40723773e-002], + 'fd': [2.14129678e-001, 1.55298698e+001, 3.67833690e-002]}, + 'Ta': {'Z': 73, 'chisq': 0.010775, + 'bond_length': [1.67, 1.47, 1.70, 0], + 'fa': [3.20236821e+000, 8.30098413e-001, 2.86552297e+000], + 'fb': [1.38446369e+001, 1.18381581e-001, 7.66369118e-001], + 'fc': [2.24813887e-002, 1.40165263e+000, 3.33740596e-001], + 'fd': [3.52934622e-002, 1.46148877e+001, 2.05704486e-001]}, + 'W': {'Z': 74, 'chisq': 0.009479, + 'bond_length': [1.61, 1.41, 1.70, 0], + 'fa': [9.24906855e-001, 2.75554557e+000, 3.30440060e+000], + 'fb': [1.28663377e-001, 7.65826479e-001, 1.34471170e+001], + 'fc': [3.29973862e-001, 1.09916444e+000, 2.06498883e-002], + 'fd': [1.98218895e-001, 1.35087534e+001, 3.38918459e-002]}, + 'Re': {'Z': 75, 'chisq': 0.004620, + 'bond_length': [1.58, 1.38, 1.70, 0], + 'fa': [1.96952105e+000, 1.21726619e+000, 4.10391685e+000], + 'fb': [4.98830620e+001, 1.33243809e-001, 1.84396916e+000], + 'fc': [2.90791978e-002, 2.30696669e-001, 6.08840299e-001], + 'fd': [2.84192813e-002, 1.90968784e-001, 1.37090356e+000]}, + 'Os': {'Z': 76, 'chisq': 0.003085, + 'bond_length': [1.55, 1.35, 1.70, 0], + 'fa': [2.06385867e+000, 1.29603406e+000, 3.96920673e+000], + 'fb': [4.05671697e+001, 1.46559047e-001, 1.82561596e+000], + 'fc': [2.69835487e-002, 2.31083999e-001, 6.30466774e-001], + 'fd': [2.84172045e-002, 1.79765184e-001, 1.38911543e+000]}, + 'Ir': {'Z': 77, 'chisq': 0.003924, + 'bond_length': [1.56, 1.36, 1.70, 0], + 'fa': [2.21522726e+000, 1.37573155e+000, 3.78244405e+000], + 'fb': [3.24464090e+001, 1.60920048e-001, 1.78756553e+000], + 'fc': [2.44643240e-002, 2.36932016e-001, 6.48471412e-001], + 'fd': [2.82909938e-002, 1.70692368e-001, 1.37928390e+000]}, + 'Pt': {'Z': 78, 'chisq': 0.003817, + 'bond_length': [1.59, 1.39, 1.72, 0], + 'fa': [9.84697940e-001, 2.73987079e+000, 3.61696715e+000], + 'fb': [1.60910839e-001, 7.18971667e-001, 1.29281016e+001], + 'fc': [3.02885602e-001, 2.78370726e-001, 1.52124129e-002], + 'fd': [1.70134854e-001, 1.49862703e+000, 2.83510822e-002]}, + 'Au': {'Z': 79, 'chisq': 0.003143, + 'bond_length': [1.64, 1.44, 1.66, 0], + 'fa': [9.61263398e-001, 3.69581030e+000, 2.77567491e+000], + 'fb': [1.70932277e-001, 1.29335319e+001, 6.89997070e-001], + 'fc': [2.95414176e-001, 3.11475743e-001, 1.43237267e-002], + 'fd': [1.63525510e-001, 1.39200901e+000, 2.71265337e-002]}, + 'Hg': {'Z': 80, 'chisq': 0.002717, + 'bond_length': [1.77, 1.57, 1.55, 0], + 'fa': [1.29200491e+000, 2.75161478e+000, 3.49387949e+000], + 'fb': [1.83432865e-001, 9.42368371e-001, 1.46235654e+001], + 'fc': [2.77304636e-001, 4.30232810e-001, 1.48294351e-002], + 'fd': [1.55110144e-001, 1.28871670e+000, 2.61903834e-002]}, + 'Tl': {'Z': 81, 'chisq': 0.003492, + 'bond_length': [1.92, 1.72, 1.96, 0], + 'fa': [3.75964730e+000, 3.21195904e+000, 6.47767825e-001], + 'fb': [1.35041513e+001, 6.66330993e-001, 9.22518234e-002], + 'fc': [2.76123274e-001, 3.18838810e-001, 1.31668419e-002], + 'fd': [1.50312897e-001, 1.12565588e+000, 2.48879842e-002]}, + 'Pb': {'Z': 82, 'chisq': 0.001158, + 'bond_length': [1.95, 1.75, 2.02, 0], + 'fa': [1.00795975e+000, 3.09796153e+000, 3.61296864e+000], + 'fb': [1.17268427e-001, 8.80453235e-001, 1.47325812e+001], + 'fc': [2.62401476e-001, 4.05621995e-001, 1.31812509e-002], + 'fd': [1.43491014e-001, 1.04103506e+000, 2.39575415e-002]}, + 'Bi': {'Z': 83, 'chisq': 0.026436, + 'bond_length': [1.90, 1.70, 1.70, 0], + 'fa': [1.59826875e+000, 4.38233925e+000, 2.06074719e+000], + 'fb': [1.56897471e-001, 2.47094692e+000, 5.72438972e+001], + 'fc': [1.94426023e-001, 8.22704978e-001, 2.33226953e-002], + 'fd': [1.32979109e-001, 9.56532528e-001, 2.23038435e-002]}, + 'Po': {'Z': 84, 'chisq': 0.008962, + 'bond_length': [1.96, 1.76, 1.70, 0], + 'fa': [1.71463223e+000, 2.14115960e+000, 4.37512413e+000], + 'fb': [9.79262841e+001, 2.10193717e-001, 3.66948812e+000], + 'fc': [2.16216680e-002, 1.97843837e-001, 6.52047920e-001], + 'fd': [1.98456144e-002, 1.33758807e-001, 7.80432104e-001]}, + 'At': {'Z': 85, 'chisq': 0.033776, + 'bond_length': [2.00, 1.80, 1.70, 0], + 'fa': [1.48047794e+000, 2.09174630e+000, 4.75246033e+000], + 'fb': [1.25943919e+002, 1.83803008e-001, 4.19890596e+000], + 'fc': [1.85643958e-002, 2.05859375e-001, 7.13540948e-001], + 'fd': [1.81383503e-002, 1.33035404e-001, 7.03031938e-001]}, + 'Rn': {'Z': 86, 'chisq': 0.050132, + 'bond_length': [2.40, 2.20, 1.70, 0], + 'fa': [6.30022295e-001, 3.80962881e+000, 3.89756067e+000], + 'fb': [1.40909762e-001, 3.08515540e+001, 6.51559763e-001], + 'fc': [2.40755100e-001, 2.62868577e+000, 3.14285931e-002], + 'fd': [1.08899672e-001, 6.42383261e+000, 2.42346699e-002]}, + 'Fr': {'Z': 87, 'chisq': 0.056720, + 'bond_length': [3.00, 2.80, 1.70, 0], + 'fa': [5.23288135e+000, 2.48604205e+000, 3.23431354e-001], + 'fb': [8.60599536e+000, 3.04543982e-001, 3.87759096e-002], + 'fc': [2.55403596e-001, 5.53607228e-001, 5.75278889e-003], + 'fd': [1.28717724e-001, 5.36977452e-001, 1.29417790e-002]}, + 'Ra': {'Z': 88, 'chisq': 0.081498, + 'bond_length': [2.46, 2.26, 1.70, 0], + 'fa': [1.44192685e+000, 3.55291725e+000, 3.91259586e+000], + 'fb': [1.18740873e-001, 1.01739750e+000, 6.31814783e+001], + 'fc': [2.16173519e-001, 3.94191605e+000, 4.60422605e-002], + 'fd': [9.55806441e-002, 3.50602732e+001, 2.20850385e-002]}, + 'Ac': {'Z': 89, 'chisq': 0.077643, + 'bond_length': [2.09, 1.88, 1.70, 0], + 'fa': [1.45864127e+000, 4.18945405e+000, 3.65866182e+000], + 'fb': [1.07760494e-001, 8.89090649e+001, 1.05088931e+000], + 'fc': [2.08479229e-001, 3.16528117e+000, 5.23892556e-002], + 'fd': [9.09335557e-002, 3.13297788e+001, 2.08807697e-002]}, + 'Th': {'Z': 90, 'chisq': 0.048096, + 'bond_length': [2.00, 1.80, 1.70, 0], + 'fa': [1.19014064e+000, 2.55380607e+000, 4.68110181e+000], + 'fb': [7.73468729e-002, 6.59693681e-001, 1.28013896e+001], + 'fc': [2.26121303e-001, 3.58250545e-001, 7.82263950e-003], + 'fd': [1.08632194e-001, 4.56765664e-001, 1.62623474e-002]}, + 'Pa': {'Z': 91, 'chisq': 0.070186, + 'bond_length': [1.83, 1.63, 1.70, 0], + 'fa': [4.68537504e+000, 2.98413708e+000, 8.91988061e-001], + 'fb': [1.44503632e+001, 5.56438592e-001, 6.69512914e-002], + 'fc': [2.24825384e-001, 3.04444846e-001, 9.48162708e-003], + 'fd': [1.03235396e-001, 4.27255647e-001, 1.77730611e-002]}, + 'U': {'Z': 92, 'chisq': 0.072478, + 'bond_length': [1.76, 1.56, 1.86, 0], + 'fa': [4.63343606e+000, 3.18157056e+000, 8.76455075e-001], + 'fb': [1.63377267e+001, 5.69517868e-001, 6.88860012e-002], + 'fc': [2.21685477e-001, 2.72917100e-001, 1.11737298e-002], + 'fd': [9.84254550e-002, 4.09470917e-001, 1.86215410e-002]}, + 'Np': {'Z': 93, 'chisq': 0.074792, + 'bond_length': [1.80, 1.60, 1.70, 0], + 'fa': [4.56773888e+000, 3.40325179e+000, 8.61841923e-001], + 'fb': [1.90992795e+001, 5.90099634e-001, 7.03204851e-002], + 'fc': [2.19728870e-001, 2.38176903e-001, 1.38306499e-002], + 'fd': [9.36334280e-002, 3.93554882e-001, 1.94437286e-002]}, + 'Pu': {'Z': 94, 'chisq': 0.071877, + 'bond_length': [1.84, 1.64, 1.70, 0], + 'fa': [5.45671123e+000, 1.11687906e-001, 3.30260343e+000], + 'fb': [1.01892720e+001, 3.98131313e-002, 3.14622212e-001], + 'fc': [1.84568319e-001, 4.93644263e-001, 3.57484743e+000], + 'fd': [1.04220860e-001, 4.63080540e-001, 2.19369542e+001]}, + 'Am': {'Z': 95, 'chisq': 0.062156, + 'bond_length': [2.01, 1.81, 1.70, 0], + 'fa': [5.38321999e+000, 1.23343236e-001, 3.46469090e+000], + 'fb': [1.07289857e+001, 4.15137806e-002, 3.39326208e-001], + 'fc': [1.75437132e-001, 3.39800073e+000, 4.69459519e-001], + 'fd': [9.98932346e-002, 2.11601535e+001, 4.51996970e-001]}, + 'Cm': {'Z': 96, 'chisq': 0.050111, + 'bond_length': [2.20, 2.00, 1.70, 0], + 'fa': [5.38402377e+000, 3.49861264e+000, 1.88039547e-001], + 'fb': [1.11211419e+001, 3.56750210e-001, 5.39853583e-002], + 'fc': [1.69143137e-001, 3.19595016e+000, 4.64393059e-001], + 'fd': [9.60082633e-002, 1.80694389e+001, 4.36318197e-001]}, + 'Bk': {'Z': 97, 'chisq': 0.044081, + 'bond_length': [2.20, 2.00, 1.70, 0], + 'fa': [3.66090688e+000, 2.03054678e-001, 5.30697515e+000], + 'fb': [3.84420906e-001, 5.48547131e-002, 1.17150262e+001], + 'fc': [1.60934046e-001, 3.04808401e+000, 4.43610295e-001], + 'fd': [9.21020329e-002, 1.73525367e+001, 4.27132359e-001]}, + 'Cf': {'Z': 98, 'chisq': 0.041053, + 'bond_length': [2.20, 2.00, 1.70, 0], + 'fa': [3.94150390e+000, 5.16915345e+000, 1.61941074e-001], + 'fb': [4.18246722e-001, 1.25201788e+001, 4.81540117e-002], + 'fc': [4.15299561e-001, 2.91761325e+000, 1.51474927e-001], + 'fd': [4.24913856e-001, 1.90899693e+001, 8.81568925e-002]} + } +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/diffraction_plot.html b/_modules/pyTEMlib/diffraction_plot.html new file mode 100644 index 00000000..7e070568 --- /dev/null +++ b/_modules/pyTEMlib/diffraction_plot.html @@ -0,0 +1,871 @@ + + + + + + pyTEMlib.diffraction_plot — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.diffraction_plot

+import matplotlib.pyplot as plt
+
+import matplotlib.patches as patches
+from mpl_toolkits.axes_grid1.anchored_artists import AnchoredSizeBar
+from matplotlib.patches import Circle  # , Ellipse, Rectangle
+from matplotlib.collections import PatchCollection
+from matplotlib.lines import Line2D
+
+from scipy.interpolate import interp1d
+from scipy.ndimage import map_coordinates, geometric_transform
+
+import ase
+import numpy as np
+import sidpy
+
+# ##################################
+# Plot Reciprocal Unit Cell in 2D #
+# ##################################
+
+
+
[docs]def plot_reciprocal_unit_cell_2D(atoms): + """Plot # unit cell in reciprocal space in 2D""" + + reciprocal_unit_cell = atoms.get_reciprocal_cell() + + # ignore y direction + + x = [reciprocal_unit_cell[0, 0], reciprocal_unit_cell[0, 0], reciprocal_unit_cell[1, 0], reciprocal_unit_cell[1, 0]] + z = [reciprocal_unit_cell[0, 2], reciprocal_unit_cell[2, 2], reciprocal_unit_cell[2, 2], reciprocal_unit_cell[0, 2]] + + # Plot 2D + fig = plt.figure() + ax = plt.gca() # current axis + + ax.scatter(x, z, c='red', s=80) + ax.add_patch( + patches.Rectangle( + (0, 0), # (x,y) + reciprocal_unit_cell[0, 0], # width + reciprocal_unit_cell[2, 2], # height + fill=False # remove background + ) + ) + ax.add_patch( + patches.FancyArrow(0, 0, reciprocal_unit_cell[0, 0], 0, width=0.02, + color='black', + head_width=0.08, # Default: 3 * width + head_length=0.1, # Default: 1.5 * head_width + length_includes_head=True # Default: False + ) + ) + ax.add_patch( + patches.FancyArrow(0, 0, 0, reciprocal_unit_cell[2, 2], width=0.02, + color='black', + head_width=0.08, # Default: 3 * width + head_length=0.1, # Default: 1.5 * head_width + length_includes_head=True # Default: False + ) + ) + + plt.xlabel('x 1/nm') + plt.ylabel('z 1/nm') + ax.axis('equal') + # plt.title('Unit Cell in Reciprocal Space of {0}'.format(tags['crystal']) ) + # texfig.savefig("recip_unit_cell") + # fig.savefig('recip_unit_cell.jpg', dpi=90, bbox_inches='tight') + plt.show() + return fig
+ + +# #################### +# Plot SAED Pattern # +# #################### +
[docs]def plotSAED_parameter(gray=False): + + tags = {'convergence_angle_A-1': 0, + 'background': 'white', # 'white' 'grey' + 'color_map': 'plasma', # ,'cubehelix' #'Greys'#'plasma' + 'color_reflections': 'intensity'} + + if gray: + tags['color_map'] = 'gray' + tags['background'] = '#303030' # 'darkgray' + tags['color_reflections'] = 'intensity' + tags['plot_HOLZ'] = 0 + tags['plot_HOLZ_excess'] = 0 + tags['plot_Kikuchi'] = 1 + tags['plot_reflections'] = 1 + + tags['color_Kikuchi'] = 'green' + + tags['linewidth_HOLZ'] = -1 # -1: linewidth according to intensity (structure factor F^2 + tags['linewidth_Kikuchi'] = -1 # -1: linewidth according to intensity (structure factor F^2 + + tags['label_HOLZ'] = 0 + tags['label_Kikuchi'] = 0 + tags['label_reflections'] = 0 + + tags['label_color'] = 'white' + tags['label_size'] = 10 + + tags['color_Laue_Zones'] = ['red', 'blue', 'green', 'blue', 'green'] # , 'green', 'red'] #for OLZ give a sequence + tags['color_zero'] = 'red' # 'None' #'white' + tags['color_ring_zero'] = 'None' # 'Red' #'white' #, 'None' + tags['width_ring_zero'] = .2 + + # plotDiffPattern(tags,True) + tags['plot_rotation'] = 0. # degree + tags['plot_shift_x'] = -0.0 + tags['plot_shift_y'] = 0.0 + + return tags
+ + +######################## +# Plot Kikuchi Pattern # +######################## +
[docs]def plotKikuchi(grey=False): + tags = {'background': 'black', # 'white' 'grey' + 'color_map': 'plasma', # ,'cubehelix'#'Greys'#'plasma' + 'color_reflections': 'intensity', + 'plot_HOLZ': 0, + 'plot_HOLZ_excess': 0, + 'plot_Kikuchi': 1, + 'plot_reflections': 1, + 'label_HOLZ': 0, + 'label_Kikuchi': 0, + 'label_reflections': 0, + 'label_color': 'white', + 'label_size': 10, + 'color_Kikuchi': 'green', + 'linewidth_HOLZ': -1, # -1: linewidth according to intensity (structure factor F^2 + 'linewidth_Kikuchi': -1, # -1: linewidth according to intensity (structure factor F^2 + 'color_Laue_Zones': ['red', 'blue', 'green', 'blue', 'green'], # , 'green', 'red'] #for OLZ give a sequence + 'color_zero': 'white', # 'None' #'white' + 'color_ring_zero': 'None', # 'Red' #'white' #, 'None' + 'width_ring_zero': 2} + + if grey: + tags['color_map'] = 'gray' + tags['background'] = '#303030' # 'darkgray' + tags['color_reflections'] = 'intensity' + + return tags
+ + # plotDiffPattern(tags,True) + + +######################## +# Plot HOLZ Pattern # +######################## + +
[docs]def plotHOLZ_parameter(grey=False): + tags = {'background': 'gray', 'color_map': 'plasma', 'color_reflections': 'intensity', 'plot_HOLZ': 1, + 'plot_HOLZ_excess': 1, 'plot_Kikuchi': 1, 'plot_reflections': 1, 'label_HOLZ': 0, 'label_Kikuchi': 0, + 'label_reflections': 0, 'label_color': 'white', 'label_size': 12, 'color_Kikuchi': 'green', + 'linewidth_HOLZ': 1, 'linewidth_Kikuchi': -1, + 'color_Laue_Zones': ['red', 'blue', 'lightblue', 'green', 'red'], 'color_zero': 'None', + 'color_ring_zero': 'Red', 'width_ring_zero': 2, 'plot_rotation': 0., 'plot_shift_x': -0.0, + 'plot_shift_y': 0.0} # 'white' 'grey' + + # plotDiffPattern(holz,True) + return tags
+ + +######################## +# Plot CBED Pattern # +######################## + +
[docs]def plotCBED_parameter(): + tags = {'background': 'black', 'color_map': 'plasma', 'color_reflections': 'intensity', 'plot_HOLZ': 1, + 'plot_HOLZ_excess': 1, 'plot_Kikuchi': 1, 'plot_reflections': 1, 'label_HOLZ': 0, 'label_Kikuchi': 0, + 'label_reflections': 0, 'label_color': 'white', 'label_size': 10, 'color_Kikuchi': 'green', + 'linewidth_HOLZ': -1, 'linewidth_Kikuchi': -1, 'color_Laue_Zones': ['red', 'blue', 'green'], + 'color_zero': 'white', 'color_ring_zero': 'Red', 'width_ring_zero': 2} # 'white' 'grey' + + # plotDiffPattern(tags,True) + return tags
+ +######################## +# Plot HOLZ Pattern # +######################## + + +
[docs]def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs): + """ + Make a scatter plot of circles. + Similar to plt.scatter, but the size of circles are in data scale. + Parameters + ---------- + x, y : scalar or array_like, shape (n, ) + Input data + s : scalar or array_like, shape (n, ) + Radius of circles. + c : color or sequence of color, optional, default : 'b' + `c` can be a single color format string, or a sequence of color + specifications of length `N`, or a sequence of `N` numbers to be + mapped to colors using the `cmap` and `norm` specified via kwargs. + Note that `c` should not be a single numeric RGB or RGBA sequence + because that is indistinguishable from an array of values + to be colormapped. (If you insist, use `color` instead.) + `c` can be a 2-D array in which the rows are RGB or RGBA, however. + vmin, vmax : scalar, optional, default: None + `vmin` and `vmax` are used in conjunction with `norm` to normalize + luminance data. If either are `None`, the min and max of the + color array is used. + kwargs : `~matplotlib.collections.Collection` properties + Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), linestyle(ls), + norm, cmap, transform, etc. + Returns + ------- + paths : `~matplotlib.collections.PathCollection` + Examples + -------- + a = np.arange(11) + circles(a, a, s=a*0.2, c=a, alpha=0.5, ec='none') + plt.colorbar() + License + -------- + This code is under [The BSD 3-Clause License] + (http://opensource.org/licenses/BSD-3-Clause) + """ + + if np.isscalar(c): + kwargs.setdefault('color', c) + c = None + + if 'fc' in kwargs: + kwargs.setdefault('facecolor', kwargs.pop('fc')) + if 'ec' in kwargs: + kwargs.setdefault('edgecolor', kwargs.pop('ec')) + if 'ls' in kwargs: + kwargs.setdefault('linestyle', kwargs.pop('ls')) + if 'lw' in kwargs: + kwargs.setdefault('linewidth', kwargs.pop('lw')) + # You can set `facecolor` with an array for each patch, + # while you can only set `facecolors` with a value for all. + + zipped = np.broadcast(x, y, s) + patches = [Circle((x_, y_), s_, picker=True) + for x_, y_, s_ in zipped] + collection = PatchCollection(patches, **kwargs) + if c is not None: + c = np.broadcast_to(c, zipped.shape).ravel() + collection.set_array(c) + collection.set_clim(vmin, vmax) + + ax = plt.gca() + ax.add_collection(collection) + ax.autoscale_view() + plt.draw_if_interactive() + if c is not None: + plt.sci(collection) + return collection
+ + +
[docs]def cartesian2polar(x, y, grid, r, t, order=3): + R, T = np.meshgrid(r, t) + + new_x = R * np.cos(T) + new_y = R * np.sin(T) + + ix = interp1d(x, np.arange(len(x))) + iy = interp1d(y, np.arange(len(y))) + + new_ix = ix(new_x.ravel()) + new_iy = iy(new_y.ravel()) + + return map_coordinates(grid, np.array([new_ix, new_iy]), + order=order).reshape(new_x.shape)
+ + +
[docs]def warp(diff, center): + """ + Define original polar grid + + Parameter: + ---------- + diff: sidpy object or numpy ndarray of + diffraction pattern + center: list or numpy array of length 2 + coordinates of center in pixel + + Return: + ------ + numpy array of diffraction pattern in polar coordinates + + """ + nx = diff.shape[0] + ny = diff.shape[1] + + x = np.linspace(1, nx, nx, endpoint=True) - center[0] + y = np.linspace(1, ny, ny, endpoint=True) - center[1] + z = diff + + # Define new polar grid + nr = int(min([center[0], center[1], diff.shape[0] - center[0], diff.shape[1] - center[1]]) - 1) + print(nr) + nt = 360 * 3 + + r = np.linspace(1, nr, nr) + t = np.linspace(0., np.pi, nt, endpoint=False) + return cartesian2polar(x, y, z, r, t, order=3).T
+ + +
[docs]def topolar(img, order=1): + """ + Transform img to its polar coordinate representation. + + order: int, default 1 + Specify the spline interpolation order. + High orders may be slow for large images. + """ + # max_radius is the length of the diagonal + # from a corner to the mid-point of img. + max_radius = 0.5 * np.linalg.norm(img.shape) + + def transform(coords): + # Put coord[1] in the interval, [-pi, pi] + theta = 2 * np.pi * coords[1] / (img.shape[1] - 1.) + + # Then map it to the interval [0, max_radius]. + # radius = float(img.shape[0]-coords[0]) / img.shape[0] * max_radius + radius = max_radius * coords[0] / img.shape[0] + + i = 0.5 * img.shape[0] - radius * np.sin(theta) + j = radius * np.cos(theta) + 0.5 * img.shape[1] + return i, j + + polar = geometric_transform(img, transform, order=order) + + rads = max_radius * np.linspace(0, 1, img.shape[0]) + angs = np.linspace(0, 2 * np.pi, img.shape[1]) + + return polar, (rads, angs)
+ + +
[docs]def plot_ring_pattern(atoms, diffraction_pattern=None, grey=False): + """ + Plot of ring diffraction pattern with matplotlib + + Parameters + ---------- + atoms: dictionary or sidpy.Dataset + information stored as dictionary either directly or in metadata attribute of sidpy.Dataset + grey: bool + plotting in greyscale if True + + Returns + ------- + fig: matplotlib figure + reference to matplotlib figure + """ + + if isinstance(atoms, dict): + tags = atoms + elif isinstance(atoms, ase.Atoms): + if 'diffraction' in atoms.info: + tags = atoms.info['diffraction'] + plot_diffraction_pattern = True + else: + raise TypeError('Diffraction information must be in metadata') + else: + raise TypeError('Diffraction info must be in sidpy Dataset or dictionary form') + if diffraction_pattern is not None: + if not(diffraction_pattern, sidpy.Dataset): + print('diffraction_pattern must be a sidpy.Dataset \n -> Ignoring this variable') + diffraction_pattern = None + d = tags['Ring_Pattern']['allowed']['g norm'] + label = tags['Ring_Pattern']['allowed']['label'] + if 'label_color' not in tags: + tags['label_color'] = 'navy' + if 'profile color' not in tags: + tags['profile color'] = 'navy' + if 'ring color' not in tags: + tags['ring color'] = 'red' + if 'label_size' not in tags: + tags['label_size'] = 10 + if 'profile height' not in tags: + tags['profile height'] = 5 + if 'plot_scalebar' not in tags: + tags['plot_scalebar'] = False + + fg, ax = plt.subplots(1, 1) + + # ### + # plot arcs of the rings + # ### + for i in range(len(d)): + pac = patches.Arc((0, 0), d[i] * 2, d[i] * 2, angle=0, theta1=45, theta2=360, color=tags['ring color']) + ax.add_patch(pac) + + #### + # show image in background + #### + if plot_diffraction_pattern is not None: + plt.imshow(diffraction_pattern, extent=diffraction_pattern.get_extent(), cmap='gray') + + ax.set_aspect("equal") + + # fg.canvas.draw() + + if tags['plot_scalebar']: + def f(axis): + l = axis.get_majorticklocs() + return len(l) > 1 and (l[1] - l[0]) + + sizex = f(ax.xaxis) + labelx = str(sizex) + ' 1/nm' + scalebar = AnchoredSizeBar(ax.transData, sizex, labelx, loc=3, + pad=0.5, color='white', frameon=False) + # size_vertical=.2, fill_bar = True) # will be implemented in matplotlib 2.1 + + ax.add_artist(scalebar) + ax.axis('off') + + # #### + # plot profile + # #### + + y = tags['Ring_Pattern']['profile_y'] + y = y / y.max() * tags['profile height'] + x = tags['Ring_Pattern']['profile_x'] + ax.plot(x, y, c=tags['profile color']) + + ax.plot([0, x[-1]], [0, 0], c=tags['profile color']) + + if 'experimental profile_y' in tags: + yy = tags['experimental profile_y'] + yy = yy / yy.max() * tags['profile height'] + xx = tags['experimental profile_x'] + ax.plot(xx, yy, c=tags['experimental profile color']) + + if 'plot_image_FOV' in tags: + max_d = tags['plot_image_FOV'] / 2 + tags['plot_shift_x'] + else: + max_d = d.max() + for i in range(len(d)): + if d[i] < max_d: + plt.text(d[i] - .2, -.5, label[i], fontsize=tags['label_size'], color=tags['label_color'], rotation=90) + + if 'plot_FOV' in tags: + l = -tags['plot_FOV'] / 2 + r = tags['plot_FOV'] / 2 + t = -tags['plot_FOV'] / 2 + b = tags['plot_FOV'] / 2 + plt.xlim(l, r) + plt.ylim(t, b) + + fg.show() + return fg
+ + +
[docs]def plot_diffraction_pattern(atoms, diffraction_pattern=None, grey=False): + """ + Plot of spot diffraction pattern with matplotlib + Plot of spot diffraction pattern with matplotlib + + Parameters + ---------- + atoms: dictionary or ase.Atoms object + information stored as dictionary either directly or in info attribute of ase.Atoms object + diffraction_pattern: None or sidpy.Dataset + diffraction pattern in background + grey: bool + plotting in greyscale if True + + Returns + ------- + fig: matplotlib figure + reference to matplotlib figure + """ + + if isinstance(atoms, dict): + tags_out = atoms + + elif isinstance(atoms, ase.Atoms): + if 'diffraction' in atoms.info: + tags_out = atoms.info['diffraction'] + plot_diffraction_pattern = True + else: + raise TypeError('Diffraction information must be in info dictionary of ase.Atoms object') + else: + raise TypeError('Diffraction info must be in ase.Atoms object or dictionary form') + + if 'output' not in atoms.info: + return + + # Get information from dictionary + HOLZ = tags_out['HOLZ'] + ZOLZ = tags_out['allowed']['ZOLZ'] + # Kikuchi = tags_out['Kikuchi'] + + Laue_Zone = tags_out['allowed']['Laue_Zone'] + + label = tags_out['allowed']['label'] + hkl_label = tags_out['allowed']['hkl'] + + angle = np.radians(atoms.info['output']['plot_rotation']) # mrad + c = np.cos(angle) + s = np.sin(angle) + r_mat = np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]]) + + # HOLZ and Kikuchi lines coordinates in Hough space + LC = tags_out['Laue_circle'] + gd = np.dot(tags_out['HOLZ']['g_deficient'] + LC, r_mat) + ge = np.dot(tags_out['HOLZ']['g_excess'], r_mat) + points = np.dot(tags_out['allowed']['g'] + LC, r_mat) + + theta = tags_out['HOLZ']['theta'] + angle + + if 'thickness' not in tags_out: + tags_out['thickness'] = 0. + if tags_out['thickness'] > 0.1: + intensity = np.real(tags_out['allowed']['Ig']) + else: + intensity = tags_out['allowed']['intensities'] + + radius = atoms.info['experimental']['convergence_angle_A-1'] + + if radius < 0.1: + radiusI = 2 + else: + radiusI = radius + # Beginning and ends of HOLZ lines + max_length = radiusI * 1.3 + h_xp = gd[:, 0] + max_length * np.cos(np.pi - theta) + h_yp = gd[:, 1] + max_length * np.sin(np.pi - theta) + h_xm = gd[:, 0] - max_length * np.cos(np.pi - theta) + h_ym = gd[:, 1] - max_length * np.sin(np.pi - theta) + + # Beginning and ends of excess HOLZ lines + max_length = radiusI * .8 + e_xp = ge[:, 0] + max_length * np.cos(np.pi - theta) + e_yp = ge[:, 1] + max_length * np.sin(np.pi - theta) + e_xm = ge[:, 0] - max_length * np.cos(np.pi - theta) + e_ym = ge[:, 1] - max_length * np.sin(np.pi - theta) + + # Beginning and ends of Kikuchi lines + if 'max_length' not in tags_out['Kikuchi']: + tags_out['Kikuchi']['max_length'] = 20 + max_length = tags_out['Kikuchi']['max_length'] + + gd = tags_out['Kikuchi']['g_deficient'] + theta = tags_out['Kikuchi']['theta'] + k_xp = gd[:, 0] + max_length * np.cos(np.pi - theta) + k_yp = gd[:, 1] + max_length * np.sin(np.pi - theta) + k_xm = gd[:, 0] - max_length * np.cos(np.pi - theta) + k_ym = gd[:, 1] - max_length * np.sin(np.pi - theta) + + if atoms.info['output']['linewidth_Kikuchi'] < 0: + if len(intensity[ZOLZ]) > 0: + intensity_kikuchi = intensity * 4. / intensity[ZOLZ].max() + else: + intensity_kikuchi = intensity + else: + intensity_kikuchi = np.ones(len(intensity)) * atoms.info['output']['linewidth_Kikuchi'] + + if atoms.info['output']['linewidth_HOLZ'] < 0: + intensity_holz = np.log(intensity + 1) + + if tags_out['HOLZ']['HOLZ'].any(): + pass # intensity_holz = intensity/intensity[tags_out['HOLZ']['HOLZ']].max()*4. + else: + intensity_holz = np.ones(len(intensity)) * atoms.info['output']['linewidth_HOLZ'] + + # ####### + # Plot # + # ####### + # cms = mpl.cm + # cm = cms.plasma#jet#, cms.gray, cms.autumn] + cm = plt.get_cmap(atoms.info['output']['color_map']) + + # fig = plt.figure() + fig = plt.figure() + + ax = plt.gca() + if 'background' not in atoms.info['output']: + atoms.info['output']['background'] = None + if atoms.info['output']['background'] is not None: + ax.set_facecolor(atoms.info['output']['background']) + + if diffraction_pattern is not None: + plt.imshow(diffraction_pattern, extent=diffraction_pattern.get_extent([0, 1]), cmap='gray') + + ix = np.argsort((points ** 2).sum(axis=1)) + p = points[ix] + inten = intensity[ix] + reflection = hkl_label[ix] + laue_color = [] + + labelP = '' + lineLabel = [] + + def onpick(event): + if isinstance(event.artist, Line2D): + thisline = event.artist + ind = ax.lines.index(thisline) + print(ind, len(points), ind - len(points)) + # ind = ind- len(points) + h, k, l = lineLabel[ind] + + if Laue_Zone[ind] > 0: + labelP = 'Laue Zone %1d; HOLZ line: [%1d,%1d,%1d]' % (Laue_Zone[ind], h, k, l) + else: + labelP = 'Kikuchi line: [%1d,%1d,%1d]' % (h, k, l) + # print(labelP) + + elif isinstance(event.artist, Circle): + print('Circle') + + else: + ind = event.ind[0] + h, k, l = reflection[ind] + + print('Reflection: [%1d,%1d,%1d]' % (h, k, l)) + + for i in range(int(Laue_Zone.max()) + 1): + if i < len(atoms.info['output']['color_Laue_Zones']): + laue_color.append(atoms.info['output']['color_Laue_Zones'][i]) + else: + laue_color.append(atoms.info['output']['color_Laue_Zones'][-1]) + + if 'plot_labels' not in atoms.info['output']: + atoms.info['output']['plot_labels'] = True + if atoms.info['output']['plot_reflections']: + if radius < 0.01: + if atoms.info['output']['color_reflections'] == 'intensity': + for i in range(len(points)): + ax.scatter(points[i, 0], points[i, 1], c=np.log(intensity[i] + 1), cmap=cm, s=100) + + if atoms.info['output']['plot_labels']: + plt.text(points[i, 0], points[i, 1], label[i], fontsize=10) + else: + for i in range(len(Laue_Zone)): + color = laue_color[int(Laue_Zone[i])] + ax.scatter(points[i, 0], points[i, 1], c=color, cmap=cm, s=100) + if atoms.info['output']['plot_labels']: + plt.text(points[i, 0], points[i, 1], label[i], fontsize=8) + + ax.scatter(LC[0], LC[1], c=atoms.info['output']['color_zero'], s=100) + radius = .2 + else: + ix = np.argsort((points ** 2).sum(axis=1)) + p = points[ix] + inten = intensity[ix] + if atoms.info['output']['color_reflections'] == 'intensity': + circles(p[:, 0], p[:, 1], s=radius, c=np.log(inten + 1), cmap=cm, alpha=0.9, edgecolor=None, picker=5) + else: + for i in range(len(Laue_Zone)): + color = laue_color[int(Laue_Zone[i])] + circles(p[i, 0], p[i, 1], s=radius, c=color, cmap=cm, alpha=0.9, edgecolor='', picker=5) # + plt.text(points[i, 0], points[i, 1], label[i], fontsize=8) + + if 'plot_dynamically_allowed' not in atoms.info['output']: + atoms.info['output']['plot_dynamically_allowed'] = False + if 'plot_forbidden' not in atoms.info['output']: + atoms.info['output']['plot_forbidden'] = False + + if atoms.info['output']['plot_dynamically_allowed']: + if 'dynamically_allowed' not in atoms.info['diffraction']['forbidden']: + print('To plot dynamically allowed reflections you must run the get_dynamically_allowed function of ' + 'kinematic_scattering library first!') + else: + points = atoms.info['diffraction']['forbidden']['g'] + dynamically_allowed = atoms.info['diffraction']['forbidden']['dynamically_allowed'] + dyn_allowed = atoms.info['diffraction']['forbidden']['g'][dynamically_allowed, :] + dyn_label = atoms.info['diffraction']['forbidden']['hkl'][dynamically_allowed, :] + + color = laue_color[0] + ax.scatter(dyn_allowed[:, 0], dyn_allowed[:, 1], c='blue', alpha=0.4, s=70) + if atoms.info['output']['plot_labels']: + for i in range(len(dyn_allowed)): + plt.text(dyn_allowed[i, 0], dyn_allowed[i, 1], dyn_label[i], fontsize=8) + if atoms.info['output']['plot_forbidden']: + forbidden_g = atoms.info['diffraction']['forbidden']['g'][np.logical_not(dynamically_allowed), :] + forbidden_hkl = atoms.info['diffraction']['forbidden']['hkl'][np.logical_not(dynamically_allowed), :] + ax.scatter(forbidden_g[:, 0], forbidden_g[:, 1], c='orange', alpha=0.4, s=70) + if atoms.info['output']['plot_labels']: + for i in range(len(forbidden_g)): + plt.text(forbidden_g[i, 0], forbidden_g[i, 1], forbidden_hkl[i], fontsize=8) + elif atoms.info['output']['plot_forbidden']: + forbidden_g = atoms.info['diffraction']['forbidden']['g'] + forbidden_hkl = atoms.info['diffraction']['forbidden']['hkl'] + ax.scatter(forbidden_g[:, 0], forbidden_g[:, 1], c='orange', alpha=0.4, s=70) + if atoms.info['output']['plot_labels']: + for i in range(len(forbidden_g)): + plt.text(forbidden_g[i, 0], forbidden_g[i, 1], forbidden_hkl[i], fontsize=8) + + k = 0 + if atoms.info['output']['plot_HOLZ']: + for i in range(len(h_xp)): + if tags_out['HOLZ']['HOLZ'][i]: + color = laue_color[int(Laue_Zone[i])] + if atoms.info['output']['plot_HOLZ']: + # plot HOLZ lines + line, = plt.plot((h_xp[i], h_xm[i]), (h_yp[i], h_ym[i]), c=color, linewidth=intensity_holz[i], + picker=5) + if atoms.info['output']['label_HOLZ']: # Add indices + plt.text(h_xp[i], h_yp[i], label[i], fontsize=8) + lineLabel.append(hkl_label[i]) + # print(i, hkl_label[i], intensity_holz[i]) + + if atoms.info['output']['plot_HOLZ_excess']: + line, = plt.plot((e_xp[i], e_xm[i]), (e_yp[i], e_ym[i]), c=color, linewidth=intensity_holz[i]) + lineLabel.append(hkl_label[i]) + + if atoms.info['output']['label_HOLZ']: # Add indices + plt.text(e_xp[i], e_yp[i], label[i], fontsize=8) + + elif atoms.info['output']['label_Kikuchi']: # Add indices + if ZOLZ[i]: + plt.text(k_xp[i], k_yp[i], label[i], fontsize=atoms.info['output']['label_size'], + color=atoms.info['output']['label_color']) + lineLabel.append(hkl_label[i]) + if atoms.info['output']['plot_Kikuchi']: + # Beginning and ends of Kikuchi lines + if atoms.info['output']['label_Kikuchi']: + label_kikuchi = [] + for i in range(len(label)): + if ZOLZ[i]: + label_kikuchi.append(label[i]) + for i in range(len(k_xp)): + line, = plt.plot((k_xp[i], k_xm[i]), (k_yp[i], k_ym[i]), c=atoms.info['output']['color_Kikuchi'], + linewidth=2) + if atoms.info['output']['label_Kikuchi']: # Add indices + plt.text(k_xp[i], k_yp[i], label[i], fontsize=atoms.info['output']['label_size'], + color=atoms.info['output']['label_color']) + + def format_coord(x, y): + return labelP + 'x=%1.4f, y=%1.4f' % (x, y) + + ax.format_coord = format_coord + + if atoms.info['output']['color_ring_zero'] != 'None': + ring = plt.Circle(LC, radius, color=atoms.info['output']['color_ring_zero'], fill=False, linewidth=2) + ax.add_artist(ring) + # print(ring) + if atoms.info['output']['color_zero'] != 'None': + circle = plt.Circle(LC, radius, color=atoms.info['output']['color_zero'], linewidth=2) + ax.add_artist(circle) + + plt.axis('equal') + if 'plot_FOV' in tags_out: + l = -tags_out['plot_FOV'] / 2 + r = tags_out['plot_FOV'] / 2 + t = -tags_out['plot_FOV'] / 2 + b = tags_out['plot_FOV'] / 2 + plt.xlim(l, r) + plt.ylim(t, b) + + fig.canvas.mpl_connect('pick_event', onpick) + # texfig.savefig("HOLZ") + + # plt.title( tags_out['crystal']) + plt.show()
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/dynamic_scattering.html b/_modules/pyTEMlib/dynamic_scattering.html new file mode 100644 index 00000000..e3fc9d11 --- /dev/null +++ b/_modules/pyTEMlib/dynamic_scattering.html @@ -0,0 +1,408 @@ + + + + + + pyTEMlib.dynamic_scattering — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.dynamic_scattering

+"""
+Dynamic Scattering Library for Multi-Slice Calculations
+
+author: Gerd Duscher
+"""
+
+import numpy as np
+import scipy.constants
+import scipy.special
+
+import pyTEMlib.kinematic_scattering as ks         # kinematic scattering Library
+
+
+
[docs]def potential_1dim(element, r): + """ Calculates the projected potential of an atom of element + + The projected potential will be in units of V nm^2, + however, internally we will use Angstrom instead of nm! + The basis for these calculations are the atomic form factors of Kirkland 2𝑛𝑑 edition + following the equation in Appendix C page 252. + + Parameter + --------- + element: str + name of 'element + r: numpy array [nxn] + impact parameters (distances from atom position) in nm + + Returns + ------- + numpy array (nxn) + projected potential in units of V nm^2 + """ + + # get elementary constants + a0 = scipy.constants.value('Bohr radius') * 1e10 # in Angstrom + rydberg_div_e = scipy.constants.value('Rydberg constant times hc in eV') # in V + e0 = 2 * rydberg_div_e * scipy.constants.value('Bohr radius') * 1e10 # now in V A + + pre_factor = 2 * np.pi ** 2 * a0 * e0 + + param = ks.electronFF[element] # parametrized form factors + f_lorentz = r * 0 # Lorentzian term + f_gauss = r * 0 # Gaussian term + for i in range(3): + f_lorentz += param['fa'][i] * scipy.special.k0(2 * np.pi * r * np.sqrt(param['fb'][i])) + f_gauss += param['fc'][i] / param['fd'][i] * np.exp(-np.pi ** 2 * r ** 2 / param['fd'][i]) + f_lorentz[0, 0] = f_lorentz[0, 1] + # / 100 is conversion from V Angstrom^2 to V nm^2 + return pre_factor * (2 * f_lorentz + f_gauss) # V Angstrom^2
+ + +
[docs]def potential_2dim(element, nx, ny, n_cell_x, n_cell_y, lattice_parameter, base): + """Make a super-cell with potentials + + Limitation is that we only place atom potential with single pixel resolution + """ + n_cell_x = int(2 ** np.log2(n_cell_x)) + n_cell_y = int(2 ** np.log2(n_cell_y)) + + pixel_size = lattice_parameter / (nx / n_cell_x) + + a_nx = a_ny = int(1 / pixel_size) + x, y = np.mgrid[0:a_nx, 0:a_ny] * pixel_size + a = int(nx / n_cell_x) + r = x ** 2 + y ** 2 + + atom_potential = potential_1dim(element, r) + + potential = np.zeros([nx, ny]) + + atom_potential_corner = np.zeros([nx, ny]) + atom_potential_corner[0:a_nx, 0:a_ny] = atom_potential + atom_potential_corner[nx - a_nx:, 0:a_ny] = np.flip(atom_potential, axis=0) + atom_potential_corner[0:a_nx, ny - a_ny:] = np.flip(atom_potential, axis=1) + atom_potential_corner[nx - a_nx:, ny - a_ny:] = np.flip(np.flip(atom_potential, axis=0), axis=1) + + unit_cell_base = np.array(base) * a + unit_cell_base = np.array(unit_cell_base, dtype=int) + + for pos in unit_cell_base: + potential = potential + np.roll(atom_potential_corner, shift=np.array(pos), axis=[0, 1]) + + for column in range(int(np.log2(n_cell_x))): + potential = potential + np.roll(potential, shift=2 ** column * a, axis=1) + for row in range(int(np.log2(n_cell_y))): + potential = potential + np.roll(potential, shift=2 ** row * a, axis=0) + + return potential
+ + +
[docs]def interaction_parameter(acceleration_voltage): + """Calculates interaction parameter sigma + + Parameter + --------- + acceleration_voltage: float + acceleration voltage in volt + + Returns + ------- + interaction parameter: float + interaction parameter (dimensionless) + """ + e0 = 510998.95 # m_0 c^2 in eV + + wavelength = ks.get_wavelength(acceleration_voltage) + e = acceleration_voltage + + return 2. * np.pi / (wavelength * e) * (e0 + e) / (2. * e0 + e)
+ + +
[docs]def get_transmission(potential, acceleration_voltage): + """ Get transmission function + + has to be multiplied in real space with wave function + + Parameter + --------- + potential: numpy array (nxn) + potential of a layer + acceleration_voltage: float + acceleration voltage in V + + Returns + ------- + complex numpy array (nxn) + """ + + sigma = interaction_parameter(acceleration_voltage) + + return np.exp(1j * sigma * potential)
+ + +
[docs]def get_propagator(size_in_pixel, delta_z, number_layers, wavelength, field_of_view, bandwidth_factor, verbose=True): + """Get propagator function + + has to be convoluted with wave function after transmission + + Parameter + --------- + size_in_pixel: int + number of pixels of one axis in square image + delta_z: float + distance between layers + number_layers: int + number of layers to make a propagator + wavelength: float + wavelength of incident electrons + field_of_view: float + field of view of image + bandwidth_factor: float + relative bandwidth to avoid anti-aliasing + + Returns + ------- + propagator: complex numpy array (layers x size_in_pixel x size_in_pixel) + + """ + + k2max = size_in_pixel / field_of_view / 2. * bandwidth_factor + print(k2max) + if verbose: + print(f"Bandwidth limited to a real space resolution of {1.0 / k2max * 1000} pm") + print(f" (= {wavelength * k2max * 1000.0:.2f} mrad) for symmetrical anti-aliasing.") + k2max = k2max * k2max + + kx, ky = np.mgrid[-size_in_pixel / 2:size_in_pixel / 2, -size_in_pixel / 2:size_in_pixel / 2] / field_of_view + k_square = kx ** 2 + ky ** 2 + k_square[k_square > k2max] = 0 # bandwidth limiting + + if verbose: + temp = np.zeros([size_in_pixel, size_in_pixel]) + temp[k_square > 0] = 1 + print(f"Number of symmetrical non-aliasing beams = {temp.sum():.0f}") + + propagator = np.zeros([number_layers, size_in_pixel, size_in_pixel], dtype=complex) + for i in range(number_layers): + propagator[i] = np.exp(-1j * np.pi * wavelength * k_square * delta_z[i]) + + return propagator
+ + +
[docs]def multi_slice(wave, number_of_unit_cell_z, number_layers, transmission, propagator): + """Multi-Slice Calculation + + The wave function will be changed iteratively + + Parameters + ---------- + wave: complex numpy array (nxn) + starting wave function + number_of_unit_cell_z: int + this gives the thickness in multiples of c lattice parameter + number_layers: int + number of layers per unit cell + transmission: complex numpy array + transmission function + propagator: complex numpy array + propagator function + + Returns + ------- + complex numpy array + """ + + for i in range(number_of_unit_cell_z): + for layer in range(number_layers): + wave = wave * transmission[layer] # transmission - real space + wave = np.fft.fft2(wave) + wave = wave * propagator[layer] # propagation; propagator is defined in reciprocal space + wave = np.fft.ifft2(wave) # back to real space + return wave
+ + +
[docs]def make_chi(theta, phi, aberrations): + """ + ### + # Aberration function chi + ### + phi and theta are meshgrids of the angles in polar coordinates. + aberrations is a dictionary with the aberrations coefficients + Attention: an empty aberration dictionary will give you a perfect aberration + """ + + chi = np.zeros(theta.shape) + for n in range(6): # First Sum up to fifth order + term_first_sum = np.power(theta, n + 1) / (n + 1) # term in first sum + + second_sum = np.zeros(theta.shape) # second Sum initialized with zeros + for m in range((n + 1) % 2, n + 2, 2): + # print(n, m) + + if m > 0: + if f'C{n}{m}a' not in aberrations: # Set non existent aberrations coefficient to zero + aberrations[f'C{n}{m}a'] = 0. + if f'C{n}{m}b' not in aberrations: + aberrations[f'C{n}{m}b'] = 0. + + # term in second sum + second_sum = second_sum + aberrations[f'C{n}{m}a'] * np.cos(m * phi) + aberrations[ + f'C{n}{m}b'] * np.sin(m * phi) + else: + if f'C{n}{m}' not in aberrations: # Set non existent aberrations coefficient to zero + aberrations[f'C{n}{m}'] = 0. + + # term in second sum + second_sum = second_sum + aberrations[f'C{n}{m}'] + chi = chi + term_first_sum * second_sum * 2 * np.pi / aberrations['wavelength'] + + return chi
+ + +
[docs]def objective_lens_function(ab, nx, ny, field_of_view, aperture_size=10): + """Objective len function to be convoluted with exit wave to derive image function + + Parameter: + ---------- + ab: dict + aberrations in nm should at least contain defocus (C10), and spherical aberration (C30) + nx: int + number of pixel in x direction + ny: int + number of pixel in y direction + field_of_view: float + field of view of potential + wavelength: float + wavelength in nm + aperture_size: float + aperture size in 1/nm + + Returns: + -------- + object function: numpy array (nx x ny) + extent: list + """ + + wavelength = ab['wavelength'] + # Reciprocal plane in 1/nm + dk = 1 / field_of_view + t_xv, t_yv = np.mgrid[int(-nx / 2):int(nx / 2), int(-ny / 2):int(ny / 2)] * dk + + # define reciprocal plane in angles + phi = np.arctan2(t_yv, t_xv) + theta = np.arctan2(np.sqrt(t_xv ** 2 + t_yv ** 2), 1 / wavelength) + + mask = theta < aperture_size * wavelength + + # calculate chi + chi = make_chi(theta, phi, ab) + + extent = [-nx / 2 * dk, nx / 2 * dk, -nx / 2 * dk, nx / 2 * dk] + return np.exp(-1j * chi) * mask, extent
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/eds_tools.html b/_modules/pyTEMlib/eds_tools.html new file mode 100644 index 00000000..228aef06 --- /dev/null +++ b/_modules/pyTEMlib/eds_tools.html @@ -0,0 +1,507 @@ + + + + + + pyTEMlib.eds_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.eds_tools

+"""
+eds_tools
+Model based quantification of energy-dispersive X-ray spectroscopy data
+Copyright by Gerd Duscher
+
+The University of Tennessee, Knoxville
+Department of Materials Science & Engineering
+
+Sources:
+   
+Units:
+    everything is in SI units, except length is given in nm and angles in mrad.
+
+Usage:
+    See the notebooks for examples of these routines
+
+All the input and output is done through a dictionary which is to be found in the meta_data
+attribute of the sidpy.Dataset
+"""
+import numpy as np
+
+import scipy
+from scipy.interpolate import interp1d, splrep  # splev, splint
+from scipy import interpolate
+from scipy.signal import peak_prominences
+from scipy.ndimage import gaussian_filter
+
+import scipy.constants as const
+
+from scipy import constants
+import matplotlib.pyplot as plt
+# import matplotlib.patches as patches
+
+# from matplotlib.widgets import SpanSelector
+# import ipywidgets as widgets
+# from IPython.display import display
+
+import requests
+
+from scipy.optimize import leastsq  # least square fitting routine fo scipy
+
+import sidpy
+
+import pickle  # pkg_resources
+import pyTEMlib.eels_tools as eels
+from pyTEMlib.xrpa_x_sections import x_sections
+
+elements_list = eels.elements
+
+shell_occupancy={'K1':2, 'L1':2, 'L2':2, 'L3':4, 'M1':2, 'M2':2, 'M3':4,'M4':4,'M5':6, 
+                 'N1':2, 'N2':2,' N3':4,'N4':4,'N5':6, 'N6':6,'N7':8,
+                 'O1':2, 'O2':2,' O3':4,'O4':4,'O5':6, 'O6':6,'O7':8, 'O8':8, 'O9': 10 }
+
+
[docs]def detector_response(detector_definition, energy_scale): + """ + Parameters + ---------- + + + Example + ------- + + tags = {} + + tags['acceleration_voltage_V'] = 30000 + + tags['detector'] ={} + tags['detector']['layers'] ={} + + ## layer thicknesses of commen materials in EDS detectors in m + tags['detector']['layers']['alLayer'] = {} + tags['detector']['layers']['alLayer']['thickness'] = 30 *1e-9 # in m + tags['detector']['layers']['alLayer']['Z'] = 13 + + tags['detector']['layers']['deadLayer'] = {} + tags['detector']['layers']['deadLayer']['thickness'] = 100 *1e-9 # in m + tags['detector']['layers']['deadLayer']['Z'] = 14 + + tags['detector']['layers']['window'] = {} + tags['detector']['layers']['window']['thickness'] = 100 *1e-9 # in m + tags['detector']['layers']['window']['Z'] = 6 + + tags['detector']['detector'] = {} + tags['detector']['detector']['thickness'] = 45 * 1e-3 # in m + tags['detector']['detector']['Z'] = 14 + tags['detector']['detector']['area'] = 30 * 1e-6 #in m2 + + energy_scale = np.linspace(.1,60,1199)*1000 i eV + detector_response(tags, energy_scale) + """ + response = np.ones(len(energy_scale)) + x_sections = eels.get_x_sections() + + for key in detector_definition['layers']: + Z = detector_definition['layers'][key]['Z'] + t = detector_definition['layers'][key]['thickness'] + photoabsorption = x_sections[str(Z)]['dat']/1e10/x_sections[str(Z)]['photoabs_to_sigma'] + lin = interp1d(x_sections[str(Z)]['ene'], photoabsorption,kind='linear') + mu = lin(energy_scale) * x_sections[str(Z)]['nominal_density']*100. #1/cm -> 1/m + + absorption = np.exp(-mu * t) + response = response*absorption + Z = detector_definition['detector']['Z'] + t = detector_definition['detector']['thickness'] + photoabsorption = x_sections[str(Z)]['dat']/1e10/x_sections[str(Z)]['photoabs_to_sigma'] + lin = interp1d(x_sections[str(Z)]['ene']/1000., photoabsorption,kind='linear') + mu = lin(energy_scale) * x_sections[str(Z)]['nominal_density']*100. #1/cm -> 1/m + response = response*(1.0 - np.exp(-mu * t))# * oo4pi; + return(response)
+ + +
[docs]def detect_peaks(dataset, minimum_number_of_peaks=30): + if not isinstance(dataset, sidpy.Dataset): + raise TypeError('Needs an sidpy dataset') + if not dataset.data_type.name == 'SPECTRUM': + raise TypeError('Need a spectrum') + resolution = 138 + if 'EDS' in dataset.metadata: + if 'energy_resolution' in dataset.metadata['EDS']: + resolution = dataset.metadata['EDS']['energy_resolution'] + start = np.searchsorted(dataset.energy_scale, 125) + ## we use half the width of the resolution for smearing + width = int(np.ceil(125/(dataset.energy_scale[1]-dataset.energy_scale[0])/2)+1) + new_spectrum = scipy.signal.savgol_filter(dataset[start:], width, 2) ## we use half the width of the resolution for smearing + #new_energy_scale = dataset.energy_scale[start:] + prominence = 10 + minor_peaks, _ = scipy.signal.find_peaks(new_spectrum, prominence=prominence) + + while len(minor_peaks) > minimum_number_of_peaks: + prominence+=10 + minor_peaks, _ = scipy.signal.find_peaks(new_spectrum, prominence=prominence) + return np.array(minor_peaks)+start
+ +
[docs]def find_elements(spectrum, minor_peaks): + if not isinstance(spectrum, sidpy.Dataset): + raise TypeError(' Need a sidpy dataset') + energy_scale = spectrum.energy_scale + elements = [] + for peak in minor_peaks: + found = False + for element in range(3,82): + if 'lines' in x_sections[str(element)]: + if 'K-L3' in x_sections[str(element)]['lines']: + if abs(x_sections[str(element)]['lines']['K-L3']['position']- energy_scale[peak]) <10: + found = True + if x_sections[str(element)]['name'] not in elements: + elements.append( x_sections[str(element)]['name']) + if not found: + if 'K-L2' in x_sections[str(element)]['lines']: + if abs(x_sections[str(element)]['lines']['K-L2']['position']- energy_scale[peak]) <10: + found = True + if x_sections[str(element)]['name'] not in elements: + elements.append( x_sections[str(element)]['name']) + if not found: + if 'L3-M5' in x_sections[str(element)]['lines']: + if abs(x_sections[str(element)]['lines']['L3-M5']['position']- energy_scale[peak]) <30: + if x_sections[str(element)]['name'] not in elements: + elements.append( x_sections[str(element)]['name']) + return elements
+ +
[docs]def get_x_ray_lines(spectrum, elements): + out_tags = {} + alpha_K = 1e6 + alpha_L = 6.5e7 + alpha_M = 8*1e8#2.2e10 + # My Fit + alpha_K = .9e6 + alpha_L = 6.e7 + alpha_M = 6*1e8#2.2e10 + # omega_K = Z**4/(alpha_K+Z**4) + # omega_L = Z**4/(alpha_L+Z**4) + # omega_M = Z**4/(alpha_M+Z**4) + for element in elements: + + atomic_number = elements_list.index(element) + out_tags[element] ={'Z': atomic_number} + energy_scale = spectrum.energy_scale + if 'K-L3' in x_sections[str(atomic_number)]['lines']: + if x_sections[str(atomic_number)]['lines']['K-L3']['position'] < 1.9e4: + height = spectrum[np.searchsorted(energy_scale, x_sections[str(atomic_number)]['lines']['K-L3']['position'] )].compute() + out_tags[element]['K-family'] = {'height': height} + out_tags[element]['K-family']['yield'] = atomic_number**4/(alpha_K+atomic_number**4)/4/1.4 + + if 'L3-M5' in x_sections[str(atomic_number)]['lines']: + if x_sections[str(atomic_number)]['lines']['L3-M5']['position'] < 1.9e4: + height = spectrum[np.searchsorted(energy_scale, x_sections[str(atomic_number)]['lines']['L3-M5']['position'] )].compute() + out_tags[element]['L-family'] = {'height': height} + out_tags[element]['L-family']['yield'] = (atomic_number**4/(alpha_L+atomic_number**4))**2 + + if 'M5-N6' in x_sections[str(atomic_number)]['lines']: + if x_sections[str(atomic_number)]['lines']['M5-N6']['position'] < 1.9e4: + height = spectrum[np.searchsorted(energy_scale, x_sections[str(atomic_number)]['lines']['M5-N7']['position'] )].compute() + out_tags[element]['M-family'] = {'height': height} + out_tags[element]['M-family']['yield'] = (atomic_number**4/(alpha_M+atomic_number**4))**2 + + for key, line in x_sections[str(atomic_number)]['lines'].items(): + other = True + if line['weight'] > 0.01 and line['position'] < 3e4: + if 'K-family' in out_tags[element]: + if key[0] == 'K': + other = False + out_tags[element]['K-family'][key]=line + if 'L-family' in out_tags[element]: + if key[:2] in ['L2', 'L3']: + other = False + out_tags[element]['L-family'][key]=line + if 'M-family' in out_tags[element]: + if key[:2] in ['M5', 'M4']: + other = False + out_tags[element]['M-family'][key]=line + if other: + if 'other' not in out_tags[element]: + out_tags[element]['other'] = {} + height = spectrum[np.searchsorted(energy_scale, x_sections[str(atomic_number)]['lines'][key]['position'] )].compute() + out_tags[element]['other'][key]=line + out_tags[element]['other'][key]['height'] = height + + xs = get_eds_cross_sections(atomic_number) + if 'K' in xs and 'K-family' in out_tags[element]: + out_tags[element]['K-family']['ionization_x_section'] = xs['K'] + if 'L' in xs and 'L-family' in out_tags[element]: + out_tags[element]['L-family']['ionization_x_section'] = xs['L'] + if 'M' in xs and 'M-family' in out_tags[element]: + out_tags[element]['M-family']['ionization_x_section'] = xs['M'] + + """ + for key, x_lines in out_tags.items(): + if 'K-family' in x_lines: + xs = eels.xsec_xrpa(np.arange(100)+x_sections[str(x_lines['Z'])]['K1']['onset'], 200,x_lines['Z'], 100).sum() + + x_lines['K-family']['ionization_x_section'] = xs + + if 'L-family' in x_lines: + xs = eels.xsec_xrpa(np.arange(100)+x_sections[str(x_lines['Z'])]['L3']['onset'], 200,x_lines['Z'], 100).sum() + x_lines['L-family']['ionization_x_section'] = xs + if 'M-family' in x_lines: + xs = eels.xsec_xrpa(np.arange(100)+x_sections[str(x_lines['Z'])]['M5']['onset'], 200,x_lines['Z'], 100).sum() + x_lines['M-family']['ionization_x_section'] = xs + """ + return out_tags
+ + +
[docs]def getFWHM(E, E_ref, FWHM_ref): + return np.sqrt(2.5*(E-E_ref)+FWHM_ref**2)
+ +
[docs]def gaussian(enrgy_scale, mu, FWHM): + sig = FWHM/2/np.sqrt(2*np.log(2)) + return np.exp(-np.power(enrgy_scale - mu, 2.) / (2 * np.power(sig, 2.)))
+ +
[docs]def get_peak(E, energy_scale): + E_ref = 5895.0 + FWHM_ref = 136 #eV + FWHM = getFWHM(E, E_ref, FWHM_ref) + gaus = gaussian(energy_scale, E, FWHM) + + return gaus /gaus.sum()
+ + +
[docs]def get_model(tags, spectrum): + + energy_scale = spectrum.energy_scale + p = [] + peaks = [] + keys = [] + for element, lines in tags.items(): + if 'K-family' in lines: + model = np.zeros(len(energy_scale)) + for line, info in lines['K-family'].items(): + if line[0] == 'K': + model += get_peak(info['position'], energy_scale)*info['weight'] + lines['K-family']['peaks'] = model/model.max() + lines['K-family']['height'] /= lines['K-family']['peaks'].max() + p.append(lines['K-family']['height']) + peaks.append(lines['K-family']['peaks']) + keys.append(element+':K-family') + if 'L-family' in lines: + model = np.zeros(len(energy_scale)) + for line, info in lines['L-family'].items(): + if line[0] == 'L': + model += get_peak(info['position'], energy_scale)*info['weight'] + lines['L-family']['peaks'] = model/model.max() + lines['L-family']['height'] /= lines['L-family']['peaks'].max() + p.append(lines['L-family']['height']) + peaks.append(lines['L-family']['peaks']) + keys.append(element+':L-family') + if 'M-family' in lines: + model = np.zeros(len(energy_scale)) + for line, info in lines['M-family'].items(): + if line[0] == 'M': + model += get_peak(info['position'], energy_scale)*info['weight'] + lines['M-family']['peaks'] = model/model.max() + lines['M-family']['height'] /= lines['M-family']['peaks'].max() + p.append(lines['M-family']['height']) + peaks.append(lines['M-family']['peaks']) + keys.append(element+':M-family') + + if 'other' in lines: + for line, info in lines['other'].items(): + info['peak'] = get_peak(info['position'], energy_scale) + peaks.append(info['peak']) + p.append(info['height']) + keys.append(element+':other:'+line) + return np.array(peaks), np.array(p), keys
+ +
[docs]def fit_model(spectrum, elements): + out_tags = get_x_ray_lines(spectrum, elements) + + peaks, pin, keys = get_model(out_tags, spectrum) + + def residuals(pp, yy): + model = np.zeros(len(yy)) + for i in range(len(pp)): + model += peaks[i]*pp[i] + err = np.abs((yy - model)[75:]) / np.sqrt(np.abs(yy[75:])) + return err + + y = spectrum.compute() + [p, _] = leastsq(residuals, pin, args=(y)) + update_fit_values(out_tags, p) + + if 'EDS' not in spectrum.metadata: + spectrum.metadata['EDS'] = {} + spectrum.metadata['EDS']['lines'] = out_tags + + return np.array(peaks), np.array(p)
+ + +
[docs]def update_fit_values(out_tags, p): + index = 0 + for element, lines in out_tags.items(): + if 'K-family' in lines: + lines['K-family']['height'] = p[index] + index += 1 + if 'L-family' in lines: + lines['L-family']['height'] = p[index] + index += 1 + if 'M-family' in lines: + lines['M-family']['height'] =p[index] + index += 1 + if 'other' in lines: + for line, info in lines['other'].items(): + info['height'] = p[index] + index += 1
+ + +
[docs]def get_eds_xsection(Xsection, energy_scale, start_bgd, end_bgd): + background = eels.power_law_background(Xsection, energy_scale, [start_bgd, end_bgd], verbose=False) + cross_section_core = Xsection- background[0] + cross_section_core[cross_section_core < 0] = 0.0 + cross_section_core[energy_scale < end_bgd] = 0.0 + return cross_section_core
+ + +
[docs]def get_eds_cross_sections(z): + energy_scale = np.arange(10, 20000) + Xsection = eels.xsec_xrpa(energy_scale, 200, z, 400.) + edge_info = eels.get_x_sections(z) + eds_cross_sections = {} + if 'K1' in edge_info: + start_bgd = edge_info['K1']['onset'] * 0.8 + end_bgd = edge_info['K1']['onset'] - 5 + if start_bgd > end_bgd: + start_bgd = end_bgd-100 + if start_bgd > energy_scale[0] and end_bgd< energy_scale[-1]-100: + eds_xsection = get_eds_xsection(Xsection, energy_scale, start_bgd, end_bgd) + eds_xsection = Xsection - eds_xsection + eds_xsection[eds_xsection<0] = 0. + start_sum = np.searchsorted(energy_scale, edge_info['K1']['onset']) + eds_cross_sections['K'] = eds_xsection[start_sum:start_sum+200].sum() + if 'L3' in edge_info: + start_bgd = edge_info['L3']['onset'] * 0.8 + end_bgd = edge_info['L3']['onset'] - 5 + if start_bgd > end_bgd: + start_bgd = end_bgd-100 + if start_bgd > energy_scale[0] and end_bgd< energy_scale[-1]-100: + eds_xsection = get_eds_xsection(Xsection, energy_scale, start_bgd, end_bgd) + eds_xsection = Xsection - eds_xsection + eds_xsection[eds_xsection<0] = 0. + start_sum = np.searchsorted(energy_scale, edge_info['L3']['onset']) + eds_cross_sections['L'] = eds_xsection[start_sum:start_sum+200].sum() + if 'M5' in edge_info: + start_bgd = edge_info['M5']['onset'] * 0.8 + end_bgd = edge_info['M5']['onset'] - 5 + if start_bgd > end_bgd: + start_bgd = end_bgd-100 + if start_bgd > energy_scale[0] and end_bgd< energy_scale[-1]-100: + eds_xsection = get_eds_xsection(Xsection, energy_scale, start_bgd, end_bgd) + eds_xsection = Xsection - eds_xsection + eds_xsection[eds_xsection<0] = 0. + start_sum = np.searchsorted(energy_scale, edge_info['M5']['onset']) + eds_cross_sections['M'] = eds_xsection[start_sum:start_sum+200].sum() + return eds_cross_sections
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/eels_dialog.html b/_modules/pyTEMlib/eels_dialog.html new file mode 100644 index 00000000..b0bb7dae --- /dev/null +++ b/_modules/pyTEMlib/eels_dialog.html @@ -0,0 +1,1482 @@ + + + + + + pyTEMlib.eels_dialog — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.eels_dialog

+"""
+QT dialog window for EELS compositional analysis
+
+Author: Gerd Duscher
+"""
+Qt_available = True
+try:
+    from PyQt5 import QtCore, QtWidgets
+except:
+    Qt_available = False
+    # print('Qt dialogs are not available')
+
+
+import numpy as np
+
+import ipywidgets
+import IPython.display
+from IPython.display import display
+import matplotlib
+import matplotlib.pylab as plt
+import matplotlib.patches as patches
+
+from pyTEMlib import file_tools as ft
+from pyTEMlib import eels_tools as eels
+from pyTEMlib import eels_dialog_utilities
+
+import sidpy
+
+if Qt_available:
+    from pyTEMlib import eels_dlg
+    
+    class EELSDialog(QtWidgets.QDialog):
+        """
+        EELS Input Dialog for Chemical Analysis
+        """
+
+        def __init__(self, datasets=None):
+            super().__init__(None, QtCore.Qt.WindowStaysOnTopHint)
+            # Create an instance of the GUI
+            if datasets is None:
+                # make a dummy dataset
+                datasets = {'Channel_000':ft.make_dummy_dataset(sidpy.DataType.SPECTRUM)}
+            elif isinstance(datasets, sidpy.Dataset):
+                datasets = {'Channel_000': datasets}    
+            elif isinstance(datasets, dict):
+                pass
+            else: 
+                raise TypeError('dataset or first item inhas to be a sidpy dataset')
+            self.datasets = datasets
+            self.dataset = datasets[list(datasets)[0]]
+            
+            if not isinstance(self.dataset, sidpy.Dataset):
+                raise TypeError('dataset or first item inhas to be a sidpy dataset')
+            
+            self.spec_dim = ft.get_dimensions_by_type('spectral', self.dataset)
+            if len(self.spec_dim) != 1:
+                raise TypeError('We need exactly one SPECTRAL dimension')
+            self.spec_dim = self.spec_dim[0]
+            
+            self.ui = eels_dlg.UiDialog(self)
+            # Run the .setup_ui() method to show the GUI
+            # self.ui.setup_ui(self)
+
+            self.set_action()
+
+            self.energy_scale = np.array([])
+            self.model = np.array([])
+            self.y_scale = 1.0
+            self.change_y_scale = 1.0
+            self.spectrum_ll = None
+            self.low_loss_key = None
+            
+            self.edges = {}
+
+            self.show_regions = False
+            self.show()
+
+            self.set_dataset(self.dataset)
+            initial_elements = []
+
+            for key in self.edges:
+                if key.isdigit():
+                    if 'element' in self.edges[key]:
+                        initial_elements.append(self.edges[key]['element'])
+           
+            self.pt_dialog = eels_dialog_utilities.PeriodicTableDialog(energy_scale=self.energy_scale,
+                                                                       initial_elements=initial_elements)
+            self.pt_dialog.signal_selected[list].connect(self.set_elements)
+
+            self.dataset.plot()
+
+            if hasattr(self.dataset.view, 'axes'):
+                self.axis = self.dataset.view.axes[-1]
+            elif hasattr(self.dataset.view, 'axis'):
+                self.axis = self.dataset.view.axis
+
+            self.figure = self.axis.figure
+            self.updY = 0
+            self.figure.canvas.mpl_connect('button_press_event', self.plot)
+
+            self.ui.do_fit_button.setFocus()
+            self.plot()
+            self.ui.do_fit_button.setFocus()
+
+        def set_dataset(self, dataset):
+
+            self.dataset = dataset
+            if 'edges' not in self.dataset.metadata or self.dataset.metadata['edges'] == {}:
+                self.dataset.metadata['edges'] = {'0': {}, 'model': {}, 'use_low_loss': False}
+            self.edges = self.dataset.metadata['edges']
+
+            spec_dim = ft.get_dimensions_by_type('spectral', dataset)[0]
+
+            if len(spec_dim) == 0:
+                raise TypeError('We need at least one SPECTRAL dimension')
+
+            self.spec_dim = spec_dim[0]
+            self.energy_scale = dataset._axes[self.spec_dim].values
+            self.ui.edit2.setText(f"{self.energy_scale[-2]:.3f}")
+
+            if 'fit_area' not in self.edges:
+                self.edges['fit_area'] = {}
+            if 'fit_start' not in self.edges['fit_area']:
+                self.ui.edit1.setText(f"{self.energy_scale[50]:.3f}")
+                self.edges['fit_area']['fit_start'] = float(self.ui.edit1.displayText())
+            else:
+                self.ui.edit1.setText(f"{self.edges['fit_area']['fit_start']:.3f}")
+            if 'fit_end' not in self.edges['fit_area']:
+                self.ui.edit2.setText(f"{self.energy_scale[-2]:.3f}")
+                self.edges['fit_area']['fit_end'] = float(self.ui.edit2.displayText())
+            else:
+                self.ui.edit2.setText(f"{self.edges['fit_area']['fit_end']:.3f}")
+
+            if self.dataset.data_type.name == 'SPECTRAL_IMAGE':
+                if 'SI_bin_x' not in self.dataset.metadata['experiment']:
+                    self.dataset.metadata['experiment']['SI_bin_x'] = 1
+                    self.dataset.metadata['experiment']['SI_bin_y'] = 1
+
+                bin_x = self.dataset.metadata['experiment']['SI_bin_x']
+                bin_y = self.dataset.metadata['experiment']['SI_bin_y']
+                self.dataset.view.set_bin([bin_x, bin_y])
+            self.update()
+
+        def update(self):
+            index = self.ui.list3.currentIndex()  # which edge
+            edge = self.edges[str(index)]
+
+            if 'z' in edge:
+                self.ui.list5.setCurrentIndex(self.ui.edge_sym.index(edge['symmetry']))
+                self.ui.edit4.setText(str(edge['z']))
+                self.ui.unit4.setText(edge['element'])
+                self.ui.edit6.setText(f"{edge['onset']:.2f}")
+                self.ui.edit7.setText(f"{edge['start_exclude']:.2f}")
+                self.ui.edit8.setText(f"{edge['end_exclude']:.2f}")
+                if self.y_scale == 1.0:
+                    self.ui.edit9.setText(f"{edge['areal_density']:.2e}")
+                    self.ui.unit9.setText('a.u.')
+                else:
+                    dispersion = self.energy_scale[1]-self.energy_scale[0]
+                    self.ui.edit9.setText(f"{edge['areal_density']*self.y_scale*1e-6/dispersion:.2f}")
+                    self.ui.unit9.setText('atoms/nm²')
+            else:
+                self.ui.list3.setCurrentIndex(0)
+                self.ui.edit4.setText(str(0))
+                self.ui.unit4.setText(' ')
+                self.ui.edit6.setText(f"{0:.2f}")
+                self.ui.edit7.setText(f"{0:.2f}")
+                self.ui.edit8.setText(f"{0:.2f}")
+                self.ui.edit9.setText(f"{0:.2e}")
+
+        def update_element(self, z):
+            # We check whether this element is already in the
+            zz = eels.get_z(z)
+            for key, edge in self.edges.items():
+                if key.isdigit():
+                    if 'z' in edge:
+                        if zz == edge['z']:
+                            return False
+
+            major_edge = ''
+            minor_edge = ''
+            all_edges = {}
+            x_section = eels.get_x_sections(zz)
+            edge_start = 10  # int(15./ft.get_slope(self.energy_scale)+0.5)
+            for key in x_section:
+                if len(key) == 2 and key[0] in ['K', 'L', 'M', 'N', 'O'] and key[1].isdigit():
+                    if self.energy_scale[edge_start] < x_section[key]['onset'] < self.energy_scale[-edge_start]:
+                        if key in ['K1', 'L3', 'M5']:
+                            major_edge = key
+                        elif key in self.ui.edge_sym:
+                            if minor_edge == '':
+                                minor_edge = key
+                            if int(key[-1]) % 2 > 0:
+                                if int(minor_edge[-1]) % 2 == 0 or key[-1] > minor_edge[-1]:
+                                    minor_edge = key
+
+                        all_edges[key] = {'onset': x_section[key]['onset'], 'original_onset': x_section[key]['onset']}
+                        
+
+            if major_edge != '':
+                key = major_edge
+            elif minor_edge != '':
+                key = minor_edge
+            else:
+                print(f'Could not find no edge of {zz} in spectrum')
+                return False
+
+            index = self.ui.list3.currentIndex()
+            # self.ui.dialog.setWindowTitle(f'{index}, {zz}')
+
+            if str(index) not in self.edges:
+                self.edges[str(index)] = {}
+
+            start_exclude = x_section[key]['onset'] - x_section[key]['excl before']
+            end_exclude = x_section[key]['onset'] + x_section[key]['excl after']
+
+            self.edges[str(index)] = {'z': zz, 'symmetry': key, 'element': eels.elements[zz],
+                                      'onset': x_section[key]['onset'], 'end_exclude': end_exclude,
+                                      'start_exclude': start_exclude}
+            self.edges[str(index)]['all_edges'] = all_edges
+            self.edges[str(index)]['chemical_shift'] = 0.0
+            self.edges[str(index)]['areal_density'] = 0.0
+            self.edges[str(index)]['original_onset'] = self.edges[str(index)]['onset']
+            return True
+
+        def on_enter(self):
+            sender = self.sender()
+            edge_list = self.ui.list3
+            # self.ui.dialog.setWindowTitle(f"{sender.objectName()}")
+
+            
+            if sender.objectName() == 'fit_start_edit':
+                value = float(str(sender.displayText()).strip())
+                if value < self.energy_scale[0]:
+                    value = self.energy_scale[0]
+                if value > self.energy_scale[-5]:
+                    value = self.energy_scale[-5]
+                self.edges['fit_area']['fit_start'] = value
+                sender.setText(str(self.edges['fit_area']['fit_start']))
+            elif sender.objectName() == 'fit_end_edit':
+                value = float(str(sender.displayText()).strip())
+                if value < self.energy_scale[5]:
+                    value = self.energy_scale[5]
+                if value > self.energy_scale[-1]:
+                    value = self.energy_scale[-1]
+                self.edges['fit_area']['fit_end'] = value
+                sender.setText(str(self.edges['fit_area']['fit_end']))
+            elif sender.objectName() == 'element_edit':
+                if str(sender.displayText()).strip() == '0':
+                    # sender.setText('PT')
+                    self.pt_dialog.energy_scale = self.energy_scale
+                    self.pt_dialog.show()
+                    pass
+                else:
+                    self.update_element(str(sender.displayText()).strip())
+                self.update()
+            elif sender.objectName() in ['onset_edit', 'excl_start_edit', 'excl_end_edit']:
+                self.check_area_consistency()
+
+            elif sender.objectName() == 'multiplier_edit':
+                index = edge_list.currentIndex()
+                self.edges[str(index)]['areal_density'] = float(self.ui.edit9.displayText())
+                if self.y_scale != 1.0:
+                    dispersion = self.energy_scale[1]-self.energy_scale[0]
+                    self.edges[str(index)]['areal_density'] /= self.y_scale * 1e-6 *dispersion
+                if 'background' not in self.edges['model']:
+                    print(' no background')
+                    return
+                self.model = self.edges['model']['background']
+                for key in self.edges:
+                    if key.isdigit():
+                        self.model = self.model + self.edges[key]['areal_density'] * self.edges[key]['data']
+                self.plot()
+            else:
+                return
+            if self.show_regions:
+                self.plot()
+
+            
+
+        def sort_elements(self):
+            onsets = []
+            for index, edge in self.edges.items():
+                if index.isdigit():
+                    onsets.append(float(edge['onset']))
+
+            arg_sorted = np.argsort(onsets)
+            edges = self.edges.copy()
+            for index, i_sorted in enumerate(arg_sorted):
+                self.edges[str(index)] = edges[str(i_sorted)].copy()
+
+            index = 0
+            edge = self.edges['0']
+            dispersion = self.energy_scale[1]-self.energy_scale[0]
+
+            while str(index + 1) in self.edges:
+                next_edge = self.edges[str(index + 1)]
+                if edge['end_exclude'] > next_edge['start_exclude'] - 5 * dispersion:
+                    edge['end_exclude'] = next_edge['start_exclude'] - 5 * dispersion
+                edge = next_edge
+                index += 1
+
+            if edge['end_exclude'] > self.energy_scale[-3]:
+                edge['end_exclude'] = self.energy_scale[-3]
+
+        def set_elements(self, selected_elements):
+            edge_list = self.ui.list3
+           
+            for index, elem in enumerate(selected_elements):
+                edge_list.setCurrentIndex(index)
+                self.update_element(elem)
+                    
+            self.sort_elements()
+            self.update()
+
+        def plot(self, event=None):
+            self.energy_scale = self.dataset._axes[self.spec_dim].values
+            if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE:
+                spectrum = self.dataset.view.get_spectrum()
+                self.axis = self.dataset.view.axes[1]
+            else:
+                spectrum = np.array(self.dataset)
+                self.axis = self.dataset.view.axis
+
+            if self.ui.select10.isChecked():
+                if 'experiment' in self.dataset.metadata:
+                    exp = self.dataset.metadata['experiment']
+                    if 'convergence_angle' not in exp:
+                        raise ValueError('need a convergence_angle in experiment of metadata dictionary ')
+                    alpha = exp['convergence_angle']
+                    beta = exp['collection_angle']
+                    beam_kv = exp['acceleration_voltage']
+
+                    eff_beta = eels.effective_collection_angle(self.energy_scale, alpha, beta, beam_kv)
+                    edges = eels.make_cross_sections(self.edges, np.array(self.energy_scale), beam_kv, eff_beta)
+                    self.edges = eels.fit_edges2(spectrum, self.energy_scale, edges)
+                    areal_density = []
+                    elements = []
+                    for key in edges:
+                        if key.isdigit():  # only edges have numbers in that dictionary
+                            elements.append(edges[key]['element'])
+                            areal_density.append(edges[key]['areal_density'])
+                    areal_density = np.array(areal_density)
+                    out_string = '\nRelative composition: \n'
+                    for i, element in enumerate(elements):
+                        out_string += f'{element}: {areal_density[i] / areal_density.sum() * 100:.1f}%  '
+
+                    self.model = self.edges['model']['spectrum']
+                    self.update()
+
+            x_limit = self.axis.get_xlim()
+            y_limit = np.array(self.axis.get_ylim())*self.change_y_scale
+            self.change_y_scale = 1.0
+            
+            self.axis.clear()
+
+            line1, = self.axis.plot(self.energy_scale, spectrum*self.y_scale, label='spectrum')
+            lines = [line1]
+
+            def onpick(event):
+                # on the pick event, find the orig line corresponding to the
+                # legend proxy line, and toggle the visibility
+                leg_line = event.artist
+                orig_line = lined[legline]
+                vis = not origline.get_visible()
+                orig_line.set_visible(vis)
+                # Change the alpha on the line in the legend, so we can see what lines
+                # have been toggled
+                if vis:
+                    leg_line.set_alpha(1.0)
+                else:
+                    leg_line.set_alpha(0.2)
+                self.figure.canvas.draw()
+
+            if len(self.model) > 1:
+                line2, = self.axis.plot(self.energy_scale, self.model*self.y_scale, label='model')
+                line3, = self.axis.plot(self.energy_scale, (spectrum - self.model)*self.y_scale, label='difference')
+                line4, = self.axis.plot(self.energy_scale, (spectrum - self.model) / np.sqrt(spectrum)*self.y_scale, label='Poisson')
+                lines = [line1, line2, line3, line4]
+                lined = dict()
+
+                legend = self.axis.legend(loc='upper right', fancybox=True, shadow=True)
+
+                legend.get_frame().set_alpha(0.4)
+                for legline, origline in zip(legend.get_lines(), lines):
+                    legline.set_picker(5)  # 5 pts tolerance
+                    lined[legline] = origline
+                self.figure.canvas.mpl_connect('pick_event', onpick)
+            self.axis.set_xlim(x_limit)
+            self.axis.set_ylim(y_limit)
+            
+            if self.y_scale != 1.:
+                self.axis.set_ylabel('scattering intensity (ppm)')
+            else:
+                self.axis.set_ylabel('intensity (counts)')
+            self.axis.set_xlabel('energy_loss (eV)')
+                
+
+            if self.ui.show_edges.isChecked():
+                self.show_edges()
+            if self.show_regions:
+                self.plot_regions()
+            self.figure.canvas.draw_idle()
+
+        def plot_regions(self):
+            y_min, y_max = self.axis.get_ylim()
+            height = y_max - y_min
+
+            rect = []
+            if 'fit_area' in self.edges:
+                color = 'blue'
+                alpha = 0.2
+                x_min = self.edges['fit_area']['fit_start']
+                width = self.edges['fit_area']['fit_end'] - x_min
+                rect.append(patches.Rectangle((x_min, y_min), width, height,
+                                              edgecolor=color, alpha=alpha, facecolor=color))
+                self.axis.add_patch(rect[0])
+                self.axis.text(x_min, y_max, 'fit region', verticalalignment='top')
+            color = 'red'
+            alpha = 0.5
+            for key in self.edges:
+                if key.isdigit():
+                    x_min = self.edges[key]['start_exclude']
+                    width = self.edges[key]['end_exclude']-x_min
+                    rect.append(patches.Rectangle((x_min, y_min), width, height,
+                                                  edgecolor=color, alpha=alpha, facecolor=color))
+                    self.axis.add_patch(rect[-1])
+                    self.axis.text(x_min, y_max, f"exclude\n edge {int(key)+1}", verticalalignment='top')
+
+        def show_edges(self):
+            x_min, x_max = self.axis.get_xlim()
+            y_min, y_max = self.axis.get_ylim()
+
+            for key, edge in self.edges.items():
+                i = 0
+                if key.isdigit():
+                    element = edge['element']
+                    for sym in edge['all_edges']:
+                        x = edge['all_edges'][sym]['onset'] + edge['chemical_shift']
+                        if x_min < x < x_max:
+                            self.axis.text(x, y_max, '\n' * i + f"{element}-{sym}",
+                                           verticalalignment='top', color='black')
+                            self.axis.axvline(x, ymin=0, ymax=1, color='gray')
+                            i += 1
+
+        def check_area_consistency(self):
+            if self.dataset is None:
+                return
+            onset = float(self.ui.edit6.displayText())
+            excl_start = float(self.ui.edit7.displayText())
+            excl_end = float(self.ui.edit8.displayText())
+            if onset < self.energy_scale[2]:
+                onset = self.energy_scale[2]
+                excl_start = self.energy_scale[2]
+            if onset > self.energy_scale[-2]:
+                onset = self.energy_scale[-2]
+                excl_end = self.energy_scale[-2]
+            if excl_start > onset:
+                excl_start = onset
+            if excl_end < onset:
+                excl_end = onset
+
+            index = self.ui.list3.currentIndex()
+            self.edges[str(index)]['chemical_shift'] = onset - self.edges[str(index)]['original_onset']
+            self.edges[str(index)]['onset'] = onset
+            self.edges[str(index)]['end_exclude'] = excl_end
+            self.edges[str(index)]['start_exclude'] = excl_start
+
+            self.update()
+
+        def on_list_enter(self):
+            sender = self.sender()
+            # self.ui.dialog.setWindowTitle(f"on list eneter {sender.objectName()}")
+
+            if sender.objectName() == 'edge_list':
+                index = self.ui.list3.currentIndex()
+
+                number_of_edges = 0
+                for key in self.edges:
+                    if key.isdigit():
+                        if int(key) > number_of_edges:
+                            number_of_edges = int(key)
+                number_of_edges += 1
+                if index > number_of_edges:
+                    index = number_of_edges
+                self.ui.list3.setCurrentIndex(index)
+                if str(index) not in self.edges:
+                    self.edges[str(index)] = {'z': 0, 'symmetry': 'K1', 'element': 'H', 'onset': 0, 'end_exclude': 0,
+                                              'start_exclude': 0, 'areal_density': 0}
+
+                self.update()
+            elif sender.objectName() == 'symmetry_list':
+                sym = self.ui.list5.currentText()
+                index = self.ui.list3.currentIndex()
+                zz = self.edges[str(index)]['z']
+                if zz > 1:
+                    x_section = eels.get_x_sections(zz)
+                    if sym in x_section:
+                        start_exclude = x_section[sym]['onset'] - x_section[sym]['excl before']
+                        end_exclude = x_section[sym]['onset'] + x_section[sym]['excl after']
+                        self.edges[str(index)].update({'symmetry': sym, 'onset': x_section[sym]['onset'],
+                                                       'end_exclude': end_exclude, 'start_exclude': start_exclude})
+                        self.edges[str(index)]['chemical_shift'] = 0.0
+                        self.edges[str(index)]['areal_density'] = 0.0
+                        self.edges[str(index)]['original_onset'] = self.edges[index]['onset']
+                        self.update()
+            elif sender.objectName() == 'symmetry_method':
+                self.ui.select5.setCurrentIndex(0)
+
+        def on_check(self):
+            sender = self.sender()
+            # self.ui.dialog.setWindowTitle(f"on_check {sender.objectName()}")
+
+
+            if sender.objectName() == 'edge_check':
+                self.show_regions = sender.isChecked()
+            elif sender.objectName() == 'conv_ll':
+                self.edges['use_low_loss'] = self.ui.check10.isChecked()
+                if self.ui.check10.isChecked():
+                    self.low_loss()
+            elif sender.objectName() == 'probability':
+                dispersion = self.energy_scale[1]-self.energy_scale[0]
+                old_y_scale = self.y_scale *1.
+                if sender.isChecked():
+                    flux_key = None
+                    spectrum_key = None
+            
+                    for key in  self.datasets.keys():
+                        if 'Reference' in key:
+                            if self.datasets[key].data_type.name == 'IMAGE': # Prefer Ronchigrams
+                                flux_key = key
+                                self.dataset.metadata['experiment']['flux_reference_key'] = flux_key
+                            elif self.datasets[key].data_type.name == 'SPECTRUM':
+                                spectrum_key = key
+                                self.dataset.metadata['experiment']['low_loss_key'] = spectrum_key
+                    if flux_key is None:
+                        flux_key = spectrum_key  
+
+                    # self.ui.dialog.setWindowTitle(f"2nd {self.dataset.metadata['experiment']['flux_ppm']:.2f}")
+                    if self.dataset.metadata['experiment']['flux_ppm'] > 0:
+                        # self.ui.dialog.setWindowTitle(f"3rD {self.dataset.metadata['experiment']['flux_ppm']:.2f}")
+                        self.y_scale = 1/self.dataset.metadata['experiment']['flux_ppm']*dispersion
+                    elif flux_key is not None:
+                        self.dataset.metadata['experiment']['flux_ppm'] = (np.array(self.datasets[flux_key])/1e6).sum() 
+                        self.dataset.metadata['experiment']['flux_ppm'] /= self.datasets[flux_key].metadata['experiment']['exposure_time']
+                        self.dataset.metadata['experiment']['flux_ppm'] *= self.dataset.metadata['experiment']['exposure_time'] 
+                        self.y_scale = 1/self.dataset.metadata['experiment']['flux_ppm']*dispersion
+                    else:
+                        self.y_scale = 1.0
+                else:
+                    self.y_scale = 1.0
+                    
+                self.change_y_scale = self.y_scale/old_y_scale
+                self.update()
+            self.plot()
+
+        def low_loss(self):
+            self.edges['use_low_loss'] = self.ui.check10.isChecked()
+            if self.low_loss_key is None:
+                for key in  self.datasets.keys():
+                    if 'Reference' in key:
+                        if self.datasets[key].data_type.name == 'SPECTRUM':
+                            self.low_loss_key = key
+                            self.dataset.metadata['experiment']['low_loss_key'] = self.low_loss_key
+            
+            if self.low_loss_key is None:
+                self.low_loss_key = ft.add_dataset_from_file(self.datasets, key_name='Reference')
+                self.spectrum_ll = self.datasets[self.low_loss_key]
+                if self.spectrum_ll.data_type.name != 'SPECTRUM':
+                    self.spectrum_ll = None
+                    self.low_loss_key = None
+
+            if self.low_loss_key is not None:
+                self.spectrum_ll = self.datasets[self.low_loss_key]
+                if 'number_of_frames' in self.spectrum_ll.metadata['experiment']:
+                    self.spectrum_ll.metadata['experiment']['exposure_time'] = \
+                        self.spectrum_ll.metadata['experiment']['single_exposure_time'] * \
+                        self.spectrum_ll.metadata['experiment']['number_of_frames'] 
+
+        def do_all_button_click(self):
+
+            if self.dataset.data_type.name != 'SPECTRAL_IMAGE':
+                self.do_fit_button_click()
+                return
+
+            if 'experiment' in self.dataset.metadata:
+                exp = self.dataset.metadata['experiment']
+                if 'convergence_angle' not in exp:
+                    raise ValueError('need a convergence_angle in experiment of metadata dictionary ')
+                alpha = exp['convergence_angle']
+                beta = exp['collection_angle']
+                beam_kv = exp['acceleration_voltage']
+            else:
+                raise ValueError('need a experiment parameter in metadata dictionary')
+
+            self.energy_scale = self.dataset._axes[self.spec_dim].values
+            eff_beta = eels.effective_collection_angle(self.energy_scale, alpha, beta, beam_kv)
+            if self.edges['use_low_loss']:
+                low_loss = np.array(self.spectrum_ll)/self.spectrum_ll.sum()
+            else:
+                low_loss = None
+
+            edges = eels.make_cross_sections(self.edges, np.array(self.energy_scale), beam_kv, eff_beta,
+                                             low_loss=low_loss)
+
+            view = self.dataset.view
+            bin_x = view.bin_x
+            bin_y = view.bin_y
+
+            start_x = view.x
+            start_y = view.y
+
+            number_of_edges = 0
+            for key in self.edges:
+                if key.isdigit():
+                    number_of_edges += 1
+
+            results = np.zeros([int(self.dataset.shape[0]/bin_x), int(self.dataset.shape[1]/bin_y), number_of_edges])
+            total_spec = int(self.dataset.shape[0]/bin_x)*int(self.dataset.shape[1]/bin_y)
+            self.ui.progress.setMaximum(total_spec)
+            self.ui.progress.setValue(0)
+            ind = 0
+            for x in range(int(self.dataset.shape[0]/bin_x)):
+
+                for y in range(int(self.dataset.shape[1]/bin_y)):
+                    ind += 1
+                    self.ui.progress.setValue(ind)
+                    view.x = x*bin_x
+                    view.y = y*bin_y
+                    spectrum = view.get_spectrum()
+
+                    edges = eels.fit_edges2(spectrum, self.energy_scale, edges)
+                    for key, edge in edges.items():
+                        if key.isdigit():
+                            # element.append(edge['element'])
+                            results[x, y, int(key)] = edge['areal_density']
+            edges['spectrum_image_quantification'] = results
+            self.ui.progress.setValue(total_spec)
+            view.x = start_x
+            view.y = start_y
+
+        def do_fit_button_click(self):
+            if 'experiment' in self.dataset.metadata:
+                exp = self.dataset.metadata['experiment']
+                if 'convergence_angle' not in exp:
+                    raise ValueError('need a convergence_angle in experiment of metadata dictionary ')
+                alpha = exp['convergence_angle']
+                beta = exp['collection_angle']
+                beam_kv = exp['acceleration_voltage']
+
+            else:
+                raise ValueError('need a experiment parameter in metadata dictionary')
+            self.energy_scale = self.dataset._axes[self.spec_dim].values
+            eff_beta = eels.effective_collection_angle(self.energy_scale, alpha, beta, beam_kv)
+
+            if self.edges['use_low_loss']:
+                low_loss = self.spectrum_ll / self.spectrum_ll.sum()
+            else:
+                low_loss = None
+            edges = eels.make_cross_sections(self.edges, np.array(self.energy_scale), beam_kv, eff_beta, low_loss)
+
+            if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE:
+                spectrum = self.dataset.view.get_spectrum()
+            else:
+                spectrum = self.dataset
+            self.edges = eels.fit_edges2(spectrum, self.energy_scale, edges)
+            areal_density = []
+            elements = []
+            for key in edges:
+                if key.isdigit():  # only edges have numbers in that dictionary
+                    elements.append(edges[key]['element'])
+                    areal_density.append(edges[key]['areal_density'])
+            areal_density = np.array(areal_density)
+            out_string = '\nRelative composition: \n'
+            for i, element in enumerate(elements):
+                out_string += f'{element}: {areal_density[i] / areal_density.sum() * 100:.1f}%  '
+
+            self.model = self.edges['model']['spectrum']
+            self.update()
+            self.plot()
+
+        def do_auto_id_button_click(self):
+            # self.ui.dialog.setWindowTitle(f"auto id ")
+            self.ui.do_fit_button.setFocus()
+
+            if '0' not in self.edges:
+                self.edges['0'] ={}
+            found_edges = eels.auto_id_edges(self.dataset)
+        
+            to_delete = []
+            if len(found_edges) >0:
+                for key in self.edges:
+                    if key.isdigit():
+                        to_delete.append(key)
+            for key in to_delete:
+                del self.edges[key]
+            if len(to_delete) == 0:
+                self.edges['0'] = {}
+            
+            selected_elements = []
+            for key in found_edges:
+                selected_elements.append(key)
+            self.set_elements(selected_elements)
+                
+            for button in self.pt_dialog.button:
+                if button.text() in selected_elements:
+                    button.setChecked(True)
+                else:
+                    button.setChecked(False)
+            self.update()
+
+        def do_select_button_click(self):
+            self.pt_dialog.energy_scale = self.energy_scale
+            self.pt_dialog.show()
+            self.update()
+
+        def set_action(self):
+            self.ui.edit1.editingFinished.connect(self.on_enter)
+            self.ui.edit2.editingFinished.connect(self.on_enter)
+            self.ui.list3.activated[str].connect(self.on_list_enter)
+            self.ui.check3.clicked.connect(self.on_check)
+            self.ui.edit4.editingFinished.connect(self.on_enter)
+            self.ui.list5.activated[str].connect(self.on_list_enter)
+            self.ui.select5.activated[str].connect(self.on_list_enter)
+
+            self.ui.edit6.editingFinished.connect(self.on_enter)
+            self.ui.edit7.editingFinished.connect(self.on_enter)
+            self.ui.edit8.editingFinished.connect(self.on_enter)
+            self.ui.edit9.editingFinished.connect(self.on_enter)
+
+            self.ui.check10.clicked.connect(self.on_check)
+            self.ui.select10.clicked.connect(self.on_check)
+            self.ui.show_edges.clicked.connect(self.on_check)
+            self.ui.check_probability.clicked.connect(self.on_check)
+            
+            self.ui.do_all_button.clicked.connect(self.do_all_button_click)
+            self.ui.do_fit_button.clicked.connect(self.do_fit_button_click)
+            self.ui.auto_id_button.clicked.connect(self.do_auto_id_button_click)
+            self.ui.select_button.clicked.connect(self.do_select_button_click)
+
+
+    class CurveVisualizer(object):
+        """Plots a sidpy.Dataset with spectral dimension-type
+
+        """
+        def __init__(self, dset, spectrum_number=None, axis=None, leg=None, **kwargs):
+            if not isinstance(dset, sidpy.Dataset):
+                raise TypeError('dset should be a sidpy.Dataset object')
+            if axis is None:
+                self.fig = plt.figure()
+                self.axis = self.fig.add_subplot(1, 1, 1)
+            else:
+                self.axis = axis
+                self.fig = axis.figure
+
+            self.dset = dset
+            self.selection = []
+            [self.spec_dim, self.energy_scale] = ft.get_dimensions_by_type('spectral', self.dset)[0]
+
+            self.lined = dict()
+            self.plot(**kwargs)
+
+        def plot(self, **kwargs):
+            if self.dset.data_type.name == 'IMAGE_STACK':
+                line1, = self.axis.plot(self.energy_scale.values, self.dset[0, 0], label='spectrum', **kwargs)
+            else:
+                line1, = self.axis.plot(self.energy_scale.values, self.dset, label='spectrum', **kwargs)
+            lines = [line1]
+            if 'add2plot' in self.dset.metadata:
+                data = self.dset.metadata['add2plot']
+                for key, line in data.items():
+                    line_add, = self.axis.plot(self.energy_scale.values,  line['data'], label=line['legend'])
+                    lines.append(line_add)
+
+                legend = self.axis.legend(loc='upper right', fancybox=True, shadow=True)
+                legend.get_frame().set_alpha(0.4)
+
+                for legline, origline in zip(legend.get_lines(), lines):
+                    legline.set_picker(True)
+                    legline.set_pickradius(5)  # 5 pts tolerance
+                    self.lined[legline] = origline
+                self.fig.canvas.mpl_connect('pick_event', self.onpick)
+
+            self.axis.axhline(0, color='gray', alpha=0.6)
+            self.axis.set_xlabel(self.dset.labels[0])
+            self.axis.set_ylabel(self.dset.data_descriptor)
+            self.axis.ticklabel_format(style='sci', scilimits=(-2, 3))
+            self.fig.canvas.draw_idle()
+
+        def update(self, **kwargs):
+            x_limit = self.axis.get_xlim()
+            y_limit = self.axis.get_ylim()
+            self.axis.clear()
+            self.plot(**kwargs)
+            self.axis.set_xlim(x_limit)
+            self.axis.set_ylim(y_limit)
+
+        def onpick(self, event):
+            # on the pick event, find the orig line corresponding to the
+            # legend proxy line, and toggle the visibility
+            legline = event.artist
+            origline = self.lined[legline]
+            vis = not origline.get_visible()
+            origline.set_visible(vis)
+            # Change the alpha on the line in the legend, so we can see what lines
+            # have been toggled
+            if vis:
+                legline.set_alpha(1.0)
+            else:
+                legline.set_alpha(0.2)
+            self.fig.canvas.draw()
+
+
[docs]def get_sidebar(): + side_bar = ipywidgets.GridspecLayout(13, 3,width='auto', grid_gap="0px") + + + row = 0 + side_bar[row, :3] = ipywidgets.ToggleButton(description='Fit Area', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + tooltip='Shows fit regions and regions excluded from fit', + button_style='info') #ipywidgets.ButtonStyle(button_color='lightblue')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=7.5,description='Fit Start:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='20px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Fit End:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='20px')) + + row += 1 + + side_bar[row, :3] = ipywidgets.Button(description='Elements', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + row += 1 + side_bar[row, :2] = ipywidgets.Dropdown( + options=[('Edge 1', 0), ('Edge 2', 1), ('Edge 3', 2), ('Edge 4', 3),('Add Edge', -1)], + value=0, + description='Edges:', + disabled=False, + layout=ipywidgets.Layout(width='200px')) + """side_bar[row,2] = ipywidgets.ToggleButton( + description='Regions', + disabled=False, + button_style='', # 'success', 'info', 'warning', 'danger' or '' + tooltip='Shows fit regions and regions excluded from fit', + layout=ipywidgets.Layout(width='100px') + ) + """ + row += 1 + side_bar[row, :2] = ipywidgets.IntText(value=7.5,description='Z:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.Dropdown( + options=['K1','L3', 'M5', 'M3', 'M1', 'N7', 'N5', 'N3', 'N1'], + value='K1', + description='Symmetry:', + disabled=False, + layout=ipywidgets.Layout(width='200px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Onset:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Excl.Start:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Excl.End:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Mutliplier:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="a.u.", layout=ipywidgets.Layout(width='100px')) + row += 1 + + side_bar[row, :3] = ipywidgets.Button(description='Quantification', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + + row += 1 + side_bar[row,0] = ipywidgets.ToggleButton( + description='Probabiity', + disabled=False, + button_style='', # 'success', 'info', 'warning', 'danger' or '' + tooltip='Changes y-axis to probability of flux is given', + layout=ipywidgets.Layout(width='100px') + ) + side_bar[row,1] = ipywidgets.ToggleButton( + description='Conv.LL', + disabled=False, + button_style='', # 'success', 'info', 'warning', 'danger' or '' + tooltip='Changes y-axis to probability of flux is given', + layout=ipywidgets.Layout(width='100px') + ) + side_bar[row,2] = ipywidgets.ToggleButton( + description='Show Edges', + disabled=False, + button_style='', # 'success', 'info', 'warning', 'danger' or '' + tooltip='Changes y-axis to probability of flux is given', + layout=ipywidgets.Layout(width='100px') + ) + return side_bar
+ + +import ipywidgets + + +
[docs]class CompositionWidget(object): + def __init__(self, datasets=None, index=0): + + if not isinstance(datasets, dict): + raise TypeError('dataset or first item has to be a sidpy dataset') + self.datasets = datasets + self.dataset = datasets[list(datasets)[0]] + self.model = [] + self.sidebar = get_sidebar() + + self.set_dataset() + + self.periodic_table = eels_dialog_utilities.PeriodicTableWidget(self.energy_scale) + self.elements_cancel_button = ipywidgets.Button(description='Cancel') + self.elements_select_button = ipywidgets.Button(description='Select') + self.elements_auto_button = ipywidgets.Button(description='Auto ID') + + self.periodic_table_panel = ipywidgets.VBox([self.periodic_table.periodic_table, + ipywidgets.HBox([self.elements_cancel_button, self.elements_auto_button, self.elements_select_button])]) + + + self.app_layout = ipywidgets.AppLayout( + left_sidebar=self.sidebar, + center=self.view.panel, + footer=None,#message_bar, + pane_heights=[0, 10, 0], + pane_widths=[4, 10, 0], + ) + self.set_action() + display(self.app_layout) + + + def line_select_callback(self, x_min, x_max): + self.start_cursor.value = np.round(x_min,3) + self.end_cursor.value = np.round(x_max, 3) + self.start_channel = np.searchsorted(self.datasets[self.key].energy_loss, self.start_cursor.value) + self.end_channel = np.searchsorted(self.datasets[self.key].energy_loss, self.end_cursor.value) + + + def plot(self, scale=True): + self.view.change_y_scale = self.change_y_scale + self.view.y_scale = self.y_scale + self.energy_scale = self.dataset.energy_loss.values + + if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE: + spectrum = self.dataset.view.get_spectrum() + else: + spectrum = self.dataset + if len(self.model) > 1: + additional_spectra = {'model': self.model, + 'difference': spectrum-self.model} + else: + additional_spectra = None + self.view.plot(scale=True, additional_spectra=additional_spectra ) + self.change_y_scale = 1. + + if self.sidebar[12, 2].value: + self.show_edges() + if self.sidebar[0, 0].value: + self.plot_regions() + self.view.figure.canvas.draw_idle() + + + def plot_regions(self): + axis = self.view.figure.gca() + y_min, y_max = axis.get_ylim() + height = y_max - y_min + + rect = [] + if 'fit_area' in self.edges: + color = 'blue' + alpha = 0.2 + x_min = self.edges['fit_area']['fit_start'] + width = self.edges['fit_area']['fit_end'] - x_min + rect.append(patches.Rectangle((x_min, y_min), width, height, + edgecolor=color, alpha=alpha, facecolor=color)) + axis.add_patch(rect[0]) + axis.text(x_min, y_max, 'fit region', verticalalignment='top') + color = 'red' + alpha = 0.5 + + for key in self.edges: + if key.isdigit(): + x_min = self.edges[key]['start_exclude'] + width = self.edges[key]['end_exclude']-x_min + rect.append(patches.Rectangle((x_min, y_min), width, height, + edgecolor=color, alpha=alpha, facecolor=color)) + axis.add_patch(rect[-1]) + axis.text(x_min, y_max, f"exclude\n edge {int(key)+1}", verticalalignment='top') + + def show_edges(self): + axis = self.view.figure.gca() + x_min, x_max = axis.get_xlim() + y_min, y_max = axis.get_ylim() + + for key, edge in self.edges.items(): + i = 0 + if key.isdigit(): + element = edge['element'] + for sym in edge['all_edges']: + x = edge['all_edges'][sym]['onset'] + edge['chemical_shift'] + if x_min < x < x_max: + axis.text(x, y_max, '\n' * i + f"{element}-{sym}", + verticalalignment='top', color='black') + axis.axvline(x, ymin=0, ymax=1, color='gray') + i += 1 + + + + + def set_dataset(self, index=0): + spec_dim = self.dataset.get_dimensions_by_type(sidpy.DimensionType.SPECTRAL) + self.spec_dim = self.dataset._axes[spec_dim[0]] + + self.energy_scale = self.spec_dim.values + self.dataset.metadata['experiment']['offset'] = self.energy_scale[0] + self.dataset.metadata['experiment']['dispersion'] = self.energy_scale[1] - self.energy_scale[0] + if 'edges' not in self.dataset.metadata or self.dataset.metadata['edges'] == {}: + self.dataset.metadata['edges'] = {'0': {}, 'model': {}, 'use_low_loss': False} + + self.edges = self.dataset.metadata['edges'] + if '0' not in self.edges: + self.edges['0'] = {} + + if 'fit_area' not in self.edges: + self.edges['fit_area'] = {} + if 'fit_start' not in self.edges['fit_area']: + self.sidebar[1,0].value = np.round(self.energy_scale[50], 3) + self.edges['fit_area']['fit_start'] = self.sidebar[1,0].value + else: + self.sidebar[1,0].value = np.round(self.edges['fit_area']['fit_start'],3) + if 'fit_end' not in self.edges['fit_area']: + self.sidebar[2,0].value = np.round(self.energy_scale[-2], 3) + self.edges['fit_area']['fit_end'] = self.sidebar[2,0].value + else: + self.sidebar[2,0].value = np.round(self.edges['fit_area']['fit_end'],3) + + if self.dataset.data_type.name == 'SPECTRAL_IMAGE': + if 'SI_bin_x' not in self.dataset.metadata['experiment']: + self.dataset.metadata['experiment']['SI_bin_x'] = 1 + self.dataset.metadata['experiment']['SI_bin_y'] = 1 + + bin_x = self.dataset.metadata['experiment']['SI_bin_x'] + bin_y = self.dataset.metadata['experiment']['SI_bin_y'] + # self.dataset.view.set_bin([bin_x, bin_y]) + if self.dataset.data_type.name =='SPECTRAL_IMAGE': + self.view = eels_dialog_utilities.SIPlot(self.dataset) + else: + self.view = eels_dialog_utilities.SpectrumPlot(self.dataset) + self.y_scale = 1.0 + self.change_y_scale = 1.0 + + self.update() + + def update_element(self, z=0, index=-1): + # We check whether this element is already in the + if z == 0: + z = self.sidebar[5,0].value + + zz = eels.get_z(z) + for key, edge in self.edges.items(): + if key.isdigit(): + if 'z' in edge: + if zz == edge['z']: + return False + + major_edge = '' + minor_edge = '' + all_edges = {} + x_section = eels.get_x_sections(zz) + edge_start = 10 # int(15./ft.get_slope(self.energy_scale)+0.5) + for key in x_section: + if len(key) == 2 and key[0] in ['K', 'L', 'M', 'N', 'O'] and key[1].isdigit(): + if self.energy_scale[edge_start] < x_section[key]['onset'] < self.energy_scale[-edge_start]: + if key in ['K1', 'L3', 'M5']: + major_edge = key + elif key in self.sidebar[6,0].options: + if minor_edge == '': + minor_edge = key + if int(key[-1]) % 2 > 0: + if int(minor_edge[-1]) % 2 == 0 or key[-1] > minor_edge[-1]: + minor_edge = key + + all_edges[key] = {'onset': x_section[key]['onset']} + + if major_edge != '': + key = major_edge + elif minor_edge != '': + key = minor_edge + else: + print(f'Could not find no edge of {zz} in spectrum') + return False + if index == -1: + index = self.sidebar[4, 0].value + # self.ui.dialog.setWindowTitle(f'{index}, {zz}') + + if str(index) not in self.edges: + self.edges[str(index)] = {} + + start_exclude = x_section[key]['onset'] - x_section[key]['excl before'] + end_exclude = x_section[key]['onset'] + x_section[key]['excl after'] + + self.edges[str(index)] = {'z': zz, 'symmetry': key, 'element': eels.elements[zz], + 'onset': x_section[key]['onset'], 'end_exclude': end_exclude, + 'start_exclude': start_exclude} + self.edges[str(index)]['all_edges'] = all_edges + self.edges[str(index)]['chemical_shift'] = 0.0 + self.edges[str(index)]['areal_density'] = 0.0 + self.edges[str(index)]['original_onset'] = self.edges[str(index)]['onset'] + return True + + def sort_elements(self): + onsets = [] + for index, edge in self.edges.items(): + if index.isdigit(): + onsets.append(float(edge['onset'])) + + arg_sorted = np.argsort(onsets) + edges = self.edges.copy() + for index, i_sorted in enumerate(arg_sorted): + self.edges[str(index)] = edges[str(i_sorted)].copy() + + index = 0 + edge = self.edges['0'] + dispersion = self.energy_scale[1]-self.energy_scale[0] + + while str(index + 1) in self.edges: + next_edge = self.edges[str(index + 1)] + if edge['end_exclude'] > next_edge['start_exclude'] - 5 * dispersion: + edge['end_exclude'] = next_edge['start_exclude'] - 5 * dispersion + edge = next_edge + index += 1 + + if edge['end_exclude'] > self.energy_scale[-3]: + edge['end_exclude'] = self.energy_scale[-3] + + def set_elements(self, value=0): + selected_elements = self.periodic_table.get_output() + edges = self.edges.copy() + to_delete = [] + old_elements = [] + if len(selected_elements) > 0: + for key in self.edges: + if key.isdigit(): + to_delete.append(key) + old_elements.append(self.edges[key]['element']) + + for key in to_delete: + edges[key] = self.edges[key] + del self.edges[key] + + for index, elem in enumerate(selected_elements): + if elem in old_elements: + self.edges[str(index)] = edges[str(old_elements.index(elem))] + else: + self.update_element(elem, index=index) + self.sort_elements() + self.update() + self.set_figure_pane() + + def set_element(self, elem): + self.update_element(self.sidebar[5, 0].value) + # self.sort_elements() + self.update() + + def cursor2energy_scale(self, value): + dispersion = (self.end_cursor.value - self.start_cursor.value) / (self.end_channel - self.start_channel) + self.datasets[self.key].energy_loss *= (self.sidebar[3, 0].value/dispersion) + self.sidebar[3, 0].value = dispersion + offset = self.start_cursor.value - self.start_channel * dispersion + self.datasets[self.key].energy_loss += (self.sidebar[2, 0].value-self.datasets[self.key].energy_loss[0]) + self.sidebar[2, 0].value = offset + self.plot() + + def set_fit_area(self, value): + if self.sidebar[1,0].value > self.sidebar[2,0].value: + self.sidebar[1,0].value = self.sidebar[2,0].value -1 + if self.sidebar[1,0].value < self.energy_scale[0]: + self.sidebar[1,0].value = self.energy_scale[0] + if self.sidebar[2,0].value > self.energy_scale[-1]: + self.sidebar[2,0].value = self.energy_scale[-1] + self.edges['fit_area']['fit_start'] = self.sidebar[1,0].value + self.edges['fit_area']['fit_end'] = self.sidebar[2,0].value + + self.plot() + + def set_y_scale(self, value): + self.change_y_scale = 1/self.y_scale + self.y_scale = 1.0 + if self.dataset.metadata['experiment']['flux_ppm'] > 0: + if self.sidebar[12, 0].value: + dispersion = self.energy_scale[1] - self.energy_scale[0] + self.y_scale = 1/self.dataset.metadata['experiment']['flux_ppm'] * dispersion + + self.change_y_scale *= self.y_scale + self.update() + self.plot() + + def auto_id(self, value=0): + found_edges = eels.auto_id_edges(self.dataset) + if len(found_edges) > 0: + self.periodic_table.elements_selected = found_edges + self.periodic_table.update() + + def find_elements(self, value=0): + + if '0' not in self.edges: + self.edges['0'] = {} + # found_edges = eels.auto_id_edges(self.dataset) + found_edges = {} + + selected_elements = [] + elements = self.edges.copy() + + for key in self.edges: + if key.isdigit(): + if 'element' in self.edges[key]: + selected_elements.append(self.edges[key]['element']) + self.periodic_table.elements_selected = selected_elements + self.periodic_table.update() + self.app_layout.center = self.periodic_table_panel # self.periodic_table.periodic_table + + def set_figure_pane(self, value=0): + + self.app_layout.center = self.view.panel + + def update(self, index=0): + + index = self.sidebar[4,0].value # which edge + if index < 0: + options = list(self.sidebar[4,0].options) + options.insert(-1, (f'Edge {len(self.sidebar[4,0].options)}', len(self.sidebar[4,0].options)-1)) + self.sidebar[4,0].options= options + self.sidebar[4,0].value = len(self.sidebar[4,0].options)-2 + if str(index) not in self.edges: + self.edges[str(index)] = {'z': 0, 'element': 'x', 'symmetry': 'K1', 'onset': 0, 'start_exclude': 0, 'end_exclude':0, + 'areal_density': 0, 'chemical_shift':0} + if 'z' not in self.edges[str(index)]: + self.edges[str(index)] = {'z': 0, 'element': 'x', 'symmetry': 'K1', 'onset': 0, 'start_exclude': 0, 'end_exclude':0, + 'areal_density': 0, 'chemical_shift':0} + edge = self.edges[str(index)] + + self.sidebar[5,0].value = edge['z'] + self.sidebar[5,2].value = edge['element'] + self.sidebar[6,0].value = edge['symmetry'] + self.sidebar[7,0].value = edge['onset'] + self.sidebar[8,0].value = edge['start_exclude'] + self.sidebar[9,0].value = edge['end_exclude'] + if self.y_scale == 1.0: + self.sidebar[10, 0].value = edge['areal_density'] + self.sidebar[10, 2].value = 'a.u.' + else: + dispersion = self.energy_scale[1]-self.energy_scale[0] + self.sidebar[10, 0].value = np.round(edge['areal_density']/self.dataset.metadata['experiment']['flux_ppm']*1e-6, 2) + self.sidebar[10, 2].value = 'atoms/nm²' + + + def do_fit(self, value=0): + if 'experiment' in self.dataset.metadata: + exp = self.dataset.metadata['experiment'] + if 'convergence_angle' not in exp: + raise ValueError('need a convergence_angle in experiment of metadata dictionary ') + alpha = exp['convergence_angle'] + beta = exp['collection_angle'] + beam_kv = exp['acceleration_voltage'] + + else: + raise ValueError('need a experiment parameter in metadata dictionary') + + eff_beta = eels.effective_collection_angle(self.energy_scale, alpha, beta, beam_kv) + + self.low_loss = None + if self.sidebar[12, 1].value: + for key in self.datasets.keys(): + if key != self.key: + if isinstance(self.datasets[key], sidpy.Dataset): + if self.datasets[key].data_type.name == 'SPECTRUM': + if self.datasets[key].energy_loss[0] < 0: + self.low_loss = self.datasets[key]/self.datasets[key].sum() + + edges = eels.make_cross_sections(self.edges, np.array(self.energy_scale), beam_kv, eff_beta, self.low_loss) + + if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE: + spectrum = self.dataset.view.get_spectrum() + else: + spectrum = self.dataset + self.edges = eels.fit_edges2(spectrum, self.energy_scale, edges) + areal_density = [] + elements = [] + for key in edges: + if key.isdigit(): # only edges have numbers in that dictionary + elements.append(edges[key]['element']) + areal_density.append(edges[key]['areal_density']) + areal_density = np.array(areal_density) + out_string = '\nRelative composition: \n' + for i, element in enumerate(elements): + out_string += f'{element}: {areal_density[i] / areal_density.sum() * 100:.1f}% ' + + self.model = self.edges['model']['spectrum'] + self.update() + self.plot() + + def modify_onset(self, value=-1): + edge_index = self.sidebar[4, 0].value + edge = self.edges[str(edge_index)] + edge['onset'] = self.sidebar[7,0].value + if 'original_onset' not in edge: + edge['original_onset'] = edge['onset'] + edge['chemical_shift'] = edge['onset'] - edge['original_onset'] + self.update() + + + def modify_start_exclude(self, value=-1): + edge_index = self.sidebar[4, 0].value + edge = self.edges[str(edge_index)] + edge['start_exclude'] = self.sidebar[8,0].value + self.plot() + + def modify_end_exclude(self, value=-1): + edge_index = self.sidebar[4, 0].value + edge = self.edges[str(edge_index)] + edge['end_exclude'] = self.sidebar[9,0].value + self.plot() + + def modify_areal_density(self, value=-1): + edge_index = self.sidebar[4, 0].value + edge = self.edges[str(edge_index)] + + edge['areal_density'] = self.sidebar[10, 0].value + if self.y_scale != 1.0: + dispersion = self.energy_scale[1]-self.energy_scale[0] + edge['areal_density'] = self.sidebar[10, 0].value *self.dataset.metadata['experiment']['flux_ppm']/1e-6 + + self.model = self.edges['model']['background'] + for key in self.edges: + if key.isdigit(): + if 'data' in self.edges[key]: + + self.model = self.model + self.edges[key]['areal_density'] * self.edges[key]['data'] + self.plot() + + def set_action(self): + self.sidebar[1, 0].observe(self.set_fit_area, names='value') + self.sidebar[2, 0].observe(self.set_fit_area, names='value') + + self.sidebar[3, 0].on_click(self.find_elements) + self.sidebar[4, 0].observe(self.update) + self.sidebar[5, 0].observe(self.set_element, names='value') + + self.sidebar[7, 0].observe(self.modify_onset, names='value') + self.sidebar[8, 0].observe(self.modify_start_exclude, names='value') + self.sidebar[9, 0].observe(self.modify_end_exclude, names='value') + self.sidebar[10, 0].observe(self.modify_areal_density, names='value') + + self.sidebar[11, 0].on_click(self.do_fit) + self.sidebar[12, 2].observe(self.plot) + self.sidebar[0, 0].observe(self.plot) + + self.sidebar[12,0].observe(self.set_y_scale) + + self.elements_cancel_button.on_click(self.set_figure_pane) + self.elements_auto_button.on_click(self.auto_id) + self.elements_select_button.on_click(self.set_elements)
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/eels_dialog_utilities.html b/_modules/pyTEMlib/eels_dialog_utilities.html new file mode 100644 index 00000000..d2c7ca7e --- /dev/null +++ b/_modules/pyTEMlib/eels_dialog_utilities.html @@ -0,0 +1,1637 @@ + + + + + + pyTEMlib.eels_dialog_utilities — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for pyTEMlib.eels_dialog_utilities

+""" Interactive routines for EELS analysis
+
+this file provides additional dialogs for EELS quantification
+
+Author: Gerd Duscher
+"""
+
+import numpy as np
+Qt_available = True
+try:
+    from PyQt5 import QtCore, QtGui, QtWidgets
+
+except:
+    Qt_available = False
+    # print('Qt dialogs are not available')
+
+import sidpy
+import matplotlib
+import matplotlib.pyplot as plt
+
+import matplotlib.patches as patches
+from matplotlib.widgets import RectangleSelector, SpanSelector
+
+import h5py  # TODO: needs to go
+
+from IPython.display import display
+import ipywidgets
+
+from pyTEMlib import eels_tools as eels
+from pyTEMlib import file_tools as ft
+
+major_edges = ['K1', 'L3', 'M5', 'N5']
+all_edges = ['K1', 'L1', 'L2', 'L3', 'M1', 'M2', 'M3', 'M4', 'M5', 'N1', 'N2', 'N3', 'N4', 'N5', 'N6', 'N7', 'O1', 'O2',
+             'O3', 'O4', 'O5', 'O6', 'O7', 'P1', 'P2', 'P3']
+first_close_edges = ['K1', 'L3', 'M5', 'M3', 'N5', 'N3']
+
+if Qt_available:
+
+    class PeriodicTableDialog(QtWidgets.QDialog):
+        """ Modal dialog to get a selection of elements.
+
+        Elements that are not having a valid cross-sections are disabled.
+
+        Parameters
+        ----------
+        initial_elements: list of str
+            the elements that are already selected
+        energy_scale: list or numpy array
+            energy-scale of spectrum/spectra to determine likely edges
+
+        Returns
+        -------
+        list of strings: elements.
+
+        Example
+        -------
+        >> PT_dialog =  periodic_table_dialog(None, ['Mn', 'O'])
+        >> if PT_dialog.exec_() == periodic_table_dialog.Accepted:
+        >>     selected_elements = PT_dialog.get_output()
+        >> print(selected_elements)
+        """
+
+        signal_selected = QtCore.pyqtSignal(list)
+
+        def __init__(self, initial_elements=None, energy_scale=None, parent=None):
+            super(PeriodicTableDialog, self).__init__(None, QtCore.Qt.WindowStaysOnTopHint)
+
+            if initial_elements is None:
+                initial_elements = [' ']
+            self.initial_elements = initial_elements
+            if energy_scale is None:
+                energy_scale = [100., 150., 200.]
+            self.parent = parent
+            self._output = []
+            self.elements_selected = initial_elements
+            self.energy_scale = np.array(energy_scale)
+
+            self.setWindowTitle("Periodic Table")
+            likely_edges = get_likely_edges(self.energy_scale)
+            self.likely_edges = likely_edges
+
+            # GD:font = wx.Font(10, wx.MODERN, wx.NORMAL, wx.BOLD)
+            self.buttons1 = []
+            self.button = []
+            self.pt_info = get_periodic_table_info()
+            self.init_ui()
+
+            for button in self.button:
+                if button.text() in initial_elements:
+                    button.toggle()
+                pass
+
+        def on_close(self):
+            self.get_output()
+            self.signal_selected[list].emit(self._output)
+            self.accept()
+
+        def get_output(self):
+            self._output = []
+            for btn in self.button:
+                if btn.isChecked():
+                    self._output.append(btn.text())
+
+        def exec_(self):
+            super(PeriodicTableDialog, self).exec_()
+            return self._output
+
+        def init_ui(self):
+
+            v_sizer = QtWidgets.QVBoxLayout()
+            g_sizer = QtWidgets.QGridLayout()
+
+            main_group = QtWidgets.QWidget()
+
+            color1 = "background-color: lightblue;\n"
+            color1l = "background-color: dodgerblue;\n"
+            color2 = "background-color: coral;\n"
+
+            for symbol, parameter in self.pt_info.items():
+                self.button.append(QtWidgets.QPushButton(symbol))
+                if parameter['PT_row'] > 7:
+                    self.button[-1].setStyleSheet(color2)
+                elif '*' in symbol:
+                    self.button[-1].setStyleSheet(color2)
+                else:
+                    if symbol in self.likely_edges:
+                        self.button[-1].setStyleSheet(color1l)
+                    else:
+                        self.button[-1].setStyleSheet(color1)
+                if parameter['Z'] == 0:
+                    self.button[-1].setEnabled(False)
+                self.button[-1].setFixedWidth(50)
+                self.button[-1].setCheckable(True)
+                g_sizer.addWidget(self.button[-1], parameter['PT_row'], parameter['PT_col'])
+            main_group.setLayout(g_sizer)
+
+            v_sizer.addWidget(main_group)
+            self.setLayout(v_sizer)
+
+            ok_button = QtWidgets.QPushButton('OK')
+            ok_button.clicked.connect(self.on_close)
+
+            v_sizer.addWidget(ok_button)
+            self.setLayout(v_sizer)
+
+
+    class EnergySelector(QtWidgets.QDialog):
+        """Dialog and cursor to set energy scale"""
+
+        signal_selected = QtCore.pyqtSignal(bool)
+
+        def __init__(self, dset=None):
+            super(EnergySelector, self).__init__(None, QtCore.Qt.WindowStaysOnTopHint)
+
+            if not isinstance(dset, sidpy.Dataset):
+                return
+            if dset is None:
+                return
+            if dset.view is None:
+                return
+            self.dataset = dset
+
+            if hasattr(dset.view, 'axis'):
+                self.axis = dset.view.axis
+                # self.setWindowTitle('p')
+            elif hasattr(dset.view, 'axes'):
+                self.axis = dset.view.axes[1]
+            else:
+                return
+
+            self.spec_dim = -1
+            for dim, axis in self.dataset._axes.items():
+                if axis.dimension_type == sidpy.DimensionType.SPECTRAL:
+                    self.spec_dim = dim
+            if self.spec_dim < 0:
+                raise TypeError('We need at least one SPECTRAL dimension')
+
+            self.energy_scale = self.dataset._axes[self.spec_dim].values
+            self.dispersion = self.energy_scale[1] - self.energy_scale[0]
+            self.offset = self.energy_scale[0]
+            self.spectrum = np.zeros(2)
+
+            self.change = 0
+
+            self.x_min = self.energy_scale[int(len(self.energy_scale)/4)]
+            self.x_max = self.energy_scale[int(len(self.energy_scale) / 4*3)]
+            self.setWindowTitle("Select Energy")
+
+            valid_float = QtGui.QDoubleValidator()
+
+            layout = QtWidgets.QGridLayout()
+            layout.setVerticalSpacing(2)
+            self.label1 = QtWidgets.QLabel('Start:')
+            self.edit1 = QtWidgets.QLineEdit('0')
+            self.edit1.setValidator(valid_float)
+            self.unit1 = QtWidgets.QLabel('eV')
+
+            self.label2 = QtWidgets.QLabel('End:')
+            self.edit2 = QtWidgets.QLineEdit('0')
+            self.edit2.setValidator(valid_float)
+            self.unit2 = QtWidgets.QLabel('eV')
+
+            self.label3 = QtWidgets.QLabel('Dispersion:')
+            self.edit3 = QtWidgets.QLineEdit('0')
+            self.edit3.setValidator(valid_float)
+            self.unit3 = QtWidgets.QLabel('eV')
+
+            self.edit1.editingFinished.connect(self.on_enter)
+            self.edit2.editingFinished.connect(self.on_enter)
+            self.edit3.editingFinished.connect(self.on_enter)
+
+            layout.addWidget(self.label1, 0, 0)
+            layout.addWidget(self.edit1, 0, 1)
+            layout.addWidget(self.unit1, 0, 2)
+
+            layout.addWidget(self.label2, 1, 0)
+            layout.addWidget(self.edit2, 1, 1)
+            layout.addWidget(self.unit2, 1, 2)
+
+            layout.addWidget(self.label3, 2, 0)
+            layout.addWidget(self.edit3, 2, 1)
+            layout.addWidget(self.unit3, 2, 2)
+
+            self.ok_button = QtWidgets.QPushButton('OK')
+            self.ok_button.clicked.connect(self.on_close)
+            self.cancel_button = QtWidgets.QPushButton('Cancel')
+            self.cancel_button.clicked.connect(self.on_close)
+
+            layout.addWidget(self.ok_button, 3, 0)
+            layout.addWidget(self.cancel_button, 3, 2)
+
+            self.setLayout(layout)
+            self.edit1.setFocus()
+            self.plot()
+
+            self.selector = SpanSelector(self.axis, self.line_select_callback,
+                                         direction="horizontal",
+                                         interactive=True,
+                                         props=dict(facecolor='blue', alpha=0.2))
+            self.edit1.setText(f'{self.x_min:.3f}')
+            self.edit2.setText(f'{self.x_max:.3f}')
+            self.edit3.setText(f'{self.dispersion:.4f}')
+            self.update()
+
+        def line_select_callback(self, eclick, erelease):
+            y_min, y_max = self.axis.get_ylim()
+            self.x_min = self.selector.extents[0]
+            self.x_max = self.selector.extents[1]
+            # self.selector.extents = (self.x_min, self.x_max, y_min, y_max)
+
+            self.edit1.setText(f'{self.x_min:.3f}')
+            self.edit2.setText(f'{self.x_max:.3f}')
+
+        def on_enter(self):
+            sender = self.sender()
+
+            if sender == self.edit1:
+                value = float(str(sender.displayText()).strip())
+                if value == self.x_min:
+                    return
+                self.change = value - self.x_min
+                self.x_min += self.change
+                self.x_max += self.change
+                self.offset += self.change
+
+                self.edit1.setText(f"{self.x_min:.2f}")
+                self.edit2.setText(f"{self.x_max:.2f}")
+
+                self.energy_scale = np.arange(len(self.energy_scale)) * self.dispersion + self.offset
+
+                self.update()
+                # self.axis.draw()
+                # self.setWindowTitle(f'shift, {self.change}, {self.x_min}')
+
+            elif sender == self.edit2:
+                value = float(str(sender.displayText()).strip())
+                if value == self.x_max:
+                    return
+                start_channel = np.searchsorted(self.energy_scale, self.x_min)
+                end_channel = np.searchsorted(self.energy_scale, self.x_max)
+
+                self.x_max = value
+
+                if end_channel - start_channel != 0:
+                    self.dispersion = (self.x_max - self.x_min) / (end_channel - start_channel)
+                self.offset = self.x_min - start_channel * self.dispersion
+                self.edit2.setText(f"{self.x_max:.3f}")
+                self.edit3.setText(f"{self.dispersion:.4f}")
+                self.energy_scale = np.arange(len(self.energy_scale)) * self.dispersion + self.offset
+
+                self.update()
+                # self.axis.draw()
+                # self.setWindowTitle(f'range, {self.change}, {self.dispersion}')
+
+            elif sender == self.edit3:
+                value = float(str(sender.displayText()).strip())
+                if self.dispersion == value:
+                    return
+
+                start_channel = np.searchsorted(self.energy_scale, self.x_min)
+                end_channel = np.searchsorted(self.energy_scale, self.x_max)
+                self.dispersion = value
+                self.energy_scale = np.arange(len(self.energy_scale)) * self.dispersion + self.offset
+                self.x_min = self.energy_scale[start_channel]
+                self.x_max = self.energy_scale[end_channel]
+                self.update()
+                # self.axis.draw()
+                self.edit3.setText(f"{self.dispersion:.3f}")
+                self.change = 0
+
+        def on_close(self):
+            sender = self.sender()
+            if sender == self.ok_button:
+                pass
+                self.dataset.set_dimension(self.spec_dim, sidpy.Dimension(self.energy_scale, name='energy_scale',
+                                                                          units='eV', quantity='energy loss',
+                                                                          dimension_type='spectral'))
+            else:
+                pass
+            self.selector.set_visible(False)
+            self.signal_selected[bool].emit(True)
+            self.accept()
+
+        def plot(self):
+            if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE:
+                self.spectrum = self.dataset.view.get_spectrum()
+            else:
+                self.spectrum = np.array(self.dataset)
+            x_limit = self.axis.get_xlim()
+            y_limit = self.axis.get_ylim()
+
+            self.axis.clear()
+            self.cplot = self.axis.plot(self.energy_scale, self.spectrum, label='spectrum')
+            self.axis.set_xlim(x_limit)
+            self.axis.set_ylim(y_limit)
+
+            self.axis.figure.canvas.draw()
+
+        def update(self):
+            x_limit = self.axis.get_xlim()
+            y_limit = self.axis.get_ylim()
+            self.selector.extents = (self.x_min, self.x_max)
+
+            x_limit = np.array(x_limit) + self.change
+
+            self.cplot[0].set_data(self.energy_scale, self.spectrum)
+            self.axis.set_xlim(x_limit)
+            self.axis.set_ylim(y_limit)
+            self.axis.figure.canvas.draw()
+
+
+
+
+
+
[docs]class RegionSelector(object): + """Selects fitting region and the regions that are excluded for each edge. + + Select a region with a spanSelector and then type 'a' for all the fitting region or a number for the edge + you want to define the region excluded from the fit (solid state effects). + + see Chapter4 'CH4-Working_with_X-Sections,ipynb' notebook + + """ + + def __init__(self, ax): + self.ax = ax + self.regions = {} + self.rect = None + self.xmin = 0 + self.width = 0 + + self.span = SpanSelector(ax, self.on_select1, + direction="horizontal", + interactive=True, + props=dict(facecolor='blue', alpha=0.2)) + self.cid = ax.figure.canvas.mpl_connect('key_press_event', self.click) + self.draw = ax.figure.canvas.mpl_connect('draw_event', self.onresize) + + def on_select1(self, xmin, xmax): + self.xmin = xmin + self.width = xmax - xmin + + def onresize(self, event): + self.update() + + def delete_region(self, key): + if key in self.regions: + if 'Rect' in self.regions[key]: + self.regions[key]['Rect'].remove() + self.regions[key]['Text'].remove() + del (self.regions[key]) + + def update(self): + + y_min, y_max = self.ax.get_ylim() + for key in self.regions: + if 'Rect' in self.regions[key]: + self.regions[key]['Rect'].remove() + self.regions[key]['Text'].remove() + + xmin = self.regions[key]['xmin'] + width = self.regions[key]['width'] + height = y_max - y_min + alpha = self.regions[key]['alpha'] + color = self.regions[key]['color'] + self.regions[key]['Rect'] = patches.Rectangle((xmin, y_min), width, height, + edgecolor=color, alpha=alpha, facecolor=color) + self.ax.add_patch(self.regions[key]['Rect']) + + self.regions[key]['Text'] = self.ax.text(xmin, y_max, self.regions[key]['text'], verticalalignment='top') + + def click(self, event): + if str(event.key) in ['1', '2', '3', '4', '5', '6']: + key = str(event.key) + text = 'exclude \nedge ' + key + alpha = 0.5 + color = 'red' + elif str(event.key) in ['a', 'A', 'B', 'b', 'f', 'F']: + key = '0' + color = 'blue' + alpha = 0.2 + text = 'fit region' + else: + return + + if key not in self.regions: + self.regions[key] = {} + + self.regions[key]['xmin'] = self.xmin + self.regions[key]['width'] = self.width + self.regions[key]['color'] = color + self.regions[key]['alpha'] = alpha + self.regions[key]['text'] = text + + self.update() + + def set_regions(self, region, start_x, width): + key = '' + if 'fit' in str(region): + key = '0' + if region in ['0', '1', '2', '3', '4', '5', '6']: + key = region + if region in [0, 1, 2, 3, 4, 5, 6]: + key = str(region) + + if key not in self.regions: + self.regions[key] = {} + if key in ['1', '2', '3', '4', '5', '6']: + self.regions[key]['text'] = 'exclude \nedge ' + key + self.regions[key]['alpha'] = 0.5 + self.regions[key]['color'] = 'red' + elif key == '0': + self.regions[key]['text'] = 'fit region' + self.regions[key]['alpha'] = 0.2 + self.regions[key]['color'] = 'blue' + + self.regions[key]['xmin'] = start_x + self.regions[key]['width'] = width + + self.update() + + def get_regions(self): + tags = {} + for key in self.regions: + if key == '0': + area = 'fit_area' + else: + area = key + tags[area] = {} + tags[area]['start_x'] = self.regions[key]['xmin'] + tags[area]['width_x'] = self.regions[key]['width'] + + return tags + + def disconnect(self): + for key in self.regions: + if 'Rect' in self.regions[key]: + self.regions[key]['Rect'].remove() + self.regions[key]['Text'].remove() + del self.span + self.ax.figure.canvas.mpl_disconnect(self.cid) + # self.ax.figure.canvas.mpl_disconnect(self.draw) + pass
+ + +
[docs]class RangeSelector(RectangleSelector): + """Select ranges of edge fitting interactively""" + def __init__(self, ax, on_select): + drawtype = 'box' + spancoords = 'data' + rectprops = dict(facecolor="blue", edgecolor="black", alpha=0.2, fill=True) + + super().__init__(ax, on_select, drawtype=drawtype, + minspanx=0, minspany=0, useblit=False, + lineprops=None, rectprops=rectprops, spancoords=spancoords, + button=None, maxdist=10, marker_props=None, + interactive=True, state_modifier_keys=None) + + self.artists = [self.to_draw, self._center_handle.artist, + self._edge_handles.artist] + + def draw_shape(self, extents): + x0, x1, y0, y1 = extents + xmin, xmax = sorted([x0, x1]) + # ymin, ymax = sorted([y0, y1]) + xlim = sorted(self.ax.get_xlim()) + ylim = sorted(self.ax.get_ylim()) + + xmin = max(xlim[0], xmin) + ymin = ylim[0] + xmax = min(xmax, xlim[1]) + ymax = ylim[1] + + self.to_draw.set_x(xmin) + self.to_draw.set_y(ymin) + self.to_draw.set_width(xmax - xmin) + self.to_draw.set_height(ymax - ymin)
+ + +
[docs]def get_likely_edges(energy_scale): + """get likely ionization edges within energy_scale""" + x_sections = eels.get_x_sections() + # print(energy_scale) + energy_origin = energy_scale[0] + energy_window = energy_scale[-1] - energy_origin + selected_edges_unsorted = {} + likely_edges = [] + selected_elements = [] + for element in range(1, 83): + # print(element) + element_z = str(eels.get_z(element)) + + for key in x_sections[element_z]: + if key in all_edges: + onset = x_sections[element_z][key]['onset'] + if onset > energy_origin: + if onset - energy_origin < energy_window: + if element not in selected_edges_unsorted: + selected_edges_unsorted[element] = {} + # print(element, x_sections[element]['name'], key, x_sections[element][key]['onset']) + # text = f"\n {x_sections[element_z]['name']:2s}-{key}: " \ + # f"{x_sections[element_z][key]['onset']:8.1f} eV " + # print(text) + + selected_edges_unsorted[element][key] = {} + selected_edges_unsorted[element][key]['onset'] = x_sections[element_z][key]['onset'] + + if key in major_edges: + selected_edges_unsorted[element][key]['intensity'] = 'major' + selected_elements.append(x_sections[element_z]['name']) + else: + selected_edges_unsorted[element][key]['intensity'] = 'minor' + + if element in selected_edges_unsorted: + for key in selected_edges_unsorted[element]: + if selected_edges_unsorted[element][key]['intensity'] == 'major': + likely_edges.append(x_sections[str(element)]['name']) # = {'z':element, 'symmetry': key} + + return likely_edges
+ + +
[docs]class SpectrumPlot(sidpy.viz.dataset_viz.CurveVisualizer): + def __init__(self, dset, spectrum_number=0, figure=None, **kwargs): + with plt.ioff(): + self.figure = plt.figure() + self.figure.canvas.toolbar_position = 'right' + self.figure.canvas.toolbar_visible = True + + super().__init__(dset, spectrum_number=spectrum_number, figure=self.figure, **kwargs) + + self.start_cursor = ipywidgets.FloatText(value=0, description='Start:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + self.end_cursor = ipywidgets.FloatText(value=0, description='End:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + self.panel = ipywidgets.VBox([ipywidgets.HBox([ipywidgets.Label('',layout=ipywidgets.Layout(width='100px')), ipywidgets.Label('Cursor:'), + self.start_cursor,ipywidgets.Label('eV'), + self.end_cursor, ipywidgets.Label('eV')]), + self.figure.canvas]) + + self.selector = matplotlib.widgets.SpanSelector(self.axis, self.line_select_callback, + direction="horizontal", + interactive=True, + props=dict(facecolor='blue', alpha=0.2)) + + def line_select_callback(self, x_min, x_max): + self.start_cursor.value = np.round(x_min, 3) + self.end_cursor.value = np.round(x_max, 3) + self.start_channel = np.searchsorted(self.dset.energy_loss, self.start_cursor.value) + self.end_channel = np.searchsorted(self.dset.energy_loss, self.end_cursor.value) + + def plot(self, scale=True, additional_spectra=None): + + self.energy_scale = self.dset.energy_loss.values + x_limit = self.axis.get_xlim() + y_limit = np.array(self.axis.get_ylim()) + + self.axis.clear() + + self.axis.plot(self.energy_scale, self.dset*self.y_scale, label='spectrum') + + if additional_spectra is not None: + if isinstance(additional_spectra, dict): + for key, spectrum in additional_spectra.items(): + self.axis.plot(self.energy_scale, spectrum*self.y_scale, label=key) + + self.axis.set_xlabel(self.dset.labels[0]) + self.axis.set_ylabel(self.dset.data_descriptor) + self.axis.ticklabel_format(style='sci', scilimits=(-2, 3)) + if scale: + self.axis.set_ylim(np.array(y_limit)*self.change_y_scale) + + self.change_y_scale = 1.0 + if self.y_scale != 1.: + self.axis.set_ylabel('scattering probability (ppm/eV)') + self.selector = matplotlib.widgets.SpanSelector(self.axis, self.line_select_callback, + direction="horizontal", + interactive=True, + props=dict(facecolor='blue', alpha=0.2)) + self.axis.legend() + self.figure.canvas.draw_idle()
+ + +
[docs]class SIPlot(sidpy.viz.dataset_viz.SpectralImageVisualizer): + def __init__(self, dset, figure=None, horizontal=True, **kwargs): + if figure is None: + with plt.ioff(): + self.figure = plt.figure() + else: + self.figure = figure + self.figure.canvas.toolbar_position = 'right' + self.figure.canvas.toolbar_visible = True + + super().__init__(dset, figure= self.figure, horizontal=horizontal, **kwargs) + + self.start_cursor = ipywidgets.FloatText(value=0, description='Start:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + self.end_cursor = ipywidgets.FloatText(value=0, description='End:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + self.panel = ipywidgets.VBox([ipywidgets.HBox([ipywidgets.Label('',layout=ipywidgets.Layout(width='100px')), ipywidgets.Label('Cursor:'), + self.start_cursor,ipywidgets.Label('eV'), + self.end_cursor, ipywidgets.Label('eV')]), + self.figure.canvas]) + self.axis = self.axes[-1] + self.selector = matplotlib.widgets.SpanSelector(self.axis, self.line_select_callback, + direction="horizontal", + interactive=True, + props=dict(facecolor='blue', alpha=0.2)) + + def line_select_callback(self, x_min, x_max): + self.start_cursor.value = np.round(x_min, 3) + self.end_cursor.value = np.round(x_max, 3) + self.start_channel = np.searchsorted(self.dset.energy_loss, self.start_cursor.value) + self.end_channel = np.searchsorted(self.dset.energy_loss, self.end_cursor.value) + + def plot(self, scale=True, additional_spectra=None): + + xlim = self.axes[1].get_xlim() + ylim = self.axes[1].get_ylim() + self.axes[1].clear() + self.get_spectrum() + if len(self.energy_scale)!=self.spectrum.shape[0]: + self.spectrum = self.spectrum.T + self.axes[1].plot(self.energy_scale, self.spectrum.compute(), label='experiment') + if additional_spectra is not None: + if isinstance(additional_spectra, dict): + for key, spectrum in additional_spectra.items(): + self.axes[1].plot(self.energy_scale, spectrum, label=key) + + if self.set_title: + self.axes[1].set_title('spectrum {}, {}'.format(self.x, self.y)) + self.fig.tight_layout() + self.selector = matplotlib.widgets.SpanSelector(self.axes[1], self.line_select_callback, + direction="horizontal", + interactive=True, + props=dict(facecolor='blue', alpha=0.2)) + + self.axes[1].set_xlim(xlim) + self.axes[1].set_ylim(ylim) + self.axes[1].set_xlabel(self.xlabel) + self.axes[1].set_ylabel(self.ylabel) + + self.fig.canvas.draw_idle()
+ + + + +
[docs]def get_periodic_table_widget(energy_scale=None): + + if energy_scale is None: + energy_scale = [100., 150., 200.] + + likely_edges = get_likely_edges(energy_scale) + + pt_info = get_periodic_table_info() + table = ipywidgets.GridspecLayout(10, 18,width= '60%', grid_gap="0px") + for symbol, parameter in pt_info.items(): + #print(parameter['PT_row'], parameter['PT_col']) + if parameter['PT_row'] > 7: + color = 'warning' + elif '*' in symbol: + color = 'warning' + else: + if symbol in likely_edges: + color = 'primary' + else: + color = 'info' + table[parameter['PT_row'], parameter['PT_col']] = ipywidgets.ToggleButton(description=symbol, + value=False, + button_style=color, + layout=ipywidgets.Layout(width='auto'), + style={"button_width": "30px"}) + return table
+ + +
[docs]class PeriodicTableWidget(object): + """ ipywidget to get a selection of elements. + + Elements that are not having a valid cross-sections are disabled. + + Parameters + ---------- + initial_elements: list of str + the elements that are already selected + energy_scale: list or numpy array + energy-scale of spectrum/spectra to determine likely edges + + Returns + ------- + list of strings: elements. + use get_output() function + """ + + def __init__(self, initial_elements=None, energy_scale=None): + + if initial_elements is None: + initial_elements = [' '] + self.elements_selected = initial_elements + if energy_scale is None: + energy_scale = [100., 150., 200.] + self._output = [] + self.energy_scale = np.array(energy_scale) + self.pt_info = get_periodic_table_info() + + self.periodic_table = get_periodic_table_widget(energy_scale) + self.update() + + def get_output(self): + self.elements_selected = [] + for symbol, parameter in self.pt_info.items(): + if self.periodic_table[parameter['PT_row'], parameter['PT_col']].value == True: # [parameter['PT_row'], parameter['PT_col']] + self.elements_selected.append(self.periodic_table[parameter['PT_row'], parameter['PT_col']].description) + return self.elements_selected + + def update(self): + for symbol, parameter in self.pt_info.items(): + if str(self.periodic_table[parameter['PT_row'], parameter['PT_col']].description) in list(self.elements_selected): + self.periodic_table[parameter['PT_row'], parameter['PT_col']].value = True
+ + + + +
[docs]def get_periodic_table_info(): + """Info for periodic table dialog""" + pt_info = \ + {'H': {'PT_row': 0, 'PT_col': 0, 'Z': 0}, + 'He': {'PT_row': 0, 'PT_col': 17, 'Z': 2}, 'Li': {'PT_row': 1, 'PT_col': 0, 'Z': 3}, + 'Be': {'PT_row': 1, 'PT_col': 1, 'Z': 4}, 'B': {'PT_row': 1, 'PT_col': 12, 'Z': 5}, + 'C': {'PT_row': 1, 'PT_col': 13, 'Z': 6}, 'N': {'PT_row': 1, 'PT_col': 14, 'Z': 7}, + 'O': {'PT_row': 1, 'PT_col': 15, 'Z': 8}, 'F': {'PT_row': 1, 'PT_col': 16, 'Z': 9}, + 'Ne': {'PT_row': 1, 'PT_col': 17, 'Z': 10}, 'Na': {'PT_row': 2, 'PT_col': 0, 'Z': 11}, + 'Mg': {'PT_row': 2, 'PT_col': 1, 'Z': 12}, 'Al': {'PT_row': 2, 'PT_col': 12, 'Z': 13}, + 'Si': {'PT_row': 2, 'PT_col': 13, 'Z': 14}, 'P': {'PT_row': 2, 'PT_col': 14, 'Z': 15}, + 'S': {'PT_row': 2, 'PT_col': 15, 'Z': 16}, 'Cl': {'PT_row': 2, 'PT_col': 16, 'Z': 17}, + 'Ar': {'PT_row': 2, 'PT_col': 17, 'Z': 18}, 'K': {'PT_row': 3, 'PT_col': 0, 'Z': 19}, + 'Ca': {'PT_row': 3, 'PT_col': 1, 'Z': 20}, 'Sc': {'PT_row': 3, 'PT_col': 2, 'Z': 21}, + 'Ti': {'PT_row': 3, 'PT_col': 3, 'Z': 22}, 'V ': {'PT_row': 3, 'PT_col': 4, 'Z': 23}, + 'Cr': {'PT_row': 3, 'PT_col': 5, 'Z': 24}, 'Mn': {'PT_row': 3, 'PT_col': 6, 'Z': 25}, + 'Fe': {'PT_row': 3, 'PT_col': 7, 'Z': 26}, 'Co': {'PT_row': 3, 'PT_col': 8, 'Z': 27}, + 'Ni': {'PT_row': 3, 'PT_col': 9, 'Z': 28}, 'Cu': {'PT_row': 3, 'PT_col': 10, 'Z': 29}, + 'Zn': {'PT_row': 3, 'PT_col': 11, 'Z': 30}, 'Ga': {'PT_row': 3, 'PT_col': 12, 'Z': 31}, + 'Ge': {'PT_row': 3, 'PT_col': 13, 'Z': 32}, 'As': {'PT_row': 3, 'PT_col': 14, 'Z': 33}, + 'Se': {'PT_row': 3, 'PT_col': 15, 'Z': 34}, 'Br': {'PT_row': 3, 'PT_col': 16, 'Z': 35}, + 'Kr': {'PT_row': 3, 'PT_col': 17, 'Z': 36}, 'Rb': {'PT_row': 4, 'PT_col': 0, 'Z': 37}, + 'Sr': {'PT_row': 4, 'PT_col': 1, 'Z': 38}, 'Y': {'PT_row': 4, 'PT_col': 2, 'Z': 39}, + 'Zr': {'PT_row': 4, 'PT_col': 3, 'Z': 40}, 'Nb': {'PT_row': 4, 'PT_col': 4, 'Z': 41}, + 'Mo': {'PT_row': 4, 'PT_col': 5, 'Z': 42}, 'Tc': {'PT_row': 4, 'PT_col': 6, 'Z': 43}, + 'Ru': {'PT_row': 4, 'PT_col': 7, 'Z': 44}, 'Rh': {'PT_row': 4, 'PT_col': 8, 'Z': 45}, + 'Pd': {'PT_row': 4, 'PT_col': 9, 'Z': 46}, 'Ag': {'PT_row': 4, 'PT_col': 10, 'Z': 47}, + 'Cd': {'PT_row': 4, 'PT_col': 11, 'Z': 48}, 'In': {'PT_row': 4, 'PT_col': 12, 'Z': 49}, + 'Sn': {'PT_row': 4, 'PT_col': 13, 'Z': 50}, 'Sb': {'PT_row': 4, 'PT_col': 14, 'Z': 51}, + 'Te': {'PT_row': 4, 'PT_col': 15, 'Z': 52}, 'I': {'PT_row': 4, 'PT_col': 16, 'Z': 53}, + 'Xe': {'PT_row': 4, 'PT_col': 17, 'Z': 54}, 'Cs': {'PT_row': 5, 'PT_col': 0, 'Z': 55}, + 'Ba': {'PT_row': 5, 'PT_col': 1, 'Z': 56}, 'Hf': {'PT_row': 5, 'PT_col': 3, 'Z': 72}, + 'Ta': {'PT_row': 5, 'PT_col': 4, 'Z': 73}, 'W': {'PT_row': 5, 'PT_col': 5, 'Z': 74}, + 'Re': {'PT_row': 5, 'PT_col': 6, 'Z': 75}, 'Os': {'PT_row': 5, 'PT_col': 7, 'Z': 76}, + 'Ir': {'PT_row': 5, 'PT_col': 8, 'Z': 77}, 'Pt': {'PT_row': 5, 'PT_col': 9, 'Z': 78}, + 'Au': {'PT_row': 5, 'PT_col': 10, 'Z': 79}, 'Hg': {'PT_row': 5, 'PT_col': 11, 'Z': 80}, + 'Pb': {'PT_row': 5, 'PT_col': 13, 'Z': 82}, 'Bi': {'PT_row': 5, 'PT_col': 14, 'Z': 0}, + 'Po': {'PT_row': 5, 'PT_col': 15, 'Z': 0}, 'At': {'PT_row': 5, 'PT_col': 16, 'Z': 0}, + 'Rn': {'PT_row': 5, 'PT_col': 17, 'Z': 0}, 'Fr': {'PT_row': 6, 'PT_col': 0, 'Z': 0}, + 'Ra': {'PT_row': 6, 'PT_col': 1, 'Z': 0}, 'Rf': {'PT_row': 6, 'PT_col': 3, 'Z': 0}, + 'Db': {'PT_row': 6, 'PT_col': 4, 'Z': 0}, 'Sg': {'PT_row': 6, 'PT_col': 5, 'Z': 0}, + 'Bh': {'PT_row': 6, 'PT_col': 6, 'Z': 0}, 'Hs': {'PT_row': 6, 'PT_col': 7, 'Z': 0}, + 'Mt': {'PT_row': 6, 'PT_col': 8, 'Z': 0}, 'Ds': {'PT_row': 6, 'PT_col': 9, 'Z': 0}, + 'Rg': {'PT_row': 6, 'PT_col': 10, 'Z': 0}, 'La': {'PT_row': 8, 'PT_col': 3, 'Z': 57}, + 'Ce': {'PT_row': 8, 'PT_col': 4, 'Z': 58}, 'Pr': {'PT_row': 8, 'PT_col': 5, 'Z': 59}, + 'Nd': {'PT_row': 8, 'PT_col': 6, 'Z': 60}, 'Pm': {'PT_row': 8, 'PT_col': 7, 'Z': 61}, + 'Sm': {'PT_row': 8, 'PT_col': 8, 'Z': 62}, 'Eu': {'PT_row': 8, 'PT_col': 9, 'Z': 63}, + 'Gd': {'PT_row': 8, 'PT_col': 10, 'Z': 64}, 'Tb': {'PT_row': 8, 'PT_col': 11, 'Z': 65}, + 'Dy': {'PT_row': 8, 'PT_col': 12, 'Z': 66}, 'Ho': {'PT_row': 8, 'PT_col': 13, 'Z': 67}, + 'Er': {'PT_row': 8, 'PT_col': 14, 'Z': 68}, 'Tm': {'PT_row': 8, 'PT_col': 15, 'Z': 69}, + 'Yb': {'PT_row': 8, 'PT_col': 16, 'Z': 70}, 'Lu': {'PT_row': 8, 'PT_col': 17, 'Z': 71}, + 'Ac': {'PT_row': 9, 'PT_col': 3, 'Z': 0}, 'Th': {'PT_row': 9, 'PT_col': 4, 'Z': 0}, + 'Pa': {'PT_row': 9, 'PT_col': 5, 'Z': 0}, 'U': {'PT_row': 9, 'PT_col': 6, 'Z': 0}, + 'Np': {'PT_row': 9, 'PT_col': 7, 'Z': 0}, 'Pu': {'PT_row': 9, 'PT_col': 8, 'Z': 0}, + 'Am': {'PT_row': 9, 'PT_col': 9, 'Z': 0}, 'Cm': {'PT_row': 9, 'PT_col': 10, 'Z': 0}, + 'Bk': {'PT_row': 9, 'PT_col': 11, 'Z': 0}, 'Cf': {'PT_row': 9, 'PT_col': 12, 'Z': 0}, + 'Es': {'PT_row': 9, 'PT_col': 13, 'Z': 0}, 'Fm': {'PT_row': 9, 'PT_col': 14, 'Z': 0}, + 'Md': {'PT_row': 9, 'PT_col': 15, 'Z': 0}, 'No': {'PT_row': 9, 'PT_col': 16, 'Z': 0}, + 'Lr': {'PT_row': 9, 'PT_col': 17, 'Z': 0}, + '*': {'PT_row': 5, 'PT_col': 2, 'PT_col2': 8, 'PT_row2': 2, 'Z': 0}, + '**': {'PT_row': 6, 'PT_col': 2, 'PT_col2': 9, 'PT_row2': 2, 'Z': 0}} + + return pt_info
+ + +
[docs]class InteractiveSpectrumImage(object): + """Interactive spectrum imaging plot + + Attributes: + ----------- + dictionary with a minimum of the following keys: + ['image']: displayed image + ['data']: data cube + ['intensity_scale_ppm']: intensity scale + ['ylabel']: intensity label + ['spectra'] dictionary which contains dictionaries for each spectrum style ['1-2']: + ['spectrum'] = tags['cube'][y,x,:] + ['spectra'][f'{x}-{y}']['energy_scale'] = tags['energy_scale'] + ['intensity_scale'] = 1/tags['cube'][y,x,:].sum()*1e6 + + Please note the possibility to load any image for the selection of the spectrum + Also there is the possibility to display the survey image. + + For analysis, we have the following options: + 'fix_energy': set zero-loss peak maximum to zero !! Low loss spectra only!! + 'fit_zero_loss': fit zero-loss peak with model function !! Low loss spectra only!! + 'fit_low_loss': fit low-loss spectrum with model peaks !! Low loss spectra only!! + + + 'fit_composition': fit core-loss spectrum with background and cross-sections!! Core loss spectra only!! + 'fit_ELNES': fit core-loss edge with model peaks !! Core loss spectra only!! + """ + + def __init__(self, data_source, horizontal=True): + + box_layout = ipywidgets.Layout(display='flex', + flex_flow='row', + align_items='stretch', + width='100%') + + words = ['fix_energy', 'fit_zero_loss', 'fit_low_loss', 'fit_composition', 'fit_ELNES'] + + self.buttons = [ipywidgets.ToggleButton(value=False, description=word, disabled=False) for word in words] + box = ipywidgets.Box(children=self.buttons, layout=box_layout) + display(box) + + # MAKE Dictionary + + if isinstance(data_source, dict): + self.tags = data_source + elif isinstance(data_source, h5py.Group): + self.tags = self.set_tags(data_source) + else: + print('Data source must be a dictionary or channel') + return + + # Button(description='edge_quantification') + for button in self.buttons: + button.observe(self.on_button_clicked, 'value') # on_click(self.on_button_clicked) + + self.figure = plt.figure() + self.horizontal = horizontal + self.x = 0 + self.y = 0 + + self.extent = [0, self.tags['cube'].shape[1], self.tags['cube'].shape[0], 0] + self.rectangle = [0, self.tags['cube'].shape[1], 0, self.tags['cube'].shape[0]] + self.scaleX = 1.0 + self.scaleY = 1.0 + self.analysis = [] + self.plot_legend = False + if 'ylabel' not in self.tags: + self.tags['ylabel'] = 'intensity [a.u.]' + self.SI = False + + if horizontal: + self.ax1 = plt.subplot(1, 2, 1) + self.ax2 = plt.subplot(1, 2, 2) + else: + self.ax1 = plt.subplot(2, 1, 1) + self.ax2 = plt.subplot(2, 1, 2) + + self.cube = self.tags['cube'] + self.image = self.tags['cube'].sum(axis=2) + + self.ax1.imshow(self.image, extent=self.extent) + if horizontal: + self.ax1.set_xlabel('distance [pixels]') + else: + self.ax1.set_ylabel('distance [pixels]') + self.ax1.set_aspect('equal') + + self.rect = patches.Rectangle((0, 0), 1, 1, linewidth=1, edgecolor='r', facecolor='red', alpha=0.2) + self.ax1.add_patch(self.rect) + self.intensity_scale = self.tags['spectra'][f'{self.x}-{self.y}']['intensity_scale'] + self.spectrum = self.tags['spectra'][f'{self.x}-{self.y}']['spectrum'] * self.intensity_scale + self.energy_scale = self.tags['spectra'][f'{self.x}-{self.y}']['energy_scale'] + + self.ax2.plot(self.energy_scale, self.spectrum) + self.ax2.set_title(f' spectrum {self.x},{self.y} ') + self.ax2.set_xlabel('energy loss [eV]') + self.ax2.set_ylabel(self.tags['ylabel']) + self.cid = self.figure.canvas.mpl_connect('button_press_event', self.onclick) + + plt.tight_layout() + + def on_button_clicked(self, b): + # print(b['owner'].description) + selection = b['owner'].description + if b['new']: + if selection == 'fit_composition': + if 'region_tags' in self.tags and 'edges_present' in self.tags \ + and 'acceleration_voltage' in self.tags \ + and 'collection_angle' in self.tags: + pass + else: + self.buttons[3].value = False + return + elif selection in ['fix_energy', 'fit_zero_loss']: + if self.energy_scale[0] > 0: + button_index = ['fix_energy', 'fit_zero_loss'].index(selection) + self.buttons[button_index].value = False + return + self.analysis.append(selection) + self.update() + else: + + if selection in self.analysis: + self.analysis.remove(selection) + + def do_all(self, selection=None, verbose=True): + x = self.x + y = self.y + if selection is None: + selection = self.analysis + for self.x in range(self.cube.shape[1]): + if verbose: + print(f' row: {self.x}') + for self.y in range(self.cube.shape[0]): + + if 'fit_zero_loss' in selection: + title = self.fit_zero_loss(plot_this=False) + + elif 'fix_energy' in selection: + self.ax2.set_title('bn') + title = self.fix_energy() + + elif 'fit_composition' in selection: + title = self.fit_quantification(plot_this=False) + + self.x = x + self.y = y + + def onclick(self, event): + x = int(event.xdata) + y = int(event.ydata) + + # print(x,y) + if self.rectangle[0] <= x < self.rectangle[0] + self.rectangle[1]: + if self.rectangle[2] <= y < self.rectangle[2] + self.rectangle[3]: + self.x = int((x - self.rectangle[0]) / self.rectangle[1] * self.cube.shape[1]) + self.y = int((y - self.rectangle[2]) / self.rectangle[3] * self.cube.shape[0]) + else: + return + else: + return + + if event.inaxes in [self.ax1]: + x = (self.x * self.rectangle[1] / self.cube.shape[1] + self.rectangle[0]) + y = (self.y * self.rectangle[3] / self.cube.shape[0] + self.rectangle[2]) + + self.rect.set_xy([x, y]) + self.update() + + def update(self): + xlim = self.ax2.get_xlim() + ylim = self.ax2.get_ylim() + self.ax2.clear() + self.intensity_scale = self.tags['spectra'][f'{self.x}-{self.y}']['intensity_scale'] + self.spectrum = self.tags['spectra'][f'{self.x}-{self.y}']['spectrum'] * self.intensity_scale + self.energy_scale = self.tags['spectra'][f'{self.x}-{self.y}']['energy_scale'] + + if 'fit_zero_loss' in self.analysis: + title = self.fit_zero_loss() + self.ax2.set_title(title) + elif 'fix_energy' in self.analysis: + self.ax2.set_title('bn') + title = self.fix_energy() + self.ax2.set_title(title) + + elif 'fit_composition' in self.analysis: + title = self.fit_quantification() + self.ax2.set_title(title) + + else: + self.ax2.set_title(f' spectrum {self.x},{self.y} ') + self.ax2.plot(self.energy_scale, self.spectrum, color='#1f77b4', label='experiment') + + if self.plot_legend: + self.ax2.legend(shadow=True) + self.ax2.set_xlim(xlim) + self.ax2.set_ylim(ylim) + self.ax2.set_xlabel('energy loss [eV]') + self.ax2.set_ylabel(self.tags['ylabel']) + self.ax2.set_xlim(xlim) + + # self.ax2.draw() + + def set_tags(self, channel): + # TODO: change to sidpy dataset tags = ft.h5_get_dictionary(channel) + tags = {} + if tags['data_type'] == 'spectrum_image': + tags['image'] = tags['data'] + tags['data'] = tags['cube'][0, 0, :] + if 'intensity_scale_ppm' not in channel: + channel['intensity_scale_ppm'] = 1 + + tags['ylabel'] = 'intensity [a.u.]' + tags['spectra'] = {} + for x in range(tags['spatial_size_y']): + for y in range(tags['spatial_size_x']): + tags['spectra'][f'{x}-{y}'] = {} + tags['spectra'][f'{x}-{y}']['spectrum'] = tags['cube'][y, x, :] + tags['spectra'][f'{x}-{y}']['energy_scale'] = tags['energy_scale'] + tags['spectra'][f'{x}-{y}']['intensity_scale'] = 1 / tags['cube'][y, x, :].sum() * 1e6 + tags['ylabel'] = 'inel. scat. int. [ppm]' + + return tags + + def fix_energy(self): + + energy_scale = self.tags['spectra'][f'{self.x}-{self.y}']['energy_scale'] + spectrum = self.tags['spectra'][f'{self.x}-{self.y}']['spectrum'] * self.intensity_scale + fwhm, delta_e = eels.fix_energy_scale(spectrum, energy_scale) + self.tags['spectra'][f'{self.x}-{self.y}']['delta_e'] = delta_e + self.tags['spectra'][f'{self.x}-{self.y}']['fwhm'] = fwhm + self.energy_scale = energy_scale - delta_e + title = f'spectrum {self.x},{self.y} fwhm: {fwhm:.2f}, dE: {delta_e:.3f}' + return title + + def fit_zero_loss(self, plot_this=True): + + energy_scale = self.tags['spectra'][f'{self.x}-{self.y}']['energy_scale'] + spectrum = self.tags['spectra'][f'{self.x}-{self.y}']['spectrum'] * self.intensity_scale + if 'zero_loss_fit_width' not in self.tags: + self.tags['zero_loss_fit_width'] = .5 + if self.tags['zero_loss_fit_width'] / (energy_scale[1] - energy_scale[0]) < 6: + self.tags['zero_loss_fit_width'] = (energy_scale[1] - energy_scale[0]) * 6 + fwhm, delta_e = eels.fix_energy_scale(spectrum, energy_scale) + energy_scale = energy_scale - delta_e + z_oss, p_zl = eels.resolution_function(energy_scale, spectrum, self.tags['zero_loss_fit_width']) + fwhm2, delta_e2 = eels.fix_energy_scale(z_oss, energy_scale) + + self.tags['spectra'][f'{self.x}-{self.y}']['resolution_function'] = z_oss + self.tags['spectra'][f'{self.x}-{self.y}']['p_zl'] = p_zl + self.tags['spectra'][f'{self.x}-{self.y}']['delta_e'] = delta_e + self.tags['spectra'][f'{self.x}-{self.y}']['fwhm_resolution'] = fwhm2 + self.tags['spectra'][f'{self.x}-{self.y}']['fwhm'] = fwhm + + if plot_this: + self.ax2.plot(energy_scale, z_oss, label='resolution function', color='black') + self.ax2.plot(energy_scale, self.spectrum - z_oss, label='difference', color='orange') + self.ax2.axhline(linewidth=0.5, color='black') + self.energy_scale = energy_scale + title = f'spectrum {self.x},{self.y} fwhm: {fwhm:.2f}' # ', dE: {delta_e2:.5e}' + return title + + def fit_quantification(self, plot_this=True): + energy_scale = self.tags['spectra'][f'{self.x}-{self.y}']['energy_scale'] + spectrum = self.tags['spectra'][f'{self.x}-{self.y}']['spectrum'] * self.intensity_scale + edges = eels.make_edges(self.tags['edges_present'], energy_scale, self.tags['acceleration_voltage'], + self.tags['collection_angle']) + edges = eels.fit_edges(spectrum, self.tags['spectra'][f'{self.x}-{self.y}']['energy_scale'], + self.tags['region_tags'], edges) + self.tags['spectra'][f'{self.x}-{self.y}']['edges'] = edges.copy() + if plot_this: + self.ax2.plot(energy_scale, edges['model']['spectrum'], label='model') + self.ax2.plot(energy_scale, self.spectrum - edges['model']['spectrum'], label='difference') + self.ax2.axhline(linewidth=0.5, color='black') + else: + self.tags['spectra'][f'{self.x}-{self.y}']['do_all'] = 'done' + title = f'spectrum {self.x},{self.y} ' + + for key in edges: + if key.isdigit(): + title = title + f"{edges[key]['element']}: {edges[key]['areal_density']:.2e}; " + + return title + + def set_legend(self, set_legend): + self.plot_legend = set_legend + + def get_xy(self): + return [self.x, self.y] + + def get_current_spectrum(self): + return self.cube[self.y, self.x, :] + + def set_z_contrast_image(self, z_channel=None): + if z_channel is not None: + self.tags['Z_contrast_channel'] = z_channel + if 'Z_contrast_channel' not in self.tags: + print('add Z contrast channel group to dictionary first!') + return + + z_tags = {} # TODO change to sidpy dataset ft.h5_get_dictionary(z_channel) + extent = [self.rectangle[0], self.rectangle[0] + self.rectangle[1], + self.rectangle[2] + self.rectangle[3], self.rectangle[2]] + self.ax1.imshow(z_tags['data'], extent=extent, cmap='gray') + + def overlay_z_contrast_image(self, z_channel=None): + + if self.SI: + if z_channel is not None: + self.tags['Z_contrast_channel'] = z_channel + if 'Z_contrast_channel' not in self.tags: + print('add survey channel group to dictionary first!') + return + + z_tags = {} # TODO: change to sidpy ft.h5_get_dictionary(self.tags['Z_contrast_channel']) + + xlim = self.ax1.get_xlim() + ylim = self.ax1.get_ylim() + extent = [self.rectangle[0], self.rectangle[0] + self.rectangle[1], + self.rectangle[2] + self.rectangle[3], self.rectangle[2]] + self.ax1.imshow(z_tags['data'], extent=extent, cmap='viridis', alpha=0.5) + self.ax1.set_ylim(ylim) + self.ax1.set_xlim(xlim) + + def overlay_data(self, data=None): + + if self.SI: + if data is None: + data = self.cube.sum(axis=2) + + xlim = self.ax1.get_xlim() + ylim = self.ax1.get_ylim() + extent = [self.rectangle[0], self.rectangle[0] + self.rectangle[1], + self.rectangle[2] + self.rectangle[3], self.rectangle[2]] + self.ax1.imshow(data, extent=extent, alpha=0.7, cmap='viridis') + self.ax1.set_ylim(ylim) + self.ax1.set_xlim(xlim) + + def set_survey_image(self, si_channel=None): + + if si_channel is not None: + self.tags['survey_channel'] = si_channel + if 'survey_channel' not in self.tags: + print('add survey channel group to dictionary first!') + return + si_channel = self.tags['survey_channel'] + si_tags = {} # TODO: change to sidpy ft.h5_get_dictionary(si_channel) + tags2 = dict(si_channel.attrs) + + self.ax1.set_aspect('equal') + self.scaleX = si_channel['spatial_scale_x'][()] + self.scaleY = si_channel['spatial_scale_y'][()] + + self.ax1.imshow(si_tags['data'], extent=si_tags['extent'], cmap='gray') + if self.horizontal: + self.ax1.set_xlabel('distance [nm]') + else: + self.ax1.set_ylabel('distance [nm]') + + annotation_done = [] + for key in tags2: + if 'annotations' in key: + annotation_number = key[12] + if annotation_number not in annotation_done: + annotation_done.append(annotation_number) + + if tags2['annotations_' + annotation_number + '_type'] == 'text': + x = tags2['annotations_' + annotation_number + '_x'] + y = tags2['annotations_' + annotation_number + '_y'] + text = tags2['annotations_' + annotation_number + '_text'] + self.ax1.text(x, y, text, color='r') + + elif tags2['annotations_' + annotation_number + '_type'] == 'circle': + radius = 20 * self.scaleX # tags['annotations'][key]['radius'] + xy = tags2['annotations_' + annotation_number + '_position'] + circle = patches.Circle(xy, radius, color='r', fill=False) + self.ax1.add_artist(circle) + + elif tags2['annotations_' + annotation_number + '_type'] == 'spectrum image': + width = tags2['annotations_' + annotation_number + '_width'] + height = tags2['annotations_' + annotation_number + '_height'] + position = tags2['annotations_' + annotation_number + '_position'] + rectangle = patches.Rectangle(position, width, height, color='r', fill=False) + self.rectangle = [position[0], width, position[1], height] + self.ax1.add_artist(rectangle) + self.ax1.text(position[0], position[1], 'Spectrum Image', color='r') + self.rect.set_width(width / self.cube.shape[1]) + self.rect.set_height(height / self.cube.shape[0]) + self.SI = True
+ + +
[docs]class ElementalEdges(object): + """ Adds ionization edges of element z to plot with axis ax + + There is an optional parameter maximum_chemical_shift which allows to change + the energy range in which the edges are searched. + + available functions: + - update(): updates the drawing of ionization edges + - set_edge(Z) : changes atomic number and updates everything accordingly + - disconnect: makes everything invisible and stops drawing + - reconnect: undo of disconnect + + usage: + >> fig, ax = plt.subplots() + >> ax.plot(energy_scale, spectrum) + >> Z= 42 + >> cursor = ElementalEdges(ax, Z) + + + see Chapter4 'CH4-Working_with_X-Sections' notebook + """ + + def __init__(self, ax, z): + self.ax = ax + self.labels = None + self.lines = None + self.Z = eels.get_z(z) + self.color = 'black' + self.x_sections = eels.get_x_sections() + self.cid = ax.figure.canvas.mpl_connect('draw_event', self.onresize) + # self.update() is not necessary because of a drawing event is issued + + def set_edge(self, z): + self.Z = eels.get_z(z) + if self.cid is None: + self.cid = self.ax.figure.canvas.mpl_connect('draw_event', self.onresize) + self.update() + + def onresize(self, event): + self.update() + + def update(self): + if self.labels is not None: + for label in self.labels: + label.remove() + if self.lines is not None: + for line in self.lines: + line.remove() + self.labels = [] + self.lines = [] + x_min, x_max = self.ax.get_xlim() + y_min, y_max = self.ax.get_ylim() + + element = str(self.Z) + x_sections = self.x_sections + for key in all_edges: + if key in x_sections[element] and 'onset' in x_sections[element][key]: + x = x_sections[element][key]['onset'] + if x_min < x < x_max: + if key in first_close_edges: + label2 = self.ax.text(x, y_max, f"{x_sections[element]['name']}-{key}", + verticalalignment='top', rotation=0, color=self.color) + else: + label2 = self.ax.text(x, y_max, f"\n{x_sections[element]['name']}-{key}", + verticalalignment='top', color=self.color) + line2 = self.ax.axvline(x, ymin=0, ymax=1, color=self.color) + + self.labels.append(label2) + self.lines.append(line2) + + def reconnect(self): + self.cid = self.ax.figure.canvas.mpl_connect('draw_event', self.onresize) + self.update() + + def disconnect(self): + if self.labels is not None: + for label in self.labels: + label.remove() + if self.lines is not None: + for line in self.lines: + line.remove() + self.labels = None + self.lines = None + self.ax.figure.canvas.mpl_disconnect(self.cid)
+ + +
[docs]class EdgesAtCursor(object): + """ + Adds a Cursor to a plot, which plots all major (possible) ionization edges at + the cursor location if left (right) mouse button is clicked. + + Attributes + ---------- + ax: matplotlib axis + x: numpy array + energy_scale of spectrum + y: numpy array + intensities of spectrum + maximal_chemical_shift: float + optional parameter maximum_chemical_shift which allows to change the energy range in which the edges + are searched. + + Example + ------- + fig, ax = plt.subplots() + ax.plot(energy_scale, spectrum) + cursor = EdgesAtCursor(ax, energy_scale, spectrum) + + see Chapter4 'CH4-Working_with_X-Sections' notebook + + """ + + def __init__(self, ax, x, y, maximal_chemical_shift=5): + self.ax = ax + self.ly = ax.axvline(x[0], color='k', alpha=0.2) # the vert line + self.marker, = ax.plot(x[0], y[0], marker="o", color="crimson", zorder=3) + self.x = x + self.y = y + self.txt = ax.text(0.7, 0.9, '', verticalalignment='bottom') + self.select = 0 + self.label = None + self.line = None + self.cid = ax.figure.canvas.mpl_connect('button_press_event', self.click) + self.mouse_cid = ax.figure.canvas.mpl_connect('motion_notify_event', self.mouse_move) + self.maximal_chemical_shift = maximal_chemical_shift + + def click(self, event): + + # print('click', event) + if not event.inaxes: + return + x, y = event.xdata, event.ydata + + index = np.searchsorted(self.x, [x])[0] + x = self.x[index] + y = self.y[index] + self.select = x + + y_min, y_max = self.ax.get_ylim() + + if self.label is not None: + self.label.remove() + self.line.remove() + if event.button == 1: + self.label = self.ax.text(x, y_max, eels.find_major_edges(event.xdata, self.maximal_chemical_shift), + verticalalignment='top') + self.line, = self.ax.plot([x, x], [y_min, y_max], color='black') + if event.button == 3: + self.line, = self.ax.plot([x, x], [y_min, y_max], color='black') + self.label = self.ax.text(x, y_max, eels.find_all_edges(event.xdata, self.maximal_chemical_shift), + verticalalignment='top') + self.ax.set_ylim(y_min, y_max) + + def mouse_move(self, event): + if not event.inaxes: + return + + x, y = event.xdata, event.ydata + index = np.searchsorted(self.x, [x])[0] + x = self.x[index] + y = self.y[index] + self.select = x + self.ly.set_xdata(x) + self.marker.set_data([x], [y]) + self.txt.set_text(f'\n x={x:1.2f}, y={y:1.2g}\n') + + # self.ax.text(x, y*2,find_major_edges(x)) + self.txt.set_position((x, y)) + self.ax.figure.canvas.draw_idle() + + def del_edges(self): + if self.label is not None: + self.label.remove() + self.line.remove() + self.label = None + + def disconnect(self): + self.ly.remove() + self.marker.remove() + self.txt.remove() + + self.ax.figure.canvas.mpl_disconnect(self.cid) + self.ax.figure.canvas.mpl_disconnect(self.mouse_cid)
+ + +
[docs]def make_box_layout(): + return ipywidgets.Layout(border='solid 1px black', margin='0px 10px 10px 0px', padding='5px 5px 5px 5px')
+ + +
[docs]class plot_EELS(ipywidgets.HBox): + def __init__(self, dataset): + super().__init__() + output = ipywidgets.Output() + self.dataset = dataset + self.spec_dim = 0 + initial_color = '#FF00DD' + + with output: + self.fig, self.axis = plt.subplots(constrained_layout=True, figsize=(5, 3.5)) + + self.axis.set_title(dataset.title.split('/')[-1]) + self.line, = self.axis.plot(dataset.dim_0.values, dataset, lw=2, label='spectrum') + legend = self.axis.legend(fancybox=True, shadow=True) + + lines = [self.line] + self.line_dictionary = {} # Will map legend lines to original lines. + for legend_line, original_line in zip(legend.get_lines(), lines): + legend_line.set_picker(True) # Enable picking on the legend line. + self.line_dictionary[legend_line] = original_line + self.ax = self.axis + self.fig.canvas.toolbar_position = 'bottom' + self.fig.canvas.mpl_connect('pick_event', self.on_legend_pick) + + # define widgets + int_slider = ipywidgets.IntSlider( + value=1, + min=0, + max=10, + step=1, + description='freq' + ) + self.offset = ipywidgets.Text( + value='0', + width=5, + description='offset', + continuous_update=False + ) + self.dispersion = ipywidgets.Text( + value='0', + width=5, + description='dispersion', + continuous_update=False + ) + + self.exposure = ipywidgets.Text( + value='0', + width=5, + description='exposure', + continuous_update=False + ) + + button_energy_scale = ipywidgets.Button(description='Cursor') + button_elements_at_cursor = ipywidgets.Button(description='Elements Cursor') + button_main_elements = ipywidgets.Button(description='Main Elements') + + controls = ipywidgets.VBox([ + ipywidgets.HBox([self.offset, ipywidgets.Label('eV')]), + ipywidgets.HBox([self.dispersion, ipywidgets.Label('eV/channel')]), + ipywidgets.HBox([self.exposure, ipywidgets.Label('s')]), + button_energy_scale, + ipywidgets.HBox([button_elements_at_cursor, button_main_elements]) + ]) + + controls.layout = make_box_layout() + + out_box = ipywidgets.Box([output]) + output.layout = make_box_layout() + + # observe stuff + int_slider.observe(self.update, 'value') + + self.offset.value = f'{self.dataset.dim_0.values[0]}' + self.offset.observe(self.set_dimension, 'value') + self.offset.value = f'{self.dataset.dim_0.values[0]}' + + self.dispersion.observe(self.set_dimension, 'value') + self.dispersion.value = f'{self.dataset.dim_0.values[1] - self.dataset.dim_0.values[0]}' + self.dispersion.value = '0' + self.exposure.observe(self.update_exposure, 'value') + self.exposure.value = '0' + + # add to children + self.children = [controls, output] + +
[docs] def update(self): + """Draw line in plot""" + self.line.set_ydata(self.dataset) + self.line.set_xdata(self.dataset.dim_0.values) + # self.axis.plot(self.dataset.energy_loss, self.dataset) + self.fig.canvas.draw()
+ + def line_color(self, change): + self.line.set_color(change.new) + + def update_exposure(self): + pass + + def update_ylabel(self, change): + self.ax.set_ylabel(change.new) + + def set_dimension(self, change): + self.spec_dim = ft.get_dimensions_by_type('SPECTRAL', self.dataset) + self.spec_dim = self.spec_dim[0] + old_energy_scale = self.spec_dim[1] + energy_scale = np.arange(len(self.dataset.dim_0.values))*float(self.dispersion.value)+float(self.offset.value) + self.dataset.set_dimension(self.spec_dim[0], sidpy.Dimension(energy_scale, + name=old_energy_scale.name, + dimension_type='SPECTRAL', + units='eV', + quantity='energy loss')) + self.update() + + def on_legend_pick(self, event): + legend_line = event.artist + original_line = self.line_dictionary[legend_line] + visible = not original_line.get_visible() + original_line.set_visible(visible) + legend_line.set_alpha(1.0 if visible else 0.2) + self.fig.canvas.draw()
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/eels_tools.html b/_modules/pyTEMlib/eels_tools.html new file mode 100644 index 00000000..6cc2210e --- /dev/null +++ b/_modules/pyTEMlib/eels_tools.html @@ -0,0 +1,2284 @@ + + + + + + pyTEMlib.eels_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.eels_tools

+"""
+eels_tools
+Model based quantification of electron energy-loss data
+Copyright by Gerd Duscher
+
+The University of Tennessee, Knoxville
+Department of Materials Science & Engineering
+
+Sources:
+   M. Tian et al.
+
+Units:
+    everything is in SI units, except length is given in nm and angles in mrad.
+
+Usage:
+    See the notebooks for examples of these routines
+
+All the input and output is done through a dictionary which is to be found in the meta_data
+attribute of the sidpy.Dataset
+"""
+import numpy as np
+
+import scipy
+from scipy.interpolate import interp1d, splrep  # splev, splint
+from scipy import interpolate
+from scipy.signal import peak_prominences
+from scipy.ndimage import gaussian_filter
+
+from scipy import constants
+import matplotlib.pyplot as plt
+
+import requests
+
+from scipy.optimize import leastsq  # least square fitting routine fo scipy
+
+import pickle  # pkg_resources,
+
+# ## And we use the image tool library of pyTEMlib
+import pyTEMlib.file_tools as ft
+from pyTEMlib.xrpa_x_sections import x_sections
+
+import sidpy
+from sidpy.base.num_utils import get_slope
+
+major_edges = ['K1', 'L3', 'M5', 'N5']
+all_edges = ['K1', 'L1', 'L2', 'L3', 'M1', 'M2', 'M3', 'M4', 'M5', 'N1', 'N2', 'N3', 'N4', 'N5', 'N6', 'N7', 'O1', 'O2',
+             'O3', 'O4', 'O5', 'O6', 'O7', 'P1', 'P2', 'P3']
+first_close_edges = ['K1', 'L3', 'M5', 'M3', 'N5', 'N3']
+
+elements = [' ', 'H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Na',
+            'Mg', 'Al', 'Si', 'P', 'S', 'Cl', 'Ar', 'K', 'Ca', 'Sc', 'Ti', 'V',
+            'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'Ga', 'Ge', 'As', 'Se', 'Br',
+            'Kr', 'Rb', 'Sr', 'Y', 'Zr', 'Nb', 'Mo', 'Tc', 'Ru', 'Rh', 'Pd', 'Ag',
+            'Cd', 'In', 'Sn', 'Sb', 'Te', 'I', 'Xe', 'Cs', 'Ba', 'La', 'Ce', 'Pr',
+            'Nd', 'Pm', 'Sm', 'Eu', 'Gd', 'Tb', 'Dy', 'Ho', 'Er', 'Tm', 'Yb', 'Lu',
+            'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir', 'Pt', 'Au', 'Hg', 'Tl', 'Pb', 'Bi']
+
+
+# kroeger_core(e_data,a_data,eps_data,ee,thick, relativistic =True)
+# kroeger_core2(e_data,a_data,eps_data,acceleration_voltage_kev,thickness, relativistic =True)
+# get_wave_length(e0)
+
+# plot_dispersion(plotdata, units, a_data, e_data, title, max_p, ee, ef = 4., ep= 16.8, Es = 0, IBT = [])
+# drude(tags, e, ep, ew, tnm, eb)
+# drude(ep, eb, gamma, e)
+# drude_lorentz(epsInf,leng, ep, eb, gamma, e, Amplitude)
+# zl_func( p,  x)
+
+###
+
[docs]def set_previous_quantification(current_dataset): + """Set previous quantification from a sidpy.Dataset""" + + current_channel = current_dataset.h5_dataset.parent + found_metadata = False + for key in current_channel: + if 'Log' in key: + if current_channel[key]['analysis'][()] == 'EELS_quantification': + current_dataset.metadata.update(current_channel[key].attrs) # ToDo: find red dictionary + found_metadata = True + print('found previous quantification') + + if not found_metadata: + # setting important experimental parameter + current_dataset.metadata['experiment'] = ft.read_dm3_info(current_dataset.original_metadata) + + if 'experiment' not in current_dataset.metadata: + current_dataset.metadata['experiment'] = {} + if 'convergence_angle' not in current_dataset.metadata['experiment']: + current_dataset.metadata['experiment']['convergence_angle'] = 30 + if 'collection_angle' not in current_dataset.metadata['experiment']: + current_dataset.metadata['experiment']['collection_angle'] = 50 + if 'acceleration_voltage' not in current_dataset.metadata['experiment']: + current_dataset.metadata['experiment']['acceleration_voltage'] = 200000
+### + +# ############################################################### +# Peak Fit Functions +# ################################################################ + + +
[docs]def residuals_smooth(p, x, y, only_positive_intensity): + """part of fit""" + + err = (y - model_smooth(x, p, only_positive_intensity)) + return err
+ + +
[docs]def model_smooth(x, p, only_positive_intensity=False): + """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
+ + +
[docs]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
+ + +
[docs]def residuals_ll2(p, x, y, only_positive_intensity): + """part of fit""" + + err = (y - model_ll(x, p, only_positive_intensity)) + return err
+ + +
[docs]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
+ + +
[docs]def fit_peaks(spectrum, energy_scale, pin, start_fit, end_fit, only_positive_intensity=False): + """fit peaks to spectrum + + Parameters + ---------- + spectrum: numpy array + spectrum to be fitted + energy_scale: numpy array + energy scale of spectrum + pin: list of float + intial guess of peaks position amplitude width + start_fit: int + channel where fit starts + end_fit: int + channel where fit starts + only_positive_intensity: boolean + allows only for positive amplitudes if True; default = False + + Returns + ------- + p: list of float + fitting parameters + """ + + # TODO: remove zero_loss_fit_width add absolute + + 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_flat), ftol=1e-3, args=(fit_energy, fit_spectrum, + only_positive_intensity)) + p = [] + for i in range(len(pin)): + 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
+ + +################################################################# +# CORE - LOSS functions +################################################################# + + +
[docs]def get_x_sections(z=0): + """Reads X-ray fluorescent cross-sections from a pickle file. + + Parameters + ---------- + z: int + atomic number if zero all cross-sections will be returned + + Returns + ------- + dictionary + cross-section of an element or of all elements if z = 0 + + """ + # pkl_file = open(data_path + '/edges_db.pkl', 'rb') + # x_sections = pickle.load(pkl_file) + # pkl_file.close() + # x_sections = pyTEMlib.config_dir.x_sections + z = int(z) + + if z < 1: + return x_sections + else: + z = str(z) + if z in x_sections: + return x_sections[z] + else: + return 0
+ + +
[docs]def get_z(z): + """Returns the atomic number independent of input as a string or number + + Parameter + --------- + z: int, str + atomic number of chemical symbol (0 if not valid) + """ + x_sections = get_x_sections() + + z_out = 0 + if str(z).isdigit(): + z_out = int(z) + elif isinstance(z, str): + for key in x_sections: + if x_sections[key]['name'].lower() == z.lower(): # Well one really should know how to write elemental + z_out = int(key) + return z_out
+ + +
[docs]def list_all_edges(z, verbose=False): + """List all ionization edges of an element with atomic number z + + Parameters + ---------- + z: int + atomic number + + Returns + ------- + out_string: str + string with all major edges in energy range + """ + + element = str(z) + x_sections = get_x_sections() + out_string = '' + if verbose: + print('Major edges') + edge_list = {x_sections[element]['name']: {}} + + for key in all_edges: + if key in x_sections[element]: + if 'onset' in x_sections[element][key]: + if verbose: + print(f" {x_sections[element]['name']}-{key}: {x_sections[element][key]['onset']:8.1f} eV ") + out_string = out_string + f" {x_sections[element]['name']}-{key}: " \ + f"{x_sections[element][key]['onset']:8.1f} eV /n" + edge_list[x_sections[element]['name']][key] = x_sections[element][key]['onset'] + return out_string, edge_list
+ + +
[docs]def find_major_edges(edge_onset, maximal_chemical_shift=5.): + """Find all major edges within an energy range + + Parameters + ---------- + edge_onset: float + approximate energy of ionization edge + maximal_chemical_shift: float + optional, range of energy window around edge_onset to look for major edges + + Returns + ------- + text: str + string with all major edges in energy range + + """ + text = '' + x_sections = get_x_sections() + for element in x_sections: + for key in x_sections[element]: + + # if isinstance(x_sections[element][key], dict): + if key in major_edges: + + if abs(x_sections[element][key]['onset'] - edge_onset) < maximal_chemical_shift: + # print(element, x_sections[element]['name'], key, x_sections[element][key]['onset']) + text = text + f"\n {x_sections[element]['name']:2s}-{key}: " \ + f"{x_sections[element][key]['onset']:8.1f} eV " + + return text
+ + +
[docs]def find_all_edges(edge_onset, maximal_chemical_shift=5): + """Find all (major and minor) edges within an energy range + + Parameters + ---------- + edge_onset: float + approximate energy of ionization edge + maximal_chemical_shift: float + optional, range of energy window around edge_onset to look for major edges + + Returns + ------- + text: str + string with all edges in energy range + + """ + + text = '' + x_sections = get_x_sections() + for element in x_sections: + for key in x_sections[element]: + + if isinstance(x_sections[element][key], dict): + if 'onset' in x_sections[element][key]: + if abs(x_sections[element][key]['onset'] - edge_onset) < maximal_chemical_shift: + # print(element, x_sections[element]['name'], key, x_sections[element][key]['onset']) + text = text + f"\n {x_sections[element]['name']:2s}-{key}: " \ + f"{x_sections[element][key]['onset']:8.1f} eV " + return text
+ + +
[docs]def find_associated_edges(dataset): + onsets = [] + edges = [] + if 'edges' in dataset.metadata: + for key, edge in dataset.metadata['edges'].items(): + if key.isdigit(): + element = edge['element'] + pre_edge = 0. # edge['onset']-edge['start_exclude'] + post_edge = edge['end_exclude'] - edge['onset'] + + for sym in edge['all_edges']: # TODO: Could be replaced with exclude + onsets.append(edge['all_edges'][sym]['onset'] + edge['chemical_shift']-pre_edge) + edges.append([key, f"{element}-{sym}", onsets[-1]]) + for key, peak in dataset.metadata['peak_fit']['peaks'].items(): + if key.isdigit(): + distance = dataset.energy_loss[-1] + index = -1 + for ii, onset in enumerate(onsets): + if onset < peak['position'] < onset+post_edge: + if distance > np.abs(peak['position'] - onset): + distance = np.abs(peak['position'] - onset) # TODO: check whether absolute is good + distance_onset = peak['position'] - onset + index = ii + if index >= 0: + peak['associated_edge'] = edges[index][1] # check if more info is necessary + peak['distance_to_onset'] = distance_onset
+ + +
[docs]def find_white_lines(dataset): + if 'edges' in dataset.metadata: + white_lines = {} + for index, peak in dataset.metadata['peak_fit']['peaks'].items(): + if index.isdigit(): + if 'associated_edge' in peak: + if peak['associated_edge'][-2:] in ['L3', 'L2', 'M5', 'M4']: + if peak['distance_to_onset'] < 10: + area = np.sqrt(2 * np.pi) * peak['amplitude'] * np.abs(peak['width']/np.sqrt(2 * np.log(2))) + if peak['associated_edge'] not in white_lines: + white_lines[peak['associated_edge']] = 0. + if area > 0: + white_lines[peak['associated_edge']] += area # TODO: only positive ones? + white_line_ratios = {} + white_line_sum = {} + for sym, area in white_lines.items(): + if sym[-2:] in ['L2', 'M4', 'M2']: + if area > 0 and f"{sym[:-1]}{int(sym[-1]) + 1}" in white_lines: + if white_lines[f"{sym[:-1]}{int(sym[-1]) + 1}"] > 0: + white_line_ratios[f"{sym}/{sym[-2]}{int(sym[-1]) + 1}"] = area / white_lines[ + f"{sym[:-1]}{int(sym[-1]) + 1}"] + white_line_sum[f"{sym}+{sym[-2]}{int(sym[-1]) + 1}"] = ( + area + white_lines[f"{sym[:-1]}{int(sym[-1]) + 1}"]) + + areal_density = 1. + if 'edges' in dataset.metadata: + for key, edge in dataset.metadata['edges'].items(): + if key.isdigit(): + if edge['element'] == sym.split('-')[0]: + areal_density = edge['areal_density'] + break + white_line_sum[f"{sym}+{sym[-2]}{int(sym[-1]) + 1}"] /= areal_density + + dataset.metadata['peak_fit']['white_lines'] = white_lines + dataset.metadata['peak_fit']['white_line_ratios'] = white_line_ratios + dataset.metadata['peak_fit']['white_line_sums'] = white_line_sum
+ + +
[docs]def second_derivative(dataset, sensitivity): + """Calculates second derivative of a sidpy.dataset""" + + dim = dataset.get_spectrum_dims() + energy_scale = np.array(dataset._axes[dim[0]]) + if dataset.data_type.name == 'SPECTRAL_IMAGE': + spectrum = dataset.view.get_spectrum() + else: + spectrum = np.array(dataset) + + spec = scipy.ndimage.gaussian_filter(spectrum, 3) + + dispersion = get_slope(energy_scale) + second_dif = np.roll(spec, -3) - 2 * spec + np.roll(spec, +3) + second_dif[:3] = 0 + second_dif[-3:] = 0 + + # find if there is a strong edge at high energy_scale + noise_level = 2. * np.std(second_dif[3:50]) + [indices, _] = scipy.signal.find_peaks(second_dif, noise_level) + width = 50 / dispersion + if width < 50: + width = 50 + start_end_noise = int(len(energy_scale) - width) + for index in indices[::-1]: + if index > start_end_noise: + start_end_noise = index - 70 + + noise_level_start = sensitivity * np.std(second_dif[3:50]) + noise_level_end = sensitivity * np.std(second_dif[start_end_noise: start_end_noise + 50]) + slope = (noise_level_end - noise_level_start) / (len(energy_scale) - 400) + noise_level = noise_level_start + np.arange(len(energy_scale)) * slope + return second_dif, noise_level
+ + +
[docs]def find_edges(dataset, sensitivity=2.5): + """find edges within a sidpy.Dataset""" + + dim = dataset.get_spectrum_dims() + energy_scale = np.array(dataset._axes[dim[0]]) + + second_dif, noise_level = second_derivative(dataset, sensitivity=sensitivity) + + [indices, peaks] = scipy.signal.find_peaks(second_dif, noise_level) + + peaks['peak_positions'] = energy_scale[indices] + peaks['peak_indices'] = indices + edge_energies = [energy_scale[50]] + edge_indices = [] + + [indices, _] = scipy.signal.find_peaks(-second_dif, noise_level) + minima = energy_scale[indices] + + for peak_number in range(len(peaks['peak_positions'])): + position = peaks['peak_positions'][peak_number] + if position - edge_energies[-1] > 20: + impossible = minima[minima < position] + impossible = impossible[impossible > position - 5] + if len(impossible) == 0: + possible = minima[minima > position] + possible = possible[possible < position + 5] + if len(possible) > 0: + edge_energies.append((position + possible[0])/2) + edge_indices.append(np.searchsorted(energy_scale, (position + possible[0])/2)) + + selected_edges = [] + for peak in edge_indices: + if 525 < energy_scale[peak] < 533: + selected_edges.append('O-K1') + else: + selected_edge = '' + edges = find_major_edges(energy_scale[peak], 20) + edges = edges.split('\n') + minimum_dist = 100. + for edge in edges[1:]: + edge = edge[:-3].split(':') + name = edge[0].strip() + energy = float(edge[1].strip()) + if np.abs(energy - energy_scale[peak]) < minimum_dist: + minimum_dist = np.abs(energy - energy_scale[peak]) + selected_edge = name + + if selected_edge != '': + selected_edges.append(selected_edge) + + return selected_edges
+ + +
[docs]def assign_likely_edges(edge_channels, energy_scale): + edges_in_list = [] + result = {} + for channel in edge_channels: + if channel not in edge_channels[edges_in_list]: + shift = 5 + element_list = find_major_edges(energy_scale[channel], maximal_chemical_shift=shift) + while len(element_list) < 1: + shift+=1 + element_list = find_major_edges(energy_scale[channel], maximal_chemical_shift=shift) + + if len(element_list) > 1: + while len(element_list) > 0: + shift-=1 + element_list = find_major_edges(energy_scale[channel], maximal_chemical_shift=shift) + element_list = find_major_edges(energy_scale[channel], maximal_chemical_shift=shift+1) + element = (element_list[:4]).strip() + z = get_z(element) + result[element] =[] + _, edge_list = list_all_edges(z) + + for peak in edge_list: + for edge in edge_list[peak]: + possible_minor_edge = np.argmin(np.abs(energy_scale[edge_channels]-edge_list[peak][edge])) + if np.abs(energy_scale[edge_channels[possible_minor_edge]]-edge_list[peak][edge]) < 3: + #print('nex', next_e) + edges_in_list.append(possible_minor_edge) + + result[element].append(edge) + + return result
+ + +
[docs]def auto_id_edges(dataset): + edge_channels = identify_edges(dataset) + dim = dataset.get_spectrum_dims() + energy_scale = np.array(dataset._axes[dim[0]]) + found_edges = assign_likely_edges(edge_channels, energy_scale) + return found_edges
+ + +
[docs]def identify_edges(dataset, noise_level=2.0): + """ + Using first derivative to determine edge onsets + Any peak in first derivative higher than noise_level times standard deviation will be considered + + Parameters + ---------- + dataset: sidpy.Dataset + the spectrum + noise_level: float + ths number times standard deviation in first derivative decides on whether an edge onset is significant + + Return + ------ + edge_channel: numpy.ndarray + + """ + dim = dataset.get_spectrum_dims() + energy_scale = np.array(dataset._axes[dim[0]]) + dispersion = get_slope(energy_scale) + spec = scipy.ndimage.gaussian_filter(dataset, 3/dispersion) # smooth with 3eV wideGaussian + + first_derivative = spec - np.roll(spec, +2) + first_derivative[:3] = 0 + first_derivative[-3:] = 0 + + # find if there is a strong edge at high energy_scale + noise_level = noise_level*np.std(first_derivative[3:50]) + [edge_channels, _] = scipy.signal.find_peaks(first_derivative, noise_level) + + return edge_channels
+ + +
[docs]def add_element_to_dataset(dataset, z): + """ + """ + # We check whether this element is already in the + energy_scale = dataset.energy_loss + zz = get_z(z) + if 'edges' not in dataset.metadata: + dataset.metadata['edges'] = {'model': {}, 'use_low_loss': False} + index = 0 + for key, edge in dataset.metadata['edges'].items(): + if key.isdigit(): + index += 1 + if 'z' in edge: + if zz == edge['z']: + index = int(key) + break + + major_edge = '' + minor_edge = '' + all_edges = {} + x_section = get_x_sections(zz) + edge_start = 10 # int(15./ft.get_slope(self.energy_scale)+0.5) + for key in x_section: + if len(key) == 2 and key[0] in ['K', 'L', 'M', 'N', 'O'] and key[1].isdigit(): + if energy_scale[edge_start] < x_section[key]['onset'] < energy_scale[-edge_start]: + if key in ['K1', 'L3', 'M5', 'M3']: + major_edge = key + + all_edges[key] = {'onset': x_section[key]['onset']} + + if major_edge != '': + key = major_edge + elif minor_edge != '': + key = minor_edge + else: + print(f'Could not find no edge of {zz} in spectrum') + return False + + + if str(index) not in dataset.metadata['edges']: + dataset.metadata['edges'][str(index)] = {} + + start_exclude = x_section[key]['onset'] - x_section[key]['excl before'] + end_exclude = x_section[key]['onset'] + x_section[key]['excl after'] + + dataset.metadata['edges'][str(index)] = {'z': zz, 'symmetry': key, 'element': elements[zz], + 'onset': x_section[key]['onset'], 'end_exclude': end_exclude, + 'start_exclude': start_exclude} + dataset.metadata['edges'][str(index)]['all_edges'] = all_edges + dataset.metadata['edges'][str(index)]['chemical_shift'] = 0.0 + dataset.metadata['edges'][str(index)]['areal_density'] = 0.0 + dataset.metadata['edges'][str(index)]['original_onset'] = dataset.metadata['edges'][str(index)]['onset'] + return True
+ + +
[docs]def make_edges(edges_present, energy_scale, e_0, coll_angle, low_loss=None): + """Makes the edges dictionary for quantification + + Parameters + ---------- + edges_present: list + list of edges + energy_scale: numpy array + energy scale on which to make cross-section + e_0: float + acceleration voltage (in V) + coll_angle: float + collection angle in mrad + low_loss: numpy array with same length as energy_scale + low_less spectrum with which to convolve the cross-section (default=None) + + Returns + ------- + edges: dict + dictionary with all information on cross-section + """ + x_sections = get_x_sections() + edges = {} + for i, edge in enumerate(edges_present): + element, symmetry = edge.split('-') + z = 0 + for key in x_sections: + if element == x_sections[key]['name']: + z = int(key) + edges[i] = {} + edges[i]['z'] = z + edges[i]['symmetry'] = symmetry + edges[i]['element'] = element + + for key in edges: + xsec = x_sections[str(edges[key]['z'])] + if 'chemical_shift' not in edges[key]: + edges[key]['chemical_shift'] = 0 + if 'symmetry' not in edges[key]: + edges[key]['symmetry'] = 'K1' + if 'K' in edges[key]['symmetry']: + edges[key]['symmetry'] = 'K1' + elif 'L' in edges[key]['symmetry']: + edges[key]['symmetry'] = 'L3' + elif 'M' in edges[key]['symmetry']: + edges[key]['symmetry'] = 'M5' + else: + edges[key]['symmetry'] = edges[key]['symmetry'][0:2] + + edges[key]['original_onset'] = xsec[edges[key]['symmetry']]['onset'] + edges[key]['onset'] = edges[key]['original_onset'] + edges[key]['chemical_shift'] + edges[key]['start_exclude'] = edges[key]['onset'] - xsec[edges[key]['symmetry']]['excl before'] + edges[key]['end_exclude'] = edges[key]['onset'] + xsec[edges[key]['symmetry']]['excl after'] + + edges = make_cross_sections(edges, energy_scale, e_0, coll_angle, low_loss) + + return edges
+ +
[docs]def fit_dataset(dataset): + energy_scale = dataset.energy_loss + if 'fit_area' not in dataset.metadata['edges']: + dataset.metadata['edges']['fit_area'] = {} + if 'fit_start' not in dataset.metadata['edges']['fit_area']: + dataset.metadata['edges']['fit_area']['fit_start'] = energy_scale[50] + if 'fit_end' not in dataset.metadata['edges']['fit_area']: + dataset.metadata['edges']['fit_area']['fit_end'] = energy_scale[-2] + dataset.metadata['edges']['use_low_loss'] = False + + if 'experiment' in dataset.metadata: + exp = dataset.metadata['experiment'] + if 'convergence_angle' not in exp: + raise ValueError('need a convergence_angle in experiment of metadata dictionary ') + alpha = exp['convergence_angle'] + beta = exp['collection_angle'] + beam_kv = exp['acceleration_voltage'] + energy_scale = dataset.energy_loss + eff_beta = effective_collection_angle(energy_scale, alpha, beta, beam_kv) + edges = make_cross_sections(dataset.metadata['edges'], np.array(energy_scale), beam_kv, eff_beta) + dataset.metadata['edges'] = fit_edges2(dataset, energy_scale, edges) + areal_density = [] + elements = [] + for key in edges: + if key.isdigit(): # only edges have numbers in that dictionary + elements.append(edges[key]['element']) + areal_density.append(edges[key]['areal_density']) + areal_density = np.array(areal_density) + out_string = '\nRelative composition: \n' + for i, element in enumerate(elements): + out_string += f'{element}: {areal_density[i] / areal_density.sum() * 100:.1f}% ' + + print(out_string)
+ + +
[docs]def auto_chemical_composition(dataset): + + found_edges = auto_id_edges(dataset) + for key in found_edges: + add_element_to_dataset(dataset, key) + fit_dataset(dataset)
+ + +
[docs]def make_cross_sections(edges, energy_scale, e_0, coll_angle, low_loss=None): + """Updates the edges dictionary with collection angle-integrated X-ray photo-absorption cross-sections + + """ + for key in edges: + if str(key).isdigit(): + edges[key]['data'] = xsec_xrpa(energy_scale, e_0 / 1000., edges[key]['z'], coll_angle, + edges[key]['chemical_shift']) / 1e10 # from barnes to 1/nm^2 + if low_loss is not None: + low_loss = np.roll(np.array(low_loss), 1024 - np.argmax(np.array(low_loss))) + edges[key]['data'] = scipy.signal.convolve(edges[key]['data'], low_loss/low_loss.sum(), mode='same') + + edges[key]['onset'] = edges[key]['original_onset'] + edges[key]['chemical_shift'] + edges[key]['X_section_type'] = 'XRPA' + edges[key]['X_section_source'] = 'pyTEMlib' + + return edges
+ + +
[docs]def power_law(energy, a, r): + """power law for power_law_background""" + return a * np.power(energy, -r)
+ + +
[docs]def power_law_background(spectrum, energy_scale, fit_area, verbose=False): + """fit of power law to spectrum """ + + # Determine energy window for background fit in pixels + startx = np.searchsorted(energy_scale, fit_area[0]) + endx = np.searchsorted(energy_scale, fit_area[1]) + + x = np.array(energy_scale)[startx:endx] + + y = np.array(spectrum)[startx:endx].flatten() + + # Initial values of parameters + p0 = np.array([1.0E+20, 3]) + + # background fitting + def bgdfit(pp, yy, xx): + err = yy - power_law(xx, pp[0], pp[1]) + return err + + [p, _] = leastsq(bgdfit, p0, args=(y, x), maxfev=2000) + + background_difference = y - power_law(x, p[0], p[1]) + background_noise_level = std_dev = np.std(background_difference) + if verbose: + print(f'Power-law background with amplitude A: {p[0]:.1f} and exponent -r: {p[1]:.2f}') + print(background_difference.max() / background_noise_level) + + print(f'Noise level in spectrum {std_dev:.3f} counts') + + # Calculate background over the whole energy scale + background = power_law(energy_scale, p[0], p[1]) + return background, p
+ + +
[docs]def cl_model(x, p, number_of_edges, xsec): + """ core loss model for fitting""" + y = (p[9] * np.power(x, (-p[10]))) + p[7] * x + p[8] * x * x + for i in range(number_of_edges): + y = y + p[i] * xsec[i, :] + return y
+ + +
[docs]def fit_edges2(spectrum, energy_scale, edges): + """fit edges for quantification""" + + dispersion = energy_scale[1] - energy_scale[0] + # Determine fitting ranges and masks to exclude ranges + mask = np.ones(len(spectrum)) + + background_fit_start = edges['fit_area']['fit_start'] + if edges['fit_area']['fit_end'] > energy_scale[-1]: + edges['fit_area']['fit_end'] = energy_scale[-1] + background_fit_end = edges['fit_area']['fit_end'] + + startx = np.searchsorted(energy_scale, background_fit_start) + endx = np.searchsorted(energy_scale, background_fit_end) + mask[0:startx] = 0.0 + mask[endx:-1] = 0.0 + for key in edges: + if key.isdigit(): + if edges[key]['start_exclude'] > background_fit_start + dispersion: + if edges[key]['start_exclude'] < background_fit_end - dispersion * 2: + if edges[key]['end_exclude'] > background_fit_end - dispersion: + # we need at least one channel to fit. + edges[key]['end_exclude'] = background_fit_end - dispersion + startx = np.searchsorted(energy_scale, edges[key]['start_exclude']) + if startx < 2: + startx = 1 + endx = np.searchsorted(energy_scale, edges[key]['end_exclude']) + mask[startx: endx] = 0.0 + + ######################## + # Background Fit + ######################## + bgd_fit_area = [background_fit_start, background_fit_end] + background, [A, r] = power_law_background(spectrum, energy_scale, bgd_fit_area, verbose=False) + + ####################### + # Edge Fit + ####################### + x = energy_scale + blurred = gaussian_filter(spectrum, sigma=5) + + y = blurred # now in probability + y[np.where(y < 1e-8)] = 1e-8 + + xsec = [] + number_of_edges = 0 + for key in edges: + if key.isdigit(): + xsec.append(edges[key]['data']) + number_of_edges += 1 + xsec = np.array(xsec) + + def model(xx, pp): + yy = background + pp[6] + pp[7] * xx + pp[8] * xx * xx + for i in range(number_of_edges): + pp[i] = np.abs(pp[i]) + yy = yy + pp[i] * xsec[i, :] + return yy + + def residuals(pp, xx, yy): + err = np.abs((yy - model(xx, pp)) * mask) # / np.sqrt(np.abs(y)) + return err + + scale = y[100] + pin = np.array([scale / 5, scale / 5, scale / 5, scale / 5, scale / 5, scale / 5, -scale / 10, 1.0, 0.001]) + [p, _] = leastsq(residuals, pin, args=(x, y)) + + for key in edges: + if key.isdigit(): + edges[key]['areal_density'] = p[int(key)] + + edges['model'] = {} + edges['model']['background'] = (background + p[6] + p[7] * x + p[8] * x * x) + edges['model']['background-poly_0'] = p[6] + edges['model']['background-poly_1'] = p[7] + edges['model']['background-poly_2'] = p[8] + edges['model']['background-A'] = A + edges['model']['background-r'] = r + edges['model']['spectrum'] = model(x, p) + edges['model']['blurred'] = blurred + edges['model']['mask'] = mask + edges['model']['fit_parameter'] = p + edges['model']['fit_area_start'] = edges['fit_area']['fit_start'] + edges['model']['fit_area_end'] = edges['fit_area']['fit_end'] + + return edges
+ + +
[docs]def fit_edges(spectrum, energy_scale, region_tags, edges): + """fit edges for quantification""" + + # Determine fitting ranges and masks to exclude ranges + mask = np.ones(len(spectrum)) + + background_fit_end = energy_scale[-1] + for key in region_tags: + end = region_tags[key]['start_x'] + region_tags[key]['width_x'] + + startx = np.searchsorted(energy_scale, region_tags[key]['start_x']) + endx = np.searchsorted(energy_scale, end) + + if key == 'fit_area': + mask[0:startx] = 0.0 + mask[endx:-1] = 0.0 + else: + mask[startx:endx] = 0.0 + if region_tags[key]['start_x'] < background_fit_end: # Which is the onset of the first edge? + background_fit_end = region_tags[key]['start_x'] + + ######################## + # Background Fit + ######################## + bgd_fit_area = [region_tags['fit_area']['start_x'], background_fit_end] + background, [A, r] = power_law_background(spectrum, energy_scale, bgd_fit_area, verbose=False) + + ####################### + # Edge Fit + ####################### + x = energy_scale + blurred = gaussian_filter(spectrum, sigma=5) + + y = blurred # now in probability + y[np.where(y < 1e-8)] = 1e-8 + + xsec = [] + number_of_edges = 0 + for key in edges: + if key.isdigit(): + xsec.append(edges[key]['data']) + number_of_edges += 1 + xsec = np.array(xsec) + + def model(xx, pp): + yy = background + pp[6] + pp[7] * xx + pp[8] * xx * xx + for i in range(number_of_edges): + pp[i] = np.abs(pp[i]) + yy = yy + pp[i] * xsec[i, :] + return yy + + def residuals(pp, xx, yy): + err = np.abs((yy - model(xx, pp)) * mask) # / np.sqrt(np.abs(y)) + return err + + scale = y[100] + pin = np.array([scale / 5, scale / 5, scale / 5, scale / 5, scale / 5, scale / 5, -scale / 10, 1.0, 0.001]) + [p, _] = leastsq(residuals, pin, args=(x, y)) + + for key in edges: + if key.isdigit(): + edges[key]['areal_density'] = p[int(key) - 1] + + edges['model'] = {} + edges['model']['background'] = (background + p[6] + p[7] * x + p[8] * x * x) + edges['model']['background-poly_0'] = p[6] + edges['model']['background-poly_1'] = p[7] + edges['model']['background-poly_2'] = p[8] + edges['model']['background-A'] = A + edges['model']['background-r'] = r + edges['model']['spectrum'] = model(x, p) + edges['model']['blurred'] = blurred + edges['model']['mask'] = mask + edges['model']['fit_parameter'] = p + edges['model']['fit_area_start'] = region_tags['fit_area']['start_x'] + edges['model']['fit_area_end'] = region_tags['fit_area']['start_x'] + region_tags['fit_area']['width_x'] + + return edges
+ + +
[docs]def find_peaks(dataset, fit_start, fit_end, sensitivity=2): + """find peaks in spectrum""" + + if dataset.data_type.name == 'SPECTRAL_IMAGE': + spectrum = dataset.view.get_spectrum() + else: + spectrum = np.array(dataset) + + spec_dim = ft.get_dimensions_by_type('SPECTRAL', dataset)[0] + energy_scale = np.array(spec_dim[1]) + + second_dif, noise_level = second_derivative(dataset, sensitivity=sensitivity) + [indices, _] = scipy.signal.find_peaks(-second_dif, noise_level) + + start_channel = np.searchsorted(energy_scale, fit_start) + end_channel = np.searchsorted(energy_scale, fit_end) + peaks = [] + for index in indices: + if start_channel < index < end_channel: + peaks.append(index - start_channel) + + if 'model' in dataset.metadata: + model = dataset.metadata['model'][start_channel:end_channel] + + elif energy_scale[0] > 0: + if 'edges' not in dataset.metadata: + return + if 'model' not in dataset.metadata['edges']: + return + model = dataset.metadata['edges']['model']['spectrum'][start_channel:end_channel] + + else: + model = np.zeros(end_channel - start_channel) + + energy_scale = energy_scale[start_channel:end_channel] + + difference = np.array(spectrum)[start_channel:end_channel] - model + fit = np.zeros(len(energy_scale)) + p_out = [] + if len(peaks) > 0: + p_in = np.ravel([[energy_scale[i], difference[i], .7] for i in peaks]) + [p_out, _] = scipy.optimize.leastsq(residuals_smooth, p_in, ftol=1e-3, args=(energy_scale, + difference, + False)) + fit = fit + model_smooth(energy_scale, p_out, False) + + peak_model = np.zeros(len(spec_dim[1])) + peak_model[start_channel:end_channel] = fit + + return peak_model, p_out
+ + +
[docs]def find_maxima(y, number_of_peaks): + """ find the first most prominent peaks + + peaks are then sorted by energy + + Parameters + ---------- + y: numpy array + (part) of spectrum + number_of_peaks: int + + Returns + ------- + numpy array + indices of peaks + """ + blurred2 = gaussian_filter(y, sigma=2) + peaks, _ = scipy.signal.find_peaks(blurred2) + prominences = peak_prominences(blurred2, peaks)[0] + prominences_sorted = np.argsort(prominences) + peaks = peaks[prominences_sorted[-number_of_peaks:]] + + peak_indices = np.argsort(peaks) + return peaks[peak_indices]
+ + +
[docs]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))
+ + +
[docs]def lorentz(x, p): + """lorentzian function""" + lorentz_peak = 0.5 * p[2] / np.pi / ((x - p[0]) ** 2 + (p[2] / 2) ** 2) + return p[1] * lorentz_peak / lorentz_peak.max()
+ + +
[docs]def zl(x, p, p_zl): + """zero-loss function""" + p_zl_local = p_zl.copy() + p_zl_local[2] += p[0] + p_zl_local[5] += p[0] + zero_loss = zl_func(p_zl_local, x) + return p[1] * zero_loss / zero_loss.max()
+ + +
[docs]def model3(x, p, number_of_peaks, peak_shape, p_zl, pin=None, restrict_pos=0, restrict_width=0): + """ model for fitting low-loss spectrum""" + if pin is None: + pin = p + + # if len([restrict_pos]) == 1: + # restrict_pos = [restrict_pos]*number_of_peaks + # if len([restrict_width]) == 1: + # restrict_width = [restrict_width]*number_of_peaks + y = np.zeros(len(x)) + + for i in range(number_of_peaks): + index = int(i * 3) + if restrict_pos > 0: + if p[index] > pin[index] * (1.0 + restrict_pos): + p[index] = pin[index] * (1.0 + restrict_pos) + if p[index] < pin[index] * (1.0 - restrict_pos): + p[index] = pin[index] * (1.0 - restrict_pos) + + p[index + 1] = abs(p[index + 1]) + # print(p[index + 1]) + p[index + 2] = abs(p[index + 2]) + if restrict_width > 0: + if p[index + 2] > pin[index + 2] * (1.0 + restrict_width): + p[index + 2] = pin[index + 2] * (1.0 + restrict_width) + + if peak_shape[i] == 'Lorentzian': + y = y + lorentz(x, p[index:]) + elif peak_shape[i] == 'zl': + + y = y + zl(x, p[index:], p_zl) + else: + y = y + gauss(x, p[index:]) + return y
+ + +
[docs]def sort_peaks(p, peak_shape): + """sort fitting parameters by peak position""" + number_of_peaks = int(len(p) / 3) + p3 = np.reshape(p, (number_of_peaks, 3)) + sort_pin = np.argsort(p3[:, 0]) + + p = p3[sort_pin].flatten() + peak_shape = np.array(peak_shape)[sort_pin].tolist() + + return p, peak_shape
+ + +
[docs]def add_peaks(x, y, peaks, pin_in=None, peak_shape_in=None, shape='Gaussian'): + """ add peaks to fitting parameters""" + if pin_in is None: + return + if peak_shape_in is None: + return + + pin = pin_in.copy() + + peak_shape = peak_shape_in.copy() + if isinstance(shape, str): # if peak_shape is only a string make a list of it. + shape = [shape] + + if len(shape) == 1: + shape = shape * len(peaks) + for i, peak in enumerate(peaks): + pin.append(x[peak]) + pin.append(y[peak]) + pin.append(.3) + peak_shape.append(shape[i]) + + return pin, peak_shape
+ + +
[docs]def fit_model(x, y, pin, number_of_peaks, peak_shape, p_zl, restrict_pos=0, restrict_width=0): + """model for fitting low-loss spectrum""" + + pin_original = pin.copy() + + def residuals3(pp, xx, yy): + err = (yy - model3(xx, pp, number_of_peaks, peak_shape, p_zl, pin_original, restrict_pos, + restrict_width)) / np.sqrt(np.abs(yy)) + return err + + [p, _] = leastsq(residuals3, pin, args=(x, y)) + # p2 = p.tolist() + # p3 = np.reshape(p2, (number_of_peaks, 3)) + # sort_pin = np.argsort(p3[:, 0]) + + # p = p3[sort_pin].flatten() + # peak_shape = np.array(peak_shape)[sort_pin].tolist() + + return p, peak_shape
+ + +
[docs]def fix_energy_scale(spec, energy=None): + """Shift energy scale according to zero-loss peak position + + This function assumes that the fzero loss peak is the maximum of the spectrum. + """ + + # determine start and end fitting region in pixels + if isinstance(spec, sidpy.Dataset): + if energy is None: + energy = spec.energy_loss.values + spec = np.array(spec) + + else: + if energy is None: + return + if not isinstance(spec, np.ndarray): + return + + start = np.searchsorted(np.array(energy), -10) + end = np.searchsorted(np.array(energy), 10) + startx = np.argmax(spec[start:end]) + start + + end = startx + 3 + start = startx - 3 + for i in range(10): + if spec[startx - i] < 0.3 * spec[startx]: + start = startx - i + if spec[startx + i] < 0.3 * spec[startx]: + end = startx + i + if end - start < 3: + end = startx + 2 + start = startx - 2 + + x = np.array(energy[int(start):int(end)]) + y = np.array(spec[int(start):int(end)]).copy() + + y[np.nonzero(y <= 0)] = 1e-12 + + p0 = [energy[startx], 1000.0, (energy[end] - energy[start]) / 3.] # Initial guess is a normal distribution + + def errfunc(pp, xx, yy): + return (gauss(xx, pp) - yy) / np.sqrt(yy) # Distance to the target function + + [p1, _] = leastsq(errfunc, np.array(p0[:]), args=(x, y)) + fit_mu, area, fwhm = p1 + + return fwhm, fit_mu
+ +
[docs]def resolution_function2(dataset, width =0.3): + guess = [0.2, 1000, 0.02, 0.2, 1000, 0.2] + p0 = np.array(guess) + + start = np.searchsorted(dataset.energy_loss, -width / 2.) + end = np.searchsorted(dataset.energy_loss, width / 2.) + x = dataset.energy_loss[start:end] + y = np.array(dataset)[start:end] + def zl2(pp, yy, xx): + eerr = (yy - zl_func(pp, xx)) # /np.sqrt(y) + return eerr + + [p_zl, _] = leastsq(zl2, p0, args=(y, x), maxfev=2000) + + z_loss = zl_func(p_zl, dataset.energy_loss) + z_loss = dataset.like_data(z_loss) + z_loss.title = 'resolution_function' + z_loss.metadata['zero_loss_parameter']=p_zl + + dataset.metadata['low_loss']['zero_loss'] = {'zero_loss_parameter': p_zl, + 'zero_loss_fit': 'Product2Lorentzians'} + zero_loss = dataset.like_array(z_loss) + return zero_loss, p_zl
+ + + +
[docs]def resolution_function(energy_scale, spectrum, width, verbose=False): + """get resolution function (zero-loss peak shape) from low-loss spectrum""" + + guess = [0.2, 1000, 0.02, 0.2, 1000, 0.2] + p0 = np.array(guess) + + start = np.searchsorted(energy_scale, -width / 2.) + end = np.searchsorted(energy_scale, width / 2.) + x = energy_scale[start:end] + y = spectrum[start:end] + + def zl2(pp, yy, xx): + eerr = (yy - zl_func(pp, xx)) # /np.sqrt(y) + return eerr + + def zl_restrict(pp, yy, xx): + + if pp[2] > xx[-1] * .8: + pp[2] = xx[-1] * .8 + if pp[2] < xx[0] * .8: + pp[2] = xx[0] * .8 + + if pp[5] > xx[-1] * .8: + pp[5] = xx[-1] * .8 + if pp[5] < x[0] * .8: + pp[5] = xx[0] * .8 + + if len(pp) > 6: + pp[7] = abs(pp[7]) + if abs(pp[7]) > (pp[1] + pp[4]) / 10: + pp[7] = abs(pp[1] + pp[4]) / 10 + if abs(pp[8]) > 1: + pp[8] = pp[8] / abs(pp[8]) + pp[6] = abs(pp[6]) + pp[9] = abs(pp[9]) + + pp[0] = abs(pp[0]) + pp[3] = abs(pp[3]) + if pp[0] > (xx[-1] - xx[0]) / 2.0: + pp[0] = xx[-1] - xx[0] / 2.0 + if pp[3] > (xx[-1] - xx[0]) / 2.0: + pp[3] = xx[-1] - xx[0] / 2.0 + + yy[yy < 0] = 0. # no negative numbers in sqrt below + eerr = (yy - zl_func(pp, xx)) / np.sqrt(yy) + + return eerr + + [p_zl, _] = leastsq(zl2, p0, args=(y, x), maxfev=2000) + if verbose: + print('Fit of a Product of two Lorentzian') + print('Positions: ', p_zl[2], p_zl[5], 'Distance: ', p_zl[2] - p_zl[5]) + print('Width: ', p_zl[0], p_zl[3]) + print('Areas: ', p_zl[1], p_zl[4]) + err = (y - zl_func(p_zl, x)) / np.sqrt(y) + print(f'Goodness of Fit: {sum(err ** 2) / len(y) / sum(y) * 1e2:.5}%') + + z_loss = zl_func(p_zl, energy_scale) + + return z_loss, p_zl
+ + +
[docs]def get_energy_shifts(spectrum_image, energy_scale=None, zero_loss_fit_width=0.3): + """ get shift of spectrum from zero-loss peak position + better to use get resolution_functions + """ + resolution_functions = get_resolution_functions(spectrum_image, energy_scale=energy_scale, zero_loss_fit_width=zero_loss_fit_width) + return resolution_functions.metadata['low_loss']['shifts'], resolution_functions.metadata['low_loss']['widths']
+ +
[docs]def get_resolution_functions(spectrum_image, energy_scale=None, zero_loss_fit_width=0.3): + """get resolution_function and shift of spectra form zero-loss peak position""" + if isinstance(spectrum_image, sidpy.Dataset): + energy_dimension = spectrum_image.get_dimensions_by_type('spectral') + if len(energy_dimension) != 1: + raise TypeError('Dataset needs to have exactly one spectral dimension to analyze zero-loss peak') + energy_dimension = spectrum_image.get_dimension_by_number(energy_dimension)[0] + energy_scale = energy_dimension.values + spatial_dimension = spectrum_image.get_dimensions_by_type('spatial') + if len(spatial_dimension) == 0: + fwhm, delta_e = fix_energy_scale(spectrum_image) + z_loss, p_zl = resolution_function(energy_scale - delta_e, spectrum_image, zero_loss_fit_width) + fwhm2, delta_e2 = fix_energy_scale(z_loss, energy_scale - delta_e) + return delta_e + delta_e2, fwhm2 + elif len(spatial_dimension) != 2: + return + shifts = np.zeros(spectrum_image.shape[0:2]) + widths = np.zeros(spectrum_image.shape[0:2]) + resolution_functions = spectrum_image.copy() + for x in range(spectrum_image.shape[0]): + for y in range(spectrum_image.shape[1]): + spectrum = np.array(spectrum_image[x, y]) + fwhm, delta_e = fix_energy_scale(spectrum, energy_scale) + z_loss, p_zl = resolution_function(energy_scale - delta_e, spectrum, zero_loss_fit_width) + resolution_functions[x, y] = z_loss + fwhm2, delta_e2 = fix_energy_scale(z_loss, energy_scale - delta_e) + shifts[x, y] = delta_e + delta_e2 + widths[x,y] = fwhm2 + + resolution_functions.metadata['low_loss'] = {'shifts': shifts, + 'widths': widths} + return resolution_functions
+ + +
[docs]def shift_on_same_scale(spectrum_image, shifts=None, energy_scale=None, master_energy_scale=None): + """shift spectrum in energy""" + if isinstance(spectrum_image, sidpy.Dataset): + if shifts is None: + if 'low_loss' in spectrum_image.metadata: + if 'shifts' in spectrum_image.metadata['low_loss']: + shifts = spectrum_image.metadata['low_loss']['shifts'] + else: + resolution_functions = get_resolution_functions(spectrum_image) + shifts = resolution_functions.metadata['low_loss']['shifts'] + energy_dimension = spectrum_image.get_dimensions_by_type('spectral') + if len(energy_dimension) != 1: + raise TypeError('Dataset needs to have exactly one spectral dimension to analyze zero-loss peak') + energy_dimension = spectrum_image.get_dimension_by_number(energy_dimension)[0] + energy_scale = energy_dimension.values + master_energy_scale = energy_scale.copy() + + new_si = spectrum_image.copy() + new_si *= 0.0 + for x in range(spectrum_image.shape[0]): + for y in range(spectrum_image.shape[1]): + tck = interpolate.splrep(np.array(energy_scale - shifts[x, y]), np.array(spectrum_image[x, y]), k=1, s=0) + new_si[x, y, :] = interpolate.splev(master_energy_scale, tck, der=0) + return new_si
+ + +
[docs]def get_wave_length(e0): + """get deBroglie wavelength of electron accelerated by energy (in eV) e0""" + + ev = constants.e * e0 + return constants.h / np.sqrt(2 * constants.m_e * ev * (1 + ev / (2 * constants.m_e * constants.c ** 2)))
+ + +
[docs]def drude(peak_position, peak_width, gamma, energy_scale): + """dielectric function according to Drude theory""" + + eps = 1 - (peak_position ** 2 - peak_width * energy_scale * 1j) / (energy_scale ** 2 + 2 * energy_scale * gamma * 1j) # Mod drude term + return eps
+ + +
[docs]def drude_lorentz(eps_inf, leng, ep, eb, gamma, e, amplitude): + """dielectric function according to Drude-Lorentz theory""" + + eps = eps_inf + for i in range(leng): + eps = eps + amplitude[i] * (1 / (e + ep[i] + gamma[i] * 1j) - 1 / (e - ep[i] + gamma[i] * 1j)) + return eps
+ + +
[docs]def plot_dispersion(plotdata, units, a_data, e_data, title, max_p, ee, ef=4., ep=16.8, es=0, ibt=[]): + """Plot loss function """ + + [x, y] = np.meshgrid(e_data + 1e-12, a_data[1024:2048] * 1000) + + z = plotdata + lev = np.array([0.01, 0.05, 0.1, 0.25, 0.5, 1, 2, 3, 4, 4.9]) * max_p / 5 + + wavelength = get_wave_length(ee) + q = a_data[1024:2048] / (wavelength * 1e9) # in [1/nm] + scale = np.array([0, a_data[-1], e_data[0], e_data[-1]]) + ev2hertz = constants.value('electron volt-hertz relationship') + + if units[0] == 'mrad': + units[0] = 'scattering angle [mrad]' + scale[1] = scale[1] * 1000. + light_line = constants.c * a_data # for mrad + elif units[0] == '1/nm': + units[0] = 'scattering vector [1/nm]' + scale[1] = scale[1] / (wavelength * 1e9) + light_line = 1 / (constants.c / ev2hertz) * 1e-9 + + if units[1] == 'eV': + units[1] = 'energy loss [eV]' + + if units[2] == 'ppm': + units[2] = 'probability [ppm]' + if units[2] == '1/eV': + units[2] = 'probability [eV$^{-1}$ srad$^{-1}$]' + + alpha = 3. / 5. * ef / ep + + ax2 = plt.gca() + fig2 = plt.gcf() + im = ax2.imshow(z.T, clim=(0, max_p), origin='lower', aspect='auto', extent=scale) + co = ax2.contour(y, x, z, levels=lev, colors='k', origin='lower') + # ,extent=(-ang*1000.,ang*1000.,e_data[0],e_data[-1]))#, vmin = p_vol.min(), vmax = 1000) + + fig2.colorbar(im, ax=ax2, label=units[2]) + + ax2.plot(a_data, light_line, c='r', label='light line') + # ax2.plot(e_data*light_line*np.sqrt(np.real(eps_data)),e_data, color='steelblue', + # label='$\omega = c q \sqrt{\epsilon_2}$') + + # ax2.plot(q, Ep_disp, c='r') + ax2.plot([11.5 * light_line, 0.12], [11.5, 11.5], c='r') + + ax2.text(.05, 11.7, 'surface plasmon', color='r') + ax2.plot([0.0, 0.12], [16.8, 16.8], c='r') + ax2.text(.05, 17, 'volume plasmon', color='r') + ax2.set_xlim(0, scale[1]) + ax2.set_ylim(0, 20) + # Interband transitions + ax2.plot([0.0, 0.25], [4.2, 4.2], c='g', label='interband transitions') + ax2.plot([0.0, 0.25], [5.2, 5.2], c='g') + ax2.set_ylabel(units[1]) + ax2.set_xlabel(units[0]) + ax2.legend(loc='lower right')
+ + +
[docs]def zl_func(p, x): + """zero-loss peak function""" + + p[0] = abs(p[0]) + + gauss1 = np.zeros(len(x)) + gauss2 = np.zeros(len(x)) + lorentz3 = np.zeros(len(x)) + lorentz = ((0.5 * p[0] * p[1] / 3.14) / ((x - p[2]) ** 2 + ((p[0] / 2) ** 2))) + lorentz2 = ((0.5 * p[3] * p[4] / 3.14) / ((x - (p[5])) ** 2 + ((p[3] / 2) ** 2))) + if len(p) > 6: + lorentz3 = (0.5 * p[6] * p[7] / 3.14) / ((x - p[8]) ** 2 + (p[6] / 2) ** 2) + gauss2 = p[10] * np.exp(-(x - p[11]) ** 2 / (2.0 * (p[9] / 2.3548) ** 2)) + # ((0.5 * p[9]* p[10]/3.14)/((x- (p[11]))**2+(( p[9]/2)**2))) + y = (lorentz * lorentz2) + gauss1 + gauss2 + lorentz3 + + return y
+ + +
[docs]def drude2(tags, e, p): + """dielectric function according to Drude theory for fitting""" + + return drude(e, p[0], p[1], p[2], p[3])
+ + +
[docs]def xsec_xrpa(energy_scale, e0, z, beta, shift=0): + """ Calculate momentum-integrated cross-section for EELS from X-ray photo-absorption cross-sections. + + X-ray photo-absorption cross-sections from NIST. + Momentum-integrated cross-section for EELS according to Egerton Ultramicroscopy 50 (1993) 13-28 equation (4) + + Parameters + ---------- + energy_scale: numpy array + energy scale of spectrum to be analyzed + e0: float + acceleration voltage in keV + z: int + atomic number of element + beta: float + effective collection angle in mrad + shift: float + chemical shift of edge in eV + """ + beta = beta * 0.001 # collection half angle theta [rad] + # theta_max = self.parent.spec[0].convAngle * 0.001 # collection half angle theta [rad] + dispersion = energy_scale[1] - energy_scale[0] + + x_sections = get_x_sections(z) + enexs = x_sections['ene'] + datxs = x_sections['dat'] + + # enexs = enexs[:len(datxs)] + + ##### + # Cross Section according to Egerton Ultramicroscopy 50 (1993) 13-28 equation (4) + ##### + + # Relativistic correction factors + t = 511060.0 * (1.0 - 1.0 / (1.0 + e0 / 511.06) ** 2) / 2.0 + gamma = 1 + e0 / 511.06 + a = 6.5 # e-14 *10**14 + b = beta + + theta_e = enexs / (2 * gamma * t) + + g = 2 * np.log(gamma) - np.log((b ** 2 + theta_e ** 2) / (b ** 2 + theta_e ** 2 / gamma ** 2)) - ( + gamma - 1) * b ** 2 / (b ** 2 + theta_e ** 2 / gamma ** 2) + datxs = datxs * (a / enexs / t) * (np.log(1 + b ** 2 / theta_e ** 2) + g) / 1e8 + + datxs = datxs * dispersion # from per eV to per dispersion + coeff = splrep(enexs, datxs, s=0) # now in areal density atoms / m^2 + xsec = np.zeros(len(energy_scale)) + # shift = 0# int(ek -onsetXRPS)#/dispersion + lin = interp1d(enexs, datxs, kind='linear') # Linear instead of spline interpolation to avoid oscillations. + if energy_scale[0] < enexs[0]: + start = np.searchsorted(energy_scale, enexs[0])+1 + else: + start = 0 + xsec[start:] = lin(energy_scale[start:] - shift) + + return xsec
+ + +
[docs]def drude_simulation(dset, e, ep, ew, tnm, eb): + """probabilities of dielectric function eps relative to zero-loss integral (i0 = 1) + + Gives probabilities of dielectric function eps relative to zero-loss integral (i0 = 1) per eV + Details in R.F.Egerton: EELS in the Electron Microscope, 3rd edition, Springer 2011 + + # function drude(ep,ew,eb,epc,e0,beta,nn,tnm) + # Given the plasmon energy (ep), plasmon fwhm (ew) and binding energy(eb), + # this program generates: + # EPS1, EPS2 from modified Eq. (3.40), ELF=Im(-1/EPS) from Eq. (3.42), + # single scattering from Eq. (4.26) and SRFINT from Eq. (4.31) + # The output is e, ssd into the file drude.ssd (for use in Flog etc.) + # and e,eps1 ,eps2 into drude.eps (for use in Kroeger etc.) + # Gives probabilities relative to zero-loss integral (i0 = 1) per eV + # Details in R.F.Egerton: EELS in the Electron Microscope, 3rd edition, Springer 2011 + # Version 10.11.26 + + + b.7 drude Simulation of a Low-Loss Spectrum + The program DRUDE calculates a single-scattering plasmon-loss spectrum for + a specimen of a given thickness tnm (in nm), recorded with electrons of a + specified incident energy e0 by a spectrometer that accepts scattering up to a + specified collection semi-angle beta. It is based on the extended drude model + (Section 3.3.2), with a volume energy-loss function elf in accord with Eq. (3.64) and + a surface-scattering energy-loss function srelf as in Eq. (4.31). Retardation effects + and coupling between the two surface modes are not included. The surface term can + be made negligible by entering a large specimen thickness (tnm > 1000). + Surface intensity srfint and volume intensity volint are calculated from + Eqs. (4.31) and (4.26), respectively. The total spectral intensity ssd is written to + the file DRUDE.SSD, which can be used as input for KRAKRO. These intensities are + all divided by i0, to give relative probabilities (per eV). The real and imaginary parts + of the dielectric function are written to DRUDE.EPS and can be used for comparison + with the results of Kramers–Kronig analysis (KRAKRO.DAT). + Written output includes the surface-loss probability Ps, obtained by integrating + srfint (a value that relates to two surfaces but includes the negative begrenzungs + term), for comparison with the analytical integration represented by Eq. (3.77). The + volume-loss probability p_v is obtained by integrating volint and is used to calculate + the volume plasmon mean free path (lam = tnm/p_v). The latter is listed and + compared with the MFP obtained from Eq. (3.44), which represents analytical integration + assuming a zero-width plasmon peak. The total probability (Pt = p_v+Ps) is + calculated and used to evaluate the thickness (lam.Pt) that would be given by the formula + t/λ = ln(It/i0), ignoring the surface-loss probability. Note that p_v will exceed + 1 for thicker specimens (t/λ > 1), since it represents the probability of plasmon + scattering relative to that of no inelastic scattering. + The command-line usage is drude(ep,ew,eb,epc,beta,e0,tnm,nn), where ep is the + plasmon energy, ew the plasmon width, eb the binding energy of the electrons (0 for + a metal), and nn is the number of channels in the output spectrum. An example of + the output is shown in Fig. b.1a,b. + + """ + + epc = dset.energy_scale[1] - dset.energy_scale[0] # input('ev per channel : '); + + b = dset.metadata['collection_angle']/ 1000. # rad + epc = dset.energy_scale[1] - dset.energy_scale[0] # input('ev per channel : '); + 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(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 = 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 / epc # S probability per channel + ssd = volint # + srfint; + + if e[0] < -1.0: + xs = int(abs(-e[0] / epc)) + + 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 + (b * 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
+ + +
[docs]def effective_collection_angle(energy_scale, alpha, beta, beam_kv): + """Calculates the effective collection angle in mrad: + + Translate from original Fortran program + Calculates the effective collection angle in mrad: + Parameter + --------- + energy_scale: numpy array + first and last energy loss of spectrum in eV + alpha: float + convergence angle in mrad + beta: float + collection angle in mrad + beamKV: float + acceleration voltage in V + + Returns + ------- + eff_beta: float + effective collection angle in mrad + + # function y = effbeta(ene, alpha, beta, beam_kv) + # + # This program computes etha(alpha,beta), that is the collection + # efficiency associated to the following geometry : + # + # alpha = half angle of illumination (0 -> pi/2) + # beta = half angle of collection (0 -> pi/2) + # (pi/2 = 1570.795 mrad) + # + # A constant angular distribution of incident electrons is assumed + # for any incident angle (-alpha,alpha). These electrons imping the + # target and a single energy-loss event occurs, with a characteristic + # angle theta-e (relativistic). The angular distribution of the + # electrons after the target is analytically derived. + # This program integrates this distribution from theta=0 up to + # theta=beta with an adjustable angular step. + # This program also computes beta* which is the theoretical + # collection angle which would give the same value of etha(alpha,beta) + # with a parallel incident beam. + # + # subroutines and function subprograms required + # --------------------------------------------- + # none + # + # comments + # -------- + # + # The following parameters are asked as input : + # accelerating voltage (kV), energy loss range (eV) for the study, + # energy loss step (eV) in this range, alpha (mrad), beta (mrad). + # The program returns for each energy loss step : + # alpha (mrad), beta (mrad), theta-e (relativistic) (mrad), + # energy loss (eV), etha (#), beta * (mrad) + # + # author : + # -------- + # Pierre TREBBIA + # US 41 : "Microscopie Electronique Analytique Quantitative" + # Laboratoire de Physique des Solides, Bat. 510 + # Universite Paris-Sud, F91405 ORSAY Cedex + # Phone : (33-1) 69 41 53 68 + # + """ + if beam_kv == 0: + beam_kv = 100.0 + + if alpha == 0: + return beta + + if beta == 0: + return alpha + + z1 = beam_kv # eV + z2 = energy_scale[0] + z3 = energy_scale[-1] + z4 = 100.0 + + z5 = alpha * 0.001 # rad + z6 = beta * 0.001 # rad + z7 = 500.0 # number of integration steps to be modified at will + + # main loop on energy loss + # + for zx in range(int(z2), int(z3), int(z4)): # ! zx = current energy loss + eta = 0.0 + x0 = float(zx) * (z1 + 511060.) / (z1 * (z1 + 1022120.)) # x0 = relativistic theta-e + x1 = np.pi / (2. * x0) + x2 = x0 * x0 + z5 * z5 + x3 = z5 / x0 * z5 / x0 + x4 = 0.1 * np.sqrt(x2) + dtheta = (z6 - x4) / z7 + # + # calculation of the analytical expression + # + for zi in range(1, int(z7)): + theta = x4 + dtheta * float(zi) + x5 = theta * theta + x6 = 4. * x5 * x0 * x0 + x7 = x2 - x5 + x8 = np.sqrt(x7 * x7 + x6) + x9 = (x8 + x7) / (2. * x0 * x0) + x10 = 2. * theta * dtheta * np.log(x9) + eta = eta + x10 + + eta = eta + x2 / 100. * np.log(1. + x3) # addition of the central contribution + x4 = z5 * z5 * np.log(1. + x1 * x1) # normalisation + eta = eta / x4 + # + # correction by geometrical factor (beta/alpha)**2 + # + if z6 < z5: + x5 = z5 / z6 + eta = eta * x5 * x5 + + etha2 = eta * 100. + # + # calculation of beta * + # + x6 = np.power((1. + x1 * x1), eta) + x7 = x0 * np.sqrt(x6 - 1.) + beta = x7 * 1000. # in mrad + + return beta
+ + +
[docs]def kroeger_core(e_data, a_data, eps_data, ee, thick, relativistic=True): + """This function calculates the differential scattering probability + + .. math:: + \\frac{d^2P}{d \\Omega d_e} + of the low-loss region for total loss and volume plasmon loss + + Args: + e_data (array): energy scale [eV] + a_data (array): angle or momentum range [rad] + eps_data (array): dielectric function data + ee (float): acceleration voltage [keV] + thick (float): thickness in m + relativistic: boolean include relativistic corrections + + Returns: + P (numpy array 2d): total loss probability + p_vol (numpy array 2d): volume loss probability + """ + + # $d^2P/(dEd\Omega) = \frac{1}{\pi^2 a_0 m_0 v^2} \Im \left[ \frac{t\mu^2}{\varepsilon \phi^2 } \right] $ \ + + # ee = 200 #keV + # thick = 32.0# nm + thick = thick * 1e-9 # input thickness now in m + # Define constants + # ec = 14.4; + m_0 = constants.value(u'electron mass') # REST electron mass in kg + # h = constants.Planck # Planck's constant + hbar = constants.hbar + + c = constants.speed_of_light # speed of light m/s + bohr = constants.value(u'Bohr radius') # Bohr radius in meters + e = constants.value(u'elementary charge') # electron charge in Coulomb + print('hbar =', hbar, ' [Js] =', hbar / e, '[ eV s]') + + # Calculate fixed terms of equation + va = 1 - (511. / (511. + ee)) ** 2 # ee is incident energy in keV + v = c * np.sqrt(va) + beta = v / c # non-relativistic for =1 + + if relativistic: + gamma = 1. / np.sqrt(1 - beta ** 2) + else: + gamma = 1 # set = 1 to correspond to E+B & Siegle + + momentum = m_0 * v * gamma # used for xya, E&B have no gamma + + # ##### Define mapped variables + + # Define independent variables E, theta + a_data = np.array(a_data) + e_data = np.array(e_data) + [energy, theta] = np.meshgrid(e_data + 1e-12, a_data) + # Define CONJUGATE dielectric function variable eps + [eps, _] = np.meshgrid(np.conj(eps_data), a_data) + + # ##### Calculate lambda in equation EB 2.3 + theta2 = theta ** 2 + 1e-15 + theta_e = energy * e / momentum / v + theta_e2 = theta_e ** 2 + + lambda2 = theta2 - eps * theta_e2 * beta ** 2 # Eq 2.3 + + lambd = np.sqrt(lambda2) + if (np.real(lambd) < 0).any(): + print(' error negative lambda') + + # ##### Calculate lambda0 in equation EB 2.4 + # According to Kröger real(lambda0) is defined as positive! + + phi2 = lambda2 + theta_e2 # Eq. 2.2 + lambda02 = theta2 - theta_e2 * beta ** 2 # eta=1 Eq 2.4 + lambda02[lambda02 < 0] = 0 + lambda0 = np.sqrt(lambda02) + if not (np.real(lambda0) >= 0).any(): + print(' error negative lambda0') + + de = thick * energy * e / 2.0 / hbar / v # Eq 2.5 + + xya = lambd * de / theta_e # used in Eqs 2.6, 2.7, 4.4 + + lplus = lambda0 * eps + lambd * np.tanh(xya) # eta=1 %Eq 2.6 + lminus = lambda0 * eps + lambd / np.tanh(xya) # eta=1 %Eq 2.7 + + mue2 = 1 - (eps * beta ** 2) # Eq. 4.5 + phi20 = lambda02 + theta_e2 # Eq 4.6 + phi201 = theta2 + theta_e2 * (1 - (eps + 1) * beta ** 2) # eta=1, eps-1 in E+B Eq.(4.7) + + # Eq 4.2 + a1 = phi201 ** 2 / eps + a2 = np.sin(de) ** 2 / lplus + np.cos(de) ** 2 / lminus + a = a1 * a2 + + # Eq 4.3 + b1 = beta ** 2 * lambda0 * theta_e * phi201 + b2 = (1. / lplus - 1. / lminus) * np.sin(2. * de) + b = b1 * b2 + + # Eq 4.4 + c1 = -beta ** 4 * lambda0 * lambd * theta_e2 + c2 = np.cos(de) ** 2 * np.tanh(xya) / lplus + c3 = np.sin(de) ** 2 / np.tanh(xya) / lminus + c = c1 * (c2 + c3) + + # Put all the pieces together... + p_coef = e / (bohr * np.pi ** 2 * m_0 * v ** 2) + + p_v = thick * mue2 / eps / phi2 + + p_s1 = 2. * theta2 * (eps - 1) ** 2 / phi20 ** 2 / phi2 ** 2 # ASSUMES eta=1 + p_s2 = hbar / momentum + p_s3 = a + b + c + + p_s = p_s1 * p_s2 * p_s3 + + # print(p_v.min(),p_v.max(),p_s.min(),p_s.max()) + # Calculate P and p_vol (volume only) + dtheta = a_data[1] - a_data[0] + scale = np.sin(np.abs(theta)) * dtheta * 2 * np.pi + + p = p_coef * np.imag(p_v - p_s) # Eq 4.1 + p_vol = p_coef * np.imag(p_v) * scale + + # lplus_min = e_data[np.argmin(np.real(lplus), axis=1)] + # lminus_min = e_data[np.argmin(np.imag(lminus), axis=1)] + + p_simple = p_coef * np.imag(1 / eps) * thick / ( + theta2 + theta_e2) * scale # Watch it eps is conjugated dielectric function + + return p, p * scale * 1e2, p_vol * 1e2, p_simple * 1e2 # ,lplus_min,lminus_min
+ + +
[docs]def kroeger_core2(e_data, a_data, eps_data, acceleration_voltage_kev, thickness, relativistic=True): + """This function calculates the differential scattering probability + + .. math:: + \\frac{d^2P}{d \\Omega d_e} + of the low-loss region for total loss and volume plasmon loss + + Args: + e_data (array): energy scale [eV] + a_data (array): angle or momentum range [rad] + eps_data (array) dielectric function + acceleration_voltage_kev (float): acceleration voltage [keV] + thickness (float): thickness in nm + relativistic (boolean): relativistic correction + + Returns: + P (numpy array 2d): total loss probability + p_vol (numpy array 2d): volume loss probability + + return P, P*scale*1e2,p_vol*1e2, p_simple*1e2 + """ + + # $d^2P/(dEd\Omega) = \frac{1}{\pi^2 a_0 m_0 v^2} \Im \left[ \frac{t\mu^2}{\varepsilon \phi^2 } \right] + """ + # Internally everything is calculated in si units + # acceleration_voltage_kev = 200 #keV + # thick = 32.0*10-9 # m + + """ + a_data = np.array(a_data) + e_data = np.array(e_data) + # adjust input to si units + wavelength = get_wave_length(acceleration_voltage_kev * 1e3) # in m + thickness = thickness * 1e-9 # input thickness now in m + + # Define constants + # ec = 14.4; + m_0 = constants.value(u'electron mass') # REST electron mass in kg + # h = constants.Planck # Planck's constant + hbar = constants.hbar + + c = constants.speed_of_light # speed of light m/s + bohr = constants.value(u'Bohr radius') # Bohr radius in meters + e = constants.value(u'elementary charge') # electron charge in Coulomb + # print('hbar =', hbar ,' [Js] =', hbar/e ,'[ eV s]') + + # Calculate fixed terms of equation + va = 1 - (511. / (511. + acceleration_voltage_kev)) ** 2 # acceleration_voltage_kev is incident energy in keV + v = c * np.sqrt(va) + + if relativistic: + beta = v / c # non-relativistic for =1 + gamma = 1. / np.sqrt(1 - beta ** 2) + else: + beta = 1 + gamma = 1 # set = 1 to correspond to E+B & Siegle + + momentum = m_0 * v * gamma # used for xya, E&B have no gamma + + # ##### Define mapped variables + + # Define independent variables E, theta + [energy, theta] = np.meshgrid(e_data + 1e-12, a_data) + # Define CONJUGATE dielectric function variable eps + [eps, _] = np.meshgrid(np.conj(eps_data), a_data) + + # ##### Calculate lambda in equation EB 2.3 + theta2 = theta ** 2 + 1e-15 + + theta_e = energy * e / momentum / v # critical angle + + lambda2 = theta2 - eps * theta_e ** 2 * beta ** 2 # Eq 2.3 + + lambd = np.sqrt(lambda2) + if (np.real(lambd) < 0).any(): + print(' error negative lambda') + + # ##### Calculate lambda0 in equation EB 2.4 + # According to Kröger real(lambda0) is defined as positive! + + phi2 = lambda2 + theta_e ** 2 # Eq. 2.2 + lambda02 = theta2 - theta_e ** 2 * beta ** 2 # eta=1 Eq 2.4 + lambda02[lambda02 < 0] = 0 + lambda0 = np.sqrt(lambda02) + if not (np.real(lambda0) >= 0).any(): + print(' error negative lambda0') + + de = thickness * energy * e / (2.0 * hbar * v) # Eq 2.5 + xya = lambd * de / theta_e # used in Eqs 2.6, 2.7, 4.4 + + lplus = lambda0 * eps + lambd * np.tanh(xya) # eta=1 %Eq 2.6 + lminus = lambda0 * eps + lambd / np.tanh(xya) # eta=1 %Eq 2.7 + + mue2 = 1 - (eps * beta ** 2) # Eq. 4.5 + phi20 = lambda02 + theta_e ** 2 # Eq 4.6 + phi201 = theta2 + theta_e ** 2 * (1 - (eps + 1) * beta ** 2) # eta=1, eps-1 in E+b Eq.(4.7) + + # Eq 4.2 + a1 = phi201 ** 2 / eps + a2 = np.sin(de) ** 2 / lplus + np.cos(de) ** 2 / lminus + a = a1 * a2 + + # Eq 4.3 + b1 = beta ** 2 * lambda0 * theta_e * phi201 + b2 = (1. / lplus - 1. / lminus) * np.sin(2. * de) + b = b1 * b2 + + # Eq 4.4 + c1 = -beta ** 4 * lambda0 * lambd * theta_e ** 2 + c2 = np.cos(de) ** 2 * np.tanh(xya) / lplus + c3 = np.sin(de) ** 2 / np.tanh(xya) / lminus + c = c1 * (c2 + c3) + + # Put all the pieces together... + p_coef = e / (bohr * np.pi ** 2 * m_0 * v ** 2) + + p_v = thickness * mue2 / eps / phi2 + + p_s1 = 2. * theta2 * (eps - 1) ** 2 / phi20 ** 2 / phi2 ** 2 # ASSUMES eta=1 + p_s2 = hbar / momentum + p_s3 = a + b + c + + p_s = p_s1 * p_s2 * p_s3 + + # print(p_v.min(),p_v.max(),p_s.min(),p_s.max()) + # Calculate P and p_vol (volume only) + dtheta = a_data[1] - a_data[0] + scale = np.sin(np.abs(theta)) * dtheta * 2 * np.pi + + p = p_coef * np.imag(p_v - p_s) # Eq 4.1 + p_vol = p_coef * np.imag(p_v) * scale + + # lplus_min = e_data[np.argmin(np.real(lplus), axis=1)] + # lminus_min = e_data[np.argmin(np.imag(lminus), axis=1)] + + p_simple = p_coef * np.imag(1 / eps) * thickness / (theta2 + theta_e ** 2) * scale + # Watch it: eps is conjugated dielectric function + + return p, p * scale * 1e2, p_vol * 1e2, p_simple * 1e2 # ,lplus_min,lminus_min
+ + +########################## +# EELS Database +########################## + + +
[docs]def read_msa(msa_string): + """read msa formated file""" + parameters = {} + y = [] + x = [] + # Read the keywords + data_section = False + msa_lines = msa_string.split('\n') + + for line in msa_lines: + if data_section is False: + if len(line) > 0: + if line[0] == "#": + try: + key, value = line.split(': ') + value = value.strip() + except ValueError: + key = line + value = None + key = key.strip('#').strip() + + if key != 'SPECTRUM': + parameters[key] = value + else: + data_section = True + else: + # Read the data + + if len(line) > 0 and line[0] != "#" and line.strip(): + if parameters['DATATYPE'] == 'XY': + xy = line.replace(',', ' ').strip().split() + y.append(float(xy[1])) + x.append(float(xy[0])) + elif parameters['DATATYPE'] == 'Y': + print('y') + data = [ + float(i) for i in line.replace(',', ' ').strip().split()] + y.extend(data) + parameters['data'] = np.array(y) + if 'XPERCHAN' in parameters: + parameters['XPERCHAN'] = str(parameters['XPERCHAN']).split(' ')[0] + parameters['OFFSET'] = str(parameters['OFFSET']).split(' ')[0] + parameters['energy_scale'] = np.arange(len(y)) * float(parameters['XPERCHAN']) + float(parameters['OFFSET']) + return parameters
+ + +
[docs]def get_spectrum_eels_db(formula=None, edge=None, title=None, element=None): + """ + get spectra from EELS database + chemical formula and edge is accepted. + Could expose more of the search parameters + """ + valid_edges = ['K', 'L1', 'L2,3', 'M2,3', 'M4,5', 'N2,3', 'N4,5', 'O2,3', 'O4,5'] + if edge is not None and edge not in valid_edges: + print('edge should be a in ', valid_edges) + + spectrum_type = None + title = title + author = None + element = element + min_energy = None + max_energy = None + resolution = None + min_energy_compare = "gt" + max_energy_compare = "lt", + resolution_compare = "lt" + max_n = -1 + monochromated = None + order = None + order_direction = "ASC" + verify_certificate = True + # Verify arguments + + if spectrum_type is not None and spectrum_type not in {'coreloss', 'lowloss', 'zeroloss', 'xrayabs'}: + raise ValueError("spectrum_type must be one of \'coreloss\', \'lowloss\', " + "\'zeroloss\', \'xrayabs\'.") + # valid_edges = ['K', 'L1', 'L2,3', 'M2,3', 'M4,5', 'N2,3', 'N4,5', 'O2,3', 'O4,5'] + + params = { + "type": spectrum_type, + "title": title, + "author": author, + "edge": edge, + "min_energy": min_energy, + "max_energy": max_energy, + "resolution": resolution, + "resolution_compare": resolution_compare, + "monochromated": monochromated, + "formula": formula, + 'element': element, + "min_energy_compare": min_energy_compare, + "max_energy_compare": max_energy_compare, + "per_page": max_n, + "order": order, + "order_direction": order_direction, + } + + request = requests.get('http://api.eelsdb.eu/spectra', params=params, verify=True) + # spectra = [] + jsons = request.json() + if "message" in jsons: + # Invalid query, EELSdb raises error. + raise IOError( + "Please report the following error to the HyperSpy developers: " + "%s" % jsons["message"]) + reference_spectra = {} + for json_spectrum in jsons: + download_link = json_spectrum['download_link'] + # print(download_link) + msa_string = requests.get(download_link, verify=verify_certificate).text + # print(msa_string[:100]) + parameters = read_msa(msa_string) + if 'XPERCHAN' in parameters: + reference_spectra[parameters['TITLE']] = parameters + print(parameters['TITLE']) + print(f'found {len(reference_spectra.keys())} spectra in EELS database)') + + return reference_spectra
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/file_tools.html b/_modules/pyTEMlib/file_tools.html new file mode 100644 index 00000000..58348ce4 --- /dev/null +++ b/_modules/pyTEMlib/file_tools.html @@ -0,0 +1,1383 @@ + + + + + + pyTEMlib.file_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.file_tools

+"""file_tools: All tools to load and save data
+
+##################################
+
+ 2018 01 31 Included Nion Swift files to be opened
+ major revision 2020 09 to include sidpy and pyNSID data formats
+ 2022 change to ase format for structures: this changed the default unit of length to Angstrom!!!
+
+##################################
+"""
+
+import numpy as np
+import h5py
+import os
+import pickle
+
+# For structure files of various flavor for instance POSCAR and other theory packages
+import ase.io
+
+# =============================================
+#   Include  pycroscopy libraries                                      #
+# =============================================
+import SciFiReaders
+import pyNSID
+import sidpy
+import ipywidgets as widgets
+from IPython.display import display
+
+# =============================================
+#   Include  pyTEMlib libraries                                      #
+# =============================================
+import pyTEMlib.crystal_tools
+from pyTEMlib.config_dir import config_path
+from pyTEMlib.sidpy_tools import *
+
+from pyTEMlib.sidpy_tools import *
+
+Qt_available = True
+try:
+    from PyQt5 import QtCore, QtWidgets, QtGui
+except ModuleNotFoundError:
+    print('Qt dialogs are not available')
+    Qt_available = False
+
+Dimension = sidpy.Dimension
+
+get_slope = sidpy.base.num_utils.get_slope
+__version__ = '2022.3.3'
+
+
+
[docs]class FileWidget(object): + """Widget to select directories or widgets from a list + + Works in google colab. + The widget converts the name of the nion file to the one in Nion's swift software, + because it is otherwise incomprehensible + + Attributes + ---------- + dir_name: str + name of starting directory + extension: list of str + extensions of files to be listed in widget + + Methods + ------- + get_directory + set_options + get_file_name + + Example + ------- + >>from google.colab import drive + >>drive.mount("/content/drive") + >>file_list = pyTEMlib.file_tools.FileWidget() + next code cell: + >>dataset = pyTEMlib.file_tools.open_file(file_list.file_name) + + """ + + def __init__(self, dir_name=None, extension=['*']): + self.save_path = False + self.dir_dictionary = {} + self.dir_list = ['.', '..'] + self.display_list = ['.', '..'] + + self.dir_name = '.' + if dir_name is None: + self.dir_name = get_last_path() + self.save_path = True + elif os.path.isdir(dir_name): + self.dir_name = dir_name + + self.get_directory(self.dir_name) + self.dir_list = ['.'] + self.extensions = extension + self.file_name = '' + self.datasets ={} + self.dataset = None + + self.select_files = widgets.Select( + options=self.dir_list, + value=self.dir_list[0], + description='Select file:', + disabled=False, + rows=10, + layout=widgets.Layout(width='70%') + ) + + select_button = widgets.Button(description='Select Main', + layout=widgets.Layout(width='auto', grid_area='header'), + style=widgets.ButtonStyle(button_color='lightblue')) + + add_button = widgets.Button(description='Add', + layout=widgets.Layout(width='auto', grid_area='header'), + style=widgets.ButtonStyle(button_color='lightblue')) + + self.path_choice = widgets.Dropdown(options=['None'], + value='None', + description='directory:', + disabled=False, + button_style='', + layout=widgets.Layout(width='90%')) + self.dataset_list = ['None'] + self.loaded_datasets = widgets.Dropdown(options=self.dataset_list, + value=self.dataset_list[0], + description='loaded datasets:', + disabled=False, + button_style='') + + self.set_options() + ui = widgets.VBox([self.path_choice, self.select_files, widgets.HBox([select_button, add_button, self.loaded_datasets])]) + display(ui) + + self.select_files.observe(self.get_file_name, names='value') + self.path_choice.observe(self.set_dir, names='value') + + select_button.on_click(self.select_main) + add_button.on_click(self.add_dataset) + self.loaded_datasets.observe(self.selected_dataset) + + def select_main(self, value=0): + self.datasets = {} + self.loaded_datasets.value = self.dataset_list[0] + self.dataset_list = [] + #self.loaded_datasets.options = self.dataset_list + + self.datasets = open_file(self.file_name) + self.dataset_list = [] + for key in self.datasets.keys(): + self.dataset_list.append(f'{key}: {self.datasets[key].title}') + self.loaded_datasets.options = self.dataset_list + self.loaded_datasets.value = self.dataset_list[0] + self.dataset = self.datasets[list(self.datasets.keys())[0]] + self.selected_dataset = self.dataset + + def add_dataset(self, value=0): + key = add_dataset_from_file(self.datasets, self.file_name, 'Channel') + self.dataset_list.append(f'{key}: {self.datasets[key].title}') + self.loaded_datasets.options = self.dataset_list + self.loaded_datasets.value = self.dataset_list[-1] + +
[docs] def get_directory(self, directory=None): + self.dir_name = directory + self.dir_dictionary = {} + self.dir_list = [] + self.dir_list = ['.', '..'] + os.listdir(directory)
+ + def set_dir(self, value=0): + self.dir_name = self.path_choice.value + self.select_files.index = 0 + self.set_options() + + def selected_dataset(self, value=0): + + key = self.loaded_datasets.value.split(':')[0] + if key != 'None': + self.selected_dataset = self.datasets[key] + +
[docs] def set_options(self): + self.dir_name = os.path.abspath(os.path.join(self.dir_name, self.dir_list[self.select_files.index])) + dir_list = os.listdir(self.dir_name) + file_dict = update_directory_list(self.dir_name) + + sort = np.argsort(file_dict['directory_list']) + self.dir_list = ['.', '..'] + self.display_list = ['.', '..'] + for j in sort: + self.display_list.append(f" * {file_dict['directory_list'][j]}") + self.dir_list.append(file_dict['directory_list'][j]) + + sort = np.argsort(file_dict['display_file_list']) + + for i, j in enumerate(sort): + if '--' in dir_list[j]: + self.display_list.append(f" {i:3} {file_dict['display_file_list'][j]}") + else: + self.display_list.append(f" {i:3} {file_dict['display_file_list'][j]}") + self.dir_list.append(file_dict['file_list'][j]) + + self.dir_label = os.path.split(self.dir_name)[-1] + ':' + self.select_files.options = self.display_list + + path = self.dir_name + old_path = ' ' + path_list = [] + while path != old_path: + path_list.append(path) + old_path = path + path = os.path.split(path)[0] + self.path_choice.options = path_list + self.path_choice.value = path_list[0]
+ +
[docs] def get_file_name(self, b): + + if os.path.isdir(os.path.join(self.dir_name, self.dir_list[self.select_files.index])): + self.set_options() + + elif os.path.isfile(os.path.join(self.dir_name, self.dir_list[self.select_files.index])): + self.file_name = os.path.join(self.dir_name, self.dir_list[self.select_files.index])
+ + +
[docs]class ChooseDataset(object): + """Widget to select dataset object """ + + def __init__(self, input_object, show_dialog=True): + self.datasets = None + if isinstance(input_object, sidpy.Dataset): + if isinstance(input_object.h5_dataset, h5py.Dataset): + self.current_channel = input_object.h5_dataset.parent + elif isinstance(input_object, h5py.Group): + self.current_channel = input_object + elif isinstance(input_object, h5py.Dataset): + self.current_channel = input_object.parent + elif isinstance(input_object, dict): + self.datasets = input_object + else: + raise ValueError('Need hdf5 group or sidpy Dataset to determine image choices') + self.dataset_names = [] + self.dataset_list = [] + self.dataset_type = None + self.dataset = None + if not isinstance(self.datasets, dict): + self.reader = SciFiReaders.NSIDReader(self.current_channel.file.filename) + else: + self.reader = None + self.get_dataset_list() + self.select_image = widgets.Dropdown(options=self.dataset_list, + value=self.dataset_list[0], + description='select dataset:', + disabled=False, + button_style='') + if show_dialog: + display(self.select_image) + + self.select_image.observe(self.set_dataset, names='value') + self.set_dataset(0) + self.select_image.index = (len(self.dataset_names) - 1) + +
[docs] def get_dataset_list(self): + """ Get by Log number sorted list of datasets""" + if not isinstance(self.datasets, dict): + dataset_list = self.reader.read() + self.datasets = {} + for dataset in dataset_list: + self.datasets[dataset.title] = dataset + order = [] + keys = [] + for title, dset in self.datasets.items(): + if isinstance(dset, sidpy.Dataset): + if self.dataset_type is None or dset.data_type == self.data_type: + if 'Log' in title: + order.append(2) + else: + order.append(0) + keys.append(title) + for index in np.argsort(order): + self.dataset_names.append(keys[index]) + self.dataset_list.append(keys[index] + ': ' + self.datasets[keys[index]].title)
+ + def set_dataset(self, b): + index = self.select_image.index + self.key = self.dataset_names[index] + self.dataset = self.datasets[self.key] + self.dataset.title = self.dataset.title.split('/')[-1] + self.dataset.title = self.dataset.title.split('/')[-1]
+ + +
[docs]def add_to_dict(file_dict, name): + full_name = os.path.join(file_dict['directory'], name) + basename, extension = os.path.splitext(name) + size = os.path.getsize(full_name) * 2 ** -20 + display_name = name + if len(extension) == 0: + display_file_list = f' {name} - {size:.1f} MB' + elif extension[0] == 'hf5': + if extension in ['.hf5']: + display_file_list = f" {name} - {size:.1f} MB" + elif extension in ['.h5', '.ndata']: + try: + reader = SciFiReaders.NionReader(full_name) + dataset_nion = reader.read() + display_name = dataset_nion.title + display_file_list = f" {display_name}{extension} - {size:.1f} MB" + except: + display_file_list = f" {name} - {size:.1f} MB" + else: + display_file_list = f' {name} - {size:.1f} MB' + file_dict[name] = {'display_string': display_file_list, 'basename': basename, 'extension': extension, + 'size': size, 'display_name': display_name}
+ + +
[docs]def update_directory_list(directory_name): + dir_list = os.listdir(directory_name) + + if '.pyTEMlib.files.pkl' in dir_list: + with open(os.path.join(directory_name, '.pyTEMlib.files.pkl'), 'rb') as f: + file_dict = pickle.load(f) + if directory_name != file_dict['directory']: + print('directory moved since last time read') + file_dict['directory'] = directory_name + dir_list.remove('.pyTEMlib.files.pkl') + else: + file_dict = {'directory': directory_name} + + # add new files + file_dict['file_list'] = [] + file_dict['display_file_list'] = [] + file_dict['directory_list'] = [] + + for name in dir_list: + if os.path.isfile(os.path.join(file_dict['directory'], name)): + if name not in file_dict: + add_to_dict(file_dict, name) + file_dict['file_list'].append(name) + file_dict['display_file_list'].append(file_dict[name]['display_string']) + else: + file_dict['directory_list'].append(name) + remove_item = [] + + # delete items of deleted files + save_pickle = False + + for name in file_dict.keys(): + if name not in dir_list and name not in ['directory', 'file_list', 'directory_list', 'display_file_list']: + remove_item.append(name) + else: + if 'extension' in file_dict[name]: + save_pickle = True + for item in remove_item: + file_dict.pop(item) + + if save_pickle: + with open(os.path.join(file_dict['directory'], '.pyTEMlib.files.pkl'), 'wb') as f: + pickle.dump(file_dict, f) + return file_dict
+ + +#### +# General Open and Save Methods +#### + +
[docs]def get_last_path(): + """Returns the path of the file last opened""" + try: + fp = open(config_path + '\\path.txt', 'r') + path = fp.read() + fp.close() + except IOError: + path = '' + + if len(path) < 2: + path = '.' + return path
+ + +
[docs]def save_path(filename): + """Save path of last opened file""" + + if len(filename) > 1: + fp = open(config_path + '\\path.txt', 'w') + path, fname = os.path.split(filename) + fp.write(path) + fp.close() + else: + path = '.' + return path
+ + +if Qt_available: + def get_qt_app(): + """ + will start QT Application if not running yet + + :returns: QApplication + + """ + + # start qt event loop + _instance = QtWidgets.QApplication.instance() + if not _instance: + # print('not_instance') + _instance = QtWidgets.QApplication([]) + + return _instance + + +
[docs]def open_file_dialog_qt(file_types=None): # , multiple_files=False): + """Opens a File dialog which is used in open_file() function + + This function uses pyQt5. + The app of the Gui has to be running for QT. Tkinter does not run on Macs at this point in time. + In jupyter notebooks use %gui Qt early in the notebook. + + The file looks first for a path.txt file for the last directory you used. + + Parameters + ---------- + file_types : string + file type filter in the form of '*.hf5' + + + Returns + ------- + filename : string + full filename with absolute path and extension as a string + + Example + ------- + >> import file_tools as ft + >> filename = ft.openfile_dialog() + >> print(filename) + + """ + """will start QT Application if not running yet and returns QApplication """ + + # determine file types by extension + if file_types is None: + file_types = 'TEM files (*.dm3 *.dm4 *.emd *.ndata *.h5 *.hf5);;pyNSID files (*.hf5);;QF files ( *.qf3);;' \ + 'DM files (*.dm3 *.dm4);;Nion files (*.ndata *.h5);;All files (*)' + elif file_types == 'pyNSID': + file_types = 'pyNSID files (*.hf5);;TEM files (*.dm3 *.dm4 *.qf3 *.ndata *.h5 *.hf5);;QF files ( *.qf3);;' \ + 'DM files (*.dm3 *.dm4);;Nion files (*.ndata *.h5);;All files (*)' + + # file_types = [("TEM files",["*.dm*","*.hf*","*.ndata" ]),("pyNSID files","*.hf5"),("DM files","*.dm*"), + # ("Nion files",["*.h5","*.ndata"]),("all files","*.*")] + + # Determine last path used + path = get_last_path() + + if Qt_available: + _ = get_qt_app() + filename = sidpy.io.interface_utils.openfile_dialog_QT(file_types=file_types, file_path=path) + save_path(filename) + return filename
+ +
[docs]def save_file_dialog_qt(file_types=None): # , multiple_files=False): + """Opens a File dialog which is used in open_file() function + + This function uses pyQt5. + The app of the Gui has to be running for QT. Tkinter does not run on Macs at this point in time. + In jupyter notebooks use %gui Qt early in the notebook. + + The file looks first for a path.txt file for the last directory you used. + + Parameters + ---------- + file_types : string + file type filter in the form of '*.hf5' + + + Returns + ------- + filename : string + full filename with absolute path and extension as a string + + Example + ------- + >> import file_tools as ft + >> filename = ft.openfile_dialog() + >> print(filename) + + """ + """will start QT Application if not running yet and returns QApplication """ + + # determine file types by extension + if file_types is None: + file_types = 'pyNSID files (*.hf5);;TEM files (*.dm3 *.dm4 *.qf3 *.ndata *.h5 *.hf5);;QF files ( *.qf3);;' \ + 'DM files (*.dm3 *.dm4);;Nion files (*.ndata *.h5);;All files (*)' + elif file_types == 'TEM': + file_types = 'TEM files (*.dm3 *.dm4 *.emd *.ndata *.h5 *.hf5);;pyNSID files (*.hf5);;QF files ( *.qf3);;' \ + 'DM files (*.dm3 *.dm4);;Nion files (*.ndata *.h5);;All files (*)' + + + # file_types = [("TEM files",["*.dm*","*.hf*","*.ndata" ]),("pyNSID files","*.hf5"),("DM files","*.dm*"), + # ("Nion files",["*.h5","*.ndata"]),("all files","*.*")] + + # Determine last path used + path = get_last_path() + + if Qt_available: + _ = get_qt_app() + filename = sidpy.io.interface_utils.savefile_dialog(file_types=file_types, file_path=path) + save_path(filename) + return filename
+ + +
[docs]def save_dataset(dataset, filename=None, h5_group=None): + """ Saves a dataset to a file in pyNSID format + Parameters + ---------- + dataset: sidpy.Dataset + the data + filename: str + name of file to be opened, if filename is None, a QT file dialog will try to open + h5_group: hd5py.Group + not used yet + """ + if filename is None: + filename = save_file_dialog_qt() + h5_filename = get_h5_filename(filename) + h5_file = h5py.File(h5_filename, mode='a') + path, file_name = os.path.split(filename) + basename, _ = os.path.splitext(file_name) + + if isinstance(dataset, dict): + h5_group = save_dataset_dictionary(h5_file, dataset) + return h5_group + + elif isinstance(dataset, sidpy.Dataset): + h5_dataset = save_single_dataset(h5_file, dataset, h5_group=h5_group) + return h5_dataset.parent + else: + raise TypeError('Only sidpy.datasets or dictionaries can be saved with pyTEMlib')
+ + +
[docs]def save_single_dataset(h5_file, dataset, h5_group=None): + if h5_group is None: + h5_measurement_group = sidpy.hdf.prov_utils.create_indexed_group(h5_file, 'Measurement_') + h5_group = sidpy.hdf.prov_utils.create_indexed_group(h5_measurement_group, 'Channel_') + + elif isinstance(h5_group, str): + if h5_group not in h5_file: + h5_group = h5_file.create_group(h5_group) + else: + if h5_group[-1] == '/': + h5_group = h5_group[:-1] + + channel = h5_group.split('/')[-1] + h5_measurement_group = h5_group[:-len(channel)] + h5_group = sidpy.hdf.prov_utils.create_indexed_group(h5_group, 'Channel_') + else: + raise ValueError('h5_group needs to be string or None') + + h5_dataset = pyNSID.hdf_io.write_nsid_dataset(dataset, h5_group) + dataset.h5_dataset = h5_dataset + h5_dataset.file.flush() + return h5_dataset
+ + +
[docs]def save_dataset_dictionary(h5_file, datasets): + h5_measurement_group = sidpy.hdf.prov_utils.create_indexed_group(h5_file, 'Measurement_') + for key, dataset in datasets.items(): + if key[-1] == '/': + key = key[:-1] + if isinstance(dataset, sidpy.Dataset): + h5_group = h5_measurement_group.create_group(key) + h5_dataset = pyNSID.hdf_io.write_nsid_dataset(dataset, h5_group) + dataset.h5_dataset = h5_dataset + h5_dataset.file.flush() + elif isinstance(dataset, dict): + sidpy.hdf.hdf_utils.write_dict_to_h5_group(h5_measurement_group, dataset, key) + else: + print('could not save item ', key, 'of dataset dictionary') + return h5_measurement_group
+ + +
[docs]def h5_group_to_dict(group, group_dict={}): + if not isinstance(group, h5py.Group): + raise TypeError('we need a h5py group to read from') + if not isinstance(group_dict, dict): + raise TypeError('group_dict needs to be a python dictionary') + + group_dict[group.name.split('/')[-1]] = dict(group.attrs) + for key in group.keys(): + h5_group_to_dict(group[key], group_dict[group.name.split('/')[-1]]) + return group_dict
+ + +
[docs]def open_file(filename=None, h5_group=None, write_hdf_file=False): # save_file=False, + """Opens a file if the extension is .hf5, .ndata, .dm3 or .dm4 + + If no filename is provided the QT open_file windows opens (if QT_available==True) + Everything will be stored in a NSID style hf5 file. + Subroutines used: + - NSIDReader + - nsid.write_ + - get_main_tags + - get_additional tags + + Parameters + ---------- + filename: str + name of file to be opened, if filename is None, a QT file dialog will try to open + h5_group: hd5py.Group + not used yet #TODO: provide hook for usage of external chosen group + write_hdf_file: bool + set to false so that sidpy dataset will not be written to hf5-file automatically + + Returns + ------- + sidpy.Dataset + sidpy dataset with location of hdf5 dataset as attribute + + """ + if filename is None: + selected_file = open_file_dialog_qt() + filename = selected_file + + else: + if not isinstance(filename, str): + raise TypeError('filename must be a non-empty string or None (to a QT open file dialog)') + elif filename == '': + raise TypeError('filename must be a non-empty string or None (to a QT open file dialog)') + + path, file_name = os.path.split(filename) + basename, extension = os.path.splitext(file_name) + + if extension == '.hf5': + reader = SciFiReaders.NSIDReader(filename) + datasets = reader.read() + if len(datasets) < 1: + print('no hdf5 dataset found in file') + return {} + else: + dataset_dict = {} + for index, dataset in enumerate(datasets): + title = dataset.title.split('/')[2] + dataset.title = dataset.title.split('/')[-1] + dataset_dict[title] = dataset + if index == 0: + file = datasets[0].h5_dataset.file + master_group = datasets[0].h5_dataset.parent.parent.parent + for key in master_group.keys(): + + if key not in dataset_dict: + dataset_dict[key] = h5_group_to_dict(master_group[key]) + print() + if not write_hdf_file: + file.close() + # datasets[0].h5_dataset = None + return dataset_dict + + """ + should go to no dataset found + if 'Raw_Data' in h5_group: + dataset = read_old_h5group(h5_group) + dataset.h5_dataset = h5_group['Raw_Data'] + """ + + elif extension in ['.dm3', '.dm4', '.ndata', '.ndata1', '.h5', '.emd', '.emi']: + + # tags = open_file(filename) + if extension in ['.dm3', '.dm4']: + reader = SciFiReaders.DMReader(filename) + + elif extension in ['.emi']: + try: + import hyperspy.api as hs + s = hs.load(filename) + dataset_dict = {} + spectrum_number = 0 + if not isinstance(s, list): + s = [s] + for index, datum in enumerate(s): + dset = SciFiReaders.convert_hyperspy(datum) + if datum.data.ndim == 1: + dset.title = dset.title + f'_{spectrum_number}_Spectrum' + spectrum_number +=1 + elif datum.data.ndim == 3: + dset.title = dset.title +'_SI' + dset = dset.T + dset.title = dset.title[11:] + dataset_dict[f'Channel_{index:03d}']=dset + return dataset_dict + except ImportError: + print('This file type needs hyperspy to be installed to be able to be read') + return + elif extension == '.emd': + reader = SciFiReaders.EMDReader(filename) + + elif extension in ['.ndata', '.h5']: + reader = SciFiReaders.NionReader(filename) + + else: + raise NotImplementedError('extension not supported') + + path, file_name = os.path.split(filename) + basename, _ = os.path.splitext(file_name) + if extension != '.emi': + dset = reader.read() + + if extension in ['.dm3', '.dm4']: + title = (basename.strip().replace('-', '_')).split('/')[-1] + if not isinstance(dset, list): + print('Please use new SciFiReaders Package for full functionality') + dset = [dset] + if 'PageSetup' in dset[0].original_metadata: + del dset[0].original_metadata['PageSetup'] + dset[0].original_metadata['original_title'] = title + + if isinstance(dset, list): + if len(dset) < 1: + print('no dataset found in file') + return {} + else: + dataset_dict = {} + for index, dataset in enumerate(dset): + if extension == '.emi': + if 'experiment' in dataset.metadata: + if 'detector' in dataset.metadata['experiment']: + dataset.title = dataset.metadata['experiment']['detector'] + dataset.filename = basename.strip() + # read_essential_metadata(dataset) + dataset.metadata['filename'] = filename + dataset_dict[f'Channel_{index:03}'] = dataset + else: + dset.filename = basename.strip().replace('-', '_') + read_essential_metadata(dset) + dset.metadata['filename'] = filename + dataset_dict = {'Channel_000': dset} + + if write_hdf_file: + h5_master_group = save_dataset(dataset_dict, filename=filename) + + save_path(filename) + return dataset_dict + else: + print('file type not handled yet.') + return
+ + +################################################################ +# Read Functions +################################################################# + +
[docs]def read_essential_metadata(dataset): + """Updates dataset.metadata['experiment'] with essential information read from original metadata + + This depends on whether it is originally a nion or a dm3 file + """ + if not isinstance(dataset, sidpy.Dataset): + raise TypeError("we need a sidpy.Dataset") + experiment_dictionary = {} + if 'metadata' in dataset.original_metadata: + if 'hardware_source' in dataset.original_metadata['metadata']: + experiment_dictionary = read_nion_image_info(dataset.original_metadata) + if 'DM' in dataset.original_metadata: + experiment_dictionary = read_dm3_info(dataset.original_metadata) + if 'experiment' not in dataset.metadata: + dataset.metadata['experiment'] = {} + + dataset.metadata['experiment'].update(experiment_dictionary)
+ + +
[docs]def read_dm3_info(original_metadata): + """Read essential parameter from original_metadata originating from a dm3 file""" + if not isinstance(original_metadata, dict): + raise TypeError('We need a dictionary to read') + + if 'DM' not in original_metadata: + return {} + if 'ImageTags' not in original_metadata: + return {} + exp_dictionary = original_metadata['ImageTags'] + experiment = {} + if 'EELS' in exp_dictionary: + if 'Acquisition' in exp_dictionary['EELS']: + for key, item in exp_dictionary['EELS']['Acquisition'].items(): + if 'Exposure' in key: + _, units = key.split('(') + if units[:-1] == 's': + experiment['single_exposure_time'] = item + if 'Integration' in key: + _, units = key.split('(') + if units[:-1] == 's': + experiment['exposure_time'] = item + if 'frames' in key: + experiment['number_of_frames'] = item + + if 'Experimental Conditions' in exp_dictionary['EELS']: + for key, item in exp_dictionary['EELS']['Experimental Conditions'].items(): + if 'Convergence' in key: + experiment['convergence_angle'] = item + if 'Collection' in key: + # print(item) + # for val in item.values(): + experiment['collection_angle'] = item + if 'number_of_frames' not in experiment: + experiment['number_of_frames'] = 1 + if 'exposure_time' not in experiment: + if 'single_exposure_time' in experiment: + experiment['exposure_time'] = experiment['number_of_frames'] * experiment['single_exposure_time'] + + else: + if 'Acquisition' in exp_dictionary: + if 'Parameters' in exp_dictionary['Acquisition']: + if 'High Level' in exp_dictionary['Acquisition']['Parameters']: + if 'Exposure (s)' in exp_dictionary['Acquisition']['Parameters']['High Level']: + experiment['exposure_time'] = exp_dictionary['Acquisition']['Parameters']['High Level'][ + 'Exposure (s)'] + + if 'Microscope Info' in exp_dictionary: + if 'Microscope' in exp_dictionary['Microscope Info']: + experiment['microscope'] = exp_dictionary['Microscope Info']['Microscope'] + if 'Voltage' in exp_dictionary['Microscope Info']: + experiment['acceleration_voltage'] = exp_dictionary['Microscope Info']['Voltage'] + + return experiment
+ + +
[docs]def read_nion_image_info(original_metadata): + """Read essential parameter from original_metadata originating from a dm3 file""" + if not isinstance(original_metadata, dict): + raise TypeError('We need a dictionary to read') + if 'metadata' not in original_metadata: + return {} + if 'hardware_source' not in original_metadata['metadata']: + return {} + if 'ImageScanned' not in original_metadata['metadata']['hardware_source']: + return {} + + exp_dictionary = original_metadata['metadata']['hardware_source']['ImageScanned'] + experiment = exp_dictionary + # print(exp_dictionary) + if 'autostem' in exp_dictionary: + pass
+ + +
[docs]def get_h5_filename(fname): + """Determines file name of hdf5 file for newly converted data file""" + + path, filename = os.path.split(fname) + basename, extension = os.path.splitext(filename) + h5_file_name_original = os.path.join(path, basename + '.hf5') + h5_file_name = h5_file_name_original + + if os.path.exists(os.path.abspath(h5_file_name_original)): + count = 1 + h5_file_name = h5_file_name_original[:-4] + '-' + str(count) + '.hf5' + while os.path.exists(os.path.abspath(h5_file_name)): + count += 1 + h5_file_name = h5_file_name_original[:-4] + '-' + str(count) + '.hf5' + + if h5_file_name != h5_file_name_original: + path, filename = os.path.split(h5_file_name) + print('Cannot overwrite file. Using: ', filename) + return str(h5_file_name)
+ + +
[docs]def get_start_channel(h5_file): + """ Legacy for get start channel""" + + DeprecationWarning('Depreciated: use function get_main_channel instead') + return get_main_channel(h5_file)
+ + +
[docs]def get_main_channel(h5_file): + """Returns name of first channel group in hdf5-file""" + + current_channel = None + if 'Measurement_000' in h5_file: + if 'Measurement_000/Channel_000' in h5_file: + current_channel = h5_file['Measurement_000/Channel_000'] + return current_channel
+ + +
[docs]def h5_tree(input_object): + """Just a wrapper for the sidpy function print_tree, + + so that sidpy does not have to be loaded in notebook + + """ + + if isinstance(input_object, sidpy.Dataset): + if not isinstance(input_object.h5_dataset, h5py.Dataset): + raise ValueError('sidpy dataset does not have an associated h5py dataset') + h5_file = input_object.h5_dataset.file + elif isinstance(input_object, h5py.Dataset): + h5_file = input_object.file + elif isinstance(input_object, (h5py.Group, h5py.File)): + h5_file = input_object + else: + raise TypeError('should be a h5py.object or sidpy Dataset') + sidpy.hdf_utils.print_tree(h5_file)
+ + +
[docs]def log_results(h5_group, dataset=None, attributes=None): + """Log Results in hdf5-file + + Saves either a sidpy.Dataset or dictionary in a hdf5-file. + The group for the result will consist of 'Log_' and a running index. + That group will be placed in h5_group. + + Parameters + ---------- + h5_group: hd5py.Group, or sidpy.Dataset + groups where result group are to be stored + dataset: sidpy.Dataset or None + sidpy dataset to be stored + attributes: dict + dictionary containing results that are not based on a sidpy.Dataset + + Returns + ------- + log_group: hd5py.Group + group in hdf5 file with results. + + """ + if isinstance(h5_group, sidpy.Dataset): + h5_group = h5_group.h5_dataset + if not isinstance(h5_group, h5py.Dataset): + raise TypeError('Use h5_dataset of sidpy.Dataset is not a valid h5py.Dataset') + h5_group = h5_group.parent.parent + + if not isinstance(h5_group, h5py.Group): + raise TypeError('Need a valid h5py.Group for logging results') + + if dataset is None: + log_group = sidpy.hdf.prov_utils.create_indexed_group(h5_group, 'Log_') + else: + log_group = pyNSID.hdf_io.write_results(h5_group, dataset=dataset) + if hasattr(dataset, 'meta_data'): + if 'analysis' in dataset.meta_data: + log_group['analysis'] = dataset.meta_data['analysis'] + if hasattr(dataset, 'structures'): + for structure in dataset.structures.values(): + h5_add_crystal_structure(log_group, structure) + + dataset.h5_dataset = log_group[dataset.title.replace('-', '_')][dataset.title.replace('-', '_')] + if attributes is not None: + for key, item in attributes.items(): + if not isinstance(item, dict): + log_group[key] = attributes[key] + else: + log_group.create_group(key) + sidpy.hdf.hdf_utils.write_simple_attrs(log_group[key], attributes[key]) + return log_group
+ + +
[docs]def add_dataset_from_file(datasets, filename=None, key_name='Log', single_dataset=True): + """Add dataset to datasets dictionary + + Parameters + ---------- + dataset: dict + dictionary to write to file + filename: str, default: None, + name of file to open, if None, adialog will appear + key_name: str, default: 'Log' + name for key in dictionary with running number being added + + Returns + ------- + key_name: str + actual last used name of dictionary key + """ + + datasets2 = open_file(filename=filename) + first_dataset = datasets2[list(datasets2)[0]] + if isinstance(first_dataset, sidpy.Dataset): + + index = 0 + for key in datasets.keys(): + if key_name in key: + if int(key[-3:]) >= index: + index = int(key[-3:])+1 + if single_dataset: + datasets[key_name+f'_{index:03}'] = first_dataset + else: + for dataset in datasets2.values(): + datasets[key_name+f'_{index:03}'] = dataset + index += 1 + index -= 1 + else: + return None + + return f'{key_name}_{index:03}'
+ + +# ## +# Crystal Structure Read and Write +# ## +
[docs]def read_poscar(file_name=None): + """ + Open a POSCAR file from Vasp + If no file name is provided an open file dialog to select a POSCAR file appears + + Parameters + ---------- + file_name: str + if None is provided an open file dialog will appear + + Return + ------ + crystal: ase.Atoms + crystal structure in ase format + """ + + if file_name is None: + file_name = open_file_dialog_qt('POSCAR (POSCAR*.txt);;All files (*)') + + # use ase package to read file + base = os.path.basename(file_name) + base_name = os.path.splitext(base)[0] + crystal = ase.io.read(file_name, format='vasp', parallel=False) + + # make dictionary and plot structure (not essential for further notebook) + crystal.info = {'title': base_name} + return crystal
+ + +
[docs]def read_cif(file_name=None, verbose=False): # open file dialog to select cif file + """ + Open a cif file + If no file name is provided an open file dialog to select a cif file appears + + Parameters + ---------- + file_name: str + if None is provided an open file dialog will appear + verbose: bool + + Return + ------ + crystal: ase.Atoms + crystal structure in ase format + """ + + if file_name is None: + file_name = open_file_dialog_qt('cif (*.cif);;All files (*)') + # use ase package to read file + + base = os.path.basename(file_name) + base_name = os.path.splitext(base)[0] + crystal = ase.io.read(file_name, format='cif', store_tags=True, parallel=False) + + # make dictionary and plot structure (not essential for further notebook) + if crystal.info is None: + crystal.info = {'title': base_name} + crystal.info.update({'title': base_name}) + if verbose: + print('Opened cif file for ', crystal.get_chemical_formula()) + + return crystal
+ + +
[docs]def h5_add_crystal_structure(h5_file, input_structure, name=None): + """Write crystal structure to NSID file""" + + if isinstance(input_structure, ase.Atoms): + + crystal_tags = pyTEMlib.crystal_tools.get_dictionary(input_structure) + if crystal_tags['metadata'] == {}: + crystal_tags['metadata'] = {'title': input_structure.get_chemical_formula()} + elif isinstance(input_structure, dict): + crystal_tags = input_structure + else: + raise TypeError('Need a dictionary or an ase.Atoms object with ase installed') + + structure_group = sidpy.hdf.prov_utils.create_indexed_group(h5_file, 'Structure_') + + for key, item in crystal_tags.items(): + if not isinstance(item, dict): + structure_group[key] = item + + if 'base' in crystal_tags: + structure_group['relative_positions'] = crystal_tags['base'] + if 'title' in crystal_tags: + structure_group['title'] = str(crystal_tags['title']) + structure_group['_' + crystal_tags['title']] = str(crystal_tags['title']) + + # ToDo: Save all of info dictionary + if 'metadata' in input_structure: + structure_group.create_group('metadata') + sidpy.hdf.hdf_utils.write_simple_attrs(structure_group['metadata'], input_structure['metadata']) + + h5_file.file.flush() + return structure_group
+ + +
[docs]def h5_add_to_structure(structure_group, crystal_tags): + """add dictionary as structure group""" + + for key in crystal_tags: + if key in structure_group.keys(): + print(key, ' not written; use new name') + else: + structure_group[key] = crystal_tags[key]
+ + +
[docs]def h5_get_crystal_structure(structure_group): + """Read crystal structure from NSID file + Any additional information will be read as dictionary into the info attribute of the ase.Atoms object + + Parameters + ---------- + structure_group: h5py.Group + location in hdf5 file to where the structure information is stored + + Returns + ------- + atoms: ase.Atoms object + crystal structure in ase format + + """ + + crystal_tags = {'unit_cell': structure_group['unit_cell'][()], + 'base': structure_group['relative_positions'][()], + 'title': structure_group['title'][()]} + if '2D' in structure_group: + crystal_tags['2D'] = structure_group['2D'][()] + elements = structure_group['elements'][()] + crystal_tags['elements'] = [] + for e in elements: + crystal_tags['elements'].append(e.astype(str, copy=False)) + + atoms = pyTEMlib.crystal_tools.atoms_from_dictionary(crystal_tags) + if 'metadata' in structure_group: + atoms.info = sidpy.hdf.hdf_utils.h5_group_to_dict(structure_group) + + if 'zone_axis' in structure_group: + atoms.info = {'experiment': {'zone_axis': structure_group['zone_axis'][()]}} + # ToDo: Read all of info dictionary + return atoms
+ + +############################################### +# Support old pyTEM file format +############################################### + +
[docs]def read_old_h5group(current_channel): + """Make a sidpy.Dataset from pyUSID style hdf5 group + + Parameters + ---------- + current_channel: h5_group + + Returns + ------- + sidpy.Dataset + """ + + dim_dir = [] + if 'nDim_Data' in current_channel: + h5_dataset = current_channel['nDim_Data'] + reader = pyNSID.NSIDReader(h5_dataset.file.filename) + dataset = reader.read(h5_dataset) + dataset.h5_file = current_channel.file + return dataset + elif 'Raw_Data' in current_channel: + if 'image_stack' in current_channel: + sid_dataset = sidpy.Dataset.from_array(np.swapaxes(current_channel['image_stack'][()], 2, 0)) + dim_dir = ['SPATIAL', 'SPATIAL', 'TEMPORAL'] + elif 'data' in current_channel: + sid_dataset = sidpy.Dataset.from_array(current_channel['data'][()]) + dim_dir = ['SPATIAL', 'SPATIAL'] + else: + size_x = int(current_channel['spatial_size_x'][()]) + size_y = int(current_channel['spatial_size_y'][()]) + if 'spectral_size_x' in current_channel: + size_s = int(current_channel['spectral_size_x'][()]) + else: + size_s = 0 + data = np.reshape(current_channel['Raw_Data'][()], (size_x, size_y, size_s)) + sid_dataset = sidpy.Dataset.from_array(data) + if size_x > 1: + dim_dir.append('SPATIAL') + if size_y > 1: + dim_dir.append('SPATIAL') + if size_s > 1: + dim_dir.append('SPECTRAL') + sid_dataset.h5_dataset = current_channel['Raw_Data'] + + elif 'data' in current_channel: + sid_dataset = sidpy.Dataset.from_array(current_channel['data'][()]) + dim_dir = ['SPATIAL', 'SPATIAL'] + sid_dataset.h5_dataset = current_channel['data'] + else: + return + + if 'SPATIAL' in dim_dir: + if 'SPECTRAL' in dim_dir: + sid_dataset.data_type = sidpy.DataType.SPECTRAL_IMAGE + elif 'TEMPORAL' in dim_dir: + sid_dataset.data_type = sidpy.DataType.IMAGE_STACK + else: + sid_dataset.data_type = sidpy.DataType.IMAGE + else: + sid_dataset.data_type = sidpy.DataType.SPECTRUM + + sid_dataset.quantity = 'intensity' + sid_dataset.units = 'counts' + if 'analysis' in current_channel: + sid_dataset.source = current_channel['analysis'][()] + + set_dimensions(sid_dataset, current_channel) + + return sid_dataset
+ + +
[docs]def set_dimensions(dset, current_channel): + """Attaches correct dimension from old pyTEMlib style. + + Parameters + ---------- + dset: sidpy.Dataset + current_channel: hdf5.Group + """ + dim = 0 + if dset.data_type == sidpy.DataType.IMAGE_STACK: + dset.set_dimension(dim, sidpy.Dimension(np.arange(dset.shape[dim]), name='frame', + units='frame', quantity='stack', + dimension_type='TEMPORAL')) + dim += 1 + if 'IMAGE' in dset.data_type: + + if 'spatial_scale_x' in current_channel: + scale_x = current_channel['spatial_scale_x'][()] + else: + scale_x = 1 + if 'spatial_units' in current_channel: + units_x = current_channel['spatial_units'][()] + if len(units_x) < 2: + units_x = 'pixel' + else: + units_x = 'generic' + if 'spatial_scale_y' in current_channel: + scale_y = current_channel['spatial_scale_y'][()] + else: + scale_y = 0 + dset.set_dimension(dim, sidpy.Dimension('x', np.arange(dset.shape[dim])*scale_x, + units=units_x, quantity='Length', + dimension_type='SPATIAL')) + dim += 1 + dset.set_dimension(dim, sidpy.Dimension('y', np.arange(dset.shape[dim])*scale_y, + units=units_x, quantity='Length', + dimension_type='SPATIAL')) + dim += 1 + if dset.data_type in [sidpy.DataType.SPECTRUM, sidpy.DataType.SPECTRAL_IMAGE]: + if 'spectral_scale_x' in current_channel: + scale_s = current_channel['spectral_scale_x'][()] + else: + scale_s = 1.0 + if 'spectral_units_x' in current_channel: + units_s = current_channel['spectral_units_x'] + else: + units_s = 'eV' + + if 'spectral_offset_x' in current_channel: + offset = current_channel['spectral_offset_x'] + else: + offset = 0.0 + dset.set_dimension(dim, sidpy.Dimension(np.arange(dset.shape[dim]) * scale_s + offset, + name='energy', + units=units_s, + quantity='energy_loss', + dimension_type='SPECTRAL'))
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/graph_tools.html b/_modules/pyTEMlib/graph_tools.html new file mode 100644 index 00000000..3280e813 --- /dev/null +++ b/_modules/pyTEMlib/graph_tools.html @@ -0,0 +1,1281 @@ + + + + + + pyTEMlib.graph_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.graph_tools

+"""
+
+"""
+import numpy as np
+# import ase
+import sys
+
+# from scipy.spatial import cKDTree, Voronoi, ConvexHull
+import scipy.spatial
+import scipy.optimize
+import scipy.interpolate
+
+from skimage.measure import grid_points_in_poly, points_in_poly
+
+# import plotly.graph_objects as go
+# import plotly.express as px
+import matplotlib.patches as patches
+
+import pyTEMlib.crystal_tools
+from tqdm.auto import tqdm, trange
+
+from .graph_viz import *
+
+
+###########################################################################
+# utility functions
+###########################################################################
+
+
[docs]def interstitial_sphere_center(vertex_pos, atom_radii, optimize=True): + """ + Function finds center and radius of the largest interstitial sphere of a simplex. + Which is the center of the cirumsphere if all atoms have the same radius, + but differs for differently sized atoms. + In the last case, the circumsphere center is used as starting point for refinement. + + Parameters + ----------------- + vertex_pos : numpy array + The position of vertices of a tetrahedron + atom_radii : float + bond radii of atoms + optimize: boolean + whether atom bond lengths are optimized or not + Returns + ---------- + new_center : numpy array + The center of the largest interstitial sphere + radius : float + The radius of the largest interstitial sphere + """ + center, radius = circum_center(vertex_pos, tol=1e-4) + + def distance_deviation(sphere_center): + return np.std(np.linalg.norm(vertex_pos - sphere_center, axis=1) - atom_radii) + + if np.std(atom_radii) == 0 or not optimize: + return center, radius-atom_radii[0] + else: + center_new = scipy.optimize.minimize(distance_deviation, center) + return center_new.x, np.linalg.norm(vertex_pos[0]-center_new.x)-atom_radii[0]
+ + +
[docs]def circum_center(vertex_pos, tol=1e-4): + """ + Function finds the center and the radius of the circumsphere of every simplex. + Reference: + Fiedler, Miroslav. Matrices and graphs in geometry. No. 139. Cambridge University Press, 2011. + (p.29 bottom: example 2.1.11) + Code started from https://github.com/spatala/gbpy + with help of https://codereview.stackexchange.com/questions/77593/calculating-the-volume-of-a-tetrahedron + + Parameters + ----------------- + vertex_pos : numpy array + The position of vertices of a tetrahedron + tol : float + Tolerance defined to identify co-planar tetrahedrons + Returns + ---------- + circum_center : numpy array + The center of the circumsphere + circum_radius : float + The radius of the circumsphere + """ + + # Make Cayley-Menger Matrix + number_vertices = len(vertex_pos) + matrix_c = np.identity(number_vertices+1)*-1+1 + distances = scipy.spatial.distance.pdist(np.asarray(vertex_pos, dtype=float), metric='sqeuclidean') + matrix_c[1:, 1:] = scipy.spatial.distance.squareform(distances) + det_matrix_c = (np.linalg.det(matrix_c)) + if abs(det_matrix_c) < tol: + return np.array(vertex_pos[0]*0), 0 + matrix = -2 * np.linalg.inv(matrix_c) + + center = vertex_pos[0, :]*0 + for i in range(number_vertices): + center += matrix[0, i+1] * vertex_pos[i, :] + center /= np.sum(matrix[0, 1:]) + + circum_radius = np.sqrt(matrix[0, 0]) / 2 + + return np.array(center), circum_radius
+ + +
[docs]def voronoi_volumes(atoms): + """ + Volumes of voronoi cells from + https://stackoverflow.com/questions/19634993/volume-of-voronoi-cell-python + """ + points = atoms.positions + v = scipy.spatial.Voronoi(points) + vol = np.zeros(v.npoints) + for i, reg_num in enumerate(v.point_region): + indices = v.regions[reg_num] + if -1 in indices: # some regions can be opened + vol[i] = 0 + else: + try: + hull = scipy.spatial.ConvexHull(v.simplices[indices]) + vol[i] = hull.volume + except: + vol[i] = 0. + + if atoms.info is None: + atoms.info = {} + # atoms.info.update({'volumes': vol}) + return vol
+ + +
[docs]def get_bond_radii(atoms, bond_type='bond'): + """ get all bond radii from Kirkland + Parameter: + ---------- + atoms ase.Atoms object + structure information in ase format + type: str + type of bond 'covalent' or 'metallic' + """ + + r_a = [] + for atom in atoms: + if atom.symbol == 'X': + r_a.append(1.2) + else: + if bond_type == 'covalent': + r_a.append(pyTEMlib.crystal_tools.electronFF[atom.symbol]['bond_length'][0]) + else: + r_a.append(pyTEMlib.crystal_tools.electronFF[atom.symbol]['bond_length'][1]) + if atoms.info is None: + atoms.info = {} + atoms.info['bond_radii'] = r_a + return r_a
+ + +
[docs]def set_bond_radii(atoms, bond_type='bond'): + """ set certain or all bond-radii taken from Kirkland + + Bond_radii are also stored in atoms.info + + Parameter: + ---------- + atoms ase.Atoms object + structure information in ase format + type: str + type of bond 'covalent' or 'metallic' + Return: + ------- + r_a: list + list of atomic bond-radii + + """ + if atoms.info is None: + atoms.info = {} + if 'bond_radii' in atoms.info: + r_a = atoms.info['bond_radii'] + else: + r_a = np.ones(len(atoms)) + + for atom in atoms: + if bond_type == 'covalent': + r_a[atom.index] = (pyTEMlib.crystal_tools.electronFF[atom.symbol]['bond_length'][0]) + else: + r_a[atom.index] = (pyTEMlib.crystal_tools.electronFF[atom.symbol]['bond_length'][1]) + atoms.info['bond_radii'] = r_a + return r_a
+ + +
[docs]def get_voronoi(tetrahedra, atoms, bond_radii=None, optimize=True): + """ + Find Voronoi vertices and keep track of associated tetrahedrons and interstitial radii + + Used in find_polyhedra function + + Parameters + ---------- + tetrahedra: scipy.spatial.Delaunay object + Delaunay tesselation + atoms: ase.Atoms object + the structural information + optimize: boolean + whether to use different atom radii or not + + Returns + ------- + voronoi_vertices: list + list of positions of voronoi vertices + voronoi_tetrahedra: + list of indices of associated vertices of tetrahedra + r_vv: list of float + list of all interstitial sizes + """ + + extent = atoms.cell.lengths() + if atoms.info is None: + atoms.info = {} + + if bond_radii is not None: + bond_radii = [bond_radii]*len(atoms) + elif 'bond_radii' in atoms.info: + bond_radii = atoms.info['bond_radii'] + + else: + bond_radii = get_bond_radii(atoms) + + voronoi_vertices = [] + voronoi_tetrahedrons = [] + r_vv = [] + r_aa = [] + print('Find interstitials (finding centers for different elements takes a bit)') + for vertices in tqdm(tetrahedra.simplices): + r_a = [] + for vert in vertices: + r_a.append(bond_radii[vert]) + voronoi, radius = interstitial_sphere_center(atoms.positions[vertices], r_a, optimize=optimize) + + r_a = np.average(r_a) # np.min(r_a) + r_aa.append(r_a) + + if (voronoi >= 0).all() and (extent - voronoi > 0).all() and radius > 0.01: + voronoi_vertices.append(voronoi) + voronoi_tetrahedrons.append(vertices) + r_vv.append(radius) + return voronoi_vertices, voronoi_tetrahedrons, r_vv, np.max(r_aa)
+ + +
[docs]def find_overlapping_spheres(voronoi_vertices, r_vv, r_a, cheat=1.): + """Find overlapping spheres""" + + vertex_tree = scipy.spatial.cKDTree(voronoi_vertices) + + pairs = vertex_tree.query_pairs(r=r_a * 2) + + overlapping_pairs = [] + for (i, j) in pairs: + if np.linalg.norm(voronoi_vertices[i] - voronoi_vertices[j]) < (r_vv[i] + r_vv[j]) * cheat: + overlapping_pairs.append([i, j]) + + return np.array(sorted(overlapping_pairs))
+ + +
[docs]def find_interstitial_clusters(overlapping_pairs): + """Make clusters + Breadth first search to go through the list of overlapping spheres or circles to determine clusters + """ + visited_all = [] + clusters = [] + for initial in overlapping_pairs[:, 0]: + if initial not in visited_all: + # breadth first search + visited = [] # the atoms we visited + queue = [initial] + while queue: + node = queue.pop(0) + if node not in visited_all: + visited.append(node) + visited_all.append(node) + # neighbors = overlapping_pairs[overlapping_pairs[:,0]==node,1] + neighbors = np.append(overlapping_pairs[overlapping_pairs[:, 1] == node, 0], + overlapping_pairs[overlapping_pairs[:, 0] == node, 1]) + + for i, neighbour in enumerate(neighbors): + if neighbour not in visited: + queue.append(neighbour) + clusters.append(visited) + return clusters, visited_all
+ + +
[docs]def make_polygons(atoms, voronoi_vertices, voronoi_tetrahedrons, clusters, visited_all): + """ make polygons from convex hulls of vertices around interstitial positions""" + polyhedra = {} + for index, cluster in tqdm(enumerate(clusters)): + cc = [] + for c in cluster: + cc = cc + list(voronoi_tetrahedrons[c]) + + hull = scipy.spatial.ConvexHull(atoms.positions[list(set(cc)), :2]) + faces = [] + triangles = [] + for s in hull.simplices: + faces.append(atoms.positions[list(set(cc))][s]) + triangles.append(list(s)) + polyhedra[index] = {'vertices': atoms.positions[list(set(cc))], 'indices': list(set(cc)), + 'faces': faces, 'triangles': triangles, + 'length': len(list(set(cc))), + 'combined_vertices': cluster, + 'interstitial_index': index, + 'interstitial_site': np.array(voronoi_tetrahedrons)[cluster].mean(axis=0), + 'atomic_numbers': atoms.get_atomic_numbers()[list(set(cc))]} # , 'volume': hull.volume} + # 'coplanar': hull.coplanar} + + print('Define conventional interstitial polyhedra') + running_number = index + 0 + for index in trange(len(voronoi_vertices)): + if index not in visited_all: + vertices = voronoi_tetrahedrons[index] + hull = scipy.spatial.ConvexHull(atoms.positions[vertices, :2]) + faces = [] + triangles = [] + for s in hull.simplices: + faces.append(atoms.positions[vertices][s]) + triangles.append(list(s)) + + polyhedra[running_number] = {'vertices': atoms.positions[vertices], 'indices': vertices, + 'faces': faces, 'triangles': triangles, + 'length': len(vertices), + 'combined_vertices': index, + 'interstitial_index': running_number, + 'interstitial_site': np.array(voronoi_tetrahedrons)[index], + 'atomic_numbers': atoms.get_atomic_numbers()[vertices]} + # 'volume': hull.volume} + + running_number += 1 + + return polyhedra
+ + +
[docs]def make_polyhedrons(atoms, voronoi_vertices, voronoi_tetrahedrons, clusters, visited_all): + """collect output data and make dictionary""" + + polyhedra = {} + import scipy.sparse + connectivity_matrix = scipy.sparse.dok_matrix((len(atoms), len(atoms)), dtype=bool) + + print('Define clustered interstitial polyhedra') + for index, cluster in tqdm(enumerate(clusters)): + cc = [] + for c in cluster: + cc = cc + list(voronoi_tetrahedrons[c]) + cc = list(set(cc)) + + hull = scipy.spatial.ConvexHull(atoms.positions[cc]) + faces = [] + triangles = [] + for s in hull.simplices: + faces.append(atoms.positions[cc][s]) + triangles.append(list(s)) + for k in range(len(s)): + l = (k + 1) % len(s) + if cc[s[k]] > cc[s[l]]: + connectivity_matrix[cc[s[l]], cc[s[k]]] = True + else: + connectivity_matrix[cc[s[k]], cc[s[l]]] = True + + polyhedra[index] = {'vertices': atoms.positions[list(set(cc))], 'indices': list(set(cc)), + 'faces': faces, 'triangles': triangles, + 'length': len(list(set(cc))), + 'combined_vertices': cluster, + 'interstitial_index': index, + 'interstitial_site': np.array(voronoi_tetrahedrons)[cluster].mean(axis=0), + 'atomic_numbers': atoms.get_atomic_numbers()[list(set(cc))], + 'volume': hull.volume} + # 'coplanar': hull.coplanar} + + print('Define conventional interstitial polyhedra') + running_number = index + 0 + for index in range(len(voronoi_vertices)): + if index not in visited_all: + vertices = voronoi_tetrahedrons[index] + hull = scipy.spatial.ConvexHull(atoms.positions[vertices]) + faces = [] + triangles = [] + for s in hull.simplices: + faces.append(atoms.positions[vertices][s]) + triangles.append(list(s)) + for k in range(len(s)): + l = (k + 1) % len(s) + if cc[s[k]] > cc[s[l]]: + connectivity_matrix[cc[s[l]], cc[s[k]]] = True + else: + connectivity_matrix[cc[s[k]], cc[s[l]]] = True + + polyhedra[running_number] = {'vertices': atoms.positions[vertices], 'indices': vertices, + 'faces': faces, 'triangles': triangles, + 'length': len(vertices), + 'combined_vertices': index, + 'interstitial_index': running_number, + 'interstitial_site': np.array(voronoi_tetrahedrons)[index], + 'atomic_numbers': atoms.get_atomic_numbers()[vertices], + 'volume': hull.volume} + + running_number += 1 + if atoms.info is None: + atoms.info = {} + atoms.info.update({'graph': {'connectivity_matrix': connectivity_matrix}}) + return polyhedra
+ + +################################################################## +# polyhedra functions +################################################################## + +
[docs]def get_non_periodic_supercell(super_cell): + super_cell.wrap() + atoms = super_cell*3 + atoms.positions -= super_cell.cell.lengths() + atoms.positions[:,0] += super_cell.cell[0,0]*.0 + del(atoms[atoms.positions[: , 0]<-5]) + del(atoms[atoms.positions[: , 0]>super_cell.cell[0,0]+5]) + del(atoms[atoms.positions[: , 1]<-5]) + del(atoms[atoms.positions[: , 1]>super_cell.cell[1,1]+5]) + del(atoms[atoms.positions[: , 2]<-5]) + del(atoms[atoms.positions[: , 2]>super_cell.cell[2,2]+5]) + return atoms
+ +
[docs]def get_connectivity_matrix(crystal, atoms, polyhedra): + crystal_tree = scipy.spatial.cKDTree(crystal.positions) + + + connectivity_matrix = np.zeros([len(atoms),len(atoms)], dtype=int) + + for polyhedron in polyhedra.values(): + vertices = polyhedron['vertices'] - crystal.cell.lengths() + atom_ind = np.array(polyhedron['indices']) + dd, polyhedron['atom_indices'] = crystal_tree.query(vertices , k=1) + to_bond = np.where(dd<0.001)[0] + + for triangle in polyhedron['triangles']: + triangle = np.array(triangle) + for permut in [[0,1], [1,2], [0,2]]: + vertex = [np.min(triangle[permut]), np.max(triangle[permut])] + if vertex[0] in to_bond or vertex[1] in to_bond: + connectivity_matrix[atom_ind[vertex[1]], atom_ind[vertex[0]]] = 1 + connectivity_matrix[atom_ind[vertex[0]], atom_ind[vertex[1]]] = 1 + return connectivity_matrix
+ + + +
[docs]def get_bonds(crystal, shift= 0., verbose = False, cheat=1.0): + """ + Get polyhedra, and bonds from and edges and lengths of edges for each polyhedron and store it in info dictionary of new ase.Atoms object + + Parameter: + ---------- + crystal: ase.atoms_object + information on all polyhedra + """ + crystal.positions += shift * crystal.cell[0, 0] + crystal.wrap() + + atoms = get_non_periodic_supercell(crystal) + atoms = atoms[atoms.numbers.argsort()] + + + atoms.positions += crystal.cell.lengths() + polyhedra = find_polyhedra(atoms, cheat=cheat) + + connectivity_matrix = get_connectivity_matrix(crystal, atoms, polyhedra) + coord = connectivity_matrix.sum(axis=1) + + del(atoms[np.where(coord==0)]) + new_polyhedra = {} + index = 0 + octahedra =[] + tetrahedra = [] + other = [] + super_cell_atoms =[] + + atoms_tree = scipy.spatial.cKDTree(atoms.positions-crystal.cell.lengths()) + crystal_tree = scipy.spatial.cKDTree(crystal.positions) + connectivity_matrix = np.zeros([len(atoms),len(atoms)], dtype=float) + + for polyhedron in polyhedra.values(): + polyhedron['vertices'] -= crystal.cell.lengths() + vertices = polyhedron['vertices'] + center = np.average(polyhedron['vertices'], axis=0) + + dd, polyhedron['indices'] = atoms_tree.query(vertices , k=1) + atom_ind = (np.array(polyhedron['indices'])) + dd, polyhedron['atom_indices'] = crystal_tree.query(vertices , k=1) + + to_bond = np.where(dd<0.001)[0] + super_cell_atoms.extend(list(atom_ind[to_bond])) + + edges = [] + lengths = [] + for triangle in polyhedron['triangles']: + triangle = np.array(triangle) + for permut in [[0,1], [1,2], [0,2]]: + vertex = [np.min(triangle[permut]), np.max(triangle[permut])] + length = np.linalg.norm(vertices[vertex[0]]-vertices[vertex[1]]) + if vertex[0] in to_bond or vertex[1] in to_bond: + connectivity_matrix[atom_ind[vertex[1]], atom_ind[vertex[0]]] = length + connectivity_matrix[atom_ind[vertex[0]], atom_ind[vertex[1]]] = length + if vertex[0] not in to_bond: + atoms[atom_ind[vertex[0]]].symbol = 'Be' + if vertex[1] not in to_bond: + atoms[atom_ind[vertex[1]]].symbol = 'Be' + if vertex not in edges: + edges.append(vertex) + lengths.append(np.linalg.norm(vertices[vertex[0]]-vertices[vertex[1]] )) + polyhedron['edges'] = edges + polyhedron['edge_lengths'] = lengths + if all(center > -0.000001) and all(center < crystal.cell.lengths()-0.01): + new_polyhedra[str(index)]=polyhedron + if polyhedron['length'] == 4: + tetrahedra.append(str(index)) + elif polyhedron['length'] == 6: + octahedra.append(str(index)) + else: + other.append(str(index)) + if verbose: + print(polyhedron['length']) + index += 1 + atoms.positions -= crystal.cell.lengths() + coord = connectivity_matrix.copy() + coord[np.where(coord>.1)] = 1 + coord = coord.sum(axis=1) + + super_cell_atoms = np.sort(np.unique(super_cell_atoms)) + atoms.info.update({'polyhedra': {'polyhedra': new_polyhedra, + 'tetrahedra': tetrahedra, + 'octahedra': octahedra, + 'other' : other}}) + atoms.info.update({'bonds': {'connectivity_matrix': connectivity_matrix, + 'super_cell_atoms': super_cell_atoms, + 'super_cell_dimensions': crystal.cell.array, + 'coordination': coord}}) + atoms.info.update({'supercell': crystal}) + return atoms
+ +
[docs]def plot_atoms(atoms: ase.Atoms, polyhedra_indices=None, plot_bonds=False, color='', template=None, atom_size=None, max_size=35) -> go.Figure: + """ + Plot structure in a ase.Atoms object with plotly + + If the info dictionary of the atoms object contains bond or polyedra information, these can be set tobe plotted + + Partameter: + ----------- + atoms: ase.Atoms object + structure of supercell + polyhedra_indices: list of integers + indices of polyhedra to be plotted + plot_bonds: boolean + whether to plot bonds or not + + Returns: + -------- + fig: plotly figure object + handle to figure needed to modify appearance + """ + energies = np.zeros(len(atoms)) + if 'bonds' in atoms.info: + if 'atom_energy' in atoms.info['bonds']: + energies = np.round(np.array(atoms.info['bonds']['atom_energy'] - 12 * atoms.info['bonds']['ideal_bond_energy']) *1000,0) + + for atom in atoms: + if atom.index not in atoms.info['bonds']['super_cell_atoms']: + energies[atom.index] = 0. + if color == 'coordination': + colors = atoms.info['bonds']['coordination'] + elif color == 'layer': + colors = atoms.positions[:, 2] + elif color == 'energy': + colors = energies + colors[colors>50] = 50 + colors = np.log(1+ energies) + + else: + colors = atoms.get_atomic_numbers() + + if atom_size is None: + atom_size = atoms.get_atomic_numbers()*4 + elif isinstance(atom_size, float): + atom_size = atoms.get_atomic_numbers()*4*atom_size + atom_size[atom_size>max_size] = max_size + elif isinstance(atom_size, int): + atom_size = [atom_size]*len(atoms) + if len(atom_size) != len(atoms): + atom_size = [10]*len(atoms) + print('wrong length of atom_size parameter') + plot_polyhedra = False + data = [] + if polyhedra_indices is not None: + if 'polyhedra' in atoms.info: + if polyhedra_indices == -1: + data = plot_polyhedron(atoms.info['polyhedra']['polyhedra'], range(len(atoms.info['polyhedra']['polyhedra']))) + plot_polyhedra = True + elif isinstance(polyhedra_indices, list): + data = plot_polyhedron(atoms.info['polyhedra']['polyhedra'], polyhedra_indices) + plot_polyhedra = True + text = [] + if 'bonds' in atoms.info: + coord = atoms.info['bonds']['coordination'] + for atom in atoms: + if atom.index in atoms.info['bonds']['super_cell_atoms']: + + text.append(f'Atom {atom.index}: coordination={coord[atom.index]}' + + f'x:{atom.position[0]:.2f} \n y:{atom.position[1]:.2f} \n z:{atom.position[2]:.2f}') + if 'atom_energy' in atoms.info['bonds']: + text[-1] += f"\n energy: {energies[atom.index]:.0f} meV" + else: + text.append('') + else: + text = [''] * len(atoms) + + if plot_bonds: + data += get_plot_bonds(atoms) + if plot_polyhedra or plot_bonds: + fig = go.Figure(data=data) + else: + fig = go.Figure() + if color=='energy': + fig.add_trace(go.Scatter3d( + mode='markers', + x=atoms.positions[:,0], y=atoms.positions[:,1], z=atoms.positions[:,2], + hovertemplate='<b>%{text}</b><extra></extra>', + text = text, + marker=dict( + color=colors, + size=atom_size, + sizemode='diameter', + colorscale='Rainbow', #px.colors.qualitative.Light24, + colorbar=dict(thickness=10, orientation='h')))) + #hover_name = colors))) # ["blue", "green", "red"]))) + + elif 'bonds' in atoms.info: + fig.add_trace(go.Scatter3d( + mode='markers', + x=atoms.positions[:,0], y=atoms.positions[:,1], z=atoms.positions[:,2], + hovertemplate='<b>%{text}</b><extra></extra>', + text = text, + marker=dict( + color=colors, + size=atom_size, + sizemode='diameter', + colorscale= px.colors.qualitative.Light24))) + #hover_name = colors))) # ["blue", "green", "red"]))) + + else: + fig.add_trace(go.Scatter3d( + mode='markers', + x=atoms.positions[:,0], y=atoms.positions[:,1], z=atoms.positions[:,2], + marker=dict( + color=colors, + size=atom_size, + sizemode='diameter', + colorbar=dict(thickness=10), + colorscale= px.colors.qualitative.Light24))) + #hover_name = colors))) # ["blue", "green", "red"]))) + fig.update_layout(width=1000, height=700, showlegend=False, template=template) + fig.update_layout(scene_aspectmode='data', + scene_aspectratio=dict(x=1, y=1, z=1)) + + camera = {'up': {'x': 0, 'y': 1, 'z': 0}, + 'center': {'x': 0, 'y': 0, 'z': 0}, + 'eye': {'x': 0, 'y': 0, 'z': 1}} + fig.update_coloraxes(showscale=True) + fig.update_layout(scene_camera=camera, title=r"Al-GB $") + fig.update_scenes(camera_projection_type="orthographic" ) + fig.show() + return fig
+ + + + +
[docs]def find_polyhedra(atoms, optimize=True, cheat=1.0, bond_radii=None): + """ get polyhedra information from an ase.Atoms object + + This is following the method of Banadaki and Patala + http://dx.doi.org/10.1038/s41524-017-0016-0 + + We are using the bond radius according to Kirkland, which is tabulated in + - pyTEMlib.crystal_tools.electronFF[atoms.symbols[vert]]['bond_length'][1] + + Parameter + --------- + atoms: ase.Atoms object + the structural information + cheat: float + does not exist + + Returns + ------- + polyhedra: dict + dictionary with all information of polyhedra + """ + if not isinstance(atoms, ase.Atoms): + raise TypeError('This function needs an ase.Atoms object') + + if np.abs(atoms.positions[:, 2]).sum() <= 0.01: + tetrahedra = scipy.spatial.Delaunay(atoms.positions[:, :2]) + else: + tetrahedra = scipy.spatial.Delaunay(atoms.positions) + + voronoi_vertices, voronoi_tetrahedrons, r_vv, r_a = get_voronoi(tetrahedra, atoms, optimize=optimize, bond_radii=bond_radii) + if np.abs(atoms.positions[:, 2]).sum() <= 0.01: + r_vv = np.array(r_vv)*3. + overlapping_pairs = find_overlapping_spheres(voronoi_vertices, r_vv, r_a, cheat=cheat) + + clusters, visited_all = find_interstitial_clusters(overlapping_pairs) + + if np.abs(atoms.positions[:, 2]).sum() <= 0.01: + rings = get_polygons(atoms, clusters, voronoi_tetrahedrons) + return rings + else: + polyhedra = make_polyhedrons(atoms, voronoi_vertices, voronoi_tetrahedrons, clusters, visited_all) + return polyhedra
+ + +
[docs]def polygon_sort(corners): + center = np.average(corners[:, :2], axis=0) + angles = (np.arctan2(corners[:,0]-center[0], corners[:,1]-center[1]) + 2.0 * np.pi)% (2.0 * np.pi) + return corners[np.argsort(angles)]
+ +
[docs]def get_polygons(atoms, clusters, voronoi_tetrahedrons): + polygons = [] + cyclicity = [] + centers = [] + corners =[] + for index, cluster in (enumerate(clusters)): + cc = [] + for c in cluster: + cc = cc + list(voronoi_tetrahedrons[c]) + + sorted_corners = polygon_sort(atoms.positions[list(set(cc)), :2]) + cyclicity.append(len(sorted_corners)) + corners.append(sorted_corners) + centers.append(np.mean(sorted_corners[:,:2], axis=0)) + polygons.append(patches.Polygon(np.array(sorted_corners)[:,:2], closed=True, fill=True, edgecolor='red')) + + rings={'atoms': atoms.positions[:, :2], + 'cyclicity': np.array(cyclicity), + 'centers': np.array(centers), + 'corners': corners, + 'polygons': polygons} + return rings
+ + +
[docs]def sort_polyhedra_by_vertices(polyhedra, visible=range(4, 100), z_lim=[0, 100], verbose=False): + indices = [] + + for key, polyhedron in polyhedra.items(): + if 'length' not in polyhedron: + polyhedron['length'] = len(polyhedron['vertices']) + + if polyhedron['length'] in visible: + center = polyhedron['vertices'].mean(axis=0) + if z_lim[0] < center[2] < z_lim[1]: + indices.append(key) + if verbose: + print(key, polyhedron['length'], center) + return indices
+ +# color_scheme = ['lightyellow', 'silver', 'rosybrown', 'lightsteelblue', 'orange', 'cyan', 'blue', 'magenta', +# 'firebrick', 'forestgreen'] + + + +########################## +# New Graph Stuff +########################## + + +#################### +# Distortion Matrix +#################### +
[docs]def get_distortion_matrix(atoms, ideal_lattice): + """ Calculates distortion matrix + + Calculates the distortion matrix by comparing ideal and distorted Voronoi tiles + """ + + vor = scipy.spatial.Voronoi(atoms) + + # determine a middle Voronoi tile + ideal_vor = scipy.spatial.Voronoi(ideal_lattice) + near_center = np.average(ideal_lattice, axis=0) + index = np.argmin(np.linalg.norm(ideal_lattice - near_center, axis=0)) + + # the ideal vertices fo such an Voronoi tile (are there crystals with more than one voronoi?) + ideal_vertices = ideal_vor.vertices[ideal_vor.regions[ideal_vor.point_region[index]]] + ideal_vertices = get_significant_vertices(ideal_vertices - np.average(ideal_vertices, axis=0)) + + distortion_matrix = [] + for index in range(vor.points.shape[0]): + done = int((index + 1) / vor.points.shape[0] * 50) + sys.stdout.write('\r') + # progress output : + sys.stdout.write("[%-50s] %d%%" % ('=' * done, 2 * done)) + sys.stdout.flush() + + # determine vertices of Voronoi polygons of an atom with number index + poly_point = vor.points[index] + poly_vertices = get_significant_vertices(vor.vertices[vor.regions[vor.point_region[index]]] - poly_point) + + # where ATOM has to be moved (not pixel) + ideal_point = ideal_lattice[index] + + # transform voronoi to ideal one and keep transformation matrix A + uncorrected, corrected, aa = transform_voronoi(poly_vertices, ideal_vertices) + + # pixel positions + corrected = corrected + ideal_point + (np.rint(poly_point) - poly_point) + for i in range(len(corrected)): + # original image pixels + x, y = uncorrected[i] + np.rint(poly_point) + # collect the two origin and target coordinates and store + distortion_matrix.append([x, y, corrected[i, 0], corrected[i, 1]]) + print() + return np.array(distortion_matrix)
+ + +
[docs]def undistort(distortion_matrix, image_data): + """ Undistort image according to distortion matrix + + Uses the griddata interpolation of scipy to apply distortion matrix to image. + The distortion matrix contains in origin and target pixel coordinates + target is where the pixel has to be moved (floats) + + Parameters + ---------- + distortion_matrix: numpy array (Nx2) + distortion matrix (format N x 2) + image_data: numpy array or sidpy.Dataset + image + + Returns + ------- + interpolated: numpy array + undistorted image + """ + + intensity_values = image_data[(distortion_matrix[:, 0].astype(int), distortion_matrix[:, 1].astype(int))] + + corrected = distortion_matrix[:, 2:4] + + size_x, size_y = 2 ** np.round(np.log2(image_data.shape[0:2])) # nearest power of 2 + size_x = int(size_x) + size_y = int(size_y) + grid_x, grid_y = np.mgrid[0:size_x - 1:size_x * 1j, 0:size_y - 1:size_y * 1j] + print('interpolate') + + interpolated = scipy.interpolate.griddata(np.array(corrected), np.array(intensity_values), (grid_x, grid_y), method='linear') + return interpolated
+ + +def transform_voronoi(vertices, ideal_voronoi): + """ find transformation matrix A between a distorted polygon and a perfect reference one + + Returns + ------- + uncorrected: list of points: + all points on a grid within original polygon + corrected: list of points: + coordinates of these points where pixel have to move to + aa: 2x2 matrix A: + transformation matrix + """ + + # Find Transformation Matrix, note polygons have to be ordered first. + sort_vert = [] + for vert in ideal_voronoi: + sort_vert.append(np.argmin(np.linalg.norm(vertices - vert, axis=1))) + vertices = np.array(vertices)[sort_vert] + + # Solve the least squares problem X * A = Y + # to find our transformation matrix aa = A + aa, res, rank, s = np.linalg.lstsq(vertices, ideal_voronoi, rcond=None) + + # expand polygon to include more points in distortion matrix + vertices2 = vertices + np.sign(vertices) # +np.sign(vertices) + + ext_v = int(np.abs(vertices2).max() + 1) + + polygon_grid = np.mgrid[0:ext_v * 2 + 1, :ext_v * 2 + 1] - ext_v + polygon_grid = np.swapaxes(polygon_grid, 0, 2) + polygon_array = polygon_grid.reshape(-1, polygon_grid.shape[-1]) + + p = points_in_poly(polygon_array, vertices2) + uncorrected = polygon_array[p] + + corrected = np.dot(uncorrected, aa) + + return uncorrected, corrected, aa + + +
[docs]def get_maximum_view(distortion_matrix): + distortion_matrix_extent = np.ones(distortion_matrix.shape[1:], dtype=int) + distortion_matrix_extent[distortion_matrix[0] == -1000.] = 0 + + area = distortion_matrix_extent + view_square = np.array([0, distortion_matrix.shape[1] - 1, 0, distortion_matrix.shape[2] - 1], dtype=int) + while np.array(np.where(area == 0)).shape[1] > 0: + view_square = view_square + [1, -1, 1, -1] + area = distortion_matrix_extent[view_square[0]:view_square[1], view_square[2]:view_square[3]] + + change = [-int(np.sum(np.min(distortion_matrix_extent[:view_square[0], view_square[2]:view_square[3]], axis=1))), + int(np.sum(np.min(distortion_matrix_extent[view_square[1]:, view_square[2]:view_square[3]], axis=1))), + -int(np.sum(np.min(distortion_matrix_extent[view_square[0]:view_square[1], :view_square[2]], axis=0))), + int(np.sum(np.min(distortion_matrix_extent[view_square[0]:view_square[1], view_square[3]:], axis=0)))] + + return np.array(view_square) + change
+ + +
[docs]def get_significant_vertices(vertices, distance=3): + """Calculate average for all points that are closer than distance apart, otherwise leave the points alone + + Parameters + ---------- + vertices: numpy array (n,2) + list of points + distance: float + (in same scale as points ) + + Returns + ------- + ideal_vertices: list of floats + list of points that are all a minimum of 3 apart. + """ + + tt = scipy.spatial.cKDTree(np.array(vertices)) + near = tt.query_ball_point(vertices, distance) + ideal_vertices = [] + for indices in near: + if len(indices) == 1: + ideal_vertices.append(vertices[indices][0]) + else: + ideal_vertices.append(np.average(vertices[indices], axis=0)) + ideal_vertices = np.unique(np.array(ideal_vertices), axis=0) + angles = np.arctan2(ideal_vertices[:, 1], ideal_vertices[:, 0]) + ang_sort = np.argsort(angles) + + ideal_vertices = ideal_vertices[ang_sort] + + return ideal_vertices
+ + +
[docs]def transform_voronoi(vertices, ideal_voronoi): + """ + find transformation matrix A between a polygon and a perfect one + + returns: + list of points: all points on a grid within original polygon + list of points: coordinates of these points where pixel have to move to + 2x2 matrix aa: transformation matrix + """ + # Find Transformation Matrix, note polygons have to be ordered first. + sort_vert = [] + for vert in ideal_voronoi: + sort_vert.append(np.argmin(np.linalg.norm(vertices - vert, axis=1))) + vertices = np.array(vertices)[sort_vert] + + # Solve the least squares problem X * A = Y + # to find our transformation matrix A + aa, res, rank, s = np.linalg.lstsq(vertices, ideal_voronoi, rcond=None) + + # expand polygon to include more points in distortion matrix + vertices2 = vertices + np.sign(vertices) # +np.sign(vertices) + + ext_v = int(np.abs(vertices2).max() + 1) + + polygon_grid = np.mgrid[0:ext_v * 2 + 1, :ext_v * 2 + 1] - ext_v + polygon_grid = np.swapaxes(polygon_grid, 0, 2) + polygon_array = polygon_grid.reshape(-1, polygon_grid.shape[-1]) + + p = points_in_poly(polygon_array, vertices2) + uncorrected = polygon_array[p] + + corrected = np.dot(uncorrected, aa) + + return uncorrected, corrected, aa
+ + + +
[docs]def undistort_sitk(image_data, distortion_matrix): + """ use simple ITK to undistort image + + Parameters + ---------- + image_data: numpy array with size NxM + distortion_matrix: sidpy.Dataset or numpy array with size 2 x P x Q + with P, Q >= M, N + + Returns + ------- + image: numpy array MXN + + """ + resampler = sitk.ResampleImageFilter() + resampler.SetReferenceImage(sitk.GetImageFromArray(image_data)) + resampler.SetInterpolator(sitk.sitkBSpline) + resampler.SetDefaultPixelValue(0) + + distortion_matrix2 = distortion_matrix[:, :image_data.shape[0], :image_data.shape[1]] + + displ2 = sitk.Compose( + [sitk.GetImageFromArray(-distortion_matrix2[1]), sitk.GetImageFromArray(-distortion_matrix2[0])]) + out_tx = sitk.DisplacementFieldTransform(displ2) + resampler.SetTransform(out_tx) + out = resampler.Execute(sitk.GetImageFromArray(image_data)) + return sitk.GetArrayFromImage(out)
+ + +
[docs]def undistort_stack_sitk(distortion_matrix, image_stack): + """ + use simple ITK to undistort stack of image + input: + image: numpy array with size NxM + distortion_matrix: h5 Dataset or numpy array with size 2 x P x Q + with P, Q >= M, N + output: + image M, N + + """ + + resampler = sitk.ResampleImageFilter() + resampler.SetReferenceImage(sitk.GetImageFromArray(image_stack[0])) + resampler.SetInterpolator(sitk.sitkBSpline) + resampler.SetDefaultPixelValue(0) + + displ2 = sitk.Compose( + [sitk.GetImageFromArray(-distortion_matrix[1]), sitk.GetImageFromArray(-distortion_matrix[0])]) + out_tx = sitk.DisplacementFieldTransform(displ2) + resampler.SetTransform(out_tx) + + interpolated = np.zeros(image_stack.shape) + + nimages = image_stack.shape[0] + + if QT_available: + progress = pyTEMlib.sidpy_tools.ProgressDialog("Correct Scan Distortions", nimages) + + for i in range(nimages): + if QT_available: + progress.setValue(i) + out = resampler.Execute(sitk.GetImageFromArray(image_stack[i])) + interpolated[i] = sitk.GetArrayFromImage(out) + + progress.setValue(nimages) + + if QT_available: + progress.setValue(nimages) + + return interpolated
+ + +
[docs]def undistort_stack(distortion_matrix, data): + """ Undistort stack with distortion matrix + + Use the griddata interpolation of scipy to apply distortion matrix to image + The distortion matrix contains in each pixel where the pixel has to be moved (floats) + + Parameters + ---------- + distortion_matrix: numpy array + distortion matrix to undistort image (format image.shape[0], image.shape[2], 2) + data: numpy array or sidpy.Dataset + image + """ + + corrected = distortion_matrix[:, 2:4] + intensity_values = data[:, distortion_matrix[:, 0].astype(int), distortion_matrix[:, 1].astype(int)] + + size_x, size_y = 2 ** np.round(np.log2(data.shape[1:])) # nearest power of 2 + size_x = int(size_x) + size_y = int(size_y) + + grid_x, grid_y = np.mgrid[0:size_x - 1:size_x * 1j, 0:size_y - 1:size_y * 1j] + print('interpolate') + + interpolated = np.zeros([data.shape[0], size_x, size_y]) + nimages = data.shape[0] + done = 0 + + if QT_available: + progress = ft.ProgressDialog("Correct Scan Distortions", nimages) + for i in range(nimages): + if QT_available: + progress.set_value(i) + elif done < int((i + 1) / nimages * 50): + done = int((i + 1) / nimages * 50) + sys.stdout.write('\r') + # progress output : + sys.stdout.write("[%-50s] %d%%" % ('=' * done, 2 * done)) + sys.stdout.flush() + + interpolated[i, :, :] = griddata(corrected, intensity_values[i, :], (grid_x, grid_y), method='linear') + if QT_available: + progress.set_value(nimages) + print(':-)') + print('You have successfully completed undistortion of image stack') + return interpolated
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/graph_viz.html b/_modules/pyTEMlib/graph_viz.html new file mode 100644 index 00000000..823ce98a --- /dev/null +++ b/_modules/pyTEMlib/graph_viz.html @@ -0,0 +1,564 @@ + + + + + + pyTEMlib.graph_viz — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.graph_viz

+"""
+##################################################################
+# plotting functions for graph_tools
+##################################################################
+
+part of pyTEMlib
+a pycrosccopy package
+
+Author: Gerd Duscher
+First Version: 2022-01-08
+"""
+import numpy as np
+import ase
+
+import plotly.graph_objects as go
+import plotly.express as px
+
+import pyTEMlib.crystal_tools
+import pyTEMlib.graph_tools
+
+
+
[docs]def plot_super_cell(super_cell, shift_x=0.): + """ make a super_cell to plot with extra atoms at periodic boundaries""" + + if not isinstance(super_cell, ase.Atoms): + raise TypeError('Need an ase Atoms object') + + plot_boundary = super_cell * (2, 2, 3) + plot_boundary.positions[:, 0] = plot_boundary.positions[:, 0] - super_cell.cell[0, 0] * shift_x + + del plot_boundary[plot_boundary.positions[:, 2] > super_cell.cell[2, 2] * 1.5 + 0.1] + del plot_boundary[plot_boundary.positions[:, 1] > super_cell.cell[1, 1] + 0.1] + del plot_boundary[plot_boundary.positions[:, 0] > super_cell.cell[0, 0] + 0.1] + del plot_boundary[plot_boundary.positions[:, 0] < -0.1] + plot_boundary.cell = super_cell.cell * (1, 1, 1.5) + + return plot_boundary
+ + +
[docs]def plot_polyhedron(polyhedra, indices, center=False): + """ + Information to plot polyhedra with plotly + + Parameter + --------- + polyhedra: dict + dictionary of all polyhedra + indices: list or integer + list or index of polyhedron to plot. + center: boolean + whether to center polyhedra on origin + + Returns + ------- + data: dict + instructions to plot for plotly + """ + + if isinstance(indices, int): + indices = [indices] + if len(indices) == 0: + print('Did not find any polyhedra') + return {} + + center_point = np.mean(polyhedra[indices[0]]['vertices'], axis=0) + + if center: + print(center_point) + center = center_point + else: + center = [0, 0, 0] + + data = [] + for index in indices: + polyhedron = polyhedra[index] + + vertices = polyhedron['vertices'] - center + faces = np.array(polyhedron['triangles']) + x, y, z = vertices.T + i_i, j_j, k_k = faces.T + + mesh = dict(type='mesh3d', + x=x, + y=y, + z=z, + i=i_i, + j=j_j, + k=k_k, + name='', + opacity=0.2, + color=px.colors.qualitative.Light24[len(vertices) % 24] + ) + tri_vertices = vertices[faces] + x_e = [] + y_e = [] + z_e = [] + for t_v in tri_vertices: + x_e += [t_v[k % 3][0] for k in range(4)] + [None] + y_e += [t_v[k % 3][1] for k in range(4)] + [None] + z_e += [t_v[k % 3][2] for k in range(4)] + [None] + + # define the lines to be plotted + lines = dict(type='scatter3d', + x=x_e, + y=y_e, + z=z_e, + mode='lines', + name='', + line=dict(color='rgb(70,70,70)', width=1.5)) + data.append(mesh) + data.append(lines) + return data
+ + +
[docs]def plot_bonds(polyhedra): + """ + Information to plot bonds with plotly + + Parameter + --------- + polyhedra: dict + dictionary of all polyhedra + + Returns + ------- + data: dict + instructions to plot for plotly + """ + indices = range(len(polyhedra)) + + data = [] + for index in indices: + polyhedron = polyhedra[index] + + vertices = polyhedron['vertices'] + faces = np.array(polyhedron['triangles']) + x, y, z = vertices.T + i_i, j_j, k_k = faces.T + + tri_vertices = vertices[faces] + x_e = [] + y_e = [] + z_e = [] + for t_v in tri_vertices: + x_e += [t_v[k % 3][0] for k in range(4)] + [None] + y_e += [t_v[k % 3][1] for k in range(4)] + [None] + z_e += [t_v[k % 3][2] for k in range(4)] + [None] + + # define the lines to be plotted + lines = dict(type='scatter3d', + x=x_e, + y=y_e, + z=z_e, + mode='lines', + name='', + line=dict(color='rgb(70,70,70)', width=1.5)) + data.append(lines) + return data
+ + +
[docs]def get_boundary_polyhedra(polyhedra, boundary_x=0, boundary_width=0.5, verbose=True, z_lim=[0, 100]): + """ + get indices of polyhedra at boundary (assumed to be parallel to x-axis) + + Parameter + --------- + polyhedra: dict + dictionary of all polyhedra + boundary_x: float + position of boundary in Angstrom + boundary_width: float + width of boundary where center of polyhedra are considered in Angstrom + verbose: boolean + optional + z_lim: list + upper and lower limit of polyhedra to plot + + Returns + ------- + boundary_polyhedra: list + list of polyhedra at boundary + """ + boundary_polyhedra = [] + for key, polyhedron in polyhedra.items(): + center = polyhedron['vertices'].mean(axis=0) + if abs(center[0] - boundary_x) < 0.5 and (z_lim[0] < center[2] < z_lim[1]): + boundary_polyhedra.append(key) + if verbose: + print(key, polyhedron['length'], center) + + return boundary_polyhedra
+ + +
[docs]def plot_with_polyhedra(polyhedra, indices, atoms=None, title=''): + """ + plot atoms and polyhedra with plotly + + Parameter + --------- + polyhedra: dict + dictionary of all polyhedra + indices: list or integer + list or index of polyhedron to plot. + atoms: ase.Atoms + optional structure info to plot atoms (with correct color) + + Returns + ------- + fig: plotly.figure + plotly figure instance + """ + + data = plot_polyhedron(polyhedra, indices) + if not isinstance(atoms, ase.Atoms): + atoms = None + + data[0]['opacity'] = 0.05 + fig = go.Figure(data=data) + if atoms is not None: + fig.add_trace(go.Scatter3d( + mode='markers', + x=atoms.positions[:, 0], y=atoms.positions[:, 1], z=atoms.positions[:, 2], + marker=dict( + color=atoms.get_atomic_numbers(), + size=5, + sizemode='diameter', + colorscale=["blue", "green", "red"]))) + + fig.update_layout(width=1000, height=700, showlegend=False) + fig.update_layout(scene_aspectmode='data', + scene_aspectratio=dict(x=1, y=1, z=1)) + + camera = {'up': {'x': 1, 'y': 0, 'z': 0}, + 'center': {'x': 0, 'y': 0, 'z': 0}, + 'eye': {'x': 0, 'y': 0, 'z': 1}} + + fig.update_layout(scene_camera=camera, title=title) + fig.update_scenes(camera_projection_type="orthographic") + return fig
+ + +
[docs]def plot_supercell(supercell, size=(1, 1, 1), shift_x=0.25, title=''): + """ + plot supercell with plotly + + Parameter + --------- + supercell: ase.Atoms + optional structure info to plot atoms (with correct color) + shift_x: float + amount of shift in x direction of supercell + title: str + title of plot + + Returns + ------- + fig: plotly.figure + plotly figure instance + """ + + plot_cell = pyTEMlib.graph_tools.plot_super_cell(supercell * size, shift_x=shift_x) + + # grain_boundary.cell.volume + supercell_area = supercell.cell.lengths()[1] / supercell.cell.lengths()[2] + print(supercell.symbols) + volume__bulk_atom = 16.465237835776012 + ideal_volume = len(supercell.positions) * volume__bulk_atom + print(len(supercell.positions) * volume__bulk_atom, supercell.cell.volume) + x_0 = ideal_volume / supercell.cell.lengths()[1] / supercell.cell.lengths()[2] + print(f'Zero volume expansion supercell length: {x_0 / 10:.2f} nm; ' + f' compared to actual {supercell.cell.lengths()[0] / 10:.2f} nm') + + fig = go.Figure(data=[ + go.Scatter3d(x=plot_cell.positions[:, 0], y=plot_cell.positions[:, 1], z=plot_cell.positions[:, 2], + mode='markers', + marker=dict( + color=plot_cell.get_atomic_numbers(), + size=5, + sizemode='diameter', + colorscale=["blue", "green", "red"]))]) + + fig.update_layout(width=700, margin=dict(r=10, l=10, b=10, t=10)) + fig.update_layout(scene_aspectmode='data', + scene_aspectratio=dict(x=1, y=1, z=1)) + + camera = dict( + up=dict(x=0, y=1, z=0), + center=dict(x=0, y=0, z=0), + eye=dict(x=0, y=0, z=1) + ) + fig.update_layout(scene_camera=camera, title=title) + fig.update_scenes(camera_projection_type="orthographic") + return fig
+ + +
[docs]def plot_supercell_bonds(polyhedra, atoms, volumes=None, atom_size=15, title=''): + """ + plot atoms and bonds with plotly + + Parameter + --------- + polyhedra: dict + dictionary of all polyhedra + atoms: ase.Atoms + optional structure info to plot atoms (with correct color) + volumes: list + list of volumes, optional structure + atoms_size: float + sie of atoms to plot + title: str + title of plot + + Returns + ------- + fig: plotly.figure + plotly figure instance + """ + + data = plot_bonds(polyhedra) + if volumes is None: + volumes = [atom_size] * len(atoms.get_atomic_numbers()) + + fig = go.Figure(data=data) + fig.add_trace(go.Scatter3d( + mode='markers', + x=atoms.positions[:, 0], y=atoms.positions[:, 1], z=atoms.positions[:, 2], + marker=dict( + color=atoms.get_atomic_numbers(), + size=np.asarray(volumes) ** 2 / 10, + sizemode='diameter', + colorscale=["blue", "green", "red"]))) + + fig.update_layout(width=1000, height=700, showlegend=False) + fig.update_layout(scene_aspectmode='data', + scene_aspectratio=dict(x=1, y=1, z=1)) + + camera = {'up': {'x': 0, 'y': 1, 'z': 0}, + 'center': {'x': 0, 'y': 0, 'z': 0}, + 'eye': {'x': 0, 'y': 0, 'z': 1}} + fig.update_layout(scene_camera=camera, title=title) + fig.update_scenes(camera_projection_type="orthographic") + return fig
+ + +
[docs]def plot_supercell_polyhedra(polyhedra, indices, atoms, volumes=None, title=''): + """ + plot atoms and polyhedra with plotly + + Parameter + --------- + polyhedra: dict + dictionary of all polyhedra + indices: list + list of indices of polyhedra to plot + atoms: ase.Atoms + optional structure info to plot atoms (with correct color) + volumes: list + list of volumes, optional structure + title: str + title of plot + + Returns + ------- + fig: plotly.figure + plotly figure instance + """ + data = plot_polyhedron(polyhedra, indices) + if volumes is None: + volumes = [10] * len(atoms.get_atomic_numbers()) + + fig = go.Figure(data=data) + fig.add_trace(go.Scatter3d( + mode='markers', + x=atoms.positions[:, 0], y=atoms.positions[:, 1], z=atoms.positions[:, 2], + marker=dict( + color=atoms.get_atomic_numbers(), + size=np.asarray(volumes)**2 / 10, + sizemode='diameter', + colorscale=["blue", "green", "red"]))) + + fig.update_layout(width=1000, height=700, showlegend=False) + fig.update_layout(scene_aspectmode='data', + scene_aspectratio=dict(x=1, y=1, z=1)) + + camera = {'up': {'x': 0, 'y': 1, 'z': 0}, + 'center': {'x': 0, 'y': 0, 'z': 0}, + 'eye': {'x': 0, 'y': 0, 'z': 1}} + fig.update_layout(scene_camera=camera, title=title) + fig.update_scenes(camera_projection_type="orthographic") + return fig
+ + +
[docs]def show_polyhedra(polyhedra, boundary_polyhedra, atoms, volumes=None, title=f''): + """ + plot polyhedra and atoms of vertices with plotly + + Parameter + --------- + polyhedra: dict + dictionary of all polyhedra + boundary_polyhedra: list + list of indices of polyhedra to plot + atoms: ase.Atoms + optional structure info to plot atoms (with correct color) + volumes: list + list of volumes, optional structure + title: str + title of plot + + Returns + ------- + fig: plotly.figure + plotly figure instance + """ + + data = plot_polyhedron(polyhedra, boundary_polyhedra) + atom_indices = [] + for poly in boundary_polyhedra: + atom_indices.extend(polyhedra[poly]['indices']) + atom_indices = list(set(atom_indices)) + atomic_numbers = [] + atomic_volumes = [] + for atom in atom_indices: + atomic_numbers.append(atoms[atom].number) + atomic_volumes.append(volumes[atoms[atom].index] ** 2 / 10) + + if volumes is None: + atomic_volumes = [10] * len(atoms.get_atomic_numbers()) + fig = go.Figure(data=data) + + fig.add_trace(go.Scatter3d( + mode='markers', + x=atoms.positions[atom_indices, 0], y=atoms.positions[atom_indices, 1], z=atoms.positions[atom_indices, 2], + marker=dict( + color=atomic_numbers, + size=atomic_volumes, + sizemode='diameter', + colorscale=["blue", "green", "red"]))) + + fig.update_layout(width=1000, height=700, showlegend=False) + fig.update_layout(scene_aspectmode='data', + scene_aspectratio=dict(x=1, y=1, z=1)) + + camera = {'up': {'x': 1, 'y': 0, 'z': 0}, + 'center': {'x': 0, 'y': 0, 'z': 0}, + 'eye': {'x': 0, 'y': 0, 'z': 1}} + fig.update_layout(scene_camera=camera, title=title) + fig.update_scenes(camera_projection_type="orthographic") + return fig
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/image_tools.html b/_modules/pyTEMlib/image_tools.html new file mode 100644 index 00000000..bd44f6c1 --- /dev/null +++ b/_modules/pyTEMlib/image_tools.html @@ -0,0 +1,1280 @@ + + + + + + pyTEMlib.image_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.image_tools

+"""
+image_tools.py
+by Gerd Duscher, UTK
+part of pyTEMlib
+MIT license except where stated differently
+"""
+
+import numpy as np
+
+import matplotlib as mpl
+import matplotlib.pylab as plt
+import matplotlib.widgets as mwidgets
+# from matplotlib.widgets import RectangleSelector
+
+import sidpy
+import pyTEMlib.file_tools as ft
+import pyTEMlib.sidpy_tools
+# import pyTEMlib.probe_tools
+
+from tqdm.auto import trange, tqdm
+
+# import itertools
+from itertools import product
+
+from scipy import fftpack
+# from scipy import signal
+from scipy.interpolate import interp1d  # , interp2d
+import scipy.optimize as optimization
+
+# Multidimensional Image library
+import scipy.ndimage as ndimage
+import scipy.constants as const
+
+# from scipy.spatial import Voronoi, KDTree, cKDTree
+
+import skimage
+
+import skimage.registration as registration
+# from skimage.feature import register_translation  # blob_dog, blob_doh
+from skimage.feature import peak_local_max
+# from skimage.measure import points_in_poly
+
+# our blob detectors from the scipy image package
+from skimage.feature import blob_log  # blob_dog, blob_doh
+
+from sklearn.feature_extraction import image
+from sklearn.utils.extmath import randomized_svd
+from sklearn.cluster import DBSCAN
+
+from collections import Counter
+
+
+_SimpleITK_present = True
+try:
+    import SimpleITK as sitk
+except ImportError:
+    sitk = False
+    _SimpleITK_present = False
+
+if not _SimpleITK_present:
+    print('SimpleITK not installed; Registration Functions for Image Stacks not available\n' +
+          'install with: conda install -c simpleitk simpleitk ')
+
+
+# Wavelength in 1/nm
+
[docs]def get_wavelength(e0): + """ + Calculates the relativistic corrected de Broglie wave length of an electron + + Parameters + ---------- + e0: float + acceleration voltage in volt + + Returns + ------- + wave length in 1/nm + """ + + eV = const.e * e0 + return const.h/np.sqrt(2*const.m_e*eV*(1+eV/(2*const.m_e*const.c**2)))*10**9
+ + +
[docs]def fourier_transform(dset): + """ + Reads information into dictionary 'tags', performs 'FFT', and provides a smoothed FT and reciprocal + and intensity limits for visualization. + + Parameters + ---------- + dset: sidpy.Dataset + image + + Returns + ------- + fft_dset: sidpy.Dataset + Fourier transform with correct dimensions + + Example + ------- + >>> fft_dataset = fourier_transform(sidpy_dataset) + >>> fft_dataset.plot() + """ + + assert isinstance(dset, sidpy.Dataset), 'Expected a sidpy Dataset' + + selection = [] + image_dim = [] + # image_dim = get_image_dims(sidpy.DimensionTypes.SPATIAL) + + if dset.data_type == sidpy.DataType.IMAGE_STACK: + image_dim = dset.get_image_dims() + stack_dim = dset.get_dimensions_by_type('TEMPORAL') + + if len(image_dim) != 2: + raise ValueError('need at least two SPATIAL dimension for an image stack') + + for i in range(dset.dims): + if i in image_dim: + selection.append(slice(None)) + if len(stack_dim) == 0: + stack_dim = i + selection.append(slice(None)) + elif i in stack_dim: + stack_dim = i + selection.append(slice(None)) + else: + selection.append(slice(0, 1)) + + image_stack = np.squeeze(np.array(dset)[selection]) + new_image = np.sum(np.array(image_stack), axis=stack_dim) + elif dset.data_type == sidpy.DataType.IMAGE: + new_image = np.array(dset) + else: + return + + new_image = new_image - new_image.min() + fft_transform = (np.fft.fftshift(np.fft.fft2(new_image))) + + image_dims = pyTEMlib.sidpy_tools.get_image_dims(dset) + + units_x = '1/' + dset._axes[image_dims[0]].units + units_y = '1/' + dset._axes[image_dims[1]].units + + fft_dset = sidpy.Dataset.from_array(fft_transform) + fft_dset.quantity = dset.quantity + fft_dset.units = 'a.u.' + fft_dset.data_type = 'IMAGE' + fft_dset.source = dset.title + fft_dset.modality = 'fft' + + fft_dset.set_dimension(0, sidpy.Dimension(np.fft.fftshift(np.fft.fftfreq(new_image.shape[0], + d=ft.get_slope(dset.x.values))), + + name='u', units=units_x, dimension_type='RECIPROCAL', + quantity='reciprocal_length')) + fft_dset.set_dimension(1, sidpy.Dimension(np.fft.fftshift(np.fft.fftfreq(new_image.shape[1], + d=ft.get_slope(dset.y.values))), + name='v', units=units_y, dimension_type='RECIPROCAL', + quantity='reciprocal_length')) + + return fft_dset
+ + +
[docs]def power_spectrum(dset, smoothing=3): + """ + Calculate power spectrum + + Parameters + ---------- + dset: sidpy.Dataset + image + smoothing: int + Gaussian smoothing + + Returns + ------- + power_spec: sidpy.Dataset + power spectrum with correct dimensions + + """ + + fft_transform = fourier_transform(dset) # dset.fft() + fft_mag = np.abs(fft_transform) + fft_mag2 = ndimage.gaussian_filter(fft_mag, sigma=(smoothing, smoothing), order=0) + + power_spec = fft_transform.like_data(np.log(1.+fft_mag2)) + + # prepare mask + x, y = np.meshgrid(power_spec.v.values, power_spec.u.values) + mask = np.zeros(power_spec.shape) + + mask_spot = x ** 2 + y ** 2 > 1 ** 2 + mask = mask + mask_spot + mask_spot = x ** 2 + y ** 2 < 11 ** 2 + mask = mask + mask_spot + + mask[np.where(mask == 1)] = 0 # just in case of overlapping disks + + minimum_intensity = np.array(power_spec)[np.where(mask == 2)].min() * 0.95 + maximum_intensity = np.array(power_spec)[np.where(mask == 2)].max() * 1.05 + power_spec.metadata = {'fft': {'smoothing': smoothing, + 'minimum_intensity': minimum_intensity, 'maximum_intensity': maximum_intensity}} + power_spec.title = 'power spectrum ' + power_spec.source + + return power_spec
+ + +
[docs]def diffractogram_spots(dset, spot_threshold, return_center = True, eps = 0.1): + """Find spots in diffractogram and sort them by distance from center + + Uses blob_log from scipy.spatial + + Parameters + ---------- + dset: sidpy.Dataset + diffractogram + spot_threshold: float + threshold for blob finder + + Returns + ------- + spots: numpy array + sorted position (x,y) and radius (r) of all spots + """ + + # spot detection (for future reference there is no symmetry assumed here) + data = np.array(np.log(1+np.abs(dset))) + data = data - data.min() + data = data/data.max() + # some images are strange and blob_log does not work on the power spectrum + try: + spots_random = blob_log(data, max_sigma=5, threshold=spot_threshold) + except ValueError: + spots_random = peak_local_max(np.array(data.T), min_distance=3, threshold_rel=spot_threshold) + spots_random = np.hstack(spots_random, np.zeros((spots_random.shape[0], 1))) + + print(f'Found {spots_random.shape[0]} reflections') + + # Needed for conversion from pixel to Reciprocal space + rec_scale = np.array([ft.get_slope(dset.u.values), ft.get_slope(dset.v.values)]) + spots_random[:, :2] = spots_random[:, :2]*rec_scale+[dset.u.values[0], dset.v.values[0]] + # sort reflections + spots_random[:, 2] = np.linalg.norm(spots_random[:, 0:2], axis=1) + spots_index = np.argsort(spots_random[:, 2]) + spots = spots_random[spots_index] + # third row is angles + spots[:, 2] = np.arctan2(spots[:, 0], spots[:, 1]) + + if return_center == True: + points = spots[:, 0:2] + + # Calculate the midpoints between all points + reshaped_points = points[:, np.newaxis, :] + midpoints = (reshaped_points + reshaped_points.transpose(1, 0, 2)) / 2.0 + midpoints = midpoints.reshape(-1, 2) + + # Find the most dense cluster of midpoints + dbscan = DBSCAN(eps = eps, min_samples = 2) + labels = dbscan.fit_predict(midpoints) + cluster_counter = Counter(labels) + largest_cluster_label = max(cluster_counter, key=cluster_counter.get) + largest_cluster_points = midpoints[labels == largest_cluster_label] + + # Average of these midpoints must be the center + center = np.mean(largest_cluster_points,axis=0) + + return spots, center
+ + +
[docs]def adaptive_fourier_filter(dset, spots, low_pass=3, reflection_radius=0.3): + """ + Use spots in diffractogram for a Fourier Filter + + Parameters: + ----------- + dset: sidpy.Dataset + image to be filtered + spots: np.ndarray(N,2) + sorted spots in diffractogram in 1/nm + low_pass: float + low pass filter in center of diffractogram in 1/nm + reflection_radius: float + radius of masked reflections in 1/nm + + Output: + ------- + Fourier filtered image + """ + + if not isinstance(dset, sidpy.Dataset): + raise TypeError('We need a sidpy.Dataset') + fft_transform = fourier_transform(dset) + + # prepare mask + x, y = np.meshgrid(fft_transform.v.values, fft_transform.u.values) + mask = np.zeros(dset.shape) + + # mask reflections + for spot in spots: + mask_spot = (x - spot[1]) ** 2 + (y - spot[0]) ** 2 < reflection_radius ** 2 # make a spot + mask = mask + mask_spot # add spot to mask + + # mask zero region larger (low-pass filter = intensity variations) + mask_spot = x ** 2 + y ** 2 < low_pass ** 2 + mask = mask + mask_spot + mask[np.where(mask > 1)] = 1 + fft_filtered = np.array(fft_transform * mask) + + filtered_image = dset.like_data(np.fft.ifft2(np.fft.fftshift(fft_filtered)).real) + filtered_image.title = 'Fourier filtered ' + dset.title + filtered_image.source = dset.title + filtered_image.metadata = {'analysis': 'adaptive fourier filtered', 'spots': spots, + 'low_pass': low_pass, 'reflection_radius': reflection_radius} + return filtered_image
+ + +
[docs]def rotational_symmetry_diffractogram(spots): + """ Test rotational symmetry of diffraction spots""" + + rotation_symmetry = [] + for n in [2, 3, 4, 6]: + cc = np.array( + [[np.cos(2 * np.pi / n), np.sin(2 * np.pi / n), 0], [-np.sin(2 * np.pi / n), np.cos(2 * np.pi / n), 0], + [0, 0, 1]]) + sym_spots = np.dot(spots, cc) + dif = [] + for p0, p1 in product(sym_spots[:, 0:2], spots[:, 0:2]): + dif.append(np.linalg.norm(p0 - p1)) + dif = np.array(sorted(dif)) + + if dif[int(spots.shape[0] * .7)] < 0.2: + rotation_symmetry.append(n) + return rotation_symmetry
+ +##################################################### +# Registration Functions +##################################################### + + +
[docs]def complete_registration(main_dataset, storage_channel=None): + """Rigid and then non-rigid (demon) registration + + Performs rigid and then non-rigid registration, please see individual functions: + - rigid_registration + - demon_registration + + Parameters + ---------- + main_dataset: sidpy.Dataset + dataset of data_type 'IMAGE_STACK' to be registered + storage_channel: h5py.Group + optional - location in hdf5 file to store datasets + + Returns + ------- + non_rigid_registered: sidpy.Dataset + rigid_registered_dataset: sidpy.Dataset + + """ + + if not isinstance(main_dataset, sidpy.Dataset): + raise TypeError('We need a sidpy.Dataset') + if main_dataset.data_type.name != 'IMAGE_STACK': + raise TypeError('Registration makes only sense for an image stack') + + print('Rigid_Registration') + + rigid_registered_dataset = rigid_registration(main_dataset) + if storage_channel is None: + storage_channel = main_dataset.h5_dataset.parent.parent + + registration_channel = ft.log_results(storage_channel, rigid_registered_dataset) + + print('Non-Rigid_Registration') + + non_rigid_registered = demon_registration(rigid_registered_dataset) + registration_channel = ft.log_results(storage_channel, non_rigid_registered) + + return non_rigid_registered, rigid_registered_dataset
+ + +
[docs]def demon_registration(dataset, verbose=False): + """ + Diffeomorphic Demon Non-Rigid Registration + + Depends on: + simpleITK and numpy + Please Cite: http://www.simpleitk.org/SimpleITK/project/parti.html + and T. Vercauteren, X. Pennec, A. Perchant and N. Ayache + Diffeomorphic Demons Using ITK\'s Finite Difference Solver Hierarchy + The Insight Journal, http://hdl.handle.net/1926/510 2007 + + Parameters + ---------- + dataset: sidpy.Dataset + stack of image after rigid registration and cropping + verbose: boolean + optional for increased output + Returns + ------- + dem_reg: stack of images with non-rigid registration + + Example + ------- + dem_reg = demon_reg(stack_dataset, verbose=False) + """ + + if not isinstance(dataset, sidpy.Dataset): + raise TypeError('We need a sidpy.Dataset') + if dataset.data_type.name != 'IMAGE_STACK': + raise TypeError('Registration makes only sense for an image stack') + + dem_reg = np.zeros(dataset.shape) + nimages = dataset.shape[0] + if verbose: + print(nimages) + # create fixed image by summing over rigid registration + + fixed_np = np.average(np.array(dataset), axis=0) + + if not _SimpleITK_present: + print('This feature is not available: \n Please install simpleITK with: conda install simpleitk -c simpleitk') + + fixed = sitk.GetImageFromArray(fixed_np) + fixed = sitk.DiscreteGaussian(fixed, 2.0) + + # demons = sitk.SymmetricForcesDemonsRegistrationFilter() + demons = sitk.DiffeomorphicDemonsRegistrationFilter() + + demons.SetNumberOfIterations(200) + demons.SetStandardDeviations(1.0) + + resampler = sitk.ResampleImageFilter() + resampler.SetReferenceImage(fixed) + resampler.SetInterpolator(sitk.sitkBSpline) + resampler.SetDefaultPixelValue(0) + + done = 0 + + for i in trange(nimages): + + moving = sitk.GetImageFromArray(dataset[i]) + moving_f = sitk.DiscreteGaussian(moving, 2.0) + displacement_field = demons.Execute(fixed, moving_f) + out_tx = sitk.DisplacementFieldTransform(displacement_field) + resampler.SetTransform(out_tx) + out = resampler.Execute(moving) + dem_reg[i, :, :] = sitk.GetArrayFromImage(out) + + print(':-)') + print('You have successfully completed Diffeomorphic Demons Registration') + + demon_registered = dataset.like_data(dem_reg) + demon_registered.title = 'Non-Rigid Registration' + demon_registered.source = dataset.title + + demon_registered.metadata = {'analysis': 'non-rigid demon registration'} + if 'input_crop' in dataset.metadata: + demon_registered.metadata['input_crop'] = dataset.metadata['input_crop'] + if 'input_shape' in dataset.metadata: + demon_registered.metadata['input_shape'] = dataset.metadata['input_shape'] + demon_registered.metadata['input_dataset'] = dataset.source + return demon_registered
+ + +############################### +# Rigid Registration New 05/09/2020 + +
[docs]def rigid_registration(dataset): + """ + Rigid registration of image stack with pixel accuracy + + Uses simple cross_correlation + (we determine drift from one image to next) + + Parameters + ---------- + dataset: sidpy.Dataset + sidpy dataset with image_stack dataset + + Returns + ------- + rigid_registered: sidpy.Dataset + Registered Stack and drift (with respect to center image) + """ + + if not isinstance(dataset, sidpy.Dataset): + raise TypeError('We need a sidpy.Dataset') + if dataset.data_type.name != 'IMAGE_STACK': + raise TypeError('Registration makes only sense for an image stack') + + frame_dim = [] + spatial_dim = [] + selection = [] + + for i, axis in dataset._axes.items(): + if axis.dimension_type.name == 'SPATIAL': + spatial_dim.append(i) + selection.append(slice(None)) + else: + frame_dim.append(i) + selection.append(slice(0, 1)) + + if len(spatial_dim) != 2: + print('need two spatial dimensions') + if len(frame_dim) != 1: + print('need one frame dimensions') + + nopix = dataset.shape[spatial_dim[0]] + nopiy = dataset.shape[spatial_dim[1]] + nimages = dataset.shape[frame_dim[0]] + + print('Stack contains ', nimages, ' images, each with', nopix, ' pixels in x-direction and ', nopiy, + ' pixels in y-direction') + + fixed = dataset[tuple(selection)].squeeze().compute() + fft_fixed = np.fft.fft2(fixed) + + relative_drift = [[0., 0.]] + + for i in trange(nimages): + selection[frame_dim[0]] = slice(i, i+1) + moving = dataset[tuple(selection)].squeeze().compute() + fft_moving = np.fft.fft2(moving) + image_product = fft_fixed * fft_moving.conj() + cc_image = np.fft.fftshift(np.fft.ifft2(image_product)) + shift =np.array(ndimage.maximum_position(cc_image.real))-cc_image.shape[0]/2 + fft_fixed = fft_moving + relative_drift.append(shift) + rig_reg, drift = rig_reg_drift(dataset, relative_drift) + + + crop_reg, input_crop = crop_image_stack(rig_reg, drift) + + rigid_registered = dataset.like_data(crop_reg) + rigid_registered.title = 'Rigid Registration' + rigid_registered.source = dataset.title + rigid_registered.metadata = {'analysis': 'rigid sub-pixel registration', 'drift': drift, + 'input_crop': input_crop, 'input_shape': dataset.shape[1:]} + + # if hasattr(rigid_registered, 'z'): + # del rigid_registered.z + # if hasattr(rigid_registered, 'x'): + # del rigid_registered.x + # if hasattr(rigid_registered, 'y'): + # del rigid_registered.y + + + # rigid_registered._axes = {} + rigid_registered.set_dimension(0, dataset._axes[frame_dim[0]]) + rigid_registered.set_dimension(1, dataset._axes[spatial_dim[0]][input_crop[0]:input_crop[1]]) + rigid_registered.set_dimension(2, dataset._axes[spatial_dim[1]][input_crop[2]:input_crop[3]]) + return rigid_registered.rechunk({0: 'auto', 1: -1, 2: -1})
+ +
[docs]def rig_reg_drift(dset, rel_drift): + """ Shifting images on top of each other + + Uses relative drift to shift images on top of each other, + with center image as reference. + Shifting is done with shift routine of ndimage from scipy. + This function is used by rigid_registration routine + + Parameters + ---------- + dset: sidpy.Dataset + dataset with image_stack + rel_drift: + relative_drift from image to image as list of [shiftx, shifty] + + Returns + ------- + stack: numpy array + drift: list of drift in pixel + """ + + frame_dim = [] + spatial_dim = [] + selection = [] + + for i, axis in dset._axes.items(): + if axis.dimension_type.name == 'SPATIAL': + spatial_dim.append(i) + selection.append(slice(None)) + else: + frame_dim.append(i) + selection.append(slice(0, 1)) + + if len(spatial_dim) != 2: + print('need two spatial dimensions') + if len(frame_dim) != 1: + print('need one frame dimensions') + + rig_reg = np.zeros([dset.shape[frame_dim[0]], dset.shape[spatial_dim[0]], dset.shape[spatial_dim[1]]]) + + # absolute drift + drift = np.array(rel_drift).copy() + + drift[0] = [0, 0] + for i in range(drift.shape[0]): + drift[i] = drift[i - 1] + rel_drift[i] + center_drift = drift[int(drift.shape[0] / 2)] + drift = drift - center_drift + # Shift images + for i in range(rig_reg.shape[0]): + selection[frame_dim[0]] = slice(i, i+1) + # Now we shift + rig_reg[i, :, :] = ndimage.shift(dset[tuple(selection)].squeeze().compute(), [drift[i, 0], drift[i, 1]], order=3) + return rig_reg, drift
+ + +
[docs]def crop_image_stack(rig_reg, drift): + """Crop images in stack according to drift + + This function is used by rigid_registration routine + + Parameters + ---------- + rig_reg: numpy array (N,x,y) + drift: list (2,B) + + Returns + ------- + numpy array + """ + + xpmin = int(-np.floor(np.min(np.array(drift)[:, 0]))) + xpmax = int(rig_reg.shape[1] - np.ceil(np.max(np.array(drift)[:, 0]))) + ypmin = int(-np.floor(np.min(np.array(drift)[:, 1]))) + ypmax = int(rig_reg.shape[2] - np.ceil(np.max(np.array(drift)[:, 1]))) + + return rig_reg[:, xpmin:xpmax, ypmin:ypmax], [xpmin, xpmax, ypmin, ypmax]
+ +
[docs]class ImageWithLineProfile: + """Image with line profile""" + + def __init__(self, data, extent, title=''): + fig, ax = plt.subplots(1, 1) + self.figure = fig + self.title = title + self.line_plot = False + self.ax = ax + self.data = data + self.extent = extent + self.ax.imshow(data, extent=extent) + self.ax.set_title(title) + self.line, = self.ax.plot([0], [0], color='orange') # empty line + self.end_x = self.line.get_xdata() + self.end_y = self.line.get_ydata() + self.cid = self.line.figure.canvas.mpl_connect('button_press_event', self) + +
[docs] def __call__(self, event): + if event.inaxes != self.line.axes: + return + self.start_x = self.end_x + self.start_y = self.end_y + + self.line.set_data([self.start_x, event.xdata], [self.start_y, event.ydata]) + self.line.figure.canvas.draw() + + self.end_x = event.xdata + self.end_y = event.ydata + + self.update()
+ + def update(self): + if not self.line_plot: + self.line_plot = True + self.figure.clear() + self.ax = self.figure.subplots(2, 1) + self.ax[0].imshow(self.data, extent=self.extent) + self.ax[0].set_title(self.title) + + self.line, = self.ax[0].plot([0], [0], color='orange') # empty line + self.line_plot, = self.ax[1].plot([], [], color='orange') + self.ax[1].set_xlabel('distance [nm]') + + x0 = self.start_x + x1 = self.end_x + y0 = self.start_y + y1 = self.end_y + length_plot = np.sqrt((x1-x0)**2+(y1-y0)**2) + + num = length_plot*(self.data.shape[0]/self.extent[1]) + x = np.linspace(x0, x1, num)*(self.data.shape[0]/self.extent[1]) + y = np.linspace(y0, y1, num)*(self.data.shape[0]/self.extent[1]) + + # Extract the values along the line, using cubic interpolation + zi2 = ndimage.map_coordinates(self.data.T, np.vstack((x, y))) + + x_axis = np.linspace(0, length_plot, len(zi2)) + self.x = x_axis + self.z = zi2 + + self.line_plot.set_xdata(x_axis) + self.line_plot.set_ydata(zi2) + self.ax[1].set_xlim(0, x_axis.max()) + self.ax[1].set_ylim(zi2.min(), zi2.max()) + self.ax[1].draw()
+ + +
[docs]def histogram_plot(image_tags): + """interactive histogram""" + nbins = 75 + color_map_list = ['gray', 'viridis', 'jet', 'hot'] + if 'minimum_intensity' not in image_tags: + image_tags['minimum_intensity'] = image_tags['plotimage'].min() + minimum_intensity = image_tags['minimum_intensity'] + if 'maximum_intensity' not in image_tags: + image_tags['maximum_intensity'] = image_tags['plotimage'].max() + data = image_tags['plotimage'] + vmin = image_tags['minimum_intensity'] + vmax = image_tags['maximum_intensity'] + if 'color_map' not in image_tags: + image_tags['color_map'] = color_map_list[0] + cmap = plt.cm.get_cmap(image_tags['color_map']) + + colors = cmap(np.linspace(0., 1., nbins)) + + norm2 = mpl.colors.Normalize(vmin=vmin, vmax=vmax) + hist, bin_edges = np.histogram(data, np.linspace(vmin, vmax, nbins), density=True) + + width = bin_edges[1]-bin_edges[0] + + def onselect(vmin, vmax): + ax1.clear() + cmap = plt.cm.get_cmap(image_tags['color_map']) + + colors = cmap(np.linspace(0., 1., nbins)) + + norm2 = mpl.colors.Normalize(vmin=vmin, vmax=vmax) + hist2, bin_edges2 = np.histogram(data, np.linspace(vmin, vmax, nbins), density=True) + + width2 = (bin_edges2[1]-bin_edges2[0]) + + for i in range(nbins-1): + histogram[i].xy = (bin_edges2[i], 0) + histogram[i].set_height(hist2[i]) + histogram[i].set_width(width2) + histogram[i].set_facecolor(colors[i]) + ax.set_xlim(vmin, vmax) + ax.set_ylim(0, hist2.max()*1.01) + + cb1 = mpl.colorbar.ColorbarBase(ax1, cmap=cmap, norm=norm2, orientation='horizontal') + + image_tags['minimum_intensity'] = vmin + image_tags['maximum_intensity'] = vmax + + def onclick(event): + global event2 + event2 = event + print('%s click: button=%d, x=%d, y=%d, xdata=%f, ydata=%f' % + ('double' if event.dblclick else 'single', event.button, + event.x, event.y, event.xdata, event.ydata)) + if event.inaxes == ax1: + if event.button == 3: + ind = color_map_list.index(image_tags['color_map'])+1 + if ind == len(color_map_list): + ind = 0 + image_tags['color_map'] = color_map_list[ind] # 'viridis' + vmin = image_tags['minimum_intensity'] + vmax = image_tags['maximum_intensity'] + else: + vmax = data.max() + vmin = data.min() + onselect(vmin, vmax) + + fig2 = plt.figure() + + ax = fig2.add_axes([0., 0.2, 0.9, 0.7]) + ax1 = fig2.add_axes([0., 0.15, 0.9, 0.05]) + + histogram = ax.bar(bin_edges[0:-1], hist, width=width, color=colors, edgecolor='black', alpha=0.8) + onselect(vmin, vmax) + cb1 = mpl.colorbar.ColorbarBase(ax1, cmap=cmap, norm=norm2, orientation='horizontal') + + rectprops = dict(facecolor='blue', alpha=0.5) + + span = mwidgets.SpanSelector(ax, onselect, 'horizontal', rectprops=rectprops) + + cid = fig2.canvas.mpl_connect('button_press_event', onclick) + return span
+ + +
[docs]def clean_svd(im, pixel_size=1, source_size=5): + """De-noising of image by using first component of single value decomposition""" + patch_size = int(source_size/pixel_size) + if patch_size < 3: + patch_size = 3 + patches = image.extract_patches_2d(im, (patch_size, patch_size)) + patches = patches.reshape(patches.shape[0], patches.shape[1]*patches.shape[2]) + + num_components = 32 + + u, s, v = randomized_svd(patches, num_components) + u_im_size = int(np.sqrt(u.shape[0])) + reduced_image = u[:, 0].reshape(u_im_size, u_im_size) + reduced_image = reduced_image/reduced_image.sum()*im.sum() + return reduced_image
+ + +
[docs]def rebin(im, binning=2): + """ + rebin an image by the number of pixels in x and y direction given by binning + + Parameter + --------- + image: numpy array in 2 dimensions + + Returns + ------- + binned image as numpy array + """ + if len(im.shape) == 2: + return im.reshape((im.shape[0]//binning, binning, im.shape[1]//binning, binning)).mean(axis=3).mean(1) + else: + raise TypeError('not a 2D image')
+ + +
[docs]def cart2pol(points): + """Cartesian to polar coordinate conversion + + Parameters + --------- + points: float or numpy array + points to be converted (Nx2) + + Returns + ------- + rho: float or numpy array + distance + phi: float or numpy array + angle + """ + + rho = np.linalg.norm(points[:, 0:2], axis=1) + phi = np.arctan2(points[:, 1], points[:, 0]) + + return rho, phi
+ + +
[docs]def pol2cart(rho, phi): + """Polar to Cartesian coordinate conversion + + Parameters + ---------- + rho: float or numpy array + distance + phi: float or numpy array + angle + + Returns + ------- + x: float or numpy array + x coordinates of converted points(Nx2) + """ + + x = rho * np.cos(phi) + y = rho * np.sin(phi) + return x, y
+ + +
[docs]def xy2polar(points, rounding=1e-3): + """ Conversion from carthesian to polar coordinates + + the angles and distances are sorted by r and then phi + The indices of this sort is also returned + + Parameters + ---------- + points: numpy array + number of points in axis 0 first two elements in axis 1 are x and y + rounding: int + optional rounding in significant digits + + Returns + ------- + r, phi, sorted_indices + """ + + r, phi = cart2pol(points) + + phi = phi # %np.pi # only positive angles + r = (np.floor(r/rounding))*rounding # Remove rounding error differences + + sorted_indices = np.lexsort((phi, r)) # sort first by r and then by phi + r = r[sorted_indices] + phi = phi[sorted_indices] + + return r, phi, sorted_indices
+ + +
[docs]def cartesian2polar(x, y, grid, r, t, order=3): + """Transform cartesian grid to polar grid + + Used by warp + """ + + rr, tt = np.meshgrid(r, t) + + new_x = rr*np.cos(tt) + new_y = rr*np.sin(tt) + + ix = interp1d(x, np.arange(len(x))) + iy = interp1d(y, np.arange(len(y))) + + new_ix = ix(new_x.ravel()) + new_iy = iy(new_y.ravel()) + + return ndimage.map_coordinates(grid, np.array([new_ix, new_iy]), order=order).reshape(new_x.shape)
+ + +
[docs]def warp(diff): + """Takes a centered diffraction pattern (as a sidpy dataset)and warps it to a polar grid""" + """Centered diff can be produced with it.diffractogram_spots(return_center = True)""" + + # Define original polar grid + nx = np.shape(diff)[0] + ny = np.shape(diff)[1] + + # Define center pixel + pix2nm = np.gradient(diff.u.values)[0] + center_pixel = [abs(min(diff.u.values)), abs(min(diff.v.values))]//pix2nm + + x = np.linspace(1, nx, nx, endpoint = True)-center_pixel[0] + y = np.linspace(1, ny, ny, endpoint = True)-center_pixel[1] + z = diff + + # Define new polar grid + nr = int(min([center_pixel[0], center_pixel[1], diff.shape[0]-center_pixel[0], diff.shape[1]-center_pixel[1]])-1) + nt = 360*3 + + r = np.linspace(1, nr, nr) + t = np.linspace(0., np.pi, nt, endpoint = False) + + return cartesian2polar(x,y, z, r, t, order=3)
+ + +
[docs]def calculate_ctf(wavelength, cs, defocus, k): + """ Calculate Contrast Transfer Function + + everything in nm + + Parameters + ---------- + wavelength: float + deBroglie wavelength of electrons + cs: float + spherical aberration coefficient + defocus: float + defocus + k: numpy array + reciprocal scale + + Returns + ------- + ctf: numpy array + contrast transfer function + + """ + ctf = np.sin(np.pi*defocus*wavelength*k**2+0.5*np.pi*cs*wavelength**3*k**4) + return ctf
+ + +
[docs]def calculate_scherzer(wavelength, cs): + """ + Calculate the Scherzer defocus. Cs is in mm, lambda is in nm + + # Input and output in nm + """ + + scherzer = -1.155*(cs*wavelength)**0.5 # in m + return scherzer
+ + +
[docs]def get_rotation(experiment_spots, crystal_spots): + """Get rotation by comparing spots in diffractogram to diffraction Bragg spots + + Parameter + --------- + experiment_spots: numpy array (nx2) + positions (in 1/nm) of spots in diffractogram + crystal_spots: numpy array (nx2) + positions (in 1/nm) of Bragg spots according to kinematic scattering theory + + """ + + r_experiment, phi_experiment = cart2pol(experiment_spots) + + # get crystal spots of same length and sort them by angle as well + r_crystal, phi_crystal, crystal_indices = xy2polar(crystal_spots) + angle_index = np.argmin(np.abs(r_experiment-r_crystal[1]) ) + rotation_angle = phi_experiment[angle_index]%(2*np.pi) - phi_crystal[1] + print(phi_experiment[angle_index]) + st = np.sin(rotation_angle) + ct = np.cos(rotation_angle) + rotation_matrix = np.array([[ct, -st], [st, ct]]) + + return rotation_matrix, rotation_angle
+ + + +
[docs]def calibrate_image_scale(fft_tags, spots_reference, spots_experiment): + """depreciated get change of scale from comparison of spots to Bragg angles """ + gx = fft_tags['spatial_scale_x'] + gy = fft_tags['spatial_scale_y'] + + dist_reference = np.linalg.norm(spots_reference, axis=1) + distance_experiment = np.linalg.norm(spots_experiment, axis=1) + + first_reflections = abs(distance_experiment - dist_reference.min()) < .2 + print('Evaluate ', first_reflections.sum(), 'reflections') + closest_exp_reflections = spots_experiment[first_reflections] + + def func(params, xdata, ydata): + dgx, dgy = params + return np.sqrt((xdata * dgx) ** 2 + (ydata * dgy) ** 2) - dist_reference.min() + + x0 = [1.001, 0.999] + [dg, sig] = optimization.leastsq(func, x0, args=(closest_exp_reflections[:, 0], closest_exp_reflections[:, 1])) + return dg
+ + + +
[docs]def align_crystal_reflections(spots, crystals): + """ Depreciated - use diffraction spots""" + + crystal_reflections_polar = [] + angles = [] + exp_r, exp_phi = cart2pol(spots) # just in polar coordinates + spots_polar = np.array([exp_r, exp_phi]) + + for i in range(len(crystals)): + tags = crystals[i] + r, phi, indices = xy2polar(tags['allowed']['g']) # sorted by r and phi , only positive angles + # we mask the experimental values that are found already + angle = 0. + + angle_i = np.argmin(np.abs(exp_r - r[1])) + angle = exp_phi[angle_i] - phi[0] + angles.append(angle) # Determine rotation angle + + crystal_reflections_polar.append([r, angle + phi, indices]) + tags['allowed']['g_rotated'] = pol2cart(r, angle + phi) + for spot in tags['allowed']['g']: + dif = np.linalg.norm(spots[:, 0:2]-spot[0:2], axis=1) + # print(dif.min()) + if dif.min() < 1.5: + ind = np.argmin(dif) + + return crystal_reflections_polar, angles
+ + +# Deconvolution +
[docs]def decon_lr(o_image, probe, verbose=False): + """ + # This task generates a restored image from an input image and point spread function (PSF) using + # the algorithm developed independently by Lucy (1974, Astron. J. 79, 745) and Richardson + # (1972, J. Opt. Soc. Am. 62, 55) and adapted for HST imagery by Snyder + # (1990, in Restoration of HST Images and Spectra, ST ScI Workshop Proceedings; see also + # Snyder, Hammoud, & White, JOSA, v. 10, no. 5, May 1993, in press). + # Additional options developed by Rick White (STScI) are also included. + # + # The Lucy-Richardson method can be derived from the maximum likelihood expression for data + # with a Poisson noise distribution. Thus, it naturally applies to optical imaging data such as HST. + # The method forces the restored image to be positive, in accord with photon-counting statistics. + # + # The Lucy-Richardson algorithm generates a restored image through an iterative method. The essence + # of the iteration is as follows: the (n+1)th estimate of the restored image is given by the nth estimate + # of the restored image multiplied by a correction image. That is, + # + # original data + # image = image --------------- * reflect(PSF) + # n+1 n image * PSF + # n + + # where the *'s represent convolution operators and reflect(PSF) is the reflection of the PSF, i.e. + # reflect((PSF)(x,y)) = PSF(-x,-y). When the convolutions are carried out using fast Fourier transforms + # (FFTs), one can use the fact that FFT(reflect(PSF)) = conj(FFT(PSF)), where conj is the complex conjugate + # operator. + """ + + if len(o_image) < 1: + return o_image + + if o_image.shape != probe.shape: + print('Weirdness ', o_image.shape, ' != ', probe.shape) + + probe_c = np.ones(probe.shape, dtype=np.complex64) + probe_c.real = probe + + error = np.ones(o_image.shape, dtype=np.complex64) + est = np.ones(o_image.shape, dtype=np.complex64) + source = np.ones(o_image.shape, dtype=np.complex64) + source.real = o_image + + response_ft = fftpack.fft2(probe_c) + + ap_angle = o_image.metadata['experiment']['convergence_angle'] / 1000.0 # now in rad + + e0 = float(o_image.metadata['experiment']['acceleration_voltage']) + + wl = get_wavelength(e0) + o_image.metadata['experiment']['wavelength'] = wl + + over_d = 2 * ap_angle / wl + + dx = o_image.x[1]-o_image.x[0] + dk = 1.0 / float(o_image.x[-1]) # last value of x-axis is field of view + screen_width = 1 / dx + + aperture = np.ones(o_image.shape, dtype=np.complex64) + # Mask for the aperture before the Fourier transform + n = o_image.shape[0] + size_x = o_image.shape[0] + size_y = o_image.shape[1] + app_ratio = over_d / screen_width * n + + theta_x = np.array(-size_x / 2. + np.arange(size_x)) + theta_y = np.array(-size_y / 2. + np.arange(size_y)) + t_xv, t_yv = np.meshgrid(theta_x, theta_y) + + tp1 = t_xv ** 2 + t_yv ** 2 >= app_ratio ** 2 + aperture[tp1.T] = 0. + # print(app_ratio, screen_width, dk) + + progress = tqdm(total=500) + # de = 100 + dest = 100 + i = 0 + while abs(dest) > 0.0001: # or abs(de) > .025: + i += 1 + error_old = np.sum(error.real) + est_old = est.copy() + error = source / np.real(fftpack.fftshift(fftpack.ifft2(fftpack.fft2(est) * response_ft))) + est = est * np.real(fftpack.fftshift(fftpack.ifft2(fftpack.fft2(error) * np.conjugate(response_ft)))) + # est = est_old * est + # est = np.real(fftpack.fftshift(fftpack.ifft2(fftpack.fft2(est)*fftpack.fftshift(aperture) ))) + + error_new = np.real(np.sum(np.power(error, 2))) - error_old + dest = np.sum(np.power((est - est_old).real, 2)) / np.sum(est) * 100 + # print(np.sum((est.real - est_old.real)* (est.real - est_old.real) )/np.sum(est.real)*100 ) + + if error_old != 0: + de = error_new / error_old * 1.0 + else: + de = error_new + + if verbose: + print( + ' LR Deconvolution - Iteration: {0:d} Error: {1:.2f} = change: {2:.5f}%, {3:.5f}%'.format(i, error_new, + de, + abs(dest))) + if i > 500: + dest = 0.0 + print('terminate') + progress.update(1) + progress.write(f"converged in {i} iterations") + # progress.close() + print('\n Lucy-Richardson deconvolution converged in ' + str(i) + ' iterations') + est2 = np.real(fftpack.ifft2(fftpack.fft2(est) * fftpack.fftshift(aperture))) + out_dataset = o_image.like_data(est2) + out_dataset.title = 'Lucy Richardson deconvolution' + out_dataset.data_type = 'image' + return out_dataset
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/info_dialog.html b/_modules/pyTEMlib/info_dialog.html new file mode 100644 index 00000000..f6d773e9 --- /dev/null +++ b/_modules/pyTEMlib/info_dialog.html @@ -0,0 +1,667 @@ + + + + + + pyTEMlib.info_dialog — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.info_dialog

+"""
+Input Dialog for EELS Analysis
+
+Author: Gerd Duscher
+
+"""
+import numpy as np
+import sidpy
+
+Qt_available = True
+try:
+    from PyQt5 import QtCore,  QtWidgets
+except:
+    Qt_available = False
+    # print('Qt dialogs are not available')
+
+import ipywidgets
+
+from IPython.display import display
+
+from pyTEMlib.microscope import microscope
+from pyTEMlib import file_tools as ft
+from pyTEMlib import eels_dialog_utilities
+_version = 000
+
+
+if Qt_available:
+    from pyTEMlib import info_dlg
+    from pyTEMlib import interactive_eels as ieels
+    class InfoDialog(QtWidgets.QDialog):
+        """
+        Input Dialog for EELS Analysis
+
+        Opens a PyQt5 GUi Dialog that allows to set the experimental parameter necessary for a Quantification.
+
+
+        The dialog operates on a sidpy dataset
+        """
+
+        def __init__(self, datasets=None, key=None):
+            super().__init__(None, QtCore.Qt.WindowStaysOnTopHint)
+            # Create an instance of the GUI
+            self.ui = info_dlg.UiDialog(self)
+            self.set_action()
+            self.datasets = datasets
+
+            self.spec_dim = []
+            self.energy_scale = np.array([])
+            self.experiment = {}
+            self.energy_dlg = None
+            self.axis = None
+            
+            self.y_scale = 1.0
+            self.change_y_scale = 1.0
+            self.show()
+
+            if self.datasets is None:
+                # make a dummy dataset for testing
+                key = 'Channel_000'
+                self.datasets={key: ft.make_dummy_dataset(sidpy.DataType.SPECTRUM)}
+            if key is None:
+                key = list(self.datasets.keys())[0]
+            self.dataset = self.datasets[key]
+            self.key = key
+            if not isinstance(self.dataset, sidpy.Dataset):
+                raise TypeError('dataset has to be a sidpy dataset')
+
+            self.set_dataset(self.dataset)
+
+            #  view = self.dataset.plot()
+            if hasattr(self.dataset.view, 'axes'):
+                self.axis = self.dataset.view.axes[-1]
+            elif hasattr(self.dataset.view, 'axis'):
+                self.axis = self.dataset.view.axis
+            self.figure = self.axis.figure
+            self.plot()
+            self.update()
+
+        def set_dataset(self, dataset):
+            self.dataset = dataset
+            if not hasattr(self.dataset, '_axes'):
+                self.dataset._axes = self.dataset.axes
+            if not hasattr(self.dataset, 'meta_data'):
+                self.dataset.meta_data = {}
+
+            spec_dim = dataset.get_dimensions_by_type(sidpy.DimensionType.SPECTRAL)
+            if len(spec_dim) != 1:
+                raise TypeError('We need exactly one SPECTRAL dimension')
+            self.spec_dim = self.dataset._axes[spec_dim[0]]
+            self.energy_scale = self.spec_dim.values.copy()
+
+            minimum_info = {'offset': self.energy_scale[0],
+                            'dispersion': self.energy_scale[1] - self.energy_scale[0],
+                            'exposure_time': 0.0,
+                            'convergence_angle': 0.0, 'collection_angle': 0.0,
+                            'acceleration_voltage': 100.0, 'binning': 1, 'conversion': 1.0,
+                            'flux_ppm': -1.0, 'flux_unit': 'counts', 'current': 1.0, 'SI_bin_x': 1, 'SI_bin_y': 1}
+            if 'experiment' not in self.dataset.metadata:
+                self.dataset.metadata['experiment'] = minimum_info
+            self.experiment = self.dataset.metadata['experiment']
+
+            for key, item in minimum_info.items():
+                if key not in self.experiment:
+                    self.experiment[key] = item
+            self.set_flux_list()
+
+        def set_dimension(self):
+            spec_dim = self.dataset.get_dimensions_by_type(sidpy.DimensionType.SPECTRAL)
+            self.spec_dim = self.dataset._axes[spec_dim[0]]
+            old_energy_scale = self.spec_dim
+            self.dataset.set_dimension(spec_dim[0], sidpy.Dimension(np.array(self.energy_scale),
+                                                                    name=old_energy_scale.name,
+                                                                    dimension_type=sidpy.DimensionType.SPECTRAL,
+                                                                    units='eV',
+                                                                    quantity='energy loss'))
+
+        def update(self):
+
+            self.ui.offsetEdit.setText(f"{self.experiment['offset']:.3f}")
+            self.ui.dispersionEdit.setText(f"{self.experiment['dispersion']:.3f}")
+            self.ui.timeEdit.setText(f"{self.experiment['exposure_time']:.6f}")
+
+            self.ui.convEdit.setText(f"{self.experiment['convergence_angle']:.2f}")
+            self.ui.collEdit.setText(f"{self.experiment['collection_angle']:.2f}")
+            self.ui.E0Edit.setText(f"{self.experiment['acceleration_voltage']/1000.:.2f}")
+
+            self.ui.binningEdit.setText(f"{self.experiment['binning']}")
+            self.ui.conversionEdit.setText(f"{self.experiment['conversion']:.2f}")
+            self.ui.fluxEdit.setText(f"{self.experiment['flux_ppm']:.2f}")
+            self.ui.fluxUnit.setText(f"{self.experiment['flux_unit']}")
+            self.ui.VOAEdit.setText(f"{self.experiment['current']:.2f}")
+            self.ui.statusBar.showMessage('Message in statusbar.')
+
+        def on_enter(self):
+            sender = self.sender()
+
+            if sender == self.ui.offsetEdit:
+                value = float(str(sender.displayText()).strip())
+                self.experiment['offset'] = value
+                sender.setText(f"{value:.2f}")
+                self.energy_scale = self.energy_scale - self.energy_scale[0] + value
+                self.set_dimension()
+                self.plot()
+            elif sender == self.ui.dispersionEdit:
+                value = float(str(sender.displayText()).strip())
+                self.experiment['dispersion'] = value
+                self.energy_scale = np.arange(len(self.energy_scale)) * value + self.energy_scale[0]
+                self.set_dimension()
+                self.plot()
+                sender.setText(f"{value:.3f}")
+            elif sender == self.ui.timeEdit:
+                value = float(str(sender.displayText()).strip())
+                self.experiment['exposure_time'] = value
+                sender.setText(f"{value:.2f}")
+            elif sender == self.ui.convEdit:
+                value = float(str(sender.displayText()).strip())
+                self.experiment['convergence_angle'] = value
+                sender.setText(f"{value:.2f}")
+            elif sender == self.ui.collEdit:
+                value = float(str(sender.displayText()).strip())
+                self.experiment['collection_angle'] = value
+                sender.setText(f"{value:.2f}")
+            elif sender == self.ui.E0Edit:
+                value = float(str(sender.displayText()).strip())
+                self.experiment['acceleration_voltage'] = value*1000.0
+                sender.setText(f"{value:.2f}")
+            elif sender == self.ui.fluxEdit:
+                value = float(str(sender.displayText()).strip())
+                if value == 0:
+                    self.set_flux()
+                else:
+                    self.experiment['flux_ppm'] = value
+                    sender.setText(f"{value:.2f}")
+            elif sender == self.ui.binXEdit or sender == self.ui.binYEdit:
+                if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE:
+                    bin_x = int(self.ui.binXEdit.displayText())
+                    bin_y = int(self.ui.binYEdit.displayText())
+                    self.experiment['SI_bin_x'] = bin_x
+                    self.experiment['SI_bin_y'] = bin_y
+                    self.dataset.view.set_bin([bin_x, bin_y])
+                    self.ui.binXEdit.setText(str(self.dataset.view.bin_x))
+                    self.ui.binYEdit.setText(str(self.dataset.view.bin_y))
+            else:
+                print('not supported yet')
+
+        def plot(self):
+            if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE:
+                spectrum = self.dataset.view.get_spectrum()
+                self.axis = self.dataset.view.axes[1]
+            else:
+                spectrum = np.array(self.dataset)
+                self.axis = self.dataset.view.axis
+
+            spectrum *= self.y_scale
+
+            x_limit = self.axis.get_xlim()
+            y_limit = np.array(self.axis.get_ylim())
+            self.axis.clear()
+            
+
+            self.axis.plot(self.energy_scale, spectrum, label='spectrum')
+            self.axis.set_xlim(x_limit)
+            if self.change_y_scale !=1.0:
+                y_limit *= self.change_y_scale
+                self.change_y_scale = 1.0
+            self.axis.set_ylim(y_limit)
+            
+            if self.y_scale != 1.:
+                self.axis.set_ylabel('scattering intensity (ppm)')
+                
+            self.axis.set_xlabel('energy_loss (eV)')
+
+            self.figure.canvas.draw_idle()
+
+        def on_list_enter(self):
+            sender = self.sender()
+            if sender == self.ui.TEMList:
+                microscope.set_microscope(self.ui.TEMList.currentText())
+                self.experiment['microscope'] = microscope.name
+                self.experiment['convergence_angle'] = microscope.alpha
+                self.experiment['collection_angle'] = microscope.beta
+                self.experiment['acceleration_voltage'] = microscope.E0
+                self.update()
+
+        def set_energy_scale(self):
+            self.energy_dlg = ieels.EnergySelector(self.dataset)
+
+            self.energy_dlg.signal_selected[bool].connect(self.set_energy)
+            self.energy_dlg.show()
+
+        def set_energy(self, k):
+            spec_dim = self.dataset.get_dimensions_by_type(sidpy.DimensionType.SPECTRAL)
+            self.spec_dim = self.dataset._axes[spec_dim[0]]
+
+            self.energy_scale = self.spec_dim.values
+            self.experiment['offset'] = self.energy_scale[0]
+            self.experiment['dispersion'] = self.energy_scale[1] - self.energy_scale[0]
+            self.update()
+
+        def set_flux(self, key):
+            self.ui.statusBar.showMessage('on_set_flux')
+            new_flux = 1.0
+            title = key
+            metadata = {}
+            if key in self.datasets.keys():
+                flux_dataset = self.datasets[key]
+                if isinstance(flux_dataset, sidpy.Dataset):
+                    exposure_time = -1.0
+                    flux_dataset = self.datasets[key]
+                    if flux_dataset.data_type.name == 'IMAGE' or 'SPECTRUM' in flux_dataset.data_type.name:
+                        if 'exposure_time' in flux_dataset.metadata['experiment']:
+                            if 'number_of_frames' in flux_dataset.metadata['experiment']:
+                                exposure_time = flux_dataset.metadata['experiment']['single_exposure_time'] * flux_dataset.metadata['experiment']['number_of_frames'] 
+                            else:
+                                exposure_time = flux_dataset.metadata['experiment']['exposure_time']
+                        else:
+                            exposure_time = -1.0
+                            flux_dataset.metadata['experiment']['exposure_time'] = -1
+                            print('Did not find exposure time assume 1s')
+                        if exposure_time > 0:
+                            new_flux  = np.sum(np.array(flux_dataset*1e-6))/exposure_time*self.dataset.metadata['experiment']['exposure_time']
+                            title = flux_dataset.title
+                            metadata = flux_dataset.metadata
+                            self.experiment['flux_ppm'] = new_flux
+                            self.experiment['flux_units'] = 'Mcounts '
+                            self.experiment['flux_source'] = title
+                            self.experiment['flux_metadata'] = metadata
+    
+                            self.update()
+
+        def on_check(self):
+            sender = self.sender()
+        
+            if sender.objectName() == 'probability':
+                dispersion = self.energy_scale[1]-self.energy_scale[0]
+                if sender.isChecked():
+                    self.y_scale = 1/self.experiment['flux_ppm']*dispersion
+                    self.change_y_scale = 1/self.experiment['flux_ppm']*dispersion
+                else:
+                    self.y_scale = 1.
+                    self.change_y_scale = self.experiment['flux_ppm']/dispersion
+                self.plot()
+
+        def set_flux_list(self):
+            length_list = self.ui.select_flux.count()+1
+            for i in range(2, length_list):
+                self.ui.select_flux.removeItem(i)
+            for key in self.datasets.keys():
+                if isinstance(self.datasets[key], sidpy.Dataset):
+                    if self.datasets[key].title != self.dataset.title:
+                        self.ui.select_flux.addItem(key+': '+self.datasets[key].title)
+
+        def on_list_enter(self):
+            self.ui.statusBar.showMessage('on_list')
+            sender = self.sender()
+            if sender.objectName() == 'select_flux_list':
+                self.ui.statusBar.showMessage('list')
+                index = self.ui.select_flux.currentIndex()
+                self.ui.statusBar.showMessage('list'+str(index))
+                if index == 1:
+                    ft.add_dataset_from_file(self.datasets, key_name='Reference')
+                    self.set_flux_list()
+                else:
+                    key = str(self.ui.select_flux.currentText()).split(':')[0]
+                    self.set_flux(key)
+                    
+                self.update()
+
+        def set_action(self):
+            self.ui.statusBar.showMessage('action')
+            self.ui.offsetEdit.editingFinished.connect(self.on_enter)
+            self.ui.dispersionEdit.editingFinished.connect(self.on_enter)
+            self.ui.timeEdit.editingFinished.connect(self.on_enter)
+
+            self.ui.TEMList.activated[str].connect(self.on_list_enter)
+
+            self.ui.convEdit.editingFinished.connect(self.on_enter)
+            self.ui.collEdit.editingFinished.connect(self.on_enter)
+            self.ui.E0Edit.editingFinished.connect(self.on_enter)
+            self.ui.binningEdit.editingFinished.connect(self.on_enter)
+            self.ui.conversionEdit.editingFinished.connect(self.on_enter)
+            self.ui.fluxEdit.editingFinished.connect(self.on_enter)
+            self.ui.VOAEdit.editingFinished.connect(self.on_enter)
+            self.ui.energy_button.clicked.connect(self.set_energy_scale)
+            self.ui.select_flux.activated[str].connect(self.on_list_enter)
+
+            self.ui.check_probability.clicked.connect(self.on_check)
+            
+            self.ui.binXEdit.editingFinished.connect(self.on_enter)
+            self.ui.binYEdit.editingFinished.connect(self.on_enter)
+
+
+
[docs]def get_sidebar(): + side_bar = ipywidgets.GridspecLayout(17, 3,width='auto', grid_gap="0px") + + side_bar[0, :2] = ipywidgets.Dropdown( + options=[('None', 0)], + value=0, + description='Main Dataset:', + disabled=False) + + row = 1 + side_bar[row, :3] = ipywidgets.Button(description='Energy Scale', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=7.5,description='Offset:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.Label(value="eV", layout=ipywidgets.Layout(width='20px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Dispersion:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.Label(value="eV", layout=ipywidgets.Layout(width='20px')) + + row += 1 + side_bar[row, :3] = ipywidgets.Button(description='Microscope', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=7.5,description='Conv.Angle:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.Label(value="mrad", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Coll.Angle:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.Label(value="mrad", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Acc Voltage:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.Label(value="keV", layout=ipywidgets.Layout(width='100px')) + row += 1 + + side_bar[row, :3] = ipywidgets.Button(description='Quantification', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + row+=1 + side_bar[row, :2] = ipywidgets.Dropdown( + options=[('None', 0)], + value=0, + description='Reference:', + disabled=False) + side_bar[row,2] = ipywidgets.ToggleButton( + description='Probability', + disabled=False, + button_style='', # 'success', 'info', 'warning', 'danger' or '' + tooltip='Changes y-axis to probability if flux is given', + layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Exp_Time:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.Label(value="s", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=7.5,description='Flux:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.Label(value="Mcounts", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Conversion:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.Label(value=r"e$^-$/counts", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Current:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.Label(value="pA", layout=ipywidgets.Layout(width='100px') ) + + row += 1 + + side_bar[row, :3] = ipywidgets.Button(description='Spectrum Image', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + + row += 1 + side_bar[row, :2] = ipywidgets.IntText(value=1, description='bin X:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + row += 1 + side_bar[row, :2] = ipywidgets.IntText(value=1, description='bin X:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + + for i in range(14, 17): + side_bar[i, 0].layout.display = "none" + return side_bar
+ +
[docs]class InfoWidget(object): + def __init__(self, datasets=None): + self.datasets = datasets + self.dataset = None + + self.sidebar = get_sidebar() + + self.set_dataset() + self.set_action() + + self.app_layout = ipywidgets.AppLayout( + left_sidebar=self.sidebar, + center=self.view.panel, + footer=None,#message_bar, + pane_heights=[0, 10, 0], + pane_widths=[4, 10, 0], + ) + display(self.app_layout) + + def get_spectrum(self): + if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE: + spectrum = self.dataset.view.get_spectrum() + self.axis = self.view.axes[1] + else: + spectrum = np.array(self.dataset) + self.axis = self.view.axis + + spectrum *= self.y_scale + return spectrum + + def plot(self, scale=True): + self.energy_scale = self.dataset.energy_loss.values + self.view.change_y_scale = self.change_y_scale + self.view.y_scale = self.y_scale + + self.view.plot() + + def set_dataset(self, index=0): + spectrum_list = [] + reference_list =[('None', -1)] + dataset_index = self.sidebar[0, 0].value + for index, key in enumerate(self.datasets.keys()): + if 'Reference' not in key: + if 'SPECTR' in self.datasets[key].data_type.name: + spectrum_list.append((f'{key}: {self.datasets[key].title}', index)) + reference_list.append((f'{key}: {self.datasets[key].title}', index)) + + self.sidebar[0,0].options = spectrum_list + self.sidebar[9,0].options = reference_list + self.key = list(self.datasets)[dataset_index] + self.dataset = self.datasets[self.key] + if 'SPECTRUM' in self.dataset.data_type.name: + for i in range(14, 17): + self.sidebar[i, 0].layout.display = "none" + else: + for i in range(14, 17): + self.sidebar[i, 0].layout.display = "flex" + #self.sidebar[0,0].value = dataset_index #f'{self.key}: {self.datasets[self.key].title}' + self.sidebar[2,0].value = np.round(self.datasets[self.key].energy_loss[0], 3) + self.sidebar[3,0].value = np.round(self.datasets[self.key].energy_loss[1] - self.datasets[self.key].energy_loss[0], 4) + self.sidebar[5,0].value = np.round(self.datasets[self.key].metadata['experiment']['convergence_angle'], 1) + self.sidebar[6,0].value = np.round(self.datasets[self.key].metadata['experiment']['collection_angle'], 1) + self.sidebar[7,0].value = np.round(self.datasets[self.key].metadata['experiment']['acceleration_voltage']/1000, 1) + self.sidebar[10,0].value = np.round(self.datasets[self.key].metadata['experiment']['exposure_time'], 4) + if 'flux_ppm' not in self.datasets[self.key].metadata['experiment']: + self.datasets[self.key].metadata['experiment']['flux_ppm'] = 0 + self.sidebar[11,0].value = self.datasets[self.key].metadata['experiment']['flux_ppm'] + if 'count_conversion' not in self.datasets[self.key].metadata['experiment']: + self.datasets[self.key].metadata['experiment']['count_conversion'] = 1 + self.sidebar[12,0].value = self.datasets[self.key].metadata['experiment']['count_conversion'] + if 'beam_current' not in self.datasets[self.key].metadata['experiment']: + self.datasets[self.key].metadata['experiment']['beam_current'] = 0 + self.sidebar[13,0].value = self.datasets[self.key].metadata['experiment']['beam_current'] + if self.dataset.data_type.name =='SPECTRAL_IMAGE': + self.view = eels_dialog_utilities.SIPlot(self.dataset) + else: + self.view = eels_dialog_utilities.SpectrumPlot(self.dataset) + self.y_scale = 1.0 + self.change_y_scale = 1.0 + + def cursor2energy_scale(self, value): + dispersion = (self.view.end_cursor.value - self.view.start_cursor.value) / (self.view.end_channel - self.view.start_channel) + self.datasets[self.key].energy_loss *= (self.sidebar[3, 0].value/dispersion) + self.sidebar[3, 0].value = dispersion + offset = self.view.start_cursor.value - self.view.start_channel * dispersion + self.datasets[self.key].energy_loss += (self.sidebar[2, 0].value-self.datasets[self.key].energy_loss[0]) + self.sidebar[2, 0].value = offset + self.plot() + + def set_energy_scale(self, value): + dispersion = self.datasets[self.key].energy_loss[1] - self.datasets[self.key].energy_loss[0] + self.datasets[self.key].energy_loss *= (self.sidebar[3, 0].value/dispersion) + self.datasets[self.key].energy_loss += (self.sidebar[2, 0].value-self.datasets[self.key].energy_loss[0]) + self.plot() + + def set_y_scale(self, value): + self.change_y_scale = 1/self.y_scale + if self.sidebar[9,2].value: + dispersion = self.datasets[self.key].energy_loss[1] - self.datasets[self.key].energy_loss[0] + self.y_scale = 1/self.datasets[self.key].metadata['experiment']['flux_ppm'] * dispersion + else: + self.y_scale = 1.0 + self.change_y_scale *= self.y_scale + self.plot() + + def set_flux(self, value): + self.datasets[self.key].metadata['experiment']['exposure_time'] = self.sidebar[10,0].value + if self.sidebar[9,0].value < 0: + self.datasets[self.key].metadata['experiment']['flux_ppm'] = 0. + else: + key = list(self.datasets.keys())[self.sidebar[9,0].value] + self.datasets[self.key].metadata['experiment']['flux_ppm'] = (np.array(self.datasets[key])*1e-6).sum() / self.datasets[key].metadata['experiment']['exposure_time'] + self.datasets[self.key].metadata['experiment']['flux_ppm'] *= self.datasets[self.key].metadata['experiment']['exposure_time'] + self.sidebar[11,0].value = np.round(self.datasets[self.key].metadata['experiment']['flux_ppm'], 2) + + def set_microscope_parameter(self, value): + self.datasets[self.key].metadata['experiment']['convergence_angle'] = self.sidebar[5,0].value + self.datasets[self.key].metadata['experiment']['collection_angle'] = self.sidebar[6,0].value + self.datasets[self.key].metadata['experiment']['acceleration_voltage'] = self.sidebar[7,0].value*1000 + + def set_binning(self, value): + if 'SPECTRAL' in self.dataset.data_type.name: + bin_x = self.sidebar[15,0].value + bin_y = self.sidebar[16,0].value + self.dataset.view.set_bin([bin_x, bin_y]) + self.datasets[self.key].metadata['experiment']['SI_bin_x'] = bin_x + self.datasets[self.key].metadata['experiment']['SI_bin_y'] = bin_y + + def set_action(self): + self.sidebar[0,0].observe(self.set_dataset) + self.sidebar[1,0].on_click(self.cursor2energy_scale) + self.sidebar[2,0].observe(self.set_energy_scale, names='value') + self.sidebar[3,0].observe(self.set_energy_scale, names='value') + self.sidebar[5,0].observe(self.set_microscope_parameter) + self.sidebar[6,0].observe(self.set_microscope_parameter) + self.sidebar[7,0].observe(self.set_microscope_parameter) + self.sidebar[9,0].observe(self.set_flux) + self.sidebar[9,2].observe(self.set_y_scale) + self.sidebar[10,0].observe(self.set_flux) + self.sidebar[15,0].observe(self.set_binning) + self.sidebar[16,0].observe(self.set_binning)
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/info_widget.html b/_modules/pyTEMlib/info_widget.html new file mode 100644 index 00000000..7acbf7e4 --- /dev/null +++ b/_modules/pyTEMlib/info_widget.html @@ -0,0 +1,770 @@ + + + + + + pyTEMlib.info_widget — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.info_widget

+import numpy as np
+import sidpy
+
+
+import pyTEMlib.eels_dialog_utilities as ieels
+import pyTEMlib.file_tools as ft
+from pyTEMlib.microscope import microscope
+import ipywidgets
+import matplotlib.pylab as plt
+import matplotlib
+
+from IPython.display import display
+
+
+from pyTEMlib import file_tools
+from pyTEMlib import eels_tools
+
+
[docs]def get_info_sidebar(): + side_bar = ipywidgets.GridspecLayout(17, 3,width='auto', grid_gap="0px") + + side_bar[0, :2] = ipywidgets.Dropdown( + options=[('None', 0)], + value=0, + description='Main Dataset:', + disabled=False) + + row = 1 + side_bar[row, :3] = ipywidgets.Button(description='Energy Scale', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=7.5,description='Offset:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='20px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Dispersion:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='20px')) + + row += 1 + side_bar[row, :3] = ipywidgets.Button(description='Microscope', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=7.5,description='Conv.Angle:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="mrad", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Coll.Angle:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="mrad", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Acc Voltage:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="keV", layout=ipywidgets.Layout(width='100px')) + row += 1 + + side_bar[row, :3] = ipywidgets.Button(description='Quantification', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + row+=1 + side_bar[row, :2] = ipywidgets.Dropdown( + options=[('None', 0)], + value=0, + description='Reference:', + disabled=False) + side_bar[row,2] = ipywidgets.ToggleButton( + description='Probability', + disabled=False, + button_style='', # 'success', 'info', 'warning', 'danger' or '' + tooltip='Changes y-axis to probability if flux is given', + layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Exp_Time:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="s", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=7.5,description='Flux:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="Mcounts", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Conversion:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value=r"e$^-$/counts", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Current:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="pA", layout=ipywidgets.Layout(width='100px') ) + + row += 1 + + side_bar[row, :3] = ipywidgets.Button(description='Spectrum Image', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + + row += 1 + side_bar[row, :2] = ipywidgets.IntText(value=1, description='bin X:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + row += 1 + side_bar[row, :2] = ipywidgets.IntText(value=1, description='bin X:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + + for i in range(14, 17): + side_bar[i, 0].layout.display = "none" + return side_bar
+ +from sidpy.io.interface_utils import open_file_dialog +
[docs]class EELSWidget(object): + def __init__(self, datasets, sidebar, tab_title = None): + + self.datasets = datasets + self.dataset = None + + if not isinstance(sidebar, list): + tab = ipywidgets.Tab() + tab.children = [ft.FileWidget(), sidebar] + tab.titles = ['Load', 'Info'] + else: + tab = sidebar + + self.sidebar = sidebar + with plt.ioff(): + self.figure = plt.figure() + + self.figure.canvas.toolbar_position = 'right' + self.figure.canvas.toolbar_visible = True + + self.start_cursor = ipywidgets.FloatText(value=0, description='Start:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + self.end_cursor = ipywidgets.FloatText(value=0, description='End:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + self.panel = ipywidgets.VBox([ipywidgets.HBox([ipywidgets.Label('',layout=ipywidgets.Layout(width='100px')), ipywidgets.Label('Cursor:'), + self.start_cursor,ipywidgets.Label('eV'), + self.end_cursor, ipywidgets.Label('eV')]), + self.figure.canvas]) + + + self.app_layout = ipywidgets.AppLayout( + left_sidebar=tab, + center=self.panel, + footer=None,#message_bar, + pane_heights=[0, 10, 0], + pane_widths=[4, 10, 0], + ) + self.set_dataset() + + display(self.app_layout) + + def plot(self, scale=True): + self.figure.clear() + self.energy_scale = self.dataset.energy_loss.values + + if self.dataset.data_type.name == 'SPECTRUM': + self.axis = self.figure.subplots(ncols=1) + else: + self.plot_spectrum_image() + self.axis = self.axes[-1] + self.spectrum = self.get_spectrum() + + self.plot_spectrum() + + def plot_spectrum(self): + self.axis.plot(self.energy_scale, self.spectrum, label='spectrum') + x_limit = self.axis.get_xlim() + y_limit = np.array(self.axis.get_ylim()) + self.xlabel = self.datasets[self.key].labels[0] + self.ylabel = self.datasets[self.key].data_descriptor + self.axis.set_xlabel(self.datasets[self.key].labels[0]) + self.axis.set_ylabel(self.datasets[self.key].data_descriptor) + self.axis.ticklabel_format(style='sci', scilimits=(-2, 3)) + #if scale: + # self.axis.set_ylim(np.array(y_limit)*self.change_y_scale) + self.change_y_scale = 1.0 + if self.y_scale != 1.: + self.axis.set_ylabel('scattering probability (ppm/eV)') + self.selector = matplotlib.widgets.SpanSelector(self.axis, self.line_select_callback, + direction="horizontal", + interactive=True, + props=dict(facecolor='blue', alpha=0.2)) + self.axis.legend() + if self.dataset.data_type.name == 'SPECTRUM': + self.axis.set_title(self.dataset.title) + else: + self.axis.set_title(f'spectrum {self.x}, {self.y}') + self.figure.canvas.draw_idle() + + def _update(self, ev=None): + + xlim = np.array(self.axes[1].get_xlim()) + ylim = np.array(self.axes[1].get_ylim()) + self.axes[1].clear() + self.get_spectrum() + if len(self.energy_scale)!=self.spectrum.shape[0]: + self.spectrum = self.spectrum.T + self.axes[1].plot(self.energy_scale, self.spectrum.compute(), label='experiment') + + self.axes[1].set_title(f'spectrum {self.x}, {self.y}') + self.figure.tight_layout() + self.selector = matplotlib.widgets.SpanSelector(self.axis, self.line_select_callback, + direction="horizontal", + interactive=True, + props=dict(facecolor='blue', alpha=0.2)) + + self.axes[1].set_xlim(xlim) + self.axes[1].set_ylim(ylim*self.change_y_scale) + self.axes[1].set_xlabel(self.xlabel) + self.axes[1].set_ylabel(self.ylabel) + self.change_y_scale = 1.0 + self.figure.canvas.draw_idle() + + def _onclick(self, event): + self.event = event + if event.inaxes in [self.axes[0]]: + x = int(event.xdata) + y = int(event.ydata) + + x = int(x - self.rectangle[0]) + y = int(y - self.rectangle[2]) + + if x >= 0 and y >= 0: + if x <= self.rectangle[1] and y <= self.rectangle[3]: + self.x = int(x / (self.rect.get_width() / self.bin_x)) + self.y = int(y / (self.rect.get_height() / self.bin_y)) + image_dims = self.dataset.get_dimensions_by_type(sidpy.DimensionType.SPATIAL) + + if self.x + self.bin_x > self.dataset.shape[image_dims[0]]: + self.x = self.dataset.shape[image_dims[0]] - self.bin_x + if self.y + self.bin_y > self.dataset.shape[image_dims[1]]: + self.y = self.dataset.shape[image_dims[1]] - self.bin_y + + self.rect.set_xy([self.x * self.rect.get_width() / self.bin_x + self.rectangle[0], + self.y * self.rect.get_height() / self.bin_y + self.rectangle[2]]) + # self.get_spectrum() + self._update() + else: + if event.dblclick: + bottom = float(self.spectrum.min()) + if bottom < 0: + bottom *= 1.02 + else: + bottom *= 0.98 + top = float(self.spectrum.max()) + if top > 0: + top *= 1.02 + else: + top *= 0.98 + self.axis.set_ylim(bottom=bottom, top=top) + + def get_spectrum(self): + if self.dataset.data_type == sidpy.DataType.SPECTRUM: + self.spectrum = self.dataset.copy() + else: + image_dims = self.dataset.get_dimensions_by_type(sidpy.DimensionType.SPATIAL) + if self.x > self.dataset.shape[image_dims[0]] - self.bin_x: + self.x = self.dataset.shape[image_dims[0]] - self.bin_x + if self.y > self.dataset.shape[image_dims[1]] - self.bin_y: + self.y = self.dataset.shape[image_dims[1]] - self.bin_y + selection = [] + self.axis.clear() + for dim, axis in self.dataset._axes.items(): + # print(dim, axis.dimension_type) + if axis.dimension_type == sidpy.DimensionType.SPATIAL: + if dim == image_dims[0]: + selection.append(slice(self.x, self.x + self.bin_x)) + else: + selection.append(slice(self.y, self.y + self.bin_y)) + + elif axis.dimension_type == sidpy.DimensionType.SPECTRAL: + selection.append(slice(None)) + elif axis.dimension_type == sidpy.DimensionType.CHANNEL: + selection.append(slice(None)) + else: + selection.append(slice(0, 1)) + + self.spectrum = self.dataset[tuple(selection)].mean(axis=tuple(image_dims)) + + self.spectrum *= self.y_scale + + return self.spectrum.squeeze() + + def plot_spectrum_image(self): + self.axes = self.figure.subplots(ncols=2) + self.axis = self.axes[-1] + + spec_dim = self.dataset.get_dimensions_by_type(sidpy.DimensionType.SPECTRAL) + if len(spec_dim) != 1: + raise ValueError('Only one spectral dimension') + + channel_dim = self.dataset.get_dimensions_by_type(sidpy.DimensionType.CHANNEL) + channel_dim =[] + if len(channel_dim) > 1: + raise ValueError('Maximal one channel dimension') + + if len(channel_dim) > 0: + self.image = self.dataset.mean(axis=(spec_dim[0] ,channel_dim[0])) + else: + self.image = self.dataset.mean(axis=(spec_dim[0])) + + self.rect = matplotlib.patches.Rectangle((0, 0), self.bin_x, self.bin_y, linewidth=1, edgecolor='r', + facecolor='red', alpha=0.2) + size_x = self.image.shape[0] + size_y = self.image.shape[1] + self.extent = [0, size_x, size_y, 0] + self.rectangle = [0, size_x, 0, size_y] + self.axes[0].imshow(self.image.T, extent=self.extent) + self.axes[0].set_aspect('equal') + self.axes[0].add_patch(self.rect) + self.cid = self.axes[0].figure.canvas.mpl_connect('button_press_event', self._onclick) + + + def line_select_callback(self, x_min, x_max): + self.start_cursor.value = np.round(x_min, 3) + self.end_cursor.value = np.round(x_max, 3) + self.start_channel = np.searchsorted(self.datasets[self.key].energy_loss, self.start_cursor.value) + self.end_channel = np.searchsorted(self.datasets[self.key].energy_loss, self.end_cursor.value) + + def set_dataset(self, index=0): + + if len(self.datasets) == 0: + data_set = sidpy.Dataset.from_array([0, 1], name='generic') + data_set.set_dimension(0, sidpy.Dimension([0,1], 'energy_loss', units='channel', quantity='generic', + dimension_type='spectral')) + data_set.data_type = 'spectrum' + data_set.metadata= {'experiment':{'convergence_angle': 0, + 'collection_angle': 0, + 'acceleration_voltage':0, + 'exposure_time':0}} + self.datasets={'Channel_000': data_set} + index = 0 + + dataset_index = index + + self.key = list(self.datasets)[dataset_index] + self.dataset = self.datasets[self.key] + + self._udpate_sidbar() + self.y_scale = 1.0 + self.change_y_scale = 1.0 + self.x = 0 + self.y = 0 + self.bin_x = 1 + self.bin_y = 1 + self.count = 0 + + self.plot() + + def _udpate_sidbar(self): + pass + + + def set_energy_scale(self, value): + dispersion = self.datasets[self.key].energy_loss[1] - self.datasets[self.key].energy_loss[0] + self.datasets[self.key].energy_loss *= (self.sidebar[3, 0].value/dispersion) + self.datasets[self.key].energy_loss += (self.sidebar[2, 0].value-self.datasets[self.key].energy_loss[0]) + self.plot() + + def set_y_scale(self, value): + self.count += 1 + self.change_y_scale = 1.0/self.y_scale + if self.sidebar[9,2].value: + dispersion = self.datasets[self.key].energy_loss[1] - self.datasets[self.key].energy_loss[0] + self.y_scale = 1/self.datasets[self.key].metadata['experiment']['flux_ppm'] * dispersion + self.ylabel='scattering probability (ppm)' + else: + self.y_scale = 1.0 + self.ylabel='intensity (counts)' + self.change_y_scale *= self.y_scale + self._update()
+ +
[docs]class InfoWidget(EELSWidget): + def __init__(self, datasets): + + sidebar = get_info_sidebar() + super().__init__(datasets, sidebar) + self.set_action() + + def set_flux(self, value): + self.datasets[self.key].metadata['experiment']['exposure_time'] = self.sidebar[10,0].value + if self.sidebar[9,0].value < 0: + self.datasets[self.key].metadata['experiment']['flux_ppm'] = 0. + else: + key = list(self.datasets.keys())[self.sidebar[9,0].value] + self.datasets[self.key].metadata['experiment']['flux_ppm'] = (np.array(self.datasets[key])*1e-6).sum() / self.datasets[key].metadata['experiment']['exposure_time'] + self.datasets[self.key].metadata['experiment']['flux_ppm'] *= self.datasets[self.key].metadata['experiment']['exposure_time'] + self.sidebar[11,0].value = np.round(self.datasets[self.key].metadata['experiment']['flux_ppm'], 2) + + def set_microscope_parameter(self, value): + self.datasets[self.key].metadata['experiment']['convergence_angle'] = self.sidebar[5,0].value + self.datasets[self.key].metadata['experiment']['collection_angle'] = self.sidebar[6,0].value + self.datasets[self.key].metadata['experiment']['acceleration_voltage'] = self.sidebar[7,0].value*1000 + + def cursor2energy_scale(self, value): + dispersion = (self.end_cursor.value - self.start_cursor.value) / (self.end_channel - self.start_channel) + self.datasets[self.key].energy_loss *= (self.sidebar[3, 0].value/dispersion) + self.sidebar[3, 0].value = dispersion + offset = self.start_cursor.value - self.start_channel * dispersion + self.datasets[self.key].energy_loss += (self.sidebar[2, 0].value-self.datasets[self.key].energy_loss[0]) + self.sidebar[2, 0].value = offset + self.plot() + + def set_binning(self, value): + if 'SPECTRAL' in self.dataset.data_type.name: + bin_x = self.sidebar[15,0].value + bin_y = self.sidebar[16,0].value + self.dataset.view.set_bin([bin_x, bin_y]) + self.datasets[self.key].metadata['experiment']['SI_bin_x'] = bin_x + self.datasets[self.key].metadata['experiment']['SI_bin_y'] = bin_y + + def _udpate_sidbar(self): + spectrum_list = [] + reference_list =[('None', -1)] + for index, key in enumerate(self.datasets.keys()): + if 'Reference' not in key: + if 'SPECTR' in self.datasets[key].data_type.name: + spectrum_list.append((f'{key}: {self.datasets[key].title}', index)) + reference_list.append((f'{key}: {self.datasets[key].title}', index)) + + self.sidebar[0,0].options = spectrum_list + self.sidebar[9,0].options = reference_list + + if 'SPECTRUM' in self.dataset.data_type.name: + for i in range(14, 17): + self.sidebar[i, 0].layout.display = "none" + else: + for i in range(14, 17): + self.sidebar[i, 0].layout.display = "flex" + #self.sidebar[0,0].value = dataset_index #f'{self.key}: {self.datasets[self.key].title}' + self.sidebar[2,0].value = np.round(self.datasets[self.key].energy_loss[0], 3) + self.sidebar[3,0].value = np.round(self.datasets[self.key].energy_loss[1] - self.datasets[self.key].energy_loss[0], 4) + self.sidebar[5,0].value = np.round(self.datasets[self.key].metadata['experiment']['convergence_angle'], 1) + self.sidebar[6,0].value = np.round(self.datasets[self.key].metadata['experiment']['collection_angle'], 1) + self.sidebar[7,0].value = np.round(self.datasets[self.key].metadata['experiment']['acceleration_voltage']/1000, 1) + self.sidebar[10,0].value = np.round(self.datasets[self.key].metadata['experiment']['exposure_time'], 4) + if 'flux_ppm' not in self.datasets[self.key].metadata['experiment']: + self.datasets[self.key].metadata['experiment']['flux_ppm'] = 0 + self.sidebar[11,0].value = self.datasets[self.key].metadata['experiment']['flux_ppm'] + if 'count_conversion' not in self.datasets[self.key].metadata['experiment']: + self.datasets[self.key].metadata['experiment']['count_conversion'] = 1 + self.sidebar[12,0].value = self.datasets[self.key].metadata['experiment']['count_conversion'] + if 'beam_current' not in self.datasets[self.key].metadata['experiment']: + self.datasets[self.key].metadata['experiment']['beam_current'] = 0 + self.sidebar[13,0].value = self.datasets[self.key].metadata['experiment']['beam_current'] + + def update_dataset(self): + dataset_index = self.sidebar[0, 0].value + self.set_dataset(dataset_index) + + def set_action(self): + self.sidebar[0,0].observe(self.update_dataset) + self.sidebar[1,0].on_click(self.cursor2energy_scale) + self.sidebar[2,0].observe(self.set_energy_scale, names='value') + self.sidebar[3,0].observe(self.set_energy_scale, names='value') + self.sidebar[5,0].observe(self.set_microscope_parameter) + self.sidebar[6,0].observe(self.set_microscope_parameter) + self.sidebar[7,0].observe(self.set_microscope_parameter) + self.sidebar[9,0].observe(self.set_flux) + self.sidebar[9,2].observe(self.set_y_scale, names='value') + self.sidebar[10,0].observe(self.set_flux) + self.sidebar[15,0].observe(self.set_binning) + self.sidebar[16,0].observe(self.set_binning)
+ +
[docs]def get_low_loss_sidebar(): + side_bar = ipywidgets.GridspecLayout(17, 3,width='auto', grid_gap="0px") + + side_bar[0, :2] = ipywidgets.Dropdown( + options=[('None', 0)], + value=0, + description='Main Dataset:', + disabled=False) + + row = 1 + side_bar[row, :3] = ipywidgets.Button(description='Fix Energy Scale', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=7.5,description='Offset:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='20px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Dispersion:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='20px')) + + row += 1 + side_bar[row, :3] = ipywidgets.Button(description='Resolution_function', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.3, description='Fit Window:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row,:2] = ipywidgets.ToggleButton( + description='Show Resolution Function', + disabled=False, + button_style='', # 'success', 'info', 'warning', 'danger' or '' + tooltip='Changes y-axis to probability if flux is given', + layout=ipywidgets.Layout(width='100px')) + side_bar[row,2] = ipywidgets.ToggleButton( + description='Probability', + disabled=False, + button_style='', # 'success', 'info', 'warning', 'danger' or '' + tooltip='Changes y-axis to probability if flux is given', + layout=ipywidgets.Layout(width='100px')) + row += 2 + + side_bar[row, :3] = ipywidgets.Button(description='Drude Fit', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + row+=1 + side_bar[row, :2] = ipywidgets.Dropdown( + options=[('None', 0)], + value=0, + description='Reference:', + disabled=False) + side_bar[row,2] = ipywidgets.ToggleButton( + description='Probability', + disabled=False, + button_style='', # 'success', 'info', 'warning', 'danger' or '' + tooltip='Changes y-axis to probability if flux is given', + layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Exp_Time:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="s", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=7.5,description='Flux:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="Mcounts", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Conversion:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value=r"e$^-$/counts", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Current:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="pA", layout=ipywidgets.Layout(width='100px') ) + + row += 1 + + side_bar[row, :3] = ipywidgets.Button(description='Spectrum Image', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + + row += 1 + side_bar[row, :2] = ipywidgets.IntText(value=1, description='bin X:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + row += 1 + side_bar[row, :2] = ipywidgets.IntText(value=1, description='bin X:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + + for i in range(14, 17): + pass + # side_bar[i, 0].layout.display = "none" + return side_bar
+ +
[docs]class LowLossWidget(EELSWidget): + def __init__(self, datasets): + sidebar = get_low_loss_sidebar() + super().__init__(datasets, sidebar) + self.sidebar[3,0].value = self.energy_scale[0] + self.sidebar[4,0].value = self.energy_scale[1] - self.energy_scale[0] + + self.set_action() + + def _udpate_sidbar(self): + spectrum_list = [] + reference_list =[('None', -1)] + for index, key in enumerate(self.datasets.keys()): + if 'Reference' not in key: + if 'SPECTR' in self.datasets[key].data_type.name: + spectrum_list.append((f'{key}: {self.datasets[key].title}', index)) + reference_list.append((f'{key}: {self.datasets[key].title}', index)) + + self.sidebar[0,0].options = spectrum_list + self.sidebar[9,0].options = reference_list + + if 'SPECTRUM' in self.dataset.data_type.name: + for i in range(14, 17): + self.sidebar[i, 0].layout.display = "none" + else: + for i in range(14, 17): + self.sidebar[i, 0].layout.display = "flex" + + def get_resolution_function(self, value): + self.datasets['resolution_functions'] = eels_tools.get_resolution_functions(self.dataset, zero_loss_fit_width=self.sidebar[5,0].value) + if 'low_loss' not in self.dataset.metadata: + self.dataset.metadata['low_loss'] = {} + self.dataset.metadata['low_loss'].update(self.datasets['resolution_functions'].metadata['low_loss']) + self.sidebar[6,0].value = True + + def update_dataset(self): + dataset_index = self.sidebar[0, 0].value + self.set_dataset(dataset_index) + + def set_action(self): + self.sidebar[0,0].observe(self.update_dataset) + self.sidebar[1,0].on_click(self.fix_energy_scale) + self.sidebar[2,0].observe(self.set_energy_scale, names='value') + self.sidebar[3,0].observe(self.set_energy_scale, names='value') + self.sidebar[4,0].on_click(self.get_resolution_function) + self.sidebar[6,2].observe(self.set_y_scale, names='value') + self.sidebar[6,0].observe(self._update, names='value') + + def fix_energy_scale(self, value=0): + self.dataset = eels_tools.shift_on_same_scale(self.dataset) + self.datasets[self.key] = self.dataset + if 'resolution_functions' in self.datasets: + self.datasets['resolution_functions'] = eels_tools.shift_on_same_scale(self.datasets['resolution_functions']) + self._update() + + + def set_y_scale(self, value): + self.change_y_scale = 1.0/self.y_scale + if self.sidebar[6,2].value: + dispersion = self.dataset.energy_loss[1] - self.dataset.energy_loss[0] + if self.dataset.data_type.name == 'SPECTRUM': + sum = self.dataset.sum() + else: + image_dims = self.dataset.get_dimensions_by_type(sidpy.DimensionType.SPATIAL) + sum = np.average(self.dataset, axis=image_dims).sum() + + self.y_scale = 1/sum * dispersion * 1e6 + # self.datasets[self.key].metadata['experiment']['flux_ppm'] * dispersion + self.ylabel='scattering probability (ppm)' + else: + self.y_scale = 1.0 + self.ylabel='intensity (counts)' + self.change_y_scale *= self.y_scale + self._update() + + def _update(self, ev=0): + super()._update(ev) + if self.sidebar[6,0].value: + if 'resolution_functions' in self.datasets: + resolution_function = self.get_additional_spectrum('resolution_functions') + self.axis.plot(self.energy_scale, resolution_function, label='resolution_function') + self.axis.legend() + + def get_additional_spectrum(self, key): + if key not in self.datasets.keys(): + return + + if self.datasets[key].data_type == sidpy.DataType.SPECTRUM: + self.spectrum = self.datasets[key].copy() + else: + image_dims = self.datasets[key].get_dimensions_by_type(sidpy.DimensionType.SPATIAL) + selection = [] + for dim, axis in self.datasets[key]._axes.items(): + # print(dim, axis.dimension_type) + if axis.dimension_type == sidpy.DimensionType.SPATIAL: + if dim == image_dims[0]: + selection.append(slice(self.x, self.x + self.bin_x)) + else: + selection.append(slice(self.y, self.y + self.bin_y)) + + elif axis.dimension_type == sidpy.DimensionType.SPECTRAL: + selection.append(slice(None)) + elif axis.dimension_type == sidpy.DimensionType.CHANNEL: + selection.append(slice(None)) + else: + selection.append(slice(0, 1)) + + self.spectrum = self.datasets[key][tuple(selection)].mean(axis=tuple(image_dims)) + + self.spectrum *= self.y_scale + + return self.spectrum.squeeze() + + def set_binning(self, value): + if 'SPECTRAL' in self.dataset.data_type.name: + bin_x = self.sidebar[15,0].value + bin_y = self.sidebar[16,0].value + self.dataset.view.set_bin([bin_x, bin_y]) + self.datasets[self.key].metadata['experiment']['SI_bin_x'] = bin_x + self.datasets[self.key].metadata['experiment']['SI_bin_y'] = bin_y
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/kinematic_scattering.html b/_modules/pyTEMlib/kinematic_scattering.html new file mode 100644 index 00000000..9303864f --- /dev/null +++ b/_modules/pyTEMlib/kinematic_scattering.html @@ -0,0 +1,1746 @@ + + + + + + pyTEMlib.kinematic_scattering — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for pyTEMlib.kinematic_scattering

+"""
+kinematic_scattering
+Copyright by Gerd Duscher
+
+The University of Tennessee, Knoxville
+Department of Materials Science & Engineering
+
+Sources:
+   Scattering Theory:
+   Zuo and Spence, "Advanced TEM", 2017
+
+   Spence and Zuo, Electron Microdiffraction, Plenum 1992
+
+   Atomic Form Factor:
+       Kirkland: Advanced Computing in Electron Microscopy 2nd edition
+       Appendix C
+
+Units:
+    everything is in SI units, except length which is given in Angstrom.
+
+Usage:
+    See the notebooks for examples of these routines
+
+All the input and output is done through a ase.Atoms object and the dictionary in the info attribute
+"""
+
+# numerical packages used
+import numpy as np
+import scipy.constants as const
+import itertools
+
+# plotting package used
+import matplotlib.pylab as plt  # basic plotting
+
+import pyTEMlib.file_tools as ft
+from pyTEMlib.crystal_tools import *
+from pyTEMlib.diffraction_plot import *
+
+_version_ = "0.2022.1.0"
+
+print('Using kinematic_scattering library version {_version_ }  by G.Duscher')
+
+inputKeys = ['acceleration_voltage_V', 'zone_hkl', 'Sg_max', 'hkl_max']
+optional_inputKeys = ['crystal', 'lattice_parameter_nm', 'convergence_angle_mrad', 'mistilt', 'thickness',
+                      'dynamic correction', 'dynamic correction K0']
+
+
+
[docs]def read_poscar(filename): + print('read_poscar and read_cif moved to file_tools, \n' + 'please use that library in the future!') + ft.read_poscar(filename)
+ + +
[docs]def example(verbose=True): + """ + same as Zuo_fig_3_18 + """ + print('\n##########################') + print('# Start of Example Input #') + print('##########################\n') + print('Define only mandatory input: ', inputKeys) + print(' Kinematic diffraction routine will set optional input : ', optional_inputKeys) + + return Zuo_fig_3_18(verbose=verbose)
+ + +
[docs]def Zuo_fig_3_18(verbose=True): + """ + Input for Figure 3.18 in Zuo and Spence \"Advanced TEM\", 2017 + + This input acts as an example as well as a reference + + Parameters: + ----------- + verbose: boolean: + optional to see output + Returns: + ------- + atoms: ase.Atoms + Silicon crystal structure + e + dictionary: tags is the dictionary of all input and output parameter needed to reproduce that figure. + """ + + # INPUT + # Create Silicon structure (Could be produced with Silicon routine) + if verbose: + print('Sample Input for Figure 3.18 in Zuo and Spence \"Advanced TEM\", 2017') + import ase + import ase.build + a = 5.14 # A + atoms = ase.build.bulk('Si', 'diamond', a=a, cubic=True) + + experiment = {'acceleration_voltage_V': 99.2 * 1000.0, # V + 'convergence_angle_mrad': 7.15, # mrad; + 'zone_hkl': np.array([-2, 2, 1]), + 'mistilt': np.array([0, 0, 0]), # mistilt in degrees + 'Sg_max': .03, # 1/A maximum allowed excitation error + 'hkl_max': 9 # Highest evaluated Miller indices + } + # Define Experimental Conditions + if verbose: + print('###########################') + print('# Experimental Conditions #') + print('###########################') + + for key, value in experiment.items(): + print(f'tags[\'{key}\'] =', value) + + print('##################') + print('# Output Options #') + print('##################') + + # Output options + output = {'background': 'black', # 'white' 'grey' + 'color_map': 'plasma', + 'plot_HOLZ': True, + 'plot_HOLZ_excess': True, + 'plot_Kikuchi': True, + 'plot_reflections': True, + 'label_HOLZ': False, + 'label_Kikuchi': False, + 'label_reflections': False, + 'label_color': 'black', + 'label_size': 10, + 'color_Laue_Zones': ['red', 'blue', 'green', 'blue', 'green'], # for OLZ give a sequence + 'color_Kikuchi': 'green', + 'linewidth_HOLZ': -1, # -1: linewidth according to intensity (structure factor F^2) + 'linewidth_Kikuchi': -1, # -1: linewidth according to intensity (structure factor F^2) + 'color_reflections': 'intensity', # 'Laue Zone' + 'color_zero': 'white', # 'None', 'white', 'blue' + 'color_ring_zero': 'None' # 'Red' #'white' #, 'None' + } + + if verbose: + for key, value in output.items(): + print(f'tags[\'{key}\'] =', value) + print('########################') + print('# End of Example Input #') + print('########################\n\n') + + if atoms.info is None: + atoms.info = {} + atoms.info['experimental'] = experiment + atoms.info['output'] = output + + return atoms
+ + +
[docs]def zone_mistilt(zone, angles): + """ Rotation of zone axis by mistilt + + Parameters + ---------- + zone: list or numpy array of int + zone axis in Miller indices + angles: ist or numpy array of float + list of mistilt angles in degree + + Returns + ------- + new_zone_axis: np.ndarray (3) + new tilted zone axis + """ + + if not isinstance(angles, (np.ndarray, list)): + raise TypeError('angles must be a list of float of length 3') + if len(angles) != 3: + raise TypeError('angles must be a list of float of length 3') + if not isinstance(zone, (np.ndarray, list)): + raise TypeError('Miller indices must be a list of int of length 3') + + alpha, beta, gamma = np.radians(angles) + + # first we rotate alpha about x-axis + c, s = np.cos(alpha), np.sin(alpha) + rot_x = np.array([[1, 0, 0], [0, c, -s], [0, s, c]]) + + # second we rotate beta about y-axis + c, s = np.cos(beta), np.sin(beta) + rot_y = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]]) + + # third we rotate gamma about z-axis + c, s = np.cos(gamma), np.sin(gamma) + rot_z = np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]]) + + return np.dot(np.dot(np.dot(zone, rot_x), rot_y), rot_z)
+ + +
[docs]def get_metric_tensor(matrix): + """The metric tensor of the lattice.""" + metric_tensor2 = np.dot(matrix, matrix.T) + return metric_tensor2
+ + +
[docs]def vector_norm(g): + """ Length of vector + + depreciated - use np.linalg.norm + """ + g = np.array(g) + return np.sqrt(g[:, 0] ** 2 + g[:, 1] ** 2 + g[:, 2] ** 2)
+ + +
[docs]def get_wavelength(acceleration_voltage): + """ + Calculates the relativistic corrected de Broglie wavelength of an electron in Angstrom + + Parameter: + --------- + acceleration_voltage: float + acceleration voltage in volt + Returns: + ------- + wavelength: float + wave length in Angstrom + """ + if not isinstance(acceleration_voltage, (int, float)): + raise TypeError('Acceleration voltage has to be a real number') + eU = const.e * acceleration_voltage + return const.h/np.sqrt(2*const.m_e*eU*(1+eU/(2*const.m_e*const.c**2)))*10**10
+ + +
[docs]def find_nearest_zone_axis(tags): + """Test all zone axis up to a maximum of hkl_max""" + + hkl_max = 5 + # Make all hkl indices + h = np.linspace(-hkl_max, hkl_max, 2 * hkl_max + 1) # all evaluated single Miller Indices + hkl = np.array(list(itertools.product(h, h, h))) # all evaluated Miller indices + + # delete [0,0,0] + index = int(len(hkl) / 2) + zones_hkl = np.delete(hkl, index, axis=0) # delete [0,0,0] + + # make zone axis in reciprocal space + zones_g = np.dot(zones_hkl, tags['reciprocal_unit_cell']) # all evaluated reciprocal_unit_cell points + + # make zone axis in microscope coordinates of reciprocal space + zones_g = np.dot(zones_g, tags['rotation_matrix']) # rotate these reciprocal_unit_cell points + + # calculate angles with z-axis + zones_g_norm = vector_norm(zones_g) + z_axis = np.array([0, 0, 1]) + + zones_angles = np.abs(np.arccos(np.dot((zones_g.T / zones_g_norm).T, z_axis))) + + # get smallest angle + smallest = (zones_angles - zones_angles.min()) < 0.001 + if smallest.sum() > 1: # multiples of Miller index of zone axis have same angle + zone = zones_hkl[smallest] + zone_index = abs(zone).sum(axis=1) + ind = zone_index.argmin() + zone_hkl = zone[ind] + else: + zone_hkl = zones_hkl[smallest][0] + + tags['nearest_zone_axis'] = zone_hkl + + # get other zone axes up to 5 degrees away + others = np.logical_not(smallest) + next_smallest = (zones_angles[others]) < np.deg2rad(5.) + ind = np.argsort((zones_angles[others])[next_smallest]) + + tags['next_nearest_zone_axes'] = ((zones_hkl[others])[next_smallest])[ind] + + return zone_hkl
+ + +
[docs]def find_angles(zone): + """Microscope stage coordinates of zone""" + + # rotation around y-axis + r = np.sqrt(zone[1] ** 2 + zone[2] ** 2) + alpha = np.arctan(zone[0] / r) + if zone[2] < 0: + alpha = np.pi - alpha + # rotation around x-axis + if zone[2] == 0: + beta = np.pi / 2 * np.sign(zone[1]) + else: + beta = (np.arctan(zone[1] / zone[2])) + return alpha, beta
+ + +
[docs]def stage_rotation_matrix(alpha, beta): + """ Microscope stage coordinate system """ + + # FIRST we rotate beta about x-axis + c, s = np.cos(beta), np.sin(beta) + rot_x = np.array([[1, 0, 0], [0, c, -s], [0, s, c]]) + # second we rotate alpha about y-axis + c, s = np.cos(alpha), np.sin(alpha) + rot_y = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]]) + + return np.dot(rot_x, rot_y)
+ + +# ################## +# Determine rotation matrix to tilt zone axis onto z-axis +# We determine spherical coordinates to do that +# ################## + +
[docs]def get_rotation_matrix(tags): + """zone axis in global coordinate system""" + + zone_hkl = tags['zone_hkl'] + zone = np.dot(zone_hkl, tags['reciprocal_unit_cell']) + + # angle of zone with Z around x,y: + alpha, beta = find_angles(zone) + + alpha = alpha + tags['mistilt_alpha'] + beta = beta + tags['mistilt_beta'] + + tags['y-axis rotation alpha'] = alpha + tags['x-axis rotation beta'] = beta + + tags['rotation_matrix'] = rotation_matrix = stage_rotation_matrix(alpha, -beta) + + # the rotation now makes z-axis coincide with plane normal + + zone_nearest = find_nearest_zone_axis(tags) + tags['nearest_zone_axis'] = zone_nearest + + # tilt angles of coordinates of nearest zone + zone_nearest = np.dot(zone_nearest, tags['reciprocal_unit_cell']) + + alpha_nearest, beta_nearest = find_angles(zone_nearest) + + # calculate mistilt of nearest zone axis + tags['mistilt_nearest_zone alpha'] = alpha - alpha_nearest + tags['mistilt_nearest_zone beta'] = beta - beta_nearest + + tags['nearest_zone_axes'] = {} + tags['nearest_zone_axes']['0'] = {} + tags['nearest_zone_axes']['0']['hkl'] = tags['nearest_zone_axis'] + tags['nearest_zone_axes']['0']['mistilt_alpha'] = alpha - alpha_nearest + tags['nearest_zone_axes']['0']['mistilt_beta'] = beta - beta_nearest + + # find polar coordinates of next nearest zones + tags['nearest_zone_axes']['amount'] = len(tags['next_nearest_zone_axes']) + 1 + + for i in range(len(tags['next_nearest_zone_axes'])): + zone_n = tags['next_nearest_zone_axes'][i] + tags['nearest_zone_axes'][str(i + 1)] = {} + tags['nearest_zone_axes'][str(i + 1)]['hkl'] = zone_n + + zone_near = np.dot(zone_n, tags['reciprocal_unit_cell']) + # zone_near_g = np.dot(zone_near,rotation_matrix) + + tags['nearest_zone_axes'][str(i + 1)]['g'] = zone_near + alpha_nearest, beta_nearest = find_angles(zone_near) + + tags['nearest_zone_axes'][str(i + 1)]['mistilt_alpha'] = alpha - alpha_nearest + tags['nearest_zone_axes'][str(i + 1)]['mistilt_beta'] = beta - beta_nearest + # print('other' , i, np.rad2deg([alpha, alpha_nearest, beta, beta_nearest])) + + return rotation_matrix
+ + +
[docs]def check_sanity(atoms, verbose_level=0): + """ + Check sanity of input parameters + """ + stop = False + output = atoms.info['output'] + tags = atoms.info['experimental'] + for key in ['acceleration_voltage_V']: + if key not in tags: + print(f'Necessary parameter {key} not defined') + stop = True + if 'SpotPattern' not in output: + output['SpotPattern'] = False + if output['SpotPattern']: + if 'zone_hkl' not in tags: + print(' No zone_hkl defined') + stop = True + if 'Sg_max' not in tags: + print(' No Sg_max defined') + stop = True + if 'hkl_max' not in tags: + print(' No hkl_max defined') + stop = True + + if stop: + print('Input is not complete, stopping') + print('Try \'example()\' for example input') + return False + ############################################ + # Check optional input + ############################################ + + if output['SpotPattern']: + if 'mistilt_alpha degree' not in tags: + # mistilt is in microscope coordinates + tags['mistilt_alpha'] = tags['mistilt_alpha degree'] = 0.0 + if verbose_level > 0: + print('Setting undefined input: tags[\'mistilt_alpha\'] = 0.0 ') + else: + tags['mistilt_alpha'] = np.deg2rad(tags['mistilt_alpha degree']) + + if 'mistilt_beta degree' not in tags: + # mistilt is in microscope coordinates + tags['mistilt_beta'] = tags['mistilt_beta degree'] = 0.0 + if verbose_level > 0: + print('Setting undefined input: tags[\'mistilt_beta\'] = 0.0') + else: + tags['mistilt_beta'] = np.deg2rad(tags['mistilt_beta degree']) + + if 'convergence_angle_mrad' not in tags: + tags['convergence_angle_mrad'] = 0. + if verbose_level > 0: + print('Setting undefined input: tags[\'convergence_angle_mrad\'] = 0') + + if 'thickness' not in tags: + tags['thickness'] = 0. + if verbose_level > 0: + print('Setting undefined input: tags[\'thickness\'] = 0') + if 'dynamic correction' not in tags: + tags['dynamic correction'] = 0. + if verbose_level > 0: + print('Setting undefined input: tags[\'dynamic correction\'] = False') + if 'dynamic correction K0' not in tags: + tags['dynamic correction K0'] = 0. + if verbose_level > 0: + print('Setting undefined input: tags[\'dynamic correction k0\'] = False') + return not stop
+ + +
[docs]def scattering_matrix(tags, verbose_level=1): + """ Scattering matrix""" + if not check_sanity(tags, verbose_level): + return + # ## + # Pair distribution Function + # ## + unit_cell = np.array(tags['unit_cell']) + base = tags['base'] + + atom_coordinates = np.dot(base, unit_cell) + + n = 20 + x = np.linspace(-n, n, 2 * n + 1) # all evaluated multiples of x + xyz = np.array(list(itertools.product(x, x, x))) # all evaluated multiples in all direction + + mat = np.dot(xyz, unit_cell) # all evaluated unit_cells + + atom = {} + + for i in range(len(atom_coordinates)): + distances = np.linalg.norm(mat + atom_coordinates[i], axis=1) + if i == 0: + all_distances = distances + else: + all_distances = np.append(all_distances, distances) + unique, counts = np.unique(distances, return_counts=True) + + atom[str(i)] = dict(zip(unique, counts)) + print(atom[str(i)]) + + all_distances = np.append(all_distances, distances) + unique, counts = np.unique(all_distances, return_counts=True) + + plt.plot(unique, counts) + plt.show()
+ + +
[docs]def ring_pattern_calculation(atoms, verbose=False): + """ + Calculate the ring diffraction pattern of a crystal structure + + Parameters + ---------- + atoms: Crystal + crystal structure + verbose: verbose print-outs + set to False + Returns + ------- + tags: dict + dictionary with diffraction information added + """ + + # Check sanity + if not check_sanity(atoms, verbose): + return + + tags = atoms.info['experimental'] + # wavelength + tags['wave_length'] = get_wavelength(tags['acceleration_voltage_V']) + + # volume of unit_cell + unit_cell = atoms.cell.array + metric_tensor = get_metric_tensor(unit_cell) # converts hkl to g vectors and back + tags['metric_tensor'] = metric_tensor + # volume_unit_cell = np.sqrt(np.linalg.det(metric_tensor)) + + # reciprocal_unit_cell + + # We use the linear algebra package of numpy to invert the unit_cell "matrix" + reciprocal_unit_cell = atoms.cell.reciprocal() # np.linalg.inv(unit_cell).T # transposed of inverted unit_cell + tags['reciprocal_unit_cell'] = reciprocal_unit_cell + # inverse_metric_tensor = get_metric_tensor(reciprocal_unit_cell) + + hkl_max = tags['hkl_max'] + + h = np.linspace(-hkl_max, hkl_max, 2 * hkl_max + 1) # all evaluated single Miller Indices + hkl = np.array(list(itertools.product(h, h, h))) # all evaluated Miller indices + + # delete [0,0,0] + index_center = int(len(hkl) / 2) + hkl = np.delete(hkl, index_center, axis=0) # delete [0,0,0] + + g_hkl = np.dot(hkl, reciprocal_unit_cell) # all evaluated reciprocal_unit_cell points + + ################################## + # Calculate Structure Factors + ################################# + + structure_factors = [] + for j in range(len(g_hkl)): + F = 0 + for b in range(len(atoms)): + f = feq(atoms[b].symbol, np.linalg.norm(g_hkl[j])) + F += f * np.exp(-2 * np.pi * 1j * (hkl[j] * atoms.get_scaled_positions()[b]).sum()) + + structure_factors.append(F) + + F = structure_factors = np.array(structure_factors) + + # Sort reflection in allowed and forbidden # + + allowed = np.absolute(F) > 0.000001 # allowed within numerical error + + if verbose: + print('Of the {0} possible reflection {1} are allowed.'.format(hkl.shape[0], allowed.sum())) + + # information of allowed reflections + hkl_allowed = hkl[allowed][:] + g_allowed = g_hkl[allowed, :] + F_allowed = F[allowed] + g_norm_allowed = vector_norm(g_allowed) # length of all vectors = 1/ + + ind = np.argsort(g_norm_allowed) + g_norm_sorted = g_norm_allowed[ind] + hkl_sorted = hkl_allowed[ind][:] + F_sorted = F_allowed[ind] + + unique, counts = np.unique(np.around(g_norm_sorted, decimals=5), return_counts=True) + if verbose: + print('Of the {0} allowed reflection {1} have unique distances.'.format(allowed.sum(), len(unique))) + + reflections_d = [] + reflections_m = [] + reflections_F = [] + + start = 0 + for i in range(len(unique)): + end = start + counts[i] + hkl_max = np.argmax(hkl_sorted[start:end].sum(axis=1)) + + reflections_d.append(g_norm_sorted[start]) + reflections_m.append(hkl_sorted[start + hkl_max]) + reflections_F.append(F_sorted[start]) # :end].sum()) + + start = end + + if verbose: + print('\n\n [hkl] \t 1/d [1/nm] \t d [nm] \t F^2 ') + for i in range(len(unique)): + print(' {0} \t {1:.2f} \t {2:.4f} \t {3:.2f} ' + .format(reflections_m[i], unique[i]*10., 1 / unique[i]/10., np.real(reflections_F[i]) ** 2)) + + atoms.info['Ring_Pattern'] = {} + atoms.info['Ring_Pattern']['allowed'] = {} + atoms.info['Ring_Pattern']['allowed']['hkl'] = reflections_m + atoms.info['Ring_Pattern']['allowed']['g norm'] = unique + atoms.info['Ring_Pattern']['allowed']['structure factor'] = reflections_F + atoms.info['Ring_Pattern']['allowed']['multiplicity'] = counts + + atoms.info['Ring_Pattern']['profile_x'] = np.linspace(0, unique.max(), 2048) + step_size = atoms.info['Ring_Pattern']['profile_x'][1] + intensity = np.zeros(2048) + x_index = [(unique / step_size + 0.5).astype(int)] + intensity[x_index] = np.array(np.real(reflections_F)) * np.array(np.real(reflections_F)) + atoms.info['Ring_Pattern']['profile_y delta'] = intensity + + def gaussian(xx, pp): + s1 = pp[2] / 2.3548 + prefactor = 1.0 / np.sqrt(2 * np.pi * s1 ** 2) + y = (pp[1] * prefactor) * np.exp(-(xx - pp[0]) ** 2 / (2 * s1 ** 2)) + return y + + if 'thickness' in tags: + if tags['thickness'] > 0: + x = np.linspace(-1024, 1023, 2048) * step_size + p = [0.0, 1, 2 / tags['thickness']] + + gauss = gaussian(x, p) + intensity = np.convolve(np.array(intensity), np.array(gauss), mode='same') + atoms.info['Ring_Pattern']['profile_y'] = intensity + + # Make pretty labels + hkl_allowed = reflections_m + hkl_label = make_pretty_labels(hkl_allowed) + atoms.info['Ring_Pattern']['allowed']['label'] = hkl_label
+ + +
[docs]def get_dynamically_allowed(atoms, verbose=False): + if not isinstance(atoms, ase.Atoms): + print('we need an ase atoms object as input') + if 'diffraction' not in atoms.info: + print('Run the kinematic_scattering function first') + + # Dynamically Allowed Reflection + + dif = atoms.info['diffraction'] + hkl_allowed = dif['allowed']['hkl'] + hkl_forbidden = dif['forbidden']['hkl'] + indices = range(len(hkl_allowed)) + combinations = [list(x) for x in itertools.permutations(indices, 2)] + hkl_forbidden = hkl_forbidden.tolist() + dynamically_allowed = np.zeros(len(hkl_forbidden), dtype=bool) + for [i, j] in combinations: + possible = (hkl_allowed[i] + hkl_allowed[j]).tolist() + if possible in hkl_forbidden: + dynamically_allowed[hkl_forbidden.index(possible)] = True + dif['forbidden']['dynamically_allowed'] = dynamically_allowed + + if verbose: + print(f"Of the {len(hkl_forbidden)} forbidden reflection {dynamically_allowed.sum()} " + f"can be dynamically activated.")
+ # print(dif['forbidden']['hkl'][dynamically_allowed]) + + +
[docs]def kinematic_scattering(atoms, verbose=False): + """ + All kinematic scattering calculation + + Calculates Bragg spots, Kikuchi lines, excess, and deficient HOLZ lines + + Parameters + ---------- + atoms: ase.Atoms + object with crystal structure: + and with experimental parameters in info attribute: + 'acceleration_voltage_V', 'zone_hkl', 'Sg_max', 'hkl_max' + Optional parameters are: + 'mistilt', convergence_angle_mrad', and 'crystal_name' + verbose = True will give extended output of the calculation + verbose: boolean + default is False + + Returns + ------- + atoms: + There are three sub_dictionaries in info attribute: + ['allowed'], ['forbidden'], and ['HOLZ'] + ['allowed'] and ['forbidden'] dictionaries contain: + ['Sg'], ['hkl'], ['g'], ['structure factor'], ['intensities'], + ['ZOLZ'], ['FOLZ'], ['SOLZ'], ['HOLZ'], ['HHOLZ'], ['label'], and ['Laue_zone'] + the ['HOLZ'] dictionary contains: + ['slope'], ['distance'], ['theta'], ['g_deficient'], ['g_excess'], ['hkl'], ['intensities'], + ['ZOLZ'], ['FOLZ'], ['SOLZ'], ['HOLZ'], and ['HHOLZ'] + Please note that the Kikuchi lines are the HOLZ lines of ZOLZ + + There are also a few parameters stored in the main dictionary: + ['wave_length_nm'], ['reciprocal_unit_cell'], ['inner_potential_V'], ['incident_wave_vector'], + ['volume'], ['theta'], ['phi'], and ['incident_wave_vector_vacuum'] + """ + + # Check sanity + if atoms.info is None: + atoms.info = {'output': {}, 'experimental': {}} + elif 'output' in atoms.info: + output = atoms.info['output'] + else: + output = atoms.info['output'] = {} + + output['SpotPattern'] = True + + if 'experimental' not in atoms.info: + tags = atoms.info['experimental'] = {} + + if not check_sanity(atoms): + print('Input is not complete, stopping') + print('Try \'example()\' for example input') + return + + tags = atoms.info['experimental'] + + tags['wave_length'] = get_wavelength(tags['acceleration_voltage_V']) + + # ########################################### + # reciprocal_unit_cell + # ########################################### + unit_cell = atoms.cell.array + tags['unit_cell'] = unit_cell + metric_tensor = get_metric_tensor(unit_cell) # converts hkl to g vectors and back + tags['metric_tensor'] = metric_tensor + volume_unit_cell = atoms.cell.volume + + # We use the linear algebra package of numpy to invert the unit_cell "matrix" + reciprocal_unit_cell = atoms.cell.reciprocal() # np.linalg.inv(unit_cell).T # transposed of inverted unit_cell + tags['reciprocal_unit_cell'] = reciprocal_unit_cell + inverse_metric_tensor = get_metric_tensor(reciprocal_unit_cell) + + # ########################################### + # Incident wave vector k0 in vacuum and material + # ########################################### + + # Incident wave vector K0 in vacuum and material + u0 = 0.0 # in (Ang) + # atom form factor of zero reflection angle is the inner potential in 1/A + for i in range(len(atoms)): + u0 += feq(atoms[i].symbol, 0.0) + + angstrom_conversion = 1.0e10 # So [1A (in m)] * angstrom_conversion = 1 + # NanometerConversion = 1.0e9 + + scattering_factor_to_volts = (const.h ** 2) * (1e10 ** 2) / (2 * np.pi * const.m_e * const.e) * volume_unit_cell + tags['inner_potential_V'] = u0 * scattering_factor_to_volts + if verbose: + print(f'The inner potential is {u0:.1f} V') + + # Calculating incident wave vector magnitude 'k0' in material + wl = tags['wave_length'] + tags['incident_wave_vector_vacuum'] = 1 / wl + + k_0 = tags['incident_wave_vector'] = np.sqrt(1 / wl**2 + u0/volume_unit_cell) # 1/Ang + + tags['convergence_angle_A-1'] = k_0*np.sin(tags['convergence_angle_mrad']/1000.) + + if verbose: + print(f"Using an acceleration voltage of {tags['acceleration_voltage_V']/1000:.1f}kV") + print(f'Magnitude of incident wave vector in material: {k_0:.4f} 1/Ang and in vacuum: {1/wl:.4f} 1/Ang') + print(f"Which is an wave length of {1/k_0 * 100.:.3f} pm in the material and {wl * 100.:.3f} pm " + f"in the vacuum") + print(f"The convergence angle of {tags['convergence_angle_mrad']:.1f}mrad " + f"= {tags['convergence_angle_A-1']:.2f} 1/A") + print(f"Magnitude of incident wave vector in material: {k_0:.1f} 1/A which is a wavelength {100/k_0:.3f} pm") + + # ############ + # Rotate + # ############ + + # get rotation matrix to rotate zone axis onto z-axis + rotation_matrix = get_rotation_matrix(tags) + + if verbose: + print(f"Rotation alpha {np.rad2deg(tags['y-axis rotation alpha']):.1f} degree, " + f" beta {np.rad2deg(tags['x-axis rotation beta']):.1f} degree") + print(f"from zone axis {tags['zone_hkl']}") + print(f"Tilting {1} by {np.rad2deg(tags['mistilt_alpha']):.2f} " + f" in alpha and {np.rad2deg(tags['mistilt_beta']):.2f} in beta direction results in :") + # list(tags['zone_hkl']) + # + # print(f"zone axis {list(tags['nearest_zone_axis'])} with a mistilt of " + # f"{np.rad2deg(tags['mistilt_nearest_zone alpha']):.2f} in alpha " + # f"and {np.rad2deg(tags['mistilt_nearest_zone beta']):.2f} in beta direction") + nearest = tags['nearest_zone_axes'] + print('Next nearest zone axes are:') + for i in range(1, nearest['amount']): + print(f"{nearest[str(i)]['hkl']}: mistilt: {np.rad2deg(nearest[str(i)]['mistilt_alpha']):6.2f}, " + f"{np.rad2deg(nearest[str(i)]['mistilt_beta']):6.2f}") + # rotate incident wave vector + k0_unit_vector = np.array([0, 0, 1]) # incident unit wave vector + k0_vector = k0_unit_vector * k_0 # incident wave vector + cent = k0_vector # center of Ewald sphere + + if verbose: + print('Center of Ewald sphere ', k0_vector) + + # ####################### + # Find all Miller indices whose reciprocal point lies near the Ewald sphere with radius k_0 + # within a maximum excitation error Sg + # ####################### + + hkl_max = tags['hkl_max'] + Sg_max = tags['Sg_max'] # 1/Ang maximum allowed excitation error + + h = np.linspace(-hkl_max, hkl_max, 2*hkl_max+1) # all evaluated single Miller Indices + hkl = np.array(list(itertools.product(h, h, h))) # all evaluated Miller indices + g_non_rot = np.dot(hkl, reciprocal_unit_cell) # all evaluated reciprocal_unit_cell points + g_norm = np.linalg.norm(g_non_rot, axis=1) # length of all vectors + not_zero = g_norm > 0 + g_non_rot = g_non_rot[not_zero] # zero reflection will make problems further on, so we exclude it. + g_norm = g_norm[not_zero] + hkl_all = hkl[not_zero] + g = np.dot(g_non_rot, rotation_matrix) + + # ####################### + # Calculate excitation errors for all reciprocal_unit_cell points + # ####################### + + # Zuo and Spence, 'Adv TEM', 2017 -- Eq 3:14 + S = (k_0**2-np.linalg.norm(g - k0_vector, axis=1)**2)/(2*k_0) + + # g_mz = g - k0_vector + # in_sqrt = g_mz[:, 2]**2 + np.linalg.norm(g_mz, axis=1)**2 - k_0**2 + # in_sqrt[in_sqrt < 0] = 0. + # S = -g_mz[:, 2] - np.sqrt(in_sqrt) + + # ####################### + # Determine reciprocal_unit_cell points with excitation error less than the maximum allowed one: Sg_max + # ####################### + + reflections = abs(S) < Sg_max # This is now a boolean array with True for all possible reflections + + Sg = S[reflections] + g_hkl = g[reflections] + g_hkl_non_rot = g_non_rot[reflections] + hkl = hkl_all[reflections] + g_norm = g_norm[reflections] + + if verbose: + print('Of the {0} tested reciprocal_unit_cell points, {1} have an excitation error less than {2:.2f} 1/nm'. + format(len(g), len(g_hkl), Sg_max)) + + # ################################# + # Calculate Structure Factors + # ################################ + + structure_factors = [] + for j in range(len(g_hkl)): + F = 0 + for b in range(len(atoms)): + f = feq(atoms[b].symbol, g_norm[j]) # Atomic form factor for element and momentum change (g vector) + F += f * np.exp(-2*np.pi*1j*(g_hkl_non_rot[j]*atoms.positions[b]).sum()) + structure_factors.append(F) + F = structure_factors = np.array(structure_factors) + + # ########################################### + # Sort reflection in allowed and forbidden # + # ########################################### + + allowed = np.absolute(F) > 0.000001 # allowed within numerical error + + if verbose: + print('Of the {0} possible reflection {1} are allowed.'.format(hkl.shape[0], allowed.sum())) + + # information of allowed reflections + s_g_allowed = Sg[allowed] + hkl_allowed = hkl[allowed][:] + g_allowed = g_hkl[allowed, :] + F_allowed = F[allowed] + g_norm_allowed = g_norm[allowed] + + atoms.info['diffraction'] = {} + dif = atoms.info['diffraction'] + dif['allowed'] = {} + dif['allowed']['Sg'] = s_g_allowed + dif['allowed']['hkl'] = hkl_allowed + dif['allowed']['g'] = g_allowed + dif['allowed']['structure factor'] = F_allowed + + # Calculate Extinction Distance Reimer 7.23 + # - makes only sense for non-zero F + + xi_g = np.real(np.pi * volume_unit_cell * k_0 / F_allowed) + + # Calculate Intensity of beams Reimer 7.25 + if 'thickness' not in tags: + tags['thickness'] = 0. + thickness = tags['thickness'] + if thickness > 0.1: + I_g = np.real(np.pi ** 2 / xi_g ** 2 * np.sin(np.pi * thickness * s_g_allowed) ** 2 / (np.pi * s_g_allowed)**2) + dif['allowed']['Ig'] = I_g + + dif['allowed']['intensities'] = intensities = np.real(F_allowed) ** 2 + + # Calculate Extinction Distance Reimer 7.23 + # - makes only sense for non-zero F + + xi_g = np.real(np.pi * volume_unit_cell * k_0 / F_allowed) + + # ########################### + # Calculate Intensities (of allowed reflections) + # ########################### + + # Calculate Intensity of beams Reimer 7.25 + if 'thickness' not in tags: + tags['thickness'] = 0. + thickness = tags['thickness'] + if thickness > 0.1: + I_g = np.real(np.pi ** 2 / xi_g ** 2 * np.sin(np.pi * thickness * s_g_allowed) ** 2 / (np.pi * s_g_allowed)**2) + dif['allowed']['Ig'] = I_g + + dif['allowed']['intensities'] = intensities = np.real(F_allowed) ** 2 + + # information of forbidden reflections + forbidden = np.logical_not(allowed) + Sg_forbidden = Sg[forbidden] + hkl_forbidden = hkl[forbidden] + g_forbidden = g_hkl[forbidden] + F_forbidden = F[forbidden] + + dif['forbidden'] = {} + dif['forbidden']['Sg'] = Sg_forbidden + dif['forbidden']['hkl'] = hkl_forbidden + dif['forbidden']['g'] = g_forbidden + + # ########################## + # Make pretty labels + # ########################## + hkl_label = make_pretty_labels(hkl_allowed) + dif['allowed']['label'] = hkl_label + hkl_label = make_pretty_labels(hkl_forbidden) + dif['forbidden']['label'] = hkl_label + + # Center of Laue Circle + laue_circle = np.dot(tags['nearest_zone_axis'], tags['reciprocal_unit_cell']) + laue_circle = np.dot(laue_circle, rotation_matrix) + laue_circle = laue_circle / np.linalg.norm(laue_circle) * k_0 + laue_circle[2] = 0 + + dif['Laue_circle'] = laue_circle + if verbose: + print('Laue_circle', laue_circle) + + # ########################### + # Calculate Laue Zones (of allowed reflections) + # ########################### + # Below is the expression given in most books. + # However, that would only work for orthogonal crystal systems + # Laue_Zone = abs(np.dot(hkl_allowed,tags['zone_hkl'])) # works only for orthogonal systems + + # This expression works for all crystal systems + # Remember we have already tilted, and so the dot product is trivial and gives only the z-component. + length_zone_axis = np.linalg.norm(np.dot(tags['zone_hkl'], tags['unit_cell'])) + laue_zone = abs(np.dot(hkl_allowed, tags['nearest_zone_axis'])) + dif['allowed']['Laue_Zone'] = laue_zone + + ZOLZ_forbidden = abs(np.floor(g_forbidden[:, 2]*length_zone_axis+0.5)) == 0 + + dif['forbidden']['Laue_Zone'] = ZOLZ_forbidden + ZOLZ = laue_zone == 0 + FOLZ = laue_zone == 1 + SOLZ = laue_zone == 2 + HOLZ = laue_zone > 0 + HOLZp = laue_zone > 2 + + dif['allowed']['ZOLZ'] = ZOLZ + dif['allowed']['FOLZ'] = FOLZ + dif['allowed']['SOLZ'] = SOLZ + dif['allowed']['HOLZ'] = HOLZ + dif['allowed']['HOLZ_plus'] = dif['allowed']['HHOLZ'] = HOLZp + + if verbose: + print(' There are {0} allowed reflections in the zero order Laue Zone'.format(ZOLZ.sum())) + print(' There are {0} allowed reflections in the first order Laue Zone'.format((laue_zone == 1).sum())) + print(' There are {0} allowed reflections in the second order Laue Zone'.format((laue_zone == 2).sum())) + print(' There are {0} allowed reflections in the other higher order Laue Zones'.format((laue_zone > 2).sum())) + + if verbose == 2: + print(' hkl \t Laue zone \t Intensity (*1 and \t log) \t length \n') + for i in range(len(hkl_allowed)): + print(' {0} \t {1} \t {2:.3f} \t {3:.3f} \t {4:.3f} '.format(hkl_allowed[i], g_allowed[i], + intensities[i], np.log(intensities[i]+1), + g_norm_allowed[i])) + + # ########################## + # Dynamically Activated forbidden reflections + # ########################## + + double_diffraction = (np.sum(np.array(list(itertools.combinations(hkl_allowed[ZOLZ], 2))), axis=1)) + + dynamical_allowed = [] + still_forbidden = [] + for i, hkl in enumerate(hkl_forbidden): + if ZOLZ_forbidden[i]: + if hkl.tolist() in double_diffraction.tolist(): + dynamical_allowed.append(i) + else: + still_forbidden.append(i) + dif['forbidden']['dynamically_activated'] = dynamical_allowed + dif['forbidden']['forbidden'] = dynamical_allowed + if verbose: + print('Length of zone axis vector in real space {0} nm'.format(np.round(length_zone_axis, 3))) + print(f'There are {len(dynamical_allowed)} forbidden but dynamical activated diffraction spots:') + # print(tags['forbidden']['hkl'][dynamical_allowed]) + + # ################################### + # Calculate HOLZ and Kikuchi Lines # + # ################################### + + # Dynamic Correction + + # Equation Spence+Zuo 3.86a + gamma_1 = - 1./(2.*k_0) * (intensities / (2.*k_0*s_g_allowed)).sum() + # print('gamma_1',gamma_1) + + # Equation Spence+Zuo 3.84 + Kg = k_0 - k_0*gamma_1/(g_allowed[:, 2]+1e-15) + Kg[ZOLZ] = k_0 + + # Calculate angle between K0 and deficient cone vector + # For dynamic calculations K0 is replaced by Kg + Kg[:] = k_0 + d_theta = np.arcsin(g_norm_allowed/Kg/2.)-np.arcsin(np.abs(g_allowed[:, 2])/g_norm_allowed) + + # calculate length of distance of deficient cone to K0 in ZOLZ plane + gd_length = 2*np.sin(d_theta/2)*k_0 + + # Calculate nearest point of HOLZ and Kikuchi lines + g_closest = g_allowed.copy() + g_closest = g_closest*(gd_length/np.linalg.norm(g_closest, axis=1))[:, np.newaxis] + + g_closest[:, 2] = 0. + + # calculate and save line in Hough space coordinates (distance and theta) + slope = g_closest[:, 0]/(g_closest[:, 1]+1e-10) + distance = gd_length + theta = np.arctan2(g_allowed[:, 0], g_allowed[:, 1]) + + dif['HOLZ'] = {} + dif['HOLZ']['slope'] = slope + # a line is now given by + + dif['HOLZ']['distance'] = distance + dif['HOLZ']['theta'] = theta + + dif['HOLZ']['g_deficient'] = g_closest + dif['HOLZ']['g_excess'] = g_closest+g_allowed + + dif['HOLZ']['ZOLZ'] = ZOLZ + dif['HOLZ']['HOLZ'] = HOLZ + dif['HOLZ']['FOLZ'] = FOLZ + dif['HOLZ']['SOLZ'] = SOLZ + dif['HOLZ']['HHOLZ'] = HOLZp # even higher HOLZ + + dif['HOLZ']['hkl'] = dif['allowed']['hkl'] + dif['HOLZ']['intensities'] = intensities + + #################################### + # Calculate HOLZ and Kikuchi Lines # + #################################### + + tags_kikuchi = tags.copy() + tags_kikuchi['mistilt_alpha'] = 0 + tags_kikuchi['mistilt_beta'] = 0 + + for i in range(1): # tags['nearest_zone_axes']['amount']): + + zone_tags = tags['nearest_zone_axes'][str(i)] + tags_kikuchi['zone_hkl'] = zone_tags['hkl'] + if verbose: + print('Calculating Kikuchi lines for zone: ', zone_tags['hkl']) + + tags_kikuchi['Laue_circle'] = laue_circle + # Rotate to nearest zone axis + rotation_matrix = get_rotation_matrix(tags_kikuchi) + + g_kikuchi_all = np.dot(g_non_rot, rotation_matrix) + + ZOLZ = abs(g_kikuchi_all[:, 2]) < .1 + + g_kikuchi = g_kikuchi_all[ZOLZ] + S = (k_0**2-np.linalg.norm(g_kikuchi - k0_vector, axis=1)**2)/(2*k_0) + reflections = abs(S) < .01 # This is now a boolean array with True for all possible reflections + g_kikuchi = g_kikuchi[reflections] + hkl_kikuchi = (hkl_all[ZOLZ])[reflections] + + structure_factors = [] + for j in range(len(g_kikuchi)): + F = 0 + for b in range(len(atoms)): + f = feq(atoms[b].symbol, np.linalg.norm(g_kikuchi[j])) + F += f * np.exp(-2 * np.pi * 1j * (g_kikuchi[j] * atoms.positions[b]).sum()) + structure_factors.append(F) + + F = np.array(structure_factors) + + allowed_kikuchi = np.absolute(F) > 0.000001 + + g_kikuchi = g_kikuchi[allowed_kikuchi] + hkl_kikuchi = hkl_kikuchi[allowed_kikuchi] + + gd2 = g_kikuchi / 2. + gd2[:, 2] = 0. + + # calculate and save line in Hough space coordinates (distance and theta) + slope2 = gd2[:, 0] / (gd2[:, 1] + 1e-20) + distance2 = np.sqrt(gd2[:, 0] * gd2[:, 0] + gd2[:, 1] * gd2[:, 1]) + theta2 = np.arctan(slope2) + + dif['Kikuchi'] = {} + dif['Kikuchi']['slope'] = slope2 + dif['Kikuchi']['distance'] = distance2 + dif['Kikuchi']['theta'] = theta2 + dif['Kikuchi']['hkl'] = hkl_kikuchi + dif['Kikuchi']['g_hkl'] = g_kikuchi + dif['Kikuchi']['g_deficient'] = gd2 + dif['Kikuchi']['min_dist'] = gd2 + laue_circle + + if verbose: + print('pyTEMlib\'s \"kinematic_scattering\" finished')
+ + +
[docs]def kinematic_scattering2(atoms, verbose=False): + """ + All kinematic scattering calculation + + Calculates Bragg spots, Kikuchi lines, excess, and deficient HOLZ lines + + Parameters + ---------- + atoms: ase.Atoms + object with crystal structure: + and with experimental parameters in info attribute: + 'acceleration_voltage_V', 'zone_hkl', 'Sg_max', 'hkl_max' + Optional parameters are: + 'mistilt', convergence_angle_mrad', and 'crystal_name' + verbose = True will give extended output of the calculation + verbose: boolean + default is False + + Returns + ------- + ato,s: + There are three sub_dictionaries in info attribute: + ['allowed'], ['forbidden'], and ['HOLZ'] + ['allowed'] and ['forbidden'] dictionaries contain: + ['Sg'], ['hkl'], ['g'], ['structure factor'], ['intensities'], + ['ZOLZ'], ['FOLZ'], ['SOLZ'], ['HOLZ'], ['HHOLZ'], ['label'], and ['Laue_zone'] + the ['HOLZ'] dictionary contains: + ['slope'], ['distance'], ['theta'], ['g_deficient'], ['g_excess'], ['hkl'], ['intensities'], + ['ZOLZ'], ['FOLZ'], ['SOLZ'], ['HOLZ'], and ['HHOLZ'] + Please note that the Kikuchi lines are the HOLZ lines of ZOLZ + + There are also a few parameters stored in the main dictionary: + ['wave_length_nm'], ['reciprocal_unit_cell'], ['inner_potential_V'], ['incident_wave_vector'], + ['volume'], ['theta'], ['phi'], and ['incident_wave_vector_vacuum'] + """ + + # Check sanity + if atoms.info is None: + atoms.info = {'output': {}, 'experimental': {}} + elif 'output' in atoms.info: + output = atoms.info['output'] + else: + output = atoms.info['output'] = {} + + output['SpotPattern'] = True + + if 'experimental' not in atoms.info: + tags = atoms.info['experimental'] = {} + + if not check_sanity(atoms): + print('Input is not complete, stopping') + print('Try \'example()\' for example input') + return + + tags = atoms.info['experimental'] + + # wavelength + tags['wave_length'] = get_wavelength(tags['acceleration_voltage_V']) + + # volume of unit_cell + unit_cell = atoms.cell.array + metric_tensor = get_metric_tensor(unit_cell) # converts hkl to g vectors and back + tags['metric_tensor'] = metric_tensor + volume_unit_cell = atoms.cell.volume + + # reciprocal_unit_cell + + # We use the linear algebra package of numpy to invert the unit_cell "matrix" + reciprocal_unit_cell = atoms.cell.reciprocal() # np.linalg.inv(unit_cell).T # transposed of inverted unit_cell + tags['reciprocal_unit_cell'] = reciprocal_unit_cell + inverse_metric_tensor = get_metric_tensor(reciprocal_unit_cell) + + if verbose: + print('reciprocal_unit_cell') + print(np.round(reciprocal_unit_cell, 3)) + + ############################################ + # Incident wave vector k0 in vacuum and material + ############################################ + + u0 = 0.0 # in (Ang) + # atom form factor of zero reflection angle is the inner potential in 1/A + for i in range(len(atoms)): + u0 += feq(atoms[i].symbol, 0.0) + + scattering_factor_to_volts = (const.h ** 2) * (1e10 ** 2) / (2 * np.pi * const.m_e * const.e) * volume_unit_cell + + tags['inner_potential_V'] = u0 * scattering_factor_to_volts + if verbose: + print(f'The inner potential is {u0:.1f} V') + + # Calculating incident wave vector magnitude 'k0' in material + wl = tags['wave_length'] + tags['incident_wave_vector_vacuum'] = 1 / wl + + k0 = tags['incident_wave_vector'] = np.sqrt(1 / wl**2 + u0) # 1/Ang + + tags['convergence_angle_A-1'] = k0 * np.sin(tags['convergence_angle_mrad'] / 1000.) + if verbose: + print(f"Using an acceleration voltage of {tags['acceleration_voltage_V']/1000:.1f}kV") + print(f'Magnitude of incident wave vector in material: {k0:.1f} 1/Ang and in vacuum: {1/wl:.1f} 1/Ang') + print(f"Which is an wave length of {1 / k0 * 100.:.3f} pm in the material and {wl * 100.:.3f} pm " + f"in the vacuum") + print(f"The convergence angle of {tags['convergence_angle_mrad']:.1f}mrad " + f"= {tags['convergence_angle_A-1']:.2f} 1/A") + print(f"Magnitude of incident wave vector in material: {k0:.1f} 1/A which is a wavelength {100/k0:.3f} pm") + + # ############ + # Rotate + # ############ + + # get rotation matrix to rotate zone axis onto z-axis + rotation_matrix = get_rotation_matrix(tags) + + if verbose: + print(f"Rotation alpha {np.rad2deg(tags['y-axis rotation alpha']):.1f} degree, " + f" beta {np.rad2deg(tags['x-axis rotation beta']):.1f} degree") + print(f"from zone axis {tags['zone_hkl']}") + print(f"Tilting {1} by {np.rad2deg(tags['mistilt_alpha']):.2f} " + f" in alpha and {np.rad2deg(tags['mistilt_beta']):.2f} in beta direction results in :") + # list(tags['zone_hkl']) + # + # print(f"zone axis {list(tags['nearest_zone_axis'])} with a mistilt of " + # f"{np.rad2deg(tags['mistilt_nearest_zone alpha']):.2f} in alpha " + # f"and {np.rad2deg(tags['mistilt_nearest_zone beta']):.2f} in beta direction") + nearest = tags['nearest_zone_axes'] + print('Next nearest zone axes are:') + for i in range(1, nearest['amount']): + print(f"{nearest[str(i)]['hkl']}: mistilt: {np.rad2deg(nearest[str(i)]['mistilt_alpha']):6.2f}, " + f"{np.rad2deg(nearest[str(i)]['mistilt_beta']):6.2f}") + k0_unit_vector = np.array([0, 0, 1]) # incident unit wave vector + k0_vector = k0_unit_vector * k0 # incident wave vector + cent = k0_vector # center of Ewald sphere + + if verbose: + print('Center of Ewald sphere ', cent) + + # Find all Miller indices whose reciprocal point lays near the Ewald sphere with radius k0 + # within a maximum excitation error Sg + hkl_max = tags['hkl_max'] + Sg_max = tags['Sg_max'] # 1/A maximum allowed excitation error + + h = np.linspace(-hkl_max, hkl_max, 2 * hkl_max + 1) # all evaluated single Miller indices + hkl = np.array(list(itertools.product(h, h, h))) # all evaluated Miller indices + g_non_rot = np.dot(hkl, reciprocal_unit_cell) # all evaluated reciprocal_unit_cell points + + g = np.dot(g_non_rot, rotation_matrix) # rotate these reciprocal_unit_cell points + g_norm = vector_norm(g) # length of all vectors + not_zero = g_norm > 0 + g = g[not_zero] # zero reflection will make problems further on, so we exclude it. + g_non_rot = g_non_rot[not_zero] + g_norm = g_norm[not_zero] + hkl = hkl[not_zero] + + # Calculate excitation errors for all reciprocal_unit_cell points + # Zuo and Spence, 'Adv TEM', 2017 -- Eq 3:14 + S = (k0 ** 2 - vector_norm(g - cent) ** 2) / (2 * k0) + g_mz = g - k0_vector + in_sqrt = g_mz[:, 2]**2 + np.linalg.norm(g_mz, axis=1)**2 - k0**2 + in_sqrt[in_sqrt < 0] = 0. + S2 = -g_mz[:, 2] - np.sqrt(in_sqrt) + + # Determine reciprocal_unit_cell points with excitation error less than the maximum allowed one: Sg_max + + reflections = abs(S) < Sg_max # This is now a boolean array with True for all possible reflections + hkl_all = hkl.copy() + s_g = S[reflections] + g_hkl = g[reflections] + + hkl = hkl[reflections] + g_hkl_non_rot = g_non_rot[reflections] + g_norm = g_norm[reflections] + + if verbose: + print(f"Of the {len(g)} tested reciprocal_unit_cell points, {len(g_hkl)} " + f"have an excitation error less than {Sg_max:.2f} 1/Angstrom") + + # Calculate Structure Factors + base = atoms.positions + structure_factors = [] + for j in range(len(g_hkl)): + F = 0 + for b in range(len(atoms)): + f = feq(atoms[b].symbol, np.linalg.norm(g_hkl[j])) + F += f * np.exp(-2 * np.pi * 1j * (g_hkl_non_rot[j] * atoms.positions[b]).sum()) + + structure_factors.append(F) + + F = structure_factors = np.array(structure_factors) + + # Sort reflection in allowed and forbidden # + allowed = np.absolute(F) > 0.000001 # allowed within numerical error + + if verbose: + print(f"Of the {hkl.shape[0]} possible reflection {allowed.sum()} are allowed.") + + # information of allowed reflections + s_g_allowed = s_g[allowed] + hkl_allowed = hkl[allowed][:] + g_allowed = g_hkl[allowed, :] + F_allowed = F[allowed] + g_norm_allowed = g_norm[allowed] + + atoms.info['diffraction'] = {} + dif = atoms.info['diffraction'] + dif['allowed'] = {} + dif['allowed']['Sg'] = s_g_allowed + dif['allowed']['hkl'] = hkl_allowed + dif['allowed']['g'] = g_allowed + dif['allowed']['structure factor'] = F_allowed + + # Calculate Extinction Distance Reimer 7.23 + # - makes only sense for non-zero F + + xi_g = np.real(np.pi * volume_unit_cell * k0 / F_allowed) + + # Calculate Intensity of beams Reimer 7.25 + if 'thickness' not in tags: + tags['thickness'] = 0. + thickness = tags['thickness'] + if thickness > 0.1: + I_g = np.real(np.pi ** 2 / xi_g ** 2 * np.sin(np.pi * thickness * s_g_allowed) ** 2 / (np.pi * s_g_allowed)**2) + dif['allowed']['Ig'] = I_g + + dif['allowed']['intensities'] = intensities = np.real(F_allowed) ** 2 + + # information of forbidden reflections + forbidden = np.logical_not(allowed) + s_g_forbidden = s_g[forbidden] + hkl_forbidden = hkl[forbidden] + g_forbidden = g_hkl[forbidden] + F_forbidden = F[forbidden] + + dif['forbidden'] = {} + dif['forbidden']['Sg'] = s_g_forbidden + dif['forbidden']['hkl'] = hkl_forbidden.copy() + dif['forbidden']['g'] = g_forbidden + + # Make pretty labels + hkl_label = make_pretty_labels(hkl_allowed) + dif['allowed']['label'] = hkl_label + hkl_label = make_pretty_labels(hkl_forbidden) + dif['forbidden']['label'] = hkl_label + + # Dynamically Allowed Reflection + """ + indices = range(len(hkl_allowed)) + combinations = [list(x) for x in itertools.permutations(indices, 2)] + hkl_forbidden = hkl_forbidden.tolist() + dynamically_allowed = np.zeros(len(hkl_forbidden), dtype=bool) + for [i, j] in combinations: + possible = (hkl_allowed[i] + hkl_allowed[j]).tolist() + if possible in hkl_forbidden: + dynamically + _allowed[hkl_forbidden.index(possible)] = True + dif['forbidden']['dynamically_allowed'] = dynamically_allowed + + if verbose: + print(f"Of the {g_forbidden.shape[0]} forbidden reflection {dif['dynamically_allowed']['g'].shape[0]} " + f"can be dynamically activated.") + # print(dif['forbidden']['hkl'][dynamically_allowed]) + """ + + # Center of Laue Circle + laue_circle = np.dot(tags['nearest_zone_axis'], tags['reciprocal_unit_cell']) + laue_circle = np.dot(laue_circle, rotation_matrix) + laue_circle = laue_circle / np.linalg.norm(laue_circle) * k0 + laue_circle[2] = 0 + + dif['Laue_circle'] = laue_circle + if verbose: + print('Laue_circle', laue_circle) + + # ########################### + # Calculate Laue Zones (of allowed reflections) + # ########################### + # Below is the expression given in most books. + # However, that would only work for orthogonal crystal systems + # Laue_Zone = abs(np.dot(hkl_allowed,tags['zone_hkl'])) # works only for orthogonal systems + + # This expression works for all crystal systems + # Remember we have already tilted, and so the dot product is trivial and gives only the z-component. + + Laue_Zone = abs(np.dot(hkl_allowed, tags['nearest_zone_axis'])) + dif['allowed']['Laue_Zone'] = Laue_Zone + + ZOLZ = Laue_Zone == 0 + FOLZ = Laue_Zone == 1 + SOLZ = Laue_Zone == 2 + HOLZ = Laue_Zone > 2 + + dif['allowed']['ZOLZ'] = ZOLZ + dif['allowed']['FOLZ'] = FOLZ + dif['allowed']['SOLZ'] = SOLZ + dif['allowed']['HOLZ'] = HOLZ + + if verbose: + print(' There are {0} allowed reflections in the zero order Laue Zone'.format(ZOLZ.sum())) + print(' There are {0} allowed reflections in the first order Laue Zone'.format((Laue_Zone == 1).sum())) + print(' There are {0} allowed reflections in the second order Laue Zone'.format((Laue_Zone == 2).sum())) + print(' There are {0} allowed reflections in the higher order Laue Zone'.format((Laue_Zone > 2).sum())) + + if verbose: + print(' hkl \t Laue zone \t Intensity (*1 and \t log) \t length \n') + for i in range(len(hkl_allowed)): + print(' {0} \t {1} \t {2:.3f} \t {3:.3f} \t {4:.3f} '.format(hkl_allowed[i], + g_allowed[i], intensities[i], + np.log(intensities[i] + 1), + g_norm_allowed[i])) + + #################################### + # Calculate HOLZ and Kikuchi Lines # + #################################### + + tags_new_zone = tags.copy() + tags_new_zone['mistilt_alpha'] = 0 + tags_new_zone['mistilt_beta'] = 0 + + for i in range(1): # tags['nearest_zone_axes']['amount']): + + zone_tags = tags['nearest_zone_axes'][str(i)] + + if verbose: + print('Calculating Kikuchi lines for zone: ', zone_tags['hkl']) + + laue_circle = np.dot(zone_tags['hkl'], tags['reciprocal_unit_cell']) + laue_circle = np.dot(laue_circle, rotation_matrix) + laue_circle = laue_circle / np.linalg.norm(laue_circle) * k0 + laue_circle[2] = 0 + + zone_tags['Laue_circle'] = laue_circle + # Rotate to nearest zone axis + + tags_new_zone['zone_hkl'] + + theta = -(zone_tags['mistilt_alpha']) + phi = -(zone_tags['mistilt_beta']) + + # first we rotate phi about z-axis + c, s = np.cos(phi), np.sin(phi) + rot_z = np.array([[1, 0, 0], [0, c, -s], [0, s, c]]) + + # second we rotate theta about y-axis + c, s = np.cos(theta), np.sin(theta) + rot_y = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]]) + + # the rotation now makes z-axis coincide with plane normal + + rotation_matrix2 = np.dot(rot_z, rot_y) + + g_kikuchi_all = np.dot(g, rotation_matrix2) + ZOLZ = abs(g_kikuchi_all[:, 2]) < 1 + + g_kikuchi = g_kikuchi_all[ZOLZ] + S = (k0 ** 2 - vector_norm(g_kikuchi - np.array([0, 0, k0])) ** 2) / (2 * k0) + reflections = abs(S) < 0.1 # This is now a boolean array with True for all possible reflections + g_hkl_kikuchi2 = g_kikuchi[reflections] + hkl_kikuchi2 = (hkl_all[ZOLZ])[reflections] + + structure_factors = [] + for j in range(len(g_hkl_kikuchi2)): + F = 0 + for b in range(len(atoms)): + f = feq(atoms[b].symbol, np.linalg.norm(g_hkl_kikuchi2[j])) + F += f * np.exp(-2 * np.pi * 1j * (g_hkl_kikuchi2[j] * atoms.positions[b]).sum()) + + structure_factors.append(F) + + F = np.array(structure_factors) + + allowed_kikuchi = np.absolute(F) > 0.000001 + + g_hkl_kikuchi = g_hkl_kikuchi2[allowed_kikuchi] + hkl_kikuchi = hkl_kikuchi2[allowed_kikuchi] + + gd2 = g_hkl_kikuchi / 2. + gd2[:, 2] = 0. + + # calculate and save line in Hough space coordinates (distance and theta) + slope2 = gd2[:, 0] / (gd2[:, 1] + 1e-20) + distance2 = np.sqrt(gd2[:, 0] * gd2[:, 0] + gd2[:, 1] * gd2[:, 1]) + theta2 = np.arctan(slope2) + + dif['Kikuchi'] = {} + dif['Kikuchi']['slope'] = slope2 + dif['Kikuchi']['distance'] = distance2 + dif['Kikuchi']['theta'] = theta2 + dif['Kikuchi']['hkl'] = hkl_kikuchi + dif['Kikuchi']['g_hkl'] = g_hkl_kikuchi + dif['Kikuchi']['g_deficient'] = gd2 + dif['Kikuchi']['min dist'] = gd2 + laue_circle + + k_g = k0 + + # Dynamic Correction + # Does not correct ZOLZ lines !!!! + # Equation Spence+Zuo 3.86a + if 'dynamic correction' in tags: + if tags['dynamic correction']: + gamma_1 = - 1. / (2. * k0) * (intensities / (2. * k0 * s_g_allowed)).sum() + if verbose: + print('Dynamic correction gamma_1: ', gamma_1) + + # Equation Spence+Zuo 3.84 + k_g = k0 - k0 * gamma_1 / g_allowed[:, 2] + + # k_g = np.dot( [0,0,k0], rotation_matrix) + # Calculate angle between k0 and deficient cone vector + # For dynamic calculations k0 is replaced by k_g + d_theta = np.arcsin(g_norm_allowed / k_g / 2.) - np.arcsin(np.abs(g_allowed[:, 2]) / g_norm_allowed) + + # calculate length of distance of deficient cone to k0 in ZOLZ plane + gd_length = 2 * np.sin(d_theta / 2) * k0 + + # Calculate nearest point of HOLZ and Kikuchi lines + gd = g_allowed.copy() + gd[:, 0] = -gd[:, 0] * gd_length / g_norm_allowed + gd[:, 1] = -gd[:, 1] * gd_length / g_norm_allowed + gd[:, 2] = 0. + + # calculate and save line in Hough space coordinates (distance and theta) + slope = gd[:, 0] / (gd[:, 1] + 1e-20) + distance = gd_length + theta = np.arctan(slope) + + dif['HOLZ'] = {} + dif['HOLZ']['slope'] = slope + # a line is now given by + dif['HOLZ']['distance'] = distance + dif['HOLZ']['theta'] = theta + dif['HOLZ']['g_deficient'] = gd + dif['HOLZ']['g_excess'] = gd + g_allowed + dif['HOLZ']['g_allowed'] = g_allowed.copy() + + dif['HOLZ']['ZOLZ'] = ZOLZ + dif['HOLZ']['HOLZ'] = np.logical_not(ZOLZ) + dif['HOLZ']['FOLZ'] = FOLZ + dif['HOLZ']['SOLZ'] = SOLZ + dif['HOLZ']['HHOLZ'] = HOLZ # even higher HOLZ + + dif['HOLZ']['hkl'] = dif['allowed']['hkl'] + dif['HOLZ']['intensities'] = intensities + + print('done')
+ + +
[docs]def make_pretty_labels(hkls, hex_label=False): + """Make pretty labels + + Parameters + ---------- + hkls: np.ndarray + a numpy array with all the Miller indices to be labeled + hex_label: boolean - optional + if True this will make for Miller indices. + + Returns + ------- + hkl_label: list + list of labels in Latex format + """ + hkl_label = [] + for i in range(len(hkls)): + h, k, l = np.array(hkls)[i] + + if h < 0: + h_string = r'[$\bar {' + str(int(-h)) + '},' + else: + h_string = r'[$\bar {' + str(int(h)) + '},' + if k < 0: + k_string = r'\bar {' + str(int(-k)) + '},' + else: + k_string = str(int(k)) + ',' + if hex_label: + ii = -(h + k) + if ii < 0: + k_string = k_string + r'\bar {' + str(int(-ii)) + '},' + else: + k_string = k_string + str(int(ii)) + ',' + if l < 0: + l_string = r'\bar {' + str(int(-l)) + '} $]' + else: + l_string = str(int(l)) + '} $]' + label = h_string + k_string + l_string + hkl_label.append(label) + return hkl_label
+ + +
[docs]def feq(element, q): + """Atomic form factor parametrized in 1/Angstrom but converted to 1/Angstrom + + The atomic form factor is from Kirkland: Advanced Computing in Electron Microscopy 2nd edition, Appendix C. + From Appendix C of Kirkland, "Advanced Computing in Electron Microscopy", 3Ard ed. + Calculation of electron form factor for specific q: + Using equation Kirkland C.15 + + Parameters + ---------- + element: string + element name + q: float + magnitude of scattering vector in 1/Angstrom -- (=> exp(-i*g.r), physics negative convention) + + Returns + ------- + fL+fG: float + atomic scattering vector + """ + + if not isinstance(element, str): + raise TypeError('Element has to be a string') + if element not in electronFF: + if len(element) > 2: + raise TypeError('Please use standard convention for element abbreviation with not more than two letters') + else: + raise TypeError('Element {element} not known to electron diffraction should') + if not isinstance(q, (float, int)): + raise TypeError('Magnitude of scattering vector has to be a number of type float') + + # q is in magnitude of scattering vector in 1/A -- (=> exp(-i*g.r), physics negative convention) + param = electronFF[element] + f_lorentzian = 0 + f_gauss = 0 + for i in range(3): + f_lorentzian += param['fa'][i]/(q**2 + param['fb'][i]) + f_gauss += param['fc'][i]*np.exp(-q**2 * param['fd'][i]) + + # Conversion factor from scattering factors to volts. h^2/(2pi*m0*e), see e.g. Kirkland eqn. C.5 + # !NB RVolume is already in A unlike RPlanckConstant + # scattering_factor_to_volts=(PlanckConstant**2)*(AngstromConversion**2)/(2*np.pi*ElectronMass*ElectronCharge) + return f_lorentzian+f_gauss # * scattering_factor_to_volts
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/microscope.html b/_modules/pyTEMlib/microscope.html new file mode 100644 index 00000000..b07c57c9 --- /dev/null +++ b/_modules/pyTEMlib/microscope.html @@ -0,0 +1,176 @@ + + + + + + pyTEMlib.microscope — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.microscope

+""" default microscope parameters from config file
+
+Read microscope CSV file
+
+for pyTEMLib by Gerd
+
+copyright 2012, Gerd Duscher
+updated 2021
+"""
+# -*- coding: utf-8 -*-
+
+import csv
+import os.path
+
+from pyTEMlib.config_dir import config_path
+microscopes_file = os.path.join(config_path, 'microscopes.csv')
+
+
+
+
[docs]class Microscope(object): + """Class to read configuration file and provide microscope information""" + microscopes = {} + name = None + E0 = None + alpha = None + beta = None + pppc = None + correlation_factor = None + + def __init__(self): + self.load_microscopes() + default_tem = self.microscopes[list(self.microscopes.keys())[0]] + self.set_microscope(default_tem['Microscope']) + + def load_microscopes(self): + f = open(microscopes_file, 'r') + + labels = f.readline().strip().split(',') + # print labels + csv_read = csv.DictReader(f, labels, delimiter=",") + + for line in csv_read: + tem = line['Microscope'] + self.microscopes[tem] = line + for i in self.microscopes[tem]: + if i != 'Microscope': + self.microscopes[tem][i] = float(self.microscopes[tem][i]) + f.close() + + def get_available_microscope_names(self): + tem = [] + for scope in self.microscopes.keys(): + tem.append(scope) + return tem + + def set_microscope(self, microscope_name): + if microscope_name in self.microscopes: + self.name = microscope_name
+ + +microscope = Microscope() +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/peak_dialog.html b/_modules/pyTEMlib/peak_dialog.html new file mode 100644 index 00000000..3f89751c --- /dev/null +++ b/_modules/pyTEMlib/peak_dialog.html @@ -0,0 +1,1136 @@ + + + + + + pyTEMlib.peak_dialog — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.peak_dialog

+"""
+    EELS Input Dialog for ELNES Analysis
+"""
+from os import error
+Qt_available = True
+try:
+    from PyQt5 import QtCore,  QtWidgets
+except:
+    Qt_available = False
+    # print('Qt dialogs are not available')
+
+import numpy as np
+import scipy
+import scipy.optimize
+import scipy.signal
+
+import ipywidgets
+from IPython.display import display
+import matplotlib
+import matplotlib.pylab as plt
+import matplotlib.patches as patches
+
+import sidpy
+import pyTEMlib.file_tools as ft
+from pyTEMlib import  eels_tools
+from pyTEMlib import peak_dlg
+from pyTEMlib import eels_dialog_utilities
+
+advanced_present = True
+try:
+    import advanced_eels_tools
+    print('advanced EELS features enabled')
+except ModuleNotFoundError:
+    advanced_present = False
+
+_version = .001
+
+
[docs]def get_sidebar(): + side_bar = ipywidgets.GridspecLayout(16, 3, width='auto', grid_gap="0px") + row = 0 + side_bar[row, :3] = ipywidgets.Button(description='Fit Area', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=7.5,description='Fit Start:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='20px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Fit End:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='20px')) + + row += 1 + side_bar[row, :3] = ipywidgets.Button(description='Peak Finding', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + + row += 1 + + + side_bar[row, :2] = ipywidgets.Dropdown( + options=[('0', 0), ('1', 1), ('2', 2), ('3', 3), ('4', 4)], + value=0, + description='Peaks:', + disabled=False, + layout=ipywidgets.Layout(width='200px')) + + side_bar[row, 2] = ipywidgets.Button( + description='Smooth', + disabled=False, + button_style='', # 'success', 'info', 'warning', 'danger' or '' + tooltip='Do Gaussian Mixing', + layout=ipywidgets.Layout(width='100px')) + + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Number:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.Button( + description='Find', + disabled=False, + button_style='', # 'success', 'info', 'warning', 'danger' or '' + tooltip='Find first peaks from Gaussian mixture', + layout=ipywidgets.Layout(width='100px')) + + row += 1 + + side_bar[row, :3] = ipywidgets.Button(description='Peaks', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + row += 1 + side_bar[row, :2] = ipywidgets.Dropdown( + options=[('Peak 1', 0), ('Add Peak', -1)], + value=0, + description='Peaks:', + disabled=False, + layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.Dropdown( + options=[ 'Gauss', 'Lorentzian', 'Drude', 'Zero-Loss'], + value='Gauss', + description='Symmetry:', + disabled=False, + layout=ipywidgets.Layout(width='200px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Position:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Amplitude:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Width FWHM:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="eV", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.FloatText(value=0.1, description='Asymmetry:', disabled=False, color='black', layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value="a.u.", layout=ipywidgets.Layout(width='100px')) + row += 1 + + side_bar[row, :3] = ipywidgets.Button(description='White-Line', + layout=ipywidgets.Layout(width='auto', grid_area='header'), + style=ipywidgets.ButtonStyle(button_color='lightblue')) + + row += 1 + side_bar[row, :2] = ipywidgets.Dropdown( + options=[('None', 0)], + value=0, + description='Ratio:', + disabled=False, + layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value=" ", layout=ipywidgets.Layout(width='100px')) + row += 1 + side_bar[row, :2] = ipywidgets.Dropdown( + options=[('None', 0)], + value=0, + description= 'Sum:', + disabled=False, + layout=ipywidgets.Layout(width='200px')) + side_bar[row, 2] = ipywidgets.widgets.Label(value=" ", layout=ipywidgets.Layout(width='100px')) + return side_bar
+ +
[docs]class PeakFitWidget(object): + def __init__(self, datasets=None): + self.datasets = datasets + if not isinstance(datasets, dict): + raise TypeError('need dictioary of sidpy datasets') + + self.sidebar = get_sidebar() + self.key = list(self.datasets)[0] + self.dataset = datasets[self.key] + if not isinstance(self.dataset, sidpy.Dataset): + raise TypeError('dataset or first item inhas to be a sidpy dataset') + + self.model = np.array([]) + self.y_scale = 1.0 + self.change_y_scale = 1.0 + self.spectrum_ll = None + self.low_loss_key = None + + self.peaks = {} + + self.show_regions = False + + self.set_dataset() + + self.app_layout = ipywidgets.AppLayout( + left_sidebar=self.sidebar, + center=self.view.panel, + footer=None,#message_bar, + pane_heights=[0, 10, 0], + pane_widths=[4, 10, 0], + ) + display(self.app_layout) + self.set_action() + + def line_select_callback(self, x_min, x_max): + self.start_cursor.value = np.round(x_min,3) + self.end_cursor.value = np.round(x_max, 3) + self.start_channel = np.searchsorted(self.datasets[self.key].energy_loss, self.start_cursor.value) + self.end_channel = np.searchsorted(self.datasets[self.key].energy_loss, self.end_cursor.value) + + + def set_peak_list(self): + self.peak_list = [] + if 'peaks' not in self.peaks: + self.peaks['peaks'] = {} + key = 0 + for key in self.peaks['peaks']: + if key.isdigit(): + self.peak_list.append((f'Peak {int(key) + 1}', int(key))) + self.peak_list.append(('add peak', -1)) + #self.sidebar[7, 0].options = self.peak_list + #self.sidebar[7, 0].value = 0 + + + def plot(self, scale=True): + + self.view.change_y_scale = self.change_y_scale + self.view.y_scale = self.y_scale + self.energy_scale = self.dataset.energy_loss.values + + if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE: + spectrum = self.dataset.view.get_spectrum() + else: + spectrum = self.dataset + if len(self.model) > 1: + additional_spectra = {'model': self.model, + 'difference': spectrum-self.model} + else: + additional_spectra = None + if 'peaks' in self.peaks: + for index, peak in self.peaks['peaks'].items(): + p = [peak['position'], peak['amplitude'], peak['width']] + additional_spectra[f'peak {index}']= eels_tools.gauss(self.energy_scale, p) + self.view.plot(scale=True, additional_spectra=additional_spectra ) + self.change_y_scale = 1. + + self.view.figure.canvas.draw_idle() + + + def set_dataset(self, index=0): + self.spec_dim = ft.get_dimensions_by_type('spectral', self.dataset) + if len(self.spec_dim) != 1: + raise TypeError('We need exactly one SPECTRAL dimension') + self.spec_dim = self.spec_dim[0] + self.energy_scale = self.spec_dim[1] + + self.y_scale = 1.0 + self.change_y_scale = 1.0 + + if 'peak_fit' not in self.dataset.metadata: + self.dataset.metadata['peak_fit'] = {} + if 'edges' in self.dataset.metadata: + if 'fit_area' in self.dataset.metadata['edges']: + self.dataset.metadata['peak_fit']['fit_start'] = self.dataset.metadata['edges']['fit_area']['fit_start'] + self.dataset.metadata['peak_fit']['fit_end'] = self.dataset.metadata['edges']['fit_area']['fit_end'] + self.dataset.metadata['peak_fit']['peaks'] = {'0': {'position': self.energy_scale[1], + 'amplitude': 1000.0, 'width': 1.0, + 'type': 'Gauss', 'asymmetry': 0}} + + self.peaks = self.dataset.metadata['peak_fit'] + if 'fit_start' not in self.peaks: + self.peaks['fit_start'] = self.energy_scale[1] + if 'fit_end' not in self.peaks: + self.peaks['fit_end'] = self.energy_scale[-2] + + if 'peak_model' in self.peaks: + self.peak_model = self.peaks['peak_model'] + self.model = self.peak_model + if 'edge_model' in self.peaks: + self.model = self.model + self.peaks['edge_model'] + else: + self.model = np.array([]) + self.peak_model = np.array([]) + if 'peak_out_list' in self.peaks: + self.peak_out_list = self.peaks['peak_out_list'] + self.set_peak_list() + + # check whether a core loss analysis has been done previously + if not hasattr(self, 'core_loss') and 'edges' in self.dataset.metadata: + self.core_loss = True + else: + self.core_loss = False + + self.update() + if self.dataset.data_type.name =='SPECTRAL_IMAGE': + self.view = eels_dialog_utilities.SIPlot(self.dataset) + else: + self.view = eels_dialog_utilities.SpectrumPlot(self.dataset) + self.y_scale = 1.0 + self.change_y_scale = 1.0 + + def set_fit_area(self, value): + + self.peaks['fit_start'] = self.sidebar[1, 0].value + self.peaks['fit_end'] = self.sidebar[2, 0].value + + self.plot() + + def set_y_scale(self, value): + self.change_y_scale = 1/self.y_scale + if self.sidebar[12, 0].value: + dispersion = self.energy_scale[1] - self.energy_scale[0] + self.y_scale = 1/self.dataset.metadata['experiment']['flux_ppm'] * dispersion + else: + self.y_scale = 1.0 + + self.change_y_scale *= self.y_scale + self.update() + self.plot() + + def update(self, index=0): + + # self.setWindowTitle('update') + self.sidebar[1, 0].value = self.peaks['fit_start'] + self.sidebar[2, 0].value = self.peaks['fit_end'] + + peak_index = self.sidebar[7, 0].value + self.peak_index = self.sidebar[7, 0].value + if str(peak_index) not in self.peaks['peaks']: + self.peaks['peaks'][str(peak_index)] = {'position': self.energy_scale[1], 'amplitude': 1000.0, + 'width': 1.0, 'type': 'Gauss', 'asymmetry': 0} + self.sidebar[8, 0].value = self.peaks['peaks'][str(peak_index)]['type'] + if 'associated_edge' in self.peaks['peaks'][str(peak_index)]: + self.sidebar[7, 2].value = (self.peaks['peaks'][str(peak_index)]['associated_edge']) + else: + self.sidebar[7, 2].value = '' + self.sidebar[9, 0].value = self.peaks['peaks'][str(peak_index)]['position'] + self.sidebar[10, 0].value = self.peaks['peaks'][str(peak_index)]['amplitude'] + self.sidebar[11, 0].value = self.peaks['peaks'][str(peak_index)]['width'] + if 'asymmetry' not in self.peaks['peaks'][str(peak_index)]: + self.peaks['peaks'][str(peak_index)]['asymmetry'] = 0. + self.sidebar[12, 0].value = self.peaks['peaks'][str(peak_index)]['asymmetry'] + + +
[docs] def fit_peaks(self, value = 0): + """Fit spectrum with peaks given in peaks dictionary""" + # print('Fitting peaks...') + p_in = [] + for key, peak in self.peaks['peaks'].items(): + if key.isdigit(): + p_in.append(peak['position']) + p_in.append(peak['amplitude']) + p_in.append(peak['width']) + + spectrum = np.array(self.dataset) + + # set the energy scale and fit start and end points + energy_scale = np.array(self.energy_scale) + start_channel = np.searchsorted(energy_scale, self.peaks['fit_start']) + end_channel = np.searchsorted(energy_scale, self.peaks['fit_end']) + + energy_scale = self.energy_scale[start_channel:end_channel] + # select the core loss model if it exists. Otherwise, we will fit to the full spectrum. + if 'model' in self.dataset.metadata: + model = self.dataset.metadata['model'][start_channel:end_channel] + elif self.core_loss: + # print('Core loss model found. Fitting on top of the model.') + model = self.dataset.metadata['edges']['model']['spectrum'][start_channel:end_channel] + else: + # print('No core loss model found. Fitting to the full spectrum.') + model = np.zeros(end_channel - start_channel) + + # if we have a core loss model we will only fit the difference between the model and the data. + difference = np.array(spectrum[start_channel:end_channel] - model) + + # find the optimum fitting parameters + [self.p_out, _] = scipy.optimize.leastsq(eels_tools.residuals_smooth, np.array(p_in), ftol=1e-3, + args=(energy_scale, difference, False)) + + # construct the fit data from the optimized parameters + self.peak_model = np.zeros(len(self.energy_scale)) + self.model = np.zeros(len(self.energy_scale)) + self.model[start_channel:end_channel] = model + fit = eels_tools.model_smooth(energy_scale, self.p_out, False) + self.peak_model[start_channel:end_channel] = fit + self.dataset.metadata['peak_fit']['edge_model'] = self.model + self.model = self.model + self.peak_model + self.dataset.metadata['peak_fit']['peak_model'] = self.peak_model + + for key, peak in self.peaks['peaks'].items(): + if key.isdigit(): + p_index = int(key)*3 + self.peaks['peaks'][key] = {'position': self.p_out[p_index], + 'amplitude': self.p_out[p_index+1], + 'width': self.p_out[p_index+2], + 'type': 'Gauss', + 'associated_edge': ''} + + eels_tools.find_associated_edges(self.dataset) + self.find_white_lines() + self.update() + self.plot()
+ + + + def find_white_lines(self): + eels_tools.find_white_lines(self.dataset) + + self.wl_list = [] + self.wls_list = [] + if len(self.dataset.metadata['peak_fit']['white_line_ratios']) > 0: + for key in self.dataset.metadata['peak_fit']['white_line_ratios']: + self.wl_list.append(key) + for key in self.dataset.metadata['peak_fit']['white_line_sums']: + self.wls_list.append(key) + + self.sidebar[14, 0].options = self.wl_list + self.sidebar[14, 0].value = self.wl_list[0] + self.sidebar[14, 2].value = f"{self.dataset.metadata['peak_fit']['white_line_ratios'][self.wl_list[0]]:.2f}" + + self.sidebar[15, 0].options = self.wls_list + self.sidebar[15, 0].value = self.wls_list[0] + self.sidebar[15, 2].value = f"{self.dataset.metadata['peak_fit']['white_line_sums'][self.wls_list[0]]*1e6:.4f} ppm" + + else: + self.wl_list.append('Ratio') + self.wls_list.append('Sum') + + self.sidebar[14, 0].options = ['None'] + self.sidebar[14, 0].value = 'None' + self.sidebar[14, 2].value = ' ' + + self.sidebar[15, 0].options = ['None'] + self.sidebar[15, 0].value = 'None' + self.sidebar[15, 2].value = ' ' + + def find_peaks(self, value=0): + number_of_peaks = int(self.sidebar[5, 0].value) + + self.peak_list = [] + self.peaks['peaks'] = {} + for i in range(number_of_peaks): + self.peak_list.append((f'Peak {i+1}', i)) + p = self.peak_out_list[i] + self.peaks['peaks'][str(i)] = {'position': p[0], 'amplitude': p[1], 'width': p[2], 'type': 'Gauss', + 'asymmetry': 0} + + self.peak_list.append((f'add peak', -1)) + + self.sidebar[7, 0].options = self.peak_list + self.sidebar[7, 0].value = 0 + eels_tools.find_associated_edges(self.dataset) + self.find_white_lines() + + self.update() + self.plot() + +
[docs] def smooth(self, value=0): + """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. + + """ + iterations = self.sidebar[4, 0].value + self.sidebar[5, 0].value = 0 + advanced_present=False + + self.peak_model, self.peak_out_list, number_of_peaks = smooth(self.dataset, iterations, advanced_present) + + spec_dim = ft.get_dimensions_by_type('SPECTRAL', self.dataset)[0] + if spec_dim[1][0] > 0: + self.model = self.dataset.metadata['edges']['model']['spectrum'] + elif 'model' in self.dataset.metadata: + self.model = self.dataset.metadata['model'] + else: + self.model = np.zeros(len(spec_dim[1])) + + self.dataset.metadata['peak_fit']['edge_model'] = self.model + self.model = self.model + self.peak_model + self.dataset.metadata['peak_fit']['peak_model'] = self.peak_model + self.dataset.metadata['peak_fit']['peak_out_list'] = self.peak_out_list + + self.sidebar[5, 0].value = number_of_peaks + self.update() + self.plot()
+ + def make_model(self): + p_peaks = [] + for key, peak in self.peaks['peaks'].items(): + if key.isdigit(): + p_peaks.append(peak['position']) + p_peaks.append(peak['amplitude']) + p_peaks.append(peak['width']) + + + # set the energy scale and fit start and end points + energy_scale = np.array(self.energy_scale) + start_channel = np.searchsorted(energy_scale, self.peaks['fit_start']) + end_channel = np.searchsorted(energy_scale, self.peaks['fit_end']) + energy_scale = self.energy_scale[start_channel:end_channel] + # select the core loss model if it exists. Otherwise, we will fit to the full spectrum. + + fit = eels_tools.model_smooth(energy_scale, p_peaks, False) + self.peak_model[start_channel:end_channel] = fit + if 'edge_model' in self.dataset.metadata['peak_fit']: + self.model = self.dataset.metadata['peak_fit']['edge_model'] + self.peak_model + else: + self.model = np.zeros(self.dataset.shape) + + def modify_peak_position(self, value=-1): + peak_index = self.sidebar[7, 0].value + self.peaks['peaks'][str(peak_index)]['position'] = self.sidebar[9,0].value + self.make_model() + self.plot() + + def modify_peak_amplitude(self, value=-1): + peak_index = self.sidebar[7, 0].value + self.peaks['peaks'][str(peak_index)]['amplitude'] = self.sidebar[10,0].value + self.make_model() + self.plot() + + def modify_peak_width(self, value=-1): + peak_index = self.sidebar[7, 0].value + self.peaks['peaks'][str(peak_index)]['width'] = self.sidebar[11,0].value + self.make_model() + self.plot() + + def set_action(self): + self.sidebar[1, 0].observe(self.set_fit_area, names='value') + self.sidebar[2, 0].observe(self.set_fit_area, names='value') + + self.sidebar[4, 2].on_click(self.smooth) + self.sidebar[7,0].observe(self.update) + self.sidebar[5,2].on_click(self.find_peaks) + + self.sidebar[6, 0].on_click(self.fit_peaks) + self.sidebar[9, 0].observe(self.modify_peak_position, names='value') + self.sidebar[10, 0].observe(self.modify_peak_amplitude, names='value') + self.sidebar[11, 0].observe(self.modify_peak_width, names='value')
+ + + + +if Qt_available: + class PeakFitDialog(QtWidgets.QDialog): + """ + EELS Input Dialog for ELNES Analysis + """ + + def __init__(self, datasets=None): + super().__init__(None, QtCore.Qt.WindowStaysOnTopHint) + + if datasets is None: + # make a dummy dataset + datasets = ft.make_dummy_dataset('spectrum') + if not isinstance(datasets, dict): + datasets= {'Channel_000': datasets} + + self.dataset = datasets[list(datasets.keys())[0]] + self.datasets = datasets + # Create an instance of the GUI + if 'low_loss' in self.dataset.metadata: + mode = 'low_loss' + else: + mode = 'core_loss' + + self.ui = peak_dlg.UiDialog(self, mode=mode) + + self.set_action() + + self.energy_scale = np.array([]) + self.peak_out_list = [] + self.p_out = [] + self.axis = None + self.show_regions = False + self.show() + + + + if not isinstance(self.dataset, sidpy.Dataset): + raise TypeError('dataset has to be a sidpy dataset') + self.spec_dim = ft.get_dimensions_by_type('spectral', self.dataset) + if len(self.spec_dim) != 1: + raise TypeError('We need exactly one SPECTRAL dimension') + self.spec_dim = self.spec_dim[0] + self.energy_scale = self.spec_dim[1].values.copy() + + if 'peak_fit' not in self.dataset.metadata: + self.dataset.metadata['peak_fit'] = {} + if 'edges' in self.dataset.metadata: + if 'fit_area' in self.dataset.metadata['edges']: + self.dataset.metadata['peak_fit']['fit_start'] = \ + self.dataset.metadata['edges']['fit_area']['fit_start'] + self.dataset.metadata['peak_fit']['fit_end'] = self.dataset.metadata['edges']['fit_area']['fit_end'] + self.dataset.metadata['peak_fit']['peaks'] = {'0': {'position': self.energy_scale[1], + 'amplitude': 1000.0, 'width': 1.0, + 'type': 'Gauss', 'asymmetry': 0}} + + + self.peaks = self.dataset.metadata['peak_fit'] + if 'fit_start' not in self.peaks: + self.peaks['fit_start'] = self.energy_scale[1] + self.peaks['fit_end'] = self.energy_scale[-2] + + if 'peak_model' in self.peaks: + self.peak_model = self.peaks['peak_model'] + self.model = self.peak_model + if 'edge_model' in self.peaks: + self.model = self.model + self.peaks['edge_model'] + else: + self.model = np.array([]) + self.peak_model = np.array([]) + if 'peak_out_list' in self.peaks: + self.peak_out_list = self.peaks['peak_out_list'] + self.set_peak_list() + + # check whether a core loss analysis has been done previously + if not hasattr(self, 'core_loss') and 'edges' in self.dataset.metadata: + self.core_loss = True + else: + self.core_loss = False + + self.update() + self.dataset.plot() + + if self.dataset.data_type.name == 'SPECTRAL_IMAGE': + if 'SI_bin_x' not in self.dataset.metadata['experiment']: + self.dataset.metadata['experiment']['SI_bin_x'] = 1 + self.dataset.metadata['experiment']['SI_bin_y'] = 1 + bin_x = self.dataset.metadata['experiment']['SI_bin_x'] + bin_y = self.dataset.metadata['experiment']['SI_bin_y'] + + self.dataset.view.set_bin([bin_x, bin_y]) + + if hasattr(self.dataset.view, 'axes'): + self.axis = self.dataset.view.axes[-1] + elif hasattr(self.dataset.view, 'axis'): + self.axis = self.dataset.view.axis + self.figure = self.axis.figure + + if not advanced_present: + self.ui.iteration_list = ['0'] + self.ui.smooth_list.clear() + self.ui.smooth_list.addItems(self.ui.iteration_list) + self.ui.smooth_list.setCurrentIndex(0) + + if 'low_loss' in self.dataset.metadata: + self.ui.iteration_list = ['0'] + + + self.figure.canvas.mpl_connect('button_press_event', self.plot) + + + self.plot() + + def update(self): + # self.setWindowTitle('update') + self.ui.edit1.setText(f"{self.peaks['fit_start']:.2f}") + self.ui.edit2.setText(f"{self.peaks['fit_end']:.2f}") + + peak_index = self.ui.list3.currentIndex() + if str(peak_index) not in self.peaks['peaks']: + self.peaks['peaks'][str(peak_index)] = {'position': self.energy_scale[1], 'amplitude': 1000.0, + 'width': 1.0, 'type': 'Gauss', 'asymmetry': 0} + self.ui.list4.setCurrentText(self.peaks['peaks'][str(peak_index)]['type']) + if 'associated_edge' in self.peaks['peaks'][str(peak_index)]: + self.ui.unit3.setText(self.peaks['peaks'][str(peak_index)]['associated_edge']) + else: + self.ui.unit3.setText('') + self.ui.edit5.setText(f"{self.peaks['peaks'][str(peak_index)]['position']:.2f}") + self.ui.edit6.setText(f"{self.peaks['peaks'][str(peak_index)]['amplitude']:.2f}") + self.ui.edit7.setText(f"{self.peaks['peaks'][str(peak_index)]['width']:.2f}") + if 'asymmetry' not in self.peaks['peaks'][str(peak_index)]: + self.peaks['peaks'][str(peak_index)]['asymmetry'] = 0. + self.ui.edit8.setText(f"{self.peaks['peaks'][str(peak_index)]['asymmetry']:.2f}") + + def plot(self): + + spec_dim = ft.get_dimensions_by_type(sidpy.DimensionType.SPECTRAL, self.dataset) + spec_dim = spec_dim[0] + self.energy_scale = spec_dim[1].values + if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE: + spectrum = self.dataset.view.get_spectrum() + self.axis = self.dataset.view.axes[1] + name = 's' + if 'zero_loss' in self.dataset.metadata: + x = self.dataset.view.x + y = self.dataset.view.y + self.energy_scale -= self.dataset.metadata['zero_loss']['shifts'][x, y] + name = f"shift { self.dataset.metadata['zero_loss']['shifts'][x, y]:.3f}" + self.setWindowTitle(f'plot {x}') + else: + spectrum = np.array(self.dataset) + self.axis = self.dataset.view.axis + + x_limit = self.axis.get_xlim() + y_limit = self.axis.get_ylim() + self.axis.clear() + + self.axis.plot(self.energy_scale, spectrum, label='spectrum') + if 'zero_loss' in self.dataset.metadata: + self.axis.plot(self.energy_scale, spectrum, label=name) + + if len(self.model) > 1: + self.axis.plot(self.energy_scale, self.model, label='model') + self.axis.plot(self.energy_scale, spectrum - self.model, label='difference') + #self.axis.plot(self.energy_scale, (spectrum - self.model) / np.sqrt(spectrum), label='Poisson') + self.axis.legend() + self.axis.set_xlim(x_limit) + self.axis.set_ylim(y_limit) + self.axis.figure.canvas.draw_idle() + + for index, peak in self.peaks['peaks'].items(): + p = [peak['position'], peak['amplitude'], peak['width']] + self.axis.plot(self.energy_scale, eels_tools.gauss(self.energy_scale, p)) + + def fit_peaks(self): + """Fit spectrum with peaks given in peaks dictionary""" + print('Fitting peaks...') + p_in = [] + for key, peak in self.peaks['peaks'].items(): + if key.isdigit(): + p_in.append(peak['position']) + p_in.append(peak['amplitude']) + p_in.append(peak['width']) + + # check whether we have a spectral image or just a single spectrum + if self.dataset.data_type == sidpy.DataType.SPECTRAL_IMAGE: + spectrum = self.dataset.view.get_spectrum() + else: + spectrum = np.array(self.dataset) + + # set the energy scale and fit start and end points + energy_scale = np.array(self.energy_scale) + start_channel = np.searchsorted(energy_scale, self.peaks['fit_start']) + end_channel = np.searchsorted(energy_scale, self.peaks['fit_end']) + + energy_scale = self.energy_scale[start_channel:end_channel] + # select the core loss model if it exists. Otherwise, we will fit to the full spectrum. + if 'model' in self.dataset.metadata: + model = self.dataset.metadata['model'][start_channel:end_channel] + elif self.core_loss: + print('Core loss model found. Fitting on top of the model.') + model = self.dataset.metadata['edges']['model']['spectrum'][start_channel:end_channel] + else: + print('No core loss model found. Fitting to the full spectrum.') + model = np.zeros(end_channel - start_channel) + + # if we have a core loss model we will only fit the difference between the model and the data. + difference = np.array(spectrum[start_channel:end_channel] - model) + + # find the optimum fitting parameters + [self.p_out, _] = scipy.optimize.leastsq(eels_tools.residuals_smooth, np.array(p_in), ftol=1e-3, + args=(energy_scale, difference, False)) + + # construct the fit data from the optimized parameters + self.peak_model = np.zeros(len(self.energy_scale)) + self.model = np.zeros(len(self.energy_scale)) + self.model[start_channel:end_channel] = model + fit = eels_tools.model_smooth(energy_scale, self.p_out, False) + self.peak_model[start_channel:end_channel] = fit + self.dataset.metadata['peak_fit']['edge_model'] = self.model + self.model = self.model + self.peak_model + self.dataset.metadata['peak_fit']['peak_model'] = self.peak_model + + for key, peak in self.peaks['peaks'].items(): + if key.isdigit(): + p_index = int(key)*3 + self.peaks['peaks'][key] = {'position': self.p_out[p_index], + 'amplitude': self.p_out[p_index+1], + 'width': self.p_out[p_index+2], + 'associated_edge': ''} + + self.find_associated_edges() + self.find_white_lines() + self.update() + self.plot() + + def smooth(self): + """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. + + """ + iterations = int(self.ui.smooth_list.currentIndex()) + + self.peak_model, self.peak_out_list, number_of_peaks = smooth(self.dataset, iterations, advanced_present) + + spec_dim = ft.get_dimensions_by_type('SPECTRAL', self.dataset)[0] + if spec_dim[1][0] > 0: + self.model = self.dataset.metadata['edges']['model']['spectrum'] + elif 'model' in self.dataset.metadata: + self.model = self.dataset.metadata['model'] + else: + self.model = np.zeros(len(spec_dim[1])) + + self.ui.find_edit.setText(str(number_of_peaks)) + + self.dataset.metadata['peak_fit']['edge_model'] = self.model + self.model = self.model + self.peak_model + self.dataset.metadata['peak_fit']['peak_model'] = self.peak_model + self.dataset.metadata['peak_fit']['peak_out_list'] = self.peak_out_list + + self.update() + self.plot() + + def find_associated_edges(self): + onsets = [] + edges = [] + if 'edges' in self.dataset.metadata: + for key, edge in self.dataset.metadata['edges'].items(): + if key.isdigit(): + element = edge['element'] + for sym in edge['all_edges']: # TODO: Could be replaced with exclude + onsets.append(edge['all_edges'][sym]['onset'] + edge['chemical_shift']) + # if 'sym' == edge['symmetry']: + edges.append([key, f"{element}-{sym}", onsets[-1]]) + for key, peak in self.peaks['peaks'].items(): + if key.isdigit(): + distance = self.energy_scale[-1] + index = -1 + for ii, onset in enumerate(onsets): + if onset < peak['position'] < onset+50: + if distance > np.abs(peak['position'] - onset): + distance = np.abs(peak['position'] - onset) # TODO: check whether absolute is good + distance_onset = peak['position'] - onset + index = ii + if index >= 0: + peak['associated_edge'] = edges[index][1] # check if more info is necessary + peak['distance_to_onset'] = distance_onset + + def find_white_lines(self): + eels_tools.find_white_lines(self.dataset) + + self.ui.wl_list = [] + self.ui.wls_list = [] + if len(self.peaks['white_line_ratios']) > 0: + for key in self.peaks['white_line_ratios']: + self.ui.wl_list.append(key) + for key in self.peaks['white_line_sums']: + self.ui.wls_list.append(key) + + self.ui.listwl.clear() + self.ui.listwl.addItems(self.ui.wl_list) + self.ui.listwl.setCurrentIndex(0) + self.ui.unitswl.setText(f"{self.peaks['white_line_ratios'][self.ui.wl_list[0]]:.2f}") + + self.ui.listwls.clear() + self.ui.listwls.addItems(self.ui.wls_list) + self.ui.listwls.setCurrentIndex(0) + self.ui.unitswls.setText(f"{self.peaks['white_line_sums'][self.ui.wls_list[0]]*1e6:.4f} ppm") + else: + self.ui.wl_list.append('Ratio') + self.ui.wls_list.append('Sum') + + self.ui.listwl.clear() + self.ui.listwl.addItems(self.ui.wl_list) + self.ui.listwl.setCurrentIndex(0) + self.ui.unitswl.setText('') + + self.ui.listwls.clear() + self.ui.listwls.addItems(self.ui.wls_list) + self.ui.listwls.setCurrentIndex(0) + self.ui.unitswls.setText('') + + def find_peaks(self): + number_of_peaks = int(str(self.ui.find_edit.displayText()).strip()) + + # is now sorted in smooth function + # flat_list = [item for sublist in self.peak_out_list for item in sublist] + # new_list = np.reshape(flat_list, [len(flat_list) // 3, 3]) + # arg_list = np.argsort(np.abs(new_list[:, 1])) + + self.ui.peak_list = [] + self.peaks['peaks'] = {} + for i in range(number_of_peaks): + self.ui.peak_list.append(f'Peak {i+1}') + p = self.peak_out_list[i] + self.peaks['peaks'][str(i)] = {'position': p[0], 'amplitude': p[1], 'width': p[2], 'type': 'Gauss', + 'asymmetry': 0} + + self.ui.peak_list.append(f'add peak') + self.ui.list3.clear() + self.ui.list3.addItems(self.ui.peak_list) + self.ui.list3.setCurrentIndex(0) + self.find_associated_edges() + self.find_white_lines() + + self.update() + self.plot() + + def set_peak_list(self): + self.ui.peak_list = [] + if 'peaks' not in self.peaks: + self.peaks['peaks'] = {} + key = 0 + for key in self.peaks['peaks']: + if key.isdigit(): + self.ui.peak_list.append(f'Peak {int(key) + 1}') + self.ui.find_edit.setText(str(int(key) + 1)) + self.ui.peak_list.append(f'add peak') + self.ui.list3.clear() + self.ui.list3.addItems(self.ui.peak_list) + self.ui.list3.setCurrentIndex(0) + + def on_enter(self): + if self.sender() == self.ui.edit1: + value = float(str(self.ui.edit1.displayText()).strip()) + if value < self.energy_scale[0]: + value = self.energy_scale[0] + if value > self.energy_scale[-5]: + value = self.energy_scale[-5] + self.peaks['fit_start'] = value + self.ui.edit1.setText(str(self.peaks['fit_start'])) + elif self.sender() == self.ui.edit2: + value = float(str(self.ui.edit2.displayText()).strip()) + if value < self.energy_scale[5]: + value = self.energy_scale[5] + if value > self.energy_scale[-1]: + value = self.energy_scale[-1] + self.peaks['fit_end'] = value + self.ui.edit2.setText(str(self.peaks['fit_end'])) + elif self.sender() == self.ui.edit5: + value = float(str(self.ui.edit5.displayText()).strip()) + peak_index = self.ui.list3.currentIndex() + self.peaks['peaks'][str(peak_index)]['position'] = value + elif self.sender() == self.ui.edit6: + value = float(str(self.ui.edit6.displayText()).strip()) + peak_index = self.ui.list3.currentIndex() + self.peaks['peaks'][str(peak_index)]['amplitude'] = value + elif self.sender() == self.ui.edit7: + value = float(str(self.ui.edit7.displayText()).strip()) + peak_index = self.ui.list3.currentIndex() + self.peaks['peaks'][str(peak_index)]['width'] = value + + def on_list_enter(self): + self.setWindowTitle(f'list {self.sender}, {self.ui.list_model}') + if self.sender() == self.ui.list3: + if self.ui.list3.currentText().lower() == 'add peak': + peak_index = self.ui.list3.currentIndex() + self.ui.list3.insertItem(peak_index, f'Peak {peak_index+1}') + self.peaks['peaks'][str(peak_index+1)] = {'position': self.energy_scale[1], + 'amplitude': 1000.0, 'width': 1.0, + 'type': 'Gauss', 'asymmetry': 0} + self.ui.list3.setCurrentIndex(peak_index) + self.update() + + elif self.sender() == self.ui.listwls or self.sender() == self.ui.listwl: + wl_index = self.sender().currentIndex() + + self.ui.listwl.setCurrentIndex(wl_index) + self.ui.unitswl.setText(f"{self.peaks['white_line_ratios'][self.ui.wl_list[wl_index]]:.2f}") + self.ui.listwls.setCurrentIndex(wl_index) + self.ui.unitswls.setText(f"{self.peaks['white_line_sums'][self.ui.wls_list[wl_index]] * 1e6:.4f} ppm") + elif self.sender() == self.ui.list_model: + self.setWindowTitle('list 1') + if self.sender().currentIndex() == 1: + if 'resolution_function' in self.datasets: + self.setWindowTitle('list 2') + self.dataset.metadata['model'] = np.array(self.datasets['resolution_function']) + else: + self.ui.list_model.setCurrentIndex(0) + else: + self.ui.list_model.setCurrentIndex(0) + def set_action(self): + pass + self.ui.edit1.editingFinished.connect(self.on_enter) + self.ui.edit2.editingFinished.connect(self.on_enter) + self.ui.edit5.editingFinished.connect(self.on_enter) + self.ui.edit6.editingFinished.connect(self.on_enter) + self.ui.edit7.editingFinished.connect(self.on_enter) + self.ui.edit8.editingFinished.connect(self.on_enter) + self.ui.list3.activated[str].connect(self.on_list_enter) + self.ui.find_button.clicked.connect(self.find_peaks) + self.ui.smooth_button.clicked.connect(self.smooth) + self.ui.fit_button.clicked.connect(self.fit_peaks) + if hasattr(self.ui, 'listwls'): + self.ui.listwls.activated[str].connect(self.on_list_enter) + self.ui.listwl.activated[str].connect(self.on_list_enter) + else: + self.ui.zl_button.clicked.connect(self.fit_zero_loss) + self.ui.drude_button.clicked.connect(self.smooth) + self.ui.list_model.activated[str].connect(self.on_list_enter) + + def fit_zero_loss(self): + """get shift of spectrum form zero-loss peak position""" + zero_loss_fit_width=0.3 + + energy_scale = self.dataset.energy_loss + zl_dataset = self.dataset.copy() + zl_dataset.title = 'resolution_function' + shifts = np.zeros(self.dataset.shape[0:2]) + zero_p = np.zeros([self.dataset.shape[0],self.dataset.shape[1],6]) + fwhm_p = np.zeros(self.dataset.shape[0:2]) + bin_x = bin_y = 1 + total_spec = int(self.dataset.shape[0]/bin_x)*int(self.dataset.shape[1]/bin_y) + self.ui.progress.setMaximum(total_spec) + self.ui.progress.setValue(0) + zero_loss_fit_width=0.3 + ind = 0 + for x in range(self.dataset.shape[0]): + for y in range(self.dataset.shape[1]): + ind += 1 + self.ui.progress.setValue(ind) + spectrum = self.dataset[x, y, :] + fwhm, delta_e = eels_tools.fix_energy_scale(spectrum, energy_scale) + z_loss, p_zl = eels_tools.resolution_function(energy_scale - delta_e, spectrum, zero_loss_fit_width) + fwhm2, delta_e2 = eels_tools.fix_energy_scale(z_loss, energy_scale - delta_e) + shifts[x, y] = delta_e + delta_e2 + zero_p[x,y,:] = p_zl + zl_dataset[x,y] = z_loss + fwhm_p[x,y] = fwhm2 + + zl_dataset.metadata['zero_loss'] = {'parameter': zero_p, + 'shifts': shifts, + 'fwhm': fwhm_p} + self.dataset.metadata['zero_loss'] = {'parameter': zero_p, + 'shifts': shifts, + 'fwhm': fwhm_p} + + self.datasets['resolution_function'] = zl_dataset + self.update() + self.plot() + + + +
[docs]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'] + + if advanced_present and iterations > 1: + peak_model, peak_out_list = advanced_eels_tools.smooth(dataset, peaks['fit_start'], + peaks['fit_end'], iterations=iterations) + else: + 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
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/probe_tools.html b/_modules/pyTEMlib/probe_tools.html new file mode 100644 index 00000000..f221e724 --- /dev/null +++ b/_modules/pyTEMlib/probe_tools.html @@ -0,0 +1,768 @@ + + + + + + pyTEMlib.probe_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.probe_tools

+"""Functions to calculate electron probe"""
+import numpy as np
+import pyTEMlib.image_tools
+import scipy.ndimage as ndimage
+
+
+
[docs]def make_gauss(size_x, size_y, width=1.0, x0=0.0, y0=0.0, intensity=1.0): + """Make a Gaussian shaped probe """ + size_x = size_x / 2 + size_y = size_y / 2 + x, y = np.mgrid[-size_x:size_x, -size_y:size_y] + g = np.exp(-((x - x0) ** 2 + (y - y0) ** 2) / 2.0 / width ** 2) + probe = g / g.sum() * intensity + + return probe
+ + +
[docs]def make_lorentz(size_x, size_y, gamma=1.0, x0=0., y0=0., intensity=1.): + """Make a Lorentzian shaped probe """ + + size_x = np.floor(size_x / 2) + size_y = np.floor(size_y / 2) + x, y = np.mgrid[-size_x:size_x, -size_y:size_y] + g = gamma / (2 * np.pi) / np.power(((x - x0) ** 2 + (y - y0) ** 2 + gamma ** 2), 1.5) + probe = g / g.sum() * intensity + return probe
+ + +
[docs]def zero_loss_peak_weight(): + # US100 zero_loss peak for Cc of aberrations + x = np.linspace(-0.5, 0.9, 29) + y = [0.0143, 0.0193, 0.0281, 0.0440, 0.0768, 0.1447, 0.2785, 0.4955, 0.7442, 0.9380, 1.0000, 0.9483, 0.8596, + 0.7620, 0.6539, 0.5515, 0.4478, 0.3500, 0.2683, 0.1979, 0.1410, 0.1021, 0.0752, 0.0545, 0.0401, 0.0300, + 0.0229, 0.0176, 0.0139] + return x, y
+ + +
[docs]def make_chi(phi, theta, aberrations): + maximum_aberration_order = 5 + chi = np.zeros(theta.shape) + for n in range(maximum_aberration_order + 1): # First Sum up to fifth order + term_first_sum = np.power(theta, n + 1) / (n + 1) # term in first sum + + second_sum = np.zeros(theta.shape) # second Sum initialized with zeros + for m in range((n + 1) % 2, n + 2, 2): + if m > 0: + if f'C{n}{m}a' not in aberrations: # Set non existent aberrations coefficient to zero + aberrations[f'C{n}{m}a'] = 0. + if f'C{n}{m}b' not in aberrations: + aberrations[f'C{n}{m}b'] = 0. + + # term in second sum + second_sum = second_sum + aberrations[f'C{n}{m}a'] * np.cos(m * phi) + aberrations[ + f'C{n}{m}b'] * np.sin(m * phi) + else: + if f'C{n}{m}' not in aberrations: # Set non existent aberrations coefficient to zero + aberrations[f'C{n}{m}'] = 0. + + # term in second sum + second_sum = second_sum + aberrations[f'C{n}{m}'] + chi = chi + term_first_sum * second_sum * 2 * np.pi / aberrations['wavelength'] + + return chi
+ + +
[docs]def get_chi(ab, size_x, size_y, verbose=False): + """ Get aberration function chi without defocus spread + + # Internally reciprocal lattice vectors in 1/nm or rad. + # All calculations of chi in angles. + # All aberration coefficients in nm + """ + aperture_angle = ab['convergence_angle'] / 1000.0 # in rad + + wavelength = pyTEMlib.image_tools.get_wavelength(ab['acceleration_voltage']) + if verbose: + print(f"Acceleration voltage {ab['acceleration_voltage'] / 1000:}kV => wavelength {wavelength * 1000.:.2f}pm") + + ab['wavelength'] = wavelength + + # Reciprocal plane in 1/nm + dk = 1 / ab['FOV'] + k_x = np.array(dk * (-size_x / 2. + np.arange(size_x))) + k_y = np.array(dk * (-size_y / 2. + np.arange(size_y))) + t_x_v, t_y_v = np.meshgrid(k_x, k_y) + + # define reciprocal plane in angles + phi = np.arctan2(t_x_v, t_y_v) + theta = np.arctan2(np.sqrt(t_x_v ** 2 + t_y_v ** 2), 1 / wavelength) + + # calculate chi + chi = make_chi(phi, theta, ab) + + # Aperture function + mask = theta >= aperture_angle + + aperture = np.ones((size_x, size_y), dtype=float) + aperture[mask] = 0. + + return chi, aperture
+ + + + + +
[docs]def get_ronchigram(size, ab, scale='mrad'): + """ Get Ronchigram + + """ + size_x = size_y = size + chi, A_k = get_chi(ab, size_x, size_y) + + v_noise = np.random.rand(size_x, size_y) + smoothing = 5 + phi_r = ndimage.gaussian_filter(v_noise, sigma=(smoothing, smoothing), order=0) + + sigma = 6 # 6 for carbon and thin + + q_r = np.exp(-1j * sigma * phi_r) + # q_r = 1-phi_r * sigma + + T_k = A_k * (np.exp(-1j * chi)) + t_r = (np.fft.ifft2(np.fft.fftshift(T_k))) + + psi_k = np.fft.fftshift(np.fft.fft2(q_r * t_r)) + + ronchigram = np.absolute(psi_k * np.conjugate(psi_k)) + + fov_reciprocal = 1 / ab['FOV'] * size_x / 2 + if scale == '1/nm': + extent = [-fov_reciprocal, fov_reciprocal, -fov_reciprocal, fov_reciprocal] + ylabel = 'reciprocal distance [1/nm]' + else: + fov_mrad = fov_reciprocal * ab['wavelength'] * 1000 + extent = [-fov_mrad, fov_mrad, -fov_mrad, fov_mrad] + ylabel = 'reciprocal distance [mrad]' + + ab['ronchi_extent'] = extent + ab['ronchi_label'] = ylabel + return ronchigram
+ + +
[docs]def get_chi_2(ab, u, v): + chi1 = ab['C10'] * (u ** 2 + v ** 2) / 2 \ + + ab['C12a'] * (u ** 2 - v ** 2) / 2 \ + - ab['C12b'] * u * v + + chi2 = ab['C21a'] * (u ** 3 + u * v ** 2) / 3 \ + - ab['C21b'] * (u ** 2 * v + v ** 3) / 3 \ + + ab['C23a'] * (u ** 3 - 3 * u * v ** 2) / 3 \ + - ab['C23b'] * (3 * u ** 2 * v - v ** 3) / 3 + + chi3 = ab['C30'] * (u ** 4 + 2 * u ** 2 * v ** 2 + v ** 4) / 4 \ + + ab['C32a'] * (u ** 4 - v ** 4) / 4 \ + - ab['C32b'] * (u ** 3 * v + u * v ** 3) / 2 \ + + ab['C34a'] * (u ** 4 - 6 * u ** 2 * v ** 2 + v ** 4) / 4 \ + - ab['C34b'] * (4 * u ** 3 * v - 4 * u * v ** 3) / 4 + + chi4 = ab['C41a'] * (u ** 5 + 2 * u ** 3 * v ** 2 + u * v ** 4) / 5 \ + - ab['C41b'] * (u ** 4 * v + 2 * u ** 2 * v ** 3 + v ** 5) / 5 \ + + ab['C43a'] * (u ** 5 - 2 * u ** 3 * v ** 2 - 3 * u * v ** 4) / 5 \ + - ab['C43b'] * (3 * u ** 4 * v + 2 * u ** 2 * v ** 3 - v ** 5) / 5 \ + + ab['C45a'] * (u ** 5 - 10 * u ** 3 * v ** 2 + 5 * u * v ** 4) / 5 \ + - ab['C45b'] * (5 * u ** 4 * v - 10 * u ** 2 * v ** 3 + v ** 5) / 5 + + chi5 = ab['C50'] * (u ** 6 + 3 * u ** 4 * v ** 2 + 3 * u ** 2 * v ** 4 + v ** 6) / 6 \ + + ab['C52a'] * (u ** 6 + u ** 4 * v ** 2 - u ** 2 * v ** 4 - v ** 6) / 6 \ + - ab['C52b'] * (2 * u ** 5 * v + 4 * u ** 3 * v ** 3 + 2 * u * v ** 5) / 6 \ + + ab['C54a'] * (u ** 6 - 5 * u ** 4 * v ** 2 - 5 * u ** 2 * v ** 4 + v ** 6) / 6 \ + - ab['C54b'] * (4 * u ** 5 * v - 4 * u * v ** 5) / 6 \ + + ab['C56a'] * (u ** 6 - 15 * u ** 4 * v ** 2 + 15 * u ** 2 * v ** 4 - v ** 6) / 6 \ + - ab['C56b'] * (6 * u ** 5 * v - 20 * u ** 3 * v ** 3 + 6 * u * v ** 5) / 6 + + chi = chi1 + chi2 + chi3 + chi4 + chi5 + return chi * 2 * np.pi / ab['wavelength']
+ + +
[docs]def get_d2chidu2(ab, u, v): + d2chi1du2 = ab['C10'] + ab['C12a'] + + d2chi2du2 = ab['C21a'] * 2 * u \ + - ab['C21b'] * 2 / 3 * v \ + + ab['C23a'] * 2 * u \ + - ab['C23b'] * 2 * v + + d2chi3du2 = ab['C30'] * (3 * u ** 2 + v ** 2) \ + + ab['C32a'] * 3 * u ** 2 \ + - ab['C32b'] * 3 * u * v \ + + ab['C34a'] * (3 * u ** 2 - 3 * v ** 2) \ + - ab['C34b'] * 6 * u * v + + d2chi4du2 = ab['C41a'] * 4 / 5 * (5 * u ** 3 + 3 * u * v ** 2) \ + - ab['C41b'] * 4 / 5 * (3 * u ** 2 * v + v ** 3) \ + + ab['C43a'] * 4 / 5 * (5 * u ** 3 - 3 * u * v ** 2) \ + - ab['C43b'] * 4 / 5 * (9 * u ** 2 * v + v ** 3) \ + + ab['C45a'] * 4 * (u ** 3 - 3 * u * v ** 2) \ + - ab['C45b'] * 4 * (3 * u ** 2 * v - v ** 3) + + d2chi5du2 = ab['C50'] * (5 * u ** 4 + 6 * u ** 2 * v ** 2 + v ** 4) \ + + ab['C52a'] * (15 * u ** 4 + 6 * u ** 2 * v ** 2 - v ** 4) / 3 \ + - ab['C52b'] * (20 * u ** 3 * v + 12 * u * v ** 3) / 3 \ + + ab['C54a'] * 5 / 3 * (3 * u ** 4 - 6 * u ** 2 * v ** 2 - v ** 4) \ + - ab['C54b'] * 5 / 3 * (8 * u ** 3 * v) \ + + ab['C56a'] * 5 * (u ** 4 - 6 * u ** 2 * v ** 2 + v ** 4) \ + - ab['C56b'] * 20 * (u ** 3 * v - u * v ** 3) + + d2chidu2 = d2chi1du2 + d2chi2du2 + d2chi3du2 + d2chi4du2 + d2chi5du2 + return d2chidu2
+ + +
[docs]def get_d2chidudv(ab, u, v): + d2chi1dudv = -ab['C12b'] + + d2chi2dudv = ab['C21a'] * 2 / 3 * v \ + - ab['C21b'] * 2 / 3 * u \ + - ab['C23a'] * 2 * v \ + - ab['C23b'] * 2 * u + + d2chi3dudv = ab['C30'] * 2 * u * v \ + + ab['C32a'] * 0 \ + - ab['C32b'] * 3 / 2 * (u ** 2 + v ** 2) \ + - ab['C34a'] * 6 * u * v \ + - ab['C34b'] * 3 * (u ** 2 - v ** 2) + + d2chi4dudv = ab['C41a'] * 4 / 5 * (3 * u ** 2 * v + v ** 3) \ + - ab['C41b'] * 4 / 5 * (u ** 3 + 3 * u * v ** 2) \ + - ab['C43a'] * 12 / 5 * (u ** 2 * v + v ** 3) \ + - ab['C43b'] * 12 / 5 * (u ** 3 + u * v ** 2) \ + - ab['C45a'] * 4 * (3 * u ** 2 * v - v ** 3) \ + - ab['C45b'] * 4 * (u ** 3 - 3 * u * v ** 2) + + d2chi5dudv = ab['C50'] * 4 * u * v * (u ** 2 + v ** 2) \ + + ab['C52a'] * 4 / 3 * (u ** 3 * v - u * v ** 3) \ + - ab['C52b'] * (5 * u ** 4 + 18 * u ** 2 * v ** 2 + 5 * v ** 4) / 3 \ + - ab['C54a'] * 20 / 3 * (u ** 3 * v + u * v ** 3) \ + - ab['C54b'] * 10 / 3 * (u ** 4 - v ** 4) \ + - ab['C56a'] * 20 * (u ** 3 * v - u * v ** 3) \ + - ab['C56b'] * 5 * (u ** 4 - 6 * u ** 2 * v ** 2 + v ** 4) + + d2chidudv = d2chi1dudv + d2chi2dudv + d2chi3dudv + d2chi4dudv + d2chi5dudv + return d2chidudv
+ + +
[docs]def get_d2chidv2(ab, u, v): + d2chi1dv2 = ab['C10'] - ab['C12a'] + + d2chi2dv2 = ab['C21a'] * 2 / 3 * u \ + - ab['C21b'] * 2 * v \ + - ab['C23a'] * 2 * u \ + + ab['C23b'] * 2 * v + + d2chi3dv2 = ab['C30'] * (u ** 2 + 3 * v ** 2) \ + - ab['C32a'] * 3 * v ** 2 \ + - ab['C32b'] * 3 * v * u \ + - ab['C34a'] * 3 * (u ** 2 - v ** 2) \ + + ab['C34b'] * 6 * u * v + + d2chi4dv2 = ab['C41a'] * 4 / 5 * (u ** 3 + 3 * u * v ** 2) \ + - ab['C41b'] * 4 / 5 * (3 * u ** 2 * v + 5 * v ** 3) \ + - ab['C43a'] * 4 / 5 * (u ** 3 + 9 * u * v ** 2) \ + - ab['C43b'] * 4 / 5 * (3 * u ** 2 * v - 5 * v ** 3) \ + - ab['C45a'] * 4 * (u ** 3 - 3 * u * v ** 2) \ + + ab['C45b'] * 4 * (3 * u ** 2 * v - v ** 3) + + d2chi5dv2 = ab['C50'] * (u ** 4 + 6 * u ** 2 * v ** 2 + 5 * v ** 4) \ + + ab['C52a'] * (u ** 4 - 6 * u ** 2 * v ** 2 - 15 * v ** 4) / 3 \ + - ab['C52b'] * (12 * u ** 3 * v + 20 * u * v ** 3) / 3 \ + - ab['C54a'] * 5 / 3 * (u ** 4 + 6 * u ** 2 * v ** 2 - 3 * v ** 4) \ + + ab['C54b'] * 40 / 3 * u * v ** 3 \ + - ab['C56a'] * 5 * (u ** 4 - 6 * u ** 2 * v ** 2 + v ** 4) \ + + ab['C56b'] * 20 * (u ** 3 * v - u * v ** 3) + + d2chidv2 = d2chi1dv2 + d2chi2dv2 + d2chi3dv2 + d2chi4dv2 + d2chi5dv2 + return d2chidv2
+ + +
[docs]def get_source_energy_spread(): + x = np.linspace(-0.5, .9, 29) + y = [0.0143, 0.0193, 0.0281, 0.0440, 0.0768, 0.1447, 0.2785, 0.4955, 0.7442, 0.9380, 1.0000, 0.9483, 0.8596, 0.7620, + 0.6539, 0.5515, 0.4478, 0.3500, 0.2683, 0.1979, 0.1410, 0.1021, 0.0752, 0.0545, 0.0401, 0.0300, 0.0229, 0.0176, + 0.0139] + + return x, y
+ + +
[docs]def get_target_aberrations(TEM_name, acceleration_voltage): + ab = {} + if TEM_name == 'NionUS200': + if int(acceleration_voltage) == 200000: + print(f' **** Using Target Values at {acceleration_voltage / 1000}kV for Aberrations of {TEM_name}****') + ab = {'C10': 0, 'C12a': 0, 'C12b': 0, 'C21a': -335., 'C21b': 283., 'C23a': -34., 'C23b': 220., + 'C30': -8080., + 'C32a': 18800., 'C32b': -2260., 'C34a': 949., 'C34b': 949., 'C41a': 54883., 'C41b': -464102., + 'C43a': 77240.5, + 'C43b': -540842., 'C45a': -79844.4, 'C45b': -76980.8, 'C50': 9546970., 'C52a': -2494290., + 'C52b': 2999910., + 'C54a': -2020140., 'C54b': -2019630., 'C56a': -535079., 'C56b': 1851850.} + ab['source_size'] = 0.051 + ab['acceleration_voltage'] = acceleration_voltage + ab['convergence_angle'] = 30 + + ab['Cc'] = 1.3e6 # // Cc in nm + + if int(acceleration_voltage) == 100000: + print(f' **** Using Target Values at {acceleration_voltage / 1000}kV for Aberrations of {TEM_name}****') + + ab = {'C10': 0, 'C12a': 0, 'C12b': 0, 'C21a': 157., 'C21b': 169, 'C23a': -173., 'C23b': 48.7, 'C30': 201., + 'C32a': 1090., 'C32b': 6840., 'C34a': 1010., 'C34b': 79.9, 'C41a': -210696., 'C41b': -262313., + 'C43a': 348450., 'C43b': -9.7888e4, 'C45a': 6.80247e4, 'C45b': -3.14637e1, 'C50': -193896., + 'C52a': -1178950, 'C52b': -7414340, 'C54a': -1753890, 'C54b': -1753890, 'C56a': -631786, + 'C56b': -165705} + ab['source_size'] = 0.051 + ab['acceleration_voltage'] = acceleration_voltage + ab['convergence_angle'] = 30 + ab['Cc'] = 1.3e6 + + if int(acceleration_voltage) == 60000: + print(f' **** Using Target Values at {acceleration_voltage / 1000}kV for Aberrations of {TEM_name}****') + + ab = {'C10': 0, 'C12a': 0, 'C12b': 0, 'C21a': 11.5, 'C21b': 113, 'C23a': -136., 'C23b': 18.2, 'C30': 134., + 'C32a': 1080., 'C32b': 773., 'C34a': 1190., 'C34b': -593., 'C41a': -179174., 'C41b': -350378., + 'C43a': 528598, 'C43b': -257349., 'C45a': 63853.4, 'C45b': 1367.98, 'C50': 239021., 'C52a': 1569280., + 'C52b': -6229310., 'C54a': -3167620., 'C54b': -449198., 'C56a': -907315., 'C56b': -16281.9} + ab['source_size'] = 0.081 + ab['acceleration_voltage'] = acceleration_voltage + ab['convergence_angle'] = 30 + ab['Cc'] = 1.3e6 # // Cc in nm + + ab['origin'] = 'target aberrations' + ab['TEM_name'] = TEM_name + ab['wavelength'] = pyTEMlib.image_tools.get_wavelength(ab['acceleration_voltage']) + + if TEM_name == 'NionUS100': + if int(acceleration_voltage) == 100000: + print(f' **** Using Target Values at {acceleration_voltage / 1000}kV for Aberrations of {TEM_name}****') + + ab = {'C10': 0, 'C12a': 0, 'C12b': 0, 'C21a': 157., 'C21b': 169, 'C23a': -173., 'C23b': 48.7, 'C30': 201., + 'C32a': 1090., 'C32b': 6840., 'C34a': 1010., 'C34b': 79.9, 'C41a': -210696., 'C41b': -262313., + 'C43a': 348450., 'C43b': -9.7888e4, 'C45a': 6.80247e4, 'C45b': -3.14637e1, 'C50': -193896., + 'C52a': -1178950, 'C52b': -7414340, 'C54a': -1753890, 'C54b': -1753890, 'C56a': -631786, + 'C56b': -165705} + ab['source_size'] = 0.051 + ab['acceleration_voltage'] = acceleration_voltage + ab['convergence_angle'] = 30 + ab['Cc'] = 1.3e6 # // Cc in nm + + if int(acceleration_voltage) == 60000: + print(f' **** Using Target Values at {acceleration_voltage / 1000}kV for Aberrations of {TEM_name}****') + + ab = {'C10': 0, 'C12a': 0, 'C12b': 0, 'C21a': 11.5, 'C21b': 113, 'C23a': -136., 'C23b': 18.2, 'C30': 134., + 'C32a': 1080., 'C32b': 773., 'C34a': 1190., 'C34b': -593., 'C41a': -179174., 'C41b': -350378., + 'C43a': 528598, 'C43b': -257349., 'C45a': 63853.4, 'C45b': 1367.98, 'C50': 239021., 'C52a': 1569280., + 'C52b': -6229310., 'C54a': -3167620., 'C54b': -449198., 'C56a': -907315., 'C56b': -16281.9} + ab['source_size'] = 0.081 + ab['acceleration_voltage'] = acceleration_voltage + ab['convergence_angle'] = 30 + ab['Cc'] = 1.3e6 # // Cc in nm + + ab['origin'] = 'target aberrations' + ab['TEM_name'] = TEM_name + ab['wavelength'] = pyTEMlib.image_tools.get_wavelength(ab['acceleration_voltage']) + + if TEM_name == 'ZeissMC200': + ab = {'C10': 0, 'C12a': 0, 'C12b': 0, 'C21a': 0, 'C21b': 0, 'C23a': 0, 'C23b': 0, 'C30': 0., + 'C32a': 0., 'C32b': -0., 'C34a': 0., 'C34b': 0., 'C41a': 0., 'C41b': -0., 'C43a': 0., + 'C43b': -0., 'C45a': -0., 'C45b': -0., 'C50': 0., 'C52a': -0., 'C52b': 0., + 'C54a': -0., 'C54b': -0., 'C56a': -0., 'C56b': 0.} + ab['C30'] = 2.2 * 1e6 + + ab['Cc'] = 2.0 * 1e6 + + ab['source_size'] = 0.2 + ab['acceleration_voltage'] = acceleration_voltage + ab['convergence_angle'] = 10 + + ab['origin'] = 'target aberrations' + ab['TEM_name'] = TEM_name + + ab['wavelength'] = pyTEMlib.image_tools.get_wavelength(ab['acceleration_voltage']) + return ab
+ + +
[docs]def get_ronchigram_2(size, ab, scale='mrad', threshold=3): + aperture_angle = ab['convergence_angle'] / 1000.0 # in rad + + wavelength = pyTEMlib.image_tools.get_wavelength(ab['acceleration_voltage']) + # if verbose: + # print(f"Acceleration voltage {ab['acceleration_voltage']/1000:}kV => wavelength {wavelength*1000.:.2f}pm") + + ab['wavelength'] = wavelength + + size_x = size_y = size + + # Reciprocal plane in 1/nm + dk = ab['reciprocal_FOV'] / size + k_x = np.array(dk * (-size_x / 2. + np.arange(size_x))) + k_y = np.array(dk * (-size_y / 2. + np.arange(size_y))) + t_x_v, t_y_v = np.meshgrid(k_x, k_y) + + chi = get_chi_2(ab, t_x_v, t_y_v) # , verbose= True) + # define reciprocal plane in angles + phi = np.arctan2(t_x_v, t_y_v) + theta = np.arctan2(np.sqrt(t_x_v ** 2 + t_y_v ** 2), 1 / wavelength) + + # Aperture function + mask = theta >= aperture_angle + + aperture = np.ones((size_x, size_y), dtype=float) + aperture[mask] = 0. + + v_noise = np.random.rand(size_x, size_y) + smoothing = 5 + phi_r = ndimage.gaussian_filter(v_noise, sigma=(smoothing, smoothing), order=0) + + sigma = 6 # 6 for carbon and thin + + q_r = np.exp(-1j * sigma * phi_r) + # q_r = 1-phi_r * sigma + + T_k = aperture * (np.exp(-1j * chi)) + t_r = np.fft.ifft2(np.fft.fftshift(T_k)) + + Psi_k = np.fft.fftshift(np.fft.fft2(q_r * t_r)) + + ronchigram = I_k = np.absolute(Psi_k * np.conjugate(Psi_k)) + + fov_reciprocal = ab['reciprocal_FOV'] + if scale == '1/nm': + extent = [-fov_reciprocal, fov_reciprocal, -fov_reciprocal, fov_reciprocal] + ylabel = 'reciprocal distance [1/nm]' + else: + fov_mrad = fov_reciprocal * ab['wavelength'] * 1000 + extent = [-fov_mrad, fov_mrad, -fov_mrad, fov_mrad] + ylabel = 'reciprocal distance [mrad]' + + ab['ronchi_extent'] = extent + ab['ronchi_label'] = ylabel + + h = np.zeros([chi.shape[0], chi.shape[1], 2, 2]) + h[:, :, 0, 0] = get_d2chidu2(ab, t_x_v, t_y_v) + h[:, :, 0, 1] = get_d2chidudv(ab, t_x_v, t_y_v) + h[:, :, 1, 0] = get_d2chidudv(ab, t_x_v, t_y_v) + h[:, :, 1, 1] = get_d2chidv2(ab, t_x_v, t_y_v) + + # get Eigenvalues + _, s, _ = np.linalg.svd(h) + + # get smallest Eigenvalue per pixel + infinite_magnification = np.min(s, axis=2) + + # set all values below a threshold value to one, otherwise 0 + infinite_magnification[infinite_magnification <= threshold] = 1 + infinite_magnification[infinite_magnification > threshold] = 0 + + return ronchigram, infinite_magnification
+ + +# ## Aberration Function for Probe calculations +
[docs]def make_chi1(phi, theta, wavelength, ab, c1_include): + """ + # ## + # Aberration function chi without defocus + # ## + """ + t0 = np.power(theta, 1) / 1 * (float(ab['C01a']) * np.cos(1 * phi) + float(ab['C01b']) * np.sin(1 * phi)) + + if c1_include == 1: # First and second terms + t1 = np.power(theta, 2) / 2 * (ab['C10'] + ab['C12a'] * np.cos(2 * phi) + ab['C12b'] * np.sin(2 * phi)) + elif c1_include == 2: # Second terms only + t1 = np.power(theta, 2) / 2 * (ab['C12a'] * np.cos(2 * phi) + ab['C12b'] * np.sin(2 * phi)) + else: # none for zero + t1 = t0 * 0. + + t2 = np.power(theta, 3) / 3 * (ab['C21a'] * np.cos(1 * phi) + ab['C21b'] * np.sin(1 * phi) + + ab['C23a'] * np.cos(3 * phi) + ab['C23b'] * np.sin(3 * phi)) + + t3 = np.power(theta, 4) / 4 * (ab['C30'] + + ab['C32a'] * np.cos(2 * phi) + + ab['C32b'] * np.sin(2 * phi) + + ab['C34a'] * np.cos(4 * phi) + + ab['C34b'] * np.sin(4 * phi)) + + t4 = np.power(theta, 5) / 5 * (ab['C41a'] * np.cos(1 * phi) + + ab['C41b'] * np.sin(1 * phi) + + ab['C43a'] * np.cos(3 * phi) + + ab['C43b'] * np.sin(3 * phi) + + ab['C45a'] * np.cos(5 * phi) + + ab['C45b'] * np.sin(5 * phi)) + + t5 = np.power(theta, 6) / 6 * (ab['C50'] + + ab['C52a'] * np.cos(2 * phi) + + ab['C52b'] * np.sin(2 * phi) + + ab['C54a'] * np.cos(4 * phi) + + ab['C54b'] * np.sin(4 * phi) + + ab['C56a'] * np.cos(6 * phi) + + ab['C56b'] * np.sin(6 * phi)) + + chi = t0 + t1 + t2 + t3 + t4 + t5 + if 'C70' in ab: + chi += np.power(theta, 8) / 8 * (ab['C70']) + + return chi * 2 * np.pi / wavelength # np.power(theta,6)/6*( ab['C50'] )
+ + +
[docs]def probe2(ab, size_x, size_y, tags, verbose=False): + """ + + * This function creates an incident STEM probe + * at position (0,0) + * with parameters given in ab dictionary + * + * The following Aberration functions are being used: + * 1) ddf = Cc*de/E but not + Cc2*(de/E)^2, + * Cc, Cc2 = chrom. Aber. (1st, 2nd order) [1] + * 2) chi(qx,qy) = (2*pi/lambda)*{0.5*C1*(qx^2+qy^2)+ + * 0.5*C12a*(qx^2-qy^2)+ + * C12b*qx*qy+ + * C21a/3*qx*(qx^2+qy^2)+ + * ... + * +0.5*C3*(qx^2+qy^2)^2 + * +0.125*C5*(qx^2+qy^2)^3 + * ... (need to finish) + * + * + * qx = acos(k_x/K), qy = acos(k_y/K) + * + * References: + * [1] J. Zach, M. Haider, + * "Correction of spherical and Chromatic Aberration + * in a low Voltage SEM", Optik 98 (3), 112-118 (1995) + * [2] O.L. Krivanek, N. Delby, A.R. Lupini, + * "Towards sub-Angstrom Electron Beams", + * Ultramicroscopy 78, 1-11 (1999) + * + + + # Internally reciprocal lattice vectors in 1/nm or rad. + # All calculations of chi in angles. + # All aberration coefficients in nm + """ + + if 'fov' not in ab: + if 'fov' not in tags: + print(' need field of view in tags ') + else: + ab['fov'] = tags['fov'] + + if 'convAngle' not in ab: + ab['convAngle'] = 30 # in mrad + + ap_angle = ab['convAngle'] / 1000.0 # in rad + + e0 = ab['EHT'] = float(ab['EHT']) # acceleration voltage in ev + + # defocus = ab['C10'] + + if 'C01a' not in ab: + ab['C01a'] = 0. + if 'C01b' not in ab: + ab['C01b'] = 0. + + if 'C50' not in ab: + ab['C50'] = 0. + if 'C70' not in ab: + ab['C70'] = 0. + + if 'Cc' not in ab: + ab['Cc'] = 1.3e6 # Cc in nm + + def get_wl(): + h = 6.626 * 10 ** -34 + m0 = 9.109 * 10 ** -31 + ev = 1.602 * 10 ** -19 * e0 + c = 2.998 * 10 ** 8 + return h / np.sqrt(2 * m0 * ev * (1 + ev / (2 * m0 * c ** 2))) * 10 ** 9 + + wavelength = get_wl() + if verbose: + print('Acceleration voltage {0:}kV => wavelength {1:.2f}pm'.format(int(e0 / 1000), wavelength * 1000)) + ab['wavelength'] = wavelength + + # Reciprocal plane in 1/nm + dk = 1 / ab['fov'] + k_x = np.array(dk * (-size_x / 2. + np.arange(size_x))) + k_y = np.array(dk * (-size_y / 2. + np.arange(size_y))) + t_xv, t_yv = np.meshgrid(k_x, k_y) + + # define reciprocal plane in angles + phi = np.arctan2(t_xv, t_yv) + theta = np.arctan2(np.sqrt(t_xv ** 2 + t_yv ** 2), 1 / wavelength) + + # calculate chi but omit defocus + chi = np.fft.ifftshift(make_chi1(phi, theta, wavelength, ab, 2)) + probe = np.zeros((size_x, size_y)) + + # Aperture function + mask = theta >= ap_angle + + # Calculate probe with Cc + + for i in range(len(ab['zeroLoss'])): + df = ab['C10'] + ab['Cc'] * ab['zeroEnergy'][i] / e0 + if verbose: + print('defocus due to Cc: {0:.2f} nm with weight {1:.2f}'.format(df, ab['zeroLoss'][i])) + # Add defocus + chi2 = chi + np.power(theta, 2) / 2 * df + # Calculate exponent of - i * chi + chi_t = np.fft.ifftshift(np.vectorize(complex)(np.cos(chi2), -np.sin(chi2))) + # Apply aperture function + chi_t[mask] = 0. + # inverse fft of aberration function + i2 = np.fft.fftshift(np.fft.ifft2(np.fft.ifftshift(chi_t))) + # add intensities + probe = probe + np.real(i2 * np.conjugate(i2)).T * ab['zeroLoss'][i] + + ab0 = {} + for key in ab: + ab0[key] = 0. + # chiIA = np.fft.fftshift(make_chi1(phi, theta, wavelength, ab0, 0)) # np.ones(chi2.shape)*2*np.pi/wavelength + chi_i = np.ones((size_y, size_x)) + chi_i[mask] = 0. + i2 = np.fft.fftshift(np.fft.ifft2(np.fft.ifftshift(chi_i))) + ideal = np.real(i2 * np.conjugate(i2)) + + probe_f = np.fft.fft2(probe, probe.shape) + 1e-12 + ideal_f = np.fft.fft2(ideal, probe.shape) + fourier_space_division = ideal_f / probe_f + probe_r = (np.fft.ifft2(fourier_space_division, probe.shape)) + + return probe / sum(ab['zeroLoss']), np.real(probe_r)
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/sidpy_tools.html b/_modules/pyTEMlib/sidpy_tools.html new file mode 100644 index 00000000..a7a02e0f --- /dev/null +++ b/_modules/pyTEMlib/sidpy_tools.html @@ -0,0 +1,268 @@ + + + + + + pyTEMlib.sidpy_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.sidpy_tools

+"""utility functions for sidpy; will move to sidpy"""
+import numpy as np
+import sidpy
+import h5py
+import pyNSID
+import os
+import ipywidgets as widgets
+from IPython.display import display
+import json
+
+
+
[docs]class ChooseDataset(object): + """Widget to select dataset object """ + + def __init__(self, input_object, show_dialog=True): + if isinstance(input_object, sidpy.Dataset): + if isinstance(input_object.h5_dataset, h5py.Dataset): + self.current_channel = input_object.h5_dataset.parent + elif isinstance(input_object, h5py.Group): + self.current_channel = input_object + elif isinstance(input_object, h5py.Dataset): + self.current_channel = input_object.parent + else: + raise ValueError('Need hdf5 group or sidpy Dataset to determine image choices') + self.dataset_names = [] + self.dataset_list = [] + self.dataset_type = None + self.dataset = None + self.reader = pyNSID.NSIDReader(self.current_channel.file.filename) + + self.get_dataset_list() + self.select_image = widgets.Dropdown(options=self.dataset_names, + value=self.dataset_names[0], + description='select dataset:', + disabled=False, + button_style='') + if show_dialog: + display(self.select_image) + + self.select_image.observe(self.set_dataset, names='value') + self.set_dataset(0) + self.select_image.index = (len(self.dataset_names) - 1) + +
[docs] def get_dataset_list(self): + """ Get by Log number sorted list of datasets""" + datasets = self.reader.read() + order = [] + for dset in datasets: + if self.dataset_type is None or dset.data_type == self.data_type: + if 'Log' in dset.title: + position = dset.title.find('Log_') + 4 + order.append(int(dset.title[position:position + 3])+1) + else: + order.append(0) + for index in np.argsort(order): + dset = datasets[index] + self.dataset_names.append('/'.join(dset.title.replace('-', '_').split('/')[-1:])) + self.dataset_list.append(dset)
+ + def set_dataset(self, b): + index = self.select_image.index + self.dataset = self.dataset_list[index] + # Find + self.dataset.title = self.dataset.title.split('/')[-1]
+ + +
[docs]def get_dimensions_by_order(dims_in, dataset): + """get dimension + + Parameters + ---------- + dims_in: int or list of int + the dimensions by numerical order + dataset: sidpy.Dataset + + Returns + ------- + dims_out: list of dimensions + """ + + if isinstance(dims_in, int): + dims_in = [dims_in] + dims_out = [] + for item in dims_in: + if isinstance(item, int): + if item in dataset._axes: + dims_out.append([item, dataset._axes[item]]) + return dims_out
+ + +
[docs]def get_dimensions_by_type(dims_in, dataset): + """ get dimension by dimension_type name + + Parameters + ---------- + dims_in: dimension_type or list of dimension_types + the dimensions by numerical order + dataset: sidpy.Dataset + + Returns + ------- + dims_out: list of dimensions + """ + + if isinstance(dims_in, (str, sidpy.DimensionType)): + dims_in = [dims_in] + for i in range(len(dims_in)): + if isinstance(dims_in[i], str): + dims_in[i] = sidpy.DimensionType[dims_in[i].upper()] + dims_out = [] + for dim, axis in dataset._axes.items(): + if axis.dimension_type in dims_in: + dims_out.append([dim, dataset._axes[dim]]) + return dims_out
+ + +
[docs]def make_dummy_dataset(value_type): + """Make a dummy sidpy.Dataset """ + + assert isinstance(value_type, sidpy.DataType) + if type == sidpy.DataType.SPECTRUM: + dataset = sidpy.Dataset.from_array(np.arange(100)) + dataset.data_type = 'spectrum' + dataset.units = 'counts' + dataset.quantity = 'intensity' + + dataset.set_dimension(0, sidpy.Dimension(np.arange(dataset.shape[0]) + 70, name='energy_scale')) + dataset.dim_0.dimension_type = 'spectral' + dataset.dim_0.units = 'eV' + dataset.dim_0.quantity = 'energy loss' + else: + raise NotImplementedError('not implemented') + return dataset
+ + +
[docs]def plot(dataset): + dataset.plot()
+ + +
[docs]def get_image_dims(dataset): + """Get all spatial dimensions""" + + image_dims = [] + for dim, axis in dataset._axes.items(): + if axis.dimension_type == sidpy.DimensionType.SPATIAL: + image_dims.append(dim) + return image_dims
+ + +
[docs]def get_extent(dataset): + """get extent to plot with matplotlib""" + image_dims = get_image_dims(dataset) + return dataset.get_extent(image_dims)
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/simulation_tools.html b/_modules/pyTEMlib/simulation_tools.html new file mode 100644 index 00000000..80edcc6d --- /dev/null +++ b/_modules/pyTEMlib/simulation_tools.html @@ -0,0 +1,219 @@ + + + + + + pyTEMlib.simulation_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.simulation_tools

+""" dft simulations tools
+
+Part of pyTEMlib
+by Gerd Duscher
+created 10/29/2020
+
+Supports the conversion of DFT data to simulated EELS spectra
+
+- exciting_get_spectra:  importing dielectric function from the exciting program
+- final_state_broadening: apply final state broadening to loss-spectra
+"""
+
+import numpy as np
+from lxml import etree
+
+
+
[docs]def exciting_get_spectra(file): + """get EELS spectra from exciting calculation""" + + tags = {'data': {}} + + tree = etree.ElementTree(file=file) + root = tree.getroot() + + data = tags['data'] + + if root.tag in ['loss', 'dielectric']: + print(' reading ', root.tag, ' function from file ', file) + # print(root[0].tag, root[0].text) + map_def = root[0] + i = 0 + v = {} + for child_of_root in map_def: + data[child_of_root.tag] = child_of_root.attrib + v[child_of_root.tag] = [] + i += 1 + + for elem in tree.iter(tag='map'): + m_dict = elem.attrib + for key in m_dict: + v[key].append(float(m_dict[key])) + + for key in data: + data[key]['data'] = np.array(v[key]) + data['type'] = root.tag+' function' + return tags
+ + +
[docs]def final_state_broadening(x, y, start, instrument): + """Final state smearing of ELNES edges + + Parameters + ---------- + x: numpy array + x or energy loss axis of density of states + y: numpy array + y or intensity axis of density of states + start: float + start energy of edge + instrument: float + instrument broadening + + Return + ------ + out_data: numpy array + smeared intensity according to final state and instrument broadening + """ + + # Getting the smearing + a_i = 107.25*5 + b_i = 0.04688*2. + x = np.array(x)-start + zero = int(-x[0]/(x[1]-x[0]))+1 + smear_i = x*0.0 + smear_i[zero:-1] = (a_i/x[zero:-1]**2)+b_i*np.sqrt(x[zero:-1]) + h_bar = 6.58e-16 # h/2pi + pre = 1.0 + m = 6.58e-31 + smear = x*0.0 + smear[zero:-1] = pre*(h_bar/(smear_i[zero:-1]*0.000000001))*np.sqrt((2*x[zero:-1]*1.6E-19)/m) + + def lorentzian(xx, pp): + yy = ((0.5 * pp[1]/3.14)/((xx-pp[0])**2 + ((pp[1]/2)**2))) + return yy/sum(yy) + + p = [0, instrument] + in_data = y.copy() + out_data = np.array(y)*0.0 + for i in range(zero+5, len(x)): + p[0] = x[i] + p[1] = smear[i]/1.0 + lor = lorentzian(x+1e-9, p) + out_data[i] = sum(in_data*lor) + if np.isnan(out_data[i]): + out_data[i] = 0.0 + + p[1] = instrument + in_data = out_data.copy() + for i in range(zero-5, len(x)): + p[0] = x[i] + lor = lorentzian(x+1e-9, p) + out_data[i] = sum(in_data*lor) + # print(out_data[i],in_data[i], lor[i],in_data[i-1], lor[i-1], ) + return out_data
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/pyTEMlib/viz.html b/_modules/pyTEMlib/viz.html new file mode 100644 index 00000000..0ca986f2 --- /dev/null +++ b/_modules/pyTEMlib/viz.html @@ -0,0 +1,596 @@ + + + + + + pyTEMlib.viz — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for pyTEMlib.viz

+"""plotting of sidpy Datasets with bokeh for google colab"""
+
+import numpy as np
+import sidpy
+from sidpy.hdf.dtype_utils import is_complex_dtype
+
+import plotly.graph_objects as go
+from plotly.subplots import make_subplots
+from ipywidgets import widgets
+
+
+import pyTEMlib.eels_tools as eels
+import pyTEMlib.file_tools as ft
+
+
+"""from bokeh.layouts import column
+from bokeh.plotting import figure  # , show, output_notebook
+from bokeh.models import CustomJS, Slider, Span
+from bokeh.models import LinearColorMapper, ColorBar, ColumnDataSource, BoxSelectTool
+from bokeh.palettes import Spectral11
+"""
+from pyTEMlib.sidpy_tools import *
+import sys
+import matplotlib.pyplot as plt
+# from matplotlib.widgets import Slider, Button
+import matplotlib.patches as patches
+# import matplotlib.animation as animation
+
+if sys.version_info.major == 3:
+    unicode = str
+
+default_cmap = plt.cm.viridis
+
+
+
[docs]def plot(dataset, palette='Viridis256'): + """plot according to data_type""" + if dataset.data_type.name == 'IMAGE_STACK': + p = plot_stack(dataset, palette=palette) + elif dataset.data_type.name == 'IMAGE': + p = plot_image(dataset, palette=palette) + elif dataset.data_type.name == 'SPECTRUM': + p = plot_spectrum(dataset, palette=palette) + else: + p = None + return p
+ + +
[docs]def plot_stack(dataset, palette="Viridis256"): + """Plotting a stack of images + + Plotting a stack of images contained in a sidpy.Dataset. + The images can be scrolled through with a slider widget. + + Parameters + ---------- + dataset: sidpy.Dataset + sidpy dataset with data_type 'IMAGE_STACK' + palette: bokeh palette + palette is optional + + Returns + ------- + p: bokeh plot + + Example + ------- + >> import pyTEMlib + >> from bokeh.plotting import figure, show, output_notebook + >> output_notebook() + >> p = pyTEMlib.viz(dataset) + >> p.show(p) + """ + + if not isinstance(dataset, sidpy.Dataset): + raise TypeError('Need a sidpy dataset for plotting') + if dataset.data_type.name != 'IMAGE_STACK': + raise TypeError('Need an IMAGE_STACK for plotting a stack') + + stack = np.array(dataset-dataset.min()) + stack = stack/stack.max()*256 + stack = np.array(stack, dtype=int) + + color_mapper = LinearColorMapper(palette=palette, low=0, high=256) + + p = figure(match_aspect=True, plot_width=600, plot_height=600) + im_plot = p.image(image=[stack[0]], x=[0], y=[0], dw=[dataset.x[-1]], dh=[dataset.y[-1]], color_mapper=color_mapper) + p.x_range.range_padding = 0 + p.y_range.range_padding = 0 + p.xaxis.axis_label = 'distance (nm)' + p.yaxis.axis_label = 'distance (nm)' + + slider = Slider(start=0, end=stack.shape[0]-1, value=0, step=1, title="frame") + + update_curve = CustomJS(args=dict(source=im_plot, slider=slider, stack=stack), + code="""var f = slider.value; + source.data_source.data['image'] = [stack[f]]; + // necessary because we mutated source.data in-place + source.data_source.change.emit(); """) + slider.js_on_change('value', update_curve) + + return column(slider, p)
+ + +
[docs]def plot_image(dataset, palette="Viridis256"): + """Plotting an image + + Plotting an image contained in a sidpy.Dataset. + + Parameters + ---------- + dataset: sidpy.Dataset + sidpy dataset with data_type 'IMAGE_STACK' + palette: bokeh palette + palette is optional + + Returns + ------- + p: bokeh plot + + Example + ------- + >> import pyTEMlib + >> from bokeh.plotting import figure, show, output_notebook + >> output_notebook() + >> p = pyTEMlib.viz(dataset) + >> p.show(p) + + + """ + if not isinstance(dataset, sidpy.Dataset): + raise TypeError('Need a sidpy dataset for plotting') + + if dataset.data_type.name not in ['IMAGE', 'IMAGE_STACK']: + raise TypeError('Need an IMAGE or IMAGE_STACK for plotting an image') + + if dataset.data_type.name == 'IMAGE_STACK': + image = dataset.sum(axis=0) + image = sidpy.Dataset.from_array(image) + image.data_type = 'image' + image.title = dataset.title + image.set_dimension(0, dataset.dim_1) + image.set_dimension(1, dataset.dim_2) + else: + image = dataset + + p = figure(tooltips=[("x", "$x"), ("y", "$y"), ("value", "@image")], match_aspect=True, + plot_width=675, plot_height=600, ) + color_mapper = LinearColorMapper(palette=palette, low=float(image.min()), high=float(image.max())) + + # must give a vector of image data for image parameter + p.image(image=[np.array(image)], x=0, y=0, dw=image.x[-1], dh=image.y[-1], color_mapper=color_mapper, + level="image") + p.x_range.range_padding = 0 + p.y_range.range_padding = 0 + + p.grid.grid_line_width = 0. + p.xaxis.axis_label = 'distance (nm)' + p.yaxis.axis_label = 'distance (nm)' + + color_bar = ColorBar(color_mapper=color_mapper, major_label_text_font_size="7pt", + label_standoff=6, border_line_color=None, location=(0, 0)) + p.add_layout(color_bar, 'right') + return p
+ + +
[docs]def plot_spectrum(dataset, selected_range, palette=None): + """Plot spectrum""" + if not isinstance(dataset, sidpy.Dataset): + raise TypeError('Need a sidpy dataset for plotting') + + if dataset.data_type.name not in ['SPECTRUM']: + raise TypeError('Need an sidpy.Dataset of data_type SPECTRUM for plotting a spectrum ') + + p = figure(x_axis_type="linear", plot_width=800, plot_height=400, + tooltips=[("index", "$index"), ("(x,y)", "($x, $y)")], + tools="pan,wheel_zoom,box_zoom,reset, hover, lasso_select") + p.add_tools(BoxSelectTool(dimensions="width")) + + # first line is dataset + spectrum = ColumnDataSource(data=dict(x=dataset.dim_0, y=np.array(dataset))) + p.scatter('x', 'y', color='blue', size=1, alpha=0., source=spectrum, + selection_color="firebrick", selection_alpha=0.) + p.line(x='x', y='y', source=spectrum, legend_label=dataset.title, color=palette[0], line_width=2) + # add other lines if available + if 'add2plot' in dataset.metadata: + data = dataset.metadata['add2plot'] + for key, line in data.items(): + p.line(dataset.dim_0.values, line['data'], legend_label=line['legend'], color=palette[key], line_width=2) + p.legend.click_policy = "hide" + p.xaxis.axis_label = dataset.labels[0] + p.yaxis.axis_label = dataset.data_descriptor + p.title.text = dataset.title + + my_span = Span(location=0, dimension='width', line_color='gray', line_width=1) + p.add_layout(my_span) + + callback = CustomJS(args=dict(s1=spectrum), code=""" + var inds = s1.selected.indices; + if (inds.length == 0) + return; + var kernel = IPython.notebook.kernel; + kernel.execute("selected_range = " + [inds[0], inds[inds.length-1]]);""") + + spectrum.selected.js_on_change('indices', callback) + return p
+ + +
[docs]class CurveVisualizer(object): + """Plots a sidpy.Dataset with spectral dimension + + """ + def __init__(self, dset, spectrum_number=None, axis=None, leg=None, **kwargs): + if not isinstance(dset, sidpy.Dataset): + raise TypeError('dset should be a sidpy.Dataset object') + if axis is None: + self.fig = plt.figure() + self.axis = self.fig.add_subplot(1, 1, 1) + else: + self.axis = axis + self.fig = axis.figure + + self.dset = dset + self.selection = [] + [self.spec_dim, self.energy_scale] = get_dimensions_by_type('spectral', self.dset)[0] + + self.lined = dict() + self.plot(**kwargs) + + def plot(self, **kwargs): + line1, = self.axis.plot(self.energy_scale.values, self.dset, label='spectrum', **kwargs) + lines = [line1] + if 'add2plot' in self.dset.metadata: + data = self.dset.metadata['add2plot'] + for key, line in data.items(): + line_add, = self.axis.plot(self.energy_scale.values, line['data'], label=line['legend']) + lines.append(line_add) + + legend = self.axis.legend(loc='upper right', fancybox=True, shadow=True) + legend.get_frame().set_alpha(0.4) + + for legline, origline in zip(legend.get_lines(), lines): + legline.set_picker(True) + legline.set_pickradius(5) # 5 pts tolerance + self.lined[legline] = origline + self.fig.canvas.mpl_connect('pick_event', self.onpick) + + self.axis.axhline(0, color='gray', alpha=0.6) + self.axis.set_xlabel(self.dset.labels[0]) + self.axis.set_ylabel(self.dset.data_descriptor) + self.axis.ticklabel_format(style='sci', scilimits=(-2, 3)) + self.fig.canvas.draw_idle() + + def update(self, **kwargs): + x_limit = self.axis.get_xlim() + y_limit = self.axis.get_ylim() + self.axis.clear() + self.plot(**kwargs) + self.axis.set_xlim(x_limit) + self.axis.set_ylim(y_limit) + + def onpick(self, event): + # on the pick event, find the orig line corresponding to the + # legend proxy line, and toggle the visibility + legline = event.artist + origline = self.lined[legline] + vis = not origline.get_visible() + origline.set_visible(vis) + # Change the alpha on the line in the legend so we can see what lines + # have been toggled + if vis: + legline.set_alpha(1.0) + else: + legline.set_alpha(0.2) + self.fig.canvas.draw()
+ + +
[docs]def verify_spectrum_dataset(datasets): + if isinstance(datasets, sidpy.Dataset): + datasets = {'Channel_000': datasets} + + first_dataset = datasets[list(datasets)[0]] + has_complex_dataset = False + for dat in datasets.values(): + if is_complex_dtype(dat.dtype): + has_complex_dataset = True + + + if first_dataset.data_type.name != 'SPECTRUM': + raise TypeError('We need a spectrum dataset here') + if first_dataset.ndim >1: + if first_dataset.shape[1] >1: + raise TypeError('Wrong dimensions for spectrum datasset') + + energy_dim = first_dataset.get_spectrum_dims() + energy_dim = first_dataset.get_dimension_by_number(energy_dim[0])[0] + energy_dim.label = f'{energy_dim.quantity} ({energy_dim.units})' + + default_plot_dictionary = {'title': '', + 'theme': "plotly_white", + 'y_scale': 1.0, + 'y_axis_label': first_dataset.data_descriptor, + 'x_axis_label': energy_dim.label, + 'show_legend': True, + 'height': 500, + 'figure_size': None, + 'scale_bar': False, + 'colorbar': True, + 'set_title': True, + 'has_complex_dataset': has_complex_dataset} + + + default_plot_dictionary.update(first_dataset.metadata['plot_parameter']) + first_dataset.metadata['plot_parameter'] = default_plot_dictionary + + return datasets
+ +
[docs]def spectrum_view_plotly(datasets, figure=None, show=False): + + datasets = verify_spectrum_dataset(datasets) + first_dataset = datasets[list(datasets)[0]] + plot_dic = first_dataset.metadata['plot_parameter'] + + if figure is None: + if plot_dic['has_complex_dataset']: + fig = make_subplots(rows=1, cols=2, subplot_titles=("Magnitude", "Phase")) + else: + fig = go.Figure() + + else: + fig = figure + + for key, dat in datasets.items(): + if dat.data_type == first_dataset.data_type: + energy_dim = dat.get_spectrum_dims() + energy_dim = dat.get_dimension_by_number(energy_dim[0])[0] + if is_complex_dtype(dat.dtype): + fig.add_trace(go.Scatter(x=energy_dim.values, y=np.abs(dat).squeeze()*plot_dic['y_scale'], name=f'{dat.title}-Magnitude', mode="lines+markers", marker=dict(size=2)), row=1, col=1) + fig.add_trace(go.Scatter(x=energy_dim.values, y=np.angle(dat).squeeze()*plot_dic['y_scale'], name=f'{dat.title}-Phase', mode="lines+markers", marker=dict(size=2)), row=1, col=2) + else: + fig.add_trace(go.Scatter(x=energy_dim.values, y=np.array(dat).squeeze()*plot_dic['y_scale'], name=dat.title, mode="lines+markers", marker=dict(size=2))) + + + fig.update_layout( + selectdirection='h', + showlegend = plot_dic['show_legend'], + dragmode='select', + title_text=plot_dic['title'], + yaxis_title_text=plot_dic['y_axis_label'], + xaxis_title_text=plot_dic['x_axis_label'], + height=plot_dic['height'], + template=plot_dic['theme'] + ) + fig.update_layout(hovermode='x unified') + + if plot_dic['has_complex_dataset']: + fig.update_yaxes(title_text='angle (rad)', row = 1, col = 2) + fig.update_xaxes(title_text=plot_dic['x_axis_label'], row = 1, col = 2) + + config = {'displayModeBar': True} + if show: + fig.show(config=config) + return fig
+ + +
[docs]class SpectrumView(object): + def __init__(self, datasets, figure=None, **kwargs): + first_dataset = datasets[list(datasets)[0]] + if first_dataset.data_type.name != 'SPECTRUM': + raise TypeError('We need a spectrum dataset here') + if first_dataset.ndim >1: + if first_dataset.shape[1] >1: + raise TypeError('Wrong dimensions for spectrum datasset') + + energy_dim = first_dataset.get_spectrum_dims() + energy_dim = first_dataset.get_dimension_by_number(energy_dim[0])[0] + + if 'plot_parameter' not in first_dataset.metadata: + first_dataset.metadata['plot_parameter'] = {} + plot_dic = first_dataset.metadata['plot_parameter'] + energy_dim.label = f'{energy_dim.quantity} ({energy_dim.units})' + + plot_dic['title'] = kwargs.pop('title', '') + plot_dic['theme'] = kwargs.pop('theme', "plotly_white") + plot_dic['y_scale'] = kwargs.pop('y_scale', 1.0) + plot_dic['y_axis_label'] = kwargs.pop('y_axis_label', first_dataset.data_descriptor) + plot_dic['x_axis_label'] = kwargs.pop('x_axis_label', energy_dim.label) + plot_dic['height'] = kwargs.pop('height', 500) + + + if 'incident_beam_current_counts' in first_dataset.metadata['experiment']: + plot_dic['y_scale'] = 1e6/first_dataset.metadata['experiment']['incident_beam_current_counts'] + plot_dic['y_axis_label'] = ' probability (ppm)' + # plot_dic['y_scale'] = 1e6/first_dataset.sum() + + def selection_fn(trace,points,selector): + self.energy_selection = [points.point_inds[0], points.point_inds[-1]] + + self.fig = spectrum_view_plotly(datasets) + + self.spectrum_widget = go.FigureWidget(self.fig) + + self.spectrum_widget.data[0].on_selection(selection_fn) + self.spectrum_widget.data[0].on_click(self.identify_edges) + + self.edge_annotation = 0 + self.edge_line = 0 + self.regions = {} + self.initialize_edge() + + self.plot = display(self.spectrum_widget) + +
[docs] def initialize_edge(self): + """ Intitalizes edge cursor + Should be run first so that edge cursor is first + """ + self.edge_annotation = len(self.spectrum_widget.layout.annotations) + self.edge_line = len(self.spectrum_widget.layout.shapes) + self.spectrum_widget.add_vline(x=200, line_dash="dot", line_color='blue', + annotation_text= " ", + annotation_position="top right", + visible = False)
+ + def identify_edges(self, trace, points, selector): + energy = points.xs[0] + edge_names = find_edge_names(points.xs[0]) + self.spectrum_widget.layout['annotations'][self.edge_annotation].x=energy + + self.spectrum_widget.layout['annotations'][self.edge_annotation].text = f"{edge_names}" + self.spectrum_widget.layout['annotations'][self.edge_annotation].visible = True + self.spectrum_widget.layout['shapes'][self.edge_line].x0 = energy + self.spectrum_widget.layout['shapes'][self.edge_line].x1 = energy + self.spectrum_widget.layout['shapes'][self.edge_line].visible = True + self.spectrum_widget.layout.update() + + def add_region(self, text, start, end, color='blue'): + if text not in self.regions: + self.regions[text] = {'annotation': len(self.spectrum_widget.layout.annotations), + 'shape': len(self.spectrum_widget.layout.shapes), + 'start': start, + 'end': end, + 'color': color} + self.spectrum_widget.add_vrect(x0=start, x1=end, + annotation_text=text, annotation_position="top left", + fillcolor=color, opacity=0.15, line_width=0) + self.spectrum_widget.layout.update() + else: + self.update_region(text, start, end) + + + def update_region(self, text, start, end): + if text in self.regions: + region = self.regions[text] + self.spectrum_widget.layout.annotations[region['annotation']].x =start + self.spectrum_widget.layout['shapes'][region['shape']].x0 = start + self.spectrum_widget.layout['shapes'][region['shape']].x1 = end + self.spectrum_widget.layout.update() + + def regions_visibility(self, visibility=True): + + for region in self.regions.values(): + self.spectrum_widget.layout.annotations[region['annotation']].visible = visibility + self.spectrum_widget.layout.shapes[region['shape']].visible = visibility
+ + +
[docs]def find_edge_names(energy_value): + + selected_edges = [] + for shift in [1,2,5,10,20]: + selected_edge = '' + edges = eels.find_major_edges(energy_value, shift) + edges = edges.split('\n') + for edge in edges[1:]: + edge = edge[:-3].split(':') + name = edge[0].strip() + energy = float(edge[1].strip()) + selected_edge = name + + if selected_edge != '': + selected_edges.append(selected_edge) + if len(selected_edges)>0: + return selected_edges
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.animation.InteractiveAberration.rst.txt b/_sources/_autosummary/pyTEMlib.animation.InteractiveAberration.rst.txt new file mode 100644 index 00000000..2b8ba6b2 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.animation.InteractiveAberration.rst.txt @@ -0,0 +1,26 @@ +pyTEMlib.animation.InteractiveAberration +======================================== + +.. currentmodule:: pyTEMlib.animation + +.. autoclass:: InteractiveAberration + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~InteractiveAberration.on_button_clicked + ~InteractiveAberration.update + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.animation.InteractiveRonchigramMagnification.rst.txt b/_sources/_autosummary/pyTEMlib.animation.InteractiveRonchigramMagnification.rst.txt new file mode 100644 index 00000000..8574c852 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.animation.InteractiveRonchigramMagnification.rst.txt @@ -0,0 +1,26 @@ +pyTEMlib.animation.InteractiveRonchigramMagnification +===================================================== + +.. currentmodule:: pyTEMlib.animation + +.. autoclass:: InteractiveRonchigramMagnification + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~InteractiveRonchigramMagnification.on_button_clicked + ~InteractiveRonchigramMagnification.update + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.animation.add_aperture.rst.txt b/_sources/_autosummary/pyTEMlib.animation.add_aperture.rst.txt new file mode 100644 index 00000000..93141785 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.animation.add_aperture.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.animation.add\_aperture +================================ + +.. currentmodule:: pyTEMlib.animation + +.. autofunction:: add_aperture \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.animation.add_lens.rst.txt b/_sources/_autosummary/pyTEMlib.animation.add_lens.rst.txt new file mode 100644 index 00000000..de1603f8 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.animation.add_lens.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.animation.add\_lens +============================ + +.. currentmodule:: pyTEMlib.animation + +.. autofunction:: add_lens \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.animation.deficient_holz_line.rst.txt b/_sources/_autosummary/pyTEMlib.animation.deficient_holz_line.rst.txt new file mode 100644 index 00000000..969650d8 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.animation.deficient_holz_line.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.animation.deficient\_holz\_line +======================================== + +.. currentmodule:: pyTEMlib.animation + +.. autofunction:: deficient_holz_line \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.animation.deficient_kikuchi_line.rst.txt b/_sources/_autosummary/pyTEMlib.animation.deficient_kikuchi_line.rst.txt new file mode 100644 index 00000000..df8dc0bf --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.animation.deficient_kikuchi_line.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.animation.deficient\_kikuchi\_line +=========================================== + +.. currentmodule:: pyTEMlib.animation + +.. autofunction:: deficient_kikuchi_line \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.animation.geometric_ray_diagram.rst.txt b/_sources/_autosummary/pyTEMlib.animation.geometric_ray_diagram.rst.txt new file mode 100644 index 00000000..425c4faf --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.animation.geometric_ray_diagram.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.animation.geometric\_ray\_diagram +========================================== + +.. currentmodule:: pyTEMlib.animation + +.. autofunction:: geometric_ray_diagram \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.animation.propagate_beam.rst.txt b/_sources/_autosummary/pyTEMlib.animation.propagate_beam.rst.txt new file mode 100644 index 00000000..eae81da0 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.animation.propagate_beam.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.animation.propagate\_beam +================================== + +.. currentmodule:: pyTEMlib.animation + +.. autofunction:: propagate_beam \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.animation.rst.txt b/_sources/_autosummary/pyTEMlib.animation.rst.txt new file mode 100644 index 00000000..3fc8b129 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.animation.rst.txt @@ -0,0 +1,46 @@ +pyTEMlib.animation +================== + +.. automodule:: pyTEMlib.animation + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + add_aperture + add_lens + deficient_holz_line + deficient_kikuchi_line + geometric_ray_diagram + propagate_beam + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + :nosignatures: + + InteractiveAberration + InteractiveRonchigramMagnification + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.atom_tools.atom_refine.rst.txt b/_sources/_autosummary/pyTEMlib.atom_tools.atom_refine.rst.txt new file mode 100644 index 00000000..dedead2b --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.atom_tools.atom_refine.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.atom\_tools.atom\_refine +================================= + +.. currentmodule:: pyTEMlib.atom_tools + +.. autofunction:: atom_refine \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.atom_tools.atoms_clustering.rst.txt b/_sources/_autosummary/pyTEMlib.atom_tools.atoms_clustering.rst.txt new file mode 100644 index 00000000..9a173c74 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.atom_tools.atoms_clustering.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.atom\_tools.atoms\_clustering +====================================== + +.. currentmodule:: pyTEMlib.atom_tools + +.. autofunction:: atoms_clustering \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.atom_tools.find_atoms.rst.txt b/_sources/_autosummary/pyTEMlib.atom_tools.find_atoms.rst.txt new file mode 100644 index 00000000..adbb5cc9 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.atom_tools.find_atoms.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.atom\_tools.find\_atoms +================================ + +.. currentmodule:: pyTEMlib.atom_tools + +.. autofunction:: find_atoms \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.atom_tools.gauss_difference.rst.txt b/_sources/_autosummary/pyTEMlib.atom_tools.gauss_difference.rst.txt new file mode 100644 index 00000000..a50d876c --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.atom_tools.gauss_difference.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.atom\_tools.gauss\_difference +====================================== + +.. currentmodule:: pyTEMlib.atom_tools + +.. autofunction:: gauss_difference \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.atom_tools.intensity_area.rst.txt b/_sources/_autosummary/pyTEMlib.atom_tools.intensity_area.rst.txt new file mode 100644 index 00000000..13df610c --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.atom_tools.intensity_area.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.atom\_tools.intensity\_area +==================================== + +.. currentmodule:: pyTEMlib.atom_tools + +.. autofunction:: intensity_area \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.atom_tools.rst.txt b/_sources/_autosummary/pyTEMlib.atom_tools.rst.txt new file mode 100644 index 00000000..a708ea16 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.atom_tools.rst.txt @@ -0,0 +1,35 @@ +pyTEMlib.atom\_tools +==================== + +.. automodule:: pyTEMlib.atom_tools + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + atom_refine + atoms_clustering + find_atoms + gauss_difference + intensity_area + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.config_dir.rst.txt b/_sources/_autosummary/pyTEMlib.config_dir.rst.txt new file mode 100644 index 00000000..297e495c --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.config_dir.rst.txt @@ -0,0 +1,23 @@ +pyTEMlib.config\_dir +==================== + +.. automodule:: pyTEMlib.config_dir + + + + + + + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.crystal_tools.atoms_from_dictionary.rst.txt b/_sources/_autosummary/pyTEMlib.crystal_tools.atoms_from_dictionary.rst.txt new file mode 100644 index 00000000..4cb4bae6 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.crystal_tools.atoms_from_dictionary.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.crystal\_tools.atoms\_from\_dictionary +=============================================== + +.. currentmodule:: pyTEMlib.crystal_tools + +.. autofunction:: atoms_from_dictionary \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.crystal_tools.ball_and_stick.rst.txt b/_sources/_autosummary/pyTEMlib.crystal_tools.ball_and_stick.rst.txt new file mode 100644 index 00000000..478a00d6 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.crystal_tools.ball_and_stick.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.crystal\_tools.ball\_and\_stick +======================================== + +.. currentmodule:: pyTEMlib.crystal_tools + +.. autofunction:: ball_and_stick \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.crystal_tools.get_dictionary.rst.txt b/_sources/_autosummary/pyTEMlib.crystal_tools.get_dictionary.rst.txt new file mode 100644 index 00000000..f94bd929 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.crystal_tools.get_dictionary.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.crystal\_tools.get\_dictionary +======================================= + +.. currentmodule:: pyTEMlib.crystal_tools + +.. autofunction:: get_dictionary \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.crystal_tools.get_projection.rst.txt b/_sources/_autosummary/pyTEMlib.crystal_tools.get_projection.rst.txt new file mode 100644 index 00000000..f477aa00 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.crystal_tools.get_projection.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.crystal\_tools.get\_projection +======================================= + +.. currentmodule:: pyTEMlib.crystal_tools + +.. autofunction:: get_projection \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.crystal_tools.get_symmetry.rst.txt b/_sources/_autosummary/pyTEMlib.crystal_tools.get_symmetry.rst.txt new file mode 100644 index 00000000..236fcf63 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.crystal_tools.get_symmetry.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.crystal\_tools.get\_symmetry +===================================== + +.. currentmodule:: pyTEMlib.crystal_tools + +.. autofunction:: get_symmetry \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.crystal_tools.jmol_viewer.rst.txt b/_sources/_autosummary/pyTEMlib.crystal_tools.jmol_viewer.rst.txt new file mode 100644 index 00000000..add4dc97 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.crystal_tools.jmol_viewer.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.crystal\_tools.jmol\_viewer +==================================== + +.. currentmodule:: pyTEMlib.crystal_tools + +.. autofunction:: jmol_viewer \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.crystal_tools.plot_super_cell.rst.txt b/_sources/_autosummary/pyTEMlib.crystal_tools.plot_super_cell.rst.txt new file mode 100644 index 00000000..e81203f1 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.crystal_tools.plot_super_cell.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.crystal\_tools.plot\_super\_cell +========================================= + +.. currentmodule:: pyTEMlib.crystal_tools + +.. autofunction:: plot_super_cell \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.crystal_tools.plot_unit_cell.rst.txt b/_sources/_autosummary/pyTEMlib.crystal_tools.plot_unit_cell.rst.txt new file mode 100644 index 00000000..ec2e2f75 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.crystal_tools.plot_unit_cell.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.crystal\_tools.plot\_unit\_cell +======================================== + +.. currentmodule:: pyTEMlib.crystal_tools + +.. autofunction:: plot_unit_cell \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.crystal_tools.rst.txt b/_sources/_autosummary/pyTEMlib.crystal_tools.rst.txt new file mode 100644 index 00000000..39a0c1cc --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.crystal_tools.rst.txt @@ -0,0 +1,40 @@ +pyTEMlib.crystal\_tools +======================= + +.. automodule:: pyTEMlib.crystal_tools + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + atoms_from_dictionary + ball_and_stick + get_dictionary + get_projection + get_symmetry + jmol_viewer + plot_super_cell + plot_unit_cell + set_bond_radii + structure_by_name + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.crystal_tools.set_bond_radii.rst.txt b/_sources/_autosummary/pyTEMlib.crystal_tools.set_bond_radii.rst.txt new file mode 100644 index 00000000..0cf0454f --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.crystal_tools.set_bond_radii.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.crystal\_tools.set\_bond\_radii +======================================== + +.. currentmodule:: pyTEMlib.crystal_tools + +.. autofunction:: set_bond_radii \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.crystal_tools.structure_by_name.rst.txt b/_sources/_autosummary/pyTEMlib.crystal_tools.structure_by_name.rst.txt new file mode 100644 index 00000000..7cd21459 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.crystal_tools.structure_by_name.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.crystal\_tools.structure\_by\_name +=========================================== + +.. currentmodule:: pyTEMlib.crystal_tools + +.. autofunction:: structure_by_name \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.diffraction_plot.cartesian2polar.rst.txt b/_sources/_autosummary/pyTEMlib.diffraction_plot.cartesian2polar.rst.txt new file mode 100644 index 00000000..edbc6bd6 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.diffraction_plot.cartesian2polar.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.diffraction\_plot.cartesian2polar +========================================== + +.. currentmodule:: pyTEMlib.diffraction_plot + +.. autofunction:: cartesian2polar \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.diffraction_plot.circles.rst.txt b/_sources/_autosummary/pyTEMlib.diffraction_plot.circles.rst.txt new file mode 100644 index 00000000..3115db7f --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.diffraction_plot.circles.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.diffraction\_plot.circles +================================== + +.. currentmodule:: pyTEMlib.diffraction_plot + +.. autofunction:: circles \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.diffraction_plot.plotCBED_parameter.rst.txt b/_sources/_autosummary/pyTEMlib.diffraction_plot.plotCBED_parameter.rst.txt new file mode 100644 index 00000000..8b86d62c --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.diffraction_plot.plotCBED_parameter.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.diffraction\_plot.plotCBED\_parameter +============================================== + +.. currentmodule:: pyTEMlib.diffraction_plot + +.. autofunction:: plotCBED_parameter \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.diffraction_plot.plotHOLZ_parameter.rst.txt b/_sources/_autosummary/pyTEMlib.diffraction_plot.plotHOLZ_parameter.rst.txt new file mode 100644 index 00000000..5d41d318 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.diffraction_plot.plotHOLZ_parameter.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.diffraction\_plot.plotHOLZ\_parameter +============================================== + +.. currentmodule:: pyTEMlib.diffraction_plot + +.. autofunction:: plotHOLZ_parameter \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.diffraction_plot.plotKikuchi.rst.txt b/_sources/_autosummary/pyTEMlib.diffraction_plot.plotKikuchi.rst.txt new file mode 100644 index 00000000..f97ce657 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.diffraction_plot.plotKikuchi.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.diffraction\_plot.plotKikuchi +====================================== + +.. currentmodule:: pyTEMlib.diffraction_plot + +.. autofunction:: plotKikuchi \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.diffraction_plot.plotSAED_parameter.rst.txt b/_sources/_autosummary/pyTEMlib.diffraction_plot.plotSAED_parameter.rst.txt new file mode 100644 index 00000000..d6654478 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.diffraction_plot.plotSAED_parameter.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.diffraction\_plot.plotSAED\_parameter +============================================== + +.. currentmodule:: pyTEMlib.diffraction_plot + +.. autofunction:: plotSAED_parameter \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.diffraction_plot.plot_diffraction_pattern.rst.txt b/_sources/_autosummary/pyTEMlib.diffraction_plot.plot_diffraction_pattern.rst.txt new file mode 100644 index 00000000..518b39e1 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.diffraction_plot.plot_diffraction_pattern.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.diffraction\_plot.plot\_diffraction\_pattern +===================================================== + +.. currentmodule:: pyTEMlib.diffraction_plot + +.. autofunction:: plot_diffraction_pattern \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D.rst.txt b/_sources/_autosummary/pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D.rst.txt new file mode 100644 index 00000000..e7f5ecbf --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.diffraction\_plot.plot\_reciprocal\_unit\_cell\_2D +=========================================================== + +.. currentmodule:: pyTEMlib.diffraction_plot + +.. autofunction:: plot_reciprocal_unit_cell_2D \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.diffraction_plot.plot_ring_pattern.rst.txt b/_sources/_autosummary/pyTEMlib.diffraction_plot.plot_ring_pattern.rst.txt new file mode 100644 index 00000000..434539e7 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.diffraction_plot.plot_ring_pattern.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.diffraction\_plot.plot\_ring\_pattern +============================================== + +.. currentmodule:: pyTEMlib.diffraction_plot + +.. autofunction:: plot_ring_pattern \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.diffraction_plot.rst.txt b/_sources/_autosummary/pyTEMlib.diffraction_plot.rst.txt new file mode 100644 index 00000000..a3690ac8 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.diffraction_plot.rst.txt @@ -0,0 +1,41 @@ +pyTEMlib.diffraction\_plot +========================== + +.. automodule:: pyTEMlib.diffraction_plot + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + cartesian2polar + circles + plotCBED_parameter + plotHOLZ_parameter + plotKikuchi + plotSAED_parameter + plot_diffraction_pattern + plot_reciprocal_unit_cell_2D + plot_ring_pattern + topolar + warp + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.diffraction_plot.topolar.rst.txt b/_sources/_autosummary/pyTEMlib.diffraction_plot.topolar.rst.txt new file mode 100644 index 00000000..619a14a1 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.diffraction_plot.topolar.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.diffraction\_plot.topolar +================================== + +.. currentmodule:: pyTEMlib.diffraction_plot + +.. autofunction:: topolar \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.diffraction_plot.warp.rst.txt b/_sources/_autosummary/pyTEMlib.diffraction_plot.warp.rst.txt new file mode 100644 index 00000000..a9f9ad31 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.diffraction_plot.warp.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.diffraction\_plot.warp +=============================== + +.. currentmodule:: pyTEMlib.diffraction_plot + +.. autofunction:: warp \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.dynamic_scattering.get_propagator.rst.txt b/_sources/_autosummary/pyTEMlib.dynamic_scattering.get_propagator.rst.txt new file mode 100644 index 00000000..4ca99d19 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.dynamic_scattering.get_propagator.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.dynamic\_scattering.get\_propagator +============================================ + +.. currentmodule:: pyTEMlib.dynamic_scattering + +.. autofunction:: get_propagator \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.dynamic_scattering.get_transmission.rst.txt b/_sources/_autosummary/pyTEMlib.dynamic_scattering.get_transmission.rst.txt new file mode 100644 index 00000000..71648703 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.dynamic_scattering.get_transmission.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.dynamic\_scattering.get\_transmission +============================================== + +.. currentmodule:: pyTEMlib.dynamic_scattering + +.. autofunction:: get_transmission \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.dynamic_scattering.interaction_parameter.rst.txt b/_sources/_autosummary/pyTEMlib.dynamic_scattering.interaction_parameter.rst.txt new file mode 100644 index 00000000..95fc5323 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.dynamic_scattering.interaction_parameter.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.dynamic\_scattering.interaction\_parameter +=================================================== + +.. currentmodule:: pyTEMlib.dynamic_scattering + +.. autofunction:: interaction_parameter \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.dynamic_scattering.make_chi.rst.txt b/_sources/_autosummary/pyTEMlib.dynamic_scattering.make_chi.rst.txt new file mode 100644 index 00000000..d53b65f3 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.dynamic_scattering.make_chi.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.dynamic\_scattering.make\_chi +====================================== + +.. currentmodule:: pyTEMlib.dynamic_scattering + +.. autofunction:: make_chi \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.dynamic_scattering.multi_slice.rst.txt b/_sources/_autosummary/pyTEMlib.dynamic_scattering.multi_slice.rst.txt new file mode 100644 index 00000000..6e2132ca --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.dynamic_scattering.multi_slice.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.dynamic\_scattering.multi\_slice +========================================= + +.. currentmodule:: pyTEMlib.dynamic_scattering + +.. autofunction:: multi_slice \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.dynamic_scattering.objective_lens_function.rst.txt b/_sources/_autosummary/pyTEMlib.dynamic_scattering.objective_lens_function.rst.txt new file mode 100644 index 00000000..da7fc06b --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.dynamic_scattering.objective_lens_function.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.dynamic\_scattering.objective\_lens\_function +====================================================== + +.. currentmodule:: pyTEMlib.dynamic_scattering + +.. autofunction:: objective_lens_function \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.dynamic_scattering.potential_1dim.rst.txt b/_sources/_autosummary/pyTEMlib.dynamic_scattering.potential_1dim.rst.txt new file mode 100644 index 00000000..11040431 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.dynamic_scattering.potential_1dim.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.dynamic\_scattering.potential\_1dim +============================================ + +.. currentmodule:: pyTEMlib.dynamic_scattering + +.. autofunction:: potential_1dim \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.dynamic_scattering.potential_2dim.rst.txt b/_sources/_autosummary/pyTEMlib.dynamic_scattering.potential_2dim.rst.txt new file mode 100644 index 00000000..da804173 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.dynamic_scattering.potential_2dim.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.dynamic\_scattering.potential\_2dim +============================================ + +.. currentmodule:: pyTEMlib.dynamic_scattering + +.. autofunction:: potential_2dim \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.dynamic_scattering.rst.txt b/_sources/_autosummary/pyTEMlib.dynamic_scattering.rst.txt new file mode 100644 index 00000000..30331076 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.dynamic_scattering.rst.txt @@ -0,0 +1,38 @@ +pyTEMlib.dynamic\_scattering +============================ + +.. automodule:: pyTEMlib.dynamic_scattering + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + get_propagator + get_transmission + interaction_parameter + make_chi + multi_slice + objective_lens_function + potential_1dim + potential_2dim + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.eds_tools.detect_peaks.rst.txt b/_sources/_autosummary/pyTEMlib.eds_tools.detect_peaks.rst.txt new file mode 100644 index 00000000..8a772781 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eds_tools.detect_peaks.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eds\_tools.detect\_peaks +================================= + +.. currentmodule:: pyTEMlib.eds_tools + +.. autofunction:: detect_peaks \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eds_tools.detector_response.rst.txt b/_sources/_autosummary/pyTEMlib.eds_tools.detector_response.rst.txt new file mode 100644 index 00000000..89c599b3 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eds_tools.detector_response.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eds\_tools.detector\_response +====================================== + +.. currentmodule:: pyTEMlib.eds_tools + +.. autofunction:: detector_response \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eds_tools.find_elements.rst.txt b/_sources/_autosummary/pyTEMlib.eds_tools.find_elements.rst.txt new file mode 100644 index 00000000..ff769edb --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eds_tools.find_elements.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eds\_tools.find\_elements +================================== + +.. currentmodule:: pyTEMlib.eds_tools + +.. autofunction:: find_elements \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eds_tools.fit_model.rst.txt b/_sources/_autosummary/pyTEMlib.eds_tools.fit_model.rst.txt new file mode 100644 index 00000000..88f1783b --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eds_tools.fit_model.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eds\_tools.fit\_model +============================== + +.. currentmodule:: pyTEMlib.eds_tools + +.. autofunction:: fit_model \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eds_tools.gaussian.rst.txt b/_sources/_autosummary/pyTEMlib.eds_tools.gaussian.rst.txt new file mode 100644 index 00000000..ecf7bfd6 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eds_tools.gaussian.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eds\_tools.gaussian +============================ + +.. currentmodule:: pyTEMlib.eds_tools + +.. autofunction:: gaussian \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eds_tools.getFWHM.rst.txt b/_sources/_autosummary/pyTEMlib.eds_tools.getFWHM.rst.txt new file mode 100644 index 00000000..fef7f5ac --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eds_tools.getFWHM.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eds\_tools.getFWHM +=========================== + +.. currentmodule:: pyTEMlib.eds_tools + +.. autofunction:: getFWHM \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eds_tools.get_eds_cross_sections.rst.txt b/_sources/_autosummary/pyTEMlib.eds_tools.get_eds_cross_sections.rst.txt new file mode 100644 index 00000000..1f825a8f --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eds_tools.get_eds_cross_sections.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eds\_tools.get\_eds\_cross\_sections +============================================= + +.. currentmodule:: pyTEMlib.eds_tools + +.. autofunction:: get_eds_cross_sections \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eds_tools.get_eds_xsection.rst.txt b/_sources/_autosummary/pyTEMlib.eds_tools.get_eds_xsection.rst.txt new file mode 100644 index 00000000..001de3a6 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eds_tools.get_eds_xsection.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eds\_tools.get\_eds\_xsection +====================================== + +.. currentmodule:: pyTEMlib.eds_tools + +.. autofunction:: get_eds_xsection \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eds_tools.get_model.rst.txt b/_sources/_autosummary/pyTEMlib.eds_tools.get_model.rst.txt new file mode 100644 index 00000000..75a890f3 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eds_tools.get_model.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eds\_tools.get\_model +============================== + +.. currentmodule:: pyTEMlib.eds_tools + +.. autofunction:: get_model \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eds_tools.get_peak.rst.txt b/_sources/_autosummary/pyTEMlib.eds_tools.get_peak.rst.txt new file mode 100644 index 00000000..b47e7509 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eds_tools.get_peak.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eds\_tools.get\_peak +============================= + +.. currentmodule:: pyTEMlib.eds_tools + +.. autofunction:: get_peak \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eds_tools.get_x_ray_lines.rst.txt b/_sources/_autosummary/pyTEMlib.eds_tools.get_x_ray_lines.rst.txt new file mode 100644 index 00000000..0a94d744 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eds_tools.get_x_ray_lines.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eds\_tools.get\_x\_ray\_lines +====================================== + +.. currentmodule:: pyTEMlib.eds_tools + +.. autofunction:: get_x_ray_lines \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eds_tools.rst.txt b/_sources/_autosummary/pyTEMlib.eds_tools.rst.txt new file mode 100644 index 00000000..098fc29a --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eds_tools.rst.txt @@ -0,0 +1,42 @@ +pyTEMlib.eds\_tools +=================== + +.. automodule:: pyTEMlib.eds_tools + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + detect_peaks + detector_response + find_elements + fit_model + gaussian + getFWHM + get_eds_cross_sections + get_eds_xsection + get_model + get_peak + get_x_ray_lines + update_fit_values + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.eds_tools.update_fit_values.rst.txt b/_sources/_autosummary/pyTEMlib.eds_tools.update_fit_values.rst.txt new file mode 100644 index 00000000..23cd5292 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eds_tools.update_fit_values.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eds\_tools.update\_fit\_values +======================================= + +.. currentmodule:: pyTEMlib.eds_tools + +.. autofunction:: update_fit_values \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog.CompositionWidget.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog.CompositionWidget.rst.txt new file mode 100644 index 00000000..397e1bbb --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog.CompositionWidget.rst.txt @@ -0,0 +1,46 @@ +pyTEMlib.eels\_dialog.CompositionWidget +======================================= + +.. currentmodule:: pyTEMlib.eels_dialog + +.. autoclass:: CompositionWidget + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~CompositionWidget.auto_id + ~CompositionWidget.cursor2energy_scale + ~CompositionWidget.do_fit + ~CompositionWidget.find_elements + ~CompositionWidget.line_select_callback + ~CompositionWidget.modify_areal_density + ~CompositionWidget.modify_end_exclude + ~CompositionWidget.modify_onset + ~CompositionWidget.modify_start_exclude + ~CompositionWidget.plot + ~CompositionWidget.plot_regions + ~CompositionWidget.set_action + ~CompositionWidget.set_dataset + ~CompositionWidget.set_element + ~CompositionWidget.set_elements + ~CompositionWidget.set_figure_pane + ~CompositionWidget.set_fit_area + ~CompositionWidget.set_y_scale + ~CompositionWidget.show_edges + ~CompositionWidget.sort_elements + ~CompositionWidget.update + ~CompositionWidget.update_element + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog.get_sidebar.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog.get_sidebar.rst.txt new file mode 100644 index 00000000..9883a874 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog.get_sidebar.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_dialog.get\_sidebar +================================== + +.. currentmodule:: pyTEMlib.eels_dialog + +.. autofunction:: get_sidebar \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog.rst.txt new file mode 100644 index 00000000..90ed4998 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog.rst.txt @@ -0,0 +1,40 @@ +pyTEMlib.eels\_dialog +===================== + +.. automodule:: pyTEMlib.eels_dialog + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + get_sidebar + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + :nosignatures: + + CompositionWidget + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.EdgesAtCursor.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.EdgesAtCursor.rst.txt new file mode 100644 index 00000000..2a77ee32 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.EdgesAtCursor.rst.txt @@ -0,0 +1,28 @@ +pyTEMlib.eels\_dialog\_utilities.EdgesAtCursor +============================================== + +.. currentmodule:: pyTEMlib.eels_dialog_utilities + +.. autoclass:: EdgesAtCursor + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~EdgesAtCursor.click + ~EdgesAtCursor.del_edges + ~EdgesAtCursor.disconnect + ~EdgesAtCursor.mouse_move + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.ElementalEdges.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.ElementalEdges.rst.txt new file mode 100644 index 00000000..65ae1b99 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.ElementalEdges.rst.txt @@ -0,0 +1,29 @@ +pyTEMlib.eels\_dialog\_utilities.ElementalEdges +=============================================== + +.. currentmodule:: pyTEMlib.eels_dialog_utilities + +.. autoclass:: ElementalEdges + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~ElementalEdges.disconnect + ~ElementalEdges.onresize + ~ElementalEdges.reconnect + ~ElementalEdges.set_edge + ~ElementalEdges.update + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage.rst.txt new file mode 100644 index 00000000..2f0526bb --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage.rst.txt @@ -0,0 +1,39 @@ +pyTEMlib.eels\_dialog\_utilities.InteractiveSpectrumImage +========================================================= + +.. currentmodule:: pyTEMlib.eels_dialog_utilities + +.. autoclass:: InteractiveSpectrumImage + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~InteractiveSpectrumImage.do_all + ~InteractiveSpectrumImage.fit_quantification + ~InteractiveSpectrumImage.fit_zero_loss + ~InteractiveSpectrumImage.fix_energy + ~InteractiveSpectrumImage.get_current_spectrum + ~InteractiveSpectrumImage.get_xy + ~InteractiveSpectrumImage.on_button_clicked + ~InteractiveSpectrumImage.onclick + ~InteractiveSpectrumImage.overlay_data + ~InteractiveSpectrumImage.overlay_z_contrast_image + ~InteractiveSpectrumImage.set_legend + ~InteractiveSpectrumImage.set_survey_image + ~InteractiveSpectrumImage.set_tags + ~InteractiveSpectrumImage.set_z_contrast_image + ~InteractiveSpectrumImage.update + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.PeriodicTableWidget.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.PeriodicTableWidget.rst.txt new file mode 100644 index 00000000..bec72aed --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.PeriodicTableWidget.rst.txt @@ -0,0 +1,26 @@ +pyTEMlib.eels\_dialog\_utilities.PeriodicTableWidget +==================================================== + +.. currentmodule:: pyTEMlib.eels_dialog_utilities + +.. autoclass:: PeriodicTableWidget + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~PeriodicTableWidget.get_output + ~PeriodicTableWidget.update + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.RangeSelector.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.RangeSelector.rst.txt new file mode 100644 index 00000000..88dbb02d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.RangeSelector.rst.txt @@ -0,0 +1,63 @@ +pyTEMlib.eels\_dialog\_utilities.RangeSelector +============================================== + +.. currentmodule:: pyTEMlib.eels_dialog_utilities + +.. autoclass:: RangeSelector + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~RangeSelector.add_state + ~RangeSelector.clear + ~RangeSelector.connect_default_events + ~RangeSelector.connect_event + ~RangeSelector.disconnect_events + ~RangeSelector.draw_shape + ~RangeSelector.get_active + ~RangeSelector.get_visible + ~RangeSelector.ignore + ~RangeSelector.on_key_press + ~RangeSelector.on_key_release + ~RangeSelector.on_scroll + ~RangeSelector.onmove + ~RangeSelector.press + ~RangeSelector.release + ~RangeSelector.remove_state + ~RangeSelector.set_active + ~RangeSelector.set_handle_props + ~RangeSelector.set_props + ~RangeSelector.set_visible + ~RangeSelector.update + ~RangeSelector.update_background + + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~RangeSelector.active + ~RangeSelector.artists + ~RangeSelector.center + ~RangeSelector.corners + ~RangeSelector.drawon + ~RangeSelector.edge_centers + ~RangeSelector.eventson + ~RangeSelector.extents + ~RangeSelector.geometry + ~RangeSelector.rotation + ~RangeSelector.state_modifier_keys + ~RangeSelector.visible + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.RegionSelector.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.RegionSelector.rst.txt new file mode 100644 index 00000000..3c9be1dd --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.RegionSelector.rst.txt @@ -0,0 +1,32 @@ +pyTEMlib.eels\_dialog\_utilities.RegionSelector +=============================================== + +.. currentmodule:: pyTEMlib.eels_dialog_utilities + +.. autoclass:: RegionSelector + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~RegionSelector.click + ~RegionSelector.delete_region + ~RegionSelector.disconnect + ~RegionSelector.get_regions + ~RegionSelector.on_select1 + ~RegionSelector.onresize + ~RegionSelector.set_regions + ~RegionSelector.update + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.SIPlot.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.SIPlot.rst.txt new file mode 100644 index 00000000..20e24f62 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.SIPlot.rst.txt @@ -0,0 +1,30 @@ +pyTEMlib.eels\_dialog\_utilities.SIPlot +======================================= + +.. currentmodule:: pyTEMlib.eels_dialog_utilities + +.. autoclass:: SIPlot + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~SIPlot.get_spectrum + ~SIPlot.get_xy + ~SIPlot.line_select_callback + ~SIPlot.plot + ~SIPlot.set_bin + ~SIPlot.set_legend + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.SpectrumPlot.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.SpectrumPlot.rst.txt new file mode 100644 index 00000000..94ea26ec --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.SpectrumPlot.rst.txt @@ -0,0 +1,26 @@ +pyTEMlib.eels\_dialog\_utilities.SpectrumPlot +============================================= + +.. currentmodule:: pyTEMlib.eels_dialog_utilities + +.. autoclass:: SpectrumPlot + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~SpectrumPlot.line_select_callback + ~SpectrumPlot.plot + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.get_likely_edges.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.get_likely_edges.rst.txt new file mode 100644 index 00000000..602d6bc3 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.get_likely_edges.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_dialog\_utilities.get\_likely\_edges +=================================================== + +.. currentmodule:: pyTEMlib.eels_dialog_utilities + +.. autofunction:: get_likely_edges \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_info.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_info.rst.txt new file mode 100644 index 00000000..5211a730 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_info.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_dialog\_utilities.get\_periodic\_table\_info +=========================================================== + +.. currentmodule:: pyTEMlib.eels_dialog_utilities + +.. autofunction:: get_periodic_table_info \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_widget.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_widget.rst.txt new file mode 100644 index 00000000..01c432e7 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_widget.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_dialog\_utilities.get\_periodic\_table\_widget +============================================================= + +.. currentmodule:: pyTEMlib.eels_dialog_utilities + +.. autofunction:: get_periodic_table_widget \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.make_box_layout.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.make_box_layout.rst.txt new file mode 100644 index 00000000..1e5bb5eb --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.make_box_layout.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_dialog\_utilities.make\_box\_layout +================================================== + +.. currentmodule:: pyTEMlib.eels_dialog_utilities + +.. autofunction:: make_box_layout \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.plot_EELS.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.plot_EELS.rst.txt new file mode 100644 index 00000000..c83f6fa7 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.plot_EELS.rst.txt @@ -0,0 +1,86 @@ +pyTEMlib.eels\_dialog\_utilities.plot\_EELS +=========================================== + +.. currentmodule:: pyTEMlib.eels_dialog_utilities + +.. autoclass:: plot_EELS + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~plot_EELS.add_class + ~plot_EELS.add_traits + ~plot_EELS.blur + ~plot_EELS.class_own_trait_events + ~plot_EELS.class_own_traits + ~plot_EELS.class_trait_names + ~plot_EELS.class_traits + ~plot_EELS.close + ~plot_EELS.close_all + ~plot_EELS.focus + ~plot_EELS.get_manager_state + ~plot_EELS.get_state + ~plot_EELS.get_view_spec + ~plot_EELS.handle_comm_opened + ~plot_EELS.handle_control_comm_opened + ~plot_EELS.has_trait + ~plot_EELS.hold_sync + ~plot_EELS.hold_trait_notifications + ~plot_EELS.line_color + ~plot_EELS.notify_change + ~plot_EELS.observe + ~plot_EELS.on_legend_pick + ~plot_EELS.on_msg + ~plot_EELS.on_trait_change + ~plot_EELS.on_widget_constructed + ~plot_EELS.open + ~plot_EELS.remove_class + ~plot_EELS.send + ~plot_EELS.send_state + ~plot_EELS.set_dimension + ~plot_EELS.set_state + ~plot_EELS.set_trait + ~plot_EELS.setup_instance + ~plot_EELS.trait_defaults + ~plot_EELS.trait_events + ~plot_EELS.trait_has_value + ~plot_EELS.trait_metadata + ~plot_EELS.trait_names + ~plot_EELS.trait_values + ~plot_EELS.traits + ~plot_EELS.unobserve + ~plot_EELS.unobserve_all + ~plot_EELS.update + ~plot_EELS.update_exposure + ~plot_EELS.update_ylabel + + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~plot_EELS.box_style + ~plot_EELS.children + ~plot_EELS.comm + ~plot_EELS.cross_validation_lock + ~plot_EELS.keys + ~plot_EELS.layout + ~plot_EELS.log + ~plot_EELS.model_id + ~plot_EELS.tabbable + ~plot_EELS.tooltip + ~plot_EELS.widget_types + ~plot_EELS.widgets + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.rst.txt new file mode 100644 index 00000000..3723e658 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dialog_utilities.rst.txt @@ -0,0 +1,51 @@ +pyTEMlib.eels\_dialog\_utilities +================================ + +.. automodule:: pyTEMlib.eels_dialog_utilities + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + get_likely_edges + get_periodic_table_info + get_periodic_table_widget + make_box_layout + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + :nosignatures: + + EdgesAtCursor + ElementalEdges + InteractiveSpectrumImage + PeriodicTableWidget + RangeSelector + RegionSelector + SIPlot + SpectrumPlot + plot_EELS + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.eels_dlg.rst.txt b/_sources/_autosummary/pyTEMlib.eels_dlg.rst.txt new file mode 100644 index 00000000..41cf67e2 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_dlg.rst.txt @@ -0,0 +1,23 @@ +pyTEMlib.eels\_dlg +================== + +.. automodule:: pyTEMlib.eels_dlg + + + + + + + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.add_element_to_dataset.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.add_element_to_dataset.rst.txt new file mode 100644 index 00000000..de63bcc2 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.add_element_to_dataset.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.add\_element\_to\_dataset +============================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: add_element_to_dataset \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.add_peaks.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.add_peaks.rst.txt new file mode 100644 index 00000000..9ee240f0 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.add_peaks.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.add\_peaks +=============================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: add_peaks \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.assign_likely_edges.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.assign_likely_edges.rst.txt new file mode 100644 index 00000000..98056bbe --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.assign_likely_edges.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.assign\_likely\_edges +========================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: assign_likely_edges \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.auto_chemical_composition.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.auto_chemical_composition.rst.txt new file mode 100644 index 00000000..62703122 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.auto_chemical_composition.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.auto\_chemical\_composition +================================================ + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: auto_chemical_composition \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.auto_id_edges.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.auto_id_edges.rst.txt new file mode 100644 index 00000000..84cef14b --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.auto_id_edges.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.auto\_id\_edges +==================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: auto_id_edges \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.cl_model.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.cl_model.rst.txt new file mode 100644 index 00000000..32e333b8 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.cl_model.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.cl\_model +============================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: cl_model \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.drude.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.drude.rst.txt new file mode 100644 index 00000000..1582134a --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.drude.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.drude +========================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: drude \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.drude2.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.drude2.rst.txt new file mode 100644 index 00000000..30cd8c33 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.drude2.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.drude2 +=========================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: drude2 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.drude_lorentz.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.drude_lorentz.rst.txt new file mode 100644 index 00000000..0a062e2b --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.drude_lorentz.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.drude\_lorentz +=================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: drude_lorentz \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.drude_simulation.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.drude_simulation.rst.txt new file mode 100644 index 00000000..9c1a5154 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.drude_simulation.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.drude\_simulation +====================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: drude_simulation \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.effective_collection_angle.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.effective_collection_angle.rst.txt new file mode 100644 index 00000000..afa12dbe --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.effective_collection_angle.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.effective\_collection\_angle +================================================= + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: effective_collection_angle \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.find_all_edges.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.find_all_edges.rst.txt new file mode 100644 index 00000000..966dc630 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.find_all_edges.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.find\_all\_edges +===================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: find_all_edges \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.find_associated_edges.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.find_associated_edges.rst.txt new file mode 100644 index 00000000..272d9b12 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.find_associated_edges.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.find\_associated\_edges +============================================ + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: find_associated_edges \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.find_edges.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.find_edges.rst.txt new file mode 100644 index 00000000..ec67e018 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.find_edges.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.find\_edges +================================ + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: find_edges \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.find_major_edges.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.find_major_edges.rst.txt new file mode 100644 index 00000000..4ef6c0dd --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.find_major_edges.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.find\_major\_edges +======================================= + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: find_major_edges \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.find_maxima.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.find_maxima.rst.txt new file mode 100644 index 00000000..0b6e55cc --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.find_maxima.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.find\_maxima +================================= + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: find_maxima \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.find_peaks.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.find_peaks.rst.txt new file mode 100644 index 00000000..73812475 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.find_peaks.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.find\_peaks +================================ + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: find_peaks \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.find_white_lines.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.find_white_lines.rst.txt new file mode 100644 index 00000000..3c7b530d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.find_white_lines.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.find\_white\_lines +======================================= + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: find_white_lines \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.fit_dataset.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.fit_dataset.rst.txt new file mode 100644 index 00000000..7175d063 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.fit_dataset.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.fit\_dataset +================================= + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: fit_dataset \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.fit_edges.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.fit_edges.rst.txt new file mode 100644 index 00000000..76573b77 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.fit_edges.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.fit\_edges +=============================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: fit_edges \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.fit_edges2.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.fit_edges2.rst.txt new file mode 100644 index 00000000..663b4194 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.fit_edges2.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.fit\_edges2 +================================ + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: fit_edges2 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.fit_model.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.fit_model.rst.txt new file mode 100644 index 00000000..19c41411 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.fit_model.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.fit\_model +=============================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: fit_model \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.fit_peaks.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.fit_peaks.rst.txt new file mode 100644 index 00000000..92342eb3 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.fit_peaks.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.fit\_peaks +=============================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: fit_peaks \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.fix_energy_scale.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.fix_energy_scale.rst.txt new file mode 100644 index 00000000..9fdded95 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.fix_energy_scale.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.fix\_energy\_scale +======================================= + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: fix_energy_scale \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.gauss.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.gauss.rst.txt new file mode 100644 index 00000000..d6162f6c --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.gauss.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.gauss +========================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: gauss \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.get_energy_shifts.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.get_energy_shifts.rst.txt new file mode 100644 index 00000000..ec0de2f9 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.get_energy_shifts.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.get\_energy\_shifts +======================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: get_energy_shifts \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.get_resolution_functions.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.get_resolution_functions.rst.txt new file mode 100644 index 00000000..fd12f425 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.get_resolution_functions.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.get\_resolution\_functions +=============================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: get_resolution_functions \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.get_spectrum_eels_db.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.get_spectrum_eels_db.rst.txt new file mode 100644 index 00000000..9a07b093 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.get_spectrum_eels_db.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.get\_spectrum\_eels\_db +============================================ + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: get_spectrum_eels_db \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.get_wave_length.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.get_wave_length.rst.txt new file mode 100644 index 00000000..2acae613 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.get_wave_length.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.get\_wave\_length +====================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: get_wave_length \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.get_x_sections.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.get_x_sections.rst.txt new file mode 100644 index 00000000..c72bf392 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.get_x_sections.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.get\_x\_sections +===================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: get_x_sections \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.get_z.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.get_z.rst.txt new file mode 100644 index 00000000..d2052d83 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.get_z.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.get\_z +=========================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: get_z \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.identify_edges.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.identify_edges.rst.txt new file mode 100644 index 00000000..16fb5c56 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.identify_edges.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.identify\_edges +==================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: identify_edges \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.kroeger_core.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.kroeger_core.rst.txt new file mode 100644 index 00000000..f86d9ac7 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.kroeger_core.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.kroeger\_core +================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: kroeger_core \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.kroeger_core2.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.kroeger_core2.rst.txt new file mode 100644 index 00000000..5b091270 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.kroeger_core2.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.kroeger\_core2 +=================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: kroeger_core2 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.list_all_edges.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.list_all_edges.rst.txt new file mode 100644 index 00000000..3def7328 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.list_all_edges.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.list\_all\_edges +===================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: list_all_edges \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.lorentz.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.lorentz.rst.txt new file mode 100644 index 00000000..313c63d6 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.lorentz.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.lorentz +============================ + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: lorentz \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.make_cross_sections.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.make_cross_sections.rst.txt new file mode 100644 index 00000000..ab123d54 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.make_cross_sections.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.make\_cross\_sections +========================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: make_cross_sections \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.make_edges.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.make_edges.rst.txt new file mode 100644 index 00000000..f5b60916 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.make_edges.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.make\_edges +================================ + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: make_edges \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.model3.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.model3.rst.txt new file mode 100644 index 00000000..4fbdba49 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.model3.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.model3 +=========================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: model3 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.model_ll.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.model_ll.rst.txt new file mode 100644 index 00000000..892360e9 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.model_ll.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.model\_ll +============================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: model_ll \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.model_smooth.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.model_smooth.rst.txt new file mode 100644 index 00000000..2ec45965 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.model_smooth.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.model\_smooth +================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: model_smooth \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.plot_dispersion.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.plot_dispersion.rst.txt new file mode 100644 index 00000000..d09a2208 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.plot_dispersion.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.plot\_dispersion +===================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: plot_dispersion \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.power_law.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.power_law.rst.txt new file mode 100644 index 00000000..ca0bc8a7 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.power_law.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.power\_law +=============================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: power_law \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.power_law_background.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.power_law_background.rst.txt new file mode 100644 index 00000000..454e043a --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.power_law_background.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.power\_law\_background +=========================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: power_law_background \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.read_msa.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.read_msa.rst.txt new file mode 100644 index 00000000..f658011c --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.read_msa.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.read\_msa +============================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: read_msa \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.residuals_ll.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.residuals_ll.rst.txt new file mode 100644 index 00000000..bf01d371 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.residuals_ll.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.residuals\_ll +================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: residuals_ll \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.residuals_ll2.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.residuals_ll2.rst.txt new file mode 100644 index 00000000..140ed51d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.residuals_ll2.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.residuals\_ll2 +=================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: residuals_ll2 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.residuals_smooth.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.residuals_smooth.rst.txt new file mode 100644 index 00000000..efdbaa5d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.residuals_smooth.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.residuals\_smooth +====================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: residuals_smooth \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.resolution_function.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.resolution_function.rst.txt new file mode 100644 index 00000000..d6e7982d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.resolution_function.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.resolution\_function +========================================= + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: resolution_function \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.resolution_function2.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.resolution_function2.rst.txt new file mode 100644 index 00000000..e0c961af --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.resolution_function2.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.resolution\_function2 +========================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: resolution_function2 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.rst.txt new file mode 100644 index 00000000..b70b6abf --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.rst.txt @@ -0,0 +1,87 @@ +pyTEMlib.eels\_tools +==================== + +.. automodule:: pyTEMlib.eels_tools + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + add_element_to_dataset + add_peaks + assign_likely_edges + auto_chemical_composition + auto_id_edges + cl_model + drude + drude2 + drude_lorentz + drude_simulation + effective_collection_angle + find_all_edges + find_associated_edges + find_edges + find_major_edges + find_maxima + find_peaks + find_white_lines + fit_dataset + fit_edges + fit_edges2 + fit_model + fit_peaks + fix_energy_scale + gauss + get_energy_shifts + get_resolution_functions + get_spectrum_eels_db + get_wave_length + get_x_sections + get_z + identify_edges + kroeger_core + kroeger_core2 + list_all_edges + lorentz + make_cross_sections + make_edges + model3 + model_ll + model_smooth + plot_dispersion + power_law + power_law_background + read_msa + residuals_ll + residuals_ll2 + residuals_smooth + resolution_function + resolution_function2 + second_derivative + set_previous_quantification + shift_on_same_scale + sort_peaks + xsec_xrpa + zl + zl_func + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.second_derivative.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.second_derivative.rst.txt new file mode 100644 index 00000000..78d8b57b --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.second_derivative.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.second\_derivative +======================================= + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: second_derivative \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.set_previous_quantification.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.set_previous_quantification.rst.txt new file mode 100644 index 00000000..5be4200a --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.set_previous_quantification.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.set\_previous\_quantification +================================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: set_previous_quantification \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.shift_on_same_scale.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.shift_on_same_scale.rst.txt new file mode 100644 index 00000000..d46e248e --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.shift_on_same_scale.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.shift\_on\_same\_scale +=========================================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: shift_on_same_scale \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.sort_peaks.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.sort_peaks.rst.txt new file mode 100644 index 00000000..b8d11b8d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.sort_peaks.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.sort\_peaks +================================ + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: sort_peaks \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.xsec_xrpa.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.xsec_xrpa.rst.txt new file mode 100644 index 00000000..1c407fb7 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.xsec_xrpa.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.xsec\_xrpa +=============================== + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: xsec_xrpa \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.zl.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.zl.rst.txt new file mode 100644 index 00000000..e79d3ea5 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.zl.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.zl +======================= + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: zl \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.eels_tools.zl_func.rst.txt b/_sources/_autosummary/pyTEMlib.eels_tools.zl_func.rst.txt new file mode 100644 index 00000000..ba927997 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.eels_tools.zl_func.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.eels\_tools.zl\_func +============================= + +.. currentmodule:: pyTEMlib.eels_tools + +.. autofunction:: zl_func \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.ChooseDataset.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.ChooseDataset.rst.txt new file mode 100644 index 00000000..be76e356 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.ChooseDataset.rst.txt @@ -0,0 +1,26 @@ +pyTEMlib.file\_tools.ChooseDataset +================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autoclass:: ChooseDataset + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~ChooseDataset.get_dataset_list + ~ChooseDataset.set_dataset + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.FileWidget.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.FileWidget.rst.txt new file mode 100644 index 00000000..7a07ab6c --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.FileWidget.rst.txt @@ -0,0 +1,31 @@ +pyTEMlib.file\_tools.FileWidget +=============================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autoclass:: FileWidget + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~FileWidget.add_dataset + ~FileWidget.get_directory + ~FileWidget.get_file_name + ~FileWidget.select_main + ~FileWidget.selected_dataset + ~FileWidget.set_dir + ~FileWidget.set_options + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.add_dataset_from_file.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.add_dataset_from_file.rst.txt new file mode 100644 index 00000000..7b97a96d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.add_dataset_from_file.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.add\_dataset\_from\_file +============================================= + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: add_dataset_from_file \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.add_to_dict.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.add_to_dict.rst.txt new file mode 100644 index 00000000..5fea96d7 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.add_to_dict.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.add\_to\_dict +================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: add_to_dict \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.get_h5_filename.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.get_h5_filename.rst.txt new file mode 100644 index 00000000..216771e2 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.get_h5_filename.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.get\_h5\_filename +====================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: get_h5_filename \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.get_last_path.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.get_last_path.rst.txt new file mode 100644 index 00000000..797c532c --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.get_last_path.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.get\_last\_path +==================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: get_last_path \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.get_main_channel.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.get_main_channel.rst.txt new file mode 100644 index 00000000..c2af099d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.get_main_channel.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.get\_main\_channel +======================================= + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: get_main_channel \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.get_start_channel.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.get_start_channel.rst.txt new file mode 100644 index 00000000..48e1b3d3 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.get_start_channel.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.get\_start\_channel +======================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: get_start_channel \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.h5_add_crystal_structure.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.h5_add_crystal_structure.rst.txt new file mode 100644 index 00000000..3c47dd53 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.h5_add_crystal_structure.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.h5\_add\_crystal\_structure +================================================ + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: h5_add_crystal_structure \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.h5_add_to_structure.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.h5_add_to_structure.rst.txt new file mode 100644 index 00000000..1711bdd5 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.h5_add_to_structure.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.h5\_add\_to\_structure +=========================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: h5_add_to_structure \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.h5_get_crystal_structure.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.h5_get_crystal_structure.rst.txt new file mode 100644 index 00000000..27225f49 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.h5_get_crystal_structure.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.h5\_get\_crystal\_structure +================================================ + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: h5_get_crystal_structure \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.h5_group_to_dict.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.h5_group_to_dict.rst.txt new file mode 100644 index 00000000..7050f1bc --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.h5_group_to_dict.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.h5\_group\_to\_dict +======================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: h5_group_to_dict \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.h5_tree.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.h5_tree.rst.txt new file mode 100644 index 00000000..581e2263 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.h5_tree.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.h5\_tree +============================= + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: h5_tree \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.log_results.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.log_results.rst.txt new file mode 100644 index 00000000..9b85fc9c --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.log_results.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.log\_results +================================= + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: log_results \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.open_file.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.open_file.rst.txt new file mode 100644 index 00000000..1ca5b36e --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.open_file.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.open\_file +=============================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: open_file \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.open_file_dialog_qt.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.open_file_dialog_qt.rst.txt new file mode 100644 index 00000000..f159d449 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.open_file_dialog_qt.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.open\_file\_dialog\_qt +=========================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: open_file_dialog_qt \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.read_cif.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.read_cif.rst.txt new file mode 100644 index 00000000..07d67621 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.read_cif.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.read\_cif +============================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: read_cif \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.read_dm3_info.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.read_dm3_info.rst.txt new file mode 100644 index 00000000..e6683d7e --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.read_dm3_info.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.read\_dm3\_info +==================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: read_dm3_info \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.read_essential_metadata.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.read_essential_metadata.rst.txt new file mode 100644 index 00000000..f3dad1f1 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.read_essential_metadata.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.read\_essential\_metadata +============================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: read_essential_metadata \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.read_nion_image_info.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.read_nion_image_info.rst.txt new file mode 100644 index 00000000..8e21aaef --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.read_nion_image_info.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.read\_nion\_image\_info +============================================ + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: read_nion_image_info \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.read_old_h5group.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.read_old_h5group.rst.txt new file mode 100644 index 00000000..c38b7ab8 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.read_old_h5group.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.read\_old\_h5group +======================================= + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: read_old_h5group \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.read_poscar.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.read_poscar.rst.txt new file mode 100644 index 00000000..0ca3c071 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.read_poscar.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.read\_poscar +================================= + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: read_poscar \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.rst.txt new file mode 100644 index 00000000..8b7b8161 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.rst.txt @@ -0,0 +1,67 @@ +pyTEMlib.file\_tools +==================== + +.. automodule:: pyTEMlib.file_tools + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + add_dataset_from_file + add_to_dict + get_h5_filename + get_last_path + get_main_channel + get_start_channel + h5_add_crystal_structure + h5_add_to_structure + h5_get_crystal_structure + h5_group_to_dict + h5_tree + log_results + open_file + open_file_dialog_qt + read_cif + read_dm3_info + read_essential_metadata + read_nion_image_info + read_old_h5group + read_poscar + save_dataset + save_dataset_dictionary + save_file_dialog_qt + save_path + save_single_dataset + set_dimensions + update_directory_list + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + :nosignatures: + + ChooseDataset + FileWidget + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.file_tools.save_dataset.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.save_dataset.rst.txt new file mode 100644 index 00000000..57c02c8c --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.save_dataset.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.save\_dataset +================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: save_dataset \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.save_dataset_dictionary.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.save_dataset_dictionary.rst.txt new file mode 100644 index 00000000..e23b8e88 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.save_dataset_dictionary.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.save\_dataset\_dictionary +============================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: save_dataset_dictionary \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.save_file_dialog_qt.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.save_file_dialog_qt.rst.txt new file mode 100644 index 00000000..6885ea65 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.save_file_dialog_qt.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.save\_file\_dialog\_qt +=========================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: save_file_dialog_qt \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.save_path.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.save_path.rst.txt new file mode 100644 index 00000000..7b20a513 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.save_path.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.save\_path +=============================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: save_path \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.save_single_dataset.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.save_single_dataset.rst.txt new file mode 100644 index 00000000..e6d04d73 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.save_single_dataset.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.save\_single\_dataset +========================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: save_single_dataset \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.set_dimensions.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.set_dimensions.rst.txt new file mode 100644 index 00000000..04f60bbe --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.set_dimensions.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.set\_dimensions +==================================== + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: set_dimensions \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools.update_directory_list.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools.update_directory_list.rst.txt new file mode 100644 index 00000000..f7463a79 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools.update_directory_list.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.file\_tools.update\_directory\_list +============================================ + +.. currentmodule:: pyTEMlib.file_tools + +.. autofunction:: update_directory_list \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.file_tools_qt.rst.txt b/_sources/_autosummary/pyTEMlib.file_tools_qt.rst.txt new file mode 100644 index 00000000..aa925f5d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.file_tools_qt.rst.txt @@ -0,0 +1,23 @@ +pyTEMlib.file\_tools\_qt +======================== + +.. automodule:: pyTEMlib.file_tools_qt + + + + + + + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.breadth_first_search.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.breadth_first_search.rst.txt new file mode 100644 index 00000000..c6863e56 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.breadth_first_search.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.breadth\_first\_search +============================================ + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: breadth_first_search \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.circum_center.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.circum_center.rst.txt new file mode 100644 index 00000000..b1d89b11 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.circum_center.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.circum\_center +==================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: circum_center \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.find_interstitial_clusters.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.find_interstitial_clusters.rst.txt new file mode 100644 index 00000000..47b1ef8c --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.find_interstitial_clusters.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.find\_interstitial\_clusters +================================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: find_interstitial_clusters \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.find_overlapping_spheres.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.find_overlapping_spheres.rst.txt new file mode 100644 index 00000000..b487a2e2 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.find_overlapping_spheres.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.find\_overlapping\_spheres +================================================ + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: find_overlapping_spheres \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.find_polyhedra.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.find_polyhedra.rst.txt new file mode 100644 index 00000000..1a937e75 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.find_polyhedra.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.find\_polyhedra +===================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: find_polyhedra \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.get_bond_radii.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.get_bond_radii.rst.txt new file mode 100644 index 00000000..ed4c60f2 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.get_bond_radii.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.get\_bond\_radii +====================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: get_bond_radii \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.get_bonds.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.get_bonds.rst.txt new file mode 100644 index 00000000..e47b9ef2 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.get_bonds.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.get\_bonds +================================ + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: get_bonds \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.get_connectivity_matrix.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.get_connectivity_matrix.rst.txt new file mode 100644 index 00000000..b97a6ad7 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.get_connectivity_matrix.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.get\_connectivity\_matrix +=============================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: get_connectivity_matrix \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.get_distortion_matrix.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.get_distortion_matrix.rst.txt new file mode 100644 index 00000000..c43a6ced --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.get_distortion_matrix.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.get\_distortion\_matrix +============================================= + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: get_distortion_matrix \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.get_maximum_view.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.get_maximum_view.rst.txt new file mode 100644 index 00000000..f701c8b0 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.get_maximum_view.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.get\_maximum\_view +======================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: get_maximum_view \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.get_non_periodic_supercell.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.get_non_periodic_supercell.rst.txt new file mode 100644 index 00000000..a621c81d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.get_non_periodic_supercell.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.get\_non\_periodic\_supercell +=================================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: get_non_periodic_supercell \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.get_polygons.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.get_polygons.rst.txt new file mode 100644 index 00000000..163e76a3 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.get_polygons.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.get\_polygons +=================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: get_polygons \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.get_significant_vertices.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.get_significant_vertices.rst.txt new file mode 100644 index 00000000..d0685a23 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.get_significant_vertices.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.get\_significant\_vertices +================================================ + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: get_significant_vertices \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.get_voronoi.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.get_voronoi.rst.txt new file mode 100644 index 00000000..986141b8 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.get_voronoi.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.get\_voronoi +================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: get_voronoi \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.interstitial_sphere_center.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.interstitial_sphere_center.rst.txt new file mode 100644 index 00000000..b2b4b9fa --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.interstitial_sphere_center.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.interstitial\_sphere\_center +================================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: interstitial_sphere_center \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.make_polygons.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.make_polygons.rst.txt new file mode 100644 index 00000000..5889edf3 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.make_polygons.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.make\_polygons +==================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: make_polygons \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.make_polyhedrons.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.make_polyhedrons.rst.txt new file mode 100644 index 00000000..c386d7c9 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.make_polyhedrons.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.make\_polyhedrons +======================================= + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: make_polyhedrons \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.plot_atoms.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.plot_atoms.rst.txt new file mode 100644 index 00000000..4a2bb1af --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.plot_atoms.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.plot\_atoms +================================= + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: plot_atoms \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.polygon_sort.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.polygon_sort.rst.txt new file mode 100644 index 00000000..c499cd74 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.polygon_sort.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.polygon\_sort +=================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: polygon_sort \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.rst.txt new file mode 100644 index 00000000..d5d88a02 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.rst.txt @@ -0,0 +1,57 @@ +pyTEMlib.graph\_tools +===================== + +.. automodule:: pyTEMlib.graph_tools + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + breadth_first_search + circum_center + find_interstitial_clusters + find_overlapping_spheres + find_polyhedra + get_bond_radii + get_bonds + get_connectivity_matrix + get_distortion_matrix + get_maximum_view + get_non_periodic_supercell + get_polygons + get_significant_vertices + get_voronoi + interstitial_sphere_center + make_polygons + make_polyhedrons + plot_atoms + polygon_sort + set_bond_radii + sort_polyhedra_by_vertices + transform_voronoi + undistort + undistort_sitk + undistort_stack + undistort_stack_sitk + voronoi_volumes + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.set_bond_radii.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.set_bond_radii.rst.txt new file mode 100644 index 00000000..c0d8a1f2 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.set_bond_radii.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.set\_bond\_radii +====================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: set_bond_radii \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.sort_polyhedra_by_vertices.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.sort_polyhedra_by_vertices.rst.txt new file mode 100644 index 00000000..fa4e4be8 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.sort_polyhedra_by_vertices.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.sort\_polyhedra\_by\_vertices +=================================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: sort_polyhedra_by_vertices \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.transform_voronoi.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.transform_voronoi.rst.txt new file mode 100644 index 00000000..6c5542f3 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.transform_voronoi.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.transform\_voronoi +======================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: transform_voronoi \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.undistort.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.undistort.rst.txt new file mode 100644 index 00000000..3fd76888 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.undistort.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.undistort +=============================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: undistort \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.undistort_sitk.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.undistort_sitk.rst.txt new file mode 100644 index 00000000..8677a8a4 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.undistort_sitk.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.undistort\_sitk +===================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: undistort_sitk \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.undistort_stack.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.undistort_stack.rst.txt new file mode 100644 index 00000000..5fa03373 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.undistort_stack.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.undistort\_stack +====================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: undistort_stack \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.undistort_stack_sitk.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.undistort_stack_sitk.rst.txt new file mode 100644 index 00000000..64b7f427 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.undistort_stack_sitk.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.undistort\_stack\_sitk +============================================ + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: undistort_stack_sitk \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_tools.voronoi_volumes.rst.txt b/_sources/_autosummary/pyTEMlib.graph_tools.voronoi_volumes.rst.txt new file mode 100644 index 00000000..388c21c5 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_tools.voronoi_volumes.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_tools.voronoi\_volumes +====================================== + +.. currentmodule:: pyTEMlib.graph_tools + +.. autofunction:: voronoi_volumes \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_viz.get_boundary_polyhedra.rst.txt b/_sources/_autosummary/pyTEMlib.graph_viz.get_boundary_polyhedra.rst.txt new file mode 100644 index 00000000..0c76129a --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_viz.get_boundary_polyhedra.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_viz.get\_boundary\_polyhedra +============================================ + +.. currentmodule:: pyTEMlib.graph_viz + +.. autofunction:: get_boundary_polyhedra \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_viz.plot_bonds.rst.txt b/_sources/_autosummary/pyTEMlib.graph_viz.plot_bonds.rst.txt new file mode 100644 index 00000000..5062cd38 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_viz.plot_bonds.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_viz.plot\_bonds +=============================== + +.. currentmodule:: pyTEMlib.graph_viz + +.. autofunction:: plot_bonds \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_viz.plot_polyhedron.rst.txt b/_sources/_autosummary/pyTEMlib.graph_viz.plot_polyhedron.rst.txt new file mode 100644 index 00000000..41f3f7ed --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_viz.plot_polyhedron.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_viz.plot\_polyhedron +==================================== + +.. currentmodule:: pyTEMlib.graph_viz + +.. autofunction:: plot_polyhedron \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_viz.plot_super_cell.rst.txt b/_sources/_autosummary/pyTEMlib.graph_viz.plot_super_cell.rst.txt new file mode 100644 index 00000000..35ab3ea7 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_viz.plot_super_cell.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_viz.plot\_super\_cell +===================================== + +.. currentmodule:: pyTEMlib.graph_viz + +.. autofunction:: plot_super_cell \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_viz.plot_supercell.rst.txt b/_sources/_autosummary/pyTEMlib.graph_viz.plot_supercell.rst.txt new file mode 100644 index 00000000..59cc4430 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_viz.plot_supercell.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_viz.plot\_supercell +=================================== + +.. currentmodule:: pyTEMlib.graph_viz + +.. autofunction:: plot_supercell \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_viz.plot_supercell_bonds.rst.txt b/_sources/_autosummary/pyTEMlib.graph_viz.plot_supercell_bonds.rst.txt new file mode 100644 index 00000000..351562f4 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_viz.plot_supercell_bonds.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_viz.plot\_supercell\_bonds +========================================== + +.. currentmodule:: pyTEMlib.graph_viz + +.. autofunction:: plot_supercell_bonds \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_viz.plot_supercell_polyhedra.rst.txt b/_sources/_autosummary/pyTEMlib.graph_viz.plot_supercell_polyhedra.rst.txt new file mode 100644 index 00000000..dc7a594a --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_viz.plot_supercell_polyhedra.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_viz.plot\_supercell\_polyhedra +============================================== + +.. currentmodule:: pyTEMlib.graph_viz + +.. autofunction:: plot_supercell_polyhedra \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_viz.plot_with_polyhedra.rst.txt b/_sources/_autosummary/pyTEMlib.graph_viz.plot_with_polyhedra.rst.txt new file mode 100644 index 00000000..8b8c4894 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_viz.plot_with_polyhedra.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_viz.plot\_with\_polyhedra +========================================= + +.. currentmodule:: pyTEMlib.graph_viz + +.. autofunction:: plot_with_polyhedra \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.graph_viz.rst.txt b/_sources/_autosummary/pyTEMlib.graph_viz.rst.txt new file mode 100644 index 00000000..f117b307 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_viz.rst.txt @@ -0,0 +1,39 @@ +pyTEMlib.graph\_viz +=================== + +.. automodule:: pyTEMlib.graph_viz + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + get_boundary_polyhedra + plot_bonds + plot_polyhedron + plot_super_cell + plot_supercell + plot_supercell_bonds + plot_supercell_polyhedra + plot_with_polyhedra + show_polyhedra + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.graph_viz.show_polyhedra.rst.txt b/_sources/_autosummary/pyTEMlib.graph_viz.show_polyhedra.rst.txt new file mode 100644 index 00000000..01b24dbc --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.graph_viz.show_polyhedra.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.graph\_viz.show\_polyhedra +=================================== + +.. currentmodule:: pyTEMlib.graph_viz + +.. autofunction:: show_polyhedra \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_dialog.rst.txt b/_sources/_autosummary/pyTEMlib.image_dialog.rst.txt new file mode 100644 index 00000000..bdec96dc --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_dialog.rst.txt @@ -0,0 +1,23 @@ +pyTEMlib.image\_dialog +====================== + +.. automodule:: pyTEMlib.image_dialog + + + + + + + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.image_dlg.rst.txt b/_sources/_autosummary/pyTEMlib.image_dlg.rst.txt new file mode 100644 index 00000000..83472318 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_dlg.rst.txt @@ -0,0 +1,23 @@ +pyTEMlib.image\_dlg +=================== + +.. automodule:: pyTEMlib.image_dlg + + + + + + + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.image_tools.ImageWithLineProfile.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.ImageWithLineProfile.rst.txt new file mode 100644 index 00000000..3319418d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.ImageWithLineProfile.rst.txt @@ -0,0 +1,25 @@ +pyTEMlib.image\_tools.ImageWithLineProfile +========================================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autoclass:: ImageWithLineProfile + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~ImageWithLineProfile.update + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.adaptive_fourier_filter.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.adaptive_fourier_filter.rst.txt new file mode 100644 index 00000000..fa97c49d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.adaptive_fourier_filter.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.adaptive\_fourier\_filter +=============================================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: adaptive_fourier_filter \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.align_crystal_reflections.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.align_crystal_reflections.rst.txt new file mode 100644 index 00000000..2754b7c5 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.align_crystal_reflections.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.align\_crystal\_reflections +================================================= + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: align_crystal_reflections \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.calculate_ctf.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.calculate_ctf.rst.txt new file mode 100644 index 00000000..af798d84 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.calculate_ctf.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.calculate\_ctf +==================================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: calculate_ctf \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.calculate_scherzer.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.calculate_scherzer.rst.txt new file mode 100644 index 00000000..c31c9d00 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.calculate_scherzer.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.calculate\_scherzer +========================================= + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: calculate_scherzer \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.calibrate_image_scale.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.calibrate_image_scale.rst.txt new file mode 100644 index 00000000..a4a9f269 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.calibrate_image_scale.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.calibrate\_image\_scale +============================================= + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: calibrate_image_scale \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.cart2pol.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.cart2pol.rst.txt new file mode 100644 index 00000000..b238ed01 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.cart2pol.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.cart2pol +============================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: cart2pol \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.cartesian2polar.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.cartesian2polar.rst.txt new file mode 100644 index 00000000..8cdff2eb --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.cartesian2polar.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.cartesian2polar +===================================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: cartesian2polar \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.clean_svd.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.clean_svd.rst.txt new file mode 100644 index 00000000..a9818d6f --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.clean_svd.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.clean\_svd +================================ + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: clean_svd \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.complete_registration.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.complete_registration.rst.txt new file mode 100644 index 00000000..9f4495d2 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.complete_registration.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.complete\_registration +============================================ + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: complete_registration \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.crop_image_stack.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.crop_image_stack.rst.txt new file mode 100644 index 00000000..36c6c1ac --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.crop_image_stack.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.crop\_image\_stack +======================================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: crop_image_stack \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.decon_lr.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.decon_lr.rst.txt new file mode 100644 index 00000000..4b4e329f --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.decon_lr.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.decon\_lr +=============================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: decon_lr \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.demon_registration.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.demon_registration.rst.txt new file mode 100644 index 00000000..7348b1c3 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.demon_registration.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.demon\_registration +========================================= + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: demon_registration \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.diffractogram_spots.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.diffractogram_spots.rst.txt new file mode 100644 index 00000000..f01d0ceb --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.diffractogram_spots.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.diffractogram\_spots +========================================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: diffractogram_spots \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.fourier_transform.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.fourier_transform.rst.txt new file mode 100644 index 00000000..a408cad9 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.fourier_transform.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.fourier\_transform +======================================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: fourier_transform \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.get_rotation.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.get_rotation.rst.txt new file mode 100644 index 00000000..a3863007 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.get_rotation.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.get\_rotation +=================================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: get_rotation \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.get_wavelength.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.get_wavelength.rst.txt new file mode 100644 index 00000000..66b0c29d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.get_wavelength.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.get\_wavelength +===================================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: get_wavelength \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.histogram_plot.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.histogram_plot.rst.txt new file mode 100644 index 00000000..1d5f73db --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.histogram_plot.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.histogram\_plot +===================================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: histogram_plot \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.pol2cart.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.pol2cart.rst.txt new file mode 100644 index 00000000..92552551 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.pol2cart.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.pol2cart +============================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: pol2cart \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.power_spectrum.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.power_spectrum.rst.txt new file mode 100644 index 00000000..b245a87c --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.power_spectrum.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.power\_spectrum +===================================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: power_spectrum \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.rebin.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.rebin.rst.txt new file mode 100644 index 00000000..e39cd81b --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.rebin.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.rebin +=========================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: rebin \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.rig_reg_drift.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.rig_reg_drift.rst.txt new file mode 100644 index 00000000..0f6f775e --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.rig_reg_drift.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.rig\_reg\_drift +===================================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: rig_reg_drift \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.rigid_registration.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.rigid_registration.rst.txt new file mode 100644 index 00000000..26104967 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.rigid_registration.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.rigid\_registration +========================================= + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: rigid_registration \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.rotational_symmetry_diffractogram.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.rotational_symmetry_diffractogram.rst.txt new file mode 100644 index 00000000..f41fb530 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.rotational_symmetry_diffractogram.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.rotational\_symmetry\_diffractogram +========================================================= + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: rotational_symmetry_diffractogram \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.rst.txt new file mode 100644 index 00000000..a74ba4d9 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.rst.txt @@ -0,0 +1,64 @@ +pyTEMlib.image\_tools +===================== + +.. automodule:: pyTEMlib.image_tools + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + adaptive_fourier_filter + align_crystal_reflections + calculate_ctf + calculate_scherzer + calibrate_image_scale + cart2pol + cartesian2polar + clean_svd + complete_registration + crop_image_stack + decon_lr + demon_registration + diffractogram_spots + fourier_transform + get_rotation + get_wavelength + histogram_plot + pol2cart + power_spectrum + rebin + rig_reg_drift + rigid_registration + rotational_symmetry_diffractogram + warp + xy2polar + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + :nosignatures: + + ImageWithLineProfile + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.image_tools.warp.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.warp.rst.txt new file mode 100644 index 00000000..96699134 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.warp.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.warp +========================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: warp \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.image_tools.xy2polar.rst.txt b/_sources/_autosummary/pyTEMlib.image_tools.xy2polar.rst.txt new file mode 100644 index 00000000..c98aac23 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.image_tools.xy2polar.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.image\_tools.xy2polar +============================== + +.. currentmodule:: pyTEMlib.image_tools + +.. autofunction:: xy2polar \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.info_dialog.InfoWidget.rst.txt b/_sources/_autosummary/pyTEMlib.info_dialog.InfoWidget.rst.txt new file mode 100644 index 00000000..5361ac13 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.info_dialog.InfoWidget.rst.txt @@ -0,0 +1,34 @@ +pyTEMlib.info\_dialog.InfoWidget +================================ + +.. currentmodule:: pyTEMlib.info_dialog + +.. autoclass:: InfoWidget + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~InfoWidget.cursor2energy_scale + ~InfoWidget.get_spectrum + ~InfoWidget.plot + ~InfoWidget.set_action + ~InfoWidget.set_binning + ~InfoWidget.set_dataset + ~InfoWidget.set_energy_scale + ~InfoWidget.set_flux + ~InfoWidget.set_microscope_parameter + ~InfoWidget.set_y_scale + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.info_dialog.get_sidebar.rst.txt b/_sources/_autosummary/pyTEMlib.info_dialog.get_sidebar.rst.txt new file mode 100644 index 00000000..e0fec962 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.info_dialog.get_sidebar.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.info\_dialog.get\_sidebar +================================== + +.. currentmodule:: pyTEMlib.info_dialog + +.. autofunction:: get_sidebar \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.info_dialog.rst.txt b/_sources/_autosummary/pyTEMlib.info_dialog.rst.txt new file mode 100644 index 00000000..49e04b00 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.info_dialog.rst.txt @@ -0,0 +1,40 @@ +pyTEMlib.info\_dialog +===================== + +.. automodule:: pyTEMlib.info_dialog + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + get_sidebar + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + :nosignatures: + + InfoWidget + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.info_dlg.rst.txt b/_sources/_autosummary/pyTEMlib.info_dlg.rst.txt new file mode 100644 index 00000000..8c9f0c0d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.info_dlg.rst.txt @@ -0,0 +1,23 @@ +pyTEMlib.info\_dlg +================== + +.. automodule:: pyTEMlib.info_dlg + + + + + + + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.info_widget.EELSWidget.rst.txt b/_sources/_autosummary/pyTEMlib.info_widget.EELSWidget.rst.txt new file mode 100644 index 00000000..7f7134f6 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.info_widget.EELSWidget.rst.txt @@ -0,0 +1,32 @@ +pyTEMlib.info\_widget.EELSWidget +================================ + +.. currentmodule:: pyTEMlib.info_widget + +.. autoclass:: EELSWidget + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~EELSWidget.get_spectrum + ~EELSWidget.line_select_callback + ~EELSWidget.plot + ~EELSWidget.plot_spectrum + ~EELSWidget.plot_spectrum_image + ~EELSWidget.set_dataset + ~EELSWidget.set_energy_scale + ~EELSWidget.set_y_scale + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.info_widget.InfoWidget.rst.txt b/_sources/_autosummary/pyTEMlib.info_widget.InfoWidget.rst.txt new file mode 100644 index 00000000..697ceedf --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.info_widget.InfoWidget.rst.txt @@ -0,0 +1,38 @@ +pyTEMlib.info\_widget.InfoWidget +================================ + +.. currentmodule:: pyTEMlib.info_widget + +.. autoclass:: InfoWidget + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~InfoWidget.cursor2energy_scale + ~InfoWidget.get_spectrum + ~InfoWidget.line_select_callback + ~InfoWidget.plot + ~InfoWidget.plot_spectrum + ~InfoWidget.plot_spectrum_image + ~InfoWidget.set_action + ~InfoWidget.set_binning + ~InfoWidget.set_dataset + ~InfoWidget.set_energy_scale + ~InfoWidget.set_flux + ~InfoWidget.set_microscope_parameter + ~InfoWidget.set_y_scale + ~InfoWidget.update_dataset + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.info_widget.LowLossWidget.rst.txt b/_sources/_autosummary/pyTEMlib.info_widget.LowLossWidget.rst.txt new file mode 100644 index 00000000..b27c84e9 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.info_widget.LowLossWidget.rst.txt @@ -0,0 +1,38 @@ +pyTEMlib.info\_widget.LowLossWidget +=================================== + +.. currentmodule:: pyTEMlib.info_widget + +.. autoclass:: LowLossWidget + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~LowLossWidget.fix_energy_scale + ~LowLossWidget.get_additional_spectrum + ~LowLossWidget.get_resolution_function + ~LowLossWidget.get_spectrum + ~LowLossWidget.line_select_callback + ~LowLossWidget.plot + ~LowLossWidget.plot_spectrum + ~LowLossWidget.plot_spectrum_image + ~LowLossWidget.set_action + ~LowLossWidget.set_binning + ~LowLossWidget.set_dataset + ~LowLossWidget.set_energy_scale + ~LowLossWidget.set_y_scale + ~LowLossWidget.update_dataset + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.info_widget.get_info_sidebar.rst.txt b/_sources/_autosummary/pyTEMlib.info_widget.get_info_sidebar.rst.txt new file mode 100644 index 00000000..da2f1779 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.info_widget.get_info_sidebar.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.info\_widget.get\_info\_sidebar +======================================== + +.. currentmodule:: pyTEMlib.info_widget + +.. autofunction:: get_info_sidebar \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.info_widget.get_low_loss_sidebar.rst.txt b/_sources/_autosummary/pyTEMlib.info_widget.get_low_loss_sidebar.rst.txt new file mode 100644 index 00000000..af34c393 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.info_widget.get_low_loss_sidebar.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.info\_widget.get\_low\_loss\_sidebar +============================================= + +.. currentmodule:: pyTEMlib.info_widget + +.. autofunction:: get_low_loss_sidebar \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.info_widget.rst.txt b/_sources/_autosummary/pyTEMlib.info_widget.rst.txt new file mode 100644 index 00000000..00ddf10d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.info_widget.rst.txt @@ -0,0 +1,43 @@ +pyTEMlib.info\_widget +===================== + +.. automodule:: pyTEMlib.info_widget + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + get_info_sidebar + get_low_loss_sidebar + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + :nosignatures: + + EELSWidget + InfoWidget + LowLossWidget + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.interactive_eels.rst.txt b/_sources/_autosummary/pyTEMlib.interactive_eels.rst.txt new file mode 100644 index 00000000..02c7e470 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.interactive_eels.rst.txt @@ -0,0 +1,23 @@ +pyTEMlib.interactive\_eels +========================== + +.. automodule:: pyTEMlib.interactive_eels + + + + + + + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.interactive_image.rst.txt b/_sources/_autosummary/pyTEMlib.interactive_image.rst.txt new file mode 100644 index 00000000..fb04f4a8 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.interactive_image.rst.txt @@ -0,0 +1,23 @@ +pyTEMlib.interactive\_image +=========================== + +.. automodule:: pyTEMlib.interactive_image + + + + + + + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.Zuo_fig_3_18.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.Zuo_fig_3_18.rst.txt new file mode 100644 index 00000000..24980070 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.Zuo_fig_3_18.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.Zuo\_fig\_3\_18 +============================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: Zuo_fig_3_18 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.check_sanity.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.check_sanity.rst.txt new file mode 100644 index 00000000..d7861a88 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.check_sanity.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.check\_sanity +============================================ + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: check_sanity \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.example.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.example.rst.txt new file mode 100644 index 00000000..f338a0c8 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.example.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.example +====================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: example \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.feq.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.feq.rst.txt new file mode 100644 index 00000000..0788e347 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.feq.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.feq +================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: feq \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.find_angles.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.find_angles.rst.txt new file mode 100644 index 00000000..c97d7556 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.find_angles.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.find\_angles +=========================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: find_angles \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.find_nearest_zone_axis.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.find_nearest_zone_axis.rst.txt new file mode 100644 index 00000000..60d09c9f --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.find_nearest_zone_axis.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.find\_nearest\_zone\_axis +======================================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: find_nearest_zone_axis \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.get_dynamically_allowed.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.get_dynamically_allowed.rst.txt new file mode 100644 index 00000000..f9fa8850 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.get_dynamically_allowed.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.get\_dynamically\_allowed +======================================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: get_dynamically_allowed \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.get_metric_tensor.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.get_metric_tensor.rst.txt new file mode 100644 index 00000000..8c82ed56 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.get_metric_tensor.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.get\_metric\_tensor +================================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: get_metric_tensor \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.get_rotation_matrix.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.get_rotation_matrix.rst.txt new file mode 100644 index 00000000..91dd177a --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.get_rotation_matrix.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.get\_rotation\_matrix +==================================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: get_rotation_matrix \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.get_wavelength.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.get_wavelength.rst.txt new file mode 100644 index 00000000..298a29d4 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.get_wavelength.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.get\_wavelength +============================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: get_wavelength \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering.rst.txt new file mode 100644 index 00000000..75aa24ea --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.kinematic\_scattering +==================================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: kinematic_scattering \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering2.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering2.rst.txt new file mode 100644 index 00000000..dffbe5e4 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering2.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.kinematic\_scattering2 +===================================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: kinematic_scattering2 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.make_pretty_labels.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.make_pretty_labels.rst.txt new file mode 100644 index 00000000..1c669c59 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.make_pretty_labels.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.make\_pretty\_labels +=================================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: make_pretty_labels \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.read_poscar.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.read_poscar.rst.txt new file mode 100644 index 00000000..c4b9e9bb --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.read_poscar.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.read\_poscar +=========================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: read_poscar \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.ring_pattern_calculation.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.ring_pattern_calculation.rst.txt new file mode 100644 index 00000000..03b3520d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.ring_pattern_calculation.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.ring\_pattern\_calculation +========================================================= + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: ring_pattern_calculation \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.rst.txt new file mode 100644 index 00000000..673a6224 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.rst.txt @@ -0,0 +1,49 @@ +pyTEMlib.kinematic\_scattering +============================== + +.. automodule:: pyTEMlib.kinematic_scattering + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + Zuo_fig_3_18 + check_sanity + example + feq + find_angles + find_nearest_zone_axis + get_dynamically_allowed + get_metric_tensor + get_rotation_matrix + get_wavelength + kinematic_scattering + kinematic_scattering2 + make_pretty_labels + read_poscar + ring_pattern_calculation + scattering_matrix + stage_rotation_matrix + vector_norm + zone_mistilt + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.scattering_matrix.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.scattering_matrix.rst.txt new file mode 100644 index 00000000..e1cee9cb --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.scattering_matrix.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.scattering\_matrix +================================================= + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: scattering_matrix \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.stage_rotation_matrix.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.stage_rotation_matrix.rst.txt new file mode 100644 index 00000000..7b24e9b6 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.stage_rotation_matrix.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.stage\_rotation\_matrix +====================================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: stage_rotation_matrix \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.vector_norm.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.vector_norm.rst.txt new file mode 100644 index 00000000..02f70326 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.vector_norm.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.vector\_norm +=========================================== + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: vector_norm \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.kinematic_scattering.zone_mistilt.rst.txt b/_sources/_autosummary/pyTEMlib.kinematic_scattering.zone_mistilt.rst.txt new file mode 100644 index 00000000..55fa6eb3 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.kinematic_scattering.zone_mistilt.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.kinematic\_scattering.zone\_mistilt +============================================ + +.. currentmodule:: pyTEMlib.kinematic_scattering + +.. autofunction:: zone_mistilt \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.microscope.Microscope.rst.txt b/_sources/_autosummary/pyTEMlib.microscope.Microscope.rst.txt new file mode 100644 index 00000000..91b6783f --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.microscope.Microscope.rst.txt @@ -0,0 +1,39 @@ +pyTEMlib.microscope.Microscope +============================== + +.. currentmodule:: pyTEMlib.microscope + +.. autoclass:: Microscope + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~Microscope.get_available_microscope_names + ~Microscope.load_microscopes + ~Microscope.set_microscope + + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~Microscope.E0 + ~Microscope.alpha + ~Microscope.beta + ~Microscope.correlation_factor + ~Microscope.microscopes + ~Microscope.name + ~Microscope.pppc + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.microscope.rst.txt b/_sources/_autosummary/pyTEMlib.microscope.rst.txt new file mode 100644 index 00000000..2de6aaa3 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.microscope.rst.txt @@ -0,0 +1,32 @@ +pyTEMlib.microscope +=================== + +.. automodule:: pyTEMlib.microscope + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + :nosignatures: + + Microscope + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.peak_dialog.PeakFitWidget.rst.txt b/_sources/_autosummary/pyTEMlib.peak_dialog.PeakFitWidget.rst.txt new file mode 100644 index 00000000..5466365b --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.peak_dialog.PeakFitWidget.rst.txt @@ -0,0 +1,40 @@ +pyTEMlib.peak\_dialog.PeakFitWidget +=================================== + +.. currentmodule:: pyTEMlib.peak_dialog + +.. autoclass:: PeakFitWidget + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~PeakFitWidget.find_peaks + ~PeakFitWidget.find_white_lines + ~PeakFitWidget.fit_peaks + ~PeakFitWidget.line_select_callback + ~PeakFitWidget.make_model + ~PeakFitWidget.modify_peak_amplitude + ~PeakFitWidget.modify_peak_position + ~PeakFitWidget.modify_peak_width + ~PeakFitWidget.plot + ~PeakFitWidget.set_action + ~PeakFitWidget.set_dataset + ~PeakFitWidget.set_fit_area + ~PeakFitWidget.set_peak_list + ~PeakFitWidget.set_y_scale + ~PeakFitWidget.smooth + ~PeakFitWidget.update + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.peak_dialog.get_sidebar.rst.txt b/_sources/_autosummary/pyTEMlib.peak_dialog.get_sidebar.rst.txt new file mode 100644 index 00000000..4c12a0b5 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.peak_dialog.get_sidebar.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.peak\_dialog.get\_sidebar +================================== + +.. currentmodule:: pyTEMlib.peak_dialog + +.. autofunction:: get_sidebar \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.peak_dialog.rst.txt b/_sources/_autosummary/pyTEMlib.peak_dialog.rst.txt new file mode 100644 index 00000000..591455d2 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.peak_dialog.rst.txt @@ -0,0 +1,41 @@ +pyTEMlib.peak\_dialog +===================== + +.. automodule:: pyTEMlib.peak_dialog + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + get_sidebar + smooth + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + :nosignatures: + + PeakFitWidget + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.peak_dialog.smooth.rst.txt b/_sources/_autosummary/pyTEMlib.peak_dialog.smooth.rst.txt new file mode 100644 index 00000000..4f523547 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.peak_dialog.smooth.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.peak\_dialog.smooth +============================ + +.. currentmodule:: pyTEMlib.peak_dialog + +.. autofunction:: smooth \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.peak_dlg.rst.txt b/_sources/_autosummary/pyTEMlib.peak_dlg.rst.txt new file mode 100644 index 00000000..9067e1a9 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.peak_dlg.rst.txt @@ -0,0 +1,23 @@ +pyTEMlib.peak\_dlg +================== + +.. automodule:: pyTEMlib.peak_dlg + + + + + + + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.get_chi.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.get_chi.rst.txt new file mode 100644 index 00000000..ebaaff85 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.get_chi.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.get\_chi +============================== + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: get_chi \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.get_chi_2.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.get_chi_2.rst.txt new file mode 100644 index 00000000..0b241419 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.get_chi_2.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.get\_chi\_2 +================================= + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: get_chi_2 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.get_d2chidu2.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.get_d2chidu2.rst.txt new file mode 100644 index 00000000..c3ef12b8 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.get_d2chidu2.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.get\_d2chidu2 +=================================== + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: get_d2chidu2 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.get_d2chidudv.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.get_d2chidudv.rst.txt new file mode 100644 index 00000000..cdf3b520 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.get_d2chidudv.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.get\_d2chidudv +==================================== + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: get_d2chidudv \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.get_d2chidv2.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.get_d2chidv2.rst.txt new file mode 100644 index 00000000..98137959 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.get_d2chidv2.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.get\_d2chidv2 +=================================== + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: get_d2chidv2 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.get_ronchigram.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.get_ronchigram.rst.txt new file mode 100644 index 00000000..6b8db4d2 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.get_ronchigram.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.get\_ronchigram +===================================== + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: get_ronchigram \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.get_ronchigram_2.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.get_ronchigram_2.rst.txt new file mode 100644 index 00000000..3286a5fb --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.get_ronchigram_2.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.get\_ronchigram\_2 +======================================== + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: get_ronchigram_2 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.get_source_energy_spread.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.get_source_energy_spread.rst.txt new file mode 100644 index 00000000..07b44f11 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.get_source_energy_spread.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.get\_source\_energy\_spread +================================================= + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: get_source_energy_spread \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.get_target_aberrations.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.get_target_aberrations.rst.txt new file mode 100644 index 00000000..0abf7b72 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.get_target_aberrations.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.get\_target\_aberrations +============================================== + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: get_target_aberrations \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.make_chi.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.make_chi.rst.txt new file mode 100644 index 00000000..14e3b0f9 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.make_chi.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.make\_chi +=============================== + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: make_chi \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.make_chi1.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.make_chi1.rst.txt new file mode 100644 index 00000000..9d35177e --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.make_chi1.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.make\_chi1 +================================ + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: make_chi1 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.make_gauss.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.make_gauss.rst.txt new file mode 100644 index 00000000..0adf27ad --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.make_gauss.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.make\_gauss +================================= + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: make_gauss \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.make_lorentz.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.make_lorentz.rst.txt new file mode 100644 index 00000000..a9d379e8 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.make_lorentz.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.make\_lorentz +=================================== + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: make_lorentz \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.print_aberrations.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.print_aberrations.rst.txt new file mode 100644 index 00000000..b6c4917d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.print_aberrations.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.print\_aberrations +======================================== + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: print_aberrations \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.probe2.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.probe2.rst.txt new file mode 100644 index 00000000..798e9f1b --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.probe2.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.probe2 +============================ + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: probe2 \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.rst.txt new file mode 100644 index 00000000..c03950a4 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.rst.txt @@ -0,0 +1,46 @@ +pyTEMlib.probe\_tools +===================== + +.. automodule:: pyTEMlib.probe_tools + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + get_chi + get_chi_2 + get_d2chidu2 + get_d2chidudv + get_d2chidv2 + get_ronchigram + get_ronchigram_2 + get_source_energy_spread + get_target_aberrations + make_chi + make_chi1 + make_gauss + make_lorentz + print_aberrations + probe2 + zero_loss_peak_weight + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.probe_tools.zero_loss_peak_weight.rst.txt b/_sources/_autosummary/pyTEMlib.probe_tools.zero_loss_peak_weight.rst.txt new file mode 100644 index 00000000..27fa605e --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.probe_tools.zero_loss_peak_weight.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.probe\_tools.zero\_loss\_peak\_weight +============================================== + +.. currentmodule:: pyTEMlib.probe_tools + +.. autofunction:: zero_loss_peak_weight \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.rst.txt b/_sources/_autosummary/pyTEMlib.rst.txt new file mode 100644 index 00000000..f36d212b --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.rst.txt @@ -0,0 +1,62 @@ +pyTEMlib +======== + +.. automodule:: pyTEMlib + + + + + + + + + + + + + + + + + + + +.. autosummary:: + :toctree: + :template: custom-module-template.rst + :recursive: + + pyTEMlib.animation + pyTEMlib.atom_tools + pyTEMlib.config_dir + pyTEMlib.crystal_tools + pyTEMlib.diffraction_plot + pyTEMlib.dynamic_scattering + pyTEMlib.eds_tools + pyTEMlib.eels_dialog + pyTEMlib.eels_dialog_utilities + pyTEMlib.eels_dlg + pyTEMlib.eels_tools + pyTEMlib.file_tools + pyTEMlib.file_tools_qt + pyTEMlib.graph_tools + pyTEMlib.graph_viz + pyTEMlib.image_dialog + pyTEMlib.image_dlg + pyTEMlib.image_tools + pyTEMlib.info_dialog + pyTEMlib.info_dlg + pyTEMlib.info_widget + pyTEMlib.interactive_eels + pyTEMlib.interactive_image + pyTEMlib.kinematic_scattering + pyTEMlib.microscope + pyTEMlib.peak_dialog + pyTEMlib.peak_dlg + pyTEMlib.probe_tools + pyTEMlib.sidpy_tools + pyTEMlib.simulation_tools + pyTEMlib.version + pyTEMlib.viz + pyTEMlib.xrpa_x_sections + diff --git a/_sources/_autosummary/pyTEMlib.sidpy_tools.ChooseDataset.rst.txt b/_sources/_autosummary/pyTEMlib.sidpy_tools.ChooseDataset.rst.txt new file mode 100644 index 00000000..b94201f1 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.sidpy_tools.ChooseDataset.rst.txt @@ -0,0 +1,26 @@ +pyTEMlib.sidpy\_tools.ChooseDataset +=================================== + +.. currentmodule:: pyTEMlib.sidpy_tools + +.. autoclass:: ChooseDataset + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~ChooseDataset.get_dataset_list + ~ChooseDataset.set_dataset + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_order.rst.txt b/_sources/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_order.rst.txt new file mode 100644 index 00000000..a4370912 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_order.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.sidpy\_tools.get\_dimensions\_by\_order +================================================ + +.. currentmodule:: pyTEMlib.sidpy_tools + +.. autofunction:: get_dimensions_by_order \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_type.rst.txt b/_sources/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_type.rst.txt new file mode 100644 index 00000000..475763d7 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_type.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.sidpy\_tools.get\_dimensions\_by\_type +=============================================== + +.. currentmodule:: pyTEMlib.sidpy_tools + +.. autofunction:: get_dimensions_by_type \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.sidpy_tools.get_extent.rst.txt b/_sources/_autosummary/pyTEMlib.sidpy_tools.get_extent.rst.txt new file mode 100644 index 00000000..aadfd6c9 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.sidpy_tools.get_extent.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.sidpy\_tools.get\_extent +================================= + +.. currentmodule:: pyTEMlib.sidpy_tools + +.. autofunction:: get_extent \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.sidpy_tools.get_image_dims.rst.txt b/_sources/_autosummary/pyTEMlib.sidpy_tools.get_image_dims.rst.txt new file mode 100644 index 00000000..c572afe0 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.sidpy_tools.get_image_dims.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.sidpy\_tools.get\_image\_dims +====================================== + +.. currentmodule:: pyTEMlib.sidpy_tools + +.. autofunction:: get_image_dims \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.sidpy_tools.make_dummy_dataset.rst.txt b/_sources/_autosummary/pyTEMlib.sidpy_tools.make_dummy_dataset.rst.txt new file mode 100644 index 00000000..97cfaab8 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.sidpy_tools.make_dummy_dataset.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.sidpy\_tools.make\_dummy\_dataset +========================================== + +.. currentmodule:: pyTEMlib.sidpy_tools + +.. autofunction:: make_dummy_dataset \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.sidpy_tools.plot.rst.txt b/_sources/_autosummary/pyTEMlib.sidpy_tools.plot.rst.txt new file mode 100644 index 00000000..16248920 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.sidpy_tools.plot.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.sidpy\_tools.plot +========================== + +.. currentmodule:: pyTEMlib.sidpy_tools + +.. autofunction:: plot \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.sidpy_tools.rst.txt b/_sources/_autosummary/pyTEMlib.sidpy_tools.rst.txt new file mode 100644 index 00000000..8a66d0c5 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.sidpy_tools.rst.txt @@ -0,0 +1,45 @@ +pyTEMlib.sidpy\_tools +===================== + +.. automodule:: pyTEMlib.sidpy_tools + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + get_dimensions_by_order + get_dimensions_by_type + get_extent + get_image_dims + make_dummy_dataset + plot + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + :nosignatures: + + ChooseDataset + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.simulation_tools.exciting_get_spectra.rst.txt b/_sources/_autosummary/pyTEMlib.simulation_tools.exciting_get_spectra.rst.txt new file mode 100644 index 00000000..70a70efd --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.simulation_tools.exciting_get_spectra.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.simulation\_tools.exciting\_get\_spectra +================================================= + +.. currentmodule:: pyTEMlib.simulation_tools + +.. autofunction:: exciting_get_spectra \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.simulation_tools.final_state_broadening.rst.txt b/_sources/_autosummary/pyTEMlib.simulation_tools.final_state_broadening.rst.txt new file mode 100644 index 00000000..108134db --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.simulation_tools.final_state_broadening.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.simulation\_tools.final\_state\_broadening +=================================================== + +.. currentmodule:: pyTEMlib.simulation_tools + +.. autofunction:: final_state_broadening \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.simulation_tools.rst.txt b/_sources/_autosummary/pyTEMlib.simulation_tools.rst.txt new file mode 100644 index 00000000..f1a2a79c --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.simulation_tools.rst.txt @@ -0,0 +1,32 @@ +pyTEMlib.simulation\_tools +========================== + +.. automodule:: pyTEMlib.simulation_tools + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + exciting_get_spectra + final_state_broadening + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.version.rst.txt b/_sources/_autosummary/pyTEMlib.version.rst.txt new file mode 100644 index 00000000..33fc1ab0 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.version.rst.txt @@ -0,0 +1,23 @@ +pyTEMlib.version +================ + +.. automodule:: pyTEMlib.version + + + + + + + + + + + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.viz.CurveVisualizer.rst.txt b/_sources/_autosummary/pyTEMlib.viz.CurveVisualizer.rst.txt new file mode 100644 index 00000000..30469e07 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.viz.CurveVisualizer.rst.txt @@ -0,0 +1,27 @@ +pyTEMlib.viz.CurveVisualizer +============================ + +.. currentmodule:: pyTEMlib.viz + +.. autoclass:: CurveVisualizer + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~CurveVisualizer.onpick + ~CurveVisualizer.plot + ~CurveVisualizer.update + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.viz.SpectrumView.rst.txt b/_sources/_autosummary/pyTEMlib.viz.SpectrumView.rst.txt new file mode 100644 index 00000000..0f8c4600 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.viz.SpectrumView.rst.txt @@ -0,0 +1,29 @@ +pyTEMlib.viz.SpectrumView +========================= + +.. currentmodule:: pyTEMlib.viz + +.. autoclass:: SpectrumView + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + + + .. rubric:: Methods + + .. autosummary:: + :nosignatures: + + ~SpectrumView.add_region + ~SpectrumView.identify_edges + ~SpectrumView.initialize_edge + ~SpectrumView.regions_visibility + ~SpectrumView.update_region + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.viz.find_edge_names.rst.txt b/_sources/_autosummary/pyTEMlib.viz.find_edge_names.rst.txt new file mode 100644 index 00000000..57bce95d --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.viz.find_edge_names.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.viz.find\_edge\_names +============================== + +.. currentmodule:: pyTEMlib.viz + +.. autofunction:: find_edge_names \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.viz.plot.rst.txt b/_sources/_autosummary/pyTEMlib.viz.plot.rst.txt new file mode 100644 index 00000000..9dfd04c4 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.viz.plot.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.viz.plot +================= + +.. currentmodule:: pyTEMlib.viz + +.. autofunction:: plot \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.viz.plot_image.rst.txt b/_sources/_autosummary/pyTEMlib.viz.plot_image.rst.txt new file mode 100644 index 00000000..cd6299de --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.viz.plot_image.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.viz.plot\_image +======================== + +.. currentmodule:: pyTEMlib.viz + +.. autofunction:: plot_image \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.viz.plot_spectrum.rst.txt b/_sources/_autosummary/pyTEMlib.viz.plot_spectrum.rst.txt new file mode 100644 index 00000000..b8c5bd74 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.viz.plot_spectrum.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.viz.plot\_spectrum +=========================== + +.. currentmodule:: pyTEMlib.viz + +.. autofunction:: plot_spectrum \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.viz.plot_stack.rst.txt b/_sources/_autosummary/pyTEMlib.viz.plot_stack.rst.txt new file mode 100644 index 00000000..fe7e16c8 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.viz.plot_stack.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.viz.plot\_stack +======================== + +.. currentmodule:: pyTEMlib.viz + +.. autofunction:: plot_stack \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.viz.rst.txt b/_sources/_autosummary/pyTEMlib.viz.rst.txt new file mode 100644 index 00000000..a32411dd --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.viz.rst.txt @@ -0,0 +1,47 @@ +pyTEMlib.viz +============ + +.. automodule:: pyTEMlib.viz + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + + find_edge_names + plot + plot_image + plot_spectrum + plot_stack + spectrum_view_plotly + verify_spectrum_dataset + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + :nosignatures: + + CurveVisualizer + SpectrumView + + + + + + + + + diff --git a/_sources/_autosummary/pyTEMlib.viz.spectrum_view_plotly.rst.txt b/_sources/_autosummary/pyTEMlib.viz.spectrum_view_plotly.rst.txt new file mode 100644 index 00000000..29c584ef --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.viz.spectrum_view_plotly.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.viz.spectrum\_view\_plotly +=================================== + +.. currentmodule:: pyTEMlib.viz + +.. autofunction:: spectrum_view_plotly \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.viz.verify_spectrum_dataset.rst.txt b/_sources/_autosummary/pyTEMlib.viz.verify_spectrum_dataset.rst.txt new file mode 100644 index 00000000..6d4c11a7 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.viz.verify_spectrum_dataset.rst.txt @@ -0,0 +1,6 @@ +pyTEMlib.viz.verify\_spectrum\_dataset +====================================== + +.. currentmodule:: pyTEMlib.viz + +.. autofunction:: verify_spectrum_dataset \ No newline at end of file diff --git a/_sources/_autosummary/pyTEMlib.xrpa_x_sections.rst.txt b/_sources/_autosummary/pyTEMlib.xrpa_x_sections.rst.txt new file mode 100644 index 00000000..c1fc6596 --- /dev/null +++ b/_sources/_autosummary/pyTEMlib.xrpa_x_sections.rst.txt @@ -0,0 +1,23 @@ +pyTEMlib.xrpa\_x\_sections +========================== + +.. automodule:: pyTEMlib.xrpa_x_sections + + + + + + + + + + + + + + + + + + + diff --git a/_sources/about.rst.txt b/_sources/about.rst.txt new file mode 100644 index 00000000..c0e3696c --- /dev/null +++ b/_sources/about.rst.txt @@ -0,0 +1,70 @@ +======== +pyTEMlib +======== + +**Python framework for model based analysis of TEM/STEM data** + +What? +------ +* The `pyTEMlib <../pyTEMlib.html>`_: + + * is a `pycroscopy <../pycroscopy/about.html>`_ package based on `python `_ + * enables quantitative analysis through model based approach + * provides routines for the analysis of diffraction, image and spectroscopic datasets + * handles one, two, three, and four dimensional datasets + * works in jupyter notebooks and in python programs. + * provides dialog windows for metadata and analysis input in jupyter notebooks and in python programs. + +* pyNSID is a `python `_ package that currently provides three areas of analysis: + + #. **Diffraction**: Single and poly crystalline diffraction data and analysis in parallel and convergent illumination + #. **Imaging**: Image analysis, atom detection and image stack registration. + #. **EELS**: It provides a framework for quantification of EELS spectra and spectrum images. + +* Just as scipy uses numpy underneath, scientific packages like **pyTEMlib** use **sidpy** format for dataset representation +* and **pyNSID** for all file-handling. +* Dialogs are based on **pyQt5** and some features require **Ipython widgets** +* The packages **sidpy** and **pyNSID** use popular packages such as numpy, h5py, dask, matplotlib, etc. for most of +* the storage, computation, and visualization. + +.. note:: + We are running weekly hackathons for pycroscopy development every Friday from 3-5 PM - USA Eastern time. + The requirements for participation are: knowledge of python, numpy, h5py, git. + Please email vasudevanrk *at* ornl.gov to be added to the hackathons + +Why? +----- +pyTEMlib originates in the need for teaching and the development of new techniques for TEM/STEM data analysis. +Please, see my lecture note(-books) for information on the background of analysis. + + +**1. Growing data sizes** + * Cannot use desktop computers for analysis + * *Need: High performance computing, storage resources and compatible, scalable file structures* + +**2. Increasing data complexity** + * Sophisticated imaging and spectroscopy modes resulting in 5,6,7... dimensional data + * *Need: Robust software and generalized data formatting* + +**3. Multiple file formats** + * Different formats from each instrument. Proprietary in most cases + * Incompatible for correlation + * *Need: Open, instrument-independent data format* + +**4. Expensive analysis software** + * Software supplied with instruments often insufficient / incapable of custom analysis routines + * Commercial software (Eg: Matlab, Origin..) are often prohibitively expensive. + * *Need: Free, powerful, open source, user-friendly software* + +**5. Closed science** + * Analysis software and data not shared + * No guarantees of reproducibility or traceability + * *Need: open source data structures, file formats, centralized code and data repositories* + +Who? +---- +* We envision **pyTEMlib** to be a convenient package that facilitates all scientists to analyse data and develop new methods of anlysis, without being burdened with basic code functionality. +* This project is being led by staff members at Oak Ridge National Laboratory (ORNL), and professors at University of Tennessee, Knoxville +* We invite anyone interested to join our team to build better, free software for the scientific community +* Please visit our `credits and acknowledgements <./credits.html>`_ page for more information. +* If you are interested in integrating our in your existing package, please `get in touch <./contact.html>`_ with us. diff --git a/_sources/contact.rst.txt b/_sources/contact.rst.txt new file mode 100644 index 00000000..fd5230e8 --- /dev/null +++ b/_sources/contact.rst.txt @@ -0,0 +1,14 @@ +Contact us +========== +Here are a few options for you to get in touch with the developers and the user community +to ask questions, report bugs, request features etc: + +* If you have a GitHub account (free), please raise an `issue `_. +* If you have a GMail account (free), please start a new thread in our `google group `_ + +#. When reporting a bug / asking certain questions, we will be able to respond faster if you can provide: + + * a (simplified) script / snippet that reproduces the error(s) you are facing + * the full description of the error(s) + * details regarding your operating system (Mac / Windows / Linux) + * Software versions - python, pyNSID and core dependency packages (numpy, h5py, dask, matplotlib, etc.) \ No newline at end of file diff --git a/_sources/credits.rst.txt b/_sources/credits.rst.txt new file mode 100644 index 00000000..c1dbc9db --- /dev/null +++ b/_sources/credits.rst.txt @@ -0,0 +1,5 @@ +Credits +------- +The core pyTEMlib team consists of: + +* `@gduscher `_ (Prof. Gerd Duscher) \ No newline at end of file diff --git a/_sources/index.rst.txt b/_sources/index.rst.txt new file mode 100644 index 00000000..58e4119e --- /dev/null +++ b/_sources/index.rst.txt @@ -0,0 +1,42 @@ +.. pyTEMlib documentation master file, created by + sphinx-quickstart on Sun Jul 12 16:57:01 2020. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +pyTEMlib Documentation +====================== + +**Model Based Analysis of TEM/STEM Data** + +Last Update 03/25/2022 + +Jump to our `GitHub project page `_ + +.. toctree:: + :glob: + :maxdepth: 1 + :caption: pyTEMlib + + about + install + contact + credits + revisions + +Source code API +--------------- +.. autosummary:: + :toctree: _autosummary + :template: custom-module-template.rst + :recursive: + + pyTEMlib + +* :ref:`modindex` + +.. toctree:: + :glob: + :maxdepth: 2 + :caption: Examples + + notebooks/**/index diff --git a/_sources/install.rst.txt b/_sources/install.rst.txt new file mode 100644 index 00000000..60e71714 --- /dev/null +++ b/_sources/install.rst.txt @@ -0,0 +1,106 @@ +Installation +============ + +Preparing for pyTEMlib +-------------------- +`pyTEMlib `_ requires many commonly used scientific and numeric python packages such as numpy, h5py etc. +To simplify the installation process, we recommend the installation of +`Anaconda `_ which contains most of the prerequisite packages, +`conda `_ - a package / environment manager, +as well as an `interactive development environment `_ - `Spyder `_. + +Do you already have Anaconda installed? + +- No? + + - `Download and install Anaconda `_ for Python 3.6 + +- Yes? + + - Is your Anaconda based on python 3.5+? + + - No? + + - Uninstall existing Python / Anaconda distribution(s). + - Restart computer + - Yes? + + - Proceed to install pyTEMlib + +Compatibility +~~~~~~~~~~~~~ +* pyTEMlib is compatible with python 3.5 onwards. Please raise an issue if you find a bug. +* We do not support 32 bit architectures +* We only support text that is UTF-8 compliant due to restrictions posed by HDF5 + +Terminal +-------- +Installing, uninstalling, or updating pyTEMlib (or any other python package for that matter) can be performed using the ``Terminal`` application. +You will need to open the Terminal to type any command shown on this page. +Here is how you can access the Terminal on your computer: + +* Windows - Open ``Command Prompt`` by clicking on the Start button on the bottom left and typing ``cmd`` in the search box. + You can either click on the ``Command Prompt`` that appears in the search result or just hit the Enter button on your keyboard. + + * Note - be sure to install in a location where you have write access. Do not install as administrator unless you are required to do so. +* MacOS - Click on the ``Launchpad``. You will be presented a screen with a list of all your applications with a search box at the top. + Alternatively, simultaneously hold down the ``Command`` and ``Space`` keys on the keyboard to launch the ``Spotlight search``. + Type ``terminal`` in the search box and click on the ``Terminal`` application. +* Linux (e.g - Ubuntu) - Open the Dash by clicking the Ubuntu (or equivalent) icon in the upper-left, type "terminal". + Select the Terminal application from the results that appear. + +Installing pyTEMlib +----------------- +1. Ensure that a compatible Anaconda distribution has been successfully installed +2. Open a `terminal <#terminal>`_ window. +3. You can now install pyTEMlib via ``pip`` as shown below. + Type the following command into the terminal / command prompt and hit the Return / Enter key: + + * pip: + + .. code:: bash + + pip install pyTEMlib + + + + +Installing from a specific branch (advanced users **ONLY**) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Note that we do not recommend installing pyTEMlib this way since branches other than the master branch may contain bugs. + +.. note:: + Windows users will need to install ``git`` before proceeding. Please type the following command in the Command Prompt: + + .. code:: bash + + conda install git + +Install a specific branch of pyTEMlib (``dev`` in this case): + +.. code:: bash + + pip install -U git+https://github.com/pycroscopy/pyTEMlib@dev + + +Updating pyTEMlib +--------------- + +We recommend periodically updating your conda / anaconda distribution. Please see `these instructions to update anaconda <./external_guides.html#Updating-packages>`_. + +If you already have pyTEMlib installed and want to update to the latest version, use the following command in a terminal window: + +.. code:: bash + + pip install -U --no-deps pyTEMlib + +If it does not work try reinstalling the package: + +.. code:: bash + + pip uninstall pyTEMlib + pip install pyTEMlib + +Other software +-------------- +We recommend `HDF View `_ for exploring HDF5 files generated by and used in pyTEMlib. diff --git a/_sources/notebooks/EELS/index.rst.txt b/_sources/notebooks/EELS/index.rst.txt new file mode 100644 index 00000000..3629f54c --- /dev/null +++ b/_sources/notebooks/EELS/index.rst.txt @@ -0,0 +1,26 @@ +EELS_tools +========== + +part of + +pyTEMlib, a `pycroscopy library `_ + +by + +Gerd Duscher + +Materials Science & Engineering +Joint Institute of Advanced Materials +The University of Tennessee, Knoxville + +Usage of the EELS Tools of pyTEMlib + +* `Edge Onset `_ +* `Chemical Composition `_ + +.. toctree:: + :maxdepth: 1 + :hidden: + + Edge_Onset.ipynb + Analysis_Core_Loss.ipynb diff --git a/_sources/notebooks/Imaging/index.rst.txt b/_sources/notebooks/Imaging/index.rst.txt new file mode 100644 index 00000000..713a2e8c --- /dev/null +++ b/_sources/notebooks/Imaging/index.rst.txt @@ -0,0 +1,26 @@ +Image_tools +=========== + +part of + +pyTEMlib, a pycroscopy library + +by + +Gerd Duscher + +Materials Science & Engineering +Joint Institute of Advanced Materials +The University of Tennessee, Knoxville + +Usage of the Image Tools of pyTEMlib + +* `Adaptive Fourier Filter `_ +* `Registrater Image Stack `_ + +.. toctree:: + :maxdepth: 1 + :hidden: + + Adaptive_Fourier_Filter.ipynb + Register_Image_Stack.ipynb \ No newline at end of file diff --git a/_sources/revisions.rst.txt b/_sources/revisions.rst.txt new file mode 100644 index 00000000..4cac77ca --- /dev/null +++ b/_sources/revisions.rst.txt @@ -0,0 +1,13 @@ +Revisions +========= + +Starting with revision from version 0.2021.2.22 + +Revision 0.2021.3.1 +----------------- + +- Moved **read_poscar** function from *kinematic_scattering* to *file_tools.py* and added **read_cif** function. +- Revised kinematic scattering library and renamed to *kinematic_scattering.py*. This function handles tilted samples +better. +- added **image_dialog** to *interactive_image* with interactive histogram to change contrast in images +- added multislice tools in dynamic_scattering.py (supercell potential is rather basic) \ No newline at end of file diff --git a/_static/basic.css b/_static/basic.css new file mode 100644 index 00000000..cfc60b86 --- /dev/null +++ b/_static/basic.css @@ -0,0 +1,921 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/_static/css/badge_only.css b/_static/css/badge_only.css new file mode 100644 index 00000000..c718cee4 --- /dev/null +++ b/_static/css/badge_only.css @@ -0,0 +1 @@ +.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} \ No newline at end of file diff --git a/_static/css/fonts/Roboto-Slab-Bold.woff b/_static/css/fonts/Roboto-Slab-Bold.woff new file mode 100644 index 00000000..6cb60000 Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Bold.woff differ diff --git a/_static/css/fonts/Roboto-Slab-Bold.woff2 b/_static/css/fonts/Roboto-Slab-Bold.woff2 new file mode 100644 index 00000000..7059e231 Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Bold.woff2 differ diff --git a/_static/css/fonts/Roboto-Slab-Regular.woff b/_static/css/fonts/Roboto-Slab-Regular.woff new file mode 100644 index 00000000..f815f63f Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Regular.woff differ diff --git a/_static/css/fonts/Roboto-Slab-Regular.woff2 b/_static/css/fonts/Roboto-Slab-Regular.woff2 new file mode 100644 index 00000000..f2c76e5b Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Regular.woff2 differ diff --git a/_static/css/fonts/fontawesome-webfont.eot b/_static/css/fonts/fontawesome-webfont.eot new file mode 100644 index 00000000..e9f60ca9 Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.eot differ diff --git a/_static/css/fonts/fontawesome-webfont.svg b/_static/css/fonts/fontawesome-webfont.svg new file mode 100644 index 00000000..855c845e --- /dev/null +++ b/_static/css/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_static/css/fonts/fontawesome-webfont.ttf b/_static/css/fonts/fontawesome-webfont.ttf new file mode 100644 index 00000000..35acda2f Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.ttf differ diff --git a/_static/css/fonts/fontawesome-webfont.woff b/_static/css/fonts/fontawesome-webfont.woff new file mode 100644 index 00000000..400014a4 Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.woff differ diff --git a/_static/css/fonts/fontawesome-webfont.woff2 b/_static/css/fonts/fontawesome-webfont.woff2 new file mode 100644 index 00000000..4d13fc60 Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.woff2 differ diff --git a/_static/css/fonts/lato-bold-italic.woff b/_static/css/fonts/lato-bold-italic.woff new file mode 100644 index 00000000..88ad05b9 Binary files /dev/null and b/_static/css/fonts/lato-bold-italic.woff differ diff --git a/_static/css/fonts/lato-bold-italic.woff2 b/_static/css/fonts/lato-bold-italic.woff2 new file mode 100644 index 00000000..c4e3d804 Binary files /dev/null and b/_static/css/fonts/lato-bold-italic.woff2 differ diff --git a/_static/css/fonts/lato-bold.woff b/_static/css/fonts/lato-bold.woff new file mode 100644 index 00000000..c6dff51f Binary files /dev/null and b/_static/css/fonts/lato-bold.woff differ diff --git a/_static/css/fonts/lato-bold.woff2 b/_static/css/fonts/lato-bold.woff2 new file mode 100644 index 00000000..bb195043 Binary files /dev/null and b/_static/css/fonts/lato-bold.woff2 differ diff --git a/_static/css/fonts/lato-normal-italic.woff b/_static/css/fonts/lato-normal-italic.woff new file mode 100644 index 00000000..76114bc0 Binary files /dev/null and b/_static/css/fonts/lato-normal-italic.woff differ diff --git a/_static/css/fonts/lato-normal-italic.woff2 b/_static/css/fonts/lato-normal-italic.woff2 new file mode 100644 index 00000000..3404f37e Binary files /dev/null and b/_static/css/fonts/lato-normal-italic.woff2 differ diff --git a/_static/css/fonts/lato-normal.woff b/_static/css/fonts/lato-normal.woff new file mode 100644 index 00000000..ae1307ff Binary files /dev/null and b/_static/css/fonts/lato-normal.woff differ diff --git a/_static/css/fonts/lato-normal.woff2 b/_static/css/fonts/lato-normal.woff2 new file mode 100644 index 00000000..3bf98433 Binary files /dev/null and b/_static/css/fonts/lato-normal.woff2 differ diff --git a/_static/css/theme.css b/_static/css/theme.css new file mode 100644 index 00000000..19a446a0 --- /dev/null +++ b/_static/css/theme.css @@ -0,0 +1,4 @@ +html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel,.rst-content .menuselection{font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .guilabel,.rst-content .menuselection{border:1px solid #7fbbe3;background:#e7f2fa}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} \ No newline at end of file diff --git a/_static/doctools.js b/_static/doctools.js new file mode 100644 index 00000000..d06a71d7 --- /dev/null +++ b/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/_static/documentation_options.js b/_static/documentation_options.js new file mode 100644 index 00000000..7b32a105 --- /dev/null +++ b/_static/documentation_options.js @@ -0,0 +1,14 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '0.2023.9.19.dev1', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/_static/file.png b/_static/file.png new file mode 100644 index 00000000..a858a410 Binary files /dev/null and b/_static/file.png differ diff --git a/_static/js/badge_only.js b/_static/js/badge_only.js new file mode 100644 index 00000000..526d7234 --- /dev/null +++ b/_static/js/badge_only.js @@ -0,0 +1 @@ +!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}({4:function(e,t,r){}}); \ No newline at end of file diff --git a/_static/js/html5shiv-printshiv.min.js b/_static/js/html5shiv-printshiv.min.js new file mode 100644 index 00000000..2b43bd06 --- /dev/null +++ b/_static/js/html5shiv-printshiv.min.js @@ -0,0 +1,4 @@ +/** +* @preserve HTML5 Shiv 3.7.3-pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed +*/ +!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=y.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=y.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),y.elements=c+" "+a,j(b)}function f(a){var b=x[a[v]];return b||(b={},w++,a[v]=w,x[w]=b),b}function g(a,c,d){if(c||(c=b),q)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():u.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||t.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),q)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return y.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(y,b.frag)}function j(a){a||(a=b);var d=f(a);return!y.shivCSS||p||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),q||i(a,d),a}function k(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(l(b)));return g}function l(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(A+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function m(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+A+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function n(a){for(var b=a.length;b--;)a[b].removeNode()}function o(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,e,g=f(a),h=a.namespaces,i=a.parentWindow;return!B||a.printShived?a:("undefined"==typeof h[A]&&h.add(A),i.attachEvent("onbeforeprint",function(){b();for(var f,g,h,i=a.styleSheets,j=[],l=i.length,n=Array(l);l--;)n[l]=i[l];for(;h=n.pop();)if(!h.disabled&&z.test(h.media)){try{f=h.imports,g=f.length}catch(o){g=0}for(l=0;g>l;l++)n.push(f[l]);try{j.push(h.cssText)}catch(o){}}j=m(j.reverse().join("")),e=k(a),d=c(a,j)}),i.attachEvent("onafterprint",function(){n(e),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var p,q,r="3.7.3",s=a.html5||{},t=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,u=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="",p="hidden"in a,q=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){p=!0,q=!0}}();var y={elements:s.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:r,shivCSS:s.shivCSS!==!1,supportsUnknownElements:q,shivMethods:s.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=y,j(b);var z=/^$|\b(?:all|print)\b/,A="html5shiv",B=!q&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();y.type+=" print",y.shivPrint=o,o(b),"object"==typeof module&&module.exports&&(module.exports=y)}("undefined"!=typeof window?window:this,document); \ No newline at end of file diff --git a/_static/js/html5shiv.min.js b/_static/js/html5shiv.min.js new file mode 100644 index 00000000..cd1c674f --- /dev/null +++ b/_static/js/html5shiv.min.js @@ -0,0 +1,4 @@ +/** +* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed +*/ +!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3-pre",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); \ No newline at end of file diff --git a/_static/js/theme.js b/_static/js/theme.js new file mode 100644 index 00000000..1fddb6ee --- /dev/null +++ b/_static/js/theme.js @@ -0,0 +1 @@ +!function(n){var e={};function t(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return n[i].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,i){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:i})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var i=Object.create(null);if(t.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(i,o,function(e){return n[e]}.bind(null,o));return i},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){t(1),n.exports=t(3)},function(n,e,t){(function(){var e="undefined"!=typeof window?window.jQuery:t(2);n.exports.ThemeNav={navBar:null,win:null,winScroll:!1,winResize:!1,linkScroll:!1,winPosition:0,winHeight:null,docHeight:null,isRunning:!1,enable:function(n){var t=this;void 0===n&&(n=!0),t.isRunning||(t.isRunning=!0,e((function(e){t.init(e),t.reset(),t.win.on("hashchange",t.reset),n&&t.win.on("scroll",(function(){t.linkScroll||t.winScroll||(t.winScroll=!0,requestAnimationFrame((function(){t.onScroll()})))})),t.win.on("resize",(function(){t.winResize||(t.winResize=!0,requestAnimationFrame((function(){t.onResize()})))})),t.onResize()})))},enableSticky:function(){this.enable(!0)},init:function(n){n(document);var e=this;this.navBar=n("div.wy-side-scroll:first"),this.win=n(window),n(document).on("click","[data-toggle='wy-nav-top']",(function(){n("[data-toggle='wy-nav-shift']").toggleClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift")})).on("click",".wy-menu-vertical .current ul li a",(function(){var t=n(this);n("[data-toggle='wy-nav-shift']").removeClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift"),e.toggleCurrent(t),e.hashChange()})).on("click","[data-toggle='rst-current-version']",(function(){n("[data-toggle='rst-versions']").toggleClass("shift-up")})),n("table.docutils:not(.field-list,.footnote,.citation)").wrap("
"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/_static/minus.png b/_static/minus.png new file mode 100644 index 00000000..d96755fd Binary files /dev/null and b/_static/minus.png differ diff --git a/_static/plus.png b/_static/plus.png new file mode 100644 index 00000000..7107cec9 Binary files /dev/null and b/_static/plus.png differ diff --git a/_static/pygments.css b/_static/pygments.css new file mode 100644 index 00000000..0d49244e --- /dev/null +++ b/_static/pygments.css @@ -0,0 +1,75 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #eeffcc; } +.highlight .c { color: #408090; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #007020 } /* Comment.Preproc */ +.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #333333 } /* Generic.Output */ +.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0044DD } /* Generic.Traceback */ +.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #902000 } /* Keyword.Type */ +.highlight .m { color: #208050 } /* Literal.Number */ +.highlight .s { color: #4070a0 } /* Literal.String */ +.highlight .na { color: #4070a0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ +.highlight .no { color: #60add5 } /* Name.Constant */ +.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #007020 } /* Name.Exception */ +.highlight .nf { color: #06287e } /* Name.Function */ +.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #bb60d5 } /* Name.Variable */ +.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mb { color: #208050 } /* Literal.Number.Bin */ +.highlight .mf { color: #208050 } /* Literal.Number.Float */ +.highlight .mh { color: #208050 } /* Literal.Number.Hex */ +.highlight .mi { color: #208050 } /* Literal.Number.Integer */ +.highlight .mo { color: #208050 } /* Literal.Number.Oct */ +.highlight .sa { color: #4070a0 } /* Literal.String.Affix */ +.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ +.highlight .sc { color: #4070a0 } /* Literal.String.Char */ +.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ +.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4070a0 } /* Literal.String.Double */ +.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ +.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ +.highlight .sx { color: #c65d09 } /* Literal.String.Other */ +.highlight .sr { color: #235388 } /* Literal.String.Regex */ +.highlight .s1 { color: #4070a0 } /* Literal.String.Single */ +.highlight .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #06287e } /* Name.Function.Magic */ +.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ +.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ +.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ +.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ +.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/_static/searchtools.js b/_static/searchtools.js new file mode 100644 index 00000000..97d56a74 --- /dev/null +++ b/_static/searchtools.js @@ -0,0 +1,566 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = docUrlRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = docUrlRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms) + ); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + `Search finished, found ${resultCount} page(s) matching the search query.` + ); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent !== undefined) return docContent.textContent; + console.warn( + "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + /** + * execute search (requires search index to be loaded) + */ + query: (query) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + // array of [docname, title, anchor, descr, score, filename] + let results = []; + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + let score = Math.round(100 * queryLower.length / title.length) + results.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id] of foundEntries) { + let score = Math.round(100 * queryLower.length / entry.length) + results.push([ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // lookup as object + objectTerms.forEach((term) => + results.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); + + // now sort the results by score (in opposite order of appearance, since the + // display function below uses pop() to retrieve items) and then + // alphabetically + results.sort((a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; + }); + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + results = results.reverse(); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord) && !terms[word]) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord) && !titleTerms[word]) + arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); + }); + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + else fileMap.set(file, [word]); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords) => { + const text = Search.htmlToText(htmlText); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/_static/sphinx_highlight.js b/_static/sphinx_highlight.js new file mode 100644 index 00000000..aae669d7 --- /dev/null +++ b/_static/sphinx_highlight.js @@ -0,0 +1,144 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + parent.insertBefore( + span, + parent.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(SphinxHighlight.highlightSearchWords); +_ready(SphinxHighlight.initEscapeListener); diff --git a/about.html b/about.html new file mode 100644 index 00000000..4186ee8f --- /dev/null +++ b/about.html @@ -0,0 +1,207 @@ + + + + + + + pyTEMlib — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib

+

Python framework for model based analysis of TEM/STEM data

+
+

What?

+
    +
  • The pyTEMlib:

    +
      +
    • is a pycroscopy package based on python

    • +
    • enables quantitative analysis through model based approach

    • +
    • provides routines for the analysis of diffraction, image and spectroscopic datasets

    • +
    • handles one, two, three, and four dimensional datasets

    • +
    • works in jupyter notebooks and in python programs.

    • +
    • provides dialog windows for metadata and analysis input in jupyter notebooks and in python programs.

    • +
    +
  • +
  • pyNSID is a python package that currently provides three areas of analysis:

    +
      +
    1. Diffraction: Single and poly crystalline diffraction data and analysis in parallel and convergent illumination

    2. +
    3. Imaging: Image analysis, atom detection and image stack registration.

    4. +
    5. EELS: It provides a framework for quantification of EELS spectra and spectrum images.

    6. +
    +
  • +
  • Just as scipy uses numpy underneath, scientific packages like pyTEMlib use sidpy format for dataset representation

  • +
  • and pyNSID for all file-handling.

  • +
  • Dialogs are based on pyQt5 and some features require Ipython widgets

  • +
  • The packages sidpy and pyNSID use popular packages such as numpy, h5py, dask, matplotlib, etc. for most of

  • +
  • the storage, computation, and visualization.

  • +
+
+

Note

+

We are running weekly hackathons for pycroscopy development every Friday from 3-5 PM - USA Eastern time. +The requirements for participation are: knowledge of python, numpy, h5py, git. +Please email vasudevanrk at ornl.gov to be added to the hackathons

+
+
+
+

Why?

+

pyTEMlib originates in the need for teaching and the development of new techniques for TEM/STEM data analysis. +Please, see my lecture note(-books) for information on the background of analysis.

+
+
1. Growing data sizes
    +
  • Cannot use desktop computers for analysis

  • +
  • Need: High performance computing, storage resources and compatible, scalable file structures

  • +
+
+
2. Increasing data complexity
    +
  • Sophisticated imaging and spectroscopy modes resulting in 5,6,7… dimensional data

  • +
  • Need: Robust software and generalized data formatting

  • +
+
+
3. Multiple file formats
    +
  • Different formats from each instrument. Proprietary in most cases

  • +
  • Incompatible for correlation

  • +
  • Need: Open, instrument-independent data format

  • +
+
+
4. Expensive analysis software
    +
  • Software supplied with instruments often insufficient / incapable of custom analysis routines

  • +
  • Commercial software (Eg: Matlab, Origin..) are often prohibitively expensive.

  • +
  • Need: Free, powerful, open source, user-friendly software

  • +
+
+
5. Closed science
    +
  • Analysis software and data not shared

  • +
  • No guarantees of reproducibility or traceability

  • +
  • Need: open source data structures, file formats, centralized code and data repositories

  • +
+
+
+
+
+

Who?

+
    +
  • We envision pyTEMlib to be a convenient package that facilitates all scientists to analyse data and develop new methods of anlysis, without being burdened with basic code functionality.

  • +
  • This project is being led by staff members at Oak Ridge National Laboratory (ORNL), and professors at University of Tennessee, Knoxville

  • +
  • We invite anyone interested to join our team to build better, free software for the scientific community

  • +
  • Please visit our credits and acknowledgements page for more information.

  • +
  • If you are interested in integrating our in your existing package, please get in touch with us.

  • +
+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/contact.html b/contact.html new file mode 100644 index 00000000..6ca18879 --- /dev/null +++ b/contact.html @@ -0,0 +1,139 @@ + + + + + + + Contact us — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Contact us

+

Here are a few options for you to get in touch with the developers and the user community +to ask questions, report bugs, request features etc:

+
    +
  • If you have a GitHub account (free), please raise an issue.

  • +
  • If you have a GMail account (free), please start a new thread in our google group

  • +
+
    +
  1. When reporting a bug / asking certain questions, we will be able to respond faster if you can provide:

    +
      +
    • a (simplified) script / snippet that reproduces the error(s) you are facing

    • +
    • the full description of the error(s)

    • +
    • details regarding your operating system (Mac / Windows / Linux)

    • +
    • Software versions - python, pyNSID and core dependency packages (numpy, h5py, dask, matplotlib, etc.)

    • +
    +
  2. +
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/credits.html b/credits.html new file mode 100644 index 00000000..a7012981 --- /dev/null +++ b/credits.html @@ -0,0 +1,127 @@ + + + + + + + Credits — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Credits

+

The core pyTEMlib team consists of:

+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/genindex.html b/genindex.html new file mode 100644 index 00000000..97a50de1 --- /dev/null +++ b/genindex.html @@ -0,0 +1,1430 @@ + + + + + + Index — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + +

Index

+ +
+ _ + | A + | B + | C + | D + | E + | F + | G + | H + | I + | J + | K + | L + | M + | N + | O + | P + | R + | S + | T + | U + | V + | W + | X + | Y + | Z + +
+

_

+ + + +
+ +

A

+ + + +
+ +

B

+ + + +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

E

+ + + +
+ +

F

+ + + +
+ +

G

+ + + +
+ +

H

+ + + +
+ +

I

+ + + +
+ +

J

+ + +
+ +

K

+ + + +
+ +

L

+ + + +
+ +

M

+ + + +
+ +

N

+ + +
+ +

O

+ + + +
+ +

P

+ + + +
    +
  • + pyTEMlib.eels_dialog + +
  • +
  • + pyTEMlib.eels_dialog_utilities + +
  • +
  • + pyTEMlib.eels_dlg + +
  • +
  • + pyTEMlib.eels_tools + +
  • +
  • + pyTEMlib.file_tools + +
  • +
  • + pyTEMlib.file_tools_qt + +
  • +
  • + pyTEMlib.graph_tools + +
  • +
  • + pyTEMlib.graph_viz + +
  • +
  • + pyTEMlib.image_dialog + +
  • +
  • + pyTEMlib.image_dlg + +
  • +
  • + pyTEMlib.image_tools + +
  • +
  • + pyTEMlib.info_dialog + +
  • +
  • + pyTEMlib.info_dlg + +
  • +
  • + pyTEMlib.info_widget + +
  • +
  • + pyTEMlib.interactive_eels + +
  • +
  • + pyTEMlib.interactive_image + +
  • +
  • + pyTEMlib.kinematic_scattering + +
  • +
  • + pyTEMlib.microscope + +
  • +
  • + pyTEMlib.peak_dialog + +
  • +
  • + pyTEMlib.peak_dlg + +
  • +
  • + pyTEMlib.probe_tools + +
  • +
  • + pyTEMlib.sidpy_tools + +
  • +
  • + pyTEMlib.simulation_tools + +
  • +
  • + pyTEMlib.version + +
  • +
  • + pyTEMlib.viz + +
  • +
  • + pyTEMlib.xrpa_x_sections + +
  • +
+ +

R

+ + + +
+ +

S

+ + + +
+ +

T

+ + + +
+ +

U

+ + + +
+ +

V

+ + + +
+ +

W

+ + +
+ +

X

+ + + +
+ +

Y

+ + +
+ +

Z

+ + + +
+ + + +
+
+
+ +
+ +
+

© Copyright 2020, Gerd Duscher, and contributors.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..060177e1 --- /dev/null +++ b/index.html @@ -0,0 +1,154 @@ + + + + + + + pyTEMlib Documentation — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

pyTEMlib Documentation

+

Model Based Analysis of TEM/STEM Data

+

Last Update 03/25/2022

+

Jump to our GitHub project page

+ +
+

Source code API

+ + + + + + +

pyTEMlib

Created on Sat Jan 19 10:07:35 2019

+ +
+

Examples

+ +
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2020, Gerd Duscher, and contributors.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/install.html b/install.html new file mode 100644 index 00000000..d772a6a1 --- /dev/null +++ b/install.html @@ -0,0 +1,247 @@ + + + + + + + Installation — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Installation

+
+

Preparing for pyTEMlib

+

pyTEMlib requires many commonly used scientific and numeric python packages such as numpy, h5py etc. +To simplify the installation process, we recommend the installation of +Anaconda which contains most of the prerequisite packages, +conda - a package / environment manager, +as well as an interactive development environment - Spyder.

+

Do you already have Anaconda installed?

+
    +
  • No?

    + +
  • +
  • Yes?

    +
      +
    • Is your Anaconda based on python 3.5+?

      +
        +
      • No?

        +
          +
        • Uninstall existing Python / Anaconda distribution(s).

        • +
        • Restart computer

        • +
        +
      • +
      • Yes?

        +
          +
        • Proceed to install pyTEMlib

        • +
        +
      • +
      +
    • +
    +
  • +
+
+

Compatibility

+
    +
  • pyTEMlib is compatible with python 3.5 onwards. Please raise an issue if you find a bug.

  • +
  • We do not support 32 bit architectures

  • +
  • We only support text that is UTF-8 compliant due to restrictions posed by HDF5

  • +
+
+
+
+

Terminal

+

Installing, uninstalling, or updating pyTEMlib (or any other python package for that matter) can be performed using the Terminal application. +You will need to open the Terminal to type any command shown on this page. +Here is how you can access the Terminal on your computer:

+
    +
  • Windows - Open Command Prompt by clicking on the Start button on the bottom left and typing cmd in the search box. +You can either click on the Command Prompt that appears in the search result or just hit the Enter button on your keyboard.

    +
      +
    • Note - be sure to install in a location where you have write access. Do not install as administrator unless you are required to do so.

    • +
    +
  • +
  • MacOS - Click on the Launchpad. You will be presented a screen with a list of all your applications with a search box at the top. +Alternatively, simultaneously hold down the Command and Space keys on the keyboard to launch the Spotlight search. +Type terminal in the search box and click on the Terminal application.

  • +
  • Linux (e.g - Ubuntu) - Open the Dash by clicking the Ubuntu (or equivalent) icon in the upper-left, type “terminal”. +Select the Terminal application from the results that appear.

  • +
+
+
+

Installing pyTEMlib

+
    +
  1. Ensure that a compatible Anaconda distribution has been successfully installed

  2. +
  3. Open a terminal window.

  4. +
  5. You can now install pyTEMlib via pip as shown below. +Type the following command into the terminal / command prompt and hit the Return / Enter key:

    +
      +
    • pip:

      +
      pip install pyTEMlib
      +
      +
      +
    • +
    +
  6. +
+
+

Installing from a specific branch (advanced users ONLY)

+

Note that we do not recommend installing pyTEMlib this way since branches other than the master branch may contain bugs.

+
+

Note

+

Windows users will need to install git before proceeding. Please type the following command in the Command Prompt:

+
conda install git
+
+
+
+

Install a specific branch of pyTEMlib (dev in this case):

+
pip install -U git+https://github.com/pycroscopy/pyTEMlib@dev
+
+
+
+
+
+

Updating pyTEMlib

+

We recommend periodically updating your conda / anaconda distribution. Please see these instructions to update anaconda.

+

If you already have pyTEMlib installed and want to update to the latest version, use the following command in a terminal window:

+
pip install -U --no-deps pyTEMlib
+
+
+

If it does not work try reinstalling the package:

+
pip uninstall pyTEMlib
+pip install pyTEMlib
+
+
+
+
+

Other software

+

We recommend HDF View for exploring HDF5 files generated by and used in pyTEMlib.

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/notebooks/EELS/index.html b/notebooks/EELS/index.html new file mode 100644 index 00000000..8422dbcd --- /dev/null +++ b/notebooks/EELS/index.html @@ -0,0 +1,139 @@ + + + + + + + EELS_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

EELS_tools

+

part of

+

pyTEMlib, a pycroscopy library

+

by

+

Gerd Duscher

+

Materials Science & Engineering +Joint Institute of Advanced Materials +The University of Tennessee, Knoxville

+

Usage of the EELS Tools of pyTEMlib

+ +
+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/notebooks/Imaging/index.html b/notebooks/Imaging/index.html new file mode 100644 index 00000000..5ad085c0 --- /dev/null +++ b/notebooks/Imaging/index.html @@ -0,0 +1,137 @@ + + + + + + + Image_tools — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Image_tools

+

part of

+

pyTEMlib, a pycroscopy library

+

by

+

Gerd Duscher

+

Materials Science & Engineering +Joint Institute of Advanced Materials +The University of Tennessee, Knoxville

+

Usage of the Image Tools of pyTEMlib

+ +
+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/objects.inv b/objects.inv new file mode 100644 index 00000000..45fa214d Binary files /dev/null and b/objects.inv differ diff --git a/py-modindex.html b/py-modindex.html new file mode 100644 index 00000000..7479020e --- /dev/null +++ b/py-modindex.html @@ -0,0 +1,299 @@ + + + + + + Python Module Index — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + +

Python Module Index

+ +
+ p +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ p
+ pyTEMlib +
    + pyTEMlib.animation +
    + pyTEMlib.atom_tools +
    + pyTEMlib.config_dir +
    + pyTEMlib.crystal_tools +
    + pyTEMlib.diffraction_plot +
    + pyTEMlib.dynamic_scattering +
    + pyTEMlib.eds_tools +
    + pyTEMlib.eels_dialog +
    + pyTEMlib.eels_dialog_utilities +
    + pyTEMlib.eels_dlg +
    + pyTEMlib.eels_tools +
    + pyTEMlib.file_tools +
    + pyTEMlib.file_tools_qt +
    + pyTEMlib.graph_tools +
    + pyTEMlib.graph_viz +
    + pyTEMlib.image_dialog +
    + pyTEMlib.image_dlg +
    + pyTEMlib.image_tools +
    + pyTEMlib.info_dialog +
    + pyTEMlib.info_dlg +
    + pyTEMlib.info_widget +
    + pyTEMlib.interactive_eels +
    + pyTEMlib.interactive_image +
    + pyTEMlib.kinematic_scattering +
    + pyTEMlib.microscope +
    + pyTEMlib.peak_dialog +
    + pyTEMlib.peak_dlg +
    + pyTEMlib.probe_tools +
    + pyTEMlib.sidpy_tools +
    + pyTEMlib.simulation_tools +
    + pyTEMlib.version +
    + pyTEMlib.viz +
    + pyTEMlib.xrpa_x_sections +
+ + +
+
+
+ +
+ +
+

© Copyright 2020, Gerd Duscher, and contributors.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/revisions.html b/revisions.html new file mode 100644 index 00000000..9bab3c6e --- /dev/null +++ b/revisions.html @@ -0,0 +1,137 @@ + + + + + + + Revisions — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Revisions

+

Starting with revision from version 0.2021.2.22

+
+

Revision 0.2021.3.1

+
    +
  • Moved read_poscar function from kinematic_scattering to file_tools.py and added read_cif function.

  • +
  • Revised kinematic scattering library and renamed to kinematic_scattering.py. This function handles tilted samples

  • +
+

better. +- added image_dialog to interactive_image with interactive histogram to change contrast in images +- added multislice tools in dynamic_scattering.py (supercell potential is rather basic)

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/search.html b/search.html new file mode 100644 index 00000000..c1dac1ac --- /dev/null +++ b/search.html @@ -0,0 +1,134 @@ + + + + + + Search — pyTEMlib 0.2023.9.19.dev1 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + + + +
+ +
+ +
+
+
+ +
+ +
+

© Copyright 2020, Gerd Duscher, and contributors.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/searchindex.js b/searchindex.js new file mode 100644 index 00000000..dd07ec35 --- /dev/null +++ b/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["_autosummary/pyTEMlib", "_autosummary/pyTEMlib.animation", "_autosummary/pyTEMlib.animation.InteractiveAberration", "_autosummary/pyTEMlib.animation.InteractiveRonchigramMagnification", "_autosummary/pyTEMlib.animation.add_aperture", "_autosummary/pyTEMlib.animation.add_lens", "_autosummary/pyTEMlib.animation.deficient_holz_line", "_autosummary/pyTEMlib.animation.deficient_kikuchi_line", "_autosummary/pyTEMlib.animation.geometric_ray_diagram", "_autosummary/pyTEMlib.animation.propagate_beam", "_autosummary/pyTEMlib.atom_tools", "_autosummary/pyTEMlib.atom_tools.atom_refine", "_autosummary/pyTEMlib.atom_tools.atoms_clustering", "_autosummary/pyTEMlib.atom_tools.find_atoms", "_autosummary/pyTEMlib.atom_tools.gauss_difference", "_autosummary/pyTEMlib.atom_tools.intensity_area", "_autosummary/pyTEMlib.config_dir", "_autosummary/pyTEMlib.crystal_tools", "_autosummary/pyTEMlib.crystal_tools.atoms_from_dictionary", "_autosummary/pyTEMlib.crystal_tools.ball_and_stick", "_autosummary/pyTEMlib.crystal_tools.get_dictionary", "_autosummary/pyTEMlib.crystal_tools.get_projection", "_autosummary/pyTEMlib.crystal_tools.get_symmetry", "_autosummary/pyTEMlib.crystal_tools.jmol_viewer", "_autosummary/pyTEMlib.crystal_tools.plot_super_cell", "_autosummary/pyTEMlib.crystal_tools.plot_unit_cell", "_autosummary/pyTEMlib.crystal_tools.set_bond_radii", "_autosummary/pyTEMlib.crystal_tools.structure_by_name", "_autosummary/pyTEMlib.diffraction_plot", "_autosummary/pyTEMlib.diffraction_plot.cartesian2polar", "_autosummary/pyTEMlib.diffraction_plot.circles", "_autosummary/pyTEMlib.diffraction_plot.plotCBED_parameter", "_autosummary/pyTEMlib.diffraction_plot.plotHOLZ_parameter", "_autosummary/pyTEMlib.diffraction_plot.plotKikuchi", "_autosummary/pyTEMlib.diffraction_plot.plotSAED_parameter", "_autosummary/pyTEMlib.diffraction_plot.plot_diffraction_pattern", "_autosummary/pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D", "_autosummary/pyTEMlib.diffraction_plot.plot_ring_pattern", "_autosummary/pyTEMlib.diffraction_plot.topolar", "_autosummary/pyTEMlib.diffraction_plot.warp", "_autosummary/pyTEMlib.dynamic_scattering", "_autosummary/pyTEMlib.dynamic_scattering.get_propagator", "_autosummary/pyTEMlib.dynamic_scattering.get_transmission", "_autosummary/pyTEMlib.dynamic_scattering.interaction_parameter", "_autosummary/pyTEMlib.dynamic_scattering.make_chi", "_autosummary/pyTEMlib.dynamic_scattering.multi_slice", "_autosummary/pyTEMlib.dynamic_scattering.objective_lens_function", "_autosummary/pyTEMlib.dynamic_scattering.potential_1dim", "_autosummary/pyTEMlib.dynamic_scattering.potential_2dim", "_autosummary/pyTEMlib.eds_tools", "_autosummary/pyTEMlib.eds_tools.detect_peaks", "_autosummary/pyTEMlib.eds_tools.detector_response", "_autosummary/pyTEMlib.eds_tools.find_elements", "_autosummary/pyTEMlib.eds_tools.fit_model", "_autosummary/pyTEMlib.eds_tools.gaussian", "_autosummary/pyTEMlib.eds_tools.getFWHM", "_autosummary/pyTEMlib.eds_tools.get_eds_cross_sections", "_autosummary/pyTEMlib.eds_tools.get_eds_xsection", "_autosummary/pyTEMlib.eds_tools.get_model", "_autosummary/pyTEMlib.eds_tools.get_peak", "_autosummary/pyTEMlib.eds_tools.get_x_ray_lines", "_autosummary/pyTEMlib.eds_tools.update_fit_values", "_autosummary/pyTEMlib.eels_dialog", "_autosummary/pyTEMlib.eels_dialog.CompositionWidget", "_autosummary/pyTEMlib.eels_dialog.get_sidebar", "_autosummary/pyTEMlib.eels_dialog_utilities", "_autosummary/pyTEMlib.eels_dialog_utilities.EdgesAtCursor", "_autosummary/pyTEMlib.eels_dialog_utilities.ElementalEdges", "_autosummary/pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage", "_autosummary/pyTEMlib.eels_dialog_utilities.PeriodicTableWidget", "_autosummary/pyTEMlib.eels_dialog_utilities.RangeSelector", "_autosummary/pyTEMlib.eels_dialog_utilities.RegionSelector", "_autosummary/pyTEMlib.eels_dialog_utilities.SIPlot", "_autosummary/pyTEMlib.eels_dialog_utilities.SpectrumPlot", "_autosummary/pyTEMlib.eels_dialog_utilities.get_likely_edges", "_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_info", "_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_widget", "_autosummary/pyTEMlib.eels_dialog_utilities.make_box_layout", "_autosummary/pyTEMlib.eels_dialog_utilities.plot_EELS", "_autosummary/pyTEMlib.eels_dlg", "_autosummary/pyTEMlib.eels_tools", "_autosummary/pyTEMlib.eels_tools.add_element_to_dataset", "_autosummary/pyTEMlib.eels_tools.add_peaks", "_autosummary/pyTEMlib.eels_tools.assign_likely_edges", "_autosummary/pyTEMlib.eels_tools.auto_chemical_composition", "_autosummary/pyTEMlib.eels_tools.auto_id_edges", "_autosummary/pyTEMlib.eels_tools.cl_model", "_autosummary/pyTEMlib.eels_tools.drude", "_autosummary/pyTEMlib.eels_tools.drude2", "_autosummary/pyTEMlib.eels_tools.drude_lorentz", "_autosummary/pyTEMlib.eels_tools.drude_simulation", "_autosummary/pyTEMlib.eels_tools.effective_collection_angle", "_autosummary/pyTEMlib.eels_tools.find_all_edges", "_autosummary/pyTEMlib.eels_tools.find_associated_edges", "_autosummary/pyTEMlib.eels_tools.find_edges", "_autosummary/pyTEMlib.eels_tools.find_major_edges", "_autosummary/pyTEMlib.eels_tools.find_maxima", "_autosummary/pyTEMlib.eels_tools.find_peaks", "_autosummary/pyTEMlib.eels_tools.find_white_lines", "_autosummary/pyTEMlib.eels_tools.fit_dataset", "_autosummary/pyTEMlib.eels_tools.fit_edges", "_autosummary/pyTEMlib.eels_tools.fit_edges2", "_autosummary/pyTEMlib.eels_tools.fit_model", "_autosummary/pyTEMlib.eels_tools.fit_peaks", "_autosummary/pyTEMlib.eels_tools.fix_energy_scale", "_autosummary/pyTEMlib.eels_tools.gauss", "_autosummary/pyTEMlib.eels_tools.get_energy_shifts", "_autosummary/pyTEMlib.eels_tools.get_resolution_functions", "_autosummary/pyTEMlib.eels_tools.get_spectrum_eels_db", "_autosummary/pyTEMlib.eels_tools.get_wave_length", "_autosummary/pyTEMlib.eels_tools.get_x_sections", "_autosummary/pyTEMlib.eels_tools.get_z", "_autosummary/pyTEMlib.eels_tools.identify_edges", "_autosummary/pyTEMlib.eels_tools.kroeger_core", "_autosummary/pyTEMlib.eels_tools.kroeger_core2", "_autosummary/pyTEMlib.eels_tools.list_all_edges", "_autosummary/pyTEMlib.eels_tools.lorentz", "_autosummary/pyTEMlib.eels_tools.make_cross_sections", "_autosummary/pyTEMlib.eels_tools.make_edges", "_autosummary/pyTEMlib.eels_tools.model3", "_autosummary/pyTEMlib.eels_tools.model_ll", "_autosummary/pyTEMlib.eels_tools.model_smooth", "_autosummary/pyTEMlib.eels_tools.plot_dispersion", "_autosummary/pyTEMlib.eels_tools.power_law", "_autosummary/pyTEMlib.eels_tools.power_law_background", "_autosummary/pyTEMlib.eels_tools.read_msa", "_autosummary/pyTEMlib.eels_tools.residuals_ll", "_autosummary/pyTEMlib.eels_tools.residuals_ll2", "_autosummary/pyTEMlib.eels_tools.residuals_smooth", "_autosummary/pyTEMlib.eels_tools.resolution_function", "_autosummary/pyTEMlib.eels_tools.resolution_function2", "_autosummary/pyTEMlib.eels_tools.second_derivative", "_autosummary/pyTEMlib.eels_tools.set_previous_quantification", "_autosummary/pyTEMlib.eels_tools.shift_on_same_scale", "_autosummary/pyTEMlib.eels_tools.sort_peaks", "_autosummary/pyTEMlib.eels_tools.xsec_xrpa", "_autosummary/pyTEMlib.eels_tools.zl", "_autosummary/pyTEMlib.eels_tools.zl_func", "_autosummary/pyTEMlib.file_tools", "_autosummary/pyTEMlib.file_tools.ChooseDataset", "_autosummary/pyTEMlib.file_tools.FileWidget", "_autosummary/pyTEMlib.file_tools.add_dataset_from_file", "_autosummary/pyTEMlib.file_tools.add_to_dict", "_autosummary/pyTEMlib.file_tools.get_h5_filename", "_autosummary/pyTEMlib.file_tools.get_last_path", "_autosummary/pyTEMlib.file_tools.get_main_channel", "_autosummary/pyTEMlib.file_tools.get_start_channel", "_autosummary/pyTEMlib.file_tools.h5_add_crystal_structure", "_autosummary/pyTEMlib.file_tools.h5_add_to_structure", "_autosummary/pyTEMlib.file_tools.h5_get_crystal_structure", "_autosummary/pyTEMlib.file_tools.h5_group_to_dict", "_autosummary/pyTEMlib.file_tools.h5_tree", "_autosummary/pyTEMlib.file_tools.log_results", "_autosummary/pyTEMlib.file_tools.open_file", "_autosummary/pyTEMlib.file_tools.open_file_dialog_qt", "_autosummary/pyTEMlib.file_tools.read_cif", "_autosummary/pyTEMlib.file_tools.read_dm3_info", "_autosummary/pyTEMlib.file_tools.read_essential_metadata", "_autosummary/pyTEMlib.file_tools.read_nion_image_info", "_autosummary/pyTEMlib.file_tools.read_old_h5group", "_autosummary/pyTEMlib.file_tools.read_poscar", "_autosummary/pyTEMlib.file_tools.save_dataset", "_autosummary/pyTEMlib.file_tools.save_dataset_dictionary", "_autosummary/pyTEMlib.file_tools.save_file_dialog_qt", "_autosummary/pyTEMlib.file_tools.save_path", "_autosummary/pyTEMlib.file_tools.save_single_dataset", "_autosummary/pyTEMlib.file_tools.set_dimensions", "_autosummary/pyTEMlib.file_tools.update_directory_list", "_autosummary/pyTEMlib.file_tools_qt", "_autosummary/pyTEMlib.graph_tools", "_autosummary/pyTEMlib.graph_tools.breadth_first_search", "_autosummary/pyTEMlib.graph_tools.circum_center", "_autosummary/pyTEMlib.graph_tools.find_interstitial_clusters", "_autosummary/pyTEMlib.graph_tools.find_overlapping_spheres", "_autosummary/pyTEMlib.graph_tools.find_polyhedra", "_autosummary/pyTEMlib.graph_tools.get_bond_radii", "_autosummary/pyTEMlib.graph_tools.get_bonds", "_autosummary/pyTEMlib.graph_tools.get_connectivity_matrix", "_autosummary/pyTEMlib.graph_tools.get_distortion_matrix", "_autosummary/pyTEMlib.graph_tools.get_maximum_view", "_autosummary/pyTEMlib.graph_tools.get_non_periodic_supercell", "_autosummary/pyTEMlib.graph_tools.get_polygons", "_autosummary/pyTEMlib.graph_tools.get_significant_vertices", "_autosummary/pyTEMlib.graph_tools.get_voronoi", "_autosummary/pyTEMlib.graph_tools.interstitial_sphere_center", "_autosummary/pyTEMlib.graph_tools.make_polygons", "_autosummary/pyTEMlib.graph_tools.make_polyhedrons", "_autosummary/pyTEMlib.graph_tools.plot_atoms", "_autosummary/pyTEMlib.graph_tools.polygon_sort", "_autosummary/pyTEMlib.graph_tools.set_bond_radii", "_autosummary/pyTEMlib.graph_tools.sort_polyhedra_by_vertices", "_autosummary/pyTEMlib.graph_tools.transform_voronoi", "_autosummary/pyTEMlib.graph_tools.undistort", "_autosummary/pyTEMlib.graph_tools.undistort_sitk", "_autosummary/pyTEMlib.graph_tools.undistort_stack", "_autosummary/pyTEMlib.graph_tools.undistort_stack_sitk", "_autosummary/pyTEMlib.graph_tools.voronoi_volumes", "_autosummary/pyTEMlib.graph_viz", "_autosummary/pyTEMlib.graph_viz.get_boundary_polyhedra", "_autosummary/pyTEMlib.graph_viz.plot_bonds", "_autosummary/pyTEMlib.graph_viz.plot_polyhedron", "_autosummary/pyTEMlib.graph_viz.plot_super_cell", "_autosummary/pyTEMlib.graph_viz.plot_supercell", "_autosummary/pyTEMlib.graph_viz.plot_supercell_bonds", "_autosummary/pyTEMlib.graph_viz.plot_supercell_polyhedra", "_autosummary/pyTEMlib.graph_viz.plot_with_polyhedra", "_autosummary/pyTEMlib.graph_viz.show_polyhedra", "_autosummary/pyTEMlib.image_dialog", "_autosummary/pyTEMlib.image_dlg", "_autosummary/pyTEMlib.image_tools", "_autosummary/pyTEMlib.image_tools.ImageWithLineProfile", "_autosummary/pyTEMlib.image_tools.adaptive_fourier_filter", "_autosummary/pyTEMlib.image_tools.align_crystal_reflections", "_autosummary/pyTEMlib.image_tools.calculate_ctf", "_autosummary/pyTEMlib.image_tools.calculate_scherzer", "_autosummary/pyTEMlib.image_tools.calibrate_image_scale", "_autosummary/pyTEMlib.image_tools.cart2pol", "_autosummary/pyTEMlib.image_tools.cartesian2polar", "_autosummary/pyTEMlib.image_tools.clean_svd", "_autosummary/pyTEMlib.image_tools.complete_registration", "_autosummary/pyTEMlib.image_tools.crop_image_stack", "_autosummary/pyTEMlib.image_tools.decon_lr", "_autosummary/pyTEMlib.image_tools.demon_registration", "_autosummary/pyTEMlib.image_tools.diffractogram_spots", "_autosummary/pyTEMlib.image_tools.fourier_transform", "_autosummary/pyTEMlib.image_tools.get_rotation", "_autosummary/pyTEMlib.image_tools.get_wavelength", "_autosummary/pyTEMlib.image_tools.histogram_plot", "_autosummary/pyTEMlib.image_tools.pol2cart", "_autosummary/pyTEMlib.image_tools.power_spectrum", "_autosummary/pyTEMlib.image_tools.rebin", "_autosummary/pyTEMlib.image_tools.rig_reg_drift", "_autosummary/pyTEMlib.image_tools.rigid_registration", "_autosummary/pyTEMlib.image_tools.rotational_symmetry_diffractogram", "_autosummary/pyTEMlib.image_tools.warp", "_autosummary/pyTEMlib.image_tools.xy2polar", "_autosummary/pyTEMlib.info_dialog", "_autosummary/pyTEMlib.info_dialog.InfoWidget", "_autosummary/pyTEMlib.info_dialog.get_sidebar", "_autosummary/pyTEMlib.info_dlg", "_autosummary/pyTEMlib.info_widget", "_autosummary/pyTEMlib.info_widget.EELSWidget", "_autosummary/pyTEMlib.info_widget.InfoWidget", "_autosummary/pyTEMlib.info_widget.LowLossWidget", "_autosummary/pyTEMlib.info_widget.get_info_sidebar", "_autosummary/pyTEMlib.info_widget.get_low_loss_sidebar", "_autosummary/pyTEMlib.interactive_eels", "_autosummary/pyTEMlib.interactive_image", "_autosummary/pyTEMlib.kinematic_scattering", "_autosummary/pyTEMlib.kinematic_scattering.Zuo_fig_3_18", "_autosummary/pyTEMlib.kinematic_scattering.check_sanity", "_autosummary/pyTEMlib.kinematic_scattering.example", "_autosummary/pyTEMlib.kinematic_scattering.feq", "_autosummary/pyTEMlib.kinematic_scattering.find_angles", "_autosummary/pyTEMlib.kinematic_scattering.find_nearest_zone_axis", "_autosummary/pyTEMlib.kinematic_scattering.get_dynamically_allowed", "_autosummary/pyTEMlib.kinematic_scattering.get_metric_tensor", "_autosummary/pyTEMlib.kinematic_scattering.get_rotation_matrix", "_autosummary/pyTEMlib.kinematic_scattering.get_wavelength", "_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering", "_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering2", "_autosummary/pyTEMlib.kinematic_scattering.make_pretty_labels", "_autosummary/pyTEMlib.kinematic_scattering.read_poscar", "_autosummary/pyTEMlib.kinematic_scattering.ring_pattern_calculation", "_autosummary/pyTEMlib.kinematic_scattering.scattering_matrix", "_autosummary/pyTEMlib.kinematic_scattering.stage_rotation_matrix", "_autosummary/pyTEMlib.kinematic_scattering.vector_norm", "_autosummary/pyTEMlib.kinematic_scattering.zone_mistilt", "_autosummary/pyTEMlib.microscope", "_autosummary/pyTEMlib.microscope.Microscope", "_autosummary/pyTEMlib.peak_dialog", "_autosummary/pyTEMlib.peak_dialog.PeakFitWidget", "_autosummary/pyTEMlib.peak_dialog.get_sidebar", "_autosummary/pyTEMlib.peak_dialog.smooth", "_autosummary/pyTEMlib.peak_dlg", "_autosummary/pyTEMlib.probe_tools", "_autosummary/pyTEMlib.probe_tools.get_chi", "_autosummary/pyTEMlib.probe_tools.get_chi_2", "_autosummary/pyTEMlib.probe_tools.get_d2chidu2", "_autosummary/pyTEMlib.probe_tools.get_d2chidudv", "_autosummary/pyTEMlib.probe_tools.get_d2chidv2", "_autosummary/pyTEMlib.probe_tools.get_ronchigram", "_autosummary/pyTEMlib.probe_tools.get_ronchigram_2", "_autosummary/pyTEMlib.probe_tools.get_source_energy_spread", "_autosummary/pyTEMlib.probe_tools.get_target_aberrations", "_autosummary/pyTEMlib.probe_tools.make_chi", "_autosummary/pyTEMlib.probe_tools.make_chi1", "_autosummary/pyTEMlib.probe_tools.make_gauss", "_autosummary/pyTEMlib.probe_tools.make_lorentz", "_autosummary/pyTEMlib.probe_tools.print_aberrations", "_autosummary/pyTEMlib.probe_tools.probe2", "_autosummary/pyTEMlib.probe_tools.zero_loss_peak_weight", "_autosummary/pyTEMlib.sidpy_tools", "_autosummary/pyTEMlib.sidpy_tools.ChooseDataset", "_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_order", "_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_type", "_autosummary/pyTEMlib.sidpy_tools.get_extent", "_autosummary/pyTEMlib.sidpy_tools.get_image_dims", "_autosummary/pyTEMlib.sidpy_tools.make_dummy_dataset", "_autosummary/pyTEMlib.sidpy_tools.plot", "_autosummary/pyTEMlib.simulation_tools", "_autosummary/pyTEMlib.simulation_tools.exciting_get_spectra", "_autosummary/pyTEMlib.simulation_tools.final_state_broadening", "_autosummary/pyTEMlib.version", "_autosummary/pyTEMlib.viz", "_autosummary/pyTEMlib.viz.CurveVisualizer", "_autosummary/pyTEMlib.viz.SpectrumView", "_autosummary/pyTEMlib.viz.find_edge_names", "_autosummary/pyTEMlib.viz.plot", "_autosummary/pyTEMlib.viz.plot_image", "_autosummary/pyTEMlib.viz.plot_spectrum", "_autosummary/pyTEMlib.viz.plot_stack", "_autosummary/pyTEMlib.viz.spectrum_view_plotly", "_autosummary/pyTEMlib.viz.verify_spectrum_dataset", "_autosummary/pyTEMlib.xrpa_x_sections", "about", "contact", "credits", "index", "install", "notebooks/EELS/index", "notebooks/Imaging/index", "revisions"], "filenames": ["_autosummary/pyTEMlib.rst", "_autosummary/pyTEMlib.animation.rst", "_autosummary/pyTEMlib.animation.InteractiveAberration.rst", "_autosummary/pyTEMlib.animation.InteractiveRonchigramMagnification.rst", "_autosummary/pyTEMlib.animation.add_aperture.rst", "_autosummary/pyTEMlib.animation.add_lens.rst", "_autosummary/pyTEMlib.animation.deficient_holz_line.rst", "_autosummary/pyTEMlib.animation.deficient_kikuchi_line.rst", "_autosummary/pyTEMlib.animation.geometric_ray_diagram.rst", "_autosummary/pyTEMlib.animation.propagate_beam.rst", "_autosummary/pyTEMlib.atom_tools.rst", "_autosummary/pyTEMlib.atom_tools.atom_refine.rst", "_autosummary/pyTEMlib.atom_tools.atoms_clustering.rst", "_autosummary/pyTEMlib.atom_tools.find_atoms.rst", "_autosummary/pyTEMlib.atom_tools.gauss_difference.rst", "_autosummary/pyTEMlib.atom_tools.intensity_area.rst", "_autosummary/pyTEMlib.config_dir.rst", "_autosummary/pyTEMlib.crystal_tools.rst", "_autosummary/pyTEMlib.crystal_tools.atoms_from_dictionary.rst", "_autosummary/pyTEMlib.crystal_tools.ball_and_stick.rst", "_autosummary/pyTEMlib.crystal_tools.get_dictionary.rst", "_autosummary/pyTEMlib.crystal_tools.get_projection.rst", "_autosummary/pyTEMlib.crystal_tools.get_symmetry.rst", "_autosummary/pyTEMlib.crystal_tools.jmol_viewer.rst", "_autosummary/pyTEMlib.crystal_tools.plot_super_cell.rst", "_autosummary/pyTEMlib.crystal_tools.plot_unit_cell.rst", "_autosummary/pyTEMlib.crystal_tools.set_bond_radii.rst", "_autosummary/pyTEMlib.crystal_tools.structure_by_name.rst", "_autosummary/pyTEMlib.diffraction_plot.rst", "_autosummary/pyTEMlib.diffraction_plot.cartesian2polar.rst", "_autosummary/pyTEMlib.diffraction_plot.circles.rst", "_autosummary/pyTEMlib.diffraction_plot.plotCBED_parameter.rst", "_autosummary/pyTEMlib.diffraction_plot.plotHOLZ_parameter.rst", "_autosummary/pyTEMlib.diffraction_plot.plotKikuchi.rst", "_autosummary/pyTEMlib.diffraction_plot.plotSAED_parameter.rst", "_autosummary/pyTEMlib.diffraction_plot.plot_diffraction_pattern.rst", "_autosummary/pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D.rst", "_autosummary/pyTEMlib.diffraction_plot.plot_ring_pattern.rst", "_autosummary/pyTEMlib.diffraction_plot.topolar.rst", "_autosummary/pyTEMlib.diffraction_plot.warp.rst", "_autosummary/pyTEMlib.dynamic_scattering.rst", "_autosummary/pyTEMlib.dynamic_scattering.get_propagator.rst", "_autosummary/pyTEMlib.dynamic_scattering.get_transmission.rst", "_autosummary/pyTEMlib.dynamic_scattering.interaction_parameter.rst", "_autosummary/pyTEMlib.dynamic_scattering.make_chi.rst", "_autosummary/pyTEMlib.dynamic_scattering.multi_slice.rst", "_autosummary/pyTEMlib.dynamic_scattering.objective_lens_function.rst", "_autosummary/pyTEMlib.dynamic_scattering.potential_1dim.rst", "_autosummary/pyTEMlib.dynamic_scattering.potential_2dim.rst", "_autosummary/pyTEMlib.eds_tools.rst", "_autosummary/pyTEMlib.eds_tools.detect_peaks.rst", "_autosummary/pyTEMlib.eds_tools.detector_response.rst", "_autosummary/pyTEMlib.eds_tools.find_elements.rst", "_autosummary/pyTEMlib.eds_tools.fit_model.rst", "_autosummary/pyTEMlib.eds_tools.gaussian.rst", "_autosummary/pyTEMlib.eds_tools.getFWHM.rst", "_autosummary/pyTEMlib.eds_tools.get_eds_cross_sections.rst", "_autosummary/pyTEMlib.eds_tools.get_eds_xsection.rst", "_autosummary/pyTEMlib.eds_tools.get_model.rst", "_autosummary/pyTEMlib.eds_tools.get_peak.rst", "_autosummary/pyTEMlib.eds_tools.get_x_ray_lines.rst", "_autosummary/pyTEMlib.eds_tools.update_fit_values.rst", "_autosummary/pyTEMlib.eels_dialog.rst", "_autosummary/pyTEMlib.eels_dialog.CompositionWidget.rst", "_autosummary/pyTEMlib.eels_dialog.get_sidebar.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.EdgesAtCursor.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.ElementalEdges.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.PeriodicTableWidget.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.RangeSelector.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.RegionSelector.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.SIPlot.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.SpectrumPlot.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.get_likely_edges.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_info.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.get_periodic_table_widget.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.make_box_layout.rst", "_autosummary/pyTEMlib.eels_dialog_utilities.plot_EELS.rst", "_autosummary/pyTEMlib.eels_dlg.rst", "_autosummary/pyTEMlib.eels_tools.rst", "_autosummary/pyTEMlib.eels_tools.add_element_to_dataset.rst", "_autosummary/pyTEMlib.eels_tools.add_peaks.rst", "_autosummary/pyTEMlib.eels_tools.assign_likely_edges.rst", "_autosummary/pyTEMlib.eels_tools.auto_chemical_composition.rst", "_autosummary/pyTEMlib.eels_tools.auto_id_edges.rst", "_autosummary/pyTEMlib.eels_tools.cl_model.rst", "_autosummary/pyTEMlib.eels_tools.drude.rst", "_autosummary/pyTEMlib.eels_tools.drude2.rst", "_autosummary/pyTEMlib.eels_tools.drude_lorentz.rst", "_autosummary/pyTEMlib.eels_tools.drude_simulation.rst", "_autosummary/pyTEMlib.eels_tools.effective_collection_angle.rst", "_autosummary/pyTEMlib.eels_tools.find_all_edges.rst", "_autosummary/pyTEMlib.eels_tools.find_associated_edges.rst", "_autosummary/pyTEMlib.eels_tools.find_edges.rst", "_autosummary/pyTEMlib.eels_tools.find_major_edges.rst", "_autosummary/pyTEMlib.eels_tools.find_maxima.rst", "_autosummary/pyTEMlib.eels_tools.find_peaks.rst", "_autosummary/pyTEMlib.eels_tools.find_white_lines.rst", "_autosummary/pyTEMlib.eels_tools.fit_dataset.rst", "_autosummary/pyTEMlib.eels_tools.fit_edges.rst", "_autosummary/pyTEMlib.eels_tools.fit_edges2.rst", "_autosummary/pyTEMlib.eels_tools.fit_model.rst", "_autosummary/pyTEMlib.eels_tools.fit_peaks.rst", "_autosummary/pyTEMlib.eels_tools.fix_energy_scale.rst", "_autosummary/pyTEMlib.eels_tools.gauss.rst", "_autosummary/pyTEMlib.eels_tools.get_energy_shifts.rst", "_autosummary/pyTEMlib.eels_tools.get_resolution_functions.rst", "_autosummary/pyTEMlib.eels_tools.get_spectrum_eels_db.rst", "_autosummary/pyTEMlib.eels_tools.get_wave_length.rst", "_autosummary/pyTEMlib.eels_tools.get_x_sections.rst", "_autosummary/pyTEMlib.eels_tools.get_z.rst", "_autosummary/pyTEMlib.eels_tools.identify_edges.rst", "_autosummary/pyTEMlib.eels_tools.kroeger_core.rst", "_autosummary/pyTEMlib.eels_tools.kroeger_core2.rst", "_autosummary/pyTEMlib.eels_tools.list_all_edges.rst", "_autosummary/pyTEMlib.eels_tools.lorentz.rst", "_autosummary/pyTEMlib.eels_tools.make_cross_sections.rst", "_autosummary/pyTEMlib.eels_tools.make_edges.rst", "_autosummary/pyTEMlib.eels_tools.model3.rst", "_autosummary/pyTEMlib.eels_tools.model_ll.rst", "_autosummary/pyTEMlib.eels_tools.model_smooth.rst", "_autosummary/pyTEMlib.eels_tools.plot_dispersion.rst", "_autosummary/pyTEMlib.eels_tools.power_law.rst", "_autosummary/pyTEMlib.eels_tools.power_law_background.rst", "_autosummary/pyTEMlib.eels_tools.read_msa.rst", "_autosummary/pyTEMlib.eels_tools.residuals_ll.rst", "_autosummary/pyTEMlib.eels_tools.residuals_ll2.rst", "_autosummary/pyTEMlib.eels_tools.residuals_smooth.rst", "_autosummary/pyTEMlib.eels_tools.resolution_function.rst", "_autosummary/pyTEMlib.eels_tools.resolution_function2.rst", "_autosummary/pyTEMlib.eels_tools.second_derivative.rst", "_autosummary/pyTEMlib.eels_tools.set_previous_quantification.rst", "_autosummary/pyTEMlib.eels_tools.shift_on_same_scale.rst", "_autosummary/pyTEMlib.eels_tools.sort_peaks.rst", "_autosummary/pyTEMlib.eels_tools.xsec_xrpa.rst", "_autosummary/pyTEMlib.eels_tools.zl.rst", "_autosummary/pyTEMlib.eels_tools.zl_func.rst", "_autosummary/pyTEMlib.file_tools.rst", "_autosummary/pyTEMlib.file_tools.ChooseDataset.rst", "_autosummary/pyTEMlib.file_tools.FileWidget.rst", "_autosummary/pyTEMlib.file_tools.add_dataset_from_file.rst", "_autosummary/pyTEMlib.file_tools.add_to_dict.rst", "_autosummary/pyTEMlib.file_tools.get_h5_filename.rst", "_autosummary/pyTEMlib.file_tools.get_last_path.rst", "_autosummary/pyTEMlib.file_tools.get_main_channel.rst", "_autosummary/pyTEMlib.file_tools.get_start_channel.rst", "_autosummary/pyTEMlib.file_tools.h5_add_crystal_structure.rst", "_autosummary/pyTEMlib.file_tools.h5_add_to_structure.rst", "_autosummary/pyTEMlib.file_tools.h5_get_crystal_structure.rst", "_autosummary/pyTEMlib.file_tools.h5_group_to_dict.rst", "_autosummary/pyTEMlib.file_tools.h5_tree.rst", "_autosummary/pyTEMlib.file_tools.log_results.rst", "_autosummary/pyTEMlib.file_tools.open_file.rst", "_autosummary/pyTEMlib.file_tools.open_file_dialog_qt.rst", "_autosummary/pyTEMlib.file_tools.read_cif.rst", "_autosummary/pyTEMlib.file_tools.read_dm3_info.rst", "_autosummary/pyTEMlib.file_tools.read_essential_metadata.rst", "_autosummary/pyTEMlib.file_tools.read_nion_image_info.rst", "_autosummary/pyTEMlib.file_tools.read_old_h5group.rst", "_autosummary/pyTEMlib.file_tools.read_poscar.rst", "_autosummary/pyTEMlib.file_tools.save_dataset.rst", "_autosummary/pyTEMlib.file_tools.save_dataset_dictionary.rst", "_autosummary/pyTEMlib.file_tools.save_file_dialog_qt.rst", "_autosummary/pyTEMlib.file_tools.save_path.rst", "_autosummary/pyTEMlib.file_tools.save_single_dataset.rst", "_autosummary/pyTEMlib.file_tools.set_dimensions.rst", "_autosummary/pyTEMlib.file_tools.update_directory_list.rst", "_autosummary/pyTEMlib.file_tools_qt.rst", "_autosummary/pyTEMlib.graph_tools.rst", "_autosummary/pyTEMlib.graph_tools.breadth_first_search.rst", "_autosummary/pyTEMlib.graph_tools.circum_center.rst", "_autosummary/pyTEMlib.graph_tools.find_interstitial_clusters.rst", "_autosummary/pyTEMlib.graph_tools.find_overlapping_spheres.rst", "_autosummary/pyTEMlib.graph_tools.find_polyhedra.rst", "_autosummary/pyTEMlib.graph_tools.get_bond_radii.rst", "_autosummary/pyTEMlib.graph_tools.get_bonds.rst", "_autosummary/pyTEMlib.graph_tools.get_connectivity_matrix.rst", "_autosummary/pyTEMlib.graph_tools.get_distortion_matrix.rst", "_autosummary/pyTEMlib.graph_tools.get_maximum_view.rst", "_autosummary/pyTEMlib.graph_tools.get_non_periodic_supercell.rst", "_autosummary/pyTEMlib.graph_tools.get_polygons.rst", "_autosummary/pyTEMlib.graph_tools.get_significant_vertices.rst", "_autosummary/pyTEMlib.graph_tools.get_voronoi.rst", "_autosummary/pyTEMlib.graph_tools.interstitial_sphere_center.rst", "_autosummary/pyTEMlib.graph_tools.make_polygons.rst", "_autosummary/pyTEMlib.graph_tools.make_polyhedrons.rst", "_autosummary/pyTEMlib.graph_tools.plot_atoms.rst", "_autosummary/pyTEMlib.graph_tools.polygon_sort.rst", "_autosummary/pyTEMlib.graph_tools.set_bond_radii.rst", "_autosummary/pyTEMlib.graph_tools.sort_polyhedra_by_vertices.rst", "_autosummary/pyTEMlib.graph_tools.transform_voronoi.rst", "_autosummary/pyTEMlib.graph_tools.undistort.rst", "_autosummary/pyTEMlib.graph_tools.undistort_sitk.rst", "_autosummary/pyTEMlib.graph_tools.undistort_stack.rst", "_autosummary/pyTEMlib.graph_tools.undistort_stack_sitk.rst", "_autosummary/pyTEMlib.graph_tools.voronoi_volumes.rst", "_autosummary/pyTEMlib.graph_viz.rst", "_autosummary/pyTEMlib.graph_viz.get_boundary_polyhedra.rst", "_autosummary/pyTEMlib.graph_viz.plot_bonds.rst", "_autosummary/pyTEMlib.graph_viz.plot_polyhedron.rst", "_autosummary/pyTEMlib.graph_viz.plot_super_cell.rst", "_autosummary/pyTEMlib.graph_viz.plot_supercell.rst", "_autosummary/pyTEMlib.graph_viz.plot_supercell_bonds.rst", "_autosummary/pyTEMlib.graph_viz.plot_supercell_polyhedra.rst", "_autosummary/pyTEMlib.graph_viz.plot_with_polyhedra.rst", "_autosummary/pyTEMlib.graph_viz.show_polyhedra.rst", "_autosummary/pyTEMlib.image_dialog.rst", "_autosummary/pyTEMlib.image_dlg.rst", "_autosummary/pyTEMlib.image_tools.rst", "_autosummary/pyTEMlib.image_tools.ImageWithLineProfile.rst", "_autosummary/pyTEMlib.image_tools.adaptive_fourier_filter.rst", "_autosummary/pyTEMlib.image_tools.align_crystal_reflections.rst", "_autosummary/pyTEMlib.image_tools.calculate_ctf.rst", "_autosummary/pyTEMlib.image_tools.calculate_scherzer.rst", "_autosummary/pyTEMlib.image_tools.calibrate_image_scale.rst", "_autosummary/pyTEMlib.image_tools.cart2pol.rst", "_autosummary/pyTEMlib.image_tools.cartesian2polar.rst", "_autosummary/pyTEMlib.image_tools.clean_svd.rst", "_autosummary/pyTEMlib.image_tools.complete_registration.rst", "_autosummary/pyTEMlib.image_tools.crop_image_stack.rst", "_autosummary/pyTEMlib.image_tools.decon_lr.rst", "_autosummary/pyTEMlib.image_tools.demon_registration.rst", "_autosummary/pyTEMlib.image_tools.diffractogram_spots.rst", "_autosummary/pyTEMlib.image_tools.fourier_transform.rst", "_autosummary/pyTEMlib.image_tools.get_rotation.rst", "_autosummary/pyTEMlib.image_tools.get_wavelength.rst", "_autosummary/pyTEMlib.image_tools.histogram_plot.rst", "_autosummary/pyTEMlib.image_tools.pol2cart.rst", "_autosummary/pyTEMlib.image_tools.power_spectrum.rst", "_autosummary/pyTEMlib.image_tools.rebin.rst", "_autosummary/pyTEMlib.image_tools.rig_reg_drift.rst", "_autosummary/pyTEMlib.image_tools.rigid_registration.rst", "_autosummary/pyTEMlib.image_tools.rotational_symmetry_diffractogram.rst", "_autosummary/pyTEMlib.image_tools.warp.rst", "_autosummary/pyTEMlib.image_tools.xy2polar.rst", "_autosummary/pyTEMlib.info_dialog.rst", "_autosummary/pyTEMlib.info_dialog.InfoWidget.rst", "_autosummary/pyTEMlib.info_dialog.get_sidebar.rst", "_autosummary/pyTEMlib.info_dlg.rst", "_autosummary/pyTEMlib.info_widget.rst", "_autosummary/pyTEMlib.info_widget.EELSWidget.rst", "_autosummary/pyTEMlib.info_widget.InfoWidget.rst", "_autosummary/pyTEMlib.info_widget.LowLossWidget.rst", "_autosummary/pyTEMlib.info_widget.get_info_sidebar.rst", "_autosummary/pyTEMlib.info_widget.get_low_loss_sidebar.rst", "_autosummary/pyTEMlib.interactive_eels.rst", "_autosummary/pyTEMlib.interactive_image.rst", "_autosummary/pyTEMlib.kinematic_scattering.rst", "_autosummary/pyTEMlib.kinematic_scattering.Zuo_fig_3_18.rst", "_autosummary/pyTEMlib.kinematic_scattering.check_sanity.rst", "_autosummary/pyTEMlib.kinematic_scattering.example.rst", "_autosummary/pyTEMlib.kinematic_scattering.feq.rst", "_autosummary/pyTEMlib.kinematic_scattering.find_angles.rst", "_autosummary/pyTEMlib.kinematic_scattering.find_nearest_zone_axis.rst", "_autosummary/pyTEMlib.kinematic_scattering.get_dynamically_allowed.rst", "_autosummary/pyTEMlib.kinematic_scattering.get_metric_tensor.rst", "_autosummary/pyTEMlib.kinematic_scattering.get_rotation_matrix.rst", "_autosummary/pyTEMlib.kinematic_scattering.get_wavelength.rst", "_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering.rst", "_autosummary/pyTEMlib.kinematic_scattering.kinematic_scattering2.rst", "_autosummary/pyTEMlib.kinematic_scattering.make_pretty_labels.rst", "_autosummary/pyTEMlib.kinematic_scattering.read_poscar.rst", "_autosummary/pyTEMlib.kinematic_scattering.ring_pattern_calculation.rst", "_autosummary/pyTEMlib.kinematic_scattering.scattering_matrix.rst", "_autosummary/pyTEMlib.kinematic_scattering.stage_rotation_matrix.rst", "_autosummary/pyTEMlib.kinematic_scattering.vector_norm.rst", "_autosummary/pyTEMlib.kinematic_scattering.zone_mistilt.rst", "_autosummary/pyTEMlib.microscope.rst", "_autosummary/pyTEMlib.microscope.Microscope.rst", "_autosummary/pyTEMlib.peak_dialog.rst", "_autosummary/pyTEMlib.peak_dialog.PeakFitWidget.rst", "_autosummary/pyTEMlib.peak_dialog.get_sidebar.rst", "_autosummary/pyTEMlib.peak_dialog.smooth.rst", "_autosummary/pyTEMlib.peak_dlg.rst", "_autosummary/pyTEMlib.probe_tools.rst", "_autosummary/pyTEMlib.probe_tools.get_chi.rst", "_autosummary/pyTEMlib.probe_tools.get_chi_2.rst", "_autosummary/pyTEMlib.probe_tools.get_d2chidu2.rst", "_autosummary/pyTEMlib.probe_tools.get_d2chidudv.rst", "_autosummary/pyTEMlib.probe_tools.get_d2chidv2.rst", "_autosummary/pyTEMlib.probe_tools.get_ronchigram.rst", "_autosummary/pyTEMlib.probe_tools.get_ronchigram_2.rst", "_autosummary/pyTEMlib.probe_tools.get_source_energy_spread.rst", "_autosummary/pyTEMlib.probe_tools.get_target_aberrations.rst", "_autosummary/pyTEMlib.probe_tools.make_chi.rst", "_autosummary/pyTEMlib.probe_tools.make_chi1.rst", "_autosummary/pyTEMlib.probe_tools.make_gauss.rst", "_autosummary/pyTEMlib.probe_tools.make_lorentz.rst", "_autosummary/pyTEMlib.probe_tools.print_aberrations.rst", "_autosummary/pyTEMlib.probe_tools.probe2.rst", "_autosummary/pyTEMlib.probe_tools.zero_loss_peak_weight.rst", "_autosummary/pyTEMlib.sidpy_tools.rst", "_autosummary/pyTEMlib.sidpy_tools.ChooseDataset.rst", "_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_order.rst", "_autosummary/pyTEMlib.sidpy_tools.get_dimensions_by_type.rst", "_autosummary/pyTEMlib.sidpy_tools.get_extent.rst", "_autosummary/pyTEMlib.sidpy_tools.get_image_dims.rst", "_autosummary/pyTEMlib.sidpy_tools.make_dummy_dataset.rst", "_autosummary/pyTEMlib.sidpy_tools.plot.rst", "_autosummary/pyTEMlib.simulation_tools.rst", "_autosummary/pyTEMlib.simulation_tools.exciting_get_spectra.rst", "_autosummary/pyTEMlib.simulation_tools.final_state_broadening.rst", "_autosummary/pyTEMlib.version.rst", "_autosummary/pyTEMlib.viz.rst", "_autosummary/pyTEMlib.viz.CurveVisualizer.rst", "_autosummary/pyTEMlib.viz.SpectrumView.rst", "_autosummary/pyTEMlib.viz.find_edge_names.rst", "_autosummary/pyTEMlib.viz.plot.rst", "_autosummary/pyTEMlib.viz.plot_image.rst", "_autosummary/pyTEMlib.viz.plot_spectrum.rst", "_autosummary/pyTEMlib.viz.plot_stack.rst", "_autosummary/pyTEMlib.viz.spectrum_view_plotly.rst", "_autosummary/pyTEMlib.viz.verify_spectrum_dataset.rst", "_autosummary/pyTEMlib.xrpa_x_sections.rst", "about.rst", "contact.rst", "credits.rst", "index.rst", "install.rst", "notebooks/EELS/index.rst", "notebooks/Imaging/index.rst", "revisions.rst"], "titles": ["pyTEMlib", "pyTEMlib.animation", "pyTEMlib.animation.InteractiveAberration", "pyTEMlib.animation.InteractiveRonchigramMagnification", "pyTEMlib.animation.add_aperture", "pyTEMlib.animation.add_lens", "pyTEMlib.animation.deficient_holz_line", "pyTEMlib.animation.deficient_kikuchi_line", "pyTEMlib.animation.geometric_ray_diagram", "pyTEMlib.animation.propagate_beam", "pyTEMlib.atom_tools", "pyTEMlib.atom_tools.atom_refine", "pyTEMlib.atom_tools.atoms_clustering", "pyTEMlib.atom_tools.find_atoms", "pyTEMlib.atom_tools.gauss_difference", "pyTEMlib.atom_tools.intensity_area", "pyTEMlib.config_dir", "pyTEMlib.crystal_tools", "pyTEMlib.crystal_tools.atoms_from_dictionary", "pyTEMlib.crystal_tools.ball_and_stick", "pyTEMlib.crystal_tools.get_dictionary", "pyTEMlib.crystal_tools.get_projection", "pyTEMlib.crystal_tools.get_symmetry", "pyTEMlib.crystal_tools.jmol_viewer", "pyTEMlib.crystal_tools.plot_super_cell", "pyTEMlib.crystal_tools.plot_unit_cell", "pyTEMlib.crystal_tools.set_bond_radii", "pyTEMlib.crystal_tools.structure_by_name", "pyTEMlib.diffraction_plot", "pyTEMlib.diffraction_plot.cartesian2polar", "pyTEMlib.diffraction_plot.circles", "pyTEMlib.diffraction_plot.plotCBED_parameter", "pyTEMlib.diffraction_plot.plotHOLZ_parameter", "pyTEMlib.diffraction_plot.plotKikuchi", "pyTEMlib.diffraction_plot.plotSAED_parameter", "pyTEMlib.diffraction_plot.plot_diffraction_pattern", "pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D", "pyTEMlib.diffraction_plot.plot_ring_pattern", "pyTEMlib.diffraction_plot.topolar", "pyTEMlib.diffraction_plot.warp", "pyTEMlib.dynamic_scattering", "pyTEMlib.dynamic_scattering.get_propagator", "pyTEMlib.dynamic_scattering.get_transmission", "pyTEMlib.dynamic_scattering.interaction_parameter", "pyTEMlib.dynamic_scattering.make_chi", "pyTEMlib.dynamic_scattering.multi_slice", "pyTEMlib.dynamic_scattering.objective_lens_function", "pyTEMlib.dynamic_scattering.potential_1dim", "pyTEMlib.dynamic_scattering.potential_2dim", "pyTEMlib.eds_tools", "pyTEMlib.eds_tools.detect_peaks", "pyTEMlib.eds_tools.detector_response", "pyTEMlib.eds_tools.find_elements", "pyTEMlib.eds_tools.fit_model", "pyTEMlib.eds_tools.gaussian", "pyTEMlib.eds_tools.getFWHM", "pyTEMlib.eds_tools.get_eds_cross_sections", "pyTEMlib.eds_tools.get_eds_xsection", "pyTEMlib.eds_tools.get_model", "pyTEMlib.eds_tools.get_peak", "pyTEMlib.eds_tools.get_x_ray_lines", "pyTEMlib.eds_tools.update_fit_values", "pyTEMlib.eels_dialog", "pyTEMlib.eels_dialog.CompositionWidget", "pyTEMlib.eels_dialog.get_sidebar", "pyTEMlib.eels_dialog_utilities", "pyTEMlib.eels_dialog_utilities.EdgesAtCursor", "pyTEMlib.eels_dialog_utilities.ElementalEdges", "pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage", "pyTEMlib.eels_dialog_utilities.PeriodicTableWidget", "pyTEMlib.eels_dialog_utilities.RangeSelector", "pyTEMlib.eels_dialog_utilities.RegionSelector", "pyTEMlib.eels_dialog_utilities.SIPlot", "pyTEMlib.eels_dialog_utilities.SpectrumPlot", "pyTEMlib.eels_dialog_utilities.get_likely_edges", "pyTEMlib.eels_dialog_utilities.get_periodic_table_info", "pyTEMlib.eels_dialog_utilities.get_periodic_table_widget", "pyTEMlib.eels_dialog_utilities.make_box_layout", "pyTEMlib.eels_dialog_utilities.plot_EELS", "pyTEMlib.eels_dlg", "pyTEMlib.eels_tools", "pyTEMlib.eels_tools.add_element_to_dataset", "pyTEMlib.eels_tools.add_peaks", "pyTEMlib.eels_tools.assign_likely_edges", "pyTEMlib.eels_tools.auto_chemical_composition", "pyTEMlib.eels_tools.auto_id_edges", "pyTEMlib.eels_tools.cl_model", "pyTEMlib.eels_tools.drude", "pyTEMlib.eels_tools.drude2", "pyTEMlib.eels_tools.drude_lorentz", "pyTEMlib.eels_tools.drude_simulation", "pyTEMlib.eels_tools.effective_collection_angle", "pyTEMlib.eels_tools.find_all_edges", "pyTEMlib.eels_tools.find_associated_edges", "pyTEMlib.eels_tools.find_edges", "pyTEMlib.eels_tools.find_major_edges", "pyTEMlib.eels_tools.find_maxima", "pyTEMlib.eels_tools.find_peaks", "pyTEMlib.eels_tools.find_white_lines", "pyTEMlib.eels_tools.fit_dataset", "pyTEMlib.eels_tools.fit_edges", "pyTEMlib.eels_tools.fit_edges2", "pyTEMlib.eels_tools.fit_model", "pyTEMlib.eels_tools.fit_peaks", "pyTEMlib.eels_tools.fix_energy_scale", "pyTEMlib.eels_tools.gauss", "pyTEMlib.eels_tools.get_energy_shifts", "pyTEMlib.eels_tools.get_resolution_functions", "pyTEMlib.eels_tools.get_spectrum_eels_db", "pyTEMlib.eels_tools.get_wave_length", "pyTEMlib.eels_tools.get_x_sections", "pyTEMlib.eels_tools.get_z", "pyTEMlib.eels_tools.identify_edges", "pyTEMlib.eels_tools.kroeger_core", "pyTEMlib.eels_tools.kroeger_core2", "pyTEMlib.eels_tools.list_all_edges", "pyTEMlib.eels_tools.lorentz", "pyTEMlib.eels_tools.make_cross_sections", "pyTEMlib.eels_tools.make_edges", "pyTEMlib.eels_tools.model3", "pyTEMlib.eels_tools.model_ll", "pyTEMlib.eels_tools.model_smooth", "pyTEMlib.eels_tools.plot_dispersion", "pyTEMlib.eels_tools.power_law", "pyTEMlib.eels_tools.power_law_background", "pyTEMlib.eels_tools.read_msa", "pyTEMlib.eels_tools.residuals_ll", "pyTEMlib.eels_tools.residuals_ll2", "pyTEMlib.eels_tools.residuals_smooth", "pyTEMlib.eels_tools.resolution_function", "pyTEMlib.eels_tools.resolution_function2", "pyTEMlib.eels_tools.second_derivative", "pyTEMlib.eels_tools.set_previous_quantification", "pyTEMlib.eels_tools.shift_on_same_scale", "pyTEMlib.eels_tools.sort_peaks", "pyTEMlib.eels_tools.xsec_xrpa", "pyTEMlib.eels_tools.zl", "pyTEMlib.eels_tools.zl_func", "pyTEMlib.file_tools", "pyTEMlib.file_tools.ChooseDataset", "pyTEMlib.file_tools.FileWidget", "pyTEMlib.file_tools.add_dataset_from_file", "pyTEMlib.file_tools.add_to_dict", "pyTEMlib.file_tools.get_h5_filename", "pyTEMlib.file_tools.get_last_path", "pyTEMlib.file_tools.get_main_channel", "pyTEMlib.file_tools.get_start_channel", "pyTEMlib.file_tools.h5_add_crystal_structure", "pyTEMlib.file_tools.h5_add_to_structure", "pyTEMlib.file_tools.h5_get_crystal_structure", "pyTEMlib.file_tools.h5_group_to_dict", "pyTEMlib.file_tools.h5_tree", "pyTEMlib.file_tools.log_results", "pyTEMlib.file_tools.open_file", "pyTEMlib.file_tools.open_file_dialog_qt", "pyTEMlib.file_tools.read_cif", "pyTEMlib.file_tools.read_dm3_info", "pyTEMlib.file_tools.read_essential_metadata", "pyTEMlib.file_tools.read_nion_image_info", "pyTEMlib.file_tools.read_old_h5group", "pyTEMlib.file_tools.read_poscar", "pyTEMlib.file_tools.save_dataset", "pyTEMlib.file_tools.save_dataset_dictionary", "pyTEMlib.file_tools.save_file_dialog_qt", "pyTEMlib.file_tools.save_path", "pyTEMlib.file_tools.save_single_dataset", "pyTEMlib.file_tools.set_dimensions", "pyTEMlib.file_tools.update_directory_list", "pyTEMlib.file_tools_qt", "pyTEMlib.graph_tools", "pyTEMlib.graph_tools.breadth_first_search", "pyTEMlib.graph_tools.circum_center", "pyTEMlib.graph_tools.find_interstitial_clusters", "pyTEMlib.graph_tools.find_overlapping_spheres", "pyTEMlib.graph_tools.find_polyhedra", "pyTEMlib.graph_tools.get_bond_radii", "pyTEMlib.graph_tools.get_bonds", "pyTEMlib.graph_tools.get_connectivity_matrix", "pyTEMlib.graph_tools.get_distortion_matrix", "pyTEMlib.graph_tools.get_maximum_view", "pyTEMlib.graph_tools.get_non_periodic_supercell", "pyTEMlib.graph_tools.get_polygons", "pyTEMlib.graph_tools.get_significant_vertices", "pyTEMlib.graph_tools.get_voronoi", "pyTEMlib.graph_tools.interstitial_sphere_center", "pyTEMlib.graph_tools.make_polygons", "pyTEMlib.graph_tools.make_polyhedrons", "pyTEMlib.graph_tools.plot_atoms", "pyTEMlib.graph_tools.polygon_sort", "pyTEMlib.graph_tools.set_bond_radii", "pyTEMlib.graph_tools.sort_polyhedra_by_vertices", "pyTEMlib.graph_tools.transform_voronoi", "pyTEMlib.graph_tools.undistort", "pyTEMlib.graph_tools.undistort_sitk", "pyTEMlib.graph_tools.undistort_stack", "pyTEMlib.graph_tools.undistort_stack_sitk", "pyTEMlib.graph_tools.voronoi_volumes", "pyTEMlib.graph_viz", "pyTEMlib.graph_viz.get_boundary_polyhedra", "pyTEMlib.graph_viz.plot_bonds", "pyTEMlib.graph_viz.plot_polyhedron", "pyTEMlib.graph_viz.plot_super_cell", "pyTEMlib.graph_viz.plot_supercell", "pyTEMlib.graph_viz.plot_supercell_bonds", "pyTEMlib.graph_viz.plot_supercell_polyhedra", "pyTEMlib.graph_viz.plot_with_polyhedra", "pyTEMlib.graph_viz.show_polyhedra", "pyTEMlib.image_dialog", "pyTEMlib.image_dlg", "pyTEMlib.image_tools", "pyTEMlib.image_tools.ImageWithLineProfile", "pyTEMlib.image_tools.adaptive_fourier_filter", "pyTEMlib.image_tools.align_crystal_reflections", "pyTEMlib.image_tools.calculate_ctf", "pyTEMlib.image_tools.calculate_scherzer", "pyTEMlib.image_tools.calibrate_image_scale", "pyTEMlib.image_tools.cart2pol", "pyTEMlib.image_tools.cartesian2polar", "pyTEMlib.image_tools.clean_svd", "pyTEMlib.image_tools.complete_registration", "pyTEMlib.image_tools.crop_image_stack", "pyTEMlib.image_tools.decon_lr", "pyTEMlib.image_tools.demon_registration", "pyTEMlib.image_tools.diffractogram_spots", "pyTEMlib.image_tools.fourier_transform", "pyTEMlib.image_tools.get_rotation", "pyTEMlib.image_tools.get_wavelength", "pyTEMlib.image_tools.histogram_plot", "pyTEMlib.image_tools.pol2cart", "pyTEMlib.image_tools.power_spectrum", "pyTEMlib.image_tools.rebin", "pyTEMlib.image_tools.rig_reg_drift", "pyTEMlib.image_tools.rigid_registration", "pyTEMlib.image_tools.rotational_symmetry_diffractogram", "pyTEMlib.image_tools.warp", "pyTEMlib.image_tools.xy2polar", "pyTEMlib.info_dialog", "pyTEMlib.info_dialog.InfoWidget", "pyTEMlib.info_dialog.get_sidebar", "pyTEMlib.info_dlg", "pyTEMlib.info_widget", "pyTEMlib.info_widget.EELSWidget", "pyTEMlib.info_widget.InfoWidget", "pyTEMlib.info_widget.LowLossWidget", "pyTEMlib.info_widget.get_info_sidebar", "pyTEMlib.info_widget.get_low_loss_sidebar", "pyTEMlib.interactive_eels", "pyTEMlib.interactive_image", "pyTEMlib.kinematic_scattering", "pyTEMlib.kinematic_scattering.Zuo_fig_3_18", "pyTEMlib.kinematic_scattering.check_sanity", "pyTEMlib.kinematic_scattering.example", "pyTEMlib.kinematic_scattering.feq", "pyTEMlib.kinematic_scattering.find_angles", "pyTEMlib.kinematic_scattering.find_nearest_zone_axis", "pyTEMlib.kinematic_scattering.get_dynamically_allowed", "pyTEMlib.kinematic_scattering.get_metric_tensor", "pyTEMlib.kinematic_scattering.get_rotation_matrix", "pyTEMlib.kinematic_scattering.get_wavelength", "pyTEMlib.kinematic_scattering.kinematic_scattering", "pyTEMlib.kinematic_scattering.kinematic_scattering2", "pyTEMlib.kinematic_scattering.make_pretty_labels", "pyTEMlib.kinematic_scattering.read_poscar", "pyTEMlib.kinematic_scattering.ring_pattern_calculation", "pyTEMlib.kinematic_scattering.scattering_matrix", "pyTEMlib.kinematic_scattering.stage_rotation_matrix", "pyTEMlib.kinematic_scattering.vector_norm", "pyTEMlib.kinematic_scattering.zone_mistilt", "pyTEMlib.microscope", "pyTEMlib.microscope.Microscope", "pyTEMlib.peak_dialog", "pyTEMlib.peak_dialog.PeakFitWidget", "pyTEMlib.peak_dialog.get_sidebar", "pyTEMlib.peak_dialog.smooth", "pyTEMlib.peak_dlg", "pyTEMlib.probe_tools", "pyTEMlib.probe_tools.get_chi", "pyTEMlib.probe_tools.get_chi_2", "pyTEMlib.probe_tools.get_d2chidu2", "pyTEMlib.probe_tools.get_d2chidudv", "pyTEMlib.probe_tools.get_d2chidv2", "pyTEMlib.probe_tools.get_ronchigram", "pyTEMlib.probe_tools.get_ronchigram_2", "pyTEMlib.probe_tools.get_source_energy_spread", "pyTEMlib.probe_tools.get_target_aberrations", "pyTEMlib.probe_tools.make_chi", "pyTEMlib.probe_tools.make_chi1", "pyTEMlib.probe_tools.make_gauss", "pyTEMlib.probe_tools.make_lorentz", "pyTEMlib.probe_tools.print_aberrations", "pyTEMlib.probe_tools.probe2", "pyTEMlib.probe_tools.zero_loss_peak_weight", "pyTEMlib.sidpy_tools", "pyTEMlib.sidpy_tools.ChooseDataset", "pyTEMlib.sidpy_tools.get_dimensions_by_order", "pyTEMlib.sidpy_tools.get_dimensions_by_type", "pyTEMlib.sidpy_tools.get_extent", "pyTEMlib.sidpy_tools.get_image_dims", "pyTEMlib.sidpy_tools.make_dummy_dataset", "pyTEMlib.sidpy_tools.plot", "pyTEMlib.simulation_tools", "pyTEMlib.simulation_tools.exciting_get_spectra", "pyTEMlib.simulation_tools.final_state_broadening", "pyTEMlib.version", "pyTEMlib.viz", "pyTEMlib.viz.CurveVisualizer", "pyTEMlib.viz.SpectrumView", "pyTEMlib.viz.find_edge_names", "pyTEMlib.viz.plot", "pyTEMlib.viz.plot_image", "pyTEMlib.viz.plot_spectrum", "pyTEMlib.viz.plot_stack", "pyTEMlib.viz.spectrum_view_plotly", "pyTEMlib.viz.verify_spectrum_dataset", "pyTEMlib.xrpa_x_sections", "pyTEMlib", "Contact us", "Credits", "pyTEMlib Documentation", "Installation", "EELS_tools", "Image_tools", "Revisions"], "terms": {"creat": [0, 70, 78, 290, 300], "sat": 0, "jan": 0, "19": 0, "10": [0, 46, 90, 174, 221, 300], "07": 0, "35": [0, 187], "2019": 0, "author": [0, 1, 10, 17, 40, 62, 65, 91, 197, 207, 208, 236, 239, 246], "gduscher": [0, 317], "figur": [1, 8, 35, 37, 70, 72, 73, 187, 202, 203, 204, 205, 206, 249, 306, 309, 311, 312], "tem": [1, 248, 249, 315, 318], "jupyt": [1, 23, 78, 154, 163, 315], "notebook": [1, 17, 49, 66, 67, 71, 80, 151, 154, 163, 248, 315], "part": [1, 10, 14, 17, 90, 96, 120, 121, 126, 127, 128, 197, 209, 300, 320, 321], "mse": 1, "672": 1, "cours": 1, "utk": [1, 209], "gerd": [1, 10, 17, 40, 49, 62, 65, 80, 197, 207, 208, 209, 236, 239, 246, 248, 268, 300, 314, 317, 320, 321], "duscher": [1, 10, 17, 40, 49, 62, 65, 80, 197, 207, 208, 209, 236, 239, 246, 248, 268, 300, 314, 317, 320, 321], "revis": [1, 138, 318], "01": [1, 138, 197, 314], "11": [1, 30, 90, 171, 290], "2021": [1, 268], "03": [1, 318], "17": 1, "ad": [1, 141, 263, 315, 322], "aberr": [1, 2, 44, 46, 213, 276, 285, 286, 290], "function": [1, 10, 14, 17, 28, 40, 41, 42, 44, 45, 46, 49, 62, 65, 67, 68, 69, 70, 78, 80, 87, 88, 89, 90, 91, 104, 105, 113, 114, 116, 122, 129, 136, 137, 138, 151, 154, 163, 169, 171, 183, 184, 209, 210, 213, 219, 220, 221, 231, 236, 240, 248, 270, 275, 276, 286, 290, 292, 300, 304, 314, 315, 322], "class": [1, 2, 3, 62, 63, 65, 66, 67, 68, 69, 70, 71, 72, 73, 78, 138, 139, 140, 209, 210, 236, 237, 240, 241, 242, 243, 268, 269, 270, 271, 292, 293, 304, 305, 306], "horizont": [2, 3, 68, 72], "true": [2, 3, 22, 23, 35, 37, 41, 68, 72, 78, 103, 113, 114, 139, 141, 153, 174, 183, 184, 198, 223, 249, 251, 259, 260, 261, 293], "sourc": [2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 63, 64, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 198, 199, 200, 201, 202, 203, 204, 205, 206, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 237, 238, 241, 242, 243, 244, 245, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 269, 271, 272, 273, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 293, 294, 295, 296, 297, 298, 299, 301, 302, 305, 306, 307, 308, 309, 310, 311, 312, 313, 315], "base": [2, 3, 48, 49, 63, 66, 67, 68, 69, 70, 71, 72, 73, 78, 80, 90, 139, 140, 152, 210, 237, 241, 242, 243, 269, 271, 293, 305, 306, 315, 318, 319], "object": [2, 3, 19, 20, 22, 23, 35, 39, 46, 63, 66, 67, 68, 69, 71, 78, 139, 140, 149, 174, 175, 176, 183, 187, 189, 210, 237, 241, 248, 259, 260, 269, 271, 293, 305, 306], "interact": [2, 3, 43, 65, 68, 70, 227, 246, 319, 322], "explan": [2, 3], "method": [2, 3, 63, 66, 67, 68, 69, 70, 71, 72, 73, 78, 139, 140, 174, 210, 221, 237, 241, 242, 243, 269, 271, 293, 305, 306, 315], "magnif": [3, 8], "z": [4, 5, 51, 56, 67, 81, 110, 111, 115, 135], "diam": [4, 5], "radiu": [4, 11, 13, 15, 30, 171, 174, 184, 211, 223], "lens_label": [4, 5, 9], "add": [4, 5, 66, 67, 70, 78, 82, 141, 148], "apertur": [4, 9, 46], "propag": [4, 5, 9, 41, 45], "beam": [4, 5, 9, 91, 290], "plot": [4, 5, 9, 19, 24, 25, 30, 35, 36, 37, 66, 67, 68, 78, 122, 187, 198, 199, 200, 201, 202, 203, 204, 205, 206, 224, 296, 304, 305, 309, 310, 311], "f": [5, 19, 68, 90], "len": [5, 8, 46], "exact_bragg": 6, "fals": [6, 8, 32, 33, 34, 35, 37, 78, 103, 115, 121, 124, 129, 153, 155, 176, 187, 190, 200, 221, 222, 255, 259, 260, 261, 263, 276, 290, 312], "shift": [6, 104, 106, 107, 133, 135, 176, 202, 231], "laue_zon": [6, 259, 260], "1": [6, 8, 13, 19, 21, 23, 25, 38, 46, 51, 68, 70, 90, 91, 105, 171, 173, 174, 176, 202, 211, 218, 221, 223, 225, 226, 235, 252, 264, 276, 287, 288, 290, 315], "color": [6, 9, 30, 187, 202, 203, 204, 205, 206], "black": [6, 7], "ewald": 6, "sphere": [6, 172, 173, 184], "construct": [6, 78], "explain": 6, "laue": 6, "circl": [6, 172], "defici": [6, 259, 260], "holz": [6, 259, 260], "line": [6, 78, 90, 210, 259, 260], "paramet": [6, 8, 9, 11, 12, 13, 14, 19, 22, 30, 35, 37, 45, 66, 67, 69, 70, 78, 82, 91, 92, 95, 96, 103, 108, 110, 112, 113, 114, 115, 118, 134, 135, 141, 149, 152, 153, 154, 155, 156, 158, 159, 160, 163, 166, 170, 171, 175, 182, 183, 184, 192, 193, 194, 213, 216, 219, 220, 222, 223, 224, 226, 228, 229, 231, 232, 235, 250, 252, 259, 260, 261, 263, 267, 268, 290, 294, 295, 302, 309, 311], "boolean": [6, 8, 78, 103, 113, 114, 183, 184, 187, 198, 200, 222, 249, 259, 260, 261], "whether": [6, 70, 112, 157, 183, 184, 187, 200], "tilt": [6, 267, 322], "exact": 6, "bragg": [6, 215, 225, 259, 260], "condit": [6, 78], "along": [6, 9], "zone": [6, 253, 254, 257, 267], "axi": [6, 9, 41, 66, 67, 198, 235, 254, 257, 267, 302, 305], "onto": 6, "origin": [6, 39, 91, 156, 157, 158, 191, 192, 200, 221, 315], "int": [6, 9, 12, 14, 23, 38, 41, 45, 46, 78, 96, 103, 110, 111, 115, 135, 170, 229, 235, 267, 294], "first": [6, 91, 96, 112, 145, 154, 163, 170, 172, 197, 218, 235, 306], "second": [6, 131], "onli": [6, 48, 68, 78, 103], "string": [6, 9, 30, 69, 92, 95, 111, 115, 154, 163, 252], "wave": [6, 41, 42, 45, 46, 226, 258], "vector": [6, 252, 266, 276, 290], "s_g": 7, "0": [7, 8, 11, 13, 19, 23, 24, 25, 30, 63, 70, 73, 90, 91, 95, 102, 105, 106, 107, 110, 111, 112, 119, 122, 130, 135, 171, 173, 174, 176, 190, 194, 198, 201, 202, 211, 223, 235, 250, 271, 287, 288, 290], "color_b": 7, "focal_length": [8, 9], "sketch": 8, "geometr": [8, 9], "rai": [8, 9, 49, 110, 117, 135, 314], "diagram": 8, "od": 8, "one": [8, 19, 41, 70, 78, 140, 191, 221, 232, 315], "float": [8, 9, 11, 13, 19, 41, 42, 43, 46, 66, 91, 92, 95, 103, 112, 113, 114, 118, 135, 171, 174, 182, 183, 184, 192, 194, 198, 202, 203, 211, 213, 216, 223, 226, 228, 252, 258, 267, 302], "focal": [8, 9], "length": [8, 9, 17, 23, 30, 39, 49, 80, 118, 138, 176, 184, 226, 248, 258, 266], "draw": [8, 67, 70, 78], "side": 8, "return": [8, 11, 12, 13, 14, 19, 23, 27, 30, 35, 37, 41, 43, 45, 47, 69, 70, 78, 91, 92, 95, 96, 103, 110, 111, 112, 113, 114, 115, 118, 141, 144, 145, 149, 152, 153, 154, 155, 159, 160, 163, 170, 171, 174, 182, 183, 184, 191, 192, 193, 198, 199, 200, 202, 203, 204, 205, 206, 213, 216, 219, 220, 222, 223, 224, 226, 228, 229, 231, 232, 235, 252, 259, 260, 261, 263, 267, 294, 295, 302, 309, 311, 319], "type": [8, 11, 12, 13, 14, 19, 30, 35, 37, 45, 66, 69, 71, 78, 92, 95, 96, 103, 110, 112, 113, 114, 115, 118, 140, 141, 149, 152, 153, 154, 155, 159, 160, 161, 163, 175, 182, 189, 192, 193, 213, 220, 222, 223, 224, 226, 228, 229, 232, 235, 252, 259, 260, 261, 263, 267, 294, 295, 302, 309, 311, 319], "matplotlib": [8, 30, 35, 37, 66, 296, 315, 316], "source_posit": 9, "numerical_apertur": 9, "number_of_rai": 9, "lens_posit": 9, "b": [9, 30, 90, 220], "light": 9, "from": [9, 20, 23, 30, 47, 70, 71, 78, 90, 91, 106, 108, 110, 129, 132, 135, 140, 149, 156, 157, 158, 159, 160, 166, 171, 174, 175, 176, 185, 189, 196, 215, 221, 223, 231, 232, 235, 252, 268, 300, 301, 309, 311, 314, 315, 322], "given": [9, 17, 49, 80, 90, 221, 230, 248, 271, 290, 314], "list": [9, 11, 12, 14, 19, 23, 27, 39, 46, 69, 78, 90, 103, 115, 118, 139, 140, 172, 182, 183, 187, 189, 191, 198, 200, 203, 204, 205, 206, 220, 231, 261, 267, 293, 294, 295, 319], "locat": [9, 66, 149, 153, 219, 319], "z0": 9, "x0": [9, 287, 288], "off": 9, "mm": [9, 214], "numer": [9, 30, 294, 295, 319], "degre": [9, 17, 70, 267], "number": [9, 12, 30, 41, 45, 46, 67, 71, 90, 110, 111, 112, 115, 135, 139, 141, 230, 235, 293], "trace": 9, "numpi": [9, 12, 13, 14, 23, 39, 41, 42, 45, 46, 47, 66, 69, 91, 96, 103, 112, 113, 114, 118, 135, 170, 171, 182, 184, 192, 193, 194, 195, 213, 216, 220, 222, 223, 225, 228, 230, 231, 235, 261, 267, 302, 315, 316, 319], "arrai": [9, 11, 12, 13, 14, 23, 30, 39, 41, 42, 45, 46, 47, 66, 69, 70, 91, 96, 103, 113, 114, 118, 135, 170, 171, 182, 184, 192, 193, 194, 195, 213, 216, 220, 223, 225, 228, 230, 231, 235, 261, 267, 302], "lens": 9, "label": [9, 68, 259, 260, 261], "natur": [9, 221], "str": [9, 27, 47, 69, 70, 78, 92, 95, 111, 115, 140, 141, 153, 155, 160, 161, 175, 189, 202, 203, 204, 206], "atom": [10, 11, 12, 13, 14, 15, 17, 19, 20, 22, 23, 24, 25, 26, 27, 35, 36, 37, 47, 48, 67, 110, 111, 115, 135, 149, 155, 160, 170, 174, 175, 176, 177, 178, 181, 183, 184, 185, 186, 187, 189, 196, 201, 202, 203, 204, 205, 206, 248, 249, 250, 252, 255, 259, 260, 263, 314, 315], "detect": [10, 315], "all": [10, 12, 19, 49, 66, 70, 71, 78, 80, 90, 92, 95, 110, 115, 118, 138, 174, 175, 176, 182, 183, 184, 189, 191, 198, 199, 200, 203, 204, 205, 206, 223, 248, 249, 254, 259, 260, 261, 276, 290, 297, 315, 319], "i": [10, 13, 14, 17, 19, 27, 30, 44, 48, 49, 51, 66, 67, 68, 70, 78, 80, 90, 91, 104, 108, 112, 140, 149, 153, 154, 155, 157, 160, 161, 163, 174, 184, 192, 214, 220, 221, 231, 235, 248, 249, 252, 259, 260, 306, 309, 311, 315, 319, 322], "done": [10, 49, 80, 231, 248], "here": [10, 316, 319], "everyth": [10, 17, 49, 67, 80, 153, 213, 248], "unit": [10, 17, 25, 36, 45, 47, 49, 80, 122, 138, 170, 248], "pixel": [10, 39, 41, 46, 48, 191, 192, 194, 230, 231, 232], "pycroscopi": [10, 315, 319, 320, 321], "packag": [10, 197, 315, 316, 319], "imag": [11, 13, 14, 15, 38, 41, 46, 68, 192, 193, 194, 195, 207, 210, 211, 218, 220, 221, 222, 224, 229, 230, 231, 232, 309, 311, 315, 321, 322], "max_int": 11, "min_int": 11, "max_dist": 11, "4": [11, 90, 122, 135, 190, 315], "fit": [11, 68, 70, 71, 82, 86, 88, 100, 101, 102, 103, 119, 120, 121, 124, 126, 127, 128, 134, 271, 273], "gaussian": [11, 14, 82, 105, 229, 271, 273, 287], "blob": [11, 13, 223], "an": [11, 14, 15, 30, 44, 47, 67, 70, 78, 90, 91, 92, 95, 110, 112, 115, 155, 160, 174, 221, 226, 230, 249, 258, 290, 309, 316, 319], "np": [11, 12, 23, 30, 51, 105, 211, 261, 266, 267], "sidpi": [11, 13, 35, 37, 39, 49, 80, 94, 112, 131, 132, 138, 151, 152, 153, 159, 161, 166, 192, 193, 194, 211, 219, 222, 223, 224, 229, 231, 232, 234, 292, 294, 295, 298, 304, 305, 309, 311, 315], "dataset": [11, 13, 35, 37, 49, 50, 63, 80, 81, 84, 85, 93, 94, 97, 98, 99, 112, 130, 131, 132, 139, 140, 141, 152, 153, 157, 159, 161, 162, 165, 166, 192, 193, 194, 195, 211, 219, 222, 223, 224, 229, 231, 232, 234, 237, 241, 242, 243, 271, 273, 293, 294, 295, 296, 297, 298, 299, 304, 305, 306, 308, 309, 310, 311, 312, 313, 315], "posit": [11, 13, 19, 47, 103, 104, 106, 107, 134, 170, 171, 183, 184, 185, 198, 221, 223, 225, 290], "circular": 11, "mask": [11, 15, 211], "defin": [11, 19, 27, 39, 70, 71, 78, 171], "option": [11, 30, 66, 67, 68, 78, 92, 95, 198, 202, 203, 204, 205, 206, 219, 221, 222, 235, 249, 259, 260, 261, 309, 311, 316], "maximum": [11, 23, 68, 104, 221, 254], "intens": [11, 14, 15, 66, 68, 90, 224, 259, 260, 287, 288, 302], "consid": [11, 112, 198], "exclud": [11, 71, 78], "contamin": 11, "area": [11, 14, 51, 105, 271, 273, 315], "exampl": [11, 17, 23, 27, 30, 49, 51, 66, 78, 80, 90, 140, 154, 163, 171, 222, 224, 248, 249, 309, 311], "minimum": [11, 68, 182], "hole": 11, "distanc": [11, 12, 13, 19, 41, 47, 182, 216, 223, 228, 235, 259, 260], "movement": 11, "dure": 11, "sym": 11, "dictionari": [11, 17, 19, 20, 27, 35, 37, 44, 49, 68, 78, 80, 110, 117, 118, 141, 148, 149, 152, 170, 174, 176, 186, 187, 198, 199, 200, 203, 204, 205, 206, 224, 248, 249, 259, 260, 263, 271, 290], "contain": [11, 17, 19, 46, 68, 70, 152, 170, 187, 192, 194, 259, 260, 309, 311, 319], "new": [11, 70, 78, 176, 267, 315, 316], "other": [11, 78, 231], "output": [11, 49, 78, 80, 90, 186, 195, 214, 222, 248, 249, 259, 260], "dict": [11, 46, 78, 118, 141, 152, 170, 174, 198, 199, 200, 203, 204, 205, 206, 263], "mid_atom": 12, "number_of_clust": 12, "3": [12, 19, 23, 29, 30, 51, 90, 106, 107, 130, 182, 211, 217, 229, 249, 267, 282, 290, 314, 315, 319], "nearest_neighbour": 12, "7": [12, 90, 315], "A": [12, 78, 91, 191, 222, 290], "wrapper": [12, 13, 151], "sklearn": 12, "cluster": [12, 172, 181, 185, 186], "kmean": 12, "nx2": [12, 170, 192, 216, 225, 228], "evalu": [12, 90], "sort": [12, 96, 134, 139, 211, 223, 235, 271, 273, 293], "ini": 12, "nearest": 12, "neighbour": 12, "indic": [12, 96, 183, 187, 198, 200, 204, 205, 206, 235, 261, 267], "atom_s": [13, 187, 203], "threshold": [13, 223, 282], "find": [13, 92, 94, 95, 96, 97, 171, 173, 183, 184, 191, 223, 319], "simpl": [13, 25, 70, 193, 195, 232], "blob_log": [13, 223], "skimag": 13, "featur": [13, 315, 316], "visibl": [13, 70, 190], "size": [13, 23, 30, 46, 183, 184, 193, 195, 202, 281, 282, 315], "diamet": 13, "nm": [13, 17, 46, 47, 49, 80, 90, 114, 211, 213, 214, 225, 226, 276, 290, 314], "give": [13, 44, 45, 90, 91, 259, 260], "minim": 13, "between": [13, 14, 41, 90, 191], "found": [13, 49, 80], "finder": [13, 223], "usual": 13, "001": [13, 235], "we": [13, 47, 48, 68, 78, 174, 232, 271, 273, 315, 316, 319], "us": [13, 14, 19, 30, 47, 69, 70, 78, 90, 106, 112, 141, 153, 154, 161, 163, 174, 183, 184, 192, 193, 194, 195, 211, 212, 217, 218, 220, 221, 222, 223, 231, 232, 252, 266, 290, 315, 319], "rm": 13, "contrast": [13, 213, 322], "nx3": 13, "param": [14, 30, 161], "differ": [14, 183, 184, 209, 222, 315], "thi": [14, 19, 30, 45, 65, 70, 78, 90, 91, 104, 113, 114, 138, 154, 157, 163, 174, 220, 221, 231, 235, 246, 249, 261, 290, 315, 319, 322], "he": 14, "refin": [14, 184], "width": [14, 90, 103, 129, 130, 198, 287], "position_x": 14, "position_i": 14, "2d": [14, 36, 113, 114], "matrix": [14, 178, 191, 192, 194, 256, 264], "flatten": 14, "integr": [15, 90, 91, 117, 135, 315], "around": [15, 92, 95, 185], "each": [15, 68, 71, 78, 91, 176, 194, 231, 315], "setup": [16, 78], "directori": [16, 140, 154, 163], "custom": [16, 78, 315], "databas": [16, 108], "provid": [17, 27, 65, 153, 155, 160, 224, 246, 269, 315, 316], "conveni": [17, 315], "make": [17, 19, 24, 30, 41, 48, 67, 70, 118, 159, 172, 185, 186, 201, 261, 287, 288, 298], "most": [17, 96, 315, 319], "regular": 17, "crystal": [17, 21, 22, 27, 147, 149, 155, 160, 176, 177, 212, 249, 259, 260, 263], "structur": [17, 19, 20, 22, 23, 27, 138, 147, 148, 149, 155, 160, 174, 175, 183, 187, 189, 202, 203, 204, 205, 206, 249, 259, 260, 263, 315], "also": [17, 68, 78, 91, 189, 221, 235, 259, 260], "form": [17, 47, 107, 154, 163, 248, 252], "factor": [17, 47, 248, 252, 259, 260], "si": [17, 49, 80, 248], "except": [17, 49, 78, 80, 209, 248], "angl": [17, 44, 49, 80, 90, 91, 113, 114, 117, 118, 135, 215, 216, 228, 235, 267, 276, 290], "ar": [17, 27, 30, 44, 47, 66, 67, 69, 70, 71, 78, 90, 91, 96, 152, 174, 182, 184, 189, 198, 221, 235, 259, 260, 290, 314, 315, 316, 319], "assum": [17, 90, 91, 104, 198, 271, 273], "intern": [17, 47, 276, 290], "convert": [17, 140, 143, 216, 228, 252], "rad": [17, 113, 114, 276, 290], "usag": [17, 49, 67, 80, 90, 153, 248, 314, 320, 321], "see": [17, 49, 66, 67, 70, 71, 78, 80, 219, 221, 248, 249, 314, 315, 319], "routin": [17, 49, 65, 80, 220, 231, 246, 248, 315], "tag": [18, 51, 58, 68, 88, 153, 224, 249, 254, 257, 263, 264, 290], "extend": [19, 25, 90, 259, 260, 314], "max_bond_length": [19, 25], "calcul": [19, 40, 43, 45, 47, 90, 91, 113, 114, 131, 135, 171, 178, 182, 213, 214, 226, 229, 252, 258, 259, 260, 263, 275, 276, 290, 301], "data": [19, 30, 49, 68, 70, 80, 113, 138, 143, 161, 186, 194, 199, 200, 210, 221, 300, 315, 318], "ball": 19, "stick": 19, "model": [19, 49, 68, 78, 80, 86, 90, 102, 119, 273, 315, 318], "ase": [19, 20, 22, 23, 27, 35, 138, 149, 155, 160, 174, 175, 176, 183, 187, 189, 202, 203, 204, 205, 206, 248, 249, 259, 260], "inform": [19, 27, 35, 37, 118, 149, 157, 170, 174, 175, 176, 183, 187, 189, 199, 200, 224, 263, 269, 315], "like": [19, 69, 74, 78, 315], "cell": [19, 23, 25, 36, 45, 48, 140, 170, 196], "symbol": [19, 111, 174], "integ": [19, 187, 200, 205], "The": [19, 30, 45, 47, 49, 70, 78, 80, 90, 91, 140, 152, 154, 163, 171, 184, 192, 194, 221, 222, 235, 248, 252, 256, 290, 311, 314, 315, 317, 320, 321], "argument": [19, 70, 78], "scale": [19, 30, 68, 69, 103, 104, 113, 114, 118, 135, 182, 213, 215, 281, 282, 314], "effect": [19, 71, 90, 91, 135], "which": [19, 30, 49, 66, 67, 68, 70, 78, 80, 90, 91, 118, 154, 163, 174, 184, 248, 319], "includ": [19, 78, 90, 113, 138, 221], "It": [19, 90, 315], "must": [19, 22, 70, 78], "either": [19, 30, 35, 37, 152, 319], "three": [19, 78, 259, 260, 315], "singl": [19, 30, 48, 78, 90, 91, 218, 315], "direct": [19, 46, 202, 230], "By": 19, "set": [19, 68, 70, 78, 132, 153, 187, 189, 263], "valu": [19, 30, 78, 90, 91, 218, 271], "corner": [19, 70, 188], "edg": [19, 66, 67, 68, 69, 70, 71, 74, 92, 94, 95, 100, 101, 108, 112, 115, 117, 118, 135, 176, 302, 306, 320], "caus": 19, "non": [19, 219, 222, 273], "repeat": [19, 23], "veri": 19, "visualis": 19, "bond": [19, 174, 175, 176, 184, 187, 189, 199, 203], "shown": [19, 90, 319], "If": [19, 30, 78, 153, 155, 160, 187, 315, 316, 319], "zero": [19, 68, 90, 104, 106, 107, 110, 129, 136, 137], "tabul": [19, 174], "radii": [19, 175, 183, 184, 189], "super_cel": [19, 24, 180, 201], "addit": [19, 27, 65, 149, 221, 246], "info": [19, 23, 27, 35, 75, 149, 176, 187, 189, 202, 203, 204, 205, 206, 248, 259, 260], "layer": [21, 41, 42, 45, 51], "verbos": [22, 41, 115, 124, 129, 155, 176, 190, 198, 221, 222, 249, 251, 255, 259, 260, 263, 276, 290], "symmetri": [22, 233], "analysi": [22, 62, 65, 68, 90, 207, 236, 246, 270, 315, 318], "spglib": 22, "instal": [22, 23, 78, 318], "bool": [22, 35, 37, 78, 153, 155], "2": [23, 30, 39, 47, 68, 70, 90, 91, 94, 97, 105, 112, 170, 171, 182, 192, 193, 194, 195, 211, 220, 230, 290, 315, 322], "jmol": 23, "viewer": 23, "requir": [23, 91, 315, 319], "jsmol": 23, "avail": [23, 67], "through": [23, 49, 80, 172, 221, 248, 311, 315], "conda": [23, 319], "pip": [23, 319], "default": [23, 30, 38, 78, 103, 118, 138, 141, 259, 260, 268], "unit_cel": 23, "8": [23, 122, 319], "view": [23, 41, 46, 78, 170, 319], "rtype": [23, 27, 41, 42, 43, 47, 174, 198, 199, 200, 202, 203, 204, 205, 206, 230], "jsmolview": 23, "jupyter_jsmol": 23, "import": [23, 27, 140, 154, 163, 300, 309, 311], "build": [23, 315], "itertool": 23, "bulk": 23, "cu": 23, "fcc": 23, "5": [23, 30, 66, 70, 92, 94, 95, 198, 218, 221, 290, 315, 319], "76911": 23, "cubic": 23, "po": 23, "product": 23, "25": [23, 202, 318], "75": 23, "al": [23, 80], "al2cu": 23, "plot_as": 23, "displai": [23, 68], "shift_x": [24, 201, 202], "extra": [24, 201], "period": [24, 75, 201, 319], "boundari": [24, 198, 201], "ax": [25, 66, 67, 70, 71], "none": [25, 30, 35, 37, 63, 69, 72, 73, 76, 78, 82, 91, 104, 106, 107, 108, 117, 118, 119, 133, 140, 141, 147, 152, 153, 154, 155, 160, 161, 163, 165, 174, 183, 187, 203, 204, 205, 206, 219, 237, 241, 271, 305, 306, 310, 312], "crystal_nam": [27, 259, 260], "format": [27, 30, 125, 138, 149, 155, 160, 161, 175, 189, 192, 194, 261, 315], "store": [27, 35, 37, 70, 149, 152, 153, 176, 189, 219, 259, 260], "attribut": [27, 35, 37, 49, 70, 78, 80, 149, 152, 153, 248, 259, 260, 269], "pleas": [27, 68, 219, 222, 259, 260, 315, 316, 319], "note": [27, 30, 68, 78, 90, 259, 260, 315, 319], "chemic": [27, 108, 111, 135, 320], "express": [27, 221], "case": [27, 78, 184, 315, 319], "sensit": [27, 94, 97, 131], "pre": 27, "print": [27, 154, 163, 263], "crystal_data_bas": 27, "kei": [27, 68, 70, 78, 141, 319], "silicon": [27, 249], "x": [29, 30, 41, 46, 49, 66, 68, 70, 82, 86, 102, 105, 110, 116, 117, 119, 120, 121, 126, 127, 128, 135, 136, 137, 192, 193, 195, 198, 202, 217, 220, 221, 222, 223, 228, 230, 235, 302, 314], "y": [29, 30, 46, 66, 68, 70, 82, 91, 96, 102, 126, 127, 128, 217, 220, 221, 223, 230, 235, 302], "grid": [29, 39, 191, 217, 234], "r": [29, 47, 90, 123, 217, 223, 235, 252, 290], "t": [29, 78, 90, 217, 222], "order": [29, 38, 217, 290, 294, 295], "": [30, 70, 78, 140, 221, 222, 260, 316, 319], "c": [30, 45, 47, 213, 214, 248, 252], "vmin": 30, "vmax": 30, "kwarg": [30, 72, 73, 78, 305, 306], "scatter": [30, 40, 90, 113, 114, 225, 248, 252, 259, 260, 264, 314, 322], "similar": 30, "plt": [30, 66, 67], "input": [30, 49, 80, 90, 91, 111, 195, 207, 214, 221, 236, 248, 249, 250, 270, 315], "scalar": 30, "array_lik": 30, "shape": [30, 70, 82, 129, 194, 287, 288], "n": [30, 170, 182, 192, 193, 195, 211, 220, 221, 222, 290], "can": [30, 78, 90, 187, 221, 311, 316, 319], "sequenc": 30, "specif": [30, 252], "map": 30, "cmap": 30, "norm": [30, 266], "specifi": [30, 38, 78, 90], "via": [30, 78, 319], "should": [30, 46, 70, 78, 306], "rgb": 30, "rgba": 30, "becaus": [30, 140], "indistinguish": 30, "colormap": 30, "you": [30, 44, 71, 154, 163, 315, 316, 319], "insist": 30, "instead": [30, 47, 78], "d": [30, 113, 114], "row": 30, "howev": [30, 47], "conjunct": 30, "normal": 30, "lumin": 30, "min": 30, "max": 30, "collect": [30, 90, 91, 117, 118, 135, 186], "properti": [30, 70, 78], "eg": [30, 315], "alpha": [30, 91, 265], "edgecolor": 30, "ec": 30, "facecolor": 30, "fc": 30, "linewidth": 30, "lw": 30, "linestyl": 30, "l": [30, 290], "transform": [30, 38, 191, 217, 221, 224], "etc": [30, 90, 315, 316, 319], "path": [30, 90, 144, 154, 163, 164], "pathcollect": 30, "arang": 30, "colorbar": 30, "licens": [30, 209], "code": [30, 140, 171, 315], "under": [30, 271, 273], "bsd": 30, "claus": 30, "http": [30, 171, 174, 196, 222, 319], "opensourc": 30, "org": [30, 174, 222], "grei": [32, 33, 35, 37], "grai": 34, "diffraction_pattern": [35, 37], "spot": [35, 211, 212, 215, 223, 225, 233, 259, 260], "diffract": [35, 37, 39, 212, 225, 233, 234, 263, 315], "pattern": [35, 37, 39, 234, 263], "directli": [35, 37], "background": [35, 68, 70, 315], "greyscal": [35, 37], "fig": [35, 37, 66, 67, 90, 187, 202, 203, 204, 205, 206], "refer": [35, 37, 171, 231, 249, 290], "reciproc": [36, 213, 224, 276, 290], "space": [36, 42, 319], "ring": [37, 263], "metadata": [37, 78, 157, 315], "img": 38, "its": [38, 78], "polar": [38, 39, 44, 216, 217, 228, 234, 235], "coordin": [38, 39, 44, 70, 191, 192, 216, 228, 235, 253, 257, 265], "represent": [38, 315], "spline": 38, "interpol": [38, 192, 194], "high": [38, 315], "mai": [38, 78, 221, 319], "slow": 38, "larg": [38, 90], "diff": [39, 234], "center": [39, 70, 171, 184, 198, 200, 211, 223, 231, 232, 234], "ndarrai": [39, 112, 211, 261, 267], "dynam": [40, 78], "librari": [40, 320, 321, 322], "multi": [40, 45], "slice": [40, 45], "size_in_pixel": 41, "delta_z": 41, "number_lay": [41, 45], "wavelength": [41, 46, 109, 213, 214, 258, 286], "field_of_view": [41, 46], "bandwidth_factor": 41, "get": [41, 42, 69, 70, 74, 78, 106, 107, 108, 109, 129, 139, 146, 174, 175, 176, 198, 215, 225, 276, 281, 293, 294, 295, 296, 297, 301, 315, 316], "ha": [41, 42, 78, 154, 163, 170, 192, 194, 319], "convolut": [41, 46, 221], "after": [41, 78, 91, 222], "transmiss": [41, 42, 45], "squar": 41, "incid": [41, 90, 91, 290], "electron": [41, 80, 90, 91, 109, 213, 226, 248, 252, 258, 275, 290], "field": [41, 46, 78], "rel": [41, 90, 231], "bandwidth": 41, "avoid": [41, 78], "anti": [41, 70], "alias": 41, "complex": [41, 42, 45, 221, 315], "potenti": [42, 46, 47, 48, 322], "acceleration_voltag": [42, 43, 258, 284], "multipli": [42, 221], "real": [42, 90], "nxn": [42, 45, 47], "acceler": [42, 43, 91, 109, 113, 114, 118, 135, 226, 258], "voltag": [42, 43, 91, 113, 114, 118, 135, 226, 258, 290], "v": [42, 47, 91, 118, 221, 277, 278, 279, 280], "sigma": [43, 105], "volt": [43, 226, 258], "dimensionless": 43, "theta": [44, 91, 259, 260, 285, 286], "phi": [44, 216, 228, 235, 259, 260, 285, 286], "chi": [44, 276, 286, 290], "meshgrid": 44, "coeffici": [44, 213, 276, 290], "attent": 44, "empti": 44, "perfect": [44, 191], "number_of_unit_cell_z": 45, "chang": [45, 66, 67, 78, 138, 215, 322], "iter": [45, 78, 221, 273], "start": [45, 70, 103, 140, 146, 170, 171, 184, 302, 316, 319, 322], "thick": [45, 51, 90, 113, 114], "multipl": [45, 78, 315], "lattic": [45, 170, 256, 276, 290], "per": [45, 90], "ab": [46, 105, 276, 277, 278, 279, 280, 281, 282, 286, 289, 290], "nx": [46, 48], "ny": [46, 48], "aperture_s": 46, "exit": [46, 78], "deriv": [46, 91, 112, 131, 221], "least": [46, 78], "defocu": [46, 213, 214, 276, 286], "c10": 46, "spheric": [46, 213, 290], "c30": 46, "extent": [46, 70, 210, 296], "element": [47, 48, 53, 60, 67, 69, 78, 108, 110, 115, 135, 235, 252], "project": [47, 170, 222, 315, 318], "angstrom": [47, 138, 198, 248, 252, 258, 290], "basi": 47, "kirkland": [47, 174, 175, 189, 248, 252], "2\ud835\udc5b\ud835\udc51": 47, "edit": [47, 90, 248, 252], "follow": [47, 68, 78, 91, 170, 174, 221, 290, 319], "equat": [47, 135, 252], "appendix": [47, 248, 252], "page": [47, 315, 318, 319], "252": 47, "name": [47, 78, 140, 141, 142, 143, 145, 147, 153, 155, 160, 161, 252, 295], "impact": 47, "n_cell_x": 48, "n_cell_i": 48, "lattice_paramet": 48, "super": 48, "limit": [48, 70, 198, 224], "place": [48, 152], "resolut": [48, 129], "quantif": [49, 65, 80, 100, 101, 118, 132, 246, 315], "energi": [49, 66, 67, 69, 80, 90, 91, 92, 95, 96, 103, 104, 109, 113, 114, 115, 118, 123, 133, 135, 302, 314], "dispers": 49, "spectroscopi": [49, 315], "copyright": [49, 80, 248, 268, 314], "univers": [49, 80, 171, 248, 315, 320, 321], "tennesse": [49, 80, 248, 315, 320, 321], "knoxvil": [49, 80, 248, 315, 320, 321], "depart": [49, 80, 248], "materi": [49, 51, 80, 248, 320, 321], "scienc": [49, 80, 248, 315, 320, 321], "engin": [49, 80, 248, 320, 321], "mrad": [49, 80, 91, 118, 135, 281, 282], "meta_data": [49, 80], "minimum_number_of_peak": 50, "30": [50, 51], "detector_definit": 51, "energy_scal": [51, 57, 59, 66, 67, 68, 69, 74, 76, 83, 87, 91, 100, 101, 103, 106, 107, 117, 118, 124, 129, 133, 135], "acceleration_voltage_v": [51, 259, 260], "30000": 51, "detector": 51, "commen": 51, "ed": [51, 252], "m": [51, 113, 170, 193, 195, 290], "allay": 51, "1e": 51, "9": 51, "13": [51, 135], "deadlay": 51, "100": [51, 190, 198], "14": 51, "window": [51, 62, 92, 95, 153, 315, 316, 319], "6": [51, 315, 319], "45": [51, 70], "m2": 51, "linspac": 51, "60": 51, "1199": 51, "1000": [51, 90], "ev": [51, 90, 91, 109, 113, 114, 135], "spectrum": [52, 53, 58, 60, 66, 67, 68, 69, 90, 91, 96, 97, 100, 101, 102, 103, 104, 106, 112, 118, 119, 124, 129, 133, 135, 229, 271, 273, 310, 315], "minor_peak": 52, "enrgy_scal": 54, "mu": 54, "fwhm": [54, 90, 105], "e": [55, 59, 88, 89, 90, 91, 122, 221, 249, 290, 319], "e_ref": 55, "fwhm_ref": 55, "xsection": 57, "start_bgd": 57, "end_bgd": 57, "out_tag": 61, "p": [61, 86, 88, 90, 103, 105, 113, 114, 116, 119, 120, 121, 126, 127, 128, 134, 136, 137, 171, 193, 195, 309, 311], "qt": [62, 153, 154, 161, 163], "dialog": [62, 65, 75, 153, 154, 155, 160, 161, 163, 207, 236, 246, 270, 315], "eel": [62, 65, 90, 108, 135, 236, 246, 270, 300, 301, 315, 320], "composit": [62, 320], "index": [63, 152, 170, 200, 205, 318], "file": [65, 90, 110, 125, 138, 140, 141, 143, 144, 145, 147, 149, 152, 153, 154, 155, 156, 157, 158, 160, 161, 163, 164, 219, 246, 268, 269, 301, 315, 319], "maximal_chemical_shift": [66, 92, 95], "cursor": [66, 67, 70, 306], "major": [66, 70, 92, 95, 115, 138], "possibl": [66, 68], "ioniz": [66, 67, 74, 92, 95, 115], "left": [66, 70, 319], "right": 66, "mous": [66, 70], "button": [66, 70, 319], "click": [66, 319], "maximum_chemical_shift": [66, 67], "allow": [66, 67, 78, 103, 259, 260], "rang": [66, 67, 70, 91, 92, 95, 113, 114, 115, 190], "search": [66, 67, 108, 170, 172, 319], "subplot": [66, 67], "chapter4": [66, 67, 71], "ch4": [66, 67, 71], "working_with_x": [66, 67, 71], "section": [66, 67, 68, 69, 71, 90, 110, 117, 118, 135, 314], "There": [67, 259, 260], "updat": [67, 70, 78, 117, 157, 268, 318], "set_edg": 67, "accordingli": 67, "disconnect": [67, 70], "invis": 67, "stop": 67, "reconnect": 67, "undo": 67, "42": [67, 90], "data_sourc": 68, "cube": 68, "intensity_scale_ppm": 68, "ylabel": 68, "spectra": [68, 69, 107, 108, 221, 300, 301, 315], "style": [68, 78, 153, 159, 166], "intensity_scal": 68, "sum": 68, "1e6": 68, "load": [68, 138, 151], "ani": [68, 70, 78, 91, 112, 149, 319], "select": [68, 69, 70, 71, 139, 140, 155, 160, 293, 319], "survei": 68, "For": 68, "have": [68, 69, 78, 151, 184, 191, 316, 319], "fix_energi": 68, "loss": [68, 80, 86, 90, 91, 102, 104, 106, 107, 113, 114, 119, 122, 129, 136, 137, 300, 302], "peak": [68, 82, 90, 96, 97, 103, 104, 106, 107, 112, 129, 134, 137, 271, 273], "low": [68, 90, 102, 113, 114, 119, 129, 211, 290], "fit_zero_loss": 68, "fit_low_loss": 68, "fit_composit": 68, "core": [68, 86, 316, 317], "cross": [68, 69, 78, 110, 117, 118, 135, 314], "fit_eln": 68, "initial_el": 69, "ipywidget": 69, "valid": [69, 70, 78, 111], "disabl": 69, "alreadi": [69, 78, 319], "determin": [69, 112, 143, 172, 232], "get_output": 69, "on_select": 70, "rectangleselector": 70, "activ": 70, "widget": [70, 78, 139, 140, 293, 311, 315], "add_stat": 70, "state": [70, 71, 78, 209, 300, 302], "behavior": 70, "state_modifier_kei": 70, "detail": [70, 90, 316], "support": [70, 300, 319], "selector": 70, "rais": [70, 78, 316, 319], "valueerror": 70, "when": [70, 78, 221, 316], "artist": 70, "tupl": 70, "rectangl": 70, "clear": 70, "readi": 70, "connect_default_ev": 70, "connect": 70, "canva": 70, "event": [70, 78, 91, 210], "connect_ev": 70, "callback": [70, 78], "lieu": 70, "mpl_connect": 70, "sinc": [70, 90, 319], "id": [70, 78], "later": 70, "clean": 70, "up": [70, 90, 91, 254], "lower": [70, 198], "move": [70, 191, 192, 194, 292, 322], "clockwis": 70, "disconnect_ev": 70, "edge_cent": 70, "midpoint": 70, "xmin": 70, "xmax": 70, "ymin": 70, "ymax": 70, "bound": 70, "box": [70, 78, 319], "befor": [70, 78, 319], "rotat": [70, 225, 233, 267], "geometri": [70, 91, 171], "four": [70, 315], "end": [70, 78], "top": [70, 78, 231, 319], "get_act": 70, "get_vis": 70, "ignor": [70, 90], "call": [70, 78, 210], "begin": 70, "on_key_press": 70, "press": [70, 171, 221], "handler": [70, 78], "on_key_releas": 70, "releas": 70, "on_scrol": 70, "scroll": [70, 311], "onmov": 70, "remove_st": 70, "remov": [70, 78], "interv": 70, "keep": [70, 183], "implement": 70, "set_act": 70, "set_handle_prop": 70, "handle_prop": 70, "handl": [70, 187, 222, 315, 322], "docstr": 70, "know": [70, 78], "set_prop": 70, "prop": 70, "set_vis": 70, "blit": 70, "draw_idl": 70, "depend": [70, 78, 157, 222, 316], "self": [70, 78, 210], "useblit": 70, "update_background": 70, "forc": [70, 221], "region": [71, 113, 114], "spanselector": 71, "want": [71, 319], "solid": [71, 91], "ipynb": 71, "dset": [72, 73, 90, 166, 211, 223, 224, 229, 231, 305], "spectralimagevisu": 72, "spectrum_numb": [73, 305], "curvevisu": 73, "within": [74, 92, 94, 95, 191], "tabl": 75, "hbox": 78, "public": 78, "constructor": 78, "__del__": 78, "dispos": 78, "add_class": 78, "classnam": 78, "level": 78, "doesn": 78, "exist": [78, 174, 315, 319], "add_trait": 78, "trait": 78, "blur": 78, "box_styl": 78, "predefin": 78, "children": 78, "classmethod": 78, "class_own_trait_ev": 78, "parent": 78, "work": [78, 140, 315, 319], "event_handl": 78, "class_own_trait": 78, "traitlet": 78, "class_trait": 78, "class_trait_nam": 78, "just": [78, 151, 315, 319], "trait_nam": 78, "unbound": 78, "traittyp": 78, "don": 78, "anyth": 78, "about": 78, "variou": 78, "hastrait": 78, "instanc": [78, 202, 203, 204, 205, 206], "hold": [78, 319], "pass": [78, 211], "filter": [78, 154, 163, 211, 321], "take": [78, 234], "close": [78, 315], "underli": 78, "comm": 78, "automat": [78, 153], "front": 78, "cross_validation_lock": 78, "contextmanag": 78, "run": [78, 141, 152, 154, 163, 306, 315], "block": 78, "our": [78, 315, 316, 318], "lock": 78, "At": 78, "restor": [78, 221], "prior": 78, "enter": [78, 90, 319], "focu": 78, "static": 78, "get_manager_st": 78, "drop_default": 78, "full": [78, 154, 163, 316], "manag": [78, 319], "embed": 78, "get_stat": 78, "piec": 78, "unicod": 78, "handle_comm_open": 78, "msg": 78, "handle_control_comm_open": 78, "open": [78, 138, 141, 144, 153, 154, 155, 160, 161, 163, 164, 315, 319], "messag": 78, "control": 78, "channel": [78, 90, 103, 145, 146], "receiv": 78, "has_trait": 78, "hold_sync": 78, "sync": 78, "until": 78, "outermost": 78, "context": 78, "hold_trait_notif": 78, "bundl": 78, "notif": 78, "do": [78, 319], "assign": 78, "init": 78, "config": [78, 268], "race": 78, "notifi": 78, "request": [78, 316], "fire": 78, "been": [78, 319], "model_id": 78, "yet": [78, 153, 161], "automag": 78, "notify_chang": 78, "observ": 78, "callabl": 78, "sentinel": 78, "Its": 78, "signatur": 78, "where": [78, 90, 103, 149, 152, 191, 192, 194, 198, 209, 221, 319], "In": [78, 154, 163, 184], "owner": 78, "old": [78, 166], "modifi": [78, 90, 187], "appli": [78, 192, 194, 221, 300], "equal": 78, "on_msg": 78, "un": 78, "regist": [78, 219, 232], "arriv": 78, "content": [78, 140], "buffer": 78, "unregist": 78, "on_trait_chang": 78, "deprec": 78, "subclass": 78, "convent": [78, 252], "_": 78, "traitnam": 78, "_chang": 78, "thu": [78, 221], "_a_chang": 78, "fewer": 78, "below": [78, 319], "uninstal": [78, 319], "unintal": 78, "on_widget_construct": 78, "frontend": 78, "isn": 78, "remove_class": 78, "send": 78, "binari": 78, "send_stat": 78, "set_stat": 78, "sync_data": 78, "set_trait": 78, "forcibli": 78, "read": [78, 110, 125, 149, 156, 157, 158, 224, 268, 269], "setup_inst": 78, "__init__": 78, "tabbabl": 78, "tooltip": 78, "caption": 78, "trait_default": 78, "them": [78, 223], "gener": [78, 90, 221, 315, 319], "current": [78, 315], "trait_ev": 78, "associ": [78, 91, 183], "trait_has_valu": 78, "even": 78, "getattr": 78, "would": [78, 90, 91], "These": [78, 90, 91], "recogn": 78, "thei": 78, "myclass": 78, "mc": 78, "assert": 78, "trait_metadata": 78, "trait_valu": 78, "retriev": 78, "oper": [78, 221, 316], "trigger": 78, "result": [78, 90, 152, 315, 319], "absenc": 78, "unobserv": 78, "correspond": 78, "unobserve_al": 78, "gui": [79, 154, 163, 208, 239, 274], "definit": [79, 274], "eeels_dialog": 79, "tian": 80, "et": 80, "pin_in": 82, "peak_shape_in": 82, "edge_channel": [83, 112], "number_of_edg": 86, "xsec": 86, "peak_posit": 87, "peak_width": 87, "gamma": [87, 89, 288], "dielectr": [87, 88, 89, 90, 113, 300], "accord": [87, 88, 89, 90, 104, 135, 174, 192, 220, 221, 225, 302, 308], "theori": [87, 88, 89, 225, 248], "drude": [88, 89, 90], "eps_inf": 89, "leng": 89, "ep": [89, 90, 122, 223], "eb": [89, 90], "amplitud": [89, 103, 105], "lorentz": 89, "ew": 90, "tnm": 90, "probabl": [90, 113, 114], "i0": 90, "egerton": [90, 135], "microscop": [90, 253, 265], "3rd": 90, "springer": 90, "2011": [90, 171], "epc": 90, "e0": [90, 109, 135, 226], "beta": [90, 91, 135, 265], "nn": 90, "plasmon": [90, 113, 114], "bind": 90, "program": [90, 91, 271, 273, 300, 315], "eps1": 90, "eps2": 90, "eq": 90, "40": 90, "elf": 90, "im": [90, 218, 230], "26": 90, "srfint": 90, "31": [90, 138], "ssd": 90, "flog": 90, "kroeger": 90, "version": [90, 197, 316, 319, 322], "simul": [90, 300], "specimen": 90, "record": 90, "spectromet": 90, "accept": [90, 108], "semi": 90, "volum": [90, 113, 114, 171, 196, 203, 204, 206, 259, 260], "64": 90, "surfac": 90, "srelf": 90, "retard": 90, "coupl": 90, "two": [90, 235, 315], "mode": [90, 315], "term": 90, "made": 90, "neglig": 90, "volint": 90, "respect": [90, 232], "total": [90, 113, 114], "spectral": [90, 305], "written": [90, 153], "krakro": 90, "divid": 90, "imaginari": 90, "comparison": [90, 215], "kramer": 90, "kronig": 90, "dat": 90, "obtain": 90, "relat": 90, "neg": [90, 252], "begrenzung": 90, "analyt": [90, 91], "repres": [90, 221], "77": 90, "p_v": 90, "mean": [90, 105, 271, 273], "free": [90, 315, 316], "lam": 90, "latter": 90, "compar": [90, 178, 225], "mfp": 90, "44": 90, "pt": 90, "formula": [90, 108], "\u03bb": 90, "ln": 90, "exce": 90, "thicker": 90, "inelast": [90, 314], "command": [90, 319], "metal": [90, 175, 189], "1a": 90, "beam_kv": 91, "translat": 91, "fortran": 91, "last": [91, 141, 144, 154, 163, 164, 184, 318], "converg": [91, 315], "beamkv": 91, "eff_beta": 91, "effbeta": 91, "en": 91, "comput": [91, 248, 252, 315, 319], "etha": 91, "effici": 91, "half": 91, "illumin": [91, 315], "pi": [91, 105, 290], "1570": 91, "795": 91, "constant": 91, "angular": 91, "distribut": [91, 221, 319], "imp": 91, "target": [91, 192], "occur": 91, "characterist": 91, "relativist": [91, 113, 114, 226, 258], "adjust": 91, "step": 91, "theoret": 91, "same": [91, 118, 182, 184, 251], "parallel": [91, 198, 315], "subroutin": [91, 153], "subprogram": 91, "comment": 91, "ask": [91, 316], "kv": 91, "studi": 91, "pierr": 91, "trebbia": 91, "u": [91, 277, 278, 279, 280, 315, 318, 319], "41": 91, "microscopi": [91, 248, 252], "electroniqu": 91, "analytiqu": 91, "quantit": [91, 315], "laboratoir": 91, "de": [91, 218, 226, 258, 290], "physiqu": 91, "bat": 91, "510": [91, 222], "universit": 91, "pari": 91, "sud": 91, "f91405": 91, "orsai": 91, "cedex": 91, "phone": 91, "33": 91, "69": 91, "53": 91, "68": 91, "edge_onset": [92, 95], "minor": 92, "approxim": [92, 95], "look": [92, 95, 154, 163], "text": [92, 95, 319], "number_of_peak": [96, 102, 119], "promin": 96, "fit_start": 97, "fit_end": 97, "region_tag": 100, "pin": [102, 103, 119], "peak_shap": [102, 119, 134], "p_zl": [102, 119, 136], "restrict_po": [102, 119], "restrict_width": [102, 119], "start_fit": 103, "end_fit": 103, "only_positive_intens": [103, 120, 121, 126, 127, 128], "intial": 103, "guess": 103, "spec": 104, "fzero": 104, "sqrt": 105, "3548": 105, "log": [105, 139, 141, 152, 293], "spectrum_imag": [106, 107, 133], "zero_loss_fit_width": [106, 107], "better": [106, 315, 322], "resolution_funct": [106, 107], "titl": [108, 122, 202, 203, 204, 205, 206, 210], "could": 108, "expos": 108, "more": [108, 315], "debrogli": [109, 213], "fluoresc": 110, "pickl": 110, "independ": [111, 221, 315], "noise_level": 112, "onset": [112, 320], "higher": 112, "than": [112, 182, 319], "time": [112, 154, 163, 315], "standard": 112, "deviat": 112, "th": [112, 221], "decid": 112, "signific": [112, 235], "e_data": [113, 114, 122], "a_data": [113, 114, 122], "eps_data": [113, 114], "ee": [113, 122], "differenti": [113, 114], "frac": [113, 114], "2p": [113, 114], "omega": [113, 114], "d_e": [113, 114], "momentum": [113, 114, 135], "kev": [113, 114, 135], "correct": [113, 114, 166, 202, 203, 204, 205, 206, 221, 224, 226, 229, 258, 290], "p_vol": [113, 114], "acceleration_voltage_kev": 114, "1e2": 114, "p_simpl": 114, "out_str": 115, "lorentzian": [116, 288], "e_0": [117, 118], "coll_angl": [117, 118], "low_loss": [117, 118], "photo": [117, 135, 314], "absorpt": [117, 135, 314], "edges_pres": 118, "low_less": 118, "convolv": 118, "plotdata": 122, "max_p": 122, "ef": 122, "16": 122, "ibt": 122, "power": [123, 124, 229, 315], "law": [123, 124], "power_law_background": 123, "fit_area": 124, "msa_str": 125, "msa": 125, "current_dataset": 132, "previou": 132, "master_energy_scal": 133, "nist": [135, 314], "ultramicroscopi": [135, 290], "50": 135, "1993": [135, 221], "28": 135, "analyz": 135, "tool": [138, 300, 320, 321, 322], "save": [138, 152, 161, 164], "2018": 138, "nion": [138, 140, 157], "swift": [138, 140], "2020": [138, 300], "09": 138, "pynsid": [138, 161, 315, 316], "2022": [138, 197, 314, 318], "input_object": [139, 151, 293], "show_dialog": [139, 293], "get_dataset_list": [139, 293], "dir_nam": 140, "extens": [140, 153, 154, 163], "googl": [140, 304, 316], "colab": [140, 304], "softwar": [140, 315, 316], "otherwis": [140, 182], "incomprehens": 140, "get_directori": 140, "set_opt": 140, "get_file_nam": 140, "drive": 140, "mount": 140, "file_list": 140, "next": [140, 232], "open_fil": [140, 154, 163], "file_nam": [140, 155, 160], "filenam": [141, 153, 154, 161, 163, 164, 262], "key_nam": 141, "single_dataset": 141, "write": [141, 147, 319], "adialog": 141, "appear": [141, 155, 160, 187, 319], "being": [141, 290, 315], "actual": 141, "file_dict": 142, "fname": 143, "hdf5": [143, 145, 149, 152, 153, 159, 166, 219, 319], "newli": 143, "h5_file": [145, 146, 147, 162, 165], "group": [145, 148, 149, 150, 152, 153, 159, 161, 166, 219, 316], "legaci": 146, "input_structur": 147, "nsid": [147, 149, 153], "structure_group": [148, 149], "crystal_tag": 148, "h5py": [149, 219, 315, 316, 319], "group_dict": 150, "print_tre": 151, "so": [151, 153, 306, 319], "doe": [151, 154, 163, 174, 319], "h5_group": [152, 153, 159, 161, 165], "consist": [152, 317], "log_": 152, "That": [152, 221], "hd5py": [152, 153, 161], "log_group": 152, "write_hdf_fil": 153, "hf5": [153, 154, 163], "ndata": 153, "dm3": [153, 156, 157, 158], "dm4": 153, "qt_avail": 153, "nsidread": 153, "write_": 153, "get_main_tag": 153, "get_addit": 153, "try": [153, 161, 319], "todo": 153, "hook": 153, "extern": 153, "chosen": 153, "file_typ": [154, 163], "pyqt5": [154, 163, 315], "app": [154, 163], "tkinter": [154, 163], "mac": [154, 163, 316], "point": [154, 163, 182, 184, 191, 216, 221, 228, 235], "earli": [154, 163], "txt": [154, 163], "absolut": [154, 163], "ft": [154, 163, 224], "openfile_dialog": [154, 163], "cif": 155, "original_metadata": [156, 158], "essenti": [156, 157, 158], "experi": 157, "current_channel": [159, 166], "pyusid": 159, "poscar": 160, "vasp": 160, "attach": 166, "dimens": [166, 224, 229, 230, 294, 295, 297, 305], "directory_nam": 167, "graph": [170, 171], "initi": 170, "projected_cryst": 170, "breadth": [170, 172], "item": 170, "number_of_nearest_neighbour": 170, "rotated_cel": 170, "near_bas": 170, "allowed_vari": 170, "projection_tag": 170, "visit": [170, 315], "hop": 170, "ideal": [170, 178], "vertex_po": [171, 184], "tol": 171, "0001": 171, "circumspher": [171, 184], "everi": [171, 315], "simplex": [171, 184], "fiedler": 171, "miroslav": 171, "matric": 171, "No": [171, 315, 319], "139": 171, "cambridg": 171, "29": [171, 300], "bottom": [171, 319], "github": [171, 316, 318, 319], "com": [171, 196, 319], "spatala": 171, "gbpy": 171, "help": 171, "codereview": 171, "stackexchang": 171, "question": [171, 196, 316], "77593": 171, "tetrahedron": [171, 183, 184], "vertic": [171, 182, 183, 184, 185, 191, 206], "toler": 171, "identifi": 171, "co": 171, "planar": 171, "circum_radiu": 171, "overlapping_pair": 172, "go": 172, "overlap": [172, 173], "voronoi_vertic": [173, 183, 185, 186], "r_vv": [173, 183], "r_a": [173, 189], "cheat": [173, 174, 176], "optim": [174, 183, 184], "bond_radii": [174, 183, 189], "polyhedra": [174, 176, 177, 187, 190, 198, 199, 200, 203, 204, 205, 206], "banadaki": 174, "patala": 174, "dx": 174, "doi": 174, "1038": 174, "s41524": 174, "017": 174, "0016": 174, "crystal_tool": 174, "electronff": 174, "vert": 174, "bond_length": 174, "bond_typ": [175, 189], "coval": [175, 189], "polyhedron": [176, 200, 205], "atoms_object": 176, "ideal_lattic": 178, "distort": [178, 192, 194], "voronoi": [178, 183, 196], "tile": 178, "distortion_matrix": [179, 192, 193, 194, 195], "voronoi_tetrahedron": [181, 185, 186], "averag": 182, "closer": 182, "apart": 182, "leav": 182, "alon": 182, "ideal_vertic": 182, "tetrahedra": 183, "track": 183, "interstiti": [183, 184, 185], "find_polyhedra": 183, "scipi": [183, 192, 194, 223, 231, 315], "spatial": [183, 223, 297], "delaunai": 183, "tessel": 183, "voronoi_tetrahedra": 183, "atom_radii": 184, "largest": 184, "cirumspher": 184, "new_cent": 184, "visited_al": [185, 186], "polygon": [185, 191], "convex": 185, "hull": 185, "polyhedra_indic": 187, "plot_bond": 187, "templat": 187, "max_siz": 187, "plotli": [187, 199, 200, 202, 203, 204, 205, 206], "polyedra": 187, "tobe": 187, "supercel": [187, 202, 322], "need": [187, 249, 290, 315, 319], "certain": [189, 316], "taken": 189, "z_lim": [190, 198], "ideal_voronoi": 191, "2x2": 191, "aa": 191, "image_data": [192, 193], "griddata": [192, 194], "itk": [193, 195, 222], "undistort": [193, 194, 195], "nxm": [193, 195], "q": [193, 195, 252], "mxn": 193, "stack": [194, 195, 220, 222, 231, 232, 311, 315, 321], "image_stack": [195, 219, 231, 232, 309, 311], "h5": 195, "stackoverflow": 196, "19634993": 196, "python": [196, 315, 316, 319], "pycrosccopi": 197, "08": 197, "boundary_x": 198, "boundary_width": 198, "upper": [198, 319], "boundary_polyhedra": [198, 206], "instruct": [199, 200, 319], "amount": 202, "15": [203, 252], "atoms_s": 203, "sie": 203, "image_dialog": [208, 322], "py": [209, 322], "mit": 209, "profil": 210, "__call__": 210, "low_pass": 211, "reflection_radiu": 211, "diffractogram": [211, 223, 225], "fourier": [211, 221, 224, 321], "reflect": [211, 221], "depreci": [212, 215, 266], "k": [213, 290], "transfer": 213, "ctf": 213, "scherzer": 214, "lambda": [214, 290], "fft_tag": 215, "spots_refer": 215, "spots_experi": 215, "cartesian": [216, 217, 228], "convers": [216, 228, 235, 300], "rho": [216, 228], "warp": 217, "pixel_s": 218, "source_s": 218, "nois": [218, 221, 271, 273], "compon": 218, "decomposit": 218, "main_dataset": 219, "storage_channel": 219, "rigid": [219, 222, 232], "demon": [219, 222], "registr": [219, 222, 232, 315], "perform": [219, 224, 315, 319], "individu": 219, "rigid_registr": [219, 220, 231], "demon_registr": 219, "data_typ": [219, 308, 309, 311], "non_rigid_regist": 219, "rigid_registered_dataset": 219, "rig_reg": 220, "drift": [220, 231, 232], "crop": [220, 222], "o_imag": 221, "probe": [221, 275, 287, 288, 290], "task": 221, "spread": [221, 276], "psf": 221, "algorithm": 221, "develop": [221, 315, 316, 319], "luci": 221, "1974": 221, "astron": 221, "j": [221, 290], "79": 221, "745": 221, "richardson": 221, "1972": 221, "opt": 221, "soc": 221, "am": 221, "62": 221, "55": 221, "adapt": [221, 321], "hst": 221, "imageri": 221, "snyder": 221, "1990": 221, "st": 221, "sci": 221, "workshop": 221, "proceed": [221, 319], "hammoud": 221, "white": 221, "josa": 221, "rick": 221, "stsci": 221, "likelihood": 221, "poisson": 221, "optic": 221, "photon": 221, "count": 221, "statist": 221, "essenc": 221, "estim": 221, "nth": 221, "carri": 221, "out": [221, 263, 271, 273], "fast": 221, "fft": [221, 224], "fact": 221, "conj": 221, "conjug": 221, "diffeomorph": 222, "simpleitk": 222, "cite": 222, "www": 222, "parti": 222, "html": 222, "vercauteren": 222, "pennec": 222, "perchant": 222, "ayach": 222, "finit": 222, "solver": 222, "hierarchi": 222, "insight": 222, "journal": 222, "hdl": 222, "net": 222, "1926": 222, "2007": 222, "increas": [222, 315], "dem_reg": 222, "demon_reg": 222, "stack_dataset": 222, "spot_threshold": 223, "return_cent": 223, "smooth": [224, 229, 271], "visual": [224, 315], "fft_dset": 224, "fft_dataset": 224, "sidpy_dataset": 224, "experiment_spot": 225, "crystal_spot": 225, "kinemat": [225, 259, 260, 322], "brogli": [226, 258], "image_tag": 227, "histogram": [227, 322], "power_spec": 229, "bin": 230, "rel_drift": 231, "ndimag": 231, "relative_drift": 231, "shiftx": 231, "shifti": 231, "accuraci": 232, "cross_correl": 232, "rigid_regist": 232, "test": [233, 254], "round": 235, "carthesian": 235, "digit": 235, "sorted_indic": 235, "info_dialog": 239, "sidebar": 241, "tab_titl": 241, "eelswidget": [242, 243], "zuo": [248, 249], "spenc": [248, 249], "advanc": [248, 249, 252, 320, 321], "2017": [248, 249], "microdiffract": 248, "plenum": 248, "1992": 248, "2nd": [248, 252, 290], "18": 249, "act": 249, "well": [249, 319], "reproduc": [249, 315, 316], "verbose_level": [250, 264], "check": 250, "saniti": 250, "zuo_fig_3_18": 251, "parametr": 252, "3ard": 252, "magnitud": 252, "exp": 252, "g": [252, 259, 260, 266, 319], "physic": 252, "fl": 252, "fg": 252, "stage": [253, 265], "hkl_max": [254, 259, 260], "metric": 256, "tensor": 256, "global": 257, "system": [257, 265, 316], "kikuchi": [259, 260], "excess": [259, 260], "experiment": [259, 260], "zone_hkl": [259, 260], "sg_max": [259, 260], "mistilt": [259, 260, 267], "convergence_angle_mrad": [259, 260], "sub_dictionari": [259, 260], "forbidden": [259, 260], "sg": [259, 260], "hkl": [259, 260, 261], "zolz": [259, 260], "folz": [259, 260], "solz": [259, 260], "hholz": [259, 260], "slope": [259, 260], "g_defici": [259, 260], "g_excess": [259, 260], "few": [259, 260, 316], "main": [259, 260], "wave_length_nm": [259, 260], "reciprocal_unit_cel": [259, 260], "inner_potential_v": [259, 260], "incident_wave_vector": [259, 260], "incident_wave_vector_vacuum": [259, 260], "ato": 260, "hex_label": 261, "pretti": 261, "miller": [261, 267], "hkl_label": 261, "latex": 261, "linalg": 266, "ist": 267, "new_zone_axi": 267, "csv": 268, "2012": 268, "configur": 269, "eln": [270, 302], "fit_peak": 271, "lot": [271, 273], "let": [271, 273], "small": [271, 273], "advanced_pres": 273, "mixtur": 273, "bayesian": 273, "peak_fit_dialog": 274, "size_x": [276, 287, 288, 290], "size_i": [276, 287, 288, 290], "without": [276, 286, 315], "ronchigram": 281, "tem_nam": 284, "c1_includ": 286, "y0": [287, 288], "stem": [290, 315, 318], "ddf": 290, "cc": 290, "cc2": 290, "chrom": 290, "aber": 290, "1st": 290, "qx": 290, "qy": 290, "c1": 290, "c12a": 290, "c12b": 290, "c21a": 290, "c3": 290, "125": 290, "c5": 290, "finish": 290, "aco": 290, "k_x": 290, "k_y": 290, "zach": 290, "haider": 290, "chromat": 290, "sem": 290, "optik": 290, "98": 290, "112": 290, "118": 290, "1995": 290, "o": 290, "krivanek": 290, "delbi": 290, "lupini": 290, "toward": 290, "sub": 290, "78": 290, "1999": 290, "util": 292, "dims_in": [294, 295], "dims_out": [294, 295], "dimension_typ": 295, "value_typ": 298, "dummi": 298, "dft": 300, "exciting_get_spectra": 300, "excit": [300, 301], "final_state_broaden": 300, "final": [300, 302], "broaden": [300, 302], "instrument": [302, 315], "smear": 302, "densiti": 302, "out_data": 302, "bokeh": [304, 309, 311], "leg": 305, "initialize_edg": 306, "intit": 306, "energy_valu": 307, "palett": [308, 309, 310, 311], "viridis256": [308, 309, 311], "show": [309, 311, 312], "output_notebook": [309, 311], "selected_rang": 310, "slider": 311, "barn": 314, "xsec_xrpa": 314, "eels_tool": [314, 318], "larger": 314, "20": 314, "2023": 314, "framework": 315, "enabl": 315, "approach": 315, "spectroscop": 315, "dimension": 315, "poli": 315, "crystallin": 315, "underneath": 315, "scientif": [315, 319], "some": 315, "ipython": 315, "popular": 315, "dask": [315, 316], "storag": 315, "weekli": 315, "hackathon": 315, "fridai": 315, "pm": 315, "usa": 315, "eastern": 315, "particip": 315, "knowledg": 315, "git": [315, 319], "email": 315, "vasudevanrk": 315, "ornl": 315, "gov": 315, "teach": 315, "techniqu": 315, "my": 315, "lectur": 315, "book": 315, "grow": 315, "cannot": 315, "desktop": 315, "resourc": 315, "compat": 315, "scalabl": 315, "sophist": 315, "robust": 315, "proprietari": 315, "incompat": 315, "correl": 315, "expens": 315, "suppli": 315, "often": 315, "insuffici": 315, "incap": 315, "commerci": 315, "matlab": 315, "prohibit": 315, "user": [315, 316], "friendli": 315, "share": 315, "guarante": 315, "traceabl": 315, "central": 315, "repositori": 315, "envis": 315, "facilit": 315, "scientist": 315, "analys": 315, "anlysi": 315, "burden": 315, "basic": [315, 322], "led": 315, "staff": 315, "member": 315, "oak": 315, "ridg": 315, "nation": 315, "laboratori": 315, "professor": 315, "invit": 315, "anyon": 315, "interest": 315, "join": 315, "team": [315, 317], "commun": [315, 316], "credit": [315, 318], "acknowledg": 315, "your": [315, 316, 319], "touch": [315, 316], "report": 316, "bug": [316, 319], "account": 316, "issu": [316, 319], "gmail": 316, "thread": 316, "abl": 316, "respond": 316, "faster": 316, "simplifi": [316, 319], "script": 316, "snippet": 316, "error": 316, "face": 316, "descript": 316, "regard": 316, "linux": [316, 319], "pytemlib": [317, 320, 321], "prof": 317, "jump": 318, "contact": 318, "modul": 318, "image_tool": 318, "mani": 319, "commonli": 319, "To": 319, "process": 319, "recommend": 319, "anaconda": 319, "prerequisit": 319, "environ": 319, "spyder": 319, "download": 319, "ye": 319, "restart": 319, "proce": 319, "onward": 319, "32": 319, "bit": 319, "architectur": 319, "utf": 319, "compliant": 319, "due": 319, "restrict": 319, "pose": 319, "matter": 319, "applic": 319, "how": 319, "access": 319, "prompt": 319, "cmd": 319, "hit": 319, "keyboard": 319, "sure": 319, "administr": 319, "unless": 319, "maco": 319, "launchpad": 319, "present": 319, "screen": 319, "altern": 319, "simultan": 319, "down": 319, "launch": 319, "spotlight": 319, "ubuntu": 319, "dash": 319, "equival": 319, "icon": 319, "ensur": 319, "successfulli": 319, "now": 319, "wai": 319, "master": 319, "dev": 319, "latest": 319, "dep": 319, "reinstal": 319, "hdf": 319, "explor": 319, "joint": [320, 321], "institut": [320, 321], "registrat": 321, "22": 322, "read_poscar": 322, "kinematic_scatt": 322, "file_tool": 322, "read_cif": 322, "renam": 322, "sampl": 322, "interactive_imag": 322, "multislic": 322, "dynamic_scatt": 322, "rather": 322}, "objects": {"": [[0, 0, 0, "-", "pyTEMlib"]], "pyTEMlib": [[1, 0, 0, "-", "animation"], [10, 0, 0, "-", "atom_tools"], [16, 0, 0, "-", "config_dir"], [17, 0, 0, "-", "crystal_tools"], [28, 0, 0, "-", "diffraction_plot"], [40, 0, 0, "-", "dynamic_scattering"], [49, 0, 0, "-", "eds_tools"], [62, 0, 0, "-", "eels_dialog"], [65, 0, 0, "-", "eels_dialog_utilities"], [79, 0, 0, "-", "eels_dlg"], [80, 0, 0, "-", "eels_tools"], [138, 0, 0, "-", "file_tools"], [168, 0, 0, "-", "file_tools_qt"], [169, 0, 0, "-", "graph_tools"], [197, 0, 0, "-", "graph_viz"], [207, 0, 0, "-", "image_dialog"], [208, 0, 0, "-", "image_dlg"], [209, 0, 0, "-", "image_tools"], [236, 0, 0, "-", "info_dialog"], [239, 0, 0, "-", "info_dlg"], [240, 0, 0, "-", "info_widget"], [246, 0, 0, "-", "interactive_eels"], [247, 0, 0, "-", "interactive_image"], [248, 0, 0, "-", "kinematic_scattering"], [268, 0, 0, "-", "microscope"], [270, 0, 0, "-", "peak_dialog"], [274, 0, 0, "-", "peak_dlg"], [275, 0, 0, "-", "probe_tools"], [292, 0, 0, "-", "sidpy_tools"], [300, 0, 0, "-", "simulation_tools"], [303, 0, 0, "-", "version"], [304, 0, 0, "-", "viz"], [314, 0, 0, "-", "xrpa_x_sections"]], "pyTEMlib.animation": [[2, 1, 1, "", "InteractiveAberration"], [3, 1, 1, "", "InteractiveRonchigramMagnification"], [4, 2, 1, "", "add_aperture"], [5, 2, 1, "", "add_lens"], [6, 2, 1, "", "deficient_holz_line"], [7, 2, 1, "", "deficient_kikuchi_line"], [8, 2, 1, "", "geometric_ray_diagram"], [9, 2, 1, "", "propagate_beam"]], "pyTEMlib.atom_tools": [[11, 2, 1, "", "atom_refine"], [12, 2, 1, "", "atoms_clustering"], [13, 2, 1, "", "find_atoms"], [14, 2, 1, "", "gauss_difference"], [15, 2, 1, "", "intensity_area"]], "pyTEMlib.crystal_tools": [[18, 2, 1, "", "atoms_from_dictionary"], [19, 2, 1, "", "ball_and_stick"], [20, 2, 1, "", "get_dictionary"], [21, 2, 1, "", "get_projection"], [22, 2, 1, "", "get_symmetry"], [23, 2, 1, "", "jmol_viewer"], [24, 2, 1, "", "plot_super_cell"], [25, 2, 1, "", "plot_unit_cell"], [26, 2, 1, "", "set_bond_radii"], [27, 2, 1, "", "structure_by_name"]], "pyTEMlib.diffraction_plot": [[29, 2, 1, "", "cartesian2polar"], [30, 2, 1, "", "circles"], [31, 2, 1, "", "plotCBED_parameter"], [32, 2, 1, "", "plotHOLZ_parameter"], [33, 2, 1, "", "plotKikuchi"], [34, 2, 1, "", "plotSAED_parameter"], [35, 2, 1, "", "plot_diffraction_pattern"], [36, 2, 1, "", "plot_reciprocal_unit_cell_2D"], [37, 2, 1, "", "plot_ring_pattern"], [38, 2, 1, "", "topolar"], [39, 2, 1, "", "warp"]], "pyTEMlib.dynamic_scattering": [[41, 2, 1, "", "get_propagator"], [42, 2, 1, "", "get_transmission"], [43, 2, 1, "", "interaction_parameter"], [44, 2, 1, "", "make_chi"], [45, 2, 1, "", "multi_slice"], [46, 2, 1, "", "objective_lens_function"], [47, 2, 1, "", "potential_1dim"], [48, 2, 1, "", "potential_2dim"]], "pyTEMlib.eds_tools": [[50, 2, 1, "", "detect_peaks"], [51, 2, 1, "", "detector_response"], [52, 2, 1, "", "find_elements"], [53, 2, 1, "", "fit_model"], [54, 2, 1, "", "gaussian"], [55, 2, 1, "", "getFWHM"], [56, 2, 1, "", "get_eds_cross_sections"], [57, 2, 1, "", "get_eds_xsection"], [58, 2, 1, "", "get_model"], [59, 2, 1, "", "get_peak"], [60, 2, 1, "", "get_x_ray_lines"], [61, 2, 1, "", "update_fit_values"]], "pyTEMlib.eels_dialog": [[63, 1, 1, "", "CompositionWidget"], [64, 2, 1, "", "get_sidebar"]], "pyTEMlib.eels_dialog_utilities": [[66, 1, 1, "", "EdgesAtCursor"], [67, 1, 1, "", "ElementalEdges"], [68, 1, 1, "", "InteractiveSpectrumImage"], [69, 1, 1, "", "PeriodicTableWidget"], [70, 1, 1, "", "RangeSelector"], [71, 1, 1, "", "RegionSelector"], [72, 1, 1, "", "SIPlot"], [73, 1, 1, "", "SpectrumPlot"], [74, 2, 1, "", "get_likely_edges"], [75, 2, 1, "", "get_periodic_table_info"], [76, 2, 1, "", "get_periodic_table_widget"], [77, 2, 1, "", "make_box_layout"], [78, 1, 1, "", "plot_EELS"]], "pyTEMlib.eels_dialog_utilities.EdgesAtCursor": [[66, 3, 1, "", "ax"], [66, 3, 1, "", "maximal_chemical_shift"], [66, 3, 1, "", "x"], [66, 3, 1, "", "y"]], "pyTEMlib.eels_dialog_utilities.RangeSelector": [[70, 4, 1, "", "active"], [70, 5, 1, "", "add_state"], [70, 4, 1, "", "artists"], [70, 4, 1, "", "center"], [70, 5, 1, "", "clear"], [70, 5, 1, "", "connect_default_events"], [70, 5, 1, "", "connect_event"], [70, 4, 1, "", "corners"], [70, 5, 1, "", "disconnect_events"], [70, 4, 1, "", "edge_centers"], [70, 4, 1, "", "extents"], [70, 4, 1, "", "geometry"], [70, 5, 1, "", "get_active"], [70, 5, 1, "", "get_visible"], [70, 5, 1, "", "ignore"], [70, 5, 1, "", "on_key_press"], [70, 5, 1, "", "on_key_release"], [70, 5, 1, "", "on_scroll"], [70, 5, 1, "", "onmove"], [70, 5, 1, "", "press"], [70, 5, 1, "", "release"], [70, 5, 1, "", "remove_state"], [70, 4, 1, "", "rotation"], [70, 5, 1, "", "set_active"], [70, 5, 1, "", "set_handle_props"], [70, 5, 1, "", "set_props"], [70, 5, 1, "", "set_visible"], [70, 5, 1, "", "update"], [70, 5, 1, "", "update_background"]], "pyTEMlib.eels_dialog_utilities.plot_EELS": [[78, 5, 1, "", "__del__"], [78, 5, 1, "", "add_class"], [78, 5, 1, "", "add_traits"], [78, 5, 1, "", "blur"], [78, 3, 1, "", "box_style"], [78, 3, 1, "", "children"], [78, 5, 1, "", "class_own_trait_events"], [78, 5, 1, "", "class_own_traits"], [78, 5, 1, "", "class_trait_names"], [78, 5, 1, "", "class_traits"], [78, 5, 1, "", "close"], [78, 4, 1, "", "cross_validation_lock"], [78, 5, 1, "", "focus"], [78, 5, 1, "", "get_manager_state"], [78, 5, 1, "", "get_state"], [78, 5, 1, "", "handle_comm_opened"], [78, 5, 1, "", "handle_control_comm_opened"], [78, 5, 1, "", "has_trait"], [78, 5, 1, "", "hold_sync"], [78, 5, 1, "", "hold_trait_notifications"], [78, 3, 1, "", "keys"], [78, 4, 1, "", "model_id"], [78, 5, 1, "", "notify_change"], [78, 5, 1, "", "observe"], [78, 5, 1, "", "on_msg"], [78, 5, 1, "", "on_trait_change"], [78, 5, 1, "", "on_widget_constructed"], [78, 5, 1, "", "open"], [78, 5, 1, "", "remove_class"], [78, 5, 1, "", "send"], [78, 5, 1, "", "send_state"], [78, 5, 1, "", "set_state"], [78, 5, 1, "", "set_trait"], [78, 5, 1, "", "setup_instance"], [78, 3, 1, "", "tabbable"], [78, 3, 1, "", "tooltip"], [78, 5, 1, "", "trait_defaults"], [78, 5, 1, "", "trait_events"], [78, 5, 1, "", "trait_has_value"], [78, 5, 1, "", "trait_metadata"], [78, 5, 1, "", "trait_names"], [78, 5, 1, "", "trait_values"], [78, 5, 1, "", "traits"], [78, 5, 1, "", "unobserve"], [78, 5, 1, "", "unobserve_all"], [78, 5, 1, "", "update"]], "pyTEMlib.eels_tools": [[81, 2, 1, "", "add_element_to_dataset"], [82, 2, 1, "", "add_peaks"], [83, 2, 1, "", "assign_likely_edges"], [84, 2, 1, "", "auto_chemical_composition"], [85, 2, 1, "", "auto_id_edges"], [86, 2, 1, "", "cl_model"], [87, 2, 1, "", "drude"], [88, 2, 1, "", "drude2"], [89, 2, 1, "", "drude_lorentz"], [90, 2, 1, "", "drude_simulation"], [91, 2, 1, "", "effective_collection_angle"], [92, 2, 1, "", "find_all_edges"], [93, 2, 1, "", "find_associated_edges"], [94, 2, 1, "", "find_edges"], [95, 2, 1, "", "find_major_edges"], [96, 2, 1, "", "find_maxima"], [97, 2, 1, "", "find_peaks"], [98, 2, 1, "", "find_white_lines"], [99, 2, 1, "", "fit_dataset"], [100, 2, 1, "", "fit_edges"], [101, 2, 1, "", "fit_edges2"], [102, 2, 1, "", "fit_model"], [103, 2, 1, "", "fit_peaks"], [104, 2, 1, "", "fix_energy_scale"], [105, 2, 1, "", "gauss"], [106, 2, 1, "", "get_energy_shifts"], [107, 2, 1, "", "get_resolution_functions"], [108, 2, 1, "", "get_spectrum_eels_db"], [109, 2, 1, "", "get_wave_length"], [110, 2, 1, "", "get_x_sections"], [111, 2, 1, "", "get_z"], [112, 2, 1, "", "identify_edges"], [113, 2, 1, "", "kroeger_core"], [114, 2, 1, "", "kroeger_core2"], [115, 2, 1, "", "list_all_edges"], [116, 2, 1, "", "lorentz"], [117, 2, 1, "", "make_cross_sections"], [118, 2, 1, "", "make_edges"], [119, 2, 1, "", "model3"], [120, 2, 1, "", "model_ll"], [121, 2, 1, "", "model_smooth"], [122, 2, 1, "", "plot_dispersion"], [123, 2, 1, "", "power_law"], [124, 2, 1, "", "power_law_background"], [125, 2, 1, "", "read_msa"], [126, 2, 1, "", "residuals_ll"], [127, 2, 1, "", "residuals_ll2"], [128, 2, 1, "", "residuals_smooth"], [129, 2, 1, "", "resolution_function"], [130, 2, 1, "", "resolution_function2"], [131, 2, 1, "", "second_derivative"], [132, 2, 1, "", "set_previous_quantification"], [133, 2, 1, "", "shift_on_same_scale"], [134, 2, 1, "", "sort_peaks"], [135, 2, 1, "", "xsec_xrpa"], [136, 2, 1, "", "zl"], [137, 2, 1, "", "zl_func"]], "pyTEMlib.file_tools": [[139, 1, 1, "", "ChooseDataset"], [140, 1, 1, "", "FileWidget"], [141, 2, 1, "", "add_dataset_from_file"], [142, 2, 1, "", "add_to_dict"], [143, 2, 1, "", "get_h5_filename"], [144, 2, 1, "", "get_last_path"], [145, 2, 1, "", "get_main_channel"], [146, 2, 1, "", "get_start_channel"], [147, 2, 1, "", "h5_add_crystal_structure"], [148, 2, 1, "", "h5_add_to_structure"], [149, 2, 1, "", "h5_get_crystal_structure"], [150, 2, 1, "", "h5_group_to_dict"], [151, 2, 1, "", "h5_tree"], [152, 2, 1, "", "log_results"], [153, 2, 1, "", "open_file"], [154, 2, 1, "", "open_file_dialog_qt"], [155, 2, 1, "", "read_cif"], [156, 2, 1, "", "read_dm3_info"], [157, 2, 1, "", "read_essential_metadata"], [158, 2, 1, "", "read_nion_image_info"], [159, 2, 1, "", "read_old_h5group"], [160, 2, 1, "", "read_poscar"], [161, 2, 1, "", "save_dataset"], [162, 2, 1, "", "save_dataset_dictionary"], [163, 2, 1, "", "save_file_dialog_qt"], [164, 2, 1, "", "save_path"], [165, 2, 1, "", "save_single_dataset"], [166, 2, 1, "", "set_dimensions"], [167, 2, 1, "", "update_directory_list"]], "pyTEMlib.file_tools.ChooseDataset": [[139, 5, 1, "", "get_dataset_list"]], "pyTEMlib.file_tools.FileWidget": [[140, 3, 1, "", "dir_name"], [140, 3, 1, "", "extension"], [140, 5, 1, "", "get_directory"], [140, 5, 1, "", "get_file_name"], [140, 5, 1, "", "set_options"]], "pyTEMlib.graph_tools": [[170, 2, 1, "", "breadth_first_search"], [171, 2, 1, "", "circum_center"], [172, 2, 1, "", "find_interstitial_clusters"], [173, 2, 1, "", "find_overlapping_spheres"], [174, 2, 1, "", "find_polyhedra"], [175, 2, 1, "", "get_bond_radii"], [176, 2, 1, "", "get_bonds"], [177, 2, 1, "", "get_connectivity_matrix"], [178, 2, 1, "", "get_distortion_matrix"], [179, 2, 1, "", "get_maximum_view"], [180, 2, 1, "", "get_non_periodic_supercell"], [181, 2, 1, "", "get_polygons"], [182, 2, 1, "", "get_significant_vertices"], [183, 2, 1, "", "get_voronoi"], [184, 2, 1, "", "interstitial_sphere_center"], [185, 2, 1, "", "make_polygons"], [186, 2, 1, "", "make_polyhedrons"], [187, 2, 1, "", "plot_atoms"], [188, 2, 1, "", "polygon_sort"], [189, 2, 1, "", "set_bond_radii"], [190, 2, 1, "", "sort_polyhedra_by_vertices"], [191, 2, 1, "", "transform_voronoi"], [192, 2, 1, "", "undistort"], [193, 2, 1, "", "undistort_sitk"], [194, 2, 1, "", "undistort_stack"], [195, 2, 1, "", "undistort_stack_sitk"], [196, 2, 1, "", "voronoi_volumes"]], "pyTEMlib.graph_viz": [[198, 2, 1, "", "get_boundary_polyhedra"], [199, 2, 1, "", "plot_bonds"], [200, 2, 1, "", "plot_polyhedron"], [201, 2, 1, "", "plot_super_cell"], [202, 2, 1, "", "plot_supercell"], [203, 2, 1, "", "plot_supercell_bonds"], [204, 2, 1, "", "plot_supercell_polyhedra"], [205, 2, 1, "", "plot_with_polyhedra"], [206, 2, 1, "", "show_polyhedra"]], "pyTEMlib.image_tools": [[210, 1, 1, "", "ImageWithLineProfile"], [211, 2, 1, "", "adaptive_fourier_filter"], [212, 2, 1, "", "align_crystal_reflections"], [213, 2, 1, "", "calculate_ctf"], [214, 2, 1, "", "calculate_scherzer"], [215, 2, 1, "", "calibrate_image_scale"], [216, 2, 1, "", "cart2pol"], [217, 2, 1, "", "cartesian2polar"], [218, 2, 1, "", "clean_svd"], [219, 2, 1, "", "complete_registration"], [220, 2, 1, "", "crop_image_stack"], [221, 2, 1, "", "decon_lr"], [222, 2, 1, "", "demon_registration"], [223, 2, 1, "", "diffractogram_spots"], [224, 2, 1, "", "fourier_transform"], [225, 2, 1, "", "get_rotation"], [226, 2, 1, "", "get_wavelength"], [227, 2, 1, "", "histogram_plot"], [228, 2, 1, "", "pol2cart"], [229, 2, 1, "", "power_spectrum"], [230, 2, 1, "", "rebin"], [231, 2, 1, "", "rig_reg_drift"], [232, 2, 1, "", "rigid_registration"], [233, 2, 1, "", "rotational_symmetry_diffractogram"], [234, 2, 1, "", "warp"], [235, 2, 1, "", "xy2polar"]], "pyTEMlib.image_tools.ImageWithLineProfile": [[210, 5, 1, "", "__call__"]], "pyTEMlib.info_dialog": [[237, 1, 1, "", "InfoWidget"], [238, 2, 1, "", "get_sidebar"]], "pyTEMlib.info_widget": [[241, 1, 1, "", "EELSWidget"], [242, 1, 1, "", "InfoWidget"], [243, 1, 1, "", "LowLossWidget"], [244, 2, 1, "", "get_info_sidebar"], [245, 2, 1, "", "get_low_loss_sidebar"]], "pyTEMlib.kinematic_scattering": [[249, 2, 1, "", "Zuo_fig_3_18"], [250, 2, 1, "", "check_sanity"], [251, 2, 1, "", "example"], [252, 2, 1, "", "feq"], [253, 2, 1, "", "find_angles"], [254, 2, 1, "", "find_nearest_zone_axis"], [255, 2, 1, "", "get_dynamically_allowed"], [256, 2, 1, "", "get_metric_tensor"], [257, 2, 1, "", "get_rotation_matrix"], [258, 2, 1, "", "get_wavelength"], [259, 2, 1, "", "kinematic_scattering"], [260, 2, 1, "", "kinematic_scattering2"], [261, 2, 1, "", "make_pretty_labels"], [262, 2, 1, "", "read_poscar"], [263, 2, 1, "", "ring_pattern_calculation"], [264, 2, 1, "", "scattering_matrix"], [265, 2, 1, "", "stage_rotation_matrix"], [266, 2, 1, "", "vector_norm"], [267, 2, 1, "", "zone_mistilt"]], "pyTEMlib.microscope": [[269, 1, 1, "", "Microscope"]], "pyTEMlib.peak_dialog": [[271, 1, 1, "", "PeakFitWidget"], [272, 2, 1, "", "get_sidebar"], [273, 2, 1, "", "smooth"]], "pyTEMlib.peak_dialog.PeakFitWidget": [[271, 5, 1, "", "fit_peaks"], [271, 5, 1, "", "smooth"]], "pyTEMlib.probe_tools": [[276, 2, 1, "", "get_chi"], [277, 2, 1, "", "get_chi_2"], [278, 2, 1, "", "get_d2chidu2"], [279, 2, 1, "", "get_d2chidudv"], [280, 2, 1, "", "get_d2chidv2"], [281, 2, 1, "", "get_ronchigram"], [282, 2, 1, "", "get_ronchigram_2"], [283, 2, 1, "", "get_source_energy_spread"], [284, 2, 1, "", "get_target_aberrations"], [285, 2, 1, "", "make_chi"], [286, 2, 1, "", "make_chi1"], [287, 2, 1, "", "make_gauss"], [288, 2, 1, "", "make_lorentz"], [289, 2, 1, "", "print_aberrations"], [290, 2, 1, "", "probe2"], [291, 2, 1, "", "zero_loss_peak_weight"]], "pyTEMlib.sidpy_tools": [[293, 1, 1, "", "ChooseDataset"], [294, 2, 1, "", "get_dimensions_by_order"], [295, 2, 1, "", "get_dimensions_by_type"], [296, 2, 1, "", "get_extent"], [297, 2, 1, "", "get_image_dims"], [298, 2, 1, "", "make_dummy_dataset"], [299, 2, 1, "", "plot"]], "pyTEMlib.sidpy_tools.ChooseDataset": [[293, 5, 1, "", "get_dataset_list"]], "pyTEMlib.simulation_tools": [[301, 2, 1, "", "exciting_get_spectra"], [302, 2, 1, "", "final_state_broadening"]], "pyTEMlib.viz": [[305, 1, 1, "", "CurveVisualizer"], [306, 1, 1, "", "SpectrumView"], [307, 2, 1, "", "find_edge_names"], [308, 2, 1, "", "plot"], [309, 2, 1, "", "plot_image"], [310, 2, 1, "", "plot_spectrum"], [311, 2, 1, "", "plot_stack"], [312, 2, 1, "", "spectrum_view_plotly"], [313, 2, 1, "", "verify_spectrum_dataset"]], "pyTEMlib.viz.SpectrumView": [[306, 5, 1, "", "initialize_edge"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:function", "3": "py:attribute", "4": "py:property", "5": "py:method"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "function", "Python function"], "3": ["py", "attribute", "Python attribute"], "4": ["py", "property", "Python property"], "5": ["py", "method", "Python method"]}, "titleterms": {"pytemlib": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 318, 319], "anim": [1, 2, 3, 4, 5, 6, 7, 8, 9], "interactiveaberr": 2, "interactiveronchigrammagnif": 3, "add_apertur": 4, "add_len": 5, "deficient_holz_lin": 6, "deficient_kikuchi_lin": 7, "geometric_ray_diagram": 8, "propagate_beam": 9, "atom_tool": [10, 11, 12, 13, 14, 15], "atom_refin": 11, "atoms_clust": 12, "find_atom": 13, "gauss_differ": 14, "intensity_area": 15, "config_dir": 16, "crystal_tool": [17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27], "atoms_from_dictionari": 18, "ball_and_stick": 19, "get_dictionari": 20, "get_project": 21, "get_symmetri": 22, "jmol_view": 23, "paramet": [23, 27, 39, 41, 42, 43, 46, 47, 111, 174, 176, 189, 198, 199, 200, 202, 203, 204, 205, 206, 211, 225, 230, 249, 258], "plot_super_cel": [24, 201], "plot_unit_cel": 25, "set_bond_radii": [26, 189], "structure_by_nam": 27, "diffraction_plot": [28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39], "cartesian2polar": [29, 217], "circl": 30, "plotcbed_paramet": 31, "plotholz_paramet": 32, "plotkikuchi": 33, "plotsaed_paramet": 34, "plot_diffraction_pattern": 35, "plot_reciprocal_unit_cell_2d": 36, "plot_ring_pattern": 37, "topolar": 38, "warp": [39, 234], "return": [39, 46, 187, 189, 249, 258], "dynamic_scatt": [40, 41, 42, 43, 44, 45, 46, 47, 48], "get_propag": 41, "get_transmiss": 42, "interaction_paramet": 43, "make_chi": [44, 285], "multi_slic": 45, "objective_lens_funct": 46, "potential_1dim": 47, "potential_2dim": 48, "eds_tool": [49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61], "detect_peak": 50, "detector_respons": 51, "find_el": 52, "fit_model": [53, 102], "gaussian": 54, "getfwhm": 55, "get_eds_cross_sect": 56, "get_eds_xsect": 57, "get_model": 58, "get_peak": 59, "get_x_ray_lin": 60, "update_fit_valu": 61, "eels_dialog": [62, 63, 64], "compositionwidget": 63, "get_sidebar": [64, 238, 272], "eels_dialog_util": [65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78], "edgesatcursor": 66, "elementaledg": 67, "interactivespectrumimag": 68, "attribut": 68, "periodictablewidget": 69, "rangeselector": 70, "regionselector": 71, "siplot": 72, "spectrumplot": 73, "get_likely_edg": 74, "get_periodic_table_info": 75, "get_periodic_table_widget": 76, "make_box_layout": 77, "plot_eel": 78, "eels_dlg": 79, "eels_tool": [80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 320], "add_element_to_dataset": 81, "add_peak": 82, "assign_likely_edg": 83, "auto_chemical_composit": 84, "auto_id_edg": 85, "cl_model": 86, "drude": 87, "drude2": 88, "drude_lorentz": 89, "drude_simul": 90, "effective_collection_angl": 91, "find_all_edg": 92, "find_associated_edg": 93, "find_edg": 94, "find_major_edg": 95, "find_maxima": 96, "find_peak": 97, "find_white_lin": 98, "fit_dataset": 99, "fit_edg": 100, "fit_edges2": 101, "fit_peak": 103, "fix_energy_scal": 104, "gauss": 105, "get_energy_shift": 106, "get_resolution_funct": 107, "get_spectrum_eels_db": 108, "get_wave_length": 109, "get_x_sect": 110, "get_z": 111, "identify_edg": 112, "kroeger_cor": 113, "kroeger_core2": 114, "list_all_edg": 115, "lorentz": 116, "make_cross_sect": 117, "make_edg": 118, "model3": 119, "model_l": 120, "model_smooth": 121, "plot_dispers": 122, "power_law": 123, "power_law_background": 124, "read_msa": 125, "residuals_l": 126, "residuals_ll2": 127, "residuals_smooth": 128, "resolution_funct": 129, "resolution_function2": 130, "second_deriv": 131, "set_previous_quantif": 132, "shift_on_same_scal": 133, "sort_peak": 134, "xsec_xrpa": 135, "zl": 136, "zl_func": 137, "file_tool": [138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167], "choosedataset": [139, 293], "filewidget": 140, "add_dataset_from_fil": 141, "add_to_dict": 142, "get_h5_filenam": 143, "get_last_path": 144, "get_main_channel": 145, "get_start_channel": 146, "h5_add_crystal_structur": 147, "h5_add_to_structur": 148, "h5_get_crystal_structur": 149, "h5_group_to_dict": 150, "h5_tree": 151, "log_result": 152, "open_fil": 153, "open_file_dialog_qt": 154, "read_cif": 155, "read_dm3_info": 156, "read_essential_metadata": 157, "read_nion_image_info": 158, "read_old_h5group": 159, "read_poscar": [160, 262], "save_dataset": 161, "save_dataset_dictionari": 162, "save_file_dialog_qt": 163, "save_path": 164, "save_single_dataset": 165, "set_dimens": 166, "update_directory_list": 167, "file_tools_qt": 168, "graph_tool": [169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197], "breadth_first_search": 170, "circum_cent": 171, "find_interstitial_clust": 172, "find_overlapping_spher": 173, "find_polyhedra": 174, "get_bond_radii": 175, "get_bond": 176, "get_connectivity_matrix": 177, "get_distortion_matrix": 178, "get_maximum_view": 179, "get_non_periodic_supercel": 180, "get_polygon": 181, "get_significant_vertic": 182, "get_voronoi": 183, "interstitial_sphere_cent": 184, "make_polygon": 185, "make_polyhedron": 186, "plot_atom": 187, "partamet": 187, "polygon_sort": 188, "sort_polyhedra_by_vertic": 190, "transform_voronoi": 191, "undistort": 192, "undistort_sitk": 193, "undistort_stack": 194, "undistort_stack_sitk": 195, "voronoi_volum": 196, "graph_viz": [197, 198, 199, 200, 201, 202, 203, 204, 205, 206], "plot": [197, 299, 308], "function": 197, "get_boundary_polyhedra": 198, "plot_bond": 199, "plot_polyhedron": 200, "plot_supercel": 202, "plot_supercell_bond": 203, "plot_supercell_polyhedra": 204, "plot_with_polyhedra": 205, "show_polyhedra": 206, "image_dialog": 207, "image_dlg": 208, "image_tool": [209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 321], "imagewithlineprofil": 210, "adaptive_fourier_filt": 211, "output": 211, "align_crystal_reflect": 212, "calculate_ctf": 213, "calculate_scherz": 214, "calibrate_image_scal": 215, "cart2pol": 216, "clean_svd": 218, "complete_registr": 219, "crop_image_stack": 220, "decon_lr": 221, "demon_registr": 222, "diffractogram_spot": 223, "fourier_transform": 224, "get_rot": 225, "get_wavelength": [226, 258], "histogram_plot": 227, "pol2cart": 228, "power_spectrum": 229, "rebin": 230, "rig_reg_drift": 231, "rigid_registr": 232, "rotational_symmetry_diffractogram": 233, "xy2polar": 235, "info_dialog": [236, 237, 238], "infowidget": [237, 242], "info_dlg": 239, "info_widget": [240, 241, 242, 243, 244, 245], "eelswidget": 241, "lowlosswidget": 243, "get_info_sidebar": 244, "get_low_loss_sidebar": 245, "interactive_eel": 246, "interactive_imag": 247, "kinematic_scatt": [248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267], "zuo_fig_3_18": 249, "check_san": 250, "exampl": [251, 318], "feq": 252, "find_angl": 253, "find_nearest_zone_axi": 254, "get_dynamically_allow": 255, "get_metric_tensor": 256, "get_rotation_matrix": 257, "kinematic_scattering2": 260, "make_pretty_label": 261, "ring_pattern_calcul": 263, "scattering_matrix": 264, "stage_rotation_matrix": 265, "vector_norm": 266, "zone_mistilt": 267, "microscop": [268, 269], "peak_dialog": [270, 271, 272, 273], "peakfitwidget": 271, "smooth": 273, "peak_dlg": 274, "probe_tool": [275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291], "get_chi": 276, "get_chi_2": 277, "get_d2chidu2": 278, "get_d2chidudv": 279, "get_d2chidv2": 280, "get_ronchigram": 281, "get_ronchigram_2": 282, "get_source_energy_spread": 283, "get_target_aberr": 284, "make_chi1": 286, "make_gauss": 287, "make_lorentz": 288, "print_aberr": 289, "probe2": 290, "zero_loss_peak_weight": 291, "sidpy_tool": [292, 293, 294, 295, 296, 297, 298, 299], "get_dimensions_by_ord": 294, "get_dimensions_by_typ": 295, "get_ext": 296, "get_image_dim": 297, "make_dummy_dataset": 298, "simulation_tool": [300, 301, 302], "exciting_get_spectra": 301, "final_state_broaden": 302, "version": 303, "viz": [304, 305, 306, 307, 308, 309, 310, 311, 312, 313], "curvevisu": 305, "spectrumview": 306, "find_edge_nam": 307, "plot_imag": 309, "plot_spectrum": 310, "plot_stack": 311, "spectrum_view_plotli": 312, "verify_spectrum_dataset": 313, "xrpa_x_sect": 314, "what": 315, "why": 315, "who": 315, "contact": 316, "u": 316, "credit": 317, "document": 318, "sourc": 318, "code": 318, "api": 318, "instal": 319, "prepar": 319, "compat": 319, "termin": 319, "from": 319, "specif": 319, "branch": 319, "advanc": 319, "user": 319, "onli": 319, "updat": 319, "other": 319, "softwar": 319, "revis": 322, "0": 322, "2021": 322, "3": 322, "1": 322}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.intersphinx": 1, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1, "sphinx": 58}, "alltitles": {"pyTEMlib": [[0, "module-pyTEMlib"], [315, "pytemlib"], [318, null]], "pyTEMlib.animation": [[1, "module-pyTEMlib.animation"]], "pyTEMlib.animation.InteractiveAberration": [[2, "pytemlib-animation-interactiveaberration"]], "pyTEMlib.animation.InteractiveRonchigramMagnification": [[3, "pytemlib-animation-interactiveronchigrammagnification"]], "pyTEMlib.animation.add_aperture": [[4, "pytemlib-animation-add-aperture"]], "pyTEMlib.animation.add_lens": [[5, "pytemlib-animation-add-lens"]], "pyTEMlib.animation.deficient_holz_line": [[6, "pytemlib-animation-deficient-holz-line"]], "pyTEMlib.animation.deficient_kikuchi_line": [[7, "pytemlib-animation-deficient-kikuchi-line"]], "pyTEMlib.animation.geometric_ray_diagram": [[8, "pytemlib-animation-geometric-ray-diagram"]], "pyTEMlib.animation.propagate_beam": [[9, "pytemlib-animation-propagate-beam"]], "pyTEMlib.atom_tools": [[10, "module-pyTEMlib.atom_tools"]], "pyTEMlib.atom_tools.atom_refine": [[11, "pytemlib-atom-tools-atom-refine"]], "pyTEMlib.atom_tools.atoms_clustering": [[12, "pytemlib-atom-tools-atoms-clustering"]], "pyTEMlib.atom_tools.find_atoms": [[13, "pytemlib-atom-tools-find-atoms"]], "pyTEMlib.atom_tools.gauss_difference": [[14, "pytemlib-atom-tools-gauss-difference"]], "pyTEMlib.atom_tools.intensity_area": [[15, "pytemlib-atom-tools-intensity-area"]], "pyTEMlib.config_dir": [[16, "module-pyTEMlib.config_dir"]], "pyTEMlib.crystal_tools": [[17, "module-pyTEMlib.crystal_tools"]], "pyTEMlib.crystal_tools.atoms_from_dictionary": [[18, "pytemlib-crystal-tools-atoms-from-dictionary"]], "pyTEMlib.crystal_tools.ball_and_stick": [[19, "pytemlib-crystal-tools-ball-and-stick"]], "pyTEMlib.crystal_tools.get_dictionary": [[20, "pytemlib-crystal-tools-get-dictionary"]], "pyTEMlib.crystal_tools.get_projection": [[21, "pytemlib-crystal-tools-get-projection"]], "pyTEMlib.crystal_tools.get_symmetry": [[22, "pytemlib-crystal-tools-get-symmetry"]], "pyTEMlib.crystal_tools.jmol_viewer": [[23, "pytemlib-crystal-tools-jmol-viewer"]], "Parameter": [[23, "parameter"], [27, "parameter"], [41, "parameter"], [42, "parameter"], [43, "parameter"], [47, "parameter"], [111, "parameter"], [174, "parameter"], [198, "parameter"], [199, "parameter"], [200, "parameter"], [202, "parameter"], [203, "parameter"], [204, "parameter"], [205, "parameter"], [206, "parameter"], [225, "parameter"], [230, "parameter"]], "pyTEMlib.crystal_tools.plot_super_cell": [[24, "pytemlib-crystal-tools-plot-super-cell"]], "pyTEMlib.crystal_tools.plot_unit_cell": [[25, "pytemlib-crystal-tools-plot-unit-cell"]], "pyTEMlib.crystal_tools.set_bond_radii": [[26, "pytemlib-crystal-tools-set-bond-radii"]], "pyTEMlib.crystal_tools.structure_by_name": [[27, "pytemlib-crystal-tools-structure-by-name"]], "pyTEMlib.diffraction_plot": [[28, "module-pyTEMlib.diffraction_plot"]], "pyTEMlib.diffraction_plot.cartesian2polar": [[29, "pytemlib-diffraction-plot-cartesian2polar"]], "pyTEMlib.diffraction_plot.circles": [[30, "pytemlib-diffraction-plot-circles"]], "pyTEMlib.diffraction_plot.plotCBED_parameter": [[31, "pytemlib-diffraction-plot-plotcbed-parameter"]], "pyTEMlib.diffraction_plot.plotHOLZ_parameter": [[32, "pytemlib-diffraction-plot-plotholz-parameter"]], "pyTEMlib.diffraction_plot.plotKikuchi": [[33, "pytemlib-diffraction-plot-plotkikuchi"]], "pyTEMlib.diffraction_plot.plotSAED_parameter": [[34, "pytemlib-diffraction-plot-plotsaed-parameter"]], "pyTEMlib.diffraction_plot.plot_diffraction_pattern": [[35, "pytemlib-diffraction-plot-plot-diffraction-pattern"]], "pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D": [[36, "pytemlib-diffraction-plot-plot-reciprocal-unit-cell-2d"]], "pyTEMlib.diffraction_plot.plot_ring_pattern": [[37, "pytemlib-diffraction-plot-plot-ring-pattern"]], "pyTEMlib.diffraction_plot.topolar": [[38, "pytemlib-diffraction-plot-topolar"]], "pyTEMlib.diffraction_plot.warp": [[39, "pytemlib-diffraction-plot-warp"]], "Parameter:": [[39, "parameter"], [46, "parameter"], [176, "parameter"], [189, "parameter"], [258, "parameter"]], "Return:": [[39, "return"], [189, "return"]], "pyTEMlib.dynamic_scattering": [[40, "module-pyTEMlib.dynamic_scattering"]], "pyTEMlib.dynamic_scattering.get_propagator": [[41, "pytemlib-dynamic-scattering-get-propagator"]], "pyTEMlib.dynamic_scattering.get_transmission": [[42, "pytemlib-dynamic-scattering-get-transmission"]], "pyTEMlib.dynamic_scattering.interaction_parameter": [[43, "pytemlib-dynamic-scattering-interaction-parameter"]], "pyTEMlib.dynamic_scattering.make_chi": [[44, "pytemlib-dynamic-scattering-make-chi"]], "pyTEMlib.dynamic_scattering.multi_slice": [[45, "pytemlib-dynamic-scattering-multi-slice"]], "pyTEMlib.dynamic_scattering.objective_lens_function": [[46, "pytemlib-dynamic-scattering-objective-lens-function"]], "Returns:": [[46, "returns"], [187, "returns"], [249, "returns"], [258, "returns"]], "pyTEMlib.dynamic_scattering.potential_1dim": [[47, "pytemlib-dynamic-scattering-potential-1dim"]], "pyTEMlib.dynamic_scattering.potential_2dim": [[48, "pytemlib-dynamic-scattering-potential-2dim"]], "pyTEMlib.eds_tools": [[49, "module-pyTEMlib.eds_tools"]], "pyTEMlib.eds_tools.detect_peaks": [[50, "pytemlib-eds-tools-detect-peaks"]], "pyTEMlib.eds_tools.detector_response": [[51, "pytemlib-eds-tools-detector-response"]], "pyTEMlib.eds_tools.find_elements": [[52, "pytemlib-eds-tools-find-elements"]], "pyTEMlib.eds_tools.fit_model": [[53, "pytemlib-eds-tools-fit-model"]], "pyTEMlib.eds_tools.gaussian": [[54, "pytemlib-eds-tools-gaussian"]], "pyTEMlib.eds_tools.getFWHM": [[55, "pytemlib-eds-tools-getfwhm"]], "pyTEMlib.eds_tools.get_eds_cross_sections": [[56, "pytemlib-eds-tools-get-eds-cross-sections"]], "pyTEMlib.eds_tools.get_eds_xsection": [[57, "pytemlib-eds-tools-get-eds-xsection"]], "pyTEMlib.eds_tools.get_model": [[58, "pytemlib-eds-tools-get-model"]], "pyTEMlib.eds_tools.get_peak": [[59, "pytemlib-eds-tools-get-peak"]], "pyTEMlib.eds_tools.get_x_ray_lines": [[60, "pytemlib-eds-tools-get-x-ray-lines"]], "pyTEMlib.eds_tools.update_fit_values": [[61, "pytemlib-eds-tools-update-fit-values"]], "pyTEMlib.eels_dialog": [[62, "module-pyTEMlib.eels_dialog"]], "pyTEMlib.eels_dialog.CompositionWidget": [[63, "pytemlib-eels-dialog-compositionwidget"]], "pyTEMlib.eels_dialog.get_sidebar": [[64, "pytemlib-eels-dialog-get-sidebar"]], "pyTEMlib.eels_dialog_utilities": [[65, "module-pyTEMlib.eels_dialog_utilities"]], "pyTEMlib.eels_dialog_utilities.EdgesAtCursor": [[66, "pytemlib-eels-dialog-utilities-edgesatcursor"]], "pyTEMlib.eels_dialog_utilities.ElementalEdges": [[67, "pytemlib-eels-dialog-utilities-elementaledges"]], "pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage": [[68, "pytemlib-eels-dialog-utilities-interactivespectrumimage"]], "Attributes:": [[68, "attributes"]], "pyTEMlib.eels_dialog_utilities.PeriodicTableWidget": [[69, "pytemlib-eels-dialog-utilities-periodictablewidget"]], "pyTEMlib.eels_dialog_utilities.RangeSelector": [[70, "pytemlib-eels-dialog-utilities-rangeselector"]], "pyTEMlib.eels_dialog_utilities.RegionSelector": [[71, "pytemlib-eels-dialog-utilities-regionselector"]], "pyTEMlib.eels_dialog_utilities.SIPlot": [[72, "pytemlib-eels-dialog-utilities-siplot"]], "pyTEMlib.eels_dialog_utilities.SpectrumPlot": [[73, "pytemlib-eels-dialog-utilities-spectrumplot"]], "pyTEMlib.eels_dialog_utilities.get_likely_edges": [[74, "pytemlib-eels-dialog-utilities-get-likely-edges"]], "pyTEMlib.eels_dialog_utilities.get_periodic_table_info": [[75, "pytemlib-eels-dialog-utilities-get-periodic-table-info"]], "pyTEMlib.eels_dialog_utilities.get_periodic_table_widget": [[76, "pytemlib-eels-dialog-utilities-get-periodic-table-widget"]], "pyTEMlib.eels_dialog_utilities.make_box_layout": [[77, "pytemlib-eels-dialog-utilities-make-box-layout"]], "pyTEMlib.eels_dialog_utilities.plot_EELS": [[78, "pytemlib-eels-dialog-utilities-plot-eels"]], "pyTEMlib.eels_dlg": [[79, "module-pyTEMlib.eels_dlg"]], "pyTEMlib.eels_tools": [[80, "module-pyTEMlib.eels_tools"]], "pyTEMlib.eels_tools.add_element_to_dataset": [[81, "pytemlib-eels-tools-add-element-to-dataset"]], "pyTEMlib.eels_tools.add_peaks": [[82, "pytemlib-eels-tools-add-peaks"]], "pyTEMlib.eels_tools.assign_likely_edges": [[83, "pytemlib-eels-tools-assign-likely-edges"]], "pyTEMlib.eels_tools.auto_chemical_composition": [[84, "pytemlib-eels-tools-auto-chemical-composition"]], "pyTEMlib.eels_tools.auto_id_edges": [[85, "pytemlib-eels-tools-auto-id-edges"]], "pyTEMlib.eels_tools.cl_model": [[86, "pytemlib-eels-tools-cl-model"]], "pyTEMlib.eels_tools.drude": [[87, "pytemlib-eels-tools-drude"]], "pyTEMlib.eels_tools.drude2": [[88, "pytemlib-eels-tools-drude2"]], "pyTEMlib.eels_tools.drude_lorentz": [[89, "pytemlib-eels-tools-drude-lorentz"]], "pyTEMlib.eels_tools.drude_simulation": [[90, "pytemlib-eels-tools-drude-simulation"]], "pyTEMlib.eels_tools.effective_collection_angle": [[91, "pytemlib-eels-tools-effective-collection-angle"]], "pyTEMlib.eels_tools.find_all_edges": [[92, "pytemlib-eels-tools-find-all-edges"]], "pyTEMlib.eels_tools.find_associated_edges": [[93, "pytemlib-eels-tools-find-associated-edges"]], "pyTEMlib.eels_tools.find_edges": [[94, "pytemlib-eels-tools-find-edges"]], "pyTEMlib.eels_tools.find_major_edges": [[95, "pytemlib-eels-tools-find-major-edges"]], "pyTEMlib.eels_tools.find_maxima": [[96, "pytemlib-eels-tools-find-maxima"]], "pyTEMlib.eels_tools.find_peaks": [[97, "pytemlib-eels-tools-find-peaks"]], "pyTEMlib.eels_tools.find_white_lines": [[98, "pytemlib-eels-tools-find-white-lines"]], "pyTEMlib.eels_tools.fit_dataset": [[99, "pytemlib-eels-tools-fit-dataset"]], "pyTEMlib.eels_tools.fit_edges": [[100, "pytemlib-eels-tools-fit-edges"]], "pyTEMlib.eels_tools.fit_edges2": [[101, "pytemlib-eels-tools-fit-edges2"]], "pyTEMlib.eels_tools.fit_model": [[102, "pytemlib-eels-tools-fit-model"]], "pyTEMlib.eels_tools.fit_peaks": [[103, "pytemlib-eels-tools-fit-peaks"]], "pyTEMlib.eels_tools.fix_energy_scale": [[104, "pytemlib-eels-tools-fix-energy-scale"]], "pyTEMlib.eels_tools.gauss": [[105, "pytemlib-eels-tools-gauss"]], "pyTEMlib.eels_tools.get_energy_shifts": [[106, "pytemlib-eels-tools-get-energy-shifts"]], "pyTEMlib.eels_tools.get_resolution_functions": [[107, "pytemlib-eels-tools-get-resolution-functions"]], "pyTEMlib.eels_tools.get_spectrum_eels_db": [[108, "pytemlib-eels-tools-get-spectrum-eels-db"]], "pyTEMlib.eels_tools.get_wave_length": [[109, "pytemlib-eels-tools-get-wave-length"]], "pyTEMlib.eels_tools.get_x_sections": [[110, "pytemlib-eels-tools-get-x-sections"]], "pyTEMlib.eels_tools.get_z": [[111, "pytemlib-eels-tools-get-z"]], "pyTEMlib.eels_tools.identify_edges": [[112, "pytemlib-eels-tools-identify-edges"]], "pyTEMlib.eels_tools.kroeger_core": [[113, "pytemlib-eels-tools-kroeger-core"]], "pyTEMlib.eels_tools.kroeger_core2": [[114, "pytemlib-eels-tools-kroeger-core2"]], "pyTEMlib.eels_tools.list_all_edges": [[115, "pytemlib-eels-tools-list-all-edges"]], "pyTEMlib.eels_tools.lorentz": [[116, "pytemlib-eels-tools-lorentz"]], "pyTEMlib.eels_tools.make_cross_sections": [[117, "pytemlib-eels-tools-make-cross-sections"]], "pyTEMlib.eels_tools.make_edges": [[118, "pytemlib-eels-tools-make-edges"]], "pyTEMlib.eels_tools.model3": [[119, "pytemlib-eels-tools-model3"]], "pyTEMlib.eels_tools.model_ll": [[120, "pytemlib-eels-tools-model-ll"]], "pyTEMlib.eels_tools.model_smooth": [[121, "pytemlib-eels-tools-model-smooth"]], "pyTEMlib.eels_tools.plot_dispersion": [[122, "pytemlib-eels-tools-plot-dispersion"]], "pyTEMlib.eels_tools.power_law": [[123, "pytemlib-eels-tools-power-law"]], "pyTEMlib.eels_tools.power_law_background": [[124, "pytemlib-eels-tools-power-law-background"]], "pyTEMlib.eels_tools.read_msa": [[125, "pytemlib-eels-tools-read-msa"]], "pyTEMlib.eels_tools.residuals_ll": [[126, "pytemlib-eels-tools-residuals-ll"]], "pyTEMlib.eels_tools.residuals_ll2": [[127, "pytemlib-eels-tools-residuals-ll2"]], "pyTEMlib.eels_tools.residuals_smooth": [[128, "pytemlib-eels-tools-residuals-smooth"]], "pyTEMlib.eels_tools.resolution_function": [[129, "pytemlib-eels-tools-resolution-function"]], "pyTEMlib.eels_tools.resolution_function2": [[130, "pytemlib-eels-tools-resolution-function2"]], "pyTEMlib.eels_tools.second_derivative": [[131, "pytemlib-eels-tools-second-derivative"]], "pyTEMlib.eels_tools.set_previous_quantification": [[132, "pytemlib-eels-tools-set-previous-quantification"]], "pyTEMlib.eels_tools.shift_on_same_scale": [[133, "pytemlib-eels-tools-shift-on-same-scale"]], "pyTEMlib.eels_tools.sort_peaks": [[134, "pytemlib-eels-tools-sort-peaks"]], "pyTEMlib.eels_tools.xsec_xrpa": [[135, "pytemlib-eels-tools-xsec-xrpa"]], "pyTEMlib.eels_tools.zl": [[136, "pytemlib-eels-tools-zl"]], "pyTEMlib.eels_tools.zl_func": [[137, "pytemlib-eels-tools-zl-func"]], "pyTEMlib.file_tools": [[138, "module-pyTEMlib.file_tools"]], "pyTEMlib.file_tools.ChooseDataset": [[139, "pytemlib-file-tools-choosedataset"]], "pyTEMlib.file_tools.FileWidget": [[140, "pytemlib-file-tools-filewidget"]], "pyTEMlib.file_tools.add_dataset_from_file": [[141, "pytemlib-file-tools-add-dataset-from-file"]], "pyTEMlib.file_tools.add_to_dict": [[142, "pytemlib-file-tools-add-to-dict"]], "pyTEMlib.file_tools.get_h5_filename": [[143, "pytemlib-file-tools-get-h5-filename"]], "pyTEMlib.file_tools.get_last_path": [[144, "pytemlib-file-tools-get-last-path"]], "pyTEMlib.file_tools.get_main_channel": [[145, "pytemlib-file-tools-get-main-channel"]], "pyTEMlib.file_tools.get_start_channel": [[146, "pytemlib-file-tools-get-start-channel"]], "pyTEMlib.file_tools.h5_add_crystal_structure": [[147, "pytemlib-file-tools-h5-add-crystal-structure"]], "pyTEMlib.file_tools.h5_add_to_structure": [[148, "pytemlib-file-tools-h5-add-to-structure"]], "pyTEMlib.file_tools.h5_get_crystal_structure": [[149, "pytemlib-file-tools-h5-get-crystal-structure"]], "pyTEMlib.file_tools.h5_group_to_dict": [[150, "pytemlib-file-tools-h5-group-to-dict"]], "pyTEMlib.file_tools.h5_tree": [[151, "pytemlib-file-tools-h5-tree"]], "pyTEMlib.file_tools.log_results": [[152, "pytemlib-file-tools-log-results"]], "pyTEMlib.file_tools.open_file": [[153, "pytemlib-file-tools-open-file"]], "pyTEMlib.file_tools.open_file_dialog_qt": [[154, "pytemlib-file-tools-open-file-dialog-qt"]], "pyTEMlib.file_tools.read_cif": [[155, "pytemlib-file-tools-read-cif"]], "pyTEMlib.file_tools.read_dm3_info": [[156, "pytemlib-file-tools-read-dm3-info"]], "pyTEMlib.file_tools.read_essential_metadata": [[157, "pytemlib-file-tools-read-essential-metadata"]], "pyTEMlib.file_tools.read_nion_image_info": [[158, "pytemlib-file-tools-read-nion-image-info"]], "pyTEMlib.file_tools.read_old_h5group": [[159, "pytemlib-file-tools-read-old-h5group"]], "pyTEMlib.file_tools.read_poscar": [[160, "pytemlib-file-tools-read-poscar"]], "pyTEMlib.file_tools.save_dataset": [[161, "pytemlib-file-tools-save-dataset"]], "pyTEMlib.file_tools.save_dataset_dictionary": [[162, "pytemlib-file-tools-save-dataset-dictionary"]], "pyTEMlib.file_tools.save_file_dialog_qt": [[163, "pytemlib-file-tools-save-file-dialog-qt"]], "pyTEMlib.file_tools.save_path": [[164, "pytemlib-file-tools-save-path"]], "pyTEMlib.file_tools.save_single_dataset": [[165, "pytemlib-file-tools-save-single-dataset"]], "pyTEMlib.file_tools.set_dimensions": [[166, "pytemlib-file-tools-set-dimensions"]], "pyTEMlib.file_tools.update_directory_list": [[167, "pytemlib-file-tools-update-directory-list"]], "pyTEMlib.file_tools_qt": [[168, "module-pyTEMlib.file_tools_qt"]], "pyTEMlib.graph_tools": [[169, "module-pyTEMlib.graph_tools"]], "pyTEMlib.graph_tools.breadth_first_search": [[170, "pytemlib-graph-tools-breadth-first-search"]], "pyTEMlib.graph_tools.circum_center": [[171, "pytemlib-graph-tools-circum-center"]], "pyTEMlib.graph_tools.find_interstitial_clusters": [[172, "pytemlib-graph-tools-find-interstitial-clusters"]], "pyTEMlib.graph_tools.find_overlapping_spheres": [[173, "pytemlib-graph-tools-find-overlapping-spheres"]], "pyTEMlib.graph_tools.find_polyhedra": [[174, "pytemlib-graph-tools-find-polyhedra"]], "pyTEMlib.graph_tools.get_bond_radii": [[175, "pytemlib-graph-tools-get-bond-radii"]], "pyTEMlib.graph_tools.get_bonds": [[176, "pytemlib-graph-tools-get-bonds"]], "pyTEMlib.graph_tools.get_connectivity_matrix": [[177, "pytemlib-graph-tools-get-connectivity-matrix"]], "pyTEMlib.graph_tools.get_distortion_matrix": [[178, "pytemlib-graph-tools-get-distortion-matrix"]], "pyTEMlib.graph_tools.get_maximum_view": [[179, "pytemlib-graph-tools-get-maximum-view"]], "pyTEMlib.graph_tools.get_non_periodic_supercell": [[180, "pytemlib-graph-tools-get-non-periodic-supercell"]], "pyTEMlib.graph_tools.get_polygons": [[181, "pytemlib-graph-tools-get-polygons"]], "pyTEMlib.graph_tools.get_significant_vertices": [[182, "pytemlib-graph-tools-get-significant-vertices"]], "pyTEMlib.graph_tools.get_voronoi": [[183, "pytemlib-graph-tools-get-voronoi"]], "pyTEMlib.graph_tools.interstitial_sphere_center": [[184, "pytemlib-graph-tools-interstitial-sphere-center"]], "pyTEMlib.graph_tools.make_polygons": [[185, "pytemlib-graph-tools-make-polygons"]], "pyTEMlib.graph_tools.make_polyhedrons": [[186, "pytemlib-graph-tools-make-polyhedrons"]], "pyTEMlib.graph_tools.plot_atoms": [[187, "pytemlib-graph-tools-plot-atoms"]], "Partameter:": [[187, "partameter"]], "pyTEMlib.graph_tools.polygon_sort": [[188, "pytemlib-graph-tools-polygon-sort"]], "pyTEMlib.graph_tools.set_bond_radii": [[189, "pytemlib-graph-tools-set-bond-radii"]], "pyTEMlib.graph_tools.sort_polyhedra_by_vertices": [[190, "pytemlib-graph-tools-sort-polyhedra-by-vertices"]], "pyTEMlib.graph_tools.transform_voronoi": [[191, "pytemlib-graph-tools-transform-voronoi"]], "pyTEMlib.graph_tools.undistort": [[192, "pytemlib-graph-tools-undistort"]], "pyTEMlib.graph_tools.undistort_sitk": [[193, "pytemlib-graph-tools-undistort-sitk"]], "pyTEMlib.graph_tools.undistort_stack": [[194, "pytemlib-graph-tools-undistort-stack"]], "pyTEMlib.graph_tools.undistort_stack_sitk": [[195, "pytemlib-graph-tools-undistort-stack-sitk"]], "pyTEMlib.graph_tools.voronoi_volumes": [[196, "pytemlib-graph-tools-voronoi-volumes"]], "pyTEMlib.graph_viz": [[197, "module-pyTEMlib.graph_viz"]], "# plotting functions for graph_tools": [[197, "plotting-functions-for-graph-tools"]], "pyTEMlib.graph_viz.get_boundary_polyhedra": [[198, "pytemlib-graph-viz-get-boundary-polyhedra"]], "pyTEMlib.graph_viz.plot_bonds": [[199, "pytemlib-graph-viz-plot-bonds"]], "pyTEMlib.graph_viz.plot_polyhedron": [[200, "pytemlib-graph-viz-plot-polyhedron"]], "pyTEMlib.graph_viz.plot_super_cell": [[201, "pytemlib-graph-viz-plot-super-cell"]], "pyTEMlib.graph_viz.plot_supercell": [[202, "pytemlib-graph-viz-plot-supercell"]], "pyTEMlib.graph_viz.plot_supercell_bonds": [[203, "pytemlib-graph-viz-plot-supercell-bonds"]], "pyTEMlib.graph_viz.plot_supercell_polyhedra": [[204, "pytemlib-graph-viz-plot-supercell-polyhedra"]], "pyTEMlib.graph_viz.plot_with_polyhedra": [[205, "pytemlib-graph-viz-plot-with-polyhedra"]], "pyTEMlib.graph_viz.show_polyhedra": [[206, "pytemlib-graph-viz-show-polyhedra"]], "pyTEMlib.image_dialog": [[207, "module-pyTEMlib.image_dialog"]], "pyTEMlib.image_dlg": [[208, "module-pyTEMlib.image_dlg"]], "pyTEMlib.image_tools": [[209, "module-pyTEMlib.image_tools"]], "pyTEMlib.image_tools.ImageWithLineProfile": [[210, "pytemlib-image-tools-imagewithlineprofile"]], "pyTEMlib.image_tools.adaptive_fourier_filter": [[211, "pytemlib-image-tools-adaptive-fourier-filter"]], "Parameters:": [[211, "parameters"], [249, "parameters"]], "Output:": [[211, "output"]], "pyTEMlib.image_tools.align_crystal_reflections": [[212, "pytemlib-image-tools-align-crystal-reflections"]], "pyTEMlib.image_tools.calculate_ctf": [[213, "pytemlib-image-tools-calculate-ctf"]], "pyTEMlib.image_tools.calculate_scherzer": [[214, "pytemlib-image-tools-calculate-scherzer"]], "pyTEMlib.image_tools.calibrate_image_scale": [[215, "pytemlib-image-tools-calibrate-image-scale"]], "pyTEMlib.image_tools.cart2pol": [[216, "pytemlib-image-tools-cart2pol"]], "pyTEMlib.image_tools.cartesian2polar": [[217, "pytemlib-image-tools-cartesian2polar"]], "pyTEMlib.image_tools.clean_svd": [[218, "pytemlib-image-tools-clean-svd"]], "pyTEMlib.image_tools.complete_registration": [[219, "pytemlib-image-tools-complete-registration"]], "pyTEMlib.image_tools.crop_image_stack": [[220, "pytemlib-image-tools-crop-image-stack"]], "pyTEMlib.image_tools.decon_lr": [[221, "pytemlib-image-tools-decon-lr"]], "pyTEMlib.image_tools.demon_registration": [[222, "pytemlib-image-tools-demon-registration"]], "pyTEMlib.image_tools.diffractogram_spots": [[223, "pytemlib-image-tools-diffractogram-spots"]], "pyTEMlib.image_tools.fourier_transform": [[224, "pytemlib-image-tools-fourier-transform"]], "pyTEMlib.image_tools.get_rotation": [[225, "pytemlib-image-tools-get-rotation"]], "pyTEMlib.image_tools.get_wavelength": [[226, "pytemlib-image-tools-get-wavelength"]], "pyTEMlib.image_tools.histogram_plot": [[227, "pytemlib-image-tools-histogram-plot"]], "pyTEMlib.image_tools.pol2cart": [[228, "pytemlib-image-tools-pol2cart"]], "pyTEMlib.image_tools.power_spectrum": [[229, "pytemlib-image-tools-power-spectrum"]], "pyTEMlib.image_tools.rebin": [[230, "pytemlib-image-tools-rebin"]], "pyTEMlib.image_tools.rig_reg_drift": [[231, "pytemlib-image-tools-rig-reg-drift"]], "pyTEMlib.image_tools.rigid_registration": [[232, "pytemlib-image-tools-rigid-registration"]], "pyTEMlib.image_tools.rotational_symmetry_diffractogram": [[233, "pytemlib-image-tools-rotational-symmetry-diffractogram"]], "pyTEMlib.image_tools.warp": [[234, "pytemlib-image-tools-warp"]], "pyTEMlib.image_tools.xy2polar": [[235, "pytemlib-image-tools-xy2polar"]], "pyTEMlib.info_dialog": [[236, "module-pyTEMlib.info_dialog"]], "pyTEMlib.info_dialog.InfoWidget": [[237, "pytemlib-info-dialog-infowidget"]], "pyTEMlib.info_dialog.get_sidebar": [[238, "pytemlib-info-dialog-get-sidebar"]], "pyTEMlib.info_dlg": [[239, "module-pyTEMlib.info_dlg"]], "pyTEMlib.info_widget": [[240, "module-pyTEMlib.info_widget"]], "pyTEMlib.info_widget.EELSWidget": [[241, "pytemlib-info-widget-eelswidget"]], "pyTEMlib.info_widget.InfoWidget": [[242, "pytemlib-info-widget-infowidget"]], "pyTEMlib.info_widget.LowLossWidget": [[243, "pytemlib-info-widget-lowlosswidget"]], "pyTEMlib.info_widget.get_info_sidebar": [[244, "pytemlib-info-widget-get-info-sidebar"]], "pyTEMlib.info_widget.get_low_loss_sidebar": [[245, "pytemlib-info-widget-get-low-loss-sidebar"]], "pyTEMlib.interactive_eels": [[246, "module-pyTEMlib.interactive_eels"]], "pyTEMlib.interactive_image": [[247, "module-pyTEMlib.interactive_image"]], "pyTEMlib.kinematic_scattering": [[248, "module-pyTEMlib.kinematic_scattering"]], "pyTEMlib.kinematic_scattering.Zuo_fig_3_18": [[249, "pytemlib-kinematic-scattering-zuo-fig-3-18"]], "pyTEMlib.kinematic_scattering.check_sanity": [[250, "pytemlib-kinematic-scattering-check-sanity"]], "pyTEMlib.kinematic_scattering.example": [[251, "pytemlib-kinematic-scattering-example"]], "pyTEMlib.kinematic_scattering.feq": [[252, "pytemlib-kinematic-scattering-feq"]], "pyTEMlib.kinematic_scattering.find_angles": [[253, "pytemlib-kinematic-scattering-find-angles"]], "pyTEMlib.kinematic_scattering.find_nearest_zone_axis": [[254, "pytemlib-kinematic-scattering-find-nearest-zone-axis"]], "pyTEMlib.kinematic_scattering.get_dynamically_allowed": [[255, "pytemlib-kinematic-scattering-get-dynamically-allowed"]], "pyTEMlib.kinematic_scattering.get_metric_tensor": [[256, "pytemlib-kinematic-scattering-get-metric-tensor"]], "pyTEMlib.kinematic_scattering.get_rotation_matrix": [[257, "pytemlib-kinematic-scattering-get-rotation-matrix"]], "pyTEMlib.kinematic_scattering.get_wavelength": [[258, "pytemlib-kinematic-scattering-get-wavelength"]], "pyTEMlib.kinematic_scattering.kinematic_scattering": [[259, "pytemlib-kinematic-scattering-kinematic-scattering"]], "pyTEMlib.kinematic_scattering.kinematic_scattering2": [[260, "pytemlib-kinematic-scattering-kinematic-scattering2"]], "pyTEMlib.kinematic_scattering.make_pretty_labels": [[261, "pytemlib-kinematic-scattering-make-pretty-labels"]], "pyTEMlib.kinematic_scattering.read_poscar": [[262, "pytemlib-kinematic-scattering-read-poscar"]], "pyTEMlib.kinematic_scattering.ring_pattern_calculation": [[263, "pytemlib-kinematic-scattering-ring-pattern-calculation"]], "pyTEMlib.kinematic_scattering.scattering_matrix": [[264, "pytemlib-kinematic-scattering-scattering-matrix"]], "pyTEMlib.kinematic_scattering.stage_rotation_matrix": [[265, "pytemlib-kinematic-scattering-stage-rotation-matrix"]], "pyTEMlib.kinematic_scattering.vector_norm": [[266, "pytemlib-kinematic-scattering-vector-norm"]], "pyTEMlib.kinematic_scattering.zone_mistilt": [[267, "pytemlib-kinematic-scattering-zone-mistilt"]], "pyTEMlib.microscope": [[268, "module-pyTEMlib.microscope"]], "pyTEMlib.microscope.Microscope": [[269, "pytemlib-microscope-microscope"]], "pyTEMlib.peak_dialog": [[270, "module-pyTEMlib.peak_dialog"]], "pyTEMlib.peak_dialog.PeakFitWidget": [[271, "pytemlib-peak-dialog-peakfitwidget"]], "pyTEMlib.peak_dialog.get_sidebar": [[272, "pytemlib-peak-dialog-get-sidebar"]], "pyTEMlib.peak_dialog.smooth": [[273, "pytemlib-peak-dialog-smooth"]], "pyTEMlib.peak_dlg": [[274, "module-pyTEMlib.peak_dlg"]], "pyTEMlib.probe_tools": [[275, "module-pyTEMlib.probe_tools"]], "pyTEMlib.probe_tools.get_chi": [[276, "pytemlib-probe-tools-get-chi"]], "pyTEMlib.probe_tools.get_chi_2": [[277, "pytemlib-probe-tools-get-chi-2"]], "pyTEMlib.probe_tools.get_d2chidu2": [[278, "pytemlib-probe-tools-get-d2chidu2"]], "pyTEMlib.probe_tools.get_d2chidudv": [[279, "pytemlib-probe-tools-get-d2chidudv"]], "pyTEMlib.probe_tools.get_d2chidv2": [[280, "pytemlib-probe-tools-get-d2chidv2"]], "pyTEMlib.probe_tools.get_ronchigram": [[281, "pytemlib-probe-tools-get-ronchigram"]], "pyTEMlib.probe_tools.get_ronchigram_2": [[282, "pytemlib-probe-tools-get-ronchigram-2"]], "pyTEMlib.probe_tools.get_source_energy_spread": [[283, "pytemlib-probe-tools-get-source-energy-spread"]], "pyTEMlib.probe_tools.get_target_aberrations": [[284, "pytemlib-probe-tools-get-target-aberrations"]], "pyTEMlib.probe_tools.make_chi": [[285, "pytemlib-probe-tools-make-chi"]], "pyTEMlib.probe_tools.make_chi1": [[286, "pytemlib-probe-tools-make-chi1"]], "pyTEMlib.probe_tools.make_gauss": [[287, "pytemlib-probe-tools-make-gauss"]], "pyTEMlib.probe_tools.make_lorentz": [[288, "pytemlib-probe-tools-make-lorentz"]], "pyTEMlib.probe_tools.print_aberrations": [[289, "pytemlib-probe-tools-print-aberrations"]], "pyTEMlib.probe_tools.probe2": [[290, "pytemlib-probe-tools-probe2"]], "pyTEMlib.probe_tools.zero_loss_peak_weight": [[291, "pytemlib-probe-tools-zero-loss-peak-weight"]], "pyTEMlib.sidpy_tools": [[292, "module-pyTEMlib.sidpy_tools"]], "pyTEMlib.sidpy_tools.ChooseDataset": [[293, "pytemlib-sidpy-tools-choosedataset"]], "pyTEMlib.sidpy_tools.get_dimensions_by_order": [[294, "pytemlib-sidpy-tools-get-dimensions-by-order"]], "pyTEMlib.sidpy_tools.get_dimensions_by_type": [[295, "pytemlib-sidpy-tools-get-dimensions-by-type"]], "pyTEMlib.sidpy_tools.get_extent": [[296, "pytemlib-sidpy-tools-get-extent"]], "pyTEMlib.sidpy_tools.get_image_dims": [[297, "pytemlib-sidpy-tools-get-image-dims"]], "pyTEMlib.sidpy_tools.make_dummy_dataset": [[298, "pytemlib-sidpy-tools-make-dummy-dataset"]], "pyTEMlib.sidpy_tools.plot": [[299, "pytemlib-sidpy-tools-plot"]], "pyTEMlib.simulation_tools": [[300, "module-pyTEMlib.simulation_tools"]], "pyTEMlib.simulation_tools.exciting_get_spectra": [[301, "pytemlib-simulation-tools-exciting-get-spectra"]], "pyTEMlib.simulation_tools.final_state_broadening": [[302, "pytemlib-simulation-tools-final-state-broadening"]], "pyTEMlib.version": [[303, "module-pyTEMlib.version"]], "pyTEMlib.viz": [[304, "module-pyTEMlib.viz"]], "pyTEMlib.viz.CurveVisualizer": [[305, "pytemlib-viz-curvevisualizer"]], "pyTEMlib.viz.SpectrumView": [[306, "pytemlib-viz-spectrumview"]], "pyTEMlib.viz.find_edge_names": [[307, "pytemlib-viz-find-edge-names"]], "pyTEMlib.viz.plot": [[308, "pytemlib-viz-plot"]], "pyTEMlib.viz.plot_image": [[309, "pytemlib-viz-plot-image"]], "pyTEMlib.viz.plot_spectrum": [[310, "pytemlib-viz-plot-spectrum"]], "pyTEMlib.viz.plot_stack": [[311, "pytemlib-viz-plot-stack"]], "pyTEMlib.viz.spectrum_view_plotly": [[312, "pytemlib-viz-spectrum-view-plotly"]], "pyTEMlib.viz.verify_spectrum_dataset": [[313, "pytemlib-viz-verify-spectrum-dataset"]], "pyTEMlib.xrpa_x_sections": [[314, "module-pyTEMlib.xrpa_x_sections"]], "What?": [[315, "what"]], "Why?": [[315, "why"]], "Who?": [[315, "who"]], "Contact us": [[316, "contact-us"]], "Credits": [[317, "credits"]], "pyTEMlib Documentation": [[318, "pytemlib-documentation"]], "Source code API": [[318, "source-code-api"]], "Examples": [[318, null]], "Installation": [[319, "installation"]], "Preparing for pyTEMlib": [[319, "preparing-for-pytemlib"]], "Compatibility": [[319, "compatibility"]], "Terminal": [[319, "terminal"]], "Installing pyTEMlib": [[319, "installing-pytemlib"]], "Installing from a specific branch (advanced users ONLY)": [[319, "installing-from-a-specific-branch-advanced-users-only"]], "Updating pyTEMlib": [[319, "updating-pytemlib"]], "Other software": [[319, "other-software"]], "EELS_tools": [[320, "eels-tools"]], "Image_tools": [[321, "image-tools"]], "Revisions": [[322, "revisions"]], "Revision 0.2021.3.1": [[322, "revision-0-2021-3-1"]]}, "indexentries": {"module": [[0, "module-pyTEMlib"], [1, "module-pyTEMlib.animation"], [10, "module-pyTEMlib.atom_tools"], [16, "module-pyTEMlib.config_dir"], [17, "module-pyTEMlib.crystal_tools"], [28, "module-pyTEMlib.diffraction_plot"], [40, "module-pyTEMlib.dynamic_scattering"], [49, "module-pyTEMlib.eds_tools"], [62, "module-pyTEMlib.eels_dialog"], [65, "module-pyTEMlib.eels_dialog_utilities"], [79, "module-pyTEMlib.eels_dlg"], [80, "module-pyTEMlib.eels_tools"], [138, "module-pyTEMlib.file_tools"], [168, "module-pyTEMlib.file_tools_qt"], [169, "module-pyTEMlib.graph_tools"], [197, "module-pyTEMlib.graph_viz"], [207, "module-pyTEMlib.image_dialog"], [208, "module-pyTEMlib.image_dlg"], [209, "module-pyTEMlib.image_tools"], [236, "module-pyTEMlib.info_dialog"], [239, "module-pyTEMlib.info_dlg"], [240, "module-pyTEMlib.info_widget"], [246, "module-pyTEMlib.interactive_eels"], [247, "module-pyTEMlib.interactive_image"], [248, "module-pyTEMlib.kinematic_scattering"], [268, "module-pyTEMlib.microscope"], [270, "module-pyTEMlib.peak_dialog"], [274, "module-pyTEMlib.peak_dlg"], [275, "module-pyTEMlib.probe_tools"], [292, "module-pyTEMlib.sidpy_tools"], [300, "module-pyTEMlib.simulation_tools"], [303, "module-pyTEMlib.version"], [304, "module-pyTEMlib.viz"], [314, "module-pyTEMlib.xrpa_x_sections"]], "pytemlib": [[0, "module-pyTEMlib"]], "pytemlib.animation": [[1, "module-pyTEMlib.animation"]], "interactiveaberration (class in pytemlib.animation)": [[2, "pyTEMlib.animation.InteractiveAberration"]], "interactiveronchigrammagnification (class in pytemlib.animation)": [[3, "pyTEMlib.animation.InteractiveRonchigramMagnification"]], "add_aperture() (in module pytemlib.animation)": [[4, "pyTEMlib.animation.add_aperture"]], "add_lens() (in module pytemlib.animation)": [[5, "pyTEMlib.animation.add_lens"]], "deficient_holz_line() (in module pytemlib.animation)": [[6, "pyTEMlib.animation.deficient_holz_line"]], "deficient_kikuchi_line() (in module pytemlib.animation)": [[7, "pyTEMlib.animation.deficient_kikuchi_line"]], "geometric_ray_diagram() (in module pytemlib.animation)": [[8, "pyTEMlib.animation.geometric_ray_diagram"]], "propagate_beam() (in module pytemlib.animation)": [[9, "pyTEMlib.animation.propagate_beam"]], "pytemlib.atom_tools": [[10, "module-pyTEMlib.atom_tools"]], "atom_refine() (in module pytemlib.atom_tools)": [[11, "pyTEMlib.atom_tools.atom_refine"]], "atoms_clustering() (in module pytemlib.atom_tools)": [[12, "pyTEMlib.atom_tools.atoms_clustering"]], "find_atoms() (in module pytemlib.atom_tools)": [[13, "pyTEMlib.atom_tools.find_atoms"]], "gauss_difference() (in module pytemlib.atom_tools)": [[14, "pyTEMlib.atom_tools.gauss_difference"]], "intensity_area() (in module pytemlib.atom_tools)": [[15, "pyTEMlib.atom_tools.intensity_area"]], "pytemlib.config_dir": [[16, "module-pyTEMlib.config_dir"]], "pytemlib.crystal_tools": [[17, "module-pyTEMlib.crystal_tools"]], "atoms_from_dictionary() (in module pytemlib.crystal_tools)": [[18, "pyTEMlib.crystal_tools.atoms_from_dictionary"]], "ball_and_stick() (in module pytemlib.crystal_tools)": [[19, "pyTEMlib.crystal_tools.ball_and_stick"]], "get_dictionary() (in module pytemlib.crystal_tools)": [[20, "pyTEMlib.crystal_tools.get_dictionary"]], "get_projection() (in module pytemlib.crystal_tools)": [[21, "pyTEMlib.crystal_tools.get_projection"]], "get_symmetry() (in module pytemlib.crystal_tools)": [[22, "pyTEMlib.crystal_tools.get_symmetry"]], "jmol_viewer() (in module pytemlib.crystal_tools)": [[23, "pyTEMlib.crystal_tools.jmol_viewer"]], "plot_super_cell() (in module pytemlib.crystal_tools)": [[24, "pyTEMlib.crystal_tools.plot_super_cell"]], "plot_unit_cell() (in module pytemlib.crystal_tools)": [[25, "pyTEMlib.crystal_tools.plot_unit_cell"]], "set_bond_radii() (in module pytemlib.crystal_tools)": [[26, "pyTEMlib.crystal_tools.set_bond_radii"]], "structure_by_name() (in module pytemlib.crystal_tools)": [[27, "pyTEMlib.crystal_tools.structure_by_name"]], "pytemlib.diffraction_plot": [[28, "module-pyTEMlib.diffraction_plot"]], "cartesian2polar() (in module pytemlib.diffraction_plot)": [[29, "pyTEMlib.diffraction_plot.cartesian2polar"]], "circles() (in module pytemlib.diffraction_plot)": [[30, "pyTEMlib.diffraction_plot.circles"]], "plotcbed_parameter() (in module pytemlib.diffraction_plot)": [[31, "pyTEMlib.diffraction_plot.plotCBED_parameter"]], "plotholz_parameter() (in module pytemlib.diffraction_plot)": [[32, "pyTEMlib.diffraction_plot.plotHOLZ_parameter"]], "plotkikuchi() (in module pytemlib.diffraction_plot)": [[33, "pyTEMlib.diffraction_plot.plotKikuchi"]], "plotsaed_parameter() (in module pytemlib.diffraction_plot)": [[34, "pyTEMlib.diffraction_plot.plotSAED_parameter"]], "plot_diffraction_pattern() (in module pytemlib.diffraction_plot)": [[35, "pyTEMlib.diffraction_plot.plot_diffraction_pattern"]], "plot_reciprocal_unit_cell_2d() (in module pytemlib.diffraction_plot)": [[36, "pyTEMlib.diffraction_plot.plot_reciprocal_unit_cell_2D"]], "plot_ring_pattern() (in module pytemlib.diffraction_plot)": [[37, "pyTEMlib.diffraction_plot.plot_ring_pattern"]], "topolar() (in module pytemlib.diffraction_plot)": [[38, "pyTEMlib.diffraction_plot.topolar"]], "warp() (in module pytemlib.diffraction_plot)": [[39, "pyTEMlib.diffraction_plot.warp"]], "pytemlib.dynamic_scattering": [[40, "module-pyTEMlib.dynamic_scattering"]], "get_propagator() (in module pytemlib.dynamic_scattering)": [[41, "pyTEMlib.dynamic_scattering.get_propagator"]], "get_transmission() (in module pytemlib.dynamic_scattering)": [[42, "pyTEMlib.dynamic_scattering.get_transmission"]], "interaction_parameter() (in module pytemlib.dynamic_scattering)": [[43, "pyTEMlib.dynamic_scattering.interaction_parameter"]], "make_chi() (in module pytemlib.dynamic_scattering)": [[44, "pyTEMlib.dynamic_scattering.make_chi"]], "multi_slice() (in module pytemlib.dynamic_scattering)": [[45, "pyTEMlib.dynamic_scattering.multi_slice"]], "objective_lens_function() (in module pytemlib.dynamic_scattering)": [[46, "pyTEMlib.dynamic_scattering.objective_lens_function"]], "potential_1dim() (in module pytemlib.dynamic_scattering)": [[47, "pyTEMlib.dynamic_scattering.potential_1dim"]], "potential_2dim() (in module pytemlib.dynamic_scattering)": [[48, "pyTEMlib.dynamic_scattering.potential_2dim"]], "pytemlib.eds_tools": [[49, "module-pyTEMlib.eds_tools"]], "detect_peaks() (in module pytemlib.eds_tools)": [[50, "pyTEMlib.eds_tools.detect_peaks"]], "detector_response() (in module pytemlib.eds_tools)": [[51, "pyTEMlib.eds_tools.detector_response"]], "find_elements() (in module pytemlib.eds_tools)": [[52, "pyTEMlib.eds_tools.find_elements"]], "fit_model() (in module pytemlib.eds_tools)": [[53, "pyTEMlib.eds_tools.fit_model"]], "gaussian() (in module pytemlib.eds_tools)": [[54, "pyTEMlib.eds_tools.gaussian"]], "getfwhm() (in module pytemlib.eds_tools)": [[55, "pyTEMlib.eds_tools.getFWHM"]], "get_eds_cross_sections() (in module pytemlib.eds_tools)": [[56, "pyTEMlib.eds_tools.get_eds_cross_sections"]], "get_eds_xsection() (in module pytemlib.eds_tools)": [[57, "pyTEMlib.eds_tools.get_eds_xsection"]], "get_model() (in module pytemlib.eds_tools)": [[58, "pyTEMlib.eds_tools.get_model"]], "get_peak() (in module pytemlib.eds_tools)": [[59, "pyTEMlib.eds_tools.get_peak"]], "get_x_ray_lines() (in module pytemlib.eds_tools)": [[60, "pyTEMlib.eds_tools.get_x_ray_lines"]], "update_fit_values() (in module pytemlib.eds_tools)": [[61, "pyTEMlib.eds_tools.update_fit_values"]], "pytemlib.eels_dialog": [[62, "module-pyTEMlib.eels_dialog"]], "compositionwidget (class in pytemlib.eels_dialog)": [[63, "pyTEMlib.eels_dialog.CompositionWidget"]], "get_sidebar() (in module pytemlib.eels_dialog)": [[64, "pyTEMlib.eels_dialog.get_sidebar"]], "pytemlib.eels_dialog_utilities": [[65, "module-pyTEMlib.eels_dialog_utilities"]], "edgesatcursor (class in pytemlib.eels_dialog_utilities)": [[66, "pyTEMlib.eels_dialog_utilities.EdgesAtCursor"]], "ax (pytemlib.eels_dialog_utilities.edgesatcursor attribute)": [[66, "pyTEMlib.eels_dialog_utilities.EdgesAtCursor.ax"]], "maximal_chemical_shift (pytemlib.eels_dialog_utilities.edgesatcursor attribute)": [[66, "pyTEMlib.eels_dialog_utilities.EdgesAtCursor.maximal_chemical_shift"]], "x (pytemlib.eels_dialog_utilities.edgesatcursor attribute)": [[66, "pyTEMlib.eels_dialog_utilities.EdgesAtCursor.x"]], "y (pytemlib.eels_dialog_utilities.edgesatcursor attribute)": [[66, "pyTEMlib.eels_dialog_utilities.EdgesAtCursor.y"]], "elementaledges (class in pytemlib.eels_dialog_utilities)": [[67, "pyTEMlib.eels_dialog_utilities.ElementalEdges"]], "interactivespectrumimage (class in pytemlib.eels_dialog_utilities)": [[68, "pyTEMlib.eels_dialog_utilities.InteractiveSpectrumImage"]], "periodictablewidget (class in pytemlib.eels_dialog_utilities)": [[69, "pyTEMlib.eels_dialog_utilities.PeriodicTableWidget"]], "rangeselector (class in pytemlib.eels_dialog_utilities)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector"]], "active (pytemlib.eels_dialog_utilities.rangeselector property)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.active"]], "add_state() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.add_state"]], "artists (pytemlib.eels_dialog_utilities.rangeselector property)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.artists"]], "center (pytemlib.eels_dialog_utilities.rangeselector property)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.center"]], "clear() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.clear"]], "connect_default_events() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.connect_default_events"]], "connect_event() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.connect_event"]], "corners (pytemlib.eels_dialog_utilities.rangeselector property)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.corners"]], "disconnect_events() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.disconnect_events"]], "edge_centers (pytemlib.eels_dialog_utilities.rangeselector property)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.edge_centers"]], "extents (pytemlib.eels_dialog_utilities.rangeselector property)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.extents"]], "geometry (pytemlib.eels_dialog_utilities.rangeselector property)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.geometry"]], "get_active() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.get_active"]], "get_visible() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.get_visible"]], "ignore() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.ignore"]], "on_key_press() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.on_key_press"]], "on_key_release() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.on_key_release"]], "on_scroll() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.on_scroll"]], "onmove() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.onmove"]], "press() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.press"]], "release() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.release"]], "remove_state() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.remove_state"]], "rotation (pytemlib.eels_dialog_utilities.rangeselector property)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.rotation"]], "set_active() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.set_active"]], "set_handle_props() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.set_handle_props"]], "set_props() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.set_props"]], "set_visible() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.set_visible"]], "update() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.update"]], "update_background() (pytemlib.eels_dialog_utilities.rangeselector method)": [[70, "pyTEMlib.eels_dialog_utilities.RangeSelector.update_background"]], "regionselector (class in pytemlib.eels_dialog_utilities)": [[71, "pyTEMlib.eels_dialog_utilities.RegionSelector"]], "siplot (class in pytemlib.eels_dialog_utilities)": [[72, "pyTEMlib.eels_dialog_utilities.SIPlot"]], "spectrumplot (class in pytemlib.eels_dialog_utilities)": [[73, "pyTEMlib.eels_dialog_utilities.SpectrumPlot"]], "get_likely_edges() (in module pytemlib.eels_dialog_utilities)": [[74, "pyTEMlib.eels_dialog_utilities.get_likely_edges"]], "get_periodic_table_info() (in module pytemlib.eels_dialog_utilities)": [[75, "pyTEMlib.eels_dialog_utilities.get_periodic_table_info"]], "get_periodic_table_widget() (in module pytemlib.eels_dialog_utilities)": [[76, "pyTEMlib.eels_dialog_utilities.get_periodic_table_widget"]], "make_box_layout() (in module pytemlib.eels_dialog_utilities)": [[77, "pyTEMlib.eels_dialog_utilities.make_box_layout"]], "__del__() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.__del__"]], "add_class() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.add_class"]], "add_traits() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.add_traits"]], "blur() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.blur"]], "box_style (pytemlib.eels_dialog_utilities.plot_eels attribute)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.box_style"]], "children (pytemlib.eels_dialog_utilities.plot_eels attribute)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.children"]], "class_own_trait_events() (pytemlib.eels_dialog_utilities.plot_eels class method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.class_own_trait_events"]], "class_own_traits() (pytemlib.eels_dialog_utilities.plot_eels class method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.class_own_traits"]], "class_trait_names() (pytemlib.eels_dialog_utilities.plot_eels class method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.class_trait_names"]], "class_traits() (pytemlib.eels_dialog_utilities.plot_eels class method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.class_traits"]], "close() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.close"]], "cross_validation_lock (pytemlib.eels_dialog_utilities.plot_eels property)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.cross_validation_lock"]], "focus() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.focus"]], "get_manager_state() (pytemlib.eels_dialog_utilities.plot_eels static method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.get_manager_state"]], "get_state() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.get_state"]], "handle_comm_opened() (pytemlib.eels_dialog_utilities.plot_eels static method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.handle_comm_opened"]], "handle_control_comm_opened() (pytemlib.eels_dialog_utilities.plot_eels class method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.handle_control_comm_opened"]], "has_trait() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.has_trait"]], "hold_sync() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.hold_sync"]], "hold_trait_notifications() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.hold_trait_notifications"]], "keys (pytemlib.eels_dialog_utilities.plot_eels attribute)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.keys"]], "model_id (pytemlib.eels_dialog_utilities.plot_eels property)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.model_id"]], "notify_change() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.notify_change"]], "observe() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.observe"]], "on_msg() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.on_msg"]], "on_trait_change() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.on_trait_change"]], "on_widget_constructed() (pytemlib.eels_dialog_utilities.plot_eels static method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.on_widget_constructed"]], "open() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.open"]], "plot_eels (class in pytemlib.eels_dialog_utilities)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS"]], "remove_class() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.remove_class"]], "send() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.send"]], "send_state() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.send_state"]], "set_state() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.set_state"]], "set_trait() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.set_trait"]], "setup_instance() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.setup_instance"]], "tabbable (pytemlib.eels_dialog_utilities.plot_eels attribute)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.tabbable"]], "tooltip (pytemlib.eels_dialog_utilities.plot_eels attribute)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.tooltip"]], "trait_defaults() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.trait_defaults"]], "trait_events() (pytemlib.eels_dialog_utilities.plot_eels class method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.trait_events"]], "trait_has_value() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.trait_has_value"]], "trait_metadata() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.trait_metadata"]], "trait_names() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.trait_names"]], "trait_values() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.trait_values"]], "traits() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.traits"]], "unobserve() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.unobserve"]], "unobserve_all() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.unobserve_all"]], "update() (pytemlib.eels_dialog_utilities.plot_eels method)": [[78, "pyTEMlib.eels_dialog_utilities.plot_EELS.update"]], "pytemlib.eels_dlg": [[79, "module-pyTEMlib.eels_dlg"]], "pytemlib.eels_tools": [[80, "module-pyTEMlib.eels_tools"]], "add_element_to_dataset() (in module pytemlib.eels_tools)": [[81, "pyTEMlib.eels_tools.add_element_to_dataset"]], "add_peaks() (in module pytemlib.eels_tools)": [[82, "pyTEMlib.eels_tools.add_peaks"]], "assign_likely_edges() (in module pytemlib.eels_tools)": [[83, "pyTEMlib.eels_tools.assign_likely_edges"]], "auto_chemical_composition() (in module pytemlib.eels_tools)": [[84, "pyTEMlib.eels_tools.auto_chemical_composition"]], "auto_id_edges() (in module pytemlib.eels_tools)": [[85, "pyTEMlib.eels_tools.auto_id_edges"]], "cl_model() (in module pytemlib.eels_tools)": [[86, "pyTEMlib.eels_tools.cl_model"]], "drude() (in module pytemlib.eels_tools)": [[87, "pyTEMlib.eels_tools.drude"]], "drude2() (in module pytemlib.eels_tools)": [[88, "pyTEMlib.eels_tools.drude2"]], "drude_lorentz() (in module pytemlib.eels_tools)": [[89, "pyTEMlib.eels_tools.drude_lorentz"]], "drude_simulation() (in module pytemlib.eels_tools)": [[90, "pyTEMlib.eels_tools.drude_simulation"]], "effective_collection_angle() (in module pytemlib.eels_tools)": [[91, "pyTEMlib.eels_tools.effective_collection_angle"]], "find_all_edges() (in module pytemlib.eels_tools)": [[92, "pyTEMlib.eels_tools.find_all_edges"]], "find_associated_edges() (in module pytemlib.eels_tools)": [[93, "pyTEMlib.eels_tools.find_associated_edges"]], "find_edges() (in module pytemlib.eels_tools)": [[94, "pyTEMlib.eels_tools.find_edges"]], "find_major_edges() (in module pytemlib.eels_tools)": [[95, "pyTEMlib.eels_tools.find_major_edges"]], "find_maxima() (in module pytemlib.eels_tools)": [[96, "pyTEMlib.eels_tools.find_maxima"]], "find_peaks() (in module pytemlib.eels_tools)": [[97, "pyTEMlib.eels_tools.find_peaks"]], "find_white_lines() (in module pytemlib.eels_tools)": [[98, "pyTEMlib.eels_tools.find_white_lines"]], "fit_dataset() (in module pytemlib.eels_tools)": [[99, "pyTEMlib.eels_tools.fit_dataset"]], "fit_edges() (in module pytemlib.eels_tools)": [[100, "pyTEMlib.eels_tools.fit_edges"]], "fit_edges2() (in module pytemlib.eels_tools)": [[101, "pyTEMlib.eels_tools.fit_edges2"]], "fit_model() (in module pytemlib.eels_tools)": [[102, "pyTEMlib.eels_tools.fit_model"]], "fit_peaks() (in module pytemlib.eels_tools)": [[103, "pyTEMlib.eels_tools.fit_peaks"]], "fix_energy_scale() (in module pytemlib.eels_tools)": [[104, "pyTEMlib.eels_tools.fix_energy_scale"]], "gauss() (in module pytemlib.eels_tools)": [[105, "pyTEMlib.eels_tools.gauss"]], "get_energy_shifts() (in module pytemlib.eels_tools)": [[106, "pyTEMlib.eels_tools.get_energy_shifts"]], "get_resolution_functions() (in module pytemlib.eels_tools)": [[107, "pyTEMlib.eels_tools.get_resolution_functions"]], "get_spectrum_eels_db() (in module pytemlib.eels_tools)": [[108, "pyTEMlib.eels_tools.get_spectrum_eels_db"]], "get_wave_length() (in module pytemlib.eels_tools)": [[109, "pyTEMlib.eels_tools.get_wave_length"]], "get_x_sections() (in module pytemlib.eels_tools)": [[110, "pyTEMlib.eels_tools.get_x_sections"]], "get_z() (in module pytemlib.eels_tools)": [[111, "pyTEMlib.eels_tools.get_z"]], "identify_edges() (in module pytemlib.eels_tools)": [[112, "pyTEMlib.eels_tools.identify_edges"]], "kroeger_core() (in module pytemlib.eels_tools)": [[113, "pyTEMlib.eels_tools.kroeger_core"]], "kroeger_core2() (in module pytemlib.eels_tools)": [[114, "pyTEMlib.eels_tools.kroeger_core2"]], "list_all_edges() (in module pytemlib.eels_tools)": [[115, "pyTEMlib.eels_tools.list_all_edges"]], "lorentz() (in module pytemlib.eels_tools)": [[116, "pyTEMlib.eels_tools.lorentz"]], "make_cross_sections() (in module pytemlib.eels_tools)": [[117, "pyTEMlib.eels_tools.make_cross_sections"]], "make_edges() (in module pytemlib.eels_tools)": [[118, "pyTEMlib.eels_tools.make_edges"]], "model3() (in module pytemlib.eels_tools)": [[119, "pyTEMlib.eels_tools.model3"]], "model_ll() (in module pytemlib.eels_tools)": [[120, "pyTEMlib.eels_tools.model_ll"]], "model_smooth() (in module pytemlib.eels_tools)": [[121, "pyTEMlib.eels_tools.model_smooth"]], "plot_dispersion() (in module pytemlib.eels_tools)": [[122, "pyTEMlib.eels_tools.plot_dispersion"]], "power_law() (in module pytemlib.eels_tools)": [[123, "pyTEMlib.eels_tools.power_law"]], "power_law_background() (in module pytemlib.eels_tools)": [[124, "pyTEMlib.eels_tools.power_law_background"]], "read_msa() (in module pytemlib.eels_tools)": [[125, "pyTEMlib.eels_tools.read_msa"]], "residuals_ll() (in module pytemlib.eels_tools)": [[126, "pyTEMlib.eels_tools.residuals_ll"]], "residuals_ll2() (in module pytemlib.eels_tools)": [[127, "pyTEMlib.eels_tools.residuals_ll2"]], "residuals_smooth() (in module pytemlib.eels_tools)": [[128, "pyTEMlib.eels_tools.residuals_smooth"]], "resolution_function() (in module pytemlib.eels_tools)": [[129, "pyTEMlib.eels_tools.resolution_function"]], "resolution_function2() (in module pytemlib.eels_tools)": [[130, "pyTEMlib.eels_tools.resolution_function2"]], "second_derivative() (in module pytemlib.eels_tools)": [[131, "pyTEMlib.eels_tools.second_derivative"]], "set_previous_quantification() (in module pytemlib.eels_tools)": [[132, "pyTEMlib.eels_tools.set_previous_quantification"]], "shift_on_same_scale() (in module pytemlib.eels_tools)": [[133, "pyTEMlib.eels_tools.shift_on_same_scale"]], "sort_peaks() (in module pytemlib.eels_tools)": [[134, "pyTEMlib.eels_tools.sort_peaks"]], "xsec_xrpa() (in module pytemlib.eels_tools)": [[135, "pyTEMlib.eels_tools.xsec_xrpa"]], "zl() (in module pytemlib.eels_tools)": [[136, "pyTEMlib.eels_tools.zl"]], "zl_func() (in module pytemlib.eels_tools)": [[137, "pyTEMlib.eels_tools.zl_func"]], "pytemlib.file_tools": [[138, "module-pyTEMlib.file_tools"]], "choosedataset (class in pytemlib.file_tools)": [[139, "pyTEMlib.file_tools.ChooseDataset"]], "get_dataset_list() (pytemlib.file_tools.choosedataset method)": [[139, "pyTEMlib.file_tools.ChooseDataset.get_dataset_list"]], "filewidget (class in pytemlib.file_tools)": [[140, "pyTEMlib.file_tools.FileWidget"]], "dir_name (pytemlib.file_tools.filewidget attribute)": [[140, "pyTEMlib.file_tools.FileWidget.dir_name"]], "extension (pytemlib.file_tools.filewidget attribute)": [[140, "pyTEMlib.file_tools.FileWidget.extension"]], "get_directory() (pytemlib.file_tools.filewidget method)": [[140, "pyTEMlib.file_tools.FileWidget.get_directory"]], "get_file_name() (pytemlib.file_tools.filewidget method)": [[140, "pyTEMlib.file_tools.FileWidget.get_file_name"]], "set_options() (pytemlib.file_tools.filewidget method)": [[140, "pyTEMlib.file_tools.FileWidget.set_options"]], "add_dataset_from_file() (in module pytemlib.file_tools)": [[141, "pyTEMlib.file_tools.add_dataset_from_file"]], "add_to_dict() (in module pytemlib.file_tools)": [[142, "pyTEMlib.file_tools.add_to_dict"]], "get_h5_filename() (in module pytemlib.file_tools)": [[143, "pyTEMlib.file_tools.get_h5_filename"]], "get_last_path() (in module pytemlib.file_tools)": [[144, "pyTEMlib.file_tools.get_last_path"]], "get_main_channel() (in module pytemlib.file_tools)": [[145, "pyTEMlib.file_tools.get_main_channel"]], "get_start_channel() (in module pytemlib.file_tools)": [[146, "pyTEMlib.file_tools.get_start_channel"]], "h5_add_crystal_structure() (in module pytemlib.file_tools)": [[147, "pyTEMlib.file_tools.h5_add_crystal_structure"]], "h5_add_to_structure() (in module pytemlib.file_tools)": [[148, "pyTEMlib.file_tools.h5_add_to_structure"]], "h5_get_crystal_structure() (in module pytemlib.file_tools)": [[149, "pyTEMlib.file_tools.h5_get_crystal_structure"]], "h5_group_to_dict() (in module pytemlib.file_tools)": [[150, "pyTEMlib.file_tools.h5_group_to_dict"]], "h5_tree() (in module pytemlib.file_tools)": [[151, "pyTEMlib.file_tools.h5_tree"]], "log_results() (in module pytemlib.file_tools)": [[152, "pyTEMlib.file_tools.log_results"]], "open_file() (in module pytemlib.file_tools)": [[153, "pyTEMlib.file_tools.open_file"]], "open_file_dialog_qt() (in module pytemlib.file_tools)": [[154, "pyTEMlib.file_tools.open_file_dialog_qt"]], "read_cif() (in module pytemlib.file_tools)": [[155, "pyTEMlib.file_tools.read_cif"]], "read_dm3_info() (in module pytemlib.file_tools)": [[156, "pyTEMlib.file_tools.read_dm3_info"]], "read_essential_metadata() (in module pytemlib.file_tools)": [[157, "pyTEMlib.file_tools.read_essential_metadata"]], "read_nion_image_info() (in module pytemlib.file_tools)": [[158, "pyTEMlib.file_tools.read_nion_image_info"]], "read_old_h5group() (in module pytemlib.file_tools)": [[159, "pyTEMlib.file_tools.read_old_h5group"]], "read_poscar() (in module pytemlib.file_tools)": [[160, "pyTEMlib.file_tools.read_poscar"]], "save_dataset() (in module pytemlib.file_tools)": [[161, "pyTEMlib.file_tools.save_dataset"]], "save_dataset_dictionary() (in module pytemlib.file_tools)": [[162, "pyTEMlib.file_tools.save_dataset_dictionary"]], "save_file_dialog_qt() (in module pytemlib.file_tools)": [[163, "pyTEMlib.file_tools.save_file_dialog_qt"]], "save_path() (in module pytemlib.file_tools)": [[164, "pyTEMlib.file_tools.save_path"]], "save_single_dataset() (in module pytemlib.file_tools)": [[165, "pyTEMlib.file_tools.save_single_dataset"]], "set_dimensions() (in module pytemlib.file_tools)": [[166, "pyTEMlib.file_tools.set_dimensions"]], "update_directory_list() (in module pytemlib.file_tools)": [[167, "pyTEMlib.file_tools.update_directory_list"]], "pytemlib.file_tools_qt": [[168, "module-pyTEMlib.file_tools_qt"]], "pytemlib.graph_tools": [[169, "module-pyTEMlib.graph_tools"]], "breadth_first_search() (in module pytemlib.graph_tools)": [[170, "pyTEMlib.graph_tools.breadth_first_search"]], "circum_center() (in module pytemlib.graph_tools)": [[171, "pyTEMlib.graph_tools.circum_center"]], "find_interstitial_clusters() (in module pytemlib.graph_tools)": [[172, "pyTEMlib.graph_tools.find_interstitial_clusters"]], "find_overlapping_spheres() (in module pytemlib.graph_tools)": [[173, "pyTEMlib.graph_tools.find_overlapping_spheres"]], "find_polyhedra() (in module pytemlib.graph_tools)": [[174, "pyTEMlib.graph_tools.find_polyhedra"]], "get_bond_radii() (in module pytemlib.graph_tools)": [[175, "pyTEMlib.graph_tools.get_bond_radii"]], "get_bonds() (in module pytemlib.graph_tools)": [[176, "pyTEMlib.graph_tools.get_bonds"]], "get_connectivity_matrix() (in module pytemlib.graph_tools)": [[177, "pyTEMlib.graph_tools.get_connectivity_matrix"]], "get_distortion_matrix() (in module pytemlib.graph_tools)": [[178, "pyTEMlib.graph_tools.get_distortion_matrix"]], "get_maximum_view() (in module pytemlib.graph_tools)": [[179, "pyTEMlib.graph_tools.get_maximum_view"]], "get_non_periodic_supercell() (in module pytemlib.graph_tools)": [[180, "pyTEMlib.graph_tools.get_non_periodic_supercell"]], "get_polygons() (in module pytemlib.graph_tools)": [[181, "pyTEMlib.graph_tools.get_polygons"]], "get_significant_vertices() (in module pytemlib.graph_tools)": [[182, "pyTEMlib.graph_tools.get_significant_vertices"]], "get_voronoi() (in module pytemlib.graph_tools)": [[183, "pyTEMlib.graph_tools.get_voronoi"]], "interstitial_sphere_center() (in module pytemlib.graph_tools)": [[184, "pyTEMlib.graph_tools.interstitial_sphere_center"]], "make_polygons() (in module pytemlib.graph_tools)": [[185, "pyTEMlib.graph_tools.make_polygons"]], "make_polyhedrons() (in module pytemlib.graph_tools)": [[186, "pyTEMlib.graph_tools.make_polyhedrons"]], "plot_atoms() (in module pytemlib.graph_tools)": [[187, "pyTEMlib.graph_tools.plot_atoms"]], "polygon_sort() (in module pytemlib.graph_tools)": [[188, "pyTEMlib.graph_tools.polygon_sort"]], "set_bond_radii() (in module pytemlib.graph_tools)": [[189, "pyTEMlib.graph_tools.set_bond_radii"]], "sort_polyhedra_by_vertices() (in module pytemlib.graph_tools)": [[190, "pyTEMlib.graph_tools.sort_polyhedra_by_vertices"]], "transform_voronoi() (in module pytemlib.graph_tools)": [[191, "pyTEMlib.graph_tools.transform_voronoi"]], "undistort() (in module pytemlib.graph_tools)": [[192, "pyTEMlib.graph_tools.undistort"]], "undistort_sitk() (in module pytemlib.graph_tools)": [[193, "pyTEMlib.graph_tools.undistort_sitk"]], "undistort_stack() (in module pytemlib.graph_tools)": [[194, "pyTEMlib.graph_tools.undistort_stack"]], "undistort_stack_sitk() (in module pytemlib.graph_tools)": [[195, "pyTEMlib.graph_tools.undistort_stack_sitk"]], "voronoi_volumes() (in module pytemlib.graph_tools)": [[196, "pyTEMlib.graph_tools.voronoi_volumes"]], "pytemlib.graph_viz": [[197, "module-pyTEMlib.graph_viz"]], "get_boundary_polyhedra() (in module pytemlib.graph_viz)": [[198, "pyTEMlib.graph_viz.get_boundary_polyhedra"]], "plot_bonds() (in module pytemlib.graph_viz)": [[199, "pyTEMlib.graph_viz.plot_bonds"]], "plot_polyhedron() (in module pytemlib.graph_viz)": [[200, "pyTEMlib.graph_viz.plot_polyhedron"]], "plot_super_cell() (in module pytemlib.graph_viz)": [[201, "pyTEMlib.graph_viz.plot_super_cell"]], "plot_supercell() (in module pytemlib.graph_viz)": [[202, "pyTEMlib.graph_viz.plot_supercell"]], "plot_supercell_bonds() (in module pytemlib.graph_viz)": [[203, "pyTEMlib.graph_viz.plot_supercell_bonds"]], "plot_supercell_polyhedra() (in module pytemlib.graph_viz)": [[204, "pyTEMlib.graph_viz.plot_supercell_polyhedra"]], "plot_with_polyhedra() (in module pytemlib.graph_viz)": [[205, "pyTEMlib.graph_viz.plot_with_polyhedra"]], "show_polyhedra() (in module pytemlib.graph_viz)": [[206, "pyTEMlib.graph_viz.show_polyhedra"]], "pytemlib.image_dialog": [[207, "module-pyTEMlib.image_dialog"]], "pytemlib.image_dlg": [[208, "module-pyTEMlib.image_dlg"]], "pytemlib.image_tools": [[209, "module-pyTEMlib.image_tools"]], "imagewithlineprofile (class in pytemlib.image_tools)": [[210, "pyTEMlib.image_tools.ImageWithLineProfile"]], "__call__() (pytemlib.image_tools.imagewithlineprofile method)": [[210, "pyTEMlib.image_tools.ImageWithLineProfile.__call__"]], "adaptive_fourier_filter() (in module pytemlib.image_tools)": [[211, "pyTEMlib.image_tools.adaptive_fourier_filter"]], "align_crystal_reflections() (in module pytemlib.image_tools)": [[212, "pyTEMlib.image_tools.align_crystal_reflections"]], "calculate_ctf() (in module pytemlib.image_tools)": [[213, "pyTEMlib.image_tools.calculate_ctf"]], "calculate_scherzer() (in module pytemlib.image_tools)": [[214, "pyTEMlib.image_tools.calculate_scherzer"]], "calibrate_image_scale() (in module pytemlib.image_tools)": [[215, "pyTEMlib.image_tools.calibrate_image_scale"]], "cart2pol() (in module pytemlib.image_tools)": [[216, "pyTEMlib.image_tools.cart2pol"]], "cartesian2polar() (in module pytemlib.image_tools)": [[217, "pyTEMlib.image_tools.cartesian2polar"]], "clean_svd() (in module pytemlib.image_tools)": [[218, "pyTEMlib.image_tools.clean_svd"]], "complete_registration() (in module pytemlib.image_tools)": [[219, "pyTEMlib.image_tools.complete_registration"]], "crop_image_stack() (in module pytemlib.image_tools)": [[220, "pyTEMlib.image_tools.crop_image_stack"]], "decon_lr() (in module pytemlib.image_tools)": [[221, "pyTEMlib.image_tools.decon_lr"]], "demon_registration() (in module pytemlib.image_tools)": [[222, "pyTEMlib.image_tools.demon_registration"]], "diffractogram_spots() (in module pytemlib.image_tools)": [[223, "pyTEMlib.image_tools.diffractogram_spots"]], "fourier_transform() (in module pytemlib.image_tools)": [[224, "pyTEMlib.image_tools.fourier_transform"]], "get_rotation() (in module pytemlib.image_tools)": [[225, "pyTEMlib.image_tools.get_rotation"]], "get_wavelength() (in module pytemlib.image_tools)": [[226, "pyTEMlib.image_tools.get_wavelength"]], "histogram_plot() (in module pytemlib.image_tools)": [[227, "pyTEMlib.image_tools.histogram_plot"]], "pol2cart() (in module pytemlib.image_tools)": [[228, "pyTEMlib.image_tools.pol2cart"]], "power_spectrum() (in module pytemlib.image_tools)": [[229, "pyTEMlib.image_tools.power_spectrum"]], "rebin() (in module pytemlib.image_tools)": [[230, "pyTEMlib.image_tools.rebin"]], "rig_reg_drift() (in module pytemlib.image_tools)": [[231, "pyTEMlib.image_tools.rig_reg_drift"]], "rigid_registration() (in module pytemlib.image_tools)": [[232, "pyTEMlib.image_tools.rigid_registration"]], "rotational_symmetry_diffractogram() (in module pytemlib.image_tools)": [[233, "pyTEMlib.image_tools.rotational_symmetry_diffractogram"]], "warp() (in module pytemlib.image_tools)": [[234, "pyTEMlib.image_tools.warp"]], "xy2polar() (in module pytemlib.image_tools)": [[235, "pyTEMlib.image_tools.xy2polar"]], "pytemlib.info_dialog": [[236, "module-pyTEMlib.info_dialog"]], "infowidget (class in pytemlib.info_dialog)": [[237, "pyTEMlib.info_dialog.InfoWidget"]], "get_sidebar() (in module pytemlib.info_dialog)": [[238, "pyTEMlib.info_dialog.get_sidebar"]], "pytemlib.info_dlg": [[239, "module-pyTEMlib.info_dlg"]], "pytemlib.info_widget": [[240, "module-pyTEMlib.info_widget"]], "eelswidget (class in pytemlib.info_widget)": [[241, "pyTEMlib.info_widget.EELSWidget"]], "infowidget (class in pytemlib.info_widget)": [[242, "pyTEMlib.info_widget.InfoWidget"]], "lowlosswidget (class in pytemlib.info_widget)": [[243, "pyTEMlib.info_widget.LowLossWidget"]], "get_info_sidebar() (in module pytemlib.info_widget)": [[244, "pyTEMlib.info_widget.get_info_sidebar"]], "get_low_loss_sidebar() (in module pytemlib.info_widget)": [[245, "pyTEMlib.info_widget.get_low_loss_sidebar"]], "pytemlib.interactive_eels": [[246, "module-pyTEMlib.interactive_eels"]], "pytemlib.interactive_image": [[247, "module-pyTEMlib.interactive_image"]], "pytemlib.kinematic_scattering": [[248, "module-pyTEMlib.kinematic_scattering"]], "zuo_fig_3_18() (in module pytemlib.kinematic_scattering)": [[249, "pyTEMlib.kinematic_scattering.Zuo_fig_3_18"]], "check_sanity() (in module pytemlib.kinematic_scattering)": [[250, "pyTEMlib.kinematic_scattering.check_sanity"]], "example() (in module pytemlib.kinematic_scattering)": [[251, "pyTEMlib.kinematic_scattering.example"]], "feq() (in module pytemlib.kinematic_scattering)": [[252, "pyTEMlib.kinematic_scattering.feq"]], "find_angles() (in module pytemlib.kinematic_scattering)": [[253, "pyTEMlib.kinematic_scattering.find_angles"]], "find_nearest_zone_axis() (in module pytemlib.kinematic_scattering)": [[254, "pyTEMlib.kinematic_scattering.find_nearest_zone_axis"]], "get_dynamically_allowed() (in module pytemlib.kinematic_scattering)": [[255, "pyTEMlib.kinematic_scattering.get_dynamically_allowed"]], "get_metric_tensor() (in module pytemlib.kinematic_scattering)": [[256, "pyTEMlib.kinematic_scattering.get_metric_tensor"]], "get_rotation_matrix() (in module pytemlib.kinematic_scattering)": [[257, "pyTEMlib.kinematic_scattering.get_rotation_matrix"]], "get_wavelength() (in module pytemlib.kinematic_scattering)": [[258, "pyTEMlib.kinematic_scattering.get_wavelength"]], "kinematic_scattering() (in module pytemlib.kinematic_scattering)": [[259, "pyTEMlib.kinematic_scattering.kinematic_scattering"]], "kinematic_scattering2() (in module pytemlib.kinematic_scattering)": [[260, "pyTEMlib.kinematic_scattering.kinematic_scattering2"]], "make_pretty_labels() (in module pytemlib.kinematic_scattering)": [[261, "pyTEMlib.kinematic_scattering.make_pretty_labels"]], "read_poscar() (in module pytemlib.kinematic_scattering)": [[262, "pyTEMlib.kinematic_scattering.read_poscar"]], "ring_pattern_calculation() (in module pytemlib.kinematic_scattering)": [[263, "pyTEMlib.kinematic_scattering.ring_pattern_calculation"]], "scattering_matrix() (in module pytemlib.kinematic_scattering)": [[264, "pyTEMlib.kinematic_scattering.scattering_matrix"]], "stage_rotation_matrix() (in module pytemlib.kinematic_scattering)": [[265, "pyTEMlib.kinematic_scattering.stage_rotation_matrix"]], "vector_norm() (in module pytemlib.kinematic_scattering)": [[266, "pyTEMlib.kinematic_scattering.vector_norm"]], "zone_mistilt() (in module pytemlib.kinematic_scattering)": [[267, "pyTEMlib.kinematic_scattering.zone_mistilt"]], "pytemlib.microscope": [[268, "module-pyTEMlib.microscope"]], "microscope (class in pytemlib.microscope)": [[269, "pyTEMlib.microscope.Microscope"]], "pytemlib.peak_dialog": [[270, "module-pyTEMlib.peak_dialog"]], "peakfitwidget (class in pytemlib.peak_dialog)": [[271, "pyTEMlib.peak_dialog.PeakFitWidget"]], "fit_peaks() (pytemlib.peak_dialog.peakfitwidget method)": [[271, "pyTEMlib.peak_dialog.PeakFitWidget.fit_peaks"]], "smooth() (pytemlib.peak_dialog.peakfitwidget method)": [[271, "pyTEMlib.peak_dialog.PeakFitWidget.smooth"]], "get_sidebar() (in module pytemlib.peak_dialog)": [[272, "pyTEMlib.peak_dialog.get_sidebar"]], "smooth() (in module pytemlib.peak_dialog)": [[273, "pyTEMlib.peak_dialog.smooth"]], "pytemlib.peak_dlg": [[274, "module-pyTEMlib.peak_dlg"]], "pytemlib.probe_tools": [[275, "module-pyTEMlib.probe_tools"]], "get_chi() (in module pytemlib.probe_tools)": [[276, "pyTEMlib.probe_tools.get_chi"]], "get_chi_2() (in module pytemlib.probe_tools)": [[277, "pyTEMlib.probe_tools.get_chi_2"]], "get_d2chidu2() (in module pytemlib.probe_tools)": [[278, "pyTEMlib.probe_tools.get_d2chidu2"]], "get_d2chidudv() (in module pytemlib.probe_tools)": [[279, "pyTEMlib.probe_tools.get_d2chidudv"]], "get_d2chidv2() (in module pytemlib.probe_tools)": [[280, "pyTEMlib.probe_tools.get_d2chidv2"]], "get_ronchigram() (in module pytemlib.probe_tools)": [[281, "pyTEMlib.probe_tools.get_ronchigram"]], "get_ronchigram_2() (in module pytemlib.probe_tools)": [[282, "pyTEMlib.probe_tools.get_ronchigram_2"]], "get_source_energy_spread() (in module pytemlib.probe_tools)": [[283, "pyTEMlib.probe_tools.get_source_energy_spread"]], "get_target_aberrations() (in module pytemlib.probe_tools)": [[284, "pyTEMlib.probe_tools.get_target_aberrations"]], "make_chi() (in module pytemlib.probe_tools)": [[285, "pyTEMlib.probe_tools.make_chi"]], "make_chi1() (in module pytemlib.probe_tools)": [[286, "pyTEMlib.probe_tools.make_chi1"]], "make_gauss() (in module pytemlib.probe_tools)": [[287, "pyTEMlib.probe_tools.make_gauss"]], "make_lorentz() (in module pytemlib.probe_tools)": [[288, "pyTEMlib.probe_tools.make_lorentz"]], "print_aberrations() (in module pytemlib.probe_tools)": [[289, "pyTEMlib.probe_tools.print_aberrations"]], "probe2() (in module pytemlib.probe_tools)": [[290, "pyTEMlib.probe_tools.probe2"]], "zero_loss_peak_weight() (in module pytemlib.probe_tools)": [[291, "pyTEMlib.probe_tools.zero_loss_peak_weight"]], "pytemlib.sidpy_tools": [[292, "module-pyTEMlib.sidpy_tools"]], "choosedataset (class in pytemlib.sidpy_tools)": [[293, "pyTEMlib.sidpy_tools.ChooseDataset"]], "get_dataset_list() (pytemlib.sidpy_tools.choosedataset method)": [[293, "pyTEMlib.sidpy_tools.ChooseDataset.get_dataset_list"]], "get_dimensions_by_order() (in module pytemlib.sidpy_tools)": [[294, "pyTEMlib.sidpy_tools.get_dimensions_by_order"]], "get_dimensions_by_type() (in module pytemlib.sidpy_tools)": [[295, "pyTEMlib.sidpy_tools.get_dimensions_by_type"]], "get_extent() (in module pytemlib.sidpy_tools)": [[296, "pyTEMlib.sidpy_tools.get_extent"]], "get_image_dims() (in module pytemlib.sidpy_tools)": [[297, "pyTEMlib.sidpy_tools.get_image_dims"]], "make_dummy_dataset() (in module pytemlib.sidpy_tools)": [[298, "pyTEMlib.sidpy_tools.make_dummy_dataset"]], "plot() (in module pytemlib.sidpy_tools)": [[299, "pyTEMlib.sidpy_tools.plot"]], "pytemlib.simulation_tools": [[300, "module-pyTEMlib.simulation_tools"]], "exciting_get_spectra() (in module pytemlib.simulation_tools)": [[301, "pyTEMlib.simulation_tools.exciting_get_spectra"]], "final_state_broadening() (in module pytemlib.simulation_tools)": [[302, "pyTEMlib.simulation_tools.final_state_broadening"]], "pytemlib.version": [[303, "module-pyTEMlib.version"]], "pytemlib.viz": [[304, "module-pyTEMlib.viz"]], "curvevisualizer (class in pytemlib.viz)": [[305, "pyTEMlib.viz.CurveVisualizer"]], "spectrumview (class in pytemlib.viz)": [[306, "pyTEMlib.viz.SpectrumView"]], "initialize_edge() (pytemlib.viz.spectrumview method)": [[306, "pyTEMlib.viz.SpectrumView.initialize_edge"]], "find_edge_names() (in module pytemlib.viz)": [[307, "pyTEMlib.viz.find_edge_names"]], "plot() (in module pytemlib.viz)": [[308, "pyTEMlib.viz.plot"]], "plot_image() (in module pytemlib.viz)": [[309, "pyTEMlib.viz.plot_image"]], "plot_spectrum() (in module pytemlib.viz)": [[310, "pyTEMlib.viz.plot_spectrum"]], "plot_stack() (in module pytemlib.viz)": [[311, "pyTEMlib.viz.plot_stack"]], "spectrum_view_plotly() (in module pytemlib.viz)": [[312, "pyTEMlib.viz.spectrum_view_plotly"]], "verify_spectrum_dataset() (in module pytemlib.viz)": [[313, "pyTEMlib.viz.verify_spectrum_dataset"]], "pytemlib.xrpa_x_sections": [[314, "module-pyTEMlib.xrpa_x_sections"]]}}) \ No newline at end of file