finalv0.1

This commit is contained in:
rskoupy
2024-11-22 12:42:41 +01:00
parent adc04b1edf
commit 86f3885c3c
4 changed files with 393 additions and 302 deletions

View File

@ -40,14 +40,20 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 6,
"id": "5c5feaae-861c-4277-9dd5-aee373b3c174",
"metadata": {},
"metadata": {
"editable": true,
"slideshow": {
"slide_type": ""
},
"tags": []
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "c64267f661284b108b24ed204c5a7127",
"model_id": "b125450f3b5147c692b7d32f30844c8e",
"version_major": 2,
"version_minor": 0
},
@ -73,7 +79,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 5,
"id": "fecbecdb-0fac-4ac8-a2b3-1ccb3f869a77",
"metadata": {},
"outputs": [],
@ -117,14 +123,14 @@
"\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",
"logo = widg.Image(value=image, format='png', layout=widg.Layout(grid_area='logo',width='95%',))\n",
"ali = dict(style = {'description_width': '110px','button_width': '55px', 'font_weight': 'bold'}, button_style='', disabled = False)\n",
"ali2 = dict(style = {'description_width': '60px' ,'button_width': '90px', 'font_weight': 'bold'}, button_style='', disabled = False)\n",
"ali3 = dict(style = {'description_width': '110px','button_width': '45px', 'font_weight': 'bold'}, button_style='', disabled = False)\n",
"method = widg.ToggleButtons(options=[('SSB ','ssb'),('ITR ','iterative')],description='',icons=['opera','refresh'], tooltips=['Single side band ptychography', 'Iterative reconstruction methods (PIE, ML, DM)'],\n",
"method = widg.ToggleButtons(options=[('SSB ','ssb'),('ITR ','iterative')],description='',icons=['opera','refresh'], tooltips=['Single side band ptychography', 'Iterative reconstruction methods (e.g. 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_set = widg.Button(description='Electron beam settings',layout=widg.Layout(width='95%',grid_area='beam_set'),style=widg.ButtonStyle(button_color='#3b446b',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=2500, step=5, readout_format='d',continuous_update=False, layout=widg.Layout(width='95%', grid_area='beam_set4'), **ali)\n",
@ -132,20 +138,30 @@
"aperture = widg.ToggleButtons(options=pty.load_apertures(), description='', layout=widg.Layout(width='95%', grid_area='beam_set2'), **ali3)\n",
"\n",
"### Scanning parameters\n",
"scanning_set = widg.Button(description='Scanning parameters', layout=widg.Layout(width='95%', grid_area='scanning_set'),style=widg.ButtonStyle(button_color='#222261', font_weight= 'bold',font_size= '16px',text_color='white'),disabled = False)\n",
"scanning_set = widg.Button(description='Scanning parameters', layout=widg.Layout(width='95%', grid_area='scanning_set'),style=widg.ButtonStyle(button_color='#3b446b', font_weight= 'bold',font_size= '16px',text_color='white'),disabled = False)\n",
"mag = widg.Dropdown(options=pty.load_magnifications(), value=20, description='Magnification Mx', layout=widg.Layout(width='95%', grid_area='scanning_set1'), **ali)\n",
"matrix = widg.Dropdown(options=pty.load_mappings(), value=256, description='Matrix', layout=widg.Layout(width='95%', grid_area='scanning_set2'), **ali)\n",
"dwell_time = widg.Dropdown(options=pty.load_dwelltimes(), value=10, description='Dwell time (μs)', layout=widg.Layout(width='95%', grid_area='scanning_set3'), **ali)\n",
"\n",
"### Detection\n",
"camera_set = widg.Button(description='Detection',layout=widg.Layout(width='95%', grid_area='camera_set'),style=widg.ButtonStyle(button_color='#222261', font_weight= 'bold',font_size= '16px',text_color='white'),disabled = False)\n",
"camera_set = widg.Button(description='Detection',layout=widg.Layout(width='95%', grid_area='camera_set'),style=widg.ButtonStyle(button_color='#3b446b', 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",
"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), ('24',24), ('32',32), ('48',48)], value=1, description='', icons = ['ban','',''], layout=widg.Layout(width='95%', grid_area='camera_set3'), **ali3)\n",
"binning = widg.ToggleButtons(options=[('',1), ('2',2), ('4',4), ('8',8), ('16',16)], value=1, description='', icons = ['ban','','','',''], layout=widg.Layout(width='95%', grid_area='camera_set3'), **ali3)\n",
"camera_set6 = widg.Button(description='Post-acquisition treatments (ITR)',layout=widg.Layout(width='95%', grid_area='camera_set6'),style=widg.ButtonStyle(button_color='white', font_size= '16px',text_color='black'),disabled = False)\n",
"\n",
"\n",
"\n",
"padding = widg.SelectionSlider(options=[('none',1), ('double',2), ('triple',3), ('quadruple',4), ('quintuple',5)], value=1, description='Padding', continuous_update=False, orientation='horizontal', readout=True, layout=widg.Layout(width='95%', grid_area='camera_set4'), **ali)\n",
"pattern_resto = widg.SelectionSlider(options=[('none',1), ('double',2), ('triple',3), ('quadruple',4), ('quintuple',5)], value=1, description='Pattern recovery', continuous_update=False, orientation='horizontal', readout=True, layout=widg.Layout(width='95%', grid_area='camera_set5'), **ali)\n",
"\n",
"\n",
"\n",
"\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",
@ -164,8 +180,8 @@
"\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",
" binning, beam_res, aperture_res, aperture_res2, fov_res, dwell_time_res, graph_size, name1, visual_set, padding, pattern_resto, camera_set6],\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 35px 35px 35px 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",
@ -183,6 +199,9 @@
" \"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",
" \"camera_set6 camera_set6 camera_set6 camera_set6 camera_set6\"\n",
" \"camera_set4 camera_set4 camera_set4 camera_set4 camera_set4 \"\n",
" \"camera_set5 camera_set5 camera_set5 camera_set5 camera_set5 \"\n",
" \". . . . . \"\n",
" \"visual_set visual_set visual_set visual_set visual_set \"\n",
" \"name1 name1 gr_size2 gr_size2 gr_size2 \"'''))\n",
@ -196,43 +215,38 @@
"### 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",
"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.BoundedFloatText(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 = '170px'),style={'description_width': '80px'})\n",
"beam_pos = widg.BoundedIntText(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 = '170px'),style={'description_width': '80px'})\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:', layout=widg.Layout(grid_area='red_box',width = '170px'),style={'description_width': '80px'})\n",
"box_col = widg.ColorPicker(concise=False, description='', value='cyan', disabled=False, layout=widg.Layout(grid_area='box_col', width = '90%'))\n",
"prof_show = widg.Checkbox(value=False, description='Profile', disabled=False, indent=False, layout=widg.Layout(grid_area='prof_show'))\n",
"\n",
"\n",
"\n",
"overlap_fig = widg.ToggleButtons(options=[('Geometrical', 'geom'),('Simulated: A', 'simA'),('Simulated: I', 'simI')], layout=widg.Layout(grid_area='overlap_fig'), style = {'button_width': '30%'}, disabled=False)\n",
"fov_show = widg.BoundedFloatText(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 = '115px'),style={'description_width': '55px'})\n",
"beam_pos = widg.BoundedIntText(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 = '120px'),style={'description_width': '70px'})\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:', layout=widg.Layout(grid_area='red_box',width = '150px'),style={'description_width': '70px'})\n",
"box_col = widg.ColorPicker(concise=False, description='', value='cyan', disabled=False, layout=widg.Layout(grid_area='box_col', width = '50px'))\n",
"prof_show = widg.Checkbox(value=False, description='Show line profile', disabled=False, indent=False, layout=widg.Layout(grid_area='prof_show'))\n",
"rs_sampling = widg.Dropdown(options=[('Overlap', 'overlap'), ('Linear sampling', 'linear'), ('Areal sampling', 'areal')], description='',layout=widg.Layout(grid_area='rs_sampling', width = '115px'),style={'description_width': '0px'})\n",
"\n",
"### Camera length based limitations and checks\n",
"cl_set = widg.Button(description='Camera length based limitations and checks for ITR', 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 coverage (α):', 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.BoundedIntText(value=10,min=0,max=20,step=1,description='Small angle approx. (°):', disabled=False,continuous_update=False,orientation='horizontal',readout=True,readout_format='d',layout=widg.Layout(grid_area='check1name', width = '200px'),style={'description_width': '140px'})\n",
"check1name = widg.BoundedIntText(value=10,min=0,max=50,step=1,description='Small angle approx. (°):', disabled=False,continuous_update=False,orientation='horizontal',readout=True,readout_format='d',layout=widg.Layout(grid_area='check1name', width = '200px'),style={'description_width': '140px'})\n",
"check2name = widg.BoundedFloatText(value=1,min=0.5,max=5,step=0.5, description='Resolution gain:', disabled=False,continuous_update=False,orientation='horizontal',readout=True, readout_format='.1f', layout=widg.Layout(grid_area='check2name', width = '200px'), style={'description_width': '140px'})\n",
"check3name = widg.IntSlider(value=50,min=0,max=100,step=10, description='Probe window coverage (%):', disabled=False,continuous_update=False,orientation='horizontal',readout=True, readout_format='d', layout=widg.Layout(grid_area='check3name', width = '100%'), style=style)\n",
"check4name = widg.IntSlider(value=70, min=0 ,max=100, step=5, description='Beam overlap (%):', disabled=False, continuous_update=False, orientation='horizontal', readout=True,readout_format='d', layout=widg.Layout(grid_area='check4name', width = '100%'),style=style)\n",
"check6name = widg.BoundedIntText(value=1,min=1,max=20,step=1, description='Overall sampling:', disabled=False,continuous_update=False,orientation='horizontal',readout=True, readout_format='d', layout=widg.Layout(grid_area='check6name', width = '200px'), style={'description_width': '140px'})\n",
"\n",
"\n",
"\n",
"### Layout\n",
"graph_controls = widg.GridBox(children=[sample_set, ctf_set, ctf_xaxis, element, beam_pos, fov_show, cl_set, overlap_fig, red_box, box_col, check0name, check1name, check2name, check3name,check4name, check6name, ctf_xaxis_name, prof_show],\n",
" layout=widg.Layout(width='109%', grid_template_rows='35px 35px 35px 35px 5px', grid_template_columns='4% 3.5% 14% 1.5% 8% 7% 9% 1% 26% 14%', grid_template_areas='''\n",
" \". ctf_set ctf_set . sample_set overlap_fig overlap_fig . cl_set cl_set \" \n",
" \". ctf_xaxis_name ctxaxis . fov_show fov_show prof_show . check0name check1name \"\n",
" \". ctf_element ctf_element . beam_pos beam_pos . . check4name check2name \"\n",
" \". . . . red_box red_box box_col . check3name check6name \"\n",
" \". . . . . . . . . . \"''')) \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, check4name, check6name, ctf_xaxis_name, prof_show, rs_sampling],\n",
" layout=widg.Layout(width='1600px', grid_template_rows='35px 35px 35px 35px 5px', grid_template_columns='4% 3.5% 14% 50px 8% 6.5% 3% 6.5% 1% 26% 14%', grid_template_areas='''\n",
" \". ctf_set ctf_set . sample_set sample_set beam_pos beam_pos . cl_set cl_set \" \n",
" \". ctf_xaxis_name ctxaxis . overlap_fig overlap_fig overlap_fig overlap_fig . check0name check1name \"\n",
" \". ctf_element ctf_element . fov_show red_box red_box box_col . check4name check2name \"\n",
" \". . . . rs_sampling . prof_show prof_show . . check6name \"\n",
" \". . . . . . . . . . . \"''')) \n",
"\n",
"def ptycho_interact(beam_energy, aperture, aperture_res, aperture_res2, probe_size, cl, matrix, defocus, mag, camera, binning, dwell_time, restr, method,\n",
" ctf_xaxis, element, graph_size, beam_pos, fov_show, overlap_fig, red_box, box_col, check0name, check1name, check2name, check3name, check4name, check6name, prof_show):\n",
" ctf_xaxis, element, graph_size, beam_pos, fov_show, overlap_fig, red_box, box_col, check0name, check1name, check2name, check4name, check6name, prof_show, padding, pattern_resto, rs_sampling):\n",
"\n",
" fov = pty.get_fov(mag) \n",
" pctf_itr = pty.get_ctf(element)\n",
@ -254,12 +268,15 @@
" overlap = (beam_diameter-step_size_corr)/beam_diameter*100\n",
" if overlap < 0:\n",
" overlap = 0 \n",
" area_oversampling = (cons.pi*beam_diameter/2*beam_diameter/2)/(step_size_corr*step_size_corr)\n",
" linear_oversampling = (2*beam_diameter/2)/(step_size_corr)\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",
" probe_window = pattern_resto*(wavelength*cl_det/100)/(size_pixel/1e6)/1000 # now in nm\n",
" oversampling = (wavelength/1000)/(2*pixel_angle/1000*step_size_corr)\n",
" max_defocus = (probe_window/4)/np.tan(semi_angle_corr/1000)\n",
" z_res = wavelength/(2*np.sin(detector_cover/1000/2)*np.sin(detector_cover/1000/2))/100 # now in A\n",
" dRssb = (wavelength/100)/(2*np.sin(2*semi_angle_corr/1000))\n",
" \n",
" ### ALL CAMERA LENGTHS PARAMETERS\n",
" cl_all = pty.load_cameralengths(camera, \"nominal\")\n",
@ -274,17 +291,17 @@
" if detector_cover_all[x] > pump_apertures[x]:\n",
" detector_cover_all[x] = pump_apertures[x] \n",
" detector_pixels_all = np.round(detector_cover_all/pixel_covers,1) \n",
" ptycho_pixel_size_all = (wavelength*np.array(cl_eff_all))/(detector_pixels_all*size_pixel/1e6)/1e4 \n",
" ptycho_pixel_size_all = ((wavelength*np.array(cl_eff_all))/(detector_pixels_all*size_pixel/1e6)/1e4)/padding\n",
" else:\n",
" ptycho_pixel_size_all = (wavelength*np.array(cl_eff_all))/(num_pixels/2*size_pixel/1e6)/1e4\n",
" ptycho_pixel_size_all = ((wavelength*np.array(cl_eff_all))/(num_pixels/2*size_pixel/1e6)/1e4)/padding\n",
"\n",
" probe_window_all = (wavelength*np.array(cl_eff_all)/100)/(size_pixel/1e6)/1000 # now in nm\n",
" probe_window_all = pattern_resto*(wavelength*np.array(cl_eff_all)/100)/(size_pixel/1e6)/1000 # now in nm\n",
" usable_probe_semi_window_all = probe_window_all/4\n",
" detector_cover_a_all = detector_cover_all/semi_angle_corr\n",
" max_defocus_all = (usable_probe_semi_window_all)/np.tan(semi_angle_corr/1000)\n",
" max_defocus_all[max_defocus_all < 0] = 'nan'\n",
" oversampling_all = (wavelength/1000)/(2*pixel_covers/1000*step_size_corr)\n",
" z_res_all = wavelength/(2*np.sin(detector_cover_all/1000/2)*np.sin(detector_cover_all/1000/2))/100 # now in A\n",
" z_res_all = (wavelength/(2*np.sin(detector_cover_all/1000/2)*np.sin(detector_cover_all/1000/2))/100)/padding # now in A\n",
"\n",
" ### MICROSCOPE SCHEME\n",
" width = 550 # in-graph setting\n",
@ -370,16 +387,15 @@
" 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",
"\n",
" ### SAMPLE PLANE\n",
" match overlap_fig: \n",
" case 'Geometrical':\n",
" case 'geom':\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 = go.Figure() \n",
" fig1.update_xaxes(title_text=\"Sample plane (nm)\", range=[-fov_show/2, fov_show/2], showgrid=False, zeroline=False)\n",
" fig1.update_yaxes(title_text=\"Overlap \"+str(np.round(overlap,1))+\" %\", range=[-fov_show/2, fov_show/2],showgrid=False, showticklabels=False)\n",
" fig1.update_xaxes(range=[-fov_show/2, fov_show/2], showgrid=False, showline=True, mirror=True, ticks='inside',linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\", title_text=\"Sample plane (nm)\",zeroline=False)\n",
" fig1.update_yaxes(range=[-fov_show/2, fov_show/2], showgrid=False, showline=True, mirror=True, ticks='',linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\", 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'))\n",
@ -390,47 +406,67 @@
" fig1.add_annotation(x=-2*step_size_corr, y=-1*step_size_corr, ax=-2*step_size_corr, ay=-2*step_size_corr, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='red')\n",
" fig1.add_annotation(x=2*step_size_corr-0.75*beam_diameter/2, y=-2*step_size_corr-0.75*beam_diameter/2, ax=2*step_size_corr, ay=-2*step_size_corr,xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='blue')\n",
" fig1.add_annotation(x=2*step_size_corr+0.75*beam_diameter/2, y=-2*step_size_corr+0.75*beam_diameter/2, ax=2*step_size_corr, ay=-2*step_size_corr,xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='blue')\n",
" fig1.add_trace(go.Scatter(showlegend=True, x=[-100], y=[-100],marker_size=12, marker_color='red', name='Step '+str(np.round(10*step_size_corr,2))+' Å')) \n",
" fig1.add_trace(go.Scatter(showlegend=True, x=[-100], y=[-100],marker_size=12, marker_color='blue', name='Beam ⌀ '+str(np.round(10*beam_diameter,2))+' Å')) \n",
" \n",
" if method == 'ssb':\n",
" omega, pctf = pty.get_ssb_ctf()\n",
" xx = wavelength/(np.sin(semi_angle_corr*omega/1000))/100\n",
" fig1.add_trace(go.Scatter(showlegend=True, x=[-100], y=[-100],marker_size=12, marker_color='green', name='Rec step '+str(np.round(xx[-1]/3,2))+' Å')) \n",
" fig1.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.0,xanchor=\"right\",x=0.9))\n",
"\n",
" fig1.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='',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
" \n",
" fig1.add_trace(go.Scatter(showlegend=True, x=[-100], y=[-100],marker_size=12, marker_color='red', name='ΔR '+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='Probe ⌀ '+str(np.round(10*beam_diameter,2))+' Å')) \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",
" fig1.add_trace(go.Scatter(showlegend=True, x=(0,0), y=(0,0),marker_size=12, marker_color='green', name= '<b>ΔR_SSB ' + str(np.round(dRssb,2))+' Å<b>', opacity = 0)) \n",
" fig1.update_layout(width=3.15*graph_size, height=3.9*graph_size, plot_bgcolor='white', margin = dict(l=0.65*graph_size, r=0.01*graph_size, t=0.8*graph_size, b=0.7*graph_size),\n",
" legend = dict(orientation=\"v\",yanchor=\"bottom\",y=1.01, xanchor=\"right\",x=1), title = {'text': \"Sample\",'y': 0.87, 'x': 0.23,'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",
" match rs_sampling:\n",
" case 'overlap':\n",
" fig1.add_trace(go.Scatter(x=(0,0), y=(0,0), name='<b>Overlap '+str(np.round(overlap,1))+' %<b>', showlegend=True, opacity = 0))\n",
" case 'linear':\n",
" fig1.add_trace(go.Scatter(x=(0,0), y=(0,0), name='<b>Linear sampl. '+str(np.round(linear_oversampling,1))+'<b>', showlegend=True, opacity = 0))\n",
" case 'areal':\n",
" fig1.add_trace(go.Scatter(x=(0,0), y=(0,0), name='<b>Area sampl. '+str(np.round(area_oversampling,1))+'<b>', showlegend=True, opacity = 0))\n",
"\n",
" case 'Ilumination':\n",
" fig1.update_layout(width=2.9*graph_size, height=3.7*graph_size, plot_bgcolor='white', margin =dict(l=0.2*graph_size, r=0.1*graph_size, t=0.8*graph_size, b=0),\n",
" legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=1), title={'text': \"Sample\",'y': 0.87, 'x': 0.1,'xanchor': 'left','yanchor': 'top'})\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
" \n",
" case overlap_fig if overlap_fig in ['simI', 'simA']:\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.square(intensity.array)\n",
" intensity = np.abs(intensity)\n",
" probe_simul = probe.build().intensity().compute().array\n",
" \n",
" if overlap_fig == \"simI\":\n",
" probe_simul = np.square(probe_simul)\n",
" probe_simul = np.abs(probe_simul)\n",
" elif overlap_fig == \"simA\":\n",
" probe_simul = np.abs(probe_simul)\n",
"\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",
" field = np.zeros([probe_simul.shape[0]+(beam_pos)*x_pix, probe_simul.shape[1]+(beam_pos)*x_pix])\n",
" cen = int(probe_simul.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",
" field[xy:probe_simul.shape[0]+xy,xx:probe_simul.shape[0]+xx]=field[xy:probe_simul.shape[0]+xy,xx:probe_simul.shape[0]+xx]+probe_simul\n",
" \n",
" field_size =int(field.shape[0]) \n",
" field_cen = int(field.shape[0]/2)\n",
@ -440,34 +476,35 @@
" 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='inferno'), 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",
" fig1.add_trace(go.Scatter(x=np.array(probe_window/4), y=np.array(probe_window/4), name='Uniformity '+str(np.round(uniformity,1))+' %', showlegend=True, opacity = 0))\n",
" \n",
" fig1.update_xaxes(range=[0, field_size-1], 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)])\n",
" fig1.update_yaxes(range=[0, field_size-1], showticklabels=False)\n",
" fig1.update_layout(width=3.2*graph_size, height=3.9*graph_size, margin =dict(l=0.5*graph_size, r=0.1*graph_size, t=0.9*graph_size, b=0.55*graph_size),\n",
" legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.8), title={'text':\"Illumination\",'y':0.90,'x':0.4,'xanchor':'left','yanchor':'top'})\n",
" else:\n",
" fig1 = go.Figure() \n",
" fig1.update_layout(title={'text': \"abTEM not available\",'y': 0.98, 'x': 0.14,'xanchor': 'left','yanchor': 'top'})\n",
" fig1.update_layout(width=3.1*graph_size, height=3.9*graph_size, margin =dict(l=0.5*graph_size, r=0.2*graph_size, t=0.9*graph_size, b=0.55*graph_size))\n",
" fig1.update_layout(title={'text': \"abTEM not available\",'y': 0.98, 'x': 0.14,'xanchor': 'left','yanchor': 'top'},\n",
" width=3.2*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",
" ### 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 = go.Figure() \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\")\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\") \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+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",
" fig2.update_xaxes(title_text=\"Detector pixel array\", range=[0.5, num_pixels+0.5], tickvals = [1, num_pixels/2+0.5, num_pixels],\n",
" ticktext = [1, num_pixels/2, num_pixels], showticklabels=True, showgrid=True, 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\",title_text=\"Cover angle (mrad)\", showticklabels=True, showgrid=True,\n",
" 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(width=3.45*graph_size, height=4.7*graph_size, margin =dict(l=0.65*graph_size, r=0.25*graph_size, t=1.9*graph_size, b=0),\n",
" title={'text': \"Detector\",'y':0.65, 'x': 0.44,'xanchor': 'left','yanchor': 'top'}, plot_bgcolor='white', legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"left\",x=0.1))\n",
"\n",
" match method: \n",
" case 'ssb':\n",
" ### CAMERA LENGTH GRAPH\n",
@ -479,16 +516,15 @@
" 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.add_annotation(x=np.log10(np.max(cl_all)), y=detector_cover, text=str(np.round(covered_alfas,1)), showarrow=False, xshift=15, 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=-15, 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_xaxes(range=[np.log10(np.min(cl_all)/1.5), np.log10(np.max(cl_all)*1.5)], 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_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",
" 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",
" width=3.61*graph_size, height=3.4*graph_size, margin =dict(l=0.3*graph_size, r=0.25*graph_size, t=0.3*graph_size, b=0.3*graph_size))\n",
" \n",
" ### SSB-PCTF\n",
" omega, pctf = pty.get_ssb_ctf()\n",
@ -497,10 +533,9 @@
" fig5 = go.Figure() \n",
" fig5.update_yaxes(title_text=\"Transfer (-)\")\n",
" match ctf_xaxis:\n",
" case 'α':\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",
" fig5.update_xaxes(title_text=\"Spatial frequency (ω)\", range=[0, 2], zeroline=False)\n",
" case 'mrad':\n",
" for x in apertures:\n",
" if x == apertures[0]:\n",
@ -508,8 +543,7 @@
" 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",
" fig5.update_xaxes(title_text=\"Spatial frequency (mrad)\", range=[0, 2*semi_angle_corr], zeroline=False)\n",
" case 'Å':\n",
" for x in apertures:\n",
" d = wavelength/(np.sin(pty.get_angle_corr(x)*omega/1000))/100 # Full pitch size\n",
@ -520,10 +554,10 @@
" fig5.add_trace(go.Scatter(showlegend=True, x=xx, y=pctf, marker_color='red', name='Selected aperture'))\n",
" fig5.update_xaxes(title_text=\"Spacing (Å)\", range=[-0.5, 2], type=\"log\", zeroline=False)\n",
" \n",
" fig5.update_layout(plot_bgcolor='white', title={'text': \"Phase CTF\",'y':0.99, 'x':0.42,'xanchor': 'left','yanchor': 'top'},legend=dict(orientation=\"h\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.95)) \n",
" fig5.update_xaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
" fig5.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
" fig5.update_layout(width=3.5*graph_size, height=2.2*graph_size, margin = dict(l=0.3*graph_size, r=0.3*graph_size, t=0.5*graph_size, b=0.4*graph_size))\n",
" 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), plot_bgcolor='white',\n",
" 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",
" \n",
" case 'iterative':\n",
" ### ITR-PCTF\n",
@ -531,9 +565,9 @@
" fig5 = go.Figure() \n",
" fig5.update_yaxes(title_text=\"Transfer (-)\")\n",
" match ctf_xaxis: \n",
" case 'α':\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_xaxes(title_text=\"Spatial frequency (ω)\", range=[0, 6], zeroline=False)\n",
" fig5.update_yaxes(range=[0, 1.1])\n",
" case 'mrad': \n",
" for x in apertures:\n",
@ -542,7 +576,7 @@
" 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",
" fig5.update_xaxes(title_text=\"Spatial frequency (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",
@ -554,14 +588,14 @@
" 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",
" 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",
" 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",
"\n",
" ### PROBE WINDOW\n",
" match overlap_fig:\n",
" case 'Geometrical': \n",
" case 'geom': \n",
" if beam_diameter < probe_window/2:\n",
" color = \"green\"\n",
" elif beam_diameter < probe_window:\n",
@ -574,69 +608,66 @@
"\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",
" fig3.add_trace(go.Scatter(x=np.array(probe_window/2), y=np.array(probe_window/2), name='<b>Maximal Δf '+str(np.round(max_defocus,1))+' nm<b>', showlegend=True, marker_color=color, opacity = 0))\n",
"\n",
" for i in range(0, len(opacity)):\n",
" fig3.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=opacity[i], fillcolor=color, x0=probe_window/2-beam_diameter/xcoef[i], y0=probe_window/2-beam_diameter/xcoef[i], \n",
" x1=probe_window/2+beam_diameter/xcoef[i], y1=probe_window/2+beam_diameter/xcoef[i], line_color=color)\n",
" \n",
" fig3.update_xaxes(title_text=\"Probe window (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",
" fig3.update_xaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\", \n",
" title_text=\"Probe window (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(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\",\n",
" range=[0, probe_window], tickvals = [0, probe_window/4, probe_window/2, 3*probe_window/4, probe_window], showticklabels=False)\n",
" fig3.update_layout(width=3.2*graph_size, height=4.0*graph_size, margin =dict(l=0.5*graph_size, r=0, t=0.8*graph_size, b=0.75*graph_size), plot_bgcolor='white',\n",
" legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.8),title={'text':\"Probe\",'y':0.92,'x':0.48,'xanchor':'left','yanchor':'top'}) \n",
"\n",
" case 'Ilumination': \n",
" case overlap_fig if overlap_fig in ['simI', 'simA']:\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",
" probe_simul = probe.build().intensity().compute().array\n",
" \n",
" cen2 = intensity3.shape\n",
" if overlap_fig == \"simI\":\n",
" probe_simul = np.square(probe_simul)\n",
" probe_simul = np.abs(probe_simul)\n",
" elif overlap_fig == \"simA\":\n",
" probe_simul = np.abs(probe_simul)\n",
" \n",
" cen2 = probe_simul.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",
" just_probe_window = probe_simul[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(probe_simul)*100\n",
" cross_section = probe_simul[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(px.imshow(probe_simul).data[0])\n",
" if prof_show == True:\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",
" \n",
"\n",
" fig3.add_trace(go.Scatter(x=np.array(probe_window/4), y=np.array(probe_window/4), name='Probe covered '+str(np.round(int_tot,1))+' %', showlegend=True, opacity = 0))\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 \"+str(np.round(int_tot,1))+' %','y':0.85, 'x':0.2,'xanchor': 'left','yanchor': 'top'})\n",
" fig3.update_traces(dict(showscale=False, coloraxis=None, colorscale='inferno'), selector={'type':'heatmap'})\n",
" \n",
" fig3.update_yaxes(showticklabels=False)\n",
" fig3.update_xaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\", title_text=\"Probe window (nm)\", showgrid=False, showticklabels=True,\n",
" tickvals = [sirkaB/2, sirkaB, 3*sirkaB/2], ticktext = [0, np.round(sirkaB/200,2), np.round(sirkaB/100,2)])\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",
" fig3.update_xaxes(range=[0, 2*sirkaB-1], mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\", title_text=\"Probe window (nm)\", showgrid=False, showticklabels=True, tickvals = [sirkaB/2, sirkaB, 3*sirkaB/2], ticktext = [0, np.round(sirkaB/200,2), np.round(sirkaB/100,2)])\n",
" fig3.update_yaxes(range=[0, 2*sirkaB-1],showticklabels=False)\n",
" fig3.update_layout(width=3.0*graph_size, height=3.9*graph_size, margin =dict(l=0.4*graph_size, r=0.1*graph_size, t=0.9*graph_size, b=0.55*graph_size),\n",
" legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.8),title={'text':\"Probe\",'y':0.9,'x':0.4,'xanchor':'left','yanchor':'top'})\n",
" else:\n",
" fig3 = go.Figure() \n",
" fig3.update_layout(title={'text': \"abTEM not available\",'y': 0.98, 'x': 0.14,'xanchor': 'left','yanchor': 'top'})\n",
" fig3.update_layout(width=2.7*graph_size, height=3.9*graph_size, margin =dict(l=0.1*graph_size, r=0.1*graph_size, t=0.9*graph_size, b=0.55*graph_size))\n",
" \n",
" ### FINAL CHECKS \n",
" check1 = widg.Valid(value= bool(overlap > check4name), description='Beam overlap',layout=widg.Layout(width='250px'), style = {'description_width': '100px'}, disabled=True)\n",
" check2 = widg.Valid(value= bool(step_size_corr*10 > (wavelength*cl_det)/(num_pixels*size_pixel/1e6)/1e4), description='Resolution gain', layout=widg.Layout(width='250px'), style = {'description_width': '100px'}, disabled=True)\n",
" check3 = widg.Valid(value= bool(beam_diameter/2 < probe_window/2), description='Box coverage', layout=widg.Layout(width='250px'), style = {'description_width': '100px'}, disabled=True) \n",
" check4 = widg.Valid(value= bool(oversampling > 1), description='Overall sampling', layout=widg.Layout(width='250px'), style = {'description_width': '100px'}, disabled=True) \n",
" checks = widg.VBox([widg.HBox([check1, check2]), widg.HBox([check3, check4])]) # Label('Final checks')\n",
" checks.layout = widg.Layout(margin='0px 0px 0px 100px', padding='0px 0px 0px 0px', border='solid 3px gray') # border='dashed 1px gray'\n",
"\n",
" ### CAMERA LENGTH TABLE\n",
" dictionary = {}\n",
" tab = np.array([cl_all, np.round(ptycho_pixel_size_all,2), np.round(z_res_all,2), np.round(detector_cover_all,1), np.round(detector_cover_a_all,1), np.round(probe_window_all,1), np.round(oversampling_all,1)])\n",
" tab = np.array([cl_all, np.round(ptycho_pixel_size_all,2), np.round(z_res_all,2), np.round(detector_cover_all,1) , np.round(detector_cover_a_all,1), \n",
" np.round(probe_window_all,2), np.round(max_defocus_all,1), np.round(oversampling_all,1)])\n",
" \n",
" for i in range(0,len(cl_eff_all)):\n",
" button_style = 'success'\n",
" icons=['','','','','','','']\n",
" data = tab[:,int(i)] # 0.cl, 1. ptycho pix xy, 2. ptycho pix z, 3.det cov, 4.det cov a, 5.max def, 6.probe window, 7.oversampling\n",
" icons=['','','','','','','','','']\n",
" data = tab[:,int(i)] # 0.cl, 1. ptycho pix xy, 2. ptycho pix z, 3.det cov, 4.det cov a, 5.probe window restored, 6. max defocus, 7.oversampling,\n",
" \n",
" if cl == data[0]:\n",
" icons[0]= \"hand-point-left\"\n",
@ -653,22 +684,28 @@
" icons[4]= \"bell\"\n",
" button_style = 'warning'\n",
" \n",
" if beam_diameter > check3name/100*data[5]:\n",
" if beam_diameter > data[5]/2:\n",
" icons[5]= \"bell\"\n",
" button_style = 'warning'\n",
" \n",
" if data[6] < 1: # check6name = 'Sampling > 1' \n",
" icons[6]= \"ban\"\n",
" \n",
" if data[7] < 1: # check6name = 'Sampling > 1' \n",
" icons[7]= \"ban\"\n",
" button_style = 'danger' \n",
" if data[6] > 1 and data[6] < int(check6name): # check6name = 'Sampling > check6name' \n",
" icons[6]= \"ban\"\n",
" button_style = 'warning' \n",
" \n",
" dictionary[i] = widg.ToggleButtons(options=tuple(data), text_color= 'red', button_style=button_style, icons = icons, layout=widg.Layout(width=str(int(graph_size/100*65))+'px'),\n",
" style = {'description_width': '0px','button_width': str(int(graph_size/100*63))+'px'}, disabled=True)\n",
" legend = widg.ToggleButtons(options=['Nominal CL (cm)','Resolution XY (Å)','Minimal slice th. (Å)', 'Detector cover (mrad)','Detector cover (α)', 'Probe window (nm)', 'Overall sampling'],\n",
" button_style='', layout=widg.Layout(width='150px'), style = {'description_width': '0px','button_width': \"150px\"}, disabled=True) \n",
" if data[7] > 1 and data[6] < int(check6name): # check6name = 'Sampling > check6name' \n",
" icons[7]= \"bell\"\n",
" button_style = 'warning' \n",
"\n",
" if data[7] < pattern_resto:\n",
" icons[7]= \"ban\"\n",
" button_style = 'danger' \n",
" \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*70))+'px'),\n",
" style = {'description_width': '0px','button_width': str(int(graph_size/100*67))+'px'}, disabled=True)\n",
" legend = widg.ToggleButtons(options=['L (cm)','∆x (Å)','∆z (Å)', 'θ (mrad)','θ (α)', 'Dψ (nm)', 'Δf (nm)','Ŝx,y'],\n",
" tooltips=['Nominal camera length','Reconstucted pixel size','Minimal slice thickness for multi-slice reconstruction', 'Maximum detected angle',\n",
" 'Maximum detected angle in multiplications of probe semi-angle', 'Probe window size', 'Maximum defocus to create an adequately sampled probe', 'Combined sampling'],\n",
" button_style='', layout=widg.Layout(width='85px'), style = {'description_width': '0px','button_width': \"80px\"}, disabled=True) \n",
" \n",
" # FIX here\n",
" match len(cl_eff_all):\n",
@ -696,17 +733,37 @@
" cltab = widg.HBox([legend, dictionary[0], dictionary[1], dictionary[2], dictionary[3], dictionary[4], dictionary[5], dictionary[6], dictionary[7], dictionary[8], dictionary[9], dictionary[10]])\n",
"\n",
" cltab = widg.VBox([widg.Label('CAMERA LENGTH GUIDE'), cltab])\n",
" cltab.layout = widg.Layout(border='solid 0px gray',margin='0px 0px 0px 0px', padding='5px 5px 5px 5px')\n",
" cltab.layout = widg.Layout(border='solid 0px gray',margin='0px 0px 0px 15px', padding='5px 5px 5px 5px')\n",
"\n",
" ### SHOWING\n",
" left = widg.VBox([go.FigureWidget(fig5),go.FigureWidget(fig2)])\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",
" check_width = '220px'\n",
" check_descr_width = '120px'\n",
" check1_ssb = widg.Valid(value= bool(step_size_corr*10 < dRssb), description='Real-space sampling', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True)\n",
" check2_ssb = widg.Valid(value= bool(1 < covered_alfas) , description='Detector coverage', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True)\n",
" check3_ssb = widg.Valid(value= bool(3 < beam_diameter_pix) , description='Minimal BF size', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True)\n",
" checks_ssb = widg.VBox([check1_ssb, check2_ssb,check3_ssb]) # Label('Final checks')\n",
" checks_ssb.layout = widg.Layout(margin='100px 0px 0px 30px', padding='0px 0px 0px 0px', border='solid 0px gray') # border='dashed 1px gray'\n",
"\n",
" left = widg.VBox([go.FigureWidget(fig5),go.FigureWidget(fig2)])\n",
" total = widg.HBox([left, go.FigureWidget(fig), right])\n",
"\n",
" right = widg.VBox([go.FigureWidget(fig1), widg.HBox([go.FigureWidget(fig4), checks_ssb]) ])\n",
" \n",
" case 'iterative':\n",
" check_width = '220px'\n",
" check_descr_width = '120px'\n",
" check1_itr = widg.Valid(value= bool(overlap > check4name), description='Beam overlap',layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True)\n",
" check2_itr = widg.Valid(value= bool(step_size_corr*10 > (wavelength*cl_det)/(num_pixels*size_pixel/1e6)/1e4), description='Resolution gain', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True)\n",
" check3_itr = widg.Valid(value= bool(beam_diameter/2 < probe_window/2), description='Probe window', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True) \n",
" check4_itr = widg.Valid(value= bool(oversampling > 1), description='Combined sampling', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True) \n",
" check5_itr = widg.Valid(value= bool(oversampling > pattern_resto), description='Pattern recovery', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True) \n",
" checks_itr = widg.HBox([widg.VBox([check1_itr, check2_itr]), widg.VBox([check3_itr, check4_itr]), widg.VBox([check5_itr])]) # Label('Final checks')\n",
" checks_itr.layout = widg.Layout(margin='0px 0px 0px 5px', padding='0px 0px 0px 0px', border='solid 0px gray') # border='dashed 1px gray'\n",
"\n",
" right = widg.VBox([widg.HBox([go.FigureWidget(fig1),go.FigureWidget(fig3)]), cltab, checks_itr])\n",
" \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",
@ -714,9 +771,9 @@
"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, \"prof_show\":prof_show}) \n",
" \"check1name\": check1name, \"check2name\": check2name, \"check4name\": check4name, \"check6name\": check6name, \"prof_show\":prof_show, \"padding\":padding, \"pattern_resto\":pattern_resto, \"rs_sampling\": rs_sampling}) \n",
"\n",
"ptychoscopy = widg.VBox([top_set, widg.HBox([controls, widg.VBox([graph_controls, gui])])])\n"
"ptychoscopy = widg.VBox([top_set, widg.HBox([controls, widg.VBox([graph_controls, gui])])])"
]
}
],

