import os
import PyQt5
dirname = os.path.dirname(PyQt5.__file__)
plugin_path = os.path.join(dirname, 'plugins', 'platforms')
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = plugin_path
import PyQt5.QtWidgets as Qt# QApplication, QWidget, QMainWindow, QPushButton, QHBoxLayout
import PyQt5.QtGui as QtGui
import PyQt5.QtCore as QtCore
import logging
import sys
import argparse
from pyThorlabsPM100A.driver import ThorlabsPM100A
from pyThorlabsPM100A.plots import PlotObject


graphics_dir = os.path.join(os.path.dirname(__file__), 'graphics')

class interface():
    output = {'Power':0} 
    currentPowerUnits = 'W'
    continuous_read = False #When this is set to True, the data from device are acquired continuosly at the rate set by self.refresh_time
    refresh_time = 0.2 #default refresh rate, in seconds
    stored_data = [] # List used to store data acquired by device
    plot_window = None # QWidget object of the widget (i.e. floating window) that will contain the plot
    plot_object = None # PlotObject object of the plot where self.store_powers is plotted
    current_power_string = " " # Last power read from powermeter, as a string
    connected_device_name = ''
    _verbose = True #Keep track of whether this instance of the interface should produce logs or not
    _name_logger = ''

    def __init__(self, app, mainwindow, parent, name_logger=__package__):
        # app           = The pyqt5 QApplication() object
        # mainwindow    = Main Window of the application
        # parent        = a QWidget (or QMainWindow) object that will be the parent for the gui of this device.
        #                 When this script is ran on its own (i.e. not within another gui) mainwindow and parent are actually the same object
        # name_logger   = The name of the logger used for this particular istance of the interface object. If none is specified, the name of package is used as logger name

        self.mainwindow = mainwindow
        self.app = app
        self.parent = parent
        self.mainwindow.child = self #make sure that the window embedding this interface knows about its child (this is mainly used to link the closing events when using multiple windows)
 
        self.instrument = ThorlabsPM100A() 
        self.name_logger = name_logger #Setting this property will also create the logger,set defaulat output style, and store the logger object in self.logger

    @property
    def verbose(self):
        return self.verbose

    @verbose.setter
    def verbose(self,verbose):
        #When the verbose property of this interface is changed, we also update accordingly the level of the logger object
        if verbose: loglevel = logging.INFO
        else: loglevel = logging.CRITICAL
        self.logger.setLevel(level=loglevel)

    @property
    def name_logger(self):
        return self._name_logger

    @name_logger.setter
    def name_logger(self,name):
        #Create logger, and set default output style.
        self._name_logger = name
        self.logger = logging.getLogger(self._name_logger)
        self.verbose = self._verbose #This will automatically set the logger verbosity too
        if not self.logger.handlers:
            formatter = logging.Formatter(f"[{self.name_logger}]: %(message)s")
            ch = logging.StreamHandler()
            ch.setFormatter(formatter)
            self.logger.addHandler(ch)
        self.logger.propagate = False

    def create_gui(self,plot=False): 
        '''
            plot, boolean
            If set true, the GUI also generates a plot object (and a button to show/hide the plot) to plot the content of the self.stored_data object
        '''
        self.widgets_enabled_when_connected = []     #The widgets in this list will only be enabled when the interface has succesfully connected to a device
        self.widgets_enabled_when_disconnected = []  #The widgets in this list will only be enabled when the interface is not connected to a device
        
        hbox1 = Qt.QHBoxLayout()
        self.label_DeviceList = Qt.QLabel("Devices: ")
        self.combo_Devices = Qt.QComboBox()
        #self.combo_Devices.resize(self.combo_Devices.sizeHint())
        self.button_RefreshDeviceList = Qt.QPushButton("")
        self.button_RefreshDeviceList.setIcon(QtGui.QIcon(os.path.join(graphics_dir,'refresh.png')))
        self.button_RefreshDeviceList.clicked.connect(self.click_button_refresh_list_devices)
        hbox1.addWidget(self.label_DeviceList)
        hbox1.addWidget(self.combo_Devices,stretch=1)
        hbox1.addWidget(self.button_RefreshDeviceList)
        #hbox1.addStretch(1)

        hbox2 = Qt.QHBoxLayout()
        self.button_ConnectDevice = Qt.QPushButton("Connect")
        self.button_ConnectDevice.clicked.connect(self.click_button_connect_disconnect)
        self.button_SetZeroPowermeter = Qt.QPushButton("Set Zero")
        self.button_SetZeroPowermeter.clicked.connect(self.click_button_set_zero_powermeter)
        self.label_Wavelength = Qt.QLabel("Wavelength: ")
        self.edit_Wavelength = Qt.QLineEdit()
        self.edit_Wavelength.returnPressed.connect(self.press_enter_wavelength)
        self.edit_Wavelength.setAlignment(QtCore.Qt.AlignRight)
        #self.edit_Wavelength.setMaximumWidth(50)
        self.label_WavelengthUnits = Qt.QLabel("nm")
        self.label_PowerRange = Qt.QLabel("Power range: ")
        self.button_DecreasePowerRange = Qt.QPushButton("<")
        self.button_DecreasePowerRange.setToolTip('Decrease the powermeter power range.')
        self.button_DecreasePowerRange.setMaximumWidth(15)
        self.button_DecreasePowerRange.clicked.connect(lambda x:self.click_button_change_power_range(-1))
        self.edit_PowerRange = Qt.QLineEdit()
        self.edit_PowerRange.setToolTip('Maximum power measurable in the current power range (unless \'Auto\' is checked).')
        #self.edit_PowerRange.setMaximumWidth(60)
        self.edit_PowerRange.setReadOnly(True)
        self.button_IncreasePowerRange = Qt.QPushButton(">")
        self.button_IncreasePowerRange.setToolTip('Increase the powermeter power range.')
        self.button_IncreasePowerRange.setMaximumWidth(15)
        self.button_IncreasePowerRange.clicked.connect(lambda x:self.click_button_change_power_range(+1))
        self.box_PowerRangeAuto = Qt.QCheckBox("Auto")
        self.box_PowerRangeAuto.stateChanged.connect(self.click_box_PowerRangeAuto)
        self.box_PowerRangeAuto.setToolTip('Set the power range of the powermeter to Automatic.')
        hbox2.addWidget(self.button_ConnectDevice)
        hbox2.addWidget(self.button_SetZeroPowermeter)
        hbox2.addWidget(self.label_Wavelength)
        hbox2.addWidget(self.edit_Wavelength)
        hbox2.addWidget(self.label_WavelengthUnits)
        hbox2.addWidget(self.label_PowerRange)
        hbox2.addWidget(self.button_DecreasePowerRange)
        hbox2.addWidget(self.edit_PowerRange)
        hbox2.addWidget(self.button_IncreasePowerRange)
        hbox2.addWidget(self.box_PowerRangeAuto)
        #hbox2.addStretch(1)

        hbox3 = Qt.QHBoxLayout()
        self.button_StartPauseReading = Qt.QPushButton("")
        self.button_StartPauseReading.setIcon(QtGui.QIcon(os.path.join(graphics_dir,'play.png')))
        self.button_StartPauseReading.setToolTip('Start or pause the reading from the powermeter. The previous data points are not discarded when pausing.') 
        self.button_StartPauseReading.clicked.connect(self.click_button_StartPauseReading)
        self.button_StopReading = Qt.QPushButton("")
        self.button_StopReading.setIcon(QtGui.QIcon(os.path.join(graphics_dir,'stop.png')))
        self.button_StopReading.setToolTip('Stop the reading from the powermeter. All previous data points are discarded.') 
        self.button_StopReading.clicked.connect(self.click_button_StopReading)

        self.label_RefreshTime = Qt.QLabel("Refresh time (s): ")
        self.label_RefreshTime.setToolTip('Specifies how often the power is read from the powermeter (Minimum value = 0.001 s).') 
        self.edit_RefreshTime  = Qt.QLineEdit()
        self.edit_RefreshTime.setText(f"{self.refresh_time:.3f}")
        self.edit_RefreshTime.setToolTip('Specifies how often the power is read from the powermeter (Minimum value = 0.001 s).') 
        self.edit_RefreshTime.returnPressed.connect(self.press_enter_refresh_time)
        self.edit_RefreshTime.setAlignment(QtCore.Qt.AlignRight)
        #self.edit_RefreshTime.setMaximumWidth(50)

        font = QtGui.QFont("Times", 12,QtGui.QFont.Bold)
        self.label_Power = Qt.QLabel("Power: ")
        self.label_Power.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignCenter)
        self.label_Power.setFont(font)
        self.edit_Power = Qt.QLineEdit()
        self.edit_Power.setFont(font)
        self.edit_Power.setText(self.current_power_string)
        #self.edit_Power.setMaximumWidth(150)
        #self.edit_Power.resize(self.edit_Power.sizeHint());
        self.edit_Power.setAlignment(QtCore.Qt.AlignRight)
        self.edit_Power.setReadOnly(True)
        if plot:
            self.button_ShowHidePlot = Qt.QPushButton("Show/Hide Plot")
            #self.button_StopReading.setIcon(QtGui.QIcon(os.path.join(graphics_dir,'stop.png')))
            self.button_ShowHidePlot.setToolTip('Show/Hide Plot.') 
            self.button_ShowHidePlot.clicked.connect(self.click_button_ShowHidePlot)

        hbox3.addWidget(self.button_StartPauseReading)
        hbox3.addWidget(self.button_StopReading)
        hbox3.addWidget(self.label_RefreshTime)
        hbox3.addWidget(self.edit_RefreshTime)
        hbox3.addWidget(self.label_Power)
        hbox3.addWidget(self.edit_Power)
        if plot:
            hbox3.addWidget(self.button_ShowHidePlot)
        #hbox3.addStretch(1)
                
        vbox = Qt.QVBoxLayout()
        vbox.addLayout(hbox1)  
        vbox.addLayout(hbox2)  
        vbox.addLayout(hbox3)  
        vbox.addStretch(1)

        self.parent.setLayout(vbox) #This line makes sure that all widgest defined so far are assigned to the widget defines in self.parent
        
        #self.parent.layout().setSizeConstraint(Qt.QLayout.SetFixedSize)
        self.parent.resize(self.parent.minimumSize())

        self.widgets_enabled_when_connected = [self.button_SetZeroPowermeter, 
                                               self.edit_Wavelength, 
                                               self.edit_PowerRange, 
                                               self.box_PowerRangeAuto, 
                                               self.button_IncreasePowerRange, 
                                               self.button_DecreasePowerRange,
                                               self.button_StartPauseReading,
                                               self.button_StopReading]

        self.widgets_enabled_when_disconnected = [self.combo_Devices , 
                                                  self.button_RefreshDeviceList]

        self.click_button_refresh_list_devices()    #By calling this method, as soon as the gui is created we also look for devices
        self.set_disconnected_state()               #When GUI is created, all widgets are set to the "Disconnected" state
        if plot:
            self.create_plot()
        return self

    def create_plot(self):
        '''
        This function creates an additional (separated) window with a pyqtgraph object, which plots the contents of self.stored_data
        '''
        self.plot_window = Qt.QWidget() #This is the widget that will contain the plot. Since it does not have a parent, the plot will be in a floating (separated) window
        self.plot_object = PlotObject(self.app, self.mainwindow, self.plot_window)
        styles = {"color": "#fff", "font-size": "20px"}
        self.plot_object.graphWidget.setLabel("left", "Power", **styles)
        self.plot_object.graphWidget.setLabel("bottom", "Acqusition #", **styles)
        self.plot_window.setWindowTitle(f"Powermeter: {self.connected_device_name}")
        self.plot_window.show()
        self.plot_window.setHidden(True)
        

### GUI Events Functions

    def click_button_refresh_list_devices(self):
        '''
        Get a list of all powermeters connected, by using the method ListDevices() of the object powermeter. For each device we obtain its identity and its address.
        For each device, we create the string "identity -->  address" and we add the string to the corresponding combobox in the "Powermeter settings" panel 
        '''
        #First we empty the combobox
        self.combo_Devices.clear()
        
        #Then we read the list of devices
        self.logger.info(f"Looking for devices...") 
        (list_valid_devices,list_IDN) = self.instrument.list_devices()
        if(len(list_valid_devices)>0):
            list_IDNs_and_devices = [i + " -->  " + j for i, j in zip(list_IDN, list_valid_devices)] 
            self.combo_Devices.addItems(list_IDNs_and_devices)  
        self.logger.info(f"Found {len(list_valid_devices)} devices.") 

    def click_button_connect_disconnect(self):
        ''' 
        This function establishes the connection to the powermeter selected in the combobox list, or disconnects the powermeter, depending on the value of the variable self.instrument.connected .   
        If self.instrument.connected == False, then the powermeter is not connected, and we attempt connection
        If self.instrument.connected == True, then the powermeter is connected, and we attempt disconnection
        '''
        
        if(self.instrument.connected == False): # We attempt connection       
            self.connect_device()
        elif(self.instrument.connected == True): # We attempt disconnection
            self.disconnect_device()

    def click_box_PowerRangeAuto(self, state):
        if state == QtCore.Qt.Checked:
            status = 'ON'
            status_bool = True
        else:
            status = 'OFF'
            status_bool = False
        self.logger.info(f"Setting the auto-ranging function to {status} for the device {self.connected_device_name}...")    
        try:
            self.instrument.auto_power_range  = status_bool
            self.logger.info(f"Setting changed succesfully.")
        except Exception as e:
            self.logger.error(f"An error occurred while setting the auto-ranging status: {e}")

        self.read_status_power_autorange()
        self.read_power_range()

    def click_button_set_zero_powermeter(self):
        try: 
            (Msg,ID) = self.instrument.set_zero()
            self.logger.info(f"Zero-ing the device {self.connected_device_name}...")
            if ID == 1:
                self.logger.info(f"Device was succesfully zeroed.")
            else:
                self.logger.error(f"An error occurred while zero-ing this device: {Msg}")
        except Exception as e:
            self.logger.error(f"An error occurred while zero-ing this device: {e}")
        return

    def press_enter_wavelength(self):
        wl = self.edit_Wavelength.text()
        if int(self.instrument.wavelength) == int(wl): #in this case the number in the refresh time edit box is the same as the wavelength currently set
                return True
        self.logger.info(f"Setting the wavelength to {wl} for the device {self.connected_device_name}...")
        try: 
            self.instrument.wavelength = wl
            self.logger.info(f"Wavelength set correctly.")
        except Exception as e:
            self.logger.error(f"An error occurred while setting the wavelength: {e}")
            self.edit_Wavelength.setText(str(self.instrument.wavelength))
            return False
        self.read_power_range() #The boundaries of the power ranges might change when the wavelength is changed, so we need to update it after changing the wavelength
        return True
        

    def click_button_change_power_range(self,direction):
        if direction == +1:
            string = 'increase'
        else: 
            string = 'decrease'
        self.logger.info(f"Trying to {string} the power range...")
        self.instrument.move_to_next_power_range(direction)
        self.read_power_range()
       
    def click_button_StartPauseReading(self): 
        if(self.continuous_read == False):
            self.start_reading()
        elif (self.continuous_read == True):
            self.pause_reading()
        return

    def click_button_StopReading(self):
        self.stop_reading()

    def press_enter_refresh_time(self):
        refresh_time = self.edit_RefreshTime.text()
        try: 
            refresh_time = float(refresh_time)
            if self.refresh_time == refresh_time: #in this case the number in the refresh time edit box is the same as the refresh time currently stored
                return True
        except ValueError:
            self.logger.error(f"The refresh time must be a valid number.")
            self.edit_RefreshTime.setText(f"{self.refresh_time:.3f}")
            return False
        if refresh_time < 0.001:
            self.logger.error(f"The refresh time must be positive and >= 1ms.")
            self.edit_RefreshTime.setText(f"{self.refresh_time:.3f}")
            return False
        self.logger.info(f"The refresh time is now {refresh_time} s.")
        self.refresh_time = refresh_time
        self.edit_RefreshTime.setText(f"{self.refresh_time:.3f}")
        return True

    def click_button_ShowHidePlot(self):
        self.plot_window.setHidden(not self.plot_window.isHidden())
        #self.plot_frame.activate()
        #self.parent.resize(self.parent.minimumSizeHint())

