Beispiel #1
0
	def deleteLater(self, *args):
		self.delete()
		return FigureCanvasQTAgg.deleteLater(self, *args)
Beispiel #2
0
class GuiProgram(Ui_sweepergui):

    cols = 0
    sweep_id = 0
    full_data = []
    negative_current = False
    log_sweep = True
    stop = True
    decade_combo_values = ['5', '10', '25', '50']

    def __init__(self, dialog):
        Ui_sweepergui.__init__(self)
        self.setupUi(dialog)

        # Connect "add" button with a custom function (addInputTextToListbox)
        self.exportButton.clicked.connect(self.export_data)
        self.startBtn.clicked.connect(self.startFunc)
        self.logRadioButton.clicked.connect(self.switch_linear)
        self.linRadioButton.clicked.connect(self.switch_linear)

        # Populate comboBox
        self.decadeComboBox.clear()
        self.decadeComboBox.addItems(self.decade_combo_values)
        self.decadeComboBox.setCurrentIndex(1)

        # Try to load last parameters from Pickle
        self.load_parameters()

        # Připojení k instrumentu
        #self.inst = Instrument('GPIB0::17::INSTR', visa_location='C:\WINDOWS\SysWOW64\\visa32.dll')
        self.inst = Instrument('GPIB0::17::INSTR', virtual=False)

    def artSleep(self, sleepTime):
        """
        Čeká čas sleepTime v sekundách, zatím ale každých 50 milisekund řeší
        akce, o které se někdo pokoušel v GUI.
        """
        stop_time = QtCore.QTime()
        stop_time.restart()
        while stop_time.elapsed() < sleepTime * 1000:
            QtWidgets.QApplication.processEvents(QtCore.QEventLoop.AllEvents,
                                                 50)

    def plot_figure(self):
        fig1 = Figure()
        ax1f1 = fig1.add_subplot(111)
        ax1f1.plot(np.random.rand(5))
        self.rmmpl()
        self.addmpl(fig1)

    def plot_data(self, data):
        fig1 = Figure()
        ax1f1 = fig1.add_subplot(111)
        ax1f1.set_xlabel('I [A]')
        ax1f1.set_ylabel('U [V]')
        ax1f1.set_title('Sweep ID: ' + self.sweep_id)
        for d in data:
            x, y = d
            ax1f1.plot(x, y, color='red')
            if self.log_sweep:
                ax1f1.set_xscale('log')
            else:
                ax1f1.set_xscale('linear')
        self.rmmpl()
        self.addmpl(fig1)

    def addmpl(self, fig):
        self.canvas = FigureCanvas(fig)
        self.mplvl.addWidget(self.canvas)
        self.canvas.draw()
        self.toolbar = NavigationToolbar(self.canvas,
                                         self.mplwindow,
                                         coordinates=True)
        self.mplvl.addWidget(self.toolbar)

    def rmmpl(self, ):
        self.mplvl.removeWidget(self.canvas)
        self.canvas.close()
        self.canvas.deleteLater()

        self.mplvl.removeWidget(self.toolbar)
        self.toolbar.close()
        self.toolbar.deleteLater()

    def save_parameters(self):
        parameters_dict = {
            'sw_min': str(self.startEdit.text()),
            'sw_max': str(self.endEdit.text()),
            'step': str(self.stepEdit.text()),
            'delay': int(self.delaySpinBox.value()),
            'decade': int(self.decadeComboBox.currentIndex()),
            'n': int(self.pocetMereniBox.value()),
            'log_sweep': self.logRadioButton.isChecked(),
            'lin_sweep': self.linRadioButton.isChecked(),
            'sense_local': self.senseLocalRadioButton.isChecked(),
            'sense_remote': self.senseRemoteRadioButton.isChecked(),
            'col_source': self.sourceCheckBox.checkState(),
            'col_delay': self.delayCheckBox.checkState(),
            'col_measure': self.measureCheckBox.checkState(),
            'col_time': self.timeCheckBox.checkState(),
            'stabilize_time': self.stableSpinBox.value(),
            'sleep_time': self.sleepSpinBox.value()
        }

        # For pickle, the file needs to be opened in binary mode, hence the "wb"
        with open("last_parameters.pickle", "wb") as params_file:
            pickle.dump(parameters_dict, params_file)

    def load_parameters(self):
        try:
            # For pickle, the file needs to be opened in binary mode, hence the "wb"
            with open("last_parameters.pickle", "rb") as params_file:
                parameters_dict = pickle.load(params_file)

            self.startEdit.setText(parameters_dict['sw_min'])
            self.endEdit.setText(parameters_dict['sw_max'])
            self.stepEdit.setText(parameters_dict['step'])
            self.delaySpinBox.setValue(parameters_dict['delay'])
            self.decadeComboBox.setCurrentIndex(parameters_dict['decade'])
            self.pocetMereniBox.setValue(parameters_dict['n'])

            self.logRadioButton.setChecked(parameters_dict['log_sweep'])
            self.linRadioButton.setChecked(parameters_dict['lin_sweep'])
            self.senseLocalRadioButton.setChecked(
                parameters_dict['sense_local'])
            self.senseRemoteRadioButton.setChecked(
                parameters_dict['sense_remote'])

            self.sourceCheckBox.setChecked(parameters_dict['col_source'])
            self.delayCheckBox.setChecked(parameters_dict['col_delay'])
            self.measureCheckBox.setChecked(parameters_dict['col_measure'])
            self.timeCheckBox.setChecked(parameters_dict['col_time'])

            self.stableSpinBox.setValue(parameters_dict['stabilize_time'])
            self.sleepSpinBox.setValue(parameters_dict['sleep_time'])

            self.switch_linear()

            print("Nacteni poslednich parametru uspesne! :)")

        except:
            print("Nacteni poslednich parametru selhalo. :(")

    def validateInput(self, sw_min, sw_max, decade, delay, log_sweep, step):
        # Unit testing :P
        try:
            a = float(sw_min)
            a = float(sw_max)
            if not log_sweep:
                a = float(step)
        except:
            return False

        # Code
        if log_sweep:
            if (float(sw_min) > 0 and float(sw_max) > 0
                    and float(sw_min) != float(sw_max)):
                return True
            else:
                return False
        else:
            # lin sweep
            if (float(sw_min) != float(sw_max)
                    and abs(float(sw_max) - float(sw_min)) > float(step)):
                return True
            else:
                return False

    def stopFunc(self):
        print('ABORT! Attempted to STOP sweep!')
        self.inst.operate(False)
        self.stop = True

    def startFunc(self):
        ''' Posbírá z GUI parametry a odpovídajícím způsobem přeloží.'''
        # vypnout ruční brzdu
        self.stop = False

        # aktuální čas pro ID
        self.sweep_id = '{0:%Y-%m-%d_%H-%M-%S}'.format(datetime.datetime.now())

        sw_min = str(self.startEdit.text())
        sw_max = str(self.endEdit.text())
        step = str(self.stepEdit.text())
        delay = str(self.delaySpinBox.value())
        decade = str(self.decadeComboBox.currentIndex())
        n = self.pocetMereniBox.value()

        self.bigProgBar.setValue(0)
        self.bigProgBar.setMaximum(n)
        self.littleProgBar.setValue(0)

        log_sweep = self.logRadioButton.isChecked()
        lin_sweep = self.linRadioButton.isChecked()
        self.log_sweep = log_sweep

        sense_local = self.senseLocalRadioButton.isChecked()
        sense_remote = self.senseRemoteRadioButton.isChecked()
        self.sense_local = sense_local

        col_source = self.sourceCheckBox.checkState()
        col_delay = self.delayCheckBox.checkState()
        col_measure = self.measureCheckBox.checkState()
        col_time = self.timeCheckBox.checkState()

        self.cols = 0
        if col_source:
            self.cols += 1
        if col_delay:
            self.cols += 2
        if col_measure:
            self.cols += 4
        if col_time:
            self.cols += 8

        if self.validateInput(sw_min, sw_max, decade, delay, log_sweep, step):
            self.save_parameters()
            self.measure(sw_min, sw_max, decade, delay, log_sweep, step, n)
        else:
            print('Input failed validation.')
            self.show_notification('failed_validation')

    def show_notification(self, code):
        if code == 'failed_validation':
            msg = QtWidgets.QMessageBox()
            msg.setIcon(QtWidgets.QMessageBox.Warning)
            msg.setText("Chybné parametry sweepu.")
            msg.setInformativeText("")
            msg.setWindowTitle("Sweeper - varování")
            msg.setDetailedText("TODO")
            msg.exec_()

    def measure(self, sw_min, sw_max, decade, delay, log_sweep, step, n):
        ''' Spustí měření s již validovanými parametry. '''
        # Disable UI
        self.enable_ui(False)

        # Declare Export not done on this sweep
        self.exportButton.setText('Export')

        # Local or Remote sense?
        if self.sense_local:
            print("Zapinam Sense - LOCAL.")
            self.inst.write("O0X")
        else:
            print("Zapinam Sense - REMOTE.")
            self.inst.write("O1X")

        # Úvodní stabilizace
        stabilize_time = self.stableSpinBox.value()
        print("Uvodni stabilizace v DC modu - {} s.".format(stabilize_time))
        self.stabilize(sw_min, stabilize_time)

        # Nastavení sweepu
        self.inst.set_source_and_function('I', 'Sweep')
        # Nastavení formátu dat
        self.inst.write("G" + str(self.cols) + ",2,2X")

        if self.log_sweep:
            self.inst.write("Q2," + sw_min + "," + sw_max + "," + decade +
                            ",0," + delay + "X")
        else:
            self.inst.write("Q1," + sw_min + "," + sw_max + "," + step +
                            ",0," + delay + "X")

        data = []
        self.full_data = []
        n_hotovych_mereni = 0
        for mereni in range(n):
            if self.stop:
                break
            output = self.run_sweep()
            if output:
                sweep_results = misc.nice_format(output, cols=self.cols)
                data.append(misc.unpack(sweep_results, cols=self.cols))
                self.full_data.append(sweep_results)

                print('Ukladam docasna data...')
                self.dump_data()

                n_hotovych_mereni += 1
                self.bigProgBar.setValue(n_hotovych_mereni)
                self.plot_data(data)

                if n_hotovych_mereni != n:
                    sleep_time = self.sleepSpinBox.value()
                    print("Pauza mezi sweepy - {} s.".format(sleep_time))
                    self.artSleep(sleep_time)

            else:
                print("Output was empty. Interrupted measurement?")

        self.inst.operate(False)
        self.enable_ui(True)
        #self.plot_data(data)

    def run_sweep(self):
        ''' Provede jeden sweep, který už musí být definovaný ve stroji.
            Na konci 3 vteřiny spí, aby se mělo napětí čas ustálit před dalším měřením.

            Vrací string se všemi hodnotami sweepu.
        '''
        print('\nSpoustim sweep...')
        self.inst.write("U8X")
        out = self.inst.read()
        print('U8X -> ' + out)
        out = out.replace('\r', '').replace('\n', '')
        print("Out: {}".format(out))
        sweep_defined_size = int(out[-4:])
        print('Pocet bodu ve sweepu: ' + str(sweep_defined_size))

        self.littleProgBar.setValue(0)
        self.inst.trigger()  # Immediate trigger
        sweep_done = False
        while not sweep_done:
            if self.stop:
                break
            self.artSleep(0.2)
            self.inst.write("U11X")
            status = self.inst.read()
            if (status == 'SMS' + str(sweep_defined_size).zfill(4) + '\r\n'):
                sweep_done = True
            else:
                status_edit = status.replace('\r', '').replace('\n', '')
                try:
                    progress = int(status_edit[-4:])
                    self.littleProgBar.setValue(
                        int(progress / sweep_defined_size * 100))
                except:
                    print('Invalid progress!')
        print('Jeden sweep hotov.')
        self.littleProgBar.setValue(100)

        if self.stop:
            return ""
        else:
            return self.inst.read()

    def stabilize(self, bias, stabilize_time):
        # Počáteční stabilizace
        self.inst.set_source_and_function('I', 'DC')
        self.inst.write("B" + bias + ",0,20X")
        self.inst.operate(True)
        self.inst.trigger()
        self.artSleep(stabilize_time)

    def switch_linear(self):
        log_sweep = self.logRadioButton.isChecked()
        lin_sweep = self.linRadioButton.isChecked()
        if log_sweep:
            self.stepEdit.setEnabled(False)
            self.decadeComboBox.setEnabled(True)
        else:
            self.decadeComboBox.setEnabled(False)
            self.stepEdit.setEnabled(True)

    def enable_ui(self, status):
        ui_elements = [
            self.startEdit,
            self.endEdit,
            self.stepEdit,
            self.delaySpinBox,
            self.decadeComboBox,
            self.pocetMereniBox,
            self.logRadioButton,
            self.linRadioButton,
            self.senseLocalRadioButton,
            self.senseRemoteRadioButton,
            self.sourceCheckBox,
            self.delayCheckBox,
            self.measureCheckBox,
            self.timeCheckBox,
            self.stableSpinBox,
            self.sleepSpinBox,
        ]

        for element in ui_elements:
            element.setEnabled(status)

        if status:
            self.switch_linear()

        if status:
            self.startBtn.clicked.disconnect()
            self.startBtn.clicked.connect(self.startFunc)
            self.startBtn.setText("Start")
        else:
            self.startBtn.clicked.disconnect()
            self.startBtn.clicked.connect(self.stopFunc)
            self.startBtn.setText("Abort")
            self.exportButton.setText('Export')

    def get_export_data(self):
        output = ""
        output += '# ======== Sweep ID: ' + self.sweep_id + ' ========' + '\n'
        output += '# ======== ' + str(len(
            self.full_data)) + ' sweeps' + ' ========' + '\n'

        output += self.get_measurement_parameters()

        for data in self.full_data:
            output += '# ======== SWEEP START ========\n'
            output += data.replace(',', '    ')
            output += '# ======== SWEEP END ========\n\n'

        return output

    def dump_data(self):
        save_file_name = 'C:\Repa\k237\sweeper\data_temp.txt'
        try:
            with open(save_file_name, "w", encoding="utf-8") as text_file:
                text = self.get_export_data()
                text_file.write(text)
        except:
            print("Nouzovy dump se nepovedl.")

    def export_data(self):
        """
        Exportuje data pomocí ukládacího dialogu Qt. V případě chybného zadání
        souboru nic neudělá a postěžuje si do konzole.
        """
        proposed_name = self.sweep_id

        # Qt Dialog na výběr souboru k uložení
        save_file_name, _ = QtWidgets.QFileDialog.getSaveFileName(
            None, 'Exportovat výsledky měření',
            'C:\Repa\k237\data\sweep_' + proposed_name + '.txt',
            'Text Files (*.txt);;All Files (*)')

        # Vlastní uložení souboru
        try:
            with open(save_file_name, "w", encoding="utf-8") as text_file:
                text = self.get_export_data()
                text_file.write(text)

            # Update GUI
            self.exportButton.setText('Export ✔')
        except:
            print("Export neuspesny. Data pravdepodobne nejsou ulozena!")

            # Update GUI
            self.exportButton.setText('Export ✗')

    def get_measurement_parameters(self):
        out = ''
        out += "# Sweep ID: {}\n".format(self.sweep_id)
        if self.log_sweep:
            out += "# Log sweep:\n"
            out += "# Rozsah (min, max) [A]: {}, {}\n".format(
                self.startEdit.text(), self.endEdit.text())
            out += "# Bodů na dekádu [-]: {}\n".format(
                self.decade_combo_values[self.decadeComboBox.currentIndex()])
        else:
            out += "# Linear sweep\n"
            out += "# Rozsah (min, max, points) [A]: {}, {}, {}\n".format(
                self.startEdit.text(), self.endEdit.text(),
                self.stepEdit.text())

        out += "# Delay [ms]: {}\n".format(self.delaySpinBox.value())
        out += "# Počet charakteristik [-]: {}\n".format(
            self.pocetMereniBox.value())

        if self.sense_local:
            out += "# Sense: local\n"
        else:
            out += "# Sense: remote\n"

        out += "# Sloupce (Source, Measure, Delay, Time): {} {} {} {}\n".format(
            int(self.sourceCheckBox.checkState() / 2),
            int(self.measureCheckBox.checkState() / 2),
            int(self.delayCheckBox.checkState() / 2),
            int(self.timeCheckBox.checkState() / 2))

        out += "# Uvodní DC stabilizace [s]: {}\n".format(
            self.stableSpinBox.value())
        out += "# Stabilizace [s]: {}\n".format(self.sleepSpinBox.value())

        return out
Beispiel #3
0
 def deleteLater(self, *args):
     self.delete()
     return FigureCanvasQTAgg.deleteLater(self, *args)
Beispiel #4
0
class GuiProgram(Ui_sweepergui):

    cols = 0
    sweep_id = 'mereni'
    full_data = []
    negative_current = False
    log_sweep = True
    stop = True
    decade_combo_values = ['5', '10', '25', '50']
    save_directory = False
    save_filename = False

    def __init__(self, dialog):
        Ui_sweepergui.__init__(self)
        self.setupUi(dialog)

        # Connect "add" button with a custom function (addInputTextToListbox)
        self.exportButton.clicked.connect(self.export_data)
        self.startBtn.clicked.connect(self.startFunc)
        self.logRadioButton.clicked.connect(self.switch_linear)
        self.linRadioButton.clicked.connect(self.switch_linear)
        self.dynamicDelayRadio.clicked.connect(self.switch_dynamic_delay)
        self.constantDelayRadio.clicked.connect(self.switch_dynamic_delay)

        # Populate comboBox
        self.decadeComboBox.clear()
        self.decadeComboBox.addItems(self.decade_combo_values)
        self.decadeComboBox.setCurrentIndex(1)

        self.exportButton.setEnabled(False)

        # Try to load last parameters from Pickle
        self.load_parameters()

        self.save_directory = os.path.dirname(os.path.abspath(__file__))

        # Připojení k instrumentu
        #self.inst = Instrument('GPIB0::17::INSTR', visa_location='C:\WINDOWS\SysWOW64\\visa32.dll')
        self.inst = Instrument('GPIB0::17::INSTR', virtual=True)

    def make_pretty(self):
        self.littleProgBar.setValue(84)
        self.littleProgBar.setMaximum(100)
        self.bigProgBar.setMaximum(5)
        self.bigProgBar.setValue(3)

        self.startBtn.setText('Stop')

        self.ax.clear()  # Clear contents of current axis

        # Plot cosmetics
        self.ax.set_xlabel('Current $I$ (nA)')
        self.ax.set_ylabel('Voltage $U$ (V)')
        self.ax.set_title(
            'Sweep ID: 2018-04-21_11:22:37  $n$-ZnO/$p$-GaN  sample #692')

        data = []
        dd = np.loadtxt('demo_data/01.txt')
        for i in range(int(len(dd.T) / 2)):
            data.append((dd[:, 2 * i] * 1e6, dd[:, 2 * i + 1]))

        color_1 = '#0066FF'
        color_3 = '#6600CC'
        color_2 = '#FF0000'

        self.ax.plot(data[2][0], data[2][1], color=color_2)
        self.ax.plot(data[3][0], data[3][1], '--', color=color_2)

        self.ax.plot(data[4][0], data[4][1], color=color_3)
        self.ax.plot(data[5][0], data[5][1], '--', color=color_3)

        self.ax.plot(data[0][0], data[0][1], color=color_1)
        self.ax.plot(data[1][0], data[1][1], '--', color=color_1)

        #plt.tight_layout()

    # --- PLOTTING -----------------------------------------------------------
    # ------------------------------------------------------------------------
    # ------------------------------------------------------------------------
    # ------------------------------------------------------------------------

    def plot_data(self, data):
        ''' Plots the provided data onto the figure in the GUI. '''

        original_xlim = self.ax.get_xlim()
        original_ylim = self.ax.get_ylim()

        self.ax.clear()  # Clear contents of current axis

        # Plot cosmetics
        self.ax.set_xlabel('I [A]')
        self.ax.set_ylabel('U [V]')
        self.ax.set_title('Sweep ID: ' + self.sweep_id)

        for i in range(len(data)):
            x, y = data[i]
            if i == len(data) - 1:
                color = '#0066FF'
            elif i == len(data) - 2:
                color = '#6600CC'
            else:
                color = '#FF0000'
            if self.chkLoop.checkState():
                half = int(len(x) / 2)
                end = len(x)
                self.ax.plot(x[0:half], y[0:half], color=color)
                self.ax.plot(x[half:end], y[half:end], '--', color=color)
            else:
                self.ax.plot(x, y, color=color)
            if self.log_sweep:
                self.ax.set_xscale('log')
            else:
                self.ax.set_xscale('linear')

            if i != 0 and self.chkLockRange.checkState():
                self.ax.set_xlim(original_xlim)
                self.ax.set_ylim(original_ylim)

        self.canvas.get_default_filename = self.get_default_filename
        self.canvas.draw()  # Propagate changes to GUI

    def clear_plot(self):
        self.ax.clear()  # Clear contents of current axis
        self.canvas.draw()  # Propagate changes to GUI

    def put_figure_into_gui(self, fig, ax):
        ''' Creates a figure and places it inside the GUI container. '''

        # Figure
        self.fig = fig
        self.ax = ax

        # Canvas
        self.canvas = FigureCanvas(self.fig)
        self.mplvl.addWidget(self.canvas)
        self.canvas.draw()

        # Toolbar
        self.toolbar = NavigationToolbar(self.canvas,
                                         self.mplwindow,
                                         coordinates=True)
        self.mplvl.addWidget(self.toolbar)

    def remove_figure_from_gui(self, ):
        ''' Deletes the figure from the GUI. '''

        # Canvas
        self.mplvl.removeWidget(self.canvas)
        self.canvas.close()
        self.canvas.deleteLater()  # this prevents memory leaks

        # Toolbar
        self.mplvl.removeWidget(self.toolbar)
        self.toolbar.close()
        self.toolbar.deleteLater()  # this prevent memory leaks

    def get_default_filename(self):
        """
        Return a string, which includes extension, suitable for use as
        a default filename.
        """
        default_basename = self.save_filename or "sweep_{}".format(
            self.sweep_id) or 'image'
        default_filetype = self.canvas.get_default_filetype()
        default_filename = default_basename + '.' + default_filetype

        save_dir = os.path.expanduser(
            matplotlib.rcParams.get('savefig.directory', ''))

        # ensure non-existing filename in save dir
        i = 1
        while os.path.isfile(os.path.join(save_dir, default_filename)):
            # attach numerical count to basename
            default_filename = '{0}_({1}).{2}'.format(default_basename, i,
                                                      default_filetype)
            i += 1

        return default_filename

    # --- GUI collecting and starting MEASUREMENTS ---------------------------
    # ------------------------------------------------------------------------
    # ------------------------------------------------------------------------
    # ------------------------------------------------------------------------

    def validateInput(self, sw_min, sw_max, decade, delay, log_sweep, step):
        # Unit testing :P
        try:
            a = float(sw_min)
            a = float(sw_max)
            if not log_sweep:
                a = float(step)
        except:
            return False, "Některé parametry se nedají převést na čísla."

        # Code
        if log_sweep:
            if (float(sw_min) > 0 and float(sw_max) > 0
                    and float(sw_min) != float(sw_max)):
                return True, "OK"
            else:
                return False, "Kraje intervalu jsou stejné nebo je alespoň jeden záp**ný."
        else:
            # lin sweep
            if (float(sw_min) != float(sw_max)
                    and abs(float(sw_max) - float(sw_min)) > float(step)):
                # step fits into (start, stop) interval and start != stop
                test_array = np.arange(float(sw_max), float(sw_min),
                                       float(step))
                if self.chkLoop.checkState() and len(test_array) * 2 > 1000:
                    return False, "Počet bodů ve sweepu je {} > 1000. \nBuffer by přetekl, zvolte jemnější krok, menší rozsah nebo vypněte obousměrnost měření.".format(
                        2 * len(test_array))
                elif len(test_array) > 1000:
                    return False, "Počet bodů ve sweepu je {} > 1000. \nBuffer by přetekl, zvolte jemnější krok nebo menší rozsah.".format(
                        len(test_array))
                else:
                    return True, "OK"
            else:
                return False, "Kraje intervalu se rovnají, nebo je krok větší než rozsah."

    def stopFunc(self):
        print('ABORT! Attempted to STOP sweep!')
        self.inst.operate(False)
        self.stop = True

    def startFunc(self):
        ''' Posbírá z GUI parametry a odpovídajícím způsobem přeloží.'''
        # vypnout ruční brzdu
        self.stop = False

        # aktuální čas pro ID
        self.sweep_id = '{0:%Y-%m-%d_%H-%M-%S}'.format(datetime.datetime.now())
        self.save_filename = False

        sense_local = self.senseLocalRadioButton.isChecked()
        sense_remote = self.senseRemoteRadioButton.isChecked()
        self.sense_local = sense_local

        sw_min = str(self.startEdit.text())
        sw_max = str(self.endEdit.text())
        step = str(self.stepEdit.text())

        # Pokud je zapojený zesilovač
        if not self.sense_local:
            sw_min = str(float(sw_min) * 1e3)
            sw_max = str(float(sw_max) * 1e3)
            step = str(float(step) * 1e3)

        # TODO: this should be made more logical...
        self.custom_capacity_used = self.dynamicDelayRadio.isChecked()
        if self.custom_capacity_used:
            self.custom_capacity = int(self.capacitySpinBox.value())

        delay = str(self.delaySpinBox.value())
        decade = str(self.decadeComboBox.currentIndex())
        n = self.pocetMereniBox.value()

        self.bigProgBar.setValue(0)
        self.bigProgBar.setMaximum(n)
        self.littleProgBar.setValue(0)

        log_sweep = self.logRadioButton.isChecked()
        lin_sweep = self.linRadioButton.isChecked()
        self.log_sweep = log_sweep

        col_source = self.sourceCheckBox.checkState()
        col_delay = self.delayCheckBox.checkState()
        col_measure = self.measureCheckBox.checkState()
        col_time = self.timeCheckBox.checkState()

        self.cols = 0
        if col_source:
            self.cols += 1
        if col_delay:
            self.cols += 2
        if col_measure:
            self.cols += 4
        if col_time:
            self.cols += 8

        input_valid, err = self.validateInput(sw_min, sw_max, decade, delay,
                                              log_sweep, step)
        if self.chkAutorange.checkState():
            sweep_range = '0'
        else:
            sweep_range = str(
                misc.get_range_number(float(sw_min), float(sw_max)))
            print("!! Using sweep range: {}".format(sweep_range))
            if sweep_range == '0':
                print(
                    'POZOR: Manualni nastaveni range selhalo, prilis vysoke proudy?'
                )

        if input_valid:
            self.save_parameters()
            self.measure(sw_min, sw_max, decade, delay, log_sweep, step, n,
                         sweep_range)
        else:
            self.show_notification(err)

    # --- ACTUAL MEASUREMENTS ------------------------------------------------
    # ------------------------------------------------------------------------
    # ------------------------------------------------------------------------
    # ------------------------------------------------------------------------

    def measure(self, sw_min, sw_max, decade, delay, log_sweep, step, n,
                sweep_range):
        ''' Spustí měření s již validovanými parametry. '''
        # Disable UI
        self.enable_ui(False)

        # Smaže aktuální graf
        self.clear_plot()

        # Declare Export not done on this sweep
        self.exportButton.setText('Export')

        # Local or Remote sense?
        if self.sense_local:
            print("Zapinam Sense - LOCAL.")
            self.inst.write("O0X")
        else:
            print("Zapinam Sense - REMOTE.")
            self.inst.write("O1X")

        # Úvodní stabilizace
        stabilize_time = self.stableSpinBox.value()
        print("Uvodni stabilizace v DC modu - {} s.".format(stabilize_time))
        self.stabilize(sw_min, stabilize_time)

        # Nastavení sweepu
        self.inst.set_source_and_function('I', 'Sweep')
        # Nastavení formátu dat
        self.inst.write("G" + str(self.cols) + ",2,2X")

        if self.log_sweep:
            self.inst.write("Q2," + sw_min + "," + sw_max + "," + decade +
                            "," + sweep_range + "," + delay + "X")
            if self.chkLoop.checkState():
                self.inst.write("Q8," + sw_max + "," + sw_min + "," + decade +
                                "," + sweep_range + "," + delay + "X")
        else:
            self.inst.write("Q1," + sw_min + "," + sw_max + "," + step + "," +
                            sweep_range + "," + delay + "X")
            if self.chkLoop.checkState():
                self.inst.write("Q7," + sw_max + "," + sw_min + "," + step +
                                "," + sweep_range + "," + delay + "X")

        # Manual modification of delays for each value
        if self.custom_capacity_used:
            if self.chkLoop.checkState():
                delay_arr = delays.delays_round(float(sw_min), float(sw_max),
                                                int(decade),
                                                self.custom_capacity)
            else:
                delay_arr = delays.delays_up(float(sw_min), float(sw_max),
                                             int(decade), self.custom_capacity)
            self.inst.set_custom_delays(delay_arr)

        data = []
        self.full_data = []
        self.np_data = []
        n_hotovych_mereni = 0
        for mereni in range(n):
            if self.stop:
                break
            output = self.run_sweep()
            if output:
                if not self.sense_local:
                    output = misc.shift_data(output, cols=self.cols, shift=-3)
                sweep_results = misc.nice_format(output, cols=self.cols)
                unpacked_results = misc.unpack(sweep_results, cols=self.cols)
                data.append(unpacked_results)
                self.full_data.append(sweep_results)
                self.np_data = misc.pack_data(self.np_data, unpacked_results)

                print('Ukladam docasna data...')
                self.dump_data()

                n_hotovych_mereni += 1
                self.bigProgBar.setValue(n_hotovych_mereni)
                self.plot_data(data)

                if n_hotovych_mereni != n:
                    sleep_time = self.sleepSpinBox.value()
                    print("Pauza mezi sweepy - {} s.".format(sleep_time))
                    self.artSleep(sleep_time)

            else:
                print("Output byl prazdny. Prerusene mereni?")

        self.inst.operate(False)
        self.enable_ui(True)

    def run_sweep(self):
        ''' Provede jeden sweep, který už musí být definovaný ve stroji.
            Na konci 3 vteřiny spí, aby se mělo napětí čas ustálit před dalším měřením.

            Vrací string se všemi hodnotami sweepu.
        '''
        print('\nSpoustim sweep...')
        self.inst.write("U8X")
        out = self.inst.read()
        print('U8X -> ' + out)
        out = out.replace('\r', '').replace('\n', '')
        print("Out: {}".format(out))
        sweep_defined_size = int(out[-4:])
        print('Pocet bodu ve sweepu: ' + str(sweep_defined_size))

        self.littleProgBar.setValue(0)
        self.inst.trigger()  # Immediate trigger
        sweep_done = False
        while not sweep_done:
            if self.stop:
                break
            self.artSleep(0.2)
            self.inst.write("U11X")
            status = self.inst.read()
            if (status == 'SMS' + str(sweep_defined_size).zfill(4) + '\r\n'):
                sweep_done = True
            else:
                status_edit = status.replace('\r', '').replace('\n', '')
                try:
                    progress = int(status_edit[-4:])
                    self.littleProgBar.setValue(
                        int(progress / sweep_defined_size * 100))
                except:
                    print('Invalid progress!')
        print('Jeden sweep hotov.')
        self.littleProgBar.setValue(100)

        if self.stop:
            return ""
        else:
            return self.inst.read()

    def stabilize(self, bias, stabilize_time):
        # Počáteční stabilizace
        self.inst.set_source_and_function('I', 'DC')
        self.inst.write("B" + bias + ",0,20X")
        self.inst.operate(True)
        self.inst.trigger()
        self.artSleep(stabilize_time)

    # --- EXPORT and DATA operations -----------------------------------------
    # ------------------------------------------------------------------------
    # ------------------------------------------------------------------------
    # ------------------------------------------------------------------------

    def dump_data(self):
        save_file_name = 'C:\Repa\k237\data_temp.txt'
        try:
            np.savetxt(save_file_name,
                       self.np_data,
                       fmt='%.4e',
                       header=self.get_measurement_parameters() +
                       "\nPOZOR, prubezne ukladana data mohou byt nekompletni",
                       delimiter='\t')
        except:
            print("Nouzovy dump se nepovedl.")

    def export_data(self):
        """
        Exportuje data pomocí ukládacího dialogu Qt. V případě chybného zadání
        souboru nic neudělá a postěžuje si do konzole.
        """

        proposed_name = self.save_filename or 'sweep_' + self.sweep_id

        # Qt Dialog na výběr souboru k uložení
        save_file_name, _ = QtWidgets.QFileDialog.getSaveFileName(
            None,
            'Exportovat výsledky měření',
            #'C:\Repa\k237\data\sweep_' + proposed_name + '.txt',
            os.path.join(self.save_directory, proposed_name + '.txt'),
            'Text Files (*.txt);;All Files (*)')

        # Vlastní uložení souboru
        try:
            np.savetxt(save_file_name,
                       self.np_data,
                       fmt='%.4e',
                       header=self.get_measurement_parameters(),
                       delimiter='\t')

            # Update GUI
            self.exportButton.setText('Export ✔')
            self.save_directory = os.path.dirname(save_file_name)
            self.save_filename = os.path.splitext(
                os.path.basename(save_file_name))[0]
        except:
            print("Export neuspesny. Data pravdepodobne nejsou ulozena!")

            # Update GUI
            self.exportButton.setText('Export ✗')

    def get_measurement_parameters(self):
        out = ''
        out += "Sweep ID: {}\n".format(self.sweep_id)
        if self.log_sweep:
            out += "Log sweep:\n"
            out += "Rozsah (min, max) [A]: {}, {}\n".format(
                self.startEdit.text(), self.endEdit.text())
            out += "Bodu na dekadu [-]: {}\n".format(
                self.decade_combo_values[self.decadeComboBox.currentIndex()])
        else:
            out += "Linear sweep\n"
            out += "Rozsah (min, max, points) [A]: {}, {}, {}\n".format(
                self.startEdit.text(), self.endEdit.text(),
                self.stepEdit.text())

        out += "Delay [ms]: {}\n".format(self.delaySpinBox.value())
        out += "Pocet charakteristik [-]: {}\n".format(
            self.pocetMereniBox.value())

        if self.sense_local:
            out += "Sense: local\n"
        else:
            out += "Sense: remote\n"

        out += "Sloupce (Source, Measure, Delay, Time): {} {} {} {}\n".format(
            int(self.sourceCheckBox.checkState() / 2),
            int(self.measureCheckBox.checkState() / 2),
            int(self.delayCheckBox.checkState() / 2),
            int(self.timeCheckBox.checkState() / 2))

        out += "Uvodni DC stabilizace [s]: {}\n".format(
            self.stableSpinBox.value())
        out += "Stabilizace [s]: {}\n".format(self.sleepSpinBox.value())
        out += "\nI[A] (x)\tU[V .e-3] (y1, y2, ...) "

        return out

    # --- GUI parameters and ENABLE/DISABLE ----------------------------------
    # ------------------------------------------------------------------------
    # ------------------------------------------------------------------------
    # ------------------------------------------------------------------------

    def save_parameters(self):
        parameters_dict = {
            'sw_min': str(self.startEdit.text()),
            'sw_max': str(self.endEdit.text()),
            'step': str(self.stepEdit.text()),
            'delay': int(self.delaySpinBox.value()),
            'decade': int(self.decadeComboBox.currentIndex()),
            'n': int(self.pocetMereniBox.value()),
            'log_sweep': self.logRadioButton.isChecked(),
            'lin_sweep': self.linRadioButton.isChecked(),
            'sense_local': self.senseLocalRadioButton.isChecked(),
            'sense_remote': self.senseRemoteRadioButton.isChecked(),
            'col_source': self.sourceCheckBox.checkState(),
            'col_delay': self.delayCheckBox.checkState(),
            'col_measure': self.measureCheckBox.checkState(),
            'col_time': self.timeCheckBox.checkState(),
            'stabilize_time': self.stableSpinBox.value(),
            'sleep_time': self.sleepSpinBox.value(),
            'chk_loop': self.chkLoop.checkState(),
            'chk_lock_range': self.chkLockRange.checkState(),
            'chk_autorange': self.chkAutorange.checkState(),
        }

        # For pickle, the file needs to be opened in binary mode, hence the "wb"
        with open("last_parameters.pickle", "wb") as params_file:
            pickle.dump(parameters_dict, params_file)

    def load_parameters(self):
        try:
            # For pickle, the file needs to be opened in binary mode, hence the "wb"
            with open("last_parameters.pickle", "rb") as params_file:
                parameters_dict = pickle.load(params_file)

            self.startEdit.setText(parameters_dict['sw_min'])
            self.endEdit.setText(parameters_dict['sw_max'])
            self.stepEdit.setText(parameters_dict['step'])
            self.delaySpinBox.setValue(parameters_dict['delay'])
            self.decadeComboBox.setCurrentIndex(parameters_dict['decade'])
            self.pocetMereniBox.setValue(parameters_dict['n'])

            self.logRadioButton.setChecked(parameters_dict['log_sweep'])
            self.linRadioButton.setChecked(parameters_dict['lin_sweep'])
            self.senseLocalRadioButton.setChecked(
                parameters_dict['sense_local'])
            self.senseRemoteRadioButton.setChecked(
                parameters_dict['sense_remote'])

            self.sourceCheckBox.setChecked(parameters_dict['col_source'])
            self.delayCheckBox.setChecked(parameters_dict['col_delay'])
            self.measureCheckBox.setChecked(parameters_dict['col_measure'])
            self.timeCheckBox.setChecked(parameters_dict['col_time'])

            self.stableSpinBox.setValue(parameters_dict['stabilize_time'])
            self.sleepSpinBox.setValue(parameters_dict['sleep_time'])

            self.chkLoop.setChecked(parameters_dict['chk_loop'])
            self.chkLockRange.setChecked(parameters_dict['chk_lock_range'])
            self.chkAutorange.setChecked(parameters_dict['chk_autorange'])

            self.switch_linear()
            self.switch_dynamic_delay()

            print("Nacteni poslednich parametru uspesne! :)")

        except:
            print("Nacteni poslednich parametru selhalo. :(")

    def switch_linear(self):
        log_sweep = self.logRadioButton.isChecked()
        lin_sweep = self.linRadioButton.isChecked()
        if log_sweep:
            self.stepEdit.setEnabled(False)
            self.decadeComboBox.setEnabled(True)
        else:
            self.decadeComboBox.setEnabled(False)
            self.stepEdit.setEnabled(True)

    def switch_dynamic_delay(self):
        const_delay = self.constantDelayRadio.isChecked()
        dynamic_delay = self.dynamicDelayRadio.isChecked()
        if const_delay:
            self.capacitySpinBox.setEnabled(False)
            self.delaySpinBox.setEnabled(True)
        else:
            self.delaySpinBox.setEnabled(False)
            self.capacitySpinBox.setEnabled(True)

    def enable_ui(self, status):
        ui_elements = [
            self.startEdit,
            self.endEdit,
            self.stepEdit,
            self.delaySpinBox,
            self.decadeComboBox,
            self.pocetMereniBox,
            self.logRadioButton,
            self.linRadioButton,
            self.senseLocalRadioButton,
            self.senseRemoteRadioButton,
            self.sourceCheckBox,
            self.delayCheckBox,
            self.measureCheckBox,
            self.timeCheckBox,
            self.stableSpinBox,
            self.sleepSpinBox,
            self.chkLoop,
            self.chkAutorange,
            self.exportButton,
        ]

        for element in ui_elements:
            element.setEnabled(status)

        if status:
            self.switch_linear()
            self.switch_dynamic_delay()

        if status:
            self.startBtn.clicked.disconnect()
            self.startBtn.clicked.connect(self.startFunc)
            self.startBtn.setText("Start")
            self.exportButton.setFocus()
        else:
            self.startBtn.clicked.disconnect()
            self.startBtn.clicked.connect(self.stopFunc)
            self.startBtn.setText("Abort")
            self.startBtn.setFocus()
            self.exportButton.setText('Export')

    def artSleep(self, sleepTime):
        """
        Čeká čas sleepTime v sekundách, zatím ale každých 50 milisekund řeší
        akce, o které se někdo pokoušel v GUI.
        """
        stop_time = QtCore.QTime()
        stop_time.restart()
        while stop_time.elapsed() < sleepTime * 1000:
            QtWidgets.QApplication.processEvents(QtCore.QEventLoop.AllEvents,
                                                 50)

    def show_notification(self, err):
        msg = QtWidgets.QMessageBox()
        msg.setIcon(QtWidgets.QMessageBox.Warning)
        msg.setText("Chybné parametry sweepu.")
        msg.setInformativeText(err)
        msg.setWindowTitle("Sweeper - varování")
        msg.exec_()
