Пример #1
1
class matplotlibWidget(QWidget):
    def __init__(self, parent = None):
        QWidget.__init__(self, parent)
        self.canvas = MplCanvas()
        self.gl = QGridLayout()
        alignment = Qt.Alignment()
        self.gl.addWidget(self.canvas,0,0,-1,-1,alignment)

        self.toolbar = NavigationToolbar(self.canvas, self)
        self.toolbar.hide()

        # Just some button 

        self.button1 = QPushButton('Zoom')
        self.button1.clicked.connect(self.zoom)

        self.button2 = QPushButton('Pan')
        self.button2.clicked.connect(self.pan)

        self.button3 = QPushButton('Home')
        self.button3.clicked.connect(self.home)

        self.gl.addWidget(self.toolbar,1,0,alignment)
        self.gl.addWidget(self.button1,1,1,alignment)
        self.gl.addWidget(self.button2,1,2,alignment)
        self.gl.addWidget(self.button3,1,3,alignment)

        self.setLayout(self.gl)

    def home(self):
        self.toolbar.home()
    def zoom(self):
        self.toolbar.zoom()
    def pan(self):
        self.toolbar.pan()
Пример #2
0
class Window(QtWidgets.QDialog):
    def __init__(self, data, parent=None):
        super(Window, self).__init__(parent)

        self.data = data
        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)

        self.toolbar = NavigationToolbar(self.canvas, self)
        self.toolbar.hide()

        self.button = QtWidgets.QPushButton('Plot')
        self.button.clicked.connect(self.plot)

        self.button1 = QtWidgets.QPushButton('Zoom')
        self.button1.clicked.connect(self.zoom)

        self.button2 = QtWidgets.QPushButton('Pan')
        self.button2.clicked.connect(self.pan)

        self.button3 = QtWidgets.QPushButton('Home')
        self.button3.clicked.connect(self.home)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)
        layout.addWidget(self.button)
        layout.addWidget(self.button1)
        layout.addWidget(self.button2)
        layout.addWidget(self.button3)

        self.setLayout(layout)

    def home(self):
        self.toolbar.home()

    def zoom(self):
        self.toolbar.zoom()

    def pan(self):
        self.toolbar.pan()

    def plot(self):
        # PlotCanvas(self.data)

        data = self.data
        ax = self.figure.add_subplot(111)
        ax.hold(False)
        ax.set_title("Basic Distribution")

        ax.plot(data, 'r*-')
        self.canvas.draw()
Пример #3
0
class Window(QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)

        self.toolbar = NavigationToolbar(self.canvas, self)
        self.toolbar.hide()

        # Just some button
        self.button = QPushButton('Plot')
        self.button.clicked.connect(self.plot)

        self.button1 = QPushButton('Zoom')
        self.button1.clicked.connect(self.zoom)

        self.button2 = QPushButton('Pan')
        self.button2.clicked.connect(self.pan)

        self.button3 = QPushButton('Home')
        self.button3.clicked.connect(self.home)

        # set the layout
        layout = QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)
        layout.addWidget(self.button)
        layout.addWidget(self.button1)
        layout.addWidget(self.button2)
        layout.addWidget(self.button3)
        self.setLayout(layout)

    def home(self):
        self.toolbar.home()

    def zoom(self):
        self.toolbar.zoom()

    def pan(self):
        self.toolbar.pan()

    def plot(self):
        ''' plot some random stuff '''
        data = [random.random() for i in range(25)]
        ax = self.figure.add_subplot(111)
        ax.hold(False)
        ax.plot(data, '*-')
        self.canvas.draw()
Пример #4
0
 def home(self):
     # always unzoom completely
     if hasattr(self, '_views'):
         self._views.clear()
     if hasattr(self, '_positions'):
         self._positions.clear()
     self.canvas.figure.gca().autoscale()
     self.canvas.draw()
     return NavigationToolbar2QT.home(self)
Пример #5
0
class PulsedNMR(QMainWindow, Ui_PulsedNMR):
  rates = {0:25.0e3, 1:50.0e3, 2:250.0e3, 3:500.0e3, 4:2500.0e3}
  def __init__(self):
    super(PulsedNMR, self).__init__()
    self.setupUi(self)
    self.rateValue.addItems(['25', '50', '250', '500', '2500'])
    # IP address validator
    rx = QRegExp('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$')
    self.addrValue.setValidator(QRegExpValidator(rx, self.addrValue))
    # state variable
    self.idle = True
    # number of samples to show on the plot
    self.size = 50000
    # buffer and offset for the incoming samples
    self.buffer = bytearray(8 * self.size)
    self.offset = 0
    # create figure
    figure = Figure()
    figure.set_facecolor('none')
    self.axes = figure.add_subplot(111)
    self.canvas = FigureCanvas(figure)
    self.plotLayout.addWidget(self.canvas)
    # create navigation toolbar
    self.toolbar = NavigationToolbar(self.canvas, self.plotWidget, False)
    # remove subplots action
    actions = self.toolbar.actions()
    self.toolbar.removeAction(actions[7])
    self.plotLayout.addWidget(self.toolbar)
    # create TCP socket
    self.socket = QTcpSocket(self)
    self.socket.connected.connect(self.connected)
    self.socket.readyRead.connect(self.read_data)
    self.socket.error.connect(self.display_error)
    # connect signals from buttons and boxes
    self.startButton.clicked.connect(self.start)
    self.freqValue.valueChanged.connect(self.set_freq)
    self.awidthValue.valueChanged.connect(self.set_awidth)
    self.deltaValue.valueChanged.connect(self.set_delta)
    self.rateValue.currentIndexChanged.connect(self.set_rate)
    # set rate
    self.rateValue.setCurrentIndex(2)
    # create timer for the repetitions
    self.timer = QTimer(self)
    self.timer.timeout.connect(self.fire)

  def start(self):
    if self.idle:
      self.startButton.setEnabled(False)
      self.socket.connectToHost(self.addrValue.text(), 1001)
    else:
      self.idle = True
      self.timer.stop()
      self.socket.close()
      self.offset = 0
      self.startButton.setText('Start')
      self.startButton.setEnabled(True)

  def connected(self):
    self.idle = False
    self.set_freq(self.freqValue.value())
    self.set_rate(self.rateValue.currentIndex())
    self.set_awidth(self.awidthValue.value())
    self.fire()
    self.timer.start(self.deltaValue.value())
    self.startButton.setText('Stop')
    self.startButton.setEnabled(True)

  def read_data(self):
    size = self.socket.bytesAvailable()
    if self.offset + size < 8 * self.size:
      self.buffer[self.offset:self.offset + size] = self.socket.read(size)
      self.offset += size
    else:
      self.buffer[self.offset:8 * self.size] = self.socket.read(8 * self.size - self.offset)
      self.offset = 0
      # plot the signal envelope
      data = np.frombuffer(self.buffer, np.complex64)
      self.curve.set_ydata(np.abs(data))
      self.canvas.draw()

  def display_error(self, socketError):
    if socketError == QAbstractSocket.RemoteHostClosedError:
      pass
    else:
      QMessageBox.information(self, 'PulsedNMR', 'Error: %s.' % self.socket.errorString())
    self.startButton.setText('Start')
    self.startButton.setEnabled(True)

  def set_freq(self, value):
    if self.idle: return
    self.socket.write(struct.pack('<I', 0<<28 | int(1.0e6 * value)))

  def set_rate(self, index):
    # time axis
    rate = float(PulsedNMR.rates[index])
    time = np.linspace(0.0, (self.size - 1) * 1000.0 / rate, self.size)
    # reset toolbar
    self.toolbar.home()
    self.toolbar._views.clear()
    self.toolbar._positions.clear()
    # reset plot
    self.axes.clear()
    self.axes.grid()
    # plot zeros and get store the returned Line2D object
    self.curve, = self.axes.plot(time, np.zeros(self.size))
    x1, x2, y1, y2 = self.axes.axis()
    # set y axis limits
    self.axes.axis((x1, x2, -0.1, 0.4))
    self.axes.set_xlabel('time, ms')
    self.canvas.draw()
    # set repetition time
    minimum = self.size / rate * 2000.0
    if minimum < 100.0: minimum = 100.0
    self.deltaValue.setMinimum(minimum)
    self.deltaValue.setValue(minimum)
    if self.idle: return
    self.socket.write(struct.pack('<I', 1<<28 | index))

  def set_awidth(self, value):
    if self.idle: return
    self.socket.write(struct.pack('<I', 2<<28 | int(1.0e1 * value)))

  def set_delta(self, value):
    if self.idle: return
    self.timer.stop()
    self.timer.start(value)

  def fire(self):
    if self.idle: return
    self.socket.write(struct.pack('<I', 3<<28))
Пример #6
0
    def home(self, *args):
        # call super's home() method
        NavigationToolbar2QT.home(self, args)

        # send a signal to parent class for further operation
        self.home_button_pressed.emit()
Пример #7
0
class PulsedNMR(QMainWindow, Ui_PulsedNMR):
  rates = {0:25.0e3, 1:50.0e3, 2:125.0e3, 3:250.0e3, 4:500.0e3, 5:1250.0e3}
  def __init__(self):
    super(PulsedNMR, self).__init__()
    self.setupUi(self)
    self.rateValue.addItems(['25', '50', '125', '250', '500', '1250'])
    # IP address validator
    rx = QRegExp('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])|rp-[0-9A-Fa-f]{6}\.local$')
    self.addrValue.setValidator(QRegExpValidator(rx, self.addrValue))
    # state variable
    self.idle = True
    # number of samples to show on the plot
    self.size = 50000
    # buffer and offset for the incoming samples
    self.buffer = bytearray(16 * self.size)
    self.offset = 0
    self.data = np.frombuffer(self.buffer, np.int32)
    # create figure
    figure = Figure()
    figure.set_facecolor('none')
    self.axes = figure.add_subplot(111)
    self.canvas = FigureCanvas(figure)
    self.plotLayout.addWidget(self.canvas)
    # create navigation toolbar
    self.toolbar = NavigationToolbar(self.canvas, self.plotWidget, False)
    # remove subplots action
    actions = self.toolbar.actions()
    if int(matplotlib.__version__[0]) < 2:
      self.toolbar.removeAction(actions[7])
    else:
      self.toolbar.removeAction(actions[6])
    self.plotLayout.addWidget(self.toolbar)
    # create TCP socket
    self.socket = QTcpSocket(self)
    self.socket.connected.connect(self.connected)
    self.socket.readyRead.connect(self.read_data)
    self.socket.error.connect(self.display_error)
    # connect signals from buttons and boxes
    self.startButton.clicked.connect(self.start)
    self.freqValue.valueChanged.connect(self.set_freq)
    self.deltaValue.valueChanged.connect(self.set_delta)
    self.rateValue.currentIndexChanged.connect(self.set_rate)
    # set rate
    self.rateValue.setCurrentIndex(3)
    # create timer for the repetitions
    self.startTimer = QTimer(self)
    self.startTimer.timeout.connect(self.timeout)
    self.timer = QTimer(self)
    self.timer.timeout.connect(self.start_sequence)

  def start(self):
    if self.idle:
      self.startButton.setEnabled(False)
      self.socket.connectToHost(self.addrValue.text(), 1001)
      self.startTimer.start(5000)
    else:
      self.stop()

  def stop(self):
    self.idle = True
    self.timer.stop()
    self.socket.abort()
    self.offset = 0
    self.startButton.setText('Start')
    self.startButton.setEnabled(True)

  def timeout(self):
    self.display_error('timeout')

  def connected(self):
    self.startTimer.stop()
    self.idle = False
    self.set_freq(self.freqValue.value())
    self.set_rate(self.rateValue.currentIndex())
    self.start_sequence()
    self.timer.start(self.deltaValue.value())
    self.startButton.setText('Stop')
    self.startButton.setEnabled(True)

  def read_data(self):
    size = self.socket.bytesAvailable()
    if self.offset + size < 16 * self.size:
      self.buffer[self.offset:self.offset + size] = self.socket.read(size)
      self.offset += size
    else:
      self.buffer[self.offset:16 * self.size] = self.socket.read(16 * self.size - self.offset)
      self.offset = 0
      # plot the signal envelope
      self.curve.set_ydata(np.abs(self.data.astype(np.float32).view(np.complex64)[0::2] / (1 << 30)))
      self.canvas.draw()

  def display_error(self, socketError):
    self.startTimer.stop()
    if socketError == 'timeout':
      QMessageBox.information(self, 'PulsedNMR', 'Error: connection timeout.')
    else:
      QMessageBox.information(self, 'PulsedNMR', 'Error: %s.' % self.socket.errorString())
    self.stop()

  def set_freq(self, value):
    if self.idle: return
    self.socket.write(struct.pack('<Q', 0<<60 | int(1.0e6 * value)))
    self.socket.write(struct.pack('<Q', 1<<60 | int(1.0e6 * value)))

  def set_rate(self, index):
    # time axis
    rate = float(PulsedNMR.rates[index])
    time = np.linspace(0.0, (self.size - 1) * 1000.0 / rate, self.size)
    # reset toolbar
    self.toolbar.home()
    self.toolbar.update()
    # reset plot
    self.axes.clear()
    self.axes.grid()
    # plot zeros and get store the returned Line2D object
    self.curve, = self.axes.plot(time, np.zeros(self.size))
    x1, x2, y1, y2 = self.axes.axis()
    # set y axis limits
    self.axes.axis((x1, x2, -0.1, 1.1))
    self.axes.set_xlabel('time, ms')
    self.canvas.draw()
    if self.idle: return
    self.socket.write(struct.pack('<Q', 2<<60 | int(125.0e6 / rate / 2)))

  def set_delta(self, value):
    if self.idle: return
    self.timer.stop()
    self.timer.start(value)

  def clear_pulses(self):
    if self.idle: return
    self.socket.write(struct.pack('<Q', 7<<60))

  def add_delay(self, width):
    if self.idle: return
    self.socket.write(struct.pack('<Q', 8<<60 | int(width - 4)))

  def add_pulse(self, level, phase, width):
    if self.idle: return
    self.socket.write(struct.pack('<Q', 8<<60 | int(width)))
    self.socket.write(struct.pack('<Q', 9<<60 | int(phase << 16 | level)))

  def start_sequence(self):
    if self.idle: return
    awidth = 125 * self.awidthValue.value()
    bwidth = 125 * self.bwidthValue.value()
    delay = 125 * self.delayValue.value()
    size = self.size
    self.clear_pulses()
    self.add_pulse(32766, 0, awidth)
    self.add_delay(delay)
    self.add_pulse(32766, 0, bwidth)
    self.socket.write(struct.pack('<Q', 10<<60 | int(size)))
