diff --git a/hp4155/memristor (Version 4.0)/help.py b/hp4155/memristor (Version 4.0)/help.py deleted file mode 100644 index 97d5da2a6f9ef322e913d490809ed9b8fe229ae1..0000000000000000000000000000000000000000 --- a/hp4155/memristor (Version 4.0)/help.py +++ /dev/null @@ -1,513 +0,0 @@ -""" -This is a python file containing all the important functions for memristor measurement - -Available Functions - -measurements in the HP4155a -plot results -create data frame -ini file decoder -enabing and disabling widgets for jupyter(lists) -""" - -import sys -sys.path.insert(0, '..') #append parent directory - -import hp4155a -import matplotlib.pyplot as plt - -import tkinter as tk -from tkinter import filedialog -import tkinter.messagebox - -import numpy as np -from IPython.display import display, clear_output -import pandas as pd -from datetime import datetime -import ipywidgets as widgets -import time -import os - - -#contact check between two SMUs (i,j) -def contact_check(i,j,device): - smu = [1,2,3,4] - device.measurement_mode('SAMP') - parameters ={ - 'mode' : 'LIN', - 'hold': 0, - 'interval':2e-3, - 'points': 1, - 'filter': 'OFF', - 'value':0.01, #voltage value - 'comp':0.1 #compliance value - } - - device.setup_sampling(parameters) - - device.auto_sampling_time('ON') - device.integration_time('MED') - - smu_v = device.smu_dict() - smu_v.update( - vname = f'V{i}', - iname = f'I{i}', - mode = 'V', - func = 'CONS' - ) - device.setup_smu(i,smu_v) - - smu_ground = device.smu_dict() - smu_ground.update( - vname =f'V{j}', - iname = f'I{j}', - mode = 'COMM', - func='CONS' - ) - device.setup_smu(j,smu_ground) - - #one smu is measuring - #one smu is ground - - #set voltage and compliance - device.setup_smu_sampling(i,parameters) - - #smus to remove - smu_disable = smu.copy() - smu_disable.remove(i) - smu_disable.remove(j) - - for number in smu_disable: - device.smu_disable(number) - - device.user_function(f'R{i}{j}','OHM',f'V{i}/I{i}') - device.display_variable('X','@TIME') - device.display_variable('Y1',f'R{i}{j}') - device.single_measurement() - while device.operation_completed() == False: - time.sleep(2) - - R = device.return_values(f'R{i}{j}')[0] #only the first value - print(f"R{i}{j}:{'{:.2e}'.format(R)} Ohm") - device.del_user_functions() - device.autoscaling() - return R - - -#these are all the sampling checks -def regular_contact_check(device): - resistances = {} - for i in range(1,4): # iterate through smus 1-4 - for j in range(4,i,-1): - """ - We have the following pairs in order - 1-4,1-3,1-2,2-4,2-3,3-4 - """ - R=contact_check(i,j,device) - resistances[f"{i}-{j}"] = R - - #convert dictionary to df - df = pd.DataFrame(resistances.items(), columns=['SMU pair', 'Resistance (Ohm)']) - return df - -def EBL(device): - # EBL are SMUs 1-4 and 2-3 - resistances = {} - for i,j in zip(range(1,3),range(4,2,-1)): #loop simultaneously 1-4,2-3 pairs - R = contact_check(i,j,device) - resistances[f"{i}-{j}"] = R - - #convert dictionary to df - df = pd.DataFrame(resistances.items(), columns=['SMU pair', 'Resistance (Ohm)']) - return df - -def OL(device): - # OL smu 3-4,1-2 - resistances= {} - for i,j in zip(range(3,0,-2),range(4,1,-2)): #loop simultaneously 3-4 , 1-2 pairs - R = contact_check(i,j,device) - resistances[f"{i}-{j}"] = R - - #convert dictionary to df - df = pd.DataFrame(resistances.items(), columns=['SMU pair', 'Resistance (Ohm)']) - return df - -#double sweep from start to stop and then from start to stop -def sweep(start,stop,step,comp,integration,device): #step cannot be negative - if start < stop and step < 0 : - step = -step - elif start > stop and step > 0 : - step = -step - - smu_v = device.smu_dict() - smu_ground = device.smu_dict() - parameters = device.var1_dict() - - smu_v.update( - iname = 'I2', - vname = 'V2', - mode = 'V', - func = 'VAR1' - ) - smu_ground.update( - iname ='I4', - vname = 'V4', - mode = 'COMM', - func = 'CONS' - ) - parameters.update( - mode ='DOUB', - start = start, - stop = stop, - step = step, - comp = comp, - pcomp = 0 - ) - - #disable smus 1 and 3 - device.measurement_mode('SWE') - device.smu_disable(1) - device.smu_disable(3) - - device.setup_smu(2,smu_v) - device.setup_smu(4,smu_ground) - device.setup_var1(parameters) - device.integration_time(integration) - - #display variables - device.display_variable('X','V2') - device.display_variable('Y1','I2') - - #execute measurement - device.single_measurement() - while device.operation_completed()==False: - time.sleep(2) - - device.autoscaling() - - #return values - V=device.return_values('V2') - I=device.return_values('I2') - - #convert the list to np.array to return the absolute values for the logarithmic scale - V = np.array(V) - I = np.array(I) - - #return all values to the function - return V, I - -#sampling check -def sampling_check(voltage,device): - - parameters ={ - 'mode' : 'LIN', - 'hold': 0, - 'interval':2e-3, - 'points': 5, - 'filter': 'OFF', - 'value':voltage, #voltage value - 'comp':0.1 #compliance value - } - smu_v = device.smu_dict() - smu_ground = device.smu_dict() - - - smu_v.update( - iname = 'I2', - vname = 'V2', - mode = 'V', - func = 'CONS' - ) - smu_ground.update( - iname ='I4', - vname = 'V4', - mode = 'COMM', - func = 'CONS' - ) - - device.measurement_mode('SAMP') - device.smu_disable(1) - device.smu_disable(3) - device.setup_smu(2,smu_v) - device.setup_smu(4,smu_ground) - - device.setup_smu_sampling(2,parameters) - device.setup_sampling(parameters) - - device.integration_time('LONG') - - #remove total sampling time - device.auto_sampling_time('ON') - - device.user_function('R','OHM','V2/I2') - - device.display_variable('X','@INDEX') - device.display_variable('Y1','R') - device.single_measurement() - while device.operation_completed() == False: - time.sleep(2) - - index = np.array(device.return_values('@INDEX')) - R = np.array(device.return_values('R')) - R_mean = np.average(R) - device.del_user_functions() - device.autoscaling() - - # Plot the results - fig,ax = plt.subplots() - - ax.set_title(f"Average Resistance(Sampling Check):{'{:.2e}'.format(R_mean)} Ohm") - ax.set_yscale('log') - ax.set_ylabel('Resistance (Ohm)') - ax.set_xlabel('Sampling Index') - ax.set_xticks(index) - ax.scatter(index,np.absolute(R),label = f"Voltage={voltage}V") - ax.legend() - display(fig) - - return R_mean - -#new (retention) -def retention(voltage,period,duration,device): - parameters ={ - 'mode' : 'LIN', - 'hold': 0, - 'interval':2e-3, - 'points': 0, - 'filter': 'OFF', - 'value':voltage, #voltage value - 'comp':0.1 #compliance value - } - smu_v = device.smu_dict() - smu_ground = device.smu_dict() - - smu_v.update( - iname = 'I2', - vname = 'V2', - mode = 'V', - func = 'CONS' - ) - smu_ground.update( - iname ='I4', - vname = 'V4', - mode = 'COMM', - func = 'CONS' - ) - - device.measurement_mode('SAMP') - device.smu_disable(1) - device.smu_disable(3) - device.setup_smu(2,smu_v) - device.setup_smu(4,smu_ground) - - device.setup_smu_sampling(2,parameters) - - device.integration_time('LONG') - device.total_sampling_time(duration) - - if int(duration/period)+1<=10001: - parameters.update(points=int(duration/period)+1) - else: - parameters.update(points = 'MAX') - device.setup_sampling(parameters) - - device.integration_time('MED') - device.user_function('R','OHM','V2/I2') - - - device.display_variable('X','@TIME') - device.display_variable('Y1','R') - device.single_measurement() - while device.operation_completed() == False: - time.sleep(2) - - - TIME = device.return_values('@TIME') - R = device.return_values('R') - TIME = np.array(TIME) - R = np.array(R) - device.del_user_functions() - device.autoscaling() - return TIME,R - - -#plot sweep results -def plot_sweep(x,y,title): - #plot results - fig, (ax1, ax2) = plt.subplots(2,sharex=True,figsize=(8,6)) #the plots share the same x axis - fig.suptitle(title) - ax1.set_title('Linear I') - ax1.set(xlabel='Voltage(V)',ylabel='Current(A)') - ax2.set_title('Logarithmic I') - ax2.set(xlabel='Voltage(V)',ylabel='Current(A)') - ax2.set_yscale('log') - - ax1.plot(x,y) - ax2.plot(x,np.absolute(y)) - fig.tight_layout() - display(fig) - -def plot_retention(x,y): - fig, ax = plt.subplots() - fig.suptitle('Retention') - ax.set(xlabel='time(s)',ylabel='Resistance(Ohm)') - ax.set_yscale('log') - ax.set_xscale('linear') - ax.plot(x,y) - display(fig) - - -def create_data_frame(x,y): - header = ['V(V)','ABSV(V)',"I(A)",'ABSI(A)',"R(Ohm)"] - data = {header[0]:x,header[1]:np.absolute(x),header[2]:y,header[3]:np.absolute(y),header[4]:np.divide(x,y)} - df = pd.DataFrame(data) - return df - -def create_retention_data_frame(x,y): - header = ['Time(s)','R(Ohm)'] - data = {header[0]:x,header[1]:y} - df = pd.DataFrame(data) - return df - - -#write results to file -def write_to_file(file,title:list,df): - #append escape character after each element - index = 1 - while index <= len(title): - title.insert(index,"\n") - index = index+2 - - #write to file - with open(file,'a') as f: - f.writelines(title) - f.write("\n") - f.write(df.to_string()) - f.write("\n\n") - -#### new functions ############## -def disable_widgets(widgets_list): - for widget in widgets_list: - widget.disabled = True - -def change_state(widgets_list): - for widget in widgets_list: - widget.disabled = not widget.disabled - -def enable_widgets(widgets_list): - for widget in widgets_list: - widget.disabled = False - -#a check values function -def check_values(step,set_voltage,reset_voltage): - 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 step > abs(set_voltage) or step > abs(reset_voltage) or step==0:#invalid parameter setting - valid = False - tkinter.messagebox.showerror(message="Invalid parameter setting!") - - #now if the set-reset voltages have the same polarity show a warning - elif set_voltage*reset_voltage>0: - valid = tk.messagebox.askokcancel(message="Set-Reset voltages have the same polarity. Continue?") - - else: - pass - - root.destroy() - return valid - - -def information_box(information): - #open dialog and hide the main window - root = tk.Tk() - root.withdraw() - root.lift() #show window above all other applications - - root.attributes("-topmost", True)#window stays above all other applications - - #display meaagebox - tkinter.messagebox.showinfo(message=information) - root.destroy() - -#choose directory to save measurement results -#and check if you have access -def check_writable(folder): - filename = "test.txt" - file = os.path.join(folder,filename) - - #protection against removing existing file in python - i=1 - while os.path.exists(file): - filename=f"test{i}.txt" - file = os.path.join(folder,filename) - try: - with open(file,'a'): - writable = True - os.remove(file) - except: - writable = False - information_box(f"{folder} is not writable!") - - return writable - -def choose_folder(): - root = tk.Tk() - root.withdraw() - root.lift() #show window above all other applications - - root.attributes("-topmost", True)#window stays above all other applications - - #choose nonemty folder - folder = tk.filedialog.askdirectory() - - while folder == '': - folder = tk.filedialog.askdirectory() - - #check if writable in a while loop - writable=check_writable(folder) - - while writable == False: - #choose a correct folder - folder = tk.filedialog.askdirectory() - - while folder == '': - folder = tk.filedialog.askdirectory() - - #check writable if not repeat - writable=check_writable(folder) - - root.destroy() - return folder - - -def upload_results(source_file,target_file,target_file_dir): - """ - New function (UPLOAD RESULTS) - IMPORTANT FOR ALL MEASUREMENTS - THE RESULTS ARE MOVED FROM SOURCE FILE TO TARGET FILE EVEN LOCALLY - """ - while True: - try: - with (open(source_file,'r') as source,open(target_file,'a') as target): - target.write(source.read()) - os.remove(source_file) - return source_file,target_file,target_file_dir - except: - information_box(f"{target_file} is no longer accessible. Please change directory") - target_file_dir = choose_folder() - filename = os.path.basename(target_file) - target_file =os.path.join(target_file_dir,filename) - #and then try again - - - - - - - \ No newline at end of file diff --git a/hp4155/memristor (Version 4.0)/help_pulse.py b/hp4155/memristor (Version 4.0)/help_pulse.py deleted file mode 100644 index a5195597a879a8520133f809c25e500d4346c8e3..0000000000000000000000000000000000000000 --- a/hp4155/memristor (Version 4.0)/help_pulse.py +++ /dev/null @@ -1,463 +0,0 @@ -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): - 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.display_variable("Y1",'I2') - - 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) - - del device - - 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): - 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.display_variable("Y1",'R') - - 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.del_user_functions() - 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") - -import ipywidgets as widgets - -#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 - - diff --git a/hp4155/memristor (Version 4.0)/memristor.py b/hp4155/memristor (Version 4.0)/memristor.py deleted file mode 100644 index b4530d7a3be729ccf2e88bd9a3d0e3a76fd1cea4..0000000000000000000000000000000000000000 --- a/hp4155/memristor (Version 4.0)/memristor.py +++ /dev/null @@ -1,583 +0,0 @@ -### this is the new memrstor measurement (set and reset as many times as the user wants and full sweeps with a button) -from help import * -import ipywidgets as widgets -from keyboard import add_hotkey,remove_hotkey - -# pulsed libraries -from help_pulse import * - -#create temporary file to store the results localy -temp_file= os.path.join(os.getcwd(),'tempfile.txt') - -# the three naming fields - -sample_series= widgets.Text( - value= '', - placeholder ='Enter text here:', - description = 'sample series:', - style = {'description_width': 'initial'} - ) - -field = widgets.Text( - value= '', - placeholder ='Enter text here:', - description = 'Field:', - style = {'description_width': 'initial'}, - ) - -DUT = widgets.Text( - value= '', - placeholder ='Enter text here:', - description = 'DUT:', - style = {'description_width': 'initial'}, - ) - - -#choose a new folder button -new_folder = widgets.Button(description='change folder') - -image = widgets.Image( - value=open("schematic.png", "rb").read(), - format='png', - width=300, - height=100, -) - -contact_check = widgets.Button(description = 'CONTACT CHECK') -qcc = widgets.Button(description = 'QUICK CONTACT CHECK',layout=widgets.Layout(width='80%'),style={"button_width": "auto"}) -qcc_select = widgets.RadioButtons(description = 'QCC type:',options = ['EBL','OL']) - -vertical1 = widgets.VBox([sample_series,field,DUT,new_folder,contact_check,qcc,qcc_select]) -vertical2 = widgets.VBox([image]) -all_text_boxes = widgets.HBox([vertical1,vertical2]) - - - -#first series of parameters -step = widgets.BoundedFloatText( - value=0.01, - min=0, - max=100, - step=0.01, - description='Step(V):', -) - -integration_time=widgets.Dropdown( - options=['SHORt', 'MEDium', 'LONG'], - value='MEDium', - description='Integration:', - #style = {'description_width': 'initial'}, -) - -sampling=widgets.Checkbox(description='sampling check') - -auto_qcc = widgets.Checkbox( - description = 'Auto QCC after Reset', - style = {'description_width': 'initial'}, - value = True -) - -# THE BUTTONS -#create buttons as it shown in the how_buttons_look -set=widgets.Button(description='SET') -reset=widgets.Button(description='RESET') -full=widgets.Button(description='FULL SWEEP') -number = widgets.BoundedIntText(value=1,min=1,max=sys.maxsize,step=1,description='full sweeps:',disabled=False) #number of measuremts for the full sweep -retention_button=widgets.Button(description='RETENTION') - - - -#parameter boxes -Vset=widgets.BoundedFloatText( - value=1, - min=-100, - max=100, - step=0.1, - description='Voltage(V):', -) - -#parameter buttons -CC_vset=widgets.BoundedFloatText( - value=1e-3, - min=-0.1, - max=0.1, - step=0.01, - description= 'Comp(A):', -) - -#parameter buttons -Vreset=widgets.BoundedFloatText( - value=-1, - min=-100, - max=100, - step=0.1, - description='Voltage(V):', -) - -#parameter buttons -CC_vreset=widgets.BoundedFloatText( - value=1e-3, - min=-0.1, - max=0.1, - step=0.01, - description='Comp(A):', -) - -Vretention=widgets.BoundedFloatText( - value=1, - min=-100, - max=100, - step=1, - description='Voltage(V):', -) - -period=widgets.BoundedFloatText( - value=1, - min=2e-3, - max=65.535, - step=1, - description='Period(s):', -) - -duration=widgets.BoundedFloatText( - value=60, - min=60e-6, - max=1e11, - step=1, - description='Duration(s):', -) - - - -#align a button with a checkbox or integer bounded texts horizontaly -line0=widgets.HBox([step,integration_time,sampling,auto_qcc]) -line1 = widgets.HBox([set,Vset,CC_vset]) -line2 = widgets.HBox([reset,Vreset,CC_vreset]) -line3 = widgets.HBox([full,number]) -line4 = widgets.HBox([retention_button,Vretention,period,duration]) - -#pack them into a single vertical box -all = widgets.VBox([line0,line1,line2,line3,line4]) -output = widgets.Output() - - -#choose folder directory -folder=choose_folder() - - -#display all at the end -display(all_text_boxes) - -cons_widgets,cons_dict = constant_pulse() -sweep_widgets,sweep_dict = sweep_pulse() - -sweep_button = widgets.Button(description = "SWEEP PULSE") -cons_button = widgets.Button(description = "CONSTANT PULSE") - - -children = [all,widgets.VBox([sweep_widgets,sweep_button]),widgets.VBox([cons_widgets,cons_button])] -titles = ["Regular","Sweep Pulse","Constant Pulse"] -tab = widgets.Tab() -tab.children = children -tab.titles = titles - -display(tab,output) - -all_widgets=[sweep_button,cons_button,sample_series,field,DUT,set,reset,full,new_folder,retention_button,contact_check,qcc,qcc_select,Vset,CC_vset,Vreset,CC_vreset,step,integration_time,number,sampling,Vretention,period,duration,auto_qcc] -add_widgets_to_list(cons_dict,all_widgets) -add_widgets_to_list(sweep_dict,all_widgets) - -device = hp4155a.HP4155a('GPIB0::17::INSTR') -device.reset() -device.disable_not_smu() - -def on_contact_check_clicked(b): - global folder,temp_file - with output: - clear_output() - change_state(all_widgets) - device.inst.lock_excl() - - filename=f"{sample_series.value}_{field.value}_{DUT.value}.txt" - file = os.path.join(folder,filename) - - R = regular_contact_check(device) - date = str(datetime.today().replace(microsecond=0)) - title = [f"Full Contact Check at {date}"] - - write_to_file(temp_file,title,R) - - #upload results - temp_file,file,folder=upload_results(temp_file,file,folder) - - information_box("Contact Check Completed") - device.inst.unlock() - - change_state(all_widgets) - -def on_qcc_clicked(b): - global folder,temp_file - with output: - clear_output() - change_state(all_widgets) - device.inst.lock_excl() - - filename=f"{sample_series.value}_{field.value}_{DUT.value}.txt" - file = os.path.join(folder,filename) - device.inst.lock_excl() - - if qcc_select.value == 'EBL': - R = EBL(device) - else: # OL - R = OL(device) #df - - date = str(datetime.today().replace(microsecond=0)) - title = [f"Quick Contact Check ({qcc_select.value}) at {date}"] - - write_to_file(temp_file,title,R) - - #upload results - temp_file,file,folder=upload_results(temp_file,file,folder) - - information_box("Quick Contact Check Completed") - - device.inst.unlock() - - change_state(all_widgets) - - -def on_set_button_clicked(b): - global folder,temp_file - with output: - #disable buttons - change_state(all_widgets) - - filename=f"{sample_series.value}_{field.value}_{DUT.value}.txt" - file = os.path.join(folder,filename) - - #lock the device - device.inst.lock_excl() - - clear_output() - - #check values - valid = check_values(step.value,Vset.value,Vreset.value) - - - if valid == True: - if sampling.value == True: #do sampling set before set process(100mV) - R_mean_before= sampling_check(-0.01,device) - - - #execute measurement,plot results and save them - V12,I12 = sweep(0,Vset.value,step.value,CC_vset.value,integration_time.value,device) - plot_sweep(V12,I12,'SET') - df = create_data_frame(V12,I12) - display(df) - - - if sampling.value == True: #do sampling set after set process(10mV) - R_mean_after = sampling_check(0.01,device) - - date = str(datetime.today().replace(microsecond=0)) - title = [f"SET Memristor at {date}",f"Set Voltage={Vset.value}V",f"current compliance={CC_vset.value}A"] - if sampling.value == True: - title.extend([f"R(Ohm) Before/After",f"{R_mean_before} {R_mean_after}"]) - write_to_file(temp_file,title,df) - - #upload results - temp_file,file,folder=upload_results(temp_file,file,folder) - - #show messagebox - information_box("Measurement finished!") - - #unlock device - device.inst.unlock() - - change_state(all_widgets) - -def on_reset_button_clicked(b): - global folder,temp_file - with output: - change_state(all_widgets) - - filename=f"{sample_series.value}_{field.value}_{DUT.value}.txt" - file = os.path.join(folder,filename) - - #lock device - device.inst.lock_excl() - - clear_output() - - #check values - valid = check_values(step.value,Vset.value,Vreset.value) - - - if valid == True: - if sampling.value == True: #do sampling set before reset process(10mV) - R_mean_before = sampling_check(0.01,device) - - #execute measurement,plot results and save them - V34,I34 = sweep(0,Vreset.value,step.value,CC_vreset.value,integration_time.value,device) - plot_sweep(V34,I34,'RESET') - df = create_data_frame(V34,I34) - display(df) - - if sampling.value == True: #do sampling set after reset process(100mV) - R_mean_after = sampling_check(-0.01,device) - - date = str(datetime.today().replace(microsecond=0)) - title =[f"RESET Memristor at {date}",f"Reset Voltage={Vreset.value}V",f"current compliance={CC_vreset.value}A"] - if sampling.value == True: - title.extend([f"R(Ohm) Before/After",f"{R_mean_before} {R_mean_after}"]) - write_to_file(temp_file,title,df) - - #Quick Contact Check after reset Process - if auto_qcc.value == True: - if qcc_select.value == 'EBL': - R=EBL(device) - else: # OL - R=OL(device) - - title = [f"Automatic Quick Contact Check({qcc_select.value}) after Reset"] - write_to_file(temp_file,title,R) - - #upload results - temp_file,file,folder=upload_results(temp_file,file,folder) - - #show messagebox - information_box("Measurement finished!") - - #unlock device - device.inst.unlock() - - change_state(all_widgets) - -def on_full_button_clicked(b): - global folder,temp_file - with output: - change_state(all_widgets) - - filename=f"{sample_series.value}_{field.value}_{DUT.value}.txt" - file = os.path.join(folder,filename) - - # lock device - device.inst.lock_excl() - - clear_output() - - #check values - valid = check_values(step.value,Vset.value,Vreset.value) - date = str(datetime.today().replace(microsecond=0)) - - if valid == True: - with open(temp_file,'a') as f: - header =[f"{number.value} full sweeps with parameters:",f"Set Voltage = {Vset.value}V",f"Current compliance set = {CC_vset.value}A",f"Reset Voltage = {Vreset.value}V",f"Current compliance reset = {CC_vreset.value}A"] - - fig, (ax1, ax2) = plt.subplots(2,sharex=True,figsize=(8,6)) #the plots share the same x axis - fig.suptitle('FULL SWEEP') - ax1.set_title('Linear I') - ax1.set(xlabel='Voltage(V)',ylabel='Current(A)') - ax2.set_title('Logarithmic I') - ax2.set(xlabel='Voltage(V)',ylabel='Current(A)') - ax2.set_yscale('log') - - stop = False - - def break_loop(): - nonlocal stop - stop = True - #help list with the resistances - resistances = [] - - add_hotkey("esc",break_loop) - #execute number of measurements - for i in range(number.value):#here it is easier to implement the sampling checks - clear_output(wait = True) - if i>0: - display(fig) - if sampling.value == True: #before set(100mv) - R_mean_init = sampling_check(-0.01,device) - resistances.append(R_mean_init) - - V12,I12 = sweep(0,Vset.value,step.value,CC_vset.value,integration_time.value,device) #set - plot_sweep(V12,I12,f"SET Iteration {i+1}") - - #after set/before reset - if sampling.value == True: #before set(10mv) - R_mean_set = sampling_check(0.01,device) - resistances.append(R_mean_set) - - V34,I34 = sweep(0,Vreset.value,step.value,CC_vreset.value,integration_time.value,device) #reset - plot_sweep(V34,I34,f"RESET Iteration {i+1}") - - - #after reset - if sampling.value == True:#-0.1V - R_mean_reset = sampling_check(-0.01,device) - resistances.append(R_mean_reset) - - #Quick Contact Check after reset Process - if auto_qcc.value == True: - if qcc_select.value == 'EBL': - R = EBL(device) - else: # OL - R = OL(device) - - #butterfly curve - V=np.concatenate((V12,V34)) - I=np.concatenate((I12,I34)) - - #create data frame and save to file - df = create_data_frame(V,I) - display(df) - if i == 0 : - header.extend([f"{i+1} Iteration"]) - title = header.copy() - else: - title = [f"{i+1} Iteration"] - if sampling.value == True: - title.extend([f"R(Ohm) INIT/SET/RESET",f"{R_mean_init} {R_mean_set} {R_mean_reset}"]) - - write_to_file(temp_file,title,df) - - if auto_qcc.value == True: - title= [f"Quick Contact Check({qcc_select.value}) after Reset"] - write_to_file(temp_file,title,R) - - #plot results - ax1.plot(V,I) - ax2.plot(V,np.absolute(I)) - fig.tight_layout() - - #check for loop termination - if stop == True: - clear_output(wait= True) - time.sleep(2) - display(fig) - information_box("Endurance stopped after esc!") - f.write("endurance stopped!\n\n") - break - else: - clear_output(wait = True) - time.sleep(2) - display(fig) - information_box("Endurance completed!") - f.write("endurance completed!\n\n") - - remove_hotkey('esc') - stop = False - - #plot resistances if sampling value == True or len(resistances) !=0 - if len(resistances)!=0: - indexes = np.arange(1,len(resistances)+1) - resistances = np.absolute(resistances) - - fig, ax = plt.subplots() - - fig.suptitle('Average Resistances from sampling checks') - ax.set(xlabel='Index',ylabel='Resistance(Ohm)',yscale='log') - ax.scatter(indexes,resistances) - display(fig) - - - #upload results - temp_file,file,folder=upload_results(temp_file,file,folder) - - #unlock the device - device.inst.unlock() - change_state(all_widgets) - - -#new_folder clicked -def on_new_folder_button_clicked(b): - global folder - with output: - change_state(all_widgets) - - folder = choose_folder() #choose new folder - - change_state(all_widgets) - -def on_retention_button_clicked(b): - global folder,temp_file - with output: - - change_state(all_widgets) - - - device.inst.lock_excl() - - clear_output() - - filename=f"{sample_series.value}_{field.value}_{DUT.value}.txt" - file = os.path.join(folder,filename) - - #execute measurement - t,R=retention(Vretention.value,period.value,duration.value,device) - plot_retention(t,R) - df=create_retention_data_frame(t,R) - date = str(datetime.today().replace(microsecond=0)) - title =[f"Retention Memristor at {date}",f"Voltage={Vretention.value}V",f"period={period.value}s",f"duration={duration.value}s"] - - write_to_file(temp_file,title,df) - #upload results - temp_file,file,folder=upload_results(temp_file,file,folder) - #show messagebox - information_box("Measurement finished!") - - device.inst.unlock() - - change_state(all_widgets) - - -def on_sweep_button_clicked(b): - with output: - clear_output() - change_state(all_widgets) - check_pulse(sweep_dict) - - sample_dict= { - 'series':sample_series, - 'field':field, - 'dut':DUT - } - - times,values = sweep_meas(sweep_dict,device) - plot_sweep_pulse(values) - save_sweep(folder,sample_dict,values,times,sweep_dict) - change_state(all_widgets) - - -def on_constant_button_clicked(b): - with output: - global first - clear_output() - change_state(all_widgets) - - check_pulse(sweep_dict) - - sample_dict= { - 'series':sample_series, - 'field':field, - 'dut':DUT - } - - times,values = constant_meas(cons_dict,device) - plot_constant_pulse(values) - save_constant(folder,sample_dict,values,times,cons_dict) - change_state(all_widgets) - - -#link buttons to widgets (pulsed) -sweep_button.on_click(on_sweep_button_clicked) -cons_button.on_click(on_constant_button_clicked) - -#link buttons with functions -set.on_click(on_set_button_clicked) -reset.on_click(on_reset_button_clicked) -full.on_click(on_full_button_clicked) -new_folder.on_click(on_new_folder_button_clicked) -retention_button.on_click(on_retention_button_clicked) -contact_check.on_click(on_contact_check_clicked) -qcc.on_click(on_qcc_clicked) diff --git a/hp4155/memristor (Version 4.0)/memristor_buttons.ipynb b/hp4155/memristor (Version 4.0)/memristor_buttons.ipynb deleted file mode 100644 index c9aa7e1d764af70e814dd3f28e2a6ef48ee6801e..0000000000000000000000000000000000000000 --- a/hp4155/memristor (Version 4.0)/memristor_buttons.ipynb +++ /dev/null @@ -1,86 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "b913930d-b120-4e59-8a42-d9eecb526a61", - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "04df3def923445eb95f28afa67430db0", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(VBox(children=(Text(value='', description='sample series:', placeholder='Enter text here:', sty…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "0eeebb7ea7f64c97814087e1c195f32b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Tab(children=(VBox(children=(HBox(children=(BoundedFloatText(value=0.01, description='Step(V):', step=0.01), D…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ff84a98e2896443cbf3470c994e9b383", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "%run memristor.py" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1047e606-d5cb-420b-892f-766226339854", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/hp4155/memristor (Version 4.0)/schematic.png b/hp4155/memristor (Version 4.0)/schematic.png deleted file mode 100644 index 7a3a144bfd6c17374838b2d9222e57173fe2fcd8..0000000000000000000000000000000000000000 Binary files a/hp4155/memristor (Version 4.0)/schematic.png and /dev/null differ