This commit is contained in:
rskoupy
2024-11-12 17:48:41 +01:00
parent 88cf2c1845
commit adc04b1edf
9 changed files with 693 additions and 145 deletions

View File

@ -47,7 +47,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "37bb53443b8a4d50bb614d7156907632",
"model_id": "c64267f661284b108b24ed204c5a7127",
"version_major": 2,
"version_minor": 0
},
@ -127,7 +127,7 @@
"beam_set = widg.Button(description='Electron beam settings',layout=widg.Layout(width='95%',grid_area='beam_set'),style=widg.ButtonStyle(button_color='#222261',font_weight='bold',font_size='16px',text_color='white'),disabled=False) \n",
"beam_energy = widg.Dropdown(options=pty.load_energies(), value=200, description='Beam energy (keV)', layout=widg.Layout(width='95%', grid_area='beam_set1'), **ali)\n",
"probe_size = widg.Dropdown(options=pty.load_probes(), value='8C', description='Probe', layout=widg.Layout(width='95%', grid_area='beam_set3'), **ali)\n",
"defocus = widg.FloatSlider(description='Defocus (nm)', value=0, min=0, max=1000, step=5, readout_format='d',continuous_update=False, layout=widg.Layout(width='95%', grid_area='beam_set4'), **ali)\n",
"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",
"aperture_name = widg.Label(value = 'Aperture', layout=widg.Layout(width='95%', grid_area='aperture_name'),)\n",
"aperture = widg.ToggleButtons(options=pty.load_apertures(), description='', layout=widg.Layout(width='95%', grid_area='beam_set2'), **ali3)\n",
"\n",
@ -145,7 +145,7 @@
"restr_name = widg.Label(value = 'PAAR',layout=widg.Layout(width='95%', grid_area='restr_name'))\n",
"restr = widg.ToggleButtons(options=[('.',False), ('..',True)], value = False, description='',icons = ['ban','check'], layout=widg.Layout(width='95%', grid_area='camera_set2'),style = {'description_width': '80px','button_width': '48%', 'font_weight': 'bold'}, button_style='')\n",
"binning_name = widg.Label(value = 'Binning',layout=widg.Layout(width='95%', grid_area='binning_name'))\n",
"binning = widg.ToggleButtons(options=[('.',1), ('2',2), ('4',4), ('8',8), ('16',16), ('32',32), ('48',48)], value=1, description='', icons = ['ban','',''], layout=widg.Layout(width='95%', grid_area='camera_set3'), **ali3)\n",
"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",
"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",
@ -159,7 +159,7 @@
"\n",
"### Visualisation\n",
"visual_set = widg.Button(description='Visualisation',layout=widg.Layout(width='95%', grid_area='visual_set'),style=widg.ButtonStyle(button_color='white', font_weight= 'bold',font_size= '16px',text_color='black'),disabled = False)\n",
"name1 = widg.Button(description='Graphs (%)',layout=widg.Layout(width='95%', grid_area='name1'),style=widg.ButtonStyle(button_color='white', font_weight= 'bold',text_color='black'), disabled = False)\n",
"name1 = widg.Button(description='Scale (%)',layout=widg.Layout(width='95%', grid_area='name1'),style=widg.ButtonStyle(button_color='white', font_weight= 'bold',text_color='black'), disabled = False)\n",
"graph_size = widg.IntSlider(value=100,min=75,max=125,step=5, description='', layout=widg.Layout(width='95%', grid_area='gr_size2'), button_style='primary',disabled=False,)\n",
"\n",
"### Layout\n",
@ -189,6 +189,7 @@
"\n",
"### GRAPH CONTROL\n",
"style = {'description_width': 'initial'}\n",
"style2 = {'description_width': '200px'}\n",
"top_set = widg.Button(description='',layout=widg.Layout(width='%', grid_area='scanning_set'), style=widg.ButtonStyle(button_color='white', font_weight= 'bold',font_size= '16px',text_color='#0d48a1'),disabled = True)\n",
"style_graph = widg.ButtonStyle(button_color='#F5F5F5', font_weight= 'bold',font_size= '16px',text_color='black')\n",
"\n",
@ -201,33 +202,37 @@
"### Sample\n",
"sample_set = widg.Button(description='Sample',layout=widg.Layout(width='100%', grid_area='sample_set'), style=style_graph, disabled = True)\n",
"overlap_fig = widg.ToggleButtons(options=['Geometrical','Ilumination'], layout=widg.Layout(grid_area='overlap_fig'), style = {'button_width': '45%'}, disabled=False)\n",
"fov_show = widg.FloatSlider(value=0.3, min=0.1, max=10, step=0.1, description='FoV (nm):', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='.1f', layout=widg.Layout(grid_area='fov_show', width = '100%'))\n",
"beam_pos = widg.IntSlider(value=4, min=4, max=100, step=2, description='Add beams:', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d', layout=widg.Layout(grid_area='beam_pos', width = '100%'))\n",
"red_box = widg.Dropdown(options=[('tiny', 0.1), ('small', 0.2), ('middle', 0.3), ('large', 0.4), ('whole', 0.5)], value=0.1, description='Uniformity box', layout=widg.Layout(grid_area='red_box', width = '95%'),style=style)\n",
"box_col = widg.ColorPicker(concise=False, description='', value='cyan', disabled=False, layout=widg.Layout(grid_area='box_col', width = '85%'),)\n",
"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",
"\n",
"### Camera length based limitations and checks\n",
"cl_set = widg.Button(description='Camera length based limitations and checks', layout=widg.Layout(width='100%', grid_area='cl_set'), style=style_graph, disabled = True)\n",
"check0name = widg.IntRangeSlider(value=[1,6],min=0, max=10,step=1, description='Detector cover (α):', disabled=False, continuous_update=False, orientation='horizontal',readout=True, readout_format='d',layout=widg.Layout(grid_area='check0name', width = '100%'),style=style)\n",
"check1name = widg.IntSlider(value=10,min=0,max=20,step=5,description='Low angle approx. (°):', disabled=False,continuous_update=False,orientation='horizontal',readout=True,readout_format='d',layout=widg.Layout(grid_area='check1name', width = '100%'),style=style)\n",
"check2name = widg.Checkbox(value=False,description='Resolution gain (ITR)',disabled=False, indent=False,layout=widg.Layout(grid_area='check2name'))\n",
"check3name = widg.Checkbox(value=True, description='Recon. box coverage (ITR)',disabled=False, indent=False,layout=widg.Layout(grid_area='check3name'))\n",
"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",
"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 (ITR)', disabled=False,continuous_update=False,orientation='horizontal',readout=True, readout_format='d', layout=widg.Layout(grid_area='check6name', 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],\n",
" layout=widg.Layout(width='109%', grid_template_rows='35px 35px 35px 35px 5px', grid_template_columns='4% 3.5% 14% 1.5% 8% 8% 8% 1% 26% 14%', grid_template_areas='''\n",
" \". ctf_set ctf_set . sample_set overlap_fig overlap_fig . cl_set cl_set \" \n",
" \". ctf_xaxis_name ctxaxis . fov_show fov_show fov_show . check0name check2name \"\n",
" \". ctf_element ctf_element . beam_pos beam_pos beam_pos . check4name check3name \"\n",
" \". . . . red_box red_box box_col . check1name check6name \"\n",
" \". . . . . . . . . . \"'''))\n",
"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",
"\n",
"def ptycho_interact(beam_energy, aperture, aperture_res, aperture_res2, probe_size, cl, matrix, defocus, mag, camera, binning, dwell_time, restr, method,\n",
" ctf_xaxis, element, graph_size, beam_pos, fov_show, overlap_fig, red_box, box_col, check0name, check1name, check2name, check3name, check4name, check6name):\n",
" ctf_xaxis, element, graph_size, beam_pos, fov_show, overlap_fig, red_box, box_col, check0name, check1name, check2name, check3name, check4name, check6name, prof_show):\n",
"\n",
" fov = pty.get_fov(mag) \n",
" pctf_itr = pty.get_ctf(element)\n",
@ -365,20 +370,21 @@
" 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",
" wid = np.linspace(-beam_pos/2,beam_pos/2,beam_pos+1)*step_size_corr\n",
" yyy = np.append(np.linspace(0,overlap,100),200)\n",
" \n",
" fig1 = make_subplots(specs=[[{\"secondary_y\": True}]])\n",
" fig1 = 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_yaxes(title_text=\"Overlap \"+str(np.round(overlap,1))+\" %\", range=[-fov_show/2, fov_show/2],showgrid=False, showticklabels=False)\n",
" \n",
" for x in range(len(wid)): \n",
" fig1.add_trace(go.Scatter(showlegend=False, x=wid, y=np.ones(len(wid))*wid[x], marker_color='black'),secondary_y=False)\n",
" fig1.add_trace(go.Scatter(showlegend=False, x=wid, y=np.ones(len(wid))*wid[x], marker_color='black'))\n",
" for y in range(len(wid)): \n",
" fig1.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.1, fillcolor=\"#FF7F7F\",name=False, x0=wid[x]-beam_diameter/2, y0=wid[y]-beam_diameter/2, x1=wid[x]+beam_diameter/2, y1=wid[y]+beam_diameter/2, line_color=\"red\",secondary_y=False)\n",
" fig1.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.1, fillcolor=\"#FF7F7F\",name=False, x0=wid[x]-beam_diameter/2, y0=wid[y]-beam_diameter/2, x1=wid[x]+beam_diameter/2, y1=wid[y]+beam_diameter/2, line_color=\"red\")\n",
" \n",
" fig1.add_annotation(x=-1*step_size_corr, y=-2*step_size_corr, ax=-2*step_size_corr, ay=-2*step_size_corr, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='red')\n",
" fig1.add_annotation(x=-2*step_size_corr, y=-1*step_size_corr, ax=-2*step_size_corr, ay=-2*step_size_corr, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='red')\n",
@ -393,12 +399,10 @@
" fig1.add_trace(go.Scatter(showlegend=True, x=[-100], y=[-100],marker_size=12, marker_color='green', name='Rec step '+str(np.round(xx[-1]/3,2))+' Å')) \n",
" fig1.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.0,xanchor=\"right\",x=0.9))\n",
"\n",
" fig1.add_trace(go.Scatter(showlegend=False, x = -fov_show/2*np.ones(len(yyy)), y=yyy, opacity=1,mode='markers',marker_symbol = \"triangle-down\",marker=dict(size=20, color=yyy, colorscale='rainbow_r', showscale=False)),secondary_y=True) \n",
" fig1.update_yaxes(range=[0, 100], showgrid=False, showticklabels=False, secondary_y=True)\n",
" fig1.update_yaxes(title_text=\"Overlap (%)\", showgrid=False, showticklabels=True, tickvals = [-fov_show/2, -fov_show/4, 0, fov_show/4, fov_show/2],ticktext = ['0', '25', '50', '75', '100'], secondary_y=False)\n",
" fig1.update_layout(plot_bgcolor='white', legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.9))\n",
" fig1.update_xaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
" fig1.update_yaxes(mirror=True,ticks='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
" fig1.update_yaxes(mirror=True,ticks='',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
" \n",
"\n",
" match method: \n",
" case 'ssb':\n",
@ -415,7 +419,8 @@
" sys.stdout = io.StringIO() # create a text trap and redirect stdout\n",
" probe = Probe(sampling = sampling, extent = 2*beam_diameter*10, energy = beam_energy*1e3, semiangle_cutoff = semi_angle_corr, defocus = defocus*10) # sampling=sampling, extent=A , energy=beam*1e3eV, semiangle_cutoff=mrad, defocus=A)\n",
" intensity = probe.build().intensity().compute()\n",
" intensity = np.abs(intensity.array)\n",
" intensity = np.square(intensity.array)\n",
" intensity = np.abs(intensity)\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",
@ -436,7 +441,7 @@
" fig1.add_trace(px.imshow(field).data[0])\n",
" fig1.add_shape(type=\"rect\",x0= field_cen-red_box*field_size, y0=field_cen-red_box*field_size, x1= field_cen+red_box*field_size, y1=field_cen+red_box*field_size,line=dict(color=box_col))\n",
" fig1.update_layout(title={'text': \"Uniformity: \"+str(np.round(uniformity,1))+\"%\",'y':0.85, 'x':0.3,'xanchor': 'left','yanchor': 'top'})\n",
" fig1.update_traces(dict(showscale=False, coloraxis=None, colorscale='plasma'), selector={'type':'heatmap'})\n",
" fig1.update_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",
@ -575,7 +580,7 @@
" fig3.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=opacity[i], fillcolor=color, x0=probe_window/2-beam_diameter/xcoef[i], y0=probe_window/2-beam_diameter/xcoef[i], \n",
" x1=probe_window/2+beam_diameter/xcoef[i], y1=probe_window/2+beam_diameter/xcoef[i], line_color=color)\n",
" \n",
" fig3.update_xaxes(title_text=\"Reconstruction box (nm)\", range=[0, probe_window], tickvals = [0, probe_window/4, probe_window/2, 3*probe_window/4, probe_window], ticktext = [0, np.round(probe_window/4,2),np.round(probe_window/2,2),np.round(3*probe_window/4,2),np.round(probe_window,2)])\n",
" fig3.update_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",
@ -589,6 +594,7 @@
" # 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",
" \n",
" cen2 = intensity3.shape\n",
" sirkaA = cen2[0]*sampling\n",
" sirkaB = np.round(probe_window,2)*10/sampling\n",
@ -599,14 +605,16 @@
"\n",
" fig3 = go.Figure() \n",
" fig3.add_trace(px.imshow(intensity3).data[0])\n",
" fig3.add_trace(go.Scatter(x=np.linspace(0,int(cen2[0])-1,len(cross_section)), y=int(cen2[0]/4)+cross_section*int(cen2[0]/2), showlegend=False, marker_color=\"white\", opacity = 0.7))\n",
" 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",
" fig3.add_shape(type=\"rect\",x0= cen2[0]/2-sirkaB/2, y0=cen2[0]/2-sirkaB/2, x1= cen2[1]/2+sirkaB/2, y1=cen2[1]/2+sirkaB/2, line=dict(color=\"red\"))\n",
" fig3.update_layout(title={'text': \"Probe cover \",'y':0.85, 'x':0.3,'xanchor': 'left','yanchor': 'top'})\n",
" fig3.update_traces(dict(showscale=False, coloraxis=None, colorscale='plasma'), selector={'type':'heatmap'})\n",
" fig3.update_xaxes(showticklabels=False).update_yaxes(showticklabels=False)\n",
" fig3.add_annotation(x=cen2[0]/2, y=cen2[0]/2+sirkaB/2, text='Recon. box '+str(np.round(probe_window,2))+' nm', showarrow=False, yshift=15)\n",
" fig3.add_annotation(x=cen2[0]/2, y=cen2[0]/2-sirkaB/2, text='Probe covered '+str(np.round(int_tot,1))+' %', showarrow=False, yshift=-15)\n",
" fig3.update_annotations(font=dict(color=\"white\"))\n",
" fig3.update_layout(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",
" else:\n",
" fig3 = go.Figure() \n",
@ -631,32 +639,35 @@
" data = tab[:,int(i)] # 0.cl, 1. ptycho pix xy, 2. ptycho pix z, 3.det cov, 4.det cov a, 5.max def, 6.probe window, 7.oversampling\n",
" \n",
" if cl == data[0]:\n",
" icons=['hand-point-left','','','','','',''] \n",
" if check2name == True and data[1] > step_size_corr*10: # check2name = 'Ptycho pixel < step size'\n",
" icons=['','bell','','','','',''] \n",
" icons[0]= \"hand-point-left\"\n",
" \n",
" if data[1] > step_size_corr*10/check2name: # check2name = 'Ptycho pixel < step size'\n",
" icons[1]= \"bell\"\n",
" button_style = 'warning'\n",
" \n",
" if data[3] > 1000*np.radians(check1name): # check1name = 'Low anlge approximation'\n",
" icons=['','','','bell','','',''] \n",
" icons[3]= \"bell\"\n",
" button_style = 'warning' \n",
" \n",
" if data[4] < check0name[0] or data[4] > check0name[1]: # 'Detector cover'\n",
" icons=['','','','','bell','',''] \n",
" icons[4]= \"bell\"\n",
" button_style = 'warning'\n",
" if check3name == True and beam_diameter > data[5]/2 and beam_diameter < data[5]:\n",
" icons=['','','','','','bell',''] \n",
" \n",
" if beam_diameter > check3name/100*data[5]:\n",
" icons[5]= \"bell\"\n",
" button_style = 'warning'\n",
" if check3name == True and beam_diameter > data[5]:\n",
" icons=['','','','','','ban',''] \n",
" button_style = 'danger'\n",
" \n",
" if data[6] < 1: # check6name = 'Sampling > 1' \n",
" icons=['','','','','','','ban'] \n",
" icons[6]= \"ban\"\n",
" \n",
" button_style = 'danger' \n",
" if data[6] > 1 and data[6] < int(check6name): # check6name = 'Sampling > check6name' \n",
" icons=['','','','','','','bell'] \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 (Å)','Resolution Z (Å)', 'Detector cover (mrad)','Detector cover (α)', 'Reconstr. box (nm)', 'Overall sampling'],\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",
" \n",
" # FIX here\n",
@ -690,7 +701,7 @@
" ### SHOWING\n",
" match method: \n",
" case 'ssb':\n",
" right = widg.VBox([go.FigureWidget(fig1),go.FigureWidget(fig4)])\n",
" right = widg.VBox([go.FigureWidget(fig1), go.FigureWidget(fig4)])\n",
" case 'iterative':\n",
" right = widg.VBox([widg.HBox([go.FigureWidget(fig1),go.FigureWidget(fig3)]), cltab, checks])\n",
"\n",
@ -703,7 +714,7 @@
"gui = widg.interactive_output(ptycho_interact, {\"beam_energy\" : beam_energy, \"aperture\": aperture, \"aperture_res\": aperture_res, \"aperture_res2\": aperture_res2, \"probe_size\": probe_size, \"cl\": cl, \"matrix\": matrix,\n",
" \"defocus\": defocus, \"mag\": mag, \"camera\": camera, \"binning\": binning, \"dwell_time\" : dwell_time, \"restr\": restr, \"method\": method, \"ctf_xaxis\": ctf_xaxis, \"element\": element,\n",
" \"graph_size\": graph_size, \"beam_pos\": beam_pos, \"fov_show\": fov_show, \"overlap_fig\" :overlap_fig, \"red_box\": red_box, \"box_col\":box_col, \"check0name\":check0name, \n",
" \"check1name\": check1name, \"check2name\": check2name, \"check3name\": check3name, \"check4name\": check4name, \"check6name\": check6name}) \n",
" \"check1name\": check1name, \"check2name\": check2name, \"check3name\": check3name, \"check4name\": check4name, \"check6name\": check6name, \"prof_show\":prof_show}) \n",
"\n",
"ptychoscopy = widg.VBox([top_set, widg.HBox([controls, widg.VBox([graph_controls, gui])])])\n"
]

