diff --git a/.ipynb_checkpoints/ptychoScopy-checkpoint.ipynb b/.ipynb_checkpoints/ptychoScopy-checkpoint.ipynb index d67aeda..ecbd2c9 100644 --- a/.ipynb_checkpoints/ptychoScopy-checkpoint.ipynb +++ b/.ipynb_checkpoints/ptychoScopy-checkpoint.ipynb @@ -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", @@ -298,7 +315,7 @@ " x = np.linspace(-det_width, det_width, int(num_pixels)+1)\n", " \n", " fig = go.Figure() \n", - " fig.update_xaxes(range=[-width, width], showticklabels=False,zeroline=False)\n", + " fig.update_xaxes(range=[-width, width], showticklabels=False,zeroline=False)\n", " fig.update_yaxes(range=[-y_down, reduc*y_down], showticklabels=False)\n", " fig.add_shape(type=\"rect\",xref=\"x\", yref=\"y\",opacity=0.05, fillcolor=\"gray\", x0=-width, y0=-y_down, x1=width, y1=reduc*y_down,line_color=\"gray\")\n", " fig.add_shape(type=\"rect\",xref=\"x\", yref=\"y\",opacity=0.7, fillcolor=\"red\", x0=-100, y0=reduc*0.8*y_down, x1=100, y1=reduc*0.9*y_down,line_color=\"red\")\n", @@ -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= 'ΔR_SSB ' + str(np.round(dRssb,2))+' Å', 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='Overlap '+str(np.round(overlap,1))+' %', showlegend=True, opacity = 0))\n", + " case 'linear':\n", + " fig1.add_trace(go.Scatter(x=(0,0), y=(0,0), name='Linear sampl. '+str(np.round(linear_oversampling,1))+'', showlegend=True, opacity = 0))\n", + " case 'areal':\n", + " fig1.add_trace(go.Scatter(x=(0,0), y=(0,0), name='Area sampl. '+str(np.round(area_oversampling,1))+'', 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", @@ -553,15 +587,15 @@ " xx = wavelength/(np.sin(semi_angle_corr*omega_itr/1000))/100\n", " fig5.add_trace(go.Scatter(showlegend=True, x=xx, y=pctf_norm, marker_color='red', name='Selected aperture'))\n", " fig5.update_xaxes(title_text=\"Spacing (Å)\",range=[-1, 2], type=\"log\", zeroline=False)\n", - " \n", - " fig5.update_layout(title={'text': \"Phase CTF\",'y':0.99, 'x':0.42,'xanchor': 'left','yanchor': 'top'},legend=dict(orientation=\"h\",yanchor=\"bottom\",y=1.01,xanchor=\"left\",x=0),plot_bgcolor='white') \n", + " \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='Maximal Δf '+str(np.round(max_defocus,1))+' nm', showlegend=True, marker_color=color, opacity = 0))\n", "\n", " for i in range(0, len(opacity)):\n", " fig3.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=opacity[i], fillcolor=color, x0=probe_window/2-beam_diameter/xcoef[i], y0=probe_window/2-beam_diameter/xcoef[i], \n", " x1=probe_window/2+beam_diameter/xcoef[i], y1=probe_window/2+beam_diameter/xcoef[i], line_color=color)\n", " \n", - " fig3.update_xaxes(title_text=\"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", + " 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 = intensity3.shape\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,27 +733,47 @@ " 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", " \n", "gui = widg.interactive_output(ptycho_interact, {\"beam_energy\" : beam_energy, \"aperture\": aperture, \"aperture_res\": aperture_res, \"aperture_res2\": aperture_res2, \"probe_size\": probe_size, \"cl\": cl, \"matrix\": matrix,\n", - " \"defocus\": defocus, \"mag\": mag, \"camera\": camera, \"binning\": binning, \"dwell_time\" : dwell_time, \"restr\": restr, \"method\": method, \"ctf_xaxis\": ctf_xaxis, \"element\": element,\n", - " \"graph_size\": graph_size, \"beam_pos\": beam_pos, \"fov_show\": fov_show, \"overlap_fig\" :overlap_fig, \"red_box\": red_box, \"box_col\":box_col, \"check0name\":check0name, \n", - " \"check1name\": check1name, \"check2name\": check2name, \"check3name\": check3name, \"check4name\": check4name, \"check6name\": check6name, \"prof_show\":prof_show}) \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, \"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])])])" ] } ], diff --git a/ptychoScopy.ipynb b/ptychoScopy.ipynb index fdc9c46..ecbd2c9 100644 --- a/ptychoScopy.ipynb +++ b/ptychoScopy.ipynb @@ -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", @@ -306,7 +315,7 @@ " x = np.linspace(-det_width, det_width, int(num_pixels)+1)\n", " \n", " fig = go.Figure() \n", - " fig.update_xaxes(range=[-width, width], showticklabels=False,zeroline=False)\n", + " fig.update_xaxes(range=[-width, width], showticklabels=False,zeroline=False)\n", " fig.update_yaxes(range=[-y_down, reduc*y_down], showticklabels=False)\n", " fig.add_shape(type=\"rect\",xref=\"x\", yref=\"y\",opacity=0.05, fillcolor=\"gray\", x0=-width, y0=-y_down, x1=width, y1=reduc*y_down,line_color=\"gray\")\n", " fig.add_shape(type=\"rect\",xref=\"x\", yref=\"y\",opacity=0.7, fillcolor=\"red\", x0=-100, y0=reduc*0.8*y_down, x1=100, y1=reduc*0.9*y_down,line_color=\"red\")\n", @@ -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='Recom. step '+str(np.round(xx[-1]/3,2))+' Å', 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='Overlap '+str(np.round(overlap,1))+' %', 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= 'ΔR_SSB ' + str(np.round(dRssb,2))+' Å', 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='Overlap '+str(np.round(overlap,1))+' %', showlegend=True, opacity = 0))\n", + " case 'linear':\n", + " fig1.add_trace(go.Scatter(x=(0,0), y=(0,0), name='Linear sampl. '+str(np.round(linear_oversampling,1))+'', showlegend=True, opacity = 0))\n", + " case 'areal':\n", + " fig1.add_trace(go.Scatter(x=(0,0), y=(0,0), name='Area sampl. '+str(np.round(area_oversampling,1))+'', 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", @@ -571,11 +587,11 @@ " xx = wavelength/(np.sin(semi_angle_corr*omega_itr/1000))/100\n", " fig5.add_trace(go.Scatter(showlegend=True, x=xx, y=pctf_norm, marker_color='red', name='Selected aperture'))\n", " fig5.update_xaxes(title_text=\"Spacing (Å)\",range=[-1, 2], type=\"log\", zeroline=False)\n", - " \n", - " fig5.update_layout(title={'text': \"Phase CTF\",'y':0.99, 'x':0.42,'xanchor': 'left','yanchor': 'top'},legend=dict(orientation=\"h\",yanchor=\"bottom\",y=1.01,xanchor=\"left\",x=0),plot_bgcolor='white') \n", + " \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='Maximal Δf '+str(np.round(max_defocus,1))+' nm', showlegend=True, marker_color=color, opacity = 0))\n", "\n", " for i in range(0, len(opacity)):\n", " fig3.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=opacity[i], fillcolor=color, x0=probe_window/2-beam_diameter/xcoef[i], y0=probe_window/2-beam_diameter/xcoef[i], \n", " x1=probe_window/2+beam_diameter/xcoef[i], y1=probe_window/2+beam_diameter/xcoef[i], line_color=color)\n", " \n", - " fig3.update_xaxes(title_text=\"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,27 +733,47 @@ " 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", " \n", "gui = widg.interactive_output(ptycho_interact, {\"beam_energy\" : beam_energy, \"aperture\": aperture, \"aperture_res\": aperture_res, \"aperture_res2\": aperture_res2, \"probe_size\": probe_size, \"cl\": cl, \"matrix\": matrix,\n", - " \"defocus\": defocus, \"mag\": mag, \"camera\": camera, \"binning\": binning, \"dwell_time\" : dwell_time, \"restr\": restr, \"method\": method, \"ctf_xaxis\": ctf_xaxis, \"element\": element,\n", - " \"graph_size\": graph_size, \"beam_pos\": beam_pos, \"fov_show\": fov_show, \"overlap_fig\" :overlap_fig, \"red_box\": red_box, \"box_col\":box_col, \"check0name\":check0name, \n", - " \"check1name\": check1name, \"check2name\": check2name, \"check3name\": check3name, \"check4name\": check4name, \"check6name\": check6name, \"prof_show\":prof_show}) \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, \"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])])])" ] } ], diff --git a/ptychoscopy/calibrations.xlsx b/ptychoscopy/calibrations.xlsx index 960e588..6f09bdc 100644 Binary files a/ptychoscopy/calibrations.xlsx and b/ptychoscopy/calibrations.xlsx differ diff --git a/ptychoscopy/logo.PNG b/ptychoscopy/logo.PNG index 8c13bd1..f39fc04 100644 Binary files a/ptychoscopy/logo.PNG and b/ptychoscopy/logo.PNG differ