diff --git a/hp4155/ADU for double gate devices_version_3/double_gate_ADU.py b/hp4155/ADU for double gate devices_version_3/double_gate_ADU.py index 21987ebcc6e783d0db2b874b7dd3daa93dccc2b9..3097116e1a7de2c8f531611bbd7f9d2ef7e47dc3 100644 --- a/hp4155/ADU for double gate devices_version_3/double_gate_ADU.py +++ b/hp4155/ADU for double gate devices_version_3/double_gate_ADU.py @@ -8,111 +8,39 @@ from help import * from measurements import * import configparser -style = {'description_width': 'initial'} -sample = sample() -transfer_check = measurement_check("Transfer") -output_check = measurement_check("Output") -gatediode_check = measurement_check("Gatediode") - -checkboxes = widgets.HBox([transfer_check,output_check,gatediode_check]) -display(checkboxes) - -#transfer - -integration_transfer = integration_time("MEDium") -transfer_gates = gate_selection("VTG","VBG","BOTH SIMULTANEOUSLY","BOTH SEQUENTIALLY") - -Vds_transfer = secondary('VDS',0.05,0.95,1,1e-2) -Vtg_transfer = primary('VTG',-5,0.01,5,1e-3) -Vbg_transfer = primary('VBG',-15,0.1,15,1e-3) -plot_transfer = plot_config(1) -transfer_box = widgets.VBox([integration_transfer,transfer_gates,Vds_transfer.grid,Vtg_transfer.grid,Vbg_transfer.grid,plot_transfer.grid]) - - -#output -integration_output = integration_time("SHORt") -output_gates = gate_selection("VTG","VBG","BOTH") - -Vds_output = primary('VDS',0,0.01,5,1e-2) -Vtg_output = secondary('VTG',-5,2,5,1e-3) -Vbg_output = secondary('VBG',-15,5,15,1e-3) -plot_output = plot_config(2) - -output_box = widgets.VBox([integration_output,output_gates,Vds_output.grid,Vtg_output.grid,Vbg_output.grid,plot_output.grid]) - -integration_gatediode = integration_time("MEDium") -gatediode_gates = gate_selection("VTG","VBG") - -Vg_gatediode=primary('VG',-5,0.05,5,1e-3) -plot_gatediode = plot_config(3) -gatediode_box = widgets.VBox([integration_gatediode,gatediode_gates,Vg_gatediode.grid,plot_gatediode.grid]) - -#the tab widget -children = [transfer_box,output_box,gatediode_box] -titles = ["Transfer","Output","Gatediode"] -tab = widgets.Tab() -tab.children = children -tab.titles = titles - -display(tab) - -button = widgets.Button(description ='Start Measurement') -output = widgets.Output() - -export_ini_button = widgets.Button(description = 'Export as ini') -import_ini_button = widgets.Button(description='Import from ini') - -all_widgets =[transfer_gates,output_gates,button,transfer_check,integration_transfer,output_check,integration_output,gatediode_check,integration_gatediode,gatediode_gates,export_ini_button,import_ini_button] -add_widgets_to_list(sample,all_widgets) -add_widgets_to_list(Vds_transfer,all_widgets) -add_widgets_to_list(Vtg_transfer,all_widgets) -add_widgets_to_list(Vbg_transfer,all_widgets) -add_widgets_to_list(Vds_output,all_widgets) -add_widgets_to_list(Vtg_output,all_widgets) -add_widgets_to_list(Vbg_output,all_widgets) -add_widgets_to_list(Vg_gatediode,all_widgets) -add_widgets_to_list(plot_transfer,all_widgets) -add_widgets_to_list(plot_output,all_widgets) -add_widgets_to_list(plot_gatediode,all_widgets) - - -line = widgets.HBox([button,import_ini_button,export_ini_button]) -display(line,output) +#setup user interface +ui = interface() device = hp4155a.HP4155a('GPIB0::17::INSTR') def on_start_clicked(b): - with output: + with ui.output: clear_output() #disable all widgets - disable_widgets(all_widgets) + change_state(all_widgets) #additional code to check smu configuration fast without modifing a lot of code try: - check_configuration(smu_map) + check_configuration(ui.sample) except Exception as e: error_box(e) - enable_widgets(all_widgets) + change_state(ui.all_widgets) return - Setup(device) #setup the device + #setup the devicr + device.reset() - #for all measurements the same (copy the interface with values for parameter setting) - map = smu_map.copy() - for key,value in map.items(): - map[key]= value.value + #setup sweep measurement mode + device.measurement_mode('SWE') + + #disable all irrelevant units + device.disable_not_smu() - sample_copy = sample.copy() - for key,value in sample_copy.items(): - sample_copy[key]=value.value - smu_s = device.smu_dict() - smu_s.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS') #Source smu is always grounded - if transfer_check.value == True: - plot = plot_transfer.copy() - for key,value in plot.items(): - plot[key] = value.value + if ui.transfer_check.value == True: + if ui.transfer_gates.value == 'VTG': + points = number_of_points(Vds_transfer) @@ -128,7 +56,7 @@ def on_start_clicked(b): # also drain smu is the same smu_d = device.smu_dict() - smu_d.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR2') + smu_d.update() match transfer_gates.value: case 'VTG' if check_values(Vtg_transfer,'primary') and check_values(Vds_transfer,'secondary'): smu_t = device.smu_dict() diff --git a/hp4155/ADU for double gate devices_version_3/lib/help.py b/hp4155/ADU for double gate devices_version_3/lib/help.py index 8242fd1255eb1391a04de67506300b6d2967bf73..91bf965cfea647c49404a35f3f90c4b66ccd64bf 100644 --- a/hp4155/ADU for double gate devices_version_3/lib/help.py +++ b/hp4155/ADU for double gate devices_version_3/lib/help.py @@ -23,10 +23,11 @@ def get_dataframe_from_results(dictionary): df = pd.DataFrame(dictionary) return df -def number_of_points(dict): + +def number_of_points(obj): # obj is interface object try: - diff = dict['stop'].value - dict['start'].value - ratio = abs(diff/dict['step'].value) + diff = obj.stop.value - obj.start.value + ratio = abs(diff/obj.step.value) points = int(ratio+1) except ZeroDivisionError: @@ -38,68 +39,6 @@ def number_of_points(dict): points = 128 return points -def check_values(dictionary,function): - valid = True - - root = tk.Tk() - root.withdraw() - root.lift() #show window above all other applications - - root.attributes("-topmost", True)#window stays above all other applications - - if function =='primary': - if abs(dictionary['step'].value) > abs(dictionary['stop'].value-dictionary['start'].value) or dictionary['step'].value==0:#invalid parameter setting - valid = False - tkinter.messagebox.showerror(message="Invalid parameter setting!") - - if dictionary['start'].value<dictionary['step'].value and dictionary['step'].value<0: #change polarity - dictionary['step'].value =(-1)*dictionary['step'].value - - elif dictionary['start'].value>dictionary['stop'].value and dictionary['step'].value>0: - dictionary['step'].value = (-1)*dictionary['step'].value - - else: - pass - - if function == 'secondary': - if dictionary['start'].value == dictionary['stop'].value: - pass - elif abs(dictionary['step'].value) > abs(dictionary['stop'].value-dictionary['start'].value) or dictionary['step'].value==0:#invalid parameter setting - valid = False - tkinter.messagebox.showerror(message="Invalid parameter setting!") - if dictionary['start'].value<dictionary['step'].value and dictionary['step'].value<0: #change polarity - dictionary['step'].value =(-1)*dictionary['step'].value - - elif dictionary['start'].value>dictionary['stop'].value and dictionary['step'].value>0: - dictionary['step'].value = (-1)*dictionary['step'].value - - if function == 'synchronous': - pass - - if valid == True: - #check compliance - comp = dictionary['comp'].value - start = dictionary['start'].value - stop = dictionary['stop'].value - - if abs(comp)*max(abs(start),abs(stop))>2: - dictionary["comp"].value=np.sign(comp)*2/max(abs(start),abs(stop)) - - root.destroy() - return valid - -# No more dictionaries -def add_widgets_to_list(source_class,target_list): - for widget in (vars(source_class)).values(): - target_list.append(widget) - -def change_state(widgets_list): - for widget in widgets_list: - try: - widget.disabled = not widget.disabled - except: - pass # Perhaps other objects are there too - def information_box(information): #open dialog and hide the main window @@ -171,20 +110,18 @@ def load_ini(): return file # function to return ratio and offset for synchronous sweep measurement -def calculate_line(VTG,VBG): - ratio = (VBG['stop'].value-VBG['start'].value)/(VTG['stop'].value-VTG['start'].value) - offset = VBG['start'].value-ratio*VTG['start'].value +def calculate_line(VTG,VBG): # from now interface objects + ratio = (VBG.stop.value-VBG.start.value)/(VTG.stop.value-VTG.start.value) + offset = VBG.start.value-ratio*VTG.start.value return ratio,offset #check if smu configuration has a double value -def check_configuration(smu_map:dict): +def check_configuration(sample): # the sample object from the interface #convert the dictionaries values to a list - map_list = [] - for element in smu_map.values(): - map_list.append(element.value) + map_list = [sample.source.value,sample.top_gate.value,sample.back_gate.value,sample.drain.value] #remove the duplicates by using a set map_set = set(map_list) @@ -195,17 +132,14 @@ def check_configuration(smu_map:dict): # The function for graph in the tool -def graph_tool(params,device): +def graph_tool(plot_config,width,device): # the plot config object from the interface device.delete_axis("X") device.delete_axis("Y1") device.delete_axis("Y2") - device.del_user_functions() - - device.clear_error_stack() # How to define user functions correctly and not multiple times - plot_list = [params["PLOT"]["x"],params["PLOT"]["y1"],params["PLOT"]["y2"]] - plot_set= set(plot_list) + plot_list = [plot_config.x.value,plot_config.y1.value,plot_config.y2.value] + plot_set = set(plot_list) #define the no values @@ -213,7 +147,7 @@ def graph_tool(params,device): if element != "None": if element.endswith("mm"): #only I values #define the respective user function - device.user_function(element,"mA/mm",f"{element[:-2]}*{normalization_factor(params['SAMPLE']['width'])}") #max 3 + device.user_function(element,"mA/mm",f"{element[:-2]}*{normalization_factor(width)") #max 3 #define the absolute(A to indicate absolute) always 3 (max 6!) if element.startswith('I') and element.endswith('mm'): @@ -223,49 +157,38 @@ def graph_tool(params,device): # Now send the parameters in the tool - device.display_variable('X',params["PLOT"]["x"]) - device.error_occured() + device.display_variable('X',plot_config.x.value) device.axis_scale('X','LIN') - device.error_occured() - device.display_variable_min_max('X','MIN',params["PLOT"]["x_min"]) - device.error_occured() - device.display_variable_min_max('X','MAX',params["PLOT"]["x_max"]) - device.error_occured() + device.display_variable_min_max('X','MIN',plot_config.x_min.value) + device.display_variable_min_max('X','MAX',plot_config.x_max.value) - if params["PLOT"]["y1_scale"]=='LOG': - device.display_variable('Y1',"A"+params["PLOT"]["y1"]) + if plot_config.y1_scale.value=='LOG': + device.display_variable('Y1',"A"+plot_config.y1.value) else: - device.display_variable('Y1',params["PLOT"]["y1"]) - device.error_occured() - device.axis_scale('Y1',params["PLOT"]["y1_scale"]) - device.error_occured() - device.display_variable_min_max('Y1','MIN',params["PLOT"]["y1_min"]) - device.error_occured() - device.display_variable_min_max('Y1','MAX',params["PLOT"]["y1_max"]) - device.error_occured() - - if params["PLOT"]["y2"]!= "None": + device.display_variable('Y1',plot_config.y1.value) + device.axis_scale('Y1',plot_config.y1.value) + device.display_variable_min_max('Y1','MIN',plot_config.y1_min.value) + device.display_variable_min_max('Y1','MAX',plot_config.y1_max.value) + + if plot_config.y2.value!= "None": if params["PLOT"]["y2_scale"]=='LOG': - device.display_variable('Y2',"A"+params["PLOT"]["y2"]) + device.display_variable('Y2',"A"+plot_config.y2.value) else: - device.display_variable('Y2',params["PLOT"]["y2"]) - device.error_occured() - device.axis_scale('Y2',params["PLOT"]["y2_scale"]) - device.error_occured() - device.display_variable_min_max('Y2','MIN',params["PLOT"]["y2_min"]) - device.display_variable_min_max('Y2','MAX',params["PLOT"]["y2_max"]) - device.error_occured() + device.display_variable('Y2',plot_config.y2.value) + device.axis_scale('Y2',plot_config.y2_scale.value) + device.display_variable_min_max('Y2','MIN',plot_config.y2_min.value) + device.display_variable_min_max('Y2','MAX',plot_config.y2_max.value) #plot software functions -def values_to_plot(params,device): +def values_to_plot(plot_config,device): #plotted variables as they are named in the tool #return the plotted data for easier configuration plotted_variables = {'X':device.get_axis_variable('X'),'Y1': device.get_axis_variable('Y1')} - if params["PLOT"]["y2"]!= "None": + if plot_config.y2.value!= "None": plotted_variables['Y2']= device.get_axis_variable('Y2') plot_values ={} @@ -290,11 +213,27 @@ def set_axes_labels(plot_list): return axes_labels - - +def create_file(filename): + root = tk.Tk() + root.withdraw() + root.lift() #show window above all other applications - + root.attributes("-topmost", True)#window stays above all other applications - + file = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files","*.txt")],title = "save results path",initialfile =filename) + + #check if the file path is correct(.txt) + while file.endswith(".txt") == False: + #open again filedialog with error message box + tk.messagebox.showerror(message='invalid filename!') + file = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files","*.txt")],title = "save results path",initialfile =default_filename) + + root.destroy() - \ No newline at end of file +def write_sample_information(sample,file): + file.write(f"Series:{sample.processing_number.value}"+"\n") + file.write(f"Sample:{sample.sample.value}"+"\n") + file.write(f"Field:{sample.field.value}"+"\n") + file.write(f"Device:{sample.device.value}"+"\n") + file.write(f"Device Width/um:{sample.width.value}"+"\n") + \ No newline at end of file diff --git a/hp4155/ADU for double gate devices_version_3/lib/interface.py b/hp4155/ADU for double gate devices_version_3/lib/interface.py index 00641ab1a221d280f700c48fe1bfeb46c97f2700..6fa954f3c666006f27509762b798f749e1ee7389 100644 --- a/hp4155/ADU for double gate devices_version_3/lib/interface.py +++ b/hp4155/ADU for double gate devices_version_3/lib/interface.py @@ -9,6 +9,20 @@ height = 'auto' style = {'description_width': 'initial'} floatbox_width = "80%" + +# functionallities for the widgets +# No more dictionaries +def add_widgets_to_list(source_class,target_list): + for widget in (vars(source_class)).values(): + target_list.append(widget) + +def change_state(widgets_list): + for widget in widgets_list: + try: + widget.disabled = not widget.disabled + except: + pass # Perhaps other objects are there too + # here are the custom widgets def measurement_check(name): check=widgets.Checkbox( @@ -257,8 +271,118 @@ class plot_config: #meas = 1,2,3 for transfer,output,gatediode self.x_max = self.grid[5,1] self.y1_max = self.grid[5,2] self.y2_max = self.grid[5,3] - - - + + +# The whole interface +class interface: + def __init__(self): + self.sample = sample() + + self.transfer_check = measurement_check("Transfer") + self.output_check = measurement_check("Output") + self.gatediode_check = measurement_check("Gatediode") + + checkboxes = widgets.HBox([self.transfer_check,self.output_check,self.gatediode_check]) + display(checkboxes) + + #transfer + + self.integration_transfer = integration_time("MEDium") + self.transfer_gates = gate_selection("VTG","VBG","BOTH SIMULTANEOUSLY","BOTH SEQUENTIALLY") + + self.Vds_transfer = secondary('VDS',0.05,0.95,1,1e-2) + self.Vtg_transfer = primary('VTG',-5,0.01,5,1e-3) + self.Vbg_transfer = primary('VBG',-15,0.1,15,1e-3) + self.plot_transfer = plot_config(1) + transfer_box = widgets.VBox( + [ + self.integration_transfer, + self.transfer_gates, + self.Vds_transfer.grid, + self.Vtg_transfer.grid, + self.Vbg_transfer.grid, + self.plot_transfer.grid + ] + ) + + + #output + self.integration_output = integration_time("SHORt") + self.output_gates = gate_selection("VTG","VBG","BOTH") + + self.Vds_output = primary('VDS',0,0.01,5,1e-2) + self.Vtg_output = secondary('VTG',-5,2,5,1e-3) + self.Vbg_output = secondary('VBG',-15,5,15,1e-3) + self.plot_output = plot_config(2) + + output_box = widgets.VBox( + [ + self.integration_output,self.output_gates, + self.Vds_output.grid, + self.Vtg_output.grid, + self.Vbg_output.grid, + self.plot_output.grid + ] + ) + + self.integration_gatediode = integration_time("MEDium") + self.gatediode_gates = gate_selection("VTG","VBG") + + self.Vg_gatediode=primary('VG',-5,0.05,5,1e-3) + self.plot_gatediode = plot_config(3) + gatediode_box = widgets.VBox( + [ + self.integration_gatediode, + self.gatediode_gates, + self.Vg_gatediode.grid, + self.plot_gatediode.grid + ] + ) + + #the tab widget + children = [transfer_box,output_box,gatediode_box] + titles = ["Transfer","Output","Gatediode"] + tab = widgets.Tab() + tab.children = children + tab.titles = titles + + display(tab) + + # Now the buttons + self.start = widgets.Button(description ='Start Measurement') + self.output = widgets.Output() + + self.export_ini = widgets.Button(description = 'Export as ini') + self.import_ini = widgets.Button(description ='Import from ini') + + # capture all widgets + self.all_widgets=[ + self.transfer_gates, + self.output_gates, + self.start, + self.transfer_check, + self.integration_transfer, + self.output_check, + self.integration_output, + self.gatediode_check, + self.integration_gatediode, + self.gatediode_gates, + self.export_ini, + self.import_ini + ] + add_widgets_to_list(self.sample,self.all_widgets) + add_widgets_to_list(self.Vds_transfer,self.all_widgets) + add_widgets_to_list(self.Vtg_transfer,self.all_widgets) + add_widgets_to_list(self.Vbg_transfer,self.all_widgets) + add_widgets_to_list(self.Vds_output,self.all_widgets) + add_widgets_to_list(self.Vtg_output,self.all_widgets) + add_widgets_to_list(self.Vbg_output,self.all_widgets) + add_widgets_to_list(self.Vg_gatediode,self.all_widgets) + add_widgets_to_list(self.plot_transfer,self.all_widgets) + add_widgets_to_list(self.plot_output,self.all_widgets) + add_widgets_to_list(self.plot_gatediode,self.all_widgets) + + line = widgets.HBox([self.start,self.import_ini,self.export_ini]) + display(line,self.output) \ No newline at end of file diff --git a/hp4155/ADU for double gate devices_version_3/lib/measurements.py b/hp4155/ADU for double gate devices_version_3/lib/measurements.py index 74e7d38793ce00553109ea434f327ee5402957e0..71d4914f2bebd32a79afcbbb53cd776ef0ddd908 100644 --- a/hp4155/ADU for double gate devices_version_3/lib/measurements.py +++ b/hp4155/ADU for double gate devices_version_3/lib/measurements.py @@ -11,47 +11,71 @@ from decimal import Decimal import os -def Setup(device): - device.reset() - - #setup sweep measurement mode - device.measurement_mode('SWE') - - #disable all irrelevant units - device.disable_not_smu() - # Transfer only VTG -def Transfer_VTG(device,params): - # calculate normalization factor - - norm = normalization_factor(params["SAMPLE"]["width"]) - points = params["VAR2"]["points"] +def Transfer_VTG(device,ui): # ui interface + device.del_user_functions() # delete all user functions + device.clear_error_stack() # clear error stack + # setup the smus + + norm = normalization_factor(ui.sample.width.value) + points = number_of_points(ui.Vds_transfer) + + smu_source = device.smu_dict() + smu_source.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS') + + smu_top_gate = device.smu_dict() + smu_top_gate.update(vname = 'VTG',iname='ITG',mode = 'V',func='VAR1') + + smu_back_gate = device.smu_dict() + smu_back_gate.update(vname = 'VBG',iname='IBG',mode = 'COMM',func = 'CONS') + + smu_drain = device.smu_dict() + smu_drain = device.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR2') + + # setup VAR1 + var1 = device.var1_dict() + var1.update( + mode = ui.Vtg_transfer.hyst.value, + start = ui.Vtg_transfer.start.value, + stop = ui.Vtg_transfer.stop.value, + step = ui.Vtg_transfer.step.value, + comp = ui.Vtg_transfer.comp.value, + pcomp = ui.Vtg_transfer.pcomp.value + ) + + var2=device.var2_dict() #Vds_output is always used in tranfer curve with the same config + var2.update( + start=ui.Vds_transfer.start.value, + step=ui.Vds_transfer.step.value, + points=points, + comp=ui.Vds_transfer.comp.value, + pcomp=ui.Vds_transfer.pcomp.value, + ) + try: - device.setup_smu(params["MAP"]['TG'],params["SMU_T"]) - device.setup_smu(params["MAP"]['D'],params["SMU_D"]) - device.setup_smu(params["MAP"]['BG'],params["SMU_B"]) - device.setup_smu(params["MAP"]['S'],params["SMU_S"]) + device.setup_smu(ui.sample.top_gate.value,smu_top_gate) + device.setup_smu(ui.sample.drain.value,smu_drain) + device.setup_smu(ui.sample.back_gate.value,smu_back_gate) + device.setup_smu(ui.sample.source.value,smu_source) - device.setup_var1(params["VAR1"]) - device.setup_var2(params["VAR2"]) + device.setup_var1(var1) + device.setup_var2(var2) - device.integration_time(params["INTEGRATION"]) + device.integration_time(ui.integration_transfer.value) variables_list =["VTG","ITG","VDS","ID"] device.variables_to_save(variables_list) - try: - plotted_variables = graph_tool(params,device) - except Exception as e: - error_box(e) - return - + + plotted_variables = graph_tool(ui.plot_transfer,ui.sample.width.value,device) + device.single_measurement() while device.operation_completed()==False: pass - - device.autoscaling() + + if ui.sample.quick.value == False: + device.autoscaling() device.error_occured() values = dict([(variable,device.return_values(variable)) for variable in variables_list]) @@ -65,98 +89,58 @@ def Transfer_VTG(device,params): df["ITGmm/uA/um"]= (df["ITG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float') # Save the results - default_filename = f"{params['SAMPLE']['sample']}_{params['SAMPLE']['field']}_{params['SAMPLE']['device']}_TOP_GATE_U.txt" - - root = tk.Tk() - root.withdraw() - root.lift() #show window above all other applications - - root.attributes("-topmost", True)#window stays above all other applications - - file = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files","*.txt")],title = "save results path",initialfile =default_filename) - - #check if the file path is correct(.txt) - while file.endswith(".txt") == False: - #open again filedialog with error message box - tk.messagebox.showerror(message='invalid filename!') - file = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files","*.txt")],title = "save results path",initialfile =default_filename) - - root.destroy() + default_filename = f"{ui.sample.sample.value}_{ui.sample.field.value}_{ui.sample.device.value}_TOP_GATE_U.txt" + file = create_file(default_filename) + with open(file,'w') as f: date = str(datetime.today().replace(microsecond=0)) f.write(f"Transfer Curve at {date}"+"\n") - f.write(f"Series:{params['SAMPLE']['processing_number']}"+"\n") - f.write(f"Sample:{params['SAMPLE']['sample']}"+"\n") - f.write(f"Field:{params['SAMPLE']['field']}"+"\n") - f.write(f"Device:{params['SAMPLE']['device']}"+"\n") - f.write(f"Device Width/um:{params['SAMPLE']['width']}"+"\n") + f.write("Sweeping Gate:VTG"+"\n\n") f.write('Parameters\n') - f.write(f"VTG from {params['VAR1']['start']}V to {params['VAR1']['stop']}V with step {params['VAR1']['step']}V"+"\n") - f.write(f"VDS from {params['VAR2']['start']}V to {params['VAR2']['stop']}V with step {params['VAR2']['step']}V"+"\n") + f.write(f"VTG from {ui.Vtg_transfer.start.value}V to {ui.Vtg_transfer.stop.value}V with step {ui.Vtg_transfer.step.value}V"+"\n") + f.write(f"VDS from {ui.Vds_transfer.start.value}V to {ui.Vds_transfer.stop.value}V with step {ui.Vds_transfer.step.value}V"+"\n") - if params['VAR1']['pcomp']==0: - f.write(f"Top Gate Current Compliance/A:{params['VAR1']['comp']}"+"\n") + if ui.Vtg_transfer.pcomp.value==0: + f.write(f"Top Gate Current Compliance/A:{ui.Vtg_transfer.comp.value}"+"\n") else: - f.write(f"Top Gate Power Compliance/A:{params['VAR1']['pcomp']}"+"\n") + f.write(f"Top Gate Power Compliance/A:{ui.Vtg_transfer.pcomp.value}"+"\n") - if params['VAR2']['pcomp'] == 0: - f.write(f"Drain Current Compliance/A:{params['VAR1']['comp']}"+"\n") + if ui.Vds_transfer.pcomp.value == 0: + f.write(f"Drain Current Compliance/A:{ui.Vds_transfer.comp.value}"+"\n") else: - f.write(f"Drain Power Compliance/A:{params['VAR1']['pcomp']}"+"\n") - f.write(f"Integration Time:{params['INTEGRATION']}"+"\n") + f.write(f"Drain Power Compliance/A:{ui.Vds_transfer.pcomp.value}"+"\n") + f.write(f"Integration Time:{ui.integration_transfer.value}"+"\n") f.write("\nResults\n") df.to_csv(file,sep=" ",mode='a') - plot_values = values_to_plot(params,device) - - # Plot user specified results - fig,ax1= plt.subplots(figsize=(10,6),layout='constrained') - - plot_list = [params["PLOT"]["x"],params["PLOT"]["y1"],params["PLOT"]["y2"]] - scale_list =['LIN',params["PLOT"]["y1_scale"],params["PLOT"]["y2_scale"]] - axes_labels = set_axes_labels(plot_list) - - if scale_list[1]=='LOG': - ax1.set_yscale('log') + if ui.sample.quick.value == False: + plot_values = values_to_plot(ui.plot_transfer,device) + + # Plot user specified results + fig,ax1= plt.subplots(figsize=(10,6),layout='constrained') - #now set the labels - ax1.set_xlabel(axes_labels[0]) - ax1.set_ylabel(axes_labels[1]) - x = np.split(plot_values['X'],points) - y1 = np.split(plot_values['Y1'],points) - labels =np.mean(np.array_split(df["VDS/V"],points),axis = 1) # VDS values for labels + plot_list = [ui.plot_transfer.x.value] + scale_list =['LIN',ui.plot_transfer.y1_scale.value,ui.plot_transfer.y2_scale.value] + axes_labels = set_axes_labels(plot_list) - for i in range(points): - ax1.plot(x[i],y1[i],label = f"VDS:{round(labels[i],3)} (V)") + if scale_list[1]=='LOG': + ax1.set_yscale('log') - # Adding title - fig.suptitle('Transfer Curve', fontweight ="bold") - fig.legend(loc='outside right upper') - - display(fig) - #save plot if checked - if params["SAMPLE"]['save_fig'] == True: - filename= os.path.splitext(file)[0] - fig.savefig(filename+'_Y1.png') + #now set the labels + ax1.set_xlabel(axes_labels[0]) + ax1.set_ylabel(axes_labels[1]) - #add the second axis if applicable - if plot_list[2]!= "None": - fig,ax2=plt.subplots(figsize=(10,6),layout='constrained') - y2 = np.split(plot_values['Y2'],points) + x = np.split(plot_values['X'],points) + y1 = np.split(plot_values['Y1'],points) + labels =np.mean(np.array_split(df["VDS/V"],points),axis = 1) # VDS values for labels - if scale_list[2]=='LOG': - ax2.set_yscale('log') - - ax2.set_xlabel(axes_labels[0]) - - ax2.set_ylabel(axes_labels[2]) for i in range(points): - ax2.plot(x[i],y2[i],label = f"VDS:{round(labels[i],3)} (V)") + ax1.plot(x[i],y1[i],label = f"VDS:{round(labels[i],3)} (V)") # Adding title fig.suptitle('Transfer Curve', fontweight ="bold") @@ -166,7 +150,31 @@ def Transfer_VTG(device,params): #save plot if checked if params["SAMPLE"]['save_fig'] == True: filename= os.path.splitext(file)[0] - fig.savefig(filename+'_Y2.png') + fig.savefig(filename+'_Y1.png') + + #add the second axis if applicable + if plot_list[2]!= "None": + fig,ax2=plt.subplots(figsize=(10,6),layout='constrained') + y2 = np.split(plot_values['Y2'],points) + + if scale_list[2]=='LOG': + ax2.set_yscale('log') + + ax2.set_xlabel(axes_labels[0]) + + ax2.set_ylabel(axes_labels[2]) + for i in range(points): + ax2.plot(x[i],y2[i],label = f"VDS:{round(labels[i],3)} (V)") + + # Adding title + fig.suptitle('Transfer Curve', fontweight ="bold") + fig.legend(loc='outside right upper') + + display(fig) + #save plot if checked + if params["SAMPLE"]['save_fig'] == True: + filename= os.path.splitext(file)[0] + fig.savefig(filename+'_Y2.png') # Transfer only VBG diff --git a/hp4155/ADU for double gate devices_version_3/lib/transfer.py b/hp4155/ADU for double gate devices_version_3/lib/transfer.py new file mode 100644 index 0000000000000000000000000000000000000000..556e6907c56e497831750acc84aeab88769c9b9d --- /dev/null +++ b/hp4155/ADU for double gate devices_version_3/lib/transfer.py @@ -0,0 +1,126 @@ +# This file contains the transfer measurements + +import sys +sys.path.insert(0, '..') #append parent directory + +import hp4155a +from help import * +from decimal import Decimal + +import os + +def VTG(ui,device): + device.del_user_functions() # delete all user functions + device.clear_error_stack() # clear error stack + # setup the smus + + norm = normalization_factor(ui.sample.width.value) + points = number_of_points(ui.Vds_transfer) + + smu_source = device.smu_dict() + smu_source.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS') + + smu_top_gate = device.smu_dict() + smu_top_gate.update(vname = 'VTG',iname='ITG',mode = 'V',func='VAR1') + + smu_back_gate = device.smu_dict() + smu_back_gate.update(vname = 'VBG',iname='IBG',mode = 'COMM',func = 'CONS') + + smu_drain = device.smu_dict() + smu_drain = device.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR2') + + # setup VAR1 + var1 = device.var1_dict() + var1.update( + mode = ui.Vtg_transfer.hyst.value, + start = ui.Vtg_transfer.start.value, + stop = ui.Vtg_transfer.stop.value, + step = ui.Vtg_transfer.step.value, + comp = ui.Vtg_transfer.comp.value, + pcomp = ui.Vtg_transfer.pcomp.value + ) + + var2=device.var2_dict() #Vds_output is always used in tranfer curve with the same config + var2.update( + start=ui.Vds_transfer.start.value, + step=ui.Vds_transfer.step.value, + points=points, + comp=ui.Vds_transfer.comp.value, + pcomp=ui.Vds_transfer.pcomp.value, + ) + + try: + device.setup_smu(ui.sample.top_gate.value,smu_top_gate) + device.setup_smu(ui.sample.drain.value,smu_drain) + device.setup_smu(ui.sample.back_gate.value,smu_back_gate) + device.setup_smu(ui.sample.source.value,smu_source) + + device.setup_var1(var1) + device.setup_var2(var2) + + device.integration_time(ui.integration_transfer.value) + + variables_list =["VTG","ITG","VDS","ID"] + device.variables_to_save(variables_list) + + + plotted_variables = graph_tool(ui.plot_transfer,ui.sample.width.value,device) + + + device.single_measurement() + while device.operation_completed()==False: + pass + + device.error_occured() + + if ui.sample.quick.value == False: + device.autoscaling() + + + values = dict([(variable,device.return_values(variable)) for variable in variables_list]) + df = get_dataframe_from_results(values) + except Exception as e: + error_box(e) + return + + # Append the normalized current + df["IDmm/uA/um"]= (df["ID/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float') + df["ITGmm/uA/um"]= (df["ITG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float') + + # Save the results + default_filename = f"{ui.sample.sample.value}_{ui.sample.field.value}_{ui.sample.device.value}_TOP_GATE_U.txt" + file = create_file(default_filename) + + + with open(file,'w') as f: + date = str(datetime.today().replace(microsecond=0)) + f.write(f"Transfer Curve at {date}"+"\n") + write_sample_information(ui.sample,f) + f.write("Sweeping Gate:VTG"+"\n\n") + f.write('Parameters\n') + f.write(f"VTG from {ui.Vtg_transfer.start.value}V to {ui.Vtg_transfer.stop.value}V with step {ui.Vtg_transfer.step.value}V"+"\n") + f.write(f"VDS from {ui.Vds_transfer.start.value}V to {ui.Vds_transfer.stop.value}V with step {ui.Vds_transfer.step.value}V"+"\n") + + if ui.Vtg_transfer.pcomp.value==0: + f.write(f"Top Gate Current Compliance/A:{ui.Vtg_transfer.comp.value}"+"\n") + else: + f.write(f"Top Gate Power Compliance/A:{ui.Vtg_transfer.pcomp.value}"+"\n") + + if ui.Vds_transfer.pcomp.value == 0: + f.write(f"Drain Current Compliance/A:{ui.Vds_transfer.comp.value}"+"\n") + else: + f.write(f"Drain Power Compliance/A:{ui.Vds_transfer.pcomp.value}"+"\n") + f.write(f"Integration Time:{ui.integration_transfer.value}"+"\n") + f.write("\nResults\n") + + df.to_csv(file,sep=" ",mode='a') + + # here we stop! We need efficient plotting + + + + + + + + diff --git a/hp4155/ADU for double gate devices_version_3/test_interface.ipynb b/hp4155/ADU for double gate devices_version_3/test_interface.ipynb index ade47b6f25c614da6388a627116e7ed8fbdec988..279486a574ae4f3b3c1f843b712123c9e4f6072f 100644 --- a/hp4155/ADU for double gate devices_version_3/test_interface.ipynb +++ b/hp4155/ADU for double gate devices_version_3/test_interface.ipynb @@ -9,7 +9,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "b78a708f357341328ff31a4eb7d6aa48", + "model_id": "cf15158f4515448c98bcbbf8631ced8d", "version_major": 2, "version_minor": 0 }, @@ -23,7 +23,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "6d684dc17c4d4b63bd5d84b8b70816ff", + "model_id": "e0c47c8a58e5402287a451cdcf89ce66", "version_major": 2, "version_minor": 0 }, @@ -37,7 +37,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "3d56de01c1354f04be53908afea44b97", + "model_id": "943d1489c4ca464aab01a2e4b801c073", "version_major": 2, "version_minor": 0 }, @@ -51,7 +51,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "31e7dd9a0c7e47e7b75c7cf5f444ad95", + "model_id": "b338fddab9694a2e89f38d43a426f7c1", "version_major": 2, "version_minor": 0 }, @@ -65,7 +65,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "d47a7dad9691423ba72db805d019cde9", + "model_id": "4113f2f58c554acdb2064fb8cb331e9e", "version_major": 2, "version_minor": 0 }, @@ -86,95 +86,13 @@ "from interface import *\n", "from help import *\n", "\n", - "# Create the grids\n", - "#create the information grid\n", - "style = {'description_width': 'initial'}\n", - "sample = sample()\n", - "\n", - "transfer_check = measurement_check(\"Transfer\")\n", - "output_check = measurement_check(\"Output\")\n", - "gatediode_check = measurement_check(\"Gatediode\")\n", - "\n", - "checkboxes = widgets.HBox([transfer_check,output_check,gatediode_check])\n", - "display(checkboxes)\n", - "\n", - "#transfer\n", - "\n", - "integration_transfer = integration_time(\"MEDium\")\n", - "transfer_gates = gate_selection(\"VTG\",\"VBG\",\"BOTH SIMULTANEOUSLY\",\"BOTH SEQUENTIALLY\")\n", - "\n", - "Vds_transfer = secondary('VDS',0.05,0.95,1,1e-2)\n", - "Vtg_transfer = primary('VTG',-5,0.01,5,1e-3)\n", - "Vbg_transfer = primary('VBG',-15,0.1,15,1e-3)\n", - "plot_transfer = plot_config(1)\n", - "transfer_box = widgets.VBox([integration_transfer,transfer_gates,Vds_transfer.grid,Vtg_transfer.grid,Vbg_transfer.grid,plot_transfer.grid])\n", - "\n", - "\n", - "#output\n", - "integration_output = integration_time(\"SHORt\")\n", - "output_gates = gate_selection(\"VTG\",\"VBG\",\"BOTH\")\n", - "\n", - "Vds_output = primary('VDS',0,0.01,5,1e-2)\n", - "Vtg_output = secondary('VTG',-5,2,5,1e-3)\n", - "Vbg_output = secondary('VBG',-15,5,15,1e-3)\n", - "plot_output = plot_config(2)\n", - "\n", - "output_box = widgets.VBox([integration_output,output_gates,Vds_output.grid,Vtg_output.grid,Vbg_output.grid,plot_output.grid])\n", - "\n", - "integration_gatediode = integration_time(\"MEDium\")\n", - "gatediode_gates = gate_selection(\"VTG\",\"VBG\")\n", - "\n", - "Vg_gatediode=primary('VG',-5,0.05,5,1e-3)\n", - "plot_gatediode = plot_config(3)\n", - "gatediode_box = widgets.VBox([integration_gatediode,gatediode_gates,Vg_gatediode.grid,plot_gatediode.grid])\n", - "\n", - "#the tab widget\n", - "children = [transfer_box,output_box,gatediode_box]\n", - "titles = [\"Transfer\",\"Output\",\"Gatediode\"]\n", - "tab = widgets.Tab()\n", - "tab.children = children\n", - "tab.titles = titles\n", - "\n", - "display(tab)\n", - "\n", - "button = widgets.Button(description ='Start Measurement')\n", - "output = widgets.Output()\n", - "\n", - "export_ini_button = widgets.Button(description = 'Export as ini')\n", - "import_ini_button = widgets.Button(description='Import from ini')\n", - "\n", - "all_widgets =[transfer_gates,output_gates,button,transfer_check,integration_transfer,output_check,integration_output,gatediode_check,integration_gatediode,gatediode_gates,export_ini_button,import_ini_button]\n", - "add_widgets_to_list(sample,all_widgets)\n", - "add_widgets_to_list(Vds_transfer,all_widgets)\n", - "add_widgets_to_list(Vtg_transfer,all_widgets)\n", - "add_widgets_to_list(Vbg_transfer,all_widgets)\n", - "add_widgets_to_list(Vds_output,all_widgets)\n", - "add_widgets_to_list(Vtg_output,all_widgets)\n", - "add_widgets_to_list(Vbg_output,all_widgets)\n", - "add_widgets_to_list(Vg_gatediode,all_widgets)\n", - "add_widgets_to_list(plot_transfer,all_widgets)\n", - "add_widgets_to_list(plot_output,all_widgets)\n", - "add_widgets_to_list(plot_gatediode,all_widgets)\n", - "\n", - "\n", - "line = widgets.HBox([button,import_ini_button,export_ini_button])\n", - "display(line,output)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "563c17ae-e2b1-4f45-96cc-f7c86f93cc08", - "metadata": {}, - "outputs": [], - "source": [ - "change_state(all_widgets)" + "interface = interface()" ] }, { "cell_type": "code", "execution_count": null, - "id": "84efb313-b320-41a8-9e0b-64a18673a3cf", + "id": "65639b77-8c22-4132-a2cf-754276d08b72", "metadata": {}, "outputs": [], "source": []