diff --git a/interfaces/photodiode_ivl.py b/interfaces/photodiode_ivl.py
new file mode 100644
index 0000000000000000000000000000000000000000..787b21103e4110d95fb62eb0e438062070706ec7
--- /dev/null
+++ b/interfaces/photodiode_ivl.py
@@ -0,0 +1,406 @@
+""" 
+This is the photodiode measurement. Now the parser arguments are widgets
+"""
+
+import sys 
+import os
+import time
+import datetime
+import traceback
+
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+try:
+    import ivl
+    from ivl.instruments import Agilent66332A
+    from ivl.measurements import ivl_scan_photodiode
+except ModuleNotFoundError:
+    sys.path.append(".")
+    sys.path.append("..")
+    import ivl
+    from ivl.instruments import Agilent66332A
+    from ivl.measurements import ivl_scan_photodiode
+
+from PyQt6.QtWidgets import *
+from PyQt6.QtGui import *
+from PyQt6.QtCore import *
+
+from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg,NavigationToolbar2QT as NavigationToolbar
+from matplotlib.figure import Figure
+
+import tkinter as tk
+from tkinter import filedialog
+import tkinter.messagebox
+
+
+
+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 =filename)
+    root.destroy()
+    return file
+
+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()
+
+
+class MplCanvas(FigureCanvasQTAgg):
+    def __init__(self):
+        fig = Figure(figsize=(15,9),dpi=100)
+        self.axes = fig.subplots(nrows=2,ncols=2)
+        self.axes = self.axes.flatten()
+
+        self.axes[0].set_xlabel("Voltage [$V$]")
+        self.axes[0].set_ylabel("Current Density [$mA/cm^2$]")
+
+        self.axes[1].set_xlabel("Voltage [$V$]")
+        self.axes[1].set_ylabel("Radiance [$W/m^2*sr$]")
+
+        self.axes[2].set_xlabel("Current Density [$mA/cm^2$]")
+        self.axes[2].set_ylabel("Radiance [$W/m^2*sr$]")
+
+        self.axes[3].set_xlabel("Radiance [$W/m^2*sr$]")
+        self.axes[3].set_ylabel("EQE [%]")
+
+        # set the scales
+        self.axes[2].set_xscale("log")
+        self.axes[3].set_xscale("log")
+        self.axes[2].set_yscale("log")
+
+        self.axes[0].set_yscale("log")
+        self.axes[1].set_yscale("log")
+        
+
+        super().__init__(fig)
+    
+    def clear_axes(self):
+        for ax in self.axes:
+            # remove line plots
+            for line in ax.get_lines():
+                line.remove()
+
+            #remove scatter plots
+            for scatter in ax.collections:
+                scatter.remove()
+
+            ax.set_prop_cycle(None) # Reset colors
+
+
+# define the mainwindow
+
+class MainWindow(QMainWindow):
+    def __init__(self):
+        super().__init__()
+        self.setupUI()
+    
+    def setupUI(self):
+        """
+        Here we set the layout of the app
+
+        V_start : First voltage point in [V]
+        V_stop : "Last voltage point in [V]",
+        V_step : Voltage sweep increament in [V]
+
+        for the file we will create a Filedialog
+        the info can be added
+
+        info: Information to add to the header of result file.
+
+        points: Points to average for a single measurement. 
+        (Reduce to reduce voltage on time. Reducing below 
+        ~100 points does not yield increase measurement speed above ~ 50 ms  
+        per data points.)
+
+        offset: offset voltage of amplifier in [V]. If not supplied,offset is measured at the start of the script
+
+        delay: Time in [s] to wait between measurement points. (Voltage is 
+        set to 0 V during this time, mimicking a simple pulsed measurement)
+
+
+        address: Address of GPIB and serial interfaces
+        verbose: "Write info about current measurement state" True/False
+
+        RFA: Feedback resistivity * configuration factor * pinhole area
+        spectrum: path to reference spectrum for calculation of Radio-photometric quantities
+
+        substrate:"Active area in cm^2"
+
+        We always display plots
+        """
+
+        self.widget = QWidget() # Abstract main widget
+        self.app_grid = QGridLayout()
+
+        self.parameters = QVBoxLayout()
+        self.start_meas = QPushButton(text="Start Measurement")
+        self.load_spectrum = QPushButton(text = "Load spectrum reference file")
+
+        # I will search for the acceptable range of values later
+        self.v_start = QDoubleSpinBox()
+        self.v_start.setDecimals(3)
+        self.v_start.setRange(-20.475,20.475)
+        self.v_start.setValue(-8)
+        
+        self.v_stop = QDoubleSpinBox()
+        self.v_stop.setDecimals(3)
+        self.v_stop.setRange(-20.475,20.475)
+        self.v_stop.setValue(2)
+
+        self.v_step = QDoubleSpinBox()
+        self.v_step.setDecimals(3)
+        self.v_step.setRange(-2*20.475,2*20.475)
+        self.v_step.setValue(0.5)
+
+        self.info = QPlainTextEdit()
+        
+        self.points = QSpinBox()
+        self.points.setRange(0,4096)
+        self.points.setValue(4096)
+
+
+        self.offset = QDoubleSpinBox()
+        self.offset.setDecimals(4)
+        self.offset.setRange(5e-3,10e-3)
+        self.offset.setValue(7.5e-3)
+
+        self.measure_offset = QCheckBox("Measure offset voltage instead of using the above value")
+
+
+        self.delay = QDoubleSpinBox() #only softwrare delay leave it like this
+        # Minimum 0 Maximum 99.99 and 2 decimals places
+
+        
+        self.address_serial = QSpinBox() # well this is also ok for the 0 to 99 just set the default value
+        self.address_serial.setValue(3)
+
+        self.address_gpib = QSpinBox()
+        self.address_gpib.setValue(1)
+
+        self.verbose = QCheckBox("Verbose")
+        
+        self.rfa = QDoubleSpinBox() # here also set the default value
+        self.rfa.setDecimals(6)
+        self.rfa.setValue(0.827575)
+
+        self.spectrum = QLineEdit()
+
+        self.substrate = QDoubleSpinBox()
+        self.substrate.setRange(0,1)
+        self.substrate.setValue(0.11)
+        self.clear_plots = QCheckBox("Clear Plots Before Measurement")
+
+
+
+        self.parameters.addWidget(QLabel("First voltage point in [V]"))
+        self.parameters.addWidget(self.v_start)
+        self.parameters.addWidget(QLabel("Last voltage point in [V]"))
+        self.parameters.addWidget(self.v_stop)
+        self.parameters.addWidget(QLabel("Voltage sweep increament in [V]"))
+        self.parameters.addWidget(self.v_step)
+        
+        self.parameters.addWidget(QLabel("Information to add to the header of result file"))
+        self.parameters.addWidget(self.info)
+        self.parameters.addWidget(QLabel("Points to average for a single measurement"))
+        self.parameters.addWidget(self.points)
+        self.parameters.addWidget(QLabel("Offset voltage of amplifier in [V]"))
+        self.parameters.addWidget(self.offset)
+        self.parameters.addWidget(self.measure_offset)
+        self.parameters.addWidget(QLabel("Time in [s] to wait between measurement points"))
+        self.parameters.addWidget(self.delay)
+        
+        self.parameters.addWidget(QLabel("Serial address"))
+        self.parameters.addWidget(self.address_serial)
+        self.parameters.addWidget(QLabel("GPIB address"))
+        self.parameters.addWidget(self.address_gpib)
+
+        self.parameters.addWidget(self.verbose)
+        self.parameters.addWidget(QLabel("RFA: Feedback resistivity * configuration factor * pinhole area"))
+        self.parameters.addWidget(self.rfa)
+        self.parameters.addWidget(QLabel("path to reference spectrum for calculation of Radio-photometric quantities"))
+        self.parameters.addWidget(self.spectrum)
+        self.parameters.addWidget(QLabel("Active area in cm^2"))
+        self.parameters.addWidget(self.substrate)
+        self.parameters.addWidget(self.clear_plots)
+        self.parameters.addWidget(self.load_spectrum)
+        self.parameters.addWidget(self.start_meas)
+
+
+        self.parameters_widget = QWidget()
+        self.parameters_widget.setLayout(self.parameters) # an abstract widget to hold the QVBoxLayout
+
+        self.app_grid.addWidget(self.parameters_widget,0,0)
+        # add the canvas
+        # abstract widget for figure
+        self.figure_widget = QWidget()
+
+        self.sc = MplCanvas()
+        self.figure_toolbar = NavigationToolbar(self.sc, self)
+        self.figure_widget_layout = QVBoxLayout()
+        self.figure_widget_layout.addWidget(self.figure_toolbar)
+        self.figure_widget_layout.addWidget(self.sc)
+
+        self.figure_widget.setLayout(self.figure_widget_layout)
+        
+        self.app_grid.addWidget(self.figure_widget,0,1)
+
+        self.setWindowTitle("Photodiode IVL Measurement")
+        self.widget.setLayout(self.app_grid)
+        self.setCentralWidget(self.widget)
+        self.showMaximized()
+
+        self.start_meas.clicked.connect(self.start_meas_clicked)
+        self.load_spectrum.clicked.connect(self.load_spectrum_clicked)
+
+        #initialize a counter to keep track of how many measurements are done
+        self.counter = 1
+
+        # use of threads
+        self.threadpool = QThreadPool()
+    
+    def start_meas_clicked(self):
+        self.worker = Worker(self)
+        self.threadpool.start(self.worker)
+
+    def load_spectrum_clicked(self):
+        self.widget.setEnabled(False)
+
+        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(title ='Select spectrum reference file')
+        root.destroy()
+        self.spectrum.setText(file)
+        
+        self.widget.setEnabled(True)
+        
+    
+
+
+
+
+class Worker(QRunnable):
+    def __init__(self,window:MainWindow):
+        self.window = window # Keep a referernce to the main window
+        super().__init__()
+    
+    @pyqtSlot()
+    def run(self):
+        self.window.widget.setEnabled(False)
+        
+        with(
+        Agilent66332A(address=str(self.window.address_gpib.value()),timeout=30) as agi_source, 
+        Agilent66332A(connection = "serial", address = str(self.window.address_serial.value()),timeout=30) as agi_photo):
+            
+            # clear the plots
+            if self.window.clear_plots.isChecked():
+                self.window.sc.clear_axes()
+                self.window.counter = 1
+            else:
+                self.window.counter =+ 1 #increase counter
+            
+
+            if agi_source.device is None or agi_photo.device is None:
+                if "IVL_OFFLINE" not in os.environ.keys():
+                    information_box("Could not open one of the two necessary sourcemeters!")
+                    self.window.widget.setEnabled(True)
+                    return
+            
+            agi_source.set_measurement_param(points=self.window.points.value()) 
+            agi_photo.set_measurement_param(points=self.window.points.value())
+
+            agi_source.low_current_mode(True)
+            agi_photo.low_current_mode(True)
+
+            if self.window.measure_offset.isChecked():
+                dark_voltage = np.array([agi_photo.get_voltage() for _ in range(100)])
+                offset = dark_voltage.mean()
+                rms = np.std(dark_voltage)
+                if self.window.verbose.isChecked():
+                    information_box(f"Ampl. Offset: {offset*1e3:.3f} mV\n"+ f"RMS: {rms*1e3:.3} mV\n")
+                    self.window.offset.setValue(offset) # change the value on the interface
+                
+                scan_data = ivl_scan_photodiode(
+                    self.window.v_start.value(),self.window.v_stop.value(),self.window.v_step.value(),
+                    agi_source,agi_photo,
+                    delay=self.window.delay.value(), verbose = self.window.verbose.isChecked(),
+                    offset = self.window.offset.value(), substrate=self.window.substrate.value(),
+                    ref_spectrum= self.window.spectrum.text(),
+                    RFA= self.window.rfa.value()
+                )
+
+
+            voltage = scan_data["voltage_source"]
+            current_dens = scan_data["current_density"]
+            radiance = scan_data["radiance"]
+            eqe = scan_data["eqe"]
+            luminance = scan_data["luminance"]
+
+            # Plot the results
+            self.window.sc.axes[0].plot(voltage, current_dens,label = f"Measurement {self.window.counter}")
+            self.window.sc.axes[1].plot(voltage, radiance,label = f"Measurement {self.window.counter}")
+            self.window.sc.axes[2].scatter(current_dens,radiance,label = f"Measurement {self.window.counter}")
+            self.window.sc.axes[3].scatter(radiance,eqe,label = f"Measurement {self.window.counter}")
+
+            for i in range(4):
+                self.window.sc.axes[i].legend()
+            
+            self.window.sc.draw_idle()
+
+            filename = "_ivl.txt"
+
+            header = "Voltage Current_Density Radiance Luminance EQE"
+            header += " Raw_Current Raw_Photovoltage\n"
+            header += "[V] [mA/cm^2] [W/m^2*sr] [cd/m^2] [%] [A] [V]\n"
+
+
+            info = str(datetime.datetime.now().date())
+        
+            data = (
+                voltage, current_dens, radiance, luminance, eqe, 
+                scan_data["current"], scan_data["photo_voltage"]
+            )
+
+            data = np.array(data).T
+
+            if self.window.info.toPlainText() != "":
+                info += ": "+ self.window.info.toPlainText()
+
+            header += info
+
+            data_path = create_file(filename)
+            np.savetxt(data_path, data, header = header, fmt='%.3e')
+            self.window.widget.setEnabled(True)
+    
+app= QApplication(sys.argv)
+w= MainWindow()
+app.exec()
+
+
+
+