View File

@ -40,7 +40,7 @@
},
{
"cell_type": "code",
"execution_count": 359,
"execution_count": 6,
"id": "5c5feaae-861c-4277-9dd5-aee373b3c174",
"metadata": {
"editable": true,
@ -53,7 +53,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "a761f00de7e946deadcb8d2324fd5a26",
"model_id": "b125450f3b5147c692b7d32f30844c8e",
"version_major": 2,
"version_minor": 0
},
@ -66,9 +66,7 @@
}
],
"source": [
"display(ptychoscopy)\n",
"\n",
"\n"
"display(ptychoscopy)"
]
},
{
@ -81,7 +79,7 @@
},
{
"cell_type": "code",
"execution_count": 358,
"execution_count": 5,
"id": "fecbecdb-0fac-4ac8-a2b3-1ccb3f869a77",
"metadata": {},
"outputs": [],
@ -125,14 +123,14 @@
"\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",
"logo = widg.Image(value=image, format='png', layout=widg.Layout(grid_area='logo',width='95%',))\n",
"ali = dict(style = {'description_width': '110px','button_width': '55px', 'font_weight': 'bold'}, button_style='', disabled = False)\n",
"ali2 = dict(style = {'description_width': '60px' ,'button_width': '90px', 'font_weight': 'bold'}, button_style='', disabled = False)\n",
"ali3 = dict(style = {'description_width': '110px','button_width': '45px', 'font_weight': 'bold'}, button_style='', disabled = False)\n",
"method = widg.ToggleButtons(options=[('SSB ','ssb'),('ITR ','iterative')],description='',icons=['opera','refresh'], tooltips=['Single side band ptychography', 'Iterative reconstruction methods (PIE, ML, DM)'],\n",
"method = widg.ToggleButtons(options=[('SSB ','ssb'),('ITR ','iterative')],description='',icons=['opera','refresh'], tooltips=['Single side band ptychography', 'Iterative reconstruction methods (e.g. 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_set = widg.Button(description='Electron beam settings',layout=widg.Layout(width='95%',grid_area='beam_set'),style=widg.ButtonStyle(button_color='#3b446b',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=2500, step=5, readout_format='d',continuous_update=False, layout=widg.Layout(width='95%', grid_area='beam_set4'), **ali)\n",
@ -140,20 +138,30 @@
"aperture = widg.ToggleButtons(options=pty.load_apertures(), description='', layout=widg.Layout(width='95%', grid_area='beam_set2'), **ali3)\n",
"\n",
"### Scanning parameters\n",
"scanning_set = widg.Button(description='Scanning parameters', layout=widg.Layout(width='95%', grid_area='scanning_set'),style=widg.ButtonStyle(button_color='#222261', font_weight= 'bold',font_size= '16px',text_color='white'),disabled = False)\n",
"scanning_set = widg.Button(description='Scanning parameters', layout=widg.Layout(width='95%', grid_area='scanning_set'),style=widg.ButtonStyle(button_color='#3b446b', font_weight= 'bold',font_size= '16px',text_color='white'),disabled = False)\n",
"mag = widg.Dropdown(options=pty.load_magnifications(), value=20, description='Magnification Mx', layout=widg.Layout(width='95%', grid_area='scanning_set1'), **ali)\n",
"matrix = widg.Dropdown(options=pty.load_mappings(), value=256, description='Matrix', layout=widg.Layout(width='95%', grid_area='scanning_set2'), **ali)\n",
"dwell_time = widg.Dropdown(options=pty.load_dwelltimes(), value=10, description='Dwell time (μs)', layout=widg.Layout(width='95%', grid_area='scanning_set3'), **ali)\n",
"\n",
"### Detection\n",
"camera_set = widg.Button(description='Detection',layout=widg.Layout(width='95%', grid_area='camera_set'),style=widg.ButtonStyle(button_color='#222261', font_weight= 'bold',font_size= '16px',text_color='white'),disabled = False)\n",
"camera_set = widg.Button(description='Detection',layout=widg.Layout(width='95%', grid_area='camera_set'),style=widg.ButtonStyle(button_color='#3b446b', 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",
"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), ('24',24), ('32',32), ('48',48)], value=1, description='', icons = ['ban','',''], layout=widg.Layout(width='95%', grid_area='camera_set3'), **ali3)\n",
"binning = widg.ToggleButtons(options=[('',1), ('2',2), ('4',4), ('8',8), ('16',16)], value=1, description='', icons = ['ban','','','',''], layout=widg.Layout(width='95%', grid_area='camera_set3'), **ali3)\n",
"camera_set6 = widg.Button(description='Post-acquisition treatments (ITR)',layout=widg.Layout(width='95%', grid_area='camera_set6'),style=widg.ButtonStyle(button_color='white', font_size= '16px',text_color='black'),disabled = False)\n",
"\n",
"\n",
"\n",
"padding = widg.SelectionSlider(options=[('none',1), ('double',2), ('triple',3), ('quadruple',4), ('quintuple',5)], value=1, description='Padding', continuous_update=False, orientation='horizontal', readout=True, layout=widg.Layout(width='95%', grid_area='camera_set4'), **ali)\n",
"pattern_resto = widg.SelectionSlider(options=[('none',1), ('double',2), ('triple',3), ('quadruple',4), ('quintuple',5)], value=1, description='Pattern recovery', continuous_update=False, orientation='horizontal', readout=True, layout=widg.Layout(width='95%', grid_area='camera_set5'), **ali)\n",
"\n",
"\n",
"\n",
"\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",
@ -172,8 +180,8 @@
"\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",
" binning, beam_res, aperture_res, aperture_res2, fov_res, dwell_time_res, graph_size, name1, visual_set, padding, pattern_resto, camera_set6],\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 35px 35px 35px 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",
@ -191,6 +199,9 @@
" \"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",
" \"camera_set6 camera_set6 camera_set6 camera_set6 camera_set6\"\n",
" \"camera_set4 camera_set4 camera_set4 camera_set4 camera_set4 \"\n",
" \"camera_set5 camera_set5 camera_set5 camera_set5 camera_set5 \"\n",
" \". . . . . \"\n",
" \"visual_set visual_set visual_set visual_set visual_set \"\n",
" \"name1 name1 gr_size2 gr_size2 gr_size2 \"'''))\n",
@ -204,43 +215,38 @@
"### 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",
"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', 'geom'),('Simulated: A', 'simA'),('Simulated: I', 'simI')], layout=widg.Layout(grid_area='overlap_fig'), style = {'button_width': '30%'}, disabled=False)\n",
"fov_show = widg.BoundedFloatText(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 = '110px'),style={'description_width': '55px'})\n",
"fov_show = widg.BoundedFloatText(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 = '115px'),style={'description_width': '55px'})\n",
"beam_pos = widg.BoundedIntText(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 = '120px'),style={'description_width': '70px'})\n",
"\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:', layout=widg.Layout(grid_area='red_box',width = '150px'),style={'description_width': '70px'})\n",
"box_col = widg.ColorPicker(concise=False, description='', value='cyan', disabled=False, layout=widg.Layout(grid_area='box_col', width = '50px'))\n",
"prof_show = widg.Checkbox(value=False, description='Show line profile', disabled=False, indent=False, layout=widg.Layout(grid_area='prof_show'))\n",
"\n",
"\n",
"rs_sampling = widg.Dropdown(options=[('Overlap', 'overlap'), ('Linear sampling', 'linear'), ('Areal sampling', 'areal')], description='',layout=widg.Layout(grid_area='rs_sampling', width = '115px'),style={'description_width': '0px'})\n",
"\n",
"### Camera length based limitations and checks\n",
"cl_set = widg.Button(description='Camera length based limitations and checks for ITR', 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 coverage (α):', 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.BoundedIntText(value=10,min=0,max=20,step=1,description='Small angle approx. (°):', disabled=False,continuous_update=False,orientation='horizontal',readout=True,readout_format='d',layout=widg.Layout(grid_area='check1name', width = '200px'),style={'description_width': '140px'})\n",
"check1name = widg.BoundedIntText(value=10,min=0,max=50,step=1,description='Small angle approx. (°):', disabled=False,continuous_update=False,orientation='horizontal',readout=True,readout_format='d',layout=widg.Layout(grid_area='check1name', width = '200px'),style={'description_width': '140px'})\n",
"check2name = widg.BoundedFloatText(value=1,min=0.5,max=5,step=0.5, description='Resolution gain:', disabled=False,continuous_update=False,orientation='horizontal',readout=True, readout_format='.1f', layout=widg.Layout(grid_area='check2name', width = '200px'), style={'description_width': '140px'})\n",
"check3name = widg.IntSlider(value=50,min=0,max=100,step=10, description='Probe window coverage (%):', disabled=False,continuous_update=False,orientation='horizontal',readout=True, readout_format='d', layout=widg.Layout(grid_area='check3name', width = '100%'), style=style)\n",
"check4name = widg.IntSlider(value=70, min=0 ,max=100, step=5, description='Beam overlap (%):', disabled=False, continuous_update=False, orientation='horizontal', readout=True,readout_format='d', layout=widg.Layout(grid_area='check4name', width = '100%'),style=style)\n",
"check6name = widg.BoundedIntText(value=1,min=1,max=20,step=1, description='Overall sampling:', disabled=False,continuous_update=False,orientation='horizontal',readout=True, readout_format='d', layout=widg.Layout(grid_area='check6name', width = '200px'), style={'description_width': '140px'})\n",
"\n",
"\n",
"\n",
"### Layout\n",
"graph_controls = widg.GridBox(children=[sample_set, ctf_set, ctf_xaxis, element, beam_pos, fov_show, cl_set, overlap_fig, red_box, box_col, check0name, check1name, check2name, check3name,check4name, check6name, ctf_xaxis_name, prof_show],\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, check4name, check6name, ctf_xaxis_name, prof_show, rs_sampling],\n",
" layout=widg.Layout(width='1600px', grid_template_rows='35px 35px 35px 35px 5px', grid_template_columns='4% 3.5% 14% 50px 8% 6.5% 3% 6.5% 1% 26% 14%', grid_template_areas='''\n",
" \". ctf_set ctf_set . sample_set sample_set beam_pos beam_pos . cl_set cl_set \" \n",
" \". ctf_xaxis_name ctxaxis . overlap_fig overlap_fig overlap_fig overlap_fig . check0name check1name \"\n",
" \". ctf_element ctf_element . fov_show red_box red_box box_col . check4name check2name \"\n",
" \". . . . . . prof_show prof_show . check3name check6name \"\n",
" \". . . . rs_sampling . prof_show prof_show . . check6name \"\n",
" \". . . . . . . . . . . \"''')) \n",
"\n",
"def ptycho_interact(beam_energy, aperture, aperture_res, aperture_res2, probe_size, cl, matrix, defocus, mag, camera, binning, dwell_time, restr, method,\n",
" ctf_xaxis, element, graph_size, beam_pos, fov_show, overlap_fig, red_box, box_col, check0name, check1name, check2name, check3name, check4name, check6name, prof_show):\n",
" ctf_xaxis, element, graph_size, beam_pos, fov_show, overlap_fig, red_box, box_col, check0name, check1name, check2name, check4name, check6name, prof_show, padding, pattern_resto, rs_sampling):\n",
"\n",
" fov = pty.get_fov(mag) \n",
" pctf_itr = pty.get_ctf(element)\n",
@ -262,12 +268,15 @@
" overlap = (beam_diameter-step_size_corr)/beam_diameter*100\n",
" if overlap < 0:\n",
" overlap = 0 \n",
" area_oversampling = (cons.pi*beam_diameter/2*beam_diameter/2)/(step_size_corr*step_size_corr)\n",
" linear_oversampling = (2*beam_diameter/2)/(step_size_corr)\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",
" probe_window = pattern_resto*(wavelength*cl_det/100)/(size_pixel/1e6)/1000 # now in nm\n",
" oversampling = (wavelength/1000)/(2*pixel_angle/1000*step_size_corr)\n",
" max_defocus = (probe_window/4)/np.tan(semi_angle_corr/1000)\n",
" z_res = wavelength/(2*np.sin(detector_cover/1000/2)*np.sin(detector_cover/1000/2))/100 # now in A\n",
" dRssb = (wavelength/100)/(2*np.sin(2*semi_angle_corr/1000))\n",
" \n",
" ### ALL CAMERA LENGTHS PARAMETERS\n",
" cl_all = pty.load_cameralengths(camera, \"nominal\")\n",
@ -282,17 +291,17 @@
" if detector_cover_all[x] > pump_apertures[x]:\n",
" detector_cover_all[x] = pump_apertures[x] \n",
" detector_pixels_all = np.round(detector_cover_all/pixel_covers,1) \n",
" ptycho_pixel_size_all = (wavelength*np.array(cl_eff_all))/(detector_pixels_all*size_pixel/1e6)/1e4 \n",
" ptycho_pixel_size_all = ((wavelength*np.array(cl_eff_all))/(detector_pixels_all*size_pixel/1e6)/1e4)/padding\n",
" else:\n",
" ptycho_pixel_size_all = (wavelength*np.array(cl_eff_all))/(num_pixels/2*size_pixel/1e6)/1e4\n",
" ptycho_pixel_size_all = ((wavelength*np.array(cl_eff_all))/(num_pixels/2*size_pixel/1e6)/1e4)/padding\n",
"\n",
" probe_window_all = (wavelength*np.array(cl_eff_all)/100)/(size_pixel/1e6)/1000 # now in nm\n",
" probe_window_all = pattern_resto*(wavelength*np.array(cl_eff_all)/100)/(size_pixel/1e6)/1000 # now in nm\n",
" usable_probe_semi_window_all = probe_window_all/4\n",
" detector_cover_a_all = detector_cover_all/semi_angle_corr\n",
" max_defocus_all = (usable_probe_semi_window_all)/np.tan(semi_angle_corr/1000)\n",
" max_defocus_all[max_defocus_all < 0] = 'nan'\n",
" oversampling_all = (wavelength/1000)/(2*pixel_covers/1000*step_size_corr)\n",
" z_res_all = wavelength/(2*np.sin(detector_cover_all/1000/2)*np.sin(detector_cover_all/1000/2))/100 # now in A\n",
" z_res_all = (wavelength/(2*np.sin(detector_cover_all/1000/2)*np.sin(detector_cover_all/1000/2))/100)/padding # now in A\n",
"\n",
" ### MICROSCOPE SCHEME\n",
" width = 550 # in-graph setting\n",
@ -378,7 +387,6 @@
" 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",
"\n",
" ### SAMPLE PLANE\n",
" match overlap_fig: \n",
" case 'geom':\n",
@ -386,8 +394,8 @@
" yyy = np.append(np.linspace(0,overlap,100),200)\n",
" \n",
" fig1 = go.Figure() \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",
" fig1.update_xaxes(range=[-fov_show/2, fov_show/2], showgrid=False, showline=True, mirror=True, ticks='inside',linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\", title_text=\"Sample plane (nm)\",zeroline=False)\n",
" fig1.update_yaxes(range=[-fov_show/2, fov_show/2], showgrid=False, showline=True, mirror=True, ticks='',linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\", 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'))\n",
@ -398,31 +406,44 @@
" 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=(0,0), y=(0,0),marker_size=12, marker_color='green', name='<b>Recom. step '+str(np.round(xx[-1]/3,2))+' Å<b>', opacity = 0)) \n",
" fig1.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.0,xanchor=\"right\",x=0.9))\n",
" fig1.add_trace(go.Scatter(showlegend=True, x=[-100], y=[-100],marker_size=12, marker_color='red', name='ΔR '+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='Probe ⌀ '+str(np.round(10*beam_diameter,2))+' Å')) \n",
"\n",
" fig1.update_layout(plot_bgcolor='white')\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='',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
" fig1.add_trace(go.Scatter(x=(0,0), y=(0,0), name='<b>Overlap '+str(np.round(overlap,1))+' %<b>', showlegend=True, opacity = 0))\n",
" \n",
" match method: \n",
" case 'ssb':\n",
" \n",
" fig1.update_layout(legend=dict(orientation=\"v\",yanchor=\"middle\",y=0.5,xanchor=\"right\",x=1.8))\n",
" fig1.update_layout(width=5.2*graph_size, height=4*graph_size, margin =dict(l=0.6*graph_size, r=0*graph_size, t=0.8*graph_size, b=0.7*graph_size))\n",
" fig1.update_layout(title={'text': \"Sample\",'y': 0.87, 'x': 0.36,'xanchor': 'center','yanchor': 'top'})\n",
" fig1.add_trace(go.Scatter(showlegend=True, x=(0,0), y=(0,0),marker_size=12, marker_color='green', name= '<b>ΔR_SSB ' + str(np.round(dRssb,2))+' Å<b>', opacity = 0)) \n",
" fig1.update_layout(width=3.15*graph_size, height=3.9*graph_size, plot_bgcolor='white', margin = dict(l=0.65*graph_size, r=0.01*graph_size, t=0.8*graph_size, b=0.7*graph_size),\n",
" legend = dict(orientation=\"v\",yanchor=\"bottom\",y=1.01, xanchor=\"right\",x=1), title = {'text': \"Sample\",'y': 0.87, 'x': 0.23,'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.87, 'x': 0.3,'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.1*graph_size, t=0.8*graph_size, b=0))\n",
" match rs_sampling:\n",
" case 'overlap':\n",
" fig1.add_trace(go.Scatter(x=(0,0), y=(0,0), name='<b>Overlap '+str(np.round(overlap,1))+' %<b>', showlegend=True, opacity = 0))\n",
" case 'linear':\n",
" fig1.add_trace(go.Scatter(x=(0,0), y=(0,0), name='<b>Linear sampl. '+str(np.round(linear_oversampling,1))+'<b>', showlegend=True, opacity = 0))\n",
" case 'areal':\n",
" fig1.add_trace(go.Scatter(x=(0,0), y=(0,0), name='<b>Area sampl. '+str(np.round(area_oversampling,1))+'<b>', showlegend=True, opacity = 0))\n",
"\n",
" fig1.update_layout(width=2.9*graph_size, height=3.7*graph_size, plot_bgcolor='white', margin =dict(l=0.2*graph_size, r=0.1*graph_size, t=0.8*graph_size, b=0),\n",
" legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=1), title={'text': \"Sample\",'y': 0.87, 'x': 0.1,'xanchor': 'left','yanchor': 'top'})\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
" \n",
" case overlap_fig if overlap_fig in ['simI', 'simA']:\n",
" if abtem == True:\n",
" sampling= 0.05 # sampling of the simulated potential in A\n",
@ -453,39 +474,37 @@
" uniformity = (1-(np.max(middle)-np.min(middle))/(np.max(field)-np.min(field)))*100\n",
" \n",
" fig1 = go.Figure() \n",
" fig1.update_xaxes(range=[0, field_size-1])\n",
" fig1.update_yaxes(range=[0, field_size-1])\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_traces(dict(showscale=False, coloraxis=None, colorscale='inferno'), selector={'type':'heatmap'})\n",
" fig1.add_trace(go.Scatter(x=np.array(probe_window/4), y=np.array(probe_window/4), name='Uniformity '+str(np.round(uniformity,1))+' %', showlegend=True, opacity = 0))\n",
" fig1.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.8),title={'text':\"Illumination\",'y':0.90,'x':0.4,'xanchor':'left','yanchor':'top'})\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.2*graph_size, height=3.9*graph_size, margin =dict(l=0.5*graph_size, r=0.1*graph_size, t=0.9*graph_size, b=0.55*graph_size))\n",
" \n",
" fig1.update_xaxes(range=[0, field_size-1], 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)])\n",
" fig1.update_yaxes(range=[0, field_size-1], showticklabels=False)\n",
" fig1.update_layout(width=3.2*graph_size, height=3.9*graph_size, margin =dict(l=0.5*graph_size, r=0.1*graph_size, t=0.9*graph_size, b=0.55*graph_size),\n",
" legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.8), title={'text':\"Illumination\",'y':0.90,'x':0.4,'xanchor':'left','yanchor':'top'})\n",
" else:\n",
" fig1 = go.Figure() \n",
" fig1.update_layout(title={'text': \"abTEM not available\",'y': 0.98, 'x': 0.14,'xanchor': 'left','yanchor': 'top'})\n",
" fig1.update_layout(width=3.2*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",
" fig1.update_layout(title={'text': \"abTEM not available\",'y': 0.98, 'x': 0.14,'xanchor': 'left','yanchor': 'top'},\n",
" width=3.2*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",
" ### 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 = go.Figure() \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\")\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\") \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+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",
" fig2.update_xaxes(title_text=\"Detector pixel array\", range=[0.5, num_pixels+0.5], tickvals = [1, num_pixels/2+0.5, num_pixels],\n",
" ticktext = [1, num_pixels/2, num_pixels], showticklabels=True, showgrid=True, 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\",title_text=\"Cover angle (mrad)\", showticklabels=True, showgrid=True,\n",
" 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(width=3.45*graph_size, height=4.7*graph_size, margin =dict(l=0.65*graph_size, r=0.25*graph_size, t=1.9*graph_size, b=0),\n",
" title={'text': \"Detector\",'y':0.65, 'x': 0.44,'xanchor': 'left','yanchor': 'top'}, plot_bgcolor='white', legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"left\",x=0.1))\n",
"\n",
" match method: \n",
" case 'ssb':\n",
" ### CAMERA LENGTH GRAPH\n",
@ -497,16 +516,15 @@
" 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.add_annotation(x=np.log10(np.max(cl_all)), y=detector_cover, text=str(np.round(covered_alfas,1)), showarrow=False, xshift=15, 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=-15, 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_xaxes(range=[np.log10(np.min(cl_all)/1.5), np.log10(np.max(cl_all)*1.5)], 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_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",
" 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",
" width=3.61*graph_size, height=3.4*graph_size, margin =dict(l=0.3*graph_size, r=0.25*graph_size, t=0.3*graph_size, b=0.3*graph_size))\n",
" \n",
" ### SSB-PCTF\n",
" omega, pctf = pty.get_ssb_ctf()\n",
@ -515,10 +533,9 @@
" fig5 = go.Figure() \n",
" fig5.update_yaxes(title_text=\"Transfer (-)\")\n",
" match ctf_xaxis:\n",
" case 'α':\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",
" fig5.update_xaxes(title_text=\"Spatial frequency (ω)\", range=[0, 2], zeroline=False)\n",
" case 'mrad':\n",
" for x in apertures:\n",
" if x == apertures[0]:\n",
@ -526,8 +543,7 @@
" 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",
" fig5.update_xaxes(title_text=\"Spatial frequency (mrad)\", range=[0, 2*semi_angle_corr], zeroline=False)\n",
" case 'Å':\n",
" for x in apertures:\n",
" d = wavelength/(np.sin(pty.get_angle_corr(x)*omega/1000))/100 # Full pitch size\n",
@ -538,10 +554,10 @@
" fig5.add_trace(go.Scatter(showlegend=True, x=xx, y=pctf, marker_color='red', name='Selected aperture'))\n",
" fig5.update_xaxes(title_text=\"Spacing (Å)\", range=[-0.5, 2], type=\"log\", zeroline=False)\n",
" \n",
" fig5.update_layout(plot_bgcolor='white', title={'text': \"Phase CTF\",'y':0.99, 'x':0.42,'xanchor': 'left','yanchor': 'top'},legend=dict(orientation=\"h\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.95)) \n",
" fig5.update_xaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
" fig5.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
" fig5.update_layout(width=3.5*graph_size, height=2.2*graph_size, margin = dict(l=0.3*graph_size, r=0.3*graph_size, t=0.5*graph_size, b=0.4*graph_size))\n",
" 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), plot_bgcolor='white',\n",
" 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",
" \n",
" case 'iterative':\n",
" ### ITR-PCTF\n",
@ -549,9 +565,9 @@
" fig5 = go.Figure() \n",
" fig5.update_yaxes(title_text=\"Transfer (-)\")\n",
" match ctf_xaxis: \n",
" case 'α':\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_xaxes(title_text=\"Spatial frequency (ω)\", range=[0, 6], zeroline=False)\n",
" fig5.update_yaxes(range=[0, 1.1])\n",
" case 'mrad': \n",
" for x in apertures:\n",
@ -560,7 +576,7 @@
" 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",
" fig5.update_xaxes(title_text=\"Spatial frequency (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",
@ -572,10 +588,10 @@
" 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",
" 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",
" 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",
"\n",
" ### PROBE WINDOW\n",
" match overlap_fig:\n",
@ -592,18 +608,18 @@
"\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 recom. Δf '+str(np.round(max_defocus,1))+' nm', showlegend=True, marker_color=color, opacity = 0))\n",
" fig3.add_trace(go.Scatter(x=np.array(probe_window/2), y=np.array(probe_window/2), name='<b>Maximal Δf '+str(np.round(max_defocus,1))+' nm<b>', showlegend=True, marker_color=color, opacity = 0))\n",
"\n",
" for i in range(0, len(opacity)):\n",
" fig3.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=opacity[i], fillcolor=color, x0=probe_window/2-beam_diameter/xcoef[i], y0=probe_window/2-beam_diameter/xcoef[i], \n",
" x1=probe_window/2+beam_diameter/xcoef[i], y1=probe_window/2+beam_diameter/xcoef[i], line_color=color)\n",
" \n",
" fig3.update_xaxes(title_text=\"Probe window (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",
" fig3.update_xaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\", \n",
" title_text=\"Probe window (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(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\",\n",
" range=[0, probe_window], tickvals = [0, probe_window/4, probe_window/2, 3*probe_window/4, probe_window], showticklabels=False)\n",
" fig3.update_layout(width=3.2*graph_size, height=4.0*graph_size, margin =dict(l=0.5*graph_size, r=0, t=0.8*graph_size, b=0.75*graph_size), plot_bgcolor='white',\n",
" legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.8),title={'text':\"Probe\",'y':0.92,'x':0.48,'xanchor':'left','yanchor':'top'}) \n",
"\n",
" case overlap_fig if overlap_fig in ['simI', 'simA']:\n",
" if abtem == True:\n",
@ -632,34 +648,26 @@
" 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",
"\n",
" fig3.add_trace(go.Scatter(x=np.array(probe_window/4), y=np.array(probe_window/4), name='Probe covered '+str(np.round(int_tot,1))+' %', showlegend=True, opacity = 0))\n",
" fig3.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.8),title={'text':\"Probe\",'y':0.9,'x':0.4,'xanchor':'left','yanchor':'top'})\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_traces(dict(showscale=False, coloraxis=None, colorscale='inferno'), selector={'type':'heatmap'})\n",
" fig3.update_xaxes(range=[0, 2*sirkaB-1], mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\", title_text=\"Probe window (nm)\", showgrid=False, showticklabels=True,\n",
" tickvals = [sirkaB/2, sirkaB, 3*sirkaB/2], ticktext = [0, np.round(sirkaB/200,2), np.round(sirkaB/100,2)])\n",
" fig3.update_xaxes(range=[0, 2*sirkaB-1], mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\", title_text=\"Probe window (nm)\", showgrid=False, showticklabels=True, tickvals = [sirkaB/2, sirkaB, 3*sirkaB/2], ticktext = [0, np.round(sirkaB/200,2), np.round(sirkaB/100,2)])\n",
" fig3.update_yaxes(range=[0, 2*sirkaB-1],showticklabels=False)\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",
" fig3.update_layout(width=3.0*graph_size, height=3.9*graph_size, margin =dict(l=0.4*graph_size, r=0.1*graph_size, t=0.9*graph_size, b=0.55*graph_size),\n",
" legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.8),title={'text':\"Probe\",'y':0.9,'x':0.4,'xanchor':'left','yanchor':'top'})\n",
" else:\n",
" fig3 = go.Figure() \n",
" fig3.update_layout(title={'text': \"abTEM not available\",'y': 0.98, 'x': 0.14,'xanchor': 'left','yanchor': 'top'})\n",
" fig3.update_layout(width=2.7*graph_size, height=3.9*graph_size, margin =dict(l=0.1*graph_size, r=0.1*graph_size, t=0.9*graph_size, b=0.55*graph_size))\n",
" \n",
" ### FINAL CHECKS \n",
" check1 = widg.Valid(value= bool(overlap > check4name), description='Beam overlap',layout=widg.Layout(width='250px'), style = {'description_width': '100px'}, disabled=True)\n",
" check2 = widg.Valid(value= bool(step_size_corr*10 > (wavelength*cl_det)/(num_pixels*size_pixel/1e6)/1e4), description='Resolution gain', layout=widg.Layout(width='250px'), style = {'description_width': '100px'}, disabled=True)\n",
" check3 = widg.Valid(value= bool(beam_diameter/2 < probe_window/2), description='Box coverage', layout=widg.Layout(width='250px'), style = {'description_width': '100px'}, disabled=True) \n",
" check4 = widg.Valid(value= bool(oversampling > 1), description='Overall sampling', layout=widg.Layout(width='250px'), style = {'description_width': '100px'}, disabled=True) \n",
" checks = widg.VBox([widg.HBox([check1, check2]), widg.HBox([check3, check4])]) # Label('Final checks')\n",
" checks.layout = widg.Layout(margin='0px 0px 0px 100px', padding='0px 0px 0px 0px', border='solid 3px gray') # border='dashed 1px gray'\n",
"\n",
" ### CAMERA LENGTH TABLE\n",
" dictionary = {}\n",
" tab = np.array([cl_all, np.round(ptycho_pixel_size_all,2), np.round(z_res_all,2), np.round(detector_cover_all,1), np.round(detector_cover_a_all,1), np.round(probe_window_all,1), np.round(oversampling_all,1)])\n",
" tab = np.array([cl_all, np.round(ptycho_pixel_size_all,2), np.round(z_res_all,2), np.round(detector_cover_all,1) , np.round(detector_cover_a_all,1), \n",
" np.round(probe_window_all,2), np.round(max_defocus_all,1), np.round(oversampling_all,1)])\n",
" \n",
" for i in range(0,len(cl_eff_all)):\n",
" button_style = 'success'\n",
" icons=['','','','','','','']\n",
" data = tab[:,int(i)] # 0.cl, 1. ptycho pix xy, 2. ptycho pix z, 3.det cov, 4.det cov a, 5.max def, 6.probe window, 7.oversampling\n",
" icons=['','','','','','','','','']\n",
" data = tab[:,int(i)] # 0.cl, 1. ptycho pix xy, 2. ptycho pix z, 3.det cov, 4.det cov a, 5.probe window restored, 6. max defocus, 7.oversampling,\n",
" \n",
" if cl == data[0]:\n",
" icons[0]= \"hand-point-left\"\n",
@ -676,22 +684,28 @@
" icons[4]= \"bell\"\n",
" button_style = 'warning'\n",
" \n",
" if beam_diameter > check3name/100*data[5]:\n",
" if beam_diameter > data[5]/2:\n",
" icons[5]= \"bell\"\n",
" button_style = 'warning'\n",
" \n",
" if data[6] < 1: # check6name = 'Sampling > 1' \n",
" icons[6]= \"ban\"\n",
" \n",
" if data[7] < 1: # check6name = 'Sampling > 1' \n",
" icons[7]= \"ban\"\n",
" button_style = 'danger' \n",
" if data[6] > 1 and data[6] < int(check6name): # check6name = 'Sampling > check6name' \n",
" icons[6]= \"ban\"\n",
" button_style = 'warning' \n",
" \n",
" dictionary[i] = widg.ToggleButtons(options=tuple(data), text_color= 'red', button_style=button_style, icons = icons, layout=widg.Layout(width=str(int(graph_size/100*65))+'px'),\n",
" style = {'description_width': '0px','button_width': str(int(graph_size/100*63))+'px'}, disabled=True)\n",
" legend = widg.ToggleButtons(options=['Nominal CL (cm)','Resolution XY (Å)','Minimal slice th. (Å)', 'Detector cover (mrad)','Detector cover (α)', 'Probe window (nm)', 'Overall sampling'],\n",
" button_style='', layout=widg.Layout(width='150px'), style = {'description_width': '0px','button_width': \"150px\"}, disabled=True) \n",
" if data[7] > 1 and data[6] < int(check6name): # check6name = 'Sampling > check6name' \n",
" icons[7]= \"bell\"\n",
" button_style = 'warning' \n",
"\n",
" if data[7] < pattern_resto:\n",
" icons[7]= \"ban\"\n",
" button_style = 'danger' \n",
" \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*70))+'px'),\n",
" style = {'description_width': '0px','button_width': str(int(graph_size/100*67))+'px'}, disabled=True)\n",
" legend = widg.ToggleButtons(options=['L (cm)','∆x (Å)','∆z (Å)', 'θ (mrad)','θ (α)', 'Dψ (nm)', 'Δf (nm)','Ŝx,y'],\n",
" tooltips=['Nominal camera length','Reconstucted pixel size','Minimal slice thickness for multi-slice reconstruction', 'Maximum detected angle',\n",
" 'Maximum detected angle in multiplications of probe semi-angle', 'Probe window size', 'Maximum defocus to create an adequately sampled probe', 'Combined sampling'],\n",
" button_style='', layout=widg.Layout(width='85px'), style = {'description_width': '0px','button_width': \"80px\"}, disabled=True) \n",
" \n",
" # FIX here\n",
" match len(cl_eff_all):\n",
@ -719,17 +733,37 @@
" cltab = widg.HBox([legend, dictionary[0], dictionary[1], dictionary[2], dictionary[3], dictionary[4], dictionary[5], dictionary[6], dictionary[7], dictionary[8], dictionary[9], dictionary[10]])\n",
"\n",
" cltab = widg.VBox([widg.Label('CAMERA LENGTH GUIDE'), cltab])\n",
" cltab.layout = widg.Layout(border='solid 0px gray',margin='0px 0px 0px 0px', padding='5px 5px 5px 5px')\n",
" cltab.layout = widg.Layout(border='solid 0px gray',margin='0px 0px 0px 15px', padding='5px 5px 5px 5px')\n",
"\n",
" ### SHOWING\n",
" left = widg.VBox([go.FigureWidget(fig5),go.FigureWidget(fig2)])\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",
" check_width = '220px'\n",
" check_descr_width = '120px'\n",
" check1_ssb = widg.Valid(value= bool(step_size_corr*10 < dRssb), description='Real-space sampling', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True)\n",
" check2_ssb = widg.Valid(value= bool(1 < covered_alfas) , description='Detector coverage', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True)\n",
" check3_ssb = widg.Valid(value= bool(3 < beam_diameter_pix) , description='Minimal BF size', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True)\n",
" checks_ssb = widg.VBox([check1_ssb, check2_ssb,check3_ssb]) # Label('Final checks')\n",
" checks_ssb.layout = widg.Layout(margin='100px 0px 0px 30px', padding='0px 0px 0px 0px', border='solid 0px gray') # border='dashed 1px gray'\n",
"\n",
" left = widg.VBox([go.FigureWidget(fig5),go.FigureWidget(fig2)])\n",
" total = widg.HBox([left, go.FigureWidget(fig), right])\n",
"\n",
" right = widg.VBox([go.FigureWidget(fig1), widg.HBox([go.FigureWidget(fig4), checks_ssb]) ])\n",
" \n",
" case 'iterative':\n",
" check_width = '220px'\n",
" check_descr_width = '120px'\n",
" check1_itr = widg.Valid(value= bool(overlap > check4name), description='Beam overlap',layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True)\n",
" check2_itr = widg.Valid(value= bool(step_size_corr*10 > (wavelength*cl_det)/(num_pixels*size_pixel/1e6)/1e4), description='Resolution gain', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True)\n",
" check3_itr = widg.Valid(value= bool(beam_diameter/2 < probe_window/2), description='Probe window', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True) \n",
" check4_itr = widg.Valid(value= bool(oversampling > 1), description='Combined sampling', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True) \n",
" check5_itr = widg.Valid(value= bool(oversampling > pattern_resto), description='Pattern recovery', layout=widg.Layout(width=check_width), style = {'description_width': check_descr_width}, disabled=True) \n",
" checks_itr = widg.HBox([widg.VBox([check1_itr, check2_itr]), widg.VBox([check3_itr, check4_itr]), widg.VBox([check5_itr])]) # Label('Final checks')\n",
" checks_itr.layout = widg.Layout(margin='0px 0px 0px 5px', padding='0px 0px 0px 0px', border='solid 0px gray') # border='dashed 1px gray'\n",
"\n",
" right = widg.VBox([widg.HBox([go.FigureWidget(fig1),go.FigureWidget(fig3)]), cltab, checks_itr])\n",
" \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",
@ -737,9 +771,9 @@
"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, \"prof_show\":prof_show}) \n",
" \"check1name\": check1name, \"check2name\": check2name, \"check4name\": check4name, \"check6name\": check6name, \"prof_show\":prof_show, \"padding\":padding, \"pattern_resto\":pattern_resto, \"rs_sampling\": rs_sampling}) \n",
"\n",
"ptychoscopy = widg.VBox([top_set, widg.HBox([controls, widg.VBox([graph_controls, gui])])])\n"
"ptychoscopy = widg.VBox([top_set, widg.HBox([controls, widg.VBox([graph_controls, gui])])])"
]
}
],

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

After

Width:  |  Height:  |  Size: 193 KiB