View File

@ -40,14 +40,20 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 359,
"id": "5c5feaae-861c-4277-9dd5-aee373b3c174",
"metadata": {},
"metadata": {
"editable": true,
"slideshow": {
"slide_type": ""
},
"tags": []
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "37bb53443b8a4d50bb614d7156907632",
"model_id": "a761f00de7e946deadcb8d2324fd5a26",
"version_major": 2,
"version_minor": 0
},
@ -60,7 +66,9 @@
}
],
"source": [
"display(ptychoscopy)"
"display(ptychoscopy)\n",
"\n",
"\n"
]
},
{
@ -73,7 +81,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 358,
"id": "fecbecdb-0fac-4ac8-a2b3-1ccb3f869a77",
"metadata": {},
"outputs": [],
@ -127,7 +135,7 @@
"beam_set = widg.Button(description='Electron beam settings',layout=widg.Layout(width='95%',grid_area='beam_set'),style=widg.ButtonStyle(button_color='#222261',font_weight='bold',font_size='16px',text_color='white'),disabled=False) \n",
"beam_energy = widg.Dropdown(options=pty.load_energies(), value=200, description='Beam energy (keV)', layout=widg.Layout(width='95%', grid_area='beam_set1'), **ali)\n",
"probe_size = widg.Dropdown(options=pty.load_probes(), value='8C', description='Probe', layout=widg.Layout(width='95%', grid_area='beam_set3'), **ali)\n",
"defocus = widg.FloatSlider(description='Defocus (nm)', value=0, min=0, max=1000, step=5, readout_format='d',continuous_update=False, layout=widg.Layout(width='95%', grid_area='beam_set4'), **ali)\n",
"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",
"aperture_name = widg.Label(value = 'Aperture', layout=widg.Layout(width='95%', grid_area='aperture_name'),)\n",
"aperture = widg.ToggleButtons(options=pty.load_apertures(), description='', layout=widg.Layout(width='95%', grid_area='beam_set2'), **ali3)\n",
"\n",
@ -145,7 +153,7 @@
"restr_name = widg.Label(value = 'PAAR',layout=widg.Layout(width='95%', grid_area='restr_name'))\n",
"restr = widg.ToggleButtons(options=[('.',False), ('..',True)], value = False, description='',icons = ['ban','check'], layout=widg.Layout(width='95%', grid_area='camera_set2'),style = {'description_width': '80px','button_width': '48%', 'font_weight': 'bold'}, button_style='')\n",
"binning_name = widg.Label(value = 'Binning',layout=widg.Layout(width='95%', grid_area='binning_name'))\n",
"binning = widg.ToggleButtons(options=[('.',1), ('2',2), ('4',4), ('8',8), ('16',16), ('32',32), ('48',48)], value=1, description='', icons = ['ban','',''], layout=widg.Layout(width='95%', grid_area='camera_set3'), **ali3)\n",
"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",
"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",
@ -159,7 +167,7 @@
"\n",
"### Visualisation\n",
"visual_set = widg.Button(description='Visualisation',layout=widg.Layout(width='95%', grid_area='visual_set'),style=widg.ButtonStyle(button_color='white', font_weight= 'bold',font_size= '16px',text_color='black'),disabled = False)\n",
"name1 = widg.Button(description='Graphs (%)',layout=widg.Layout(width='95%', grid_area='name1'),style=widg.ButtonStyle(button_color='white', font_weight= 'bold',text_color='black'), disabled = False)\n",
"name1 = widg.Button(description='Scale (%)',layout=widg.Layout(width='95%', grid_area='name1'),style=widg.ButtonStyle(button_color='white', font_weight= 'bold',text_color='black'), disabled = False)\n",
"graph_size = widg.IntSlider(value=100,min=75,max=125,step=5, description='', layout=widg.Layout(width='95%', grid_area='gr_size2'), button_style='primary',disabled=False,)\n",
"\n",
"### Layout\n",
@ -189,6 +197,7 @@
"\n",
"### GRAPH CONTROL\n",
"style = {'description_width': 'initial'}\n",
"style2 = {'description_width': '200px'}\n",
"top_set = widg.Button(description='',layout=widg.Layout(width='%', grid_area='scanning_set'), style=widg.ButtonStyle(button_color='white', font_weight= 'bold',font_size= '16px',text_color='#0d48a1'),disabled = True)\n",
"style_graph = widg.ButtonStyle(button_color='#F5F5F5', font_weight= 'bold',font_size= '16px',text_color='black')\n",
"\n",
@ -200,34 +209,38 @@
"\n",
"### Sample\n",
"sample_set = widg.Button(description='Sample',layout=widg.Layout(width='100%', grid_area='sample_set'), style=style_graph, disabled = True)\n",
"overlap_fig = widg.ToggleButtons(options=['Geometrical','Ilumination'], layout=widg.Layout(grid_area='overlap_fig'), style = {'button_width': '45%'}, disabled=False)\n",
"fov_show = widg.FloatSlider(value=0.3, min=0.1, max=10, step=0.1, description='FoV (nm):', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='.1f', layout=widg.Layout(grid_area='fov_show', width = '100%'))\n",
"beam_pos = widg.IntSlider(value=4, min=4, max=100, step=2, description='Add beams:', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d', layout=widg.Layout(grid_area='beam_pos', width = '100%'))\n",
"red_box = widg.Dropdown(options=[('tiny', 0.1), ('small', 0.2), ('middle', 0.3), ('large', 0.4), ('whole', 0.5)], value=0.1, description='Uniformity box', layout=widg.Layout(grid_area='red_box', width = '95%'),style=style)\n",
"box_col = widg.ColorPicker(concise=False, description='', value='cyan', disabled=False, layout=widg.Layout(grid_area='box_col', width = '85%'),)\n",
"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",
"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",
"\n",
"### Camera length based limitations and checks\n",
"cl_set = widg.Button(description='Camera length based limitations and checks', layout=widg.Layout(width='100%', grid_area='cl_set'), style=style_graph, disabled = True)\n",
"check0name = widg.IntRangeSlider(value=[1,6],min=0, max=10,step=1, description='Detector cover (α):', disabled=False, continuous_update=False, orientation='horizontal',readout=True, readout_format='d',layout=widg.Layout(grid_area='check0name', width = '100%'),style=style)\n",
"check1name = widg.IntSlider(value=10,min=0,max=20,step=5,description='Low angle approx. (°):', disabled=False,continuous_update=False,orientation='horizontal',readout=True,readout_format='d',layout=widg.Layout(grid_area='check1name', width = '100%'),style=style)\n",
"check2name = widg.Checkbox(value=False,description='Resolution gain (ITR)',disabled=False, indent=False,layout=widg.Layout(grid_area='check2name'))\n",
"check3name = widg.Checkbox(value=True, description='Recon. box coverage (ITR)',disabled=False, indent=False,layout=widg.Layout(grid_area='check3name'))\n",
"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",
"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 (ITR)', disabled=False,continuous_update=False,orientation='horizontal',readout=True, readout_format='d', layout=widg.Layout(grid_area='check6name', 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],\n",
" layout=widg.Layout(width='109%', grid_template_rows='35px 35px 35px 35px 5px', grid_template_columns='4% 3.5% 14% 1.5% 8% 8% 8% 1% 26% 14%', grid_template_areas='''\n",
" \". ctf_set ctf_set . sample_set overlap_fig overlap_fig . cl_set cl_set \" \n",
" \". ctf_xaxis_name ctxaxis . fov_show fov_show fov_show . check0name check2name \"\n",
" \". ctf_element ctf_element . beam_pos beam_pos beam_pos . check4name check3name \"\n",
" \". . . . red_box red_box box_col . check1name check6name \"\n",
" \". . . . . . . . . . \"'''))\n",
"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='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",
" \". . . . . . . . . . . \"''')) \n",
"\n",
"def ptycho_interact(beam_energy, aperture, aperture_res, aperture_res2, probe_size, cl, matrix, defocus, mag, camera, binning, dwell_time, restr, method,\n",
" ctf_xaxis, element, graph_size, beam_pos, fov_show, overlap_fig, red_box, box_col, check0name, check1name, check2name, check3name, check4name, check6name):\n",
" ctf_xaxis, element, graph_size, beam_pos, fov_show, overlap_fig, red_box, box_col, check0name, check1name, check2name, check3name, check4name, check6name, prof_show):\n",
"\n",
" fov = pty.get_fov(mag) \n",
" pctf_itr = pty.get_ctf(element)\n",
@ -365,20 +378,21 @@
" 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 = make_subplots(specs=[[{\"secondary_y\": True}]])\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",
" \n",
" for x in range(len(wid)): \n",
" fig1.add_trace(go.Scatter(showlegend=False, x=wid, y=np.ones(len(wid))*wid[x], marker_color='black'),secondary_y=False)\n",
" fig1.add_trace(go.Scatter(showlegend=False, x=wid, y=np.ones(len(wid))*wid[x], marker_color='black'))\n",
" for y in range(len(wid)): \n",
" fig1.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.1, fillcolor=\"#FF7F7F\",name=False, x0=wid[x]-beam_diameter/2, y0=wid[y]-beam_diameter/2, x1=wid[x]+beam_diameter/2, y1=wid[y]+beam_diameter/2, line_color=\"red\",secondary_y=False)\n",
" fig1.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=0.1, fillcolor=\"#FF7F7F\",name=False, x0=wid[x]-beam_diameter/2, y0=wid[y]-beam_diameter/2, x1=wid[x]+beam_diameter/2, y1=wid[y]+beam_diameter/2, line_color=\"red\")\n",
" \n",
" fig1.add_annotation(x=-1*step_size_corr, y=-2*step_size_corr, ax=-2*step_size_corr, ay=-2*step_size_corr, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='red')\n",
" fig1.add_annotation(x=-2*step_size_corr, y=-1*step_size_corr, ax=-2*step_size_corr, ay=-2*step_size_corr, xref='x',yref='y',axref='x',ayref='y',text='', showarrow=True,arrowhead=2,arrowsize=2,arrowwidth=1,arrowcolor='red')\n",
@ -390,42 +404,48 @@
" 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.add_trace(go.Scatter(showlegend=True, x=(0,0), y=(0,0),marker_size=12, marker_color='green', name='<b>Recom. step '+str(np.round(xx[-1]/3,2))+' Å<b>', opacity = 0)) \n",
" fig1.update_layout(legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.0,xanchor=\"right\",x=0.9))\n",
"\n",
" fig1.add_trace(go.Scatter(showlegend=False, x = -fov_show/2*np.ones(len(yyy)), y=yyy, opacity=1,mode='markers',marker_symbol = \"triangle-down\",marker=dict(size=20, color=yyy, colorscale='rainbow_r', showscale=False)),secondary_y=True) \n",
" fig1.update_yaxes(range=[0, 100], showgrid=False, showticklabels=False, secondary_y=True)\n",
" fig1.update_yaxes(title_text=\"Overlap (%)\", showgrid=False, showticklabels=True, tickvals = [-fov_show/2, -fov_show/4, 0, fov_show/4, fov_show/2],ticktext = ['0', '25', '50', '75', '100'], secondary_y=False)\n",
" fig1.update_layout(plot_bgcolor='white', legend=dict(orientation=\"v\",yanchor=\"bottom\",y=1.01,xanchor=\"right\",x=0.9))\n",
" fig1.update_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='inside',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
"\n",
" fig1.update_yaxes(mirror=True,ticks='',showline=True,linecolor='black',gridcolor='lightgrey',title_font_color=\"#000000\")\n",
" fig1.add_trace(go.Scatter(x=(0,0), y=(0,0), name='<b>Overlap '+str(np.round(overlap,1))+' %<b>', showlegend=True, opacity = 0))\n",
" \n",
" match method: \n",
" case 'ssb':\n",
" 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",
" \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",
" 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",
" 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",
"\n",
" case 'Ilumination':\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.abs(intensity.array)\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",
@ -433,17 +453,20 @@
" 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_layout(title={'text': \"Uniformity: \"+str(np.round(uniformity,1))+\"%\",'y':0.85, 'x':0.3,'xanchor': 'left','yanchor': 'top'})\n",
" fig1.update_traces(dict(showscale=False, coloraxis=None, colorscale='plasma'), selector={'type':'heatmap'})\n",
" fig1.update_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.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(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",
" 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(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",
@ -556,7 +579,7 @@
"\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",
@ -569,44 +592,52 @@
"\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 recom. Δf '+str(np.round(max_defocus,1))+' nm', showlegend=True, marker_color=color, opacity = 0))\n",
"\n",
" for i in range(0, len(opacity)):\n",
" fig3.add_shape(type=\"circle\",xref=\"x\", yref=\"y\", opacity=opacity[i], fillcolor=color, x0=probe_window/2-beam_diameter/xcoef[i], y0=probe_window/2-beam_diameter/xcoef[i], \n",
" x1=probe_window/2+beam_diameter/xcoef[i], y1=probe_window/2+beam_diameter/xcoef[i], line_color=color)\n",
" \n",
" fig3.update_xaxes(title_text=\"Reconstruction box (nm)\", range=[0, probe_window], tickvals = [0, probe_window/4, probe_window/2, 3*probe_window/4, probe_window], ticktext = [0, np.round(probe_window/4,2),np.round(probe_window/2,2),np.round(3*probe_window/4,2),np.round(probe_window,2)])\n",
" fig3.update_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",
"\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",
" cen2 = intensity3.shape\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 = 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(go.Scatter(x=np.linspace(0,int(cen2[0])-1,len(cross_section)), y=int(cen2[0]/4)+cross_section*int(cen2[0]/2), showlegend=False, marker_color=\"white\", opacity = 0.7))\n",
" fig3.add_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",
" 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_layout(title={'text': \"Probe cover \",'y':0.85, 'x':0.3,'xanchor': 'left','yanchor': 'top'})\n",
" fig3.update_traces(dict(showscale=False, coloraxis=None, colorscale='plasma'), selector={'type':'heatmap'})\n",
" fig3.update_xaxes(showticklabels=False).update_yaxes(showticklabels=False)\n",
" fig3.add_annotation(x=cen2[0]/2, y=cen2[0]/2+sirkaB/2, text='Recon. box '+str(np.round(probe_window,2))+' nm', showarrow=False, yshift=15)\n",
" fig3.add_annotation(x=cen2[0]/2, y=cen2[0]/2-sirkaB/2, text='Probe covered '+str(np.round(int_tot,1))+' %', showarrow=False, yshift=-15)\n",
" fig3.update_annotations(font=dict(color=\"white\"))\n",
" fig3.update_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_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",
" else:\n",
" fig3 = go.Figure() \n",
@ -631,32 +662,35 @@
" data = tab[:,int(i)] # 0.cl, 1. ptycho pix xy, 2. ptycho pix z, 3.det cov, 4.det cov a, 5.max def, 6.probe window, 7.oversampling\n",
" \n",
" if cl == data[0]:\n",
" icons=['hand-point-left','','','','','',''] \n",
" if check2name == True and data[1] > step_size_corr*10: # check2name = 'Ptycho pixel < step size'\n",
" icons=['','bell','','','','',''] \n",
" icons[0]= \"hand-point-left\"\n",
" \n",
" if data[1] > step_size_corr*10/check2name: # check2name = 'Ptycho pixel < step size'\n",
" icons[1]= \"bell\"\n",
" button_style = 'warning'\n",
" \n",
" if data[3] > 1000*np.radians(check1name): # check1name = 'Low anlge approximation'\n",
" icons=['','','','bell','','',''] \n",
" icons[3]= \"bell\"\n",
" button_style = 'warning' \n",
" \n",
" if data[4] < check0name[0] or data[4] > check0name[1]: # 'Detector cover'\n",
" icons=['','','','','bell','',''] \n",
" icons[4]= \"bell\"\n",
" button_style = 'warning'\n",
" if check3name == True and beam_diameter > data[5]/2 and beam_diameter < data[5]:\n",
" icons=['','','','','','bell',''] \n",
" \n",
" if beam_diameter > check3name/100*data[5]:\n",
" icons[5]= \"bell\"\n",
" button_style = 'warning'\n",
" if check3name == True and beam_diameter > data[5]:\n",
" icons=['','','','','','ban',''] \n",
" button_style = 'danger'\n",
" \n",
" if data[6] < 1: # check6name = 'Sampling > 1' \n",
" icons=['','','','','','','ban'] \n",
" icons[6]= \"ban\"\n",
" \n",
" button_style = 'danger' \n",
" if data[6] > 1 and data[6] < int(check6name): # check6name = 'Sampling > check6name' \n",
" icons=['','','','','','','bell'] \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 (Å)','Resolution Z (Å)', 'Detector cover (mrad)','Detector cover (α)', 'Reconstr. box (nm)', 'Overall sampling'],\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",
" \n",
" # FIX here\n",
@ -690,7 +724,7 @@
" ### SHOWING\n",
" match method: \n",
" case 'ssb':\n",
" right = widg.VBox([go.FigureWidget(fig1),go.FigureWidget(fig4)])\n",
" right = widg.VBox([go.FigureWidget(fig1), go.FigureWidget(fig4)])\n",
" case 'iterative':\n",
" right = widg.VBox([widg.HBox([go.FigureWidget(fig1),go.FigureWidget(fig3)]), cltab, checks])\n",
"\n",
@ -703,7 +737,7 @@
"gui = widg.interactive_output(ptycho_interact, {\"beam_energy\" : beam_energy, \"aperture\": aperture, \"aperture_res\": aperture_res, \"aperture_res2\": aperture_res2, \"probe_size\": probe_size, \"cl\": cl, \"matrix\": matrix,\n",
" \"defocus\": defocus, \"mag\": mag, \"camera\": camera, \"binning\": binning, \"dwell_time\" : dwell_time, \"restr\": restr, \"method\": method, \"ctf_xaxis\": ctf_xaxis, \"element\": element,\n",
" \"graph_size\": graph_size, \"beam_pos\": beam_pos, \"fov_show\": fov_show, \"overlap_fig\" :overlap_fig, \"red_box\": red_box, \"box_col\":box_col, \"check0name\":check0name, \n",
" \"check1name\": check1name, \"check2name\": check2name, \"check3name\": check3name, \"check4name\": check4name, \"check6name\": check6name}) \n",
" \"check1name\": check1name, \"check2name\": check2name, \"check3name\": check3name, \"check4name\": check4name, \"check6name\": check6name, \"prof_show\":prof_show}) \n",
"\n",
"ptychoscopy = widg.VBox([top_set, widg.HBox([controls, widg.VBox([graph_controls, gui])])])\n"
]