### END GUI Events Functions

    def connect_device(self):
        device_full_name = self.combo_Devices.currentText() # Get the device name from the combobox
        if(device_full_name==''): # Check  that the name is not empty
            self.logger.error("No valid device has been selected")
            return
        self.set_connecting_state()
        device_name = device_full_name.split(' --> ')[1].lstrip() # We extract the device address from the device name
        self.logger.info(f"Connecting to device {device_name}...")
        (Msg,ID) = self.instrument.connect_device(device_name) # Try to connect by using the method ConnectDevice of the powermeter object
        if(ID==1):  #If connection was successful
            self.logger.info(f"Connected to device {device_name}.")
            self.connected_device_name = device_name
            self.set_connected_state()
            self.start_reading()
        else: #If connection was not successful
            self.logger.error(f"Error: {Msg}")
            self.set_disconnected_state()

    def disconnect_device(self):
        self.logger.info(f"Disconnecting from device {self.connected_device_name}...")
        (Msg,ID) = self.instrument.disconnect_device()
        if(ID==1): # If disconnection was successful
            self.logger.info(f"Disconnected from device {self.connected_device_name}.")
            self.continuous_read = 0 # We set this variable to 0 so that the continuous reading from the powermeter will stop
            self.set_disconnected_state()
        else: #If disconnection was not successful
            self.logger.error(f"Error: {Msg}")
 
    def disable_widget(self,widgets):
        for widget in widgets:
            widget.setEnabled(False)   

    def enable_widget(self,widgets):
        for widget in widgets:
            widget.setEnabled(True)   

    def set_disconnected_state(self):
        self.disable_widget(self.widgets_enabled_when_connected)
        self.enable_widget(self.widgets_enabled_when_disconnected)
        self.edit_PowerRange.setText('')
        self.edit_Wavelength.setText('')
        self.button_ConnectDevice.setText("Connect")
        self.edit_Power.setText('')

    def set_connecting_state(self):
        self.disable_widget(self.widgets_enabled_when_connected)
        self.enable_widget(self.widgets_enabled_when_disconnected)
        self.button_ConnectDevice.setText("Connecting...")

    def set_connected_state(self):
        self.enable_widget(self.widgets_enabled_when_connected)
        self.disable_widget(self.widgets_enabled_when_disconnected)
        self.button_ConnectDevice.setText("Disconnect")
        self.read_wavelength()
        self.read_status_power_autorange()
        self.read_power_range()
        #If a self.plot_object was created, update window title with powermeter name and vertical axis of plot with current Power units
        if self.plot_object: 
            self.plot_object.graphWidget.setLabel("left", f"Power [{self.instrument._power_units}]")
            self.plot_window.setWindowTitle(f"Powermeter: {self.connected_device_name}")

    def set_pause_state(self):
        self.button_StartPauseReading.setIcon(QtGui.QIcon(os.path.join(graphics_dir,'play.png')))
    def set_reading_state(self):
        self.button_StartPauseReading.setIcon(QtGui.QIcon(os.path.join(graphics_dir,'pause.png')))
    def set_stopped_state(self):    
        self.button_StartPauseReading.setIcon(QtGui.QIcon(os.path.join(graphics_dir,'play.png')))
        
    def read_wavelength(self):
        self.logger.info(f"Reading current wavelength from device {self.connected_device_name}...") 
        self.wavelength = self.instrument.wavelength
        if self.wavelength == None:
            self.logger.error(f"An error occurred while reading the wavelength from this device.")
            return
        self.edit_Wavelength.setText(str(int(self.wavelength)))
        self.logger.info(f"Current wavelength is {self.wavelength}.") 
        return

    def read_power_range(self):
        self.logger.info(f"Reading current power range from device {self.connected_device_name}...") 
        self.power_range = self.instrument.power_range
        if self.power_range == None:
            self.logger.error(f"An error occurred while reading the power range from this device.")
            return
        self.edit_PowerRange.setText(f"{self.power_range:.2e}")
        self.edit_PowerRange.setCursorPosition(1)
        self.logger.info(f"Current power range is {self.power_range}.") 

    def read_status_power_autorange(self):
        self.logger.info(f"Reading the status of the auto-ranging function for the device {self.connected_device_name}...")   
        try:
            auto_power_range = self.instrument.auto_power_range
            self.box_PowerRangeAuto.setChecked(auto_power_range)
            if auto_power_range:
                status = 'ON'
                self.disable_widget([self.edit_PowerRange,self.button_IncreasePowerRange, self.button_DecreasePowerRange])
            else:
                status = 'OFF'
                self.enable_widget([self.edit_PowerRange,self.button_IncreasePowerRange, self.button_DecreasePowerRange])
            self.logger.info(f"The auto-ranging function is currently set to {status}.")
        except Exception as e:
            self.logger.error(f"An error occurred while reading the auto-ranging status: {e}")

    def start_reading(self):
        if(self.instrument.connected == False):
            self.logger.error(f"No device is connected.")
            return
        #self.logger.info(f"Updating wavelength and refresh time before starting reading...")
        if not(self.press_enter_refresh_time()): #read the current value in the refresh_time textbox, and validates it. The function returns True/False if refresh_time was valid
            return
        if not(self.press_enter_wavelength()): #read the current value in the refresh_time textbox, and validates it. The function returns True/False if refresh_time was valid
            return
        
        self.set_reading_state() # Change some widgets

        self.continuous_read = True #Until this variable is set to True, the function UpdatePower will be repeated continuosly 
        self.logger.info(f"Starting reading from device {self.connected_device_name}...")
        # Call the function self.Update(), which will do stome suff (read power and store it in a global variable) and then call itself continuosly until the variable self.ContinuousRead is set back to 0
        self.Update()
        return
 
    def pause_reading(self):
        #Sets self.ContinuousRead to 0 (this will force the function Update() to stop calling itself)
        self.continuous_read = False
        self.logger.info(f"Paused reading from device {self.connected_device_name}.")
        self.set_pause_state() # Change some widgets
        return

    def stop_reading(self):
        #Sets self.ContinuousRead to 0 (this will force the function Update() to stop calling itself)
        self.continuous_read = False
        self.stored_data = []
        self.Update() #We call one more time the self.Update() function to make sure plots is cleared. Since self.continuous_read is already set to False, Update() will not acquire data anymore
        self.logger.info(f"Stopped reading from device {self.connected_device_name}. All stored data have been deleted.")
        self.set_stopped_state() # Change some widgets
        # ...
        return
        
    def Update(self):
        '''
        This routine reads continuosly the power from the powermeter and stores its value
        If we are continuosly acquiring the power (i.e. if self.ContinuousRead = 1) then:
            1) Reads the power from the powermeter object and stores it in the self.output dictionary
            2) Update the value of the variable self.current_power_string by generating a string containing the power and its units
            3) Update the textbox in the GUI
            3) Call itself after a time given by self.refresh_time
        '''
        if self.plot_object:
            self.plot_object.data.setData(list(range(1, len(self.stored_data)+1)), self.stored_data) #This line is executed even when self.continuous_read == False, to make sure that plot gets cleared when user press the stop button
        if(self.continuous_read == True):
            (currentPower,currentPowerUnits) = self.instrument.power
            self.output['Power'] = currentPower
            #self.output['PowerUnits'] = currentPowerUnits

            self.stored_data.append(currentPower)

            #StoredPowers_np = np.array(self.StoredPowers)
            #Fluctuation = 100 * StoredPowers_np[-10:].ptp(axis=0)  / StoredPowers_np[-10:].mean(axis=0)  
            
            #self.PowerFluctuationString.set("{:.2f}".format(Fluctuation) + " %")

            #super().Update()
            self.current_power_string = f"{currentPower:.2e}" + ' ' +  currentPowerUnits
            self.edit_Power.setText(self.current_power_string)
            QtCore.QTimer.singleShot(int(self.refresh_time*1e3), self.Update)
           
        return

    def closeEvent(self):
        if (self.instrument.connected == True):
            self.disconnect_device()
        if self.plot_window:
            self.plot_window.close()

class MainWindow(Qt.QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle(__package__)
        # Set the central widget of the Window.
        # self.setCentralWidget(self.container)
    def closeEvent(self, event):
        if self.child:
            self.child.closeEvent()

def main():
    parser = argparse.ArgumentParser(description = "",epilog = "")
    parser.add_argument("-s", "--decrease_verbose", help="Decrease verbosity.", action="store_true")
    args = parser.parse_args()
    
    app = Qt.QApplication(sys.argv)
    window = MainWindow()
    Interface = interface(app,window,window) #In this case window is both the MainWindow and the parent of the gui
    Interface.verbose = not(args.decrease_verbose)
    app.aboutToQuit.connect(Interface.closeEvent) 
    Interface.create_gui(plot=True)
    
    window.show()
    app.exec()# Start the event loop.

if __name__ == '__main__':
    main()
