diff --git a/hp4155/ADU_for_double_gate_devices_version_3/double_gate_ADU.py b/hp4155/ADU_for_double_gate_devices_version_3/double_gate_ADU.py
new file mode 100644
index 0000000000000000000000000000000000000000..c7d8946a74df40248e03357beffb540890e8e3dd
--- /dev/null
+++ b/hp4155/ADU_for_double_gate_devices_version_3/double_gate_ADU.py
@@ -0,0 +1,264 @@
+import sys
+sys.path.insert(0, './lib')
+sys.path.insert(0, '..') #append parent directory
+
+
+import hp4155a
+from interface import *
+from help import *
+import transfer
+import output
+import gatediode
+import configparser
+
+
+#setup user interface
+ui = interface()
+device = hp4155a.HP4155a('GPIB0::17::INSTR')
+
+def on_start_clicked(b):
+    with ui.output:
+        clear_output()
+        #disable all widgets
+        change_state(ui.all_widgets)
+
+        #additional code to check smu configuration fast without modifing a lot of code
+        try:
+            check_configuration(ui.sample)
+        except Exception as e:
+            error_box(e)
+            change_state(ui.all_widgets)
+            return
+
+        #setup the devicr
+        device.reset()
+
+        #setup sweep measurement mode
+        device.measurement_mode('SWE')
+    
+        #disable all irrelevant units
+        device.disable_not_smu()
+
+        if ui.transfer_check.value == True:
+            if ui.transfer_gates.value == 'VTG':
+                transfer.VTG(ui,device)
+            elif ui.transfer_gates.value == 'VBG': 
+                transfer.VBG(ui,device)
+            elif ui.transfer_gates.value == 'BOTH SIMULTANEOUSLY':
+                transfer.SIM(ui,device)
+            else: # Sequential measurement
+                transfer.SEQ(ui,device)
+                
+        if ui.output_check.value == True:
+            if ui.output_gates.value == "VTG":
+               output.VTG(ui,device)
+            elif ui.output_gates.value == "VBG":
+               output.VBG(ui,device)
+            else: # Both
+                output.SEQ(ui,device)
+                    
+
+        if ui.gatediode_check.value == True:
+            if ui.gatediode_gates.value == 'VTG':
+                gatediode.VTG(ui,device)
+            else: #VBG
+                gatediode.VBG(ui,device)
+        
+        information_box("Measurement finished!")
+        change_state(ui.all_widgets)
+            
+def on_export_ini_clicked(b):
+    with ui.output:
+        change_state(ui.all_widgets)
+        config = configparser.ConfigParser()
+        default_filename = 'ADU_double_gate.ini'
+        try:
+            file = save_as_ini(default_filename)
+            with open(file,'w') as configfile:
+                config.add_section('ALL VALUES ARE IN SI-UNITS!')
+                config.add_section('IT IS RECOMMENDED TO CHANGE THE INI FILE FROM THE INTERFACE AND DO NOT CHANGE ANY VALUES MANUALLY')
+    
+                # Transfer curve
+                config.add_section('Transfer')
+                config.set('Transfer','Integration',ui.integration_transfer.value)
+    
+                config.add_section("Vtg_transfer")
+                for parameter, widget in vars(ui.Vtg_transfer).items():
+                    if parameter != "grid":
+                        config.set("Vtg_transfer",parameter,str(widget.value))
+                   
+    
+                config.add_section("Vbg_transfer")
+                for parameter,widget in vars(ui.Vbg_transfer).items():
+                    if parameter != "grid":
+                        config.set('Vbg_transfer',parameter,str(widget.value))
+    
+                config.add_section('Vds_transfer')
+                for parameter,widget in vars(ui.Vds_transfer).items():
+                    if parameter != "grid":
+                        config.set('Vds_transfer',parameter,str(widget.value))
+                    
+
+                config.add_section('Plot_transfer')
+                for parameter,widget in vars(ui.plot_transfer).items():
+                    if parameter != "grid":
+                        config.set('Plot_transfer',parameter,str(widget.value))
+                    
+                #output
+                config.add_section('Output')
+                config.set('Output','Integration',ui.integration_output.value)
+    
+                config.add_section("Vtg_output")
+                for parameter,widget in vars(ui.Vtg_output).items():
+                    if parameter != "grid":
+                        config.set('Vtg_output',parameter,str(widget.value))
+                    
+    
+                config.add_section("Vbg_output")
+                for parameter,widget in vars(ui.Vbg_output).items():
+                    if parameter != "grid":
+                        config.set('Vbg_output',parameter,str(widget.value))
+                    
+                
+                config.add_section('Vds_output')
+                for parameter,widget in vars(ui.Vds_output).items():
+                    if parameter != "grid":
+                        config.set('Vds_output',parameter,str(widget.value))
+                    
+
+                config.add_section('Plot_output')
+                for parameter,widget in vars(ui.plot_output).items():
+                    if parameter != "grid":
+                        config.set('Plot_output',parameter,str(widget.value))
+                    
+                # Gatediode
+                config.add_section('Gatediode')
+                config.set('Gatediode','Integration',ui.integration_gatediode.value)
+    
+                config.add_section("Vg_gatediode")
+                for parameter,widget in vars(ui.Vg_gatediode).items():
+                    if parameter != "grid":
+                        config.set('Vg_gatediode',parameter,str(widget.value)) 
+
+                config.add_section('Plot_gatediode')
+                for parameter,widget in vars(ui.plot_gatediode).items():
+                    if parameter != "grid":
+                        config.set('Plot_gatediode',parameter,str(widget.value))
+
+                # add the smu configuration
+                config.add_section('SMU_configuration')
+                config.set("SMU_configuration","D",str(ui.sample.drain.value))
+                config.set("SMU_configuration","TG",str(ui.sample.top_gate.value))
+                config.set("SMU_configuration","BG",str(ui.sample.back_gate.value))
+                config.set("SMU_configuration","S",str(ui.sample.source.value))
+
+                # Add the sweeping gates
+                config.add_section('Sweeping_gates')
+                config.set('Sweeping_gates','Transfer',str(ui.transfer_gates.value))
+                config.set('Sweeping_gates','Output',str(ui.output_gates.value))
+                config.set('Sweeping_gates','Gatediode',str(ui.gatediode_gates.value))
+                
+    
+                config.write(configfile)
+        except Exception as e:
+            information_box(e)
+        
+        change_state(ui.all_widgets)
+
+
+def on_import_ini_clicked(b):
+    with ui.output:
+        change_state(ui.all_widgets)
+        #load values to the interface
+        config = configparser.ConfigParser()
+        try:
+            file = load_ini()
+        except Exception as e:
+            information_box(e)
+            enable_widgets(all_widgets)
+            return
+
+        try:
+            #read the values from each section
+            config.read(file)
+    
+            #transfer curve
+            ui.integration_transfer.value = config.get('Transfer', "integration")
+            for parameter,widget in vars(ui.Vtg_transfer).items():
+                if parameter != "grid":
+                    widget.value = config.get('Vtg_transfer',parameter)
+            for parameter,widget in vars(ui.Vds_transfer).items():
+                if parameter != "grid":
+                    widget.value = config.get('Vds_transfer',parameter)
+            for parameter,widget in vars(ui.Vbg_transfer).items():
+                if parameter != "grid":
+                    widget.value = config.get('Vbg_transfer',parameter)
+            for parameter,widget in vars(ui.plot_transfer).items():
+                if parameter != "grid":
+                    widget.value = config.get('Plot_transfer',parameter)
+            
+            #output curve
+            ui.integration_output.value = config.get('Output','integration')
+            for parameter,widget in vars(ui.Vtg_output).items():
+                if parameter != "grid":
+                    widget.value = config.get('Vtg_output',parameter)
+            for parameter,widget in vars(ui.Vds_output).items():
+                if parameter != "grid":
+                    widget.value = config.get('Vds_output',parameter)
+            for parameter,widget in vars(ui.Vbg_output).items():
+                if parameter != "grid":
+                    widget.value = config.get('Vbg_output',parameter)
+            for parameter,widget in vars(ui.plot_output).items():
+                if parameter != "grid":
+                    widget.value = config.get('Plot_output',parameter)
+        
+            # gatediode
+            ui.integration_gatediode.value = config.get('Gatediode','integration')
+            for parameter,widget in vars(ui.Vg_gatediode).items():
+                if parameter != "grid":
+                    widget.value = config.get('Vg_gatediode',parameter)
+    
+            for parameter,widget in vars(ui.plot_gatediode).items():
+                if parameter != "grid":
+                    widget.value = config.get('Plot_gatediode',parameter)
+    
+            # SMU map
+            ui.sample.drain.value = int(config.get("SMU_configuration","d"))
+            ui.sample.top_gate.value = int(config.get("SMU_configuration","tg"))
+            ui.sample.back_gate.value = int(config.get("SMU_configuration","bg"))
+            ui.sample.source.value = int(config.get("SMU_configuration","s"))
+            
+            # sweeping gates
+            ui.transfer_gates.value = config.get('Sweeping_gates','Transfer')
+            ui.output_gates.value = config.get('Sweeping_gates','Output')
+            ui.gatediode_gates.value = config.get('Sweeping_gates','Gatediode')
+    
+            information_box("all parameters loaded succesfully")
+        except Exception as error:
+            if type(error).__name__ =='NoSectionError':
+                information_box(f"{error}.Explanation: Section(header) [section] does not exist. Create a new ini file or compare it with functional ini files!")
+            elif type(error).__name__=='NoOptionError':
+                information_box(f'{error}.Explanation: The variable name before the equal sign is not recognized. Create a new ini file or compare it with functional ini files!')
+            elif type(error).__name__ == 'TraitError':
+                information_box(f'{error}.Explanation: Invalid Parameter Setting. Check if you set an invalid value!')
+            elif type(error).__name__ =="DuplicateOptionError":
+                information_box(f"{error}. Explaination: The section contains the setted parameter more than once!")
+            else:
+                information_box(f"A {type(error).__name__} has occurred. Create A new ini file")
+        change_state(ui.all_widgets)
+
+            
+ui.start.on_click(on_start_clicked)
+ui.import_ini.on_click(on_import_ini_clicked)
+ui.export_ini.on_click(on_export_ini_clicked)
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hp4155/ADU_for_double_gate_devices_version_3/double_gate_ADU_interface.ipynb b/hp4155/ADU_for_double_gate_devices_version_3/double_gate_ADU_interface.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..bccf7119845f923c3f56960e8137605718e24d62
--- /dev/null
+++ b/hp4155/ADU_for_double_gate_devices_version_3/double_gate_ADU_interface.ipynb
@@ -0,0 +1,114 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "51b012d0-95b0-41c2-81bb-2205f3c53be2",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "0879807dae214b789264fdcd4c264999",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(VBox(children=(Label(value='Sample Information', layout=Layout(height='auto', width='50%'), sty…"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "6d4ea5ad1b6143a4ae91ee17406184bf",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(Checkbox(value=True, description='Transfer', indent=False), Checkbox(value=True, description='O…"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "92b167e872da4970ac54d2be519e3f98",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "Tab(children=(VBox(children=(Dropdown(description='Integration Time', index=1, layout=Layout(height='auto', wi…"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "3d99607bed9d4b9e886dad6d5a98062e",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(Button(description='Start Measurement', style=ButtonStyle()), Button(description='Import from i…"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "e6f9253c0a1b41b6ad3476cd030f6b8f",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "Output()"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "%run double_gate_ADU.py"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "3d0c5404-a1c6-40f9-bffd-625199c945a7",
+   "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/ADU_for_double_gate_devices_version_3/lib/gatediode.py b/hp4155/ADU_for_double_gate_devices_version_3/lib/gatediode.py
new file mode 100644
index 0000000000000000000000000000000000000000..68352d61d34c4e5b19940ca1c8535b970753c455
--- /dev/null
+++ b/hp4155/ADU_for_double_gate_devices_version_3/lib/gatediode.py
@@ -0,0 +1,186 @@
+# This are the gatediode measurements
+
+import sys
+sys.path.insert(0, '..') #append parent directory
+
+import hp4155a
+from help import *
+from decimal import Decimal
+
+import os
+
+def VTG(ui,device):
+    device.del_user_functions() # delete all user functions 
+    device.clear_error_stack() # clear error stack
+    # setup the smus
+
+    norm = normalization_factor(ui.sample.width.value)
+
+    smu_source = device.smu_dict()
+    smu_source.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS')
+
+    smu_top_gate = device.smu_dict()
+    smu_top_gate.update(vname = 'VTG',iname='ITG',mode = 'V',func='VAR1')
+
+    # setup VAR1
+    var1 = device.var1_dict()
+    var1.update(
+        mode = ui.Vg_gatediode.hyst.value,
+        start = ui.Vg_gatediode.start.value,
+        stop = ui.Vg_gatediode.stop.value,
+        step = ui.Vg_gatediode.step.value,
+        comp = ui.Vg_gatediode.comp.value,
+        pcomp = ui.Vg_gatediode.pcomp.value
+    )
+
+    try:
+        device.setup_smu(ui.sample.top_gate.value,smu_top_gate)
+        device.setup_smu(ui.sample.source.value,smu_source)
+    
+        # disable back gate smu
+        device.smu_disable(ui.sample.back_gate.value)
+    
+        # disable drain smu
+        device.smu_disable(ui.sample.drain.value)
+
+        device.setup_var1(var1)
+        device.integration_time(ui.integration_gatediode.value)
+        
+        variables_list = ['VTG','ITG']
+        device.variables_to_save(variables_list)
+
+        plotted_variables = graph_tool(ui.plot_gatediode,ui.sample.width.value,device)
+
+        device.error_occured()
+        
+        device.single_measurement()
+        while device.operation_completed()==False:
+            pass
+
+        device.error_occured()
+
+        if ui.sample.quick.value == False:
+            device.autoscaling()
+       
+    
+        values = dict([(variable,device.return_values(variable)) for variable in variables_list])
+        df = get_dataframe_from_results(values)
+    except Exception as e:
+        error_box(e)
+        return
+    
+    # Append the normalized current 
+    df["ITGmm/uA/um"]= (df["ITG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+    default_filename = f"{ui.sample.sample.value}_{ui.sample.field.value}_{ui.sample.device.value}_TOP_GATE_D.txt"
+    file = create_file(default_filename)
+
+    with open(file,'w') as f:
+        date = str(datetime.today().replace(microsecond=0))
+        f.write(f"Gatediode Curve at {date}"+"\n")
+        write_sample_information(ui.sample,f)
+        f.write("Sweeping Gate:VTG"+"\n\n")
+        f.write('Parameters\n')
+        f.write(f"VTG from {ui.Vg_gatediode.start.value}V to {ui.Vg_gatediode.stop.value}V with step {ui.Vg_gatediode.step.value}V"+"\n")
+        
+        if ui.Vg_gatediode.pcomp.value==0:
+            f.write(f"Top Gate Current Compliance/A:{ui.Vg_gatediode.comp.value}"+"\n")
+        else:
+            f.write(f"Top Gate Power Compliance/A:{ui.Vg_gatediode.pcomp.value}"+"\n")
+
+        f.write(f"Integration Time:{ui.integration_gatediode.value}"+"\n")
+        f.write("\nResults\n")
+
+    df.to_csv(file,sep=" ",mode='a')
+
+    if ui.sample.quick.value == False:
+        df["label"] = df.apply(lambda row: "_nolegend_",axis = 1) # assign labels
+        create_plot(ui.plot_gatediode,df,file,"Top Gate Gatediode Measurement",None,ui.sample.save_fig.value)
+
+def VBG(ui,device):
+    device.del_user_functions() # delete all user functions 
+    device.clear_error_stack() # clear error stack
+    # setup the smus
+
+    norm = normalization_factor(ui.sample.width.value)
+
+    smu_source = device.smu_dict()
+    smu_source.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS')
+
+    smu_back_gate = device.smu_dict()
+    smu_back_gate.update(vname = 'VBG',iname='IBG',mode = 'V',func='VAR1')
+
+    # setup VAR1
+    var1 = device.var1_dict()
+    var1.update(
+        mode = ui.Vg_gatediode.hyst.value,
+        start = ui.Vg_gatediode.start.value,
+        stop = ui.Vg_gatediode.stop.value,
+        step = ui.Vg_gatediode.step.value,
+        comp = ui.Vg_gatediode.comp.value,
+        pcomp = ui.Vg_gatediode.pcomp.value
+    )
+
+    try:
+        device.setup_smu(ui.sample.top_gate.value,smu_back_gate)
+        device.setup_smu(ui.sample.source.value,smu_source)
+    
+        # disable back gate smu
+        device.smu_disable(ui.sample.back_gate.value)
+    
+        # disable drain smu
+        device.smu_disable(ui.sample.drain.value)
+
+        device.setup_var1(var1)
+        device.integration_time(ui.integration_gatediode.value)
+        
+        variables_list = ['VBG','IBG']
+        device.variables_to_save(variables_list)
+
+        plotted_variables = graph_tool(ui.plot_gatediode,ui.sample.width.value,device)
+
+        device.error_occured()
+        
+        device.single_measurement()
+        while device.operation_completed()==False:
+            pass
+
+        device.error_occured()
+
+        if ui.sample.quick.value == False:
+            device.autoscaling()
+       
+    
+        values = dict([(variable,device.return_values(variable)) for variable in variables_list])
+        df = get_dataframe_from_results(values)
+    except Exception as e:
+        error_box(e)
+        return
+    
+    # Append the normalized current 
+    df["IBGmm/uA/um"]= (df["IBG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+    default_filename = f"{ui.sample.sample.value}_{ui.sample.field.value}_{ui.sample.device.value}_BACK_GATE_D.txt"
+    file = create_file(default_filename)
+
+    with open(file,'w') as f:
+        date = str(datetime.today().replace(microsecond=0))
+        f.write(f"Gatediode Curve at {date}"+"\n")
+        write_sample_information(ui.sample,f)
+        f.write("Sweeping Gate:VBG"+"\n\n")
+        f.write('Parameters\n')
+        f.write(f"VTG from {ui.Vg_gatediode.start.value}V to {ui.Vg_gatediode.stop.value}V with step {ui.Vg_gatediode.step.value}V"+"\n")
+        
+        if ui.Vg_gatediode.pcomp.value==0:
+            f.write(f"Top Gate Current Compliance/A:{ui.Vg_gatediode.comp.value}"+"\n")
+        else:
+            f.write(f"Top Gate Power Compliance/A:{ui.Vg_gatediode.pcomp.value}"+"\n")
+
+        f.write(f"Integration Time:{ui.integration_gatediode.value}"+"\n")
+        f.write("\nResults\n")
+
+    df.to_csv(file,sep=" ",mode='a')
+
+    if ui.sample.quick.value == False:
+        df["label"] = df.apply(lambda row: "_nolegend_",axis = 1) # assign labels
+        create_plot(ui.plot_gatediode,df,file,"Top Gate Gatediode Measurement",None,ui.sample.save_fig.value)
+        
+    
\ No newline at end of file
diff --git a/hp4155/ADU_for_double_gate_devices_version_3/lib/help.py b/hp4155/ADU_for_double_gate_devices_version_3/lib/help.py
new file mode 100644
index 0000000000000000000000000000000000000000..40f602d3486fafb1df850701baf00481da19d4e2
--- /dev/null
+++ b/hp4155/ADU_for_double_gate_devices_version_3/lib/help.py
@@ -0,0 +1,291 @@
+import matplotlib.pyplot as plt
+import numpy as np
+import time
+from datetime import datetime
+
+import tkinter as tk
+from tkinter import filedialog
+import tkinter.messagebox
+import copy
+import os 
+
+import pandas as pd
+
+#Get dataframe from results
+def get_dataframe_from_results(dictionary):
+    # creating a shallow copy
+    dictionary_copy = copy.copy(dictionary)
+    for old_key in dictionary_copy.keys():
+        if old_key[0]=='I':
+            new_key = old_key+"/A"
+        else: #V
+            new_key = old_key + "/V"
+        dictionary[new_key] = dictionary.pop(old_key)
+   
+    df = pd.DataFrame(dictionary)
+    return df
+
+def number_of_points(obj): # obj is interface object
+    try:
+        diff = obj.stop.value - obj.start.value
+        ratio = abs(diff/obj.step.value)
+        points = int(ratio+1)
+    
+    except ZeroDivisionError:
+        points = 1
+
+    #the programm crashed because for secondary step we had no problem setting start = stop and then it was dividing by zero
+    
+    if points>128:
+        points = 128
+    return points
+
+
+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()
+
+def error_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.showerror(message=information)
+    root.destroy()
+
+#normalization factor to is for both normalizations 10**6/width mA/mm = uA/um = 10**(-6)A/um (returned from the tool)
+def normalization_factor(width):
+    factor = 10**6/width
+    return factor
+
+
+def save_as_ini(default_filename):
+    root = tk.Tk()
+    root.withdraw()
+    root.lift() #show window above all other applications
+
+    root.attributes("-topmost", True)#window stays above all other applications
+
+    file = filedialog.asksaveasfilename(defaultextension=".ini", filetypes=[("Ini files","*.ini")],title = "save as ini",initialfile =default_filename)
+
+    #check if the file path is correct(.txt)
+    while file.endswith(".ini") == False:
+        #open again filedialog with error message box
+        answer=tk.messagebox.askyesno(message='Do you want to cancel the ini file Save?')
+        if answer == True:
+            raise Exception("Ini File Operation aborted!")
+        else:
+            file = filedialog.asksaveasfilename(defaultextension=".ini", filetypes=[("Ini files","*.ini")],title = "save as ini",initialfile =default_filename)
+    root.destroy()
+    return file
+
+def load_ini():
+    root = tk.Tk()
+    root.withdraw()
+    root.lift() #show window above all other applications
+
+    root.attributes("-topmost", True)#window stays above all other applications
+
+    
+    file = filedialog.askopenfilename(filetypes=[("Ini files","*.ini")],title ='Select ini file')
+    while file.endswith(".ini") == False:
+        #open again filedialog with error message box
+        answer=tk.messagebox.askyesno(message='Do you want to cancel the ini file load?')
+        if answer == True:
+            raise Exception("Ini File Operation aborted!")
+        else:
+            file = filedialog.askopenfilename(filetypes=[("Ini files","*.ini")],title = "Select ini file")
+    root.destroy()
+    return file
+
+# function to return ratio and offset for synchronous sweep measurement
+def calculate_line(VTG,VBG): # from now interface objects
+    ratio = (VBG.stop.value-VBG.start.value)/(VTG.stop.value-VTG.start.value)
+    offset = VBG.start.value-ratio*VTG.start.value    
+    return ratio,offset
+
+
+
+#check if smu configuration has a double value
+def check_configuration(sample): # the sample object from the interface
+    #convert the dictionaries values to a list
+    
+    map_list = [sample.source.value,sample.top_gate.value,sample.back_gate.value,sample.drain.value]
+
+    #remove the duplicates by using a set
+    map_set = set(map_list)
+
+    if len(map_set)!= len(map_list): #we have duplicates
+        raise Exception("You cannot assign a smu to multiple contacts")
+
+
+
+# The function for graph in the tool
+def graph_tool(plot_config,width,device): # the plot config object from the interface
+    device.delete_axis("X")
+    device.delete_axis("Y1")
+    device.delete_axis("Y2")
+
+    # How to define user functions correctly and not multiple times
+    plot_list = [plot_config.x.value,plot_config.y1.value,plot_config.y2.value]
+    plot_set = set(plot_list)
+
+    
+    #define the no values
+    for element in plot_set:
+        if element != "None":
+            if element.endswith("mm"): #only I values
+                #define the respective user function
+                device.user_function(element,"mA/mm",f"{element[:-2]}*{normalization_factor(width)}") #max 3
+    
+            #define the absolute(A to indicate absolute) always 3 (max 6!)
+            if element.startswith('I') and element.endswith('mm'):
+                device.user_function('A'+element,"mA/mm",f"ABS({element})")
+            elif element.startswith('I') and element.endswith('mm')== False: 
+                device.user_function('A'+element,"A",f"ABS({element})")  
+             
+
+    # Now send the parameters in the tool
+    device.display_variable('X',plot_config.x.value)
+    device.axis_scale('X','LIN')
+    device.display_variable_min_max('X','MIN',plot_config.x_min.value)
+    device.display_variable_min_max('X','MAX',plot_config.x_max.value)
+
+
+    if plot_config.y1_scale.value=='LOG':
+        device.display_variable('Y1',"A"+plot_config.y1.value)
+    else:
+        device.display_variable('Y1',plot_config.y1.value)
+    device.axis_scale('Y1',plot_config.y1_scale.value)
+    device.display_variable_min_max('Y1','MIN',plot_config.y1_min.value)
+    device.display_variable_min_max('Y1','MAX',plot_config.y1_max.value)
+
+    if plot_config.y2.value!= "None":
+        if plot_config.y2_scale.value=='LOG':
+            device.display_variable('Y2',"A"+plot_config.y2.value)
+        else:
+            device.display_variable('Y2',plot_config.y2.value)
+        device.axis_scale('Y2',plot_config.y2_scale.value)
+        device.display_variable_min_max('Y2','MIN',plot_config.y2_min.value)
+        device.display_variable_min_max('Y2','MAX',plot_config.y2_max.value)
+
+
+
+#plot software functions
+def column_to_plot(element):
+    if element != "None":
+        if element.startswith("V"):
+            column = element+"/V"
+            label = f"{element} (V)"
+        elif element.startswith('I') and element.endswith('mm'):
+            column = element + "/uA/um"
+            label = f"{element[:-2]} (uA/um)"
+        else: # regular I
+            column = element+"/A"
+            label = f"{element} (A)"
+
+    return column,label 
+
+def create_file(filename):
+    root = tk.Tk()
+    root.withdraw()
+    root.lift() #show window above all other applications
+
+    root.attributes("-topmost", True)#window stays above all other applications
+
+    file = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files","*.txt")],title = "save results path",initialfile =filename)
+
+    #check if the file path is correct(.txt)
+    while file.endswith(".txt") == False:
+        #open again filedialog with error message box
+        tk.messagebox.showerror(message='invalid filename!')
+        file = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files","*.txt")],title = "save results path",initialfile =default_filename)
+
+    root.destroy()
+
+    return file
+
+def write_sample_information(sample,file):
+    file.write(f"Series:{sample.processing_number.value}"+"\n")
+    file.write(f"Sample:{sample.sample.value}"+"\n")
+    file.write(f"Field:{sample.field.value}"+"\n")
+    file.write(f"Device:{sample.device.value}"+"\n")
+    file.write(f"Device Width/um:{sample.width.value}"+"\n")
+
+def create_plot(plot_config,df,file,fig_title,legend_title,save):
+    labels = df["label"].unique()
+    colors = plt.cm.tab20.colors[:len(labels)]
+    
+    fig,ax1 = plt.subplots(figsize = (10,6))
+    x_col,x_label = column_to_plot(plot_config.x.value)
+    y1_col, y1_label = column_to_plot(plot_config.y1.value)
+
+    if plot_config.y1_scale.value == 'LOG':
+        ax1.set_yscale('log')
+        for color, label in zip(colors,labels):
+            subset = df[df["label"]== label]
+            ax1.plot(subset[x_col],subset[y1_col].abs(),color = color,label = label)
+    else:
+        for color, label in zip(colors,labels):
+            subset = df[df["label"]== label]
+            ax1.plot(subset[x_col],subset[y1_col],color = color,label = label)
+
+    ax1.set_xlabel(x_label)
+    ax1.set_ylabel(y1_label)
+    ax1.set_title(fig_title,fontweight = 'bold')
+    ax1.grid(True)
+    ax1.legend(
+        title = legend_title,
+        bbox_to_anchor = (1.05,1),
+        loc = "upper left"
+    )
+    
+    fig.tight_layout()
+    display(fig)
+
+    if save:
+        filename = os.path.splitext(file)[0]
+        fig.savefig(filename+"_Y1.png")
+
+    # now for the y2 axis
+    if plot_config.y2.value!= "None":
+        fig,ax2 = plt.subplots(figsize = (10,6))
+        y2_col, y2_label = column_to_plot(plot_config.y2.value)
+
+        if plot_config.y2_scale.value == 'LOG':
+            ax2.set_yscale('log')
+            for color, label in zip(colors,labels):
+                subset = df[df["label"]== label]
+                ax2.plot(subset[x_col],subset[y2_col].abs(),color = color,label = label)
+        else:
+            for color, label in zip(colors,labels):
+                subset = df[df["label"]== label]
+                ax2.plot(subset[x_col],subset[y2_col],color = color,label = label)
+
+        ax2.set_xlabel(x_label)
+        ax2.set_ylabel(y2_label)
+        ax2.set_title(fig_title,fontweight = 'bold')
+        ax2.grid(True)
+        ax2.legend(
+            title = legend_title,
+            bbox_to_anchor = (1.05,1),
+            loc = "upper left"
+        )
+        fig.tight_layout()
+        display(fig)
+
+        if save:
+            filename = os.path.splitext(file)[0]
+            fig.savefig(filename+"_Y2.png")
\ No newline at end of file
diff --git a/hp4155/ADU_for_double_gate_devices_version_3/lib/interface.py b/hp4155/ADU_for_double_gate_devices_version_3/lib/interface.py
new file mode 100644
index 0000000000000000000000000000000000000000..c1deb7d1c25e72d4691813be97ef2e4c36089dd5
--- /dev/null
+++ b/hp4155/ADU_for_double_gate_devices_version_3/lib/interface.py
@@ -0,0 +1,388 @@
+import ipywidgets as widgets
+from ipywidgets import GridspecLayout,Layout
+from IPython.display import clear_output
+import sys
+import os
+
+width = "50%"
+height = 'auto'
+style = {'description_width': 'initial'}
+floatbox_width = "80%"
+
+
+# functionallities for the widgets
+# No more dictionaries 
+def add_widgets_to_list(source_class,target_list):
+    for widget in (vars(source_class)).values():
+        target_list.append(widget)
+
+def change_state(widgets_list):
+    for widget in widgets_list:
+        try: 
+            widget.disabled = not widget.disabled
+        except:
+            pass # Perhaps other objects are there too
+
+# here are the custom widgets
+def measurement_check(name):
+    check=widgets.Checkbox(
+        description = name,
+        value = True,
+        indent = False
+    )
+
+    return check
+    
+
+def integration_time(selection):
+    
+    options_integration=["SHORt","MEDium","LONG"]
+    
+    integration= widgets.Dropdown(
+        options=options_integration,
+        value=selection,description='Integration Time',
+        style =style,
+        layout=Layout(height='auto', width="30%")
+    )
+    
+    return integration
+
+def gate_selection(*options):
+    gates = widgets.Dropdown(
+        options = options,
+        description = 'Selected Gate(s):',
+        style = style 
+    )
+    return gates
+
+# Here are the custom grids
+class primary:
+    def __init__(self,name,start,step,stop,comp):
+        self.grid = GridspecLayout(4,4)
+        self.grid[:,3]=widgets.Label(name,layout=Layout(height='auto', width='auto'))
+        self.grid[:,3].style.font_weight = 'bold'
+    
+    
+        #first line
+        self.grid[0,0]=widgets.Label("Start(V)",layout=Layout(height='auto', width='auto'))
+        self.grid[0,1]=widgets.Label("Step(V)",layout=Layout(height='auto', width='auto'))
+        self.grid[0,2]=widgets.Label("Stop(V)",layout=Layout(height='auto', width='auto'))
+    
+        #second line
+        self.grid[1,0]=widgets.BoundedFloatText(value=start,min=-100,max=100,step=1,layout=Layout(height='auto', width=floatbox_width))
+        self.grid[1,1]=widgets.BoundedFloatText(value=step,min=-200,max=200,step=1,layout=Layout(height='auto', width=floatbox_width))
+        self.grid[1,2]=widgets.BoundedFloatText(value=stop,min=-100,max=100,step=1,layout=Layout(height='auto', width=floatbox_width))
+    
+        #third line 
+        self.grid[2,0]=widgets.Label("Compliance(A)",layout=Layout(height='auto', width='auto'))
+        self.grid[2,1] =widgets.Label("Power Compliance(W)(0=OFF)",layout=Layout(height='auto', width='auto'))#mind the gap
+        self.grid[2,2] =widgets.Label("Hysterisis",layout=Layout(height='auto', width='auto'))#mind the gap
+    
+        #fourth line
+        self.grid[3,0]=widgets.BoundedFloatText(value=comp,min=-0.1,max=0.1,step=0.01,layout=Layout(height='auto', width=floatbox_width))
+        self.grid[3,1]=widgets.BoundedFloatText(value=0,min=0,max=2,step=0.1,layout=Layout(height='auto', width=floatbox_width))#mind the gap
+        self.grid[3,2]=widgets.Dropdown(options=['SINGle','DOUBle'],value='SINGle',layout=Layout(height='auto', width=floatbox_width))#mind the gap
+
+   
+        self.start = self.grid[1,0]
+        self.step = self.grid[1,1]
+        self.stop = self.grid[1,2]
+        self.comp = self.grid[3,0]
+        self.hyst = self.grid[3,2]
+        self.pcomp = self.grid[3,1]
+
+class secondary:
+    def __init__(self,name,start,step,stop,comp):
+        self.grid = GridspecLayout(4,4)
+        self.grid[:,3]=widgets.Label(name,layout=Layout(height='auto', width='auto'))
+        self.grid[:,3].style.font_weight = 'bold'
+    
+        #first line
+        self.grid[0,0]=widgets.Label("Start(V)",layout=Layout(height='auto', width='auto'))
+        self.grid[0,1]=widgets.Label("Step(V)",layout=Layout(height='auto', width='auto'))
+        self.grid[0,2]=widgets.Label("Stop(V)",layout=Layout(height='auto', width='auto'))
+    
+        #second line
+        self.grid[1,0]=widgets.BoundedFloatText(value=start,min=-100,max=100,step=1,layout=Layout(height='auto', width=floatbox_width))
+        self.grid[1,1]=widgets.BoundedFloatText(value=step,min=-200,max=200,step=1,layout=Layout(height='auto', width=floatbox_width))
+        self.grid[1,2]=widgets.BoundedFloatText(value=stop,min=-100,max=100,step=1,layout=Layout(height='auto', width=floatbox_width))
+    
+        #third line 
+        self.grid[2,0]=widgets.Label("Compliance(A)",layout=Layout(height='auto', width='auto'))
+        self.grid[2,2] =widgets.Label("Power Compliance(W)(0=OFF)",layout=Layout(height='auto', width='auto'))#mind the gap
+    
+        #fourth line
+        self.grid[3,0]=widgets.BoundedFloatText(value=comp,min=-0.1,max=0.1,step=0.01,layout=Layout(height='auto', width=floatbox_width))
+        self.grid[3,2]=widgets.BoundedFloatText(value=0,min=0,max=2,step=0.1,layout=Layout(height='auto', width=floatbox_width))#mind the gap
+    
+        self.start = self.grid[1,0]
+        self.step = self.grid[1,1]
+        self.stop = self.grid[1,2]
+        self.comp = self.grid[3,0]
+        self.pcomp = self.grid[3,2]
+        
+        
+        
+
+class sample:
+    def __init__(self):
+        width = '90%'
+        sample_information=widgets.Label("Sample Information",layout=Layout(height=height, width='50%'))
+        sample_information.style.font_weight='bold'
+        self.grid=GridspecLayout(3,2)
+        
+        for i in range(3):
+            for j in range(2):
+                if i ==2 and j == 1:
+                    self.grid[i,j]=widgets.Checkbox(value = True,indent = False)
+                elif i == 2 and j == 0:                
+                    self.grid[i,j]=widgets.BoundedFloatText(
+                        value=100,
+                        min=1e-3,
+                        max=sys.float_info.max,step=1,
+                        layout=Layout(height=height, width=width)
+                    )
+                else:
+                    self.grid[i,j]=widgets.Text(layout=Layout(height=height, width=width))
+    
+        self.grid[0,0].description = "Processing-Nr:"
+        self.grid[1,0].description = "Sample:"
+        self.grid[2,0].description = "Device Width(um):"
+        self.grid[0,1].description = "Field(XYY):"
+        self.grid[1,1].description = "Device:"
+        self.grid[2,1].description ='Save Plots'
+    
+        for i in range(3):
+            for j in range(2):
+                self.grid[i,j].style = style
+    
+        
+    
+        config = widgets.Label("SMU Configuration",layout=Layout(height='auto', width='auto'))
+    
+        self.top_gate = widgets.Dropdown(options=[1,2,3,4],value=1,layout=Layout(height='auto', width='auto'),description = 'Top Gate:',style = style)
+        self.drain = widgets.Dropdown(options=[1,2,3,4],value=2,layout=Layout(height='auto', width='auto'),description = 'Drain:',style = style)
+        self.back_gate = widgets.Dropdown(options=[1,2,3,4],value=3,layout=Layout(height='auto', width='auto'),description = 'Back Gate:',style = style)
+        self.source = widgets.Dropdown(options=[1,2,3,4],value=4,layout=Layout(height='auto', width='auto'),description = 'Source(Ground):',style = style)
+        self.quick = widgets.Checkbox(description = "Quick Measurement",value = False, indent = False)
+    
+    
+        vbox2 = widgets.VBox([config,self.top_gate,self.drain,self.back_gate,self.source,self.quick])
+        vbox1=widgets.VBox([sample_information,self.grid])
+        display(widgets.HBox([vbox1,vbox2]))
+    
+        self.processing_number = self.grid[0,0]
+        self.sample = self.grid[1,0]
+        self.field = self.grid[0,1]
+        self.device = self.grid[1,1]    
+        self.width = self.grid[2,0]
+        self.save_fig = self.grid[2,1]
+        
+
+class plot_config: #meas = 1,2,3 for transfer,output,gatediode 
+    def __init__(self,meas):
+        
+        self.grid = GridspecLayout(6,4)
+    
+        if meas == 2 : # constraints
+            options_x = ['VDS']
+        else :
+            options_x= ['VTG','VBG']
+        
+        if meas ==3:
+            options = ['ITG','IBG','ITGmm','IBGmm','None']
+        else:
+            options = ['ITG','IBG','ID','ITGmm','IBGmm','IDmm','None']
+    
+        # define the default values (y2 is always empty) taken from the interface
+        if meas == 1:# Transfer
+            x_name = 'VTG'
+            x_scale = 'LIN'
+            x_min = -5
+            x_max = 5
+            y1_name = 'IDmm'
+            y1_scale = 'LOG'
+            y1_min = 0
+            y1_max = 100
+        
+        elif meas == 2: # outptut
+            x_name = 'VDS'
+            x_scale = 'LIN'
+            x_min = 0
+            x_max = 5
+            y1_name = 'IDmm'
+            y1_scale = 'LIN'
+            y1_min = -100
+            y1_max = 100
+    
+        else: # == 3 gatediode
+            x_name = 'VTG'
+            x_scale = 'LIN'
+            x_min = -5
+            x_max = 5
+            y1_name = 'ITGmm'
+            y1_scale = 'LOG'
+            y1_min = 0
+            y1_max = 10
+    
+        
+        self.grid[0,:]=widgets.Label('Send Plotting configurations to the tool',layout=Layout(height='auto', width='auto'))
+        #first line headers
+        self.grid[1,1]= widgets.Label('X',layout=Layout(height='auto', width='auto'))
+        self.grid[1,2]= widgets.Label('Y1',layout=Layout(height='auto', width='auto'))
+        self.grid[1,3]= widgets.Label('Y2',layout=Layout(height='auto', width='auto'))
+    
+        #first column 
+        self.grid[2,0] = widgets.Label('NAME',layout=Layout(height='auto', width='auto'))
+        self.grid[3,0] = widgets.Label('SCALE',layout=Layout(height='auto', width='auto'))
+        self.grid[4,0] = widgets.Label('MIN',layout=Layout(height='auto', width='auto'))
+        self.grid[5,0] = widgets.Label('MAX',layout=Layout(height='auto', width='auto'))
+    
+        #iterate through the second line (NAME)
+        must_options = [x for x in options if x!='None']
+        self.grid[2,1]=widgets.Dropdown(layout=Layout(height='auto', width='auto'),options = options_x,value = x_name)
+        self.grid[2,2]=widgets.Dropdown(layout=Layout(height='auto', width='auto'),options = must_options,value = y1_name)
+        self.grid[2,3]=widgets.Dropdown(layout=Layout(height='auto', width='auto'),options = options,value = "None")
+    
+        #Iterate through the third line (scale) 
+        options_scale = ['LIN','LOG']
+        self.grid[3,1] = widgets.Dropdown(value = x_scale,options = options_scale, layout=Layout(height='auto', width='auto'),disabled = True)
+        self.grid[3,2] = widgets.Dropdown(value = y1_scale,options = options_scale, layout=Layout(height='auto', width='auto'))
+        self.grid[3,3] = widgets.Dropdown(value = 'LIN',options = options_scale, layout=Layout(height='auto', width='auto'))
+    
+        #iterate throuh the last 2 lines(min-max)
+       
+        self.grid[4,1] = widgets.FloatText(value = x_min,layout=Layout(height='auto', width='auto')) #min
+        self.grid[4,2] = widgets.FloatText(value = y1_min,layout=Layout(height='auto', width='auto')) #min
+        self.grid[4,3] = widgets.FloatText(value = 0,layout=Layout(height='auto', width='auto')) #min
+    
+        self.grid[5,1]=widgets.FloatText(value = x_max,layout=Layout(height='auto', width='auto')) #max X-axis
+        self.grid[5,2]=widgets.FloatText(value = y1_max,layout=Layout(height='auto', width='auto')) #max Y1-axis
+        self.grid[5,3]=widgets.FloatText(value = 0,layout=Layout(height='auto', width='auto')) #max Y2-axis
+
+        self.x = self.grid[2,1]
+        self.y1 = self.grid[2,2]
+        self.y2 = self.grid[2,3]
+        self.y1_scale = self.grid[3,2]
+        self.y2_scale = self.grid[3,3]
+        self.x_min = self.grid[4,1]
+        self.y1_min = self.grid[4,2]
+        self.y2_min = self.grid[4,3]
+        self.x_max = self.grid[5,1]
+        self.y1_max = self.grid[5,2]
+        self.y2_max = self.grid[5,3]
+
+
+# The whole interface
+class interface:
+    def __init__(self):
+        self.sample = sample()
+        
+        self.transfer_check = measurement_check("Transfer")
+        self.output_check = measurement_check("Output")
+        self.gatediode_check = measurement_check("Gatediode")
+        
+        checkboxes = widgets.HBox([self.transfer_check,self.output_check,self.gatediode_check])
+        display(checkboxes)
+        
+        #transfer
+        
+        self.integration_transfer = integration_time("MEDium")
+        self.transfer_gates = gate_selection("VTG","VBG","BOTH SIMULTANEOUSLY","BOTH SEQUENTIALLY")
+        
+        self.Vds_transfer = secondary('VDS',0.05,0.95,1,1e-2)
+        self.Vtg_transfer = primary('VTG',-5,0.01,5,1e-3)
+        self.Vbg_transfer = primary('VBG',-15,0.1,15,1e-3)
+        self.plot_transfer = plot_config(1)
+        transfer_box = widgets.VBox(
+            [
+                self.integration_transfer,
+                self.transfer_gates,
+                self.Vds_transfer.grid,
+                self.Vtg_transfer.grid,
+                self.Vbg_transfer.grid,
+                self.plot_transfer.grid
+            ]
+        )
+        
+        
+        #output
+        self.integration_output = integration_time("SHORt")
+        self.output_gates = gate_selection("VTG","VBG","BOTH")
+        
+        self.Vds_output = primary('VDS',0,0.01,5,1e-2)
+        self.Vtg_output = secondary('VTG',-5,2,5,1e-3)
+        self.Vbg_output = secondary('VBG',-15,5,15,1e-3)
+        self.plot_output = plot_config(2)
+        
+        output_box = widgets.VBox(
+            [
+                self.integration_output,self.output_gates,
+                self.Vds_output.grid,
+                self.Vtg_output.grid,
+                self.Vbg_output.grid,
+                self.plot_output.grid
+            ]
+        )
+        
+        self.integration_gatediode = integration_time("MEDium")
+        self.gatediode_gates = gate_selection("VTG","VBG")
+        
+        self.Vg_gatediode=primary('VG',-5,0.05,5,1e-3)
+        self.plot_gatediode = plot_config(3)
+        gatediode_box = widgets.VBox(
+            [
+                self.integration_gatediode,
+                self.gatediode_gates,
+                self.Vg_gatediode.grid,
+                self.plot_gatediode.grid
+            ]
+        )
+        
+        #the tab widget
+        children = [transfer_box,output_box,gatediode_box]
+        titles = ["Transfer","Output","Gatediode"]
+        tab = widgets.Tab()
+        tab.children = children
+        tab.titles = titles
+        
+        display(tab)
+
+        # Now the buttons
+        self.start = widgets.Button(description ='Start Measurement')
+        self.output = widgets.Output()
+
+        self.export_ini = widgets.Button(description = 'Export as ini')
+        self.import_ini = widgets.Button(description ='Import from ini')
+
+        # capture all widgets
+        self.all_widgets=[
+            self.transfer_gates,
+            self.output_gates,
+            self.start,         
+            self.transfer_check,
+            self.integration_transfer,
+            self.output_check,
+            self.integration_output,
+            self.gatediode_check,
+            self.integration_gatediode,
+            self.gatediode_gates,
+            self.export_ini,
+            self.import_ini
+        ]
+        add_widgets_to_list(self.sample,self.all_widgets)
+        add_widgets_to_list(self.Vds_transfer,self.all_widgets)
+        add_widgets_to_list(self.Vtg_transfer,self.all_widgets)
+        add_widgets_to_list(self.Vbg_transfer,self.all_widgets)
+        add_widgets_to_list(self.Vds_output,self.all_widgets)
+        add_widgets_to_list(self.Vtg_output,self.all_widgets)
+        add_widgets_to_list(self.Vbg_output,self.all_widgets)
+        add_widgets_to_list(self.Vg_gatediode,self.all_widgets)
+        add_widgets_to_list(self.plot_transfer,self.all_widgets)
+        add_widgets_to_list(self.plot_output,self.all_widgets)
+        add_widgets_to_list(self.plot_gatediode,self.all_widgets)
+
+        line = widgets.HBox([self.start,self.import_ini,self.export_ini])
+        display(line,self.output)
+
+    
\ No newline at end of file
diff --git a/hp4155/ADU_for_double_gate_devices_version_3/lib/output.py b/hp4155/ADU_for_double_gate_devices_version_3/lib/output.py
new file mode 100644
index 0000000000000000000000000000000000000000..dbc7fd30d66cfef0568f6fd9e3346d7b413d12d6
--- /dev/null
+++ b/hp4155/ADU_for_double_gate_devices_version_3/lib/output.py
@@ -0,0 +1,378 @@
+# This file contains the output measurements
+
+import sys
+sys.path.insert(0, '..') #append parent directory
+
+import hp4155a
+from help import *
+from decimal import Decimal
+
+import os
+
+def VTG(ui,device):
+    device.del_user_functions() # delete all user functions 
+    device.clear_error_stack() # clear error stack
+    # setup the smus
+
+    norm = normalization_factor(ui.sample.width.value)
+    points = number_of_points(ui.Vtg_output)
+
+    
+    smu_source = device.smu_dict()
+    smu_source.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS')
+
+    smu_top_gate = device.smu_dict()
+    smu_top_gate.update(vname = 'VTG',iname='ITG',mode = 'V',func='VAR2')
+
+    smu_back_gate = device.smu_dict()
+    smu_back_gate.update(vname = 'VBG',iname='IBG',mode = 'COMM',func = 'CONS')
+
+    smu_drain = device.smu_dict()
+    smu_drain.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR1')
+
+    # setup VAR1
+    var1 = device.var1_dict()
+    var1.update(
+        mode = ui.Vds_output.hyst.value,
+        start = ui.Vds_output.start.value,
+        stop = ui.Vds_output.stop.value,
+        step = ui.Vds_output.step.value,
+        comp = ui.Vds_output.comp.value,
+        pcomp = ui.Vds_output.pcomp.value
+    )
+
+    var2=device.var2_dict() #Vds_output is always used in tranfer curve with the same config
+    var2.update(
+        start=ui.Vtg_output.start.value,
+        step=ui.Vtg_output.step.value,
+        points=points,
+        comp=ui.Vtg_output.comp.value,
+        pcomp=ui.Vtg_output.pcomp.value,
+    )
+
+    try:
+        device.setup_smu(ui.sample.top_gate.value,smu_top_gate)
+        device.setup_smu(ui.sample.drain.value,smu_drain)
+        device.setup_smu(ui.sample.back_gate.value,smu_back_gate)
+        device.setup_smu(ui.sample.source.value,smu_source)
+    
+        device.setup_var1(var1)
+        device.setup_var2(var2)
+    
+        device.integration_time(ui.integration_output.value)
+        variables_list = ['VDS','ID','VTG','ITG']
+        device.variables_to_save(variables_list)
+
+        plotted_variables = graph_tool(ui.plot_output,ui.sample.width.value,device)
+
+        device.error_occured()
+
+        device.single_measurement()
+        
+        while device.operation_completed()==False:
+            pass
+
+        device.error_occured()
+
+        if ui.sample.quick.value == False:
+            device.autoscaling()
+       
+    
+        values = dict([(variable,device.return_values(variable)) for variable in variables_list])
+        df = get_dataframe_from_results(values)
+    except Exception as e:
+        error_box(e)
+        return
+
+    # Append the normalized current 
+    df["IDmm/uA/um"]= (df["ID/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+    df["ITGmm/uA/um"]= (df["ITG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+
+    default_filename = f"{ui.sample.sample.value}_{ui.sample.field.value}_{ui.sample.device.value}_TOP_GATE_A.txt"
+    file = create_file(default_filename)
+
+    with open(file,'w') as f:
+        date = str(datetime.today().replace(microsecond=0))
+        f.write(f"Output Curve at {date}"+"\n")
+        write_sample_information(ui.sample,f)
+        f.write("Sweeping Gate:VTG"+"\n\n")
+        f.write('Parameters\n')
+        f.write(f"VTG from {ui.Vtg_output.start.value}V to {ui.Vtg_output.stop.value}V with step {ui.Vtg_output.step.value}V"+"\n")
+        f.write(f"VDS from {ui.Vds_output.start.value}V to {ui.Vds_output.stop.value}V with step {ui.Vds_output.step.value}V"+"\n")
+        
+        if ui.Vtg_output.pcomp.value==0:
+            f.write(f"Top Gate Current Compliance/A:{ui.Vtg_output.comp.value}"+"\n")
+        else:
+            f.write(f"Top Gate Power Compliance/A:{ui.Vtg_output.pcomp.value}"+"\n")
+
+        if ui.Vds_output.pcomp.value == 0:
+            f.write(f"Drain Current Compliance/A:{ui.Vds_output.comp.value}"+"\n")
+        else:
+             f.write(f"Drain Power Compliance/A:{ui.Vds_output.pcomp.value}"+"\n")
+        f.write(f"Integration Time:{ui.integration_output.value}"+"\n")
+        f.write("\nResults\n")
+
+    df.to_csv(file,sep=" ",mode='a')
+
+    if ui.sample.quick.value == False:
+        df["label"] = df.apply(lambda row:f"VTG = {row['VTG/V']} (V)",axis = 1) # assign labels
+        create_plot(ui.plot_output,df,file,"Top Gate Output Measurement", "Swept VTG voltages:",ui.sample.save_fig.value)
+
+
+def VBG(ui,device):
+    device.del_user_functions() # delete all user functions 
+    device.clear_error_stack() # clear error stack
+    # setup the smus
+
+    norm = normalization_factor(ui.sample.width.value)
+    points = number_of_points(ui.Vbg_output)
+
+    
+    smu_source = device.smu_dict()
+    smu_source.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS')
+
+    smu_top_gate = device.smu_dict()
+    smu_top_gate.update(vname = 'VTG',iname='ITG',mode = 'COMM',func='CONS')
+
+    smu_back_gate = device.smu_dict()
+    smu_back_gate.update(vname = 'VBG',iname='IBG',mode = 'V',func = 'VAR2')
+
+    smu_drain = device.smu_dict()
+    smu_drain.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR1')
+
+    # setup VAR1
+    var1 = device.var1_dict()
+    var1.update(
+        mode = ui.Vds_output.hyst.value,
+        start = ui.Vds_output.start.value,
+        stop = ui.Vds_output.stop.value,
+        step = ui.Vds_output.step.value,
+        comp = ui.Vds_output.comp.value,
+        pcomp = ui.Vds_output.pcomp.value
+    )
+
+    var2=device.var2_dict() #Vds_output is always used in tranfer curve with the same config
+    var2.update(
+        start=ui.Vbg_output.start.value,
+        step=ui.Vbg_output.step.value,
+        points=points,
+        comp=ui.Vbg_output.comp.value,
+        pcomp=ui.Vbg_output.pcomp.value,
+    )
+
+    try:
+        device.setup_smu(ui.sample.top_gate.value,smu_top_gate)
+        device.setup_smu(ui.sample.drain.value,smu_drain)
+        device.setup_smu(ui.sample.back_gate.value,smu_back_gate)
+        device.setup_smu(ui.sample.source.value,smu_source)
+    
+        device.setup_var1(var1)
+        device.setup_var2(var2)
+    
+        device.integration_time(ui.integration_output.value)
+
+        variables_list = ['VDS','ID','VBG','IBG']
+        device.variables_to_save(variables_list)
+
+        plotted_variables = graph_tool(ui.plot_output,ui.sample.width.value,device)
+
+        device.error_occured()
+        
+        device.single_measurement()
+        
+        while device.operation_completed()==False:
+            pass
+
+        device.error_occured()
+
+        if ui.sample.quick.value == False:
+            device.autoscaling()
+       
+    
+        values = dict([(variable,device.return_values(variable)) for variable in variables_list])
+        df = get_dataframe_from_results(values)
+    except Exception as e:
+        error_box(e)
+        return
+
+    # Append the normalized current 
+    df["IDmm/uA/um"]= (df["ID/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+    df["IBGmm/uA/um"]= (df["IBG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+
+
+    # Save the results
+    default_filename = f"{ui.sample.sample.value}_{ui.sample.field.value}_{ui.sample.device.value}_BACK_GATE_A.txt"
+    file = create_file(default_filename)
+
+    with open(file,'w') as f:
+        date = str(datetime.today().replace(microsecond=0))
+        f.write(f"Output Curve at {date}"+"\n")
+        write_sample_information(ui.sample,f)
+        f.write("Sweeping Gate:VBG"+"\n\n")
+        f.write('Parameters\n')
+        f.write(f"VBG from {ui.Vbg_output.start.value}V to {ui.Vbg_output.stop.value}V with step {ui.Vbg_output.step.value}V"+"\n")
+        f.write(f"VDS from {ui.Vds_output.start.value}V to {ui.Vds_output.stop.value}V with step {ui.Vds_output.step.value}V"+"\n")
+        
+        if ui.Vbg_output.pcomp.value==0:
+            f.write(f"Back Gate Current Compliance/A:{ui.Vbg_output.comp.value}"+"\n")
+        else:
+            f.write(f"Back Gate Power Compliance/A:{ui.Vbg_output.pcomp.value}"+"\n")
+
+        if ui.Vds_output.pcomp.value == 0:
+            f.write(f"Drain Current Compliance/A:{ui.Vds_output.comp.value}"+"\n")
+        else:
+             f.write(f"Drain Power Compliance/A:{ui.Vds_output.pcomp.value}"+"\n")
+        f.write(f"Integration Time:{ui.integration_output.value}"+"\n")
+        f.write("\nResults\n")
+
+    df.to_csv(file,sep=" ",mode='a')
+
+    if ui.sample.quick.value == False:
+        df["label"] = df.apply(lambda row:f"VBG = {row['VBG/V']} (V)",axis = 1) # assign labels
+        create_plot(ui.plot_output,df,file,"Back Gate Output Measurement", "Swept VBG voltages:",ui.sample.save_fig.value)
+
+def SEQ(ui,device):
+    device.del_user_functions() # delete all user functions 
+    device.clear_error_stack() # clear error stack
+    norm = normalization_factor(ui.sample.width.value)
+    points_VTG = number_of_points(ui.Vtg_output)
+    points_VBG = number_of_points(ui.Vbg_output)
+
+    try:
+        values_VBG = np.linspace(ui.Vbg_output.start.value, ui.Vbg_output.stop.value,num = points_VBG,endpoint = True)
+    except:
+        error_box("Invalid VBG values!")
+        return
+
+    smu_source = device.smu_dict()
+    smu_source.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS')
+
+    smu_top_gate = device.smu_dict()
+    smu_top_gate.update(vname = 'VTG',iname='ITG',mode = 'V',func='VAR2')
+
+    smu_back_gate = device.smu_dict()
+    smu_back_gate.update(vname = 'VBG',iname='IBG',mode = 'V',func = 'CONS') 
+
+    smu_drain = device.smu_dict()
+    smu_drain.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR1')
+
+    # setup VAR1
+    var1 = device.var1_dict()
+    var1.update(
+        mode = ui.Vds_output.hyst.value,
+        start = ui.Vds_output.start.value,
+        stop = ui.Vds_output.stop.value,
+        step = ui.Vds_output.step.value,
+        comp = ui.Vds_output.comp.value,
+        pcomp = ui.Vds_output.pcomp.value
+    )
+
+    var2=device.var2_dict() #Vds_output is always used in tranfer curve with the same config
+    var2.update(
+        start=ui.Vtg_output.start.value,
+        step=ui.Vtg_output.step.value,
+        points=points_VTG,
+        comp=ui.Vtg_output.comp.value,
+        pcomp=ui.Vtg_output.pcomp.value,
+    )
+    
+    try:
+        device.setup_smu(ui.sample.top_gate.value,smu_top_gate)
+        device.setup_smu(ui.sample.drain.value,smu_drain)
+        device.setup_smu(ui.sample.back_gate.value,smu_back_gate)
+        device.setup_smu(ui.sample.source.value,smu_source)
+    
+        device.setup_var1(var1) 
+        device.setup_var2(var2)
+
+        device.integration_time(ui.integration_output.value)
+        
+        variables_list =["VBG","IBG","VDS","ID","VTG","ITG"]
+        device.variables_to_save(variables_list)
+
+        plotted_variables = graph_tool(ui.plot_output,ui.sample.width.value,device)
+
+        device.error_occured()
+        for i,value in enumerate(values_VBG):
+            cons = device.cons_smu_dict()
+            cons.update(comp = ui.Vbg_output.comp.value, value = value)
+            device.setup_cons_smu(ui.sample.back_gate.value,cons)
+
+            if i == 0:
+                device.single_measurement()
+            else:
+                device.append_measurement()
+            
+            while device.operation_completed()==False:
+                pass
+            device.error_occured()
+
+        if ui.sample.quick.value == False:
+            device.autoscaling()
+        
+        values = dict([(variable,device.return_values(variable)) for variable in variables_list])
+        df = get_dataframe_from_results(values)
+
+    except Exception as e:
+        error_box(e)
+        return
+
+    # Append the normalized current 
+    df["IDmm/uA/um"]= (df["ID/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+    df["IBGmm/uA/um"]= (df["IBG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+    df["ITGmm/uA/um"]= (df["ITG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+
+
+    # Save the results
+    default_filename = f"{ui.sample.sample.value}_{ui.sample.field.value}_{ui.sample.device.value}_BOTH_GATES_SEQ_A.txt"
+    file = create_file(default_filename)
+
+    with open(file,'w') as f:
+        date = str(datetime.today().replace(microsecond=0))
+        f.write(f"output Curve at {date}"+"\n")
+        write_sample_information(ui.sample,f)
+        f.write("Sweeping Gate:VTG,VBG sequentially"+"\n\n")
+        f.write('Parameters\n')
+        f.write(f"VBG from {ui.Vbg_output.start.value}V to {ui.Vbg_output.stop.value}V with step {ui.Vbg_output.step.value}V"+"\n")
+        f.write(f"VTG from {ui.Vtg_output.start.value}V to {ui.Vtg_output.stop.value}V with step {ui.Vbg_output.step.value}V"+"\n")
+        f.write(f"VDS from {ui.Vds_output.start.value}V to {ui.Vds_output.stop.value}V with step {ui.Vds_output.step.value}V"+"\n")
+        
+        f.write(f"Back Gate Current Compliance/A:{ui.Vbg_output.comp.value}"+"\n")
+
+        if ui.Vtg_output.pcomp.value==0:
+            f.write(f"Top Gate Current Compliance/A:{ui.Vtg_output.comp.value}"+"\n")
+        else:
+            f.write(f"Top Gate Power Compliance/A:{ui.Vtg_output.pcomp.value}"+"\n")        
+
+        if ui.Vds_output.pcomp.value == 0:
+            f.write(f"Drain Current Compliance/A:{ui.Vds_output.comp.value}"+"\n")
+        else:
+             f.write(f"Drain Power Compliance/A:{ui.Vds_output.pcomp.value}"+"\n")
+        f.write(f"Integration Time:{ui.integration_output.value}"+"\n")
+        f.write("\nResults\n")
+
+    df.to_csv(file,sep=" ",mode='a')
+
+    if ui.sample.quick.value == False:
+        df["label"] = df.apply(lambda row:f"VTG = {row['VTG/V']} (V), VBG = {row['VBG/V']} (V)",axis = 1) # assign labels
+        create_plot(ui.plot_output,df,file,"Sequential Sweep of Both Gates Output Measurement", "Swept voltages:",ui.sample.save_fig.value)
+        
+        
+
+    
+    
+
+
+        
+    
+
+
+    
+
+    
+
+    
+        
+
+    
+    
\ No newline at end of file
diff --git a/hp4155/ADU_for_double_gate_devices_version_3/lib/transfer.py b/hp4155/ADU_for_double_gate_devices_version_3/lib/transfer.py
new file mode 100644
index 0000000000000000000000000000000000000000..d9851d71b5fbe4f447bd2fcbc27465118cc008fe
--- /dev/null
+++ b/hp4155/ADU_for_double_gate_devices_version_3/lib/transfer.py
@@ -0,0 +1,500 @@
+# This file contains the transfer measurements
+
+import sys
+sys.path.insert(0, '..') #append parent directory
+
+import hp4155a
+from help import *
+from decimal import Decimal
+
+import os
+
+def VTG(ui,device):
+    device.del_user_functions() # delete all user functions 
+    device.clear_error_stack() # clear error stack
+    # setup the smus
+
+    norm = normalization_factor(ui.sample.width.value)
+    points = number_of_points(ui.Vds_transfer)
+
+    smu_source = device.smu_dict()
+    smu_source.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS')
+
+    smu_top_gate = device.smu_dict()
+    smu_top_gate.update(vname = 'VTG',iname='ITG',mode = 'V',func='VAR1')
+
+    smu_back_gate = device.smu_dict()
+    smu_back_gate.update(vname = 'VBG',iname='IBG',mode = 'COMM',func = 'CONS')
+
+    smu_drain = device.smu_dict()
+    smu_drain.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR2')
+
+    # setup VAR1
+    var1 = device.var1_dict()
+    var1.update(
+        mode = ui.Vtg_transfer.hyst.value,
+        start = ui.Vtg_transfer.start.value,
+        stop = ui.Vtg_transfer.stop.value,
+        step = ui.Vtg_transfer.step.value,
+        comp = ui.Vtg_transfer.comp.value,
+        pcomp = ui.Vtg_transfer.pcomp.value
+    )
+
+    var2=device.var2_dict() #Vds_output is always used in tranfer curve with the same config
+    var2.update(
+        start=ui.Vds_transfer.start.value,
+        step=ui.Vds_transfer.step.value,
+        points=points,
+        comp=ui.Vds_transfer.comp.value,
+        pcomp=ui.Vds_transfer.pcomp.value,
+    )
+   
+    try:
+        device.setup_smu(ui.sample.top_gate.value,smu_top_gate)
+        device.setup_smu(ui.sample.drain.value,smu_drain)
+        device.setup_smu(ui.sample.back_gate.value,smu_back_gate)
+        device.setup_smu(ui.sample.source.value,smu_source)
+    
+        device.setup_var1(var1)
+        device.setup_var2(var2)
+    
+        device.integration_time(ui.integration_transfer.value)
+    
+        variables_list =["VTG","ITG","VDS","ID"]
+        device.variables_to_save(variables_list)
+    
+        plotted_variables = graph_tool(ui.plot_transfer,ui.sample.width.value,device)
+
+        device.error_occured()
+        
+        device.single_measurement()
+        while device.operation_completed()==False:
+            pass
+
+        device.error_occured()
+
+        if ui.sample.quick.value == False:
+            device.autoscaling()
+       
+    
+        values = dict([(variable,device.return_values(variable)) for variable in variables_list])
+        df = get_dataframe_from_results(values)
+    except Exception as e:
+        error_box(e)
+        return
+
+    # Append the normalized current 
+    df["IDmm/uA/um"]= (df["ID/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+    df["ITGmm/uA/um"]= (df["ITG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+
+    # Save the results
+    default_filename = f"{ui.sample.sample.value}_{ui.sample.field.value}_{ui.sample.device.value}_TOP_GATE_U.txt"
+    file = create_file(default_filename)
+    
+    with open(file,'w') as f:
+        date = str(datetime.today().replace(microsecond=0))
+        f.write(f"Transfer Curve at {date}"+"\n")
+        write_sample_information(ui.sample,f)
+        f.write("Sweeping Gate:VTG"+"\n\n")
+        f.write('Parameters\n')
+        f.write(f"VTG from {ui.Vtg_transfer.start.value}V to {ui.Vtg_transfer.stop.value}V with step {ui.Vtg_transfer.step.value}V"+"\n")
+        f.write(f"VDS from {ui.Vds_transfer.start.value}V to {ui.Vds_transfer.stop.value}V with step {ui.Vds_transfer.step.value}V"+"\n")
+        
+        if ui.Vtg_transfer.pcomp.value==0:
+            f.write(f"Top Gate Current Compliance/A:{ui.Vtg_transfer.comp.value}"+"\n")
+        else:
+            f.write(f"Top Gate Power Compliance/A:{ui.Vtg_transfer.pcomp.value}"+"\n")
+
+        if ui.Vds_transfer.pcomp.value == 0:
+            f.write(f"Drain Current Compliance/A:{ui.Vds_transfer.comp.value}"+"\n")
+        else:
+             f.write(f"Drain Power Compliance/A:{ui.Vds_transfer.pcomp.value}"+"\n")
+        f.write(f"Integration Time:{ui.integration_transfer.value}"+"\n")
+        f.write("\nResults\n")
+
+    df.to_csv(file,sep=" ",mode='a')
+
+    if ui.sample.quick.value == False:
+        df["label"] = df.apply(lambda row:f"VDS = {row['VDS/V']} (V)",axis = 1) # assign labels
+        create_plot(ui.plot_transfer,df,file,"Top Gate Transfer Measurement", "Swept VDS voltages:",ui.sample.save_fig.value)
+
+def VBG(ui,device):
+    device.del_user_functions() # delete all user functions 
+    device.clear_error_stack() # clear error stack
+    # setup the smus
+
+    norm = normalization_factor(ui.sample.width.value)
+    points = number_of_points(ui.Vds_transfer)
+
+    smu_source = device.smu_dict()
+    smu_source.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS')
+
+    smu_top_gate = device.smu_dict()
+    smu_top_gate.update(vname = 'VTG',iname='ITG',mode = 'COMM',func='CONS')
+
+    smu_back_gate = device.smu_dict()
+    smu_back_gate.update(vname = 'VBG',iname='IBG',mode = 'V',func = 'VAR1')
+
+    smu_drain = device.smu_dict()
+    smu_drain.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR2')
+
+    
+    var1 = device.var1_dict()
+    var1.update(
+        mode = ui.Vbg_transfer.hyst.value,
+        start = ui.Vbg_transfer.start.value,
+        stop = ui.Vbg_transfer.stop.value,
+        step = ui.Vbg_transfer.step.value,
+        comp = ui.Vbg_transfer.comp.value,
+        pcomp = ui.Vbg_transfer.pcomp.value
+    )
+
+    var2=device.var2_dict() #Vds_output is always used in tranfer curve with the same config
+    var2.update(
+        start=ui.Vds_transfer.start.value,
+        step=ui.Vds_transfer.step.value,
+        points=points,
+        comp=ui.Vds_transfer.comp.value,
+        pcomp=ui.Vds_transfer.pcomp.value,
+    )
+
+    try:
+        device.setup_smu(ui.sample.top_gate.value,smu_top_gate)
+        device.setup_smu(ui.sample.drain.value,smu_drain)
+        device.setup_smu(ui.sample.back_gate.value,smu_back_gate)
+        device.setup_smu(ui.sample.source.value,smu_source)
+    
+        device.setup_var1(var1)
+        device.setup_var2(var2)
+    
+        device.integration_time(ui.integration_transfer.value)
+
+        variables_list =["VBG","IBG","VDS","ID"]
+        device.variables_to_save(variables_list)
+
+        plotted_variables = graph_tool(ui.plot_transfer,ui.sample.width.value,device)
+
+        device.error_occured()
+        
+        device.single_measurement()
+        
+        while device.operation_completed()==False:
+            pass
+
+        device.error_occured()
+
+        if ui.sample.quick.value == False:
+            device.autoscaling()
+       
+    
+        values = dict([(variable,device.return_values(variable)) for variable in variables_list])
+        df = get_dataframe_from_results(values)
+    except Exception as e:
+        error_box(e)
+        return
+
+    # Append the normalized current 
+    df["IDmm/uA/um"]= (df["ID/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+    df["IBGmm/uA/um"]= (df["IBG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+
+
+    # Save the results
+    default_filename = f"{ui.sample.sample.value}_{ui.sample.field.value}_{ui.sample.device.value}_BACK_GATE_U.txt"
+    file = create_file(default_filename)
+
+    with open(file,'w') as f:
+        date = str(datetime.today().replace(microsecond=0))
+        f.write(f"Transfer Curve at {date}"+"\n")
+        write_sample_information(ui.sample,f)
+        f.write("Sweeping Gate:VBG"+"\n\n")
+        f.write('Parameters\n')
+        f.write(f"VBG from {ui.Vbg_transfer.start.value}V to {ui.Vbg_transfer.stop.value}V with step {ui.Vbg_transfer.step.value}V"+"\n")
+        f.write(f"VDS from {ui.Vds_transfer.start.value}V to {ui.Vds_transfer.stop.value}V with step {ui.Vds_transfer.step.value}V"+"\n")
+        
+        if ui.Vbg_transfer.pcomp.value==0:
+            f.write(f"Back Gate Current Compliance/A:{ui.Vbg_transfer.comp.value}"+"\n")
+        else:
+            f.write(f"Back Gate Power Compliance/A:{ui.Vbg_transfer.pcomp.value}"+"\n")
+
+        if ui.Vds_transfer.pcomp.value == 0:
+            f.write(f"Drain Current Compliance/A:{ui.Vds_transfer.comp.value}"+"\n")
+        else:
+             f.write(f"Drain Power Compliance/A:{ui.Vds_transfer.pcomp.value}"+"\n")
+        f.write(f"Integration Time:{ui.integration_transfer.value}"+"\n")
+        f.write("\nResults\n")
+
+    df.to_csv(file,sep=" ",mode='a')
+
+    if ui.sample.quick.value == False:
+        df["label"] = df.apply(lambda row:f"VDS = {row['VDS/V']} (V)",axis = 1) # assign labels
+        create_plot(ui.plot_transfer,df,file,"Back Gate Transfer Measurement", "Swept VDS voltages:",ui.sample.save_fig.value)
+
+
+# Simultaneously bóth gates
+def SIM(ui,device):
+    device.del_user_functions() # delete all user functions 
+    device.clear_error_stack() # clear error stack
+    # setup the smus
+
+    norm = normalization_factor(ui.sample.width.value)
+    points = number_of_points(ui.Vds_transfer)
+
+    smu_source = device.smu_dict()
+    smu_source.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS')
+
+    smu_top_gate = device.smu_dict()
+    smu_top_gate.update(vname = 'VTG',iname='ITG',mode = 'V',func='VAR1')
+
+    smu_back_gate = device.smu_dict()
+    smu_back_gate.update(vname = 'VBG',iname='IBG',mode = 'V',func = 'VARD')
+
+    smu_drain = device.smu_dict()
+    smu_drain.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR2')
+
+    
+    var1 = device.var1_dict()
+    var1.update(
+        mode = ui.Vtg_transfer.hyst.value,
+        start = ui.Vtg_transfer.start.value,
+        stop = ui.Vtg_transfer.stop.value,
+        step = ui.Vtg_transfer.step.value,
+        comp = ui.Vtg_transfer.comp.value,
+        pcomp = ui.Vtg_transfer.pcomp.value
+    )
+
+    var2=device.var2_dict() #Vds_output is always used in tranfer curve with the same config
+    var2.update(
+        start=ui.Vds_transfer.start.value,
+        step=ui.Vds_transfer.step.value,
+        points=points,
+        comp=ui.Vds_transfer.comp.value,
+        pcomp=ui.Vds_transfer.pcomp.value,
+    )
+
+    #calculate parameters for VARD
+    ratio,offset = calculate_line(ui.Vtg_transfer,ui.Vbg_transfer)
+    
+    # update VBG step
+    ui.Vbg_transfer.step.value = Decimal(str(ratio)) * Decimal(str(ui.Vtg_transfer.step.value))
+
+    vard = device.vard_dict()
+    vard.update(
+        offset = offset,
+        ratio = ratio,
+        comp = ui.Vbg_transfer.comp.value,
+        pcomp = ui.Vbg_transfer.pcomp.value
+    )
+
+    try:
+        device.setup_smu(ui.sample.top_gate.value,smu_top_gate)
+        device.setup_smu(ui.sample.drain.value,smu_drain)
+        device.setup_smu(ui.sample.back_gate.value,smu_back_gate)
+        device.setup_smu(ui.sample.source.value,smu_source)
+    
+        device.setup_var1(var1)
+        device.setup_var2(var2)
+        device.setup_vard(vard)
+    
+        device.integration_time(ui.integration_transfer.value)
+
+        variables_list =["VBG","IBG","VDS","ID","VTG","ITG"]
+        device.variables_to_save(variables_list)
+
+        plotted_variables = graph_tool(ui.plot_transfer,ui.sample.width.value,device)
+        
+        device.error_occured()
+        
+        device.single_measurement()
+        
+        while device.operation_completed()==False:
+            pass
+
+        device.error_occured()
+
+        if ui.sample.quick.value == False:
+            device.autoscaling()
+       
+    
+        values = dict([(variable,device.return_values(variable)) for variable in variables_list])
+        df = get_dataframe_from_results(values)
+    except Exception as e:
+        error_box(e)
+        return
+
+    # Append the normalized current 
+    df["IDmm/uA/um"]= (df["ID/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+    df["IBGmm/uA/um"]= (df["IBG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+    df["ITGmm/uA/um"]= (df["ITG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+
+
+    # Save the results
+    default_filename = f"{ui.sample.sample.value}_{ui.sample.field.value}_{ui.sample.device.value}_BOTH_GATES_SIM_U.txt"
+    file = create_file(default_filename)
+
+    with open(file,'w') as f:
+        date = str(datetime.today().replace(microsecond=0))
+        f.write(f"Transfer Curve at {date}"+"\n")
+        write_sample_information(ui.sample,f)
+        f.write("Sweeping Gate:VTG,VBG simultaneously"+"\n\n")
+        f.write('Parameters\n')
+        f.write(f"VBG from {ui.Vbg_transfer.start.value}V to {ui.Vbg_transfer.stop.value}V with step {ui.Vbg_transfer.step.value}V"+"\n")
+        f.write(f"VTG from {ui.Vtg_transfer.start.value}V to {ui.Vtg_transfer.stop.value}V with step {ui.Vbg_transfer.step.value}V"+"\n")
+        f.write(f"VDS from {ui.Vds_transfer.start.value}V to {ui.Vds_transfer.stop.value}V with step {ui.Vds_transfer.step.value}V"+"\n")
+        
+        if ui.Vbg_transfer.pcomp.value==0:
+            f.write(f"Back Gate Current Compliance/A:{ui.Vbg_transfer.comp.value}"+"\n")
+        else:
+            f.write(f"Back Gate Power Compliance/A:{ui.Vbg_transfer.pcomp.value}"+"\n")
+
+        if ui.Vtg_transfer.pcomp.value==0:
+            f.write(f"Top Gate Current Compliance/A:{ui.Vtg_transfer.comp.value}"+"\n")
+        else:
+            f.write(f"Top Gate Power Compliance/A:{ui.Vtg_transfer.pcomp.value}"+"\n")        
+
+        if ui.Vds_transfer.pcomp.value == 0:
+            f.write(f"Drain Current Compliance/A:{ui.Vds_transfer.comp.value}"+"\n")
+        else:
+             f.write(f"Drain Power Compliance/A:{ui.Vds_transfer.pcomp.value}"+"\n")
+        f.write(f"Integration Time:{ui.integration_transfer.value}"+"\n")
+        f.write("\nResults\n")
+
+    df.to_csv(file,sep=" ",mode='a')
+
+    if ui.sample.quick.value == False:
+        df["label"] = df.apply(lambda row:f"VDS = {row['VDS/V']} (V)",axis = 1) # assign labels
+        create_plot(ui.plot_transfer,df,file,"Simultaneous Sweep of Both Gates Transfer Measurement", "Swept VDS voltages:",ui.sample.save_fig.value)
+
+def SEQ(ui,device):
+    device.del_user_functions() # delete all user functions 
+    device.clear_error_stack() # clear error stack
+    norm = normalization_factor(ui.sample.width.value)
+    points_VDS = number_of_points(ui.Vds_transfer)
+    points_VBG = number_of_points(ui.Vbg_transfer)
+
+
+    try:
+        values_VBG = np.linspace(ui.Vbg_transfer.start.value,ui.Vbg_transfer.stop.value,num = points_VBG, endpoint = True)
+    except:
+        error_box("Invalid VBG values!")
+        return
+
+    smu_source = device.smu_dict()
+    smu_source.update(vname ='VS',iname = 'IS',mode = 'COMM',func='CONS')
+
+    smu_top_gate = device.smu_dict()
+    smu_top_gate.update(vname = 'VTG',iname='ITG',mode = 'V',func='VAR1')
+
+    smu_back_gate = device.smu_dict()
+    smu_back_gate.update(vname = 'VBG',iname='IBG',mode = 'V',func = 'CONS') # Only VTG is swept
+
+    smu_drain = device.smu_dict()
+    smu_drain.update(vname='VDS',iname='ID',mode = 'V',func = 'VAR2')
+
+
+    # setup VAR1
+    var1 = device.var1_dict()
+    var1.update(
+        mode = ui.Vtg_transfer.hyst.value,
+        start = ui.Vtg_transfer.start.value,
+        stop = ui.Vtg_transfer.stop.value,
+        step = ui.Vtg_transfer.step.value,
+        comp = ui.Vtg_transfer.comp.value,
+        pcomp = ui.Vtg_transfer.pcomp.value
+    )
+
+    var2=device.var2_dict() #Vds_output is always used in tranfer curve with the same config
+    var2.update(
+        start=ui.Vds_transfer.start.value,
+        step=ui.Vds_transfer.step.value,
+        points=points_VDS,
+        comp=ui.Vds_transfer.comp.value,
+        pcomp=ui.Vds_transfer.pcomp.value,
+    )
+    
+    try:
+        device.setup_smu(ui.sample.top_gate.value,smu_top_gate)
+        device.setup_smu(ui.sample.drain.value,smu_drain)
+        device.setup_smu(ui.sample.back_gate.value,smu_back_gate)
+        device.setup_smu(ui.sample.source.value,smu_source)
+    
+        device.setup_var1(var1) # VTG is swept first 
+        device.setup_var2(var2) # Then VDS is swept
+    
+        device.integration_time(ui.integration_transfer.value)
+
+        variables_list =["VBG","IBG","VDS","ID","VTG","ITG"]
+        device.variables_to_save(variables_list)
+
+        plotted_variables = graph_tool(ui.plot_transfer,ui.sample.width.value,device)
+
+        device.error_occured()
+
+        # In the end VBG is swept
+        for i,value in enumerate(values_VBG):
+            cons = device.cons_smu_dict()
+            cons.update(comp = ui.Vbg_transfer.comp.value, value = value)
+            device.setup_cons_smu(ui.sample.back_gate.value,cons)
+            
+            if i == 0:
+                device.single_measurement()
+            else:
+                device.append_measurement()
+            
+            while device.operation_completed()==False:
+                pass
+            device.error_occured()
+        
+        if ui.sample.quick.value == False:
+            device.autoscaling()
+        
+        values = dict([(variable,device.return_values(variable)) for variable in variables_list])
+        df = get_dataframe_from_results(values)
+
+    except Exception as e:
+        error_box(e)
+        return
+
+    # Append the normalized current 
+    df["IDmm/uA/um"]= (df["ID/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+    df["IBGmm/uA/um"]= (df["IBG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+    df["ITGmm/uA/um"]= (df["ITG/A"].apply(lambda x: Decimal(str(x))*Decimal(str(norm)))).astype('float')
+
+
+    # Save the results
+    default_filename = f"{ui.sample.sample.value}_{ui.sample.field.value}_{ui.sample.device.value}_BOTH_GATES_SEQ_U.txt"
+    file = create_file(default_filename)
+
+    with open(file,'w') as f:
+        date = str(datetime.today().replace(microsecond=0))
+        f.write(f"Transfer Curve at {date}"+"\n")
+        write_sample_information(ui.sample,f)
+        f.write("Sweeping Gate:VTG,VBG sequentially"+"\n\n")
+        f.write('Parameters\n')
+        f.write(f"VBG from {ui.Vbg_transfer.start.value}V to {ui.Vbg_transfer.stop.value}V with step {ui.Vbg_transfer.step.value}V"+"\n")
+        f.write(f"VTG from {ui.Vtg_transfer.start.value}V to {ui.Vtg_transfer.stop.value}V with step {ui.Vbg_transfer.step.value}V"+"\n")
+        f.write(f"VDS from {ui.Vds_transfer.start.value}V to {ui.Vds_transfer.stop.value}V with step {ui.Vds_transfer.step.value}V"+"\n")
+        
+        f.write(f"Back Gate Current Compliance/A:{ui.Vbg_transfer.comp.value}"+"\n")
+
+        if ui.Vtg_transfer.pcomp.value==0:
+            f.write(f"Top Gate Current Compliance/A:{ui.Vtg_transfer.comp.value}"+"\n")
+        else:
+            f.write(f"Top Gate Power Compliance/A:{ui.Vtg_transfer.pcomp.value}"+"\n")        
+
+        if ui.Vds_transfer.pcomp.value == 0:
+            f.write(f"Drain Current Compliance/A:{ui.Vds_transfer.comp.value}"+"\n")
+        else:
+             f.write(f"Drain Power Compliance/A:{ui.Vds_transfer.pcomp.value}"+"\n")
+        f.write(f"Integration Time:{ui.integration_transfer.value}"+"\n")
+        f.write("\nResults\n")
+
+    df.to_csv(file,sep=" ",mode='a')
+
+    if ui.sample.quick.value == False:
+        if ui.plot_transfer.x.value == 'VTG':
+            df["label"] = df.apply(lambda row:f"VDS = {row['VDS/V']} (V), VBG = {row['VBG/V']} (V)",axis = 1) # assign labels
+            
+        else:
+            df["label"] = df.apply(lambda row:f"VDS = {row['VDS/V']} (V), VTG = {row['VTG/V']} (V)",axis = 1) # assign labels
+
+        create_plot(ui.plot_transfer,df,file,"Sequential Sweep of Both Gates Transfer Measurement", "Swept voltages:",ui.sample.save_fig.value)
\ No newline at end of file