Beispiel #5
0
class Ui_MainWindow(object):
    def openOverview(self):
        #Connects to the SQL Server
        self.window = QtWidgets.QMainWindow()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self.window)
        MainWindow.close()
        self.window.show()
        return

    def setupUi(self, MainWindow):
        self.conn = mysql.connector.connect(
            host="myrds1.cijcu6ghykxh.ap-southeast-1.rds.amazonaws.com",
            user="******",
            passwd="admin123",
            database="myrds1")

        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(831, 666)
        MainWindow.setToolTipDuration(0)
        MainWindow.setFixedSize(831, 666)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.line = QtWidgets.QFrame(self.centralwidget)
        self.line.setGeometry(QtCore.QRect(0, 90, 891, 16))
        self.line.setFrameShape(QtWidgets.QFrame.HLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setObjectName("line")
        self.line_2 = QtWidgets.QFrame(self.centralwidget)
        self.line_2.setGeometry(QtCore.QRect(210, 0, 20, 641))
        self.line_2.setFrameShape(QtWidgets.QFrame.VLine)
        self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_2.setObjectName("line_2")
        self.total_cases = QtWidgets.QLabel(self.centralwidget)
        self.total_cases.setEnabled(True)
        self.total_cases.setGeometry(QtCore.QRect(260, 140, 531, 51))
        font = QtGui.QFont()
        font.setFamily("Montserrat")
        font.setPointSize(17)
        font.setBold(False)
        font.setItalic(False)
        font.setWeight(50)
        self.total_cases.setFont(font)
        self.total_cases.setAutoFillBackground(False)
        self.total_cases.setAlignment(QtCore.Qt.AlignCenter)
        self.total_cases.setObjectName("total_cases")
        self.total_death = QtWidgets.QLabel(self.centralwidget)
        self.total_death.setGeometry(QtCore.QRect(410, 290, 231, 61))
        font = QtGui.QFont()
        font.setFamily("Montserrat")
        font.setPointSize(17)
        font.setBold(False)
        font.setWeight(50)
        self.total_death.setFont(font)
        self.total_death.setAlignment(QtCore.Qt.AlignCenter)
        self.total_death.setObjectName("total_death")
        self.total_recovered = QtWidgets.QLabel(self.centralwidget)
        self.total_recovered.setGeometry(QtCore.QRect(380, 440, 291, 61))
        font = QtGui.QFont()
        font.setFamily("Montserrat")
        font.setPointSize(17)
        font.setBold(False)
        font.setWeight(50)
        self.total_recovered.setFont(font)
        self.total_recovered.setAlignment(QtCore.Qt.AlignCenter)
        self.total_recovered.setObjectName("total_recovered")
        self.title_status = QtWidgets.QLabel(self.centralwidget)
        self.title_status.setGeometry(QtCore.QRect(260, 10, 571, 81))
        font = QtGui.QFont()
        font.setFamily("PT Sans Caption")
        font.setPointSize(23)
        font.setBold(True)
        font.setWeight(75)
        self.title_status.setFont(font)
        self.title_status.setObjectName("title_status")

        ### GUI for the Overview Layout. ###
        self.cases_textBrowser = QtWidgets.QLabel(self.centralwidget)
        self.cases_textBrowser.setGeometry(QtCore.QRect(390, 190, 261, 61))
        self.cases_textBrowser.setObjectName("cases_textBrowser")
        self.cases_textBrowser.setStyleSheet(
            "QLabel { background-color : white; color : black; }")
        self.cases_textBrowser.setAlignment(QtCore.Qt.AlignCenter)
        self.death_textBrowser = QtWidgets.QLabel(self.centralwidget)
        self.death_textBrowser.setGeometry(QtCore.QRect(390, 340, 261, 61))
        self.death_textBrowser.setObjectName("death_textBrowser")
        self.death_textBrowser.setStyleSheet(
            "QLabel { background-color : white; color : black; }")
        self.death_textBrowser.setAlignment(QtCore.Qt.AlignCenter)
        self.recoverd_textBrowser = QtWidgets.QLabel(self.centralwidget)
        self.recoverd_textBrowser.setGeometry(QtCore.QRect(390, 490, 261, 61))
        self.recoverd_textBrowser.setObjectName("recoverd_textBrowser")
        self.recoverd_textBrowser.setStyleSheet(
            "QLabel { background-color : white; color : black; }")
        self.recoverd_textBrowser.setAlignment(QtCore.Qt.AlignCenter)
        fontfortextbrowser = QtGui.QFont()
        fontfortextbrowser.setFamily("Montserrat")
        fontfortextbrowser.setPointSize(25)
        fontfortextbrowser.setBold(False)
        fontfortextbrowser.setWeight(100)
        self.cases_textBrowser.setFont(fontfortextbrowser)
        self.death_textBrowser.setFont(fontfortextbrowser)
        self.recoverd_textBrowser.setFont(fontfortextbrowser)
        ###End.###

        ###Layout for Overview. ###
        self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.verticalLayoutWidget.setGeometry(QtCore.QRect(20, 130, 160, 371))
        self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setSpacing(0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.overview_button = QtWidgets.QPushButton(self.verticalLayoutWidget)
        font = QtGui.QFont()
        font.setPointSize(10)

        ### Buttons ####
        self.overview_button.setFont(font)
        self.overview_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.overview_button.setToolTipDuration(0)
        self.overview_button.setAutoFillBackground(True)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("Images/flat-icon-png-40260.png"),
                       QtGui.QIcon.Selected, QtGui.QIcon.On)
        self.overview_button.setIcon(icon)
        self.overview_button.setIconSize(QtCore.QSize(40, 40))
        self.overview_button.setObjectName("overview_button")
        self.verticalLayout.addWidget(self.overview_button)
        self.charts_button = QtWidgets.QPushButton(self.verticalLayoutWidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.charts_button.setFont(font)
        self.charts_button.setToolTipDuration(1)
        self.charts_button.setAutoFillBackground(True)
        icon1 = QtGui.QIcon()
        icon1.addPixmap(
            QtGui.QPixmap(
                "Images/kisspng-computer-icons-bar-chart-charts-5abed4a903cbf3.1869123215224557210156.png"
            ), QtGui.QIcon.Selected, QtGui.QIcon.On)
        self.charts_button.setIcon(icon1)
        self.charts_button.setIconSize(QtCore.QSize(40, 40))
        self.charts_button.setObjectName("charts_button")
        self.verticalLayout.addWidget(self.charts_button)
        self.location_button = QtWidgets.QPushButton(self.verticalLayoutWidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.location_button.setFont(font)
        self.location_button.setAutoFillBackground(True)
        icon2 = QtGui.QIcon()
        icon2.addPixmap(QtGui.QPixmap("Images/icons8-location-64.png"),
                        QtGui.QIcon.Selected, QtGui.QIcon.On)
        self.location_button.setIcon(icon2)
        self.location_button.setIconSize(QtCore.QSize(40, 40))
        self.location_button.setObjectName("location_button")
        self.verticalLayout.addWidget(self.location_button)
        self.patterns_button = QtWidgets.QPushButton(self.verticalLayoutWidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.patterns_button.setFont(font)
        self.patterns_button.setAutoFillBackground(True)
        icon3 = QtGui.QIcon()
        icon3.addPixmap(QtGui.QPixmap("Images/iconfinder_10_1516234.png"),
                        QtGui.QIcon.Selected, QtGui.QIcon.On)
        self.patterns_button.setIcon(icon3)
        self.patterns_button.setIconSize(QtCore.QSize(40, 40))
        self.patterns_button.setObjectName("patterns_button")
        self.verticalLayout.addWidget(self.patterns_button)
        self.news_button = QtWidgets.QPushButton(self.verticalLayoutWidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.news_button.setFont(font)
        self.news_button.setAutoFillBackground(True)
        icon4 = QtGui.QIcon()
        icon4.addPixmap(QtGui.QPixmap("Images/news.png"), QtGui.QIcon.Selected,
                        QtGui.QIcon.On)
        self.news_button.setIcon(icon4)
        self.news_button.setIconSize(QtCore.QSize(40, 40))
        self.verticalLayout.addWidget(self.news_button)
        ### End  ####

        ### Labels and Picture setup ###
        self.line_3 = QtWidgets.QFrame(self.centralwidget)
        self.line_3.setGeometry(QtCore.QRect(200, 0, 16, 711))
        self.line_3.setFrameShape(QtWidgets.QFrame.VLine)
        self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_3.setObjectName("line_3")
        self.about_button = QtWidgets.QPushButton(self.centralwidget)
        self.about_button.setGeometry(QtCore.QRect(20, 590, 158, 39))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.about_button.setFont(font)
        icon4 = QtGui.QIcon()
        icon4.addPixmap(
            QtGui.QPixmap("Images/25f03a917cfb2c9beb28d0ffcd236ffa.png"),
            QtGui.QIcon.Selected, QtGui.QIcon.On)
        self.about_button.setIcon(icon4)
        self.about_button.setIconSize(QtCore.QSize(30, 30))
        self.about_button.setObjectName("about_button")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(270, 10, 71, 81))
        self.label.setStyleSheet(
            "image: url(:/header/Images/philippines.png);")
        self.label.setText("")
        self.label.setObjectName("label")
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(20, 20, 161, 61))
        self.label_3.setStyleSheet(
            "image: url(:/header/Images/mapua-logo2.png);")
        self.label_3.setText("")
        self.label_3.setObjectName("label_3")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(-10, 0, 841, 771))
        self.label_2.setStyleSheet(
            "background-image: url(:/bg/Images/bg-main4.png);")
        self.label_2.setText("")
        self.label_2.setObjectName("label_2")
        ### End    ###

        ### Raises the widget.  ###
        self.label_2.raise_()
        self.line.raise_()
        self.line_2.raise_()
        self.total_cases.raise_()
        self.total_death.raise_()
        self.total_recovered.raise_()
        self.title_status.raise_()
        self.cases_textBrowser.raise_()
        self.death_textBrowser.raise_()
        self.recoverd_textBrowser.raise_()
        self.verticalLayoutWidget.raise_()
        self.line_3.raise_()
        self.about_button.raise_()
        self.label.raise_()
        self.label_3.raise_()
        ### End. ####

        ### About Us Button ###
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.actionAbout_Us = QtWidgets.QAction(MainWindow)
        self.actionAbout_Us.setObjectName("actionAbout_Us")
        ### End

        #Charts UI
        self.chartsView = QtWidgets.QGraphicsView(self.centralwidget)
        self.chartsView.setGeometry(QtCore.QRect(228, 159, 541, 421))
        self.chartsView.setObjectName("chartsView")
        self.updateChart_button = QtWidgets.QPushButton(self.centralwidget)
        self.updateChart_button.setGeometry(QtCore.QRect(610, 110, 161, 41))
        font = QtGui.QFont()
        font.setPointSize(14)
        self.updateChart_button.setFont(font)
        self.updateChart_button.setObjectName("updateChart_button")
        self.updateChart_button.setText("Update")
        self.guide1 = QtWidgets.QLabel(self.centralwidget)
        self.guide1.setGeometry(QtCore.QRect(230, 100, 371, 20))
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setItalic(True)
        font.setWeight(75)
        self.guide1.setFont(font)
        self.guide1.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignTop)
        self.guide1.setObjectName("guide1")
        self.horizontalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.horizontalLayoutWidget.setGeometry(QtCore.QRect(
            230, 120, 371, 31))
        self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(
            self.horizontalLayoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.prevDate = QtWidgets.QDateEdit(self.horizontalLayoutWidget)
        self.prevDate.setMinimumDate(QtCore.QDate(2020, 3, 8))
        self.prevDate.setDate(QtCore.QDate(2020, 3, 8))
        self.prevDate.setObjectName("prevDate")
        self.horizontalLayout.addWidget(self.prevDate)
        self.currentDate = QtWidgets.QDateEdit(self.horizontalLayoutWidget)
        self.currentDate.setMinimumDateTime(
            QtCore.QDateTime(QtCore.QDate(2020, 3, 9), QtCore.QTime(0, 0, 0)))
        self.currentDate.setMinimumDate(QtCore.QDate(2020, 3, 9))
        self.currentDate.setDate(QtCore.QDate(2020, 3, 9))
        self.currentDate.setObjectName("currentDate")
        self.horizontalLayout.addWidget(self.currentDate)
        self.updateChart_button.raise_()
        self.horizontalLayoutWidget.raise_()
        self.prevDate.raise_()
        self.currentDate.raise_()
        self.chartsView.raise_()
        self.guide1.raise_()
        self.chartsView.hide()
        self.updateChart_button.hide()
        self.horizontalLayoutWidget.hide()
        self.prevDate.hide()
        self.currentDate.hide()
        self.guide1.hide()
        self.layoutlim = 0
        #/ChartUI

        #Location UI
        self.locationView = QtWidgets.QLabel(self.centralwidget)
        self.locationView.setGeometry(QtCore.QRect(240, 110, 660, 520))
        self.locationView.setObjectName("locationView")
        self.loc = location_widget(self.locationView)
        self.locationView.raise_()
        self.locationView.hide()

        #Patterns UI
        fontforLabel = QtGui.QFont()
        fontforLabel.setFamily("Montserrat")
        fontforLabel.setPointSize(17)
        fontforLabel.setBold(False)
        fontforLabel.setWeight(50)
        self.textBrowser_Current = QtWidgets.QLabel(self.centralwidget)
        self.textBrowser_Current.setStyleSheet(
            "QLabel { background-color : white; color : black; }")
        self.textBrowser_Current.setAlignment(QtCore.Qt.AlignCenter)
        self.textBrowser_Current.setGeometry(QtCore.QRect(290, 330, 201, 61))
        self.textBrowser_Current.setObjectName("textBrowser_Current")
        self.textBrowser_Tomorrow = QtWidgets.QLabel(self.centralwidget)
        self.textBrowser_Tomorrow.setStyleSheet(
            "QLabel { background-color : white; color : black; }")
        self.textBrowser_Tomorrow.setAlignment(QtCore.Qt.AlignCenter)
        self.textBrowser_Tomorrow.setGeometry(QtCore.QRect(560, 330, 201, 61))
        self.textBrowser_Tomorrow.setObjectName("textBrowser_Tomorrow")
        fontfortextbrowser1 = QtGui.QFont()
        fontfortextbrowser1.setFamily("Montserrat")
        fontfortextbrowser1.setPointSize(25)
        fontfortextbrowser1.setBold(False)
        fontfortextbrowser1.setWeight(100)
        self.textBrowser_Current.setFont(fontfortextbrowser1)
        self.textBrowser_Tomorrow.setFont(fontfortextbrowser1)
        self.label_Current = QtWidgets.QLabel(self.centralwidget)
        self.label_Current.setGeometry(QtCore.QRect(340, 270, 231, 61))
        self.label_Current.setObjectName("label_Current")
        self.label_Current.setFont(fontforLabel)
        self.label_Tomorrow = QtWidgets.QLabel(self.centralwidget)
        self.label_Tomorrow.setGeometry(QtCore.QRect(545, 270, 231, 61))
        self.label_Tomorrow.setObjectName("label_Tomorrow")
        self.label_Tomorrow.setAlignment(QtCore.Qt.AlignCenter)
        self.label_Tomorrow.setFont(fontforLabel)
        self.label_Current.raise_()
        self.label_Tomorrow.raise_()
        self.patterns_calcu()
        #/Patterns UI

        #News_UI
        self.doh_list = news_ui.news_ui(self.centralwidget)
        self.doh_list.setObjectName('doh_list')
        ws = DOH_Scrapper.DOH_Scrapper()
        ws.run()
        rawData = ws.getData()
        array_data = []
        for x in rawData:
            data = news_ui.News()
            data.ArticleName = x[0]
            data.ArticleLink = x[1]
            array_data.append(data)
        self.doh_list.add_News(array_data)
        self.doh_list.raise_()
        #/News UI

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        #Data for Overview
        self.overview_data = COVID19_Scrapper.COVID19_Scrapper()
        data = []
        data = self.overview_data.x
        self.cases_textBrowser.setText(data[0])
        self.death_textBrowser.setText(data[1])
        self.recoverd_textBrowser.setText(data[2])
        #/Data for Overview

        self.updateChart_button.clicked.connect(self.on_update_chart_clicked)
        self.charts_button.clicked.connect(self.on_charts_clicked)
        self.patterns_button.clicked.connect(self.on_patterns_clicked)
        self.location_button.clicked.connect(self.on_location_clicked)
        self.overview_button.clicked.connect(self.on_overview_clicked)
        self.news_button.clicked.connect(self.on_news_clicked)
        self.on_overview_clicked()
        return

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "COVIDRecon"))
        self.total_cases.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-weight:600; text-decoration: underline; color:#ffffff;\">TOTAL CASES</span></p></body></html>"
            ))
        self.total_death.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline; color:#ffffff;\">TOTAL DEATHS</span></p></body></html>"
            ))
        self.total_recovered.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline; color:#ffffff;\">TOTAL RECOVERED</span></p></body></html>"
            ))
        self.title_status.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" color:#ffffff;\">COVID-19 Philippines</span></p></body></html>"
            ))
        self.overview_button.setToolTip(
            _translate("MainWindow", "Show Summary"))
        self.overview_button.setText(_translate("MainWindow", " OVERVIEW"))
        self.charts_button.setToolTip(
            _translate(
                "MainWindow",
                "<html><head/><body><p>Show latest cases of COVID-19.</p></body></html>"
            ))
        self.charts_button.setText(_translate("MainWindow", " CHARTS"))
        self.location_button.setText(_translate("MainWindow", " LOCATION"))
        self.patterns_button.setText(_translate("MainWindow", " PATTERNS"))
        self.about_button.setText(_translate("MainWindow", "  ABOUT US"))
        self.label_Current.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline; color:#ffffff;\">Current</span></p></body></html>"
            ))
        self.label_Tomorrow.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline; color:#ffffff;text-align:center;\">After a Week</span></p></body></html>"
            ))
        self.about_button.clicked.connect(lambda: webbrowser.open(
            'https://vppexis.github.io/CPE106L-ProjectCovidRecon/'))
        self.actionAbout_Us.setText(_translate("MainWindow", "About Us"))
        self.news_button.setText(_translate("MainWindow", "DOH NEWS"))
        self.about_button.clicked.connect(lambda: webbrowser.open(
            'https://vppexis.github.io/CPE106L-ProjectCovidRecon/'))
        self.actionAbout_Us.setText(_translate("MainWindow", "About Us"))
        self.guide1.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-weight:600; color:#ffffff;\">Date/Month/Year</span></p></body></html>"
            ))
        return

    #Gathers data for the chart.
    def data_gather(self):
        cursor = self.conn.cursor()
        cursor.execute(
            "SELECT date_rep_conf,COUNT(date_rep_conf) FROM casesByNCR GROUP BY date_rep_conf HAVING COUNT(date_rep_conf) > 1;"
        )
        result = cursor.fetchall()
        self.df = pd.DataFrame(result, columns=['date', 'cases'])
        self.data_cases = self.df[['date', 'cases']]
        self.date_x = self.data_cases['date']
        self.cases_y = self.data_cases['cases']
        return

    #Main functin for charts.
    def setup_chart(self):
        if self.layoutlim == 0:
            # Date gather
            cursor = self.conn.cursor()
            cursor.execute(
                "SELECT date_rep_conf,COUNT(date_rep_conf) FROM casesByNCR GROUP BY date_rep_conf HAVING COUNT(date_rep_conf) > 1;"
            )
            result = cursor.fetchall()
            self.df = pd.DataFrame(result, columns=['date', 'cases'])
            self.data_cases = self.df[['date', 'cases']]
            date_x = self.data_cases['date']
            cases_y = self.data_cases['cases']

            # Making the layout for the graph
            self.layout = QtWidgets.QVBoxLayout(self.chartsView)
            self.dynamic_canvas = FigureCanvasQTAgg(Figure(figsize=(5, 3)))
            self.layout.addWidget(self.dynamic_canvas)

            x = date_x
            y = np.cumsum(cases_y)

            dynamic_ax = self.dynamic_canvas.figure.subplots()
            self.dynamic_canvas.figure.autofmt_xdate()
            self.dynamic_canvas.figure.fmt_xdata = mdates.DateFormatter(
                '%y-%m-%d')
            self.recovered_chart()
            self.died_chart()
            dynamic_ax.plot(x, y, label='Cases', color='r')
            dynamic_ax.plot(self.R_x, self.R_y, label='Recovered', color='g')
            dynamic_ax.plot(self.D_x, self.D_y, label='Died', color='b')
            dynamic_ax.legend()
            dynamic_ax.set_xlabel('Dates of Report')
            dynamic_ax.set_ylabel('Population Affected')
            dynamic_ax.set_title('COVID-19 Cases')
            self.layoutlim = 1
        return

    ### Chart for Recovered Data.
    def recovered_chart(self):
        cursor = self.conn.cursor()
        if self.layoutlim == 0:
            cursor.execute(
                "SELECT date_rep_conf, Count(health_status) from casesByNCR where health_status = 'Recovered'GROUP BY date_rep_conf;"
            )
            result = cursor.fetchall()
        else:
            cursor.execute(
                "SELECT date_rep_conf,Count(health_status)from casesByNCR where (health_status = 'Recovered') And date_rep_conf between %s AND %s group by date_rep_conf",
                (self.minDate, self.maxDate))
            result = cursor.fetchall()

        df = pd.DataFrame(result, columns=['date', 'recovered'])
        data_cases = df[['date', 'recovered']]
        self.R_x = data_cases['date']
        self.R_y = np.cumsum(data_cases['recovered'])
        return

    ### Charts for dead data.
    def died_chart(self):
        cursor = self.conn.cursor()
        if self.layoutlim == 0:
            cursor.execute(
                "SELECT date_rep_conf, Count(health_status) from casesByNCR where health_status = 'Died'GROUP BY date_rep_conf;"
            )
            result = cursor.fetchall()
        else:
            cursor.execute(
                "SELECT date_rep_conf,Count(health_status)from casesByNCR where (health_status = 'Died') And date_rep_conf between %s AND %s group by date_rep_conf",
                (self.minDate, self.maxDate))
            result = cursor.fetchall()
        df = pd.DataFrame(result, columns=['date', 'Died'])
        data_cases = df[['date', 'Died']]
        self.D_x = data_cases['date']
        self.D_y = np.cumsum(data_cases['Died'])
        return

    ### Updates the Graph
    def update_chart(self):
        self.minDate = self.prevDate.date().toPyDate()
        self.maxDate = self.currentDate.date().toPyDate()
        cursor = self.conn.cursor()
        cursor.execute(
            "SELECT date_rep_conf,Count(date_rep_conf) from casesByNCR where date_rep_conf between %s AND %s group by date_rep_conf having count(date_rep_conf) > 1;",
            (self.minDate, self.maxDate))
        result = cursor.fetchall()
        df = pd.DataFrame(result, columns=['date', 'cases'])
        data_cases = df[['date', 'cases']]
        x = data_cases['date']
        y = np.cumsum(data_cases['cases'])

        self.dynamic_canvas = FigureCanvasQTAgg(Figure(figsize=(5, 3)))
        self.layout.addWidget(self.dynamic_canvas)

        dynamic_ax = self.dynamic_canvas.figure.subplots()
        self.dynamic_canvas.figure.autofmt_xdate()
        self.dynamic_canvas.figure.fmt_xdata = mdates.DateFormatter('%y-%m-%d')
        self.recovered_chart()
        self.died_chart()
        dynamic_ax.plot(x, y, label='Cases', color='r')
        dynamic_ax.plot(self.R_x, self.R_y, label='Recovered', color='g')
        dynamic_ax.plot(self.D_x, self.D_y, label='Died', color='b')
        dynamic_ax.legend()
        dynamic_ax.set_xlabel('Dates of Report')
        dynamic_ax.set_ylabel('Population Affected')
        dynamic_ax.set_title('COVID-19 Cases')
        return

    ### Deletes the graph.
    def delete_canvas(self):
        self.dynamic_canvas.deleteLater()
        return

    ### Method for hiding Overview UI action
    def hide_overview_ui(self):
        self.total_cases.hide()
        self.total_death.hide()
        self.total_recovered.hide()
        self.cases_textBrowser.hide()
        self.death_textBrowser.hide()
        self.recoverd_textBrowser.hide()
        return

    ### Method for hiding Charts UI action
    def hide_charts_ui(self):
        self.chartsView.hide()
        self.updateChart_button.hide()
        self.horizontalLayoutWidget.hide()
        self.prevDate.hide()
        self.currentDate.hide()
        self.guide1.hide()
        return

    ### Method for hiding Location UI action
    def hide_location_ui(self):
        self.locationView.hide()
        return

    ### Method for hiding Patterns UI action
    def hide_patterns_ui(self):
        self.textBrowser_Current.hide()
        self.textBrowser_Tomorrow.hide()
        self.label_Current.hide()
        self.label_Tomorrow.hide()
        return

    ### Method for hiding News UI action.
    def hide_news_ui(self):
        self.doh_list.hide()
        return

    ### Method for Overview UI action.
    def on_overview_ui(self):
        self.total_cases.show()
        self.total_death.show()
        self.total_recovered.show()
        self.cases_textBrowser.show()
        self.death_textBrowser.show()
        self.recoverd_textBrowser.show()
        return

    ### Method for Charts UI action.
    def on_charts_ui(self):
        self.chartsView.show()
        self.updateChart_button.show()
        self.horizontalLayoutWidget.show()
        self.prevDate.show()
        self.currentDate.show()
        self.guide1.show()
        self.setup_chart()
        return

    ### Method for Location UI action.
    def on_location_ui(self):
        self.locationView.show()
        return

    ### Method for Patterns UI action.
    def on_patterns_ui(self):
        self.textBrowser_Current.show()
        self.textBrowser_Tomorrow.show()
        self.label_Current.show()
        self.label_Tomorrow.show()
        return

    ### Method for News UI action.
    def on_news_ui(self):
        self.doh_list.show()
        return

    ### Button action when overview is clicked.
    def on_overview_clicked(self):
        self.on_overview_ui()
        self.hide_charts_ui()
        self.hide_location_ui()
        self.hide_patterns_ui()
        self.hide_news_ui()
        return