View File

@ -0,0 +1,506 @@
#!/usr/bin/env python3
### Packages import
import numpy as np
from copy import deepcopy
from pandas import read_excel
import scipy.constants as cons
from ptychoscopy import pty
def get_versions():
"""
--------------------------------------------------------------
Show versions of the used packages.
--------------------------------------------------------------
Inputs:
none
"""
import sys
print (sys.version)
import openpyxl
print("Openpyxl version ", openpyxl.__version__)
import numpy as np
print("Numpy version ", np.__version__)
import scipy
print("Scipy version ", scipy.__version__)
import plotly
print("Plotly version ", plotly.__version__)
import pandas
print("Pandas version ", pandas.__version__)
import IPython
print("IPython version ", IPython.__version__)
import ipywidgets
print("Ipywidgets version ", ipywidgets.__version__)
try:
import abtem
print("abTEM version ", abtem.__version__)
except:
print("abTEM not available ")
return
def get_omegas():
"""
--------------------------------------------------------------------
Loads x-axis in multiplications of probe semi-angle for iterative
CTF curves from sheet called "CTF" ("CTF" row).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='CTF')
excel_lin = list((excel_data[excel_data.CTF.isin(["CTF"])]))
omegas = excel_lin[1::]
return omegas
def get_ctf(element):
"""
--------------------------------------------------------------------
Loads iterative CTF curve for chosen element from sheet called "CTF"
("chosen element" row).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
element ... name of the chosen CTF profile
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='CTF', header = 0)
excel_line = np.array(excel_data[excel_data.CTF.isin([element])])
ctf = excel_line[0]
ctf = ctf[1::]
return ctf
def get_wavelength(beam):
"""
--------------------------------------------------------------------
Computes relativistic electron wavelength.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
beam ... beam energy
Outputs:
wavelength ... electron wavelength in m
"""
wavelength = cons.h/np.sqrt(2*cons.electron_mass*cons.elementary_charge*beam*1e3*(1+((cons.elementary_charge*beam*1e3)/(2*cons.electron_mass*cons.speed_of_light**2))))
return wavelength
def get_fov(mag):
"""
--------------------------------------------------------------------
Loads field of view at 1x magnification and computes field of view
at given magnification.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
mag ... image magnification in millions
Outputs:
fov ... field of view in nm
"""
FoVat1x = [str(e) for e in list(read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges').FoVat1x)]
FoVat1x = np.array([x for x in FoVat1x if x != 'nan']).astype(float)
FoVat1x = FoVat1x.item()
fov = FoVat1x/(mag*1e6)
return fov
def get_angle(aperture):
"""
--------------------------------------------------------------------
Loads probe semi-angle of the chosen aperture.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
aperture ... probe defining aperture name
Outputs:
angle ... probe semi-angle in mrad
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes',header=0)
excel_line = excel_data[excel_data.Probe.isin(['SemiAngle'])]
angle = excel_line[aperture]
angle = np.array(angle).item()
return angle
def get_angle_corr(aperture):
"""
--------------------------------------------------------------------
Loads corrected probe semi-angle of the chosen aperture.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
aperture ... probe defining aperture name
Outputs:
angle_corr ... corrected probe semi-angle in mrad
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes',header=0)
excel_line = excel_data[excel_data.Probe.isin(['SemiAngleCorr'])]
angle_corr = excel_line[aperture]
angle_corr = np.array(angle_corr).item()
return angle_corr
def get_current(probe, aperture):
"""
--------------------------------------------------------------------
Loads probe current for chosen probe size and aperture.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
probe ... chosen probe name
aperture ... probe defining aperture name
Outputs:
current ... probe current in pA
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes',header=0)
excel_line = excel_data[excel_data.Probe.isin([probe])]
current = excel_line[aperture]
current = np.array(current).item()
return current
def get_pixel_angle(cl, camera, binning):
"""
--------------------------------------------------------------------
Loads and computes probe current for chosen probe size and aperture.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
cl ... chosen nominal camera length
camera ... chosen camera type
binning... chosen camera binning
Outputs:
pixel_angle ... single pixel cover angle in mrad
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Pixel',header=0)
excel_line = excel_data[excel_data.NominalCL.isin([cl])]
pixel_angle = excel_line[camera]
pixel_angle = np.array(pixel_angle).item()
pixel_angle = pixel_angle*binning
return pixel_angle
def get_cl_detector(cl, detector):
"""
--------------------------------------------------------------------
Loads effective camera length.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
cl ... chosen nominal camera length
detector ... chosen detector type
Outputs:
cl_detector ... efective camera length of detector in cm
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Camera_length')
excel_line = excel_data[excel_data.NominalCL.isin([cl])]
cl_detector = excel_line[detector]
cl_detector = cl_detector.item()
return cl_detector
def get_aq_frec(dwell_time):
"""
--------------------------------------------------------------------
Compute acquisition frame rate from dwell time.
--------------------------------------------------------------------
Inputs:
dwell_time ... beam position dwell time in us
Outputs:
aq_frec ... detection frame rate in kHz
"""
aq_frec = 1000/dwell_time
return aq_frec
def get_step_size(fov, matrix):
"""
--------------------------------------------------------------------
Compute scanning step size.
--------------------------------------------------------------------
Inputs:
matrix ... number of beam positions in scanning matrix
Outputs:
step_size ... detection frame rate in nm
"""
step_size = fov/(matrix-1)
return step_size
def get_step_correction():
"""
--------------------------------------------------------------------
Load scanning correction coefficient.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
Outputs:
step_correction ... scaling factor
"""
step_correction = [str(e) for e in list(read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges').StepSizeCorr)]
step_correction = np.array([x for x in step_correction if x != 'nan']).astype(float)
step_correction = step_correction.item()
return step_correction
def get_beam_diameter(aperture, defocus, angle_corr):
"""
--------------------------------------------------------------------
Computes geometrical beam diameter.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
aperture ... probe defining aperture name
defocus ... introduced beam defocus in nm
Outputs:
beam_diameter ... beam diameter in nm
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes')
excel_line = excel_data[excel_data.Probe.isin(['Def0Diameter'])]
beam_0_diameter = np.array([excel_line[aperture]]).astype(float)
beam_0_diameter = beam_0_diameter.item()
beam_diameter = 2*defocus*np.tan(angle_corr/1000)+beam_0_diameter
return beam_diameter
def get_0beam_diameter(aperture):
"""
--------------------------------------------------------------------
Computes geometrical beam diameter at 0 nm defocus.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
aperture ... probe defining aperture name
Outputs:
beam_0_diameter ... beam diameter in nm
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes')
excel_line = excel_data[excel_data.Probe.isin(['Def0Diameter'])]
beam_0_diameter = np.array([excel_line[aperture]]).astype(float)
beam_0_diameter = beam_0_diameter.item()
return beam_0_diameter
def get_detector(camera, binning):
"""
--------------------------------------------------------------------
Loads detection array size toghether with pixel size and computes
effective pixel size (inluding binning).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
camera ... detector name
binning ... applied diffraction pattern binning
Outputs:
num_pixels ... number of pixel in detection array
size_pixel ... detection pixel size in um
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Detector')
excel_line = excel_data[excel_data.Type.isin(['Array'])]
num_pixels = np.array([excel_line[camera]]).astype(float)
num_pixels = num_pixels.item()
num_pixels = num_pixels/binning
excel_line = excel_data[excel_data.Type.isin(['RealSize'])]
size_pixel = excel_line[camera]
size_pixel = size_pixel.item()
size_pixel = size_pixel*binning
return num_pixels, size_pixel
def get_pixel_covers(camera, binning):
"""
--------------------------------------------------------------------
Computes effective single detection pixel cover angle.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
camera ... detector name
binning ... applied diffraction pattern binning
Outputs:
pixel_covers ... effective pixel cover angle in mrad
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Pixel')
pixel_covers = list(excel_data[camera])
pixel_covers = [str(e) for e in pixel_covers]
pixel_covers = [x for x in pixel_covers if x != 'nan']
pixel_covers = [float(e) for e in pixel_covers]
pixel_covers = np.array(pixel_covers)
pixel_covers = pixel_covers*binning
return pixel_covers
def get_pumping_apertures():
"""
--------------------------------------------------------------------
Load differencial pumping aperture caused maximal detection angle
limitation for all camera lengths.
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
Outputs:
pump_apert ... maximal detected angles in mrad for all camera lengths
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Camera_length')
pump_apert = [str(e) for e in list(excel_data.PAAR)]
pump_apert = [x for x in pump_apert if x != 'nan']
pump_apert = [float(e) for e in pump_apert]
return pump_apert
def get_ssb_ctf():
"""
--------------------------------------------------------------------
Computes SSB CTF.
--------------------------------------------------------------------
Inputs:
none
Outputs:
omega ... scattering angle from 0 to 2 alpha
pctf ... ssb ctf
"""
omega = np.linspace(1e-6,2,100)
p = np.arccos(np.minimum(1,omega))
p[np.isnan(p)] = 0
p2 = 1-(omega**2)
p2[p2 <0] = 0
p3 = omega*np.sqrt(p2)
p3[np.isnan(p3)] = 0
pctf = (2/cons.pi)*(np.arccos(omega/2)-p+p3-(omega/2*np.sqrt(1-(omega/2)**2)))
return omega, pctf
def get_cl4ssb(detector_cover_a_all, camera, which):
"""
--------------------------------------------------------------------
Computes maximal camera length for SSB.
--------------------------------------------------------------------
Inputs:
detector_cover_a_all ... detector cover in alfa for all camera lengths
Outputs:
ssb_cl ... maximal recommended camera length
kolik ... covered alfa of minimal detector cover
"""
ssb_cl = deepcopy(detector_cover_a_all)
ssb_cl[ssb_cl<1] = "nan"
ssb_cl = np.nanmin(ssb_cl)
kde = np.array(np.where(ssb_cl == detector_cover_a_all)).item()
kolik = np.array(detector_cover_a_all[kde])
cl_all = load_cameralengths(camera, which)
ssb_cl = np.array(cl_all[kde])
return ssb_cl, kolik
def load_elements():
"""
--------------------------------------------------------------------
Loads names of various phase contrast transfer functions from sheet
called "CTF" ("CTF" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='CTF')
elements = [str(e) for e in list(excel_data.CTF)]
elements = [x for x in elements if x != 'nan']
return elements
def load_apertures():
"""
--------------------------------------------------------------------
Loads aperture names from sheet called "Probes" ("Probe" row).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes')
excel_lin = list((excel_data[excel_data.Probe.isin(["Probe"])]))
apertures = excel_lin[1::]
return apertures
def load_detectors():
"""
--------------------------------------------------------------------
Loads detector names from sheet called "Detector" ("Type" row).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Detector')
excel_lin = list((excel_data[excel_data.Type.isin(["Type"])]))
detectors = excel_lin[1::]
return detectors
def load_probes():
"""
--------------------------------------------------------------------
Loads probe size names from sheet called "Probes" ("Probe" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
probes = list(read_excel(r'ptychoscopy/calibrations.xlsx', sheet_name='Probes').Probe)
probes = probes[3::] # from fifth row
return probes
def load_magnifications():
"""
--------------------------------------------------------------------
Loads list of possible magnifications in millions from sheet called
"Ranges" ("Magnification" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges')
magnifications = list(excel_data.Magnification)
return magnifications
def load_energies():
"""
--------------------------------------------------------------------
Loads list of possible beam energies in keV from sheet called
"Ranges" ("BeamEnergy" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges')
energies = [str(e) for e in list(excel_data.BeamEnergy)]
energies = [x for x in energies if x != 'nan']
energies = [int(float(e)) for e in energies]
return energies
def load_mappings():
"""
--------------------------------------------------------------------
Loads list of possible scanning matricies from sheet called "Ranges"
("Mapping" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges')
mappings = [str(e) for e in list(excel_data.Mapping)]
mappings = [x for x in mappings if x != 'nan']
mappings = [int(float(e)) for e in mappings]
return mappings
def load_dwelltimes():
"""
--------------------------------------------------------------------
Loads list of possible dwell times in us from sheet called "Ranges"
("DwellTime" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Ranges')
dwelltimes = [str(e) for e in list(excel_data.DwellTime)]
dwelltimes = [x for x in dwelltimes if x != 'nan']
dwelltimes = [int(float(e)) for e in dwelltimes]
return dwelltimes
def load_cameralengths(camera, which):
"""
--------------------------------------------------------------------
Loads list of possible nominal camera lengths in cm from sheet
called "Pixel" ("NominalCL" column).
--------------------------------------------------------------------
Inputs:
calib ... path to the calibration file
"""
match which:
case "nominal":
cameralengths = list(read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Camera_length').NominalCL)
case "effective":
excel_data = read_excel(r'ptychoscopy/calibrations.xlsx',sheet_name='Camera_length')
cameralengths = list(np.array(excel_data[camera]))
return cameralengths

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -375,9 +375,6 @@ def get_cl4ssb(detector_cover_a_all, camera, which):
ssb_cl = np.array(cl_all[kde])
return ssb_cl, kolik
def load_elements():
"""
--------------------------------------------------------------------