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

Debugging Part 1 (Day 1)

parent c9d3990c
No related branches found
No related tags found
No related merge requests found
%% Cell type:code id:8faef648-e31f-48c5-a101-d6070b2d1990 tags:
``` python
import sys
sys.path.insert(0, './lib')
sys.path.insert(0, '..') #append parent directory
import os
import configparser
import warnings
from interface import *
from help import *
import hp4155a
first_page = page_1()
second_page = page_2()
third_page = page_3()
fourth_page = page_4()
fifth_page = page_5()
titles = ["SMUs","User Functions","Parameters","Plotting","Save to file"]
children = [first_page,second_page,third_page,fourth_page,fifth_page]
tab = widgets.Tab()
tab.children = children
tab.titles = titles
display(tab)
start = widgets.Button(description='Start Measurement')
ini = widgets.Button(description = 'Import from ini.')
output = widgets.Output()
display(widgets.HBox([start,ini]),output)
device = hp4155a.HP4155a('GPIB0::17::INSTR')
def on_start_clicked(b):
with output:
clear_output()
change_state(first_page,second_page,third_page,fourth_page,fifth_page)
start.disabled = True
ini.disabled = True
# Reset the device
device.reset()
# Step 1 create the dictionaries appropriately for every measurement
# read general information
measurement_mode = third_page[0,0].value
measurement_name = fifth_page[0,0].value
processing_nr = fifth_page[1,0].value
sample_series = fifth_page[2,0].value
field = fifth_page[3,0].value
dut = fifth_page[4,0].value
integration = third_page[0,1].value
# we need constant smus for all measurements
# Constant Smus
cons_smus = []
for j in range(1,5):
cons_smus.append(create_dict(value = third_page[21,j].value,comp=third_page[22,j].value))
# 2nd page
user_functions = []
#iterate over the rows
for i in range(1,7):
if second_page[i,0].value!="": # do not save user functions without names
user_functions.append(
create_dict(
name = second_page[i,0].value,
unit=second_page[i,1].value,
expression = second_page[i,2].value
)
)
# Page 4
axes = [] # 0 is x-axis , 1 is y1-axis and 2 is y2-axis
for j in range(1,4): #iterate over the column
axes.append(
create_dict(
name = fourth_page[1,j].value,
scale = fourth_page[2,j].value,
min =fourth_page[3,j].value,
max = fourth_page[4,j].value
)
)
# Page 5
variables = []
for i in range(8):
if fifth_page[6+i,0].value!="": # do not save empty rows
variables.append(
create_dict(
name = fifth_page[6+i,0].value,
unit =fifth_page[6+i,1].value
)
)
# first sweep
if measurement_mode == 'SWEEP':
#page 1
smus = []
#iterate over the rows
for i in range(1,5):
smus.append(
create_dict(
vname = first_page[i,1].value,
iname = first_page[i,2].value,
mode = first_page[i,3].value,
func = first_page[i,4].value,
disabled = first_page[i,5].value
)
)
# Page 3
#match hysteris checkbox with the command forwarded to the tool
if third_page[9,0].value == True:
hyst = 'DOUB'
else:
hyst = 'SING'
var1 = create_dict(
start = third_page[4,0].value,
stop = third_page[5,0].value,
step = third_page[6,0].value,
comp = third_page[7,0].value,
pcomp =third_page[8,0].value,
mode = hyst
)
var2 = create_dict(
start = third_page[4,1].value,
step = third_page[5,1].value,
points = third_page[6,1].value,
comp = third_page[7,1].value,
pcomp=third_page[8,1].value
)
vard = create_dict(
offset=third_page[4,2].value,
ratio = third_page[5,2].value,
comp = third_page[7,2].value,
pcomp=third_page[8,2].value
)
pulse = create_dict(
period=third_page[4,3].value,
width = third_page[5,3].value,
base = third_page[6,3].value
)
# Now execute measurement
#setup sweep measurement mode
device.measurement_mode('SWE')
#disable all irrelevant units
device.disable_not_smu()
# First Setup Smus
for i,smu in enumerate(smus):
if smu['disabled'] == False:
device.setup_smu(i+1,smu)
else: #disabled
device.smu_disable(i+1)
# Setup User Functions
for user_function in user_functions:
device.user_function(user_function['name'],user_function['unit'],user_function['expression'])
# Set the integration time
device.integration_time(integration)
# Setup VAR1 (always in sweep measurements)
device.setup_var1(var1) # device will check for errors
# Now set the 3 additional columns
if check_sweep_func(smus,'VAR2') == True:
device.setup_var2(var2)
if check_sweep_func(smus,'VARD') == True:
device.setup_vard(vard)
if check_sweep_pulse(smus)== True:
device.setup_pulse(pulse)
# Check for constant SMUs but not grounded
cons_smu_numbers = check_sweep_cons(smus)
for i, cons_smu in enumerate(cons_smus):
if i+1 in cons_smu_numbers: # check if the constant smu was found in the first page func
device.setup_cons_smu(i+1,cons_smu)
# Now set the axes
setup_axes(axes,device)
# Set the variables to be saved (This function has an exemption)
try:
save_variables(axes,variables,device)
except Exception as e:
error_box(e)
change_state(first_page,second_page,third_page,fourth_page,fifth_page)
start.disabled = False
ini.disabled = False
return
# Start the measurement
device.single_measurement()
while device.operation_completed()==False:
pass
device.autoscaling()
# List all errors occured
counter,message = device.list_all_errors()
if counter>1:
error_box(message)
change_state(first_page,second_page,third_page,fourth_page,fifth_page)
start.disabled = False
ini.disabled = False
return
# Get the data from the device
# These are correcly defined and include the plotted ones
values = {}
for variable in variables:
key = f"{variable['name']} ({variable['unit']})"
values[key] = device.return_values(variable['name'])
plot_results(values,device)
# Save results
df = pd.DataFrame(values)
filename = f"{sample_series}_{field}_{dut}_{measurement_name}.txt"
txt_file = create_file(filename)
ini_file = os.path.splitext(txt_file)[0]+'.ini'
with open(txt_file,'w') as f:
date = str(datetime.today().replace(microsecond=0))
f.write(f"{measurement_name} (sweep) at {date}:"+"\n")
f.write("Sample Information\n")
f.write(f"Processing Number:{processing_nr}"+"\n")
f.write(f"Sample Series:{sample_series}"+"\n")
f.write(f"Field:{field}"+"\n")
f.write(f"DUT:{dut}"+"\n")
f.write("\n")
f.write(f"Measurement parameters can be found at: {ini_file}"+"\n")
f.write("\nResults\n")
df.to_csv(txt_file,sep=" ",mode='a')
# export interface to ini file
# First the Smus
config = configparser.ConfigParser()
with open(ini_file,'w') as configfile:
config.add_section("THESE ARE THE PARAMETERS OF THE CORRESPONDING MEASUREMENT")
config.add_section("THE WHOLE INTERFACE IS SAVED SO FIND WHAT YOU NEED")
config.add_section("DO NOT MODIFY THIS FILE")
config.add_section(f"MEASUREMENT MODE: {measurement_mode}")
config.add_section(f"INTEGRATION TIME: {integration}")
# First the smus
config.add_section("SMUS")
for i, smu in enumerate(smus):
config.add_section(f"SMU{i+1}")
for key,value in smu.items():
config.set(f"SMU{i+1}",key,value)
# Secondly the user functions
config.add_section("USER FUNCTIONS")
for i, user_function in enumerate(user_functions):
config.add_section(f"USER FUNCTION {i+1}")
for key,value in user_function.items():
config.set(f"USER FUNCTION {i+1}",key,value)
# Then the 3rd page
config.add_section("VAR1")
for key,value in var1.items():
config.set("VAR1",key,value)
config.add_section("VAR2")
for key,value in var2.items():
config.set("VAR2",key,value)
config.add_section("VARD")
for key, value in vard.items():
config.set("VARD",key,value)
config.add_section("PULSE")
for key,value in pulse.items():
config.set("PULSE",key,value)
# Now The constant smus
config.add_section('CONSTANT SMUS')
for i, cons_smu in enumerate(cons_smus):
config.add_section(f"CONSTANT SMU{i+1}")
for key, value in cons_smu.items():
config.set(f"CONSTANT SMU{i+1}",key,value)
# Page 4 The axes
config.add_section('AXES')
for i,axis in enumerate(axes):
config_add_section(f"AXIS {i+1}")
for key,value in axis.items():
config.set(f"AXIS {i+1}",key,value)
# Page 5 The varibles
config.add_section("SAVED VARIABLES")
for i, variable in enumerate(variables):
config.add_section(f"VARIABLE {i+1}")
for key,value in variable.items():
config.set(f"VARIABLE {i+1}",key,value)
config.write(configfile)
# Sampling Measurement Mode
elif measurement_mode=='SAMPLING':
# sampling parameters
parameters= create_dict(
mode=third_page[12,0].value,
interval=third_page[13,0].value,
hold=third_page[16,0].value,
points=third_page[14,0].value,
filter=int(third_page[17,0].value)
)
duration = third_page[13,0].value
# Set the smus all constant
#page 1
smus = []
#iterate over the rows and set the function to constant
for i in range(1,5):
smus.append(
create_dict(
vname = first_page[i,1].value,
iname = first_page[i,2].value,
mode = first_page[i,3].value,
func = 'CONS',
disabled = first_page[i,5].value
)
)
# Now start the measurement
device.measurement_mode('SAMP')
#disable all irrelevant units
device.disable_not_smu()
# First Setup Smus
for i,smu in enumerate(smus):
if smu['disabled'] == False:
device.setup_smu(i+1,smu)
else: #disabled
device.smu_disable(i+1)
# Setup User Functions
for user_function in user_functions:
device.user_function(user_function['name'],user_function['unit'],user_function['expression'])
# Set the integration time
device.integration_time(integration)
# Set the sampling parameters
device.setup_sampling(parameters)
# Set the total sampling time
if duration<= 0:
warnings.warn("Non positive measurement duration. Auto Sampling time will be set")
device.auto_sampling_time(1)
else:
device.total_sampling_time(duration)
# Setup the constant SMUs
cons_smu_numbers = check_cons_smu_sampling(smus)
for i, cons_smu in enumerate(smus):
if i+1 in cons_smu_numbers: # check if the constant smu was found in the first page func
device.setup_smu_sampling(i+1,cons_smu)
# Set integration time
device.intergration_time(integration_time)
# Now set the axes
setup_axes(axes,device)
# Set the variables to be saved (This function has an exemption)
try:
save_variables(axes,variables,device)
except Exception as e:
error_box(e)
change_state(first_page,second_page,third_page,fourth_page,fifth_page)
start.disabled = False
ini.disabled = False
return
# Start the measurement
device.single_measurement()
while device.operation_completed()==False:
pass
device.autoscaling()
# List all errors occured
counter,message = device.list_all_errors()
if counter>1:
error_box(message)
change_state(first_page,second_page,third_page,fourth_page,fifth_page)
start.disabled = False
ini.disabled = False
return
# Get the data from the device
# These are correcly defined and include the plotted ones
values = {}
for variable in variables:
key = f"{variable['name']} ({variable['unit']})"
values[key] = device.return_values(variable['name'])
plot_results(values,device)
# Save results
df = pd.DataFrame(values)
filename = f"{sample_series}_{field}_{dut}_{measurement_name}_sampling.txt"
txt_file = create_file(filename)
ini_file = os.path.splitext(txt_file)[0]+'.ini'
with open(txt_file,'w') as f:
date = str(datetime.today().replace(microsecond=0))
f.write(f"{measurement_name} (sampling) at {date}:"+"\n")
f.write("Sample Information\n")
f.write(f"Processing Number:{processing_nr}"+"\n")
f.write(f"Sample Series:{sample_series}"+"\n")
f.write(f"Field:{field}"+"\n")
f.write(f"DUT:{dut}"+"\n")
f.write("\n")
f.write(f"Measurement parameters can be found at: {ini_file}"+"\n")
f.write("\nResults\n")
df.to_csv(txt_file,sep=" ",mode='a')
# export interface to ini file
# First the Smus
config = configparser.ConfigParser()
with open(ini_file,'w') as configfile:
config.add_section("THESE ARE THE PARAMETERS OF THE CORRESPONDING MEASUREMENT")
config.add_section("THE WHOLE INTERFACE IS SAVED SO FIND WHAT YOU NEED")
config.add_section("DO NOT MODIFY THIS FILE")
config.add_section(f"MEASUREMENT MODE: {measurement_mode}")
config.add_section(f"INTEGRATION TIME: {integration}")
# First the smus
config.add_section("SMUS")
for i, smu in enumerate(smus):
config.add_section(f"SMU{i+1}")
for key,value in smu.items():
config.set(f"SMU{i+1}",key,value)
# Secondly the user functions
config.add_section("USER FUNCTIONS")
for i, user_function in enumerate(user_functions):
config.add_section(f"USER FUNCTION {i+1}")
for key,value in user_function.items():
config.set(f"USER FUNCTION {i+1}",key,value)
# Then the 3rd page
config.add_section('SAMPLING PARAMETERS')
for key,value in parameters.items():
config.set('SAMPLING PARAMETERS',key,value)
# Now the constant smus
config.add_section('CONSTANT SMUS')
for i, cons_smu in enumerate(cons_smus):
config.add_section(f"CONSTANT SMU{i+1}")
for key, value in cons_smu.items():
config.set(f"CONSTANT SMU{i+1}",key,value)
# Page 4 The axes
config.add_section('AXES')
for i,axis in enumerate(axes):
config_add_section(f"AXIS {i+1}")
for key,value in axis.items():
config.set(f"AXIS {i+1}",key,value)
# Page 5 The varibles
config.add_section("SAVED VARIABLES")
for i, variable in enumerate(variables):
config.add_section(f"VARIABLE {i+1}")
for key,value in variable.items():
config.set(f"VARIABLE {i+1}",key,value)
config.write(configfile)
else: # Stress
#page 1
smus = []
#iterate over the rows and set the function to constant
for i in range(1,5):
# Set SYNC non SYNC mode
mode= first_page[i,3].value
if mode != 'COMM':
func = 'SYNC'
else:
func = 'NSYNC'
smus.append(
create_dict(
name = first_page[i,1].value,
mode = mode,
func = func,
disabled = first_page[i,5].value
)
)
# Now define the parameters
duration = third_page[13,0].value
if duration <= 0:
error_box("Stress Time should be positive!")
change_state(first_page,second_page,third_page,fourth_page,fifth_page)
return
hold_time = third_page[16,0].value
filter = int(third_page[17,0].value)
# Now start the measurement
device.stress_page()
device.stress_disable_not_smu()
# First Setup Smus
for i,smu in enumerate(smus):
if smu['disabled'] == False:
device.smu_stress(i+1,smu)
else: #disabled
device.smu_stress_disable(i+1)
# Now set the Parameters
device.stress_filter(filter)
device.hold_time(hold_time)
device.stress_time(duration)
cons_smu_numbers = check_cons_smu_sampling(smus) # works also for sampling
for i, cons_smu in enumerate(smus):
if i+1 in cons_smu_numbers: # check if the constant smu was found in the first page func
device.setup_smu_stress(i+1,cons_smu)
# Now start the measurement
device.start_stress()
while device.operation_completed() == False:
pass
# List all errors occured
counter,message = device.list_all_errors()
if counter>1:
error_box(message)
change_state(first_page,second_page,third_page,fourth_page,fifth_page)
start.disabled = False
ini.disabled = False
return
filename = f"{sample_series}_{field}_{dut}_{measurement_name}_sweep.txt"
txt_file = create_file(filename)
ini_file = os.path.splitext(txt_file)[0]+'.ini'
with open(txt_file,'w') as f:
date = str(datetime.today().replace(microsecond=0))
f.write(f"{measurement_name} (Stress) at {date}:"+"\n")
f.write("Sample Information\n")
f.write(f"Processing Number:{processing_nr}"+"\n")
f.write(f"Sample Series:{sample_series}"+"\n")
f.write(f"Field:{field}"+"\n")
f.write(f"DUT:{dut}"+"\n")
f.write("\n")
f.write(f"Measurement parameters can be found at: {ini_file}"+"\n")
f.write("\nNo Results Available\n")
#export the interface to ini file
config = configparser.ConfigParser()
with open(ini_file,'w') as configfile:
config.add_section("THESE ARE THE PARAMETERS OF THE CORRESPONDING MEASUREMENT")
config.add_section("THE WHOLE INTERFACE IS SAVED SO FIND WHAT YOU NEED")
config.add_section("DO NOT MODIFY THIS FILE")
config.add_section(f"MEASUREMENT MODE: {measurement_mode}")
# First the smus
config.add_section("SMUS")
for i, smu in enumerate(smus):
config.add_section(f"SMU{i+1}")
for key,value in smu.items():
config.set(f"SMU{i+1}",key,value)
config.add_section('PARAMETERS')
config.set('PARAMETERS', "STRESS TIME",duration)
config.set('PARAMETERS', "HOLD TIME",hold_time)
config.set('PARAMETERS', "FILTER",filter)
# Now the constant smus
config.add_section('CONSTANT SMUS')
for i, cons_smu in enumerate(cons_smus):
config.add_section(f"CONSTANT SMU{i+1}")
for key, value in cons_smu.items():
config.set(f"CONSTANT SMU{i+1}",key,value)
config.write(configfile)
# End of fuction
information_box("Measurement finished!")
change_state(first_page,second_page,third_page,fourth_page,fifth_page)
start.disabled = False
ini.disabled = False
return # just to be sure
# This should be tested at the end.
# After the ini files have been created
"""
def on_ini_clicked(b):
with output:
clear_output()
change_state(first_page,second_page,third_page,fourth_page,fifth_page)
start.disabled = True
ini.disabled = True
#load values to the interface
config = configparser.ConfigParser()
try:
file = load_ini()
except Exception as e:
error_box(e)
change_state(first_page,second_page,third_page,fourth_page,fifth_page)
start.disabled = False
ini.disabled = False
return
try:
# Now we do exactly the opposite thing dictionaries to widgets
#read the values from each section
config.read(file)
# Get the sections
sections = config.sections()
# Get the measurement Mode
measurement_mode = get_mode(sections)
# Get the constant smus
for j in range(1,5):
third_page[21,j].value = config.get(f"CONSTANT SMU{j}",'value')
third_page[22,j].value = config.get(f"CONSTANT SMU{j}",'comp')
if measurement_mode == 'SWEEP':
third_page[0,0].value = measurement_mode
third_page[0,1].value = get_integration(sections)
"""
start.on_click(on_start_clicked)
```
%% Output
%% Cell type:code id:a40693da-961a-434d-89f5-6443c0acb517 tags:
``` python
%run main.py
```
%% Output
%% Cell type:code id:62768354-a7ff-4f1c-b26a-27fdb88bd545 tags:
%% Cell type:code id:b4134f36-9202-45f5-ad20-b71dfc315edd tags:
``` python
```
......
......@@ -4,26 +4,27 @@ import pandas as pd
import matplotlib.pyplot as plt
from IPython.display import clear_output
from datetime import datetime
from tkinter import filedialog
# Check the functionalities of smus VAR1,VAR2 and VARD
def check_sweep_func(smus:list,func:str):
for i, smu in enumerate(smus):
if smu["func"] == func:
if smu["func"] == func and smu["disabled"]== False:
return True
return False
# Check if there is a pulsed smu for sweep smu
def check_sweep_pulse(smus:list):
for smu in smus:
if "PULSE" in smu["mode"]:
return True:
if "PULSE" in smu["mode"] and smu["disabled"]== False:
return True
return False
# Check if there any constant smus and return their numbers
def check_sweep_cons(smus:list):
cons_smu_numbers = []
for i,smu in enumerate(smus):
if smu['func']=='CONS' and smu['mode']!='COMM': # Non Grounded SMUs
if (smu['func']=='CONS' and smu['mode']!='COMM') and smu['disabled']== False: # Non Grounded SMUs
cons_smu_numbers.append(i+1) # for the actual number of smus
return cons_smu_numbers
......@@ -54,7 +55,7 @@ def save_variables(axes,variables,device):
# Retrieve the axes names (variable)
axes_names=[]
for i,ax in enumerate(axes):
if i != 2 and ax['name']!="" # Y2 axis can be left empty
if i != 2 and ax['name']!="": # Y2 axis can be left empty
axes_names.append(ax['name'])
# Now Check if axes names are in the variable names
......@@ -62,11 +63,6 @@ def save_variables(axes,variables,device):
if ax_name not in variable_names:
raise Exception("Plotted Variables should be saved!")
# Now save the variables
variable_names =[]
for variable in variables:
variable_names.append(variable['name'])
# Send the command to tool
device.variables_to_save(variable_names)
......@@ -99,25 +95,36 @@ def information_box(information):
# We plot results: but we will play with the axes!
def plot_results(values,device):
# convert scale from tool to matplotlib
def get_scale(scale):
if scale == 'LIN':
scale = 'linear'
else:
scale = 'log'
return scale
# Get the names of the plotted variables
x_var = device.get_axis_variable('X')
y1_var = device.get_axis_variable('Y1')
y2_var = device.get_axis_variable('Y2') # we will check for the empty
y2_var = device.get_axis_variable('Y2')
# Get the scales of the plotted variables
x_scale = device.get_axis_scale('X') # we will check the response too
x_scale = device.get_axis_scale('X')
x_scale = get_scale(x_scale)
y1_scale = device.get_axis_scale('Y1')
y1_scale = get_scale(y1_scale)
y2_scale = device.get_axis_scale('Y2')
y2_scale = get_scale(y2_scale)
# Find the values that will be plotted
for key, results in value.items():
for key, results in values.items():
if x_var in key: # check if the substring is contained
x_values = results.copy() # This is a list
x_label = key
elif y1_var in key:
y1_values = results.copy()
y1_label = key
elif y2_var in key and y2_var != None:
elif y2_var in key and y2_var !="":
y2_values = results.copy()
y2_label = key
......@@ -132,7 +139,7 @@ def plot_results(values,device):
ax1.scatter(x_values,y1_values,color='y')
ax1.tick_params(axis ='y', labelcolor ='y',which='both')
if y2_var!= None:
if y2_var!= "":
# Adding Twin Axes # Blue color
ax2 = ax1.twinx()
......
......@@ -62,7 +62,7 @@ def on_start_clicked(b):
user_functions = []
#iterate over the rows
for i in range(1,7):
if second_page[i,0]!="": # do not save user functions without names
if second_page[i,0].value!="": # do not save user functions without names
user_functions.append(
create_dict(
name = second_page[i,0].value,
......@@ -184,7 +184,7 @@ def on_start_clicked(b):
# Check for constant SMUs but not grounded
cons_smu_numbers = check_sweep_cons(smus)
for i, cons_smu in enumerate(smus):
for i, cons_smu in enumerate(cons_smus):
if i+1 in cons_smu_numbers: # check if the constant smu was found in the first page func
device.setup_cons_smu(i+1,cons_smu)
......@@ -286,7 +286,7 @@ def on_start_clicked(b):
for key, value in vard.items():
config.set("VARD",key,value)
config.add_section("PULSE"):
config.add_section("PULSE")
for key,value in pulse.items():
config.set("PULSE",key,value)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment