diff --git a/.ipynb_checkpoints/ptychoScopy-checkpoint.ipynb b/.ipynb_checkpoints/ptychoScopy-checkpoint.ipynb
index 1c53730..dde1a93 100644
--- a/.ipynb_checkpoints/ptychoScopy-checkpoint.ipynb
+++ b/.ipynb_checkpoints/ptychoScopy-checkpoint.ipynb
@@ -2,93 +2,52 @@
"cells": [
{
"cell_type": "markdown",
- "id": "1e474cb7-5fd4-4113-a3fa-ddf5ca152ce5",
+ "id": "cfe429ad-a3da-4b34-a78d-2828fcfe5f49",
"metadata": {},
"source": [
- "# ptychoScopy\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",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7ad928f6-e3a8-4a1b-a9a2-1d5993374d9a",
+ "metadata": {},
+ "source": [
+ " Code @ Radim Skoupý, PSI Villigen 2024"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "62ff068b-4918-46fd-8045-7a1f8f8cd851",
+ "metadata": {},
+ "source": [
+ "Jupyter Notebook/Lab based interactive data acquisition tool designed for appropriate ptychographic data collection. It consists of **SSB** (Single Side Band ptychography) or **full-field ITR** (iterative reconstruction methods) tabs where method related charts may be found. With this tool, you can check the probe CTF, scanning step size, probe overlap, illumination uniformity, detector camera length a proper angular range collection, reconstructed probe size and many more. For in-detail intructions and up-to-date version visit [GitLab](https://gitlab.psi.ch/em-and-diffraction/low-dose-electron-ptychography/ptychoscopy/-/wikis/ptychoScopy) repository.\n",
+ " \n",
+ "#### Start the interactive gui by running the field called RUN ME and then\n",
"```python\n",
- "display(HBox([controls, VBox([small_controls, gui])]))\n",
- "```"
+ "display(ptychoscopy)\n",
+ "```\n",
+ "\n",
+ "#### Check installed package versions\n",
+ "```python\n",
+ "from ptychoscopy import pty\n",
+ "pty.get_versions() # run before \"display(ptychoscopy)\" field\n",
+ "```\n",
+ "\n",
+ "#### If you use ptychoScopy in your research, we kindly ask that you cite our paper:\n",
+ "Skoupy R., Mueller E., Pennycook T., Guizar-Sicairos M., Fabbri E., Poghosyan E. ptychoScopy: Users Guide for Optimal Acquisition Design with Electron Ptychography, xxxx, xx, [DOI](https://doi.org)"
]
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "9414daad-2958-4c26-8f29-8f6fe92fe992",
- "metadata": {},
- "outputs": [],
- "source": [
- "# # Used packages\n",
- "# import sys\n",
- "# print (sys.version)\n",
- "# import openpyxl\n",
- "# print(\"Openpyxl version \", openpyxl.__version__)\n",
- "# import numpy as np\n",
- "# print(\"Numpy version \", np.__version__)\n",
- "# import scipy\n",
- "# print(\"Scipy version \", scipy.__version__)\n",
- "# import plotly\n",
- "# print(\"Plotly version \", plotly.__version__)\n",
- "# import pandas\n",
- "# print(\"Pandas version \", pandas.__version__)\n",
- "# import IPython\n",
- "# print(\"IPython version \", IPython.__version__)\n",
- "# import ipywidgets\n",
- "# print(\"Ipywidgets version \", ipywidgets.__version__)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "de350192-85ae-4d38-8ed3-14ad43843e01",
- "metadata": {},
- "outputs": [],
- "source": [
- "### Initial packages import ###################################################\n",
- "import ipywidgets as widgets\n",
- "import io\n",
- "import sys\n",
- "import numpy as np\n",
- "from abtem import Probe\n",
- "import scipy.constants as cons\n",
- "from scipy.stats import norm\n",
- "import plotly.express as px\n",
- "import plotly.graph_objects as go\n",
- "from scipy.interpolate import splrep, BSpline \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, FloatSlider, Checkbox, Button, ButtonStyle, GridBox,IntSlider,Combobox, ColorPicker"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "id": "7937f054-fcd0-4e67-a20f-7696f5903a94",
+ "execution_count": 4,
+ "id": "5c5feaae-861c-4277-9dd5-aee373b3c174",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
- "model_id": "c9cf20bfd02a4b7483a582dca71bdb4e",
+ "model_id": "37bb53443b8a4d50bb614d7156907632",
"version_major": 2,
"version_minor": 0
},
@@ -101,995 +60,652 @@
}
],
"source": [
- "\n",
- "display(VBox([top_set, HBox([controls, VBox([small_controls, gui])])]))\n"
+ "display(ptychoscopy)"
]
},
{
- "cell_type": "code",
- "execution_count": 14,
- "id": "41ac78f4-8a75-4258-bfd4-539b28746088",
+ "cell_type": "markdown",
+ "id": "b2865f08-6c85-4ce9-9173-a63e738a1224",
"metadata": {},
- "outputs": [],
"source": [
- "### CONTROLS ##########################################\n",
- "ali = dict(style = {'description_width': '110px','button_width': '55px', 'font_weight': 'bold'}, button_style='', disabled = False)\n",
- "ali2 = dict(style = {'description_width': '60px' ,'button_width': '90px', 'font_weight': 'bold'}, button_style='', disabled = False)\n",
- "ali3 = dict(style = {'description_width': '110px','button_width': '45px', 'font_weight': 'bold'}, button_style='', disabled = False)\n",
- "# header = Button(description='Control panel',layout=Layout(width='auto', grid_area='header'), style=ButtonStyle(button_color='navy', font_weight= 'bold',font_size= '20px',font_variant='small-caps',text_color='white'),disabled = False)\n",
- "\n",
- "beam_set = Button(description='Electron beam settings',layout=Layout(width='95%', grid_area='beam_set'), style=ButtonStyle(button_color='#222261', font_weight= 'bold',font_size= '16px',text_color='white'),disabled = False) \n",
- "beam = Dropdown(options=opt.energies(), value=200,description='Beam energy (keV)', layout=Layout(width='95%', grid_area='beam_set1'), **ali )\n",
- "aperture_name = Label(value = 'Aperture',layout=Layout(width='95%', grid_area='aperture_name'),)\n",
- "if len(opt.apertures())>5:\n",
- " aperture = Dropdown(options=opt.apertures(), description='', layout=Layout(width='95%', grid_area='beam_set2'), **ali)\n",
- "else:\n",
- " aperture = ToggleButtons(options=opt.apertures(), description='', layout=Layout(width='95%', grid_area='beam_set2'), **ali3)\n",
- "\n",
- "probe = Dropdown(options=opt.probes(), value='8C', description='Probe', layout=Layout(width='95%', grid_area='beam_set3'), **ali)\n",
- "defocus = IntSlider(description='Defocus (nm)', value=0, min=0, max=1000, step=1, continuous_update=False, layout=Layout(width='95%', grid_area='beam_set4'), **ali)\n",
- "\n",
- "scanning_set = Button(description='Scanning parameters',layout=Layout(width='95%', grid_area='scanning_set'),style=ButtonStyle(button_color='#222261', font_weight= 'bold',font_size= '16px',text_color='white'),disabled = False)\n",
- "mag = Dropdown(options=opt.magnifications(),value=20,description='Magnification Mx', layout=Layout(width='95%', grid_area='scanning_set1'), **ali)\n",
- "matrix = Dropdown(options=opt.mappings(), value=256, description='Matrix', layout=Layout(width='95%', grid_area='scanning_set2'), **ali)\n",
- "dwell_time = Dropdown(options=opt.dwelltimes(), value=10, description='Dwell time (μs)', layout=Layout(width='95%', grid_area='scanning_set3'), **ali)\n",
- "\n",
- "camera_set = Button(description='Detection',layout=Layout(width='95%', grid_area='camera_set'),style=ButtonStyle(button_color='#222261', font_weight= 'bold',font_size= '16px',text_color='white'),disabled = False)\n",
- "cl = Dropdown(options=opt.cameralengths(), value=8, description='Nominal CL (cm)', layout=Layout(width='95%', grid_area='cl_set1'), **ali3)\n",
- "camera_name = Label(value = 'Detector',layout=Layout(width='95%', grid_area='camera_name'),)\n",
- "camera = ToggleButtons(options=opt.detectors(), description='', layout=Layout(width='95%', grid_area='camera_set1'), style = {'description_width': '60px','button_width': str(100/len(opt.detectors())-len(opt.detectors()))+'%', 'font_weight': 'bold'}, button_style='')\n",
- "restriction_name = Label(value = 'PAAR',layout=Layout(width='95%', grid_area='restriction_name'),)\n",
- "restriction = ToggleButtons(options=[('.',False), ('..',True)], value = False, description='',icons = ['ban','check'], layout=Layout(width='95%', grid_area='camera_set2'),style = {'description_width': '80px','button_width': '48%', 'font_weight': 'bold'}, button_style='')\n",
- "binning_name = Label(value = 'Binning',layout=Layout(width='95%', grid_area='binning_name'),)\n",
- "binning = ToggleButtons(options=[('.',1), ('2',2), ('4',4), ('8',8), ('16',16), ('24',24), ('32',32), ('48',48)], value=1, description='', icons = ['ban','',''], layout=Layout(width='95%', grid_area='camera_set3'), **ali3)\n",
- "\n",
- "beam_res = Label(value = f'λ (pm) '+ str(\"{:.1f}\".format(pty.get_wavelength(beam.value)*1e12)),layout=Layout(width='auto', grid_area='sidebar1'),)\n",
- "beam.observe(inte.show_wavelength, names='value') \n",
- "aperture_res = Label(value = f'Semi-angle (mrad) '+ str(\"{:.1f}\".format(pty.get_angle(aperture.value))), layout=Layout(width='auto', grid_area='sidebar2'),)\n",
- "aperture.observe(inte.show_probe_angle, names='value') \n",
- "aperture_res2 = Label(value = f'corr. '+ str(\"{:.2f}\".format(pty.get_angle_corr(aperture.value))),layout=Layout(width='auto', grid_area='sidebar5'),)\n",
- "aperture.observe(inte.show_corrprobe_angle, names='value') \n",
- "fov_res = Label(value = f'FoV (nm) '+ str(\"{:.1f}\".format(pty.get_fov(mag.value))),layout=Layout(width='auto', grid_area='sidebar3'),) \n",
- "mag.observe(inte.show_fov, names='value') \n",
- "dwell_time_res = Label(value = f'Rate (kHz) '+ str(\"{:.1f}\".format(pty.get_aq_frec(dwell_time.value))),layout=Layout(width='auto', grid_area='sidebar4'),) \n",
- "dwell_time.observe(inte.show_frame_rate, names='value') \n",
- "\n",
- "\n",
- "visual_set = Button(description='Visualisation',layout=Layout(width='95%', grid_area='visual_set'),style=ButtonStyle(button_color='white', font_weight= 'bold',font_size= '16px',text_color='black'),disabled = False)\n",
- "\n",
- "file = open(\"./logo_psi.png\", \"rb\")\n",
- "image = file.read()\n",
- "logo1 = widgets.Image(value=image, format='png', layout=Layout(grid_area='logo1'))\n",
- "\n",
- "file = open(\"./logo4.png\", \"rb\")\n",
- "image = file.read()\n",
- "logo2 = widgets.Image(value=image,format='png', layout=Layout(grid_area='logo2'))\n",
- "\n",
- "method = ToggleButtons(options=[('SSB ','direct'), ('ITR ','iterative')], description='', icons = ['opera','refresh'], tooltips=['Single side band ptychography', 'Iterative reconstruction methods (PIE, ML, DM)'],\n",
- " layout=Layout(width='95%', grid_area='methods2'), style = {'button_width': '48%','font_weight': 'bold'}, button_style='', disabled = False)\n",
- "\n",
- "name1 = Button(description='Graphs (%)',layout=Layout(width='95%', grid_area='name1'),style=ButtonStyle(button_color='white', font_weight= 'bold',text_color='black'), disabled = False)\n",
- "graph_size = IntSlider(value=100,min=75,max=125,step=5, description='', layout=Layout(width='95%', grid_area='gr_size2'), button_style='primary',disabled=False,)\n",
- "\n",
- "chart = ToggleButtons(options=[('L ','micr'), ('R ','dedic'),('L+R ','both')],value = 'both',icons = ['columns','columns','columns'], description='',\n",
- " layout=Layout(width='95%', grid_area='charts'), style = {'button_width': '30%', 'font_weight': 'bold'}, button_style='',disabled=False,)\n",
- "\n",
- "controls = GridBox(children=[logo2,method, beam_set, beam,aperture_name, aperture, probe, defocus, scanning_set, mag,matrix,dwell_time, cl,camera_set, \n",
- " camera,camera_name, restriction_name, restriction, binning_name, binning, beam_res, aperture_res,aperture_res2,fov_res, dwell_time_res, graph_size,name1, chart, visual_set],\n",
- " layout=Layout(width='325px', grid_template_rows='90px 40px 35px 35px 35px 35px 35px 30px 30px 35px 35px 35px 35px 35px 35px 35px 80px 10px 75px 10px 35px 35px 35px', grid_template_columns='20% 10% 30% 15% 25%', grid_template_areas='''\n",
- " \"logo2 logo2 logo2 logo2 logo2\" \n",
- " \"methods2 methods2 methods2 methods2 methods2\"\n",
- " \"beam_set beam_set beam_set beam_set beam_set\" \n",
- " \"beam_set1 beam_set1 beam_set1 beam_set1 beam_set1\"\n",
- " \"beam_set3 beam_set3 beam_set3 beam_set3 beam_set3\"\n",
- " \"beam_set4 beam_set4 beam_set4 beam_set4 beam_set4\"\n",
- " \"aperture_name beam_set2 beam_set2 beam_set2 beam_set2\"\n",
- " \". sidebar2 sidebar2 sidebar2 sidebar5\"\n",
- " \"scanning_set scanning_set scanning_set scanning_set scanning_set\" \n",
- " \"scanning_set1 scanning_set1 scanning_set1 scanning_set1 scanning_set1\"\n",
- " \"scanning_set2 scanning_set2 scanning_set2 scanning_set2 scanning_set2\"\n",
- " \"scanning_set3 scanning_set3 scanning_set3 scanning_set3 scanning_set3\"\n",
- " \"camera_set camera_set camera_set camera_set camera_set\"\n",
- " \"cl_set1 cl_set1 cl_set1 cl_set1 cl_set1\"\n",
- " \"camera_name camera_set1 camera_set1 camera_set1 camera_set1\"\n",
- " \"restriction_name camera_set2 camera_set2 camera_set2 camera_set2\"\n",
- " \"binning_name camera_set3 camera_set3 camera_set3 camera_set3\"\n",
- " \". . . . .\"\n",
- " \". . . . .\"\n",
- " \". . . . .\"\n",
- " \"visual_set visual_set visual_set visual_set visual_set\"\n",
- " \"name1 name1 gr_size2 gr_size2 gr_size2\"\n",
- " \"charts charts charts charts charts\"\n",
- " '''))\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "### SMALL CONTROLS ##########################################\n",
- "style = {'description_width': 'initial'}\n",
- "element = Dropdown(options=opt.elements(), description='Element (ITR)', layout=Layout(width='95%', grid_area='ctf_element'))\n",
- "ctf_xaxis_name = Label(value = 'x-axis',layout=Layout(width='95%', grid_area='ctf_xaxis_name'),)\n",
- "ctf_xaxis = ToggleButtons(options=['α','mrad', 'Å'], layout=Layout(grid_area='ctxaxis'), style = {'button_width': '30%'}, disabled=False)\n",
- "overlap_fig = ToggleButtons(options=['Geometrical','Intensity'], layout=Layout(grid_area='overlap_fig'), style = {'button_width': '45%'}, disabled=False)\n",
- "beam_pos = IntSlider(value=4, min=4, max=16, step=2, description='Add beams:', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d', layout=Layout(grid_area='beam_pos', width = '100%'))\n",
- "\n",
- "fov_show = FloatSlider(value=0.3, min=0.1, max=10, step=0.1, description='FoV (nm):', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='.1f', layout=Layout(grid_area='fov_show', width = '100%'))\n",
- "top_set = Button(description='',layout=Layout(width='%', grid_area='scanning_set'), style=ButtonStyle(button_color='white', font_weight= 'bold',font_size= '16px',text_color='#0d48a1'),disabled = True)\n",
- "red_box = Dropdown(options=[('tiny', 0.1), ('small', 0.2), ('middle', 0.3), ('large', 0.4), ('whole', 0.5)], value=0.1, description='Uniformity box', layout=Layout(grid_area='red_box', width = '95%'),style=style)\n",
- "\n",
- "\n",
- "box_col = ColorPicker(concise=False,description='',value='cyan',disabled=False, layout=Layout(grid_area='box_col', width = '85%'),)\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "check0name = widgets.IntRangeSlider(value=[1, 6],min=0, max=10,step=1,description='Detector cover (α):',disabled=False,continuous_update=False,orientation='horizontal',readout=True, readout_format='d',layout=Layout(grid_area='check0name', width = '100%'),style=style)\n",
- "check1name = widgets.IntSlider(value=10,min=0,max=20,step=5,description='Low angle approx. (°):', disabled=False,continuous_update=False,orientation='horizontal',readout=True,readout_format='d',layout=Layout(grid_area='check1name', width = '100%'),style=style)\n",
- "check2name = widgets.Checkbox(value=False,description='Superresolution (ITR)',disabled=False, indent=False,layout=Layout(grid_area='check2name'))\n",
- "check3name = widgets.Checkbox(value=True, description='Recon. box coverage (ITR)',disabled=False, indent=False,layout=Layout(grid_area='check3name'))\n",
- "check4name = widgets.IntSlider(value=70,min=0,max=100,step=5,description='Beam overlap (%):', disabled=False,continuous_update=False,orientation='horizontal',readout=True,readout_format='d',layout=Layout(grid_area='check4name', width = '100%'),style=style)\n",
- "check6name = widgets.Checkbox(value=False,description='Overall sampling (ITR)',disabled=False, indent=False,layout=Layout(grid_area='check6name'),style=style)\n",
- "\n",
- "sample_set= Button(description='Sample',layout=Layout(width='100%', grid_area='sample_set'), style=ButtonStyle(button_color='#F5F5F5', font_weight= 'bold',font_size= '16px',text_color='black'),disabled = True)\n",
- "ctf_set = Button(description='PCTF',layout=Layout(width='100%', grid_area='ctf_set'), style=ButtonStyle(button_color='#F5F5F5', font_weight= 'bold',font_size= '16px',text_color='black'),disabled = True)\n",
- "cl_set = Button(description='Camera length based limitations and checks', layout=Layout(width='100%', grid_area='cl_set'), style=ButtonStyle(button_color='#F5F5F5', font_weight= 'bold',font_size= '16px',text_color='black'), disabled = True)\n",
- "\n",
- "small_controls = GridBox(children=[sample_set, ctf_set, ctf_xaxis, element, beam_pos, fov_show, cl_set, overlap_fig, red_box, box_col, check0name, check1name, check2name, check3name,check4name, check6name, ctf_xaxis_name],\n",
- " layout=Layout(width='109%', grid_template_rows='35px 35px 35px 35px 5px', grid_template_columns='4% 3.5% 14% 1.5% 8% 8% 8% 1% 27% 13%', grid_template_areas='''\n",
- " \". ctf_set ctf_set . sample_set overlap_fig overlap_fig . cl_set cl_set \" \n",
- " \". ctf_xaxis_name ctxaxis . fov_show fov_show fov_show . check0name check2name \"\n",
- " \". ctf_element ctf_element . beam_pos beam_pos beam_pos . check4name check6name \"\n",
- " \". . . . red_box red_box box_col . check1name check3name \"\n",
- " \". . . . . . . . . . \"'''))\n",
- "\n",
- "\n",
- "\n",
- "def ptycho_interact(beam, aperture, aperture_res, aperture_res2, probe, cl, matrix, defocus, mag, camera, binning, dwell_time, restriction, method, ctf_xaxis, element, graph_size, chart, beam_pos, fov_show, overlap_fig, red_box, box_col, check0name, check1name,\n",
- " check2name, check3name, check4name, check6name):\n",
- " \n",
- " ### SINGLE SETTING PARAMETERS ###\n",
- " # beam ... energy in keV\n",
- " pctf_itr = pty.get_ctf(element)\n",
- " omega_itr = np.array(pty.get_omegas())\n",
- " wavelength = pty.get_wavelength(beam)*1e12 # in pm\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) # in nm\n",
- " step_size_corr = np.array(pty.get_step_correction())*pty.get_step_size(matrix) # in nm\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)/(size_pixel/1e6)/1000 # now in nm\n",
- " oversampling = (wavelength/1000)/(2*pixel_angle/1000*step_size_corr)\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*size_pixel/1e6)/1e4\n",
- " \n",
- " probe_window_all = (wavelength*np.array(opt.cameralengths_eff())/100)/(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)/np.tan(semi_angle_corr/1000)\n",
- " max_defocus_all[max_defocus_all < 0] = 'nan'\n",
- " omega = np.linspace(1e-6,2,100) \n",
- " pctf = pty.get_ssb_ctf()\n",
- " apertury = opt.apertures()\n",
- " oversampling_all = (wavelength/1000)/(2*pixel_covers/1000*step_size_corr)\n",
- " \n",
- "\n",
- " \n",
- "\n",
- " ### SAMPLE PLANE ##########################################\n",
- " if overlap_fig == 'Geometrical': \n",
- " wid = np.linspace(-beam_pos/2,beam_pos/2,beam_pos+1) * step_size_corr\n",
- " yyy = np.append(np.linspace(0,overlap,100), 200)\n",
- " \n",
- " fig5 = make_subplots(specs=[[{\"secondary_y\": True}]])\n",
- " fig5.update_xaxes(title_text=\"Sample plane (nm)\", range=[-fov_show/2, fov_show/2], showgrid=False, zeroline=False)\n",
- " fig5.update_yaxes(range=[-fov_show/2, fov_show/2],showgrid=False, showticklabels=False)\n",
- " \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='black'),secondary_y=False)\n",
- " \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_annotation(x=-1*step_size_corr, y=-2*step_size_corr, ax=-2*step_size_corr, ay=-2*step_size_corr, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='red')\n",
- " fig5.add_annotation(x=-2*step_size_corr, y=-1*step_size_corr, ax=-2*step_size_corr, ay=-2*step_size_corr, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='red')\n",
- " fig5.add_annotation(x=2*step_size_corr-0.75*beam_diameter/2, y=-2*step_size_corr-0.75*beam_diameter/2, ax=2*step_size_corr, ay=-2*step_size_corr,xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='magenta')\n",
- " fig5.add_annotation(x=2*step_size_corr+0.75*beam_diameter/2, y=-2*step_size_corr+0.75*beam_diameter/2, ax=2*step_size_corr, ay=-2*step_size_corr,xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='magenta')\n",
- " fig5.add_trace(go.Scatter(showlegend=True, x=[-1], y=[-1],marker_size=12, marker_color='red', name='Step size '+str(np.round(10*step_size_corr,2))+' Å')) \n",
- " fig5.add_trace(go.Scatter(showlegend=True, x=[-1], y=[-1],marker_size=12, marker_color='magenta', name='Beam ⌀ '+str(np.round(10*beam_diameter,2))+' Å')) \n",
- " \n",
- " if method == 'direct':\n",
- " xx = wavelength/(np.sin(semi_angle_corr*omega/1000))/100\n",
- " fig5.add_trace(go.Scatter(showlegend=True, x=[-1], y=[-1],marker_size=12, marker_color='green', name='Rec step '+str(np.round(xx[-1]/3,2))+' Å')) \n",
- " fig5.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.0,xanchor=\"right\",x=0.9))\n",
- "\n",
- " fig5.add_trace(go.Scatter(showlegend=False, x = -fov_show/2*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(range=[0, 100], showgrid=False, showticklabels=False, secondary_y=True)\n",
- " fig5.update_yaxes(title_text=\"Overlap (%)\", showgrid=False, showticklabels=True, tickvals = [-fov_show/2, -fov_show/4, 0, fov_show/4, fov_show/2],ticktext = ['0', '25', '50', '75', '100'], secondary_y=False)\n",
- " fig5.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.9))\n",
- " fig5.update_layout(plot_bgcolor='white')\n",
- " fig5.update_xaxes(mirror=True,ticks='outside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
- " fig5.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
- "\n",
- " if method == 'direct':\n",
- " fig5.update_layout(width=3.6*graph_size, height=4*graph_size, margin =dict(l=0.6*graph_size, r=0.3*graph_size, t=0.1*graph_size, b=0.7*graph_size))\n",
- " fig5.update_layout(title={'text': \"Sample\",'y': 0.87, 'x': 0.17,'xanchor': 'left','yanchor': 'top'})\n",
- " if method == 'iterative':\n",
- " fig5.update_layout(legend=dict(orientation=\"h\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=1))\n",
- " fig5.update_layout(title={'text': \"Sample\",'y': 0.98, 'x': 0.14,'xanchor': 'left','yanchor': 'top'})\n",
- " fig5.update_layout(width=4.1*graph_size, height=3.1*graph_size, margin =dict(l=1.3*graph_size, r=0.0*graph_size, t=0.1*graph_size, b=0))\n",
- "\n",
- "\n",
- " elif overlap_fig == 'Intensity':\n",
- "\n",
- " ### INTENSIY DISTRIBUTION ##################################\n",
- " # create a text trap and redirect stdout\n",
- " text_trap = io.StringIO()\n",
- " sys.stdout = text_trap\n",
- " \n",
- " sampling= 0.02 # sampling of the simulated potential in A\n",
- "\n",
- " probe = Probe(sampling = sampling, extent = 2*beam_diameter*10, energy = beam*1e3, semiangle_cutoff = semi_angle_corr, defocus = defocus*10)\n",
- " # probe = Probe(sampling=sampling, extent= A , energy=beam*1e3 eV, semiangle_cutoff = mrad, defocus= A)\n",
- " intensity = probe.build().intensity().compute()\n",
- " intensity = intensity.array\n",
- " # # now restore stdout function\n",
- " sys.stdout = sys.__stdout__\n",
- "\n",
- " x_pix = int(step_size_corr*10/sampling) # step size from nm to A\n",
- " field = np.zeros([intensity.shape[0]+(beam_pos)*x_pix, intensity.shape[1]+(beam_pos)*x_pix])\n",
- " cen = int(intensity.shape[0]/2)\n",
- " o = int(intensity.shape[0]/2)\n",
- " for i in range(0,beam_pos+1):\n",
- " for j in range(0,beam_pos+1):\n",
- " xx = x_pix*i\n",
- " xy = x_pix*j\n",
- " field[cen-o+xy : cen+o+xy, cen-o+xx : cen+o+xx] = field[cen-o+xy : cen+o+xy, cen-o+xx : cen+o+xx] + intensity\n",
- "\n",
- " field_cen = int(field.shape[0]/2)\n",
- " middle = field[int(field_cen-(x_pix*(beam_pos)*red_box)): int(field_cen+(x_pix*(beam_pos)*red_box)), int(field_cen-(x_pix*(beam_pos)*red_box)): int(field_cen+(x_pix*(beam_pos)*red_box))]\n",
- " uniformity = (1-((np.max(middle)-np.min(middle))/np.max(middle)))*100\n",
- " \n",
- " fig5 = go.Figure() \n",
- " fig5.add_trace(px.imshow(field).data[0],)\n",
- "\n",
- " field_size = int(field.shape[0]) \n",
- " field_cen = int(field.shape[0]/2) \n",
- " \n",
- " fig5.add_shape(type=\"rect\",x0= field_cen-red_box*field_size, y0=field_cen-red_box*field_size, x1= field_cen+red_box*field_size, y1=field_cen+red_box*field_size,line=dict(color=box_col),)\n",
- " fig5.update_layout(title={'text': \"Uniformity: \"+str(np.round(uniformity,1))+\"%\",'y':0.96, 'x':0.35,'xanchor': 'left','yanchor': 'top'})\n",
- " fig5.update_traces(dict(showscale=False, coloraxis=None, colorscale='plasma'), selector={'type':'heatmap'})\n",
- "\n",
- " fig5.update_yaxes(showticklabels=False)\n",
- " fig5.update_xaxes(mirror=True,ticks='outside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
- " fig5.update_xaxes(title_text=\"Sample plane (nm)\", showgrid=False, showticklabels=True, tickvals = [0, field.shape[0]/2, field.shape[0]-1], \n",
- " ticktext = [0, np.round((field.shape[0]/2)*sampling,1), np.round((field.shape[0]-1)*sampling)])\n",
- "\n",
- " \n",
- " if method == 'direct':\n",
- " fig5.update_layout(width=3.2*graph_size, height=3.2*graph_size, margin =dict(l=0.4*graph_size, r=0.05*graph_size, t=0.3*graph_size, b=0))\n",
- "\n",
- " if method == 'iterative':\n",
- " fig5.update_layout(width=3.9*graph_size, height=3.1*graph_size, margin =dict(l=1.3*graph_size, r=0.2*graph_size, t=0.3*graph_size, b=0))\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- " \n",
- " \n",
- " ### DETECTOR PLANE ##########################################\n",
- " fig6 = make_subplots(specs=[[{\"secondary_y\": True}]])\n",
- " # fig6.update_xaxes(title_text=\"\", range=[0.5, num_pixels+0.5], tickvals = [1, num_pixels/2+0.5, num_pixels], ticktext = [1, \"Detector pixel array\", num_pixels], showticklabels=True,showgrid=True) \n",
- "\n",
- " fig6.update_xaxes(title_text=\"Detector pixel array\", range=[0.5, num_pixels+0.5], tickvals = [1, num_pixels/2+0.5, num_pixels], ticktext = [1, num_pixels/2, num_pixels], showticklabels=True,showgrid=True) \n",
- " fig6.update_yaxes(range=[0.5, num_pixels+0.5], showticklabels=False, showgrid=False, secondary_y=False)\n",
- " fig6.add_shape(type=\"circle\",xref=\"x\", yref=\"y\",opacity=0.5, fillcolor=\"#FF7F7F\", x0=(num_pixels+1)/2-beam_diameter_pix/2, y0=(num_pixels+1)/2-beam_diameter_pix/2, x1=(num_pixels+1)/2+beam_diameter_pix/2, y1=(num_pixels+1)/2+beam_diameter_pix/2,line_color=\"red\",secondary_y=False)\n",
- " fig6.add_shape(type=\"rect\",xref=\"x\", yref=\"y\",opacity=0.5, fillcolor=\"#f0f921\", x0=0.5, y0=0.5, x1=1.5, y1=1.5,line_color=\"#000004\",secondary_y=False)\n",
- " fig6.add_trace(go.Scatter(showlegend=True, x=[0], y=[0],marker_size=12, marker_color='#FF7F7F', name='Cover angle '+str(np.round(detector_cover,1))+' mrad', opacity = 0)) \n",
- " fig6.add_annotation(x=(num_pixels+1)/2-beam_diameter_pix/2, y=(num_pixels+1)/2, ax=(num_pixels+1)/2+beam_diameter_pix/2, ay=(num_pixels+1)/2, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='black')\n",
- " fig6.add_annotation(x=(num_pixels+1)/2+beam_diameter_pix/2,y=(num_pixels+1)/2, ax=(num_pixels+1)/2-beam_diameter_pix/2, ay=(num_pixels+1)/2, xref='x',yref='y',axref='x',ayref='y', text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='black')\n",
- " fig6.add_annotation(x=(num_pixels+1)/2, y=(num_pixels+1)/2, text=str(np.round(beam_diameter_pix,1))+\" pix\", showarrow=False, yshift=10)\n",
- " fig6.add_annotation(x=1, y=1, text=str(np.round(size_pixel,2))+\" μm ≈ \" +str(np.round(pixel_angle,4))+\" mrad\", showarrow=False, xshift=70+(50/np.sqrt(num_pixels)), yshift=10+(50/np.sqrt(num_pixels)))\n",
- " fig6.add_trace(go.Scatter(showlegend=False,x=[-1], y=[-1]),secondary_y=True)\n",
- " fig6.update_yaxes(title_text=\"\", range=[-1, 1], showticklabels=False, showgrid=False, tickvals = [-1, 0, 0.85], ticktext = [\"\", \"Max cover angle (mrad)\", str(np.round(detector_cover,1))], secondary_y=True) \n",
- " fig6.update_yaxes(tickangle=-90)\n",
- " fig6.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.9))\n",
- " fig6.update_layout(plot_bgcolor='white')\n",
- " fig6.update_xaxes(mirror=True,ticks='outside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
- " fig6.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
- " fig6.update_layout(title={'text': \"Detector\",'y':0.975, 'x': 0.09,'xanchor': 'left','yanchor': 'top'})\n",
- " fig6.update_layout(width=2.9*graph_size, height=3.1*graph_size, margin =dict(l=0.1*graph_size, r=0.1*graph_size, t=0.1*graph_size, b=0)) \n",
- " \n",
- " focusdepth = wavelength/(semi_angle_corr/1000)**2/1000\n",
- " ssb_cl, kolik = pty.cl4ssb(detector_cover_a_all)\n",
- "\n",
- "\n",
- " \n",
- " ### MICROSCOPE SCHEME ##########################################\n",
- " width = 500 # in-graph setting\n",
- " det_width = 400 # in-graph setting\n",
- " y_down = np.log(np.max(opt.cameralengths()))\n",
- " reduc = 0.4 # in-graph setting\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",
- " fig8.add_shape(type=\"rect\",xref=\"x\", yref=\"y\",opacity=0.05, fillcolor=\"gray\", x0=-width, y0=-y_down, x1=width, y1=reduc*y_down,line_color=\"gray\")\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=\"Aperture \", showarrow=False, yshift=2)\n",
- " fig8.add_annotation(x=-0.7*width, y=reduc*0.8*y_down, text=str(aperture), showarrow=False, yshift=-15)\n",
- " fig8.add_annotation(x=0.0*width, y=-y_down,text='Acquisition time (s) '+ str(np.round(matrix*matrix*dwell_time/1e6,1)), showarrow=False, yshift=-10)\n",
- " fig8.add_annotation(x=0, y=reduc*0.96*y_down,text='λ (pm) '+ str(np.round((pty.get_wavelength(beam)*1e12),2)), showarrow=False, 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=70, 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.7*width, y=0,text=\"Sample\", 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.4*width, y=0.05*y_down,text=\"FoV \"+str(np.round(fov,2))+\" nm\", showarrow=False, yshift=0)\n",
- " fig8.add_annotation(x=0.5*width, y=0.05*y_down,text=\"Dose \"+str(np.round(dose,1))+\" e/Å2\", showarrow=False, yshift=-40)\n",
- " fig8.add_annotation(x=-0.5*width, y=0.05*y_down,text=\"DoF \"+str(np.round(focusdepth,1))+\" nm\", showarrow=False, yshift=-40)\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.7*width, y=-np.log(cl),text=\"Detector\", showarrow=False,align= 'left', yshift=15)\n",
- " fig8.add_annotation(x=-0.7*width, y=-np.log(cl),text=str(np.round(cl_det,2))+' cm', showarrow=False,align= 'left', yshift=-15) \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",
- " if method == 'direct':\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*width, y=-np.log(ssb_cl),text=\"\", 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=\"PAAR\", 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.85*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(width=3.5*graph_size, height=7.2*graph_size, margin = dict(l=0.3*graph_size, r=0, t=0.0*graph_size, b=0))\n",
- " fig8.update_layout(plot_bgcolor='white')\n",
- "\n",
- "\n",
- " \n",
- " ### METHODS ########################################## \n",
- " if method == 'direct':\n",
- " \n",
- " xx = wavelength/(np.sin(semi_angle_corr*omega/1000))/100 # pitch size\n",
- " \n",
- " ### PROBE ##########################################\n",
- " fig = go.Figure() \n",
- " fig.update_yaxes(title_text=\"Transfer (-)\")\n",
- "\n",
- " if ctf_xaxis == 'α': \n",
- " fig.add_trace(go.Scatter(showlegend=True, x=omega, y=pctf, marker_color='red', name='Common for all',))\n",
- " fig.update_xaxes(title_text=\"Scattering angle (α)\", range=[0, 2], zeroline=False)\n",
- " \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='black', name='SSB-CTF',))\n",
- "\n",
- " fig.add_trace(go.Scatter(showlegend=False, x=semi_angle_corr*omega, y=pctf, marker_color='red'))\n",
- " fig.update_layout(legend=dict(orientation=\"h\",yanchor=\"bottom\",y=0.85,xanchor=\"right\",x=1))\n",
- " fig.update_xaxes(title_text=\"Spacial frequency (mrad)\", range=[0, 60], zeroline=False)\n",
- " \n",
- " elif ctf_xaxis == 'Å':\n",
- " for x in apertury:\n",
- " d = wavelength/(np.sin(pty.get_angle_corr(x)*omega/1000))/100 # Full pitch size\n",
- " fig.add_trace(go.Scatter(showlegend=False, x=d, y=pctf, marker_color='black', name='SSB-CTF',))\n",
- "\n",
- " fig.add_trace(go.Scatter(showlegend=False, x=xx, y=pctf, marker_color='red'))\n",
- " fig.update_xaxes(title_text=\"Real space distance (Å)\", range=[-1, 2], type=\"log\", zeroline=False)\n",
- "\n",
- " fig.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.9))\n",
- " fig.update_layout(title={'text': \"PCTF\",'y':0.7, 'x':0.28,'xanchor': 'left','yanchor': 'top'})\n",
- " fig.update_layout(plot_bgcolor='white')\n",
- " fig.update_xaxes(mirror=True,ticks='outside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
- " fig.update_yaxes(mirror=True,ticks='outside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
- " fig.update_layout(width=4.95*graph_size, height=3.3*graph_size, margin = dict(l=1.3*graph_size, r=0.25*graph_size, t=1.2*graph_size, b=0.3*graph_size))\n",
- " \n",
- "\n",
- "\n",
- "\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='black'), secondary_y=False,)\n",
- " fig4.add_trace(go.Scatter(showlegend=False, x=opt.cameralengths(), y=detector_cover_a_all,marker_color='black'), 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 = \"Recommended CL\"), secondary_y=True,) \n",
- " fig4.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=0.75,xanchor=\"right\",x=0.9))\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=5.25*graph_size, height=3*graph_size, margin =dict(l=1.3*graph_size, r=0.25*graph_size, t=0.3*graph_size, b=0.3*graph_size))\n",
- " fig4.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.9), plot_bgcolor='white')\n",
- " fig4.update_xaxes(mirror=True,ticks='outside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
- " fig4.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
- " fig4.update_layout(title={'text': \"CL\",'y':0.87, 'x':0.26,'xanchor': 'left','yanchor': 'top'})\n",
- " \n",
- " \n",
- " elif method == 'iterative': \n",
- " ### PROBE ##########################################\n",
- " pctf_norm = pctf_itr/np.max(pctf_itr)\n",
- "\n",
- " fig = go.Figure() \n",
- " fig.update_yaxes(title_text=\"Transfer (-)\")\n",
- " match ctf_xaxis: \n",
- " case 'α':\n",
- " fig.add_trace(go.Scatter(showlegend=False, x=omega_itr, y= pctf_norm, marker_color='red',))\n",
- " fig.update_xaxes(title_text=\"Scattering angle (α)\", range=[0, 5], zeroline=False)\n",
- " fig.update_yaxes(range=[0, 1.1])\n",
- " \n",
- " case 'mrad': \n",
- " for x in apertury:\n",
- " fig.add_trace(go.Scatter(showlegend=False, x=pty.get_angle_corr(x)*omega_itr, y=pctf_norm, marker_color='black', name='',))\n",
- " \n",
- " fig.add_trace(go.Scatter(showlegend=False, x=semi_angle_corr*omega_itr, y=pctf_norm, marker_color='red'))\n",
- " fig.update_xaxes(title_text=\"Spacial frequency (mrad)\", range=[0, 100], zeroline=False)\n",
- "\n",
- " case 'Å':\n",
- " for x in apertury:\n",
- " d = wavelength/(np.sin(pty.get_angle_corr(x)*omega_itr/1000))/100\n",
- " fig.add_trace(go.Scatter(showlegend=False, x=d, y=pctf_norm, marker_color='black', name='CTF'))\n",
- " \n",
- " xx = wavelength/(np.sin(semi_angle_corr*omega_itr/1000))/100\n",
- " fig.add_trace(go.Scatter(showlegend=False, x=xx, y=pctf_norm, marker_color='red'))\n",
- " fig.update_xaxes(title_text=\"Real space distance (Å)\",range=[-1, 2], type=\"log\", zeroline=False) # \n",
- "\n",
- " fig.update_layout(legend=dict(orientation=\"h\",yanchor=\"bottom\",y=0.8,xanchor=\"right\",x=0.95))\n",
- " fig.update_layout(width=4.25*graph_size, height=2.2*graph_size, margin = dict(l=1.3*graph_size, r=0.3*graph_size, t=0.22*graph_size, b=0.7*graph_size))\n",
- " fig.update_layout(title={'text': \"PCTF\",'y':0.99, 'x':0.33,'xanchor': 'left','yanchor': 'top'})\n",
- " fig.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.9),plot_bgcolor='white')\n",
- " fig.update_xaxes(mirror=True,ticks='outside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
- " fig.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- " ### FINAL CHECKS ########################################## \n",
- " align_check = dict(layout=Layout(width='235px') , style = {'description_width': '140px','button_width': \"95px\"}, disabled=True,) \n",
- " check1 = Valid(value= bool(overlap > check4name), description='Beam overlap', **align_check)\n",
- " check2 = Valid(value= bool(step_size_corr*10 > (wavelength * cl_det)/(num_pixels*size_pixel/1e6)/1e4), description='Superresolution', **align_check)\n",
- " check3 = Valid(value= bool(beam_diameter/2 < probe_window/2), description='Recon. box coverage', **align_check) \n",
- " check4 = Valid(value= bool(oversampling > 1), description='Overall sampling', **align_check) \n",
- "\n",
- " \n",
- " checks = VBox([check1, check2, check3, check4]) # Label('Final checks')\n",
- " checks.layout = Layout(margin='30px 0px 00px 240px', padding='5px 5px 5px 5px') # border='dashed 1px gray',\n",
- "\n",
- " \n",
- "\n",
- " \n",
- " ### PROBE WINDOW ##########################################\n",
- " if overlap_fig == 'Geometrical': \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=\"#6F6F6F\", x0=probe_window/4, y0=probe_window/4, x1=3*probe_window/4, y1=3*probe_window/4,line_color=\"#6F6F6F\")\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, opacity = 0))\n",
- " fig7.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.2, fillcolor=color, x0=probe_window/2-beam_diameter/8, y0=probe_window/2-beam_diameter/8, x1=probe_window/2+beam_diameter/8, y1=probe_window/2+beam_diameter/8, line_color=color,)\n",
- " fig7.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.2, fillcolor=color, x0=probe_window/2-beam_diameter/6, y0=probe_window/2-beam_diameter/6, x1=probe_window/2+beam_diameter/6, y1=probe_window/2+beam_diameter/6, line_color=color,)\n",
- " fig7.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.2, fillcolor=color, x0=probe_window/2-beam_diameter/5, y0=probe_window/2-beam_diameter/5, x1=probe_window/2+beam_diameter/5, y1=probe_window/2+beam_diameter/5, line_color=color,)\n",
- " fig7.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.2, fillcolor=color, x0=probe_window/2-beam_diameter/4.25, y0=probe_window/2-beam_diameter/4.25, x1=probe_window/2+beam_diameter/4.25, y1=probe_window/2+beam_diameter/4.25, line_color=color,)\n",
- " fig7.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.2, fillcolor=color, x0=probe_window/2-beam_diameter/3.5, y0=probe_window/2-beam_diameter/3.5, x1=probe_window/2+beam_diameter/3.5, y1=probe_window/2+beam_diameter/3.5, line_color=color,)\n",
- " fig7.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.2, fillcolor=color, x0=probe_window/2-beam_diameter/3, y0=probe_window/2-beam_diameter/3, x1=probe_window/2+beam_diameter/3, y1=probe_window/2+beam_diameter/3, line_color=color,)\n",
- " fig7.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.2, fillcolor=color, x0=probe_window/2-beam_diameter/2.5, y0=probe_window/2-beam_diameter/2.5, x1=probe_window/2+beam_diameter/2.5, y1=probe_window/2+beam_diameter/2.5, line_color=color,)\n",
- " fig7.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.4, 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=\"Reconstruction box (nm)\", range=[0, probe_window], tickvals = [0, probe_window/4, probe_window/2, 3*probe_window/4, probe_window], ticktext = [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)])\n",
- " fig7.update_yaxes(range=[0, probe_window], tickvals = [0, probe_window/4, probe_window/2, 3*probe_window/4, probe_window], showticklabels=False,)\n",
- " fig7.update_yaxes(range=[0, probe_window], showticklabels=False,)\n",
- " fig7.update_yaxes(range=[0, probe_window], showticklabels=False,)\n",
- " fig7.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=1),title={'text': \"Probe\",'y':0.975, 'x':0.05,'xanchor': 'left','yanchor': 'top'})\n",
- " fig7.update_layout(width=2.7*graph_size, height=3.1*graph_size, margin =dict(l=0, r=0, t=0.1*graph_size, b=0)) \n",
- " fig7.update_layout(plot_bgcolor='white')\n",
- " fig7.update_xaxes(mirror=True,ticks='outside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
- " fig7.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
- "\n",
- "\n",
- " ####################\n",
- " ####################\n",
- " ####################\n",
- " ####################\n",
- " ####################\n",
- " elif method == 'iterative': \n",
- " sampling= 0.1 # sampling of the simulated potential in A\n",
- " probe = Probe(sampling = sampling, extent = 2*probe_window*10, energy = beam*1e3, semiangle_cutoff = semi_angle_corr, defocus = defocus*10)\n",
- " # probe = Probe(sampling=sampling, extent= A , energy=beam*1e3 eV, semiangle_cutoff = mrad, defocus= A)\n",
- " intensity2 = probe.build().intensity().compute()\n",
- " intensity2 = intensity2.array\n",
- " inten = intensity2/np.max(intensity2)\n",
- " \n",
- " cen2 = inten.shape\n",
- " sirkaA = cen2[0]*sampling\n",
- " sirkaB = probe_window*10/sampling\n",
- "\n",
- " just_probe_window = inten[int(cen2[0]/2)-int(sirkaB/2) : int(cen2[0]/2)+int(sirkaB/2), int(cen2[0]/2)-int(sirkaB/2) : int(cen2[0]/2)+int(sirkaB/2)]\n",
- " int_tot = np.sum(just_probe_window)/np.sum(inten)*100\n",
- "\n",
- " fig7 = go.Figure() \n",
- " fig7.add_trace(px.imshow(inten).data[0],)\n",
- " fig7.add_shape(type=\"rect\",x0= cen2[0]/2-sirkaB/2, y0=cen2[0]/2-sirkaB/2, x1= cen2[1]/2+sirkaB/2, y1=cen2[1]/2+sirkaB/2, line=dict(color=\"white\"),)\n",
- " fig7.update_layout(title={'text': \"Probe cover \",'y':0.96, 'x':0.05,'xanchor': 'left','yanchor': 'top'})\n",
- " fig7.update_layout(width=2.7*graph_size, height=2.65*graph_size, margin =dict(l=0.1*graph_size, r=0.1*graph_size, t=0.3*graph_size, b=0))\n",
- " fig7.update_traces(dict(showscale=False, \n",
- " coloraxis=None, \n",
- " colorscale='plasma'), selector={'type':'heatmap'})\n",
- " fig7.update_xaxes(showticklabels=False).update_yaxes(showticklabels=False)\n",
- " fig7.add_annotation(x=cen2[0]/2, y=cen2[0]/2+sirkaB/2, text='Recon. box '+str(np.round(probe_window,2))+' nm', showarrow=False, yshift=15)\n",
- " fig7.add_annotation(x=cen2[0]/2, y=cen2[0]/2-sirkaB/2, text='Probe covered '+str(np.round(int_tot,1))+' %', showarrow=False, yshift=-15)\n",
- " fig7.update_annotations(font=dict(color=\"white\"))\n",
- " # fig7.update_annotations(font=dict(family=\"sans serif\", size=18, color=\"red\"))\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- " \n",
- " \n",
- "\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), opt.cameralengths(), np.round(oversampling_all,1)])\n",
- "\n",
- " align6 = dict(layout=Layout(width=str(int(graph_size/100*57))+'px') , style = {'description_width': '0px','button_width': str(int(graph_size/100*56))+'px'}, disabled=True,)\n",
- " align7 = dict(layout=Layout(width='128px') , style = {'description_width': '0px','button_width': \"128px\"}, disabled=True,)\n",
- " \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, 5.oversampling\n",
- " data_tuple = tuple(tab[0:5,int(i)]) + (\"\",tab[5,int(i)])\n",
- " icons=['','','','','']\n",
- "\n",
- "# check1name = 'Low anlge approximation'\n",
- "# check2name = 'Ptycho pixel < step size'\n",
- "# check3name = 'Beam fits in probe window'\n",
- "# check4name = 'Detector cover < 1α'\n",
- "# check5name = 'Detector cover > 6α'\n",
- "# check6name = 'Oversampling > 1'\n",
- "\n",
- " if data[1] > 1000*np.radians(check1name):\n",
- " button_style = 'danger' \n",
- " \n",
- " if check2name == True: \n",
- " if data[0] > step_size_corr*10:\n",
- " button_style = 'danger'\n",
- " \n",
- " if check3name == True: \n",
- " if data[3] < defocus:\n",
- " button_style = 'danger'\n",
- " \n",
- " if data[2] < check0name[0]:\n",
- " button_style = 'danger' \n",
- "\n",
- " if data[2] > check0name[1]:\n",
- " button_style = 'warning' \n",
- "\n",
- " if check6name == True: \n",
- " if data[5] < 1:\n",
- " button_style = 'danger' \n",
- " \n",
- " if cl == data[4]:\n",
- " icons=['','','','','','check'] \n",
- " \n",
- " dictionary[i] = ToggleButtons(options=data_tuple, text_color= 'red', button_style=button_style, icons = icons, **align6)\n",
- "\n",
- " legend = ToggleButtons(options=['Ptycho pixel (Å)','Det. cover (mrad)','Det. cover (α)', 'Max. def. (nm)','Nominal CL (cm)','Selected by CL ','Oversampling'], \n",
- " tooltips=['Dependent on: detector, beam energy, camera length', 'Dependent on: detector, camera length', 'Dependent on: detector, camera length, probe semi-angle', \n",
- " 'Dependent on: detector, binning, beam energy, camera length, zero defocus beam diameter, probe semi-angle', 'Just nominal camera length'],button_style='', **align7) \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('Recommended parameters for proper ptychographic reconstruction.'), cltab])\n",
- " cltab.layout = Layout(border='solid 0px gray',margin='10px 0px 10px 125px', padding='5px 5px 5px 5px')\n",
- "\n",
- "\n",
- "\n",
- " ### SHOWING ###\n",
- " if method == 'direct': \n",
- " match chart:\n",
- " case 'micr':\n",
- " total = HBox([go.FigureWidget(fig8)]) \n",
- " case 'dedic':\n",
- " total = VBox([ HBox([go.FigureWidget(fig) ,go.FigureWidget(fig5)]), HBox([go.FigureWidget(fig4),go.FigureWidget(fig6)])])\n",
- " case _: \n",
- " right_column = VBox([HBox([go.FigureWidget(fig) ,go.FigureWidget(fig5)]), HBox([go.FigureWidget(fig4),go.FigureWidget(fig6)])]) \n",
- " left_column = go.FigureWidget(fig8)\n",
- " total = HBox([left_column, right_column])\n",
- " \n",
- " total.layout = Layout(border='solid 0px gray',margin='0px 0px 0px 20px', padding='0px 0px 0px 0px') \n",
- " display(total)\n",
- "\n",
- " elif method == 'iterative': \n",
- " match chart:\n",
- " case 'micr':\n",
- " total = HBox([go.FigureWidget(fig8)])\n",
- " case 'dedic':\n",
- " sample_overlap = HBox([go.FigureWidget(fig5), go.FigureWidget(fig7), go.FigureWidget(fig6)]) \n",
- " total = VBox([HBox([go.FigureWidget(fig),go.FigureWidget(fig9)]), sample_overlap, HBox([cltab, checks])]) \n",
- " case _:\n",
- " sample_overlap = HBox([go.FigureWidget(fig5), go.FigureWidget(fig7), go.FigureWidget(fig6)]) \n",
- " right_column = VBox([HBox([go.FigureWidget(fig), checks]) , sample_overlap, cltab]) \n",
- " left_column = VBox([go.FigureWidget(fig8)]) \n",
- " total = HBox([left_column, right_column]) \n",
- " \n",
- " total.layout = Layout(border='solid 0px gray',margin='0px 0px 0px 10px', padding='0px 0px 0px 10px') \n",
- " display(total)\n",
- "\n",
- " return \n",
- " \n",
- "gui = interactive_output(ptycho_interact, {\"beam\": beam, \"aperture\": aperture,\"aperture_res\": aperture_res,\"aperture_res2\": aperture_res2, \"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, \"element\": element, \"graph_size\": graph_size,\"chart\": chart, \"beam_pos\": beam_pos, \n",
- " \"fov_show\": fov_show, \"overlap_fig\":overlap_fig, \"red_box\": red_box, \"box_col\":box_col, \"check0name\":check0name, \"check1name\": check1name, \"check2name\": check2name, \"check3name\": check3name, \"check4name\": check4name, \"check6name\": check6name}) \n"
+ "## RUN ME"
]
},
{
"cell_type": "code",
"execution_count": 3,
- "id": "68780f2b-efa0-4240-870b-2b0876977e90",
+ "id": "fecbecdb-0fac-4ac8-a2b3-1ccb3f869a77",
"metadata": {},
"outputs": [],
"source": [
- "### Function definitions ###################################################\n",
- "calib = r'calibrations.xlsx' # Path to the calibration file\n",
- "class interaction: \n",
- " \"\"\"Loads calibration settings and ranges from .xlsx file.\n",
- " These are than used for widgets creation.\"\"\"\n",
- " \n",
- " def __init__(self):\n",
- " self.calib = calib\n",
+ "### Initial packages import\n",
+ "import io\n",
+ "import sys\n",
+ "import numpy as np\n",
+ "import ipywidgets as widg\n",
+ "import scipy.constants as cons\n",
+ "import plotly.express as px\n",
+ "import plotly.graph_objects as go\n",
+ "from ptychoscopy import pty\n",
+ "from IPython.display import display\n",
+ "from plotly.subplots import make_subplots\n",
"\n",
- " def elements(self):\n",
- " excel_data = read_excel(calib,sheet_name='CTF')\n",
- " elements = [str(e) for e in list(excel_data.CTF)]\n",
- " elements = [x for x in elements if x != 'nan']\n",
- " return elements\n",
+ "try:\n",
+ " from abtem import Probe\n",
+ " abtem = True\n",
+ "except:\n",
+ " abtem = False\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",
+ "def show_wavelength(caller):\n",
+ " beam_res.value = f'λ (pm) {str(\"{:.1f}\".format(pty.get_wavelength(caller.new)*1e12))}'\n",
+ " return beam_res.value\n",
+ "def show_probe_angle(caller):\n",
+ " aperture_res.value = f'Semi-angle (mrad) {\"{:.1f}\".format(pty.get_angle(caller.new))}' \n",
+ " return aperture_res.value\n",
+ "def show_corrprobe_angle(caller):\n",
+ " aperture_res2.value = f'corr. {\"{:.2f}\".format(pty.get_angle_corr(caller.new))}'\n",
+ " return aperture_res2.value\n",
+ "def show_fov(caller):\n",
+ " fov_res.value = f'FoV (nm) {\"{:.1f}\".format(pty.get_fov(caller.new))}'\n",
+ " return fov_res.value\n",
+ "def show_frame_rate(caller):\n",
+ " dwell_time_res.value = f'Rate (kHz) {\"{:.1f}\".format(pty.get_aq_frec(caller.new))}' \n",
+ " return dwell_time_res.value\n",
+ "def show_cd_det(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",
+ "### MICROSCOPE CONTROL PANEL\n",
+ "image = open(\"ptychoscopy/logo.png\", \"rb\").read()\n",
+ "logo = widg.Image(value=image, format='png', layout=widg.Layout(grid_area='logo'))\n",
+ "ali = dict(style = {'description_width': '110px','button_width': '55px', 'font_weight': 'bold'}, button_style='', disabled = False)\n",
+ "ali2 = dict(style = {'description_width': '60px' ,'button_width': '90px', 'font_weight': 'bold'}, button_style='', disabled = False)\n",
+ "ali3 = dict(style = {'description_width': '110px','button_width': '45px', 'font_weight': 'bold'}, button_style='', disabled = False)\n",
+ "method = widg.ToggleButtons(options=[('SSB ','ssb'),('ITR ','iterative')],description='',icons=['opera','refresh'], tooltips=['Single side band ptychography', 'Iterative reconstruction methods (PIE, ML, DM)'],\n",
+ " layout=widg.Layout(width='95%', grid_area='methods'), style = {'button_width': '48%','font_weight': 'bold'}, button_style='', disabled = False)\n",
+ "### Electron beam settings\n",
+ "beam_set = widg.Button(description='Electron beam settings',layout=widg.Layout(width='95%',grid_area='beam_set'),style=widg.ButtonStyle(button_color='#222261',font_weight='bold',font_size='16px',text_color='white'),disabled=False) \n",
+ "beam_energy = widg.Dropdown(options=pty.load_energies(), value=200, description='Beam energy (keV)', layout=widg.Layout(width='95%', grid_area='beam_set1'), **ali)\n",
+ "probe_size = widg.Dropdown(options=pty.load_probes(), value='8C', description='Probe', layout=widg.Layout(width='95%', grid_area='beam_set3'), **ali)\n",
+ "defocus = widg.FloatSlider(description='Defocus (nm)', value=0, min=0, max=1000, step=5, readout_format='d',continuous_update=False, layout=widg.Layout(width='95%', grid_area='beam_set4'), **ali)\n",
+ "aperture_name = widg.Label(value = 'Aperture', layout=widg.Layout(width='95%', grid_area='aperture_name'),)\n",
+ "aperture = widg.ToggleButtons(options=pty.load_apertures(), description='', layout=widg.Layout(width='95%', grid_area='beam_set2'), **ali3)\n",
+ "\n",
+ "### Scanning parameters\n",
+ "scanning_set = widg.Button(description='Scanning parameters', layout=widg.Layout(width='95%', grid_area='scanning_set'),style=widg.ButtonStyle(button_color='#222261', font_weight= 'bold',font_size= '16px',text_color='white'),disabled = False)\n",
+ "mag = widg.Dropdown(options=pty.load_magnifications(), value=20, description='Magnification Mx', layout=widg.Layout(width='95%', grid_area='scanning_set1'), **ali)\n",
+ "matrix = widg.Dropdown(options=pty.load_mappings(), value=256, description='Matrix', layout=widg.Layout(width='95%', grid_area='scanning_set2'), **ali)\n",
+ "dwell_time = widg.Dropdown(options=pty.load_dwelltimes(), value=10, description='Dwell time (μs)', layout=widg.Layout(width='95%', grid_area='scanning_set3'), **ali)\n",
+ "\n",
+ "### Detection\n",
+ "camera_set = widg.Button(description='Detection',layout=widg.Layout(width='95%', grid_area='camera_set'),style=widg.ButtonStyle(button_color='#222261', font_weight= 'bold',font_size= '16px',text_color='white'),disabled = False)\n",
+ "cl = widg.Dropdown(options=pty.load_cameralengths(aperture, \"nominal\"), value=8, description='Nominal CL (cm)', layout=widg.Layout(width='95%', grid_area='cl_set1'), **ali3)\n",
+ "camera_name = widg.Label(value = 'Detector',layout=widg.Layout(width='95%', grid_area='camera_name'),)\n",
+ "camera = widg.ToggleButtons(options=pty.load_detectors(), description='', layout=widg.Layout(width='95%', grid_area='camera_set1'), style = {'description_width': '60px','button_width': str(100/len(pty.load_detectors())-len(pty.load_detectors()))+'%', 'font_weight': 'bold'}, button_style='')\n",
+ "restr_name = widg.Label(value = 'PAAR',layout=widg.Layout(width='95%', grid_area='restr_name'))\n",
+ "restr = widg.ToggleButtons(options=[('.',False), ('..',True)], value = False, description='',icons = ['ban','check'], layout=widg.Layout(width='95%', grid_area='camera_set2'),style = {'description_width': '80px','button_width': '48%', 'font_weight': 'bold'}, button_style='')\n",
+ "binning_name = widg.Label(value = 'Binning',layout=widg.Layout(width='95%', grid_area='binning_name'))\n",
+ "binning = widg.ToggleButtons(options=[('.',1), ('2',2), ('4',4), ('8',8), ('16',16), ('32',32), ('48',48)], value=1, description='', icons = ['ban','',''], layout=widg.Layout(width='95%', grid_area='camera_set3'), **ali3)\n",
+ "beam_res = widg.Label(value = f'λ (pm) ' + str(\"{:.1f}\".format(pty.get_wavelength(beam_energy.value)*1e12)),layout=widg.Layout(width='auto', grid_area='sidebar1'))\n",
+ "aperture_res = widg.Label(value = f'Semi-angle (mrad) '+ str(\"{:.1f}\".format(pty.get_angle(aperture.value))), layout=widg.Layout(width='auto', grid_area='sidebar2'))\n",
+ "aperture_res2 = widg.Label(value = f'corr. ' + str(\"{:.2f}\".format(pty.get_angle_corr(aperture.value))), layout=widg.Layout(width='auto', grid_area='sidebar5'))\n",
+ "fov_res = widg.Label(value = f'FoV (nm) ' + str(\"{:.1f}\".format(pty.get_fov(mag.value))), layout=widg.Layout(width='auto', grid_area='sidebar3')) \n",
+ "dwell_time_res= widg.Label(value = f'Rate (kHz) ' + str(\"{:.1f}\".format(pty.get_aq_frec(dwell_time.value))), layout=widg.Layout(width='auto', grid_area='sidebar4')) \n",
+ "mag.observe(show_fov, names='value') \n",
+ "beam_energy.observe(show_wavelength, names='value') \n",
+ "aperture.observe(show_probe_angle, names='value') \n",
+ "dwell_time.observe(show_frame_rate, names='value') \n",
+ "aperture.observe(show_corrprobe_angle, names='value') \n",
+ "\n",
+ "### Visualisation\n",
+ "visual_set = widg.Button(description='Visualisation',layout=widg.Layout(width='95%', grid_area='visual_set'),style=widg.ButtonStyle(button_color='white', font_weight= 'bold',font_size= '16px',text_color='black'),disabled = False)\n",
+ "name1 = widg.Button(description='Graphs (%)',layout=widg.Layout(width='95%', grid_area='name1'),style=widg.ButtonStyle(button_color='white', font_weight= 'bold',text_color='black'), disabled = False)\n",
+ "graph_size = widg.IntSlider(value=100,min=75,max=125,step=5, description='', layout=widg.Layout(width='95%', grid_area='gr_size2'), button_style='primary',disabled=False,)\n",
+ "\n",
+ "### Layout\n",
+ "controls = widg.GridBox(children=[logo, method, beam_energy, beam_set, aperture_name, aperture, probe_size, defocus, scanning_set, mag, matrix, dwell_time, cl,camera_set, camera, camera_name, restr_name, restr, binning_name,\n",
+ " binning, beam_res, aperture_res, aperture_res2, fov_res, dwell_time_res, graph_size, name1, visual_set],\n",
+ " layout=widg.Layout(width='325px', grid_template_rows='90px 40px 35px 35px 35px 35px 35px 30px 30px 35px 35px 35px 35px 35px 35px 35px 80px 95px 35px 35px 35px', grid_template_columns='20% 10% 30% 15% 25%', grid_template_areas='''\n",
+ " \"logo logo logo logo logo \" \n",
+ " \"methods methods methods methods methods \"\n",
+ " \"beam_set beam_set beam_set beam_set beam_set \" \n",
+ " \"beam_set1 beam_set1 beam_set1 beam_set1 beam_set1 \"\n",
+ " \"beam_set3 beam_set3 beam_set3 beam_set3 beam_set3 \"\n",
+ " \"beam_set4 beam_set4 beam_set4 beam_set4 beam_set4 \"\n",
+ " \"aperture_name beam_set2 beam_set2 beam_set2 beam_set2 \"\n",
+ " \". sidebar2 sidebar2 sidebar2 sidebar5 \"\n",
+ " \"scanning_set scanning_set scanning_set scanning_set scanning_set \" \n",
+ " \"scanning_set1 scanning_set1 scanning_set1 scanning_set1 scanning_set1\"\n",
+ " \"scanning_set2 scanning_set2 scanning_set2 scanning_set2 scanning_set2\"\n",
+ " \"scanning_set3 scanning_set3 scanning_set3 scanning_set3 scanning_set3\"\n",
+ " \"camera_set camera_set camera_set camera_set camera_set \"\n",
+ " \"cl_set1 cl_set1 cl_set1 cl_set1 cl_set1 \"\n",
+ " \"camera_name camera_set1 camera_set1 camera_set1 camera_set1 \"\n",
+ " \"restr_name camera_set2 camera_set2 camera_set2 camera_set2 \"\n",
+ " \"binning_name camera_set3 camera_set3 camera_set3 camera_set3 \"\n",
+ " \". . . . . \"\n",
+ " \"visual_set visual_set visual_set visual_set visual_set \"\n",
+ " \"name1 name1 gr_size2 gr_size2 gr_size2 \"'''))\n",
+ "\n",
+ "### GRAPH CONTROL\n",
+ "style = {'description_width': 'initial'}\n",
+ "top_set = widg.Button(description='',layout=widg.Layout(width='%', grid_area='scanning_set'), style=widg.ButtonStyle(button_color='white', font_weight= 'bold',font_size= '16px',text_color='#0d48a1'),disabled = True)\n",
+ "style_graph = widg.ButtonStyle(button_color='#F5F5F5', font_weight= 'bold',font_size= '16px',text_color='black')\n",
+ "\n",
+ "### PCTF\n",
+ "ctf_set = widg.Button(description='Phase CTF',layout=widg.Layout(width='100%', grid_area='ctf_set'), style=style_graph,disabled = True)\n",
+ "ctf_xaxis_name = widg.Label(value = 'x-axis',layout=widg.Layout(width='95%', grid_area='ctf_xaxis_name'),)\n",
+ "ctf_xaxis = widg.ToggleButtons(options=['α','mrad', 'Å'], layout=widg.Layout(grid_area='ctxaxis'), style = {'button_width': '30%'}, disabled=False)\n",
+ "element = widg.Dropdown(options=pty.load_elements(), description='Element (ITR)', layout=widg.Layout(width='95%', grid_area='ctf_element'))\n",
+ "\n",
+ "### Sample\n",
+ "sample_set = widg.Button(description='Sample',layout=widg.Layout(width='100%', grid_area='sample_set'), style=style_graph, disabled = True)\n",
+ "overlap_fig = widg.ToggleButtons(options=['Geometrical','Ilumination'], layout=widg.Layout(grid_area='overlap_fig'), style = {'button_width': '45%'}, disabled=False)\n",
+ "fov_show = widg.FloatSlider(value=0.3, min=0.1, max=10, step=0.1, description='FoV (nm):', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='.1f', layout=widg.Layout(grid_area='fov_show', width = '100%'))\n",
+ "beam_pos = widg.IntSlider(value=4, min=4, max=100, step=2, description='Add beams:', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d', layout=widg.Layout(grid_area='beam_pos', width = '100%'))\n",
+ "red_box = widg.Dropdown(options=[('tiny', 0.1), ('small', 0.2), ('middle', 0.3), ('large', 0.4), ('whole', 0.5)], value=0.1, description='Uniformity box', layout=widg.Layout(grid_area='red_box', width = '95%'),style=style)\n",
+ "box_col = widg.ColorPicker(concise=False, description='', value='cyan', disabled=False, layout=widg.Layout(grid_area='box_col', width = '85%'),)\n",
+ "\n",
+ "### Camera length based limitations and checks\n",
+ "cl_set = widg.Button(description='Camera length based limitations and checks', layout=widg.Layout(width='100%', grid_area='cl_set'), style=style_graph, disabled = True)\n",
+ "check0name = widg.IntRangeSlider(value=[1,6],min=0, max=10,step=1, description='Detector cover (α):', disabled=False, continuous_update=False, orientation='horizontal',readout=True, readout_format='d',layout=widg.Layout(grid_area='check0name', width = '100%'),style=style)\n",
+ "check1name = widg.IntSlider(value=10,min=0,max=20,step=5,description='Low angle approx. (°):', disabled=False,continuous_update=False,orientation='horizontal',readout=True,readout_format='d',layout=widg.Layout(grid_area='check1name', width = '100%'),style=style)\n",
+ "check2name = widg.Checkbox(value=False,description='Resolution gain (ITR)',disabled=False, indent=False,layout=widg.Layout(grid_area='check2name'))\n",
+ "check3name = widg.Checkbox(value=True, description='Recon. box coverage (ITR)',disabled=False, indent=False,layout=widg.Layout(grid_area='check3name'))\n",
+ "check4name = widg.IntSlider(value=70, min=0 ,max=100, step=5, description='Beam overlap (%):', disabled=False, continuous_update=False, orientation='horizontal', readout=True,readout_format='d', layout=widg.Layout(grid_area='check4name', width = '100%'),style=style)\n",
+ "check6name = widg.BoundedIntText(value=1,min=1,max=20,step=1, description='Overall sampling (ITR)', disabled=False,continuous_update=False,orientation='horizontal',readout=True, readout_format='d', layout=widg.Layout(grid_area='check6name', width = '100%'), style=style)\n",
+ "\n",
+ "\n",
+ "\n",
+ "### Layout\n",
+ "graph_controls = widg.GridBox(children=[sample_set, ctf_set, ctf_xaxis, element, beam_pos, fov_show, cl_set, overlap_fig, red_box, box_col, check0name, check1name, check2name, check3name,check4name, check6name, ctf_xaxis_name],\n",
+ " layout=widg.Layout(width='109%', grid_template_rows='35px 35px 35px 35px 5px', grid_template_columns='4% 3.5% 14% 1.5% 8% 8% 8% 1% 26% 14%', grid_template_areas='''\n",
+ " \". ctf_set ctf_set . sample_set overlap_fig overlap_fig . cl_set cl_set \" \n",
+ " \". ctf_xaxis_name ctxaxis . fov_show fov_show fov_show . check0name check2name \"\n",
+ " \". ctf_element ctf_element . beam_pos beam_pos beam_pos . check4name check3name \"\n",
+ " \". . . . red_box red_box box_col . check1name check6name \"\n",
+ " \". . . . . . . . . . \"'''))\n",
+ "\n",
+ "def ptycho_interact(beam_energy, aperture, aperture_res, aperture_res2, probe_size, cl, matrix, defocus, mag, camera, binning, dwell_time, restr, method,\n",
+ " ctf_xaxis, element, graph_size, beam_pos, fov_show, overlap_fig, red_box, box_col, check0name, check1name, check2name, check3name, check4name, check6name):\n",
+ "\n",
+ " fov = pty.get_fov(mag) \n",
+ " pctf_itr = pty.get_ctf(element)\n",
+ " cl_det = pty.get_cl_detector(cl, camera)\n",
+ " step_size = pty.get_step_size(fov, matrix) # in nm\n",
+ " semi_angle = pty.get_angle(aperture)\n",
+ " omega_itr = np.array(pty.get_omegas())\n",
+ " frame_rate = pty.get_aq_frec(dwell_time)\n",
+ " current = pty.get_current(probe_size,aperture) \n",
+ " wavelength = pty.get_wavelength(beam_energy)*1e12 # in pm\n",
+ " semi_angle_corr = pty.get_angle_corr(aperture) \n",
+ " pixel_angle = pty.get_pixel_angle(cl, camera, binning)\n",
+ " beam_diameter = pty.get_beam_diameter(aperture, defocus, semi_angle_corr)\n",
+ " num_pixels, size_pixel = pty.get_detector(camera, binning)\n",
+ " step_size_corr = np.array(pty.get_step_correction())*pty.get_step_size(fov, matrix) # in nm\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",
+ " e_per_scan = (dwell_time/1e6)*(current/1e12/cons.e)\n",
+ " dose = ((matrix**2)*e_per_scan)/((((matrix-1)*step_size_corr)**2)*100)\n",
+ " probe_window = (wavelength*cl_det/100)/(size_pixel/1e6)/1000 # now in nm\n",
+ " oversampling = (wavelength/1000)/(2*pixel_angle/1000*step_size_corr)\n",
+ " max_defocus = (probe_window/4)/np.tan(semi_angle_corr/1000)\n",
+ " z_res = wavelength/(2*np.sin(detector_cover/1000/2)*np.sin(detector_cover/1000/2))/100 # now in A\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",
+ " ### ALL CAMERA LENGTHS PARAMETERS\n",
+ " cl_all = pty.load_cameralengths(camera, \"nominal\")\n",
+ " cl_eff_all = pty.load_cameralengths(camera, \"effective\")\n",
+ " apertures = pty.load_apertures()\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",
+ "\n",
+ " if restr == True:\n",
+ " for x in range(0,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,1) \n",
+ " ptycho_pixel_size_all = (wavelength*np.array(cl_eff_all))/(detector_pixels_all*size_pixel/1e6)/1e4 \n",
+ " else:\n",
+ " ptycho_pixel_size_all = (wavelength*np.array(cl_eff_all))/(num_pixels/2*size_pixel/1e6)/1e4\n",
+ "\n",
+ " probe_window_all = (wavelength*np.array(cl_eff_all)/100)/(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)/np.tan(semi_angle_corr/1000)\n",
+ " max_defocus_all[max_defocus_all < 0] = 'nan'\n",
+ " oversampling_all = (wavelength/1000)/(2*pixel_covers/1000*step_size_corr)\n",
+ " z_res_all = wavelength/(2*np.sin(detector_cover_all/1000/2)*np.sin(detector_cover_all/1000/2))/100 # now in A\n",
+ "\n",
+ " ### MICROSCOPE SCHEME\n",
+ " width = 550 # in-graph setting\n",
+ " det_width = 400 # in-graph setting\n",
+ " reduc = 0.4 # in-graph setting\n",
+ " defo = np.power(defocus,0.4)/100\n",
+ " y_down = np.log(np.max(cl_all))\n",
+ " ssb_cl, kolik = pty.get_cl4ssb(detector_cover_a_all, camera, \"nominal\")\n",
+ " focusdepth = wavelength/(semi_angle_corr/1000)**2/1000\n",
+ " y = -np.log(cl)*np.ones(int(num_pixels)+1)\n",
+ " x = np.linspace(-det_width, det_width, int(num_pixels)+1)\n",
" \n",
- " def probes(self):\n",
- " probes = list(read_excel(self.calib,sheet_name='Probes').Probe)\n",
- " probes = probes[3::]\n",
- " return probes\n",
+ " fig = go.Figure() \n",
+ " fig.update_xaxes(range=[-width, width], showticklabels=False,zeroline=False)\n",
+ " fig.update_yaxes(range=[-y_down, reduc*y_down], showticklabels=False)\n",
+ " fig.add_shape(type=\"rect\",xref=\"x\", yref=\"y\",opacity=0.05, fillcolor=\"gray\", x0=-width, y0=-y_down, x1=width, y1=reduc*y_down,line_color=\"gray\")\n",
+ " fig.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",
+ " fig.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",
+ " fig.add_annotation(x=-0.7*width, y=reduc*0.8*y_down, text=\"Aperture \", showarrow=False, yshift=2)\n",
+ " fig.add_annotation(x=-0.2*width, y=reduc*0.8*y_down, text=str(aperture), showarrow=False, yshift=-15)\n",
+ " fig.add_annotation(x=0, y=-y_down,text='Net acquisition time (s) '+ str(np.round(matrix*matrix*dwell_time/1e6,1)),showarrow=False,yshift=-10)\n",
+ " fig.add_annotation(x=0, y=reduc*0.96*y_down,text='λ (pm) '+ str(np.round(wavelength,2)),showarrow=False,yshift=0)\n",
+ "\n",
+ " # Beam\n",
+ " fig.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",
+ " fig.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",
+ " fig.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",
+ " fig.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",
+ " fig.add_annotation(x=-0.3*width, y=0.05*y_down,text=\"Δf \"+str(np.round(defocus,1))+\" nm\", showarrow=False)\n",
+ " fig.add_annotation(x=0, y=reduc*0.5*y_down,text=\"Current \"+str(np.round(current,1))+\" pA\", showarrow=True,ax=90, ay=0, yshift=0)\n",
+ " fig.add_annotation(x=0, y=reduc*0.5*y_down,text=\"e per spot \"+str(np.round(e_per_scan,1)), showarrow=True,ax=90, ay=0, yshift=-20)\n",
+ " fig.add_annotation(x=-1.7*det_width, y=reduc*0.5*y_down, ax=-0.5*det_width, ay=reduc*0.5*y_down, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=3,arrowsize=2,arrowwidth=2,arrowcolor='black')\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",
+ " # Sample\n",
+ " fig.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",
+ " fig.add_annotation(x=-0.7*width, y=0,text=\"Sample\", showarrow=False, yshift=15, xshift =-8)\n",
+ " fig.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",
+ " fig.add_annotation(x=0.4*width, y=0.05*y_down,text=\"FoV \"+str(np.round(fov,2))+\" nm\", showarrow=False, yshift=0)\n",
+ " fig.add_annotation(x=0.5*width, y=0.05*y_down,text=\"Dose \"+str(np.round(dose,1))+\" e/Å2\", showarrow=False, yshift=-40)\n",
+ " fig.add_annotation(x=-0.5*width, y=0.05*y_down,text=\"DoF \"+str(np.round(focusdepth,1))+\" nm\", showarrow=False, yshift=-40)\n",
+ " fig.add_annotation(x=1.7*det_width, y=0, ax=np.log(fov)/20*width, ay=0, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=3,arrowsize=2,arrowwidth=2,arrowcolor='black')\n",
+ " \n",
+ " # Detector\n",
+ " fig.add_trace(go.Scatter(showlegend=False, x=x, y=y, mode='markers', marker_symbol=\"line-ns\",marker_line_width=0.5))\n",
+ " fig.add_annotation(x=-0.5*width, y=-np.log(cl),text=\"Detector\", showarrow=False,align= 'left', yshift=15)\n",
+ " fig.add_annotation(x=-1.7*det_width, y=-np.log(cl), ax=-det_width, ay=-np.log(cl), xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=3,arrowsize=2,arrowwidth=2,arrowcolor='black',yshift=0)\n",
+ "\n",
+ " # Scattering\n",
+ " fig.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",
+ " fig.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",
+ " \n",
+ " # BF disk\n",
+ " fig.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",
+ " fig.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",
+ " if method == 'ssb':\n",
+ " fig.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",
+ " fig.add_annotation(x=0*width, y=-np.log(ssb_cl),text=\"\", showarrow=False, align= 'left', yshift=15)\n",
+ " if restr == True:\n",
+ " fig.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",
+ " fig.add_annotation(x=-0.35*width, y=-reduc*0.2*y_down,text=\"PAAR\", showarrow=False,align= 'left', yshift=-15)\n",
+ " \n",
+ " # Cover\n",
+ " fig.add_annotation(x=0, y=-np.log(cl), ax=det_width, ay=-np.log(cl), xref='x',yref='y',axref='x',ayref='y', text='', showarrow=True,arrowhead=3,arrowsize=1,arrowwidth=1,arrowcolor='black')\n",
+ " fig.add_annotation(x=det_width,y=-np.log(cl), ax=0, ay=-np.log(cl), xref='x',yref='y',axref='x',ayref='y', text='', showarrow=True,arrowhead=3,arrowsize=1,arrowwidth=1,arrowcolor='black')\n",
+ " fig.add_annotation(x=det_width/2, y=-np.log(cl), text=str(np.round(detector_cover,1)) + \" mrad or \" + str(np.round(covered_alfas,1))+\"α\", showarrow=False, yshift=15, xshift=0)\n",
+ " \n",
+ " # CLs\n",
+ " xx = 0\n",
+ " for x in cl_all:\n",
+ " if xx == 0:\n",
+ " fig.add_annotation(x=-0.7*width, y=-np.log(x),text=\"Nominal CL\", showarrow=False, yshift=50)\n",
+ " fig.add_annotation(x=-0.7*width, y=-np.log(x),text=\"(cm)\", showarrow=False, yshift=35)\n",
+ " fig.add_annotation(x= 0.7*width, y=-np.log(x),text=\"Effective CL\", showarrow=False, yshift=50)\n",
+ " fig.add_annotation(x= 0.7*width, y=-np.log(x),text=\"(cm)\", showarrow=False, yshift=35)\n",
+ " fig.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",
+ " fig.add_annotation(x=-0.9*width, y=-np.log(x), text=str(x), showarrow=False, yshift=8)\n",
+ " fig.add_annotation(x=0.85*width, y=-np.log(x), text=str(np.round(cl_eff_all[xx],1)), showarrow=False, yshift=8)\n",
+ " xx +=1\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",
+ " fig.add_annotation(x=width, y=-np.log(cl_all[0]), ax=width, ay=-np.log(cl_all[-1]), xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=0,arrowsize=2,arrowwidth=2,arrowcolor='gray',yshift=0)\n",
+ " fig.add_annotation(x=1.7*det_width, y=-(np.log(cl_all[0])+np.log(cl_all[-1]))/2,ax=width, ay=-(np.log(cl_all[0])+np.log(cl_all[-1]))/2, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=3,arrowsize=2,arrowwidth=2,arrowcolor='black')\n",
+ " fig.update_xaxes(title_text=\"\")\n",
+ " fig.update_layout(plot_bgcolor='white',width=4.1*graph_size, height=7.2*graph_size, margin = dict(l=0.45*graph_size, r=0.45*graph_size, t=0.0*graph_size, b=0))\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",
+ " ### SAMPLE PLANE\n",
+ " match overlap_fig: \n",
+ " case 'Geometrical':\n",
+ " wid = np.linspace(-beam_pos/2,beam_pos/2,beam_pos+1)*step_size_corr\n",
+ " yyy = np.append(np.linspace(0,overlap,100),200)\n",
+ " \n",
+ " fig1 = make_subplots(specs=[[{\"secondary_y\": True}]])\n",
+ " fig1.update_xaxes(title_text=\"Sample plane (nm)\", range=[-fov_show/2, fov_show/2], showgrid=False, zeroline=False)\n",
+ " fig1.update_yaxes(range=[-fov_show/2, fov_show/2],showgrid=False, showticklabels=False)\n",
+ " \n",
+ " for x in range(len(wid)): \n",
+ " fig1.add_trace(go.Scatter(showlegend=False, x=wid, y=np.ones(len(wid))*wid[x], marker_color='black'),secondary_y=False)\n",
+ " for y in range(len(wid)): \n",
+ " fig1.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",
+ " fig1.add_annotation(x=-1*step_size_corr, y=-2*step_size_corr, ax=-2*step_size_corr, ay=-2*step_size_corr, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='red')\n",
+ " fig1.add_annotation(x=-2*step_size_corr, y=-1*step_size_corr, ax=-2*step_size_corr, ay=-2*step_size_corr, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='red')\n",
+ " fig1.add_annotation(x=2*step_size_corr-0.75*beam_diameter/2, y=-2*step_size_corr-0.75*beam_diameter/2, ax=2*step_size_corr, ay=-2*step_size_corr,xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='blue')\n",
+ " fig1.add_annotation(x=2*step_size_corr+0.75*beam_diameter/2, y=-2*step_size_corr+0.75*beam_diameter/2, ax=2*step_size_corr, ay=-2*step_size_corr,xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='blue')\n",
+ " fig1.add_trace(go.Scatter(showlegend=True, x=[-100], y=[-100],marker_size=12, marker_color='red', name='Step '+str(np.round(10*step_size_corr,2))+' Å')) \n",
+ " fig1.add_trace(go.Scatter(showlegend=True, x=[-100], y=[-100],marker_size=12, marker_color='blue', name='Beam ⌀ '+str(np.round(10*beam_diameter,2))+' Å')) \n",
+ " \n",
+ " if method == 'ssb':\n",
+ " omega, pctf = pty.get_ssb_ctf()\n",
+ " xx = wavelength/(np.sin(semi_angle_corr*omega/1000))/100\n",
+ " fig1.add_trace(go.Scatter(showlegend=True, x=[-100], y=[-100],marker_size=12, marker_color='green', name='Rec step '+str(np.round(xx[-1]/3,2))+' Å')) \n",
+ " fig1.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.0,xanchor=\"right\",x=0.9))\n",
+ "\n",
+ " fig1.add_trace(go.Scatter(showlegend=False, x = -fov_show/2*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",
+ " fig1.update_yaxes(range=[0, 100], showgrid=False, showticklabels=False, secondary_y=True)\n",
+ " fig1.update_yaxes(title_text=\"Overlap (%)\", showgrid=False, showticklabels=True, tickvals = [-fov_show/2, -fov_show/4, 0, fov_show/4, fov_show/2],ticktext = ['0', '25', '50', '75', '100'], secondary_y=False)\n",
+ " fig1.update_layout(plot_bgcolor='white', legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.9))\n",
+ " fig1.update_xaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
+ " fig1.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
+ "\n",
+ " match method: \n",
+ " case 'ssb':\n",
+ " fig1.update_layout(width=3.6*graph_size, height=4*graph_size, margin =dict(l=0.6*graph_size, r=0.3*graph_size, t=0.1*graph_size, b=0.7*graph_size))\n",
+ " fig1.update_layout(title={'text': \"Sample\",'y': 0.87, 'x': 0.17,'xanchor': 'left','yanchor': 'top'})\n",
+ " case 'iterative':\n",
+ " fig1.update_layout(legend=dict(orientation=\"h\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=1.0))\n",
+ " fig1.update_layout(title={'text': \"Sample\",'y': 0.92, 'x': 0.5,'xanchor': 'left','yanchor': 'top'})\n",
+ " fig1.update_layout(width=3.5*graph_size, height=3.7*graph_size, margin =dict(l=0.8*graph_size, r=0.0*graph_size, t=0.8*graph_size, b=0))\n",
+ "\n",
+ " case 'Ilumination':\n",
+ " if abtem == True:\n",
+ " sampling= 0.05 # sampling of the simulated potential in A\n",
+ " sys.stdout = io.StringIO() # create a text trap and redirect stdout\n",
+ " probe = Probe(sampling = sampling, extent = 2*beam_diameter*10, energy = beam_energy*1e3, semiangle_cutoff = semi_angle_corr, defocus = defocus*10) # sampling=sampling, extent=A , energy=beam*1e3eV, semiangle_cutoff=mrad, defocus=A)\n",
+ " intensity = probe.build().intensity().compute()\n",
+ " intensity = np.abs(intensity.array)\n",
+ " sys.stdout = sys.__stdout__ # now restore stdout function\n",
+ " x_pix = int(step_size_corr*10/sampling) # step size from nm to A\n",
+ " field = np.zeros([intensity.shape[0]+(beam_pos)*x_pix, intensity.shape[1]+(beam_pos)*x_pix])\n",
+ " cen = int(intensity.shape[0]/2)\n",
+ " \n",
+ " for i in range(0,beam_pos+1):\n",
+ " for j in range(0,beam_pos+1):\n",
+ " xx = x_pix*i\n",
+ " xy = x_pix*j\n",
+ " field[xy:intensity.shape[0]+xy,xx:intensity.shape[0]+xx]=field[xy:intensity.shape[0]+xy,xx:intensity.shape[0]+xx]+intensity\n",
+ " \n",
+ " field_size =int(field.shape[0]) \n",
+ " field_cen = int(field.shape[0]/2)\n",
+ " middle = field[int(field_cen-(x_pix*(beam_pos)*red_box)):int(field_cen+(x_pix*(beam_pos)*red_box)),int(field_cen-(x_pix*(beam_pos)*red_box)):int(field_cen+(x_pix*(beam_pos)*red_box))]\n",
+ " uniformity = (1-(np.max(middle)-np.min(middle))/(np.max(field)-np.min(field)))*100\n",
" \n",
- "opt = interaction()\n",
+ " fig1 = go.Figure() \n",
+ " fig1.add_trace(px.imshow(field).data[0])\n",
+ " fig1.add_shape(type=\"rect\",x0= field_cen-red_box*field_size, y0=field_cen-red_box*field_size, x1= field_cen+red_box*field_size, y1=field_cen+red_box*field_size,line=dict(color=box_col))\n",
+ " fig1.update_layout(title={'text': \"Uniformity: \"+str(np.round(uniformity,1))+\"%\",'y':0.85, 'x':0.3,'xanchor': 'left','yanchor': 'top'})\n",
+ " fig1.update_traces(dict(showscale=False, coloraxis=None, colorscale='plasma'), selector={'type':'heatmap'})\n",
+ " fig1.update_xaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\", title_text=\"Sample plane (nm)\", showgrid=False, showticklabels=True,\n",
+ " tickvals = [0, field.shape[0]/2, field.shape[0]-1], ticktext = [0, np.round((field.shape[0]/2)*sampling,1), np.round((field.shape[0]-1)*sampling,1)]).update_yaxes(showticklabels=False)\n",
+ " fig1.update_layout(width=3.1*graph_size, height=3.9*graph_size, margin =dict(l=0.5*graph_size, r=0.2*graph_size, t=0.9*graph_size, b=0.55*graph_size))\n",
+ " else:\n",
+ " fig1 = go.Figure() \n",
+ " fig1.update_layout(title={'text': \"abTEM not available\",'y': 0.98, 'x': 0.14,'xanchor': 'left','yanchor': 'top'})\n",
+ " fig1.update_layout(width=3.1*graph_size, height=3.9*graph_size, margin =dict(l=0.5*graph_size, r=0.2*graph_size, t=0.9*graph_size, b=0.55*graph_size))\n",
"\n",
- "\n",
- "class ptychoScopy:\n",
- " \"\"\"Computes various characteristics describing used setting.\"\"\"\n",
+ " ### DETECTOR PLANE\n",
+ " fig2 = make_subplots(specs=[[{\"secondary_y\": True}]])\n",
+ " fig2.update_xaxes(title_text=\"Detector pixel array\", range=[0.5, num_pixels+0.5], tickvals = [1, num_pixels/2+0.5, num_pixels], ticktext = [1, num_pixels/2, num_pixels], showticklabels=True,showgrid=True) \n",
+ " fig2.update_yaxes(range=[0.5, num_pixels+0.5], showticklabels=False, showgrid=False, secondary_y=False)\n",
+ " fig2.add_shape(type=\"circle\",xref=\"x\", yref=\"y\",opacity=0.5, fillcolor=\"#FF7F7F\", x0=(num_pixels+1)/2-beam_diameter_pix/2, y0=(num_pixels+1)/2-beam_diameter_pix/2, x1=(num_pixels+1)/2+beam_diameter_pix/2, y1=(num_pixels+1)/2+beam_diameter_pix/2,line_color=\"red\",secondary_y=False)\n",
+ " fig2.add_shape(type=\"rect\",xref=\"x\", yref=\"y\",opacity=0.5, fillcolor=\"#f0f921\", x0=0.5, y0=0.5, x1=1.5, y1=1.5,line_color=\"#000004\",secondary_y=False) \n",
+ " fig2.add_annotation(x=(num_pixels+1)/2-beam_diameter_pix/2, y=(num_pixels+1)/2, ax=(num_pixels+1)/2+beam_diameter_pix/2, ay=(num_pixels+1)/2, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='black')\n",
+ " fig2.add_annotation(x=(num_pixels+1)/2+beam_diameter_pix/2,y=(num_pixels+1)/2, ax=(num_pixels+1)/2-beam_diameter_pix/2, ay=(num_pixels+1)/2, xref='x',yref='y',axref='x',ayref='y', text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='black')\n",
+ " fig2.add_annotation(x=(num_pixels+1)/2, y=(num_pixels+1)/2, text=str(np.round(beam_diameter_pix,1))+\" pix\", showarrow=False, yshift=10)\n",
+ " fig2.add_annotation(x=1, y=1, text=str(np.round(size_pixel,2))+\" μm ≈ \" +str(np.round(pixel_angle,4))+\" mrad\", showarrow=False, xshift=70+(50/np.sqrt(num_pixels)), yshift=10+(50/np.sqrt(num_pixels)))\n",
+ " fig2.update_yaxes(title_text=\"Cover angle (mrad)\", showticklabels=True, showgrid=True, range=[0.5, num_pixels+0.5], tickvals = [1, num_pixels/2+0.5, num_pixels], ticktext = [str(np.round(-detector_cover,1)), \"0\", str(np.round(detector_cover,1))])\n",
+ " fig2.update_layout(plot_bgcolor='white', legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"left\",x=0.1))\n",
+ " fig2.update_xaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
+ " fig2.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
+ " fig2.update_layout(title={'text': \"Detector\",'y':0.65, 'x': 0.44,'xanchor': 'left','yanchor': 'top'})\n",
+ " fig2.update_layout(width=3.45*graph_size, height=4.7*graph_size, margin =dict(l=0.65*graph_size, r=0.1*graph_size, t=1.9*graph_size, b=0)) \n",
+ " fig2.add_annotation(x=(num_pixels+1)/2, y=(num_pixels+1)/2, text=\"BF disk\", showarrow=False, yshift=-15, font=dict(family=\"calibri\", size=18, color=\"#FF7F7F\"))\n",
" \n",
- " def __init__(self):\n",
- " self.calib = calib\n",
+ " match method: \n",
+ " case 'ssb':\n",
+ " ### CAMERA LENGTH GRAPH\n",
+ " fig4 = make_subplots(specs=[[{\"secondary_y\": True}]])\n",
+ " fig4.add_trace(go.Scatter(showlegend=False,x=cl_all, y=detector_cover_all, marker_color='black'), secondary_y=False)\n",
+ " fig4.add_trace(go.Scatter(showlegend=False,x=cl_all, y=detector_cover_a_all,marker_color='black'), 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 = \"Maximal CL\"), secondary_y=True) \n",
+ " fig4.add_trace(go.Scatter(showlegend=False,x=[np.min(cl_all)/1.5,np.array(cl)], y=[detector_cover, detector_cover], mode='lines',marker_color='gray'), secondary_y=False)\n",
+ " fig4.add_trace(go.Scatter(showlegend=False,x=[np.array(cl),np.array(cl)], y=[0, np.array(covered_alfas)], mode='lines',marker_color='gray'), secondary_y=True)\n",
+ " fig4.add_trace(go.Scatter(showlegend=False,x=[np.array(cl),np.max(cl_all)*1.5], y=[np.array(covered_alfas), np.array(covered_alfas)], mode='lines',marker_color='gray'), secondary_y=True)\n",
+ " fig4.add_trace(go.Scatter(showlegend=False,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_annotation(x=np.log10(np.max(cl_all)), y=detector_cover, text=str(np.round(covered_alfas,1)), showarrow=False, xshift=20, yshift=+10, secondary_y=False)\n",
+ " fig4.add_annotation(x=np.log10(np.min(cl_all)), y=detector_cover, text=str(np.round(detector_cover,1)), showarrow=False, xshift=-20, yshift=+10, secondary_y=False)\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_xaxes(title_text=\"Nominal camera length (cm)\", type=\"log\", tickvals = cl_all, mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
+ " fig4.update_xaxes(range=[np.log10(np.min(cl_all)/1.5), np.log10(np.max(cl_all)*1.5)]) \n",
+ " fig4.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\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(title={'text': \"Camera length\",'y':0.95, 'x':0.17,'xanchor': 'left','yanchor': 'top'}, legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.95), plot_bgcolor='white')\n",
+ " fig4.update_layout(width=3.61*graph_size, height=3.4*graph_size, margin =dict(l=0.3*graph_size, r=0.25*graph_size, t=0.3*graph_size, b=0.3*graph_size))\n",
+ " \n",
+ " ### SSB-PCTF\n",
+ " omega, pctf = pty.get_ssb_ctf()\n",
+ " xx = wavelength/(np.sin(semi_angle_corr*omega/1000))/100 # pitch size\n",
+ " \n",
+ " fig5 = go.Figure() \n",
+ " fig5.update_yaxes(title_text=\"Transfer (-)\")\n",
+ " match ctf_xaxis:\n",
+ " case 'α':\n",
+ " fig5.add_trace(go.Scatter(showlegend=True, x=omega, y=pctf, marker_color='red', name='For all apertures')) \n",
+ " fig5.update_xaxes(title_text=\"Scattering angle (α)\", range=[0, 2], zeroline=False)\n",
+ " \n",
+ " case 'mrad':\n",
+ " for x in apertures:\n",
+ " if x == apertures[0]:\n",
+ " fig5.add_trace(go.Scatter(showlegend=True, x=pty.get_angle_corr(x)*omega, y=pctf, marker_color='gray', name='Others'))\n",
+ " else:\n",
+ " fig5.add_trace(go.Scatter(showlegend=False, x=pty.get_angle_corr(x)*omega, y=pctf, marker_color='gray'))\n",
+ " fig5.add_trace(go.Scatter(showlegend=True, x=semi_angle_corr*omega, y=pctf, marker_color='red', name='Selected aperture'))\n",
+ " fig5.update_xaxes(title_text=\"Scattering angle (mrad)\", range=[0, 2*semi_angle_corr], zeroline=False)\n",
"\n",
- " def get_omegas(self):\n",
- " excel_data = read_excel(calib,sheet_name='CTF')\n",
- " excel_lin = list((excel_data[excel_data.CTF.isin([\"CTF\"])]))\n",
- " self.omegas = excel_lin[1::]\n",
- " return self.omegas\n",
+ " case 'Å':\n",
+ " for x in apertures:\n",
+ " d = wavelength/(np.sin(pty.get_angle_corr(x)*omega/1000))/100 # Full pitch size\n",
+ " if x == apertures[0]:\n",
+ " fig5.add_trace(go.Scatter(showlegend=True, x=d, y=pctf, marker_color='gray', name='Others'))\n",
+ " else:\n",
+ " fig5.add_trace(go.Scatter(showlegend=False, x=d, y=pctf, marker_color='gray'))\n",
+ " fig5.add_trace(go.Scatter(showlegend=True, x=xx, y=pctf, marker_color='red', name='Selected aperture'))\n",
+ " fig5.update_xaxes(title_text=\"Spacing (Å)\", range=[-0.5, 2], type=\"log\", zeroline=False)\n",
+ " \n",
+ " fig5.update_layout(plot_bgcolor='white', title={'text': \"Phase CTF\",'y':0.99, 'x':0.42,'xanchor': 'left','yanchor': 'top'},legend=dict(orientation=\"h\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.95)) \n",
+ " fig5.update_xaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
+ " fig5.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
+ " fig5.update_layout(width=3.5*graph_size, height=2.2*graph_size, margin = dict(l=0.3*graph_size, r=0.3*graph_size, t=0.5*graph_size, b=0.4*graph_size))\n",
+ " \n",
+ " case 'iterative':\n",
+ " ### ITR-PCTF\n",
+ " pctf_norm = pctf_itr/np.max(pctf_itr)\n",
+ " fig5 = go.Figure() \n",
+ " fig5.update_yaxes(title_text=\"Transfer (-)\")\n",
+ " match ctf_xaxis: \n",
+ " case 'α':\n",
+ " fig5.add_trace(go.Scatter(showlegend=True, x=omega_itr, y= pctf_norm, marker_color='red', name='For all apertures'))\n",
+ " fig5.update_xaxes(title_text=\"Scattering angle (α)\", range=[0, 6], zeroline=False)\n",
+ " fig5.update_yaxes(range=[0, 1.1])\n",
+ " case 'mrad': \n",
+ " for x in apertures:\n",
+ " if x == apertures[0]:\n",
+ " fig5.add_trace(go.Scatter(showlegend=True, x=pty.get_angle_corr(x)*omega_itr, y=pctf_norm, marker_color='gray', name='Others'))\n",
+ " else:\n",
+ " fig5.add_trace(go.Scatter(showlegend=False, x=pty.get_angle_corr(x)*omega_itr, y=pctf_norm, marker_color='gray'))\n",
+ " fig5.add_trace(go.Scatter(showlegend=True, x=semi_angle_corr*omega_itr, y=pctf_norm, marker_color='red', name='Selected aperture'))\n",
+ " fig5.update_xaxes(title_text=\"Scattering angle (mrad)\", range=[0, 6*semi_angle_corr], zeroline=False)\n",
+ " case 'Å':\n",
+ " for x in apertures:\n",
+ " d = wavelength/(np.sin(pty.get_angle_corr(x)*omega_itr/1000))/100\n",
+ " if x == apertures[0]:\n",
+ " fig5.add_trace(go.Scatter(showlegend=True, x=d, y=pctf_norm, marker_color='gray', name='Others'))\n",
+ " else:\n",
+ " fig5.add_trace(go.Scatter(showlegend=False, x=d, y=pctf_norm, marker_color='gray'))\n",
+ " xx = wavelength/(np.sin(semi_angle_corr*omega_itr/1000))/100\n",
+ " fig5.add_trace(go.Scatter(showlegend=True, x=xx, y=pctf_norm, marker_color='red', name='Selected aperture'))\n",
+ " fig5.update_xaxes(title_text=\"Spacing (Å)\",range=[-1, 2], type=\"log\", zeroline=False)\n",
+ " \n",
+ " fig5.update_layout(title={'text': \"Phase CTF\",'y':0.99, 'x':0.42,'xanchor': 'left','yanchor': 'top'},legend=dict(orientation=\"h\",yanchor=\"bottom\",y=1.01,xanchor=\"left\",x=0),plot_bgcolor='white') \n",
+ " fig5.update_xaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
+ " fig5.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
+ " fig5.update_layout(width=3.5*graph_size, height=2.2*graph_size, margin = dict(l=0.3*graph_size, r=0.3*graph_size, t=0.5*graph_size, b=0.4*graph_size))\n",
"\n",
- " def get_ctf(self, element):\n",
- " excel_data = read_excel(calib, sheet_name='CTF', header = 0)\n",
- " excel_line = np.array(excel_data[excel_data.CTF.isin([element])])\n",
- " ctf = excel_line[0]\n",
- " self.ctf = ctf[1::]\n",
- " return self.ctf\n",
+ " ### PROBE WINDOW\n",
+ " match overlap_fig:\n",
+ " case 'Geometrical': \n",
+ " if beam_diameter < probe_window/2:\n",
+ " color = \"green\"\n",
+ " elif beam_diameter < probe_window:\n",
+ " color = \"orange\"\n",
+ " else:\n",
+ " color = \"red\"\n",
+ "\n",
+ " opacity =[0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4]\n",
+ " xcoef = [8, 6, 5, 4.25, 3.5, 3, 2.5, 2]\n",
+ "\n",
+ " fig3 = go.Figure() \n",
+ " fig3.add_shape(type=\"rect\",xref=\"x\", yref=\"y\",opacity=0.3, fillcolor=\"#6F6F6F\", x0=probe_window/4, y0=probe_window/4, x1=3*probe_window/4, y1=3*probe_window/4,line_color=\"#6F6F6F\")\n",
+ " fig3.add_trace(go.Scatter(x=np.array(probe_window/2), y=np.array(probe_window/2), name='Maximal recomm. Δf '+str(np.round(max_defocus,1))+' nm', showlegend=True, marker_color=color, opacity = 0))\n",
+ "\n",
+ " for i in range(0, len(opacity)):\n",
+ " fig3.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=opacity[i], fillcolor=color, x0=probe_window/2-beam_diameter/xcoef[i], y0=probe_window/2-beam_diameter/xcoef[i], \n",
+ " x1=probe_window/2+beam_diameter/xcoef[i], y1=probe_window/2+beam_diameter/xcoef[i], line_color=color)\n",
+ " \n",
+ " fig3.update_xaxes(title_text=\"Reconstruction box (nm)\", range=[0, probe_window], tickvals = [0, probe_window/4, probe_window/2, 3*probe_window/4, probe_window], ticktext = [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)])\n",
+ " fig3.update_yaxes(range=[0, probe_window], tickvals = [0, probe_window/4, probe_window/2, 3*probe_window/4, probe_window], showticklabels=False)\n",
+ " fig3.update_layout(plot_bgcolor='white',legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.8),title={'text':\"Probe\",'y':0.92,'x':0.4,'xanchor':'left','yanchor':'top'})\n",
+ " fig3.update_xaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
+ " fig3.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
+ " fig3.update_layout(width=2.7*graph_size, height=4.0*graph_size, margin =dict(l=0, r=0, t=0.8*graph_size, b=0.75*graph_size)) \n",
+ "\n",
+ " case 'Ilumination': \n",
+ " if abtem == True:\n",
+ " sampling= 0.1 # sampling of the simulated potential in A\n",
+ " probe = Probe(sampling = sampling, extent = 2*probe_window*10, energy = beam_energy*1e3, semiangle_cutoff = semi_angle_corr, defocus = defocus*10)\n",
+ " # probe = Probe(sampling=sampling, extent= A , energy=beam*1e3 eV, semiangle_cutoff = mrad, defocus= A)\n",
+ " intensity2 = probe.build().intensity().compute().array\n",
+ " intensity3 = intensity2/np.max(intensity2)\n",
+ " cen2 = intensity3.shape\n",
+ " sirkaA = cen2[0]*sampling\n",
+ " sirkaB = np.round(probe_window,2)*10/sampling\n",
+ " just_probe_window = intensity3[int(cen2[0]/2)-int(sirkaB/2):int(cen2[0]/2)+int(sirkaB/2), int(cen2[0]/2)-int(sirkaB/2):int(cen2[0]/2)+int(sirkaB/2)]\n",
+ " int_tot = np.sum(just_probe_window)/np.sum(intensity3)*100\n",
+ " cross_section = intensity2[int(cen2[0]/2),:]\n",
+ " cross_section = (cross_section-np.min(cross_section))/np.max(cross_section)\n",
+ "\n",
+ " fig3 = go.Figure() \n",
+ " fig3.add_trace(px.imshow(intensity3).data[0])\n",
+ " fig3.add_trace(go.Scatter(x=np.linspace(0,int(cen2[0])-1,len(cross_section)), y=int(cen2[0]/4)+cross_section*int(cen2[0]/2), showlegend=False, marker_color=\"white\", opacity = 0.7))\n",
+ " fig3.add_shape(type=\"rect\",x0= cen2[0]/2-sirkaB/2, y0=cen2[0]/2-sirkaB/2, x1= cen2[1]/2+sirkaB/2, y1=cen2[1]/2+sirkaB/2, line=dict(color=\"red\"))\n",
+ " fig3.update_layout(title={'text': \"Probe cover \",'y':0.85, 'x':0.3,'xanchor': 'left','yanchor': 'top'})\n",
+ " fig3.update_traces(dict(showscale=False, coloraxis=None, colorscale='plasma'), selector={'type':'heatmap'})\n",
+ " fig3.update_xaxes(showticklabels=False).update_yaxes(showticklabels=False)\n",
+ " fig3.add_annotation(x=cen2[0]/2, y=cen2[0]/2+sirkaB/2, text='Recon. box '+str(np.round(probe_window,2))+' nm', showarrow=False, yshift=15)\n",
+ " fig3.add_annotation(x=cen2[0]/2, y=cen2[0]/2-sirkaB/2, text='Probe covered '+str(np.round(int_tot,1))+' %', showarrow=False, yshift=-15)\n",
+ " fig3.update_annotations(font=dict(color=\"white\"))\n",
+ " fig3.update_layout(width=2.7*graph_size, height=3.9*graph_size, margin =dict(l=0.1*graph_size, r=0.1*graph_size, t=0.9*graph_size, b=0.55*graph_size))\n",
+ " else:\n",
+ " fig3 = go.Figure() \n",
+ " fig3.update_layout(title={'text': \"abTEM not available\",'y': 0.98, 'x': 0.14,'xanchor': 'left','yanchor': 'top'})\n",
+ " fig3.update_layout(width=2.7*graph_size, height=3.9*graph_size, margin =dict(l=0.1*graph_size, r=0.1*graph_size, t=0.9*graph_size, b=0.55*graph_size))\n",
+ " \n",
+ " ### FINAL CHECKS \n",
+ " check1 = widg.Valid(value= bool(overlap > check4name), description='Beam overlap',layout=widg.Layout(width='250px'), style = {'description_width': '100px'}, disabled=True)\n",
+ " check2 = widg.Valid(value= bool(step_size_corr*10 > (wavelength*cl_det)/(num_pixels*size_pixel/1e6)/1e4), description='Resolution gain', layout=widg.Layout(width='250px'), style = {'description_width': '100px'}, disabled=True)\n",
+ " check3 = widg.Valid(value= bool(beam_diameter/2 < probe_window/2), description='Box coverage', layout=widg.Layout(width='250px'), style = {'description_width': '100px'}, disabled=True) \n",
+ " check4 = widg.Valid(value= bool(oversampling > 1), description='Overall sampling', layout=widg.Layout(width='250px'), style = {'description_width': '100px'}, disabled=True) \n",
+ " checks = widg.VBox([widg.HBox([check1, check2]), widg.HBox([check3, check4])]) # Label('Final checks')\n",
+ " checks.layout = widg.Layout(margin='0px 0px 0px 100px', padding='0px 0px 0px 0px', border='solid 3px gray') # border='dashed 1px gray'\n",
+ "\n",
+ " ### CAMERA LENGTH TABLE\n",
+ " dictionary = {}\n",
+ " tab = np.array([cl_all, np.round(ptycho_pixel_size_all,2), np.round(z_res_all,2), np.round(detector_cover_all,1), np.round(detector_cover_a_all,1), np.round(probe_window_all,1), np.round(oversampling_all,1)])\n",
+ " \n",
+ " for i in range(0,len(cl_eff_all)):\n",
+ " button_style = 'success'\n",
+ " icons=['','','','','','','']\n",
+ " data = tab[:,int(i)] # 0.cl, 1. ptycho pix xy, 2. ptycho pix z, 3.det cov, 4.det cov a, 5.max def, 6.probe window, 7.oversampling\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",
- " FoVat1x = [str(e) for e in list(read_excel(calib,sheet_name='Ranges').FoVat1x)]\n",
- " FoVat1x = np.array([x for x in FoVat1x if x != 'nan']).astype(float)\n",
- " FoVat1x = FoVat1x.item()\n",
- " self.fov = FoVat1x/(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",
+ " if cl == data[0]:\n",
+ " icons=['hand-point-left','','','','','',''] \n",
+ " if check2name == True and data[1] > step_size_corr*10: # check2name = 'Ptycho pixel < step size'\n",
+ " icons=['','bell','','','','',''] \n",
+ " button_style = 'warning'\n",
+ " if data[3] > 1000*np.radians(check1name): # check1name = 'Low anlge approximation'\n",
+ " icons=['','','','bell','','',''] \n",
+ " button_style = 'warning' \n",
+ " \n",
+ " if data[4] < check0name[0] or data[4] > check0name[1]: # 'Detector cover'\n",
+ " icons=['','','','','bell','',''] \n",
+ " button_style = 'warning'\n",
+ " if check3name == True and beam_diameter > data[5]/2 and beam_diameter < data[5]:\n",
+ " icons=['','','','','','bell',''] \n",
+ " button_style = 'warning'\n",
+ " if check3name == True and beam_diameter > data[5]:\n",
+ " icons=['','','','','','ban',''] \n",
+ " button_style = 'danger'\n",
+ " if data[6] < 1: # check6name = 'Sampling > 1' \n",
+ " icons=['','','','','','','ban'] \n",
+ " button_style = 'danger' \n",
+ " if data[6] > 1 and data[6] < int(check6name): # check6name = 'Sampling > check6name' \n",
+ " icons=['','','','','','','bell'] \n",
+ " button_style = 'warning' \n",
+ " dictionary[i] = widg.ToggleButtons(options=tuple(data), text_color= 'red', button_style=button_style, icons = icons, layout=widg.Layout(width=str(int(graph_size/100*65))+'px'),\n",
+ " style = {'description_width': '0px','button_width': str(int(graph_size/100*63))+'px'}, disabled=True)\n",
+ " legend = widg.ToggleButtons(options=['Nominal CL (cm)','Resolution XY (Å)','Resolution Z (Å)', 'Detector cover (mrad)','Detector cover (α)', 'Reconstr. box (nm)', 'Overall sampling'],\n",
+ " button_style='', layout=widg.Layout(width='150px'), style = {'description_width': '0px','button_width': \"150px\"}, disabled=True) \n",
+ " \n",
+ " # FIX here\n",
+ " match len(cl_eff_all):\n",
+ " case 1: \n",
+ " cltab = widg.HBox([legend, dictionary[0]])\n",
+ " case 2: \n",
+ " cltab = widg.HBox([legend, dictionary[0], dictionary[1]])\n",
+ " case 3: \n",
+ " cltab = widg.HBox([legend, dictionary[0], dictionary[1], dictionary[2]])\n",
+ " case 4: \n",
+ " cltab = widg.HBox([legend, dictionary[0], dictionary[1], dictionary[2], dictionary[3]])\n",
+ " case 5: \n",
+ " cltab = widg.HBox([legend, dictionary[0], dictionary[1], dictionary[2], dictionary[3], dictionary[4]])\n",
+ " case 6: \n",
+ " cltab = widg.HBox([legend, dictionary[0], dictionary[1], dictionary[2], dictionary[3], dictionary[4], dictionary[5]])\n",
+ " case 7: \n",
+ " cltab = widg.HBox([legend, dictionary[0], dictionary[1], dictionary[2], dictionary[3], dictionary[4], dictionary[5], dictionary[6]])\n",
+ " case 8: \n",
+ " cltab = widg.HBox([legend, dictionary[0], dictionary[1], dictionary[2], dictionary[3], dictionary[4], dictionary[5], dictionary[6], dictionary[7]])\n",
+ " case 9: \n",
+ " cltab = widg.HBox([legend, dictionary[0], dictionary[1], dictionary[2], dictionary[3], dictionary[4], dictionary[5], dictionary[6], dictionary[7], dictionary[8]])\n",
+ " case 10: \n",
+ " cltab = widg.HBox([legend, dictionary[0], dictionary[1], dictionary[2], dictionary[3], dictionary[4], dictionary[5], dictionary[6], dictionary[7], dictionary[8], dictionary[9]])\n",
+ " case 11: \n",
+ " cltab = widg.HBox([legend, dictionary[0], dictionary[1], dictionary[2], dictionary[3], dictionary[4], dictionary[5], dictionary[6], dictionary[7], dictionary[8], dictionary[9], dictionary[10]])\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",
+ " cltab = widg.VBox([widg.Label('CAMERA LENGTH GUIDE'), cltab])\n",
+ " cltab.layout = widg.Layout(border='solid 0px gray',margin='0px 0px 0px 0px', padding='5px 5px 5px 5px')\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 = 2*defocus*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",
+ " ### SHOWING\n",
+ " match method: \n",
+ " case 'ssb':\n",
+ " right = widg.VBox([go.FigureWidget(fig1),go.FigureWidget(fig4)])\n",
+ " case 'iterative':\n",
+ " right = widg.VBox([widg.HBox([go.FigureWidget(fig1),go.FigureWidget(fig3)]), cltab, checks])\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",
+ " left = widg.VBox([go.FigureWidget(fig5),go.FigureWidget(fig2)])\n",
+ " total = widg.HBox([left, go.FigureWidget(fig), right])\n",
+ " total.layout = widg.Layout(border='solid 0px gray',margin='10px 10px 10px 10px', padding='0px 0px 0px 0px') \n",
+ " display(total)\n",
+ " return \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",
- " 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",
- "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",
- " def show_wavelength(self,caller):\n",
- " beam_res.value = f'λ (pm) {str(\"{:.1f}\".format(pty.get_wavelength(caller.new)*1e12))}'\n",
- " return beam_res.value\n",
- " \n",
- " def show_probe_angle(self,caller):\n",
- " aperture_res.value = f'Semi-angle (mrad) {\"{:.1f}\".format(pty.get_angle(caller.new))}' \n",
- " return aperture_res.value\n",
- " \n",
- " def show_corrprobe_angle(self,caller):\n",
- " aperture_res2.value = f'corr. {\"{:.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'FoV (nm) {\"{:.1f}\".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'Rate (kHz) {\"{:.1f}\".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",
+ "gui = widg.interactive_output(ptycho_interact, {\"beam_energy\" : beam_energy, \"aperture\": aperture, \"aperture_res\": aperture_res, \"aperture_res2\": aperture_res2, \"probe_size\": probe_size, \"cl\": cl, \"matrix\": matrix,\n",
+ " \"defocus\": defocus, \"mag\": mag, \"camera\": camera, \"binning\": binning, \"dwell_time\" : dwell_time, \"restr\": restr, \"method\": method, \"ctf_xaxis\": ctf_xaxis, \"element\": element,\n",
+ " \"graph_size\": graph_size, \"beam_pos\": beam_pos, \"fov_show\": fov_show, \"overlap_fig\" :overlap_fig, \"red_box\": red_box, \"box_col\":box_col, \"check0name\":check0name, \n",
+ " \"check1name\": check1name, \"check2name\": check2name, \"check3name\": check3name, \"check4name\": check4name, \"check6name\": check6name}) \n",
"\n",
- "inte = interaction() "
+ "ptychoscopy = widg.VBox([top_set, widg.HBox([controls, widg.VBox([graph_controls, gui])])])\n"
]
}
],
diff --git a/ptychoScopy.ipynb b/ptychoScopy.ipynb
index e8a7a96..dde1a93 100644
--- a/ptychoScopy.ipynb
+++ b/ptychoScopy.ipynb
@@ -40,14 +40,14 @@
},
{
"cell_type": "code",
- "execution_count": 68,
+ "execution_count": 4,
"id": "5c5feaae-861c-4277-9dd5-aee373b3c174",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
- "model_id": "3910cf673b40428cbbaaa2a78bfa0200",
+ "model_id": "37bb53443b8a4d50bb614d7156907632",
"version_major": 2,
"version_minor": 0
},
@@ -73,7 +73,7 @@
},
{
"cell_type": "code",
- "execution_count": 67,
+ "execution_count": 3,
"id": "fecbecdb-0fac-4ac8-a2b3-1ccb3f869a77",
"metadata": {},
"outputs": [],
@@ -213,15 +213,17 @@
"check2name = widg.Checkbox(value=False,description='Resolution gain (ITR)',disabled=False, indent=False,layout=widg.Layout(grid_area='check2name'))\n",
"check3name = widg.Checkbox(value=True, description='Recon. box coverage (ITR)',disabled=False, indent=False,layout=widg.Layout(grid_area='check3name'))\n",
"check4name = widg.IntSlider(value=70, min=0 ,max=100, step=5, description='Beam overlap (%):', disabled=False, continuous_update=False, orientation='horizontal', readout=True,readout_format='d', layout=widg.Layout(grid_area='check4name', width = '100%'),style=style)\n",
- "check6name = widg.Checkbox(value=False, description='Overall sampling (ITR)', disabled=False, indent=False,layout=widg.Layout(grid_area='check6name'), style=style)\n",
+ "check6name = widg.BoundedIntText(value=1,min=1,max=20,step=1, description='Overall sampling (ITR)', disabled=False,continuous_update=False,orientation='horizontal',readout=True, readout_format='d', layout=widg.Layout(grid_area='check6name', width = '100%'), style=style)\n",
+ "\n",
+ "\n",
"\n",
"### Layout\n",
"graph_controls = widg.GridBox(children=[sample_set, ctf_set, ctf_xaxis, element, beam_pos, fov_show, cl_set, overlap_fig, red_box, box_col, check0name, check1name, check2name, check3name,check4name, check6name, ctf_xaxis_name],\n",
- " layout=widg.Layout(width='109%', grid_template_rows='35px 35px 35px 35px 5px', grid_template_columns='4% 3.5% 14% 1.5% 8% 8% 8% 1% 27% 13%', grid_template_areas='''\n",
+ " layout=widg.Layout(width='109%', grid_template_rows='35px 35px 35px 35px 5px', grid_template_columns='4% 3.5% 14% 1.5% 8% 8% 8% 1% 26% 14%', grid_template_areas='''\n",
" \". ctf_set ctf_set . sample_set overlap_fig overlap_fig . cl_set cl_set \" \n",
" \". ctf_xaxis_name ctxaxis . fov_show fov_show fov_show . check0name check2name \"\n",
- " \". ctf_element ctf_element . beam_pos beam_pos beam_pos . check4name check6name \"\n",
- " \". . . . red_box red_box box_col . check1name check3name \"\n",
+ " \". ctf_element ctf_element . beam_pos beam_pos beam_pos . check4name check3name \"\n",
+ " \". . . . red_box red_box box_col . check1name check6name \"\n",
" \". . . . . . . . . . \"'''))\n",
"\n",
"def ptycho_interact(beam_energy, aperture, aperture_res, aperture_res2, probe_size, cl, matrix, defocus, mag, camera, binning, dwell_time, restr, method,\n",
@@ -252,7 +254,8 @@
" probe_window = (wavelength*cl_det/100)/(size_pixel/1e6)/1000 # now in nm\n",
" oversampling = (wavelength/1000)/(2*pixel_angle/1000*step_size_corr)\n",
" max_defocus = (probe_window/4)/np.tan(semi_angle_corr/1000)\n",
- "\n",
+ " z_res = wavelength/(2*np.sin(detector_cover/1000/2)*np.sin(detector_cover/1000/2))/100 # now in A\n",
+ " \n",
" ### ALL CAMERA LENGTHS PARAMETERS\n",
" cl_all = pty.load_cameralengths(camera, \"nominal\")\n",
" cl_eff_all = pty.load_cameralengths(camera, \"effective\")\n",
@@ -276,7 +279,7 @@
" max_defocus_all = (usable_probe_semi_window_all)/np.tan(semi_angle_corr/1000)\n",
" max_defocus_all[max_defocus_all < 0] = 'nan'\n",
" oversampling_all = (wavelength/1000)/(2*pixel_covers/1000*step_size_corr)\n",
- "\n",
+ " z_res_all = wavelength/(2*np.sin(detector_cover_all/1000/2)*np.sin(detector_cover_all/1000/2))/100 # now in A\n",
"\n",
" ### MICROSCOPE SCHEME\n",
" width = 550 # in-graph setting\n",
@@ -387,7 +390,7 @@
" if method == 'ssb':\n",
" omega, pctf = pty.get_ssb_ctf()\n",
" xx = wavelength/(np.sin(semi_angle_corr*omega/1000))/100\n",
- " fig1.add_trace(go.Scatter(showlegend=True, x=[-1], y=[-1],marker_size=12, marker_color='green', name='Rec step '+str(np.round(xx[-1]/3,2))+' Å')) \n",
+ " fig1.add_trace(go.Scatter(showlegend=True, x=[-100], y=[-100],marker_size=12, marker_color='green', name='Rec step '+str(np.round(xx[-1]/3,2))+' Å')) \n",
" fig1.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.0,xanchor=\"right\",x=0.9))\n",
"\n",
" fig1.add_trace(go.Scatter(showlegend=False, x = -fov_show/2*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",
@@ -620,36 +623,40 @@
"\n",
" ### CAMERA LENGTH TABLE\n",
" dictionary = {}\n",
- " tab = np.array([cl_all, np.round(ptycho_pixel_size_all,2), np.round(detector_cover_all,1), np.round(detector_cover_a_all,1), np.round(probe_window_all,1), np.round(oversampling_all,1)])\n",
+ " tab = np.array([cl_all, np.round(ptycho_pixel_size_all,2), np.round(z_res_all,2), np.round(detector_cover_all,1), np.round(detector_cover_a_all,1), np.round(probe_window_all,1), np.round(oversampling_all,1)])\n",
" \n",
" for i in range(0,len(cl_eff_all)):\n",
" button_style = 'success'\n",
- " icons=['','','','','','']\n",
- " data = tab[:,int(i)] # 0.cl, 1. ptycho pix, 2.det cov 3.det cov a, 4.max def, 5.probe window, 6.oversampling\n",
+ " icons=['','','','','','','']\n",
+ " data = tab[:,int(i)] # 0.cl, 1. ptycho pix xy, 2. ptycho pix z, 3.det cov, 4.det cov a, 5.max def, 6.probe window, 7.oversampling\n",
" \n",
" if cl == data[0]:\n",
- " icons=['hand-point-left','','','','',''] \n",
+ " icons=['hand-point-left','','','','','',''] \n",
" if check2name == True and data[1] > step_size_corr*10: # check2name = 'Ptycho pixel < step size'\n",
- " icons=['','bell','','','',''] \n",
+ " icons=['','bell','','','','',''] \n",
" button_style = 'warning'\n",
- " if data[2] > 1000*np.radians(check1name): # check1name = 'Low anlge approximation'\n",
- " icons=['','','bell','','',''] \n",
+ " if data[3] > 1000*np.radians(check1name): # check1name = 'Low anlge approximation'\n",
+ " icons=['','','','bell','','',''] \n",
" button_style = 'warning' \n",
- " if data[3] < check0name[0] or data[3] > check0name[1]: # 'Detector cover'\n",
- " icons=['','','','bell','',''] \n",
+ " \n",
+ " if data[4] < check0name[0] or data[4] > check0name[1]: # 'Detector cover'\n",
+ " icons=['','','','','bell','',''] \n",
" button_style = 'warning'\n",
- " if check3name == True and beam_diameter > data[4]/2 and beam_diameter < data[4]:\n",
- " icons=['','','','','','bell'] \n",
+ " if check3name == True and beam_diameter > data[5]/2 and beam_diameter < data[5]:\n",
+ " icons=['','','','','','bell',''] \n",
" button_style = 'warning'\n",
- " if check3name == True and beam_diameter > data[4]:\n",
- " icons=['','','','','','ban'] \n",
+ " if check3name == True and beam_diameter > data[5]:\n",
+ " icons=['','','','','','ban',''] \n",
" button_style = 'danger'\n",
- " if check6name == True and data[5] < 1: # check6name = 'Sampling > 1' \n",
- " icons=['','','','','ban',''] \n",
- " button_style = 'danger' \n",
+ " if data[6] < 1: # check6name = 'Sampling > 1' \n",
+ " icons=['','','','','','','ban'] \n",
+ " button_style = 'danger' \n",
+ " if data[6] > 1 and data[6] < int(check6name): # check6name = 'Sampling > check6name' \n",
+ " icons=['','','','','','','bell'] \n",
+ " button_style = 'warning' \n",
" dictionary[i] = widg.ToggleButtons(options=tuple(data), text_color= 'red', button_style=button_style, icons = icons, layout=widg.Layout(width=str(int(graph_size/100*65))+'px'),\n",
" style = {'description_width': '0px','button_width': str(int(graph_size/100*63))+'px'}, disabled=True)\n",
- " legend = widg.ToggleButtons(options=['Nominal CL (cm)','Recon. pixel size (Å)','Detector cover (mrad)','Detector cover (α)', 'Probe box (nm)', 'Overall sampling'],\n",
+ " legend = widg.ToggleButtons(options=['Nominal CL (cm)','Resolution XY (Å)','Resolution Z (Å)', 'Detector cover (mrad)','Detector cover (α)', 'Reconstr. box (nm)', 'Overall sampling'],\n",
" button_style='', layout=widg.Layout(width='150px'), style = {'description_width': '0px','button_width': \"150px\"}, disabled=True) \n",
" \n",
" # FIX here\n",
@@ -678,7 +685,7 @@
" cltab = widg.HBox([legend, dictionary[0], dictionary[1], dictionary[2], dictionary[3], dictionary[4], dictionary[5], dictionary[6], dictionary[7], dictionary[8], dictionary[9], dictionary[10]])\n",
"\n",
" cltab = widg.VBox([widg.Label('CAMERA LENGTH GUIDE'), cltab])\n",
- " cltab.layout = widg.Layout(border='solid 0px gray',margin='10px 0px 10px 25px', padding='5px 5px 5px 5px')\n",
+ " cltab.layout = widg.Layout(border='solid 0px gray',margin='0px 0px 0px 0px', padding='5px 5px 5px 5px')\n",
"\n",
" ### SHOWING\n",
" match method: \n",
diff --git a/ptychoscopy/__pycache__/pty.cpython-311.pyc b/ptychoscopy/__pycache__/pty.cpython-311.pyc
index 93aec97..3f091ab 100644
Binary files a/ptychoscopy/__pycache__/pty.cpython-311.pyc and b/ptychoscopy/__pycache__/pty.cpython-311.pyc differ
diff --git a/ptychoscopy/calibrations.xlsx b/ptychoscopy/calibrations.xlsx
index 993ddcc..c14b6e2 100644
Binary files a/ptychoscopy/calibrations.xlsx and b/ptychoscopy/calibrations.xlsx differ
diff --git a/ptychoscopy/pty.py b/ptychoscopy/pty.py
index ecd5ea9..792d558 100644
--- a/ptychoscopy/pty.py
+++ b/ptychoscopy/pty.py
@@ -1,3 +1,5 @@
+#!/usr/bin/env python3
+
### Packages import
import numpy as np
from copy import deepcopy