Пример #8
0
class spectralPattern_window(QDialog):
    def __init__(self,pxx,frequencies,data,Fs):         
        QDialog.__init__(self);
        loadUi('graph_spectral.ui',self);
        self.setWindowIcon(QtGui.QIcon("logo.png"))
        self.label_title.setText('Eliminación de artefactos por espectro de potencia')
        self.label_maxValue.setText('Valor máximo [potencia]')
        
        self.data=data
        self.Fs=Fs
        self.channels,self.points=shape(self.data)
        self.epochs(self.data, self.channels, self.points)
        self.pxx=pxx
        self.frequencies=frequencies
        
        
            
        
        self.button_zoom.clicked.connect(self.zoom)
        self.button_pan.clicked.connect(self.pan)
        self.button_home.clicked.connect(self.home)
        self.button_apply.clicked.connect(self.implementation)
        self.button_cancel.clicked.connect(self.cancelar)
        self.figure = Figure(figsize=(5,4), dpi=100)
        self.canvas = FigureCanvas(self.figure)
        self.axes=self.figure.add_subplot(111)
        self.toolbar=NavigationToolbar(self.canvas,self)
        self.toolbar.hide()
         
        layout=QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)
        self.field_graph.setLayout(layout)
        self.axes.clear()
        self.canvas.draw()
        self.plot()
        
    def cancelar(self):
        spectralPattern_window.close(self);
        
    def home(self):
        self.toolbar.home()
    def zoom(self):
        self.toolbar.zoom()
    def pan(self):
        self.toolbar.pan()
         
    def plot(self):
        legends=['Ch 1','Ch 2','Ch 3','Ch 4','Ch 5','Ch 6','Ch 7','Ch 8']
        r=[]
        
        for c in range(shape(self.pxx)[0]):
            r.append(c*35)
            self.axes.plot(self.frequencies[c,::],sqrt(self.pxx[c,::])+c*35,linewidth=0.5)
        self.axes.set_yticklabels(legends)
        self.axes.set_yticks(r)
        self.axes.grid(True)
        self.axes.set_xlim([0,40])
        self.axes.set_xlabel('Frecuency [Hz]')
        self.axes.set_ylabel('Power density [V^2/Hz]')
        self.axes.set_title('Periodograma de Welch') 
        
    def epochs(self,data,channels,points):
      
        self.filtered_signal=data
        
        self.size_epoch=self.Fs*2
        self.num_epoch=points/self.size_epoch
        delete=points%self.size_epoch
          
        self.filtered_signal=self.filtered_signal[::,0:(points-delete)]
        self.epochs_file=reshape(self.filtered_signal,(channels,int(self.size_epoch),int((points-delete)/self.size_epoch)),order='F')
        return(self.epochs_file)
#         
    def implementation(self):
        max_value=float(self.field_maxValue.text())
        self.myepochs=self.epochs(self.data, self.channels, self.points)
        x,y=spectral_pattern.spectral(self.myepochs, max_value,self.Fs)
        newSignal=reshape(x,(shape(x)[0],shape(x)[1]*shape(x)[2]),order='F')
        self.graph_method = window_graph(self.data, self.Fs,3,newSignal,y,shape(self.myepochs)[2]);
        self.graph_method.show();
Пример #9
0
class TimeSeries(QWidget):
        def __init__(self, label, parent = None):
            super(TimeSeries, self).__init__(parent)

            self.label = label

            self.init()
            self.implementGrid()

            self.new_series = []
            self.new_series_labels = []

        def init(self):
            # FigureCanvas to show the mesh in
            self.figure = plt.figure()
            self.figure.set_facecolor((45/255, 45/255, 45/255))
            self.canvas = FigureCanvas(self.figure)
            self.canvas.setFixedSize(750,276)

            self.figure.subplots_adjust(left = 0.1, right = 0.94, bottom = 0.1, top = 0.9)
            self.ax = self.figure.add_subplot(111)
            self.ax.set_xlim(0,1.25)
            self.ax.set_facecolor((45/255, 45/255, 45/255))

            broken_white = (150/255, 150/255, 150/255)
            self.ax.grid('on', color = broken_white)
            self.ax.spines['bottom'].set_color(broken_white)
            self.ax.spines['top'].set_color(broken_white)
            self.ax.spines['right'].set_color(broken_white)
            self.ax.spines['left'].set_color(broken_white)
            self.ax.tick_params(axis='x', colors=broken_white, labelsize = 7)
            self.ax.tick_params(axis='y', colors=broken_white, labelsize = 7)
            self.ax.xaxis.label.set_color(broken_white)
            self.ax.yaxis.label.set_color(broken_white)

            self.ax.set_ylabel(self.label, fontweight = 'bold', fontsize = 9)

            self.Export = QPushButton()
            self.Export.setToolTip('Export graph as PNG')
            im = QIcon('support_files/export.png')
            self.Export.setIcon(im)
            self.Export.setDisabled(True)
            self.Export.clicked.connect(self.exportGraph)
            self.Export.setStyleSheet("""
            QPushButton {
                border-width: 25px solid white;
                border-radius: 0px;
                color: rgb(180,180,180);
                background-color: rgb(55, 55, 60, 0);
                }
            QPushButton:pressed {
                color: rgb(100,100,100,150);
                background-color: rgb(25, 25, 25, 150);
                }
            """)

            self.AddExtSeries = QPushButton()
            self.AddExtSeries.setToolTip('Add a series from a npy file')
            im = QIcon('support_files/add.png')
            self.AddExtSeries.setIcon(im)
            self.AddExtSeries.setDisabled(True)
            self.AddExtSeries.clicked.connect(self.addExtraSeries)
            self.AddExtSeries.setStyleSheet("""
            QPushButton {
                border-width: 25px solid white;
                border-radius: 0px;
                color: rgb(180,180,180);
                background-color: rgb(55, 55, 60, 0);
                }
            QPushButton:pressed {
                color: rgb(100,100,100,150);
                background-color: rgb(25, 25, 25, 150);
                }
            """)

            self.SaveNPY = QPushButton()
            self.SaveNPY.setToolTip('Save the series in a numpy array file (.npy)')
            im = QIcon('support_files/save_npy.png')
            self.SaveNPY.setIcon(im)
            self.SaveNPY.setDisabled(True)
            self.SaveNPY.clicked.connect(self.saveNPY)
            self.SaveNPY.setStyleSheet("""
            QPushButton {
                border-width: 25px solid white;
                border-radius: 0px;
                color: rgb(180,180,180);
                background-color: rgb(55, 55, 60, 0);
                }
            QPushButton:pressed {
                color: rgb(100,100,100,150);
                background-color: rgb(25, 25, 25, 150);
                }
            """)

            # buttons to zoom and pan
            self.zoombut = QPushButton()
            self.zoombut.setCheckable(True)
            self.zoombut.setEnabled(False)
            im = QIcon('support_files/zoom_trans.png')
            self.zoombut.setIcon(im)
            self.zoombut.setDisabled(True)
            self.zoombut.clicked.connect(self.zoom)
            self.zoombut.setStyleSheet("""
            QPushButton {
                border-width: 25px solid white;
                border-radius: 0px;
                color: rgb(180,180,180);
                background-color: rgb(55, 55, 60, 0);
                }
            QPushButton:checked {
                color: rgb(100,100,100,150);
                background-color: rgb(255, 128, 0);
                }
            """)

            self.homebut = QPushButton()
            self.homebut.setEnabled(False)
            im = QIcon('support_files/home_trans.png')
            self.homebut.setIcon(im)
            self.homebut.setDisabled(True)
            self.homebut.clicked.connect(self.home)
            self.homebut.setStyleSheet("""
            QPushButton {
                border-width: 25px solid white;
                border-radius: 0px;
                color: rgb(180,180,180,50);
                background-color: rgb(25, 25, 60, 0);
                }
            QPushButton:pressed {
                color: rgb(100,100,100,150);
                background-color: rgb(255, 128, 0);
                }
            """)

            self.toolbar = NavigationToolbar(self.canvas, self)
            self.toolbar.hide()

        def implementGrid(self):
            grid = QGridLayout()
            grid.addWidget(self.canvas,0,0)

            box1 = QVBoxLayout()
            box1.addSpacing(30)
            box1.addWidget(self.Export)
            box1.addWidget(self.AddExtSeries)
            box1.addWidget(self.SaveNPY)
            box1.addStretch()
            box1.addWidget(self.zoombut)
            box1.addWidget(self.homebut)
            box1.addWidget(QLabel())

            box2 = QHBoxLayout()
            box2.addStretch()
            box2.addLayout(box1)
            box2.addSpacing(15)
            grid.addLayout(box2,0,0)

            self.setLayout(grid)

        def plotSeries(self, T, var, t0, t1, x, y):

            self.Export.setEnabled(True)
            self.AddExtSeries.setEnabled(True)
            self.SaveNPY.setEnabled(True)
            self.zoombut.setEnabled(True)
            self.homebut.setEnabled(True)
            self.new_series = []
            self.new_series_labels = []

            self.x, self.y = x, y
            self.T = T
            self.var = var
            self.t0 = t0
            self.t1 = t1

            mask = (T>t0)*(T<t1)
            self.mask = mask
            self.varmin = np.min(var[mask])
            self.varmax = np.max(var[mask])
            self.varrange = self.varmax - self.varmin

            self.ax.set_xlim(t0,t1)

            self.ax.clear()
            self.ax.grid('on')
            self.ax.plot(T, var,'.-', color = (1, 128/255, 0), label = 'active output')
            self.ax.set_ylim(max(-999,self.varmin - 0.1*self.varrange), min(999,self.varmax + 0.1*self.varrange))
            self.ax.set_ylabel(self.label, fontweight = 'bold', fontsize = 9)
            self.canvas.draw()

        def exportGraph(self):
            lab = 'x: %d, y: %d' % (self.x, self.y)
            fn, _ = QFileDialog.getSaveFileName(self,"QFileDialog.getSaveFileName()","","All Files (*);;PNG Files (*.png)", options=QFileDialog.Options())

            if len(fn) > 0:
                f, a = plt.subplots(figsize = (15,4))
                f.subplots_adjust(left = 0.1, right = 0.94, bottom = 0.1, top = 0.9)
                a.plot(self.T, self.var,'.-', color = (1, 128/255, 0), label = lab)
                a.grid('on')
                a.set_ylabel(self.label, fontweight = 'bold', fontsize = 11)
                a.set_xlim(self.t0,self.t1)
                a.set_ylim(max(-999,self.varmin - 0.1*self.varrange), min(999,self.varmax + 0.1*self.varrange))

                for i in range(len(self.new_series)):
                    series = self.new_series[i]
                    lab = self.new_series_labels[i]
                    T = np.array(series[:,0], dtype = 'datetime64')
                    V = series[:,1]
                    a.plot(T, V, '.-', label = lab)

                a.set_ylim(max(-999,self.varmin - 0.1*self.varrange), min(999,self.varmax + 0.1*self.varrange))
                a.legend(loc = 1)
                f.savefig(fn)
                f.clear()

        def saveNPY(self):
            fn, _ = QFileDialog.getSaveFileName(self,"QFileDialog.getSaveFileName()","","All Files (*);;Numpy Files (*.npy)", options=QFileDialog.Options())

            if len(fn) > 0:
                if fn[-4:] != '.npy': fn + '.npy'
                T = self.T - np.timedelta64(3600,'s')
                var = self.var
                arr = np.empty((T.shape[0], 2))
                arr[:,0] = T
                arr[:,1] = var

                np.save(fn, arr)

        def addExtraSeries(self):
            options = QFileDialog.Options()
            fn, _ = QFileDialog.getOpenFileName(self,"QFileDialog.getOpenFileName()", "","Numpy files (*.npy)", options=options)

            if len(fn) > 0:
                arr = np.load(fn)
                if arr.shape[1] != 2:
                    msg = QMessageBox()
                    msg.setIcon(QMessageBox.Critical)
                    msg.setText("Not a valid numpy file. This array does not have two columns.")
                    msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)

                else:
                    self.new_series.append(arr)
                    lab = fn.split('/')[-1][:-4].replace('_',' ')
                    self.new_series_labels.append(lab)
                    T = np.array(arr[:,0], dtype = 'datetime64') + np.timedelta64(3600,'s')
                    self.ax.plot(T, arr[:,1], '.-', label = lab, scalex = False, scaley = False)
                    self.ax.legend(loc = 1)
                    self.varmin = np.min([self.varmin, np.min(arr[:,1])])
                    self.varmax = np.max([self.varmax, np.max(arr[:,1])])
                    self.varrange = abs(self.varmax - self.varmin)
                    #self.ax.set_ylim(max(-999,self.varmin - 0.1*self.varrange), min(999,self.varmax + 0.1*self.varrange))
                    self.canvas.draw()

        def home(self):
            self.toolbar.home()

        def zoom(self):
            if self.zoombut.isChecked():
                self.toolbar.zoom()
                self.record_pressing_event = False
            else:
                self.toolbar.zoom(False)
