Beispiel #1
0
    def _plot(self):
        """ Network performance graph """
        setConfigOption('background', '#FF000000')
        _graph = PlotWidget()
        _graph.setMenuEnabled(enableMenu=False)
        _graph.setMouseEnabled(x=False, y=False)
        _graph.hideButtons()

        self._out_curve = _graph.getPlotItem().plot()
        self._inc_curve = _graph.getPlotItem().plot()

        self._legend = LegendItem(offset=(50, 10))
        self._legend.setParentItem(_graph.getPlotItem())
        self._legend.addItem(self._out_curve, self._lang.NetworkGraphOutgoing)
        self._legend.addItem(self._inc_curve, self._lang.NetworkGraphIncoming)

        self._base.net_perf_lyt.addWidget(_graph)

        self._menu_popup = QMenu()
        _action = QAction(QIcon('icon/reload.png'), self._lang.PopupReload,
                          self._base.net_perf_box)
        _action.triggered.connect(self.reload)
        self._menu_popup.addAction(_action)

        self._base.net_perf_box.setContextMenuPolicy(Qt.CustomContextMenu)
        self._base.net_perf_box.customContextMenuRequested.connect(
            self._popup_show)
Beispiel #2
0
class SensirionSBPlot(QWidget):
    def __init__(self, plot_title, color, bufferSize):
        super().__init__()
        masterLayout = QVBoxLayout()
        self.pen = mkPen(color, width=1.25)

        layout = QVBoxLayout()
        self.group = QGroupBox(plot_title)
        self.plot = PlotWidget()
        self.plot.getPlotItem().showGrid(x=True, y=True, alpha=1)
        if "qdarkstyle" in sys.modules:
            self.plot.setBackground((25, 35, 45))
        self.buffer = RingBuffer(capacity=bufferSize, dtype=float)

        self.group.setLayout(layout)
        layout.addWidget(self.plot)
        masterLayout.addWidget(self.group)

        self.setLayout(masterLayout)

    def change_capacity(self, value):
        if value > len(self.buffer):
            newBuf = RingBuffer(capacity=value, dtype=float)
            newBuf.extend(self.buffer)
            self.buffer = newBuf

        elif value < len(self.buffer):
            newBuf = RingBuffer(capacity=value, dtype=float)
            newBuf.extend(self.buffer[:-value])
            self.buffer = newBuf

    def update_plot(self, sample):
        self.plot.clear()
        self.buffer.append(sample)
        self.plot.plot(self.buffer, pen=self.pen, symbolPen=self.pen, symbol='o', symbolSize=5, name="symbol ='o'")
Beispiel #3
0
class FFTViewerUi(Frontend):

    backend: FFTAnalyzer

    gui = 'gui/image_viewer.ui'

    def setupUi(self):
        super().setupUi()

        self.widget = PlotWidget(parent=self)
        self.setCentralWidget(self.widget)

        self.plot_item = self.widget.getPlotItem()
        self.plot_item.setLabel('left', 'Intensity')
        self.plot_item.setLabel('bottom', 'Position')
        self.plot_item.showGrid(x=True, y=True, alpha=0.3)
        self.plot_item.enableAutoScale()

        self.plot_data_item = self.plot_item.plot(x=np.zeros((2, )),
                                                  y=np.zeros((2, )))

    def connect_backend(self):
        super().connect_backend()

        self.backend.new_data.connect(self.refresh)

    def refresh(self, fft, timestamp=None):
        self.plot_data_item.setData(x=fft.x, y=fft.absolute)
    def __call__(self) -> PlotWidget:
        """ Generate an interactive pyqtgraph plot widget from this plotter's
        data
        """

        graph = PlotWidget()
        plot = graph.getPlotItem()

        plot.setLabel("left", "membrane potential (mV)")
        plot.setLabel("bottom", "time (s)")

        plot.addLegend()

        if self.initial is not None:
            plot.plot(self.time,
                      self.initial,
                      pen=mkPen(color=TEST_PULSE_INIT_COLOR, width=2),
                      name="initial")

        if self.previous is not None:
            plot.plot(self.time,
                      self.previous,
                      pen=mkPen(color=TEST_PULSE_PREV_COLOR, width=2),
                      name="previous")

        plot.plot(self.time,
                  self.voltage,
                  pen=mkPen(color=TEST_PULSE_CURRENT_COLOR, width=2),
                  name=f"sweep {self.sweep_number}")

        return graph
Beispiel #5
0
class SpectraViewerUi(Frontend):
    backend: SpectraAnalyzer

    gui = 'gui/image_viewer.ui'

    def setupUi(self):
        super().setupUi()

        self.widget = PlotWidget(parent=self)
        self.setCentralWidget(self.widget)

        self.plot_item = self.widget.getPlotItem()
        self.plot_item.setLabel('left', 'Intensity')
        self.plot_item.setLabel('bottom', 'Wavelength')
        self.plot_item.showGrid(x=True, y=True, alpha=0.3)
        self.plot_item.enableAutoRange()

        self.plot_data_item = self.plot_item.plot(x=np.zeros((2, )),
                                                  y=np.zeros((2, )))

    def connect_backend(self):
        super().connect_backend()

        self.backend.new_data.connect(self.refresh)

    def refresh(self, spectrum, timestamp=None):
        self.plot_data_item.setData(x=spectrum.x, y=spectrum.y.flatten())
Beispiel #6
0
class rabi_plot(QtGui.QWidget):
    def __init__(self, parent=None, gage = None, d= None, s =None, NI = None):

        QtGui.QWidget.__init__(self, parent)
        self.initGUI()

    def initGUI(self):

        self.p_upper = PlotWidget()
        self.p_lower = PlotWidget()
        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.p_upper)
        layout.addWidget(self.p_lower)
        self.setLayout(layout)
        self.p1 = self.p_upper.getPlotItem()
        self.p2 = self.p_lower.getPlotItem()
        self.p1.addLegend()
        self.p1data = self.p1.plot([0],pen = 'r', name = 'averaged')
        self.p2data = self.p1.plot([0],pen = 'g', name = 'instant')
        self.p1.setLabel('bottom','Time','ns')
        self.p2.setLabel('bottom','Freq','kHz')
        self.p_upper.setTitle('Rabi raw data')
        self.p_lower.setTitle('Rabi FFT')
Beispiel #7
0
class timetraceplots(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.initGUI()

    def initGUI(self):
        self.plot = PlotWidget()
        layout = QtGui.QHBoxLayout()
        layout.addWidget(self.plot)
        self.setLayout(layout)
        self.p1 = self.plot.getPlotItem()
        self.p2 = self.plot.getPlotItem()
        self.p1.addLegend()
        self.p1data = self.p1.plot([0],pen = 'r',name = '   ch 1')
        self.p2data = self.p2.plot([0],pen = 'g', name = '  ch 2')
        self.vLine5 = pg.InfiniteLine(angle=90, movable=True)

        self.p1.addItem(self.vLine5, ignoreBounds=True)
    def __call__(self) -> PlotWidget:
        """ Generate an interactive pyqtgraph plot widget from this plotter's
        data
        """

        graph = PlotWidget()
        plot = graph.getPlotItem()

        plot.setLabel("left", "membrane potential (mV)")
        plot.setLabel("bottom", "time (s)")

        plot.plot(self.time,
                  self.voltage,
                  pen=mkPen(color=EXP_PULSE_CURRENT_COLOR, width=2))
        plot.addLine(y=self.baseline,
                     pen=mkPen(color=EXP_PULSE_BASELINE_COLOR, width=2),
                     label="baseline")

        return graph
Beispiel #9
0
class PlotWindow(QtWidgets.QWidget):
    """Виджет для рисования графиков"""
    def __init__(self):
        super().__init__()
        self.plot_w = PlotWidget(self)
        self.plot_w.setGeometry(QtCore.QRect(0,
                                             0,
                                             self.width(),
                                             self.height()))
        self.canvas = self.plot_w.getPlotItem()
        # self.panel = NavigationToolbar2QT(self.canvas, self, (0, 0))

    def plot(self, *data, mode='plot', **kwargs):
        """Рисование графов"""
        if mode == 'plot':
            self.canvas.addItem(self.canvas.plot(*data, **kwargs))
        return self.canvas

    def plot_clear(self):
        """Отчистка графика"""
        self.canvas.clear()
Beispiel #10
0
class RatingView(QtWidgets.QWidget):
    _ratings_ready = QtCore.pyqtSignal(object, object)
    _node_ratings_ready = QtCore.pyqtSignal(object)

    def __init__(self):
        super().__init__()

        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)

        self._cubeable_plot = PlotWidget(
            axisItems={'bottom': TimeAxisItem(orientation='bottom')})
        self._nodes_plot = PlotWidget(
            axisItems={'bottom': TimeAxisItem(orientation='bottom')})

        self._splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
        self._splitter.setStretchFactor(0, 1)
        self._splitter.setStretchFactor(1, 1)

        layout.addWidget(self._splitter)

        self._splitter.addWidget(self._cubeable_plot)
        self._splitter.addWidget(self._nodes_plot)

        self._display_target: t.Optional[t.Tuple[int,
                                                 CardboardCubeable]] = None

        self._ratings_ready.connect(self._set_cubeable_ratings)
        self._node_ratings_ready.connect(self._set_nodes_ratings)
        LOGIN_CONTROLLER.login_success.connect(self._on_login)

    @classmethod
    def _get_color(cls, n: int = 0) -> QColor:
        return QColor(100 + (n * 70) % 155, 100 + ((n + 1) * 50) % 155,
                      100 + ((n + 2) * 40) % 155)

    @functools.lru_cache(maxsize=128)
    def _get_rating_points(
        self, release_id: int, cardboard_cubeable: CardboardCubeable
    ) -> Promise[t.Sequence[RatingPoint]]:
        return Context.cube_api_client.rating_history_for_cardboard_cubeable(
            release_id,
            cardboard_cubeable,
        )

    @functools.lru_cache(maxsize=256)
    def _get_node_rating_points(
            self, release_id: int,
            node: CardboardNodeChild) -> Promise[t.Sequence[NodeRatingPoint]]:
        return Context.cube_api_client.rating_history_for_node(
            release_id,
            node,
        ).then(lambda ratings: (node, ratings))

    def _on_login(self, *args, **kwargs) -> None:
        self._get_rating_points.cache_clear()
        self._get_node_rating_points.cache_clear()

    def _set_cubeable_ratings(self, cardboard_cubeable: CardboardCubeable,
                              ratings: t.Sequence[RatingPoint]) -> None:
        self._cubeable_plot.clear()
        data_item = self._cubeable_plot.plot(
            [p.rating_map.created_at.timestamp() for p in ratings],
            [p.rating for p in ratings])
        legend = self._cubeable_plot.addLegend(labelTextSize='15pt')
        legend.addItem(
            data_item, cardboard_cubeable.name if isinstance(
                cardboard_cubeable, Cardboard) else
            cardboard_cubeable.description)
        self._cubeable_plot.getPlotItem().enableAutoRange()

    def _set_nodes_ratings(
        self, ratings: t.Iterable[t.Tuple[CardboardNodeChild,
                                          t.Sequence[NodeRatingPoint]]]
    ) -> None:
        self._nodes_plot.show()
        self._nodes_plot.clear()
        legend = self._nodes_plot.addLegend(labelTextSize='15pt')

        for idx, (node_child, ratings) in enumerate(ratings):
            data_item = self._nodes_plot.plot(
                [p.rating_map.created_at.timestamp() for p in ratings],
                [p.rating for p in ratings],
                pen=mkPen(color=self._get_color(idx)),
            )
            legend.addItem(
                data_item,
                node_child.name if isinstance(node_child, Cardboard) else
                node_child.get_minimal_string())
        self._nodes_plot.getPlotItem().enableAutoRange()

    def on_focus_event(self, focus_event: FocusEvent) -> None:
        if not self.isVisible(
        ) or not focus_event.release_id or Context.focus_card_frozen:
            return

        cardboard_cubeable = focusable_as_cardboards(focus_event.focusable)

        display_target = (focus_event.release_id, cardboard_cubeable)
        if display_target == self._display_target:
            return
        self._display_target = display_target

        promise = self._get_rating_points(focus_event.release_id,
                                          cardboard_cubeable)

        if promise.is_pending:
            promise.then(lambda ratings: self._ratings_ready.emit(
                cardboard_cubeable, ratings)).catch(logging.warning)
        elif promise.is_fulfilled:
            self._set_cubeable_ratings(cardboard_cubeable, promise.get())

        if isinstance(
                cardboard_cubeable, CardboardTrap
        ) and cardboard_cubeable.intention_type == IntentionType.GARBAGE:
            promise = Promise.all([
                self._get_node_rating_points(focus_event.release_id, node) for
                node in cardboard_cubeable.node.children.distinct_elements()
            ])
            if promise.is_pending:
                promise.then(self._node_ratings_ready.emit).catch(
                    logging.warning)
            elif promise.is_fulfilled:
                self._set_nodes_ratings(promise.get())
        else:
            self._nodes_plot.hide()
Beispiel #11
0
class widget_mfi_lin_plot(QWidget):

    #-----------------------------------------------------------------------
    # DEFINE THE INITIALIZATION FUNCTION.
    #-----------------------------------------------------------------------

    def __init__(self, core):

        # Inherit all attributes of an instance of "QWidget".

        super(widget_mfi_lin_plot, self).__init__()

        # Store the Janus core.

        self.core = core

        # Prepare to respond to signals received from the core.

        self.connect(self.core, SIGNAL('janus_rset'), self.resp_rset)
        self.connect(self.core, SIGNAL('janus_chng_mfi'), self.resp_chng_mfi)

        # Initialize this widget's instance of "PlotWidget", which will
        # contain the plot of MFI magnetic field data.

        # Note.  The "QGridLayout" object given to this widget as its
        #        layout is essentially a dummy.  I could have just had
        #        this class inherit "PlotWidget", but I think that this
        #        gives me a bit more control (and a similar structure
        #        "janus_widget_fc_cup").

        self.setLayout(QGridLayout())

        self.plt = PlotWidget()
        self.layout().addWidget(self.plt)

        self.layout().setContentsMargins(0, 0, 0, 0)

        # Extract the individual elements of the "PlotWidget" object
        # (e.g., it's axes) for more convenient access later.

        self.vbx = self.plt.getViewBox()

        self.axs_x = self.plt.getAxis('bottom')
        self.axs_y = self.plt.getAxis('left')

        self.ptm = self.plt.getPlotItem()

        # Initialize and store the pens and fonts.

        self.pen_vbx = mkPen(color='k')
        self.pen_crv_m = mkPen(color='k')
        self.pen_crv_n = mkPen(color='k')
        self.pen_crv_x = mkPen(color='r')
        self.pen_crv_y = mkPen(color='g')
        self.pen_crv_z = mkPen(color='b')

        self.fnt = self.core.app.font()

        # Configure the plot: disable automatic adjustments and
        # adjustments made by the user, change the background and
        # foreground colors, enable grid lines for both axes, label the
        # axes, adjust the tick font size, adjust the "AxisItem" sizes,
        # and add a margin around the entire plot.

        self.plt.disableAutoRange()
        self.plt.setMouseEnabled(False, False)
        self.plt.setMenuEnabled(False)
        self.plt.hideButtons()

        self.plt.setBackground('w')
        setConfigOption('foreground', 'k')

        #####self.plt.showGrid( True, True )

        labelStyle = {'color': 'k'}
        self.axs_x.setLabel('Time [s]', **labelStyle)
        self.axs_y.setLabel('Magnetic Field [nT]', **labelStyle)

        self.axs_x.label.setFont(self.fnt)
        self.axs_y.label.setFont(self.fnt)

        self.axs_x.setTickFont(self.fnt)
        self.axs_y.setTickFont(self.fnt)

        self.axs_x.setHeight(35)
        self.axs_y.setWidth(40)

        self.vbx.border = self.pen_vbx

        self.ptm.setContentsMargins(5, 5, 5, 5)

        # Initialize the curves that will be added to this plot.

        self.crv_m = None
        self.crv_n = None
        self.crv_x = None
        self.crv_y = None
        self.crv_z = None
        self.pl = []

        # Populate this plot and adjust it's settings.

        self.make_plt()

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR POPULATING THE PLOT.
    #-----------------------------------------------------------------------

    def make_plt(self):

        # Reset the plot (i.e., remove all plot elements).

        self.rset_plt()

        # Establish the ranges of its time and magnetic field values.
        # If the core contains no data or only a single datum,
        # improvise (for the purpose of later establishing axis limits).

        if (self.core.n_mfi >= 1):

            # Establish the domain of the plot.

            t_min = min(amin(self.core.mfi_s), 0.)
            t_max = max(amax(self.core.mfi_s), self.core.fc_spec['dur'])

            # Establish the range of the plot.  As part of this,
            # ensure that the range satisfies a minimum size and has
            # sufficient padding.

            b_max = amax(self.core.mfi_b)
            b_min = -b_max

            d_t_0 = t_max - t_min
            d_b_0 = b_max - b_min

            d_t = max(1.5 + d_t_0, 3.)
            d_b = max(1.2 * d_b_0, 5.)

            t_max = t_min + d_t

            b_min = b_min - (d_b - d_b_0) / 2.
            b_max = b_max + (d_b - d_b_0) / 2.

        else:

            t_min = 0.001
            t_max = 3.500

            b_min = -2.5
            b_max = 2.5

        # Set the range of the axis of each plot.

        self.plt.setXRange(t_min, t_max, padding=0.0)
        self.plt.setYRange(b_min, b_max, padding=0.0)

        # Set the PESA-L pen with a width corresponding to one rotation
        # Note: For some reason, the lines are not wide enough unless 5
        #       is added to the scaled width of the rotation time

        rot = 3.05 * self.axs_x.width() / (t_max - t_min) + 5

        self.pen_pl = mkPen(color=(245, 245, 245), width=rot)

        # If the core contains no Wind/MFI magnetic field data, return.

        if (self.core.n_mfi <= 0):
            return

        # Generate and display each curve for the plot.

        self.crv_m = PlotDataItem(self.core.mfi_s,
                                  self.core.mfi_b,
                                  pen=self.pen_crv_m)
        self.crv_n = PlotDataItem(self.core.mfi_s,
                                  [-b for b in self.core.mfi_b],
                                  pen=self.pen_crv_n)
        self.crv_x = PlotDataItem(self.core.mfi_s,
                                  self.core.mfi_b_x,
                                  pen=self.pen_crv_x)
        self.crv_y = PlotDataItem(self.core.mfi_s,
                                  self.core.mfi_b_y,
                                  pen=self.pen_crv_y)
        self.crv_z = PlotDataItem(self.core.mfi_s,
                                  self.core.mfi_b_z,
                                  pen=self.pen_crv_z)

        # If PESA-L spectra were loaded, add the vertical indicators
        # showing their time relative to the start of the FC spectrum

        for n in range(len(self.core.pl_spec_arr)):

            time = self.core.pl_spec_arr[n]['time'][0]

            t_0 = self.core.fc_spec['time']

            delta_t = (time - t_0).total_seconds()

            self.pl += [
                InfiniteLine(delta_t + self.core.fc_spec['rot'] / 2.,
                             pen=self.pen_pl)
            ]

        for i in range(len(self.pl)):

            self.plt.addItem(self.pl[i])

        self.plt.addItem(self.crv_m)
        self.plt.addItem(self.crv_n)
        self.plt.addItem(self.crv_x)
        self.plt.addItem(self.crv_y)
        self.plt.addItem(self.crv_z)

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR RESETTING THIS PLOT (CLEARING ALL ELEMENTS).
    #-----------------------------------------------------------------------

    def rset_plt(self):

        # Hide and remove each of this plot's elements.

        if (self.crv_m is not None):
            self.plt.removeItem(self.crv_m)

        if (self.crv_n is not None):
            self.plt.removeItem(self.crv_n)

        if (self.crv_x is not None):
            self.plt.removeItem(self.crv_x)

        if (self.crv_y is not None):
            self.plt.removeItem(self.crv_y)

        if (self.crv_z is not None):
            self.plt.removeItem(self.crv_z)

        if (self.pl != []):

            for i in range(len(self.pl)):

                self.plt.removeItem(self.pl[i])

        # if ( self.crv_colat is not None ) :
        # 	self.plt.removeItem( self.crv_colat )

        # if ( self.crv_lon is not None ) :
        # 	self.plt.removeItem( self.crv_lon )

        # Permanently delete this plot's elements by setting each of the
        # variables that store them to "None".

        self.crv_m = None
        self.crv_n = None
        self.crv_x = None
        self.crv_y = None
        self.crv_z = None
        self.pl = []

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR RESPONDING TO THE "rset" SIGNAL.
    #-----------------------------------------------------------------------

    def resp_rset(self):

        # Reset the plot.

        self.rset_plt()

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR RESPONDING TO THE "chng_mfi" SIGNAL.
    #-----------------------------------------------------------------------

    def resp_chng_mfi(self):

        # Regenerate the plot.

        self.make_plt()
Beispiel #12
0
class CamViewer(Display):
    # Emitted when the user changes the value.
    roi_x_signal = Signal(str)
    roi_y_signal = Signal(str)
    roi_w_signal = Signal(str)
    roi_h_signal = Signal(str)

    def __init__(self, parent=None, args=None):
        super(CamViewer, self).__init__(parent=parent, args=args)

        # Set up the list of cameras, and all the PVs
        test_dict = { "image": "ca://MTEST:Image", "max_width": "ca://MTEST:ImageWidth", "max_height": "ca://MTEST:ImageWidth", "roi_x": None, "roi_y": None, "roi_width": None, "roi_height": None }
        # self.cameras = { "VCC": vcc_dict, "C-Iris": c_iris_dict, "Test": test_dict }
        self.cameras = {"Testing IOC Image": test_dict }
        self._channels = []
        self.imageChannel = None

        # Populate the camera combo box
        self.ui.cameraComboBox.clear()
        for camera in self.cameras:
            self.ui.cameraComboBox.addItem(camera)

        # When the camera combo box changes, disconnect from PVs, re-initialize, then reconnect.
        self.ui.cameraComboBox.activated[str].connect(self.cameraChanged)

        # Set up the color map combo box.
        self.ui.colorMapComboBox.clear()
        for key, map_name in cmap_names.items():
            self.ui.colorMapComboBox.addItem(map_name, userData=key)
        self.ui.imageView.colorMap = self.ui.colorMapComboBox.currentData()
        self.ui.colorMapComboBox.activated[str].connect(self.colorMapChanged)

        # Set up the color map limit sliders and line edits.
        # self._color_map_limit_sliders_need_config = True
        self.ui.colorMapMinSlider.valueChanged.connect(self.setColorMapMin)
        self.ui.colorMapMaxSlider.valueChanged.connect(self.setColorMapMax)
        self.ui.colorMapMinLineEdit.returnPressed.connect(self.colorMapMinLineEditChanged)
        self.ui.colorMapMaxLineEdit.returnPressed.connect(self.colorMapMaxLineEditChanged)

        # Set up the stuff for single-shot and average modes.
        self.ui.singleShotRadioButton.setChecked(True)
        self._average_mode_enabled = False
        self.ui.singleShotRadioButton.clicked.connect(self.enableSingleShotMode)
        self.ui.averageRadioButton.clicked.connect(self.enableAverageMode)
        self.ui.numShotsLineEdit.returnPressed.connect(self.numAverageChanged)

        # Add a plot for vertical lineouts
        self.yLineoutPlot = PlotWidget()
        self.yLineoutPlot.setMaximumWidth(80)
        self.yLineoutPlot.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.yLineoutPlot.getPlotItem().invertY()
        self.yLineoutPlot.hideAxis('bottom')
        # self.yLineoutPlot.setYLink(self.ui.imageView.getView())
        self.ui.imageGridLayout.addWidget(self.yLineoutPlot, 0, 0)
        self.yLineoutPlot.hide()
        # We do some mangling of the .ui file here and move the imageView over a cell, kind of ugly.
        self.ui.imageGridLayout.removeWidget(self.ui.imageView)
        self.ui.imageGridLayout.addWidget(self.ui.imageView, 0, 1)

        # Add a plot for the horizontal lineouts
        self.xLineoutPlot = PlotWidget()
        self.xLineoutPlot.setMaximumHeight(80)
        self.xLineoutPlot.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.xLineoutPlot.hideAxis('left')
        # self.xLineoutPlot.setXLink(self.ui.imageView.getView())
        self.ui.imageGridLayout.addWidget(self.xLineoutPlot, 1, 1)
        self.xLineoutPlot.hide()

        # Update the lineout plot ranges when the image gets panned or zoomed
        self.ui.imageView.getView().sigRangeChanged.connect(self.updateLineoutRange)

        # Instantiate markers.
        self.marker_dict = {1:{}, 2:{}, 3:{}, 4:{}}
        marker_size = QPointF(20., 20.)
        self.marker_dict[1]['marker'] = ImageMarker((0, 0), size=marker_size, pen=mkPen((100, 100, 255), width=5))
        self.marker_dict[1]['button'] = self.ui.marker1Button
        self.marker_dict[1]['xlineedit'] = self.ui.marker1XPosLineEdit
        self.marker_dict[1]['ylineedit'] = self.ui.marker1YPosLineEdit

        self.marker_dict[2]['marker'] = ImageMarker((0, 0), size=marker_size, pen=mkPen((255, 100, 100), width=5))
        self.marker_dict[2]['button'] = self.ui.marker2Button
        self.marker_dict[2]['xlineedit'] = self.ui.marker2XPosLineEdit
        self.marker_dict[2]['ylineedit'] = self.ui.marker2YPosLineEdit

        self.marker_dict[3]['marker'] = ImageMarker((0, 0), size=marker_size, pen=mkPen((60, 255, 60), width=5))
        self.marker_dict[3]['button'] = self.ui.marker3Button
        self.marker_dict[3]['xlineedit'] = self.ui.marker3XPosLineEdit
        self.marker_dict[3]['ylineedit'] = self.ui.marker3YPosLineEdit

        self.marker_dict[4]['marker'] = ImageMarker((0, 0), size=marker_size, pen=mkPen((255, 60, 255), width=5))
        self.marker_dict[4]['button'] = self.ui.marker4Button
        self.marker_dict[4]['xlineedit'] = self.ui.marker4XPosLineEdit
        self.marker_dict[4]['ylineedit'] = self.ui.marker4YPosLineEdit
        # Disable auto-ranging the image (it feels strange when the zoom changes as you move markers around.)
        self.ui.imageView.getView().disableAutoRange()
        for d in self.marker_dict:
            marker = self.marker_dict[d]['marker']
            marker.setZValue(20)
            marker.hide()
            marker.sigRegionChanged.connect(self.markerMoved)
            self.ui.imageView.getView().addItem(marker)
            self.marker_dict[d]['button'].toggled.connect(self.enableMarker)
            curvepen = QPen(marker.pen)
            curvepen.setWidth(1)
            self.marker_dict[d]['xcurve'] = self.xLineoutPlot.plot(pen=curvepen)
            self.marker_dict[d]['ycurve'] = self.yLineoutPlot.plot(pen=curvepen)
            self.marker_dict[d]['xlineedit'].returnPressed.connect(self.markerPositionLineEditChanged)
            self.marker_dict[d]['ylineedit'].returnPressed.connect(self.markerPositionLineEditChanged)

        # Set up zoom buttons
        self.ui.zoomInButton.clicked.connect(self.zoomIn)
        self.ui.zoomOutButton.clicked.connect(self.zoomOut)
        self.ui.zoomToActualSizeButton.clicked.connect(self.zoomToActualSize)

        # Set up ROI buttons
        self.ui.setROIButton.clicked.connect(self.setROI)
        self.ui.resetROIButton.clicked.connect(self.resetROI)

        self.destroyed.connect(functools.partial(widget_destroyed, self.channels))


    @Slot()
    def zoomIn(self):
        self.ui.imageView.getView().scaleBy((0.5, 0.5))

    @Slot()
    def zoomOut(self):
        self.ui.imageView.getView().scaleBy((2.0, 2.0))

    @Slot()
    def zoomToActualSize(self):
        if len(self.image_data) == 0:
            return
        self.ui.imageView.getView().setRange(xRange=(0, self.image_data.shape[0]), yRange=(0, self.image_data.shape[1]), padding=0.0)

    def disable_all_markers(self):
        for d in self.marker_dict:
            self.marker_dict[d]['button'].setChecked(False)
            self.marker_dict[d]['marker'].setPos((0, 0))

    @Slot(bool)
    def enableMarker(self, checked):
        any_markers_visible = False
        for d in self.marker_dict:
            marker = self.marker_dict[d]['marker']
            button = self.marker_dict[d]['button']
            any_markers_visible = any_markers_visible or button.isChecked()
            marker.setVisible(button.isChecked())
            self.markerMoved(d)
            self.marker_dict[d]['xcurve'].setVisible(button.isChecked())
            self.marker_dict[d]['ycurve'].setVisible(button.isChecked())
            self.marker_dict[d]['xlineedit'].setEnabled(button.isChecked())
            self.marker_dict[d]['ylineedit'].setEnabled(button.isChecked())
        if any_markers_visible:
            self.xLineoutPlot.show()
            self.yLineoutPlot.show()
        else:
            self.xLineoutPlot.hide()
            self.yLineoutPlot.hide()

    @Slot()
    def markerPositionLineEditChanged(self):
        for d in self.marker_dict:
            marker = self.marker_dict[d]['marker']
            x_line_edit = self.marker_dict[d]['xlineedit']
            y_line_edit = self.marker_dict[d]['ylineedit']
            try:
                new_x = int(x_line_edit.text())
                new_y = int(y_line_edit.text())
                if new_x <= marker.maxBounds.width() and new_y <= marker.maxBounds.height():
                    marker.setPos((new_x, new_y))
            except:
                pass
            coords = marker.getPixelCoords()
            x_line_edit.setText(str(coords[0]))
            y_line_edit.setText(str(coords[1]))

    @Slot(object)
    def markerMoved(self, marker):
        self.updateLineouts()
        for marker_index in self.marker_dict:
            marker = self.marker_dict[marker_index]['marker']
            x_line_edit = self.marker_dict[marker_index]['xlineedit']
            y_line_edit = self.marker_dict[marker_index]['ylineedit']
            coords = marker.getPixelCoords()
            x_line_edit.setText(str(coords[0]))
            y_line_edit.setText(str(coords[1]))

    @Slot(object, object)
    def updateLineoutRange(self, view, new_ranges):
        self.ui.xLineoutPlot.setRange(xRange=new_ranges[0], padding=0.0)
        self.ui.yLineoutPlot.setRange(yRange=new_ranges[1], padding=0.0)

    def updateLineouts(self):
        for marker_index in self.marker_dict:
            marker = self.marker_dict[marker_index]['marker']
            xcurve = self.marker_dict[marker_index]['xcurve']
            ycurve = self.marker_dict[marker_index]['ycurve']
            if marker.isVisible():
                result, coords = marker.getArrayRegion(self.image_data, self.ui.imageView.getImageItem())
                xcurve.setData(y=result[0], x=np.arange(len(result[0])))
                ycurve.setData(y=np.arange(len(result[1])), x=result[1])

    @Slot()
    def enableSingleShotMode(self):
        self._average_mode_enabled = False
        self._average_buffer = np.ndarray(0)

    @Slot()
    def enableAverageMode(self):
        self._average_mode_enabled = True

    @Slot(str)
    def cameraChanged(self, new_camera):
        new_camera = str(new_camera)
        if self.imageChannel == self.cameras[new_camera]["image"]:
            return
        close_widget_connections(self)
        self.disable_all_markers()
        self.initializeCamera(new_camera)

    def initializeCamera(self, new_camera):
        new_camera = str(new_camera)
        self._color_map_limit_sliders_need_config = True
        self.times = np.zeros(10)
        self.old_timestamp = 0
        self.image_width = 0  # current width (width of ROI)
        self.image_max_width = 0  # full width.  Only used to reset ROI to full.
        self.image_max_height = 0  # full height.  Only used to reset ROI to full.
        self.image_data = np.zeros(0)
        self._average_counter = 0
        self._average_buffer = np.ndarray(0)
        self._needs_auto_range = True
        self.imageChannel = self.cameras[new_camera]["image"]
        self.widthChannel = self.cameras[new_camera]["roi_width"] or self.cameras[new_camera]["max_width"]
        self.maxWidthChannel = self.cameras[new_camera]["max_width"]
        self.maxHeightChannel = self.cameras[new_camera]["max_height"]
        self.roiXChannel = self.cameras[new_camera]["roi_x"]
        self.roiYChannel = self.cameras[new_camera]["roi_y"]
        self.roiWidthChannel = self.cameras[new_camera]["roi_width"]
        self.roiHeightChannel = self.cameras[new_camera]["roi_height"]

        self._channels = [PyDMChannel(address=self.imageChannel, connection_slot=self.connectionStateChanged, value_slot=self.receiveImageWaveform, severity_slot=self.alarmSeverityChanged),
                                            PyDMChannel(address=self.widthChannel, value_slot=self.receiveImageWidth),
                                            PyDMChannel(address=self.maxWidthChannel, value_slot=self.receiveMaxWidth),
                                            PyDMChannel(address=self.maxHeightChannel, value_slot=self.receiveMaxHeight)]
        if self.roiXChannel and self.roiYChannel and self.roiWidthChannel and self.roiHeightChannel:
            self._channels.extend([PyDMChannel(address=self.roiXChannel, value_slot=self.receiveRoiX, value_signal=self.roi_x_signal, write_access_slot=self.roiWriteAccessChanged),
                                                         PyDMChannel(address=self.roiYChannel, value_slot=self.receiveRoiY, value_signal=self.roi_y_signal),
                                                         PyDMChannel(address=self.roiWidthChannel, value_slot=self.receiveRoiWidth, value_signal=self.roi_w_signal),
                                                         PyDMChannel(address=self.roiHeightChannel, value_slot=self.receiveRoiHeight, value_signal=self.roi_h_signal)])
            self.ui.roiXLineEdit.setEnabled(True)
            self.ui.roiYLineEdit.setEnabled(True)
            self.ui.roiWLineEdit.setEnabled(True)
            self.ui.roiHLineEdit.setEnabled(True)
        else:
            self.ui.roiXLineEdit.clear()
            self.ui.roiXLineEdit.setEnabled(False)
            self.ui.roiYLineEdit.clear()
            self.ui.roiYLineEdit.setEnabled(False)
            self.ui.roiWLineEdit.clear()
            self.ui.roiWLineEdit.setEnabled(False)
            self.ui.roiHLineEdit.clear()
            self.ui.roiHLineEdit.setEnabled(False)
        establish_widget_connections(self)

    @Slot()
    def setROI(self):
        self.roi_x_signal.emit(self.ui.roiXLineEdit.text())
        self.roi_y_signal.emit(self.ui.roiYLineEdit.text())
        self.roi_w_signal.emit(self.ui.roiWLineEdit.text())
        self.roi_h_signal.emit(self.ui.roiHLineEdit.text())

    @Slot()
    def resetROI(self):
        self.roi_x_signal.emit(str(0))
        self.roi_y_signal.emit(str(0))
        self.roi_w_signal.emit(str(self.image_max_width))
        self.roi_h_signal.emit(str(self.image_max_height))

    @Slot(str)
    def colorMapChanged(self, _):
        self.ui.imageView.colorMap = self.ui.colorMapComboBox.currentData()

    def configureColorMapLimitSliders(self, max_int):
        self.ui.colorMapMinSlider.setMaximum(max_int)
        self.ui.colorMapMaxSlider.setMaximum(max_int)
        self.ui.colorMapMaxSlider.setValue(max_int)
        self.ui.colorMapMinSlider.setValue(0)
        self.setColorMapMin(0)
        self.setColorMapMax(max_int)
        self._color_map_limit_sliders_need_config = False

    @Slot()
    def colorMapMinLineEditChanged(self):
        try:
            new_min = int(self.ui.colorMapMinLineEdit.text())
        except:
            self.ui.colorMapMinLineEdit.setText(str(self.ui.colorMapMinSlider.value()))
            return
        if new_min < 0:
            new_min = 0
        if new_min > self.ui.colorMapMinSlider.maximum():
            new_min = self.ui.colorMapMinSlider.maximum()
        self.ui.colorMapMinSlider.setValue(new_min)

    @Slot(int)
    def setColorMapMin(self, new_min):
        if new_min > self.ui.colorMapMaxSlider.value():
            self.ui.colorMapMaxSlider.setValue(new_min)
            self.ui.colorMapMaxLineEdit.setText(str(new_min))
        self.ui.colorMapMinLineEdit.setText(str(new_min))
        self.ui.imageView.setColorMapLimits(new_min, self.ui.colorMapMaxSlider.value())

    @Slot()
    def colorMapMaxLineEditChanged(self):
        try:
            new_max = int(self.ui.colorMapMaxLineEdit.text())
        except:
            self.ui.colorMapMaxLineEdit.setText(str(self.ui.colorMapMaxSlider.value()))
            return
        if new_max < 0:
            new_max = 0
        if new_max > self.ui.colorMapMaxSlider.maximum():
            new_max = self.ui.colorMapMaxSlider.maximum()
        self.ui.colorMapMaxSlider.setValue(new_max)

    @Slot(int)
    def setColorMapMax(self, new_max):
        if new_max < self.ui.colorMapMinSlider.value():
            self.ui.colorMapMinSlider.setValue(new_max)
            self.ui.colorMapMinLineEdit.setText(str(new_max))
        self.ui.colorMapMaxLineEdit.setText(str(new_max))
        self.ui.imageView.setColorMapLimits(self.ui.colorMapMinSlider.value(), new_max)

    def createAverageBuffer(self, size, type, initial_val=[]):
        num_shots = 1
        try:
            num_shots = int(self.ui.numShotsLineEdit.text())
        except:
            self.ui.numShotsLineEdit.setText(str(num_shots))
        if num_shots < 1:
            num_shots = 1
            self.ui.numShotsLineEdit.setText(str(num_shots))
        if num_shots > 200:
            num_shots = 200
            self.ui.numShotsLineEdit.setText(str(num_shots))
        if len(initial_val) > 0:
            return np.full((num_shots, size), initial_val, dtype=type)
        else:
            return np.zeros(shape=(num_shots, size), dtype=type)

    @Slot()
    def numAverageChanged(self):
        self._average_buffer = np.zeros(0)

    @Slot(np.ndarray)
    def receiveImageWaveform(self, new_waveform):
        if not self.image_width:
            return

        # Calculate the average rate
        new_timestamp = time.time()
        if not (self.old_timestamp == 0):
            delta = new_timestamp - self.old_timestamp
            self.times = np.roll(self.times, 1)
            self.times[0] = delta
            avg_delta = np.mean(self.times)
            self.ui.dataRateLabel.setText("{:.1f} Hz".format((1.0 / avg_delta)))
            self.ui.displayRateLabel.setText("{:.1f} Hz".format((1.0 / avg_delta)))
        self.old_timestamp = new_timestamp

        # If this is the first image, set up the color map slider limits
        if self._color_map_limit_sliders_need_config:
            max_int = np.iinfo(new_waveform.dtype).max
            self.configureColorMapLimitSliders(max_int)

        # If we are in average mode, add this image to the circular averaging buffer, otherwise just display it.
        if self._average_mode_enabled:
            if len(self._average_buffer) == 0:
                self._average_buffer = self.createAverageBuffer(len(new_waveform), new_waveform.dtype, new_waveform)
                self._average_counter = 0
            self._average_counter = (self._average_counter + 1) % len(self._average_buffer)
            # self._average_buffer = np.roll(self._average_buffer, 1, axis=0)
            self._average_buffer[self._average_counter] = new_waveform
            mean = np.mean(self._average_buffer, axis=0).astype(new_waveform.dtype)
            self.image_data = mean.reshape((int(self.image_width), -1), order='F')
        else:
            self.image_data = new_waveform.reshape((int(self.image_width), -1), order='F')
        self.setMarkerBounds()
        self.updateLineouts()
        self.ui.imageView.image_value_changed(self.image_data)
        self.calculateStats()
        if self._needs_auto_range:
            self.ui.imageView.getView().autoRange(padding=0.0)
            current_range = self.ui.imageView.getView().viewRange()
            self._needs_auto_range = False

    def calculateStats(self):
        # Full image stats
        mean = np.mean(self.image_data)
        std = np.std(self.image_data)
        width = self.image_data.shape[0]
        height = self.image_data.shape[1]
        min_val = np.min(self.image_data)
        max_val = np.max(self.image_data)
        self.ui.imageStatsLabel.setText("Mean: {0:.2f}, Std: {1:.2f}, Min: {2}, Max: {3}, Width: {4}, Height: {5}".format(mean, std, min_val, max_val, width, height))
        # Current view stats
        current_range = self.ui.imageView.getView().viewRange()
        view_x_min = int(max(0, current_range[0][0]))
        view_x_max = int(min(self.image_data.shape[0], current_range[0][1]))
        view_y_min = int(max(0, current_range[1][0]))
        view_y_max = int(min(self.image_data.shape[1], current_range[1][1]))
        view_slice = self.image_data[view_x_min:view_x_max, view_y_min:view_y_max]
        mean = np.mean(view_slice)
        std = np.std(view_slice)
        width = view_slice.shape[0]
        height = view_slice.shape[1]
        min_val = np.min(view_slice)
        max_val = np.max(view_slice)
        self.ui.viewStatsLabel.setText("Mean: {0:.2f}, Std: {1:.2f}, Min: {2}, Max: {3}, Width: {4}, Height: {5}".format(mean, std, min_val, max_val, width, height))

    def setMarkerBounds(self):
        for marker_index in self.marker_dict:
            marker = self.marker_dict[marker_index]['marker']
            marker.maxBounds = QRectF(0, 0, self.image_data.shape[0] + marker.size()[0] - 1, self.image_data.shape[1] + marker.size()[1] - 1)

    @Slot(int)
    def receiveImageWidth(self, new_width):
        self.image_width = new_width
        self.ui.imageView.image_width_changed(self.image_width)

    @Slot(int)
    def receiveMaxWidth(self, new_max_width):
        self.image_max_width = new_max_width

    @Slot(int)
    def receiveMaxHeight(self, new_max_height):
        self.image_max_height = new_max_height

    @Slot(int)
    def receiveRoiX(self, new_roi_x):
        self.ui.roiXLineEdit.setText(str(new_roi_x))

    @Slot(int)
    def receiveRoiY(self, new_roi_y):
        self.ui.roiYLineEdit.setText(str(new_roi_y))

    @Slot(int)
    def receiveRoiWidth(self, new_roi_w):
        self.ui.roiWLineEdit.setText(str(new_roi_w))

    @Slot(int)
    def receiveRoiHeight(self, new_roi_h):
        self.ui.roiHLineEdit.setText(str(new_roi_h))

    # -2 to +2, -2 is LOLO, -1 is LOW, 0 is OK, etc.
    @Slot(int)
    def alarmStatusChanged(self, new_alarm_state):
        pass

    # 0 = NO_ALARM, 1 = MINOR, 2 = MAJOR, 3 = INVALID
    @Slot(int)
    def alarmSeverityChanged(self, new_alarm_severity):
        pass

    @Slot(bool)
    def roiWriteAccessChanged(self, can_write_roi):
        self.ui.setROIButton.setEnabled(can_write_roi)
        self.ui.resetROIButton.setEnabled(can_write_roi)
        self.ui.roiXLineEdit.setReadOnly(not can_write_roi)
        self.ui.roiYLineEdit.setReadOnly(not can_write_roi)
        self.ui.roiWLineEdit.setReadOnly(not can_write_roi)
        self.ui.roiHLineEdit.setReadOnly(not can_write_roi)

    # false = disconnected, true = connected
    @Slot(bool)
    def connectionStateChanged(self, connected):
        if connected:
            self.ui.imageView.redraw_timer.start()
        else:
            self.ui.imageView.redraw_timer.stop()
        self.ui.connectedLabel.setText({True: "Yes", False: "No"}[connected])

    def ui_filename(self):
        return 'camviewer.ui'

    def channels(self):
        return self._channels
Beispiel #13
0
class BusMonitorWidget(QGroupBox):
    DEFAULT_PLOT_X_RANGE = 120
    BUS_LOAD_PLOT_MAX_SAMPLES = 5000

    def __init__(self, parent, node, iface_name):
        super(BusMonitorWidget, self).__init__(parent)
        self.setTitle('CAN bus activity (%s)' %
                      iface_name.split(os.path.sep)[-1])

        self._node = node
        self._hook_handle = self._node.can_driver.add_io_hook(self._frame_hook)

        self._columns = [
            BasicTable.Column('Dir',
                              lambda e: (e[0].upper()),
                              searchable=False),
            BasicTable.Column('Local Time',
                              TimestampRenderer(),
                              searchable=False),
            BasicTable.Column(
                'CAN ID', lambda e:
                (('%0*X' % (8 if e[1].extended else 3, e[1].id)).rjust(8),
                 colorize_can_id(e[1]))),
            BasicTable.Column(
                'Data Hex', lambda e:
                (' '.join(['%02X' % x for x in e[1].data]).ljust(3 * e[
                    1].MAX_DATA_LENGTH), colorize_transfer_id(e))),
            BasicTable.Column(
                'Data ASCII', lambda e:
                (''.join([(chr(x) if 32 <= x <= 126 else '.')
                          for x in e[1].data]), colorize_transfer_id(e))),
            BasicTable.Column(
                'Src', lambda e: render_node_id_with_color(e[1], 'src')),
            BasicTable.Column(
                'Dst', lambda e: render_node_id_with_color(e[1], 'dst')),
            BasicTable.Column('Data Type',
                              lambda e: render_data_type_with_color(e[1]),
                              resize_mode=QHeaderView.Stretch),
        ]

        self._log_widget = RealtimeLogWidget(
            self,
            columns=self._columns,
            font=get_monospace_font(),
            post_redraw_hook=self._redraw_hook)
        self._log_widget.on_selection_changed = self._update_measurement_display

        def flip_row_mark(row, col):
            if col == 0:
                item = self._log_widget.table.item(row, col)
                if item.icon().isNull():
                    item.setIcon(get_icon('circle'))
                    flash(self,
                          'Row %d was marked, click again to unmark',
                          row,
                          duration=3)
                else:
                    item.setIcon(QIcon())

        self._log_widget.table.cellPressed.connect(flip_row_mark)

        self._stat_update_timer = QTimer(self)
        self._stat_update_timer.setSingleShot(False)
        self._stat_update_timer.timeout.connect(self._update_stat)
        self._stat_update_timer.start(500)

        self._traffic_stat = TrafficStatCounter()

        self._stat_frames_tx = QLabel('N/A', self)
        self._stat_frames_rx = QLabel('N/A', self)
        self._stat_traffic = QLabel('N/A', self)

        self._load_plot = PlotWidget(background=(0, 0, 0))
        self._load_plot.setRange(xRange=(0, self.DEFAULT_PLOT_X_RANGE),
                                 padding=0)
        self._load_plot.setMaximumHeight(150)
        self._load_plot.setMinimumHeight(100)
        self._load_plot.setMinimumWidth(100)
        self._load_plot.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self._load_plot.showGrid(x=True, y=True, alpha=0.4)
        self._load_plot.setToolTip('Frames per second')
        self._load_plot.getPlotItem().getViewBox().setMouseEnabled(x=True,
                                                                   y=False)
        self._load_plot.enableAutoRange()
        self._bus_load_plot = self._load_plot.plot(name='Frames per second',
                                                   pen=mkPen(QColor(
                                                       Qt.lightGray),
                                                             width=1))
        self._bus_load_samples = [], []
        self._started_at_mono = time.monotonic()

        layout = QVBoxLayout(self)

        layout.addWidget(self._log_widget, 1)

        stat_vars_layout = QGridLayout(self)
        stat_layout_next_row = 0

        def add_stat_row(label, value):
            nonlocal stat_layout_next_row
            stat_vars_layout.addWidget(QLabel(label, self),
                                       stat_layout_next_row, 0)
            stat_vars_layout.addWidget(value, stat_layout_next_row, 1)
            value.setMinimumWidth(75)
            stat_layout_next_row += 1

        add_stat_row('Frames transmitted:', self._stat_frames_tx)
        add_stat_row('Frames received:', self._stat_frames_rx)
        add_stat_row('Frames per second:', self._stat_traffic)
        stat_vars_layout.setRowStretch(stat_layout_next_row, 1)

        stat_layout = QHBoxLayout(self)
        stat_layout.addLayout(stat_vars_layout)
        stat_layout.addWidget(self._load_plot, 1)

        layout.addLayout(stat_layout, 0)
        self.setLayout(layout)

    def close(self):
        self._hook_handle.remove()

    def _update_stat(self):
        bus_load, ts_mono = self._traffic_stat.get_frames_per_second()
        self._stat_traffic.setText(str(int(bus_load + 0.5)))

        if len(self._bus_load_samples[0]) >= self.BUS_LOAD_PLOT_MAX_SAMPLES:
            self._bus_load_samples[0].pop(0)
            self._bus_load_samples[1].pop(0)

        self._bus_load_samples[1].append(bus_load)
        self._bus_load_samples[0].append(ts_mono - self._started_at_mono)

        self._bus_load_plot.setData(*self._bus_load_samples)

        (xmin, xmax), _ = self._load_plot.viewRange()
        diff = xmax - xmin
        xmax = self._bus_load_samples[0][-1]
        xmin = self._bus_load_samples[0][-1] - diff
        self._load_plot.setRange(xRange=(xmin, xmax), padding=0)

    def _redraw_hook(self):
        self._stat_frames_tx.setText(str(self._traffic_stat.tx))
        self._stat_frames_rx.setText(str(self._traffic_stat.rx))

    def _frame_hook(self, direction, frame):
        self._traffic_stat.add_frame(direction, frame)
        self._log_widget.add_item_async((direction, frame))

    def _update_measurement_display(self, selected_rows_cols):
        if not selected_rows_cols:
            return

        min_row = min([row for row, _ in selected_rows_cols])
        max_row = max([row for row, _ in selected_rows_cols])

        def get_row_ts(row):
            return TimestampRenderer.parse_timestamp(
                self._log_widget.table.item(row, 1).text())

        def get_load_str(num_frames, dt):
            if dt >= 1e-6:
                return 'average load %.1f FPS' % (num_frames / dt)
            return 'average load is unknown'

        if min_row == max_row:
            num_frames = min_row
            first_ts = get_row_ts(0)
            current_ts = get_row_ts(min_row)
            dt = current_ts - first_ts
            flash(self,
                  '%d frames from beginning, %.3f sec since first frame, %s',
                  num_frames, dt, get_load_str(num_frames, dt))
        else:
            num_frames = max_row - min_row + 1
            first_ts = get_row_ts(min_row)
            last_ts = get_row_ts(max_row)
            dt = last_ts - first_ts
            flash(self, '%d frames, timedelta %.6f sec, %s', num_frames, dt,
                  get_load_str(num_frames, dt))
Beispiel #14
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        pq.setConfigOption('background', 'y')
        pq.setConfigOption('foreground', 'k')
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(912, 659)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.text_hodnoty1 = QtWidgets.QTextBrowser(self.centralwidget)
        self.text_hodnoty1.setGeometry(QtCore.QRect(30, 60, 151, 181))
        self.text_hodnoty1.setObjectName("text_hodnoty1")
        self.text_hodnoty2 = QtWidgets.QTextBrowser(self.centralwidget)
        self.text_hodnoty2.setGeometry(QtCore.QRect(445, 50, 151, 192))
        self.text_hodnoty2.setObjectName("text_hodnoty2")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(30, 10, 201, 21))
        font = QtGui.QFont()
        font.setFamily("System")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)

        self.label.setFont(font)
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(30, 40, 47, 13))
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(450, 30, 47, 13))
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(200, 60, 121, 16))
        self.label_4.setObjectName("label_4")
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(200, 110, 121, 16))
        self.label_5.setObjectName("label_5")
        self.label_6 = QtWidgets.QLabel(self.centralwidget)
        self.label_6.setGeometry(QtCore.QRect(610, 50, 121, 16))
        self.label_6.setObjectName("label_6")
        self.label_7 = QtWidgets.QLabel(self.centralwidget)
        self.label_7.setGeometry(QtCore.QRect(610, 110, 121, 16))
        self.label_7.setObjectName("label_7")
        self.prumer1 = QtWidgets.QTextBrowser(self.centralwidget)
        self.prumer1.setGeometry(QtCore.QRect(200, 80, 141, 31))
        self.prumer1.setObjectName("prumer1")
        self.prumer2 = QtWidgets.QTextBrowser(self.centralwidget)
        self.prumer2.setGeometry(QtCore.QRect(610, 70, 141, 31))
        self.prumer2.setObjectName("prumer2")
        self.smodch1 = QtWidgets.QTextBrowser(self.centralwidget)
        self.smodch1.setGeometry(QtCore.QRect(200, 130, 141, 31))
        self.smodch1.setObjectName("smodch1")
        self.smodch2 = QtWidgets.QTextBrowser(self.centralwidget)
        self.smodch2.setGeometry(QtCore.QRect(610, 130, 141, 31))
        self.smodch2.setObjectName("smodch2")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(0, 0, 771, 281))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
        self.groupBox.setPalette(palette)
        self.groupBox.setAutoFillBackground(True)
        self.groupBox.setTitle("")
        self.groupBox.setObjectName("groupBox")
        self.buttonMereni = QtWidgets.QPushButton(self.groupBox)
        self.buttonMereni.setGeometry(QtCore.QRect(610, 200, 141, 41))
        self.buttonMereni.setObjectName("buttonMereni")
        self.buttonMereni.clicked.connect(self.one_measure)
        self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_2.setGeometry(QtCore.QRect(770, 0, 141, 281))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
        self.groupBox_2.setPalette(palette)
        self.groupBox_2.setAutoFillBackground(True)
        self.groupBox_2.setTitle("")
        self.groupBox_2.setObjectName("groupBox_2")
        self.label_8 = QtWidgets.QLabel(self.groupBox_2)
        self.label_8.setGeometry(QtCore.QRect(10, 80, 121, 16))
        font = QtGui.QFont()
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.label_8.setFont(font)
        self.label_8.setAlignment(QtCore.Qt.AlignCenter)
        self.label_8.setObjectName("label_8")
        self.rozdil = QtWidgets.QTextBrowser(self.groupBox_2)
        self.rozdil.setGeometry(QtCore.QRect(20, 100, 111, 31))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        self.rozdil.setPalette(palette)
        self.rozdil.setObjectName("rozdil")
        self.groupBox_3 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_3.setGeometry(QtCore.QRect(0, 280, 911, 381))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
        self.groupBox_3.setPalette(palette)
        self.groupBox_3.setAutoFillBackground(True)
        self.groupBox_3.setTitle("")
        self.groupBox_3.setObjectName("groupBox_3")
        self.label_9 = QtWidgets.QLabel(self.groupBox_3)
        self.label_9.setGeometry(QtCore.QRect(20, 10, 201, 21))
        font = QtGui.QFont()
        font.setFamily("System")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.label_9.setFont(font)
        self.label_9.setObjectName("label_9")
        self.graphicsView = PlotWidget(self.groupBox_3)
        self.graphicsView.setGeometry(QtCore.QRect(250, 10, 651, 341))
        self.graphicsView.setObjectName("graphicsView")
        self.label_10 = QtWidgets.QLabel(self.groupBox_3)
        self.label_10.setGeometry(QtCore.QRect(20, 40, 91, 16))
        self.label_10.setObjectName("label_10")
        self.label_11 = QtWidgets.QLabel(self.groupBox_3)
        self.label_11.setGeometry(QtCore.QRect(20, 60, 91, 16))
        self.label_11.setObjectName("label_11")
        self.label_12 = QtWidgets.QLabel(self.groupBox_3)
        self.label_12.setGeometry(QtCore.QRect(20, 80, 91, 16))
        self.label_12.setObjectName("label_12")
        self.lineEdit = QtWidgets.QLineEdit(self.groupBox_3)
        self.lineEdit.setGeometry(QtCore.QRect(20, 100, 221, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.lineEdit.setText(
            datetime.datetime.now().strftime("Data_" + "%Y-%m-%d_%H%M%S" +
                                             ".csv"))
        reg_ex = QtCore.QRegExp("([a-zA-Z0-9\s_,\]\[\(\)\-:])+.csv$")
        self.lineEdit.setValidator(
            QtGui.QRegExpValidator(reg_ex, self.lineEdit))

        self.lineEdit_interval = QtWidgets.QLineEdit(self.groupBox_3)
        self.lineEdit_interval.setGeometry(QtCore.QRect(90, 60, 151, 20))
        self.lineEdit_interval.setInputMethodHints(QtCore.Qt.ImhDigitsOnly)
        self.lineEdit_interval.setObjectName("lineEdit_interval")
        self.lineEdit_interval.setValidator(QtGui.QIntValidator())
        self.lineEdit_pocet_2 = QtWidgets.QLineEdit(self.groupBox_3)
        self.lineEdit_pocet_2.setGeometry(QtCore.QRect(90, 40, 151, 20))
        self.lineEdit_pocet_2.setInputMethodHints(QtCore.Qt.ImhDigitsOnly)
        self.lineEdit_pocet_2.setObjectName("lineEdit_pocet_2")
        self.lineEdit_pocet_2.setValidator(QtGui.QIntValidator())
        self.buttonMereniDynamicke = QtWidgets.QPushButton(self.groupBox_3)
        self.buttonMereniDynamicke.setGeometry(QtCore.QRect(20, 120, 221, 21))
        self.buttonMereniDynamicke.setObjectName("buttonMereniDynamicke")
        self.buttonMereniDynamicke.clicked.connect(self.multiple_measure)
        self.text_dynhodnoty = QtWidgets.QTextBrowser(self.groupBox_3)
        self.text_dynhodnoty.setGeometry(QtCore.QRect(20, 170, 151, 181))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        self.text_dynhodnoty.setPalette(palette)
        self.text_dynhodnoty.setObjectName("text_dynhodnoty")
        self.label_13 = QtWidgets.QLabel(self.groupBox_3)
        self.label_13.setGeometry(QtCore.QRect(20, 150, 47, 13))
        self.label_13.setObjectName("label_13")
        self.groupBox.raise_()
        self.text_hodnoty1.raise_()
        self.text_hodnoty2.raise_()
        self.label.raise_()
        self.label_2.raise_()
        self.label_3.raise_()
        self.label_4.raise_()
        self.label_5.raise_()
        self.label_6.raise_()
        self.label_7.raise_()
        self.prumer1.raise_()
        self.prumer2.raise_()
        self.smodch1.raise_()
        self.smodch2.raise_()
        self.groupBox_2.raise_()
        self.groupBox_3.raise_()
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

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

    def multiple_measure(self):
        print("multiple")
        self.buttonMereni.setEnabled(False)
        self.buttonMereniDynamicke.setEnabled(False)
        self.graphicsView.plotItem.clear()
        total_measurements = int(self.lineEdit_pocet_2.text())
        period_time = int(self.lineEdit_interval.text())
        dyn_value = np.array([])
        dyn_prumer1 = np.array([])
        dyn_prumer2 = np.array([])
        dyn_smodch1 = np.array([])
        dyn_smodch2 = np.array([])

        self.text_dynhodnoty.setText("")
        QtGui.QGuiApplication.processEvents()

        for measurement in range(total_measurements):
            self.text_hodnoty1.setText("")
            self.text_hodnoty2.setText("")
            self.rozdil.setText("0")
            self.prumer1.setText("0")
            self.prumer2.setText("0")
            self.smodch1.setText("0")
            self.smodch2.setText("0")
            json_trigger_command = """
                                {"id":1,"method":"call","params":{"path":"measval/cmdTriggerCapturedValue1","args":[]}}
                                """
            json_get_command = """
                                {"method":"fetch_all","params":{"path":"measval/values/capturedValue1"}}
                                """
            json_trigger = json.loads(json_trigger_command)
            json_get = json.loads(json_get_command)
            expected_message = """"path":"measval/values/capturedValue1""" ""
            sensor1_values = [None] * 10
            measured_values = np.zeros((10, ))
            try:
                ws = create_connection("ws://10.0.0.46:8081")
            except Exception as ex:
                print(ex)
            print("Start mereni 1:" + str(datetime.datetime.now()))
            for mereni in range(10):
                ws.send(json.dumps(json_trigger))
                result = ws.recv()
                time.sleep(.1)
                # TODO check result
                ws.send(json.dumps(json_get))
                clipx_message = ""
                while expected_message not in clipx_message:
                    clipx_message = ws.recv()

                    sensor1_values[mereni] = json.loads(clipx_message)
                self.text_hodnoty1.append("{:.4E}".format(
                    Decimal(sensor1_values[mereni]["params"]["value"])))
                QtGui.QGuiApplication.processEvents()
                measured_values[mereni] = sensor1_values[mereni]["params"][
                    "value"]
            ws.close()
            print("Stop mereni 1:" + str(datetime.datetime.now()))
            dyn_prumer1 = np.append(dyn_prumer1, measured_values.mean())
            dyn_smodch1 = np.append(dyn_smodch1, measured_values.std())
            self.prumer1.setText("{:.4E}".format(
                Decimal(measured_values.mean())))
            self.smodch1.setText("{:.4E}".format(Decimal(
                measured_values.std())))
            QtGui.QGuiApplication.processEvents()

            sensor2_values = [None] * 10
            measured2_values = np.zeros((10, 1))
            ws2 = create_connection("ws://10.0.0.52:8081")
            self.text_hodnoty2.setText("")
            print("Start mereni 2:" + str(datetime.datetime.now()))
            for mereni in range(10):
                ws2.send(json.dumps(json_trigger))
                result = ws2.recv()
                time.sleep(.1)
                # TODO check result
                ws2.send(json.dumps(json_get))
                clipx_message = ""
                while not expected_message in clipx_message:
                    clipx_message = ws2.recv()

                    sensor2_values[mereni] = json.loads(clipx_message)

                # print(sensor1_values[mereni]["params"]["value"])
                self.text_hodnoty2.append("{:.4E}".format(
                    Decimal(sensor2_values[mereni]["params"]["value"])))
                QtGui.QGuiApplication.processEvents()
                measured2_values[mereni] = sensor2_values[mereni]["params"][
                    "value"]

            ws2.close()
            print("Stop mereni 2:" + str(datetime.datetime.now()))
            dyn_prumer2 = np.append(dyn_prumer2, measured2_values.mean())
            dyn_smodch2 = np.append(dyn_smodch2, measured2_values.std())
            self.prumer2.setText("{:.4E}".format(
                Decimal(measured2_values.mean())))
            self.smodch2.setText("{:.4E}".format(
                Decimal(measured2_values.std())))

            dyn_value = np.append(
                dyn_value,
                measured_values.mean() - measured2_values.mean())
            self.text_dynhodnoty.append("{:.4E}".format(Decimal(
                dyn_value[-1])))
            self.rozdil.setText("{:.4E}".format(Decimal(
                dyn_value[measurement])))
            if len(dyn_value) > 1:
                try:
                    self.graphicsView.plot(dyn_value,
                                           pen=pq.mkPen(
                                               'b',
                                               width=3,
                                               style=QtCore.Qt.SolidLine,
                                               color=(200, 200, 255)))
                    self.graphicsView.getPlotItem().showGrid(x=True,
                                                             y=True,
                                                             alpha=1)
                    QtGui.QGuiApplication.processEvents()
                except Exception as ex:
                    print(ex)
            start_pause = (datetime.datetime.now())

            time_difference = start_pause - start_pause
            time_difference_seconds = time_difference.total_seconds()
            while time_difference_seconds < period_time:
                time.sleep(0.05)
                QtGui.QGuiApplication.processEvents()
                time_difference = datetime.datetime.now() - start_pause
                time_difference_seconds = time_difference.total_seconds()
        self.buttonMereni.setEnabled(True)
        self.buttonMereniDynamicke.setEnabled(True)
        QtGui.QGuiApplication.processEvents()
        output = np.asarray(
            [dyn_value, dyn_value, dyn_value, dyn_value, dyn_value])
        try:
            np.savetxt(self.lineEdit.text(),
                       output.transpose(),
                       delimiter=",",
                       header="diff,smodch1,smodch2,prumer1,prumer2")
        except Exception as ex:
            print(ex)
        self.lineEdit.setText(
            datetime.datetime.now().strftime("Data_" + "%Y-%m-%d_%H%M%S" +
                                             ".csv"))
        QtGui.QGuiApplication.processEvents()

    def one_measure(self):
        self.buttonMereni.setEnabled(False)
        self.buttonMereniDynamicke.setEnabled(False)
        QtGui.QGuiApplication.processEvents()
        self.text_hodnoty1.setText("")
        self.text_hodnoty2.setText("")
        self.rozdil.setText("0")
        self.prumer1.setText("")
        self.prumer2.setText("")
        self.rozdil.setText("")
        json_trigger_command = """
                    {"id":1,"method":"call","params":{"path":"measval/cmdTriggerCapturedValue1","args":[]}}
                    """
        json_get_command = """
                    {"method":"fetch_all","params":{"path":"measval/adcBinVal32"}}
                    """
        json_trigger = json.loads(json_trigger_command)
        json_get = json.loads(json_get_command)
        expected_message = """"path":"measval/values/capturedValue1""" ""
        sensor1_values = [None] * 10
        measured_values = np.zeros((10, ))

        ws = create_connection("ws://10.0.0.46:8081")

        for mereni in range(10):
            ws.send(json.dumps(json_trigger))
            result = ws.recv()
            time.sleep(.1)
            # TODO check result
            ws.send(json.dumps(json_get))
            clipx_message = ""
            while expected_message not in clipx_message:
                clipx_message = ws.recv()

                sensor1_values[mereni] = json.loads(clipx_message)
            self.text_hodnoty1.append(
                str(sensor1_values[mereni]["params"]["value"]))
            QtGui.QGuiApplication.processEvents()
            measured_values[mereni] = sensor1_values[mereni]["params"]["value"]
        ws.close()

        self.prumer1.setText("{:.4E}".format(Decimal(measured_values.mean())))
        self.smodch1.setText("{:.4E}".format(Decimal(measured_values.std())))
        QtGui.QGuiApplication.processEvents()
        sensor2_values = [None] * 10
        measured2_values = np.zeros((10, 1))
        ws2 = create_connection("ws://10.0.0.46:8081")
        self.text_hodnoty2.setText("")
        for mereni in range(10):
            ws2.send(json.dumps(json_trigger))
            result = ws2.recv()
            time.sleep(.1)
            print(mereni)
            # TODO check result
            ws2.send(json.dumps(json_get))
            clipx_message = ""
            while not expected_message in clipx_message:
                clipx_message = ws2.recv()

                sensor2_values[mereni] = json.loads(clipx_message)

            # print(sensor1_values[mereni]["params"]["value"])
            self.text_hodnoty2.append("{:.4E}".format(
                Decimal(sensor2_values[mereni]["params"]["value"])))
            QtGui.QGuiApplication.processEvents()
            measured2_values[mereni] = sensor2_values[mereni]["params"][
                "value"]

        ws2.close()

        self.prumer2.setText("{:.4E}".format(Decimal(measured2_values.mean())))
        self.smodch2.setText("{:.4E}".format(Decimal(measured2_values.std())))
        rozdil = measured_values.mean() - measured2_values.mean()
        self.rozdil.setText("{:.4E}".format(Decimal(rozdil)))
        self.buttonMereni.setEnabled(True)
        self.buttonMereniDynamicke.setEnabled(True)
        QtGui.QGuiApplication.processEvents()

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Měření"))
        self.label.setText(_translate("MainWindow", "Statické měření"))
        self.label_2.setText(_translate("MainWindow", "Čidlo 1"))
        self.label_3.setText(_translate("MainWindow", "Čidlo 2"))
        self.label_4.setText(_translate("MainWindow", "Průměrná hodnota"))
        self.label_5.setText(_translate("MainWindow", "Směrodatná odchylka"))
        self.label_6.setText(_translate("MainWindow", "Průměrná hodnota"))
        self.label_7.setText(_translate("MainWindow", "Směrodatná odchylka"))
        self.buttonMereni.setText(_translate("MainWindow", "Měření"))
        self.label_8.setText(_translate("MainWindow", "Rozdíl"))
        self.label_9.setText(_translate("MainWindow", "Dynamické měření"))
        self.label_10.setText(_translate("MainWindow", "Počet měření"))
        self.label_11.setText(_translate("MainWindow", "Interval [s]"))
        self.label_12.setText(_translate("MainWindow", "Název souboru"))
        self.buttonMereniDynamicke.setText(
            _translate("MainWindow", "Zahájit měření"))
        self.label_13.setText(_translate("MainWindow", "Hodnoty"))
Beispiel #15
0
class widget_mfi_lon_plot(QWidget):

    #-----------------------------------------------------------------------
    # DEFINE THE INITIALIZATION FUNCTION.
    #-----------------------------------------------------------------------

    def __init__(self, core):

        # Inherit all attributes of an instance of "QWidget".

        super(widget_mfi_lon_plot, self).__init__()

        # Store the Janus core.

        self.core = core

        # Prepare to respond to signals received from the core.

        self.connect(self.core, SIGNAL('janus_rset'), self.resp_rset)
        self.connect(self.core, SIGNAL('janus_chng_mfi'), self.resp_chng_mfi)

        # Initialize this widget's instance of "PlotWidget", which will
        # contain the plot of MFI magnetic field data.

        # Note.  The "QGridLayout" object given to this widget as its
        #        layout is essentially a dummy.  I could have just had
        #        this class inherit "PlotWidget", but I think that this
        #        gives me a bit more control (and a similar structure
        #        "janus_widget_fc_cup").

        self.setLayout(QGridLayout())

        self.plt = PlotWidget()
        self.layout().addWidget(self.plt)

        self.layout().setContentsMargins(0, 0, 0, 0)

        # Extract the individual elements of the "PlotWidget" object
        # (e.g., it's axes) for more convenient access later.

        self.vbx = self.plt.getViewBox()

        self.axs_x = self.plt.getAxis('bottom')
        self.axs_y = self.plt.getAxis('left')

        self.ptm = self.plt.getPlotItem()

        # Initialize and store the pens and fonts.

        self.pen_vbx = mkPen(color='k')
        self.pen_crv_lon = mkPen(color='#FFD700')

        self.fnt = self.core.app.font()

        # Configure the plot: disable automatic adjustments and
        # adjustments made by the user, change the background and
        # foreground colors, enable grid lines for both axes, label the
        # axes, adjust the tick font size, adjust the "AxisItem" sizes,
        # and add a margin around the entire plot.

        self.plt.disableAutoRange()
        self.plt.setMouseEnabled(False, False)
        self.plt.setMenuEnabled(False)
        self.plt.hideButtons()

        self.plt.setBackground('w')
        setConfigOption('foreground', 'k')

        #####self.plt.showGrid( True, True )

        labelStyle = {'color': 'k'}
        self.axs_x.setLabel('Time [s]', **labelStyle)
        self.axs_y.setLabel('Azim. [deg]', **labelStyle)

        self.axs_x.label.setFont(self.fnt)
        self.axs_y.label.setFont(self.fnt)

        self.axs_x.setTickFont(self.fnt)
        self.axs_y.setTickFont(self.fnt)

        self.axs_x.setHeight(35)
        self.axs_y.setWidth(40)

        self.vbx.border = self.pen_vbx

        self.ptm.setContentsMargins(5, 5, 5, 5)

        # Initialize the curves that will be added to this plot.

        self.crv_lon = None

        # Populate this plot and adjust it's settings.

        self.make_plt()

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR POPULATING THE PLOT.
    #-----------------------------------------------------------------------

    def make_plt(self):

        # Reset the plot (i.e., remove all plot elements).

        self.rset_plt()

        # Establish the ranges of its time and magnetic field values.
        # If the core contains no data or only a single datum,
        # improvise (for the purpose of later establishing axis limits).

        if (self.core.n_mfi >= 1):

            # Establish the domain of the plot.

            t_min = min(amin(self.core.mfi_s), 0.)
            t_max = max(amax(self.core.mfi_s), self.core.fc_spec['dur'])

            # Establish the range of the plot.  As part of this,
            # ensure that the range satisfies a minimum size and has
            # sufficient padding.

            ang_max = max(self.core.mfi_b_lon)
            ang_min = min(self.core.mfi_b_lon)

            ang_max = 5. + ang_max
            ang_min = -5. + ang_min

            d_t_0 = t_max - t_min

            d_t = max(1.5 + d_t_0, 3.)

            t_max = t_min + d_t

        else:

            t_min = 0.001
            t_max = 3.500

            ang_min = -360
            ang_max = 360

        # Set the range of the axis of each plot.

        self.plt.setXRange(t_min, t_max, padding=0.0)
        self.plt.setYRange(ang_min, ang_max, padding=0.0)

        # If the core contains no Wind/MFI magnetic field data, return.

        if (self.core.n_mfi <= 0):
            return

        # Generate and display each curve for the plot.

        self.crv_lon = PlotDataItem(self.core.mfi_s,
                                    self.core.mfi_b_lon,
                                    pen=self.pen_crv_lon)

        self.plt.addItem(self.crv_lon)

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR RESETTING THIS PLOT (CLEARING ALL ELEMENTS).
    #-----------------------------------------------------------------------

    def rset_plt(self):

        # Hide and remove each of this plot's elements.

        if (self.crv_lon is not None):
            self.plt.removeItem(self.crv_lon)

        # Permanently delete this plot's elements by setting each of the
        # variables that store them to "None".

        self.crv_lon = None

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR RESPONDING TO THE "rset" SIGNAL.
    #-----------------------------------------------------------------------

    def resp_rset(self):

        # Reset the plot.

        self.rset_plt()

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR RESPONDING TO THE "chng_mfi" SIGNAL.
    #-----------------------------------------------------------------------

    def resp_chng_mfi(self):

        # Regenerate the plot.

        self.make_plt()
class PyQtGraphDataPlot(QWidget):

    limits_changed = Signal()

    def __init__(self, parent=None):
        super(PyQtGraphDataPlot, self).__init__(parent)
        self._plot_widget = PlotWidget()
        self._plot_widget.getPlotItem().addLegend()
        self._plot_widget.setBackground((255, 255, 255))
        self._plot_widget.setXRange(0, 10, padding=0)
        vbox = QVBoxLayout()
        vbox.addWidget(self._plot_widget)
        self.setLayout(vbox)
        self._plot_widget.getPlotItem().sigRangeChanged.connect(self.limits_changed)

        self._curves = {}
        self._current_vline = None

    def add_curve(self, curve_id, curve_name, curve_color=QColor(Qt.blue), markers_on=False):
        pen = mkPen(curve_color, width=1)
        symbol = "o"
        symbolPen = mkPen(QColor(Qt.black))
        symbolBrush = mkBrush(curve_color)
        # this adds the item to the plot and legend
        if markers_on:
            plot = self._plot_widget.plot(name=curve_name, pen=pen, symbol=symbol, symbolPen=symbolPen, symbolBrush=symbolBrush, symbolSize=4)
        else:
            plot = self._plot_widget.plot(name=curve_name, pen=pen)
        self._curves[curve_id] = plot

    def remove_curve(self, curve_id):
        curve_id = str(curve_id)
        if curve_id in self._curves:
            self._plot_widget.removeItem(self._curves[curve_id])
            del self._curves[curve_id]
            self._update_legend()
           
    def _update_legend(self):
        # clear and rebuild legend (there is no remove item method for the legend...)
        self._plot_widget.clear()
        self._plot_widget.getPlotItem().legend.items = []
        for curve in self._curves.values():
            self._plot_widget.addItem(curve)
        if self._current_vline:
            self._plot_widget.addItem(self._current_vline)
 
    def redraw(self):
        pass

    def set_values(self, curve_id, data_x, data_y):
        curve = self._curves[curve_id]
        curve.setData(data_x, data_y)

    def vline(self, x, color):
        if self._current_vline:
            self._plot_widget.removeItem(self._current_vline)
        self._current_vline = self._plot_widget.addLine(x=x, pen=color)

    def set_xlim(self, limits):
        # TODO: this doesn't seem to handle fast updates well
        self._plot_widget.setXRange(limits[0], limits[1], padding=0)

    def set_ylim(self, limits):
        self._plot_widget.setYRange(limits[0], limits[1], padding=0)

    def get_xlim(self):
        x_range, _ = self._plot_widget.viewRange()
        return x_range

    def get_ylim(self):
        _, y_range = self._plot_widget.viewRange()
        return y_range
Beispiel #17
0
class ControllerGUITab(QWidget):
    LEFT_COLUMN_MAX_WIDTH = 400

    # This signal tells the global tab if is not possible to start dosing for this tab
    # False is sent out when the dosing vectors are incorrect or when the process is already started
    dosingSignal = pyqtSignal(bool)

    # This just signals if saving was enabled/disabled by the user in the tab, so the global tab can update itself
    savingSignal = pyqtSignal(bool)

    # Signal when a sample is ready for the combined plot
    sampleReady = pyqtSignal(int, np.float16)

    def __init__(self, controller: Controller):
        super().__init__()
        # Create the master layout
        outerLayout = QHBoxLayout()
        self.graph = None
        self.controller = controller
        self.temperatureController = None
        self.tempControllerGroup = None
        self.sensor1 = None
        self.sensor2 = None
        self.sensor1Group = None
        self.sensor2Group = None

        self.vorNormalButton = None
        self.vorClosedButton = None
        self.vorOpenButton = None

        self.gasFactorEdit = None
        self.pvFullScaleEdit = None
        self.pvSigtypeDropdown = None
        self.spFullScaleEdit = None
        self.spSigtypeDropdown = None
        self.spSourceDropdown = None
        self.decimalDropdown = None
        self.measureUnitsDropdown = None
        self.timebaseDropdown = None

        self.bufferSizeEdit = None
        self.intervalEdit = None
        self.setpointEdit = None
        self.setpointUnitsLabel = None
        self.saveCsvButton = None

        self.sensor1Timer = None
        self.sensor1SampleIntervalEdit = None
        self.sensor1BufferSizeEdit = None

        self.sensor2Timer = None
        self.sensor2SampleIntervalEdit = None
        self.sensor2BufferSizeEdit = None

        self.temperatureSlider = None
        self.temperatureLabel = None
        self.tempReadoutLabel = None
        self.rangeLowEdit = None
        self.rangeHighEdit = None
        self.rampingCheckbox = None
        self.gradientEdit = None
        self.tempControlButton = None

        self.dosingTimesEdit = None
        self.dosingTimes = None
        self.dosingValuesEdit = None
        self.dosingValues = None
        self.dosingUnitsLabel = None
        self.dosingLabel = None
        self.dosingVorStateLabel = None
        self.dosingControlButton = None
        self.dosingEnabled = False

        # Data buffers
        self.sampleBufferSize = 64
        self.samplesPV = RingBuffer(capacity=self.sampleBufferSize,
                                    dtype=np.float16)
        self.samplesTotalizer = RingBuffer(capacity=self.sampleBufferSize,
                                           dtype=np.float32)
        self.sampleTimestamps = RingBuffer(capacity=self.sampleBufferSize,
                                           dtype=datetime)

        # Nest the inner layouts into the outer layout
        outerLayout.addLayout(self.create_left_column())
        outerLayout.addLayout(self.create_right_column())
        # Set the window's main layout
        self.setLayout(outerLayout)

        # Generic timer that calls generic_update every second
        # Used to update a few labels
        self.genericTimer = QTimer()
        self.genericTimer.timeout.connect(self.update_generic)
        self.genericTimer.start(1000)

        self.graphTimer = QTimer()
        self.graphTimer.timeout.connect(self.update_plot)
        self.graphTimer.start(int(60 * 1000 * float(self.intervalEdit.text())))

        self.dosingValue = None
        self.dosingTimer = QTimer()
        self.dosingTimer.timeout.connect(self.dosing_process)

        self.csvFile = None
        self.csvIterator = 1

        self.defaultStyleSheet = QLineEdit().styleSheet()

        # Current dosing value, used to set the setpoint edit
        # text correctly after a process shutdown
        self.spValue = 1.0

        # Get initial dosing values from the text inside
        self.dosingValues = [
            float(x) for x in self.dosingValuesEdit.text().split(sep=',')
            if x.strip() != ''
        ]
        self.dosingTimes = [
            float(x) * 60 * 1000
            for x in self.dosingTimesEdit.text().split(sep=',')
            if x.strip() != ''
        ]
        self.dosingValues.reverse()
        self.dosingTimes.reverse()

    def get_measurement(self):
        # Proper implementation that gets the data from the device over serial
        current, total, timestamp = self.controller.get_measurements()
        if total is not None:
            self.samplesTotalizer.append(total)
            self.samplesPV.append(current)
            self.sampleTimestamps.append(timestamp)
            self.sampleReady.emit(self.controller.channel, current)

    # Save samples to a csv file, named after the current time and controller number it is coming from
    # After this function saving is continued by update_plot function, which calls append_to_csv
    def save_to_csv_start(self):
        # If saving is invoked from global tab while it is already enabled, close the old file,
        # so no sensor data will be lost and it will be closed properly
        if self.csvFile is not None:
            self.save_to_csv_stop()
        filename = datetime.now().strftime(
            f"controller{self.controller.channel}_%Y-%m-%d_%H-%M-%S.csv")

        self.csvFile = open(filename, 'w')
        self.csvFile.write(
            f"Gas factor:{self.controller.get_gas()}\tDecimal point:{self.controller.get_decimal_point()},\tUnits:{self.controller.get_measurement_units()}/{self.controller.get_time_base()}\n"
        )
        self.csvFile.write("{:<15} {:^18} {:>19}\n".format(
            "Measurement", "Totalizer", "Time of measurement"))
        for i in range(0, len(self.samplesPV) - 1):
            self.csvFile.write("{:<15},{:^18},{:>19}\n".format(
                self.samplesPV[len(self.samplesPV) - 1],
                self.samplesTotalizer[len(self.samplesPV) - 1],
                self.sampleTimestamps[len(self.samplesPV) -
                                      1].strftime("%Y/%m/%d,%H:%M:%S")))

        self.saveCsvButton.clicked.disconnect()
        self.saveCsvButton.clicked.connect(self.save_to_csv_stop)
        self.saveCsvButton.setText("Stop saving to CSV")
        self.savingSignal.emit(True)

    def append_to_csv(self):
        # check if file is bigger than ~8MB
        if self.csvFile.tell() > 8192000:
            name = re.sub(
                r"(|_[0-9]+).csv", f"_{self.csvIterator}.csv",
                self.csvFile.name.split("\\")[
                    len(self.csvFile.name.split("\\")) - 1])
            self.csvIterator += 1
            self.append_sensor()
            self.csvFile.close()
            self.csvFile = open(name, 'w')
        self.csvFile.write("{:<15},{:^18},{:>19}\n".format(
            self.samplesPV[len(self.samplesPV) - 1],
            self.samplesTotalizer[len(self.samplesPV) - 1],
            self.sampleTimestamps[len(self.samplesPV) -
                                  1].strftime("%Y/%m/%d,%H:%M:%S")))

    def save_to_csv_stop(self):
        self.append_sensor()
        self.csvFile.close()
        self.csvFile = None
        self.saveCsvButton.clicked.disconnect()
        self.saveCsvButton.clicked.connect(self.save_to_csv_start)
        self.saveCsvButton.setText("Start saving to CSV")
        self.csvIterator = 1
        self.savingSignal.emit(False)

    def append_sensor(self):
        # if available, append data from sensors
        if self.sensor1 is not None and len(self.sensor1.buffer) > 0:
            self.csvFile.write(f"Sensor 1 header: {self.sensor1.header}\n")
            for i in range(0, len(self.sensor1.buffer)):
                self.csvFile.write(str(self.sensor1.buffer[i]))
            self.sensor1.buffer.clear()
            self.csvFile.write('\n')

        if self.sensor2 is not None and len(self.sensor2.buffer) > 0:
            self.csvFile.write(f"Sensor 2 header: {self.sensor2.header}\n")
            for i in range(0, len(self.sensor2.buffer)):
                self.csvFile.write(str(self.sensor2.buffer[i]))
            self.sensor2.buffer.clear()

    # Handler functions for UI elements
    # TODO: react to returned value from functions
    def update_vor_normal(self):
        if self.vorNormalButton.isChecked():
            # disable other buttons to clarify which VOR state is active
            self.vorClosedButton.setChecked(False)
            self.vorOpenButton.setChecked(False)
            self.controller.set_valve_override(Controller.VOR_OPTION_NORMAL)
            self.dosingVorStateLabel.setText("VOR is normal")
            self.dosingVorStateLabel.setStyleSheet("color: green;")

    def update_vor_closed(self):
        if self.vorClosedButton.isChecked():
            self.vorNormalButton.setChecked(False)
            self.vorOpenButton.setChecked(False)
            self.controller.set_valve_override(Controller.VOR_OPTION_CLOSED)
            self.dosingVorStateLabel.setText("VOR is closed")
            self.dosingVorStateLabel.setStyleSheet("color: red;")

    def update_vor_open(self):
        if self.vorOpenButton.isChecked():
            self.vorClosedButton.setChecked(False)
            self.vorNormalButton.setChecked(False)
            self.controller.set_valve_override(Controller.VOR_OPTION_OPEN)
            self.dosingVorStateLabel.setText("VOR is open")
            self.dosingVorStateLabel.setStyleSheet("color: red;")

    def update_gas_factor(self):
        self.controller.set_gas_factor(float(self.gasFactorEdit.text()))

    def update_pv_full_scale(self):
        self.controller.set_pv_full_scale(float(self.pvFullScaleEdit.text()))

    def update_pv_signal_type(self):
        self.controller.set_pv_signal_type(
            self.pvSigtypeDropdown.currentText())

    def update_sp_full_scale(self):
        self.controller.set_sp_full_scale(float(self.spFullScaleEdit.text()))

    def update_sp_signal_type(self):
        self.controller.set_sp_signal_type(
            self.spSigtypeDropdown.currentText())

    def update_source(self):
        self.controller.set_source(self.spSourceDropdown.currentText())

    def update_decimal_point(self):
        self.controller.set_decimal_point(self.decimalDropdown.currentText())

    def update_measure_units(self):
        if self.dosingUnitsLabel is not None:
            self.dosingUnitsLabel.setText(
                f"{self.measureUnitsDropdown.currentText()}/{self.timebaseDropdown.currentText()}"
            )
        if self.setpointUnitsLabel is not None:
            self.setpointUnitsLabel.setText(
                f"{self.measureUnitsDropdown.currentText()}/{self.timebaseDropdown.currentText()}"
            )
        self.controller.set_measurement_units(
            self.measureUnitsDropdown.currentText())

    def update_time_base(self):
        if self.dosingUnitsLabel is not None:
            self.dosingUnitsLabel.setText(
                f"{self.measureUnitsDropdown.currentText()}/{self.timebaseDropdown.currentText()}"
            )
        if self.setpointUnitsLabel is not None:
            self.setpointUnitsLabel.setText(
                f"{self.measureUnitsDropdown.currentText()}/{self.timebaseDropdown.currentText()}"
            )
        self.controller.set_time_base(self.timebaseDropdown.currentText())

    def update_buffer_size(self):
        self.change_buffer_size(int(self.bufferSizeEdit.text()))
        self.sampleBufferSize = int(self.bufferSizeEdit.text())

    def update_graph_timer(self):
        self.graphTimer.setInterval(
            float(self.intervalEdit.text()) * 60 * 1000)

    def update_setpoint(self):
        value = float(self.setpointEdit.text())
        self.controller.set_setpoint(value)

    def update_sensor1_timer(self):
        self.sensor1Timer.setInterval(
            float(self.sensor1SampleIntervalEdit.text()) * 60 * 1000)

    def update_sensor1_buffer(self):
        self.sensor1.change_buffer_size(int(self.sensor1BufferSizeEdit.text()))

    def update_sensor2_timer(self):
        self.sensor2Timer.setInterval(
            float(self.sensor2SampleIntervalEdit.text()) * 60 * 1000)

    def update_sensor2_buffer(self):
        self.sensor2.change_buffer_size(int(self.sensor2BufferSizeEdit.text()))

    def update_temperature(self):
        self.temperatureController.set_temperature(
            float(self.temperatureSlider.value()))
        self.temperatureLabel.setText(self.temperatureSlider.value())

    def update_range_low(self):
        newTemp = self.temperatureController.set_range_low(
            float(self.rangeLowEdit.text()))
        self.temperatureSlider.setMinimum(float(self.rangeLowEdit.text()))
        self.temperatureSlider.setValue(newTemp)

    def update_range_high(self):
        newTemp = self.temperatureController.set_range_high(
            float(self.rangeHighEdit.text()))
        self.temperatureSlider.setMaximum(float(self.rangeHighEdit.text()))
        self.temperatureSlider.setValue(newTemp)

    def update_ramping_enable(self):
        if self.rampingCheckbox.isChecked():
            self.temperatureController.ramping_on()
        else:
            self.temperatureController.ramping_off()

    def update_gradient(self):
        self.temperatureController.set_gradient(float())

    def update_temp_control_enable(self):
        if self.tempControlButton.isChecked():
            self.temperatureController.ramping_on()
            self.tempControlButton.setText("Disable output")
        else:
            self.temperatureController.ramping_off()
            self.tempControlButton.setText("Enable output")

    def update_dosing_vectors(self):
        self.dosingValues = [
            float(x) for x in self.dosingValuesEdit.text().split(sep=',')
            if x.strip() != ''
        ]
        self.dosingTimes = [
            float(x) * 1000 * 60
            for x in self.dosingTimesEdit.text().split(sep=',')
            if x.strip() != ''
        ]

        # Since we will be using pop() to get the next values, we reverse the arrays
        self.dosingValues.reverse()
        self.dosingTimes.reverse()

        if len(self.dosingTimes) != len(self.dosingValues) or len(
                self.dosingTimes) * len(self.dosingValues) == 0:
            self.dosingTimesEdit.setStyleSheet("color: red;")
            self.dosingValuesEdit.setStyleSheet("color: red;")
            self.dosingControlButton.setEnabled(False)
            self.dosingSignal.emit(True)
        else:
            self.dosingTimesEdit.setStyleSheet(self.defaultStyleSheet)
            self.dosingValuesEdit.setStyleSheet(self.defaultStyleSheet)
            self.dosingControlButton.setEnabled(True)
            self.dosingSignal.emit(False)

    def update_dosing_state(self):
        if self.dosingControlButton.isChecked():
            self.dosingValuesEdit.setEnabled(False)
            self.dosingValuesEdit.setStyleSheet("color: grey")
            self.dosingTimesEdit.setEnabled(False)
            self.dosingTimesEdit.setStyleSheet("color: grey")
            self.dosingControlButton.setText("Disable dosing")
            self.setpointEdit.setEnabled(False)
            self.dosingEnabled = True
            self.dosingSignal.emit(True)
            # Set VOR to normal for dosing
            self.vorNormalButton.setChecked(True)
            self.update_vor_normal()
            self.dosing_process()
        else:
            self.dosingValuesEdit.setEnabled(True)
            self.dosingValuesEdit.setStyleSheet(self.defaultStyleSheet)
            self.dosingTimesEdit.setEnabled(True)
            self.dosingTimesEdit.setStyleSheet(self.defaultStyleSheet)
            self.dosingControlButton.setText("Enable dosing")
            self.setpointEdit.setEnabled(True)
            self.dosingEnabled = False
            self.end_dosing_process()

    # This function sets the setpoint to those values that were set when "Enable dosing" was pressed
    # and iterates over them
    def dosing_process(self):
        self.spValue = self.dosingValues.pop()
        spTime = self.dosingTimes.pop()

        self.setpointEdit.setText(f"{str(self.spValue)} - dosing is enabled")
        self.controller.set_setpoint(self.spValue)

        if len(self.dosingTimes) == 0:
            self.dosingTimer.timeout.disconnect()
            self.dosingTimer.singleShot(spTime, self.end_dosing_process)

        self.dosingTimer.setInterval(spTime)
        self.dosingTimer.start()

    def update_generic(self):
        if self.dosingTimer.isActive() and len(self.dosingValues) > 0:
            if self.dosingTimer.remainingTime() / 1000 > 60:
                self.dosingLabel.setText(
                    f"{int(self.dosingTimer.remainingTime() / (1000 * 60))} minutes {int(self.dosingTimer.remainingTime() / 1000) % 60} seconds until next dosing value: {self.dosingValues[-1]}"
                )
            else:
                self.dosingLabel.setText(
                    f"{int(self.dosingTimer.remainingTime() / 1000)} seconds until next dosing value: {self.dosingValues[-1]}"
                )
        elif self.dosingTimer.isActive() and len(self.dosingValues) == 0:
            self.dosingLabel.setText(
                f"{int(self.dosingTimer.remainingTime() / 1000)} seconds until end of process"
            )
        else:
            self.dosingLabel.setText("Dosing disabled")

        if self.temperatureController is not None:
            self.tempReadoutLabel.setText(
                f"Readout: {self.temperatureController.read_temperature()} ℃")
        else:
            self.tempReadoutLabel.setText("Readout: None ℃")

    def end_dosing_process(self):
        self.dosingControlButton.setChecked(False)
        self.dosingControlButton.setText("Enable dosing")
        self.dosingLabel.setText("Dosing disabled")
        self.dosingTimer.stop()

        # Since all the values have been popped and the text is unchanged, we fill the vectors again
        self.dosingValues = [
            float(x) for x in self.dosingValuesEdit.text().split(sep=',')
            if x.strip() != ''
        ]
        self.dosingTimes = [
            float(x) * 60 * 1000
            for x in self.dosingTimesEdit.text().split(sep=',')
            if x.strip() != ''
        ]
        self.dosingValues.reverse()
        self.dosingTimes.reverse()

        # Remove the string portion from setpoint field
        self.setpointEdit.setText(str(self.spValue))

        # Unlock the setpoint and dosing values/times fields
        self.setpointEdit.setEnabled(True)
        self.dosingValuesEdit.setEnabled(True)
        self.dosingTimesEdit.setEnabled(True)

        # Return to normal stylesheet
        self.dosingValuesEdit.setStyleSheet(self.defaultStyleSheet)
        self.dosingTimesEdit.setStyleSheet(self.defaultStyleSheet)

        # reconnect the dosing_process function to the timer
        self.dosingTimer.timeout.connect(self.dosing_process)

        # Set the setpoint to 0 and close valve at the end
        self.controller.set_setpoint(0)
        self.setpointEdit.setText("0")

        self.vorClosedButton.setChecked(True)
        self.dosingSignal.emit(False)
        self.update_vor_closed()

    def update_plot(self):
        self.graph.clear()
        self.get_measurement()
        self.graph.plot(self.samplesPV,
                        pen=pyqtgraph.mkPen((255, 127, 0), width=1.25),
                        symbolBrush=(255, 127, 0),
                        symbolPen=pyqtgraph.mkPen((255, 127, 0)),
                        symbol='o',
                        symbolSize=5,
                        name="symbol ='o'")
        if self.csvFile is not None:
            self.append_to_csv()

    def update_sensor1_group(self):
        if self.sensor1Group.isChecked():
            dg = SensorConfigDialog()
            dg.accepted.connect(self.connect_sensor1)
            # if unsuccessful, disable the temperature controller group
            if dg.exec_() == 0:
                self.sensor1Group.setChecked(False)
        else:
            self.sensor1.close()
            self.sensor1Timer.stop()
            self.sensor1 = None

    # connect to sensor instance 1 using values returned by the dialog
    def connect_sensor1(self, values):
        self.sensor1 = Sensor(comport=values['port'],
                              baudrate=values['baudrate'],
                              databits=values['databits'],
                              parity=values['paritybits'],
                              stopbits=values['stopbits'],
                              dataHeader=values['header'])
        self.sensor1Timer = QTimer()
        self.sensor1Timer.setInterval(
            float(self.sensor1SampleIntervalEdit.text()) * 1000 * 60)
        self.sensor1Timer.timeout.connect(self.sensor1_get_data)
        self.sensor1Timer.start()

    # Wrapper function to handle exceptions from GUI level
    def sensor1_get_data(self):
        try:
            self.sensor1.getData()
        except SerialException as se:
            dg = QErrorMessage()
            dg.setWindowIcon(QIcon(':/icon.png'))
            dg.setWindowTitle("Sensor 1 Exception")

            filename = datetime.now().strftime("sensor1_%Y-%m-%d_%H-%M-%S.csv")
            dumpFile = open(filename, 'w')

            dumpFile.write(f"Sensor 1 header: {self.sensor1.header}\n")
            for i in range(0, len(self.sensor1.buffer)):
                self.csvFile.write(str(self.sensor1.buffer[i]))
            dumpFile.close()

            self.sensor1Group.setChecked(False)
            self.update_sensor1_group()
            dg.showMessage(f"Sensor 1 has encountered an exception: {se}")
            dg.exec_()

    def update_sensor2_group(self):
        if self.sensor2Group.isChecked():
            dg = SensorConfigDialog()
            dg.accepted.connect(self.connect_sensor2)
            # if unsuccessful, disable the temperature controller group
            if dg.exec_() == 0:
                self.sensor2Group.setChecked(False)
        else:
            self.sensor2.close()
            self.sensor2Timer.stop()
            self.sensor2 = None

    # connect to sensor instance 2 using values returned by the dialog
    def connect_sensor2(self, values):
        self.sensor2 = Sensor(comport=values['port'],
                              baudrate=values['baudrate'],
                              databits=values['databits'],
                              parity=values['paritybits'],
                              stopbits=values['stopbits'],
                              dataHeader=values['header'])
        self.sensor2Timer = QTimer()
        self.sensor2Timer.setInterval(
            float(self.sensor2SampleIntervalEdit.text()) * 1000 * 60)
        self.sensor2Timer.timeout.connect(self.sensor2_get_data)
        self.sensor2Timer.start()

    # Wrapper function to handle exceptions from GUI level
    def sensor2_get_data(self):
        try:
            self.sensor2.getData()
        except SerialException as se:
            dg = QErrorMessage()
            dg.setWindowIcon(QIcon(':/icon.png'))
            dg.setWindowTitle("Sensor 2 Exception")

            filename = datetime.now().strftime("sensor2_%Y-%m-%d_%H-%M-%S.csv")
            dumpFile = open(filename, 'w')

            dumpFile.write(f"Sensor 2 header: {self.sensor2.header}\n")
            for i in range(0, len(self.sensor2.buffer)):
                self.csvFile.write(str(self.sensor2.buffer[i]))
            dumpFile.close()

            self.sensor2Group.setChecked(False)
            self.update_sensor2_group()
            dg.showMessage(f"Sensor 2 has encountered an exception: {se}")
            dg.exec_()

    def update_temperature_group(self):
        if self.tempControllerGroup.isChecked():
            dg = AR6X2ConfigDialog()
            dg.accepted.connect(self.connect_temp_controller)
            # if unsuccessful, disable the temperature controller group
            if dg.exec_() == 0:
                self.tempControllerGroup.setChecked(False)
        else:
            self.temperatureController = None
            self.tempControlButton.setText("Enable output")

    # Connect to the AR6X2 controller using given parameters
    def connect_temp_controller(self, values):
        self.temperatureController = AR6X2(port=values['port'],
                                           address=values['address'])

    def create_left_column(self):
        # Create a vertical layout for the left column
        leftColumnLayout = QVBoxLayout()

        # Valve override group
        vorGroup = QGroupBox("Valve override")
        vorLayout = QHBoxLayout()

        self.vorNormalButton = QPushButton("Normal")
        self.vorNormalButton.setMinimumWidth(50)
        self.vorNormalButton.setFixedHeight(75)
        self.vorNormalButton.setCheckable(True)
        self.vorNormalButton.clicked.connect(self.update_vor_normal)

        self.vorClosedButton = QPushButton("Closed")
        self.vorClosedButton.setMinimumWidth(50)
        self.vorClosedButton.setFixedHeight(75)
        self.vorClosedButton.setCheckable(True)
        self.vorClosedButton.clicked.connect(self.update_vor_closed)

        self.vorOpenButton = QPushButton("Open")
        self.vorOpenButton.setMinimumWidth(50)
        self.vorOpenButton.setFixedHeight(75)
        self.vorOpenButton.setCheckable(True)
        self.vorOpenButton.clicked.connect(self.update_vor_open)

        vorState = self.controller.get_valve_override()
        if vorState == "Normal":
            self.vorNormalButton.setChecked(True)
            self.vorClosedButton.setChecked(False)
            self.vorOpenButton.setChecked(False)
        elif vorState == "Closed":
            self.vorNormalButton.setChecked(False)
            self.vorClosedButton.setChecked(True)
            self.vorOpenButton.setChecked(False)
        elif vorState == "Open":
            self.vorNormalButton.setChecked(False)
            self.vorClosedButton.setChecked(False)
            self.vorOpenButton.setChecked(True)
        else:
            raise ValueError(f"Unexpected vor state: {vorState}")

        vorLayout.addWidget(self.vorNormalButton)
        vorLayout.addWidget(self.vorClosedButton)
        vorLayout.addWidget(self.vorOpenButton)

        vorGroup.setLayout(vorLayout)
        vorGroup.setMaximumWidth(ControllerGUITab.LEFT_COLUMN_MAX_WIDTH)
        leftColumnLayout.addWidget(vorGroup, alignment=Qt.AlignTop)

        # Process configuration group
        processGroup = QGroupBox("Process configuration")
        processLayout = QFormLayout()

        self.gasFactorEdit = QLineEdit()
        self.gasFactorEdit.setValidator(
            QRegExpValidator(QRegExp("[0-9]{1,3}(|\\.[0-9]{1,3})")))
        self.gasFactorEdit.editingFinished.connect(self.update_gas_factor)
        self.gasFactorEdit.setText("{:.5f}".format(self.controller.get_gas()))

        self.pvFullScaleEdit = QLineEdit()
        self.pvFullScaleEdit.setValidator(
            QRegExpValidator(QRegExp("(-|)[0-9]{1,3}(|\\.[0-9]{1,3})")))
        self.pvFullScaleEdit.editingFinished.connect(self.update_pv_full_scale)
        self.pvFullScaleEdit.setText(str(self.controller.get_pv_full_scale()))

        self.pvSigtypeDropdown = QComboBox()
        self.pvSigtypeDropdown.addItems(Controller.INPUT_PORT_TYPES.keys())
        self.pvSigtypeDropdown.currentTextChanged.connect(
            self.update_pv_signal_type)
        self.pvSigtypeDropdown.setCurrentText(
            str(self.controller.get_pv_signal_type()))

        self.spFullScaleEdit = QLineEdit()
        self.spFullScaleEdit.setValidator(
            QRegExpValidator(QRegExp("(-|)[0-9]{1,3}(|\\.[0-9]{1,3})")))
        self.spFullScaleEdit.editingFinished.connect(self.update_sp_full_scale)
        self.spFullScaleEdit.setText(str(self.controller.get_sp_full_scale()))

        self.spSigtypeDropdown = QComboBox()
        self.spSigtypeDropdown.addItems(Controller.OUTPUT_PORT_TYPES.keys())
        self.spSigtypeDropdown.currentTextChanged.connect(
            self.update_sp_signal_type)
        self.spSigtypeDropdown.setCurrentText(
            str(self.controller.get_sp_signal_type()))

        self.spSourceDropdown = QComboBox()
        self.spSourceDropdown.addItems(Controller.SP_SOURCES.keys())
        self.spSourceDropdown.currentTextChanged.connect(self.update_source)
        self.spSourceDropdown.setCurrentText(str(self.controller.get_source()))

        self.decimalDropdown = QComboBox()
        self.decimalDropdown.addItems(Controller.DECIMAL_POINTS.keys())
        self.decimalDropdown.currentTextChanged.connect(
            self.update_decimal_point)
        self.decimalDropdown.setCurrentText(
            str(self.controller.get_decimal_point()))

        self.measureUnitsDropdown = QComboBox()
        self.measureUnitsDropdown.addItems(Controller.MEASUREMENT_UNITS.keys())
        self.measureUnitsDropdown.currentTextChanged.connect(
            self.update_measure_units)
        self.measureUnitsDropdown.setCurrentText(
            str(self.controller.get_measurement_units()))

        self.timebaseDropdown = QComboBox()
        self.timebaseDropdown.addItems(Controller.RATE_TIME_BASE.keys())
        self.timebaseDropdown.currentTextChanged.connect(self.update_time_base)
        self.timebaseDropdown.setCurrentText(
            str(self.controller.get_time_base()))

        processLayout.addRow(QLabel("Gas factor"), self.gasFactorEdit)
        processLayout.addRow(QLabel("PV Full Scale"), self.pvFullScaleEdit)
        processLayout.addRow(QLabel("PV Signal Type"), self.pvSigtypeDropdown)
        processLayout.addRow(QLabel("SP Full Scale"), self.spFullScaleEdit)
        processLayout.addRow(QLabel("SP Signal Type"), self.spSigtypeDropdown)
        processLayout.addRow(QLabel("Setpoint source"), self.spSourceDropdown)
        processLayout.addRow(QLabel("Decimal point"), self.decimalDropdown)
        processLayout.addRow(QLabel("Measurement units"),
                             self.measureUnitsDropdown)
        processLayout.addRow(QLabel("Time base"), self.timebaseDropdown)

        processGroup.setLayout(processLayout)
        processGroup.setMaximumWidth(ControllerGUITab.LEFT_COLUMN_MAX_WIDTH)
        leftColumnLayout.addWidget(processGroup, alignment=Qt.AlignTop)
        leftColumnLayout.setStretch(1, 100)

        runtimeGroup = QGroupBox("Runtime options")
        runtimeLayout = QVBoxLayout()

        layout = QHBoxLayout()

        self.bufferSizeEdit = QLineEdit()
        self.bufferSizeEdit.setText("64")
        self.bufferSizeEdit.setValidator(QIntValidator())
        self.bufferSizeEdit.editingFinished.connect(self.update_buffer_size)

        layout.addWidget(QLabel("Sample buffer size"))
        layout.addWidget(self.bufferSizeEdit)
        layout.addWidget(QLabel("samples"))

        runtimeLayout.addLayout(layout)

        layout = QHBoxLayout()

        self.intervalEdit = QLineEdit()
        self.intervalEdit.setText("1")
        self.intervalEdit.setValidator(
            QRegExpValidator(QRegExp("[0-9]*(|\\.[0-9]*)")))
        self.intervalEdit.editingFinished.connect(self.update_graph_timer)

        layout.addWidget(QLabel("Data update interval"))
        layout.addWidget(self.intervalEdit)
        layout.addWidget(QLabel("minutes"))

        runtimeLayout.addLayout(layout)

        layout = QHBoxLayout()

        self.setpointEdit = QLineEdit()
        self.setpointEdit.setValidator(
            QRegExpValidator(QRegExp("[0-9]*(|\\.[0-9]*)")))
        self.setpointEdit.editingFinished.connect(self.update_setpoint)
        self.setpointEdit.setText(str(self.controller.get_setpoint()))

        self.setpointUnitsLabel = QLabel(
            f"{self.measureUnitsDropdown.currentText()}/{self.timebaseDropdown.currentText()}"
        )

        layout.addWidget(QLabel("Setpoint"))
        layout.addWidget(self.setpointEdit)
        layout.addWidget(self.setpointUnitsLabel)

        runtimeLayout.addLayout(layout)

        layout = QHBoxLayout()

        manualMeasureButton = QPushButton("Get measurement")
        manualMeasureButton.clicked.connect(self.update_plot)
        self.saveCsvButton = QPushButton("Start saving to CSV")
        self.saveCsvButton.clicked.connect(self.save_to_csv_start)

        layout.addWidget(manualMeasureButton)
        layout.addWidget(self.saveCsvButton)

        runtimeLayout.addLayout(layout)

        runtimeGroup.setLayout(runtimeLayout)
        runtimeGroup.setMaximumWidth(ControllerGUITab.LEFT_COLUMN_MAX_WIDTH)
        runtimeGroup.setFixedHeight(150)

        leftColumnLayout.addWidget(runtimeGroup, alignment=Qt.AlignBottom)

        return leftColumnLayout

    def create_right_column(self):
        # Create layouts and elements for the right column, including graph and sensor/temperature control/dosing groups
        rightColumnLayout = QVBoxLayout()
        rightInnerGrid = QGridLayout()

        # Creation of sensor 1 and sub-elements
        self.sensor1Group = QGroupBox("Sensor 1")
        self.sensor1Group.setCheckable(True)
        self.sensor1Group.setChecked(False)
        self.sensor1Group.clicked.connect(self.update_sensor1_group)
        sensor1Layout = QVBoxLayout()

        layout = QHBoxLayout()

        self.sensor1SampleIntervalEdit = QLineEdit()
        self.sensor1SampleIntervalEdit.setValidator(
            QRegExpValidator(QRegExp("[0-9]*(|\\.[0-9]*)")))
        self.sensor1SampleIntervalEdit.setFixedWidth(100)
        self.sensor1SampleIntervalEdit.editingFinished.connect(
            self.update_sensor1_timer)
        self.sensor1SampleIntervalEdit.setText("1")

        label = QLabel('Sampling interval')
        label.setFixedWidth(90)
        layout.addWidget(label)
        layout.addWidget(self.sensor1SampleIntervalEdit)
        layout.addWidget(QLabel('minutes'))
        layout.setStretch(2, 10)
        sensor1Layout.addLayout(layout)

        layout = QHBoxLayout()

        self.sensor1BufferSizeEdit = QLineEdit()
        self.sensor1BufferSizeEdit.setValidator(QIntValidator())
        self.sensor1BufferSizeEdit.setFixedWidth(100)
        self.sensor1BufferSizeEdit.editingFinished.connect(
            self.update_sensor1_buffer)
        self.sensor1BufferSizeEdit.setText("64")

        label = QLabel('Buffer size')
        label.setFixedWidth(90)
        layout.addWidget(label)
        layout.addWidget(self.sensor1BufferSizeEdit)
        layout.addWidget(QLabel('samples'))
        layout.setStretch(2, 10)
        sensor1Layout.addLayout(layout)
        self.sensor1Group.setLayout(sensor1Layout)

        # Creation of sensor 2 and sub-elements
        self.sensor2Group = QGroupBox("Sensor 2")
        self.sensor2Group.setCheckable(True)
        self.sensor2Group.setChecked(False)
        self.sensor2Group.clicked.connect(self.update_sensor2_group)
        sensor2Layout = QVBoxLayout()

        layout = QHBoxLayout()

        self.sensor2SampleIntervalEdit = QLineEdit()
        self.sensor2SampleIntervalEdit.setValidator(
            QRegExpValidator(QRegExp("[0-9]*(|\\.[0-9]*)")))
        self.sensor2SampleIntervalEdit.setFixedWidth(100)
        self.sensor2SampleIntervalEdit.editingFinished.connect(
            self.update_sensor2_timer)
        self.sensor2SampleIntervalEdit.setText("1")

        label = QLabel('Sampling interval')
        label.setFixedWidth(90)
        layout.addWidget(label)
        layout.addWidget(self.sensor2SampleIntervalEdit)
        layout.addWidget(QLabel('minutes'))
        layout.setStretch(2, 10)
        sensor2Layout.addLayout(layout)

        layout = QHBoxLayout()

        self.sensor2BufferSizeEdit = QLineEdit()
        self.sensor2BufferSizeEdit.setValidator(QIntValidator())
        self.sensor2BufferSizeEdit.setFixedWidth(100)
        self.sensor2BufferSizeEdit.editingFinished.connect(
            self.update_sensor2_buffer)
        self.sensor2BufferSizeEdit.setText("64")

        label = QLabel('Buffer size')
        label.setFixedWidth(90)
        layout.addWidget(label)
        layout.addWidget(self.sensor2BufferSizeEdit)
        layout.addWidget(QLabel('samples'))
        layout.setStretch(2, 10)
        sensor2Layout.addLayout(layout)
        self.sensor2Group.setLayout(sensor2Layout)

        self.tempControllerGroup = QGroupBox("Temperature controller")
        self.tempControllerGroup.setCheckable(True)
        self.tempControllerGroup.setEnabled(
            False)  # Disabled functionality as it is untested
        self.tempControllerGroup.setChecked(False)
        self.tempControllerGroup.clicked.connect(self.update_temperature_group)
        tempControllerLayout = QVBoxLayout()

        layout = QHBoxLayout()

        self.temperatureSlider = QSlider(Qt.Horizontal)
        self.temperatureSlider.setMinimumWidth(95)
        self.temperatureSlider.setMaximumWidth(1000)
        self.temperatureSlider.setMinimum(-199.9)
        self.temperatureSlider.setMaximum(850.0)
        self.temperatureSlider.setValue(100)
        self.temperatureSlider.sliderMoved.connect(self.update_temperature)
        self.temperatureLabel = QLabel("100")
        layout.addWidget(QLabel("Temperature"), alignment=Qt.AlignLeft)
        layout.addWidget(self.temperatureSlider, alignment=Qt.AlignLeft)
        layout.addWidget(self.temperatureLabel, alignment=Qt.AlignLeft)
        layout.addWidget(QLabel("℃"), alignment=Qt.AlignLeft)

        layout.setStretch(3, 200)
        tempControllerLayout.addLayout(layout)

        # these edits have validators, but input still has to be capped
        layout = QHBoxLayout()
        self.rangeLowEdit = QLineEdit()
        self.rangeLowEdit.setMinimumWidth(30)
        self.rangeLowEdit.setMaximumWidth(60)
        self.rangeLowEdit.setText("-199.9")
        self.rangeLowEdit.setValidator(
            QRegExpValidator(
                QRegExp("(-[0-9]{1,3}\\.[0-9]|[0-9]{1,3}\\.[0-9|[0-9]{1,4})")))
        self.rangeLowEdit.editingFinished.connect(self.update_range_low)

        self.rangeHighEdit = QLineEdit()
        self.rangeHighEdit.setMinimumWidth(30)
        self.rangeHighEdit.setMaximumWidth(60)
        self.rangeHighEdit.setText("850.0")
        self.rangeHighEdit.setValidator(
            QRegExpValidator(
                QRegExp("(-[0-9]{1,3}\\.[0-9]|[0-9]{1,3}\\.[0-9|[0-9]{1,4})")))
        self.rangeHighEdit.editingFinished.connect(self.update_range_high)

        layout.addWidget(QLabel("Range"))
        layout.addWidget(self.rangeLowEdit, alignment=Qt.AlignLeft)
        layout.addWidget(self.rangeHighEdit, alignment=Qt.AlignLeft)
        layout.addWidget(QLabel("℃"))
        layout.setStretch(3, 10)
        tempControllerLayout.addLayout(layout)

        self.rampingCheckbox = QCheckBox()
        self.rampingCheckbox.stateChanged.connect(self.update_ramping_enable)

        self.tempReadoutLabel = QLabel("Readout: None ℃")

        layout = QHBoxLayout()
        layout.addWidget(QLabel("Ramping"), alignment=Qt.AlignLeft)
        layout.addWidget(self.rampingCheckbox, alignment=Qt.AlignLeft)
        layout.addWidget(self.tempReadoutLabel, alignment=Qt.AlignBottom)
        layout.setStretch(1, 10)

        tempControllerLayout.addLayout(layout)

        layout = QHBoxLayout()

        self.gradientEdit = QLineEdit()
        self.gradientEdit.setMinimumWidth(30)
        self.gradientEdit.setMaximumWidth(60)
        self.gradientEdit.setText("0.1")  # default value from the datasheet
        self.gradientEdit.editingFinished.connect(self.update_gradient)

        self.tempControlButton = QPushButton("Enable output")
        self.tempControlButton.setCheckable(True)
        self.tempControlButton.clicked.connect(self.update_temp_control_enable)

        layout.addWidget(QLabel("Gradient"), alignment=Qt.AlignLeft)
        layout.addWidget(self.gradientEdit, alignment=Qt.AlignLeft)
        layout.addWidget(QLabel("℃/min"))
        layout.addWidget(self.tempControlButton, alignment=Qt.AlignBottom)
        layout.setStretch(2, 10)

        tempControllerLayout.addLayout(layout)

        self.tempControllerGroup.setLayout(tempControllerLayout)
        self.tempControllerGroup.setMinimumWidth(200)
        self.tempControllerGroup.setFixedHeight(150)

        dosingGroup = QGroupBox("Dosing control")
        dosingGroup.setCheckable(False)
        dosingLayout = QVBoxLayout()

        layout = QHBoxLayout()
        self.dosingTimesEdit = QLineEdit()
        self.dosingTimesEdit.setMinimumWidth(160)
        self.dosingTimesEdit.setText("1, 1, 1.5")
        self.dosingTimesEdit.setValidator(
            QRegExpValidator(QRegExp("(([0-9]+|[0-9]+\\.[0-9]+),(| ))+")))
        self.dosingTimesEdit.textChanged.connect(self.update_dosing_vectors)

        label = QLabel("Times")
        label.setFixedWidth(55)

        layout.addWidget(label)
        layout.addWidget(self.dosingTimesEdit)
        layout.addWidget(QLabel("minutes"))
        dosingLayout.addLayout(layout)

        layout = QHBoxLayout()
        self.dosingValuesEdit = QLineEdit()
        self.dosingValuesEdit.setMinimumWidth(160)
        self.dosingValuesEdit.setText("1.0, 2.0, 5.0")
        self.dosingValuesEdit.setValidator(
            QRegExpValidator(QRegExp("(([0-9]+|[0-9]+\\.[0-9]+),(| ))+")))
        self.dosingValuesEdit.textChanged.connect(self.update_dosing_vectors)

        label = QLabel("Setpoints")
        label.setFixedWidth(55)

        self.dosingUnitsLabel = QLabel(
            f"{self.measureUnitsDropdown.currentText()}/{self.timebaseDropdown.currentText()}"
        )

        layout.addWidget(label)
        layout.addWidget(self.dosingValuesEdit)
        layout.addWidget(self.dosingUnitsLabel)
        dosingLayout.addLayout(layout)

        self.dosingLabel = QLabel("Dosing disabled")

        self.dosingVorStateLabel = QLabel(
            f"VOR is {self.controller.get_valve_override().lower()}")

        if "normal" in self.dosingVorStateLabel.text():
            self.dosingVorStateLabel.setStyleSheet("color: green")
        else:
            self.dosingVorStateLabel.setStyleSheet("color: red")

        self.dosingControlButton = QPushButton("Start dosing")
        self.dosingControlButton.setCheckable(True)
        self.dosingControlButton.clicked.connect(self.update_dosing_state)

        dosingLayout.addWidget(self.dosingLabel, alignment=Qt.AlignLeft)
        layout = QHBoxLayout()
        layout.addWidget(self.dosingVorStateLabel, alignment=Qt.AlignLeft)
        layout.addWidget(self.dosingControlButton, alignment=Qt.AlignRight)

        dosingLayout.addLayout(layout)

        # finally, assign the layout to the group
        dosingGroup.setLayout(dosingLayout)
        dosingGroup.setMinimumWidth(200)
        dosingGroup.setFixedHeight(150)

        rightInnerGrid.addWidget(self.sensor1Group, 0, 0)
        rightInnerGrid.addWidget(self.sensor2Group, 0, 1)
        rightInnerGrid.addWidget(self.tempControllerGroup, 1, 0)
        rightInnerGrid.addWidget(dosingGroup, 1, 1)

        rightInnerGrid.setColumnStretch(0, 100)
        rightInnerGrid.setColumnStretch(1, 100)

        self.graph = PlotWidget()
        self.graph.getPlotItem().showGrid(x=True, y=True, alpha=1)
        if "qdarkstyle" in sys.modules:
            self.graph.setBackground((25, 35, 45))

        rightColumnLayout.addWidget(self.graph)
        rightColumnLayout.addLayout(rightInnerGrid)

        return rightColumnLayout

    # function to change the amount of stored samples without losing previously gathered samples
    def change_buffer_size(self, value):
        if value > self.sampleBufferSize:
            newBufPV = RingBuffer(capacity=value, dtype=np.float16)
            newBufTotal = RingBuffer(capacity=value, dtype=np.float32)
            newTimestampBuf = RingBuffer(capacity=value, dtype=datetime)

            newBufPV.extend(self.samplesPV)
            newBufTotal.extend(self.samplesTotalizer)
            newTimestampBuf.extend(self.sampleTimestamps)

            self.samplesPV = newBufPV
            self.samplesTotalizer = newBufTotal
            self.sampleTimestamps = newTimestampBuf
        elif value < self.sampleBufferSize:
            newBufPV = RingBuffer(capacity=value, dtype=np.float16)
            newBufTotal = RingBuffer(capacity=value, dtype=np.float32)
            newTimestampBuf = RingBuffer(capacity=value, dtype=datetime)

            newBufPV.extend(self.samplesPV[:-value])
            newBufTotal.extend(self.samplesTotalizer[:-value])
            newTimestampBuf.extend(self.sampleTimestamps[:-value])

            self.samplesPV = newBufPV
            self.samplesTotalizer = newBufTotal
            self.sampleTimestamps = newTimestampBuf
Beispiel #18
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1146, 673)
        MainWindow.setAutoFillBackground(False)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(20, 50, 171, 51))
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(20, 110, 171, 51))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_3.setGeometry(QtCore.QRect(20, 170, 171, 51))
        self.pushButton_3.setObjectName("pushButton_3")
        self.lcdNumber = QtWidgets.QLCDNumber(self.centralwidget)
        self.lcdNumber.setGeometry(QtCore.QRect(20, 390, 161, 81))
        self.lcdNumber.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.lcdNumber.setFrameShadow(QtWidgets.QFrame.Raised)
        self.lcdNumber.setLineWidth(4)
        self.lcdNumber.setSmallDecimalPoint(False)
        self.lcdNumber.setObjectName("lcdNumber")
        self.lcdNumber_2 = QtWidgets.QLCDNumber(self.centralwidget)
        self.lcdNumber_2.setGeometry(QtCore.QRect(20, 530, 161, 81))
        self.lcdNumber_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.lcdNumber_2.setFrameShadow(QtWidgets.QFrame.Raised)
        self.lcdNumber_2.setLineWidth(4)
        self.lcdNumber_2.setSmallDecimalPoint(False)
        self.lcdNumber_2.setObjectName("lcdNumber_2")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(20, 505, 91, 21))
        font = QtGui.QFont()
        font.setPointSize(20)
        font.setBold(True)
        font.setItalic(False)
        font.setWeight(75)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(20, 360, 121, 21))
        font = QtGui.QFont()
        font.setPointSize(20)
        font.setBold(True)
        font.setItalic(False)
        font.setWeight(75)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(220, 230, 71, 31))
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(220, 20, 60, 16))
        self.label_4.setObjectName("label_4")
        self.wave = PlotWidget(self.centralwidget)
        self.wave.setGeometry(QtCore.QRect(220, 40, 901, 191))
        self.wave.setObjectName("wave")
        self.spectrum = PlotWidget(self.centralwidget)
        self.spectrum.setGeometry(QtCore.QRect(220, 260, 901, 351))
        self.spectrum.setObjectName("spectrum")
        self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar.setGeometry(QtCore.QRect(20, 330, 161, 23))
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(20, 305, 161, 21))
        font = QtGui.QFont()
        font.setPointSize(20)
        self.label_5.setFont(font)
        self.label_5.setText("")
        self.label_5.setObjectName("label_5")
        self.radioButton = QtWidgets.QRadioButton(self.centralwidget)
        self.radioButton.setGeometry(QtCore.QRect(30, 240, 100, 20))
        self.radioButton.setChecked(True)
        self.radioButton.setObjectName("radioButton")
        self.radioButton_2 = QtWidgets.QRadioButton(self.centralwidget)
        self.radioButton_2.setGeometry(QtCore.QRect(110, 240, 100, 20))
        self.radioButton_2.setObjectName("radioButton_2")

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1146, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.pushButton.clicked.connect(MainWindow.slot1)
        self.pushButton_2.clicked.connect(MainWindow.slot2)
        self.pushButton_3.clicked.connect(MainWindow.slot3)
        self.radioButton.clicked.connect(MainWindow.slot4)
        self.radioButton_2.clicked.connect(MainWindow.slot5)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        # 波形グラフ
        self.plotwid1 = PlotWidget(self.centralwidget)
        self.plotwid1.setGeometry(QtCore.QRect(220, 40, 901, 191))
        self.plotwid1.setObjectName("wave")
        self.plotitem1 = self.plotwid1.getPlotItem()
        self.plotitem1.setMouseEnabled(x=False, y=False)
        self.plotitem1.setYRange(-1, 1)
        self.plotitem1.setXRange(0, MainWindow.N, padding=0)

        # スペクトルグラフ
        self.plotwid2 = PlotWidget(self.centralwidget)
        self.plotwid2.setGeometry(QtCore.QRect(220, 260, 901, 351))
        self.plotwid2.setObjectName("spectrum")
        self.plotitem2 = self.plotwid2.getPlotItem()
        self.plotitem2.setMouseEnabled(x=False, y=True)
        self.plotitem2.setYRange(35, 250)
        self.plotitem2.setXRange(20, MainWindow.RATE / 2, padding=0)

        # Plot data
        self.curve_wave = self.plotitem1.plot()
        self.curve_spectrum = self.plotitem2.plot()
        self.max_spectrum = self.plotitem2.plot(pen=pg.mkPen(color="r"))

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "校正イヤホン測定"))
        self.pushButton_2.setText(_translate("MainWindow", "百均イヤホン測定"))
        self.pushButton_3.setText(_translate("MainWindow", "終了"))
        self.label.setText(_translate("MainWindow", "音圧"))
        self.label_2.setText(_translate("MainWindow", "周波数[Hz]"))
        self.label_3.setText(_translate("MainWindow", "FFT"))
        self.label_4.setText(_translate("MainWindow", "波形"))
        self.radioButton.setText(_translate("MainWindow", "左耳L"))
        self.radioButton_2.setText(_translate("MainWindow", "右耳R"))
Beispiel #19
0
class DirectDriveWindow(QWidget):
    virtual_controller = None  # will hold an instance of the VirtualController-class
    motor_controller = None  # will hold an instance of the MotorController-class
    game_interfacer = None  # will hold an instance of the GameInterfacer-class

    # Variables that will be shared between multiple processes
    raw_force_signal_global = Value(
        'f', 0.0)  # raw force-feedback value coming from the game
    game_status_playing_global = Value(
        'b', False)  # game status (playing/not-playing)
    motor_pause_mode = Value(
        'b', False)  # if the motor should be idle when game is paused

    data_reconstruction = Value(
        'b', False)  # if the data-reconstruction feature should be used
    data_smoothing_level = Value(
        'i', 0)  # if the temproal smoothing feature should be used

    friction_global = Value('f', 0.0)  # strength of the friction effect
    damping_global = Value('f', 0.0)  # strength of the damping effect
    inertia_global = Value('f', 0.0)  # strength of the inertia effect

    encoder_pos_global = Value(
        'f', 0.0)  # holds the wheel position in encoder counts
    wheel_position_deg_global = Value(
        'f', 0.0)  # holds the wheel position in degrees
    lock_to_lock_global = Value(
        'f', 900.0
    )  # holds the digital limit of the wheel (used by the virtual controller)
    bump_to_bump_global = Value(
        'f', 900.0
    )  # holds the physical limit of the wheel (used by the motor controller)

    motor_current_global = Value(
        'f', 0.0
    )  # holds the current(Ampere) that is applied to the motor at any moment

    actual_max_force_global = Value(
        'f', 0.0
    )  # sets the actual maximum torque(Nm) the motor should be limited to
    invert_force_global = Value(
        'b', False)  # if the raw force-feedback value should be inverted

    motor_connected_global = Value(
        'b', False)  # motor status (connected/not-connected)
    motor_controller_due_for_restart_global = Value(
        'b', False)  # is set to true when connection to odrive board is lost

    motor_control_rate = Value(
        'f', 0.0)  # target refresh rate for the motor-control process

    profiles = []  # holds all loaded and newly created profiles
    selected_profile_index = 0  # holds the index of the currently selected profile

    graph_sample_rate = 60  # update-rate(Hz) for the motor-current graph
    graph_history_time_sec = 2  # time-window of the motor-current graph

    def __init__(self):
        super().__init__()
        self.setGeometry(100, 100, 1700, 575)
        self.setWindowTitle('DIY Direct Drive Wheel')

        #self.updater = LiveGuiUpdater()
        #self.updater.ticked.connect(self.LiveGuiTick)
        #self.updater.start()

        self.timer = QTimer()
        self.timer.timeout.connect(self.graph_update)
        self.timer.setInterval(int(1000 / self.graph_sample_rate))
        self.timer.start()

        self.gui_timer = QTimer()
        self.gui_timer.timeout.connect(self.LiveGuiTick)
        self.gui_timer.setInterval(int(1000 / 60))
        self.gui_timer.start()

        self.virtual_controller = VirtualController()
        self.virtual_controller.set_frequency(180)
        self.virtual_controller.steering_value_deg = self.wheel_position_deg_global
        self.virtual_controller.lock_to_lock = self.lock_to_lock_global
        self.virtual_controller.start()

        self.game_interfacer = GameInterfacer()
        self.game_interfacer.set_frequency(180)
        self.game_interfacer.wheel_force = self.raw_force_signal_global
        self.game_interfacer.invert_force = self.invert_force_global
        self.game_interfacer.game_status_playing = self.game_status_playing_global

        self.motor_controller = MotorController()
        self.motor_controller.set_frequency(360)
        self.motor_controller.signal_in = self.raw_force_signal_global
        self.motor_controller.game_status_playing = self.game_status_playing_global
        self.motor_controller.motor_pause_mode = self.motor_pause_mode
        self.motor_controller.data_reconstruction = self.data_reconstruction
        self.motor_controller.data_smoothing_level = self.data_smoothing_level
        self.motor_controller.friction = self.friction_global
        self.motor_controller.damping = self.damping_global
        self.motor_controller.inertia = self.inertia_global
        self.motor_controller.encoder_pos = self.encoder_pos_global
        self.motor_controller.wheel_pos_deg = self.wheel_position_deg_global
        self.motor_controller.bump_to_bump = self.bump_to_bump_global
        self.motor_controller.motor_current = self.motor_current_global
        self.motor_controller.actual_max_force = self.actual_max_force_global
        self.motor_controller.motor_connected = self.motor_connected_global
        self.motor_controller.due_for_restart = self.motor_controller_due_for_restart_global
        self.motor_controller.achieved_freq = self.motor_control_rate
        self.motor_controller.start()

        self.lblMotorRate = QLabel('motor control rate:', self)
        self.lblMotorRate.setFont(QFont("Times", 24, QFont.Normal))
        self.lblMotorRate.move(675, 25)

        self.lblMotorRateHz = QLabel('0.00 Hz', self)
        self.lblMotorRateHz.setFont(QFont("Times", 24, QFont.Normal))
        self.lblMotorRateHz.adjustSize()
        self.lblMotorRateHz.move(1125 - self.lblMotorRateHz.width(), 25)

        self.force_graph = PlotWidget(self)
        self.force_graph.move(675, 75)
        self.force_graph.resize(1000, 475)
        self.force_graph.setYRange(-15.0, 15.0)
        self.force_graph.setBackground((255, 255, 255))
        self.force_graph.showGrid(x=False, y=True)
        self.force_graph.addLegend()

        pen_ffb = pg.mkPen(color=(0, 0, 255))
        self.ffb_curve = self.force_graph.getPlotItem().plot(
            pen=pen_ffb, name='Game FFB (Nm)')
        pen_current = pg.mkPen(color=(0, 255, 0))
        self.current_curve = self.force_graph.getPlotItem().plot(
            pen=pen_current, name='Motor Torque (Nm)')
        self.ffb_history = [
            0
        ] * self.graph_sample_rate * self.graph_history_time_sec
        self.current_history = [
            0
        ] * self.graph_sample_rate * self.graph_history_time_sec

        self.load_profiles_from_file()
        self.build_gui()
        self.select_profile(0)

    # updates the graph showing the raw ffb and the motor torque
    def graph_update(self):
        # adding the latest raw game-ffb value(scaled to the actual torque value) to a list storing a history of this value
        self.ffb_history.append(self.raw_force_signal_global.value /
                                self.actual_max_force_global.value)
        if len(self.ffb_history
               ) >= self.graph_history_time_sec * self.graph_sample_rate:
            self.ffb_history.pop(0)
        self.ffb_curve.setData(self.ffb_history)

        # adding the latest final motor torque value to a list storing a history of this value
        self.current_history.append(
            self.motor_current_global.value /
            (self.actual_max_force_global.value * 2.75))
        if len(self.current_history
               ) >= self.graph_history_time_sec * self.graph_sample_rate:
            self.current_history.pop(0)
        self.current_curve.setData(self.current_history)

        # displaying the actually achieved refresh rate of the motor-control process
        self.lblMotorRateHz.setText(
            str(int(self.motor_control_rate.value * 100) / 100) + ' Hz')
        if self.motor_control_rate.value >= 360.0:
            self.lblMotorRateHz.setStyleSheet(
                'QLabel { color: rgb(0,155,0); }')
        else:
            self.lblMotorRateHz.setStyleSheet(
                'QLabel { color: rgb(155,0,0); }')

    # initializes and configures all the GUI-elements
    def build_gui(self):
        # WHEEL POSITION DATA AND SETTINGS

        # current bar
        self.lblCurrent = QLabel(self)
        self.lblCurrent.move(25 + 128, 25)
        self.lblCurrent.resize(0, 25)
        self.lblCurrent.setAutoFillBackground(True)
        self.lblCurrent.setStyleSheet(
            'QLabel { background-color: rgb(0,255,0); }')

        self.lblCurrentDivider = QLabel(self)
        self.lblCurrentDivider.move(25 + 128 - 1, 20)
        self.lblCurrentDivider.resize(2, 35)
        self.lblCurrentDivider.setAutoFillBackground(True)
        self.lblCurrentDivider.setStyleSheet(
            'QLabel { background-color: rgb(0,0,0); }')

        # wheel image
        self.lblWheelImage = QLabel(self)
        self.wheel_image = QImage('wheel_image.png')
        self.wheel_image_discon = QImage('wheel_image_disconnect.png')
        self.wheel_pixmap = QPixmap.fromImage(self.wheel_image)
        self.lblWheelImage.setPixmap(self.wheel_pixmap)
        self.lblWheelImage.resize(self.wheel_pixmap.width(),
                                  self.wheel_pixmap.height())
        self.lblWheelImage.move(25, 75)

        # motor status label
        self.lblMotorStatus_1 = QLabel('Motor Status:', self)
        self.lblMotorStatus_1.move(15, 60)
        self.lblMotorStatus_2 = QLabel('Not Connected', self)
        self.lblMotorStatus_2.move(15, 75)
        self.lblMotorStatus_2.setStyleSheet('QLabel { color: rgb(155,0,0); }')

        # wheel position
        self.lblWheelPos = QLabel('0.0°', self)
        self.lblWheelPos.move(25 + 150 + 25, 75 + 256 + 10)
        self.lblWheelPos.resize(200, 50)
        self.lblWheelPos.setFont(QFont("Times", 24, QFont.Normal))

        # center button
        center_pos = [25, 75 + 256 + 22, 150, 30]
        self.btnCenter = QPushButton('center Wheel', self)
        self.btnCenter.move(center_pos[0], center_pos[1])
        self.btnCenter.resize(center_pos[2], center_pos[3])
        self.btnCenter.clicked.connect(self.center_wheel)

        # lock-to-lock slider
        self.locklock_pos = [25, 425, 250, 0]
        self.lblLock = QLabel('Lock to Lock:', self)
        self.lblLock.move(self.locklock_pos[0], self.locklock_pos[1])
        self.sliLock = QSlider(Qt.Horizontal, self)
        self.sliLock.setTickPosition(QSlider.TicksAbove)
        self.sliLock.setTickInterval(10)
        self.sliLock.setMinimum(10)
        self.sliLock.setMaximum(120)
        self.sliLock.setValue(90)
        self.sliLock.setSingleStep(1)
        self.sliLock.move(self.locklock_pos[0], self.locklock_pos[1] + 20)
        self.sliLock.resize(self.locklock_pos[2], 25)
        self.sliLock.valueChanged.connect(self.change_lock)
        self.lblLockVal = QLabel('900°', self)
        self.lblLockVal.adjustSize()
        self.lblLockVal.move(
            self.locklock_pos[0] + self.locklock_pos[2] -
            self.lblLockVal.width(), self.locklock_pos[1])

        # bump_to_bump slider
        self.bumpbump_pos = [25, 500, 250, 0]
        self.lblBump = QLabel('Bump to Bump:', self)
        self.lblBump.move(self.bumpbump_pos[0], self.bumpbump_pos[1])
        self.sliBump = QSlider(Qt.Horizontal, self)
        self.sliBump.setTickPosition(QSlider.TicksAbove)
        self.sliBump.setTickInterval(10)
        self.sliBump.setMinimum(10)
        self.sliBump.setMaximum(120)
        self.sliBump.setValue(90)
        self.sliBump.setSingleStep(1)
        self.sliBump.move(self.bumpbump_pos[0], self.bumpbump_pos[1] + 20)
        self.sliBump.resize(self.bumpbump_pos[2], 25)
        self.sliBump.valueChanged.connect(self.change_bump)
        self.lblBumpVal = QLabel('900°', self)
        self.lblBumpVal.adjustSize()
        self.lblBumpVal.move(
            self.bumpbump_pos[0] + self.bumpbump_pos[2] -
            self.lblBumpVal.width(), self.bumpbump_pos[1])

        # WHEEL FORCE AND BEHAVIOR SETTINGS

        # game select combobox
        gameselect_pos = [325, 25, 250, 25]
        self.cbxGame = QComboBox(self)
        self.cbxGame.move(gameselect_pos[0], gameselect_pos[1])
        self.cbxGame.resize(gameselect_pos[2], gameselect_pos[3])
        for game in self.game_interfacer.games_available:
            self.cbxGame.addItem(game)
        self.cbxGame.activated.connect(self.select_game)

        # invert force checkbox
        invert_pos = [325, 55]
        self.cbInvert = QCheckBox('Invert Force Feedback', self)
        self.cbInvert.move(invert_pos[0], invert_pos[1])
        self.cbInvert.stateChanged.connect(self.toggle_invert)

        # motor pause mode checkbox
        motorpause_pos = [325, 85]
        self.cbMotorPause = QCheckBox('pause motor when game is paused', self)
        self.cbMotorPause.move(motorpause_pos[0], motorpause_pos[1])
        self.cbMotorPause.stateChanged.connect(self.toggle_motor_pause_mode)
        self.cbMotorPause.toggle()

        # maximum force slider
        self.max_force_pos = [325, 125, 250, 0]
        self.lblMaxForce = QLabel('Maximum Force in Nm:', self)
        self.lblMaxForce.move(self.max_force_pos[0], self.max_force_pos[1])
        self.sliMaxForce = QSlider(Qt.Horizontal, self)
        self.sliMaxForce.setTickPosition(QSlider.TicksAbove)
        self.sliMaxForce.setTickInterval(10)
        self.sliMaxForce.setMinimum(1)
        self.sliMaxForce.setMaximum(150)
        self.sliMaxForce.setValue(0)
        self.sliMaxForce.setSingleStep(1)
        self.sliMaxForce.move(self.max_force_pos[0],
                              self.max_force_pos[1] + 20)
        self.sliMaxForce.resize(self.max_force_pos[2], 25)
        self.sliMaxForce.valueChanged.connect(self.change_max_force)
        self.lblMaxForceVal = QLabel('0.0 Nm - (0.0 Amp)', self)
        self.lblMaxForceVal.adjustSize()
        self.lblMaxForceVal.move(
            self.max_force_pos[0] + self.max_force_pos[2] -
            self.lblMaxForceVal.width(), self.max_force_pos[1])

        # reconstruction checkbox
        reconst_pos = [325, 175 + 3]
        self.cbReconst = QCheckBox('Use Data Reconstruction', self)
        self.cbReconst.move(reconst_pos[0], reconst_pos[1])
        self.cbReconst.stateChanged.connect(self.toggle_reconstruction)
        self.cbReconst.setEnabled(False)

        # smoothing level combobox
        smoothing_pos = [475, 175, 100, 25]
        self.cbxSmoothing = QComboBox(self)
        self.cbxSmoothing.move(smoothing_pos[0], smoothing_pos[1])
        self.cbxSmoothing.resize(smoothing_pos[2], smoothing_pos[3])
        self.cbxSmoothing.addItem('no Smoothing')
        self.cbxSmoothing.addItem('1')
        self.cbxSmoothing.addItem('2')
        self.cbxSmoothing.addItem('3')
        self.cbxSmoothing.addItem('4')
        self.cbxSmoothing.addItem('5')
        self.cbxSmoothing.addItem('6')
        self.cbxSmoothing.addItem('7')
        self.cbxSmoothing.addItem('8')
        self.cbxSmoothing.addItem('9')
        self.cbxSmoothing.activated.connect(self.change_smoothing)
        self.cbxSmoothing.setEnabled(False)

        # friction slider
        self.friction_pos = [325, 215, 250, 0]
        self.lblFriction = QLabel('Friction:', self)
        self.lblFriction.move(self.friction_pos[0], self.friction_pos[1])
        self.sliFriction = QSlider(Qt.Horizontal, self)
        self.sliFriction.setTickPosition(QSlider.TicksAbove)
        self.sliFriction.setTickInterval(10)
        self.sliFriction.setMinimum(0)
        self.sliFriction.setMaximum(100)
        self.sliFriction.setValue(0)
        self.sliFriction.setSingleStep(1)
        self.sliFriction.move(self.friction_pos[0], self.friction_pos[1] + 20)
        self.sliFriction.resize(self.friction_pos[2], 25)
        self.sliFriction.valueChanged.connect(self.change_friction)
        self.lblFrictionVal = QLabel('0 %', self)
        self.lblFrictionVal.adjustSize()
        self.lblFrictionVal.move(
            self.friction_pos[0] + self.friction_pos[2] -
            self.lblFrictionVal.width(), self.friction_pos[1])

        # damping slider
        self.damping_pos = [325, 275, 250, 0]
        self.lblDamping = QLabel('Damping:', self)
        self.lblDamping.move(self.damping_pos[0], self.damping_pos[1])
        self.sliDamping = QSlider(Qt.Horizontal, self)
        self.sliDamping.setTickPosition(QSlider.TicksAbove)
        self.sliDamping.setTickInterval(10)
        self.sliDamping.setMinimum(0)
        self.sliDamping.setMaximum(100)
        self.sliDamping.setValue(0)
        self.sliDamping.setSingleStep(1)
        self.sliDamping.move(self.damping_pos[0], self.damping_pos[1] + 20)
        self.sliDamping.resize(self.damping_pos[2], 25)
        self.sliDamping.valueChanged.connect(self.change_damping)
        self.lblDampingVal = QLabel('0 %', self)
        self.lblDampingVal.adjustSize()
        self.lblDampingVal.move(
            self.damping_pos[0] + self.damping_pos[2] -
            self.lblDampingVal.width(), self.damping_pos[1])

        # inertia slider
        self.inertia_pos = [325, 335, 250, 0]
        self.lblInertia = QLabel('Inertia:', self)
        self.lblInertia.move(self.inertia_pos[0], self.inertia_pos[1])
        self.sliInertia = QSlider(Qt.Horizontal, self)
        self.sliInertia.setTickPosition(QSlider.TicksAbove)
        self.sliInertia.setTickInterval(10)
        self.sliInertia.setMinimum(0)
        self.sliInertia.setMaximum(100)
        self.sliInertia.setValue(0)
        self.sliInertia.setSingleStep(1)
        self.sliInertia.move(self.inertia_pos[0], self.inertia_pos[1] + 20)
        self.sliInertia.resize(self.inertia_pos[2], 25)
        self.sliInertia.valueChanged.connect(self.change_inertia)
        self.lblInertiaVal = QLabel('0 %', self)
        self.lblInertiaVal.adjustSize()
        self.lblInertiaVal.move(
            self.inertia_pos[0] + self.inertia_pos[2] -
            self.lblInertiaVal.width(), self.inertia_pos[1])

        # profile select combobox
        profileselect_pos = [325, 430, 250, 25]
        self.cbxProfiles = QComboBox(self)
        self.cbxProfiles.move(profileselect_pos[0], profileselect_pos[1])
        self.cbxProfiles.resize(profileselect_pos[2], profileselect_pos[3])
        for profile in self.profiles:
            self.cbxProfiles.addItem(profile.name)
        self.cbxProfiles.activated.connect(self.select_profile)

        # create profile button
        profilecreate_pos = [325, 460, 250, 25]
        self.btnCreate = QPushButton('create new profile', self)
        self.btnCreate.move(profilecreate_pos[0], profilecreate_pos[1])
        self.btnCreate.resize(profilecreate_pos[2], profilecreate_pos[3])
        self.btnCreate.clicked.connect(self.create_profile)

        # rename profile button
        profilerename_pos = [325, 490, 250, 25]
        self.btnRename = QPushButton('rename profile', self)
        self.btnRename.move(profilerename_pos[0], profilerename_pos[1])
        self.btnRename.resize(profilerename_pos[2], profilerename_pos[3])
        self.btnRename.clicked.connect(self.rename_profile)

        # cancel rename button
        cancelrename_pos = [325 + 200, 490, 50, 25]
        self.btnCancelRename = QPushButton('cancel', self)
        self.btnCancelRename.move(cancelrename_pos[0], cancelrename_pos[1])
        self.btnCancelRename.resize(cancelrename_pos[2], cancelrename_pos[3])
        self.btnCancelRename.clicked.connect(self.cancel_rename)
        self.btnCancelRename.setVisible(False)

        # rename textbox
        self.txtRename = QLineEdit(self)
        self.txtRename.move(profilerename_pos[0], profilerename_pos[1])
        self.txtRename.resize(profilerename_pos[2] - 35 - 55,
                              profilerename_pos[3])
        self.txtRename.setVisible(False)
        self.txtRename.textChanged.connect(self.check_name_validity)

        # save profile button
        profilesave_pos = [325, 520, 120, 25]
        self.btnSave = QPushButton('save profile', self)
        self.btnSave.move(profilesave_pos[0], profilesave_pos[1])
        self.btnSave.resize(profilesave_pos[2], profilesave_pos[3])
        self.btnSave.clicked.connect(self.save_current_profile_internally)

        # delete profile button
        profiledelete_pos = [325 + 130, 520, 120, 25]
        self.btnDelete = QPushButton('delete profile', self)
        self.btnDelete.move(profiledelete_pos[0], profiledelete_pos[1])
        self.btnDelete.resize(profiledelete_pos[2], profiledelete_pos[3])
        self.btnDelete.clicked.connect(self.delete_current_profile)

    # updates the GUI-elements that indicate the status of the motor (connected/not-connected)
    def LiveGuiTick(self):
        self.lblWheelPos.setText(
            str(int(self.wheel_position_deg_global.value * 10) / 10) + '°')

        self.lblCurrent.resize(
            int(
                np.abs(self.motor_current_global.value /
                       (self.actual_max_force_global.value * 2.75) * 128)), 25)
        if self.motor_current_global.value < 0.0:
            self.lblCurrent.move(
                25 + 128 -
                np.abs(self.motor_current_global.value /
                       (self.actual_max_force_global.value * 2.75) * 128), 25)

        tf = QTransform()
        tf.rotate(self.wheel_position_deg_global.value)

        if self.motor_connected_global.value:
            self.lblMotorStatus_2.setText('Connected')
            self.lblMotorStatus_2.setStyleSheet(
                'QLabel { color: rgb(0,155,0); }')
            img_rot = self.wheel_image.transformed(tf)
            self.btnCenter.setEnabled(True)
            self.lblWheelPos.setStyleSheet('QLabel { color: rgb(0,0,0); }')
        else:
            self.lblMotorStatus_2.setText('Not Connected')
            self.lblMotorStatus_2.setStyleSheet(
                'QLabel { color: rgb(155,0,0); }')
            img_rot = self.wheel_image_discon.transformed(tf)
            self.btnCenter.setEnabled(False)
            self.lblWheelPos.setStyleSheet(
                'QLabel { color: rgb(155,155,155); }')

        diagonal_overlength = (np.sqrt(np.square(256) * 2) - 256) / 2
        shift = int(
            np.abs(
                np.sin(np.deg2rad(self.wheel_position_deg_global.value * 2)) *
                diagonal_overlength))
        crop_rect = QRect(shift, shift, 256, 256)
        self.wheel_pixmap = QPixmap.fromImage(img_rot).copy(crop_rect)
        self.lblWheelImage.setPixmap(self.wheel_pixmap)

        if self.motor_controller_due_for_restart_global.value:
            self.motor_controller_due_for_restart_global.value = False
            print('restarting motor...')
            try:
                self.motor_controller.motor_control_process.terminate()
            except:
                pass
            self.motor_controller.start()

    # helper function to get the index of a profile with a certain name from the profile-list
    def get_profile_index(self, name):
        for i in range(len(self.profiles)):
            if self.profiles[i].name == name:
                return i

    # WHEEL POSITION SETTING FUNCTIONS
    def center_wheel(self):
        print('centering wheel')
        self.motor_controller.set_encoder_offset()

    def change_lock(self):
        val = int(self.sender().value() * 10)
        self.lblLockVal.setText(str(val) + '°')
        self.lock_to_lock_global.value = val
        self.lblLockVal.adjustSize()
        self.lblLockVal.move(
            self.locklock_pos[0] + self.locklock_pos[2] -
            self.lblLockVal.width(), self.locklock_pos[1])

    def change_bump(self):
        val = int(self.sender().value() * 10)
        self.lblBumpVal.setText(str(val) + '°')
        self.bump_to_bump_global.value = val
        self.lblBumpVal.adjustSize()
        self.lblBumpVal.move(
            self.bumpbump_pos[0] + self.bumpbump_pos[2] -
            self.lblBumpVal.width(), self.bumpbump_pos[1])

    # WHEEL FORCE SETTING FUNCTIONS
    def select_game(self, item_index):
        print('selecting', item_index)
        self.game_interfacer.terminate()
        time.sleep(1)
        self.game_interfacer.start(item_index)

    def toggle_invert(self, state):
        if state == Qt.Checked:
            self.invert_force_global.value = True
        else:
            self.invert_force_global.value = False

    def toggle_motor_pause_mode(self, state):
        if state == Qt.Checked:
            self.motor_pause_mode.value = True
        else:
            self.motor_pause_mode.value = False

    def change_max_force(self):
        val = self.sender().value() / 10
        self.lblMaxForceVal.setText(
            str(val) + ' Nm - (' + str(int(val * 2.75 * 100) / 100) + ' Amp)')
        self.actual_max_force_global.value = val
        self.lblMaxForceVal.adjustSize()
        self.lblMaxForceVal.move(
            self.max_force_pos[0] + self.max_force_pos[2] -
            self.lblMaxForceVal.width(), self.max_force_pos[1])
        self.force_graph.setYRange(-val, val)

    def change_friction(self):
        val = self.sender().value() / 100
        self.lblFrictionVal.setText(str(int(val * 100)) + ' %')
        self.friction_global.value = val
        self.lblFrictionVal.adjustSize()
        self.lblFrictionVal.move(
            self.friction_pos[0] + self.friction_pos[2] -
            self.lblFrictionVal.width(), self.friction_pos[1])

    def change_damping(self):
        val = self.sender().value() / 100
        self.lblDampingVal.setText(str(int(val * 100)) + ' %')
        self.damping_global.value = val
        self.lblDampingVal.adjustSize()
        self.lblDampingVal.move(
            self.damping_pos[0] + self.damping_pos[2] -
            self.lblDampingVal.width(), self.damping_pos[1])

    def change_inertia(self):
        val = self.sender().value() / 100
        self.lblInertiaVal.setText(str(int(val * 100)) + ' %')
        self.inertia_global.value = val
        self.lblInertiaVal.adjustSize()
        self.lblInertiaVal.move(
            self.inertia_pos[0] + self.inertia_pos[2] -
            self.lblInertiaVal.width(), self.inertia_pos[1])

    def toggle_reconstruction(self, state):
        if state == Qt.Checked:
            self.data_reconstruction.value = True
        else:
            self.data_reconstruction.value = False

    def change_smoothing(self, item_index):
        self.data_smoothing_level.value = item_index

    def select_profile(self, selected_profile):
        self.sliLock.setValue(
            int(self.profiles[selected_profile].lock_to_lock / 10))
        self.sliBump.setValue(
            int(self.profiles[selected_profile].bump_to_bump / 10))
        self.cbInvert.setChecked(
            bool(self.profiles[selected_profile].invert_force))
        self.sliMaxForce.setValue(
            int(self.profiles[selected_profile].max_force * 10))
        self.cbReconst.setChecked(
            bool(self.profiles[selected_profile].use_reconstruction))
        self.cbxSmoothing.setCurrentIndex(
            int(self.profiles[selected_profile].smoothing_level))
        self.sliFriction.setValue(
            int(self.profiles[selected_profile].friction * 100))
        self.sliDamping.setValue(
            int(self.profiles[selected_profile].damping * 100))
        self.sliInertia.setValue(
            int(self.profiles[selected_profile].inertia * 100))

    def save_current_profile_internally(self):
        current_index = self.cbxProfiles.currentIndex()
        self.profiles[
            current_index].lock_to_lock = self.lock_to_lock_global.value
        self.profiles[
            current_index].bump_to_bump = self.bump_to_bump_global.value
        self.profiles[
            current_index].invert_force = self.invert_force_global.value
        self.profiles[
            current_index].max_force = self.actual_max_force_global.value
        self.profiles[
            current_index].use_reconstruction = self.data_reconstruction.value
        self.profiles[
            current_index].smoothing_level = self.data_smoothing_level.value
        self.profiles[current_index].friction = self.friction_global.value
        self.profiles[current_index].damping = self.damping_global.value
        self.profiles[current_index].inertia = self.inertia_global.value
        self.save_profiles_to_file()

    def save_profiles_to_file(self):
        root = ET.Element('profiles')
        for profile in self.profiles:
            prof_elem = ET.SubElement(root, 'profile', name=profile.name)

            ET.SubElement(prof_elem,
                          'lock_to_lock').text = str(profile.lock_to_lock)
            ET.SubElement(prof_elem,
                          'bump_to_bump').text = str(profile.bump_to_bump)

            ET.SubElement(prof_elem, 'invert_force').text = str(
                bool(profile.invert_force))

            ET.SubElement(prof_elem, 'max_force').text = str(profile.max_force)

            ET.SubElement(prof_elem, 'use_reconstruction').text = str(
                bool(profile.use_reconstruction))
            ET.SubElement(prof_elem, 'smoothing_level').text = str(
                profile.smoothing_level)

            ET.SubElement(prof_elem, 'friction').text = str(profile.friction)
            ET.SubElement(prof_elem, 'damping').text = str(profile.damping)
            ET.SubElement(prof_elem, 'inertia').text = str(profile.inertia)

        tree = ET.ElementTree(root)
        tree.write("profiles.xml")

    def load_profiles_from_file(self):
        self.profiles.clear()
        tree = ET.parse('profiles.xml')
        root = tree.getroot()
        for prof in root:
            profile = Profile(prof.attrib['name'])
            profile.lock_to_lock = float(prof[0].text)
            profile.bump_to_bump = float(prof[1].text)
            profile.invert_force = bool(prof[2].text == 'True')
            profile.max_force = float(prof[3].text)
            profile.use_reconstruction = bool(prof[4].text == 'True')
            profile.smoothing_level = int(prof[5].text)
            profile.friction = float(prof[6].text)
            profile.damping = float(prof[7].text)
            profile.inertia = float(prof[8].text)
            self.profiles.append(profile)

    def delete_current_profile(self):
        current_index = self.cbxProfiles.currentIndex()
        print('deleting profile at index:', current_index)
        self.profiles.pop(current_index)
        self.cbxProfiles.clear()
        for profile in self.profiles:
            self.cbxProfiles.addItem(profile.name)
        self.cbxProfiles.setCurrentIndex(0)
        self.select_profile(0)
        self.save_current_profile_internally()
        if len(self.profiles) == 1:
            self.btnDelete.setEnabled(False)

    def create_profile(self):
        new_profile = Profile('profile #' + str(len(self.profiles) + 1))
        current_index = self.cbxProfiles.currentIndex()

        new_profile.lock_to_lock = self.profiles[current_index].lock_to_lock
        new_profile.bump_to_bump = self.profiles[current_index].bump_to_bump
        new_profile.invert_force = self.profiles[current_index].invert_force
        new_profile.max_force = self.profiles[current_index].max_force
        new_profile.use_reconstruction = self.profiles[
            current_index].use_reconstruction
        new_profile.smoothing_level = self.profiles[
            current_index].smoothing_level
        new_profile.friction = self.profiles[current_index].friction
        new_profile.damping = self.profiles[current_index].damping
        new_profile.inertia = self.profiles[current_index].inertia
        self.profiles.append(new_profile)

        self.cbxProfiles.clear()
        for profile in self.profiles:
            self.cbxProfiles.addItem(profile.name)
        self.cbxProfiles.setCurrentIndex(len(self.profiles) - 1)
        self.select_profile(len(self.profiles) - 1)
        self.save_current_profile_internally()
        if len(self.profiles) > 1:
            self.btnDelete.setEnabled(True)

    def rename_profile(self):
        rename_pos = [325, 490, 250, 25]
        if self.sender().text() == 'rename profile':
            self.sender().setText('OK')
            self.sender().move(rename_pos[0] + 220 - 55, rename_pos[1])
            self.sender().resize(rename_pos[2] - 220, rename_pos[3])
            self.cbxProfiles.setEnabled(False)
            self.btnCreate.setEnabled(False)
            self.btnSave.setEnabled(False)
            self.btnDelete.setEnabled(False)
            self.btnCancelRename.setVisible(True)
            self.txtRename.setVisible(True)
            current_index = self.cbxProfiles.currentIndex()
            self.txtRename.setText(self.profiles[current_index].name)
        else:
            self.sender().setText('rename profile')
            self.sender().move(rename_pos[0], rename_pos[1])
            self.sender().resize(rename_pos[2], rename_pos[3])
            self.cbxProfiles.setEnabled(True)
            self.btnCreate.setEnabled(True)
            self.btnSave.setEnabled(True)
            self.btnDelete.setEnabled(True)
            self.btnCancelRename.setVisible(False)
            self.txtRename.setVisible(False)
            current_index = self.cbxProfiles.currentIndex()
            self.profiles[current_index].name = self.txtRename.text()

            self.cbxProfiles.clear()
            for profile in self.profiles:
                self.cbxProfiles.addItem(profile.name)
            self.cbxProfiles.setCurrentIndex(current_index)
            self.select_profile(current_index)
            self.save_current_profile_internally()

    def cancel_rename(self):
        rename_pos = [325, 490, 250, 25]
        self.btnRename.setText('rename profile')
        self.btnRename.move(rename_pos[0], rename_pos[1])
        self.btnRename.resize(rename_pos[2], rename_pos[3])
        self.cbxProfiles.setEnabled(True)
        self.btnCreate.setEnabled(True)
        self.btnSave.setEnabled(True)
        self.btnDelete.setEnabled(True)
        self.btnCancelRename.setVisible(False)
        self.txtRename.setVisible(False)

    def check_name_validity(self, text):
        if text == '':
            self.btnRename.setEnabled(False)
        else:
            self.btnRename.setEnabled(True)
Beispiel #20
0
class TimeSeriesWidget(QtWidgets.QWidget):
    """ Time-series widget with built-in display controls. """

    # Internal refresh signal
    _refresh_signal = QtCore.pyqtSignal(np.ndarray, np.ndarray)

    # Signal to change the y-axis units
    _yaxis_units_signal = QtCore.pyqtSignal(str)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.plot_widget = PlotWidget(
            parent=self,
            title="Diffraction time-series",
            labels={"left": ("Intensity", "a. u."), "bottom": ("time", "ps")},
        )
        self._yaxis_units_signal.connect(self.set_yaxis_units)

        self.plot_widget.getPlotItem().showGrid(x=True, y=True)

        # Internal state on whether or not to 'connect the dots'
        self._time_series_connect = False
        self._symbol_size = 5

        # Internal memory on last time-series info
        self._last_times = None
        self._last_intensities_abs = None
        self._refresh_signal.connect(self.plot)

        self.connect_widget = QtWidgets.QCheckBox("Connect time-series", self)
        self.connect_widget.toggled.connect(self.enable_connect)

        self.symbol_size_widget = QtWidgets.QSpinBox(parent=self)
        self.symbol_size_widget.setRange(1, 25)
        self.symbol_size_widget.setValue(self._symbol_size)
        self.symbol_size_widget.setPrefix("Symbol size: ")
        self.symbol_size_widget.valueChanged.connect(self.set_symbol_size)

        self.absolute_intensity_widget = QtWidgets.QCheckBox(
            "Show absolute intensity", self
        )
        self.absolute_intensity_widget.toggled.connect(self.toggle_absolute_intensity)

        self.exponential_fit_widget = QtWidgets.QPushButton(
            "Calculate exponential decay", self
        )
        self.exponential_fit_widget.clicked.connect(self.fit_exponential_decay)

        self.fit_constants_label = QtWidgets.QLabel(self)

        self.controls = QtWidgets.QHBoxLayout()
        self.controls.addWidget(self.connect_widget)
        self.controls.addWidget(self.absolute_intensity_widget)
        self.controls.addWidget(self.symbol_size_widget)
        self.controls.addWidget(self.exponential_fit_widget)
        self.controls.addWidget(self.fit_constants_label)
        self.controls.addStretch(1)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.plot_widget)
        layout.addLayout(self.controls)
        self.setLayout(layout)

    @QtCore.pyqtSlot(str)
    def set_yaxis_units(self, units):
        """ Set the y-axis label """
        self.plot_widget.getPlotItem().setLabel("left", text="Intensity", units=units)

    @QtCore.pyqtSlot(bool)
    def toggle_absolute_intensity(self, absolute):
        # Normalize to intensity before time-zero
        if absolute:
            self._yaxis_units_signal.emit("counts")
        else:
            self._yaxis_units_signal.emit("a.u.")

        self.refresh()

    @QtCore.pyqtSlot(np.ndarray, np.ndarray)
    def plot(self, time_points, intensity):
        """
        Plot the a time-series. Time-series are normalized to the intensity before photoexcitation.

        Parameters
        ----------
        time_points : `~numpy.ndarray`, shape (N,)
            Time-delays [ps]
        intensity : `~numpy.ndarray`, shape (N,)
            Diffracted intensity in absolute units.
        """
        self._last_times = np.asarray(time_points)
        self._last_intensities_abs = np.asarray(intensity)

        # Normalize to intensity before time-zero
        # Note that the change in units is taken care of in the toggle_absolute_intensity method
        absolute = self.absolute_intensity_widget.isChecked()
        intensity = (
            self._last_intensities_abs
            if absolute
            else self._last_intensities_abs
            / np.mean(self._last_intensities_abs[self._last_times < 0])
        )

        # Only compute the colors if number of time-points changes or first time
        pens, brushes = pens_and_brushes(len(time_points))

        connect_kwargs = {"pen": None} if not self._time_series_connect else dict()
        self.plot_widget.plot(
            x=self._last_times,
            y=intensity,
            symbol="o",
            symbolPen=pens,
            symbolBrush=brushes,
            symbolSize=self._symbol_size,
            clear=True,
            **connect_kwargs
        )

        # Don't forget to clear the fit constants
        self.fit_constants_label.clear()

    @QtCore.pyqtSlot()
    def fit_exponential_decay(self):
        """ Try to fit to a time-series with an exponential decay. If successful, plot the result. """
        times = self._last_times
        intensity = self._last_intensities_abs

        # time-zero, amplitude, time-constant, offset
        initial_guesses = (0, intensity.max(), 1, intensity.min())

        try:
            params, pcov = curve_fit(
                exponential_decay, times, intensity, p0=initial_guesses
            )
        except RuntimeError:
            return

        fit = exponential_decay(times, *params)
        absolute = self.absolute_intensity_widget.isChecked()
        if not absolute:
            fit /= np.mean(self._last_intensities_abs[self._last_times < 0])
        self.plot_widget.plot(x=times, y=fit, symbol=None, clear=False)

        # Write fit parameters to text items
        tconst, tconsterr = params[2], np.sqrt(pcov[2, 2])
        tzero, tzeroerr = params[0], np.sqrt(pcov[0, 0])
        self.fit_constants_label.setText(
            "Time-constant: ({:.3f}±{:.3f} ps, Time-zero: ({:.3f}±{:.3f}) ps".format(
                tconst, tconsterr, tzero, tzeroerr
            )
        )

    @QtCore.pyqtSlot()
    def refresh(self):
        self._refresh_signal.emit(self._last_times, self._last_intensities_abs)

    @QtCore.pyqtSlot()
    def clear(self):
        self.plot_widget.clear()

    @QtCore.pyqtSlot(bool)
    def enable_connect(self, toggle):
        self._time_series_connect = toggle
        self.refresh()

    @QtCore.pyqtSlot(int)
    def set_symbol_size(self, size):
        self._symbol_size = size
        self.refresh()
Beispiel #21
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(882, 605)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.labelHKLS = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.labelHKLS.setFont(font)
        self.labelHKLS.setObjectName("labelHKLS")
        self.gridLayout.addWidget(self.labelHKLS, 13, 0, 1, 4)
        self.label_19 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_19.setFont(font)
        self.label_19.setObjectName("label_19")
        self.gridLayout.addWidget(self.label_19, 15, 6, 1, 1)
        self.labelSimpara = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.labelSimpara.setFont(font)
        self.labelSimpara.setObjectName("labelSimpara")
        self.gridLayout.addWidget(self.labelSimpara, 0, 0, 1, 2)
        self.labelHKLS_2 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.labelHKLS_2.setFont(font)
        self.labelHKLS_2.setObjectName("labelHKLS_2")
        self.gridLayout.addWidget(self.labelHKLS_2, 13, 4, 1, 3)
        self.label_17 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_17.setFont(font)
        self.label_17.setObjectName("label_17")
        self.gridLayout.addWidget(self.label_17, 14, 4, 1, 1)
        self.idealLueftenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.idealLueftenInput.setFont(font)
        self.idealLueftenInput.setObjectName("idealLueftenInput")
        self.gridLayout.addWidget(self.idealLueftenInput, 14, 1, 1, 2)
        self.textEditCalcInfo = QtWidgets.QTextEdit(self.centralwidget)
        self.textEditCalcInfo.setMaximumSize(QtCore.QSize(16777215, 61))
        self.textEditCalcInfo.setObjectName("textEditCalcInfo")
        self.gridLayout.addWidget(self.textEditCalcInfo, 21, 0, 1, 7)
        self.CustomLueftenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.CustomLueftenInput.setFont(font)
        self.CustomLueftenInput.setObjectName("CustomLueftenInput")
        self.gridLayout.addWidget(self.CustomLueftenInput, 14, 5, 1, 1)
        self.CustomInnereLastenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.CustomInnereLastenInput.setFont(font)
        self.CustomInnereLastenInput.setObjectName("CustomInnereLastenInput")
        self.gridLayout.addWidget(self.CustomInnereLastenInput, 16, 5, 1, 1)
        self.NatLueftenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.NatLueftenInput.setFont(font)
        self.NatLueftenInput.setObjectName("NatLueftenInput")
        self.gridLayout.addWidget(self.NatLueftenInput, 18, 1, 1, 2)
        self.label_20 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_20.setFont(font)
        self.label_20.setObjectName("label_20")
        self.gridLayout.addWidget(self.label_20, 15, 4, 1, 1)
        self.NachtlueftenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.NachtlueftenInput.setFont(font)
        self.NachtlueftenInput.setObjectName("NachtlueftenInput")
        self.gridLayout.addWidget(self.NachtlueftenInput, 15, 1, 1, 2)
        self.TaglueftenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.TaglueftenInput.setFont(font)
        self.TaglueftenInput.setObjectName("TaglueftenInput")
        self.gridLayout.addWidget(self.TaglueftenInput, 16, 1, 1, 2)
        self.label_14 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_14.setFont(font)
        self.label_14.setObjectName("label_14")
        self.gridLayout.addWidget(self.label_14, 19, 3, 1, 1)
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_4.setFont(font)
        self.label_4.setObjectName("label_4")
        self.gridLayout.addWidget(self.label_4, 14, 3, 1, 1)
        self.label_23 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_23.setFont(font)
        self.label_23.setObjectName("label_23")
        self.gridLayout.addWidget(self.label_23, 16, 4, 1, 1)
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setMaximumSize(QtCore.QSize(14, 22))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.gridLayout.addWidget(self.label_2, 1, 2, 1, 1)
        self.label_8 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_8.setFont(font)
        self.label_8.setObjectName("label_8")
        self.gridLayout.addWidget(self.label_8, 17, 0, 1, 1)
        self.label_12 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_12.setFont(font)
        self.label_12.setObjectName("label_12")
        self.gridLayout.addWidget(self.label_12, 18, 0, 1, 1)
        self.label = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setMinimumSize(QtCore.QSize(121, 0))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_3.setFont(font)
        self.label_3.setObjectName("label_3")
        self.gridLayout.addWidget(self.label_3, 14, 0, 1, 1)
        self.label_18 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_18.setFont(font)
        self.label_18.setObjectName("label_18")
        self.gridLayout.addWidget(self.label_18, 14, 6, 1, 1)
        self.SonnenschutzInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.SonnenschutzInput.setFont(font)
        self.SonnenschutzInput.setObjectName("SonnenschutzInput")
        self.gridLayout.addWidget(self.SonnenschutzInput, 17, 1, 1, 2)
        self.startTempInput = QtWidgets.QLineEdit(self.centralwidget)
        self.startTempInput.setMaximumSize(QtCore.QSize(100, 16777215))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.startTempInput.setFont(font)
        self.startTempInput.setObjectName("startTempInput")
        self.gridLayout.addWidget(self.startTempInput, 3, 1, 1, 1)
        self.MechLueftenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.MechLueftenInput.setFont(font)
        self.MechLueftenInput.setObjectName("MechLueftenInput")
        self.gridLayout.addWidget(self.MechLueftenInput, 19, 1, 1, 2)
        self.startSimulation = QtWidgets.QPushButton(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.startSimulation.setFont(font)
        self.startSimulation.setObjectName("startSimulation")
        self.gridLayout.addWidget(self.startSimulation, 20, 4, 1, 2)
        self.label_16 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_16.setFont(font)
        self.label_16.setObjectName("label_16")
        self.gridLayout.addWidget(self.label_16, 16, 0, 1, 1)
        self.label_11 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_11.setFont(font)
        self.label_11.setObjectName("label_11")
        self.gridLayout.addWidget(self.label_11, 18, 3, 1, 1)
        self.label_6 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_6.setFont(font)
        self.label_6.setObjectName("label_6")
        self.gridLayout.addWidget(self.label_6, 15, 0, 1, 1)
        self.CustomSonnenschutzInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.CustomSonnenschutzInput.setFont(font)
        self.CustomSonnenschutzInput.setObjectName("CustomSonnenschutzInput")
        self.gridLayout.addWidget(self.CustomSonnenschutzInput, 15, 5, 1, 1)
        self.label_13 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_13.setFont(font)
        self.label_13.setObjectName("label_13")
        self.gridLayout.addWidget(self.label_13, 19, 0, 1, 1)
        self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar.setMinimumSize(QtCore.QSize(0, 0))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.progressBar.setFont(font)
        self.progressBar.setProperty("value", 24)
        self.progressBar.setObjectName("progressBar")
        self.gridLayout.addWidget(self.progressBar, 20, 0, 1, 4)
        self.label_10 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_10.setFont(font)
        self.label_10.setObjectName("label_10")
        self.gridLayout.addWidget(self.label_10, 11, 0, 1, 1)
        self.label_15 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_15.setFont(font)
        self.label_15.setObjectName("label_15")
        self.gridLayout.addWidget(self.label_15, 16, 3, 1, 1)
        self.labelStandort = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.labelStandort.setFont(font)
        self.labelStandort.setObjectName("labelStandort")
        self.gridLayout.addWidget(self.labelStandort, 10, 0, 1, 2)
        self.label_24 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_24.setFont(font)
        self.label_24.setObjectName("label_24")
        self.gridLayout.addWidget(self.label_24, 16, 6, 1, 1)
        self.zeitschrittInput = QtWidgets.QLineEdit(self.centralwidget)
        self.zeitschrittInput.setMaximumSize(QtCore.QSize(100, 16777215))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.zeitschrittInput.setFont(font)
        self.zeitschrittInput.setObjectName("zeitschrittInput")
        self.gridLayout.addWidget(self.zeitschrittInput, 1, 1, 1, 1)
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_5.setFont(font)
        self.label_5.setObjectName("label_5")
        self.gridLayout.addWidget(self.label_5, 15, 3, 1, 1)
        self.label_21 = QtWidgets.QLabel(self.centralwidget)
        self.label_21.setText("")
        self.label_21.setObjectName("label_21")
        self.gridLayout.addWidget(self.label_21, 6, 1, 1, 1)
        self.label_7 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_7.setFont(font)
        self.label_7.setObjectName("label_7")
        self.gridLayout.addWidget(self.label_7, 17, 3, 1, 1)
        self.stopSimulation = QtWidgets.QPushButton(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.stopSimulation.setFont(font)
        self.stopSimulation.setObjectName("stopSimulation")
        self.gridLayout.addWidget(self.stopSimulation, 20, 6, 1, 1)
        self.label_22 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_22.setFont(font)
        self.label_22.setObjectName("label_22")
        self.gridLayout.addWidget(self.label_22, 2, 0, 1, 1)
        self.genauigkeitInput = QtWidgets.QLineEdit(self.centralwidget)
        self.genauigkeitInput.setMaximumSize(QtCore.QSize(100, 16777215))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.genauigkeitInput.setFont(font)
        self.genauigkeitInput.setObjectName("genauigkeitInput")
        self.gridLayout.addWidget(self.genauigkeitInput, 2, 1, 1, 1)
        self.label_26 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_26.setFont(font)
        self.label_26.setObjectName("label_26")
        self.gridLayout.addWidget(self.label_26, 3, 0, 1, 1)
        self.label_25 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_25.setFont(font)
        self.label_25.setObjectName("label_25")
        self.gridLayout.addWidget(self.label_25, 3, 2, 1, 1)
        self.label_9 = QtWidgets.QLabel(self.centralwidget)
        self.label_9.setMaximumSize(QtCore.QSize(14, 22))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_9.setFont(font)
        self.label_9.setObjectName("label_9")
        self.gridLayout.addWidget(self.label_9, 11, 2, 1, 1)
        self.SeehoeheInput = QtWidgets.QLineEdit(self.centralwidget)
        self.SeehoeheInput.setMaximumSize(QtCore.QSize(100, 16777215))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.SeehoeheInput.setFont(font)
        self.SeehoeheInput.setObjectName("SeehoeheInput")
        self.gridLayout.addWidget(self.SeehoeheInput, 11, 1, 1, 1)
        self.graphWidget = PlotWidget(self.centralwidget)
        self.graphWidget.setMinimumSize(QtCore.QSize(0, 0))
        self.graphWidget.setObjectName("graphWidget")
        self.gridLayout.addWidget(self.graphWidget, 1, 3, 11, 4)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
# to here

        '-------------------Multithreading------------------------'
        self.threadpool = QThreadPool()
        print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount())

        '-------------------Events--------------------------------'
        #Hier werden alle Events von Buttons verwaltet
        self.startSimulation.clicked.connect(self.Simulation)
        self.stopSimulation.clicked.connect(self.Stop)

        self.x = list(range(96))  # initializing plot x axis
        self.y = [float(self.startTempInput.text())] * 96  # initializing plot y axis

        self.graphWidget.setBackground('w')

        pen = pg.mkPen(color=(51, 51, 255))
        self.data_line =  self.graphWidget.plot(self.x, self.y, pen=pen)
        self.graphWidget.getPlotItem().hideAxis('bottom')
        self.timer = QtCore.QTimer()
        self.timer.setInterval(200)
        self.timer.timeout.connect(self.update_plot_data)
        self.timer.start()
        self.line = 0
        self.progress = 0
        self.progressLimit = 100

    def update_plot_data(self):
        abbruchTxt = open('Abbruch.txt', 'r')
        if abbruchTxt.read() == 'False' and self.progress < self.progressLimit: #Umrechnung des Simulationsfortschrittes in Prozent
            indexTxt = open('index.txt', 'r')
            indexTxtLines = indexTxt.readlines()
            for i in range(len(indexTxtLines)):
                indexTxtLines[i] = indexTxtLines[i].replace('\n', '')
            self.progress = float(indexTxtLines[len(indexTxtLines) - 1]) * float(self.zeitschrittInput.text()) / 86400 * 100
            self.progressBar.setProperty("value", self.progress)
            self.textEditCalcInfo.setText(open('time.txt', 'r').read())
            
                
        else:
            self.progressBar.setProperty("value", 0)
            self.progress = 0

        #Dynamic graph plot update for Qtimer
        filename = 'graphTop.txt'
        if os.stat(filename).st_size != 0:
            if self.line == 0:
                time.sleep(0.2)

            file = open(filename)
            fileLines = file.readlines()
            for i in range(len(fileLines)):
                fileLines[i] = fileLines[i].replace('\n', '')
            self.x = self.x[1:]  # Remove the first y element.
            self.x.append(self.x[-1] + 1)  # Add a new value 1 higher than the last.
            self.y = self.y[1:]  # Remove the first 
            self.y.append(float(fileLines[self.line]))  # Add a new value.
            self.data_line.setData(self.x, self.y)  # Update the data.
            file.close()
            self.line += 1
            #self.counter += 1
            if self.line == len(fileLines):
                self.line = 0

        else:
            print('No Data')
            self.x = self.x[1:]  # Remove the first x element. 
            self.x.append(self.x[-1] + 1)  # Add a new value 1 higher than the last.
            self.y = self.y[1:]  # Remove the first 
            self.y.append(float(self.startTempInput.text()))  # Add a new value.
            self.data_line.setData(self.x, self.y)


#here the functions for the workers are defined
    def SUe3_fn_worker(self, progress_callback):
        open('graphTop.txt', 'w').close()
        SUe3(float(self.zeitschrittInput.text()), float(self.genauigkeitInput.text()), float(self.startTempInput.text()), bool(int(self.idealLueftenInput.text())), bool(int(self.NachtlueftenInput.text())), 
            bool(int(self.TaglueftenInput.text())), bool(int(self.SonnenschutzInput.text())), bool(int(self.NatLueftenInput.text())), bool(int(self.MechLueftenInput.text())), 
            float(self.SeehoeheInput.text()), bool(int(self.CustomLueftenInput.text())), bool(int(self.CustomSonnenschutzInput.text())), bool(int(self.CustomInnereLastenInput.text())))


        '------------------Functions by PyQt5--------------------'
#copy after changes in .ui by Designer from here 
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "SUe-Thermischer Komfort"))
        self.labelHKLS.setText(_translate("MainWindow", "HKLS-Steuerung (automatisch)"))
        self.label_19.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.labelSimpara.setText(_translate("MainWindow", "Simulationsparameter"))
        self.labelHKLS_2.setText(_translate("MainWindow", "HKLS-Steuerung (aus Input Datei)"))
        self.label_17.setText(_translate("MainWindow", "Lüften"))
        self.idealLueftenInput.setText(_translate("MainWindow", "1"))
        self.textEditCalcInfo.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:8.25pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>"))
        self.CustomLueftenInput.setText(_translate("MainWindow", "0"))
        self.CustomInnereLastenInput.setText(_translate("MainWindow", "1"))
        self.NatLueftenInput.setText(_translate("MainWindow", "1"))
        self.label_20.setText(_translate("MainWindow", "Sonnenschutz"))
        self.NachtlueftenInput.setText(_translate("MainWindow", "0"))
        self.TaglueftenInput.setText(_translate("MainWindow", "1"))
        self.label_14.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.label_4.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.label_23.setText(_translate("MainWindow", "Innere Lasten"))
        self.label_2.setText(_translate("MainWindow", "s"))
        self.label_8.setText(_translate("MainWindow", "Sonnenschutz"))
        self.label_12.setText(_translate("MainWindow", "Nat. Lüftung"))
        self.label.setText(_translate("MainWindow", "Zeitschritt"))
        self.label_3.setText(_translate("MainWindow", "ideal Lüften"))
        self.label_18.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.SonnenschutzInput.setText(_translate("MainWindow", "0"))
        self.startTempInput.setText(_translate("MainWindow", "30"))
        self.MechLueftenInput.setText(_translate("MainWindow", "0"))
        self.startSimulation.setText(_translate("MainWindow", "Start"))
        self.label_16.setText(_translate("MainWindow", "Taglüften"))
        self.label_11.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.label_6.setText(_translate("MainWindow", "Nachtlüften"))
        self.CustomSonnenschutzInput.setText(_translate("MainWindow", "0"))
        self.label_13.setText(_translate("MainWindow", "Mech. Lüftung"))
        self.label_10.setText(_translate("MainWindow", "Seehöhe"))
        self.SeehoeheInput.setText(_translate("MainWindow", "172"))
        self.label_15.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.labelStandort.setText(_translate("MainWindow", "Standort"))
        self.label_24.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.zeitschrittInput.setText(_translate("MainWindow", "10"))
        self.label_5.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.label_7.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.stopSimulation.setText(_translate("MainWindow", "Stop"))
        self.label_22.setText(_translate("MainWindow", "Genauigkeit"))
        self.genauigkeitInput.setText(_translate("MainWindow", "1e-3"))
        self.label_26.setText(_translate("MainWindow", "Starttemperatur"))
        self.label_25.setText(_translate("MainWindow", "°C"))
        self.label_9.setText(_translate("MainWindow", "m"))
        
#to here

    '----------------------Funktionen----------------------------' 
    #Hier finden sich alle selbst geschriebenen Funktionen zu den Events

    
    def Simulation(self):        
        file = open('Abbruch.txt', 'w')
        file.write('False')
        self.line = 0
        open('graphTop.txt', 'w').close()
        open('time.txt', 'w').close()
        
        

        #SUe3(float(self.zeitschrittInput.text()), float(self.genauigkeitInput.text()), float(self.startTempInput.text()), bool(int(self.idealLueftenInput.text())), bool(int(self.NachtlueftenInput.text())), 
        #    bool(int(self.TaglueftenInput.text())), bool(int(self.SonnenschutzInput.text())), bool(int(self.NatLueftenInput.text())), bool(int(self.MechLueftenInput.text())), 
        #    float(self.SeehoeheInput.text()), bool(int(self.CustomLueftenInput.text())), bool(int(self.CustomSonnenschutzInput.text())), bool(int(self.CustomInnereLastenInput.text())))

        worker1 = Worker(self.SUe3_fn_worker) # any other args, kwargs are passed to the run function
        # execute
        self.threadpool.start(worker1)

        

   
    def Stop(self):
        file = open('Abbruch.txt', 'w')
        file.write('True')
        self.line = 0
        open('graphTop.txt', 'w').close()
        open('time.txt', 'w').close()
Beispiel #22
0
class Tiare(QtGui.QMainWindow):
    def __init__(self, *args):
        QtGui.QMainWindow.__init__(self, *args)
        self.statusBar().showMessage('Pret')
        self.th = 0
        self.widget = QtGui.QWidget(self)
        exitAction = QtGui.QAction(QtGui.QIcon('exit.png'), '&Quitter', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip("Ferme l'application")
        exitAction.triggered.connect(self.close)

        openAction = QtGui.QAction(QtGui.QIcon('open.png'), '&Charger', self)
        openAction.setShortcut('Ctrl+L')
        openAction.setStatusTip("Charge un fichier wav")
        openAction.triggered.connect(self.load)

        self.saveAction = QtGui.QAction(QtGui.QIcon('save.png'), '&Exporter', self)
        self.saveAction.setShortcut('Ctrl+S')
        self.saveAction.setStatusTip("Exporter en CSV")
        self.saveAction.triggered.connect(self.export)
        self.saveAction.setEnabled(False)
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&Fichier')
        fileMenu.addAction(openAction)
        fileMenu.addAction(self.saveAction)
        fileMenu.addAction(exitAction)

        self.th_slider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
        self.th_slider.setValue(self.th)
        self.th_slider.valueChanged[int].connect(self.change_threshold)

        self.min_len = QtGui.QSlider(QtCore.Qt.Horizontal, self)
        self.min_len.setValue(10)
        self.min_len.setMinimum(1)
        self.min_len.setMaximum(100)
        self.min_len.valueChanged[int].connect(self.change_min_len)

        self.min_len_sil = QtGui.QSlider(QtCore.Qt.Horizontal, self)
        self.min_len_sil.setValue(10)
        self.min_len_sil.setMinimum(1)
        self.min_len_sil.setMaximum(100)
        self.min_len_sil.valueChanged[int].connect(self.change_min_len)


        # Make sizer and embed stuff
        self.sizer = QtGui.QVBoxLayout(self.widget)
        self.fig_signal = PlotWidget(self.widget, background="w")
        self.fig_signal.setLimits(xMin=0, yMin=-1, yMax=1, minXRange=1, maxXRange=30, minYRange=2, maxYRange=2)
        self.fig_energy = PlotWidget(self.widget, background="w")
        self.fig_energy.setXLink(self.fig_signal)
        self.fig_segments = PlotWidget(self.widget, background="w")
        self.fig_segments.setXLink(self.fig_signal)
        self.fig_segments.hideAxis('bottom')
        self.fig_segments.hideAxis('left')
        self.fig_segments.setLimits(yMin=-1, yMax=1, minYRange=2, maxYRange=2)

        self.sizer.addWidget(self.fig_signal, 5)
        self.sizer.addWidget(self.fig_energy, 5)
        self.sizer.addWidget(self.fig_segments, 3)
        self.sizer.addWidget(QtGui.QLabel('Seuil de segmentation'), 0)
        self.sizer.addWidget(self.th_slider, 0)
        self.min_seg_label = QtGui.QLabel('Longeur minimal de segment (%.3f s)' % (float(self.min_len.value())/100))
        self.sizer.addWidget(self.min_seg_label, 0)
        self.sizer.addWidget(self.min_len, 0)

        self.min_sil_label = QtGui.QLabel('Longeur minimal de silence (%.3f s)' % (float(self.min_len_sil.value())/100))
        self.sizer.addWidget(self.min_sil_label, 0)
        self.sizer.addWidget(self.min_len_sil, 0)

        # Apply sizers
        self.setCentralWidget(self.widget)

        # Finish
        self.resize(560, 420)
        self.setWindowTitle('Tiare')
        self.energy_tl, self.energy = [], []
        self.thline = None
        self.seg_up = None
        self.seg_down = None
        self.fig_energy_plot = None
        self.segments = []
        self.samples = []
        self.sr = 0
        self.filepath = None
        self.widget.hide()
        self.show()

    def change_threshold(self, value):
        value = float(value)/100
        if self.thline is not None :
            self.thline.setData([self.energy_tl[0], self.energy_tl[-1]], [value]*2)
            self.segments = map(lambda (x, y): (self.energy_tl[x],self.energy_tl[y]),
                                cut(self.energy, value, self.min_len.value(), self.min_len_sil.value()))
            x = [v for start, stop in self.segments for v in [start, start, stop, stop]]
            y = [v for _ in self.segments for v in [-0.85, 0.85, 0.85, -0.85]]
            self.seg_up.setData(x, y)
            self.seg_down.setData([self.energy_tl[0], self.energy_tl[-1]], [-0.85, -0.85])

    def change_min_len(self, value=0):
        self.min_seg_label.setText("Longeur minimale d'un segment (%.3f s)" % (float(self.min_len.value())/100))
        self.min_sil_label.setText("Longeur minimale d'un silence (%.3f s)" % (float(self.min_len_sil.value())/100))
        self.change_threshold(self.th_slider.value())

    def compute_energy(self, value=None):
        self.energy_tl, self.energy = energy(self.samples, self.sr)
        if self.fig_energy_plot is not None:
            self.fig_energy_plot.setData(self.energy_tl, self.energy)
            self.change_min_len()

    def export(self):
        fpath = QtGui.QFileDialog.getSaveFileName(self, "Sauvegader en CSV", self.filepath+".csv")
        if fpath:
            with open(fpath[0], "w") as f:

                for start, stop in self.segments:
                    f.write("Segments\t%s\t%s\n" % (datetime(day=1, month=1, year=1901, second=int(start),
                                                             microsecond=int(10e5*(start % 1)))
                                                    .strftime("%H:%M:%S.%f"),
                                                    datetime(day=1, month=1, year=1901, second=int(stop),
                                                             microsecond=int(10e5*(stop % 1)))
                                                    .strftime("%H:%M:%S.%f")))

    def load(self):
        fpath, _ = QtGui.QFileDialog.getOpenFileName(self, 'Choisir un fichier', '~/', filter="*.wav")
        self.widget.show()
        if fpath:
            self.filepath = fpath
            self.saveAction.setEnabled(True)

            self.samples, self.sr = load_sound(fpath)
            m = max(map(abs, self.samples))
            timeline = [float(t)/self.sr for t in range(len(self.samples))]
            self.fig_signal.setLimits(xMax=timeline[-1])

            self.compute_energy()

            self.fig_signal.getPlotItem().plot(timeline, map(lambda x: x/m, self.samples))
            self.fig_energy_plot = self.fig_energy.getPlotItem().plot(self.energy_tl, self.energy)
            self.thline = self.fig_energy.getPlotItem().plot([self.energy_tl[0], self.energy_tl[-1]],
                                                             [float(self.th_slider.value())/100]*2,
                                               pen=({'color': "k", "width": 1.5}))
            self.seg_up = self.fig_segments.getPlotItem().plot([self.energy_tl[0], self.energy_tl[-1]],
                                                               [-0.85, -0.85])

            self.seg_down = self.fig_segments.getPlotItem().plot([self.energy_tl[0], self.energy_tl[-1]],
                                                                 [-0.85, -0.85])
            self.segments = FillBetweenItem(self.seg_up, self.seg_down, 0.7)
            self.fig_segments.addItem(self.segments)
Beispiel #23
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        self.probihaNuloveMereni = False
        self.nuloveHodnoty = np.array([0, 0])
        self.int_validator =QtGui.QIntValidator()
        self.float_validator = QtGui.QDoubleValidator()
        self.koeficienty = {'uzavreny': [0.000615, 0.001056], 'otevreny': [0.000895, 0.000287]}
        pq.setConfigOption('background', 'y')
        pq.setConfigOption('foreground', 'k')
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(912, 732)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.text_hodnoty1 = QtWidgets.QTextBrowser(self.centralwidget)
        self.text_hodnoty1.setGeometry(QtCore.QRect(30, 60, 151, 181))
        self.text_hodnoty1.setObjectName("text_hodnoty1")
        self.text_hodnoty2 = QtWidgets.QTextBrowser(self.centralwidget)
        self.text_hodnoty2.setGeometry(QtCore.QRect(445, 50, 151, 192))
        self.text_hodnoty2.setObjectName("text_hodnoty2")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(30, 10, 201, 21))
        font = QtGui.QFont()
        font.setFamily("System")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(30, 40, 47, 13))
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(450, 30, 47, 13))
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(200, 60, 121, 16))
        self.label_4.setObjectName("label_4")
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(200, 110, 121, 16))
        self.label_5.setObjectName("label_5")
        self.label_6 = QtWidgets.QLabel(self.centralwidget)
        self.label_6.setGeometry(QtCore.QRect(610, 50, 121, 16))
        self.label_6.setObjectName("label_6")
        self.label_7 = QtWidgets.QLabel(self.centralwidget)
        self.label_7.setGeometry(QtCore.QRect(610, 110, 121, 16))
        self.label_7.setObjectName("label_7")
        self.prumer1 = QtWidgets.QTextBrowser(self.centralwidget)
        self.prumer1.setGeometry(QtCore.QRect(200, 80, 141, 31))
        self.prumer1.setObjectName("prumer1")
        self.prumer2 = QtWidgets.QTextBrowser(self.centralwidget)
        self.prumer2.setGeometry(QtCore.QRect(610, 70, 141, 31))
        self.prumer2.setObjectName("prumer2")
        self.smodch1 = QtWidgets.QTextBrowser(self.centralwidget)
        self.smodch1.setGeometry(QtCore.QRect(200, 130, 141, 31))
        self.smodch1.setObjectName("smodch1")
        self.smodch2 = QtWidgets.QTextBrowser(self.centralwidget)
        self.smodch2.setGeometry(QtCore.QRect(610, 130, 141, 31))
        self.smodch2.setObjectName("smodch2")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(0, 0, 771, 281))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
        self.groupBox.setPalette(palette)
        self.groupBox.setAutoFillBackground(True)
        self.groupBox.setTitle("")
        self.groupBox.setObjectName("groupBox")
        self.buttonMereni = QtWidgets.QPushButton(self.groupBox)
        self.buttonMereni.setGeometry(QtCore.QRect(610, 200, 141, 41))
        self.buttonMereni.setObjectName("buttonMereni")
        self.buttonMereni.clicked.connect(self.one_measure)
        self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_2.setGeometry(QtCore.QRect(770, 0, 141, 281))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
        self.groupBox_2.setPalette(palette)
        self.groupBox_2.setAutoFillBackground(True)
        self.groupBox_2.setTitle("")
        self.groupBox_2.setObjectName("groupBox_2")
        self.label_8 = QtWidgets.QLabel(self.groupBox_2)
        self.label_8.setGeometry(QtCore.QRect(10, 80, 121, 16))
        font = QtGui.QFont()
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.label_8.setFont(font)
        self.label_8.setAlignment(QtCore.Qt.AlignCenter)
        self.label_8.setObjectName("label_8")
        self.rozdil = QtWidgets.QTextBrowser(self.groupBox_2)
        self.rozdil.setGeometry(QtCore.QRect(20, 100, 111, 31))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        self.rozdil.setPalette(palette)
        self.rozdil.setObjectName("rozdil")
        self.groupBox_3 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_3.setGeometry(QtCore.QRect(0, 280, 911, 381))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
        self.groupBox_3.setPalette(palette)
        self.groupBox_3.setAutoFillBackground(True)
        self.groupBox_3.setTitle("")
        self.groupBox_3.setObjectName("groupBox_3")
        self.label_9 = QtWidgets.QLabel(self.groupBox_3)
        self.label_9.setGeometry(QtCore.QRect(20, 10, 201, 21))
        font = QtGui.QFont()
        font.setFamily("System")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.label_9.setFont(font)
        self.label_9.setObjectName("label_9")
        self.graphicsView = PlotWidget(self.groupBox_3)
        self.graphicsView.setGeometry(QtCore.QRect(250, 10, 651, 341))
        self.graphicsView.setObjectName("graphicsView")
        self.label_10 = QtWidgets.QLabel(self.groupBox_3)
        self.label_10.setGeometry(QtCore.QRect(20, 40, 91, 16))
        self.label_10.setObjectName("label_10")
        self.label_11 = QtWidgets.QLabel(self.groupBox_3)
        self.label_11.setGeometry(QtCore.QRect(20, 60, 91, 16))
        self.label_11.setObjectName("label_11")
        self.label_12 = QtWidgets.QLabel(self.groupBox_3)
        self.label_12.setGeometry(QtCore.QRect(20, 80, 91, 16))
        self.label_12.setObjectName("label_12")
        self.lineEdit = QtWidgets.QLineEdit(self.groupBox_3)
        self.lineEdit.setGeometry(QtCore.QRect(20, 100, 221, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.lineEdit.setText(datetime.datetime.now().strftime("Data_" + "%Y-%m-%d_%H%M%S" + ".csv"))
        reg_ex = QtCore.QRegExp("([0-9]\s.")
        validator = QtGui.QRegExpValidator(reg_ex)
        self.lineEdit_interval = QtWidgets.QLineEdit(self.groupBox_3)
        self.lineEdit_interval.setGeometry(QtCore.QRect(90, 60, 151, 20))
        self.lineEdit_interval.setInputMethodHints(QtCore.Qt.ImhDigitsOnly)
        self.lineEdit_interval.setObjectName("lineEdit_interval")
        self.lineEdit_interval.setValidator(self.int_validator)
        self.lineEdit_pocet_2 = QtWidgets.QLineEdit(self.groupBox_3)
        self.lineEdit_pocet_2.setGeometry(QtCore.QRect(90, 40, 151, 20))
        self.lineEdit_pocet_2.setInputMethodHints(QtCore.Qt.ImhDigitsOnly)
        self.lineEdit_pocet_2.setValidator(self.int_validator)

        self.lineEdit_pocet_2.setObjectName("lineEdit_pocet_2")
        self.buttonMereniDynamicke = QtWidgets.QPushButton(self.groupBox_3)
        self.buttonMereniDynamicke.setGeometry(QtCore.QRect(20, 120, 221, 21))
        self.buttonMereniDynamicke.setObjectName("buttonMereniDynamicke")
        self.buttonMereniDynamicke.clicked.connect(self.multiple_measure)
        self.text_dynhodnoty = QtWidgets.QTextBrowser(self.groupBox_3)
        self.text_dynhodnoty.setGeometry(QtCore.QRect(20, 170, 151, 181))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        self.text_dynhodnoty.setPalette(palette)
        self.text_dynhodnoty.setObjectName("text_dynhodnoty")
        self.label_13 = QtWidgets.QLabel(self.groupBox_3)
        self.label_13.setGeometry(QtCore.QRect(10, 150, 47, 13))
        self.label_13.setObjectName("label_13")
        self.groupBox_4 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_4.setGeometry(QtCore.QRect(295, 660, 280, 51))
        self.groupBox_4.setObjectName("groupBox_4")
        self.pushTare2 = QtWidgets.QPushButton(self.groupBox_4)
        self.pushTare2.setGeometry(QtCore.QRect(10, 20, 50, 23))
        self.pushTare2.setObjectName("pushTare2")
        self.pushTareZrusit2 = QtWidgets.QPushButton(self.groupBox_4)
        self.pushTareZrusit2.setGeometry(QtCore.QRect(60, 20, 90, 23))
        self.pushTareZrusit2.setObjectName("pushTareZrusit2")
        self.pushNula2 = QtWidgets.QPushButton(self.groupBox_4)
        self.pushNula2.setGeometry(QtCore.QRect(150, 20, 65, 23))
        self.pushNula2.setObjectName("pushNula2")
        self.pushNulaZrusit2 = QtWidgets.QPushButton(self.groupBox_4)
        self.pushNulaZrusit2.setGeometry(QtCore.QRect(215, 20, 60, 23))
        self.pushNulaZrusit2.setObjectName("pushNulaZrusit2")
        self.groupBox_5 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_5.setGeometry(QtCore.QRect(10, 660, 280, 51))
        self.groupBox_5.setObjectName("groupBox_5")
        self.pushTare2_2 = QtWidgets.QPushButton(self.groupBox_5)
        self.pushTare2_2.setGeometry(QtCore.QRect(10, 20, 50, 23))
        self.pushTare2_2.setObjectName("pushTare2_2")
        self.pushTareZrusit2_2 = QtWidgets.QPushButton(self.groupBox_5)
        self.pushTareZrusit2_2.setGeometry(QtCore.QRect(60, 20, 90, 23))
        self.pushTareZrusit2_2.setObjectName("pushTareZrusit2_2")
        self.pushNula1 = QtWidgets.QPushButton(self.groupBox_5)
        self.pushNula1.setGeometry(QtCore.QRect(150, 20, 65, 23))
        self.pushNula1.setObjectName("pushNula1")
        self.pushNulaZrusit1 = QtWidgets.QPushButton(self.groupBox_5)
        self.pushNulaZrusit1.setGeometry(QtCore.QRect(215, 20, 60, 23))
        self.pushNulaZrusit1.setObjectName("pushNulaZrusit1")
        # parametry
        self.label_20 = QtWidgets.QLabel(self.centralwidget)
        self.label_20.setGeometry(QtCore.QRect(590, 660, 55, 13))
        self.label_20.setObjectName("label_20")



        self.groupBox_6 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_6.setGeometry(QtCore.QRect(580, 666, 330, 45))
        self.groupBox_6.setObjectName("groupBox_6")


        self.label_21 = QtWidgets.QLabel(self.groupBox_6)
        self.label_21.setGeometry(QtCore.QRect(80, 10, 20, 13))
        self.label_21.setObjectName("label_21")
        self.label_22 = QtWidgets.QLabel(self.groupBox_6)
        self.label_22.setGeometry(QtCore.QRect(80, 26, 20, 13))
        self.label_22.setObjectName("label_22")


        self.lineEdit_koef1 = QtWidgets.QLineEdit(self.groupBox_6)
        self.lineEdit_koef1.setGeometry(QtCore.QRect(5, 7, 70, 18))
        self.lineEdit_koef1.setInputMethodHints(QtCore.Qt.ImhDigitsOnly)
        self.lineEdit_koef1.setObjectName("lineEdit_koef1")
        self.lineEdit_koef1.setText(str(self.koeficienty["uzavreny"][0]))
        # self.lineEdit_koef1.setValidator(QtGui.QDoubleValidator(-0.000000,1.0000000,8,self.lineEdit_koef1))
        # self.lineEdit_koef1.setValidator(self.float_validator)
        self.lineEdit_koef1.textChanged.connect(self.editKoef1)

        self.lineEdit_koef2 = QtWidgets.QLineEdit(self.groupBox_6)
        self.lineEdit_koef2.setGeometry(QtCore.QRect(5, 23, 70, 18))
        self.lineEdit_koef2.setInputMethodHints(QtCore.Qt.ImhDigitsOnly)
        self.lineEdit_koef2.setObjectName("lineEdit_koef2")
        self.lineEdit_koef2.setText(str(self.koeficienty["uzavreny"][1]))
        # self.lineEdit_koef2.setValidator(self.float_validator)
        self.lineEdit_koef2.textChanged.connect(self.editKoef2)

        self.radio1 = QtWidgets.QRadioButton("Uzavřený", self.groupBox_6)
        self.radio1.setGeometry(QtCore.QRect(100, 3, 80, 25))
        self.radio1.setChecked(True)
        self.radio1.toggled.connect(lambda: self.btnstate(self.radio1))
        self.radio2 = QtWidgets.QRadioButton("Otevřený", self.groupBox_6)
        self.radio2.setGeometry(QtCore.QRect(100, 20, 80, 25))
        self.radio2.toggled.connect(lambda: self.btnstate(self.radio2))

        self.buttonRst = QtWidgets.QPushButton(self.groupBox_6)
        self.buttonRst.setGeometry(QtCore.QRect(170, 2, 55, 21))
        self.buttonRst.setObjectName("buttonRst")
        self.buttonRst.clicked.connect(self.resetKoef)

        self.buttonNuloveMereni = QtWidgets.QPushButton(self.groupBox_6)
        self.buttonNuloveMereni.setGeometry(QtCore.QRect(170, 22, 55, 21))
        self.buttonNuloveMereni.setObjectName("buttonNuloveMereni")
        self.buttonNuloveMereni.clicked.connect(self.nuloveMereni)

        self.lineEdit_nulova1 = QtWidgets.QLineEdit(self.groupBox_6)
        self.lineEdit_nulova1.setGeometry(QtCore.QRect(230, 3, 95, 18))
        self.lineEdit_nulova1.setObjectName("lineEdit_nulova1")
        self.lineEdit_nulova1.setText("č.1")
        self.lineEdit_nulova1.setDisabled(True)

        self.lineEdit_nulova2 = QtWidgets.QLineEdit(self.groupBox_6)
        self.lineEdit_nulova2.setGeometry(QtCore.QRect(230, 23, 95, 18))
        self.lineEdit_nulova2.setObjectName("lineEdit_nulova2")
        self.lineEdit_nulova2.setText("č.2")
        self.lineEdit_nulova2.setDisabled(True)

        self.pushNula1.clicked.connect(self.nula1)
        self.pushNula2.clicked.connect(self.nula2)
        self.pushTare2.clicked.connect(self.tare2)
        self.pushTare2_2.clicked.connect(self.tare1)
        self.pushNulaZrusit1.clicked.connect(self.nula1_zrusit)
        self.pushNulaZrusit2.clicked.connect(self.nula2_zrusit)
        self.pushTareZrusit2.clicked.connect(self.tare2_zrusit)
        self.pushTareZrusit2_2.clicked.connect(self.tare1_zrusit)

        self.groupBox.raise_()
        self.text_hodnoty1.raise_()
        self.text_hodnoty2.raise_()
        self.label.raise_()
        self.label_2.raise_()
        self.label_20.raise_()
        self.label_21.raise_()
        self.label_22.raise_()
        self.label_3.raise_()
        self.label_4.raise_()
        self.label_5.raise_()
        self.label_6.raise_()
        self.label_7.raise_()
        self.prumer1.raise_()
        self.prumer2.raise_()
        self.smodch1.raise_()
        self.smodch2.raise_()
        self.groupBox_2.raise_()
        self.groupBox_3.raise_()
        self.groupBox_4.raise_()
        self.groupBox_5.raise_()
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.radio2.click()
        self.radio1.click()
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def resetKoef(self):
        self.koeficienty = {'uzavreny': [0.000615, 0.001056], 'otevreny': [0.000895, 0.000287]}
        self.radio2.click()
        self.radio1.click()

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Měření"))
        self.label.setText(_translate("MainWindow", "Statické měření"))
        self.label_2.setText(_translate("MainWindow", "Čidlo 1"))
        self.label_3.setText(_translate("MainWindow", "Čidlo 2"))
        self.label_20.setText(_translate("MainWindow", "Parametry"))
        self.label_21.setText(_translate("MainWindow", "č.1"))
        self.label_22.setText(_translate("MainWindow", "č.2"))
        self.label_4.setText(_translate("MainWindow", "Průměrná hodnota"))
        self.label_5.setText(_translate("MainWindow", "Směrodatná odchylka"))
        self.label_6.setText(_translate("MainWindow", "Průměrná hodnota"))
        self.label_7.setText(_translate("MainWindow", "Směrodatná odchylka"))
        self.buttonMereni.setText(_translate("MainWindow", "Měření"))
        self.buttonRst.setText(_translate("MainWindow","Reset"))
        self.buttonNuloveMereni.setText(_translate("MainWindow","Měření 0"))
        self.label_8.setText(_translate("MainWindow", "Rozdíl"))
        self.label_9.setText(_translate("MainWindow", "Dynamické měření"))
        self.label_10.setText(_translate("MainWindow", "Počet měření"))
        self.label_11.setText(_translate("MainWindow", "Interval [s]"))
        self.label_12.setText(_translate("MainWindow", "Název souboru"))
        self.buttonMereniDynamicke.setText(_translate("MainWindow", "Zahájit měření"))
        self.label_13.setText(_translate("MainWindow", "Hodnoty"))
        self.groupBox_4.setTitle(_translate("MainWindow", "Čidlo 2"))
        self.pushTare2.setText(_translate("MainWindow", "Tare"))
        self.pushTareZrusit2.setText(_translate("MainWindow", "Vynulovat Tare"))
        self.pushNula2.setText(_translate("MainWindow", "Vynulovat"))
        self.pushNulaZrusit2.setText(_translate("MainWindow", "Zrušit 0"))
        self.groupBox_5.setTitle(_translate("MainWindow", "Čidlo 1"))
        self.pushTare2_2.setText(_translate("MainWindow", "Tare"))
        self.pushTareZrusit2_2.setText(_translate("MainWindow", "Vynulovat Tare"))
        self.pushNula1.setText(_translate("MainWindow", "Vynulovat"))
        self.pushNulaZrusit1.setText(_translate("MainWindow", "Zrušit 0"))

    def nuloveMereni(self):
        self.probihaNuloveMereni = True
        self.multiple_measure()
        self.probihaNuloveMereni = False
        self.lineEdit_nulova1.setText(str(self.nuloveHodnoty[0]) + " č.1")
        self.lineEdit_nulova2.setText(str(self.nuloveHodnoty[1]) + " č.2")

    def editKoef1(self):
        if self.radio1.isChecked() == True:
            try:
                self.koeficienty["uzavreny"][0] = float(self.lineEdit_koef1.text())
            except ValueError:
                print("not a float")
        if self.radio2.isChecked() == True:
            try:
                self.koeficienty["otevreny"][0] = float(self.lineEdit_koef1.text())
            except ValueError:
                print("not a float")

    def editKoef2(self):
        if self.radio1.isChecked() == True:
            try:
                self.koeficienty["uzavreny"][1] = float(self.lineEdit_koef2.text())
            except ValueError:
                print("not a float")
        if self.radio2.isChecked() == True:
            try:
                self.koeficienty["otevreny"][1] = float(self.lineEdit_koef2.text())
            except ValueError:
                print("not a float")

    def btnstate(self, b):
        if b.text() == "Otevřený":
            if b.isChecked() == True:
                self.lineEdit_koef1.setText(str(self.koeficienty['otevreny'][0]))
                self.lineEdit_koef2.setText(str(self.koeficienty['otevreny'][1]))

        if b.text() == "Uzavřený":
            if b.isChecked() == True:
                self.lineEdit_koef1.setText(str(self.koeficienty['uzavreny'][0]))
                self.lineEdit_koef2.setText(str(self.koeficienty['uzavreny'][1]))


    def nula1(self):
        # {"id":27,"method":"call","params":{"path":"measval/cmdSetZeroGros","args":[]}}
        self.send_command(1, "zero")

    def nula2(self):
        self.send_command(2, "zero")

    def tare2(self):
        self.send_command(2, "tare")

    def tare1(self):
        self.send_command(1, "tare")

    def nula1_zrusit(self):
        self.send_command(1, "clear_zero")

    def nula2_zrusit(self):
        self.send_command(2, "clear_zero")

    def tare1_zrusit(self):
        self.send_command(1, "clear_tare")

    def tare2_zrusit(self):
        self.send_command(2, "clear_tare")

    def multiple_measure(self):
        critical_fail = False
        koeficienty = np.array([0, 0])
        if self.radio1.isChecked() == True:
            koeficienty[0] = self.koeficienty["uzavreny"][0]
            koeficienty[1] = self.koeficienty["uzavreny"][1]
        if self.radio2.isChecked() == True:
            koeficienty[0] = self.koeficienty["otevreny"][0]
            koeficienty[1] = self.koeficienty["otevreny"][1]

        print("multiple")
        self.buttonMereni.setEnabled(False)
        self.buttonMereniDynamicke.setEnabled(False)
        self.graphicsView.plotItem.clear()
        if self.probihaNuloveMereni:
            total_measurements = 1
            period_time = 1
        else:
            total_measurements = int(self.lineEdit_pocet_2.text())
            period_time = int(self.lineEdit_interval.text())
        dyn_value = np.array([])
        dyn_prumer1 = np.array([])
        dyn_prumer2 = np.array([])
        dyn_smodch1 = np.array([])
        dyn_smodch2 = np.array([])

        self.text_dynhodnoty.setText("")
        QtGui.QGuiApplication.processEvents()

        for measurement in range(total_measurements):
            self.text_hodnoty1.setText("")
            self.text_hodnoty2.setText("")
            self.rozdil.setText("0")
            self.prumer1.setText("0")
            self.prumer2.setText("0")
            self.smodch1.setText("0")
            self.smodch2.setText("0")
            json_trigger_command = """
                                   {"id":1,"method":"call","params":{"path":"measval/cmdTriggerCapturedValue1","args":[]}}
                                   """
            json_get_command = """
                                   {"method":"fetch_all","params":{"path":"measval/values/capturedValue1"}}
                                   """
            json_trigger = json.loads(json_trigger_command)
            json_get = json.loads(json_get_command)
            expected_message = """"path":"measval/values/capturedValue1"""""
            sensor1_values = [None] * 1
            measured_values = np.zeros((1,))
            try:
                ws = create_connection("ws://169.254.178.232:8081")
            except Exception as ex:
                print(ex)
                critical_fail = True
            print("Start mereni 1:" + str(datetime.datetime.now()))
            if not critical_fail:
                for mereni in range(1):
                    try:
                        ws.send(json.dumps(json_trigger))
                    except Exception as ex:
                        print(ex)
                    try:
                        result = ws.recv()
                    except Exception as ex:
                        print(ex)
                        time.sleep(.1)
                        # TODO check result
                    try:
                        ws.send(json.dumps(json_get))
                        clipx_message = ""
                        while expected_message not in clipx_message:
                            try:
                                clipx_message = ws.recv()
                                print(clipx_message)
                            except Exception as ex:
                                print(ex)
                            sensor1_values[mereni] = json.loads(clipx_message)
                    except Exception as ex:
                        print(ex)
                    self.text_hodnoty1.append("{:.4E}".format(Decimal(sensor1_values[mereni]["params"]["value"]/koeficienty[0])))
                    QtGui.QGuiApplication.processEvents()
                    # TODO check jestli jde o nulové měření
                    measured_values[mereni] = sensor1_values[mereni]["params"]["value"]/koeficienty[0]
                    if self.probihaNuloveMereni:
                        self.nuloveHodnoty[0] = measured_values[mereni]
                try:
                    ws.close()
                except Exception as ex:
                    print(ex)
                print("Stop mereni 1:" + str(datetime.datetime.now()))
                dyn_prumer1 = np.append(dyn_prumer1, measured_values.mean())
                dyn_smodch1 = np.append(dyn_smodch1, measured_values.std())
                self.prumer1.setText("{:.4E}".format(Decimal(measured_values.mean())))
                self.smodch1.setText("{:.4E}".format(Decimal(measured_values.std())))
                QtGui.QGuiApplication.processEvents()

                sensor2_values = [None] * 1
                measured2_values = np.zeros((1, 1))
                try:
                    ws2 = create_connection("ws://169.254.178.218:8081")
                except Exception as ex:
                    print(ex)
                    critical_fail = True
                self.text_hodnoty2.setText("")
                print("Start mereni 2:" + str(datetime.datetime.now()))
                if not critical_fail:
                    for mereni in range(1):
                        try:
                            ws2.send(json.dumps(json_trigger))
                            result = ws2.recv()
                            time.sleep(.1)
                            # TODO check result
                            ws2.send(json.dumps(json_get))
                            clipx_message = ""
                            while not expected_message in clipx_message:
                                clipx_message = ws2.recv()

                                sensor2_values[mereni] = json.loads(clipx_message)
                        except Exception as ex:
                            print(ex)
                        # print(sensor1_values[mereni]["params"]["value"])
                        self.text_hodnoty2.append("{:.4E}".format(Decimal(sensor2_values[mereni]["params"]["value"]/koeficienty[1])))
                        QtGui.QGuiApplication.processEvents()
                        measured2_values[mereni] = sensor2_values[mereni]["params"]["value"]/koeficienty[1]
                        if self.probihaNuloveMereni:
                            self.nuloveHodnoty[1] = measured2_values[mereni]
                    try:
                        ws2.close()
                    except Exception as ex:
                        print(ex)
                    print("Stop mereni 2:" + str(datetime.datetime.now()))
                    dyn_prumer2 = np.append(dyn_prumer2, measured2_values.mean())
                    dyn_smodch2 = np.append(dyn_smodch2, measured2_values.std())
                    self.prumer2.setText("{:.4E}".format(Decimal(measured2_values.mean())))
                    self.smodch2.setText("{:.4E}".format(Decimal(measured2_values.std())))

                    dyn_value = np.append(dyn_value, measured_values.mean() - measured2_values.mean())
                    self.text_dynhodnoty.append("{:.4E}".format(Decimal(dyn_value[-1])))
                    self.rozdil.setText("{:.4E}".format(Decimal(dyn_value[measurement])))
                    if len(dyn_value) > 1:
                        try:
                            self.graphicsView.plot(dyn_value, pen=pq.mkPen('b', width=3,
                                                                           style=QtCore.Qt.SolidLine, color=(200, 200, 255)))
                            self.graphicsView.getPlotItem().showGrid(x=True, y=True, alpha=1)
                            QtGui.QGuiApplication.processEvents()
                        except Exception as ex:
                            print(ex)
                    start_pause = (datetime.datetime.now())

                    time_difference = start_pause - start_pause
                    time_difference_seconds = time_difference.total_seconds()
                    while time_difference_seconds < period_time:
                        time.sleep(0.05)
                        QtGui.QGuiApplication.processEvents()
                        time_difference = datetime.datetime.now() - start_pause
                        time_difference_seconds = time_difference.total_seconds()

                QtGui.QGuiApplication.processEvents()
                if self.probihaNuloveMereni:
                    pass
                else:
                    output = np.asarray([dyn_value, dyn_value, dyn_value, dyn_value, dyn_value])
                    try:
                        np.savetxt(self.lineEdit.text(), output.transpose(), delimiter=",",
                                   header="diff,smodch1,smodch2,prumer1,prumer2")
                    except Exception as ex:
                        print(ex)
                    self.lineEdit.setText(datetime.datetime.now().strftime("Data_" + "%Y-%m-%d_%H%M%S" + ".csv"))
                    QtGui.QGuiApplication.processEvents()
        self.buttonMereni.setEnabled(True)
        self.buttonMereniDynamicke.setEnabled(True)

    def one_measure(self):
        critical_fail = False
        koeficienty = np.array([0, 0])
        if self.radio1.isChecked() == True:
            koeficienty[0] = self.koeficienty["uzavreny"][0]
            koeficienty[1] = self.koeficienty["uzavreny"][1]
        if self.radio2.isChecked() == True:
            koeficienty[0] = self.koeficienty["otevreny"][0]
            koeficienty[1] = self.koeficienty["otevreny"][1]

        self.buttonMereni.setEnabled(False)
        self.buttonMereniDynamicke.setEnabled(False)
        QtGui.QGuiApplication.processEvents()
        self.text_hodnoty1.setText("")
        self.text_hodnoty2.setText("")
        self.rozdil.setText("0")
        self.prumer1.setText("")
        self.prumer2.setText("")
        self.rozdil.setText("")
        json_trigger_command = """
                       {"id":1,"method":"call","params":{"path":"measval/cmdTriggerCapturedValue1","args":[]}}
                       """
        json_get_command = """
                       {"method":"fetch_all","params":{"path":"measval/adcBinVal32"}}
                       """
        json_trigger = json.loads(json_trigger_command)
        json_get = json.loads(json_get_command)
        expected_message = """"path":"measval/values/capturedValue1"""""
        sensor1_values = [None] * 10
        measured_values = np.zeros((10,))
        critical_fail = False
        try:
            ws = create_connection("ws://169.254.178.232:8081")
        except Exception as ex:
            print(ex)
            critical_fail = True
        if not critical_fail:
            for mereni in range(10):
                ws.send(json.dumps(json_trigger))
                result = ws.recv()
                time.sleep(.1)
                # TODO check result
                ws.send(json.dumps(json_get))
                clipx_message = ""
                while expected_message not in clipx_message:
                    clipx_message = ws.recv()

                    sensor1_values[mereni] = json.loads(clipx_message)
                self.text_hodnoty1.append(str(sensor1_values[mereni]["params"]["value"]/koeficienty[0]))
                QtGui.QGuiApplication.processEvents()
                measured_values[mereni] = sensor1_values[mereni]["params"]["value"]/koeficienty[0]
            ws.close()

            self.prumer1.setText("{:.4E}".format(Decimal(measured_values.mean())))
            self.smodch1.setText("{:.4E}".format(Decimal(measured_values.std())))
            QtGui.QGuiApplication.processEvents()
            sensor2_values = [None] * 10
            measured2_values = np.zeros((10, 1))
            try:
                ws2 = create_connection("ws://169.254.178.218:8081")
            except Exception as ex:
                print(ex)
                critical_fail = True
            self.text_hodnoty2.setText("")
            if not critical_fail:
                for mereni in range(10):
                    ws2.send(json.dumps(json_trigger))
                    result = ws2.recv()
                    time.sleep(.1)
                    print(mereni)
                    # TODO check result
                    ws2.send(json.dumps(json_get))
                    clipx_message = ""
                    while not expected_message in clipx_message:
                        clipx_message = ws2.recv()

                        sensor2_values[mereni] = json.loads(clipx_message)

                    # print(sensor1_values[mereni]["params"]["value"])
                    self.text_hodnoty2.append("{:.4E}".format(Decimal(sensor2_values[mereni]["params"]["value"]/koeficienty[1])))
                    QtGui.QGuiApplication.processEvents()
                    measured2_values[mereni] = sensor2_values[mereni]["params"]["value"]/koeficienty[1]

                ws2.close()

                self.prumer2.setText("{:.4E}".format(Decimal(measured2_values.mean())))
                self.smodch2.setText("{:.4E}".format(Decimal(measured2_values.std())))
                rozdil = measured_values.mean() - measured2_values.mean()
                self.rozdil.setText("{:.4E}".format(Decimal(rozdil)))
        self.buttonMereni.setEnabled(True)
        self.buttonMereniDynamicke.setEnabled(True)
        QtGui.QGuiApplication.processEvents()

    def send_command(self, device, command):
        critical_fail = False
        if device == 1:
            connection_string = "ws://169.254.178.218:8081"
        else:
            connection_string = "ws://169.254.178.232:8081"

        if command == "tare":
            json_command = """
            {"id":2,"method":"call","params":{"path":"measval/cmdSetZeroNet","args":[]}}"""
        elif command == "clear_tare":
            json_command = """
            {"id":31,"method":"call","params":{"path":"measval/cmdClearOffsetNet","args":[]}}"""
        elif command == "zero":
            json_command = """
            {"id":32,"method":"call","params":{"path":"measval/cmdSetZeroGros","args":[]}}"""
            # json_command = """
            # {"id":68,"method":"set","params":{"path":"measval/scaling/zeroTargetGros","value":150}}"""
        elif command == "clear_zero":
            json_command = """
            {"id":33,"method":"call","params":{"path":"measval/cmdClearOffsetGros","args":[]}}"""
        else:
            print("ERROR")
            json_command = """"""
        try:
            ws = create_connection(connection_string)
        except Exception as ex:
            print(ex)
            critical_fail = True
        if not critical_fail:
            json_tare = json.loads(json_command)
            ws.send(json.dumps(json_tare))
            result = ws.recv()
            print(result)
            ws.close()
class PyQtGraphDataPlot(QWidget):

    limits_changed = Signal()

    def __init__(self, parent=None):
        super(PyQtGraphDataPlot, self).__init__(parent)
        self._plot_widget = PlotWidget()
        self._plot_widget.getPlotItem().addLegend()
        self._plot_widget.setBackground((255, 255, 255))
        self._plot_widget.setXRange(0, 10, padding=0)
        vbox = QVBoxLayout()
        vbox.addWidget(self._plot_widget)
        self.setLayout(vbox)
        self._plot_widget.getPlotItem().sigRangeChanged.connect(
            self.limits_changed)

        self._curves = {}
        self._current_vline = None

    def add_curve(self,
                  curve_id,
                  curve_name,
                  curve_color=QColor(Qt.blue),
                  markers_on=False):
        pen = mkPen(curve_color, width=1)
        symbol = "o"
        symbolPen = mkPen(QColor(Qt.black))
        symbolBrush = mkBrush(curve_color)
        # this adds the item to the plot and legend
        if markers_on:
            plot = self._plot_widget.plot(name=curve_name,
                                          pen=pen,
                                          symbol=symbol,
                                          symbolPen=symbolPen,
                                          symbolBrush=symbolBrush,
                                          symbolSize=4)
        else:
            plot = self._plot_widget.plot(name=curve_name, pen=pen)
        self._curves[curve_id] = plot

    def remove_curve(self, curve_id):
        curve_id = str(curve_id)
        if curve_id in self._curves:
            self._plot_widget.removeItem(self._curves[curve_id])
            del self._curves[curve_id]
            self._update_legend()

    def _update_legend(self):
        # clear and rebuild legend (there is no remove item method for the legend...)
        self._plot_widget.clear()
        self._plot_widget.getPlotItem().legend.items = []
        for curve in self._curves.values():
            self._plot_widget.addItem(curve)
        if self._current_vline:
            self._plot_widget.addItem(self._current_vline)

    def redraw(self):
        pass

    def set_values(self, curve_id, data_x, data_y):
        curve = self._curves[curve_id]
        curve.setData(data_x, data_y)

    def vline(self, x, color):
        if self._current_vline:
            self._plot_widget.removeItem(self._current_vline)
        self._current_vline = self._plot_widget.addLine(x=x, pen=color)

    def set_xlim(self, limits):
        # TODO: this doesn't seem to handle fast updates well
        self._plot_widget.setXRange(limits[0], limits[1], padding=0)

    def set_ylim(self, limits):
        self._plot_widget.setYRange(limits[0], limits[1], padding=0)

    def get_xlim(self):
        x_range, _ = self._plot_widget.viewRange()
        return x_range

    def get_ylim(self):
        _, y_range = self._plot_widget.viewRange()
        return y_range
class Ui_MainWindow(object):
    accuracy_vals = []
    recording_vals = np.zeros([
        960 * 10 * 10,
    ])
    microphone_recorder = None
    train_thread = None
    recorder_thread = None
    ser_inference_model = SER_Inference_Model()
    ser_online_model = SER_Online_Model()
    label_7_line_nr = 0
    play_th = None

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        MainWindow.resize(1300, 900)

        qr = MainWindow.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        MainWindow.move(qr.topLeft())

        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.gridLayout_2 = QtWidgets.QGridLayout()
        self.gridLayout_2.setSpacing(0)
        self.gridLayout_2.setObjectName("gridLayout_2")

        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setContentsMargins(10, 10, 10, 10)
        self.verticalLayout.setSpacing(2)
        self.verticalLayout.setObjectName("verticalLayout")

        self.groupBox_4 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_4.setMinimumSize(QtCore.QSize(670, 860))
        self.groupBox_4.setObjectName("groupBox_4")

        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(40, 400, 400, 20))
        self.label_2.setMaximumSize(QtCore.QSize(16777215, 20))
        self.label_2.setObjectName("label_2")

        self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar.setGeometry(QtCore.QRect(40, 400, 500, 40))
        self.progressBar.setMinimumSize(QtCore.QSize(500, 40))
        self.progressBar.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.progressBar.setStyleSheet(COMPLETED_STYLE_ANGRY)
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")

        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(40, 460, 400, 20))
        self.label_3.setMaximumSize(QtCore.QSize(16777215, 20))
        self.label_3.setObjectName("label_3")

        self.progressBar_2 = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar_2.setGeometry(QtCore.QRect(40, 460, 500, 40))
        self.progressBar_2.setMinimumSize(QtCore.QSize(500, 40))
        self.progressBar_2.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.progressBar_2.setStyleSheet(COMPLETED_STYLE_HAPPY)
        self.progressBar_2.setProperty("value", 0)
        self.progressBar_2.setObjectName("progressBar_2")

        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(40, 520, 400, 20))
        self.label_4.setMaximumSize(QtCore.QSize(16777215, 20))
        self.label_4.setObjectName("label_4")

        self.progressBar_3 = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar_3.setGeometry(QtCore.QRect(40, 520, 500, 40))
        self.progressBar_3.setMinimumSize(QtCore.QSize(500, 40))
        self.progressBar_3.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.progressBar_3.setStyleSheet(COMPLETED_STYLE_SAD)
        self.progressBar_3.setProperty("value", 0)
        self.progressBar_3.setObjectName("progressBar_3")

        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(40, 570, 400, 20))
        self.label_5.setMaximumSize(QtCore.QSize(16777215, 20))
        self.label_5.setObjectName("label_5")

        self.progressBar_4 = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar_4.setGeometry(QtCore.QRect(40, 560, 500, 40))
        self.progressBar_4.setMinimumSize(QtCore.QSize(500, 40))
        self.progressBar_4.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.progressBar_4.setProperty("value", 0)
        self.progressBar_4.setObjectName("progressBar_4")

        self.graphicsView = PlotWidget(self.groupBox_4)
        self.graphicsView.setGeometry(QtCore.QRect(10, 30, 650, 400))
        self.graphicsView.setObjectName("graphicsView")
        self.verticalLayout.addWidget(self.groupBox_4)
        self.gridLayout_2.addLayout(self.verticalLayout, 0, 0, 1, 1)
        self.gridLayout.addLayout(self.gridLayout_2, 0, 3, 1, 1)

        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setSizeConstraint(
            QtWidgets.QLayout.SetDefaultConstraint)
        self.verticalLayout_2.setContentsMargins(10, 10, 10, 10)
        self.verticalLayout_2.setSpacing(2)
        self.verticalLayout_2.setObjectName("verticalLayout_2")

        self.groupBox_3 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_3.setMinimumSize(QtCore.QSize(603, 110))
        self.groupBox_3.setObjectName("groupBox_3")

        self.comboBox_2 = QtWidgets.QComboBox(self.groupBox_3)
        self.comboBox_2.setGeometry(QtCore.QRect(105, 72, 441, 30))
        self.comboBox_2.setObjectName("comboBox_2")

        self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox_3)
        self.lineEdit_2.setGeometry(QtCore.QRect(105, 35, 441, 30))
        self.lineEdit_2.setObjectName("lineEdit_2")

        self.label_9 = QtWidgets.QLabel(self.groupBox_3)
        self.label_9.setGeometry(QtCore.QRect(10, 37, 90, 30))
        self.label_9.setObjectName("label_9")

        self.label_10 = QtWidgets.QLabel(self.groupBox_3)
        self.label_10.setGeometry(QtCore.QRect(60, 71, 40, 30))
        self.label_10.setObjectName("label_10")

        self.pushButtonInfPlay = QtWidgets.QPushButton(self.groupBox_3)
        self.pushButtonInfPlay.setGeometry(QtCore.QRect(550, 72, 48, 30))
        self.pushButtonInfPlay.setObjectName("pushButtonInfPlay")

        self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_2.setMinimumSize(QtCore.QSize(600, 280))
        self.groupBox_2.setObjectName("groupBox_2")

        self.label_18 = QtWidgets.QLabel(self.groupBox_2)
        self.label_18.setGeometry(QtCore.QRect(10, 75, 205, 25))
        self.label_18.setObjectName("label_18")

        self.radioButton_3 = QtWidgets.QRadioButton(self.groupBox_2)
        self.radioButton_3.setGeometry(QtCore.QRect(215, 77, 165, 25))
        self.radioButton_3.setChecked(True)
        self.radioButton_3.setAutoRepeat(False)
        self.radioButton_3.setObjectName("radioButton_3")

        self.radioButton_4 = QtWidgets.QRadioButton(self.groupBox_2)
        self.radioButton_4.setGeometry(QtCore.QRect(325, 77, 120, 25))
        self.radioButton_4.setObjectName("radioButton_4")

        self.label_8 = QtWidgets.QLabel(self.groupBox_2)
        self.label_8.setGeometry(QtCore.QRect(10, 243, 94, 25))
        self.label_8.setObjectName("label_8")

        self.lineEdit = QtWidgets.QLineEdit(self.groupBox_2)
        self.lineEdit.setGeometry(QtCore.QRect(75, 240, 70, 30))
        self.lineEdit.setObjectName("lineEdit")

        self.label_17 = QtWidgets.QLabel(self.groupBox_2)
        self.label_17.setGeometry(QtCore.QRect(460, 243, 110, 30))
        self.label_17.setObjectName("label_17")

        self.label_19 = QtWidgets.QLabel(self.groupBox_2)
        self.label_19.setGeometry(QtCore.QRect(570, 243, 30, 30))
        self.label_19.setObjectName("label_19")

        self.comboBox = QtWidgets.QComboBox(self.groupBox_2)
        self.comboBox.setGeometry(QtCore.QRect(125, 38, 460, 30))
        self.comboBox.setMinimumSize(QtCore.QSize(200, 0))
        self.comboBox.setFocusPolicy(QtCore.Qt.WheelFocus)
        self.comboBox.setMaxVisibleItems(10)
        self.comboBox.setIconSize(QtCore.QSize(16, 16))
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")

        self.label = QtWidgets.QLabel(self.groupBox_2)
        self.label.setGeometry(QtCore.QRect(10, 36, 105, 30))
        self.label.setObjectName("label")

        self.label_11 = QtWidgets.QLabel(self.groupBox_2)
        self.label_11.setGeometry(QtCore.QRect(10, 100, 130, 30))
        self.label_11.setObjectName("label_11")
        self.horizontalSlider = QtWidgets.QSlider(self.groupBox_2)
        self.horizontalSlider.setGeometry(QtCore.QRect(138, 109, 430, 17))
        self.horizontalSlider.setMaximum(10)
        self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSlider.setObjectName("horizontalSlider")
        self.label_12 = QtWidgets.QLabel(self.groupBox_2)
        self.label_12.setGeometry(QtCore.QRect(570, 102, 31, 30))
        self.label_12.setObjectName("label_12")

        self.label_15 = QtWidgets.QLabel(self.groupBox_2)
        self.label_15.setGeometry(QtCore.QRect(10, 132, 121, 25))
        self.label_15.setObjectName("label_15")
        self.horizontalSlider_2 = QtWidgets.QSlider(self.groupBox_2)
        self.horizontalSlider_2.setGeometry(QtCore.QRect(138, 137, 430, 17))
        self.horizontalSlider_2.setMaximum(10)
        self.horizontalSlider_2.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSlider_2.setObjectName("horizontalSlider_2")
        self.label_16 = QtWidgets.QLabel(self.groupBox_2)
        self.label_16.setGeometry(QtCore.QRect(570, 134, 31, 25))
        self.label_16.setObjectName("label_15")

        self.ooda_check_box = QtWidgets.QCheckBox(self.groupBox_2)
        self.ooda_check_box.setGeometry(QtCore.QRect(15, 160, 120, 31))
        self.ooda_check_box.setObjectName("checkBoxOODA")
        self.horizontalSlider_ooda = QtWidgets.QSlider(self.groupBox_2)
        self.horizontalSlider_ooda.setGeometry(QtCore.QRect(138, 168, 430, 17))
        self.horizontalSlider_ooda.setMaximum(9)
        self.horizontalSlider_ooda.setMinimum(1)
        self.horizontalSlider_ooda.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSlider_ooda.setObjectName("horizontalSlider_ooda")
        self.label_ooda = QtWidgets.QLabel(self.groupBox_2)
        self.label_ooda.setGeometry(QtCore.QRect(570, 164, 31, 25))
        self.label_ooda.setObjectName("label_ooda")

        self.label_13 = QtWidgets.QLabel(self.groupBox_2)
        self.label_13.setGeometry(QtCore.QRect(10, 197, 121, 25))
        self.label_13.setObjectName("label_13")
        self.doubleSpinBox = QtWidgets.QDoubleSpinBox(self.groupBox_2)
        self.doubleSpinBox.setGeometry(QtCore.QRect(121, 197, 100, 31))
        self.doubleSpinBox.setDecimals(5)
        self.doubleSpinBox.setSingleStep(1e-05)
        self.doubleSpinBox.setObjectName("doubleSpinBox")

        self.verticalLayout_2.addWidget(self.groupBox_2)

        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setMinimumSize(QtCore.QSize(30, 70))
        self.groupBox.setObjectName("groupBox")

        self.radioButton = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton.setGeometry(QtCore.QRect(10, 30, 60, 30))
        self.radioButton.setChecked(True)
        self.radioButton.setObjectName("radioButton")

        self.radioButton_2 = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton_2.setGeometry(QtCore.QRect(100, 30, 226, 30))
        self.radioButton_2.setObjectName("radioButton_2")

        self.pushButton = QtWidgets.QPushButton(self.groupBox)
        self.pushButton.setGeometry(QtCore.QRect(250, 30, 100, 30))
        self.pushButton.setMaximumSize(QtCore.QSize(100, 16777215))
        self.pushButton.setIconSize(QtCore.QSize(16, 16))
        self.pushButton.setObjectName("pushButton")

        self.pushButtonStop = QtWidgets.QPushButton(self.groupBox)
        self.pushButtonStop.setGeometry(QtCore.QRect(380, 30, 100, 30))
        self.pushButtonStop.setMaximumSize(QtCore.QSize(100, 16777215))
        self.pushButtonStop.setIconSize(QtCore.QSize(16, 16))
        self.pushButtonStop.setObjectName("pushButtonStop")
        self.verticalLayout_2.addWidget(self.groupBox)

        self.groupBox_5 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_5.setMinimumSize(QtCore.QSize(30, 155))
        self.groupBox_5.setObjectName("groupBox_5")
        self.verticalLayout_2.addWidget(self.groupBox_3)
        self.verticalLayout_2.addWidget(self.groupBox_5)

        self.graphicsViewRec = PlotWidget(self.groupBox_5)
        self.graphicsViewRec.setGeometry(QtCore.QRect(115, 37, 480, 110))
        self.graphicsViewRec.setObjectName("graphicsViewRec")
        self.graphicsViewRec.setYRange(-20000, 20000, padding=0)
        self.graphicsViewRec.setXRange(0, 10 * 125 * 94, padding=0)

        self.pushButtonRecord = QtWidgets.QPushButton(self.groupBox_5)
        self.pushButtonRecord.setGeometry(QtCore.QRect(10, 37, 100, 30))
        self.pushButtonRecord.setMaximumSize(QtCore.QSize(100, 16777215))
        self.pushButtonRecord.setIconSize(QtCore.QSize(16, 16))
        self.pushButtonRecord.setObjectName("pushButtonRecord")

        self.pushButtonStopRecord = QtWidgets.QPushButton(self.groupBox_5)
        self.pushButtonStopRecord.setGeometry(QtCore.QRect(10, 77, 100, 30))
        self.pushButtonStopRecord.setMaximumSize(QtCore.QSize(100, 16777215))
        self.pushButtonStopRecord.setIconSize(QtCore.QSize(16, 16))
        self.pushButtonStopRecord.setObjectName("pushButtonStopRecord")

        self.pushButtonPlay = QtWidgets.QPushButton(self.groupBox_5)
        self.pushButtonPlay.setGeometry(QtCore.QRect(10, 117, 100, 30))
        self.pushButtonPlay.setMaximumSize(QtCore.QSize(100, 16777215))
        self.pushButtonPlay.setIconSize(QtCore.QSize(16, 16))
        self.pushButtonPlay.setObjectName("pushButtonPlay")

        self.tabs = QtWidgets.QTabWidget(self.groupBox_4)
        self.tabs.setGeometry(QtCore.QRect(10, 440, 600, 400))
        self.tabs.setMinimumHeight(400)
        self.tabs.setMinimumWidth(600)
        self.tabs.setIconSize(QtCore.QSize(30, 300))
        self.tableWidget = QtWidgets.QTableWidget()
        self.tableWidget.setRowCount(5)
        self.tableWidget.setColumnCount(5)
        self.tableWidget.setHorizontalHeaderLabels(
            ["Angry", "Happy", "Sad", "Normal", " Total "])  #
        self.tableWidget.setVerticalHeaderLabels(
            ["Angry", "Happy", "Sad", "Normal", "Total"])  #

        self.tableWidget.setItem(0, 0, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(0, 1, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(0, 2, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(0, 3, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(0, 4, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(1, 0, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(1, 1, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(1, 2, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(1, 3, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(1, 4, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(2, 0, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(2, 1, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(2, 2, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(2, 3, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(2, 4, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(3, 0, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(3, 1, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(3, 2, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(3, 3, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(3, 4, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(4, 0, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(4, 1, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(4, 2, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(4, 3, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(4, 4, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.item(4, 4).setBackground(QtGui.QColor(102, 140, 255))
        self.tableWidget.item(3, 3).setBackground(QtGui.QColor(125, 125, 125))
        self.tableWidget.item(2, 2).setBackground(QtGui.QColor(125, 125, 125))
        self.tableWidget.item(1, 1).setBackground(QtGui.QColor(125, 125, 125))
        self.tableWidget.item(0, 0).setBackground(QtGui.QColor(125, 125, 125))

        for i in range(5):
            for j in range(5):
                self.tableWidget.item(i, j).setFlags(QtCore.Qt.ItemIsEnabled)
        self.tabs.resize(650, 425)

        self.label_7 = QtWidgets.QLabel(self.groupBox_4)
        self.label_7.setMinimumSize(QtCore.QSize(600, 425))
        self.label_7.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
        self.label_7.setStyleSheet("font: 9pt \"Sans Serif\";\n"
                                   "background-color: rgb(0, 0, 0);")
        self.label_7.setFrameShadow(QtWidgets.QFrame.Raised)
        self.label_7.setLineWidth(4)
        self.label_7.setTextFormat(QtCore.Qt.AutoText)
        self.label_7.setScaledContents(True)
        self.label_7.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft
                                  | QtCore.Qt.AlignTop)
        self.label_7.setWordWrap(True)
        self.label_7.setIndent(0)
        self.label_7.setOpenExternalLinks(False)
        self.label_7.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse
                                             | QtCore.Qt.TextSelectableByMouse)
        self.label_7.setObjectName("label_7")

        self.verticalLayoutTable = QtWidgets.QVBoxLayout()
        self.verticalLayoutTable.setSizeConstraint(
            QtWidgets.QLayout.SetDefaultConstraint)
        self.verticalLayoutTable.setContentsMargins(33, 95, 33, 70)
        self.verticalLayoutTable.setSpacing(9)
        self.verticalLayoutTable.setObjectName("verticalLayoutTable")

        self.label_total = QtWidgets.QLabel(self.groupBox_4)
        self.label_total.setObjectName("label_nr")

        self.tab2 = QtWidgets.QWidget()
        self.tabs.addTab(self.label_7, "Logs")
        self.tabs.addTab(self.tab2, "Confusion matrix")

        self.tab2.layout = self.verticalLayoutTable
        self.tab2.layout.addWidget(self.tableWidget)
        self.tab2.layout.addWidget(self.label_total)
        self.tab2.setLayout(self.tab2.layout)

        self.verticalLayout_2.addWidget(self.label_2)
        self.verticalLayout_2.addWidget(self.progressBar)
        self.verticalLayout_2.addWidget(self.label_3)
        self.verticalLayout_2.addWidget(self.progressBar_2)
        self.verticalLayout_2.addWidget(self.label_4)
        self.verticalLayout_2.addWidget(self.progressBar_3)
        self.verticalLayout_2.addWidget(self.label_5)
        self.verticalLayout_2.addWidget(self.progressBar_4)

        self.gridLayout.addLayout(self.verticalLayout_2, 0, 0, 1, 1)

        MainWindow.setCentralWidget(self.centralwidget)

        self.actionReset = QtWidgets.QAction(MainWindow)
        self.actionReset.setObjectName("actionReset")

        self.retranslateUi(MainWindow)
        self.lineEdit_2.setText("Inference")
        self.lineEdit.setText("10")
        self.horizontalSlider_2.setValue(5)
        self.change_label_16()
        self.horizontalSlider.setValue(8)
        self.change_label_12()
        self.horizontalSlider_ooda.setValue(8)
        self.change_label_ooda()
        self.doubleSpinBox.setValue(0.0001)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.fill_file()
        self.ooda_check_box.setChecked(False)
        self.horizontalSlider_ooda.setStyleSheet(SLYDER_DISABLED)
        self.horizontalSlider_ooda.setEnabled(False)

        self.pushButton.clicked.connect(lambda: self.on_start_button_clicked())
        self.pushButtonStop.clicked.connect(
            lambda: self.on_buttonStop_clicked())
        self.pushButtonRecord.clicked.connect(
            lambda: self.on_buttonRecord_clicked())
        self.pushButtonPlay.clicked.connect(lambda: self.play_recording())
        self.pushButtonInfPlay.clicked.connect(
            lambda: self.play_recording(self.comboBox_2.currentText()))
        self.pushButtonStopRecord.clicked.connect(
            lambda: self.on_buttonStopRecord_clicked())
        self.lineEdit_2.returnPressed.connect(lambda: self.fill_file())
        self.radioButton_2.toggled.connect(lambda: self.init_inference())
        self.horizontalSlider.valueChanged.connect(
            lambda: self.change_label_12())
        self.horizontalSlider_2.valueChanged.connect(
            lambda: self.change_label_16())
        self.horizontalSlider_ooda.valueChanged.connect(
            lambda: self.change_label_ooda())
        self.ooda_check_box.stateChanged.connect(
            lambda: self.change_horizontal_ooda())
        self.print_accuracy_graph(0)

    def refresh_label_7(self):
        self.label_7_line_nr = 0
        _translate = QtCore.QCoreApplication.translate
        self.label_7.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p><span style=\" font-weight:600; color:#55ff7f;\"> ...</span></p></body></html>"
            ))

    def refresh_graphics_view(self):
        self.graphicsView.clear()
        self.accuracy_vals = []
        self.print_accuracy_graph(0)

    def refresh_rec_graphics_view(self):
        self.recording_vals = np.zeros([
            960 * 10 * 10,
        ])

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(
            _translate("MainWindow", "Speech Emotion Recognizer"))
        self.groupBox_4.setTitle(_translate("MainWindow", "Statistics"))
        self.groupBox_5.setTitle(_translate("MainWindow", "Recording"))
        self.label_2.setText(_translate("MainWindow", "Angry"))
        self.label_3.setText(_translate("MainWindow", "Happy"))
        self.label_4.setText(_translate("MainWindow", "Sad"))
        self.label_5.setText(_translate("MainWindow", "Neutral"))
        self.groupBox_3.setTitle(
            _translate("MainWindow", "Pick a file to classify"))
        self.label_9.setText(_translate("MainWindow", "Folder path:"))
        self.label_10.setText(_translate("MainWindow", "File:"))
        self.pushButtonInfPlay.setText(_translate("MainWindow", "Play"))
        self.groupBox_2.setTitle(_translate("MainWindow", "Model settings"))
        self.radioButton_3.setText(_translate("MainWindow", "End-to-end"))
        self.radioButton_4.setText(_translate("MainWindow", "Hand-Crafted"))
        self.label_8.setText(_translate("MainWindow", "Epochs:"))
        self.label_18.setText(
            _translate("MainWindow", "Feature extraction tehnioque:"))
        self.label_11.setText(_translate("MainWindow", "Train / Test Ratio:"))
        self.label_12.setText(_translate("MainWindow", "1"))
        self.label_13.setText(_translate("MainWindow", "Learning Rate:"))
        self.label_15.setText(_translate("MainWindow", "Dropout Rate:"))
        self.label_16.setText(_translate("MainWindow", "1"))
        self.label_17.setText(_translate("MainWindow", "Current epoch:"))
        self.label_19.setText(_translate("MainWindow", "0"))
        self.label_ooda.setText(_translate("MainWindow", "0"))
        self.label_total.setText(
            _translate("MainWindow", "Numarul total de intrari = 0"))
        self.comboBox.setItemText(0, _translate("MainWindow", "EMO-DB"))
        self.comboBox.setItemText(1, _translate("MainWindow", "SAVEE"))
        self.comboBox.setItemText(2, _translate("MainWindow", "RAVDESS"))
        self.comboBox.setItemText(3, _translate("MainWindow", "ENTERFACE"))
        self.comboBox.setItemText(4, _translate("MainWindow", "EMOVO"))
        self.comboBox.setItemText(5, _translate("MainWindow", "MAV"))
        self.comboBox.setItemText(6, _translate("MainWindow", "MELD"))
        self.comboBox.setItemText(7, _translate("MainWindow", "JL"))
        self.comboBox.setItemText(7, _translate("MainWindow", "INRP"))
        self.comboBox.setItemText(8, _translate("MainWindow", "MULTIPLE"))
        self.ooda_check_box.setText(_translate("MainWindow", "OODA loop"))
        self.label.setText(_translate("MainWindow", "Select dataset:"))
        self.groupBox.setTitle(_translate("MainWindow", "Actions"))
        self.radioButton.setToolTip(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><br/></p></body></html>"
            ))
        self.radioButton.setText(_translate("MainWindow", "Train"))
        self.radioButton_2.setText(_translate("MainWindow", "Inference"))
        self.pushButton.setText(_translate("MainWindow", "Start"))
        self.pushButtonStop.setText(_translate("MainWindow", "Stop"))
        self.pushButtonRecord.setText(_translate("MainWindow", "Record"))
        self.pushButtonPlay.setText(_translate("MainWindow", "Play"))
        self.pushButtonStopRecord.setText(_translate("MainWindow", "Stop"))
        self.label_7.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p><span style=\" font-weight:600; color:#55ff7f;\"> ...</span></p></body></html>"
            ))
        self.actionReset.setText(_translate("MainWindow", "Reset"))
        self.pushButtonRecord.setEnabled(False)
        self.pushButtonStopRecord.setEnabled(False)
        self.pushButtonStop.setEnabled(False)
        self.pushButtonPlay.setEnabled(False)
        self.pushButtonInfPlay.setEnabled(False)

        self.progressBar.setEnabled(False)
        self.progressBar_2.setEnabled(False)
        self.progressBar_3.setEnabled(False)
        self.progressBar_4.setEnabled(False)
        self.label_2.setEnabled(False)
        self.label_3.setEnabled(False)
        self.label_4.setEnabled(False)
        self.label_5.setEnabled(False)
        self.groupBox_3.setEnabled(False)
        self.groupBox_5.setEnabled(False)

        self.graphicsViewRec.setYRange(-20000, 20000, padding=0)
        self.graphicsViewRec.setXRange(0, 10 * 960 * 10, padding=0)
        self.graphicsViewRec.getPlotItem().hideButtons()
        self.graphicsViewRec.getPlotItem().hideAxis('left')
        self.graphicsViewRec.getPlotItem().hideAxis('bottom')

    def print_accuracy_graph(self, accuracy):
        self.accuracy_vals.append(accuracy)
        self.graphicsView.plot(self.accuracy_vals)

    def print_recording_graph(self, frames=None):
        self.graphicsViewRec.clear()
        self.recording_vals[0:9 * 960 *
                            10] = self.recording_vals[1 * 960 * 10:10 * 10 *
                                                      960]
        self.recording_vals[9 * 960 * 10:10 * 960 * 10] = frames
        self.graphicsViewRec.plot(self.recording_vals)

    def print_stats_model(self, string):
        self.print_in_label_7(string)

    def print_label_19(self, epoch):
        self.label_19.setText(epoch)

    def print_accuracy_matrix(self, matrix):
        for i in range(matrix.shape[0]):
            for j in range(matrix.shape[1]):
                self.tableWidget.setItem(
                    i, j, QtWidgets.QTableWidgetItem(str(matrix[i][j])))
        for i in range(4):
            self.tableWidget.setItem(
                4, i, QtWidgets.QTableWidgetItem(str(np.sum(matrix[:, i]))))
            self.tableWidget.setItem(
                i, 4, QtWidgets.QTableWidgetItem(str(np.sum(matrix[i]))))
        self.tableWidget.setItem(
            4, 4, QtWidgets.QTableWidgetItem(str(np.sum(np.diag(matrix)))))
        self.tableWidget.item(4, 4).setBackground(QtGui.QColor(102, 140, 255))
        self.tableWidget.item(3, 3).setBackground(QtGui.QColor(125, 125, 125))
        self.tableWidget.item(2, 2).setBackground(QtGui.QColor(125, 125, 125))
        self.tableWidget.item(1, 1).setBackground(QtGui.QColor(125, 125, 125))
        self.tableWidget.item(0, 0).setBackground(QtGui.QColor(125, 125, 125))
        for i in range(5):
            for j in range(5):
                self.tableWidget.item(i, j).setFlags(QtCore.Qt.ItemIsEnabled)

    def open_alert_dialog(self, title="Alert", text="...", info="..."):
        msg = QtWidgets.QMessageBox()
        msg.setIcon(QtWidgets.QMessageBox.Critical)

        msg.setWindowTitle(title)
        msg.setText(text)
        msg.setInformativeText(info)
        msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
        msg.exec_()

    def on_start_button_clicked(self):
        if self.radioButton.isChecked():  # training
            self.pushButton.setEnabled(False)
            self.pushButtonStop.setEnabled(True)
            self.radioButton_2.setEnabled(False)
            self.refresh_label_7()
            self.refresh_graphics_view()
            self.train_thread = Train_App(self)
            self.train_thread.print_accuracy_signal.connect(
                self.print_accuracy_graph)
            self.train_thread.print_stats.connect(self.print_stats_model)
            self.train_thread.print_matrix.connect(self.print_accuracy_matrix)
            self.train_thread.print_epoch.connect(self.print_label_19)
            self.train_thread.start()
        elif self.radioButton_2.isChecked():  # inference
            vals = self.ser_inference_model.inference(
                self.comboBox_2.currentText()) * 100
            self.progressBar.setValue(vals[0])
            self.progressBar_2.setValue(vals[1])
            self.progressBar_3.setValue(vals[2])
            self.progressBar_4.setValue(vals[3])
            self.print_in_label_7(str(list(map('{:.8f}'.format, vals))))
        pass

    def on_buttonStop_clicked(self):
        if self.train_thread != None:
            self.train_thread.stopFlag = True
        pass

    def change_label_16(self):
        self.label_16.setText(str(float(self.horizontalSlider_2.value()) / 10))

    def change_label_12(self):
        self.label_12.setText(str(float(self.horizontalSlider.value()) / 10))

    def change_label_ooda(self):
        self.label_ooda.setText(
            str(float(self.horizontalSlider_ooda.value()) / 10))

    def change_horizontal_ooda(self):
        if self.ooda_check_box.isChecked():
            self.horizontalSlider_ooda.setStyleSheet(SLYDER_ENABLED)
            self.horizontalSlider_ooda.setEnabled(True)
        else:
            self.horizontalSlider_ooda.setStyleSheet(SLYDER_DISABLED)
            self.horizontalSlider_ooda.setEnabled(False)
        self.label_ooda.setEnabled(self.ooda_check_box.isChecked())

    def fill_file(self):
        self.ser_inference_model.files = get_files_from_directory(
            self.lineEdit_2.text())
        self.comboBox_2.clear()
        for file in self.ser_inference_model.files:
            self.comboBox_2.addItem(file)
        if self.radioButton_2.isChecked():  # inference
            self.pushButton.setEnabled(True)
            self.pushButtonInfPlay.setEnabled(True)
            self.ser_inference_model.init_model(self.lineEdit_2.text())
            if self.ser_inference_model.model == None:
                self.open_alert_dialog(
                    title="Missing Inference inference_files Alert",
                    text=
                    "We could no find any inference_files to classify in the stated folder.",
                    info=
                    "You can continue the inference process by using the online model."
                )
                self.pushButton.setEnabled(False)
                self.pushButtonInfPlay.setEnabled(False)
            self.ser_online_model.init_online_model()

    def init_inference(self):
        if self.radioButton_2.isChecked():  # inference
            if self.radioButton_4.isChecked():
                self.open_alert_dialog(
                    title=
                    "Inference is not available for hand-crafted extraction",
                    text=
                    "Hand-crafted feature extraction is used only as a baseline.",
                    info=
                    "Please train your model using the end-to-ed extraction method in order to make inference available."
                )
                self.radioButton.setChecked(True)
                self.radioButton_2.setChecked(False)
                return
            if [f for f in os.listdir("model") if not f.startswith('.')] == []:
                self.open_alert_dialog(
                    title="Missing model for Inference",
                    text="There is no machine learning model to be loaded.",
                    info=
                    "Please use the training mode to train a model before inference."
                )
                self.radioButton.setChecked(True)
                self.radioButton_2.setChecked(False)
                return
            self.pushButtonRecord.setEnabled(True)
            self.pushButtonInfPlay.setEnabled(True)
            self.progressBar.setEnabled(True)
            self.progressBar_2.setEnabled(True)
            self.progressBar_3.setEnabled(True)
            self.progressBar_4.setEnabled(True)
            self.label_2.setEnabled(True)
            self.label_3.setEnabled(True)
            self.label_4.setEnabled(True)
            self.label_5.setEnabled(True)
            self.groupBox_3.setEnabled(True)
            self.groupBox_5.setEnabled(True)
            self.groupBox_2.setEnabled(False)
            self.horizontalSlider.setStyleSheet(SLYDER_DISABLED)
            self.horizontalSlider.setEnabled(False)
            self.horizontalSlider_2.setStyleSheet(SLYDER_DISABLED)
            self.horizontalSlider_2.setEnabled(False)
            self.horizontalSlider_ooda.setStyleSheet(SLYDER_DISABLED)
            self.horizontalSlider_ooda.setEnabled(False)
            self.ser_inference_model.init_model(self.lineEdit_2.text())
            if self.ser_inference_model.model == None:
                self.open_alert_dialog(
                    title="Missing Inference inference_files Alert",
                    text=
                    "We could no find any inference_files to classify in the stated folder.",
                    info=
                    "You can continue the inference process by using the online model."
                )
                self.pushButton.setEnabled(False)
                self.pushButtonInfPlay.setEnabled(False)
            self.ser_online_model.init_online_model()
        elif self.ser_inference_model.session != None and self.radioButton.isChecked(
        ):
            self.pushButton.setEnabled(True)
            self.groupBox_2.setEnabled(True)
            self.pushButtonRecord.setEnabled(False)
            self.pushButtonInfPlay.setEnabled(False)
            self.pushButtonStopRecord.setEnabled(False)
            self.progressBar.setValue(0)
            self.progressBar.setEnabled(False)
            self.progressBar_2.setValue(0)
            self.progressBar_2.setEnabled(False)
            self.progressBar_3.setValue(0)
            self.progressBar_3.setEnabled(False)
            self.progressBar_4.setValue(0)
            self.progressBar_4.setEnabled(False)
            self.label_2.setEnabled(False)
            self.label_3.setEnabled(False)
            self.label_4.setEnabled(False)
            self.label_5.setEnabled(False)
            self.groupBox_3.setEnabled(False)
            self.groupBox_5.setEnabled(False)
            self.horizontalSlider.setStyleSheet(SLYDER_ENABLED)
            self.horizontalSlider.setEnabled(True)
            self.horizontalSlider_2.setStyleSheet(SLYDER_ENABLED)
            self.horizontalSlider_2.setEnabled(True)
            self.change_horizontal_ooda()
            self.ser_inference_model.close_model()

    def on_buttonRecord_clicked(self):
        self.refresh_rec_graphics_view()
        self.microphone_recorder = MicrophoneRecorder()
        if not self.microphone_recorder.check_device_availability():
            return
        self.recorder_thread = Record_App(self, self.microphone_recorder)
        self.recorder_thread.print_recording_signal.connect(
            self.print_recording_graph)
        self.recorder_thread.start()
        self.pushButtonStopRecord.setEnabled(True)
        self.pushButton.setEnabled(False)
        self.pushButtonInfPlay.setEnabled(False)
        self.pushButtonPlay.setEnabled(False)

    def on_buttonStopRecord_clicked(self):
        import librosa
        import pyaudio
        self.microphone_recorder.close()
        vals = []
        if np.array(self.microphone_recorder.get_frames()).shape[0] > 30:
            self.pushButtonPlay.setEnabled(True)
            self.microphone_recorder.save_to_wav()
            frames, _ = librosa.load("output.wav", 16000)
            vals = self.ser_online_model.online(frames, 44100) * 100
        else:
            self.pushButtonPlay.setEnabled(False)
            vals = [0 for _ in range(4)]
        self.progressBar.setValue(vals[0])
        self.progressBar_2.setValue(vals[1])
        self.progressBar_3.setValue(vals[2])
        self.progressBar_4.setValue(vals[3])
        self.print_in_label_7(str(list(map('{:.8f}'.format, vals))))
        self.pushButton.setEnabled(True)
        self.pushButtonRecord.setEnabled(True)
        self.pushButtonStopRecord.setEnabled(False)
        self.pushButtonInfPlay.setEnabled(True)
        self.pushButtonPlay.setEnabled(True)

    def print_in_label_7(self, str):
        _translate = QtCore.QCoreApplication.translate
        self.label_7_line_nr += 1
        if self.label_7_line_nr >= 24:
            txt = self.label_7.text().split("<html>")
            txt = "<html>".join(txt[1:25])
            self.label_7.setText(
                _translate(
                    "MainWindow", txt +
                    "<html><head/><body><span style=\" font-weight:600; color:#55ff7f;\">"
                    + str + "</span></body></html>"))
        else:
            self.label_7.setText(
                _translate(
                    "MainWindow",
                    self.label_7.text() +
                    "<html><head/><body><span style=\" font-weight:600; color:#55ff7f;\">"
                    + str + "</span></body></html>"))
        import time

    def play_recording(self, file="output.wav"):
        self.play_th = Play_App(self, file)
        self.play_th.start()
Beispiel #26
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        print('setup g')
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1021, 839)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(330, 20, 371, 51))
        self.label.setObjectName("label")
        self.lineEditPuerto = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEditPuerto.setGeometry(QtCore.QRect(360, 180, 271, 31))
        self.lineEditPuerto.setObjectName("lineEditPuerto")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(380, 120, 241, 31))
        self.label_2.setObjectName("label_2")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(460, 250, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.graphicsView = PlotWidget(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(40, 310, 961, 481))
        self.graphicsView.setObjectName("graphicsView")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1021, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        
        self.hilo1 = Hilo1(self.lineEditPuerto.text())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.pushButton.clicked.connect(self.graficar)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-size:18pt;\">Bienvenido a ECGPythonProcessing</span></p></body></html>"))
        self.label_2.setText(_translate("MainWindow", "Ingrese el puerto por donde se leeran los datos:"))
        self.pushButton.setText(_translate("MainWindow", "Iniciar"))
        
    def graficar(self):
        print('holi')
        mensaje = QtWidgets.QMessageBox()
        if(len(self.lineEditPuerto.text()) == 0):
            mensaje.about(mensaje,'Error',"El puerto no puede quedar vacio")
        else:
            self.iniciar()
            
            
         
    def update(self,valor):
        global curva,data
        try:
            data.append(float(valor))
            self.lecturas.append(float(valor))
            if(len(self.lecturas)==512):
                try:
                    print(self.lecturas)
                    publish.single("paciente/1", str(self.lecturas), hostname="10.3.0.6")
                    self.lecturas = []
                except Exception as e:
                    print(e)
                    self.lecturas = []
            xdata = np.array(data,dtype="float64")
            curva.setData(xdata)
            QtGui.QApplication.instance().processEvents()
        except Exception as e:
            print(e)
        
    def iniciar(self):
        global curva,data
        print('iniciar')
        data = [0]
        self.lecturas=[]
        curva = self.graphicsView.getPlotItem().plot()
        self.hilo1.start()
        timer = QtCore.QTimer(self.graphicsView)
        timer.timeout.connect(self.update)
        timer.start(10)
        print("Antes")
        QtGui.QApplication.instance().allWidgets()
        print("Despues")
Beispiel #27
0
class MCClassroom(QWidget):
    def __init__(self, settings, server):
        super().__init__()

        self.server = server
        self.timer = QTimer()
        self.timer.timeout.connect(self.time_tick)

        self.settings = settings
        self.current_class = None
        self.current_students = []

        self.stack = QStackedLayout()
        self.setLayout(self.stack)

        # First page: connection instructions
        connect_widget = QWidget()
        connect_layout = QVBoxLayout(connect_widget)
        connect_layout.addStretch()
        connect_label = QLabel(
            "Open a world in Minecraft, open a terminal (press t), and type:",
            self)
        connect_layout.addWidget(connect_label)
        self.connect_command = f'/connect {server.get_ip()}:{PORT}'
        connect_command_box = QLineEdit(self.connect_command, self)
        connect_command_box.setReadOnly(True)
        connect_layout.addWidget(connect_command_box)
        connect_copy_button = QPushButton("Copy to Clipboard", self)
        connect_copy_button.clicked.connect(
            lambda: QApplication.clipboard().setText(self.connect_command))
        connect_layout.addWidget(connect_copy_button)
        connection_problems_button = QPushButton("Connection Problems?", self)
        connection_problems_button.clicked.connect(self.show_connection_help)
        connect_layout.addWidget(connection_problems_button)
        connect_layout.addStretch()
        self.stack.addWidget(connect_widget)

        # Main page
        main_col_widget = QWidget()
        columns = QHBoxLayout(main_col_widget)
        col_left = QVBoxLayout()
        col_mid = QVBoxLayout()
        col_right = QVBoxLayout()
        columns.addLayout(col_left)
        columns.addSpacing(10)
        columns.addLayout(col_mid)
        columns.addSpacing(10)
        columns.addLayout(col_right)
        self.stack.addWidget(main_col_widget)

        self.pause_button = self.setup_toggle_button(col_left,
                                                     self.server.pause_game,
                                                     'Un-pause',
                                                     self.server.unpause_game,
                                                     'Pause')
        button_size = self.pause_button.size()
        self.disable_chat_button = self.setup_toggle_button(
            col_left, self.server.disable_chat, 'Enable Chat',
            self.server.enable_chat, 'Disable Chat', button_size)
        self.allow_mobs_button = self.setup_toggle_button(
            col_left, self.server.disallow_mobs, 'Allow Mobs',
            self.server.allow_mobs, 'Disable Mobs', button_size)
        self.allow_destructiveobjects_button = self.setup_toggle_button(
            col_left, self.server.disallow_destructiveobjects,
            'Enable Destructive Items', self.server.allow_destructiveobjects,
            'Disable Destructive Items', button_size)
        self.allow_player_damage_button = self.setup_toggle_button(
            col_left, self.server.disallow_player_damage,
            'Enable Player Damage', self.server.allow_player_damage,
            'Disable Player Damage', button_size)
        self.allow_pvp_button = self.setup_toggle_button(
            col_left, self.server.disallow_pvp, 'Allow Player Fighting',
            self.server.allow_pvp, 'Disable Player Fighting', button_size)
        self.immutable_button = self.setup_toggle_button(
            col_left, self.server.immutable_world,
            'Enable World Modifications', self.server.mutable_world,
            'Disable World Modifications', button_size)
        self.weather_button = self.setup_toggle_button(
            col_left, self.server.perfect_weather, 'Disable Perfect Weather',
            self.server.imperfect_weather, 'Enable Perfect Weather',
            button_size)
        self.disable_potions_button = self.setup_toggle_button(
            col_left, self.server.disable_potions, 'Enable Potions',
            self.server.enable_potions, 'Disable Potions', button_size)

        # self.clear_potions_button = QPushButton('Clear All Potion Effects', self)
        # self.clear_potions_button.resize(button_size)
        # self.clear_potions_button.clicked.connect(lambda: self.server.clear_effects("@a"))
        # col_left.addWidget(self.clear_potions_button)

        self.teleport_button = QPushButton('Teleport Everyone to You', self)
        self.teleport_button.resize(button_size)
        self.teleport_button.clicked.connect(
            lambda: self.server.teleport_all_to("@s"))
        col_left.addWidget(self.teleport_button)

        self.disconnect_button = QPushButton('Disconnect', self)
        self.disconnect_button.resize(button_size)
        self.disconnect_button.clicked.connect(self.server.socket_disconnected)
        col_left.addWidget(self.disconnect_button)

        col_left.addStretch()

        self.version_label = QLabel(f'Version {VERSION}', self)
        self.version_label.setAlignment(Qt.AlignCenter)
        col_left.addWidget(self.version_label)

        self.feedback_button = QPushButton('Feedback/Bug report', self)
        self.feedback_button.resize(button_size)
        self.feedback_button.clicked.connect(
            lambda: QDesktopServices.openUrl(FEEDBACK_URL))
        col_left.addWidget(self.feedback_button)

        # Middle Column: Roll/Register
        self.classes_combo = QComboBox(self)
        class_names = self.settings.value("class_names", [])
        self.classes_combo.addItem("Select class")
        self.classes_combo.addItem("Add a class")
        self.classes_combo.addItem("Delete a class")
        self.classes_combo.addItems(class_names)
        self.classes_combo.currentTextChanged.connect(self.class_changed)
        col_mid.addWidget(self.classes_combo)

        self.users_table = QTableWidget(0, 2)
        self.users_table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.users_table.setSizePolicy(
            QSizePolicy(QSizePolicy.Minimum, QSizePolicy.MinimumExpanding))
        self.users_table.setFixedWidth(140)
        self.users_table.verticalHeader().hide()
        header = self.users_table.horizontalHeader()
        header.setSectionResizeMode(0, QHeaderView.Stretch)
        header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
        header.hide()
        col_mid.addWidget(self.users_table)

        self.class_edit_button = QPushButton("Edit Class", self)
        col_mid.addWidget(self.class_edit_button)
        self.class_edit_button.clicked.connect(self.edit_class)

        self.chat_box = QPlainTextEdit(
            f'Minecraft Education Chat Logs {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}',
            self)
        self.chat_box.setReadOnly(True)
        col_right.addWidget(self.chat_box)

        self.chat_input = QLineEdit(self)
        self.chat_input.setPlaceholderText("Type chat here; enter to send")
        self.chat_input.returnPressed.connect(self.chat_enter)
        col_right.addWidget(self.chat_input)

        self.chat_save = QPushButton("Save Chat Logs", self)
        self.chat_save.clicked.connect(self.save_chat)
        col_right.addWidget(self.chat_save)

        self.user_map = PlotWidget()
        self.map_item = ScatterPlotItem(size=10)
        self.user_map.addItem(self.map_item)
        self.user_map.getPlotItem().hideAxis('left')
        self.user_map.getPlotItem().hideAxis('bottom')
        self.map_item.scene().sigMouseMoved.connect(self.map_hover)
        map_viewbox = self.map_item.getViewBox()
        map_viewbox.menu = None
        col_right.addWidget(self.user_map)

        self.user_map_info = QLineEdit("Hover over a user", self)
        self.user_map_info.setReadOnly(True)
        col_right.addWidget(self.user_map_info)

        self.setGeometry(300, 300, 800, 600)
        self.setWindowTitle('MineClass')

        self.stack.setCurrentIndex(0)
        self.activate_buttons(False)
        self.show()

        if is_newer_version_available():
            QMessageBox.about(
                self, "Newer Version Available",
                f'A newer version of this program is available <a href="{GITHUB_DOWNLOAD_URL}">here</a>.'
            )

        if not self.settings.value("HasRunFirstTime", False):
            self.show_connection_help()
            self.settings.setValue("HasRunFirstTime", True)

    def show_connection_help(self):
        QMessageBox.about(
            self, "Connection Help",
            '''Before using (or if Minecraft has been newly installed), go to Settings->Profile and disable "Require Encrypted Websockets"\n\n
Sometimes you'll need to attempt connecting twice (use the up arrow in the Minecraft terminal to access history'''
        )

    def save_chat(self):
        options = QFileDialog.Options()
        file_name, _ = QFileDialog.getSaveFileName(
            self,
            "Save Chat Logs",
            "",
            "Text Files (*.txt);;All Files (*)",
            options=options)
        if file_name:
            with open(file_name, "w") as f:
                f.write(self.chat_box.toPlainText())

    def chat_enter(self):
        server.send_chat(self.chat_input.text())
        self.update_chat_box("Teacher", self.chat_input.text(), "chat")
        self.chat_input.clear()

    def map_hover(self, pos):
        act_pos = self.map_item.mapFromScene(pos)
        points = self.map_item.pointsAt(act_pos)

        text = ""
        for p in points:
            text += f'{p.data()}: ({round(p.pos()[0])}, {round(p.pos()[1])}), '
        self.user_map_info.setText(text)

    def time_tick(self):
        self.server.get_users()

    def start_timer(self):
        self.time_tick()
        self.timer.start(10000)

    def stop_timer(self):
        self.timer.stop()

    def update_chat_box(self, sender, message, message_type, receiver=None):
        t = datetime.datetime.now().strftime("%H:%M:%S")
        if message_type == "chat":
            out = f'{t} <{sender}> {message}'
        elif message_type == "tell":
            out = f'{t} <{sender} whispers to {receiver}> {message}'
        self.chat_box.appendPlainText(out)

    def activate_buttons(self, activate):
        self.pause_button.setDisabled(not activate)

    def setup_toggle_button(self,
                            parent,
                            checked_action,
                            checked_text,
                            unchecked_action,
                            unchecked_text,
                            size=None):
        button = QPushButton(unchecked_text, self)
        button.resize(button.sizeHint() if size is None else size)
        button.setCheckable(True)
        parent.addWidget(button)

        def toggle_button_clicked(checked_status):
            if checked_status:
                checked_action()
                button.setText(checked_text)
            else:
                unchecked_action()
                button.setText(unchecked_text)

        button.toggled.connect(toggle_button_clicked)
        return button

    def get_students_from_grid(self):
        try:
            return [
                self.users_table.item(i, 0).text()
                for i in range(self.users_table.rowCount())
            ]
        except AttributeError:
            return []

    def edit_class(self):
        selection = self.classes_combo.currentText()
        if selection in ("Select class", "Add a class"):
            QMessageBox.about(self, "Error",
                              "Please select (or create) a class first")
            return

        current_list = self.get_students_from_grid()
        new_list, ok_pressed = QInputDialog().getMultiLineText(
            self,
            "Edit Class List",
            "Add or remove students from this class",
            text="\n".join(current_list))
        if ok_pressed:
            students = [i for i in new_list.split("\n")
                        if i]  # list comprehension to remove empty strings
            self.current_students = students
            self.settings.setValue(f'classes/{self.current_class}', students)
            self.load_users()

    def class_changed(self):
        selection = self.classes_combo.currentText()
        # if selection != "Select class":
        #     self.classes_combo.removeItem(self.classes_combo.findText("Select class"))
        if selection == "Add a class":
            new_class, ok_pressed = QInputDialog.getText(
                self, 'Class Name', 'Enter the Class Name or Code')
            if ok_pressed:
                classes = self.settings.value('class_names', [])
                if new_class in classes:
                    print('Class already exists; ignoring')
                else:
                    classes.append(new_class)
                    self.settings.setValue('class_names', classes)
                    self.classes_combo.addItem(new_class)
                self.classes_combo.setCurrentIndex(
                    self.classes_combo.findText(new_class))
        elif selection == "Select class":
            pass
        elif selection == "Delete a class":
            current_classes = self.settings.value('class_names', [])
            if current_classes:
                class_to_delete, ok_pressed = QInputDialog.getItem(
                    self, 'Delete Class', 'Select which class to delete',
                    current_classes, 0, False)
                if ok_pressed and class_to_delete:
                    current_classes.remove(class_to_delete)
                    self.settings.setValue('class_names', current_classes)
                    self.settings.remove(f'classes/{class_to_delete}')
                    self.classes_combo.removeItem(
                        self.classes_combo.findText(class_to_delete))
                    #TODO delete stdents from table
                    self.current_class = None
                    self.current_students = []
            else:
                QMessageBox.information(self, "No Classes!",
                                        "No Class to delete!")
            self.classes_combo.setCurrentIndex(0)
        else:
            self.current_class = selection
            self.current_students = self.settings.value(
                f'classes/{selection}', [])
            self.load_users()

    def load_users(self):
        if len(self.current_students) != self.users_table.rowCount():
            self.users_table.setRowCount(len(self.current_students))
        for i, user in enumerate(self.current_students):
            self.users_table.setItem(i, 0, QTableWidgetItem(user))
        self.users_table.sortItems(0, QtCore.Qt.AscendingOrder)
        self.users_table.sortItems(1, QtCore.Qt.DescendingOrder)

    def update_users_from_mc(self, users):
        table_user_count = self.users_table.rowCount()
        for i in range(table_user_count):
            current_table_user = self.users_table.item(i, 0).text()
            if current_table_user in users:
                tick = QTableWidgetItem("✓")
                tick.setTextAlignment(QtCore.Qt.AlignCenter)
                tick.setBackground(QColor(QtCore.Qt.green))
                self.users_table.setItem(i, 1, tick)
                users.remove(current_table_user)
            else:
                cross = QTableWidgetItem("✗")
                cross.setTextAlignment(QtCore.Qt.AlignCenter)
                cross.setBackground(QColor(QtCore.Qt.red))
                self.users_table.setItem(i, 1, cross)

        #handle users from server but not in table
        self.users_table.setRowCount(table_user_count + len(users))
        for i, user in enumerate(users):
            self.users_table.setItem(i + table_user_count, 0,
                                     QTableWidgetItem(user))

        self.users_table.sortItems(0, QtCore.Qt.AscendingOrder)
        self.users_table.sortItems(1, QtCore.Qt.DescendingOrder)
        self.users_table.resizeRowsToContents()

    def update_map(self, users):
        data = [
            {
                'pos': (int(u['position']['x']), int(u['position']['z'])),
                'data': u['name'],
                'brush': mkBrush(
                    'g'
                ),  #mkBrush("r" if u['name'] == self.server.self_name else "g"),
                'symbol': ("s" if u['name'] == self.server.self_name else "o"),
            } for u in users.values()
        ]
        self.map_item.setData(data)
Beispiel #28
0
class CallRatePlotWidget(QWidget):
    WWHD_FPS_ESTIMATE = 30

    def __init__(self, parent: QWidget = None):
        super().__init__(parent)
        self._backlog_length = 0
        self._display_as_fps = False
        self._main_layout = QVBoxLayout()
        self._plot_controls_hbox = QHBoxLayout()
        self._plot_controls_hbox.addWidget(QLabel('Show Latest N Seconds:'))
        self._backlog_time_edit = QLineEdit()
        self._backlog_time_edit.textChanged.connect(
            self._handle_backlog_time_changed)
        self._backlog_time_edit.setFixedWidth(40)
        self._plot_controls_hbox.addWidget(self._backlog_time_edit)
        self._plot_controls_hbox.addWidget(
            QLabel('Show as Calls/Frame (estimated):'))
        self._fps_display_checkbox = QCheckBox()
        self._fps_display_checkbox.stateChanged.connect(
            self._handle_fps_display_changed)
        self._plot_controls_hbox.addWidget(self._fps_display_checkbox)
        self._plot_controls_hbox.addStretch()
        self._main_layout.addLayout(self._plot_controls_hbox)
        self._rate_plot_widget = PlotWidget()
        self._rate_plot_item = self._rate_plot_widget.getPlotItem()
        self._rate_plot_item.setTitle('RNG Call Rate')
        self._rate_plot_item.setLabels(left='Call Rate [Calls/sec]',
                                       bottom='Time [s]')
        self._rate_plot = self._rate_plot_item.plot(antialias=False)
        self._main_layout.addWidget(self._rate_plot_widget)
        self._total_plot_widget = PlotWidget()
        self._total_plot_item = self._total_plot_widget.getPlotItem()
        self._total_plot_item.setTitle('Total RNG Calls')
        self._total_plot_item.setLabels(left='Total RNG Calls',
                                        bottom='Time [s]')
        self._total_plot = self._total_plot_item.plot()
        self._main_layout.addWidget(self._total_plot_widget)
        self._buffer = CircularFloatBuffer(3, maxlen=10000)
        self._start_time = time.perf_counter()
        self.setLayout(self._main_layout)

    def append_new_call_data(self, steps_taken, last_second_avg, total_steps):
        time_elapsed = time.perf_counter() - self._start_time
        self._buffer.append([time_elapsed, last_second_avg, total_steps])
        time_base = self._buffer.get_all_for_channel(0)
        avg_data = self._buffer.get_all_for_channel(1)
        total_data = self._buffer.get_all_for_channel(2)
        if self._display_as_fps:
            avg_data = avg_data / self.WWHD_FPS_ESTIMATE
        if self._backlog_length > 0:
            backlog_index = (time_base > (time_elapsed - self._backlog_length))
            time_base = time_base[backlog_index]
            avg_data = avg_data[backlog_index]
            total_data = total_data[backlog_index]
        self._rate_plot.setData(time_base, avg_data)
        self._total_plot.setData(time_base, total_data)

    def _handle_backlog_time_changed(self, new_text: str):
        if len(new_text) == 0:
            self._backlog_length = 0
        try:
            new_backlog_length = int(new_text)
        except (ValueError, TypeError):
            return
        if new_backlog_length <= 0:
            return
        self._backlog_length = new_backlog_length

    def _handle_fps_display_changed(self, state: int):
        if state == Qt.Unchecked:
            self._display_as_fps = False
            self._rate_plot_item.setLabels(left='Call Rate [Calls/sec]')
        elif state == Qt.Checked:
            self._display_as_fps = True
            self._rate_plot_item.setLabels(left='Call Rate [Calls/frame]')

    def clear_plots(self):
        self._buffer.clear()
Beispiel #29
0
class BusMonitorWidget(QGroupBox):
    DEFAULT_PLOT_X_RANGE = 120
    BUS_LOAD_PLOT_MAX_SAMPLES = 5000

    def __init__(self, parent, node, iface_name):
        super(BusMonitorWidget, self).__init__(parent)
        self.setTitle('CAN bus activity (%s)' % iface_name.split(os.path.sep)[-1])

        self._node = node
        self._hook_handle = self._node.can_driver.add_io_hook(self._frame_hook)

        self._columns = [
            BasicTable.Column('Dir',
                              lambda e: (e[0].upper()),
                              searchable=False),
            BasicTable.Column('Local Time', TimestampRenderer(), searchable=False),
            BasicTable.Column('CAN ID',
                              lambda e: (('%0*X' % (8 if e[1].extended else 3, e[1].id)).rjust(8),
                                         colorize_can_id(e[1]))),
            BasicTable.Column('Data Hex',
                              lambda e: (' '.join(['%02X' % x for x in e[1].data]).ljust(3 * e[1].MAX_DATA_LENGTH),
                                         colorize_transfer_id(e))),
            BasicTable.Column('Data ASCII',
                              lambda e: (''.join([(chr(x) if 32 <= x <= 126 else '.') for x in e[1].data]),
                                         colorize_transfer_id(e))),
            BasicTable.Column('Src',
                              lambda e: render_node_id_with_color(e[1], 'src')),
            BasicTable.Column('Dst',
                              lambda e: render_node_id_with_color(e[1], 'dst')),
            BasicTable.Column('Data Type',
                              lambda e: render_data_type_with_color(e[1]),
                              resize_mode=QHeaderView.Stretch),
        ]

        self._log_widget = RealtimeLogWidget(self, columns=self._columns, font=get_monospace_font(),
                                             post_redraw_hook=self._redraw_hook)
        self._log_widget.on_selection_changed = self._update_measurement_display

        def flip_row_mark(row, col):
            if col == 0:
                item = self._log_widget.table.item(row, col)
                if item.icon().isNull():
                    item.setIcon(get_icon('circle'))
                    flash(self, 'Row %d was marked, click again to unmark', row, duration=3)
                else:
                    item.setIcon(QIcon())

        self._log_widget.table.cellPressed.connect(flip_row_mark)

        self._stat_update_timer = QTimer(self)
        self._stat_update_timer.setSingleShot(False)
        self._stat_update_timer.timeout.connect(self._update_stat)
        self._stat_update_timer.start(500)

        self._traffic_stat = TrafficStatCounter()

        self._stat_frames_tx = QLabel('N/A', self)
        self._stat_frames_rx = QLabel('N/A', self)
        self._stat_traffic = QLabel('N/A', self)

        self._load_plot = PlotWidget(background=(0, 0, 0))
        self._load_plot.setRange(xRange=(0, self.DEFAULT_PLOT_X_RANGE), padding=0)
        self._load_plot.setMaximumHeight(150)
        self._load_plot.setMinimumHeight(100)
        self._load_plot.setMinimumWidth(100)
        self._load_plot.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self._load_plot.showGrid(x=True, y=True, alpha=0.4)
        self._load_plot.setToolTip('Frames per second')
        self._load_plot.getPlotItem().getViewBox().setMouseEnabled(x=True, y=False)
        self._load_plot.enableAutoRange()
        self._bus_load_plot = self._load_plot.plot(name='Frames per second', pen=mkPen(QColor(Qt.lightGray), width=1))
        self._bus_load_samples = [], []
        self._started_at_mono = time.monotonic()

        layout = QVBoxLayout(self)

        layout.addWidget(self._log_widget, 1)

        stat_vars_layout = QGridLayout(self)
        stat_layout_next_row = 0

        def add_stat_row(label, value):
            nonlocal stat_layout_next_row
            stat_vars_layout.addWidget(QLabel(label, self), stat_layout_next_row, 0)
            stat_vars_layout.addWidget(value, stat_layout_next_row, 1)
            value.setMinimumWidth(75)
            stat_layout_next_row += 1

        add_stat_row('Frames transmitted:', self._stat_frames_tx)
        add_stat_row('Frames received:', self._stat_frames_rx)
        add_stat_row('Frames per second:', self._stat_traffic)
        stat_vars_layout.setRowStretch(stat_layout_next_row, 1)

        stat_layout = QHBoxLayout(self)
        stat_layout.addLayout(stat_vars_layout)
        stat_layout.addWidget(self._load_plot, 1)

        layout.addLayout(stat_layout, 0)
        self.setLayout(layout)

    def close(self):
        self._hook_handle.remove()

    def _update_stat(self):
        bus_load, ts_mono = self._traffic_stat.get_frames_per_second()
        self._stat_traffic.setText(str(int(bus_load + 0.5)))

        if len(self._bus_load_samples[0]) >= self.BUS_LOAD_PLOT_MAX_SAMPLES:
            self._bus_load_samples[0].pop(0)
            self._bus_load_samples[1].pop(0)

        self._bus_load_samples[1].append(bus_load)
        self._bus_load_samples[0].append(ts_mono - self._started_at_mono)

        self._bus_load_plot.setData(*self._bus_load_samples)

        (xmin, xmax), _ = self._load_plot.viewRange()
        diff = xmax - xmin
        xmax = self._bus_load_samples[0][-1]
        xmin = self._bus_load_samples[0][-1] - diff
        self._load_plot.setRange(xRange=(xmin, xmax), padding=0)

    def _redraw_hook(self):
        self._stat_frames_tx.setText(str(self._traffic_stat.tx))
        self._stat_frames_rx.setText(str(self._traffic_stat.rx))

    def _frame_hook(self, direction, frame):
        self._traffic_stat.add_frame(direction, frame)
        self._log_widget.add_item_async((direction, frame))

    def _update_measurement_display(self, selected_rows_cols):
        if not selected_rows_cols:
            return

        min_row = min([row for row, _ in selected_rows_cols])
        max_row = max([row for row, _ in selected_rows_cols])

        def get_row_ts(row):
            return TimestampRenderer.parse_timestamp(self._log_widget.table.item(row, 1).text())

        def get_load_str(num_frames, dt):
            if dt >= 1e-6:
                return 'average load %.1f FPS' % (num_frames / dt)
            return 'average load is unknown'

        if min_row == max_row:
            num_frames = min_row
            first_ts = get_row_ts(0)
            current_ts = get_row_ts(min_row)
            dt = current_ts - first_ts
            flash(self, '%d frames from beginning, %.3f sec since first frame, %s',
                  num_frames, dt, get_load_str(num_frames, dt))
        else:
            num_frames = max_row - min_row + 1
            first_ts = get_row_ts(min_row)
            last_ts = get_row_ts(max_row)
            dt = last_ts - first_ts
            flash(self, '%d frames, timedelta %.6f sec, %s',
                  num_frames, dt, get_load_str(num_frames, dt))
Beispiel #30
0
class CamViewer(Display):
    #Emitted when the user changes the value.
    roi_x_signal = pyqtSignal(str)
    roi_y_signal = pyqtSignal(str)
    roi_w_signal = pyqtSignal(str)
    roi_h_signal = pyqtSignal(str)

    def __init__(self, display_manager_window):
        super(CamViewer, self).__init__(display_manager_window)

        #Set up the list of cameras, and all the PVs
        vcc_dict = {
            "image": "ca://CAMR:IN20:186:IMAGE",
            "max_width": "ca://CAMR:IN20:186:N_OF_COL",
            "max_height": "ca://CAMR:IN20:186:N_OF_ROW",
            "roi_x": None,
            "roi_y": None,
            "roi_width": None,
            "roi_height": None
        }
        c_iris_dict = {
            "image": "ca://CAMR:LR20:119:Image:ArrayData",
            "max_width": "ca://CAMR:LR20:119:MaxSizeX_RBV",
            "max_height": "ca://CAMR:LR20:119:MaxSizeY_RBV",
            "roi_x": "ca://CAMR:LR20:119:MinX",
            "roi_y": "ca://CAMR:LR20:119:MinY",
            "roi_width": "ca://CAMR:LR20:119:SizeX",
            "roi_height": "ca://CAMR:LR20:119:SizeY"
        }
        test_dict = {
            "image": "ca://MTEST:Image",
            "max_width": "ca://MTEST:ImageWidth",
            "max_height": "ca://MTEST:ImageWidth",
            "roi_x": None,
            "roi_y": None,
            "roi_width": None,
            "roi_height": None
        }
        self.cameras = {
            "VCC": vcc_dict,
            "C-Iris": c_iris_dict,
            "Test": test_dict
        }
        self._channels = []

        #Populate the camera combo box
        self.ui.cameraComboBox.clear()
        for camera in self.cameras:
            self.ui.cameraComboBox.addItem(camera)

        #Clear out any image data, reset width, get PVs ready for connection
        self.initializeCamera(self.ui.cameraComboBox.currentText())

        #When the camera combo box changes, disconnect from PVs, re-initialize, then reconnect.
        self.ui.cameraComboBox.activated[str].connect(self.cameraChanged)

        #Set up the color map combo box.
        self.ui.colorMapComboBox.clear()
        for map_name in self.ui.imageView.color_maps:
            self.ui.colorMapComboBox.addItem(map_name)
        self.ui.imageView.setColorMapToPreset(
            self.ui.colorMapComboBox.currentText())
        self.ui.colorMapComboBox.activated[str].connect(self.colorMapChanged)

        #Set up the color map limit sliders and line edits.
        #self._color_map_limit_sliders_need_config = True
        self.ui.colorMapMinSlider.valueChanged.connect(self.setColorMapMin)
        self.ui.colorMapMaxSlider.valueChanged.connect(self.setColorMapMax)
        self.ui.colorMapMinLineEdit.returnPressed.connect(
            self.colorMapMinLineEditChanged)
        self.ui.colorMapMaxLineEdit.returnPressed.connect(
            self.colorMapMaxLineEditChanged)

        #Set up the stuff for single-shot and average modes.
        self.ui.singleShotRadioButton.setChecked(True)
        self._average_mode_enabled = False
        self.ui.singleShotRadioButton.clicked.connect(
            self.enableSingleShotMode)
        self.ui.averageRadioButton.clicked.connect(self.enableAverageMode)
        self.ui.numShotsLineEdit.returnPressed.connect(self.numAverageChanged)

        #Add a plot for vertical lineouts
        self.yLineoutPlot = PlotWidget()
        self.yLineoutPlot.setMaximumWidth(80)
        self.yLineoutPlot.setSizePolicy(QSizePolicy.Minimum,
                                        QSizePolicy.Expanding)
        self.yLineoutPlot.getPlotItem().invertY()
        self.yLineoutPlot.hideAxis('bottom')
        #self.yLineoutPlot.setYLink(self.ui.imageView.getView())
        self.ui.imageGridLayout.addWidget(self.yLineoutPlot, 0, 0)
        self.yLineoutPlot.hide()
        #We do some mangling of the .ui file here and move the imageView over a cell, kind of ugly.
        self.ui.imageGridLayout.removeWidget(self.ui.imageView)
        self.ui.imageGridLayout.addWidget(self.ui.imageView, 0, 1)

        #Add a plot for the horizontal lineouts
        self.xLineoutPlot = PlotWidget()
        self.xLineoutPlot.setMaximumHeight(80)
        self.xLineoutPlot.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Minimum)
        self.xLineoutPlot.hideAxis('left')
        #self.xLineoutPlot.setXLink(self.ui.imageView.getView())
        self.ui.imageGridLayout.addWidget(self.xLineoutPlot, 1, 1)
        self.xLineoutPlot.hide()

        #Update the lineout plot ranges when the image gets panned or zoomed
        self.ui.imageView.getView().sigRangeChanged.connect(
            self.updateLineoutRange)

        #Instantiate markers.
        self.marker_dict = {1: {}, 2: {}, 3: {}, 4: {}}
        marker_size = QPointF(20., 20.)
        self.marker_dict[1]['marker'] = ImageMarker((0, 0),
                                                    size=marker_size,
                                                    pen=mkPen((100, 100, 255),
                                                              width=3))
        self.marker_dict[1]['button'] = self.ui.marker1Button
        self.marker_dict[1]['xlineedit'] = self.ui.marker1XPosLineEdit
        self.marker_dict[1]['ylineedit'] = self.ui.marker1YPosLineEdit

        self.marker_dict[2]['marker'] = ImageMarker((0, 0),
                                                    size=marker_size,
                                                    pen=mkPen((255, 100, 100),
                                                              width=3))
        self.marker_dict[2]['button'] = self.ui.marker2Button
        self.marker_dict[2]['xlineedit'] = self.ui.marker2XPosLineEdit
        self.marker_dict[2]['ylineedit'] = self.ui.marker2YPosLineEdit

        self.marker_dict[3]['marker'] = ImageMarker((0, 0),
                                                    size=marker_size,
                                                    pen=mkPen((60, 255, 60),
                                                              width=3))
        self.marker_dict[3]['button'] = self.ui.marker3Button
        self.marker_dict[3]['xlineedit'] = self.ui.marker3XPosLineEdit
        self.marker_dict[3]['ylineedit'] = self.ui.marker3YPosLineEdit

        self.marker_dict[4]['marker'] = ImageMarker((0, 0),
                                                    size=marker_size,
                                                    pen=mkPen((255, 60, 255),
                                                              width=3))
        self.marker_dict[4]['button'] = self.ui.marker4Button
        self.marker_dict[4]['xlineedit'] = self.ui.marker4XPosLineEdit
        self.marker_dict[4]['ylineedit'] = self.ui.marker4YPosLineEdit
        #Disable auto-ranging the image (it feels strange when the zoom changes as you move markers around.)
        self.ui.imageView.getView().disableAutoRange()
        for d in self.marker_dict:
            marker = self.marker_dict[d]['marker']
            marker.setZValue(20)
            marker.hide()
            marker.sigRegionChanged.connect(self.markerMoved)
            self.ui.imageView.getView().addItem(marker)
            self.marker_dict[d]['button'].toggled.connect(self.enableMarker)
            curvepen = QPen(marker.pen)
            curvepen.setWidth(1)
            self.marker_dict[d]['xcurve'] = self.xLineoutPlot.plot(
                pen=curvepen)
            self.marker_dict[d]['ycurve'] = self.yLineoutPlot.plot(
                pen=curvepen)
            self.marker_dict[d]['xlineedit'].returnPressed.connect(
                self.markerPositionLineEditChanged)
            self.marker_dict[d]['ylineedit'].returnPressed.connect(
                self.markerPositionLineEditChanged)

        #Set up zoom buttons
        self.ui.zoomInButton.clicked.connect(self.zoomIn)
        self.ui.zoomOutButton.clicked.connect(self.zoomOut)
        self.ui.zoomToActualSizeButton.clicked.connect(self.zoomToActualSize)

        #Set up ROI buttons
        self.ui.setROIButton.clicked.connect(self.setROI)
        self.ui.resetROIButton.clicked.connect(self.resetROI)

    @pyqtSlot()
    def zoomIn(self):
        self.ui.imageView.getView().scaleBy((0.5, 0.5))

    @pyqtSlot()
    def zoomOut(self):
        self.ui.imageView.getView().scaleBy((2.0, 2.0))

    @pyqtSlot()
    def zoomToActualSize(self):
        if len(self.image_data) == 0:
            return
        self.ui.imageView.getView().setRange(xRange=(0,
                                                     self.image_data.shape[0]),
                                             yRange=(0,
                                                     self.image_data.shape[1]),
                                             padding=0.0)

    def disable_all_markers(self):
        for d in self.marker_dict:
            self.marker_dict[d]['button'].setChecked(False)
            self.marker_dict[d]['marker'].setPos((0, 0))

    @pyqtSlot(bool)
    def enableMarker(self, checked):
        any_markers_visible = False
        for d in self.marker_dict:
            marker = self.marker_dict[d]['marker']
            button = self.marker_dict[d]['button']
            any_markers_visible = any_markers_visible or button.isChecked()
            marker.setVisible(button.isChecked())
            self.markerMoved(d)
            self.marker_dict[d]['xcurve'].setVisible(button.isChecked())
            self.marker_dict[d]['ycurve'].setVisible(button.isChecked())
            self.marker_dict[d]['xlineedit'].setEnabled(button.isChecked())
            self.marker_dict[d]['ylineedit'].setEnabled(button.isChecked())
        if any_markers_visible:
            self.xLineoutPlot.show()
            self.yLineoutPlot.show()
        else:
            self.xLineoutPlot.hide()
            self.yLineoutPlot.hide()

    @pyqtSlot()
    def markerPositionLineEditChanged(self):
        for d in self.marker_dict:
            marker = self.marker_dict[d]['marker']
            x_line_edit = self.marker_dict[d]['xlineedit']
            y_line_edit = self.marker_dict[d]['ylineedit']
            try:
                new_x = int(x_line_edit.text())
                new_y = int(y_line_edit.text())
                if new_x <= marker.maxBounds.width(
                ) and new_y <= marker.maxBounds.height():
                    marker.setPos((new_x, new_y))
                    return
            except:
                pass
            coords = marker.getPixelCoords()
            x_line_edit.setText(str(coords[0]))
            y_line_edit.setText(str(coords[1]))

    @pyqtSlot(object)
    def markerMoved(self, marker):
        self.updateLineouts()
        for marker_index in self.marker_dict:
            marker = self.marker_dict[marker_index]['marker']
            x_line_edit = self.marker_dict[marker_index]['xlineedit']
            y_line_edit = self.marker_dict[marker_index]['ylineedit']
            coords = marker.getPixelCoords()
            x_line_edit.setText(str(coords[0]))
            y_line_edit.setText(str(coords[1]))

    @pyqtSlot(object, object)
    def updateLineoutRange(self, view, new_ranges):
        self.ui.xLineoutPlot.setRange(xRange=new_ranges[0], padding=0.0)
        self.ui.yLineoutPlot.setRange(yRange=new_ranges[1], padding=0.0)

    def updateLineouts(self):
        for marker_index in self.marker_dict:
            marker = self.marker_dict[marker_index]['marker']
            xcurve = self.marker_dict[marker_index]['xcurve']
            ycurve = self.marker_dict[marker_index]['ycurve']
            if marker.isVisible():
                result, coords = marker.getArrayRegion(
                    self.image_data, self.ui.imageView.getImageItem())
                xcurve.setData(y=result[0], x=np.arange(len(result[0])))
                ycurve.setData(y=np.arange(len(result[1])), x=result[1])

    @pyqtSlot()
    def enableSingleShotMode(self):
        self._average_mode_enabled = False
        self._average_buffer = np.ndarray(0)

    @pyqtSlot()
    def enableAverageMode(self):
        self._average_mode_enabled = True

    @pyqtSlot(str)
    def cameraChanged(self, new_camera):
        new_camera = str(new_camera)
        if self.imageChannel == self.cameras[new_camera]["image"]:
            return
        self.display_manager_window.close_widget_connections(self)
        self.disable_all_markers()
        self.initializeCamera(new_camera)
        self.display_manager_window.establish_widget_connections(self)

    def initializeCamera(self, new_camera):
        new_camera = str(new_camera)
        self._color_map_limit_sliders_need_config = True
        self.times = np.zeros(10)
        self.old_timestamp = 0
        self.image_width = 0  #current width (width of ROI)
        self.image_max_width = 0  #full width.  Only used to reset ROI to full.
        self.image_max_height = 0  #full height.  Only used to reset ROI to full.
        self.image_data = np.zeros(0)
        self._average_counter = 0
        self._average_buffer = np.ndarray(0)
        self._needs_auto_range = True
        self.imageChannel = self.cameras[new_camera]["image"]
        self.widthChannel = self.cameras[new_camera][
            "roi_width"] or self.cameras[new_camera]["max_width"]
        self.maxWidthChannel = self.cameras[new_camera]["max_width"]
        self.maxHeightChannel = self.cameras[new_camera]["max_height"]
        self.roiXChannel = self.cameras[new_camera]["roi_x"]
        self.roiYChannel = self.cameras[new_camera]["roi_y"]
        self.roiWidthChannel = self.cameras[new_camera]["roi_width"]
        self.roiHeightChannel = self.cameras[new_camera]["roi_height"]

        self._channels = [
            PyDMChannel(address=self.imageChannel,
                        connection_slot=self.connectionStateChanged,
                        waveform_slot=self.receiveImageWaveform,
                        severity_slot=self.alarmSeverityChanged),
            PyDMChannel(address=self.widthChannel,
                        value_slot=self.receiveImageWidth),
            PyDMChannel(address=self.maxWidthChannel,
                        value_slot=self.receiveMaxWidth),
            PyDMChannel(address=self.maxHeightChannel,
                        value_slot=self.receiveMaxHeight)
        ]
        if self.roiXChannel and self.roiYChannel and self.roiWidthChannel and self.roiHeightChannel:
            self._channels.extend([
                PyDMChannel(address=self.roiXChannel,
                            value_slot=self.receiveRoiX,
                            value_signal=self.roi_x_signal,
                            write_access_slot=self.roiWriteAccessChanged),
                PyDMChannel(address=self.roiYChannel,
                            value_slot=self.receiveRoiY,
                            value_signal=self.roi_y_signal),
                PyDMChannel(address=self.roiWidthChannel,
                            value_slot=self.receiveRoiWidth,
                            value_signal=self.roi_w_signal),
                PyDMChannel(address=self.roiHeightChannel,
                            value_slot=self.receiveRoiHeight,
                            value_signal=self.roi_h_signal)
            ])
            self.ui.roiXLineEdit.setEnabled(True)
            self.ui.roiYLineEdit.setEnabled(True)
            self.ui.roiWLineEdit.setEnabled(True)
            self.ui.roiHLineEdit.setEnabled(True)
        else:
            self.ui.roiXLineEdit.clear()
            self.ui.roiXLineEdit.setEnabled(False)
            self.ui.roiYLineEdit.clear()
            self.ui.roiYLineEdit.setEnabled(False)
            self.ui.roiWLineEdit.clear()
            self.ui.roiWLineEdit.setEnabled(False)
            self.ui.roiHLineEdit.clear()
            self.ui.roiHLineEdit.setEnabled(False)

    @pyqtSlot()
    def setROI(self):
        self.roi_x_signal.emit(self.ui.roiXLineEdit.text())
        self.roi_y_signal.emit(self.ui.roiYLineEdit.text())
        self.roi_w_signal.emit(self.ui.roiWLineEdit.text())
        self.roi_h_signal.emit(self.ui.roiHLineEdit.text())

    @pyqtSlot()
    def resetROI(self):
        self.roi_x_signal.emit(str(0))
        self.roi_y_signal.emit(str(0))
        self.roi_w_signal.emit(str(self.image_max_width))
        self.roi_h_signal.emit(str(self.image_max_height))

    @pyqtSlot(str)
    def colorMapChanged(self, new_map_name):
        self.ui.imageView.setColorMapToPreset(new_map_name)

    def configureColorMapLimitSliders(self, max_int):
        self.ui.colorMapMinSlider.setMaximum(max_int)
        self.ui.colorMapMaxSlider.setMaximum(max_int)
        self.ui.colorMapMaxSlider.setValue(max_int)
        self.ui.colorMapMinSlider.setValue(0)
        self.setColorMapMin(0)
        self.setColorMapMax(max_int)
        self._color_map_limit_sliders_need_config = False

    @pyqtSlot()
    def colorMapMinLineEditChanged(self):
        try:
            new_min = int(self.ui.colorMapMinLineEdit.text())
        except:
            self.ui.colorMapMinLineEdit.setText(
                str(self.ui.colorMapMinSlider.value()))
            return
        if new_min < 0:
            new_min = 0
        if new_min > self.ui.colorMapMinSlider.maximum():
            new_min = self.ui.colorMapMinSlider.maximum()
        self.ui.colorMapMinSlider.setValue(new_min)

    @pyqtSlot(int)
    def setColorMapMin(self, new_min):
        if new_min > self.ui.colorMapMaxSlider.value():
            self.ui.colorMapMaxSlider.setValue(new_min)
            self.ui.colorMapMaxLineEdit.setText(str(new_min))
        self.ui.colorMapMinLineEdit.setText(str(new_min))
        self.ui.imageView.setColorMapLimits(new_min,
                                            self.ui.colorMapMaxSlider.value())

    @pyqtSlot()
    def colorMapMaxLineEditChanged(self):
        try:
            new_max = int(self.ui.colorMapMaxLineEdit.text())
        except:
            self.ui.colorMapMaxLineEdit.setText(
                str(self.ui.colorMapMaxSlider.value()))
            return
        if new_max < 0:
            new_max = 0
        if new_max > self.ui.colorMapMaxSlider.maximum():
            new_max = self.ui.colorMapMaxSlider.maximum()
        self.ui.colorMapMaxSlider.setValue(new_max)

    @pyqtSlot(int)
    def setColorMapMax(self, new_max):
        if new_max < self.ui.colorMapMinSlider.value():
            self.ui.colorMapMinSlider.setValue(new_max)
            self.ui.colorMapMinLineEdit.setText(str(new_max))
        self.ui.colorMapMaxLineEdit.setText(str(new_max))
        self.ui.imageView.setColorMapLimits(self.ui.colorMapMinSlider.value(),
                                            new_max)

    def createAverageBuffer(self, size, type, initial_val=[]):
        num_shots = 1
        try:
            num_shots = int(self.ui.numShotsLineEdit.text())
        except:
            self.ui.numShotsLineEdit.setText(str(num_shots))
        if num_shots < 1:
            num_shots = 1
            self.ui.numShotsLineEdit.setText(str(num_shots))
        if num_shots > 200:
            num_shots = 200
            self.ui.numShotsLineEdit.setText(str(num_shots))
        if len(initial_val) > 0:
            return np.full((num_shots, size), initial_val, dtype=type)
        else:
            return np.zeros(shape=(num_shots, size), dtype=type)

    @pyqtSlot()
    def numAverageChanged(self):
        self._average_buffer = np.zeros(0)

    @pyqtSlot(np.ndarray)
    def receiveImageWaveform(self, new_waveform):
        if not self.image_width:
            return

        #Calculate the average rate
        new_timestamp = time.time()
        if not (self.old_timestamp == 0):
            delta = new_timestamp - self.old_timestamp
            self.times = np.roll(self.times, 1)
            self.times[0] = delta
            avg_delta = np.mean(self.times)
            self.ui.dataRateLabel.setText("{:.1f} Hz".format(
                (1.0 / avg_delta)))
            self.ui.displayRateLabel.setText("{:.1f} Hz".format(
                (1.0 / avg_delta)))
        self.old_timestamp = new_timestamp

        #If this is the first image, set up the color map slider limits
        if self._color_map_limit_sliders_need_config:
            max_int = np.iinfo(new_waveform.dtype).max
            self.configureColorMapLimitSliders(max_int)

        #If we are in average mode, add this image to the circular averaging buffer, otherwise just display it.
        if self._average_mode_enabled:
            if len(self._average_buffer) == 0:
                self._average_buffer = self.createAverageBuffer(
                    len(new_waveform), new_waveform.dtype, new_waveform)
                self._average_counter = 0
            self._average_counter = (self._average_counter + 1) % len(
                self._average_buffer)
            #self._average_buffer = np.roll(self._average_buffer, 1, axis=0)
            self._average_buffer[self._average_counter] = new_waveform
            mean = np.mean(self._average_buffer,
                           axis=0).astype(new_waveform.dtype)
            self.image_data = mean.reshape((int(self.image_width), -1),
                                           order='F')
        else:
            self.image_data = new_waveform.reshape((int(self.image_width), -1),
                                                   order='F')
        self.setMarkerBounds()
        self.updateLineouts()
        self.ui.imageView.receiveImageWaveform(self.image_data)
        self.calculateStats()
        if self._needs_auto_range:
            self.ui.imageView.getView().autoRange(padding=0.0)
            current_range = self.ui.imageView.getView().viewRange()
            self._needs_auto_range = False

    def calculateStats(self):
        # Full image stats
        mean = np.mean(self.image_data)
        std = np.std(self.image_data)
        width = self.image_data.shape[0]
        height = self.image_data.shape[1]
        min_val = np.min(self.image_data)
        max_val = np.max(self.image_data)
        self.ui.imageStatsLabel.setText(
            "Mean: {0:.2f}, Std: {1:.2f}, Min: {2}, Max: {3}, Width: {4}, Height: {5}"
            .format(mean, std, min_val, max_val, width, height))
        # Current view stats
        current_range = self.ui.imageView.getView().viewRange()
        view_x_min = int(max(0, current_range[0][0]))
        view_x_max = int(min(self.image_data.shape[0], current_range[0][1]))
        view_y_min = int(max(0, current_range[1][0]))
        view_y_max = int(min(self.image_data.shape[1], current_range[1][1]))
        view_slice = self.image_data[view_x_min:view_x_max,
                                     view_y_min:view_y_max]
        mean = np.mean(view_slice)
        std = np.std(view_slice)
        width = view_slice.shape[0]
        height = view_slice.shape[1]
        min_val = np.min(view_slice)
        max_val = np.max(view_slice)
        self.ui.viewStatsLabel.setText(
            "Mean: {0:.2f}, Std: {1:.2f}, Min: {2}, Max: {3}, Width: {4}, Height: {5}"
            .format(mean, std, min_val, max_val, width, height))

    def setMarkerBounds(self):
        for marker_index in self.marker_dict:
            marker = self.marker_dict[marker_index]['marker']
            marker.maxBounds = QRectF(
                0, 0, self.image_data.shape[0] + marker.size()[0] - 1,
                self.image_data.shape[1] + marker.size()[1] - 1)

    @pyqtSlot(int)
    def receiveImageWidth(self, new_width):
        self.image_width = new_width
        self.ui.imageView.receiveImageWidth(self.image_width)

    @pyqtSlot(int)
    def receiveMaxWidth(self, new_max_width):
        self.image_max_width = new_max_width

    @pyqtSlot(int)
    def receiveMaxHeight(self, new_max_height):
        self.image_max_height = new_max_height

    @pyqtSlot(int)
    def receiveRoiX(self, new_roi_x):
        self.ui.roiXLineEdit.setText(str(new_roi_x))

    @pyqtSlot(int)
    def receiveRoiY(self, new_roi_y):
        self.ui.roiYLineEdit.setText(str(new_roi_y))

    @pyqtSlot(int)
    def receiveRoiWidth(self, new_roi_w):
        self.ui.roiWLineEdit.setText(str(new_roi_w))

    @pyqtSlot(int)
    def receiveRoiHeight(self, new_roi_h):
        self.ui.roiHLineEdit.setText(str(new_roi_h))

    # -2 to +2, -2 is LOLO, -1 is LOW, 0 is OK, etc.
    @pyqtSlot(int)
    def alarmStatusChanged(self, new_alarm_state):
        pass

    #0 = NO_ALARM, 1 = MINOR, 2 = MAJOR, 3 = INVALID
    @pyqtSlot(int)
    def alarmSeverityChanged(self, new_alarm_severity):
        pass

    @pyqtSlot(bool)
    def roiWriteAccessChanged(self, can_write_roi):
        self.ui.setROIButton.setEnabled(can_write_roi)
        self.ui.resetROIButton.setEnabled(can_write_roi)
        self.ui.roiXLineEdit.setReadOnly(not can_write_roi)
        self.ui.roiYLineEdit.setReadOnly(not can_write_roi)
        self.ui.roiWLineEdit.setReadOnly(not can_write_roi)
        self.ui.roiHLineEdit.setReadOnly(not can_write_roi)

    #false = disconnected, true = connected
    @pyqtSlot(bool)
    def connectionStateChanged(self, connected):
        self.ui.connectedLabel.setText({True: "Yes", False: "No"}[connected])

    def ui_filename(self):
        return 'camviewer.ui'

    def ui_filepath(self):
        return path.join(path.dirname(path.realpath(__file__)),
                         self.ui_filename())

    def channels(self):
        return self._channels
Beispiel #31
0
class PyQtGraphDataPlot(QWidget):

    limits_changed = Signal()

    def __init__(self, parent=None):
        super(PyQtGraphDataPlot, self).__init__(parent)
        self._plot_widget = PlotWidget()
        self._plot_widget.getPlotItem().addLegend()
        self._plot_widget.setBackground((255, 255, 255))
        self._plot_widget.setXRange(0, 10, padding=0)
        vbox = QVBoxLayout()
        vbox.addWidget(self._plot_widget)
        self.setLayout(vbox)
        self._plot_widget.getPlotItem().sigRangeChanged.connect(
            self.limits_changed)

        self.bins = 10
        self.window = 100
        self._curves = {}
        self._current_vline = None

    def add_curve(self,
                  curve_id,
                  curve_name,
                  curve_color=QColor(Qt.blue),
                  markers_on=False):
        pen = mkPen(curve_color, width=1)
        # this adds the item to the plot and legend
        plot = self._plot_widget.plot(stepMode=True,
                                      fillLevel=0,
                                      brush=(0, 0, 255, 150))
        self._curves[curve_id] = plot

    def remove_curve(self, curve_id):
        curve_id = str(curve_id)
        if curve_id in self._curves:
            self._plot_widget.removeItem(self._curves[curve_id])
            del self._curves[curve_id]
            self._update_legend()

    def _update_legend(self):
        # clear and rebuild legend (there is no remove item method for the legend...)
        self._plot_widget.clear()
        self._plot_widget.getPlotItem().legend.items = []
        for curve in self._curves.values():
            self._plot_widget.addItem(curve)
        if self._current_vline:
            self._plot_widget.addItem(self._current_vline)

    def redraw(self):
        pass

    def set_values(self, curve_id, data_x, data_y):
        curve = self._curves[curve_id]
        if len(data_y) > 0:
            y, x = numpy.histogram(data_y[-self.window:], self.bins)
            curve.setData(x, y)
        else:
            curve.clear()
        self._plot_widget.autoRange()

    def vline(self, x, color):
        if self._current_vline:
            self._plot_widget.removeItem(self._current_vline)
        self._current_vline = self._plot_widget.addLine(x=x, pen=color)

    def set_xlim(self, limits):
        # TODO: this doesn't seem to handle fast updates well
        self._plot_widget.setXRange(limits[0], limits[1], padding=0)

    def set_ylim(self, limits):
        self._plot_widget.setYRange(limits[0], limits[1], padding=0)

    def get_xlim(self):
        x_range, _ = self._plot_widget.viewRange()
        return x_range

    def get_ylim(self):
        _, y_range = self._plot_widget.viewRange()
        return y_range
Beispiel #32
0
    def initGUI(self):
        self.plot = PlotWidget()
        self.sensorplot = PlotWidget()

        self.schemeplot = PlotWidget()
        self.scheme_plot = UTILS_QT.myplot(self.schemeplot,xlabel = ['time', 's'], ylabel =['',''],logmode=False)
        self.psp = UTILS_QT.pulses_scheme_plot(self.scheme_plot)


        date_axis = TimeAxisItem(orientation='bottom')
        #date_axis = pg.graphicsItems.DateAxisItem.DateAxisItem(orientation = 'bottom')
        self.sensorplot = PlotWidget(axisItems = {'bottom': date_axis})


        win = GraphicsLayoutWidget()
        win2 = PlotWidget()



        self.view = win.addViewBox(border = 'w', invertY = True)
        self.view.setAspectLocked(True)
        self.img = ImageItem()
        self.plotaxes = win2.getPlotItem()
        #self.view.addItem(self.img)
        #self.view.addItem(self.plotaxes)
        #self.view.


        data = np.random.normal(size=(1, 600, 600), loc=1024, scale=64).astype(np.uint16)
        self.img.setImage(data[0])
        self.plotaxes.getViewBox().addItem(self.img)


        # colormap
        pos = np.array([0., 1., 0.5, 0.25, 0.75])
        #pos2 = np.array([1.0,0.75,0.5,0.25,0.])
        pos2 = np.array([0.,0.25,0.5,0.75,1.0])
        color2 = np.array([[255,242,15,255], [245,124,15,255],[170,69,16,255],[91,50,0,255],[0,0,0,255]],dtype=np.ubyte)
        color = np.array([[0,255,255,255], [255,255,0,255], [0,0,0,255], (0, 0, 255, 255), (255, 0, 0, 255)], dtype=np.ubyte)
        cmap = pg.ColorMap(pos2, color2)
        lut = cmap.getLookupTable(0.0, 1.0, 256)
        self.img.setLookupTable(lut)
        #self.img.setLevels([-50,1])

        self.tw = QtGui.QTabWidget()
        self.tw.addTab(win2,'ESR data')
        self.tw.addTab(self.sensorplot,'B field')
        self.tw.addTab(self.schemeplot,'Scheme')

        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.plot)
        #layout.addWidget(win2)
        layout.addWidget(self.tw)

        self.setLayout(layout)

        self.p1 = self.plot.getPlotItem()
        self.p2 = self.plot.getPlotItem()

        self.ps = self.sensorplot.getPlotItem()
        #self.p1.addLegend()
        self.p1data = self.p1.plot([0],pen = 'r')
        self.p2data = self.p1.plot([0],pen = 'g')
        self.psdata = self.ps.plot([],pen = 'w')
        self.ps.setLabel('left','Magnetic field', 'uT')

        self.vLine5 = pg.InfiniteLine(angle=90, movable=True)
        self.vLine6 = pg.InfiniteLine(angle=90, movable=True)
        self.plotaxes.addItem(self.vLine5, ignoreBounds=True)
        self.plotaxes.addItem(self.vLine6, ignoreBounds=True)
class Ui_MainWindow(QtWidgets.QMainWindow):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.setFixedSize(800, 618)

        MainWindow.setStyleSheet('background:#e8e8e8')

        #here starts widget setup, mostly just assigning locations and various properties
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.topDisplayDivider = QtWidgets.QFrame(self.centralwidget)
        self.topDisplayDivider.setGeometry(QtCore.QRect(0, 90, 801, 16))
        self.topDisplayDivider.setFrameShape(QtWidgets.QFrame.HLine)
        self.topDisplayDivider.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.topDisplayDivider.setObjectName("topDisplayDivider")
        self.menuDivider = QtWidgets.QFrame(self.centralwidget)
        self.menuDivider.setGeometry(QtCore.QRect(110, 100, 16, 501))
        self.menuDivider.setFrameShape(QtWidgets.QFrame.VLine)
        self.menuDivider.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.menuDivider.setObjectName("menuDivider")
        self.pushHistory = QtWidgets.QPushButton(self.centralwidget)
        self.pushHistory.setGeometry(QtCore.QRect(20, 140, 75, 23))
        self.pushHistory.setObjectName("pushHistory")
        self.pushHistory.setStyleSheet("border: 1px solid grey;")
        self.pushAnalytics = QtWidgets.QPushButton(self.centralwidget)
        self.pushAnalytics.setGeometry(QtCore.QRect(20, 210, 75, 23))
        self.pushAnalytics.setObjectName("pushAnalytics")
        self.pushExport = QtWidgets.QPushButton(self.centralwidget)
        self.pushExport.setGeometry(QtCore.QRect(20, 280, 75, 23))
        self.pushExport.setObjectName("pushExport")
        self.pushOptions = QtWidgets.QPushButton(self.centralwidget)
        self.pushOptions.setGeometry(QtCore.QRect(20, 350, 75, 23))
        self.pushOptions.setObjectName("pushOptions")

        self.pushLive = QtWidgets.QPushButton(self.centralwidget)
        self.pushLive.setGeometry(QtCore.QRect(20, 550, 75, 23))
        self.pushLive.setObjectName("pushLive")

        self.pushGraph = QtWidgets.QPushButton(self.centralwidget)
        self.pushGraph.setGeometry(QtCore.QRect(200, 550, 75, 23))
        self.pushGraph.setObjectName("pushGraph")

        self.pushGraph2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushGraph2.setGeometry(QtCore.QRect(300, 550, 75, 23))
        self.pushGraph2.setObjectName("pushGraph2")

        self.liveDisplay_1 = QtWidgets.QLabel(self.centralwidget)
        self.liveDisplay_1.setGeometry(QtCore.QRect(710, 20, 61, 61))
        self.liveDisplay_1.setObjectName("liveDisplay_1")
        self.liveDisplay_1.setStyleSheet("font: 30pt Arial MS")

        self.liveDisplay_2 = QtWidgets.QLabel(self.centralwidget)
        self.liveDisplay_2.setGeometry(QtCore.QRect(570, 20, 61, 61))
        self.liveDisplay_2.setObjectName("liveDisplay_2")
        self.liveDisplay_2.setStyleSheet("font: 30pt Arial MS")

        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(500, 20, 61, 61))
        self.label.setText("")
        self.label.setPixmap(QtGui.QPixmap("heart.png"))
        self.label.setScaledContents(True)
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(640, 20, 61, 61))
        self.label_2.setText("")
        self.label_2.setPixmap(QtGui.QPixmap("o2.png"))
        self.label_2.setScaledContents(True)
        self.label_2.setObjectName("label_2")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(140, 120, 631, 311))
        self.groupBox.setObjectName("groupBox")
        self.label_3 = QtWidgets.QLabel(self.groupBox)
        self.label_3.setGeometry(QtCore.QRect(210, 110, 151, 31))
        self.label_3.setObjectName("label_3")

        self.dateTimeEdit = QtWidgets.QDateEdit(self.centralwidget)
        self.dateTimeEdit.setGeometry(QtCore.QRect(190, 490, 194, 22))
        self.dateTimeEdit.setObjectName("dateTimeEdit")
        self.dateTimeEdit.setDate(QDate.currentDate())

        self.label_6 = QtWidgets.QLabel(self.centralwidget)
        self.label_6.setGeometry(QtCore.QRect(40, 20, 251, 41))
        font = QtGui.QFont()
        font.setPointSize(19)
        self.label_6.setFont(font)
        self.label_6.setObjectName("label_6")

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        #creating graphs
        self.graphWidgetLive = PlotWidget(self.centralwidget)
        self.graphWidgetLive.setGeometry(QtCore.QRect(40, 10, 400, 70))
        self.graphWidgetLive.setObjectName("graphWidgetLive")
        self.graphWidgetLive.getPlotItem().hideAxis('bottom')
        self.graphWidgetLive.setMouseEnabled(x=False, y=False)
        self.graphWidgetLive.setYRange(0, 150, padding=0.2)
        self.graphWidgetLive.getPlotItem().hideAxis('bottom')

        self.graphWidgetMain = PlotWidget(self.centralwidget)
        self.graphWidgetMain.setGeometry(QtCore.QRect(150, 140, 600, 275))
        self.graphWidgetMain.setObjectName("graphWidgetLive")
        self.graphWidgetMain.setMouseEnabled(x=True, y=False)
        self.graphWidgetMain.setYRange(50, 150, padding=0)
        self.graphWidgetMain.getPlotItem().hideAxis('bottom')

        self.graphWidgetLive.setBackground('w')

        pen = pg.mkPen(color=(255, 0, 0), width=2)
        pen2 = pg.mkPen(color=(0, 0, 255), width=2)
        time = [1, 2, 3, 4]
        heartRate = [90, 87, 88, 85]
        oxygenLevel = [100, 99, 99, 98]
        self.graphWidgetMain.setBackground('w')
        self.graphWidgetMain.plot(time, heartRate, pen=pen)
        self.graphWidgetMain.plot(time, oxygenLevel, pen=pen2)

        #these two values can be changed in options and are parameters for the windows notifications
        self.notifThresh = [120, 95]
        self.notifCooldown = 25

        self.serialInput = False

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

        #connecting buttons
        self.pushAnalytics.clicked.connect(self.show_Analysis)

        self.pushExport.clicked.connect(self.show_export)

        self.pushOptions.clicked.connect(self.show_popOptions)

        self.pushLive.setCheckable(True)
        self.pushLive.clicked.connect(self.show_graphLive)

        self.pushGraph.clicked.connect(self.fromFile)
        self.pushGraph2.clicked.connect(self.fromDate)

    def update_plot_data(self):

        #this is used to update the live graph by reading from serial or the debugging simulator

        self.timeLive = self.timeLive[1:]  # Remove the first y element.
        self.timeLive.append(self.timeLive[-1] +
                             1)  # Add a new value 1 higher than the last.

        if self.serialInput == True:
            serialData = serial_connection.getSerial()
        else:
            serialData = (singleGenerate(79, 3), singleGenerate(97, 1))

        if serialData[0] != 0:
            self.liveHR = self.liveHR[1:]  # Remove the first
            self.liveHR.append(serialData[0])
            self.liveDisplay_2.setText(str(self.liveHR[99]))

        if serialData[1] != 0:
            self.liveO2 = self.liveO2[1:]  # Remove the first
            self.liveO2.append(serialData[1])
            self.liveDisplay_1.setText(str(self.liveO2[99]))

        if not (serialData[0] == 0 & serialData[1] == 0):
            datasystem.data_store(serialData[0], serialData[1])

        a = datetime.datetime.now()
        b = self.startTime
        c = a - b
        print(c.total_seconds())
        if c.total_seconds() > self.notifCooldown:
            if self.notifThresh[0] < serialData[0]:
                windowsalert.sendNotifH()
                self.startTime = datetime.datetime.now()

            if self.notifThresh[1] > serialData[1] & serialData[1] != 0:
                windowsalert.sendNotifO()
                self.startTime = datetime.datetime.now()

        self.data_line_1.setData(self.timeLive,
                                 self.liveHR)  # Update the data.
        self.data_line_2.setData(self.timeLive,
                                 self.liveO2)  # Update the data.

    def show_export(self):
        #used to call the zipping function in datasystem.py, and the file dialog
        options = QFileDialog.Options() | QFileDialog.DontUseNativeDialog
        fileName = QFileDialog.getSaveFileName(self,
                                               "Select an export location",
                                               "",
                                               "Zip Files (*.zip)",
                                               options=options)
        datasystem.data_zip(fileName[0] + '.zip')

    def show_graphLive(self):
        #connects to the button for live, and also controls if the graph/reading is enabled

        self.timeLive = list(range(100))  # 100 time points
        self.liveHR = [0] * 100
        self.liveO2 = [0] * 100
        self.startTime = datetime.datetime.now() - datetime.timedelta(
            seconds=self.notifCooldown)
        print(self.startTime)

        pen = pg.mkPen(color=(255, 0, 0), width=2)
        pen2 = pg.mkPen(color=(0, 0, 255), width=2)

        self.liveDisplay_2.setText('0')
        self.liveDisplay_1.setText('0')

        if self.pushLive.isChecked():
            self.data_line_1 = self.graphWidgetLive.plot(self.timeLive,
                                                         self.liveHR,
                                                         pen=pen)
            self.data_line_2 = self.graphWidgetLive.plot(self.timeLive,
                                                         self.liveO2,
                                                         pen=pen2)
            self.timer = QtCore.QTimer()
            self.timer.setInterval(250)
            self.timer.timeout.connect(self.update_plot_data)
            self.timer.start()
            self.pushLive.setText('Stop')
        else:
            self.timer.stop()
            self.graphWidgetLive.clear()
            self.pushLive.setText('Start')

    def fromDate(self):
        #used to connect the date picker to the main graph
        x = self.dateTimeEdit.date().toPyDate()
        date = 'vitals' + str(x)
        directory = os.getcwd()
        foldername = directory + '\\vitalsmouse_userdata'
        self.importfile = foldername + '\\' + date + '.csv'

        self.show_graphMain()

    def fromFile(self):
        #used to connect the file dialog to the main graph
        options = QFileDialog.Options() | QFileDialog.DontUseNativeDialog
        fileName = QFileDialog.getOpenFileName(self,
                                               "Select a file to view",
                                               "",
                                               "CSV Files (*.csv)",
                                               options=options)
        self.importfile = fileName[0]

        self.show_graphMain()

    def show_graphMain(self):
        #loads the data from a file and displays it on the main graph

        print(self.importfile)

        self.graphWidgetMain.clear()

        maindata = datasystem.data_get(self.importfile)

        mainTime = maindata[0]
        mainHR = maindata[1]
        mainO2 = maindata[2]

        pen = pg.mkPen(color=(255, 0, 0), width=2)
        pen2 = pg.mkPen(color=(0, 0, 255), width=2)
        self.graphWidgetMain.setBackground('w')
        self.graphWidgetMain.plot(mainTime, mainHR, pen=pen)
        self.graphWidgetMain.plot(mainTime, mainO2, pen=pen2)

    def show_popOptions(self):
        #secondary window for options
        self.Options = QDialog()
        self.Options.resize(200, 250)

        self.input_label = QtWidgets.QLabel(self.Options)
        self.input_label.setGeometry(QtCore.QRect(10, 10, 61, 51))
        self.input_label.setObjectName("input_label")

        self.inputBox = QtWidgets.QComboBox(self.Options)
        self.inputBox.setGeometry(QtCore.QRect(80, 30, 69, 22))
        self.inputBox.setObjectName("inputBox")
        self.inputBox.addItem('Debug')
        self.inputBox.addItem('USB')

        self.notificationsBox = QtWidgets.QGroupBox(self.Options)
        self.notificationsBox.setGeometry(QtCore.QRect(0, 90, 211, 131))
        self.notificationsBox.setObjectName("notificationsBox")
        self.lineEdit = QtWidgets.QLineEdit(self.notificationsBox)
        self.lineEdit.setGeometry(QtCore.QRect(130, 30, 61, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.hr_label = QtWidgets.QLabel(self.notificationsBox)
        self.hr_label.setGeometry(QtCore.QRect(6, 30, 111, 20))
        self.hr_label.setObjectName("hr_label")
        self.lineEdit_2 = QtWidgets.QLineEdit(self.notificationsBox)
        self.lineEdit_2.setGeometry(QtCore.QRect(130, 60, 61, 20))
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.lineEdit_3 = QtWidgets.QLineEdit(self.notificationsBox)
        self.lineEdit_3.setGeometry(QtCore.QRect(130, 90, 61, 20))
        self.lineEdit_3.setObjectName("lineEdit_3")
        self.o2_label = QtWidgets.QLabel(self.notificationsBox)
        self.o2_label.setGeometry(QtCore.QRect(10, 60, 111, 20))
        self.o2_label.setObjectName("o2_label")
        self.cooldown_label = QtWidgets.QLabel(self.notificationsBox)
        self.cooldown_label.setGeometry(QtCore.QRect(10, 90, 111, 20))
        self.cooldown_label.setObjectName("cooldown_label")

        self.input_label.setText("Input mode")
        self.notificationsBox.setTitle(("Notifications"))
        self.lineEdit.setText(("110"))
        self.hr_label.setText(("Heartrate threshold"))
        self.lineEdit_2.setText(("95"))
        self.lineEdit_3.setText(("20"))
        self.o2_label.setText(("Oxygen threshold"))
        self.cooldown_label.setText(("Cooldown(seconds)"))

        self.Options.setWindowTitle("Options")
        self.Options.exec_()

        h = self.inputBox.currentText()

        if h == 'USB':
            self.serialInput = True
        else:
            self.serialInput = False

        heartThresh = self.lineEdit.text()
        o2Thresh = self.lineEdit_2.text()
        cool = self.lineEdit_3.text()

        self.notifThresh = (int(heartThresh), int(o2Thresh))
        self.notifCooldown = int(cool)

    def show_Analysis(self):
        #secondary window for analysis
        self.Analysis = QDialog()
        self.Analysis.resize(400, 400)

        self.dailyLine = QtWidgets.QLineEdit(self.Analysis)
        self.dailyLine.setGeometry(QtCore.QRect(210, 60, 113, 20))
        self.dailyLine.setReadOnly(True)
        self.dailyLine.setObjectName("dailyLine")
        self.yearly_label = QtWidgets.QLabel(self.Analysis)
        self.yearly_label.setGeometry(QtCore.QRect(40, 140, 101, 16))
        self.yearly_label.setObjectName("yearly_label")
        self.monthly_label = QtWidgets.QLabel(self.Analysis)
        self.monthly_label.setGeometry(QtCore.QRect(40, 100, 111, 16))
        self.monthly_label.setObjectName("monthly_label")
        self.monthlyLine = QtWidgets.QLineEdit(self.Analysis)
        self.monthlyLine.setGeometry(QtCore.QRect(210, 100, 113, 20))
        self.monthlyLine.setReadOnly(True)
        self.monthlyLine.setObjectName("monthlyLine")
        self.daily_label = QtWidgets.QLabel(self.Analysis)
        self.daily_label.setGeometry(QtCore.QRect(40, 60, 111, 16))
        self.daily_label.setObjectName("daily_label")
        self.yearlyLine = QtWidgets.QLineEdit(self.Analysis)
        self.yearlyLine.setGeometry(QtCore.QRect(210, 140, 113, 20))
        self.yearlyLine.setReadOnly(True)
        self.yearlyLine.setObjectName("yearlyLine")

        self.legend_label = QtWidgets.QLabel(self.Analysis)
        self.legend_label.setGeometry(QtCore.QRect(220, 20, 113, 20))
        self.legend_label.setObjectName("legend_label")
        self.legend_label.setText("Heartrate, Oxygen")

        self.graphWidgetAnalysis = PlotWidget(self.Analysis)
        self.graphWidgetAnalysis.setGeometry(QtCore.QRect(50, 200, 300, 150))
        self.graphWidgetAnalysis.setObjectName("graphWidgetLive")
        self.graphWidgetAnalysis.setMouseEnabled(x=False, y=False)
        self.graphWidgetAnalysis.setYRange(50, 150, padding=0)
        self.graphWidgetAnalysis.getPlotItem().hideAxis('bottom')

        analysis_data = datasystem.data_analysis()

        pen = pg.mkPen(color=(255, 0, 0), width=2)
        pen2 = pg.mkPen(color=(0, 0, 255), width=2)

        heartRate = analysis_data[3][0]
        oxygenLevel = analysis_data[3][1]

        length = len(heartRate)
        time = [int(z) for z in range(length)]
        self.graphWidgetAnalysis.setBackground('w')
        self.graphWidgetAnalysis.plot(time, heartRate, pen=pen)
        self.graphWidgetAnalysis.plot(time, oxygenLevel, pen=pen2)

        self.dailyLine.setText(
            str(round(analysis_data[0][0], 2)) + ', ' +
            str(round(analysis_data[0][1], 2)))
        self.monthlyLine.setText(
            str(round(analysis_data[1][0], 2)) + ', ' +
            str(round(analysis_data[1][1], 2)))
        self.yearlyLine.setText(
            str(round(analysis_data[2][0], 2)) + ', ' +
            str(round(analysis_data[2][1], 2)))

        self.yearly_label.setText("Yearly Average")
        self.monthly_label.setText("Monthly Average")
        self.daily_label.setText("Daily Average")

        self.Analysis.setWindowTitle("Analysis")

        self.Analysis.exec_()

    def retranslateUi(self, MainWindow):
        #this is a holdover from using pyuic5, not normally used like this
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushHistory.setText(_translate("MainWindow", "History"))
        self.pushAnalytics.setText(_translate("MainWindow", "Analytics"))
        self.pushExport.setText(_translate("MainWindow", "Export"))
        self.pushOptions.setText(_translate("MainWindow", "Options"))
        self.pushLive.setText(_translate("MainWindow", "Start"))
        self.pushGraph.setText(_translate("MainWindow", "From file"))
        self.pushGraph2.setText(_translate("MainWindow", "From date"))
        self.liveDisplay_1.setText("##")
        self.liveDisplay_2.setText("##")
        self.groupBox.setTitle(_translate("MainWindow", "History"))
Beispiel #34
0
class PyQtGraphDataPlot(QWidget):
    _colors = [
        Qt.red, Qt.blue, Qt.magenta, Qt.cyan, Qt.green, Qt.darkYellow,
        Qt.black, Qt.darkRed, Qt.gray, Qt.darkCyan
    ]

    def __init__(self, parent=None):
        super(PyQtGraphDataPlot, self).__init__(parent)
        self._plot_widget = PlotWidget()
        self._plot_widget.getPlotItem().addLegend()
        self._plot_widget.setBackground((255, 255, 255))
        self._plot_widget.setXRange(0, 10, padding=0)
        vbox = QVBoxLayout()
        vbox.addWidget(self._plot_widget)
        self.setLayout(vbox)

        self._autoscroll = False
        self._color_index = 0
        self._curves = {}

    def add_curve(self, curve_id, curve_name, data_x, data_y):
        color = QColor(self._colors[self._color_index % len(self._colors)])
        self._color_index += 1
        pen = mkPen(color, width=2)
        # this adds the item to the plot and legend
        plot = self._plot_widget.plot(name=curve_name, pen=pen)
        data_x = numpy.array(data_x)
        data_y = numpy.array(data_y)
        self._curves[curve_id] = {'x': data_x, 'y': data_y, 'plot': plot}

    def remove_curve(self, curve_id):
        curve_id = str(curve_id)
        if curve_id in self._curves:
            self._plot_widget.getPlotItem().removeItem(
                self._curves[curve_id]['plot'])
            del self._curves[curve_id]
            self._update_legend()

    def _update_legend(self):
        # clear and rebuild legend (there is no remove item method for the legend...)
        self._plot_widget.getPlotItem().clear()
        self._plot_widget.getPlotItem().legend.items = []
        for curve in self._curves.values():
            self._plot_widget.getPlotItem().addItem(curve['plot'])

    @Slot(str, list, list)
    def update_values(self, curve_id, x, y):
        curve = self._curves[curve_id]
        curve['x'] = numpy.append(curve['x'], x)
        curve['y'] = numpy.append(curve['y'], y)

    def autoscroll(self, enabled=True):
        self._autoscroll = enabled

    def redraw(self):
        for curve in self._curves.values():
            curve['plot'].setData(curve['x'], curve['y'])

        if self._autoscroll:
            # Set axis bounds
            x_range, _ = self._plot_widget.viewRange()
            x_delta = x_range[1] - x_range[0]
            x_max = 0

            for curve in self._curves.values():
                if len(curve['x']) == 0:
                    continue
                x_max = max(x_max, curve['x'][-1])

            self._plot_widget.setXRange(x_max - x_delta, x_max, padding=0)