diff --git a/README.md b/README.md
index 72e8cd7..bb0c533 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,14 @@
-# ptychoScopy
+-------------------------------------------------------------------------------
+ ptychoScopy
+-------------------------------------------------------------------------------
-Jupyter based interactive data acquisition tool designed for appropriate ptychographic experimental setup and data collection. It computes nessesary characteristics which play crutial role in final data reconstruction. You can chose of **Direct methods** (mainly Single Side Band ptychography) or **Iterative reconstruction** which takes probe defocus into account.
-With this tool, you can check for probe CTF, scanning step size, probe overlap, detector camera length a proper angular range collection, reconstructed probe size and many more.
+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 visit GitLab repository.
-More info including step by step instructions can be found in Wiki.
+Calibration file can be found in 'ptychoscopy/calibrations.xlsx'
+
+To start, open the file 'ptychoScopy.ipynb'
\ No newline at end of file
diff --git a/calibrations.xlsx b/calibrations.xlsx
deleted file mode 100644
index 20481c2..0000000
Binary files a/calibrations.xlsx and /dev/null differ
diff --git a/fibsem.PNG b/fibsem.PNG
deleted file mode 100644
index 0869d54..0000000
Binary files a/fibsem.PNG and /dev/null differ
diff --git a/logo_psi.png b/logo_psi.png
deleted file mode 100644
index c220f08..0000000
Binary files a/logo_psi.png and /dev/null differ
diff --git a/ptychoScopy.ipynb b/ptychoScopy.ipynb
index 1f1e8d0..e8a7a96 100644
--- a/ptychoScopy.ipynb
+++ b/ptychoScopy.ipynb
@@ -2,1076 +2,703 @@
"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",
+ "execution_count": 68,
+ "id": "5c5feaae-861c-4277-9dd5-aee373b3c174",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "3910cf673b40428cbbaaa2a78bfa0200",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "VBox(children=(Button(disabled=True, layout=Layout(grid_area='scanning_set', width='%'), style=ButtonStyle(but…"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
"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__)"
+ "display(ptychoscopy)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b2865f08-6c85-4ce9-9173-a63e738a1224",
+ "metadata": {},
+ "source": [
+ "## RUN ME"
]
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "de350192-85ae-4d38-8ed3-14ad43843e01",
+ "execution_count": 67,
+ "id": "fecbecdb-0fac-4ac8-a2b3-1ccb3f869a77",
"metadata": {},
"outputs": [],
"source": [
- "### Initial packages import ###################################################\n",
- "import ipywidgets as widgets\n",
+ "### Initial packages import\n",
"import io\n",
"import sys\n",
"import numpy as np\n",
- "from abtem import Probe\n",
+ "import ipywidgets as widg\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 ptychoscopy import pty\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": null,
- "id": "7937f054-fcd0-4e67-a20f-7696f5903a94",
- "metadata": {},
- "outputs": [],
- "source": [
"\n",
- "display(VBox([top_set, HBox([controls, VBox([small_controls, gui])])]))\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "41ac78f4-8a75-4258-bfd4-539b28746088",
- "metadata": {},
- "outputs": [],
- "source": [
- "### CONTROLS ##########################################\n",
- "ali = dict(style = {'description_width': '110px','button_width': '55px', 'font_weight': 'bold'}, button_style='', disabled = False)\n",
+ "try:\n",
+ " from abtem import Probe\n",
+ " abtem = True\n",
+ "except:\n",
+ " abtem = False\n",
+ "\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",
- "# 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",
+ "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",
- "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",
+ "### 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",
- "probe = Dropdown(options=opt.probes(), value='8C', description='Probe', layout=Layout(width='95%', grid_area='beam_set3'), **ali)\n",
- "defocus = FloatSlider(description='Defocus (nm)', value=0, min=0, max=1000, step=0.5, continuous_update=False, layout=Layout(width='95%', grid_area='beam_set4'), **ali)\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",
- "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",
+ "### 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",
- "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",
+ "### 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",
- " \"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",
+ " \"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.Checkbox(value=False, description='Overall sampling (ITR)', disabled=False, indent=False,layout=widg.Layout(grid_area='check6name'), style=style)\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=100, 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",
+ "### 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",
" \". 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",
+ "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",
- "\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",
+ " fov = pty.get_fov(mag) \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",
+ " 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",
- " 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",
+ " omega_itr = np.array(pty.get_omegas())\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",
+ " 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",
- " dose = ((matrix**2)*(dwell_time/1e6)*(current/1e12/cons.e))/((((matrix-1)*step_size_corr)**2)*100)\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",
"\n",
- " ### ALL CAMERA LENGTHS PARAMETERS ###\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",
- " if restriction == True:\n",
- " for x in range(len(detector_cover_all)):\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) \n",
- " ptycho_pixel_size_all = (wavelength * np.array(opt.cameralengths_eff() )) /(detector_pixels_all*size_pixel/1e6)/1e4 \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(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",
+ " 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",
- " 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",
- " intensity = np.abs(intensity)\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",
- " \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",
- " fig5 = go.Figure() \n",
- " fig5.add_trace(px.imshow(field).data[0],)\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",
- " 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,1)])\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",
+ " ### MICROSCOPE SCHEME\n",
+ " width = 550 # 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",
+ " 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",
- " 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",
+ " 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",
- " 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",
+ " 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",
- " 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",
+ " 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",
- " 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",
+ " # 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",
- " 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",
+ " 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",
- " 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",
+ " 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",
- " 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",
+ " 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",
+ " ### 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=[-1], y=[-1],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",
- " 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",
+ " 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",
- " color = \"red\"\n",
- " name = 'Beam ⌀ is too big'\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",
- " 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",
+ " ### 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",
+ " 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",
- " 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",
+ " ### 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",
+ " 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",
- " ### 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",
+ " 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",
- " 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",
+ " ### 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",
- "# 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",
+ " 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",
- " 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",
+ " 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",
- " if data[2] > check0name[1]:\n",
- " button_style = 'warning' \n",
- "\n",
- " if check6name == True: \n",
- " if data[5] < 1:\n",
- " button_style = 'danger' \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",
- " 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",
+ " 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",
- " 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",
+ " 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(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",
+ " \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[2] > 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",
+ " button_style = 'warning'\n",
+ " if check3name == True and beam_diameter > data[4]/2 and beam_diameter < data[4]:\n",
+ " icons=['','','','','','bell'] \n",
+ " button_style = 'warning'\n",
+ " if check3name == True and beam_diameter > data[4]:\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",
+ " 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",
+ " 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",
- " ### 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",
+ " 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",
"\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), checks]), sample_overlap, cltab]) \n",
- " \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",
+ " ### 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",
+ " 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",
- "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"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "68780f2b-efa0-4240-870b-2b0876977e90",
- "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",
+ "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",
- " 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",
- "\n",
- " def apertures(self):\n",
- " excel_data = read_excel(self.calib,sheet_name='Probes')\n",
- " excel_lin = list((excel_data[excel_data.Probe.isin([\"Probe\"])]))\n",
- " apertures = excel_lin[1::]\n",
- " return apertures\n",
- " \n",
- " def detectors(self):\n",
- " excel_data = read_excel(self.calib,sheet_name='Detector')\n",
- " excel_lin = list((excel_data[excel_data.Type.isin([\"Type\"])]))\n",
- " detectors = excel_lin[1::]\n",
- " return detectors\n",
- " \n",
- " def probes(self):\n",
- " probes = list(read_excel(self.calib,sheet_name='Probes').Probe)\n",
- " probes = probes[3::]\n",
- " return probes\n",
- " \n",
- " def magnifications(self):\n",
- " excel_data = read_excel(self.calib,sheet_name='Ranges')\n",
- " magnifications = list(excel_data.Magnification)\n",
- " return magnifications\n",
- " \n",
- " def energies(self): \n",
- " excel_data = read_excel(self.calib,sheet_name='Ranges')\n",
- " energies = [str(e) for e in list(excel_data.BeamEnergy)]\n",
- " energies = [x for x in energies if x != 'nan']\n",
- " energies = [int(float(e)) for e in energies]\n",
- " return energies\n",
- " \n",
- " def mappings(self): \n",
- " excel_data = read_excel(self.calib,sheet_name='Ranges')\n",
- " mappings = [str(e) for e in list(excel_data.Mapping)]\n",
- " mappings = [x for x in mappings if x != 'nan']\n",
- " mappings = [int(float(e)) for e in mappings]\n",
- " return mappings\n",
- " \n",
- " def cameralengths(self): \n",
- " cameralengths = list(read_excel(self.calib,sheet_name='Pixel').NominalCL)\n",
- " return cameralengths\n",
- " \n",
- " def cameralengths_eff(self): \n",
- " cameralengths_eff = list(read_excel(self.calib,sheet_name='Pixel').DetectorCL)\n",
- " return cameralengths_eff\n",
- "\n",
- " def dwelltimes(self): \n",
- " excel_data = read_excel(self.calib,sheet_name='Ranges')\n",
- " dwelltimes = [str(e) for e in list(excel_data.DwellTime)]\n",
- " dwelltimes = [x for x in dwelltimes if x != 'nan']\n",
- " dwelltimes = [int(float(e)) for e in dwelltimes] \n",
- " return dwelltimes \n",
- " \n",
- "opt = interaction()\n",
- "\n",
- "\n",
- "class ptychoScopy:\n",
- " \"\"\"Computes various characteristics describing used setting.\"\"\"\n",
- " \n",
- " def __init__(self):\n",
- " self.calib = calib\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",
- "\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",
- " \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",
- "\n",
- " def get_currents_over_apertures(self, aperture):\n",
- " excel_data = read_excel(calib, sheet_name='Probes',header=0)\n",
- " currents_apertures = np.array(list(excel_data[aperture]))\n",
- " return currents_apertures\n",
- "\n",
- " def get_pixel_angle(self, cl, camera, binning):\n",
- " excel_data = read_excel(calib,sheet_name='Pixel',header=0)\n",
- " excel_line = excel_data[excel_data.NominalCL.isin([cl])]\n",
- " pixel_angle = excel_line[camera]\n",
- " pixel_angle = np.array(pixel_angle).item()\n",
- " self.pixel_angle = pixel_angle*binning\n",
- " return self.pixel_angle\n",
- " \n",
- " def get_cl_detector(self,cl):\n",
- " excel_data = read_excel(calib,sheet_name='Pixel')\n",
- " excel_line = excel_data[excel_data.NominalCL.isin([cl])]\n",
- " self.cl_detector = excel_line['DetectorCL']\n",
- " self.cl_detector = self.cl_detector.item()\n",
- " return self.cl_detector\n",
- " \n",
- " def get_aq_frec(self, dwell_time):\n",
- " self.aq_frec = 1000/dwell_time\n",
- " return self.aq_frec \n",
- " \n",
- " def get_step_size(self, matrix):\n",
- " self.step_size = self.fov/(matrix-1)\n",
- " return self.step_size \n",
- " \n",
- " def get_step_correction(self): \n",
- " step_correction = [str(e) for e in list(read_excel(calib,sheet_name='Ranges').StepSizeCorr)]\n",
- " step_correction = np.array([x for x in step_correction if x != 'nan']).astype(float)\n",
- " self.step_correction = step_correction.item()\n",
- " return self.step_correction\n",
- " \n",
- " def get_beam_diameter(self, aperture, defocus):\n",
- " excel_data = read_excel(calib, sheet_name='Probes')\n",
- " excel_line = excel_data[excel_data.Probe.isin(['Def0Diameter'])]\n",
- " beam_0_diameter = np.array([excel_line[aperture]]).astype(float)\n",
- " beam_0_diameter = beam_0_diameter.item()\n",
- " self.beam_diameter = 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",
- "\n",
- " def get_pumping_apertures(self): \n",
- " excel_data = read_excel(calib,sheet_name='Pixel')\n",
- " pump_apert = [str(e) for e in list(excel_data.PAAR)]\n",
- " pump_apert = [x for x in pump_apert if x != 'nan']\n",
- " self.pump_apert = [float(e) for e in pump_apert]\n",
- " return self.pump_apert \n",
- " \n",
- " def get_ssb_ctf(self):\n",
- " ### Contrast transfer function ###\n",
- " omega = np.linspace(1e-6,2,100)\n",
- " p3 = np.arccos(np.minimum(1,omega))\n",
- " p3[np.isnan(p3)] = 0\n",
- " p5 = 1-(omega**2)\n",
- " p5[p5 <0] = 0\n",
- " p4 = omega*np.sqrt(p5)\n",
- " p4[np.isnan(p4)] = 0\n",
- " pctf = (2/cons.pi)*(np.arccos(omega/2)-p3+p4-(omega/2*np.sqrt(1-(omega/2)**2)))\n",
- " return pctf\n",
- " \n",
- " 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",
- "\n",
- "inte = interaction() "
+ "ptychoscopy = widg.VBox([top_set, widg.HBox([controls, widg.VBox([graph_controls, gui])])])\n"
]
}
],
diff --git a/ptychoscopy/__init__.py b/ptychoscopy/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ptychoscopy/__pycache__/__init__.cpython-311.pyc b/ptychoscopy/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..1f0f5cc
Binary files /dev/null and b/ptychoscopy/__pycache__/__init__.cpython-311.pyc differ
diff --git a/ptychoscopy/__pycache__/fce.cpython-311.pyc b/ptychoscopy/__pycache__/fce.cpython-311.pyc
new file mode 100644
index 0000000..d155df8
Binary files /dev/null and b/ptychoscopy/__pycache__/fce.cpython-311.pyc differ
diff --git a/ptychoscopy/__pycache__/gui.cpython-311.pyc b/ptychoscopy/__pycache__/gui.cpython-311.pyc
new file mode 100644
index 0000000..a3418d7
Binary files /dev/null and b/ptychoscopy/__pycache__/gui.cpython-311.pyc differ
diff --git a/ptychoscopy/__pycache__/pty.cpython-311.pyc b/ptychoscopy/__pycache__/pty.cpython-311.pyc
new file mode 100644
index 0000000..93aec97
Binary files /dev/null and b/ptychoscopy/__pycache__/pty.cpython-311.pyc differ
diff --git a/ptychoscopy/__pycache__/source.cpython-311.pyc b/ptychoscopy/__pycache__/source.cpython-311.pyc
new file mode 100644
index 0000000..6d8e786
Binary files /dev/null and b/ptychoscopy/__pycache__/source.cpython-311.pyc differ
diff --git a/ptychoscopy/calibrations.xlsx b/ptychoscopy/calibrations.xlsx
new file mode 100644
index 0000000..993ddcc
Binary files /dev/null and b/ptychoscopy/calibrations.xlsx differ
diff --git a/logo4.PNG b/ptychoscopy/logo.PNG
similarity index 100%
rename from logo4.PNG
rename to ptychoscopy/logo.PNG
diff --git a/ptychoscopy/pty.py b/ptychoscopy/pty.py
new file mode 100644
index 0000000..ecd5ea9
--- /dev/null
+++ b/ptychoscopy/pty.py
@@ -0,0 +1,504 @@
+### Packages import
+import numpy as np
+from copy import deepcopy
+from pandas import read_excel
+import scipy.constants as cons
+from ptychoscopy import pty
+
+
+
+def get_versions():
+ """
+ --------------------------------------------------------------
+ Show versions of the used packages.
+ --------------------------------------------------------------
+ Inputs:
+ none
+ """
+ import sys
+ print (sys.version)
+ import openpyxl
+ print("Openpyxl version ", openpyxl.__version__)
+ import numpy as np
+ print("Numpy version ", np.__version__)
+ import scipy
+ print("Scipy version ", scipy.__version__)
+ import plotly
+ print("Plotly version ", plotly.__version__)
+ import pandas
+ print("Pandas version ", pandas.__version__)
+ import IPython
+ print("IPython version ", IPython.__version__)
+ import ipywidgets
+ print("Ipywidgets version ", ipywidgets.__version__)
+
+ try:
+ import abtem
+ print("abTEM version ", abtem.__version__)
+ except:
+ print("abTEM not available ")
+ return
+
+def get_omegas():
+ """
+ --------------------------------------------------------------------
+ Loads x-axis in multiplications of probe semi-angle for iterative
+ CTF curves from sheet called "CTF" ("CTF" row).
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='CTF')
+ excel_lin = list((excel_data[excel_data.CTF.isin(["CTF"])]))
+ omegas = excel_lin[1::]
+ return omegas
+
+def get_ctf(element):
+ """
+ --------------------------------------------------------------------
+ Loads iterative CTF curve for chosen element from sheet called "CTF"
+ ("chosen element" row).
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ element ... name of the chosen CTF profile
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='CTF', header = 0)
+ excel_line = np.array(excel_data[excel_data.CTF.isin([element])])
+ ctf = excel_line[0]
+ ctf = ctf[1::]
+ return ctf
+
+def get_wavelength(beam):
+ """
+ --------------------------------------------------------------------
+ Computes relativistic electron wavelength.
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ beam ... beam energy
+ Outputs:
+ wavelength ... electron wavelength in m
+ """
+ wavelength = cons.h/np.sqrt(2*cons.electron_mass*cons.elementary_charge*beam*1e3*(1+((cons.elementary_charge*beam*1e3)/(2*cons.electron_mass*cons.speed_of_light**2))))
+ return wavelength
+
+def get_fov(mag):
+ """
+ --------------------------------------------------------------------
+ Loads field of view at 1x magnification and computes field of view
+ at given magnification.
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ mag ... image magnification in millions
+ Outputs:
+ fov ... field of view in nm
+ """
+
+ FoVat1x = [str(e) for e in list(read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges').FoVat1x)]
+ FoVat1x = np.array([x for x in FoVat1x if x != 'nan']).astype(float)
+ FoVat1x = FoVat1x.item()
+ fov = FoVat1x/(mag*1e6)
+ return fov
+
+def get_angle(aperture):
+ """
+ --------------------------------------------------------------------
+ Loads probe semi-angle of the chosen aperture.
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ aperture ... probe defining aperture name
+ Outputs:
+ angle ... probe semi-angle in mrad
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes',header=0)
+ excel_line = excel_data[excel_data.Probe.isin(['SemiAngle'])]
+ angle = excel_line[aperture]
+ angle = np.array(angle).item()
+ return angle
+
+def get_angle_corr(aperture):
+ """
+ --------------------------------------------------------------------
+ Loads corrected probe semi-angle of the chosen aperture.
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ aperture ... probe defining aperture name
+ Outputs:
+ angle_corr ... corrected probe semi-angle in mrad
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes',header=0)
+ excel_line = excel_data[excel_data.Probe.isin(['SemiAngleCorr'])]
+ angle_corr = excel_line[aperture]
+ angle_corr = np.array(angle_corr).item()
+ return angle_corr
+
+def get_current(probe, aperture):
+ """
+ --------------------------------------------------------------------
+ Loads probe current for chosen probe size and aperture.
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ probe ... chosen probe name
+ aperture ... probe defining aperture name
+ Outputs:
+ current ... probe current in pA
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes',header=0)
+ excel_line = excel_data[excel_data.Probe.isin([probe])]
+ current = excel_line[aperture]
+ current = np.array(current).item()
+ return current
+
+def get_pixel_angle(cl, camera, binning):
+ """
+ --------------------------------------------------------------------
+ Loads and computes probe current for chosen probe size and aperture.
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ cl ... chosen nominal camera length
+ camera ... chosen camera type
+ binning... chosen camera binning
+ Outputs:
+ pixel_angle ... single pixel cover angle in mrad
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Pixel',header=0)
+ excel_line = excel_data[excel_data.NominalCL.isin([cl])]
+ pixel_angle = excel_line[camera]
+ pixel_angle = np.array(pixel_angle).item()
+ pixel_angle = pixel_angle*binning
+ return pixel_angle
+
+def get_cl_detector(cl, detector):
+ """
+ --------------------------------------------------------------------
+ Loads effective camera length.
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ cl ... chosen nominal camera length
+ detector ... chosen detector type
+ Outputs:
+ cl_detector ... efective camera length of detector in cm
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Camera_length')
+ excel_line = excel_data[excel_data.NominalCL.isin([cl])]
+ cl_detector = excel_line[detector]
+ cl_detector = cl_detector.item()
+ return cl_detector
+
+def get_aq_frec(dwell_time):
+ """
+ --------------------------------------------------------------------
+ Compute acquisition frame rate from dwell time.
+ --------------------------------------------------------------------
+ Inputs:
+ dwell_time ... beam position dwell time in us
+ Outputs:
+ aq_frec ... detection frame rate in kHz
+ """
+ aq_frec = 1000/dwell_time
+ return aq_frec
+
+def get_step_size(fov, matrix):
+ """
+ --------------------------------------------------------------------
+ Compute scanning step size.
+ --------------------------------------------------------------------
+ Inputs:
+ matrix ... number of beam positions in scanning matrix
+ Outputs:
+ step_size ... detection frame rate in nm
+ """
+ step_size = fov/(matrix-1)
+ return step_size
+
+def get_step_correction():
+ """
+ --------------------------------------------------------------------
+ Load scanning correction coefficient.
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ Outputs:
+ step_correction ... scaling factor
+ """
+ step_correction = [str(e) for e in list(read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges').StepSizeCorr)]
+ step_correction = np.array([x for x in step_correction if x != 'nan']).astype(float)
+ step_correction = step_correction.item()
+ return step_correction
+
+def get_beam_diameter(aperture, defocus, angle_corr):
+ """
+ --------------------------------------------------------------------
+ Computes geometrical beam diameter.
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ aperture ... probe defining aperture name
+ defocus ... introduced beam defocus in nm
+ Outputs:
+ beam_diameter ... beam diameter in nm
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes')
+ excel_line = excel_data[excel_data.Probe.isin(['Def0Diameter'])]
+ beam_0_diameter = np.array([excel_line[aperture]]).astype(float)
+ beam_0_diameter = beam_0_diameter.item()
+ beam_diameter = 2*defocus*np.tan(angle_corr/1000)+beam_0_diameter
+ return beam_diameter
+
+def get_0beam_diameter(aperture):
+ """
+ --------------------------------------------------------------------
+ Computes geometrical beam diameter at 0 nm defocus.
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ aperture ... probe defining aperture name
+ Outputs:
+ beam_0_diameter ... beam diameter in nm
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes')
+ excel_line = excel_data[excel_data.Probe.isin(['Def0Diameter'])]
+ beam_0_diameter = np.array([excel_line[aperture]]).astype(float)
+ beam_0_diameter = beam_0_diameter.item()
+ return beam_0_diameter
+
+def get_detector(camera, binning):
+ """
+ --------------------------------------------------------------------
+ Loads detection array size toghether with pixel size and computes
+ effective pixel size (inluding binning).
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ camera ... detector name
+ binning ... applied diffraction pattern binning
+ Outputs:
+ num_pixels ... number of pixel in detection array
+ size_pixel ... detection pixel size in um
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Detector')
+ excel_line = excel_data[excel_data.Type.isin(['Array'])]
+ num_pixels = np.array([excel_line[camera]]).astype(float)
+ num_pixels = num_pixels.item()
+ num_pixels = num_pixels/binning
+ excel_line = excel_data[excel_data.Type.isin(['RealSize'])]
+ size_pixel = excel_line[camera]
+ size_pixel = size_pixel.item()
+ size_pixel = size_pixel*binning
+ return num_pixels, size_pixel
+
+def get_pixel_covers(camera, binning):
+ """
+ --------------------------------------------------------------------
+ Computes effective single detection pixel cover angle.
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ camera ... detector name
+ binning ... applied diffraction pattern binning
+ Outputs:
+ pixel_covers ... effective pixel cover angle in mrad
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Pixel')
+ pixel_covers = list(excel_data[camera])
+ pixel_covers = [str(e) for e in pixel_covers]
+ pixel_covers = [x for x in pixel_covers if x != 'nan']
+ pixel_covers = [float(e) for e in pixel_covers]
+ pixel_covers = np.array(pixel_covers)
+ pixel_covers = pixel_covers*binning
+ return pixel_covers
+
+def get_pumping_apertures():
+ """
+ --------------------------------------------------------------------
+ Load differencial pumping aperture caused maximal detection angle
+ limitation for all camera lengths.
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ Outputs:
+ pump_apert ... maximal detected angles in mrad for all camera lengths
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Camera_length')
+ pump_apert = [str(e) for e in list(excel_data.PAAR)]
+ pump_apert = [x for x in pump_apert if x != 'nan']
+ pump_apert = [float(e) for e in pump_apert]
+ return pump_apert
+
+def get_ssb_ctf():
+ """
+ --------------------------------------------------------------------
+ Computes SSB CTF.
+ --------------------------------------------------------------------
+ Inputs:
+ none
+ Outputs:
+ omega ... scattering angle from 0 to 2 alpha
+ pctf ... ssb ctf
+ """
+ omega = np.linspace(1e-6,2,100)
+ p = np.arccos(np.minimum(1,omega))
+ p[np.isnan(p)] = 0
+ p2 = 1-(omega**2)
+ p2[p2 <0] = 0
+ p3 = omega*np.sqrt(p2)
+ p3[np.isnan(p3)] = 0
+ pctf = (2/cons.pi)*(np.arccos(omega/2)-p+p3-(omega/2*np.sqrt(1-(omega/2)**2)))
+ return omega, pctf
+
+def get_cl4ssb(detector_cover_a_all, camera, which):
+ """
+ --------------------------------------------------------------------
+ Computes maximal camera length for SSB.
+ --------------------------------------------------------------------
+ Inputs:
+ detector_cover_a_all ... detector cover in alfa for all camera lengths
+ Outputs:
+ ssb_cl ... maximal recommended camera length
+ kolik ... covered alfa of minimal detector cover
+ """
+ ssb_cl = deepcopy(detector_cover_a_all)
+ ssb_cl[ssb_cl<1] = "nan"
+ ssb_cl = np.nanmin(ssb_cl)
+ kde = np.array(np.where(ssb_cl == detector_cover_a_all)).item()
+ kolik = np.array(detector_cover_a_all[kde])
+ cl_all = load_cameralengths(camera, which)
+ ssb_cl = np.array(cl_all[kde])
+ return ssb_cl, kolik
+
+
+
+
+def load_elements():
+ """
+ --------------------------------------------------------------------
+ Loads names of various phase contrast transfer functions from sheet
+ called "CTF" ("CTF" column).
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='CTF')
+ elements = [str(e) for e in list(excel_data.CTF)]
+ elements = [x for x in elements if x != 'nan']
+ return elements
+
+def load_apertures():
+ """
+ --------------------------------------------------------------------
+ Loads aperture names from sheet called "Probes" ("Probe" row).
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes')
+ excel_lin = list((excel_data[excel_data.Probe.isin(["Probe"])]))
+ apertures = excel_lin[1::]
+ return apertures
+
+def load_detectors():
+ """
+ --------------------------------------------------------------------
+ Loads detector names from sheet called "Detector" ("Type" row).
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Detector')
+ excel_lin = list((excel_data[excel_data.Type.isin(["Type"])]))
+ detectors = excel_lin[1::]
+ return detectors
+
+def load_probes():
+ """
+ --------------------------------------------------------------------
+ Loads probe size names from sheet called "Probes" ("Probe" column).
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ """
+ probes = list(read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes').Probe)
+ probes = probes[3::] # from fifth row
+ return probes
+
+def load_magnifications():
+ """
+ --------------------------------------------------------------------
+ Loads list of possible magnifications in millions from sheet called
+ "Ranges" ("Magnification" column).
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges')
+ magnifications = list(excel_data.Magnification)
+ return magnifications
+
+def load_energies():
+ """
+ --------------------------------------------------------------------
+ Loads list of possible beam energies in keV from sheet called
+ "Ranges" ("BeamEnergy" column).
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges')
+ energies = [str(e) for e in list(excel_data.BeamEnergy)]
+ energies = [x for x in energies if x != 'nan']
+ energies = [int(float(e)) for e in energies]
+ return energies
+
+def load_mappings():
+ """
+ --------------------------------------------------------------------
+ Loads list of possible scanning matricies from sheet called "Ranges"
+ ("Mapping" column).
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges')
+ mappings = [str(e) for e in list(excel_data.Mapping)]
+ mappings = [x for x in mappings if x != 'nan']
+ mappings = [int(float(e)) for e in mappings]
+ return mappings
+
+def load_dwelltimes():
+ """
+ --------------------------------------------------------------------
+ Loads list of possible dwell times in us from sheet called "Ranges"
+ ("DwellTime" column).
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ """
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges')
+ dwelltimes = [str(e) for e in list(excel_data.DwellTime)]
+ dwelltimes = [x for x in dwelltimes if x != 'nan']
+ dwelltimes = [int(float(e)) for e in dwelltimes]
+ return dwelltimes
+
+def load_cameralengths(camera, which):
+ """
+ --------------------------------------------------------------------
+ Loads list of possible nominal camera lengths in cm from sheet
+ called "Pixel" ("NominalCL" column).
+ --------------------------------------------------------------------
+ Inputs:
+ calib ... path to the calibration file
+ """
+ match which:
+ case "nominal":
+ cameralengths = list(read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Camera_length').NominalCL)
+ case "effective":
+ excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Camera_length')
+ cameralengths = list(np.array(excel_data[camera]))
+ return cameralengths
\ No newline at end of file
diff --git a/sampling criterion.xlsx b/sampling criterion.xlsx
deleted file mode 100644
index 3953b8a..0000000
Binary files a/sampling criterion.xlsx and /dev/null differ
diff --git a/scopus.png b/scopus.png
deleted file mode 100644
index 60f2a88..0000000
Binary files a/scopus.png and /dev/null differ
diff --git a/sd_0527720.cif b/sd_0527720.cif
deleted file mode 100644
index 495675d..0000000
--- a/sd_0527720.cif
+++ /dev/null
@@ -1,155 +0,0 @@
-##CIF_1.1
-
-data_sm_global
-#Used dictionaries
-loop_
-_audit_conform_dict_name
-_audit_conform_dict_version
-_audit_conform_dict_location
-cif_core.dic 2.4.2 .
-cif_pd.dic 1.0.1 .
-cif_sm.dic 0.1 'redaktion.landolt-boernstein(at)springer.com'
-
-#About this content and reference
-_sm_credits_copyright
-;PAULING FILE Multinaries Edition - 2012. SpringerMaterials Release 2014.
-http://www.paulingfile.com
-Unique LPF ID Number SD0527720
-Project Coordinator: Shuichi Iwata
-Section-Editors: Karin Cenzual (Crystal Structures), Hiroaki Okamoto (Phase
-Diagrams), Fritz Hulliger (Physical Properties)
-(c) Springer & Material Phases Data System (MPDS), Switzerland & National
-Institute for Materials Science (NIMS), Japan 2014.
-(Data generated pre-2002: (c) Springer & MPDS & NIMS;
-post-2001: (c) Springer & MPDS)
-All Rights Reserved. Version 2014.06.
-;
-
-_audit_creation_method
-;This data have been compiled from the crystallographic datasheet for
-"SmB6 Crystal Structure"
-taken from SpringerMaterials (sm_isp_sd_0527720).
-;
-
-_publ_section_references
-;Paderno Y.B., Lundstrom T.: On the Homogeneity Ranges of LaB6, EuB6 and SmB6. Acta Chemica Scandinavica, Series A: Physical and Inorganic Chemistry 37 (1983) 609-612.
-;
-
-#Phase classification
-_sm_phase_labels 'SmB6'
-_chemical_name_mineral ''
-_sm_chemical_compound_class 'boride'
-_sm_phase_prototype 'CaB6 '
-_sm_pearson_symbol 'cP7'
-_symmetry_Int_Tables_number 221
-_sm_sample_details
-;chemical analysis; B85.76Sm14.24,
-powder (determination of cell parameters)
-;
-_sm_measurement_details
-;Guinier-Hägg film (determination of cell parameters),
-X-rays, Cu Kα1; λ = 0.1540598 nm (determination of cell parameters)
-;
-_sm_interpretation_details
-;cell parameters determined and structure type assigned; composition dependence studied
-;
-
-data_sm_isp_SD0527720-standardized_unitcell
-#Cell Parameters
-_cell_length_a 4.1334
-_cell_length_b 4.1334
-_cell_length_c 4.1334
-_cell_angle_alpha 90
-_cell_angle_beta 90
-_cell_angle_gamma 90
-_sm_length_ratio_ab 1.000
-_sm_length_ratio_bc 1.000
-_sm_length_ratio_ca 1.000
-_cell_volume 70.62
-_symmetry_space_group_name_H-M 'Pm-3m'
-_symmetry_Int_Tables_number 221
-_cell_formula_units_Z 1
-_sm_cell_transformation
-;No transformation from published to standardized cell parameters necessary.
-;
-
-#Atom Coordinates
-loop_
-_atom_site_label
-_atom_site_type_symbol
-_atom_site_Wyckoff_symbol
-_sm_site_symmetry
-_atom_site_fract_x
-_atom_site_fract_y
-_atom_site_fract_z
-_atom_site_occupancy
-_sm_coordination_number
-_sm_atomic_environment_type
-B1 'B' .6f .4m.m 0.207 0.5 0.5 1 ? '?'
-Sm1 'Sm' .1a .m-3m 0 0 0 1 ? '?'
-
-_sm_atom_site_transformation
-;No transformation from published to standardized cell parameters necessary.
-Atom coordinates assigned by editor.
-;
-
-data_sm_isp_SD0527720-published_cell
-#Cell Parameters
-_cell_length_a 4.1334(2)
-_cell_length_b 4.1334(2)
-_cell_length_c 4.1334(2)
-_cell_angle_alpha 90
-_cell_angle_beta 90
-_cell_angle_gamma 90
-_sm_length_ratio_ab 1.000
-_sm_length_ratio_bc 1.000
-_sm_length_ratio_ca 1.000
-_cell_volume 70.62
-_symmetry_space_group_name_H-M 'Pm-3m'
-_symmetry_Int_Tables_number 221
-_cell_formula_units_Z 1
-
-#Atom Coordinates
-loop_
-_atom_site_label
-_atom_site_type_symbol
-_atom_site_Wyckoff_symbol
-_sm_site_symmetry
-_atom_site_fract_x
-_atom_site_fract_y
-_atom_site_fract_z
-_atom_site_occupancy
-_sm_coordination_number
-_sm_atomic_environment_type
-? ? ? ? ? ? ? ? ? ?
-
-data_sm_isp_SD0527720-niggli_reduced_cell
-#Cell Parameters
-_cell_length_a 4.1334
-_cell_length_b 4.1334
-_cell_length_c 4.1334
-_cell_angle_alpha 90
-_cell_angle_beta 90
-_cell_angle_gamma 90
-_sm_length_ratio_ab 1.000
-_sm_length_ratio_bc 1.000
-_sm_length_ratio_ca 1.000
-_cell_volume 70.62
-_symmetry_space_group_name_H-M ''
-_symmetry_Int_Tables_number ?
-_cell_formula_units_Z 1
-
-#Atom Coordinates
-loop_
-_atom_site_label
-_atom_site_type_symbol
-_atom_site_Wyckoff_symbol
-_sm_site_symmetry
-_atom_site_fract_x
-_atom_site_fract_y
-_atom_site_fract_z
-_atom_site_occupancy
-_sm_coordination_number
-_sm_atomic_environment_type
-? ? ? ? ? ? ? ? ? ?
-