Пример #10
0
class MainWindow(QtWidgets.QMainWindow, mw.Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.datalst = []
        self.modellst = []
        self.lstdatamodel = QtGui.QStandardItemModel(self.listView)
        self.listView.setModel(self.lstdatamodel)
        self.current_lst_index = -1
        self.addButton.clicked.connect(self.add)
        self.removeButton.clicked.connect(self.remove)
        self.actionCalcLSSParameter.triggered.connect(self.calculatelss)
        self.actionAutomaticElutionWindowStretching.triggered.connect(
            self.calcautelwindowstretch)
        self.actionSelectivityMap.triggered.connect(self.pltselectivitymap)
        self.actionResolutionMap.triggered.connect(self.pltresolutionmap)
        self.actionAbout.triggered.connect(self.about)
        self.actionQuit.triggered.connect(self.quit)
        self.listView.clicked.connect(self.viewmatrix)
        self.toolBox.currentChanged.connect(self.viewmatrix)

        self.zoomButton.clicked.connect(self.zoom)
        self.panButton.clicked.connect(self.pan)
        self.rescaleButton.clicked.connect(self.home)
        self.exportchromatogramButton.clicked.connect(self.exportchromatogram)
        self.setplotoptionsButton.clicked.connect(self.setplotoptions)
        self.modelBox.currentIndexChanged.connect(self.gradientanalyser)
        self.doubleSpinBox_1.valueChanged.connect(self.gradientanalyser)
        self.doubleSpinBox_2.valueChanged.connect(self.gradientanalyser)
        self.doubleSpinBox_3.valueChanged.connect(self.gradientanalyser)
        self.doubleSpinBox_4.valueChanged.connect(self.gradientanalyser)
        self.doubleSpinBox_5.valueChanged.connect(self.gradientanalyser)
        self.doubleSpinBox_6.valueChanged.connect(self.gradientanalyser)
        self.ColumnLenghtSpinBox.valueChanged.connect(self.gradientanalyser)
        self.CulumnDiameterSpinBox.valueChanged.connect(self.gradientanalyser)
        self.ColumnPorositySpinBox.valueChanged.connect(self.gradientanalyser)

        # Add plot
        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)
        self.toolbar.hide()

        # set the layout
        layout_chormatogram = QtWidgets.QVBoxLayout()
        layout_chormatogram.addWidget(self.canvas)
        self.plotterBox.setLayout(layout_chormatogram)

        # Add selectivity map plot
        #self.figure_smap = plt.figure()
        #self.canvas_smap = FigureCanvas(self.figure_smap)
        #self.toolbar_smap = NavigationToolbar(self.canvas_smap, self)
        #self.toolbar_smap.hide()

        #layout_smap = QtWidgets.QVBoxLayout()
        #layout_smap.addWidget(self.canvas_smap)
        #self.plotterBox_2.setLayout(layout_smap)

        self.tablemodel = TableModel(self)
        self.tableView.setModel(self.tablemodel)
        self.tableView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.tableView.customContextMenuRequested.connect(self.openTableMenu)

        # constant parameters
        self.crit_resolution = 1.8
        self.crit_alpha = 1.1

        self.peaks = None
        self.crit_peaks = None

    def openTableMenu(self, position):
        """ context menu event """
        menu = QtWidgets.QMenu(self)
        exportAction = menu.addAction("Export table as CSV")
        action = menu.exec_(self.tableView.viewport().mapToGlobal(position))

        if action == exportAction:
            fname, _ = QtWidgets.QFileDialog.getSaveFileName(
                self, "Save File", "CSV (*.csv)")
            self.tablemodel.SaveTable(fname)
        else:
            return

        return

    def keyPressEvent(self, e):
        if (e.modifiers() & QtCore.Qt.ControlModifier):
            if e.key() == QtCore.Qt.Key_C:  #copy
                if len(self.tableView.selectionModel().selectedIndexes()) > 0:
                    previous = self.tableView.selectionModel().selectedIndexes(
                    )[0]
                    columns = []
                    rows = []
                    for index in self.tableView.selectionModel(
                    ).selectedIndexes():
                        if previous.column() != index.column():
                            columns.append(rows)
                            rows = []
                        rows.append(str(index.data().toPyObject()))
                        previous = index
                    columns.append(rows)

                    # add rows and columns to clipboard
                    clipboard = ""
                    nrows = len(columns[0])
                    ncols = len(columns)
                    for r in xrange(nrows):
                        for c in xrange(ncols):
                            clipboard += columns[c][r]
                            if c != (ncols - 1):
                                clipboard += '\t'
                        clipboard += '\n'

                    # copy to the system clipboard
                    sys_clip = QtWidgets.QApplication.clipboard()
                    sys_clip.setText(clipboard)

    def home(self):
        self.toolbar.home()

    def zoom(self):
        self.toolbar.zoom()

    def pan(self):
        self.toolbar.pan()

    def setplotoptions(self):
        return

    def exportchromatogram(self):
        if self.peaks != None and self.crit_peaks != None:
            fname, _ = QtWidgets.QFileDialog.getSaveFileName(
                self, "Save File", "CSV (*.csv)")
            print(os.path.exists(fname))
            if not os.path.exists(fname):
                y = []
                x = []
                for i in range(len(self.peaks)):
                    x.append(self.peaks[i][0])
                    y.append(0.)
                    for j in range(1, len(self.peaks[0])):
                        y[-1] += self.peaks[i][j]

                crit_y = []
                crit_x = []
                for i in range(len(self.crit_peaks)):
                    crit_x.append(self.crit_peaks[i][0])
                    crit_y.append(0.)
                    for j in range(1, len(self.crit_peaks[0])):
                        crit_y[-1] += self.crit_peaks[i][j]

                fo = open(fname, "w")
                for i in range(len(x)):
                    fo.write("%.4f;%.4f\n" % (x[i], y[i]))
                for i in range(len(crit_x)):
                    fo.write("%.4f;%.4f\n" % (crit_x[i], crit_y[i]))
                fo.close()
        else:
            return

    def plotchromatogram(self):
        ''' plot some random stuff '''
        data = [random.random() for i in range(25)]
        ax = self.figure.add_subplot(111)
        ax.clear()
        ax.plot(data, '*-')
        self.canvas.draw()

    def add(self):
        idialog = ImportDialog()
        if idialog.exec_() == 1:
            [
                name, molname, trdata, grad, tg, td, t0, flow, c_length,
                c_diameter, c_particle
            ] = idialog.getdata()
            self.datalst.append(
                Data(name, molname, trdata, grad, tg, td, t0, flow, c_length,
                     c_diameter, c_particle))
            self.lstdatamodel.appendRow(QtGui.QStandardItem(name))

    def remove(self):
        if self.current_lst_index >= 0 and self.current_lst_index < len(
                self.datalst):
            del self.datalst[self.current_lst_index]
            self.lstdatamodel.removeRow(self.current_lst_index)

    def viewmatrix(self, indx):
        if self.toolBox.currentIndex() == 0:
            if indx:
                self.current_lst_index = indx.row()
                del self.tablemodel.arraydata[:]
                del self.tablemodel.header[:]
                self.tablemodel.clean()
                self.tableView.model().layoutChanged.emit()
                molname = self.datalst[self.current_lst_index].molname
                trdata = self.datalst[self.current_lst_index].trdata
                grad = self.datalst[self.current_lst_index].grad
                tg = self.datalst[self.current_lst_index].tg
                header = ["Molecule"]
                for j in range(len(tg)):
                    header.append(
                        str("%.1f%% %.1f%% %.1f min" %
                            (round(grad[j][0] * 100,
                                   1), round(grad[j][1] * 100, 1), tg[j])))
                self.tablemodel.setHeader(header)
                for i in range(len(trdata)):
                    row = [molname[i]]
                    for j in range(len(trdata[i])):
                        row.append(round(trdata[i][j], 2))
                    self.tablemodel.addRow(row)
        else:
            del self.tablemodel.arraydata[:]
            del self.tablemodel.header[:]
            self.tablemodel.clean()
            self.tableView.model().layoutChanged.emit()
            self.gradientanalyser()

    def about(self):
        adialog = AboutDialog()
        adialog.exec_()

    def quit(self):
        QtWidgets.QApplication.quit()

    def calculatelss(self):
        items = []
        lstmodel = self.listView.model()
        for index in range(lstmodel.rowCount()):
            item = lstmodel.item(index)
            items.append(item.text())

        runlss = ComputeLSS(items)
        if runlss.exec_() == 1:
            [indx, modelname] = runlss.getdata()
            t0 = self.datalst[indx].t0
            v_d = self.datalst[indx].vd
            flow = self.datalst[indx].flow

            lssmol = SSGenerator(None, None, None, t0, v_d, flow)

            self.modellst.append(Model())
            self.modellst[-1].modname = modelname
            self.modellst[-1].molname = self.datalst[indx].molname
            self.modellst[-1].flow = self.datalst[indx].flow
            self.modellst[-1].c_length = self.datalst[indx].c_length
            self.modellst[-1].c_diameter = self.datalst[indx].c_diameter
            self.modellst[-1].c_particle = self.datalst[indx].c_particle
            self.modelBox.addItem(modelname)

            tg = self.datalst[indx].tg
            init_B = []
            final_B = []
            for i in range(len(tg)):
                init_B.append(self.datalst[indx].grad[i][0])
                final_B.append(self.datalst[indx].grad[i][1])

            self.modellst[-1].v_d = v_d
            self.modellst[-1].v_m = t0 * flow

            for row in self.datalst[indx].trdata:
                lss_logkw, lss_s = lssmol.getlssparameters(
                    row, tg, init_B, final_B)
                self.modellst[-1].lss.append([lss_logkw, lss_s])

            if len(self.modellst) == 1:
                self.gradientanalyser()

    def calcautelwindowstretch(self):
        aws = AutomaticElutionWindowStretching(self.modellst)
        aws.exec_()

    def pltselectivitymap(self):
        smap = PlotMaps(self.modellst, "sel")
        smap.exec_()

    def pltresolutionmap(self):
        rsmap = PlotMaps(self.modellst, "res")
        rsmap.exec_()

    def gradientanalyser(self):
        indx = self.modelBox.currentIndex()
        del self.tablemodel.arraydata[:]
        del self.tablemodel.header[:]
        self.tablemodel.clean()
        header = ["Molecule", "log kW", "S", "tR"]
        self.tablemodel.setHeader(header)
        self.tableView.model().layoutChanged.emit()
        if indx >= 0 and indx < len(self.modellst):
            #predict the retention time for each compound
            molname = [name for name in self.modellst[indx].molname]
            lss = self.modellst[indx].lss
            flow_sofware = float(self.doubleSpinBox_1.value())
            init_B_soft = float(self.doubleSpinBox_2.value()) / 100.
            final_B_soft = float(self.doubleSpinBox_3.value()) / 100.
            tg_soft = float(self.doubleSpinBox_4.value())

            c_length = self.ColumnLenghtSpinBox.value()
            c_diameter = self.CulumnDiameterSpinBox.value()
            c_particle = self.ColumnPorositySpinBox.value()

            t0_soft = 0.
            td_soft = 0.

            v_m = None
            v_d = float(self.doubleSpinBox_5.value())

            #if c_length > 0 and c_diameter > 0 and c_porosity > 0:
            #    v_m = ((square(self.c_diameter)*self.c_length*pi*self.c_porosity)/4.)/1000.
            #else:
            #
            #v_m = self.modellst[indx].v_m
            #t0_soft = float(v_m/flow_sofware)
            t0_soft = float(self.doubleSpinBox_6.value())
            td_soft = float(v_d / flow_sofware)

            A = 1.0

            #N = (c_length*10000.)/(3.4*c_particle)
            trtab = []
            lssmol = SSGenerator(None, None, None, t0_soft,
                                 float(self.modellst[indx].v_d), flow_sofware)
            i = 0
            trlst = []
            for row in lss:
                lss_logkw = float(row[0])
                lss_s = float(row[1])
                W = get_lss_peak_width(c_length, c_particle, lss_logkw, lss_s,
                                       init_B_soft, final_B_soft, tg_soft,
                                       flow_sofware, self.modellst[indx].v_m,
                                       self.modellst[indx].v_d, None)
                tr = lssmol.rtpred(lss_logkw, lss_s, tg_soft, init_B_soft,
                                   final_B_soft, t0_soft, td_soft)
                if tr < t0_soft:
                    trtab.append([t0_soft, A, W])
                else:
                    trtab.append([tr, A, W])
                trlst.append([round(trtab[-1][0], 2), W, molname[i]])
                row = [
                    molname[i],
                    round(lss_logkw, 3),
                    round(lss_s, 3),
                    round(trtab[-1][0], 2)
                ]
                self.tablemodel.addRow(row)
                self.tableView.model().layoutChanged.emit()
                i += 1

            # Calculate the critical resolution
            trlst = sorted(trlst, key=lambda x: x[0])
            # get min and max time
            tr_min = tr_max = 0.
            if len(trlst) > 0:
                tr_min = trlst[0][0]
                tr_max = trlst[-1][0]
                # calculate resolution and critical couple
                # get the peak width at base multiplying by 1.7
                self.plainTextEdit.clear()
                text = "Critical couples:\n"
                self.plainTextEdit.appendPlainText(text)

                crit_trtab = []
                crit_molname = []
                ncc = 0
                for i in range(1, len(trlst)):
                    width1 = trlst[i][1] * 1.7
                    width2 = trlst[i - 1][1] * 1.7
                    tr1 = trlst[i - 1][0]
                    tr2 = trlst[i][0]
                    tmp_rs = (2 * (tr2 - tr1)) / (width1 + width2)
                    if tmp_rs < self.crit_resolution:
                        molname_a = trlst[i - 1][2]
                        molname_b = trlst[i][2]
                        text = "  - %s  %.2f min\n" % (
                            molname_a, round(trlst[i - 1][0], 2))
                        text += "  - %s  %.2f min\n" % (molname_b,
                                                        round(trlst[i][0], 2))
                        text += "Rs: %.2f\n" % round(tmp_rs, 2)
                        text += "#" * 20
                        text += "\n"
                        self.plainTextEdit.appendPlainText(text)
                        ncc += 1
                        if molname_a not in crit_molname:
                            # add to critical tr tab
                            a_indx = molname.index(molname_a)
                            crit_trtab.append(trtab.pop(a_indx))
                            crit_molname.append(molname.pop(a_indx))

                        if molname_b not in crit_molname:
                            b_indx = molname.index(molname_b)
                            crit_trtab.append(trtab.pop(b_indx))
                            crit_molname.append(molname.pop(b_indx))
                    else:
                        continue

                self.plainTextEdit.appendPlainText(
                    "Total critical couples: %d" % (ncc))

                #Create a cromatogram
                self.peaks = list(
                    zip(*BuildChromatogram(trtab, tg_soft, 0.01)))
                self.crit_peaks = list(
                    zip(*BuildChromatogram(crit_trtab, tg_soft, 0.01)))

                y = []
                x = []
                for i in range(len(self.peaks)):
                    x.append(self.peaks[i][0])
                    y.append(0.)
                    #len(self.peaks[0])
                    for j in range(1, len(self.peaks[0])):
                        y[-1] += self.peaks[i][j]

                crit_y = []
                crit_x = []
                for i in range(len(self.crit_peaks)):
                    crit_x.append(self.crit_peaks[i][0])
                    crit_y.append(0.)
                    #len(peaks[0])
                    for j in range(1, len(self.crit_peaks[0])):
                        crit_y[-1] += self.crit_peaks[i][j]
                self.figure.clear()
                ax = self.figure.add_subplot(111)
                ax.clear()
                ax.plot(x, y, "b", crit_x, crit_y, "r")

                #ax.plot(x, y, '-', color='blue')
                #ax.plot(crit_x, crit_y, '-', color='red')
                plt.xlabel('Time')
                plt.ylabel('Signal')
                plt.xlim([
                    tr_min - ((tr_min * 10.) / 100.),
                    tr_max + ((tr_max * 10.) / 100.)
                ])
                self.canvas.draw()