### Button action when charts button is clicked.

    def on_charts_clicked(self):
        self.hide_overview_ui()
        self.on_charts_ui()
        self.hide_location_ui()
        self.hide_patterns_ui()
        self.hide_news_ui()
        return

    ### Button action when update button in charts ui is clicked.
    def on_update_chart_clicked(self):
        if self.layoutlim == 0:
            self.setup_chart()
        else:
            self.delete_canvas()
            self.update_chart()
        return

    ### Button action when location button is clicked.
    def on_location_clicked(self):
        self.hide_overview_ui()
        self.hide_charts_ui()
        self.on_location_ui()
        self.hide_patterns_ui()
        self.hide_news_ui()
        return

    ### Button action when patterns button is clicked.
    def on_patterns_clicked(self):
        self.hide_overview_ui()
        self.hide_charts_ui()
        self.hide_location_ui()
        self.on_patterns_ui()
        self.hide_news_ui()
        return

    ### Button action when news button is clicked.
    def on_news_clicked(self):
        self.hide_overview_ui()
        self.hide_charts_ui()
        self.hide_location_ui()
        self.hide_patterns_ui()
        self.on_news_ui()
        return

    ### Calculate the current data to predict future Cases.
    def patterns_calcu(self):
        gpd = getpastdate()
        self.textBrowser_Current.setText(str(gpd.get_past(0)))  #current
        self.textBrowser_Tomorrow.setText(str(gpd.patterns_expected()))
        return
