From c489c53a90f65e6758584993a3bfdf516a0c336d Mon Sep 17 00:00:00 2001
From: unknown <asoalexandros@gmail.com>
Date: Wed, 4 Dec 2024 12:27:41 +0100
Subject: [PATCH] Memristor Debugging part 1

---
 hp4155/memristor (Version 4.0)/help.py        |  45 ++++---
 hp4155/memristor (Version 4.0)/help_pulse.py  |  38 +++---
 hp4155/memristor (Version 4.0)/memristor.py   | 113 ++++++++----------
 .../memristor_buttons.ipynb                   |   8 +-
 4 files changed, 94 insertions(+), 110 deletions(-)

diff --git a/hp4155/memristor (Version 4.0)/help.py b/hp4155/memristor (Version 4.0)/help.py
index c856011..f90780b 100644
--- a/hp4155/memristor (Version 4.0)/help.py	
+++ b/hp4155/memristor (Version 4.0)/help.py	
@@ -105,7 +105,10 @@ def regular_contact_check(device):
             """
             R=contact_check(i,j,device)
             resistances[f"{i}-{j}"] = R
-    return resistances
+
+    #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
@@ -113,17 +116,21 @@ def EBL(device):
     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
-    return resistances
+    
+    #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 
-    return resistances
+        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
@@ -352,9 +359,16 @@ def create_retention_data_frame(x,y):
 
 
 #write results to file
-def write_to_file(file,title,df):
-    with open(file,'a') as f:
-        f.write(title)
+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")
@@ -487,21 +501,6 @@ def upload_results(source_file,target_file,target_file_dir):
             filename = os.path.basename(target_file)
             target_file =os.path.join(target_file_dir,filename)
             #and then try again
-
-
-def save_contact_check(R,file): #save contact check to file
-    """
-    Parameters:
-    -Resistances list
-    -File to save
-    """
-
-    with open(file,'a') as f:
-        f.write("Contact Check Results:\n")
-
-        df = pd.DataFrame(R.items(), columns=['SMU pair', 'Resistance (Ohm)'])
-        f.write(df.to_string())
-        f.write("\n\n")
     
 
         
diff --git a/hp4155/memristor (Version 4.0)/help_pulse.py b/hp4155/memristor (Version 4.0)/help_pulse.py
index dac0bb6..522c6e6 100644
--- a/hp4155/memristor (Version 4.0)/help_pulse.py	
+++ b/hp4155/memristor (Version 4.0)/help_pulse.py	
@@ -36,7 +36,7 @@ def check_pulse(dictionary):
 
 
 #sweep pulse measurement
-def sweep_meas(dict,device):
+def sweep_meas(dictionary,device):
     smu_v = device.smu_dict()
     smu_ground = device.smu_dict()
     parameters = device.var1_dict()
@@ -55,14 +55,14 @@ def sweep_meas(dict,device):
     )
     parameters.update(
         mode ='SING',
-        start = dict['start'].value,
-        stop = dict['stop'].value,
-        step = dict["stop"].value-dict["start"].value)/(dict["pulses"].value-1, #define the number of steps given specific pulses
-        comp = dict["comp"].value,
+        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 = dict["base"].value,
-        width = dict["width"].value,
-        period= dict["period"].value
+        base = dictionary["base"].value,
+        width = dictionary["width"].value,
+        period= dictionary["period"].value
     )
     device.smu_disable(1)
     device.smu_disable(3)
@@ -81,7 +81,7 @@ def sweep_meas(dict,device):
 
     device.setup_pulse(parameters)
 
-    device.integration_time(dict["integration"].value)
+    device.integration_time(dictionary["integration"].value)
 
     t0 = time.time()
     device.single_measurement()
@@ -98,7 +98,7 @@ def sweep_meas(dict,device):
     R_i = np.divide(V_i,I_i)
     
     
-    expected_time = dict["period"].value*dict["pulses"].value
+    expected_time = dictionary["period"].value*dictionary["pulses"].value
 
     times = (elapsed_time,expected_time)
     values = (V_i,I_i,R_i)
@@ -157,7 +157,7 @@ def save_sweep(folder,sample_dict,values,times,sweep_dict):
         f.write(df.to_string())
         f.write("\n\n\n")
 
-def constant_meas(dict,device):
+def constant_meas(dictionary,device):
     smu_v = device.smu_dict()
     smu_ground = device.smu_dict()
     sweep_params = device.var1_dict()
@@ -185,17 +185,17 @@ def constant_meas(dict,device):
         mode ='SING',
         start = 0,
         stop = 10,
-        step = 10/(dict["pulses"].value-1, #define the number of steps given specific pulses
+        step = 10/(dictionary["pulses"].value-1), #define the number of steps given specific pulses
         comp = 0.1,
         pcomp = 0,
-        base = dict["base"].value,
-        width = dict["width"].value,
-        period= dict["period"].value
+        base = dictionary["base"].value,
+        width = dictionary["width"].value,
+        period= dictionary["period"].value
     )
     #the constant smu
     cons = {
-        'value':dict["voltage"].value,
-        'comp':dict["comp"].value
+        'value':dictionary["voltage"].value,
+        'comp':dictionary["comp"].value
     }
     
     device.measurement_mode("SWE")
@@ -217,7 +217,7 @@ def constant_meas(dict,device):
     device.range_mode(3,"AUTO")
 
     
-    device.integration_time(dict["integration"].value)
+    device.integration_time(dictionary["integration"].value)
 
     device.variables_to_save(['@INDEX','V2','I2','R'])
 
@@ -236,7 +236,7 @@ def constant_meas(dict,device):
     R_i = device.return_values('R')
 
     
-    expected_time = dict["period"].value*dict["pulses"].value
+    expected_time = dictionary["period"].value*dictionary["pulses"].value
 
     times = (elapsed_time,expected_time)
     values = (V_i,I_i,R_i)
diff --git a/hp4155/memristor (Version 4.0)/memristor.py b/hp4155/memristor (Version 4.0)/memristor.py
index 657ec6c..a42129e 100644
--- a/hp4155/memristor (Version 4.0)/memristor.py	
+++ b/hp4155/memristor (Version 4.0)/memristor.py	
@@ -197,18 +197,22 @@ def on_contact_check_clicked(b):
     with output:
         clear_output(wait = True)
         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)
-        save_contact_check(R,temp_file)
+        date = str(datetime.today().replace(microsecond=0))
+        title = [f"Full 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("Contact Check Completed")
+        device.inst.unlock()
 
         change_state(all_widgets)
 
@@ -217,29 +221,34 @@ def on_qcc_clicked(b):
     with output:
         clear_output(wait = True)
         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)
+            R = OL(device) #df
 
-        save_contact_check(R,temp_file)
+        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 first,folder,file,temp_file
+    global folder,temp_file
     with output:
         #disable buttons
         change_state(all_widgets)
@@ -247,8 +256,6 @@ def on_set_button_clicked(b):
         filename=f"{sample_series.value}_{field.value}_{DUT.value}.txt"
         file = os.path.join(folder,filename)
 
-        device = setup_memristor()
-
         #lock the  device
         device.inst.lock_excl()
 
@@ -268,17 +275,18 @@ def on_set_button_clicked(b):
             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)
-            print(df)
+            display(df)
             
 
             if sampling.value == True: #do sampling set after set process(10mV)
                 R_mean_after = sampling_check(0.01,device)
                 print(f"Average Resistance(Sampling Check):{'{:.2e}'.format(R_mean_after)} Ohm")
                 first_sampling = False
-
-            title = f"SET Memristor:"+"\n\n"+f"Set Voltage={Vset.value}V"+"\n"+f"current compliance={CC_vset.value}A"+"\n"
+            
+            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 = title + f"R(Ohm)  Before/After"+"\n"+f"{R_mean_before}  {R_mean_after}"+"\n"
+                title.extend([f"R(Ohm)  Before/After",f"{R_mean_before}  {R_mean_after}"])
             write_to_file(temp_file,title,df)
 
             #upload results
@@ -289,8 +297,6 @@ def on_set_button_clicked(b):
 
         #unlock device
         device.inst.unlock()
-
-        del device
         
         change_state(all_widgets)
  
@@ -298,7 +304,6 @@ def on_reset_button_clicked(b):
     global folder,temp_file
     with output:
         change_state(all_widgets)
-        device = setup_memristor()
 
         filename=f"{sample_series.value}_{field.value}_{DUT.value}.txt"
         file = os.path.join(folder,filename)
@@ -322,25 +327,28 @@ def on_reset_button_clicked(b):
             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)
-            print(df)
+            display(df)
             
             if sampling.value == True: #do sampling set after reset process(100mV)
                 R_mean_after = sampling_check(-0.01,device)
                 print(f"Average Resistance(Sampling Check):{'{:.2e}'.format(R_mean_after)} Ohm")
                 first_sampling = False
-            
-            title =f"RESET Memristor:"+"\n\n"+f"Reset Voltage={Vreset.value}V"+"\n"+f"current compliance={CC_vreset.value}A"+"\n"
+
+            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 = title + f"R(Ohm)  Before/After"+"\n"+f"{R_mean_before}  {R_mean_after}"+"\n"
+                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()
+                    R=EBL(device)
                 else: # OL
-                    R=OL()
-                save_contact_check(R,temp_file)
+                    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)
@@ -351,8 +359,6 @@ def on_reset_button_clicked(b):
         #unlock device
         device.inst.unlock()
 
-        del device
-
         change_state(all_widgets)
 
 def on_full_button_clicked(b):
@@ -363,8 +369,6 @@ def on_full_button_clicked(b):
         filename=f"{sample_series.value}_{field.value}_{DUT.value}.txt"
         file = os.path.join(folder,filename)
 
-        device= setup_memristor()
-
         # lock device
         device.inst.lock_excl()
         
@@ -372,31 +376,11 @@ def on_full_button_clicked(b):
 
         #check values
         valid = check_values(step.value,Vset.value,Vreset.value)
-
-        #during first button press
-        if first == True and valid == True: 
-            #disable checkboxes, text fields etc.
-            change_state(information)
-            filename=f"{sample_series.value}_{field.value}_{DUT.value}.txt"
-            file = os.path.join(folder,filename)
-            #write header to temp_file
-            write_header(temp_file,sample_series,field,DUT)
-            first = False #set first to false irrelvant if it is in the if statement or not
-
+        date = str(datetime.today().replace(microsecond=0))
         
         if valid == True:
             with open(temp_file,'a') as f:
-                f.write(f"{number.value} full sweeps with parameters:")
-                f.write("\n")
-                f.write(f"Set Voltage = {Vset.value}V")
-                f.write("\n")
-                f.write(f"Current compliance set = {CC_vset.value}A")
-                f.write("\n")
-                f.write(f"Reset Voltage = {Vreset.value}V")
-                f.write("\n")
-                f.write(f"Current compliance reset = {CC_vreset.value}A")
-                f.write("\n\n")
-                
+                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"]
                 
                 plt.figure().clear()
                 fig, (ax1, ax2) = plt.subplots(2,sharex=True,figsize=(8,6)) #the plots share the same x axis 
@@ -434,9 +418,9 @@ def on_full_button_clicked(b):
                     #Quick Contact Check after reset Process 
                     if auto_qcc.value == True:
                         if qcc_select.value == 'EBL':
-                            R = EBL()
+                            R = EBL(device)
                         else: # OL
-                            R = OL()
+                            R = OL(device)
 
                     #no reason to do check at the end because the next loop will do that(not anymore) more sampling checks
 
@@ -452,15 +436,19 @@ def on_full_button_clicked(b):
 
                     #create data frame and save to file
                     df = create_data_frame(V,I)
-                    f.write(f"{i+1} Iteration")
-                    f.write("\n")
+                    if i == 0 :
+                        header.extend([f"{i+1} Iteration"])
+                        title = header.copy()
+                    else:
+                        title = [f"{i+1} Iteration"]
                     if sampling.value == True:
-                        f.write(f"R(Ohm)  INIT/SET/RESET"+"\n"+f"{R_mean_init}  {R_mean_set} {R_mean_reset}"+"\n")
-                    f.write(df.to_string())
-                    f.write("\n\n")
+                        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:
-                        save_contact_check(R,temp_file)
+                        title= [f"Quick Contact Check({qcc_select.value}) after Reset"]
+                        write_to_file(temp_file,title,R)
 
 
                     #plot results
@@ -472,7 +460,7 @@ def on_full_button_clicked(b):
                     clear_output()
                     display(fig)
                     #plt.show()
-                    print(df)
+                    display(df)
 
                     #check for loop termination
                     if stop == True:
@@ -508,14 +496,13 @@ def on_full_button_clicked(b):
         #unlock the device
         device.inst.unlock()
 
-        del device
         
         change_state(all_widgets)
 
 
 #new_folder clicked
 def on_new_folder_button_clicked(b):
-    global folder,file,first
+    global folder
     with output:
         change_state(all_widgets)
         
@@ -524,12 +511,11 @@ def on_new_folder_button_clicked(b):
         change_state(all_widgets)
 
 def on_retention_button_clicked(b):
-    global first,folder,file,temp_file
+    global folder,temp_file
     with output:
         
         change_state(all_widgets)
 
-        device = setup_memristor()
 
         device.inst.lock_excl()
         
@@ -542,7 +528,8 @@ def on_retention_button_clicked(b):
         t,R=retention(Vretention.value,period.value,duration.value,device)
         plot_retention(t,R)
         df=create_retention_data_frame(t,R)
-        title =f"Retention Memristor:"+"\n\n"+f"Voltage={Vretention.value}V"+"\n"+f"period={period.value}s"+"\n"+f"duration={duration.value}s"+"\n"
+        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
@@ -551,8 +538,6 @@ def on_retention_button_clicked(b):
         information_box("Measurement finished!")
 
         device.inst.unlock()
-
-        del device
     
         change_state(all_widgets)
 
diff --git a/hp4155/memristor (Version 4.0)/memristor_buttons.ipynb b/hp4155/memristor (Version 4.0)/memristor_buttons.ipynb
index 401a656..35144fd 100644
--- a/hp4155/memristor (Version 4.0)/memristor_buttons.ipynb	
+++ b/hp4155/memristor (Version 4.0)/memristor_buttons.ipynb	
@@ -3,13 +3,13 @@
   {
    "cell_type": "code",
    "execution_count": 1,
-   "id": "df99f5a2-80af-4892-8633-33177239e444",
+   "id": "7611a98c-c1cf-46cb-bdd9-fd3dc6a1f53c",
    "metadata": {},
    "outputs": [
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "45a61bab685e4422bbe94514a2439059",
+       "model_id": "e907a7767009491da92ac730cb310874",
        "version_major": 2,
        "version_minor": 0
       },
@@ -23,7 +23,7 @@
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "11da2c8be6de4612a31f3a065e50bc66",
+       "model_id": "3ebd085796c54e8daaac92ddf5309393",
        "version_major": 2,
        "version_minor": 0
       },
@@ -37,7 +37,7 @@
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "0d1ba2ede27742c3aa2cd2b8ec3f50c8",
+       "model_id": "90dc92bfe8374348bc680caf722f494e",
        "version_major": 2,
        "version_minor": 0
       },
-- 
GitLab