Select Git revision
help_pulse.py 12.52 KiB
import sys
sys.path.insert(0, '..') #append parent directory
import ipywidgets as widgets
import tkinter as tk
from tkinter import filedialog
import tkinter.messagebox
import os
from datetime import datetime
import matplotlib.pyplot as plt
import numpy as np
import module
import time
import pandas as pd
from IPython.display import display, clear_output
#widgets interactivity
def add_widgets_to_list(source_dictionary,target_list):
for widget in source_dictionary.values():
target_list.append(widget)
def check_pulse(dictionary):
#check if number of pulses is ok
if dictionary['pulses'].value < 0:
dictionary['pulses'].value = -dictionary['pulses'].value
elif dictionary['pulses'].value==0:
dictionary['pulses'].value = 1
else:
pass
# Restriction: pulse period ≥ pulse width + 4 ms
if dictionary['period'].value < dictionary['width'].value+4e-3:
dictionary['period'].value = dictionary['width'].value+4e-3
#sweep pulse measurement
def sweep_meas(dictionary,device):
device.del_user_functions()
smu_v = device.smu_dict()
smu_ground = device.smu_dict()
parameters = device.var1_dict()
smu_v.update(
iname = 'I2',
vname = 'V2',
mode = 'VPULSE',
func = 'VAR1'
)
smu_ground.update(
iname ='I4',
vname = 'V4',
mode = 'COMM',
func = 'CONS'
)
parameters.update(
mode ='SING',
start = dictionary['start'].value,
stop = dictionary['stop'].value,
step = (dictionary["stop"].value-dictionary["start"].value)/(dictionary["pulses"].value-1), #define the number of steps given specific pulses
comp = dictionary['comp'].value,
pcomp = 0,
base = dictionary["base"].value,
width = dictionary["width"].value,
period= dictionary["period"].value
)
device.smu_disable(1)
device.smu_disable(3)
device.measurement_mode("SWE")
device.setup_smu(2,smu_v)
device.setup_smu(4,smu_ground)
device.setup_var1(parameters)
device.display_variable("X","V2")
device.axis_scale('X',"LIN")
device.display_variable("Y1",'I2')
device.axis_scale('Y1',"LIN")
device.range_mode(4,"AUTO")
device.range_mode(2,"AUTO")
device.setup_pulse(parameters)
device.integration_time(dictionary["integration"].value)
t0 = time.time()
device.single_measurement()
while device.operation_completed()== False:
pass
t1 = time.time()
# get the execution time
elapsed_time = t1 - t0
device.autoscaling()
I_i=device.return_values("I2")
V_i=device.return_values("V2")
R_i = np.divide(V_i,I_i)
expected_time = dictionary["period"].value*dictionary["pulses"].value
times = (elapsed_time,expected_time)
values = (V_i,I_i,R_i)
return times,values
def plot_sweep_pulse(values):
fig, ax1 = plt.subplots()
color = 'tab:red'
ax1.set_xlabel("V(V)")
ax1.set_ylabel("I(A)",color=color)
ax1.set_yscale('log')
ax1.plot(values[0],np.abs(values[1]),color=color)
ax1.tick_params(axis ='y', labelcolor = color,which = 'both')
# Adding Twin Axes
ax2 = ax1.twinx()
color = 'tab:green'
ax2.set_ylabel("R(Ohm)",color = color)
ax2.plot(values[0],np.abs(values[2]),color = color)
ax2.tick_params(axis ='y', labelcolor = color,which = 'both')
ax2.set_yscale('log')
fig.suptitle("Sweep Pulse Measurement Results")
display(fig)
def save_sweep(folder,sample_dict,values,times,sweep_dict):
filename = f"{sample_dict['series'].value}_{sample_dict['field'].value}_{sample_dict['dut'].value}.txt"
file = os.path.join(folder,filename)
with open(file,"a") as f:
date = str(datetime.today().replace(microsecond=0))
f.write(f"Sweep Pulse Measurement at {date}"+"\n")
f.write(f"period(s):{sweep_dict['period'].value}"+"\n")
f.write(f"width(s):{sweep_dict['width'].value}"+"\n")
f.write(f"base value(V):{sweep_dict['base'].value}"+"\n")
f.write(f"execution time(s):{times[0]}"+"\n")
f.write(f"expected time(s):{times[1]}"+"\n")
f.write(f"number of pulses:{sweep_dict['pulses'].value}"+"\n")
f.write(f"current compliance(A):{sweep_dict['comp'].value}"+"\n")
f.write(f"voltage:{sweep_dict['start'].value}V to {sweep_dict['stop'].value}V"+"\n")
f.write(f"integration time:{sweep_dict['integration'].value}"+"\n\n")
zipped = list(zip(values[0],values[1], values[2]))
df = pd.DataFrame(zipped, columns=['VPULSE(V)', 'IPULSE(A)', 'RPULSE(Ohm)'])
f.write("Results Sweep Pulse:\n")
f.write(df.to_string())
f.write("\n\n\n")
def constant_meas(dictionary,device):
device.del_user_functions()
smu_v = device.smu_dict()
smu_ground = device.smu_dict()
sweep_params = device.var1_dict()
smu_help = device.smu_dict() #this is the uncontacted smu
smu_v.update(
iname = 'I2',
vname = 'V2',
mode = 'V',
func = 'CONS'
)
smu_help.update(
iname = 'I3',
vname = 'V3',
mode = 'VPULSE',
func = 'VAR1'
)
smu_ground.update(
iname ='I4',
vname = 'V4',
mode = 'COMM',
func = 'CONS'
)
sweep_params.update(
mode ='SING',
start = 0,
stop = 10,
step = 10/(dictionary["pulses"].value-1), #define the number of steps given specific pulses
comp = 0.1,
pcomp = 0,
base = dictionary["base"].value,
width = dictionary["width"].value,
period= dictionary["period"].value
)
#the constant smu
cons = {
'value':dictionary["voltage"].value,
'comp':dictionary["comp"].value
}
device.measurement_mode("SWE")
device.smu_disable(1)
device.setup_smu(2,smu_v)
device.setup_smu(3,smu_help)
device.setup_smu(4,smu_ground)
device.setup_var1(sweep_params)
device.setup_pulse(sweep_params)
device.setup_cons_smu(2,cons)
device.user_function('R','OHM','V2/I2')
device.display_variable("X","@INDEX")
device.axis_scale('X',"LIN")
device.display_variable("Y1",'R')
device.axis_scale('Y1',"LIN")
device.range_mode(4,"AUTO")
device.range_mode(2,"AUTO")
device.range_mode(3,"AUTO")
device.integration_time(dictionary["integration"].value)
device.variables_to_save(['@INDEX','V2','I2','R'])
t0 = time.time()
device.single_measurement()
while device.operation_completed()== False:
pass
t1 = time.time()
# get the execution time
elapsed_time = t1 - t0
I_i=device.return_values("I2")
V_i=device.return_values("V2")
R_i = device.return_values('R')
expected_time = dictionary["period"].value*dictionary["pulses"].value
times = (elapsed_time,expected_time)
values = (V_i,I_i,R_i)
device.autoscaling()
return times,values
def plot_constant_pulse(values):
index =[]
for i in range(len(values[0])):
index.append(i+1)
fig, ax1 = plt.subplots()
color = 'tab:red'
ax1.set_xlabel("Index(Pulse number)")
ax1.set_ylabel("I(A)",color=color)
ax1.set_yscale('log')
ax1.plot(index,np.abs(values[1]),color=color,label = "Voltage(V):"+str(min(values[0])))
ax1.tick_params(axis ='y', labelcolor = color,which = 'both')
# Adding Twin Axes
ax2 = ax1.twinx()
color = 'tab:green'
ax2.set_ylabel("R(Ohm)",color = color)
ax2.plot(index,np.abs(values[2]),color=color)
ax2.set_yscale('log')
ax2.tick_params(axis ='y', labelcolor = color,which = 'both')
fig.suptitle("Constant Pulse Measurement Results")
ax1.set_title("Voltage:"+str(min(values[0]))+"V")
display(fig)
def save_constant(folder,sample_dict,values,times,cons_dict):
filename = f"{sample_dict['series'].value}_{sample_dict['field'].value}_{sample_dict['dut'].value}.txt"
file = os.path.join(folder,filename)
with open(file,"a") as f:
date = str(datetime.today().replace(microsecond=0))
f.write(f"Constant Pulse Measurement at {date}"+"\n")
f.write(f"period(s):{cons_dict['period'].value}"+"\n")
f.write(f"width(s):{cons_dict['width'].value}"+"\n")
f.write(f"base value(V):{cons_dict['base'].value}"+"\n")
f.write(f"execution time(s):{times[0]}"+"\n")
f.write(f"expected time(s):{times[1]}"+"\n")
f.write(f"number of pulses:{cons_dict['pulses'].value}"+"\n")
f.write(f"current compliance(A):{cons_dict['comp'].value}"+"\n")
f.write(f"constant voltage:{cons_dict['voltage'].value}V"+"\n")
f.write(f"integration time:{cons_dict['integration'].value}"+"\n\n")
zipped = list(zip(values[0],values[1], values[2]))
df = pd.DataFrame(zipped, columns=['VPULSE(V)', 'IPULSE(A)', 'RPULSE(Ohm)'])
f.write("Results Constant Pulse:\n")
f.write(df.to_string())
f.write("\n\n\n")
#sample interface
style = {'description_width': 'initial'}
def constant_pulse():
voltage = widgets.BoundedFloatText(
value = 10,
min = -100,
max = 100,
step = 1,
description = 'Constant Voltage(V):',
style=style,
)
comp = widgets.BoundedFloatText(
value = 0.1,
min = -0.1,
max = 0.1,
step = 0.01,
description = 'Compliance(A):',
style=style,
)
pulses = widgets.IntText(
value = 100,
description = 'Number of Pulses:',
style=style,
)
period = widgets.BoundedFloatText(
value = 5e-3,
min = 5e-3,
max = 1,
step = 5e-3,
description ='Pulse Period(s):',
style=style,
)
width = widgets.BoundedFloatText(
value = 5e-4,
min = 5e-4,
max = 1e-1,
step= 5e-4,
description ='Pulse Width(s):',
style=style,
)
base = widgets.BoundedFloatText(
value = 0,
min = -100,
max = 100,
step = 1,
description = 'Base Voltage(V):',
style=style
)
integration =widgets.Dropdown(
options=['SHORt', 'MEDium', 'LONG'],
value='MEDium',
description='Integration:',
style=style
)
pulse_parameters = widgets.VBox([pulses,period,width,base])
smu_parameters = widgets.VBox([voltage,comp,integration])
constant_pulse_widgets = widgets.HBox([smu_parameters,pulse_parameters])
constant_pulse_dict = {
'voltage': voltage,
'comp':comp,
'pulses':pulses,
'period':period,
'width':width,
'base':base,
'integration':integration
}
return constant_pulse_widgets,constant_pulse_dict
def sweep_pulse():
start_voltage = widgets.BoundedFloatText(
value = 0,
min = -100,
max = 100,
step = 1,
description = 'Start Voltage(V):',
style=style,
)
stop_voltage = widgets.BoundedFloatText(
value = 15,
min = -100,
max = 100,
step = 1,
description = 'Stop Voltage(V):',
style=style,
)
comp = widgets.BoundedFloatText(
value = 0.1,
min = -0.1,
max = 0.1,
step = 0.01,
description = 'Compliance(A):',
style=style,
)
pulses = widgets.IntText(
value = 100,
description = 'Number of Pulses:',
style=style,
)
period = widgets.BoundedFloatText(
value = 5e-3,
min = 5e-3,
max = 1,
step = 5e-3,
description ='Pulse Period(s):',
style=style,
)
width = widgets.BoundedFloatText(
value = 5e-4,
min = 5e-4,
max = 1e-1,
step= 5e-4,
description ='Pulse Width(s):',
style=style,
)
base = widgets.BoundedFloatText(
value = 0,
min = -100,
max = 100,
step = 1,
description = 'Base Voltage(V):',
style=style
)
integration =widgets.Dropdown(
options=['SHORt', 'MEDium', 'LONG'],
value='MEDium',
description='Integration:',
style=style
)
pulse_parameters = widgets.VBox([pulses,period,width,base])
smu_parameters = widgets.VBox([start_voltage,stop_voltage,comp,integration])
sweep_pulse_widgets = widgets.HBox([smu_parameters,pulse_parameters])
sweep_pulse_dict = {
'start': start_voltage,
'stop':stop_voltage,
'comp':comp,
'pulses':pulses,
'period':period,
'width':width,
'base':base,
'integration':integration
}
return sweep_pulse_widgets,sweep_pulse_dict