class Main(QMainWindow, Ui_MainWindow):

    def __init__(self, ):
        super(Main, self).__init__()
        self.setupUi(self)

        self.showMaximized()
        self.ave = np.array([])         # empty array for average bore
        self.auto_flag = False          # autoscale flag
        self.spinBoxval = 0             # defualt 4D data_cube dimension
        self.spinBox.hide()             # hide option unless 4D
        self.colourmap = 'viridis'      # default colourmap
        self.interpMethod = 'nearest'   # default interp method
        self.cmapmin = None             # default colourbar range, i.e let matplotlib decide
        self.cmapmax = None
        self.hres = 1                   # default res, i.e jut voxel numbers on axis
        self.vres = 1
        self.Normx = None               # normalisation method. default set to None
        self.Normy = None
        self.Normz = None

        self.XView.setChecked(True)
        self.fig = Figure()
        self.ax1 = self.fig.add_subplot(111)
        self.X = datacube()
        self.AveBoreView = 'X'

        # change view of cube
        self.XView.toggled.connect(lambda: self.btnstate(self.XView))
        self.YView.toggled.connect(lambda: self.btnstate(self.YView))
        self.ZView.toggled.connect(lambda: self.btnstate(self.ZView))
        self.Bore.toggled.connect(lambda: self.btnstate(self.Bore))
        self.AverageBore.toggled.connect(
            lambda: self.btnstate(self.AverageBore))

        # update data when slider moved
        self.Scroll_Horz.valueChanged[int].connect(self.sliderval)
        self.Scroll_Vert.valueChanged[int].connect(self.sliderval)

        self.file_open(args)
        self.Open.triggered.connect(self.file_open)
        self.Save_Avg_Bore.triggered.connect(self.saveBore)
        self.Reset.triggered.connect(self.reset_plot)
        self.AutoScale.triggered.connect(self.Auto_Scale_plot)
        # self.Bore_View.triggered.connect(self.ViewBore)
        self.action_Save_Gif.triggered.connect(self.saveGif)
        self.action_Colour_Map.triggered.connect(self.changeColourMap)
        self.action_Interpolation_Method.triggered.connect(self.changeInterpolationMethod)
        self.action_Colour_Bar_Clip.triggered.connect(self.changeclipColourBarRange)
        self.action_Save_Image.triggered.connect(self.saveImage)
        self.action_Normalisation_Method.triggered.connect(self.changeNormMethod)
        self.action_Bore_Location.triggered.connect(self.setBoreLocation)

        self.spinBox.valueChanged.connect(self.changeSpinbox)

    def setBoreLocation(self, ):

        xloc, ok = QtWidgets.QInputDialog.getInt(
            self, 'Input location', 'Enter X location:')

        yloc, ok = QtWidgets.QInputDialog.getInt(
            self, 'Input location', 'Enter Y location:')

        self.Scroll_Horz.setValue(xloc)
        self.Scroll_Vert.setValue(yloc)

        if self.Bore.isChecked():
            if self.BoreView == 'X':
                self.im.set_ydata(self.X.data[:, xloc, yloc][::])
            elif self.BoreView == 'Y':
                self.im.set_ydata(self.X.data[xloc, :, yloc][::])
            elif self.BoreView == 'Z':
                self.im.set_ydata(self.X.data[yloc, xloc, :][::])

        # try and redraw
        try:
            self.im.axes.figure.canvas.draw()
            if self.auto_flag:
                self.im.autoscale()
        except AttributeError:
            pass

    def changeNormMethod(self, ):
        # func to change Normalisation method of matshow
        method = self.getNormDialog()
        if(method == 'Log'):
            self.Normx = colors.LogNorm(vmin=0.1,
                                        vmax=self.X.data[self.ind, :, :].max())
            self.Normy = colors.LogNorm(vmin=0.1,
                                        vmax=self.X.data[:, self.ind, :].max())
            self.Normz = colors.LogNorm(vmin=0.1,
                                        vmax=self.X.data[:, :, self.ind].max())
        elif(method == 'Symmetric Log'):
            self.Normx = colors.SymLogNorm(linthresh=1.,
                                           vmin=self.X.data[self.ind, :, :].min(),
                                           vmax=self.X.data[self.ind, :, :].max())
            self.Normy = colors.SymLogNorm(linthresh=1.,
                                           vmin=self.X.data[:, self.ind, :].min(),
                                           vmax=self.X.data[:, self.ind, :].max())
            self.Normz = colors.SymLogNorm(linthresh=1.,
                                           vmin=self.X.data[:, :, self.ind].max(),
                                           vmax=self.X.data[:, :, self.ind].max())
        elif(method == 'Linear'):
            self.Normx = None
            self.Normy = None
            self.Normz = None
        self.reset_plot(False)
        self.init_plot()

    def saveImage(self, ):
        # saves data and image of current view
        name = self.showGifDialog()
        if self.XView.isChecked():
            np.savetxt(name + '.dat', self.X.data[self.Scroll_Vert.value(), :, :],
                       delimiter=' ')
        elif self.YView.isChecked():
            np.savetxt(name + '.dat', self.X.data[:, self.Scroll_Vert.value(), :],
                       delimiter=' ')
        elif self.ZView.isChecked():
            np.savetxt(name + '.dat', self.X.data[:, :, self.Scroll_Vert.value()],
                       delimiter=' ')

        self.hres, self.vres = self.showextentDialog()
        # scale x, y ticks to actual scale based upon user definition
        # thanks https://stackoverflow.com/a/17816809/6106938
        # change so that it uses extent=[xmin, xmax, ymin, ymax]
        # set default as None
        # then change here. extent added to matshow(*args, extent=[...])
        ticks = ticker.FuncFormatter(lambda x, pos: '{0:g}'.format(x * self.hres))
        self.ax1.xaxis.set_major_formatter(ticks)
        ticks = ticker.FuncFormatter(lambda y, pos: '{0:g}'.format(y * self.vres))
        self.ax1.yaxis.set_major_formatter(ticks)
        self.fig.savefig(name + '.png')

    def changeColourMap(self, ):
        # change cmap
        self.colourmap = self.showColourmapsDialog()
        self.reset_plot(False)
        self.init_plot()

    def changeclipColourBarRange(self, ):
        # change vmin, vmax for cbar

        self.cmapmin, self.cmapmax = self.showclipColourBarDialog()

        self.reset_plot(False)
        self.init_plot()

    def changeInterpolationMethod(self, ):
        # change interpolation method for image
        self.interpMethod = str(self.showInterpolationDialog())
        self.reset_plot(False)
        self.init_plot()

    def saveGif(self):
        rang = self.showGifframesDialog()  # get range of frames
        step = self.showGifstepDialog()    # get number of images
        name = self.showGifDialog()        # name of file
        tight = self.showGifExtent()       # tight or not
        # loop over range and make images
        tmpplace = self.Scroll_Vert.value()
        if rang * step > tmpplace:
            rang = tmpplace
        for i in range(rang):
            self.Scroll_Horz.setValue(self.ind)
            self.Scroll_Vert.setValue(tmpplace - (i * step))
            self.sliderval()
            if tight:
                extent = self.ax1.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
                self.fig.savefig(str(i).zfill(3) + 'pic.png', bbox_inches=extent)
            else:
                self.fig.savefig(str(i).zfill(3) + 'pic.png')
        # use ffmpeg to create gif
        if tight:
            os.system("mogrify -trim *pic.png")
        os.system("ffmpeg -framerate 10 -pattern_type glob -i '*pic.png' -c:v libx264 -r 24 -pix_fmt yuv420p -vf 'pad=ceil(iw/2)*2:ceil(ih/2)*2' " + name + ".mp4")
        os.system('rm *pic.png')
        print('done')

    def changeSpinbox(self):
        # for 4d data cubes
        self.spinBoxval = int(self.spinBox.value())
        fd = open(self.name, 'rb')
        self.readslice(fd, self.ndim, np.float64, self.cubeorder)
        self.reset_plot()
        self.init_plot()

    def Auto_Scale_plot(self):
        # autoscale cbar on plot and reset clipping if any
        self.cmapmin = None
        self.cmapmax = None
        if not self.auto_flag:
            self.auto_flag = True
        else:
            self.auto_flag = False

    def sliderval(self):
        # move slider and update data
        if self.XView.isChecked():
            # fd = open(self.name, 'rb')
            self.X.readslice(self.Scroll_Horz.value())
            self.im.set_data(self.X.data[self.Scroll_Vert.value(), :, :])
            # self.Scroll_Horz.setValue(0)  # pin unsed slider
        elif self.YView.isChecked():
            self.X.readslice(self.Scroll_Horz.value())
            self.im.set_data(self.X.data[:, self.Scroll_Vert.value(), :])
            # self.Scroll_Horz.setValue(0)  # pin unsed slider
        elif self.ZView.isChecked():
            self.X.readslice(self.Scroll_Horz.value())
            self.im.set_data(self.X.data[:, :, self.Scroll_Vert.value()])
            # self.Scroll_Horz.setValue(0)  # pin unsed slider
        elif self.Bore.isChecked():
            if self.BoreView == 'X':
                self.im.set_ydata(self.X.data[:, self.Scroll_Horz.value(), self.Scroll_Vert.value()][::])
                if self.auto_flag:
                    self.ax1.relim()
                    self.ax1.autoscale_view(True, True, True)
            elif self.BoreView == 'Y':
                self.im.set_ydata(self.X.data[self.Scroll_Horz.value(), :, self.Scroll_Vert.value()][::])
                if self.auto_flag:
                    self.ax1.relim()
                    self.ax1.autoscale_view(True, True, True)
            elif self.BoreView == 'Z':
                self.im.set_ydata(self.X.data[self.Scroll_Vert.value(), self.Scroll_Horz.value(), :][::])
                if self.auto_flag:
                    self.ax1.relim()
                    self.ax1.autoscale_view(True, True, True)
        elif self.AverageBore.isChecked():
            self.Scroll_Horz.setValue(self.ind)
            self.Scroll_Vert.setValue(self.ind)

        # try and redraw
        try:
            self.im.axes.figure.canvas.draw()
            if self.auto_flag:
                self.im.autoscale()
        except AttributeError:
            pass

    def addmpl(self):
        # add plot to anvas
        self.rmmpl()
        self.canvas = FigureCanvas(self.fig)
        self.mplvl.addWidget(self.canvas)
        self.canvas.draw()
        self.toolbar = NavigationToolbar(self.canvas, self.mplwindow)
        self.mplvl.addWidget(self.toolbar)

    def rmmpl(self):
        # delete plot from canvas
        try:
            self.canvas.close()
            self.canvas.deleteLater()
            self.toolbar.close()
            self.toolbar.deleteLater()
            gc.collect()
        except:
            pass

    def saveBore(self,):
        # save bore as a list of points
        name = QtWidgets.QFileDialog.getSaveFileName(self, 'Save File')
        f = open(name, 'w')
        if len(self.ave) > 1:
            for i in range(len(self.ave)):
                f.write(str(self.ave[i]) + '\n')
            f.close()
        else:
            if self.BoreView == "X":
                tmp = self.X[:, self.Scroll_Horz.value(), self.Scroll_Vert.value()]
            elif self.BoreView == "Y":
                tmp = self.X[self.Scroll_Horz.value(), :, self.Scroll_Vert.value()]
            elif self.BoreView == "Z":
                tmp = self.X[self.Scroll_Horz.value(), self.Scroll_Vert.value(), :]

            for i in range(len(tmp)):
                f.write(str(tmp[i]) + '\n')

    def file_open(self, args):

        self.reset_plot()

        while True:
            try:
                # get file name
                if args.file is None:
                    self.X.name = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File')[0]
                else:
                    self.X.name = args.file

                # get precision of data cube
                self.X.dtype, self.X.cubeorder, item = self.getPrec(args)

                # get dimensions of data cube. can be guessed
                bool4d = False
                if self.X.cubeorder == 4:
                    bool4d = True
                self.X.ndim = self.getSize(args, item, bool4d)

                try:
                    fd = open(self.X.name, 'rb')
                except FileNotFoundError:
                    self.ErrorDialog("File not Found!")
                    self.X.name = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File')[0]

                self.X.readslice(0)
                self.init_plot()
                break
            except ValueError:
                size = os.path.getsize(self.X.name)
                if "Real*8" in item:
                    size /= 8
                elif "Real*4" in item:
                    size /= 4

                mssg = "Value of Ndim or precision is incorrect for this data cube.\n On disk size is: {:010d}.\n".format(int(size))

                val2 = self.X.is_perfect_n(size, 2.)
                val3 = self.X.is_perfect_n(size, 3.)

                if (val2 and val3) != 0:
                    mssg += " Try x=y={:04d}, z=1\n or x=y=z={:04d}.".format(int(val2), int(val3))
                elif val2 != 0:
                    mssg += "Try x=y={:04d}, z=1.".format(int(val2))
                elif val3 != 0:
                    mssg += "Try x=y=z={:04d}.".format(int(val3))
                self.ErrorDialog(mssg)

                args.ndim = None
                args.fpprec = None
            except UnboundLocalError:
                pass
                break

    def getSize(self, args, item, bool4d):
        if args.ndim is None and item:
            size = os.path.getsize(self.X.name)
            if "Real*8" in item:
                size /= 8
            elif "Real*4" in item:
                size /= 4
            if self.X.is_perfect_n(size, 3.) != 0:
                size = self.X.is_perfect_n(size, 3.)
                ndim = (size, size, size)
            else:
                ndim = self.showNdimDialog(bool4d)
        else:
            ndim = (args.ndim, args.ndim, args.ndim)

        return ndim

    def getPrec(self, args):
        # get precision of data cube
        item = None
        if args.fpprec is None:
            item = str(self.showDtDialog())
            if "Real*8" in item:
                dt = np.float64
            elif "Real*4" in item:
                dt = np.float32

            if "4 dim" in item:
                dim = 4
            elif "3 dim" in item:
                dim = 3
        else:
            if args.fpprec == 1:
                dt = np.float32
                dim = 4
            elif args.fpprec == 2:
                dt = np.float64
                dim = 4
            elif args.fpprec == 3:
                dt = np.float32
                dim = 3
            elif args.fpprec == 4:
                dt = np.float64
                dim = 3
        return dt, dim, item

    def btnstate(self, b):

        if b.text() == "X View":
            if b.isChecked() is True:
                self.reset_plot(False)
                self.Scroll_Vert.setMaximum(self.rows - 1)
                self.im = self.ax1.matshow(self.X.data[self.ind, :, :],
                                           vmin=self.cmapmin, vmax=self.cmapmax,
                                           cmap=str(self.colourmap), interpolation=self.interpMethod,
                                           norm=self.Normx)
                self.fig.colorbar(self.im)
                self.fig.set_tight_layout(True)
                self.ax1.set_aspect('auto')
                self.addmpl()

        if b.text() == "Y View":
            if b.isChecked() is True:
                self.reset_plot(False)
                self.Scroll_Vert.setMaximum(self.cols - 1)
                self.im = self.ax1.matshow(self.X.data[:, self.ind, :],
                                           vmin=self.cmapmin, vmax=self.cmapmax,
                                           cmap=str(self.colourmap), interpolation=self.interpMethod,
                                           norm=self.Normy)
                self.fig.colorbar(self.im)
                self.fig.set_tight_layout(True)
                self.ax1.set_aspect('auto')
                self.addmpl()

        if b.text() == "Z View":
            if b.isChecked() is True:
                self.reset_plot(False)
                self.Scroll_Vert.setMaximum(self.slices - 1)
                self.im = self.ax1.matshow(self.X.data[:, :, self.ind],
                                           vmin=self.cmapmin, vmax=self.cmapmax,
                                           cmap=str(self.colourmap), interpolation=self.interpMethod,
                                           norm=self.Normz)
                try:
                    self.fig.colorbar(self.im)
                except ZeroDivisionError:
                    self.ErrorDialog("Divison by zero, try another range")
                    self.Normz = None
                    self.Normy = None
                    self.Normz = None
                    self.cmapmin = None
                    self.cmapmax = None
                    self.btnstate(b)
                self.fig.set_tight_layout(True)
                self.ax1.set_aspect('auto')
                self.addmpl()

        if b.text() == "Draw Bore":
            if b.isChecked() is True:
                self.ViewBore()
                self.reset_plot(False)
                if self.BoreView == 'X':
                    self.im, = self.ax1.plot(self.X.data[:, self.ind, self.ind])
                elif self.BoreView == 'Y':
                    self.im, = self.ax1.plot(self.X.data[self.ind, :, self.ind])
                elif self.BoreView == 'Z':
                    self.im, = self.ax1.plot(self.X.data[self.ind, self.ind, :])
                self.fig.set_tight_layout(True)
                self.addmpl()

        if b.text() == "Avg. Bore":
            if b.isChecked() is True:
                self.AveBoreChecked()

    def ViewBore(self):
        self.BoreView = self.showBoreViewDialog()
        if self.BoreView == 'X':
            self.view = (1, 2)
        elif self.BoreView == 'Y':
            self.view = (0, 2)
        elif self.BoreView == 'Z':
            self.view = (0, 1)

    def AveBoreChecked(self):

        self.ViewBore()

        self.reset_plot(False)
        if len(self.ave) == 0:
            self.ave = np.array([])
            self.ave = np.sum(self.X.data, self.view)
            self.ave /= (len(self.X.data[self.view[0]]) * len(self.X.data[self.view[1]]))

        self.im = self.ax1.plot(self.ave[::])
        self.fig.set_tight_layout(True)
        self.addmpl()

    def reset_plot(self, *args):
        self.ave = np.array([])

        self.fig.clf()
        self.ax1.clear()
        gc.collect()  # fixes most of memory leak

        self.fig = Figure()
        self.ax1 = self.fig.add_subplot(111)
        self.rmmpl()

    def init_plot(self, ):

        self.rmmpl()

        if self.X.cubeorder == 4:
            self.rows, self.cols, self.slices, self.depth = self.X.ndim
        else:
            self.rows, self.cols, self.slices = self.X.ndim
            self.depth = 0
        self.ind = 0  # int(rows / 2)
        if self.XView.isChecked():
            view = self.XView
            self.Scroll_Vert.setMaximum(self.rows)
            self.Scroll_Horz.setMaximum(self.depth)
        elif self.YView.isChecked():
            view = self.YView
            self.Scroll_Vert.setMaximum(self.cols)
            self.Scroll_Horz.setMaximum(self.depth)
        elif self.ZView.isChecked():
            view = self.ZView
            self.Scroll_Vert.setMaximum(self.slices)
            self.Scroll_Horz.setMaximum(self.cols)
        elif self.AverageBore.isChecked():
            view = self.AverageBore
            self.Scroll_Vert.setMaximum(self.rows)
        elif self.Bore_View.isChecked():
            view = self.ViewBore
            self.Scroll_Vert.setMaximum(self.cols)
            self.Scroll_Horz.setMaximum(self.rows)
        self.btnstate(view)
        self.Scroll_Horz.setValue(self.ind)
        self.Scroll_Vert.setValue(self.ind)

    def showGifframesDialog(self, ):
        text, ok = QtWidgets.QInputDialog.getInt(
            self, '# of frames', 'Enter # of frames:')
        if ok:
            return(text)

    def showGifstepDialog(self, ):
        text, ok = QtWidgets.QInputDialog.getInt(
            self, 'Step size', 'Enter value of step:')
        if ok:
            return(text)

    def showGifExtent(self, ):
        items = ("Colour Bar", "No Colour Bar")

        text, ok = QtWidgets.QInputDialog.getItem(
            self, "Colour Bar on GIF?", " ", items, 0, False)

        if ok and text:
            if items == "Colour Bar":
                text = False
            else:
                text = True
            return text

    def showNdimDialog(self, bool4d):
        text1, ok1 = QtWidgets.QInputDialog.getInt(
            self, 'Input Ndim', 'Enter X Ndim:')
        if ok1:
            text2, ok2 = QtWidgets.QInputDialog.getInt(
                self, 'Input Ndim', 'Enter Y Ndim:')
            if ok2:
                text3, ok3 = QtWidgets.QInputDialog.getInt(
                    self, 'Input Ndim', 'Enter Z Ndim:')
                if ok3 and bool4d:
                    text4, ok4 = QtWidgets.QInputDialog.getInt(
                        self, 'Input Ndim', 'Enter T Ndim:')
                    return (text1, text2, text3, text4)
                else:
                    return (text1, text2, text3)

    def showDtDialog(self, ):
        items = ("4 dim Real*4", "4 dim Real*8",
                 "3 dim Real*4", "3 dim Real*8")

        item, ok = QtWidgets.QInputDialog.getItem(self, "Select Fortran Precision",
                                                  "Precisions", items, 0, False)

        if ok and item:
            return item

    def showBoreViewDialog(self, ):
        items = ("X", "Y", "Z")
        item, ok = QtWidgets.QInputDialog.getItem(self, "Select Average Bore Direction",
                                                  "Views", items, 0, False)
        if ok and item:
            return item

    def showGifDialog(self, ):
        text, ok = QtWidgets.QInputDialog.getText(
            self, 'Filename Dialog', 'Enter filename:')
        if ok:
            return str(text)

    def showextentDialog(self, ):
        hres, ok = QtWidgets.QInputDialog.getDouble(
            self, 'Data Extent', 'Enter horizontal resolution:', 0, -100, 100, 9,)
        if ok:
            vres, ok = QtWidgets.QInputDialog.getDouble(
                self, 'Data Extent', 'Enter vertical resolution:', 0, -100, 100, 9,)
            if ok:
                return (hres, vres)

    def getNormDialog(self, ):
        items = ("Log", "Linear", "Symmetric Log")

        item, ok = QtWidgets.QInputDialog.getItem(self, "Select cbar normalisation method",
                                                  "Method:", items, 0, False)
        if ok and item:
            return item

    def showColourmapsDialog(self, ):
        items = ('viridis', 'inferno', 'plasma', 'magma', 'Blues', 'BuGn',
                 'BuPu', 'GnBu', 'Greens', 'Greys', 'Oranges', 'OrRd', 'PuBu',
                 'PuBuGn', 'PuRd', 'Purples', 'RdPu', 'Reds', 'YlGn', 'YlGnBu',
                 'YlOrBr', 'YlOrRd', 'afmhot', 'autumn', 'bone', 'cool',
                 'copper', 'gist_heat', 'gray', 'hot', 'pink', 'spring',
                 'summer', 'winter', 'BrBG', 'bwr', 'coolwarm', 'PiYG', 'PRGn',
                 'PuOr', 'RdBu', 'RdGy', 'RdYlBu', 'RdYlGn', 'Spectral',
                 'seismic', 'Accent', 'Dark2', 'Paired', 'Pastel1', 'Pastel2',
                 'Set1', 'Set2', 'Set3', 'Vega10', 'Vega20', 'Vega20b',
                 'Vega20c', 'gist_earth', 'terrain', 'ocean', 'gist_stern',
                 'brg', 'CMRmap', 'cubehelix', 'gnuplot', 'gnuplot2',
                 'gist_ncar', 'nipy_spectral', 'jet', 'rainbow', 'gist_rainbow',
                 'hsv', 'flag', 'prism')
        item, ok = QtWidgets.QInputDialog.getItem(self, "Select Colour Map",
                                                  "Cmaps", items, 0, False)
        if ok and item:
            return item

    def showInterpolationDialog(self, ):
        items = ('none', 'nearest', 'bilinear', 'bicubic', 'spline16',
                 'spline36', 'hanning', 'hamming', 'hermite', 'kaiser',
                 'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell',
                 'sinc', 'lanczos')
        item, ok = QtWidgets.QInputDialog.getItem(self, "Select Interpolation Method",
                                                  "Methods", items, 0, False)
        if ok and item:
            return item

    def showclipColourBarDialog(self, ):
        text1, ok1 = QtWidgets.QInputDialog.getDouble(
            self, 'Input cbar min', 'Enter min:', 0., np.finfo("d").min, np.finfo("d").max, 10)
        if ok1:
            text2, ok2 = QtWidgets.QInputDialog.getDouble(
                self, 'Input cbar max', 'Enter max:', 0., np.finfo("d").min, np.finfo("d").max, 10)
            if ok2:
                return (float(text1), float(text2))

    def ErrorDialog(self, ErrMsg):
        QtWidgets.QMessageBox.warning(self, "Error", ErrMsg)