Пример #11
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("Data View"))
        #MainWindow.resize(539, 600)
        
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))

        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.splitter = QtWidgets.QSplitter(self.centralwidget)
        self.splitter.setOrientation(QtCore.Qt.Horizontal)
        self.splitter.setObjectName(_fromUtf8("splitter"))        

        # File navigation
        self.fileSystemModel = QtWidgets.QDirModel(self.splitter)
        self.fileSystemModel.setObjectName(_fromUtf8("fileSystemModel"))
        currentDir = str(QtCore.QDir.currentPath())
        index = self.fileSystemModel.index(currentDir)
        self.treeView = QtWidgets.QTreeView(self.splitter)
        self.treeView.setObjectName(_fromUtf8("treeView"))
        self.treeView.setModel(self.fileSystemModel)
        if len(sys.argv)>1:
            self.currentFile = currentDir + '/' + sys.argv[1]
        else:
            self.currentFile = None
        self.recursive_expand( index, self.treeView )
        tVheader = self.treeView.header()
        for i in range(1,4): tVheader.hideSection(i)
        self.treeView.doubleClicked.connect(self.on_treeView_doubleClicked)

        # Plots tab
        self.tabWidget = QtWidgets.QTabWidget(self.splitter)
        self.tabWidget.setObjectName(_fromUtf8("tabWidget"))
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName(_fromUtf8("tab"))
        self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.tab)
        self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
        self.figure = plt.figure(figsize=(15,5))    
        self.canvas = FigureCanvas(self.figure)
        self.canvas.setObjectName(_fromUtf8("canvas"))
        self.toolbar = NavigationToolbar(self.canvas, self)
        self.toolbar.hide()
        self.verticalLayout_2.addWidget(self.canvas)

        # Plot buttons
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout_plotButtons"))
        self.plotTypeCombo = QtWidgets.QComboBox(self.tab)
        self.plotTypeCombo.setObjectName(_fromUtf8("plotTypeCombo"))
        self.plotTypeCombo.currentIndexChanged.connect(self.ChangePlotType)
        self.horizontalLayout.addWidget(self.plotTypeCombo)
        self.btnPlot = QtWidgets.QPushButton(self.tab)
        self.btnPlot.setObjectName(_fromUtf8("btnPlot"))
        self.btnPlot.clicked.connect(self.drawPlot)
        self.horizontalLayout.addWidget(self.btnPlot)
        self.btnZoom = QtWidgets.QPushButton(self.tab)
        self.btnZoom.setObjectName(_fromUtf8("btnZoom"))
        self.btnZoom.clicked.connect(self.plotZoom)
        self.horizontalLayout.addWidget(self.btnZoom)
        self.btnPan = QtWidgets.QPushButton(self.tab)
        self.btnPan.setObjectName(_fromUtf8("btnPan"))
        self.btnPan.clicked.connect(self.plotPan)
        self.horizontalLayout.addWidget(self.btnPan)
        self.btnHome = QtWidgets.QPushButton(self.tab)
        self.btnHome.setObjectName(_fromUtf8("btnHome"))
        self.btnHome.clicked.connect(self.plotHome)
        self.horizontalLayout.addWidget(self.btnHome)
        self.verticalLayout_2.addLayout(self.horizontalLayout)

        # x axis options
        self.horizontalLayout_xAxis = QtWidgets.QHBoxLayout()
        self.horizontalLayout_xAxis.setObjectName(_fromUtf8("horizontalLayout_xAxis"))
        self.xColSelect = QtWidgets.QComboBox(self.tab)
        self.xColSelect.setObjectName(_fromUtf8("xColSelect"))
        self.xColSelect.currentIndexChanged.connect(self.ResetUserSelections)
        self.horizontalLayout_xAxis.addWidget(self.xColSelect)
        self.horizontalLayout_xAxis.setStretchFactor(self.xColSelect,2)
        self.xbinsLabel = QtWidgets.QLabel(self.tab)
        self.xbinsLabel.setText("X Bins:")
        self.horizontalLayout_xAxis.addWidget( self.xbinsLabel )
        self.xnBinsSpin = QtWidgets.QSpinBox(self.tab)
        self.xnBinsSpin.setObjectName(_fromUtf8("xnBinsSpin"))
        self.xnBinsSpin.valueChanged.connect(self.XChangeBinning)
        self.xnBinsSpin.setRange(1,10000)
        self.horizontalLayout_xAxis.addWidget( self.xnBinsSpin )
        self.horizontalLayout_xAxis.setStretchFactor(self.xnBinsSpin,2)
        self.xminLabel = QtWidgets.QLabel(self.tab)
        self.xminLabel.setText("X Min:")
        self.horizontalLayout_xAxis.addWidget( self.xminLabel )
        self.xnMinSpin = QtWidgets.QDoubleSpinBox(self.tab)
        self.xnMinSpin.setObjectName(_fromUtf8("xnMinSpin"))
        self.xnMinSpin.valueChanged.connect(self.XChangeMin)
        self.xnMinSpin.setRange( -1e20, 1e20 )
        self.horizontalLayout_xAxis.addWidget( self.xnMinSpin )
        self.horizontalLayout_xAxis.setStretchFactor(self.xnMinSpin,2)
        self.xmaxLabel = QtWidgets.QLabel(self.tab)
        self.xmaxLabel.setText("X Max:")
        self.horizontalLayout_xAxis.addWidget( self.xmaxLabel )
        self.xnMaxSpin = QtWidgets.QDoubleSpinBox(self.tab)
        self.xnMaxSpin.setObjectName(_fromUtf8("xnMaxSpin"))
        self.xnMaxSpin.setRange( -1e20, 1e20 )
        self.xnMaxSpin.valueChanged.connect(self.XChangeMax)
        self.horizontalLayout_xAxis.addWidget( self.xnMaxSpin )
        self.horizontalLayout_xAxis.setStretchFactor(self.xnMaxSpin,2)
        self.xTypeCombo = QtWidgets.QComboBox(self.tab)
        self.xTypeCombo.setObjectName(_fromUtf8("xTypeCombo"))
        self.xTypeCombo.addItems( ['int','float','str','datetime'] )
        self.xTypeCombo.currentIndexChanged.connect(self.ChangeXDataType)
        self.horizontalLayout_xAxis.addWidget(self.xTypeCombo)
        self.horizontalLayout_xAxis.setStretchFactor(self.xTypeCombo,2)
        self.verticalLayout_2.addLayout(self.horizontalLayout_xAxis )
        
        # y axis options
        self.horizontalLayout_yAxis = QtWidgets.QHBoxLayout()
        self.horizontalLayout_yAxis.setObjectName(_fromUtf8("horizontalLayout_yAxis"))
        self.yColSelect = QtWidgets.QComboBox(self.tab)
        self.yColSelect.setObjectName(_fromUtf8("yColSelect"))
        self.yColSelect.currentIndexChanged.connect(self.ResetUserSelections)
        self.horizontalLayout_yAxis.addWidget(self.yColSelect)
        self.horizontalLayout_yAxis.setStretchFactor(self.yColSelect,2)
        self.ybinsLabel = QtWidgets.QLabel(self.tab)
        self.ybinsLabel.setText("Y Bins:")
        self.horizontalLayout_yAxis.addWidget( self.ybinsLabel )
        self.ynBinsSpin = QtWidgets.QSpinBox(self.tab)
        self.ynBinsSpin.setObjectName(_fromUtf8("ynBinsSpin"))
        self.ynBinsSpin.valueChanged.connect(self.YChangeBinning)
        self.horizontalLayout_yAxis.addWidget( self.ynBinsSpin )
        self.horizontalLayout_yAxis.setStretchFactor(self.ynBinsSpin,2)
        self.yminLabel = QtWidgets.QLabel(self.tab)
        self.yminLabel.setText("Y Min:")
        self.horizontalLayout_yAxis.addWidget( self.yminLabel )
        self.ynMinSpin = QtWidgets.QDoubleSpinBox(self.tab)
        self.ynMinSpin.setObjectName(_fromUtf8("ynMinSpin"))
        self.ynMinSpin.setRange( -1e20, 1e20 )
        self.ynMinSpin.valueChanged.connect(self.YChangeMin)
        self.horizontalLayout_yAxis.addWidget( self.ynMinSpin )
        self.horizontalLayout_yAxis.setStretchFactor(self.ynMinSpin,2)
        self.ymaxLabel = QtWidgets.QLabel(self.tab)
        self.ymaxLabel.setText("Y Max:")
        self.horizontalLayout_yAxis.addWidget( self.ymaxLabel )
        self.ynMaxSpin = QtWidgets.QDoubleSpinBox(self.tab)
        self.ynMaxSpin.setObjectName(_fromUtf8("ynMaxSpin"))
        self.ynMaxSpin.setRange( -1e20, 1e20 )
        self.ynMaxSpin.valueChanged.connect(self.YChangeMax)
        self.horizontalLayout_yAxis.addWidget( self.ynMaxSpin )
        self.horizontalLayout_yAxis.setStretchFactor(self.ynMaxSpin,2)
        self.yTypeCombo = QtWidgets.QComboBox(self.tab)
        self.yTypeCombo.setObjectName(_fromUtf8("yTypeCombo"))
        self.yTypeCombo.addItems( ['int','float','str','datetime'] )
        self.yTypeCombo.currentIndexChanged.connect(self.ChangeYDataType)
        self.horizontalLayout_yAxis.addWidget(self.yTypeCombo)
        self.horizontalLayout_yAxis.setStretchFactor(self.yTypeCombo,2)
        #self.verticalLayout_2.addLayout(self.horizontalLayout_yAxis )
        self.yAxisItems = [ self.yColSelect, self.ybinsLabel, self.ynBinsSpin, self.yminLabel, self.ynMinSpin,
                            self.ymaxLabel, self.ynMaxSpin, self.yTypeCombo ]

        self.binningChoices = [ self.ybinsLabel, self.ynBinsSpin, self.xbinsLabel, self.xnBinsSpin ]
        
        # Data tab
        self.tabWidget.addTab(self.tab, _fromUtf8(""))
        self.tab_2 = QtWidgets.QWidget()
        self.tab_2.setObjectName(_fromUtf8("tab_2"))
        self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.tab_2)
        self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))
        self.tableView = QtWidgets.QTableView(self.tab_2)
        self.tableView.setObjectName(_fromUtf8("tableView"))
        self.verticalLayout_3.addWidget(self.tableView)
        
        # Filter text entry
        self.filterHorLayout = QtWidgets.QHBoxLayout()
        self.filterHorLayout.setObjectName(_fromUtf8("filterHorLayout"))
        self.filterBox = QtWidgets.QLineEdit(self.centralwidget)
        self.filterBox.setObjectName(_fromUtf8("filterBox"))
        self.btnFilter = QtWidgets.QPushButton(self.centralwidget)
        self.btnFilter.setObjectName(_fromUtf8("btnFilter"))
        self.btnFilter.clicked.connect(self.updateTable)
        self.filterHorLayout.addWidget(self.filterBox)
        self.filterHorLayout.addWidget(self.btnFilter)
        self.verticalLayout.addLayout(self.filterHorLayout)
        
        # Setup
        self.treeView.raise_()
        self.tabWidget.addTab(self.tab_2, _fromUtf8(""))
        self.verticalLayout.addWidget(self.splitter)
        self.splitter.setStretchFactor(1, 2)
        self.centralwidget.showFullScreen()
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)

        # Set the default picture
        import matplotlib.image as mpimg
        img=mpimg.imread(r'H:\stash_projects\DataView\PandaViz.jpg')
        plt.imshow(img)

        self.hdfStore = None
        self.plotTypeCombo.addItems( ['Scatter','Line','Hist','Hist2d'] )
        self.userxBinning = False
        self.userxMax = False
        self.userxMin = False
        self.useryBinning = False
        self.useryMax = False
        self.useryMin = False        
        self.fileName = ""
        self.df = None
        self.orig_df = None
        self.filterStr = None
        self.lastFilterStr = None
        
        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
       
        if self.currentFile is not None:

            if len(self.currentFile.split( r':' )) > 1:
                self.currentFile = self.currentFile.split( r':' )[1][-1] + r':' + self.currentFile.split( r':' )[2] 
            
            self.treeView.setCurrentIndex( self.fileSystemModel.index( self.currentFile ) )
            self.recursive_expand( index, self.treeView )
            #self.on_treeView_doubleClicked(  self.fileSystemModel.index( self.currentFile ) )
            self.on_treeView_doubleClicked(self.fileSystemModel.index( self.currentFile ) ,self.currentFile )
        
    def setupCsv(self):
        self.data()
        self.columns = self.df.columns.tolist()
        self.xColSelect.clear()
        self.xColSelect.addItems( self.columns )
        self.yColSelect.clear()
        self.yColSelect.addItems( self.columns )
        self.xTypeCombo.Text = str(self.df[ self.columns[0] ].dtype)
        self.updateTable()

    def setupH5(self):
        self.h5keys = self.hdfStore.keys()
        if len(self.h5keys) > 1:
            self.chosen_h5key = str( SelectDialog.SelectDialog.getOptions( self.h5keys ) )
        else:
            self.chosen_h5key = ""
        if self.chosen_h5key == "":
            self.orig_df = self.hdfStore[ self.h5keys[0] ]
        else:
            self.orig_df = self.hdfStore[ self.chosen_h5key ]
        self.setupCsv()

    def plotLine(self):
        if self.data() is None: return
        plt.clf()
        xCol = str( self.xColSelect.currentText() )
        yCol = str( self.yColSelect.currentText() )
        ax = plt.gca()
        ax.plot( self.df[ xCol ].tolist(), self.df[ yCol ].tolist(), label=xCol + ' v ' + yCol )
        if self.userxMin or self.userxMax or self.useryMin or self.useryMax:
            ax.set_xlim( self.xnMinSpin.value(), self.xnMaxSpin.value() )
            ax.set_ylim( self.ynMinSpin.value(), self.ynMaxSpin.value() )
        else:
            self.xnMinSpin.setValue( ax.get_xlim()[0] )
            self.xnMaxSpin.setValue( ax.get_xlim()[1] )
            self.ynMinSpin.setValue( ax.get_ylim()[0] )
            self.ynMaxSpin.setValue( ax.get_ylim()[1] )            
        ax.set_xlabel( xCol )
        ax.set_ylabel( yCol )
        self.canvas.draw()
        
    def plotHist(self):
        if self.data() is None: return
        plt.clf()
        col = str( self.xColSelect.currentText() )
        if self.userxBinning: bins = self.xnBinsSpin.value()
        else: bins = 10

        if not self.userxBinning: self.xnBinsSpin.setValue( bins )

        if self.userxMin:
            Min = self.xnMinSpin.value()
        else:
            Min = self.df[col].min()
            try: self.xnMinSpin.setValue( Min )
            except: self.xnMinSpin.setValue( 0. )
        if self.userxMax:
            Max = self.xnMaxSpin.value()
        else:
            Max = self.df[col].max()
            try: self.xnMaxSpin.setValue( Max )
            except: self.xnMaxSpin.setValue( 0. )
                    
        plt.hist( sorted(self.df[ col ].tolist()), bins=bins, range=(Min,Max) )
        plt.xlabel( col )
        self.canvas.draw()
        
    def plotScatter(self):
        if self.data() is None: return
        plt.clf()
        xCol = str( self.xColSelect.currentText() )
        yCol = str( self.yColSelect.currentText() )
        ax = plt.gca()
        ax.scatter( self.df[ xCol ].tolist(), self.df[ yCol ].tolist(), label=xCol + ' v ' + yCol )
        if self.userxMin or self.userxMax or self.useryMin or self.useryMax:
            ax.set_xlim( self.xnMinSpin.value(), self.xnMaxSpin.value() )
            ax.set_ylim( self.ynMinSpin.value(), self.ynMaxSpin.value() )
        else:
            self.xnMinSpin.setValue( ax.get_xlim()[0] )
            self.xnMaxSpin.setValue( ax.get_xlim()[1] )
            self.ynMinSpin.setValue( ax.get_ylim()[0] )
            self.ynMaxSpin.setValue( ax.get_ylim()[1] )            
        ax.set_xlabel( xCol )
        ax.set_ylabel( yCol )
        self.canvas.draw()

    def plotHist2d(self):
        if self.data() is None: return
        plt.clf()
        xCol = str( self.xColSelect.currentText() )
        yCol = str( self.yColSelect.currentText() )
        ax = plt.gca()
        if self.userxBinning: bins = self.xnBinsSpin.value()
        else: bins = 10
        ax.hist2d( self.df[xCol].tolist(), self.df[yCol].tolist(), bins=bins )
        if not self.userxBinning: self.xnBinsSpin.setValue( bins )
        if not self.userxMin:
            self.xnMinSpin.setValue( ax.get_xlim()[0] )
        else:
            ax.set_xlim([self.xnMinSpin.value(), ax.get_xlim()[1] ] )
        if not self.userxMax:
            self.xnMaxSpin.setValue( ax.get_xlim()[1] )
        else:
            ax.set_xlim([ax.get_xlim()[0], self.xnMaxSpin.value() ] )
        if not self.useryMin:
            self.ynMinSpin.setValue( ax.get_ylim()[0] )
        else:
            ax.set_ylim([self.ynMinSpin.value(), ax.get_ylim()[1] ] )
        if not self.useryMax:
            self.ynMaxSpin.setValue( ax.get_ylim()[1] )
        else:
            ax.set_ylim([ax.get_ylim()[0], self.ynMaxSpin.value() ] )
        plt.xlabel( xCol )
        plt.ylabel( yCol )
        self.canvas.draw()

        
    def data(self):
        if self.orig_df is None: return None
        self.filterStr = str(self.filterBox.text())
        if self.filterStr is not None and self.filterStr != "":
            if self.filterStr != self.lastFilterStr:
                try:
                    exec("self.df = self.orig_df[" +  self.filterStr.replace("df","self.orig_df") + "]" )
                    self.lastFilterStr = self.filterStr
                except Exception as e:
                    msg = QMessageBox()
                    msg.setIcon(QMessageBox.Warning)
                    msg.setText("Filtering failed")
                    msg.setWindowTitle("Error")
                    msg.setDetailedText( str(e) )
                    msg.setStandardButtons(QMessageBox.Ok)
                    msg.exec_()
                    pass
                pass
            pass
        else:
            self.df = self.orig_df
        return True
    
    def updateTable(self):
        if self.data() is None: return
        header = self.columns
        tm = MyTableModel.MyTableModel(self.df.values, header, self)
        self.tableView.setModel(tm)
        vh = self.tableView.verticalHeader()
        vh.setVisible(False)
        hh = self.tableView.horizontalHeader()
        hh.setStretchLastSection(True)
        self.tableView.setSortingEnabled(True)
        #self.tableView.sortByColumn(0);
        tm.sort( 0,  Qt.AscendingOrder )
        
    def plotZoom(self): self.toolbar.zoom()
    def plotPan(self): self.toolbar.pan()
    def plotHome(self): self.toolbar.home()
        
    def on_treeView_doubleClicked(self, index, fileName = '' ):
        if fileName == '':
            fileName = str(index.model().filePath(index))
            
        if self.fileName == fileName: return

        if self.hdfStore is not None:
            self.hdfStore.close()
            
        if fileName.endswith( ".csv" ):
            self.hdfStore = None
            self.fileName = fileName
            self.isCsv = True
            self.isH5 = False
            self.orig_df = pd.read_csv( fileName )
            self.setupCsv()
        elif fileName.endswith(".h5"):
            self.fileName = fileName
            self.isCsv = False
            self.isH5 = True
            self.hdfStore = pd.HDFStore( fileName, 'r' )
            self.setupH5()
        
    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "PandaViz", None))
        import os.path as osp
        path = osp.join(osp.dirname(sys.modules[__name__].__file__), 'PandaViz.jpg')
        MainWindow.setWindowIcon(QIcon(path))
        self.btnZoom.setText(_translate("MainWindow", "Zoom", None))
        self.btnPlot.setText(_translate("MainWindow", "Draw", None))
        self.btnPan.setText(_translate("MainWindow", "Pan", None))
        self.btnHome.setText(_translate("MainWindow", "Reset", None))
        self.btnFilter.setText(_translate("MainWindow","Update Table", None))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Plot", None))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Data", None))

    def recursive_expand(self, index, treeView):
        treeView.expand( index )
        parent = index.parent()
        if parent != index:
            self.recursive_expand( parent, treeView )


    def drawPlot(self):
        pType = self.plotTypeCombo.currentText()
        if pType == 'Scatter': self.plotScatter()
        elif pType == 'Hist': self.plotHist()
        elif pType == 'Hist2d': self.plotHist2d()
        elif pType == 'Line': self.plotLine()

    def ChangeXDataType(self):
        if self.data() is None: return
        col = str( self.xColSelect.currentText() )
        changeType = str( self.xTypeCombo.currentText() )
        try:
            if changeType == 'datetime':
                self.df[ col ] = pd.to_datetime( self.df[ col ])
            else:
                exec("self.df[ col ] = self.df[ col ].astype("+ changeType + ")")
        except Exception as e:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Warning)
            msg.setText("Type Conversion Failed")
            msg.setWindowTitle("Error")
            msg.setDetailedText( str(e) )
            msg.setStandardButtons(QMessageBox.Ok)
            msg.exec_()
            pass
        pass

    def ChangeYDataType(self):
        if self.data() is None: return
        col = str( self.yColSelect.currentText() )
        changeType = str( self.yTypeCombo.currentText() )
        try:
            if changeType == 'datetime':
                self.df[ col ] = pd.to_datetime( self.df[ col ])
            else:
                exec("self.df[ col ] = self.df[ col ].astype("+ changeType + ")")
        except Exception as e:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Warning)
            msg.setText("Type Conversion Failed")
            msg.setWindowTitle("Error")
            msg.setDetailedText( str(e) )
            msg.setStandardButtons(QMessageBox.Ok)
            msg.exec_()
            pass
        pass
    
    def ChangePlotType(self):
        self.userBinning = False
        pType = self.plotTypeCombo.currentText()
        if pType == 'Scatter' or pType == 'Line' or pType == 'Hist2d':
            [ x.show() for x in self.yAxisItems ]
            found = False
            for i in range( self.verticalLayout_2.count() ):
                if self.verticalLayout_2.itemAt(i) == self.horizontalLayout_yAxis: found=True
            if not found: self.verticalLayout_2.addLayout( self.horizontalLayout_yAxis )
            if pType == 'Scatter' or pType == 'Line':
                [ x.hide() for x in self.binningChoices ]
            else:
                [ x.show() for x in self.binningChoices ]
        else:
            [ x.show() for x in self.binningChoices ]
            [ x.hide() for x in self.yAxisItems ]
            for i in range( self.verticalLayout_2.count() ):
                if self.verticalLayout_2.itemAt(i) == self.horizontalLayout_yAxis:
                    self.verticalLayout_2.removeItem( self.horizontalLayout_yAxis )
        self.verticalLayout_2.update()


    def XChangeBinning(self): self.userxBinning = True
    def YChangeBinning(self): self.useryBinning = True
    def XChangeMax(self): self.userxMax = True
    def YChangeMax(self): self.useryMax = True
    def XChangeMin(self): self.userxMin = True
    def YChangeMin(self): self.useryMin = True

    def ResetUserSelections(self):
        self.userxMin = False
        self.useryMin = False
        self.userxMax = False
        self.useryMax = False
        self.userxBinning = False
        self.useryBinning = False
Пример #12
0
class MCS(QMainWindow, Ui_MCS):
    """
    Class documentation goes here.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(MCS, self).__init__(parent)
        self.setupUi(self)

        # 添加 matplotlib 画布组件用于绘图
        self.canvas1 = Canvas(self.frame,
                              xlabel="Time(s)",
                              title="Sampled waveform")
        self.canvas1.get_default_filename = lambda: 'Sampled waveform.png'

        self.horizontalLayout_15.addWidget(self.canvas1)

        self.canvas2 = Canvas(self.frame,
                              xlabel="Frequency(Hz)",
                              title="FFT of Sampled waveform")
        self.canvas2.get_default_filename = lambda: ('FFT of Sampled '
                                                     'waveform.png')
        self.horizontalLayout_14.addWidget(self.canvas2)

        # 添加 matplotlib 导航工具栏用于操作图像。
        self.toolbar1 = NavigationToolbar(self.canvas1, self)
        self.toolbar1.hide()
        self.toolbar2 = NavigationToolbar(self.canvas2, self)
        self.toolbar2.hide()

        # 为文本框添加 validator
        regex = QRegExp(r'^400(\.0)?$|^[1-3]?[0-9]{1,2}(\.[0-9])?$')
        self.lineEdit_4.setValidator(QRegExpValidator(regex, self))

        self.lineEdit_5.setValidator(
            QRegExpValidator(QRegExp(r'^([1-9][0-9]{0,1}|100)$'),
                             self))  # 采样时间限制

        # 一些初始化变量值
        self.scrollbar_value = 1
        self.signal_wave = None
        self.amplitude = 2.5, 2.5
        self.data = None
        self.external_flag = False
        self.sample_freq_value = 0.1
        self.axes_color = "w"
        self.figure_color = None
        self.line_color = "C0"
        self.sample_time = 5

        # 将菜单栏中的 signal 选项改为单选。
        self.menuGroupSingal = QActionGroup(self.menuSignal)
        self.menuGroupSingal.addAction(self.actionSquare)
        self.menuGroupSingal.addAction(self.actionTriangle)
        self.menuGroupSingal.addAction(self.actionSin)
        self.menuGroupSingal.setExclusive(True)

    def zoom(self):
        """缩放图像。"""
        self.toolbar1.zoom()
        self.toolbar2.zoom()

    def pan(self):
        """拖动图像。"""
        self.toolbar1.pan()
        self.toolbar2.pan()

    def save(self):
        """保存图像。"""
        self.toolbar1.save_figure()
        self.toolbar2.save_figure()

    def generate_signal(self, freq, sample_point):
        """根据传入参数及预设,生成对应信号。"""
        # 函数的相位
        phase = 2 * np.pi * freq * sample_point

        # 模拟产生噪音信号
        noise = np.random.randn(*np.shape(sample_point)) / 50
        # noise = 0

        if self.signal_wave == 3:
            # 返回正弦波
            return self.amplitude[0] * np.sin(
                phase) + noise + self.amplitude[1]
        elif self.signal_wave == 2:
            # 返回三角波
            return (self.amplitude[0] * signal.sawtooth(phase, 0.5) + noise +
                    self.amplitude[1])
        else:
            # 返回方波
            return (self.amplitude[0] * signal.square(phase) + noise +
                    self.amplitude[1])

    def plot(self):
        """绘制图像。"""
        # 采样时间
        T = self.sample_time
        if self.external_flag:
            x, y, N, f_s = self.resume_data_from_file()
            self.horizontalScrollBar.setValue(int(N / 10))
            self.external_flag = False
        else:
            # f_s 范围 0.1k~400K 而 scrollbar_value 范围 1~1000
            f_s = int(self.scrollbar_value * 10)

            # 采样点数 N = T * f_s
            N = T * f_s

            # 生成采样点集,范围从 0-T 均分 N个点。
            x = np.linspace(0, T, N, endpoint=False)

            # 设置产生信号的频率
            freq = signal_dlg.freq

            # 采样点
            sample_point = x

            # 生成指定信号
            y = self.generate_signal(freq, sample_point)

            # 生成用于导出的数据
            self.generate_export_data(x, y, N, f_s)

        # FFT 变换
        yf2 = fft(y)
        f = fftfreq(N, 1.0 / f_s)
        mask = np.where(f >= 0)
        xf2 = f[mask]
        yf2 = abs(yf2[mask] / N)

        self.lineEdit.setText(f"{np.max(y) - np.mean(y):.4f}")

        y_ac = y - np.mean(y)
        count = ((y_ac[:-1] * y_ac[1:]) < 0).sum()
        count = count if count % 2 == 0 else count + 1
        self.lineEdit_3.setText(f"{2*T/count:.4f}")
        # self.lineEdit_3.setText(f"{((y_ac[:-1] * y_ac[1:]) < 0).sum():.5f}")
        self.lineEdit_2.setText(f"{count/(2*T):.2f}")
        self.canvas1.plot(x, y, "Time(s)", "Amplitude(V)", "Sampled waveform",
                          self.line_color, self.axes_color, self.figure_color)
        self.canvas2.plot(xf2, yf2, "Frequency(Hz)", "Amplitude(V)",
                          "FFT of Sampled waveform", self.line_color,
                          self.axes_color, self.figure_color)

    def generate_export_data(self, x, y, N, f_s):
        """生成用于输出的数据。"""
        self.data = f"{N}\n{f_s}\n" + "\n".join([str(i) for i in zip(x, y)])

    def resume_data_from_file(self):
        """从文件中恢复数据。"""
        data = self.data.split("\n")
        list_data = [eval(i) for i in data[2:]]
        N = int(data[0])
        f_s = int(data[1])
        x, y = map(list, zip(*list_data))
        x = np.array(x)
        y = np.array(y)
        return x, y, N, f_s

    @pyqtSlot()
    def on_pushButton_clicked(self):
        """pushButton 被点击时,绘制图像。"""
        self.plot()

    @pyqtSlot()
    def on_pushButton_2_clicked(self):
        """pushButton2 被点击时,允许缩放图像。"""
        self.zoom()

    @pyqtSlot()
    def on_pushButton_3_clicked(self):
        """pushButton3 被点击时,允许拖动图像。"""
        self.pan()

    @pyqtSlot()
    def on_pushButton_4_clicked(self):
        """
        点击 pushButton_4(还原采样波形) 触发采样波形恢复。
        """
        self.toolbar1.home()

    @pyqtSlot()
    def on_pushButton_5_clicked(self):
        """
        点击 pushButton_5(缩放) 允许缩放波形。
        """
        self.zoom()

    @pyqtSlot()
    def on_pushButton_6_clicked(self):
        """
        点击 pushButton_6(拖动) 允许拖动波形。
        """
        self.pan()

    @pyqtSlot()
    def on_pushButton_7_clicked(self):
        """
        点击 pushButton_7(保存) 依次弹出保存图形窗口。
        """
        self.save()

    @pyqtSlot()
    def on_pushButton_8_clicked(self):
        """
        点击 pushButton_8(还原FFT) 触发FFT波形恢复
        """
        self.toolbar2.home()

    @pyqtSlot()
    def on_pushButton_9_clicked(self):
        """
        点击 pushButton_9(采样数据),从 self.data 中读取数据,并写入弹出对话框中的
        文本框;如果 self.data 为空,则向文本框中写入报错信息。
        """
        if self.data:
            dlg_ui.textEdit.setText(self.data)
        else:
            dlg_ui.textEdit.setText("请先采集数据或导入数据。")
        Dialog.show()

    @pyqtSlot()
    def on_pushButton_10_clicked(self):
        """
        点击 pushButton_10(频率设置) 弹出频率设置对话框。
        """
        signal_dlg.show()

    @pyqtSlot()
    def on_action_Exit_triggered(self):
        """
        点击 File-Exit 退出程序。
        """
        self.close()

    @pyqtSlot(int)
    def on_horizontalScrollBar_valueChanged(self, value):
        """
        将水平滑动控件与 lineEdit_4 绑定,当滑条数值改变时,对应改变文本框中的数值。

        @param value DESCRIPTION
        @type self, int
        """
        # ScrollBar 范围为 1-1000 所以将从其获得的值除以十倍置于 lineEdit_4。
        self.lineEdit_4.setText(str(value / 10))
        self.scrollbar_value = value

    @pyqtSlot()
    def on_lineEdit_4_editingFinished(self):
        """
        当 lineEdit_4 完成编辑,即光标焦点移开或者是敲击 Enter 或 Return 后,
        该方法生效。
        """
        if self.lineEdit_4.text():
            # ScrollBar 范围为 1-1000 所以将从文本框中获得的值乘十设置为滑块值。
            value = int(float(self.lineEdit_4.text()) * 10)
            self.horizontalScrollBar.setValue(value)
        else:
            self.horizontalScrollBar.setValue(0.1)

    @pyqtSlot(bool)
    def on_actionSquare_triggered(self, checked):
        """
        点击 View-Signal-Square 时,将类属性 signal_wave 设置为1,即表示方波。
        
        @param checked DESCRIPTION
        @type self, bool
        """
        self.signal_wave = 1 if checked else None

    @pyqtSlot(bool)
    def on_actionTriangle_triggered(self, checked):
        """
        点击 View-Signal-Triangle 时,将类属性 signal_wave 设置为2,即表示三角波。
        
        @param checked DESCRIPTION
        @type self, bool
        """
        self.signal_wave = 2 if checked else None

    @pyqtSlot(bool)
    def on_actionSin_triggered(self, checked):
        """
        点击 View-Signal-Sine 时,将类属性 signal_wave 设置为3,即表示正弦波。
        
        @param checked DESCRIPTION
        @type self, bool
        """
        self.signal_wave = 3 if checked else None

    # 单选框代码,即选则输入电压。
    @pyqtSlot(bool)
    def on_radioButton_toggled(self, checked):
        """
        选中 radioButton 时,将类属性 amplitude 设置为 (2.5, 2.5),
        即输入电压为 0~5V。

        @param checked DESCRIPTION
        @type self, bool
        """
        if checked:
            self.amplitude = 2.5, 2.5

    @pyqtSlot(bool)
    def on_radioButton_2_toggled(self, checked):
        """
        选中 radioButton_2 时,将类属性 amplitude 设置为 (5, 5),
        即输入电压为 0~10V。
        
        @param checked DESCRIPTION
        @type self, bool
        """
        if checked:
            self.amplitude = 5, 5

    @pyqtSlot(bool)
    def on_radioButton_3_toggled(self, checked):
        """
        选中 radioButton_3 时,将类属性 amplitude 设置为 (5, 0),
        即输入电压为 -5~+5V。

        @param checked DESCRIPTION
        @type self, bool
        """
        if checked:
            self.amplitude = 5, 0

    @pyqtSlot(bool)
    def on_radioButton_4_toggled(self, checked):
        """
        选中 radioButton_4 时,将类属性 amplitude 设置为 (10, 0),
        即输入电压为 -10~+10V。
        
        @param checked DESCRIPTION
        @type self, bool
        """
        if checked:
            self.amplitude = 10, 0

    @pyqtSlot()
    def on_actionExport_Data_triggered(self):
        """
         点击 File—Export Data,将储存在 self.data中的数据导出到文件。
        """
        # todo: 导出到 json
        if self.data:
            fileName, _ = QFileDialog.getSaveFileName(self, "Export Data")
            if fileName:
                file = open(fileName, 'w')
                text = self.data
                file.write(text)
                file.close()
        else:
            # 如果没有采集数据,则弹出警告。
            reply = QMessageBox.warning(self, "警告", "请先采集数据!",
                                        QMessageBox.Yes | QMessageBox.No,
                                        QMessageBox.Yes)

    @pyqtSlot()
    def on_actionSave_triggered(self):
        """
        Slot documentation goes here.
        """
        self.save()

    @pyqtSlot()
    def on_actionOpen_triggered(self):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        fileName, _ = QFileDialog.getOpenFileName(self, "Open File")
        if fileName:
            file = open(fileName, "r")
            self.data = file.read()
            # 抛出错误?
            self.external_flag = True
            file.close()

    @pyqtSlot()
    def on_actionLine_Color_triggered(self):
        """
        Slot documentation goes here.
        """
        color = QColorDialog.getColor()
        self.line_color = color.name()

    @pyqtSlot()
    def on_actionFigure_Color_triggered(self):
        """
        Slot documentation goes here.
        """
        color = QColorDialog.getColor()
        self.figure_color = color.name()

    @pyqtSlot()
    def on_actionAxes_Color_triggered(self):
        """
        Slot documentation goes here.
        """
        color = QColorDialog.getColor()
        self.axes_color = color.name()

    @pyqtSlot()
    def on_lineEdit_5_editingFinished(self):
        """
        Slot documentation goes here.
        """
        if self.lineEdit_5.text():
            self.sample_time = int(self.lineEdit_5.text())

    @pyqtSlot()
    def on_actionabout_some_triggered(self):
        """
        Slot documentation goes here.
        """
        reply = QMessageBox.about(self, "About",
                                  ("This program is designed "
                                   "for Measurement and Control "
                                   "System course.\n"
                                   "Author: Weiliang Liu, "
                                   "Yichen Zhang"))

    @pyqtSlot()
    def on_actionsome_help_triggered(self):
        """
        Slot documentation goes here.
        """
        reply = QMessageBox.information(self, "帮助", "没有什么帮助!",
                                        QMessageBox.Yes | QMessageBox.No,
                                        QMessageBox.Yes)
Пример #13
0
 def home(self):
     if self.ongoing:
         if not self.figurecanvas.timerIsActive():
             self.figurecanvas.startTimer()
     else:
         NT.home(self)
Пример #14
0
class Window(QMainWindow):
    def __init__(self, camera=None, calibration=None):

        #Inherit properies from QMainWindow
        super().__init__()

        #Setting geometry attributes of MainWindow
        self.left = 10
        self.top = 10
        self.width = 720
        self.height = 480
        self.project_num = 0
        self.project_name = "Calib_"
        self.project_list = []

        #Design GUI elements
        self.initUI()

        #Declare Camera, calibration instances
        self.camera = camera
        self.calib = calibration
        self.criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,
                         30, 0.001)

    #GUI elements design
    def initUI(self):

        # Matplotlib figure to draw image frame
        self.figure = plt.figure()

        # Window canvas to host matplotlib figure
        self.canvas = FigureCanvas(self.figure)

        # ToolBar to navigate image frame
        self.toolbar = NavigationToolbar(self.canvas, self)
        self.toolbar.hide()

        #Setting Title and StatusBar
        self.setWindowTitle('Ứng dụng kiểm chuẩn máy ảnh số phổ thông')
        self.statusBar().showMessage("Trạng thái tác vụ: ")

        #Setting main menu
        mainMenu = self.menuBar()
        fileMenu = mainMenu.addMenu('Thao tác tệp tin')
        toolsMenu = mainMenu.addMenu('Xử lý dữ liệu')
        viewMenu = mainMenu.addMenu('Xem thông tin')
        editMenu = mainMenu.addMenu('Biên tập')
        searchMenu = mainMenu.addMenu('Tìm kiếm')
        helpMenu = mainMenu.addMenu('Trợ giúp')

        #Setting fileMenu
        fileMenu.addAction('Thiết lập dự án mới', self.on_file_setnewproject)
        fileMenu.addAction('Mở kho ảnh', self.on_open_imagestore)

        #Setting ToolsMenu
        toolsMenu.addAction('Tiền xử lý ảnh', self.on_preprocessing_image)
        toolsMenu.addAction('Kiểm chuẩn máy ảnh', self.on_calibrate_image)

        #Setting viewMenu
        viewMenu.addAction('Thông tin dự án', self.on_view_project_info)
        viewMenu.addAction('Dữ liệu kiểm chuẩn', self.on_view_calib_info)

        # Create central Widget
        self.central_widget = QWidget()

        # Just some button
        self.button = QPushButton('Chụp ảnh', self.central_widget)
        self.button1 = QPushButton('Phóng ảnh', self.central_widget)
        self.button2 = QPushButton('Điều hướng ảnh', self.central_widget)
        self.button3 = QPushButton('Về gốc', self.central_widget)

        #Put Buttons to HBoxLayout
        hBox = QHBoxLayout()
        hBox.addWidget(self.button)
        hBox.addWidget(self.button1)
        hBox.addWidget(self.button2)
        hBox.addWidget(self.button3)

        # set QVBoxLayout as the layout
        self.layout = QVBoxLayout(self.central_widget)
        self.layout.addWidget(self.toolbar)
        self.layout.addWidget(self.canvas)

        #Add hBoxLayout to VBoxLayout
        self.layout.addLayout(hBox)

        self.textedit = QTextEdit()
        font = QtGui.QFont()
        font.setPointSize(9)
        self.textedit.setFont(font)
        self.layout.addWidget(self.textedit)

        #Set central widget
        self.setCentralWidget(self.central_widget)

        # Events handling
        self.button.clicked.connect(self.plot)
        self.button1.clicked.connect(self.zoom)
        self.button2.clicked.connect(self.pan)
        self.button3.clicked.connect(self.home)

    #Events processing methods

    # Open image store
    @QtCore.pyqtSlot()
    def on_open_imagestore(self):
        #extract file name in a directory
        self.statusBar().showMessage(
            "Chương trình đang xử lý tác vụ: Mở kho ảnh")
        filepath = QFileDialog().getExistingDirectory(
            self, "Chọn đường dẫn tới kho ảnh")
        if filepath:
            images = Path(filepath).glob('*.jpg')
            imagelist = [str(image) for image in images]
            self.statusBar().showMessage(str("Kho ảnh nằm tại: ") + filepath)
            # check filename list and display first image
            if len(imagelist) > 2:
                #self.calib.imagelist = imagelist
                if self.project_num == 0:
                    self.project_num += 1
                    self.calib.imagelist = imagelist
                    self.calib.project_name = str("Calib_") + str(
                        self.project_num)
                else:
                    self.calib.project_name = str("Calib_") + str(
                        self.project_num)
                    self.project_list.append(self.calib)
                    self.project_num += 1
                    newcalib = Calibration()
                    newcalib.project_num = self.project_num
                    newcalib.imagelist = imagelist
                    self.calib = newcalib

                img = cv2.imread(imagelist[0])
                pic = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
                plt.imshow(pic)
                self.canvas.draw()
            else:
                self.statusBar().showMessage(
                    "Không có ảnh trong thư mục được chọn!")
        else:
            self.statusBar().showMessage(filepath)

    #Setting info for new project
    @QtCore.pyqtSlot()
    def on_file_setnewproject(self):
        self.statusBar().showMessage(
            "Chương trình đang xử lý tác vụ: Thiết lập tham số cho dự án mới")

    #Preprocessing images of current project
    @QtCore.pyqtSlot()
    def on_preprocessing_image(self):

        if len(self.calib.imagelist) > 0:
            self.calib.refresh()
            self.statusBar().showMessage(
                "Chương trình đang xử lý tác vụ: Tiền xử lý ảnh - ")
            #self.textedit.clear()
            self.textedit.append("")
            self.textedit.append("***********************************")
            #self.textedit.append("")
            self.textedit.append(
                str("Tiền xử lý ảnh dự án Calib_") + str(self.project_num) +
                str(":"))
            self.thread_image_preprocessing = Calib_Preprocess_Thread(
                self.calib)
            self.thread_image_preprocessing.sig1.connect(
                self.on_image_preprocessing_display)
            self.thread_image_preprocessing.sig2.connect(
                self.on_image_preprocessed_display)
            self.thread_image_preprocessing.sig3.connect(
                self.on_image_preprocessed_result)
            self.thread_image_preprocessing.start()

    #Calibrate current project
    @QtCore.pyqtSlot()
    def on_calibrate_image(self):
        if self.calib.preprocessing_done == True:
            # Calibrate if calib has not done
            if self.calib.calibrated == False:
                self.thread_calib = Calib_Calibrate_Thread(self.calib)
                self.thread_calib.sig1.connect(self.on_calibtation_processed)
                self.thread_calib.start()

    @QtCore.pyqtSlot()
    def on_view_project_info(self):
        pass

    @QtCore.pyqtSlot()
    def on_view_calib_info(self):
        calib_list = []
        if len(self.project_list) > 0:
            for calib in self.project_list:
                clone_calib = calib.clone()
                calib_list.append(clone_calib)

        if self.calib.calibrated == True:
            clone_calib = self.calib.clone()
            clone_calib.project_name = str("Calib_") + str(self.project_num)
            calib_list.append(clone_calib)

        if len(calib_list) > 0:
            self.calib_info = Total_Calib_Info(calib_list)
            self.calib_info.show()
        else:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Information)
            msg.setText("Chưa có dự án kiểm chuẩn được thực hiện hoàn chỉnh!")
            msg.setWindowTitle("Thông báo")
            msg.exec_()

    def home(self):
        self.toolbar.home()

    def zoom(self):
        self.toolbar.zoom(0.5)

    def pan(self):
        self.toolbar.pan()

    def plot(self):
        #Moving Camera class to a thread and emit signal from that thread
        self.thread1 = Frame_Capture_Thread(self.camera)
        self.thread1.sig1.connect(self.on_frame)
        self.thread1.start()

    def on_frame(self, frame):
        plt.imshow(frame)
        self.canvas.draw()

    #Update current image name being processed: fname is image name obtained from signal sig1 of Calib_Preprocess_Thread
    def on_image_preprocessing_display(self, fname):
        filename = fname.split('\\')[-1]
        filename_message = str(
            "Chương trình đang xử lý tác vụ: Tiền xử lý ảnh - đang xử lý file ảnh: "
        ) + filename
        self.statusBar().showMessage(filename_message)
        self.textedit.append(
            str("Tiền xử lý ảnh - đang xử lý file ảnh: ") + str(filename) +
            str("..."))

    #Update last processed image  on display : pic is image data obtained from signal sig2 of Calib_Preprocess_Thread
    def on_image_preprocessed_display(self, pic):
        plt.imshow(pic)
        self.canvas.draw()

    #Update preprocessing result -
    def on_image_preprocessed_result(self, result):
        redColor = QtGui.QColor(255, 0, 0)
        blackColor = QtGui.QColor(0, 0, 0)
        ret = result[0]
        fname = result[1]
        filename = fname.split('\\')[-1]
        if ret == True:
            self.textedit.setTextColor(blackColor)
            msg = str("Xử lý xong ảnh ") + filename + str(
                " - ảnh hợp lệ cho kiểm chuẩn!")
            self.textedit.append(msg)
        else:
            self.textedit.setTextColor(redColor)
            msg = str("Xử lý xong ảnh ") + filename + str(
                " - ảnh không hợp lệ cho kiểm chuẩn!")
            self.textedit.append(msg)
            self.textedit.setTextColor(blackColor)

        if self.calib.preprocessing_done == True:
            msg = str("Tổng số ảnh tiền xử lý: ") + str(
                self.calib.processed_count)
            self.textedit.append(msg)
            msg = str("Số ảnh hợp lệ cho kiểm chuẩn: ") + str(
                self.calib.validated_count)
            self.textedit.append(msg)
            msg = str("Số ảnh không hợp lệ cho kiểm chuẩn: ") + str(
                self.calib.processed_count - self.calib.validated_count)
            self.textedit.append(msg)
            self.statusBar().showMessage(
                "Hoàn thành tác vụ tiền xử lý ảnh - dự án Calib_" +
                str(self.project_num))

    def on_calibtation_processed(self):
        self.calib.project_name = str("Calib_") + str(self.project_num)
        self.calib_info_window = Calib_Info(self.calib)
        self.calib_info_window.show()
Пример #15
0
class window_graph(QDialog):
    def __init__(self,data,Fs,status,methodValues=0,deletedEpochs=0,totalepochs=0):         
        QDialog.__init__(self);
        loadUi('graph.ui',self);
        self.setWindowIcon(QtGui.QIcon("logo.png"))
                
        self.mySignal=data
        self.myFs=Fs
        self.status=status
        self.methodSignal=methodValues
        self.deletedEpochs=deletedEpochs
        self.numEpochs=totalepochs
        
        self.channels, self.points = shape(self.mySignal)
        #self.time_array=arange(0,self.points/self.myFs,1/self.myFs)
        
        self.button_zoom.clicked.connect(self.zoom)
        self.button_pan.clicked.connect(self.pan)
        self.button_home.clicked.connect(self.home)
        
        self.figure = Figure(figsize=(5,4), dpi=100)
        self.canvas = FigureCanvas(self.figure)
        self.axes=self.figure.add_subplot(111)
        self.toolbar=NavigationToolbar(self.canvas,self)
        self.toolbar.hide()
        
        layout=QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)
        self.field_graph.setLayout(layout)
        self.axes.clear()
        self.canvas.draw()
        self.plot()
        
    def plot(self):
        legends=['Ch 1','Ch 2','Ch 3','Ch 4','Ch 5','Ch 6','Ch 7','Ch 8']
        if self.status==1:
            for c in range(self.channels):
                self.axes.plot(self.mySignal[c,::])
            self.axes.legend(legends)   
            self.axes.set_title('Señal original')
        if self.status==2:
            r=[]
            for c in range(self.channels):
                r.append(c*150)
                self.axes.plot(self.mySignal[c,::]+c*150)
            self.axes.set_yticklabels(legends)
            self.axes.set_yticks(r)
            self.axes.set_title('Señal filtrada')
            
        if self.status==3:
            r=[]
            for c in range(self.channels):
                r.append(c*150)
                self.axes.plot(self.mySignal[c,::]+c*150)
                self.axes.plot(self.methodSignal[c,::]+c*150,'r')
                
            self.axes.set_yticklabels(legends)
            self.axes.set_yticks(r)   
            self.axes.set_title('Eliminación de épocas') 
            msg = QMessageBox(self)
            msg.setIcon(QMessageBox.Information)
            msg.setText("Se eliminaron las épocas : "+'  '.join(str(ep) for ep in self.deletedEpochs))
            msg.setWindowTitle("Épocas eliminadas")
            msg.setInformativeText("Épocas iniciales: "+str(self.numEpochs)+'\tÉpocas restantes: '+str(self.numEpochs-len(self.deletedEpochs)))
            msg.show();

            
        self.axes.set_ylabel('Voltaje [uV]') 
        self.axes.set_xlabel('Muestras')  
        self.axes.grid(True)
        self.axes.set_xlim([0,4000])
        


        self.canvas.draw()
 
    def home(self):
        self.toolbar.home()
    def zoom(self):
        self.toolbar.zoom()
    def pan(self):
        self.toolbar.pan()
Пример #16
0
class PulsedNMR(QMainWindow, Ui_PulsedNMR):
    rates = {0: 25.0e3, 1: 50.0e3, 2: 250.0e3, 3: 500.0e3, 4: 2500.0e3}

    def __init__(self):
        super(PulsedNMR, self).__init__()
        self.setupUi(self)
        self.rateValue.addItems(['25', '50', '250', '500', '2500'])
        # IP address validator
        rx = QRegExp(
            '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$'
        )
        self.addrValue.setValidator(QRegExpValidator(rx, self.addrValue))
        # state variable
        self.idle = True
        # number of samples to show on the plot
        self.size = 50000
        # buffer and offset for the incoming samples
        self.buffer = bytearray(8 * self.size)
        self.offset = 0
        self.data = np.frombuffer(self.buffer, np.complex64)
        # create figure
        figure = Figure()
        figure.set_facecolor('none')
        self.axes = figure.add_subplot(111)
        self.canvas = FigureCanvas(figure)
        self.plotLayout.addWidget(self.canvas)
        # create navigation toolbar
        self.toolbar = NavigationToolbar(self.canvas, self.plotWidget, False)
        # remove subplots action
        actions = self.toolbar.actions()
        self.toolbar.removeAction(actions[7])
        self.plotLayout.addWidget(self.toolbar)
        # create TCP socket
        self.socket = QTcpSocket(self)
        self.socket.connected.connect(self.connected)
        self.socket.readyRead.connect(self.read_data)
        self.socket.error.connect(self.display_error)
        # connect signals from buttons and boxes
        self.startButton.clicked.connect(self.start)
        self.freqValue.valueChanged.connect(self.set_freq)
        self.awidthValue.valueChanged.connect(self.set_awidth)
        self.deltaValue.valueChanged.connect(self.set_delta)
        self.rateValue.currentIndexChanged.connect(self.set_rate)
        # set rate
        self.rateValue.setCurrentIndex(2)
        # create timer for the repetitions
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.fire)

    def start(self):
        if self.idle:
            self.startButton.setEnabled(False)
            self.socket.connectToHost(self.addrValue.text(), 1001)
        else:
            self.idle = True
            self.timer.stop()
            self.socket.close()
            self.offset = 0
            self.startButton.setText('Start')
            self.startButton.setEnabled(True)

    def connected(self):
        self.idle = False
        self.set_freq(self.freqValue.value())
        self.set_rate(self.rateValue.currentIndex())
        self.set_awidth(self.awidthValue.value())
        self.fire()
        self.timer.start(self.deltaValue.value())
        self.startButton.setText('Stop')
        self.startButton.setEnabled(True)

    def read_data(self):
        size = self.socket.bytesAvailable()
        if self.offset + size < 8 * self.size:
            self.buffer[self.offset:self.offset +
                        size] = self.socket.read(size)
            self.offset += size
        else:
            self.buffer[self.offset:8 *
                        self.size] = self.socket.read(8 * self.size -
                                                      self.offset)
            self.offset = 0
            # plot the signal envelope
            self.curve.set_ydata(np.real(self.data))
            self.canvas.draw()

    def display_error(self, socketError):
        if socketError == QAbstractSocket.RemoteHostClosedError:
            pass
        else:
            QMessageBox.information(self, 'PulsedNMR',
                                    'Error: %s.' % self.socket.errorString())
        self.startButton.setText('Start')
        self.startButton.setEnabled(True)

    def set_freq(self, value):
        if self.idle: return
        self.socket.write(struct.pack('<I', 0 << 28 | int(1.0e6 * value)))

    def set_rate(self, index):
        # time axis
        rate = float(PulsedNMR.rates[index])
        time = np.linspace(0.0, (self.size - 1) * 1000.0 / rate, self.size)
        # reset toolbar
        self.toolbar.home()
        self.toolbar._views.clear()
        self.toolbar._positions.clear()
        # reset plot
        self.axes.clear()
        self.axes.grid()
        # plot zeros and get store the returned Line2D object
        self.curve, = self.axes.plot(time, np.zeros(self.size))
        x1, x2, y1, y2 = self.axes.axis()
        # set y axis limits
        self.axes.axis((x1, x2, -0.1, 0.4))
        self.axes.set_xlabel('time, ms')
        self.canvas.draw()
        # set repetition time
        minimum = self.size / rate * 2000.0
        if minimum < 100.0: minimum = 100.0
        self.deltaValue.setMinimum(minimum)
        self.deltaValue.setValue(minimum)
        if self.idle: return
        self.socket.write(struct.pack('<I', 1 << 28 | index))

    def set_awidth(self, value):
        if self.idle: return
        self.socket.write(struct.pack('<I', 2 << 28 | int(1.0e1 * value)))

    def set_delta(self, value):
        if self.idle: return
        self.timer.stop()
        self.timer.start(value)

    def fire(self):
        if self.idle: return
        self.socket.write(struct.pack('<I', 3 << 28))
Пример #17
0
class MyTableWidget(QWidget):

    sig = pyqtSignal(list)
    sigload = pyqtSignal(list)

    def __init__(self, parent):
        super(QWidget, self).__init__(parent)

        self.videosettingschanged = False

        #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
        #-------------- Make the input widges --------------#
        #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#

        # ------------------------#
        # Main buttons ans inputs #
        # ------------------------#

        # Push button to load telemac 2d output
        Load = QPushButton('Load .slf or .npy')
        Load.clicked.connect(self.openFileNameDialog)
        Load.setToolTip('Load the output from a TELEMAC 2D simulation')
        Load.setStyleSheet("""
        QPushButton {
            border-width: 25px solid white;
            border-radius: 5px;
            color: rgb(180,180,180);
            background-color: rgb(55, 55, 60);
            min-height: 40px;
            }
        QPushButton:pressed {
            color: rgb(120,120,120);
            background-color: rgb(75, 75, 80);
            }
        """)
        Load.setFixedWidth(150)

        # label to show the path of the loaded selafin file
        self.Path_label = QLabel()
        self.Path_label.setStyleSheet("""
        QLabel {
            color: rgb(180,180,180);
            padding: 10px;
            }
        """)

        # Spin box for X
        X_label = QLabel('X-coordinate:')
        X_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        X_label.setStyleSheet("""
        QLabel {
            color: rgb(180,180,180);
            background-color: rgb(35, 35, 35);
            }
        """)
        Y_label = QLabel('Y-coordinate:')
        Y_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        Y_label.setStyleSheet("""
        QLabel {
            color: rgb(180,180,180);
            background-color: rgb(35, 35, 35);
            }
        """)

        # Spin box for Y
        self.X_box = QLabel(' ')
        self.X_box.setStyleSheet("""
        QLabel {
            color: rgb(180,180,180);
            background-color: rgb(35, 35, 35);
            max-height: 30px;
            min-width: 160px;
            }
        """)
        self.Y_box = QLabel(' ')
        self.Y_box.setStyleSheet("""
        QLabel {
            color: rgb(180,180,180);
            background-color: rgb(35, 35, 35);
            max-height: 30px;
            min-width: 160px;
            }
        """)

        # date and time
        start_time = QLabel('Start Date & Time:')
        start_time.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        start_time.setStyleSheet("""
            QLabel {
            color: rgb(180,180,180);
            background-color: rgb(35, 35, 35);
            }""")
        end_time = QLabel('End Date & Time:')
        end_time.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        end_time.setStyleSheet("""
            QLabel {
            color: rgb(180,180,180);
            background-color: rgb(35, 35, 35);
            }""")

        self.start_time = QLineEdit()
        self.start_time.setStyleSheet("""
        QLineEdit {
        color: rgb(180,180,180);
        background-color: rgb(25,25,25);
        }""")
        self.end_time = QLineEdit()
        self.end_time.setStyleSheet("""
        QLineEdit {
        color: rgb(180,180,180);
        background-color: rgb(25,25,25);
        }""")

        # Push button to load telemac 2d output
        self.PlotSeries = QPushButton('Plot Series')
        self.PlotSeries.setDisabled(True)
        self.PlotSeries.clicked.connect(self.plotTimeSeries)
        self.PlotSeries.setToolTip('Plot time series of surface elevation at selected area.')
        self.PlotSeries.setStyleSheet("""
        QPushButton {
            border-width: 25px solid white;
            border-radius: 5px;
            color: rgb(180,180,180);
            background-color: rgb(55, 55, 60);
            min-height: 40px;
            }
        QPushButton:pressed {
            color: rgb(120,120,120);
            background-color: rgb(75, 75, 80);
            }
        QPushButton:disabled {
            color: rgb(50,50,50);
            background-color: rgb(25, 25, 25);
            }
        """)

        # Push button to load telemac 2d output
        self.Video = QPushButton('Generate a video')
        self.Video.setDisabled(True)
        self.Video.clicked.connect(self.plotVideo)
        self.Video.setToolTip('Generate a video of the water surface elevation over time.')
        self.Video.setStyleSheet("""
        QPushButton {
            border-width: 25px solid white;
            border-radius: 5px;
            color: rgb(180,180,180);
            background-color: rgb(55, 55, 60);
            min-height: 40px;
            }
        QPushButton:pressed {
            color: rgb(120,120,120);
            background-color: rgb(75, 75, 80);
            }
        QPushButton:disabled {
            color: rgb(50,50,50);
            background-color: rgb(25, 25, 25);
            }
        """)

        # Push button to load telemac 2d output
        self.VideoSettings = QPushButton('Video settings')
        #self.VideoSettings.setDisabled(True)
        self.VideoSettings.clicked.connect(self.setVideoSettings)
        self.VideoSettings.setToolTip('Change the settings of the video export.')
        self.VideoSettings.setStyleSheet("""
        QPushButton {
            border-width: 25px solid white;
            border-radius: 5px;
            color: rgb(180,180,180);
            background-color: rgb(55, 55, 60);
            min-height: 40px;
            }
        QPushButton:pressed {
            color: rgb(120,120,120);
            background-color: rgb(75, 75, 80);
            }
        QPushButton:disabled {
            color: rgb(50,50,50);
            background-color: rgb(25, 25, 25);
            }
        """)

        # Push button to plot a variable along the mesh
        self.PlotMesh = QPushButton('Plot variable on mesh')
        self.PlotMesh.setDisabled(True)
        self.PlotMesh.clicked.connect(self.plotMeshVar)
        self.PlotMesh.setToolTip('Generate a map with a given variable.')
        self.PlotMesh.setStyleSheet("""
        QPushButton {
            border-width: 25px solid white;
            border-radius: 5px;
            color: rgb(180,180,180);
            background-color: rgb(55, 55, 60);
            min-height: 40px;
            }
        QPushButton:pressed {
            color: rgb(120,120,120);
            background-color: rgb(75, 75, 80);
            }
        QPushButton:disabled {
            color: rgb(50,50,50);
            background-color: rgb(25, 25, 25);
            }
        """)

        # Push button to reload general mesh view
        self.ReloadMesh = QPushButton('Reload mesh view')
        self.ReloadMesh.setDisabled(True)
        self.ReloadMesh.clicked.connect(self.reloadMesh)
        self.ReloadMesh.setToolTip('Reload the general mesh view.')
        self.ReloadMesh.setStyleSheet("""
        QPushButton {
            border-width: 25px solid white;
            border-radius: 5px;
            color: rgb(180,180,180);
            background-color: rgb(55, 55, 60);
            min-height: 40px;
            }
        QPushButton:pressed {
            color: rgb(120,120,120);
            background-color: rgb(75, 75, 80);
            }
        QPushButton:disabled {
            color: rgb(50,50,50);
            background-color: rgb(25, 25, 25);
            }
        """)


        # Push button to open dialog to locate a value
        self.LocateValue = QPushButton('Locate value')
        self.LocateValue.setDisabled(True)
        self.LocateValue.clicked.connect(self.locateValue)
        self.LocateValue.setToolTip('Locate a value on the mesh (e.g. maximum h in mangroves).')
        self.LocateValue.setStyleSheet("""
        QPushButton {
            border-width: 25px solid white;
            border-radius: 5px;
            color: rgb(180,180,180);
            background-color: rgb(55, 55, 60);
            min-height: 40px;
            }
        QPushButton:pressed {
            color: rgb(120,120,120);
            background-color: rgb(75, 75, 80);
            }
        QPushButton:disabled {
            color: rgb(50,50,50);
            background-color: rgb(25, 25, 25);
            }
        """)


        self.LoadPrevious = QCheckBox('Ignore previously saved meshes')
        self.LoadPrevious.setChecked(True)
        self.LoadPrevious.setToolTip('Ignore existing files in previously_loaded_meshes and copy loaded files to this directory.')
        self.LoadPrevious.setStyleSheet("""
        QCheckBox {
         color: rgb(120,120,120);
         background-color: rgb(35,35,35);
        }
        """)

        self.RemovePrevious = QCheckBox('Clear previously saved meshes')
        self.RemovePrevious.setChecked(True)
        self.RemovePrevious.setToolTip('Clear all files tores in previously_loaded_meshes when closing.')
        self.RemovePrevious.setStyleSheet("""
        QCheckBox {
         color: rgb(120,120,120);
         background-color: rgb(35,35,35);
        }
        """)


        # ------------#
        # Time Series #
        # ------------#

        # time series objects
        self.WSE_series = TimeSeries('Water Surface Elevation [m]')
        self.Vel_series = TimeSeries('Water Velocity [m/s]')

        # ----------------------#
        # Main window with mesh #
        # ----------------------#

        # FigureCanvas to show the mesh in
        self.figure = plt.figure()
        self.figure.set_facecolor((45/255, 45/255, 45/255))
        self.canvas = FigureCanvas(self.figure)
        self.canvas.setFixedSize(700,700)

        # buttons to zoom and pan
        self.zoombut = QPushButton()
        self.zoombut.setCheckable(True)
        self.zoombut.setEnabled(False)
        im = QIcon('support_files/zoom.png')
        self.zoombut.setIcon(im)
        self.zoombut.clicked.connect(self.zoom)
        self.zoombut.setStyleSheet("""
        QPushButton {
            border-width: 25px solid white;
            border-radius: 5px;
            color: rgb(180,180,180);
            background-color: rgb(55, 55, 60);
            min-height: 40px;
            }
        QPushButton:checked {
            color: rgb(25,25,25);
            background-color: rgb(255, 128, 0);
            }
        """)

        self.panbut = QPushButton()
        self.panbut.setCheckable(True)
        self.panbut.setEnabled(False)
        im = QIcon('support_files/pan.png')
        self.panbut.setIcon(im)
        self.panbut.clicked.connect(self.pan)
        self.panbut.setStyleSheet("""
        QPushButton {
            border-width: 25px solid white;
            border-radius: 5px;
            color: rgb(180,180,180);
            background-color: rgb(55, 55, 60);
            min-height: 40px;
            }
        QPushButton:checked {
            color: rgb(25,25,25);
            background-color: rgb(255, 128, 0);
            }
        """)

        self.locbut = QPushButton()
        self.locbut.setCheckable(True)
        self.locbut.setEnabled(False)
        im = QIcon('support_files/loc.png')
        self.locbut.setIcon(im)
        self.locbut.clicked.connect(self.loc)
        self.locbut.setStyleSheet("""
        QPushButton {
            border-width: 25px solid white;
            border-radius: 5px;
            color: rgb(180,180,180);
            background-color: rgb(55, 55, 60);
            min-height: 40px;
            }
        QPushButton:checked {
            color: rgb(25,25,25);
            background-color: rgb(255, 128, 0);
            }
        """)
        self.canvas.mpl_connect("button_press_event", self.on_press)
        self.record_pressing_event = False

        self.addcoor = QPushButton('xy')
        self.addcoor.setEnabled(False)
        self.addcoor.clicked.connect(self.addCoorToMap)
        self.addcoor.setStyleSheet("""
        QPushButton {
            border-width: 25px solid white;
            border-radius: 5px;
            color: rgb(180,180,180);
            background-color: rgb(55, 55, 60);
            min-height: 40px;
            }
        QPushButton:pressed {
            color: rgb(120,120,120);
            background-color: rgb(75, 75, 80);
            }
        """)

        self.homebut = QPushButton()
        self.homebut.setEnabled(False)
        im = QIcon('support_files/home.png')
        self.homebut.setIcon(im)
        self.homebut.clicked.connect(self.home)
        self.homebut.setStyleSheet("""
        QPushButton {
            border-width: 25px solid white;
            border-radius: 5px;
            color: rgb(180,180,180);
            background-color: rgb(55, 55, 60);
            min-height: 40px;
            }
        QPushButton:pressed {
            color: rgb(120,120,120);
            background-color: rgb(75, 75, 80);
            }
        """)

        self.toolbar = NavigationToolbar(self.canvas, self)
        self.toolbar.hide()


        # label to show bathymetry
        self.Bath_label = QLabel()
        self.Bath_label.setFixedWidth(125)
        self.Bath_label.setStyleSheet("""
        QLabel {
            color: rgb(255,128,0);
            font-size: 8pt;
            background-color: rgb(35, 35, 35);
            }
        """)

        # label to show bathymetry
        self.Station_label = QLabel()
        self.Station_label.setFixedWidth(125)
        self.Station_label.setStyleSheet("""
        QLabel {
            color: rgb(255,128,0);
            font-size: 10pt;
            background-color: rgb(35, 35, 35);
            }
        """)




        #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
        #-------------- Organize and set the layout --------------#
        #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#

        self.grid = QGridLayout()
        self.grid.setSpacing(10)

        self.grid.addWidget(self.canvas, 0, 0, 9, 10)
        self.grid.addWidget(self.zoombut, 9, 0, 1, 1)
        self.grid.addWidget(self.panbut, 9, 1, 1, 1)
        self.grid.addWidget(self.locbut, 9, 2, 1, 1)
        self.grid.addWidget(self.addcoor, 9 , 3, 1, 1)
        self.grid.addWidget(self.homebut, 9, 4, 1, 1)

        self.grid.addWidget(self.Bath_label, 9, 5)
        self.grid.addWidget(self.Station_label, 9, 6)

        self.grid.addWidget(Load,0,11,1,1)
        self.grid.addWidget(self.Path_label, 0,12,1,3)

        self.grid.addWidget(X_label, 1,11,1,1)
        self.grid.addWidget(Y_label, 2,11,1,1)
        self.grid.addWidget(self.X_box, 1,12,1,1)
        self.grid.addWidget(self.Y_box, 2,12,1,1)

        self.grid.addWidget(start_time, 1, 13)
        self.grid.addWidget(end_time, 2, 13)
        self.grid.addWidget(self.start_time, 1, 14)
        self.grid.addWidget(self.end_time, 2, 14)

        self.box_buttons = QVBoxLayout()
        self.box_buttons.addWidget(self.PlotSeries)
        self.box_buttons.addWidget(self.Video)
        self.box_buttons.addWidget(self.VideoSettings)
        self.box_buttons.addWidget(self.PlotMesh)
        self.box_buttons.addWidget(self.ReloadMesh)
        self.box_buttons.addWidget(self.LocateValue)
        self.box_buttons.addWidget(self.LoadPrevious)
        self.box_buttons.addWidget(self.RemovePrevious)
        self.box_buttons.addStretch()

        self.grid.addLayout(self.box_buttons, 0, 15, 10, 1)

        self.grid.addWidget(self.WSE_series,3,11,3,4)
        self.grid.addWidget(self.Vel_series,6,11,3,4)

        self.setLayout(self.grid)

        self.show()

        #-------------------------------------#
        #-------------- Methods --------------#
        #-------------------------------------#


    def openFileNameDialog(self):
        options = QFileDialog.Options()
        self.fileName, self.cancel = QFileDialog.getOpenFileName(self,"QFileDialog.getOpenFileName()", "","Numpy files (*.npy);; Selafin Files (*.slf)", options=options)
        print('Loading file...')

        try:
            self.loadMesh()
            self.Path_label.setText(self.fileName.split('/')[-1])

        except:
            self.Path_label.setText('Something went wrong!')
            print("Unexpected error:", sys.exc_info()[0])

    def loadMesh(self):

        if self.LoadPrevious.isChecked(): ignore_previously_saved_files = True
        else : ignore_previously_saved_files = False

        self.name, self.ax, self.tc = loadMeshFromSLF(self.fileName, self.figure, self.canvas, ignore_previously_saved_files = ignore_previously_saved_files, return_tc = True)
        self.canvas.draw()
        self.loadArrays()

        self.zoombut.setEnabled(True)
        self.panbut.setEnabled(True)
        self.locbut.setEnabled(True)
        self.homebut.setEnabled(True)
        self.addcoor.setEnabled(True)

        self.Video.setEnabled(True)
        self.LocateValue.setEnabled(True)
        self.VideoSettings.setEnabled(True)
        self.PlotSeries.setEnabled(True)
        self.PlotMesh.setEnabled(True)


    def loadArrays(self):
        fn = str('./previously_loaded_meshes/'+self.name)
        self.fn = fn

        data = np.load(fn + '_data.npy')
        X = np.load(fn + '_x.npy')
        Y = np.load(fn + '_y.npy')
        self.ikle = np.load(fn + '_ikle.npy')
        self.times = np.load(fn + '_times.npy')

        # get properties
        U = data[0]
        V = data[1]
        H = data[2]
        B = data[3]
        N = data[4]

        self.U = U
        self.V = V
        self.Vel = np.sqrt(U**2+V**2)
        self.H = H
        self.SE = H+B
        self.B = B
        self.N = N
        self.X = X
        self.Y = Y

        self.XY = np.empty([np.shape(X)[0], 2])
        self.XY[:,0], self.XY[:,1] = X, Y

        # time series
        start_date = np.datetime64('2019-10-07T04:00:00')
        T = np.array([start_date], dtype = np.datetime64)
        for i in range(1,np.shape(self.times)[0]):
            td = np.timedelta64(int(self.times[i]),'s')
            T = np.append(T,start_date + td)
        self.T = T

        start_t = str(self.T[0])
        self.start_time.setText(start_t)

        end_t = str(self.T[-1])
        self.end_time.setText(end_t)

    def plotTimeSeries(self):

        start_time = np.datetime64(self.start_time.text())
        end_time = np.datetime64(self.end_time.text())

        x = float(self.X_box.text())
        y = float(self.Y_box.text())

        X = self.XY[:,0]
        Y = self.XY[:,1]

        # find the closest node to the requested lat and lon
        neighxy= getNeighbor([x, y], self.XY, return_index = False)
        x_node, y_node = neighxy
        rx = np.where(X == x_node)
        ry = np.where(Y == y_node)
        i = np.intersect1d(rx,ry)[0]

        self.WSE_series.plotSeries(T = self.T, var = self.SE[i,:], t0 = start_time, t1 = end_time, x = X[i], y = Y[i])
        self.Vel_series.plotSeries(T = self.T, var = self.Vel[i,:], t0 = start_time, t1 = end_time, x = X[i], y = Y[i])

        self.i = i

        try: self.scat2.remove()
        except: pass
        self.scat2 = self.ax.scatter(neighxy[0], neighxy[1], s = 25, color = (1, 1, 1, 0), edgecolor = (1, 128/255, 0), zorder = 1e9)
        self.canvas.draw()

        self.X_box.setText('%.2f' % neighxy[0])
        self.Y_box.setText('%.2f' % neighxy[1])
        self.X_box.setStyleSheet("""
        QLabel {
            color: rgb(255,128,0);
            background-color: rgb(35, 35, 35);
            max-height: 30px;
            min-width: 160px;
            }
        """)
        self.Y_box.setStyleSheet("""
        QLabel {
            color: rgb(255,128,0);
            background-color: rgb(35, 35, 35);
            max-height: 30px;
            min-width: 160px;
            }
        """)

        bath_str = '%.2f' % self.B[i,0]
        frict_str = '%.3f' % self.N[i,0]
        i_str = str(i)
        self.Bath_label.setText('Bath: ' + bath_str + " m\nManning's n: " + frict_str + '\nIndex: ' + i_str)

    def setVideoSettings(self):
        dlg = VideoSettingDialog(self.ax.get_xlim() + self.ax.get_ylim())

        if self.videosettingschanged:
            if self.videolims != None:
                dlg.SetWinLim.setChecked(True)
                dlg.WinLeft.setValue(self.videolims[0])
                dlg.WinRight.setValue(self.videolims[1])
                dlg.WinTop.setValue(self.videolims[2])
                dlg.WinBot.setValue(self.videolims[3])

            dlg.Min.setValue(self.videomin)
            dlg.Max.setValue(self.videomax)

        dlg.exec_( )

        if dlg.good_exit:
            self.videosettingschanged = True
            self.videovar = dlg.var
            self.videomin = dlg.min
            self.videomax = dlg.max
            self.videolims = dlg.lims
            if len(np.unique(self.videolims)) == 1:
                self.videolims = None

    def plotVideo(self):

        if self.videosettingschanged == False:
            self.videovar = 0
            self.videomin = -1
            self.videomax = 5
            self.videolims = None


        options = QFileDialog.Options()
        fn, _ = QFileDialog.getSaveFileName(self,"QFileDialog.getSaveFileName()","","All Files (*);;Text Files (*.txt)", options=options)

        if fn:
            self.thread = VideoThread()
            self.sig.connect(self.thread.on_source)
            self.sig.emit([self.fn, fn, [self.videovar, self.videomin, self.videomax, self.videolims]])
            self.thread.start()
            self.thread.sig1.connect(self.on_info)

    def on_info(self, info):
        self.Path_label.setText(str(info))

    def home(self):
        self.toolbar.home()

    def zoom(self):
        self.panbut.setChecked(False)
        self.locbut.setChecked(False)
        if self.zoombut.isChecked():
            self.toolbar.zoom()
            self.record_pressing_event = False

    def pan(self):
        self.zoombut.setChecked(False)
        self.locbut.setChecked(False)
        if self.panbut.isChecked():
            self.toolbar.pan()
            self.record_pressing_event = False

    def loc(self):
        self.zoombut.setChecked(False)
        self.panbut.setChecked(False)
        if self.toolbar._active == "PAN":
            self.toolbar.pan()
        elif self.toolbar._active == "ZOOM":
            self.toolbar.zoom()
        if self.locbut.isChecked(): self.record_pressing_event = True
        else: self.record_pressing_event = False

    def on_press(self, event):
        if self.record_pressing_event:
            self.X_box.setText('%.2f' % event.xdata)
            self.Y_box.setText('%.2f' % event.ydata)

            self.X_box.setStyleSheet("""
            QLabel {
                color: rgb(180,180,180);
                background-color: rgb(35, 35, 35);
                max-height: 30px;
                min-width: 160px;
                }
            """)
            self.Y_box.setStyleSheet("""
            QLabel {
                color: rgb(180,180,180);
                background-color: rgb(35, 35, 35);
                max-height: 30px;
                min-width: 160px;
                }
            """)

            try: self.scat1.remove()
            except: pass
            self.scat1 = self.ax.scatter(event.xdata, event.ydata, s = 25, color = (1, 128/255, 0), zorder = 1e9)
            self.canvas.draw()

            self.Station_label.setText('')

    def addCoorToMap(self):
        dlg = AddCoorDialog(None)
        dlg.exec_()

        if dlg.good_exit:
            x = dlg.x
            y = dlg.y

            try: self.scat1.remove()
            except: pass
            self.scat1 = self.ax.scatter(x, y, s = 25, color = (1, 128/255, 0), zorder = 1e9)
            self.canvas.draw()

            self.X_box.setText('%.2f' % x)
            self.Y_box.setText('%.2f' % y)

            self.Station_label.setText(dlg.StationName)

    def plotMeshVar(self):

        dlg = PlotMeshVarDialog(None)
        dlg.time.setRange(0, len(self.times)-1)
        dlg.time.setValue(len(self.times)-1)

        dlg.exec_( )

        if dlg.variable == 1: var = self.U; label_str = 'U [m/s] at timestep %d' % dlg.t
        if dlg.variable == 2: var = self.V; label_str = 'V [m/s] at timestep %d' % dlg.t
        if dlg.variable == 3: var = self.H; label_str = 'Water Depth [m] at timestep %d' % dlg.t
        if dlg.variable == 4: var = self.SE; label_str = 'Water Surface Elevation [m] at timestep %d' % dlg.t
        if dlg.variable == 5: var = self.B; label_str = 'Bathymetry [m] at timestep %d' % dlg.t
        if dlg.variable == 6: var = self.N; label_str = "Manning's n at timestep %d" % dlg.t
        if dlg.variable == 7: var = np.max(self.SE, axis = 1); label_str = "Maximum Water Surface Elevation [m]"
        if dlg.variable == 8: var = np.min(self.SE, axis = 1); label_str = "Maximum Water Surface Elevation [m]"
        if dlg.variable == 9: var = np.max(self.H, axis = 1); label_str = "Minimum Water Depth [m]"
        if dlg.variable == 10: var = np.min(self.H, axis = 1); label_str = "Minimum Water Depth [m]"


        if dlg.variable != None:

            if var.ndim == 2 and dlg.variable < 10: var = var[:,dlg.t]

            if len(dlg.min.text()) == 0 or len(dlg.max.text()) == 0: varmin, varmax = np.min(var),np.max(var)
            else: varmin, varmax = float(dlg.min.text()),float(dlg.max.text())

            self.ax.clear()
            self.figure.clf()
            self.ax = self.figure.add_subplot(111)
            plotVarMesh(self.X, self.Y, self.ikle, var, label_str, min = varmin, max = varmax, ax = self.ax, fig = self.figure, showedges = dlg.showgridedges, showgrid=dlg.showagrid)

            self.canvas.draw()

            self.ReloadMesh.setDisabled(False)
            self.LocateValue.setDisabled(False)

    def locateValue(self):
        dlg = LocateValueDialog(None)
        dlg.exec_( )

        if dlg.variable != None:
            if dlg.var.currentIndex() == 1: var = self.U; unit_str = 'm/s'; var_str = 'u'
            if dlg.var.currentIndex() == 2: var = self.V; unit_str = 'm/s'; var_str = 'v'
            if dlg.var.currentIndex() == 3: var = self.H; unit_str = 'm'; var_str = 'h'
            if dlg.var.currentIndex() == 4: var = self.SE; unit_str = 'm'; var_str = 'SE'

            #if dlg.reducer.currentText() == 'maximum': var = np.max(var, axis = 1)
            #if dlg.reducer.currentText() == 'minimum': var = np.min(var, axis = 1)

            if dlg.constvar.currentIndex() == 0: mask = self.B[:,0]
            if dlg.constvar.currentIndex() == 1: mask = self.N[:,0]

            if dlg.rel.currentText() == '>': mask = (mask < float(dlg.tresh.text()))
            elif dlg.rel.currentText() == '<': mask = (mask > float(dlg.tresh.text()))
            elif dlg.rel.currentText() == '=': mask = (mask == float(dlg.tresh.text()))
            else: print('woops')

            var_masked = var[mask]

            if dlg.reducer.currentText() == 'maximum':m = np.max(var_masked); am = np.where(var == m); lab = ' max '
            if dlg.reducer.currentText() == 'minimum':m = np.min(var_masked); am = np.where(var == m); lab = ' min '
            am = am[0][0]

            x = self.X[am]
            y = self.Y[am]
            self.locval = self.ax.scatter(x,y,s = 60,c = 'aquamarine')
            lab += '%s: %.2f %s' % (var_str, m, unit_str)
            self.loclabel = self.ax.annotate(lab,(x,y),fontsize = 8, c = 'aquamarine', bbox =dict(boxstyle="square", fc="0.1"))
            self.canvas.draw()



    def reloadMesh(self):
        self.ax.clear()
        self.ax = plotMesh(self.name, self.figure)
        self.canvas.draw()
        self.ReloadMesh.setDisabled(True)