Files
ptychoscopy/ptychoScopy.ipynb
2023-11-30 18:09:59 +01:00

808 lines
50 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cells": [
{
"cell_type": "code",
"execution_count": 41,
"id": "7425242d-3c91-4c1e-a424-08625a38ee7a",
"metadata": {},
"outputs": [],
"source": [
"### Initial packages import ###################################################\n",
"import numpy as np\n",
"import scipy.constants as cons\n",
"import plotly.graph_objects as go\n",
"from copy import deepcopy\n",
"from pandas import read_excel\n",
"from IPython.display import display\n",
"from plotly.subplots import make_subplots\n",
"from ipywidgets import interactive_output, HBox, VBox, Layout, Label, Valid, ToggleButtons, RadioButtons, Dropdown, IntSlider, Checkbox\n",
"\n",
"# print(\"Numpy version \", np.__version__)\n",
"# print(\"Pandas version \", pd.__version__)\n",
"# print(\"Ipywidgets version \", widgets.__version__)\n",
"# print(\"Plotly version \", plotly.__version__)\n",
"\n",
"### Function definitions ###################################################\n",
"\n",
"calib = r'calibrations.xlsx' # 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 = 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 = 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(read_excel(self.calib,sheet_name='Probes').Probe)\n",
" probes = probes[3::]\n",
" return probes\n",
" \n",
" def magnifications(self):\n",
" excel_data = read_excel(self.calib,sheet_name='Ranges')\n",
" magnifications = list(excel_data.Magnification)\n",
" return magnifications\n",
" \n",
" def energies(self): \n",
" excel_data = read_excel(self.calib,sheet_name='Ranges')\n",
" energies = [str(e) for e in list(excel_data.BeamEnergy)]\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 = 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(read_excel(self.calib,sheet_name='Pixel').NominalCL)\n",
" return cameralengths\n",
" \n",
" def cameralengths_eff(self): \n",
" cameralengths_eff = list(read_excel(self.calib,sheet_name='Pixel').DetectorCL)\n",
" return cameralengths_eff\n",
"\n",
" def dwelltimes(self): \n",
" excel_data = read_excel(self.calib,sheet_name='Ranges')\n",
" dwelltimes = [str(e) for e in list(excel_data.DwellTime)]\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 = read_excel(calib, sheet_name='Probes',header=0)\n",
" excel_line = excel_data[excel_data.Probe.isin(['SemiAngle'])]\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 = read_excel(calib, sheet_name='Probes',header=0)\n",
" excel_line = excel_data[excel_data.Probe.isin(['SemiAngleCorr'])]\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 = 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 = 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 = 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 = 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 = read_excel(calib,sheet_name='Pixel')\n",
" excel_line = excel_data[excel_data.NominalCL.isin([cl])]\n",
" self.cl_detector = excel_line['DetectorCL']\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(read_excel(calib,sheet_name='Ranges').StepSizeCorr)]\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 = read_excel(calib, sheet_name='Probes')\n",
" excel_line = excel_data[excel_data.Probe.isin(['Def0Diameter'])]\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 = read_excel(calib, sheet_name='Probes')\n",
" excel_line = excel_data[excel_data.Probe.isin(['Def0Diameter'])]\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 = read_excel(calib, sheet_name='Detector')\n",
" excel_line = excel_data[excel_data.Type.isin(['Array'])]\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(['RealSize'])]\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 = read_excel(calib, sheet_name='Detector')\n",
" excel_line = excel_data[excel_data.Type.isin(['Array'])]\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 = read_excel(calib, sheet_name='Detector')\n",
" excel_line = excel_data[excel_data.Type.isin(['RealSize'])]\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 = 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 = read_excel(calib,sheet_name='Pixel')\n",
" pump_apert = [str(e) for e in list(excel_data.PAAR)]\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 = 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 computing of various parameters.\"\"\"\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) {\"{:.2f}\".format(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) {\"{:.2f}\".format(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 CL (cm) {\"{:.1f}\".format(pty.get_cl_detector(caller.new))}' \n",
" return cl_det_res.value\n",
" \n",
" \n",
"inte = interaction() \n"
]
},
{
"cell_type": "code",
"execution_count": 68,
"id": "8055b802-cf83-4250-aea9-54e3e6b73db0",
"metadata": {},
"outputs": [],
"source": [
"### CONTROLS ##########################################\n",
"align = dict(layout=Layout(width='385px') , style = {'description_width': '80px','button_width': \"35px\"}, button_style='primary',disabled=False,)\n",
"align3 = dict(layout=Layout(width='230px') , style = {'description_width': '80px','button_width': \"35px\"}, button_style='primary', disabled=False,)\n",
"to_right = dict(layout=Layout(display=\"flex\", justify_content=\"flex-end\", width=\"95%\", ))\n",
"to_right2 = dict(layout=Layout(display=\"flex\", justify_content=\"flex-end\", width=\"35%\", ))\n",
"\n",
"### Main controls ###\n",
"beam = Dropdown(options=opt.energies(),value=200,description='Energy (keV)', **align3)\n",
"aperture = ToggleButtons(options=opt.apertures(), value='30um', description='Aperture', **align, tooltips=['', ''])\n",
"probe = ToggleButtons(options=opt.probes(), value='8C', description='Probe', **align, tooltips=['', ''])\n",
"defocus = IntSlider(description='Defocus (nm)', value=0, min=0, max=1000, step=1, continuous_update=False, **align )\n",
"defocus.style.handle_color = 'blue'\n",
"mag = ToggleButtons(options=opt.magnifications(),value=3,description='Mag. (Mx)', **align) \n",
"matrix = ToggleButtons(options=opt.mappings(), value=2048, description='Matrix', **align, tooltips=['', ''])\n",
"cl = ToggleButtons(options=opt.cameralengths(), value=12, description='Nominal (cm)', **align, tooltips=['', ''])\n",
"camera = Dropdown(options=opt.detectors(), description='Detector', **align3, tooltips=['', ''])\n",
"restriction = ToggleButtons(options=[('NO',False), ('YES',True)], description='Use PAAR',**align3, tooltips=['', ''])\n",
"binning = 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 = ToggleButtons(options=opt.dwelltimes(), value=10, description='Dwell time (μs)', **align, tooltips=['', ''])\n",
"\n",
"### Small controls ###\n",
"align2 = dict(layout=Layout(width='200px') , style = {'description_width': '100px','button_width': '100px'}, disabled=False,)\n",
"method = ToggleButtons(options=[('Direct methods','direct'), ('Iterative methods','iterative')], description='', **align2, button_style='', tooltips=['SSB', 'PIE, MLc, DM'])\n",
"ctf_xaxis = RadioButtons(options=['mrad', 'A'], description='CTF-SSB x-axis:', **align2) \n",
"scans = RadioButtons(options=[4,6,8,10],description='Beam positions:',continuous_update=False, **align2)\n",
"\n",
"\n",
"cl_check_laa = Checkbox(value=True, description='Low angle approximation', disabled=False, indent=False,) # Low angle approximation check - scattering angle < 10 deg\n",
"cl_check_pix = Checkbox(value=True, description='Ptycho pixel < step size', disabled=False, indent=False,) # Reconstructed pixel size < scanning step size \n",
"cl_check_def = Checkbox(value=True, description='Beam fits in probe window', disabled=False, indent=False,) # Is probe window big enough to accomodate defocused probe?\n",
"cl_check_nbf = Checkbox(value=True, description='Detector cover < 1α', disabled=False, indent=False,) # Detector cover is lower than 1 α; orange\n",
"\n",
"\n",
" \n",
"\n",
"\n",
"\n",
"\n",
"\n",
"### Live update ### \n",
"beam_res = Label(value = f'Wavelength (pm) '+ str(\"{:.2f}\".format(pty.get_wavelength(beam.value)*1e12)), **to_right2)\n",
"beam.observe(inte.show_wavelength, names='value')\n",
"camera_res = Label(value = f'Full pixel array '+ str(\"{:.0f}\".format(pty.get_det_resolution(camera.value))), **to_right2)\n",
"camera.observe(inte.show_detector, names='value')\n",
"pixel_size_res = 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 = 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 = 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 = Label(value = f'Field of view (nm) '+ str(\"{:.2f}\".format(pty.get_fov(mag.value))), **to_right)\n",
"mag.observe(inte.show_fov, names='value') \n",
"dwell_time_res = Label(value = f'Frame rate (kHz) '+ str(\"{:.2f}\".format(pty.get_aq_frec(dwell_time.value))),**to_right)\n",
"dwell_time.observe(inte.show_frame_rate, names='value') \n",
"cl_det_res = Label(value = f'Detector CL (cm) '+ str(\"{:.1f}\".format(pty.get_cl_detector(cl.value))),**to_right2)\n",
"cl.observe(inte.show_cd_det, names='value') \n",
"\n",
"### Controls layout ###\n",
"box_layout = Layout(border='solid 2px #1976D2',margin='0px 0px 0px 0px', padding='5px 5px 5px 5px')\n",
"col1 = VBox([Label('Beam'), HBox([beam ,beam_res]), aperture, probe, defocus], layout=box_layout) # aperture_res, aperture_res2,\n",
"col2 = VBox([Label('Scanning'), mag, fov_res, matrix], layout=box_layout)\n",
"col3 = VBox([Label('Camera length'), cl, HBox([restriction, cl_det_res])], layout=box_layout)\n",
"col4 = VBox([Label('Detection'), HBox([camera, camera_res]), pixel_size_res, binning, dwell_time, dwell_time_res], layout=box_layout)\n",
"\n",
"small_control = VBox([Label('Graph controls'),method, ctf_xaxis, scans, VBox([Label('Camera length check list'), cl_check_laa, cl_check_pix, cl_check_def, cl_check_nbf])], layout = Layout(border='dashed 0px gray',margin='32px 30px 00px 10px', padding='5px 5px 5px 5px'))\n",
"controls = HBox([VBox([Label(''), col1, col2, col3, col4]), small_control])\n",
"\n",
"def ptycho_interact(beam, aperture, probe, cl, matrix, defocus, mag, camera, binning, dwell_time, restriction, method, ctf_xaxis, scans, cl_check_laa, cl_check_pix, cl_check_def, cl_check_nbf):\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",
" xx = 2*wavelength/(np.sin(semi_angle_corr*omega/1000))/100\n",
" if ctf_xaxis == '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 ctf_xaxis == '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=xx, y=pctf, marker_color='red', name=str(np.round(semi_angle_corr,2))+ ' mrad',))\n",
" fig.update_xaxes(title_text=\"Real space distance (Å)\", range=[0.0001, 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], showgrid=False, zeroline=False)\n",
" fig5.update_yaxes(range=[0, scans*step_size_corr],showgrid=False, showticklabels=False)\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(10*step_size,3))+' Å ('+str(np.round(10*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(10*beam_diameter,2))+\" Å\"))\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",
" \n",
" \n",
" fig5.update_yaxes(title_text=\"Overlap %\", range=[0, 100],showgrid=False, 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",
" if restriction == True:\n",
" fig8.add_trace(go.Scatter(showlegend=False, x=[-250, -4*semi_angle, None, 4*semi_angle, 250], y=[-reduc*0.2*y_down,-reduc*0.2*y_down,None,-reduc*0.2*y_down, -reduc*0.2*y_down],mode='lines', line=dict(color='black',width=7)))\n",
" fig8.add_annotation(x=-0.35*width, y=-reduc*0.2*y_down,text=\"<b>PAAR</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=570, margin = dict(l=10, r=30, t=20, b=0))\n",
" fig8.update_layout(plot_bgcolor='white')\n",
" \n",
" \n",
" ### FINAL CHECKS ########################################## \n",
" align3 = dict(layout=Layout(width='200px') , style = {'description_width': '150px','button_width': \"100px\"}, disabled=True,) \n",
" \n",
" check1 = Valid(value= bool(overlap > 60), description='Overlap > 60 %', **align3)\n",
" check2 = Valid(value= bool(step_size_corr*10 > (wavelength * cl_det)/(num_pixels*size_pixel/1e6)/1e4), description='Ptycho pix < step size', **align3)\n",
" check3 = Valid(value= bool(beam_diameter/2 < probe_window/2), description='Beam ⌀ < window/2', **align3) \n",
" \n",
" electron_dose = Label(value = f'Electron dose (e/Å2) '+ str(np.round(dose,1)), **align3) \n",
" acquisition_time = Label(value = f'Acquisition time (s) '+ str(np.round(matrix*matrix*dwell_time/1e6,1)), **align3) \n",
" focusdepth = Label(value = f'Depth of focus (nm) '+ str(np.round(wavelength/(semi_angle_corr/1000)**2/1000,1)), **align3) \n",
"\n",
"\n",
" ### METHODS ########################################## \n",
" if method == 'direct':\n",
" \n",
" \n",
" ssb_sampling = Label(value = f'Recommended sampling (Å) '+ str(np.round(xx[-1]/3,2)), **align3) \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",
" 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",
" 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=\"Nominal 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 (mrad)\", range=[0, 1.1*np.max(detector_cover_all)], secondary_y=False)\n",
" fig4.update_yaxes(title_text=\" Cover angle (α)\", range=[0, 1.1*np.max(detector_cover_a_all)], showgrid=False, 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",
" checks = VBox([Label('Final checks'), electron_dose, ssb_sampling, focusdepth, acquisition_time]) \n",
" checks.layout = Layout(border='dashed 1px gray',margin='30px 5px 5px 5px', padding='10px 10px 10px 10px')\n",
" \n",
" \n",
" ### SHOWING ###\n",
" right_column = VBox([go.FigureWidget(fig),go.FigureWidget(fig5),go.FigureWidget(fig4)])\n",
" left_column = VBox([go.FigureWidget(fig8), go.FigureWidget(fig6)])\n",
" display(HBox([left_column, right_column, checks]))\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" if method == 'iterative':\n",
" \n",
" checks = VBox([Label('Final checks'),check1, check2, check3,electron_dose,focusdepth, acquisition_time]) \n",
" checks.layout = Layout(border='dashed 1px gray',margin='30px 5px 5px 5px', padding='10px 10px 10px 10px')\n",
" \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=Layout(width='50px') , style = {'description_width': '0px','button_width': \"33px\"}, disabled=True,)\n",
" align7 = dict(layout=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 cl_check_laa == True:\n",
" if data[1] > 1000*np.radians(10):\n",
" button_style = 'danger' \n",
" \n",
" if cl_check_pix == True: \n",
" if data[0] > step_size_corr*10:\n",
" button_style = 'danger'\n",
" \n",
" if cl_check_def == True: \n",
" if data[3] < defocus:\n",
" button_style = 'danger'\n",
" \n",
" if cl_check_nbf == True: \n",
" if data[2] < 1:\n",
" button_style = 'danger' \n",
" \n",
" dictionary[i] = ToggleButtons(options=data, description='',button_style=button_style, **align6)\n",
" \n",
" legend = ToggleButtons(options=['Ptycho pix. (Å)','Det. cover (mrad)','Det. cover (α)', 'Max. defocus (nm)','Nominal CL (cm)'], \n",
" tooltips=['Dependent on: detector, beam energy, camera length',\n",
" 'Dependent on: detector, camera length',\n",
" 'Dependent on: detector, camera length, probe semi-angle',\n",
" 'Dependent on: detector, binning, beam energy, camera length, zero defocus beam diameter, probe semi-angle',\n",
" 'Just nominal camera length',\n",
" ],button_style='', **align7) \n",
" \n",
" \n",
" \n",
" \n",
" cltab = 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 = VBox([Label('Chose your reconstructed ptychographic pixe size, check needed defocus and set CL'), cltab])\n",
" cltab.layout = Layout(border='solid 0px gray',margin='10px 10px 10px 10px', padding='10px 10px 10px 10px')\n",
" \n",
" \n",
" \n",
" ### SHOWING ###\n",
" sample_overlap = HBox([go.FigureWidget(fig5), go.FigureWidget(fig7)]) \n",
" right_column = VBox([go.FigureWidget(fig), sample_overlap, cltab ]) \n",
" left_column = VBox([go.FigureWidget(fig8), go.FigureWidget(fig6)]) \n",
" \n",
" display(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, \"ctf_xaxis\": ctf_xaxis, \"scans\": scans,\n",
" \"cl_check_laa\":cl_check_laa, \"cl_check_pix\": cl_check_pix, \"cl_check_def\": cl_check_def, \"cl_check_nbf\": cl_check_nbf}) "
]
},
{
"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",
"\n",
"For more info go to https://gitlab.psi.ch/em-and-diffraction/low-dose-electron-ptychography/ptychoscopy/-/wikis/ptychoScopy\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(HBox([controls, gui]))\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 69,
"id": "7937f054-fcd0-4e67-a20f-7696f5903a94",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "0d132191d4f0427aaa01278a955425f0",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(HBox(children=(VBox(children=(Label(value=''), VBox(children=(Label(value='Beam'), HBox(childre…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"display(HBox([controls, gui]))"
]
}
],
"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
}