Files
ptychoscopy/ptychoscopy/pty.py
2024-11-25 16:43:12 +01:00

503 lines
19 KiB
Python

#!/usr/bin/env python3
### Packages import
import numpy as np
from copy import deepcopy
from pandas import read_excel
import scipy.constants as cons
from ptychoscopy import pty
def get_versions():
"""
--------------------------------------------------------------
Show versions of the used packages.
--------------------------------------------------------------
Inputs:
none
"""
import sys
print (sys.version)
import openpyxl
print("Openpyxl version ", openpyxl.__version__)
import numpy as np
print("Numpy version ", np.__version__)
import scipy
print("Scipy version ", scipy.__version__)
import plotly
print("Plotly version ", plotly.__version__)
import pandas
print("Pandas version ", pandas.__version__)
import IPython
print("IPython version ", IPython.__version__)
import ipywidgets
print("Ipywidgets version ", ipywidgets.__version__)
try:
import abtem
print("abTEM version ", abtem.__version__)
except:
print("abTEM not available ")
return
def get_omegas():
"""
--------------------------------------------------------------------
Loads x-axis in multiplications of probe semi-angle for iterative
CTF curves from sheet called "CTF" ("CTF" row).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='CTF')
excel_lin = list((excel_data[excel_data.CTF.isin(["CTF"])]))
omegas = excel_lin[1::]
return omegas
def get_ctf(element):
"""
--------------------------------------------------------------------
Loads iterative CTF curve for chosen element from sheet called "CTF"
("chosen element" row).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
element ... name of the chosen CTF profile
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='CTF', header = 0)
excel_line = np.array(excel_data[excel_data.CTF.isin([element])])
ctf = excel_line[0]
ctf = ctf[1::]
return ctf
def get_wavelength(beam):
"""
--------------------------------------------------------------------
Computes relativistic electron wavelength.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
beam ... beam energy
Outputs:
wavelength ... electron wavelength in m
"""
wavelength = cons.h/np.sqrt(2*cons.electron_mass*cons.elementary_charge*beam*1e3*(1+((cons.elementary_charge*beam*1e3)/(2*cons.electron_mass*cons.speed_of_light**2))))
return wavelength
def get_fov(mag):
"""
--------------------------------------------------------------------
Loads field of view at 1x magnification and computes field of view
at given magnification.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
mag ... image magnification in millions
Outputs:
fov ... field of view in nm
"""
FoVat1x = [str(e) for e in list(read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges').FoVat1x)]
FoVat1x = np.array([x for x in FoVat1x if x != 'nan']).astype(float)
FoVat1x = FoVat1x.item()
fov = FoVat1x/(mag*1e6)
return fov
def get_angle(aperture):
"""
--------------------------------------------------------------------
Loads probe semi-angle of the chosen aperture.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
aperture ... probe defining aperture name
Outputs:
angle ... probe semi-angle in mrad
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes',header=0)
excel_line = excel_data[excel_data.Probe.isin(['SemiAngle'])]
angle = excel_line[aperture]
angle = np.array(angle).item()
return angle
def get_angle_corr(aperture):
"""
--------------------------------------------------------------------
Loads corrected probe semi-angle of the chosen aperture.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
aperture ... probe defining aperture name
Outputs:
angle_corr ... corrected probe semi-angle in mrad
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes',header=0)
excel_line = excel_data[excel_data.Probe.isin(['SemiAngleCorr'])]
angle_corr = excel_line[aperture]
angle_corr = np.array(angle_corr).item()
return angle_corr
def get_current(probe, aperture):
"""
--------------------------------------------------------------------
Loads probe current for chosen probe size and aperture.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
probe ... chosen probe name
aperture ... probe defining aperture name
Outputs:
current ... probe current in pA
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes',header=0)
excel_line = excel_data[excel_data.Probe.isin([probe])]
current = excel_line[aperture]
current = np.array(current).item()
return current
def get_pixel_angle(cl, camera, binning):
"""
--------------------------------------------------------------------
Loads and computes probe current for chosen probe size and aperture.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
cl ... chosen nominal camera length
camera ... chosen camera type
binning... chosen camera binning
Outputs:
pixel_angle ... single pixel cover angle in mrad
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Pixel',header=0)
excel_line = excel_data[excel_data.NominalCL.isin([cl])]
pixel_angle = excel_line[camera]
pixel_angle = np.array(pixel_angle).item()
pixel_angle = pixel_angle*binning
return pixel_angle
def get_cl_detector(cl, detector):
"""
--------------------------------------------------------------------
Loads effective camera length.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
cl ... chosen nominal camera length
detector ... chosen detector type
Outputs:
cl_detector ... efective camera length of detector in cm
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Camera_length')
excel_line = excel_data[excel_data.NominalCL.isin([cl])]
cl_detector = excel_line[detector]
cl_detector = cl_detector.item()
return cl_detector
def get_aq_frec(dwell_time):
"""
--------------------------------------------------------------------
Compute acquisition frame rate from dwell time.
--------------------------------------------------------------------
Inputs:
dwell_time ... beam position dwell time in us
Outputs:
aq_frec ... detection frame rate in kHz
"""
aq_frec = 1000/dwell_time
return aq_frec
def get_step_size(fov, matrix):
"""
--------------------------------------------------------------------
Compute scanning step size.
--------------------------------------------------------------------
Inputs:
matrix ... number of beam positions in scanning matrix
Outputs:
step_size ... detection frame rate in nm
"""
step_size = fov/(matrix-1)
return step_size
def get_step_correction():
"""
--------------------------------------------------------------------
Load scanning correction coefficient.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
Outputs:
step_correction ... scaling factor
"""
step_correction = [str(e) for e in list(read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges').StepSizeCorr)]
step_correction = np.array([x for x in step_correction if x != 'nan']).astype(float)
step_correction = step_correction.item()
return step_correction
def get_beam_diameter(aperture, defocus, angle_corr):
"""
--------------------------------------------------------------------
Computes geometrical beam diameter.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
aperture ... probe defining aperture name
defocus ... introduced beam defocus in nm
Outputs:
beam_diameter ... beam diameter in nm
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes')
excel_line = excel_data[excel_data.Probe.isin(['Def0Diameter'])]
beam_0_diameter = np.array([excel_line[aperture]]).astype(float)
beam_0_diameter = beam_0_diameter.item()
beam_diameter = 2*defocus*np.tan(angle_corr/1000)+beam_0_diameter
return beam_diameter
def get_0beam_diameter(aperture):
"""
--------------------------------------------------------------------
Computes geometrical beam diameter at 0 nm defocus.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
aperture ... probe defining aperture name
Outputs:
beam_0_diameter ... beam diameter in nm
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes')
excel_line = excel_data[excel_data.Probe.isin(['Def0Diameter'])]
beam_0_diameter = np.array([excel_line[aperture]]).astype(float)
beam_0_diameter = beam_0_diameter.item()
return beam_0_diameter
def get_detector(camera, binning):
"""
--------------------------------------------------------------------
Loads detection array size toghether with pixel size and computes
effective pixel size (inluding binning).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
camera ... detector name
binning ... applied diffraction pattern binning
Outputs:
num_pixels ... number of pixel in detection array
size_pixel ... detection pixel size in um
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Detector')
excel_line = excel_data[excel_data.Type.isin(['Array'])]
num_pixels = np.array([excel_line[camera]]).astype(float)
num_pixels = num_pixels.item()
num_pixels = num_pixels/binning
excel_line = excel_data[excel_data.Type.isin(['RealSize'])]
size_pixel = excel_line[camera]
size_pixel = size_pixel.item()
size_pixel = size_pixel*binning
return num_pixels, size_pixel
def get_pixel_covers(camera, binning):
"""
--------------------------------------------------------------------
Computes effective single detection pixel cover angle.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
camera ... detector name
binning ... applied diffraction pattern binning
Outputs:
pixel_covers ... effective pixel cover angle in mrad
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Pixel')
pixel_covers = list(excel_data[camera])
pixel_covers = [str(e) for e in pixel_covers]
pixel_covers = [x for x in pixel_covers if x != 'nan']
pixel_covers = [float(e) for e in pixel_covers]
pixel_covers = np.array(pixel_covers)
pixel_covers = pixel_covers*binning
return pixel_covers
def get_pumping_apertures():
"""
--------------------------------------------------------------------
Load differencial pumping aperture caused maximal detection angle
limitation for all camera lengths.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
Outputs:
pump_apert ... maximal detected angles in mrad for all camera lengths
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Camera_length')
pump_apert = [str(e) for e in list(excel_data.PAAR)]
pump_apert = [x for x in pump_apert if x != 'nan']
pump_apert = [float(e) for e in pump_apert]
return pump_apert
def get_ssb_ctf():
"""
--------------------------------------------------------------------
Computes SSB CTF.
--------------------------------------------------------------------
Inputs:
none
Outputs:
omega ... scattering angle from 0 to 2 alpha
pctf ... ssb ctf
"""
omega = np.linspace(1e-6,2,100)
p = np.arccos(np.minimum(1,omega))
p[np.isnan(p)] = 0
p2 = 1-(omega**2)
p2[p2 <0] = 0
p3 = omega*np.sqrt(p2)
p3[np.isnan(p3)] = 0
pctf = (2/cons.pi)*(np.arccos(omega/2)-p+p3-(omega/2*np.sqrt(1-(omega/2)**2)))
return omega, pctf
def get_cl4ssb(detector_cover_a_all, camera, which):
"""
--------------------------------------------------------------------
Computes maximal camera length for SSB.
--------------------------------------------------------------------
Inputs:
detector_cover_a_all ... detector cover in alfa for all camera lengths
Outputs:
ssb_cl ... maximal recommended camera length
kolik ... covered alfa of minimal detector cover
"""
ssb_cl = deepcopy(detector_cover_a_all)
ssb_cl[ssb_cl<1] = "nan"
ssb_cl = np.nanmin(ssb_cl)
kde = np.array(np.where(ssb_cl == detector_cover_a_all)).item()
kolik = np.array(detector_cover_a_all[kde])
cl_all = load_cameralengths(camera, which)
ssb_cl = np.array(cl_all[kde])
return ssb_cl, kolik
def load_elements():
"""
--------------------------------------------------------------------
Loads names of various phase contrast transfer functions from sheet
called "CTF" ("CTF" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='CTF')
elements = [str(e) for e in list(excel_data.CTF)]
elements = [x for x in elements if x != 'nan']
return elements
def load_apertures():
"""
--------------------------------------------------------------------
Loads aperture names from sheet called "Probes" ("Probe" row).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes')
excel_lin = list((excel_data[excel_data.Probe.isin(["Probe"])]))
apertures = excel_lin[1::]
return apertures
def load_detectors():
"""
--------------------------------------------------------------------
Loads detector names from sheet called "Detector" ("Type" row).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Detector')
excel_lin = list((excel_data[excel_data.Type.isin(["Type"])]))
detectors = excel_lin[1::]
return detectors
def load_probes():
"""
--------------------------------------------------------------------
Loads probe size names from sheet called "Probes" ("Probe" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
probes = list(read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes').Probe)
probes = probes[3::] # from fifth row
return probes
def load_magnifications():
"""
--------------------------------------------------------------------
Loads list of possible magnifications in millions from sheet called
"Ranges" ("Magnification" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges')
magnifications = list(excel_data.Magnification)
return magnifications
def load_energies():
"""
--------------------------------------------------------------------
Loads list of possible beam energies in keV from sheet called
"Ranges" ("BeamEnergy" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges')
energies = [str(e) for e in list(excel_data.BeamEnergy)]
energies = [x for x in energies if x != 'nan']
energies = [int(float(e)) for e in energies]
return energies
def load_mappings():
"""
--------------------------------------------------------------------
Loads list of possible scanning matricies from sheet called "Ranges"
("Mapping" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges')
mappings = [str(e) for e in list(excel_data.Mapping)]
mappings = [x for x in mappings if x != 'nan']
mappings = [int(float(e)) for e in mappings]
return mappings
def load_dwelltimes():
"""
--------------------------------------------------------------------
Loads list of possible dwell times in us from sheet called "Ranges"
("DwellTime" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges')
dwelltimes = [str(e) for e in list(excel_data.DwellTime)]
dwelltimes = [x for x in dwelltimes if x != 'nan']
dwelltimes = [int(float(e)) for e in dwelltimes]
return dwelltimes
def load_cameralengths(camera, which):
"""
--------------------------------------------------------------------
Loads list of possible nominal camera lengths in cm from sheet
called "Pixel" ("NominalCL" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
match which:
case "nominal":
cameralengths = list(read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Camera_length').NominalCL)
case "effective":
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Camera_length')
cameralengths = list(np.array(excel_data[camera]))
return cameralengths