Version 0.06

This commit is contained in:
rskoupy
2023-11-28 11:53:50 +01:00
commit 1cee10d034
4 changed files with 860 additions and 0 deletions

6
README.md Normal file
View File

@ -0,0 +1,6 @@
# ptychoScopy
Jupyter based interactive data acquisition tool designed for appropriate ptychographic data collection. It computes nessesary characteristics which play crutial role in final data reconstruction. You can chose of **Direct methods** (mainly Single Side Band ptychography) or **Iterative reconstruction** which takes probe defocus into account.
With this tool, you can check for probe CTF, scanning step size, probe overlap, detector camera length a proper angular range collection, reconstructed probe size and many more.
### Calibrations
Every STEM has its own combination of parameters (magnifications, probe currents, aperture angles, camera lengths or detectors). These have to be taken into account for proper data acquisition design. Before first use, fill your own values into the file **calibrations.xlsx**. Instructions how to fill are in the sheet called HELP.

BIN
calibrations.xlsx Normal file

Binary file not shown.

854
ptychoScopy.ipynb Normal file
View File

@ -0,0 +1,854 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "8f22e3c3",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"C:\\Users\\skoupy_r\\Anaconda3\\lib\\site-packages\\scipy\\__init__.py:155: UserWarning: A NumPy version >=1.18.5 and <1.25.0 is required for this version of SciPy (detected version 1.26.1\n",
" warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Numpy version 1.26.1\n",
"Matplotlib version 3.8.1\n",
"Pandas version 2.1.2\n",
"Ipywidgets version 7.6.5\n",
"Plotly version 5.9.0\n"
]
}
],
"source": [
"### Initial packages import ###\n",
"import ipywidgets as widgets\n",
"import scipy.constants as cons\n",
"import math\n",
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib\n",
"import plotly.graph_objects as go\n",
"from ipywidgets import interactive, interactive_output, interact, HBox, Layout, VBox, Label\n",
"import copy\n",
"import seaborn as sns\n",
"import matplotlib.pyplot as plt\n",
"from IPython.display import display, HTML, Markdown\n",
"\n",
"import plotly\n",
"import plotly.graph_objects as go\n",
"from plotly.subplots import make_subplots\n",
"\n",
"print(\"Numpy version \", np.__version__)\n",
"print(\"Matplotlib version \", matplotlib.__version__)\n",
"print(\"Pandas version \", pd.__version__)\n",
"print(\"Ipywidgets version \", widgets.__version__)\n",
"print(\"Plotly version \", plotly.__version__)"
]
},
{
"cell_type": "markdown",
"id": "7671c652-c4e7-4f1f-a87e-e4c67bafed51",
"metadata": {},
"source": [
"Tested with packages: \\\n",
"Numpy version 1.26.1 \\\n",
"Matplotlib version 3.8.1 \\\n",
"Pandas version 2.1.2 \\\n",
"Ipywidgets version 7.6.5 \\\n",
"Plotly version 5.9.0 "
]
},
{
"cell_type": "code",
"execution_count": 122,
"id": "7425242d-3c91-4c1e-a424-08625a38ee7a",
"metadata": {},
"outputs": [],
"source": [
"\n",
"### Function nefinitions ###\n",
"\n",
"calib = r'C:\\Users\\skoupy_r\\--PYTHON\\ptychoScopy\\calibrations.xlsx' # Full path to the calibration file\n",
"\n",
"class interaction: \n",
" \"\"\"Loads calibration settings and ranges from .xlsx file.\n",
" These are than used for widgets creation.\"\"\"\n",
" \n",
"\n",
" def __init__(self):\n",
" self.calib = calib\n",
"\n",
" def apertures(self):\n",
" excel_data = pd.read_excel(self.calib,sheet_name='Probes')\n",
" excel_lin = list((excel_data[excel_data.Probe.isin([\"Probe\"])]))\n",
" apertures = excel_lin[1::]\n",
" return apertures\n",
" \n",
" def detectors(self):\n",
" excel_data = pd.read_excel(self.calib,sheet_name='Detector')\n",
" excel_lin = list((excel_data[excel_data.Type.isin([\"Type\"])]))\n",
" detectors = excel_lin[1::]\n",
" return detectors\n",
" \n",
" def probes(self):\n",
" probes = list(pd.read_excel(self.calib,sheet_name='Probes').Probe)\n",
" probes = probes[3::]\n",
" return probes\n",
" \n",
" def magnifications(self):\n",
" excel_data = pd.read_excel(self.calib,sheet_name='Ranges')\n",
" magnifications = list(excel_data.Magnification)\n",
" return magnifications\n",
" \n",
" def energies(self): \n",
" excel_data = pd.read_excel(self.calib,sheet_name='Ranges')\n",
" energies = [str(e) for e in list(excel_data.BeamEnergy_keV)]\n",
" energies = [x for x in energies if x != 'nan']\n",
" energies = [int(float(e)) for e in energies]\n",
" return energies\n",
" \n",
" def mappings(self): \n",
" excel_data = pd.read_excel(self.calib,sheet_name='Ranges')\n",
" mappings = [str(e) for e in list(excel_data.Mapping)]\n",
" mappings = [x for x in mappings if x != 'nan']\n",
" mappings = [int(float(e)) for e in mappings]\n",
" return mappings\n",
" \n",
" def cameralengths(self): \n",
" cameralengths = list(pd.read_excel(self.calib,sheet_name='Pixel').NominalCL)\n",
" return cameralengths\n",
" \n",
" def cameralengths_eff(self): \n",
" cameralengths_eff = list(pd.read_excel(self.calib,sheet_name='Pixel').DetectorCL_cm)\n",
" return cameralengths_eff\n",
"\n",
" def dwelltimes(self): \n",
" excel_data = pd.read_excel(self.calib,sheet_name='Ranges')\n",
" dwelltimes = [str(e) for e in list(excel_data.DwellTime_us)]\n",
" dwelltimes = [x for x in dwelltimes if x != 'nan']\n",
" dwelltimes = [int(float(e)) for e in dwelltimes] \n",
" return dwelltimes \n",
" \n",
"opt = interaction()\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"class ptychoScopy:\n",
" \"\"\"Computes various characteristics describing used setting.\"\"\"\n",
" \n",
" def __init__(self):\n",
" self.calib = calib\n",
" \n",
" \n",
" \n",
" def get_wavelength(self, beam):\n",
" self.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))))\n",
" return self.wavelength\n",
" \n",
" def get_fov(self, mag):\n",
" self.fov = 214620000/(mag*1e6)\n",
" return self.fov\n",
" \n",
" def get_angle(self, aperture):\n",
" excel_data = pd.read_excel(calib, sheet_name='Probes',header=0)\n",
" excel_line = excel_data[excel_data.Probe.isin(['ProbeSemi_angle_mrad'])]\n",
" angle = excel_line[aperture]\n",
" self.angle = np.array(angle).item()\n",
" return self.angle\n",
" \n",
" def get_angle_corr(self, aperture):\n",
" excel_data = pd.read_excel(calib, sheet_name='Probes',header=0)\n",
" excel_line = excel_data[excel_data.Probe.isin(['CorrectedProbeSemi_angle_mrad'])]\n",
" angle_corr = excel_line[aperture]\n",
" self.angle_corr = np.array(angle_corr).item()\n",
" return self.angle_corr\n",
" \n",
" def get_current(self, probe,aperture):\n",
" excel_data = pd.read_excel(calib, sheet_name='Probes',header=0)\n",
" excel_line = excel_data[excel_data.Probe.isin([probe])]\n",
" current = excel_line[aperture]\n",
" self.current = np.array(current).item()\n",
" return self.current\n",
" \n",
" def get_currents_over_probes(self, probe):\n",
" excel_data = pd.read_excel(calib, sheet_name='Probes',header=0)\n",
" currents_probes = np.array(excel_data[excel_data.Probe.isin([probe])])\n",
" currents_probes = currents_probes[0]\n",
" currents_probes = currents_probes[1::]\n",
" return currents_probes\n",
"\n",
" def get_currents_over_apertures(self, aperture):\n",
" excel_data = pd.read_excel(calib, sheet_name='Probes',header=0)\n",
" currents_apertures = np.array(list(excel_data[aperture]))\n",
" return currents_apertures\n",
"\n",
" def get_pixel_angle(self, cl, camera, binning):\n",
" excel_data = pd.read_excel(calib,sheet_name='Pixel',header=0)\n",
" excel_line = excel_data[excel_data.NominalCL.isin([cl])]\n",
" pixel_angle = excel_line[camera]\n",
" pixel_angle = np.array(pixel_angle).item()\n",
" self.pixel_angle = pixel_angle*binning\n",
" return self.pixel_angle\n",
" \n",
" def get_cl_detector(self,cl):\n",
" excel_data = pd.read_excel(calib,sheet_name='Pixel')\n",
" excel_line = excel_data[excel_data.NominalCL.isin([cl])]\n",
" self.cl_detector = excel_line['DetectorCL_cm']\n",
" self.cl_detector = self.cl_detector.item()\n",
" return self.cl_detector\n",
" \n",
" def get_aq_frec(self, dwell_time):\n",
" self.aq_frec = 1000/dwell_time\n",
" return self.aq_frec \n",
" \n",
" def get_step_size(self, matrix):\n",
" self.step_size = self.fov/(matrix-1)\n",
" return self.step_size \n",
" \n",
" def get_step_correction(self): \n",
" step_correction = [str(e) for e in list(pd.read_excel(calib,sheet_name='Ranges').Step_size_correction)]\n",
" step_correction = np.array([x for x in step_correction if x != 'nan']).astype(float)\n",
" self.step_correction = step_correction.item()\n",
" return self.step_correction\n",
" \n",
" def get_beam_diameter(self, aperture, defocus):\n",
" excel_data = pd.read_excel(calib, sheet_name='Probes')\n",
" excel_line = excel_data[excel_data.Probe.isin(['0_defocus_beam_diameter_nm'])]\n",
" beam_0_diameter = np.array([excel_line[aperture]]).astype(float)\n",
" beam_0_diameter = beam_0_diameter.item()\n",
" self.beam_diameter = defocus*2*np.tan(self.angle_corr/1000)+beam_0_diameter\n",
" return self.beam_diameter\n",
" \n",
" def get_0beam_diameter(self, aperture):\n",
" excel_data = pd.read_excel(calib, sheet_name='Probes')\n",
" excel_line = excel_data[excel_data.Probe.isin(['0_defocus_beam_diameter_nm'])]\n",
" beam_0_diameter = np.array([excel_line[aperture]]).astype(float)\n",
" self.beam_0_diameter = beam_0_diameter.item()\n",
" return self.beam_0_diameter\n",
" \n",
" def get_detector(self, camera, binning):\n",
" excel_data = pd.read_excel(calib, sheet_name='Detector')\n",
" excel_line = excel_data[excel_data.Type.isin(['Pixels'])]\n",
" num_pixels = np.array([excel_line[camera]]).astype(float)\n",
" num_pixels = num_pixels.item()\n",
" self.num_pixels = num_pixels/binning\n",
" excel_line = excel_data[excel_data.Type.isin(['Real_size'])]\n",
" size_pixel = excel_line[camera]\n",
" size_pixel = size_pixel.item()\n",
" self.size_pixel = size_pixel*binning\n",
" return self.num_pixels, self.size_pixel \n",
" \n",
" def get_det_resolution(self, camera):\n",
" excel_data = pd.read_excel(calib, sheet_name='Detector')\n",
" excel_line = excel_data[excel_data.Type.isin(['Pixels'])]\n",
" num_pixels = np.array([excel_line[camera]]).astype(float)\n",
" self.num_pixels = num_pixels.item()\n",
" return self.num_pixels\n",
" \n",
" def get_det_orig_pixel_size(self, camera):\n",
" excel_data = pd.read_excel(calib, sheet_name='Detector')\n",
" excel_line = excel_data[excel_data.Type.isin(['Real_size'])]\n",
" orig_size_pixel = excel_line[camera]\n",
" self.orig_size_pixel = orig_size_pixel.item()\n",
" return self.orig_size_pixel\n",
" \n",
" def get_pixel_covers(self,camera, binning): \n",
" excel_data = pd.read_excel(calib, sheet_name='Pixel')\n",
" pixel_covers = list(excel_data[camera])\n",
" pixel_covers = [str(e) for e in pixel_covers]\n",
" pixel_covers = [x for x in pixel_covers if x != 'nan']\n",
" pixel_covers = [float(e) for e in pixel_covers] \n",
" pixel_covers = np.array(pixel_covers)\n",
" self.pixel_covers = pixel_covers * binning\n",
" return self.pixel_covers\n",
"\n",
" def get_pumping_apertures(self): \n",
" excel_data = pd.read_excel(calib,sheet_name='Pixel')\n",
" pump_apert = [str(e) for e in list(excel_data.Pumping_aperture_limitation_mrad)]\n",
" pump_apert = [x for x in pump_apert if x != 'nan']\n",
" self.pump_apert = [float(e) for e in pump_apert]\n",
" return self.pump_apert \n",
" \n",
" def get_ssb_ctf(self):\n",
" ### Contrast transfer function ###\n",
" omega = np.linspace(1e-6,2,100)\n",
" p3 = np.arccos(np.minimum(1,omega))\n",
" p3[np.isnan(p3)] = 0\n",
" p5 = 1-(omega**2)\n",
" p5[p5 <0] = 0\n",
" p4 = omega*np.sqrt(p5)\n",
" p4[np.isnan(p4)] = 0\n",
" pctf = (2/cons.pi)*(np.arccos(omega/2)-p3+p4-(omega/2*np.sqrt(1-(omega/2)**2)))\n",
" return pctf\n",
" \n",
" \n",
" def cl4ssb(self, detector_cover_a_all):\n",
" ssb_cl = copy.deepcopy(detector_cover_a_all)\n",
" ssb_cl[ssb_cl<1] = \"nan\"\n",
" ssb_cl = np.nanmin(ssb_cl)\n",
" kde = np.array(np.where(ssb_cl == detector_cover_a_all)).item()\n",
" kolik = np.array(detector_cover_a_all[kde]) \n",
" cl_all = opt.cameralengths()\n",
" ssb_cl = np.array(cl_all[kde]) # Recommended cl\n",
" return ssb_cl, kolik\n",
" \n",
"\n",
"pty = ptychoScopy() \n",
" \n",
"class interaction:\n",
" \"\"\"Live interaction with parameter computing.\"\"\"\n",
" \n",
" def __init__(self):\n",
" self.calib = calib\n",
" \n",
" \n",
" def show_wavelength(self,caller):\n",
" beam_res.value = f'Wavelength (pm) {str(\"{:.2f}\".format(pty.get_wavelength(caller.new)*1e12))}'\n",
" return beam_res.value\n",
" \n",
" def show_detector(self,caller):\n",
" camera_res.value = f'Detector full pixel array {\"{:.0f}\".format(pty.get_det_resolution(caller.new))}'\n",
" return camera_res.value\n",
" \n",
" def show_pixel_size(self,caller):\n",
" pixel_size_res.value = f'Native pixel size (μm) {\"{:.0f}\".format(pty.get_det_orig_pixel_size(caller.new))}' \n",
" return pixel_size_res.value\n",
" \n",
" def show_probe_angle(self,caller):\n",
" aperture_res.value = f'Probe semi angle (mrad) {\"{:.2f}\".format(pty.get_angle(caller.new))}' \n",
" return aperture_res.value\n",
" \n",
" def show_corrprobe_angle(self,caller):\n",
" aperture_res2.value = f'Corrected semi angle (mrad) {\"{:.2f}\".format(pty.get_angle_corr(caller.new))}'\n",
" return aperture_res2.value\n",
" \n",
" def show_fov(self,caller):\n",
" fov_res.value = f'Field of view (nm) {pty.get_fov(caller.new) }'\n",
" return fov_res.value\n",
" \n",
" def show_frame_rate(self,caller):\n",
" dwell_time_res.value = f'Frame rate (kHz) {pty.get_aq_frec(caller.new)}' \n",
" return dwell_time_res.value\n",
" \n",
" def show_cd_det(self,caller):\n",
" cl_det_res.value = f'Detector camera length (cm) {pty.get_cl_detector(caller.new)}' \n",
" return cl_det_res.value\n",
" \n",
" \n",
"inte = interaction() \n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 123,
"id": "8055b802-cf83-4250-aea9-54e3e6b73db0",
"metadata": {},
"outputs": [],
"source": [
"### CONTROLS ##########################################\n",
"align = dict(layout=widgets.Layout(width='385px') , style = {'description_width': '80px','button_width': \"35px\"}, button_style='primary',disabled=False,)\n",
"align2 = dict(layout=widgets.Layout(width='250px') , style = {'description_width': '100px','button_width': '50px'}, disabled=False,)\n",
"to_right = dict(layout=widgets.Layout(display=\"flex\", justify_content=\"flex-end\", width=\"95%\", ))\n",
"\n",
"### Main controls ###\n",
"beam = widgets.Dropdown(options=opt.energies(),value=200,description='Energy (keV)', **align)\n",
"aperture = widgets.ToggleButtons(options=opt.apertures(), value='30um', description='Aperture', **align, tooltips=['', ''])\n",
"probe = widgets.ToggleButtons(options=opt.probes(), value='8C', description='Probe', **align, tooltips=['', ''])\n",
"defocus = widgets.IntSlider(description='Defocus (nm)', value=0, min=0, max=1000, step=1, continuous_update=False, **align )\n",
"defocus.style.handle_color = 'blue'\n",
"mag = widgets.ToggleButtons(options=opt.magnifications(),value=3,description='Mag. (Mx)', **align) \n",
"matrix = widgets.ToggleButtons(options=opt.mappings(), value=2048, description='Matrix', **align, tooltips=['', ''])\n",
"cl = widgets.ToggleButtons(options=opt.cameralengths(), value=12, description='Nominal (cm)', **align, tooltips=['', ''])\n",
"camera = widgets.Dropdown(options=opt.detectors(), description='Detector', **align, tooltips=['', ''])\n",
"restriction = widgets.ToggleButtons(options=[('NO',False), ('YES',True)], description='Use PAAR',**align, tooltips=['', ''])\n",
"binning = widgets.ToggleButtons(options=[('NO',1), ('2×2',2), ('4×4',4),('6×6',6),('8×8',8)], description='Binning', **align, tooltips=['Full detector resolution', 'Binning 2x2 - detector resolution /2, pixel size *2', 'Binning 4x4'])\n",
"dwell_time = widgets.ToggleButtons(options=opt.dwelltimes(), value=10, description='Dwell time (μs)', **align, tooltips=['', ''])\n",
"\n",
"### Small controls ###\n",
"method = widgets.ToggleButtons(options=[('Direct','direct'), ('Iterative','iterative')], description='Methods', **align2, button_style='primary', tooltips=['SSB', 'PIE, MLc, DM'])\n",
"ssb_freq_length = widgets.RadioButtons(options=['mrad', 'A'], description='CTF-SSB x-axis:', **align2) \n",
"scans = widgets.RadioButtons(options=[4,6,8,10],description='Scan points:',continuous_update=False, **align2)\n",
"\n",
"### Live update ### \n",
"beam_res = widgets.Label(value = f'Wavelength (pm) '+ str(\"{:.2f}\".format(pty.get_wavelength(beam.value)*1e12)), **to_right)\n",
"beam.observe(inte.show_wavelength, names='value')\n",
"camera_res = widgets.Label(value = f'Detector full pixel array '+ str(\"{:.0f}\".format(pty.get_det_resolution(camera.value))), **to_right)\n",
"camera.observe(inte.show_detector, names='value')\n",
"pixel_size_res = widgets.Label(value = f'Native pixel size (μm) '+ str(\"{:.0f}\".format(pty.get_det_orig_pixel_size(camera.value))),**to_right)\n",
"camera.observe(inte.show_pixel_size, names='value')\n",
"aperture_res = widgets.Label(value = f'Probe semi angle (mrad) '+ str(\"{:.2f}\".format(pty.get_angle(aperture.value))), **to_right)\n",
"aperture.observe(inte.show_probe_angle, names='value') \n",
"aperture_res2 = widgets.Label(value = f'Corrected semi angle (mrad) '+ str(\"{:.2f}\".format(pty.get_angle_corr(aperture.value))), **to_right)\n",
"aperture.observe(inte.show_corrprobe_angle, names='value') \n",
"fov_res = widgets.Label(value = f'Field of view (nm) '+ str(pty.get_fov(mag.value)), **to_right)\n",
"mag.observe(inte.show_fov, names='value') \n",
"dwell_time_res = widgets.Label(value = f'Frame rate (kHz) '+ str(pty.get_aq_frec(dwell_time.value)),**to_right)\n",
"dwell_time.observe(inte.show_frame_rate, names='value') \n",
"cl_det_res = widgets.Label(value = f'Detector camera length (cm) '+ str(pty.get_cl_detector(cl.value)),**to_right)\n",
"cl.observe(inte.show_cd_det, names='value') \n",
"\n",
"box_layout = widgets.Layout(border='solid 1px blue',margin='0px 10px 10px 0px', padding='5px 5px 5px 5px')\n",
"col1 = widgets.VBox([widgets.Label('Beam'), beam, aperture, probe, defocus])\n",
"col1.layout = box_layout\n",
"col2 = widgets.VBox([widgets.Label('Scanning'), mag, matrix])\n",
"col2.layout = box_layout\n",
"col3 = widgets.VBox([widgets.Label('Camera length'), cl, restriction])\n",
"col3.layout = box_layout\n",
"col4 = widgets.VBox([widgets.Label('Detection'), camera, binning, dwell_time])\n",
"col4.layout = box_layout\n",
"\n",
"descriptions_beam = widgets.VBox([widgets.Label('Characteristics beam'), beam_res, aperture_res, aperture_res2])\n",
"descriptions_beam.layout = widgets.Layout(border='solid 1px gray', margin='0px 10px 10px 0px', padding='5px 5px 5px 5px')\n",
"descriptions_scan = widgets.VBox([widgets.Label('Characteristics scanning'), fov_res])\n",
"descriptions_scan.layout = widgets.Layout(border='solid 1px gray', margin='0px 10px 10px 0px', padding='5px 5px 5px 5px')\n",
"descriptions_cl = widgets.VBox([widgets.Label('Characteristics camera length'), cl_det_res])\n",
"descriptions_cl.layout = widgets.Layout(border='solid 1px gray', margin='0px 10px 10px 0px', padding='5px 5px 5px 5px')\n",
"descriptions_det = widgets.VBox([widgets.Label('Characteristics detector'), camera_res, pixel_size_res,dwell_time_res])\n",
"descriptions_det.layout = widgets.Layout(border='solid 1px gray', margin='0px 10px 10px 0px', padding='5px 5px 5px 5px')\n",
"\n",
"small_control = widgets.VBox([widgets.Label('Graph controls'),method, ssb_freq_length, scans, descriptions_beam, descriptions_scan, descriptions_cl, descriptions_det])\n",
"controls = widgets.HBox([widgets.VBox([widgets.Label(''), col1, col2, col3, col4]), small_control])\n",
"\n",
"\n",
"\n",
"def ptycho_interact(beam, aperture, probe, cl, matrix, defocus, mag, camera, binning, dwell_time, restriction, method, ssb_freq_length, scans):\n",
" \n",
" ### SINGLE SETTING PARAMETERS ###\n",
" wavelength = pty.get_wavelength(beam)*1e12\n",
" fov = pty.get_fov(mag)\n",
" semi_angle = pty.get_angle(aperture)\n",
" semi_angle_corr = pty.get_angle_corr(aperture) \n",
" current = pty.get_current(probe,aperture) \n",
" pixel_angle = pty.get_pixel_angle(cl, camera, binning)\n",
" cl_det = pty.get_cl_detector(cl)\n",
" frame_rate = pty.get_aq_frec(dwell_time)\n",
" step_size = pty.get_step_size(matrix)\n",
" step_size_corr = np.array(pty.get_step_correction())*pty.get_step_size(matrix)\n",
" beam_diameter = pty.get_beam_diameter(aperture, defocus)\n",
" num_pixels, size_pixel = pty.get_detector(camera, binning)\n",
" beam_diameter_pix = 2*semi_angle_corr/pixel_angle\n",
" detector_cover = num_pixels/2*pixel_angle\n",
" covered_alfas = detector_cover/semi_angle_corr\n",
" overlap = (beam_diameter-step_size_corr)/beam_diameter*100\n",
" if overlap < 0:\n",
" overlap = 0\n",
" dose = ((matrix**2)*(dwell_time/1e6)*(current/1e12/cons.e))/((((matrix-1)*step_size_corr)**2)*100)\n",
" probe_window = (wavelength*cl_det/100)/(2*size_pixel/1e6)/1000 # now in nm\n",
" \n",
" ### ALL CAMERA LENGTHS PARAMETERS ###\n",
" pixel_covers = pty.get_pixel_covers(camera, binning) \n",
" pump_apertures = pty.get_pumping_apertures()\n",
" detector_cover_all = pixel_covers*num_pixels/2\n",
" if restriction == True:\n",
" for x in range(len(detector_cover_all)):\n",
" if detector_cover_all[x] > pump_apertures[x]:\n",
" detector_cover_all[x] = pump_apertures[x] \n",
" detector_pixels_all = np.round(detector_cover_all/pixel_covers) \n",
" ptycho_pixel_size_all = (wavelength * np.array(opt.cameralengths_eff() )) /(detector_pixels_all*size_pixel/1e6)/1e4 \n",
" else:\n",
" ptycho_pixel_size_all = (wavelength * np.array(opt.cameralengths_eff() )) /(num_pixels/2*size_pixel/1e6)/1e4\n",
" \n",
" probe_window_all = (wavelength*np.array(opt.cameralengths_eff())/100)/(2*size_pixel/1e6)/1000 # now in nm\n",
" usable_probe_semi_window_all = probe_window_all/4\n",
" detector_cover_a_all = detector_cover_all/semi_angle_corr\n",
" max_defocus_all = (usable_probe_semi_window_all - pty.get_0beam_diameter(aperture)/2)/np.tan(semi_angle_corr/1000)\n",
" max_defocus_all[max_defocus_all < 0] = 'nan'\n",
" \n",
" omega = np.linspace(1e-6,2,100) \n",
" pctf = pty.get_ssb_ctf()\n",
" apertury = opt.apertures()\n",
" \n",
" ### PROBE ##########################################\n",
" fig = go.Figure() \n",
" fig.update_yaxes(title_text=\" CTF-SSB\")\n",
" if ssb_freq_length == 'mrad': \n",
" for x in apertury:\n",
" fig.add_trace(go.Scatter(showlegend=False, x=pty.get_angle_corr(x) *omega, y=pctf, marker_color='gray', name='SSB-CTF',))\n",
" \n",
" fig.add_trace(go.Scatter(x=semi_angle_corr*omega, y=pctf, marker_color='red', name=str(np.round(semi_angle_corr,2))+ ' mrad',))\n",
" fig.update_xaxes(title_text=\"Spacial frequency (mrad)\", range=[0, 60], zeroline=False)\n",
"\n",
" elif ssb_freq_length == 'A':\n",
" for x in apertury:\n",
" d = 2*wavelength/(np.sin(pty.get_angle_corr(x)*omega/1000))/100\n",
" fig.add_trace(go.Scatter(showlegend=False, x=d, y=pctf, marker_color='gray', name='SSB-CTF',))\n",
" \n",
" fig.add_trace(go.Scatter(x=2*wavelength/(np.sin(semi_angle_corr*omega/1000))/100, y=pctf, marker_color='red', name=str(np.round(semi_angle_corr,2))+ ' mrad',))\n",
" fig.update_xaxes(title_text=\"Spacial frequency (A?)\",range=[0, 2.5], type=\"log\", zeroline=False)\n",
" \n",
" fig.update_layout(legend=dict(orientation=\"h\",yanchor=\"bottom\",y=0.75,xanchor=\"right\",x=1))\n",
" # fig3.update_layout(title={'text': \"CTF\",'y':0.93, 'x':0.12,'xanchor': 'left','yanchor': 'top'})\n",
" fig.update_layout(width=800, height=225, margin = dict(l=110, r=30, t=30, b=30))\n",
"\n",
" \n",
" ### SAMPLE PLANE ##########################################\n",
" yyy = np.append(np.linspace(0,overlap,100), 200)\n",
" wid = np.linspace(0,scans-1,scans) * step_size_corr\n",
" \n",
" fig5 = make_subplots(specs=[[{\"secondary_y\": True}]])\n",
" fig5.update_xaxes(title_text=\"Sample plane (nm)\", range=[0, scans*step_size_corr], zeroline=False)\n",
" fig5.update_yaxes(range=[0, scans*step_size_corr], showticklabels=False)\n",
" \n",
" fig5.add_trace(go.Scatter(showlegend=False, x = scans*step_size_corr*np.ones(len(yyy)), y=yyy, opacity=1,mode='markers',marker_symbol = \"triangle-down\",marker=dict(size=20, color=yyy, colorscale='rainbow_r', showscale=False)),secondary_y=True) \n",
" for x in range(len(wid)):\n",
" fig5.add_trace(go.Scatter(showlegend=False, x=wid, y=np.ones(len(wid))*wid[x], marker_color='blue'),secondary_y=False)\n",
" for x in range(len(wid)): \n",
" for y in range(len(wid)): \n",
" fig5.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.1, fillcolor=\"#FF7F7F\",name=False, x0=wid[x]-beam_diameter/2, y0=wid[y]-beam_diameter/2, x1=wid[x]+beam_diameter/2, y1=wid[y]+beam_diameter/2, line_color=\"red\",secondary_y=False)\n",
"\n",
" fig5.add_trace(go.Scatter(showlegend=True, x=[-1], y=[-1],marker_size=12, marker_color='blue', name='Step '+str(np.round(step_size,3))+' nm ('+str(np.round(step_size_corr,3))+')'))\n",
" fig5.add_trace(go.Scatter(showlegend=True, x=[-1], y=[-1],marker_size=12, marker_color='#FF7F7F', name='Beam ⌀ '+ str(np.round(beam_diameter,2))+\" nm\"))\n",
" fig5.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=0.85,xanchor=\"right\",x=0.9))\n",
" fig5.add_trace(go.Scatter(showlegend=False, x = scans*step_size_corr*np.ones(len(yyy)), y=yyy, opacity=1,mode='markers',marker_symbol = \"triangle-down\",marker=dict(size=20, color=yyy, colorscale='rainbow_r', showscale=False)),secondary_y=True) \n",
" fig5.update_yaxes(title_text=\"Overlap %\", range=[0, 100], showticklabels=True, tickvals = [0, 20, 40,50, 60,70, 80, 90, 100], secondary_y=True)\n",
" fig5.update_layout(title={'text': \"Sample\",'y':0.95, 'x':0.10,'xanchor': 'left','yanchor': 'top'})\n",
" fig5.update_layout(width=430, height=380, margin =dict(l=30, r=30, t=10, b=0))\n",
"\n",
" \n",
" ### DETECTOR PLANE ##########################################\n",
" fig6 = go.Figure() \n",
" fig6.update_xaxes(title_text=\"Pixels\", range=[1, num_pixels], zeroline=False)\n",
" fig6.update_yaxes(range=[1, num_pixels], showticklabels=False,)\n",
" for x in np.linspace(1,int(np.round(covered_alfas)),int(np.round(covered_alfas))):\n",
" fig6.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", x0=num_pixels/2-x*beam_diameter_pix, y0=num_pixels/2-x*beam_diameter_pix, x1=num_pixels/2+x*beam_diameter_pix, y1=num_pixels/2+x*beam_diameter_pix,line_color=\"gray\")\n",
" fig6.add_trace(go.Scatter(showlegend=False,x=[num_pixels/2],y=[num_pixels/2-x*beam_diameter_pix],mode=\"lines+text\", text=str(int(2*x))+\"α\",textposition=\"top center\"))\n",
" \n",
" fig6.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", fillcolor=\"#FF7F7F\", x0=num_pixels/2-beam_diameter_pix/2, y0=num_pixels/2-beam_diameter_pix/2, x1=num_pixels/2+beam_diameter_pix/2, y1=num_pixels/2+beam_diameter_pix/2,line_color=\"#FF7F7F\")\n",
" fig6.add_annotation(x=num_pixels/2-beam_diameter_pix/2, y=num_pixels/2, ax=num_pixels/2+beam_diameter_pix/2, ay=num_pixels/2, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=3,arrowsize=1,arrowwidth=1,arrowcolor='black')\n",
" fig6.add_annotation(x=num_pixels/2+beam_diameter_pix/2,y=num_pixels/2, ax=num_pixels/2-beam_diameter_pix/2, ay=num_pixels/2, xref='x',yref='y',axref='x',ayref='y', text='', showarrow=True,arrowhead=3,arrowsize=1,arrowwidth=1,arrowcolor='black')\n",
" fig6.add_annotation(x=num_pixels/2, y=num_pixels/2, text=str(np.round(beam_diameter_pix,1))+\" pix\", showarrow=False, yshift=10)\n",
" fig6.add_trace(go.Scatter(x=[1,1.5,1,1.5], y=[1,1,1.5,1.5], name='Pix ∠ ' +str(np.round(pixel_angle,2))+' mrad'))\n",
" fig6.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=0.85,xanchor=\"right\",x=1))\n",
" # fig6.update_layout(title={'text': \"Detector\",'y':0.925, 'x':0.10,'xanchor': 'left','yanchor': 'top'})\n",
" fig6.update_layout(xaxis = dict(tickmode = 'array', tickvals = [1, num_pixels/4, num_pixels/2, 3*num_pixels/4, num_pixels])) \n",
" fig6.update_layout(width=350, height=280, margin = dict(l=40, r=60, t=0, b=0))\n",
"\n",
" \n",
" ssb_cl, kolik = pty.cl4ssb(detector_cover_a_all)\n",
" ### MICROSCOPE SCHEME ##########################################\n",
" width = 500 \n",
" det_width = 400\n",
" y_down = np.log(np.max(opt.cameralengths()))\n",
" reduc = 0.4\n",
" \n",
" fig8 = go.Figure() \n",
" fig8.update_xaxes(range=[-width, width], showticklabels=False,zeroline=False)\n",
" fig8.update_yaxes(range=[-y_down, reduc*y_down], showticklabels=False,)\n",
"\n",
" fig8.add_shape(type=\"rect\",xref=\"x\", yref=\"y\",opacity=0.7, fillcolor=\"red\", x0=-100, y0=reduc*0.8*y_down, x1=100, y1=reduc*0.9*y_down,line_color=\"red\")\n",
" fig8.add_trace(go.Scatter(showlegend=False, x=[-150, -2*semi_angle, None, 2*semi_angle, 150], y=[reduc*0.8*y_down,reduc*0.8*y_down,None,reduc*0.8*y_down, reduc*0.8*y_down],mode='lines', line=dict(color='black',width=7)))\n",
" fig8.add_annotation(x=-0.7*width, y=reduc*0.8*y_down, text=\"<b>Aperture </b>\"+str(aperture), showarrow=False, yshift=2)\n",
" fig8.add_annotation(x=semi_angle, y=reduc*0.7*y_down, text=\"α \"+str(np.round(semi_angle,2))+\" mrad (\"+str(np.round(semi_angle_corr,2))+\")\", showarrow=True, ax=100, ay=0, yshift=0)\n",
"\n",
" if defocus > 0:\n",
" defo = np.log(defocus)/100\n",
" else:\n",
" defo = 0 \n",
"\n",
" # Beam\n",
" fig8.add_trace(go.Scatter(showlegend=False, x=[0, 2*semi_angle, 0, 0], y=[defo*y_down, reduc*0.8*y_down, reduc*0.8*y_down, defo*y_down], mode='lines',fill=\"toself\", fillcolor=\"#FF7F7F\", opacity=0.7,line=dict(color='#FF7F7F',width=1)))\n",
" fig8.add_trace(go.Scatter(showlegend=False, x=[0, 0, -2*semi_angle, 0], y=[defo*y_down, reduc*0.8*y_down, reduc*0.8*y_down, defo*y_down],mode='lines', fill=\"toself\", fillcolor=\"red\", opacity=0.7,line=dict(color='red',width=1)))\n",
" fig8.add_annotation(x=0, y=reduc*0.5*y_down,text=\"Current \"+str(np.round(current,1))+\" pA\", showarrow=True,ax=100, ay=0, yshift=0)\n",
" \n",
" if defocus > 0:\n",
" fig8.add_annotation(x=-0.05*width, y=0, ax=-0.05*width, ay=defo*y_down, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=1,arrowsize=1,arrowwidth=1,arrowcolor='black')\n",
" fig8.add_annotation(x=-0.05*width, y=defo*y_down, ax=-0.05*width, ay=0, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=1,arrowsize=1,arrowwidth=1,arrowcolor='black')\n",
" fig8.add_annotation(x=-0.3*width, y=0.05*y_down,text=\"Δf \"+str(np.round(defocus,1))+\" nm\", showarrow=False)\n",
"\n",
" # Sample\n",
" fig8.add_trace(go.Scatter(showlegend=False, x=[-0.8*width, 0.8*width], y=[0, 0], line=dict(color='magenta',width=7), opacity=0.5))\n",
" fig8.add_annotation(x=-0.8*width, y=0,text=\"<b>Sample</b>\", showarrow=False, yshift=15)\n",
" fig8.add_trace(go.Scatter(showlegend=False, x=[-np.log(fov)/20*width, np.log(fov)/20*width, np.log(fov)/20*width, -np.log(fov)/20*width, -np.log(fov)/20*width], y=[-0.01*y_down, -0.01*y_down, 0.01*y_down, 0.01*y_down, -0.01*y_down],mode='lines', fill=\"toself\", fillcolor=\"black\", line=dict(color='black',width=1), opacity=0.5))\n",
" fig8.add_annotation(x=0.35*width, y=0.05*y_down,text=\"FoV \"+str(np.round(fov,2))+\" nm\", showarrow=False, ax=50, ay=-30, yshift=0)\n",
" \n",
" # Detector\n",
" y = -np.log(cl)*np.ones(int(num_pixels)+1)\n",
" x = np.linspace(-det_width,det_width, int(num_pixels)+1)\n",
" fig8.add_trace(go.Scatter(showlegend=False, x=x, y=y, mode='markers', marker_symbol=\"line-ns\",marker_line_width=0.5))\n",
" fig8.add_annotation(x=-0.8*width, y=-np.log(cl),text=\"<b>Detector</b>\", showarrow=False,align= 'left', yshift=15)\n",
" \n",
" # Scattering\n",
" fig8.add_trace(go.Scatter(showlegend=False, x=[0, det_width, -det_width, 0], y=[defo*y_down, -np.log(cl), -np.log(cl), -np.log(cl), defo*y_down],mode='lines', fill=\"toself\", fillcolor=\"gray\", opacity=0.1,line=dict(color='black',width=1)))\n",
" fig8.add_trace(go.Scatter(showlegend=False, x=[0, -det_width, det_width, 0], y=[defo*y_down, -np.log(cl), -np.log(cl), -np.log(cl), defo*y_down],mode='lines', fill=\"toself\", fillcolor=\"gray\", opacity=0.1,line=dict(color='black',width=1)))\n",
" # BF disk\n",
" fig8.add_trace(go.Scatter(showlegend=False, x=[0, det_width/covered_alfas, -det_width/covered_alfas, 0], y=[defo*y_down, -np.log(cl), -np.log(cl), -np.log(cl), defo*y_down],mode='lines', fill=\"toself\", fillcolor=\"#FF7F7F\", opacity=0.7,line=dict(color='#FF7F7F',width=1)))\n",
" fig8.add_trace(go.Scatter(showlegend=False, x=[0, -det_width/covered_alfas, det_width/covered_alfas, 0], y=[defo*y_down, -np.log(cl), -np.log(cl), -np.log(cl), defo*y_down],mode='lines', fill=\"toself\", fillcolor=\"red\", opacity=0.7,line=dict(color='#FF7F7F',width=1)))\n",
" \n",
" fig8.add_trace(go.Scatter(showlegend=False, x=[-width, width], y=[-np.log(ssb_cl), -np.log(ssb_cl)], opacity=0.8, line=dict(color='green',width=3)))\n",
" fig8.add_annotation(x=-0.7*width, y=-np.log(ssb_cl),text=\"<b>REC for SSB</b>\", showarrow=False,align= 'left', yshift=-15)\n",
" \n",
" # Cover\n",
" fig8.add_annotation(x=0, y=-1.05*np.log(cl), ax=det_width, ay=-1.05*np.log(cl), xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=3,arrowsize=1,arrowwidth=1,arrowcolor='black')\n",
" fig8.add_annotation(x=det_width,y=-1.05*np.log(cl), ax=0, ay=-1.05*np.log(cl), xref='x',yref='y',axref='x',ayref='y', text='', showarrow=True,arrowhead=3,arrowsize=1,arrowwidth=1,arrowcolor='black')\n",
" fig8.add_annotation(x=det_width/2, y=-1.05*np.log(cl), text=\"Cover \"+str(np.round(detector_cover,1)) + \" mrad;\" + str(np.round(covered_alfas,1))+\"α\", showarrow=False, yshift=-10, xshift=-10)\n",
"\n",
" # CLs\n",
" fig8.add_annotation(x=0.9*width, y=-np.log(1.5),text=\"CL cm\", showarrow=False, yshift=0)\n",
" for x in opt.cameralengths():\n",
" fig8.add_trace(go.Scatter(showlegend=False, x=[-width, width], y=[-np.log(x), -np.log(x)], opacity=0.3, line=dict(color='gray',width=1)))\n",
" fig8.add_annotation(x=0.9*width, y=-np.log(x),text=str(x), showarrow=False, yshift=8)\n",
"\n",
" fig8.update_xaxes(title_text=\"\")\n",
" # fig8.update_layout(title={'text': \"Microscope\" ,'y':1, 'x':0.10,'xanchor': 'left','yanchor': 'top'})\n",
" fig8.update_layout(width=350, height=550, margin = dict(l=10, r=30, t=0, b=0))\n",
" fig8.update_layout(plot_bgcolor='white')\n",
" \n",
" \n",
" ### FINAL CHECKS ########################################## \n",
" align3 = dict(layout=widgets.Layout(width='250px') , style = {'description_width': '150px','button_width': \"100px\"}, disabled=True,) \n",
" \n",
" check1 = widgets.Valid(value= bool(overlap > 60), description='Overlap > 60 %', **align3)\n",
" check2 = widgets.Valid(value= bool(step_size_corr*10 > (wavelength * cl_det)/(num_pixels*size_pixel/1e6)/1e4), description='Ptycho pix < step size', **align3)\n",
" check3 = widgets.Valid(value= bool(beam_diameter/2 < probe_window/2), description='Beam ⌀ < window/2', **align3) \n",
" \n",
" electron_dose = widgets.Label(value = f'Electron dose (e/Å2) '+ str(np.round(dose,1)), **align3) \n",
" checks = widgets.VBox([widgets.Label('Final checks'),check1,check2, check3,electron_dose]) \n",
" checks.layout = widgets.Layout(border='solid 1px gray',margin='10px 10px 10px 10px', padding='10px 10px 10px 10px')\n",
"\n",
" \n",
" ### METHODS ########################################## \n",
" if method == 'direct':\n",
" \n",
" ### CAMERA LENGTH GRAPH ##########################################\n",
" fig4 = make_subplots(specs=[[{\"secondary_y\": True}]])\n",
" fig4.add_trace(go.Scatter(showlegend=False, x=opt.cameralengths(), y=detector_cover_all, marker_color='gray'), secondary_y=False,)\n",
" fig4.add_trace(go.Scatter(showlegend=False, x=opt.cameralengths(), y=detector_cover_a_all,marker_color='gray'), secondary_y=True,)\n",
"\n",
" fig4.add_trace(go.Scatter(x=np.array(cl), y=np.array(covered_alfas), marker_size=12, marker_color='red', name = str(np.round(detector_cover,1))+ \" mrad; \"+str(np.round(covered_alfas,2))+ \" α\"), secondary_y=True,) \n",
" fig4.add_trace(go.Scatter(x=np.array(ssb_cl), y=np.array(kolik),marker_size=12, marker_color='green', name = \"Rec SSB CL\"), secondary_y=True,) \n",
"\n",
" fig4.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=0.65,xanchor=\"right\",x=0.9))\n",
" # fig4.update_layout(title={'text': \"CL to α\",'y':0.93, 'x':0.12,'xanchor': 'left','yanchor': 'top'})\n",
" fig4.update_xaxes(title_text=\"Camera length (cm)\", type=\"log\", tickvals = opt.cameralengths())\n",
" fig4.update_layout(xaxis = dict(tickmode = 'array', tickvals = [1, num_pixels/4, num_pixels/2, 3*num_pixels/4, num_pixels]))\n",
" fig4.update_yaxes(title_text=\" Cover angle (<b>mrad</b>)\", secondary_y=False)\n",
" fig4.update_yaxes(title_text=\" Cover angle (<b>α</b>)\", secondary_y=True)\n",
" fig4.update_layout(xaxis = dict(tickmode = 'array', tickvals = opt.cameralengths()))\n",
" fig4.update_layout(width=800, height=225, margin =dict(l=110, r=30, t=30, b=30))\n",
" \n",
" \n",
" ### SHOWING ###\n",
" right_column = widgets.VBox([go.FigureWidget(fig),go.FigureWidget(fig5),go.FigureWidget(fig4)])\n",
" left_column = widgets.VBox([go.FigureWidget(fig8), go.FigureWidget(fig6)])\n",
" display(widgets.HBox([left_column, right_column, checks]))\n",
" \n",
" \n",
" if method == 'iterative':\n",
" \n",
" ### PROBE WINDOW ##########################################\n",
" if beam_diameter < probe_window/2:\n",
" color = \"green\"\n",
" name = 'Beam ⌀ is fine'\n",
" elif beam_diameter < probe_window:\n",
" color = \"orange\"\n",
" name = 'Beam ⌀ is quite big'\n",
" else:\n",
" color = \"red\"\n",
" name = 'Beam ⌀ is too big'\n",
"\n",
" fig7 = go.Figure() \n",
" fig7.add_shape(type=\"rect\",xref=\"x\", yref=\"y\",opacity=0.3, fillcolor=\"LightSkyBlue\", x0=probe_window/4, y0=probe_window/4, x1=3*probe_window/4, y1=3*probe_window/4,line_color=\"LightSkyBlue\")\n",
" fig7.add_trace(go.Scatter(x=np.array(probe_window/2), y=np.array(probe_window/2), showlegend=False, marker_color=\"LightSkyBlue\"))\n",
" fig7.add_trace(go.Scatter(x=np.array(probe_window/2), y=np.array(probe_window/2), name=name, showlegend=True, marker_color=color))\n",
" fig7.add_annotation(x=probe_window/2, y=3*probe_window/4, text=\"<b>Usable area </b>\", showarrow=False, yshift=-15)\n",
" fig7.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.9, fillcolor=color, x0=probe_window/2-beam_diameter/2, y0=probe_window/2-beam_diameter/2, x1=probe_window/2+beam_diameter/2, y1=probe_window/2+beam_diameter/2, line_color=color,)\n",
" fig7.update_xaxes(title_text=\"Probe window (nm)\", range=[0, probe_window], tickvals = [0, np.round(probe_window/4,2), np.round(probe_window/2,2), np.round(3*probe_window/4,2), np.round(probe_window,2)-0.01])\n",
" fig7.update_yaxes(range=[0, probe_window], showticklabels=False,)\n",
" fig7.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=0.9,xanchor=\"right\",x=1))\n",
" fig7.update_layout(title={'text': \"Probe window \",'y':0.925, 'x':0.10,'xanchor': 'left','yanchor': 'top'})\n",
" fig7.update_layout(width=400, height=380, margin =dict(l=30, r=30, t=10, b=0)) \n",
" \n",
" ### CAMERA LENGTH TABLE ########################################## \n",
" dictionary = {}\n",
" tab = np.array([np.round(ptycho_pixel_size_all,2),np.round(detector_cover_all,1), np.round(detector_cover_a_all,1), np.round(max_defocus_all,1), np.array(opt.cameralengths())])\n",
" \n",
" align6 = dict(layout=widgets.Layout(width='50px') , style = {'description_width': '0px','button_width': \"33px\"}, disabled=True,)\n",
" align7 = dict(layout=widgets.Layout(width='130px') , style = {'description_width': '0px','button_width': \"110px\"}, disabled=True,)\n",
" for i in range(0,12):\n",
" button_style = 'success'\n",
" data = tab[:,int(i)] # 0. ptycho pix, 1.det cov 2.det cov a, 3.max def, 4.cl\n",
" \n",
" if data[1] > 1000*math.radians(10):\n",
" button_style = 'danger' \n",
" if data[0] > step_size_corr*10:\n",
" button_style = 'warning'\n",
" if data[3] < defocus:\n",
" button_style = 'danger'\n",
" if data[2] < 1:\n",
" button_style = 'warning' \n",
" \n",
" dictionary[i] = widgets.ToggleButtons(options=data, description='',button_style=button_style, **align6)\n",
" \n",
" legend = widgets.ToggleButtons(options=['Ptycho pix. (A)','Det. cover (mrad)','Det. cover (α)', 'Max. defocus (nm)','Nominal CL (cm)'], description='',button_style='', **align7) \n",
" cltab = widgets.HBox([legend,dictionary[0],dictionary[1],dictionary[2],dictionary[3],dictionary[4],dictionary[5],dictionary[6],dictionary[7],dictionary[8],dictionary[9], dictionary[10],dictionary[11]])\n",
" cltab = widgets.VBox([widgets.Label('Chose your reconstructed ptychographic pixe size, check needed defocus and set CL'), cltab])\n",
" cltab.layout = widgets.Layout(border='solid 0px gray',margin='10px 10px 10px 10px', padding='10px 10px 10px 10px')\n",
" \n",
" \n",
" \n",
" ### SHOWING ###\n",
" sample_overlap = widgets.HBox([go.FigureWidget(fig5), go.FigureWidget(fig7)]) \n",
" right_column = widgets.VBox([go.FigureWidget(fig), sample_overlap, cltab ]) \n",
" left_column = widgets.VBox([go.FigureWidget(fig8), go.FigureWidget(fig6)]) \n",
" \n",
" display(widgets.HBox([left_column, right_column, checks]))\n",
" \n",
" return \n",
" \n",
"gui = interactive_output(ptycho_interact, {\"beam\": beam, \"aperture\": aperture, \"probe\": probe, \"cl\": cl, \"matrix\": matrix, \"defocus\": defocus, \"mag\": mag, \"camera\": camera,\n",
" \"binning\": binning, \"dwell_time\": dwell_time, \"restriction\": restriction, \"method\": method, \"ssb_freq_length\": ssb_freq_length, \"scans\": scans}) "
]
},
{
"cell_type": "markdown",
"id": "1e474cb7-5fd4-4113-a3fa-ddf5ca152ce5",
"metadata": {},
"source": [
"![title](./ptychoscopy_logo.png)\n",
"\n",
"Jupyter based interactive data acquisition tool designed for appropriate ptychographic data collection. It computes nessesary characteristics which play crutial role in final data reconstruction. \n",
"You can chose of **Direct methods** (mainly Single Side Band ptychography) or **Iterative reconstruction** which takes probe defocus into account. With this tool, you can check for probe CTF, scanning step size, probe overlap, detector camera length a proper angular range collection, reconstructed probe size and many more.\n",
"### Calibrations\n",
"Every STEM has its own combination of parameters (magnifications, probe currents, aperture angles, camera lengths or detectors). These have to be taken into account for proper data acquisition design. Before first use, fill your own values into the file **calibrations.xlsx**. Instructions how to fill are in the sheet called HELP.\n",
"\n",
"### Controls\n",
"List of controls consists of all parameters needed for proper dataset acquisition design:\n",
"\n",
"| Beam | | Scanning | | Camera length | | Detection | |\n",
"|------ | ------| ------| ------| ------| ------| ------| ------|\n",
"| **Aperture**| probe forming aperture gives probe semi-angle (α) | **Magnification**| controls image field of view | **Nominal CL** | sample to detector distance gives maximal detected angle as well as angular sampling | **Detector** | detector used for data collection | \n",
"| **Energy** | energy of primary electron beam in keV ... gives final pixel size | **Matrix** | gives beam position to position distance + beam defocus = beam overlap | **Use PAAR** | Pumping Aperture Anglar Restriction, build-in aperture may limit maximal scattering angles for shortest camera lengths |**Binning** | reduction in pixel array size usually increas maximum frame rate |\n",
"| **Probe** | probe setting together with chosen probe forming aperture give probe current| | | | | **Dwell time**|single position beam time ... check your detector characteristics |\n",
"| **Defocus** | moves focus out of the sample plane - enlarges beam diameter | | | | | | |\n",
"\n",
"### Start the interactive gui by running the field\n",
"```python\n",
"display(widgets.HBox([controls, gui]))\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 124,
"id": "7937f054-fcd0-4e67-a20f-7696f5903a94",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b09b238a260d4425ab717013806e2bce",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(HBox(children=(VBox(children=(Label(value=''), VBox(children=(Label(value='Beam'), Dropdown(des…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"display(widgets.HBox([controls, gui]))"
]
},
{
"cell_type": "markdown",
"id": "e46226d7-fc21-4c83-8363-225ecd92f28e",
"metadata": {},
"source": [
"#### Instructions for **SSB**\n",
" \n",
"- set beam energy\n",
"- set probe current\n",
"- set detector (consider binning and minimal dwell time)\n",
"- set defocus to 0 \n",
"- set probe angle -> get needed CTF\n",
"- set magnification -> get FoV\n",
"- set scanning matrix -> get sampling\n",
"- set CL -> get detector cover (just over 1 alfa) \n",
"- check final dose\n",
"\n",
"#### Instructions for **Iterative reconstructions**\n",
"\n",
"- set beam energy\n",
"- set probe current\n",
"- set detector (consider binning and minimal dwell time)\n",
"- set probe angle -> get reconstructed pixel size\n",
"- set magnification -> get FoV\n",
"- set scanning matrix, defocus -> get sampling and overlap\n",
"- set CL to get final pixel size (table)\n",
"- check warnings in orange and danger in red\n",
"- check final dose\n",
"\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.13"
},
"varInspector": {
"cols": {
"lenName": 16,
"lenType": 16,
"lenVar": 40
},
"kernels_config": {
"python": {
"delete_cmd_postfix": "",
"delete_cmd_prefix": "del ",
"library": "var_list.py",
"varRefreshCmd": "print(var_dic_list())"
},
"r": {
"delete_cmd_postfix": ") ",
"delete_cmd_prefix": "rm(",
"library": "var_list.r",
"varRefreshCmd": "cat(var_dic_list()) "
}
},
"position": {
"height": "144.294px",
"left": "1149.02px",
"right": "19.9884px",
"top": "119.988px",
"width": "349.977px"
},
"types_to_exclude": [
"module",
"function",
"builtin_function_or_method",
"instance",
"_Feature"
],
"window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 5
}

BIN
ptychoscopy_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB