Skip to content
Snippets Groups Projects
Commit f7ed075f authored by Alexandros Asonitis's avatar Alexandros Asonitis
Browse files

Double Gate Devices Part 10 (Transfer measurement completed but not tested)

parent dfb00209
No related branches found
No related tags found
No related merge requests found
...@@ -5,7 +5,8 @@ sys.path.insert(0, '..') #append parent directory ...@@ -5,7 +5,8 @@ sys.path.insert(0, '..') #append parent directory
from interface import * from interface import *
from help import * from help import *
from measurements import *
import configparser
# Create the grids # Create the grids
#create the information grid #create the information grid
...@@ -75,6 +76,149 @@ add_widgets_to_list(Vg_gatediode,all_widgets) ...@@ -75,6 +76,149 @@ add_widgets_to_list(Vg_gatediode,all_widgets)
line = widgets.HBox([button,import_ini_button,export_ini_button]) line = widgets.HBox([button,import_ini_button,export_ini_button])
display(line,output) display(line,output)
device = hp4155a.HP4155a('GPIB0::17::INSTR')
def on_start_clicked(b):
with output:
clear_output()
#disable all widgets
disable_widgets(all_widgets)
Setup(device) #setup the device
if transfer_check.value == True:
match transfer_gates.value:
case 'VTG' if check_values(Vtg_transfer,'primary') and check_values(Vds_transfer,'secondary'):
pass
case 'VBG' if check_values(Vbg_transfer,'primary') and check_values(Vds_transfer,'secondary'):
pass
case 'BOTH' if check_values(Vbg_transfer,'primary') and check_values(Vds_transfer,'secondary') and check_values(Vtg_transfer,'primary'):
pass
case _ :
information_box("Transfer Measurement skipped due to invalid parameters")
if output_check.value == True:
match output_gates.value:
case 'VTG' if check_values(Vds_output,'primary') and check_values(Vtg_output,'secondary'):
pass
case 'VBG' if check_values(Vds_output,'primary') and check_values(Vbg_output,'secondary'):
pass
case 'BOTH' if check_values(Vds_output,'primary') and check_values(Vtg_output,'secondary') and check_values(Vbg_output,'secondary'):
pass
case _ :
information_box("Output Measurement skipped due to invalid parameters")
if gatediode_check.value == True:
match terminal.value:
case 'VTG' if check_values(Vg_gatediode,'primary'):
pass
case 'VBG' if check_values(Vg_gatediode,'primary'):
pass
case _ :
information_box("Gatediode Measurement skipped due to invalid parameters")
information_box("Measurement finished!")
enable_widgets(all_widgets)
def on_export_ini_clicked(b):
with output:
disable_widgets(all_widgets)
config = configparser.ConfigParser()
default_filename = 'ADU.ini'
file = save_as_ini(default_filename)
with open(file,'w') as configfile:
config.add_section('ALL VALUES ARE IN SI-UNITS!')
config.add_section('IT IS RECOMMENDED TO CHANGE THE INI FILE FROM THE INTERFACE AND DO NOT CHANGE ANY VALUES MANUALLY')
config.add_section('Transfer')
config.set('Transfer','Integration',integration_transfer.value)
config.add_section("Vgs_transfer")
for parameter,widget in Vgs_transfer.items():
config.set('Vgs_transfer',parameter,str(widget.value))
config.add_section('Vds_transfer')
for parameter,widget in Vds_transfer.items():
config.set('Vds_transfer',parameter,str(widget.value))
config.add_section('Output')
config.set('Output','Integration',integration_output.value)
config.add_section("Vgs_output")
for parameter,widget in Vgs_output.items():
config.set('Vgs_output',parameter,str(widget.value))
config.add_section('Vds_output')
for parameter,widget in Vds_output.items():
config.set('Vds_output',parameter,str(widget.value))
config.add_section('Gatediode')
config.set('Gatediode','Integration',integration_gatediode.value)
config.add_section("Vgs_gatediode")
for parameter,widget in Vgs_gatediode.items():
config.set('Vgs_gatediode',parameter,str(widget.value))
config.write(configfile)
enable_widgets(all_widgets)
def on_import_ini_clicked(b):
with output:
disable_widgets(all_widgets)
#load values to the interface
config = configparser.ConfigParser()
file = load_ini()
#print(file)
#read the values from each section
try:
config.read(file)
#transfer curve
integration_transfer.value = config.get('Transfer', "integration")
for parameter,widget in Vgs_transfer.items():
widget.value = config.get('Vgs_transfer',parameter)
for parameter,widget in Vds_transfer.items():
widget.value = config.get('Vds_transfer',parameter)
#output curve
integration_output.value = config.get('Output','integration')
for parameter,widget in Vgs_output.items():
widget.value = config.get('Vgs_output',parameter)
for parameter,widget in Vds_output.items():
widget.value = config.get('Vds_output',parameter)
# gatediode
integration_gatediode.value = config.get('Gatediode','integration')
for parameter,widget in Vgs_gatediode.items():
widget.value = config.get('Vgs_gatediode',parameter)
information_box("all parameters loaded succesfully")
except Exception as error:
if type(error).__name__ =='NoSectionError':
information_box(f"{error}.Explanation: Section(header) [section] does not exist. Create a new ini file or compare it with functional ini files!")
elif type(error).__name__=='NoOptionError':
information_box(f'{error}.Explanation: The variable name before the equal sign is not recognized. Create a new ini file or compare it with functional ini files!')
elif type(error).__name__ == 'TraitError':
information_box(f'{error}.Explanation: Invalid Parameter Setting. Check if you set an invalid value!')
elif type(error).__name__ =="DuplicateOptionError":
information_box(f"{error}. Explaination: The section contains the setted parameter more than once!")
else:
information_box(f"A {type(error).__name__} has occurred. Create A new ini file")
enable_widgets(all_widgets)
button.on_click(on_start_clicked)
#link the new widgets
import_ini_button.on_click(on_import_ini_clicked)
export_ini_button.on_click(on_export_ini_clicked)
...@@ -9,7 +9,17 @@ import tkinter.messagebox ...@@ -9,7 +9,17 @@ import tkinter.messagebox
import pandas as pd import pandas as pd
#Get dataframe from results
def get_dataframe_from_results(dict):
for old_key in results.keys():
if old_key[0]=='I':
new_key = old_key+"/A"
else: #V
new_key = old_key + "/V"
dictionary[new_key] = dictionary.pop(old_key)
df = pd.DataFrame(results)
return df
def plot_output(values,curves_var2,curves_var3): def plot_output(values,curves_var2,curves_var3):
x=np.array_split(np.array_split(values["VDS"],curves_var3),curves_var2) x=np.array_split(np.array_split(values["VDS"],curves_var3),curves_var2)
...@@ -152,61 +162,6 @@ def information_box(information): ...@@ -152,61 +162,6 @@ def information_box(information):
tkinter.messagebox.showinfo(message=information) tkinter.messagebox.showinfo(message=information)
root.destroy() root.destroy()
#saving functions : save parameters and dataframe to txt
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 =filename)
root.destroy()
return file
def save_to_file(measurement,file,sample,integration,Vgs,Vds=None):
with open(file,'w') as f:
date = str(datetime.today().replace(microsecond=0))
f.write(f"{measurement} at {date}"+"\n")
f.write(f"Series:{sample['processing_number'].value}"+"\n")
f.write(f"Sample:{sample['sample'].value}"+"\n")
f.write(f"Field:{sample['field'].value}"+"\n")
f.write(f"Device:{sample['device'].value}"+"\n")
f.write(f"Device Width/um:{sample['width'].value}"+"\n\n")
f.write('Parameters\n')
f.write(f"VGS from {Vgs['start'].value}V to {Vgs['stop'].value}V with step {Vgs['step'].value}V"+"\n")
if Vds!=None:
f.write(f"VDS from {Vds['start'].value}V to {Vds['stop'].value}V with step {Vds['step'].value}V"+"\n")
#calculate the values
Vgs_comp=Vgs["comp"].value
Vgs_pcomp=Vgs["pcomp"].value
if Vgs_pcomp==0:
f.write(f"Gate Current Compliance/A:{Vgs_comp}"+"\n")
else:
f.write(f"Gate Power Compliance/A:{Vgs_pcomp}"+"\n")
if Vds!=None:
Vds_comp=Vds["comp"].value
Vds_pcomp=Vds["pcomp"].value
if Vds_pcomp ==0:
f.write(f"Drain Current Compliance/A:{Vds_comp}"+"\n")
else:
f.write(f"Drain Power Compliance/A:{Vds_pcomp}"+"\n")
f.write(f'Integration Time:{integration.value}'+"\n")
#all results start from the same line
if Vds == None:
f.write("\n\n")
f.write("\nResults\n")
#normalization factor to is for both normalizations 10**6/width mA/mm = uA/um = 10**(-6)A/um (returned from the tool) #normalization factor to is for both normalizations 10**6/width mA/mm = uA/um = 10**(-6)A/um (returned from the tool)
def normalization_factor(width): def normalization_factor(width):
factor = 10**6/width factor = 10**6/width
......
...@@ -6,23 +6,9 @@ import sys ...@@ -6,23 +6,9 @@ import sys
sys.path.insert(0, '..') #append parent directory sys.path.insert(0, '..') #append parent directory
import hp4155a import hp4155a
import pandas as pd from help import *
import numpy as np
import matplotlib.pyplot as plt
#Get dataframe from results
def get_dataframe_from_results(dict):
for old_key in results.keys():
if old_key[0]=='I':
new_key = old_key+"/A"
else: #V
new_key = old_key + "/V"
dictionary[new_key] = dictionary.pop(old_key)
df = pd.DataFrame(results)
return df
def Setup(device): def Setup(device):
device.reset() device.reset()
...@@ -32,110 +18,370 @@ def Setup(device): ...@@ -32,110 +18,370 @@ def Setup(device):
#disable all irrelevant units #disable all irrelevant units
device.disable_not_smu() device.disable_not_smu()
def Transfer(config,device): # Transfer only VTG
#set all the smus def Transfer_VTG(VTG,VDS,integration,sample,device):
#smu2 and smu4 stay always the same during the transfer curve smu1 = device.smu_dict()
smu1.update(vname = 'VTG',iname='ITG',mode = 'V',func='VAR1')
smu2 = device.smu_dict() smu2 = device.smu_dict()
smu2.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR2') smu2.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR2')
smu3 = device.smu_dict()
smu3.update(vname = 'VBG',iname='IBG',mode = 'V',func = 'COMM')
smu4 = device.smu_dict() smu4 = device.smu_dict()
smu4.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS') smu4.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS')
if config['mode'] =='VTG': device.setup_smu(1,smu1)
smu1 = device.smu_dict() device.setup_smu(2,smu2)
smu1.update(vname ='VTG',iname = 'ITG',mode ='V',func='VAR1') device.setup_smu(3,smu3)
device.setup_smu(1,smu4)
var1 = device.var1_dict()
var1.update(
mode=VTG['hyst'].value,
start=VTG['start'].value,
stop=VTG['stop'].value,
step=VTG['step'].value,
comp =VTG['comp'].value,
pcomp=VTG['pcomp'].value
)
device.setup_var1(var1)
points = number_of_points(VDS)
var2=device.var2_dict()
var2.update(
start=VDS['start'].value,
step=VDS['step'].value,
points=points,
comp=VDS['comp'].value,
pcomp=VDS['pcomp'].value
)
device.setup_var2(var2)
device.integration_time(integration)
device.display_mode("LIST")
smu3 = device.smu_dict()
smu3.update(vname='VBG',iname ='IBG',mode='V',func='COMM') #Here VBG is grounded
variables_list =["VTG","ITG","VDS","ID"] variables_list =["VTG","ITG","VDS","ID"]
device.variables_to_save(variables_list)
elif config['mode'] =='VBG': device.single_measurement()
smu1 = device.smu_dict() while device.operation_completed()==False:
smu1.update(vname ='VTG',iname = 'ITG',mode ='V',func='COMM')#Here VTG is grounded pass
smu3 = device.smu_dict() values = dict([(variable,device.return_values(variable)) for variable in variables_list])
smu3.update(vname='VBG',iname ='IBG',mode='V',func='VAR1') df = get_dataframe_from_results(values)
variables_list=["VDS","ID","VBG","IBG"]
else:#Both gates # calculate normalization factor
smu1 = device.smu_dict() norm = normalization_factor(sample["width"].value)
smu1.update(vname ='VTG',iname = 'ITG',mode ='V',func='VAR1')#Here VTG is grounded
# Append the normalized current
df["IDmm/uA/um"]= df["ID/A"]*norm
df["ITGmm/uA/um"]= df["ITG/A"]*norm
# Plot normalized Results VTG-IDmm
fig,ax1= plt.subplots()
x = np.array_split(df["VTG/V"],points)
y = np.array_split(df["IDmm/uA/um"].abs(),points)
labels =np.mean(np.array_spilt(df["VDS/V"],points),axis = 0) # VDS values for labels
ax1.set_xlabel('$V_{TG} (V)$')
ax1.set_ylabel('$I_{D} (uA/um)$')
ax1.set_yscale('log')
for i in range(points):
ax1.plot(x[i],y[i],label = f"VDS:{labels[i]}V")
# Adding title
fig.suptitle('Transfer Curve', fontweight ="bold")
fig.legend()
fig.tight_layout()
display(fig)
# Save the results
default_filename = f"{sample['sample'].value}_{sample['field'].value}_{sample['device'].value}_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()
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:{sample['processing_number'].value}"+"\n")
f.write(f"Sample:{sample['sample'].value}"+"\n")
f.write(f"Field:{sample['field'].value}"+"\n")
f.write(f"Device:{sample['device'].value}"+"\n")
f.write(f"Device Width/um:{sample['width'].value}"+"\n")
f.write("Sweeping Gate:VTG"+"\n\n")
f.write('Parameters\n')
f.write(f"VTG from {VTG['start'].value}V to {VTG['stop'].value}V with step {VTG['step'].value}V"+"\n")
f.write(f"VDS from {VDS['start'].value}V to {VDS['stop'].value}V with step {VDS['step'].value}V"+"\n")
if VTG['pcomp'].value==0:
f.write(f"Top Gate Current Compliance/A:{VTG['comp'].value}"+"\n")
else:
f.write(f"Top Gate Power Compliance/A:{VTG['pcomp'].value}"+"\n")
if VDS['pcomp'].value == 0:
f.write(f"Drain Current Compliance/A:{VDS['comp'].value}"+"\n")
else:
f.write(f"Drain Power Compliance/A:{VDS['pcomp'].value}"+"\n")
f.write(f'Integration Time:{integration}'+"\n")
f.write("\nResults\n")
df.to_csv(file,sep=" ",mode='a')
return df
# Transfer only VBG
def transfer_VBG(VBG,VDS,integration,sample,device):
smu1 = device.smu_dict()
smu1.update(vname = 'VTG',iname='ITG',mode = 'V',func='COMM')
smu2 = device.smu_dict()
smu2.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR2')
smu3 = device.smu_dict() smu3 = device.smu_dict()
smu3.update(vname='VBG',iname ='IBG',mode='V',func='VARD') smu3.update(vname = 'VBG',iname='IBG',mode = 'V',func = 'VAR1')
variables_list=["VTG","ITG","VDS","ID","VBG","IBG"] smu4 = device.smu_dict()
smu4.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS')
device.setup_smu(1,smu1) device.setup_smu(1,smu1)
device.setup_smu(2,smu2) device.setup_smu(2,smu2)
device.setup_smu(3,smu3) device.setup_smu(3,smu3)
device.setup_smu(4,smu4) device.setup_smu(1,smu4)
var1 = device.var1_dict()
var1.update(
mode=VBG['hyst'].value,
start=VBG['start'].value,
stop=VBG['stop'].value,
step=VBG['step'].value,
comp =VBG['comp'].value,
pcomp=VBG['pcomp'].value
)
device.setup_var1(var1)
device.setup_var1(config["VAR1"]) points = number_of_points(VDS)
device.setup_var2(config["VAR2"])
if config["mode"]=='BOTH'
device.setup_vard(config["VARD"])
device.integration_time(config["integration"]) var2=device.var2_dict()
var2.update(
start=VDS['start'].value,
step=VDS['step'].value,
points=points,
comp=VDS['comp'].value,
pcomp=VDS['pcomp'].value
)
device.setup_var2(var2)
device.integration_time(integration)
device.display_mode("LIST") device.display_mode("LIST")
variables_list =["VBG","IBG","VDS","ID"]
device.variables_to_save(variables_list) device.variables_to_save(variables_list)
device.single_measurement() device.single_measurement()
while device.operation_completed()==False: while device.operation_completed()==False:
pass pass
values = dict([(variable,device.return_values(variable)) for variable in variables_list]) values = dict([(variable,device.return_values(variable)) for variable in variables_list])
df = get_dataframe_from_results(values) df = get_dataframe_from_results(values)
df["IDmm/uA/um"]= df["ID/A"]*config["norm"]
points = config["VAR2"]["Points"]
if 'ITG' in variables_list: # calculate normalization factor
df["ITGmm/uA/um"]= df["ITG/A"]*config["norm"] norm = normalization_factor(sample["width"].value)
if 'IBG' in variables_list: # Append the normalized current
df["IBGmm/uA/um"]= df["IBG/A"]*config["norm"] df["IDmm/uA/um"]= df["ID/A"]*norm
df["IBGmm/uA/um"]= df["IBG/A"]*norm
VDS = np.array_split(df["VDS/V"],points) # Plot normalized Results VTG-IDmm
IDmm = np.array_split(df["IDmm/uA/um"].abs(),points)
fig,ax1= plt.subplots() fig,ax1= plt.subplots()
# Plot results x = np.array_split(df["VBG/V"],points)
if config["mode"]=='VTG': y = np.array_split(df["IDmm/uA/um"].abs(),points)
VTG = np.array_split(df["VTG/V"],points) labels =np.mean(np.array_spilt(df["VDS/V"],points),axis = 0) # VDS values for labels
ax1.set_xlabel('$V_{TG} (V)$')
ax1.set_ylabel('$I_{D} (uA/um)$')
ax1.set_yscale('log')
for i in range(points):
ax1.plot(VTG[i],IDmm[i],label = f"VDS:{np.mean(VDS[i])}V")
elif config["mode"]=='VBG':
VBG = np.array_split(df["VBG/V"],points)
ax1.set_xlabel('$V_{BG} (V)$') ax1.set_xlabel('$V_{BG} (V)$')
ax1.set_ylabel('$I_{D} (uA/um)$') ax1.set_ylabel('$I_{D} (uA/um)$')
ax1.set_yscale('log') ax1.set_yscale('log')
for i in range(points): for i in range(points):
ax1.plot(VBG[i],IDmm[i],label = f"VDS:{np.mean(VDS[i])}V") ax1.plot(x[i],y[i],label = f"VDS:{labels[i]}V")
else: #both
VTG = np.array_split(df["VTG/V"],points) # Adding title
VBG = np.array_split(df["VBG/V"],points) fig.suptitle('Transfer Curve', fontweight ="bold")
fig.legend()
fig.tight_layout()
display(fig)
# Save the results
default_filename = f"{sample['sample'].value}_{sample['field'].value}_{sample['device'].value}_BACK_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()
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:{sample['processing_number'].value}"+"\n")
f.write(f"Sample:{sample['sample'].value}"+"\n")
f.write(f"Field:{sample['field'].value}"+"\n")
f.write(f"Device:{sample['device'].value}"+"\n")
f.write(f"Device Width/um:{sample['width'].value}"+"\n")
f.write("Sweeping Gate:VBG"+"\n\n")
f.write('Parameters\n')
f.write(f"VBG from {VBG['start'].value}V to {VBG['stop'].value}V with step {VTG['step'].value}V"+"\n")
f.write(f"VDS from {VDS['start'].value}V to {VDS['stop'].value}V with step {VDS['step'].value}V"+"\n")
#calculate the values
if VBG['pcomp'].value==0:
f.write(f"Back Gate Current Compliance/A:{VBG['comp'].value}"+"\n")
else:
f.write(f"Back Gate Power Compliance/A:{VBG['pcomp'].value}"+"\n")
if VDS['pcomp'].value == 0:
f.write(f"Drain Current Compliance/A:{VDS['comp'].value}"+"\n")
else:
f.write(f"Drain Power Compliance/A:{VDS['pcomp'].value}"+"\n")
f.write(f'Integration Time:{integration}'+"\n")
f.write("\nResults\n")
df.to_csv(file,sep=" ",mode='a')
return df
def Transfer_BOTH(VTG,VBG,VDS,integration,sample,device):
smu1 = device.smu_dict()
smu1.update(vname = 'VTG',iname='ITG',mode = 'V',func='VAR1')
smu2 = device.smu_dict()
smu2.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR2')
smu3 = device.smu_dict()
smu3.update(vname = 'VBG',iname='IBG',mode = 'V',func = 'VARD')
smu4 = device.smu_dict()
smu4.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS')
device.setup_smu(1,smu1)
device.setup_smu(2,smu2)
device.setup_smu(3,smu3)
device.setup_smu(1,smu4)
var1 = device.var1_dict()
var1.update(
mode=VTG['hyst'].value,
start=VTG['start'].value,
stop=VTG['stop'].value,
step=VTG['step'].value,
comp =VTG['comp'].value,
pcomp=VTG['pcomp'].value
)
device.setup_var1(var1)
points = number_of_points(VDS)
var2=device.var2_dict()
var2.update(
start=VDS['start'].value,
step=VDS['step'].value,
points=points,
comp=VDS['comp'].value,
pcomp=VDS['pcomp'].value
)
device.setup_var2(var2)
#calculate parameters for VARD
ratio,offset = calculate_line(VTG,VBG)
# update VBG step
VBG["step"].value = ratio * VBG["step"].value
vard = device.vard_dict()
vard.update(
offset = offset,
ratio = ratio,
comp = VBG["comp"].value,
pcomp = VBG["pcomp"].value
)
device.setup_vard(vard)
device.integration_time(integration)
device.display_mode("LIST")
variables_list =["VBG","IBG","VDS","ID","VTG","ITG"]
device.variables_to_save(variables_list)
device.single_measurement()
while device.operation_completed()==False:
pass
values = dict([(variable,device.return_values(variable)) for variable in variables_list])
df = get_dataframe_from_results(values)
# calculate normalization factor
norm = normalization_factor(sample["width"].value)
# Append the normalized current
df["IDmm/uA/um"]= df["ID/A"]*norm
df["IBGmm/uA/um"]= df["IBG/A"]*norm
df["ITGmm/uA/um"]= df['ITG']*norm
# Plot normalized Results VTG-IDmm
fig,ax1= plt.subplots()
x1 = np.array_split(df["VBG/V"],points)
y = np.array_split(df["IDmm/uA/um"].abs(),points)
x2 = np.array_spilt(df["VTG/V"],points)
labels =np.mean(np.array_spilt(df["VDS/V"],points),axis = 0) # VDS values for labels
ax1.set_xlabel('$V_{BG} (V)$') ax1.set_xlabel('$V_{BG} (V)$')
ax1.set_ylabel('$I_{D} (uA/um)$') ax1.set_ylabel('$I_{D} (uA/um)$')
ax1.set_yscale('log') ax1.set_yscale('log')
for i in range(points): for i in range(points):
ax1.plot(VBG[i],IDmm[i],label = f"VDS:{np.mean(VDS[i])}V") ax1.plot(x1[i],y[i],label = f"VDS:{labels[i]}V")
#set opposite x axis # add opposite x axis
ax2 = ax1.twinx() ax2 = ax1.twiny()
ax2.set_xlabel('$V_{TG} (V)$') ax2.set_xlabel('$V_{TG} (V)$')
for i in range(points): for i in range(points):
ax2.plot(VTG[i],IDmm[i]) ax2.plot(x2[i],y[i])
# Adding title # Adding title
fig.suptitle('Transfer Curve', fontweight ="bold") fig.suptitle('Transfer Curve', fontweight ="bold")
...@@ -143,9 +389,63 @@ def Transfer(config,device): ...@@ -143,9 +389,63 @@ def Transfer(config,device):
fig.tight_layout() fig.tight_layout()
display(fig) display(fig)
return df
# Save the results
default_filename = f"{sample['sample'].value}_{sample['field'].value}_{sample['device'].value}_BOTH_GATES_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()
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:{sample['processing_number'].value}"+"\n")
f.write(f"Sample:{sample['sample'].value}"+"\n")
f.write(f"Field:{sample['field'].value}"+"\n")
f.write(f"Device:{sample['device'].value}"+"\n")
f.write(f"Device Width/um:{sample['width'].value}"+"\n")
f.write("Sweeping Gates:VBG,VTG"+"\n\n")
f.write('Parameters\n')
f.write(f"VBG from {VBG['start'].value}V to {VBG['stop'].value}V with step {VBG['step'].value}V"+"\n")
f.write(f"VTG from {VTG['start'].value}V to {VTG['stop'].value}V with step {VTG['step'].value}V"+"\n")
f.write(f"VDS from {VDS['start'].value}V to {VDS['stop'].value}V with step {VDS['step'].value}V"+"\n")
#calculate the values
if VBG['pcomp'].value==0:
f.write(f"Back Gate Current Compliance/A:{VBG['comp'].value}"+"\n")
else:
f.write(f"Back Gate Power Compliance/A:{VBG['pcomp'].value}"+"\n")
if VTG['pcomp'].value==0:
f.write(f"Top Gate Current Compliance/A:{VTG['comp'].value}"+"\n")
else:
f.write(f"Top Gate Power Compliance/A:{VTG['pcomp'].value}"+"\n")
if VDS['pcomp'].value == 0:
f.write(f"Drain Current Compliance/A:{VDS['comp'].value}"+"\n")
else:
f.write(f"Drain Power Compliance/A:{VDS['pcomp'].value}"+"\n")
f.write(f'Integration Time:{integration}'+"\n")
f.write("\nResults\n")
df.to_csv(file,sep=" ",mode='a')
return df
def Output(config,device): def Output(config,device):
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
{ {
"data": { "data": {
"application/vnd.jupyter.widget-view+json": { "application/vnd.jupyter.widget-view+json": {
"model_id": "bd255b2a4fa44ffc81415a0fc7b31db5", "model_id": "99771e380b9e41e1bfb264445c9638b5",
"version_major": 2, "version_major": 2,
"version_minor": 0 "version_minor": 0
}, },
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
{ {
"data": { "data": {
"application/vnd.jupyter.widget-view+json": { "application/vnd.jupyter.widget-view+json": {
"model_id": "255f18a4397845dcac07e5b2f7f05012", "model_id": "bf6c9f74778f4a7d81d2e50e50f29646",
"version_major": 2, "version_major": 2,
"version_minor": 0 "version_minor": 0
}, },
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
{ {
"data": { "data": {
"application/vnd.jupyter.widget-view+json": { "application/vnd.jupyter.widget-view+json": {
"model_id": "4f1eaa6498994c99b1f9143b0d3ac60a", "model_id": "e309adbb7d1d4f368b10a2007a9b2787",
"version_major": 2, "version_major": 2,
"version_minor": 0 "version_minor": 0
}, },
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
{ {
"data": { "data": {
"application/vnd.jupyter.widget-view+json": { "application/vnd.jupyter.widget-view+json": {
"model_id": "5646c807fb214670ab6322a989f0c83f", "model_id": "529852ccf3c342b7909d07c05e4094df",
"version_major": 2, "version_major": 2,
"version_minor": 0 "version_minor": 0
}, },
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
{ {
"data": { "data": {
"application/vnd.jupyter.widget-view+json": { "application/vnd.jupyter.widget-view+json": {
"model_id": "4f87449e353e4236943096bceea9c2fe", "model_id": "b88a1fddf7d84747b34b69c7c54b6004",
"version_major": 2, "version_major": 2,
"version_minor": 0 "version_minor": 0
}, },
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment