예제 #1
0
 def update_num_legend_font(legend: pg.LegendItem,
                            **settings: _SettingType):
     if not legend:
         return
     for sample, _ in legend.items:
         sample.set_font(Updater.change_font(sample.font, settings))
         legend.setGeometry(sample.boundingRect())
예제 #2
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)
예제 #3
0
def add_to_legend(legend: pg.LegendItem, curve: pg.PlotItem, curve_name):
    """ Adds a curve to a legend

    :param legend: pg.LegendItem to add to
    :param curve: pg.PlotItem containing the relevant curve
    :param curve_name: (str) name of curve
    """

    legend.addItem(curve, ' - ' + curve_name)
예제 #4
0
 def addLegend(self, size=None, offset=(30, 30)):
     """
     Reimplement addLegend to check if legend already exists.
     The default one should do this, but doesn't
     seem to work on our extended version for some reason?
     """
     if self.legend is None:
         self.legend = LegendItem(size, offset)
         self.legend.setParentItem(self.vb)
     return self.legend
예제 #5
0
    def __init__(self, size=None, offset=None, pen=None, brush=None, **kwargs):
        LegendItem.__init__(self, size, offset)

        self.layout.setSpacing(0)
        self.layout.setColumnSpacing(0, 10)
        self.layout.setContentsMargins(20, 0, 0, 0)

        self.opts = {
            'pen': fn.mkPen(pen),
            'brush': brush,
            'labelTextColor': None,
            'box': False,
        }

        self.opts.update(kwargs)
예제 #6
0
class ExtendedPlotItem(PlotItem):
    def __init__(self, *args, **kwargs):
        """
        Create a new PlotItem, same as a base plotitem, but with a few
        extra pieces of functionality.
          - Keep track of images and allow proxying
          - Use a custom view box, such that we can do common tasks
        """
        if 'viewBox' not in kwargs:
            vb = CustomViewBox()
            kwargs['viewBox'] = vb
        super().__init__(*args, **kwargs)

        # Keep track of context menus for items in this plot
        self.itemMenus = {}

    def addItem(self, item, *args, **kwargs):
        super().addItem(item, *args, **kwargs)
        if isinstance(item, ImageItem):
            # addItem does not keep track of images, let's add it ourselves
            self.dataItems.append(item)

    def plot(self, *args, **kargs):
        """
        Reimplements PlotItem.plot to use ExtendedPlotDataItems.
        Add and return a new plot.
        See :func:`PlotDataItem.__init__ <pyqtgraph.PlotDataItem.__init__>` for data arguments

        Extra allowed arguments are:
            clear    - clear all plots before displaying new data
            params   - meta-parameters to associate with this data
        """
        clear = kargs.get('clear', False)
        params = kargs.get('params', None)

        if clear:
            self.clear()

        item = ExtendedPlotDataItem(*args, **kargs)

        if params is None:
            params = {}
        self.addItem(item, params=params)

        return item

    def makeTracesDifferent(self, saturation=0.8, value=0.9, items=None):
        """
        Color each of the traces in a plot a different color
        """
        if items is None:
            items = self.listDataItems()
        items = [x for x in items if isinstance(x, PlotDataItem)]
        ntraces = len(items)

        for i, trace in enumerate(items):
            color = colorsys.hsv_to_rgb(i / ntraces, saturation, value)
            color = tuple(int(c * 255) for c in color)
            trace.setPen(*color)

    def addLegend(self, size=None, offset=(30, 30)):
        """
        Reimplement addLegend to check if legend already exists.
        The default one should do this, but doesn't
        seem to work on our extended version for some reason?
        """
        if self.legend is None:
            self.legend = LegendItem(size, offset)
            self.legend.setParentItem(self.vb)
        return self.legend
예제 #7
0
    def __init__(self):
        GraphicsView.__init__(self)

        # create layout
        self.layout = pg.GraphicsLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(-1.)
        self.setBackground(None)
        self.setCentralItem(self.layout)

        # create axes and apply formatting
        axisItems = dict()

        for pos in ['bottom', 'left', 'top', 'right']:
            axisItems[pos] = AxisItem(orientation=pos, maxTickLength=-7)

        self.p = PlotItem(axisItems=axisItems)
        self.setTitle('Sweep data', fontScaling=1.3, color='k')
        self.layout.addItem(self.p)

        self.p.vb.setBackgroundColor('w')
        self.p.setContentsMargins(10, 10, 10, 10)

        for pos in ['bottom', 'left', 'top', 'right']:
            ax = self.p.getAxis(pos)
            ax.setZValue(0)  # draw on top of patch
            ax.setVisible(True)  # make all axes visible
            ax.setPen(width=self.LW * 2 / 3,
                      color=0.5)  # grey spines and ticks
            try:
                ax.setTextPen('k')  # black text
            except AttributeError:
                pass
            ax.setStyle(autoExpandTextSpace=True, tickTextOffset=4)

        self.p.getAxis('top').setTicks([])
        self.p.getAxis('top').setHeight(0)
        self.p.getAxis('right').setTicks([])

        self.x_axis = self.p.getAxis('bottom')
        self.y_axis = self.p.getAxis('left')

        self.x_axis.setLabel('Voltage', units='V', color='k', size='12pt')
        self.y_axis.setLabel('Current', units='A', color='k', size='12pt')
        self.y_axis.setStyle(tickTextWidth=35)

        # set auto range and mouse panning / zooming
        self.p.enableAutoRange(x=True, y=True)
        self.p.setLimits(xMin=-1e20, xMax=1e20, yMin=-1e20, yMax=1e20)

        def suggestPadding(axis):
            length = self.p.vb.width() if axis == 0 else self.p.vb.height()
            if length > 0:
                if axis == 0:
                    padding = 0
                else:
                    padding = np.clip(1. / (length**0.5), 0.02, 0.1)
            else:
                padding = 0.02
            return padding

        self.p.vb.suggestPadding = suggestPadding

        # set default ranges to start
        self.p.setXRange(-10, 10)
        self.p.setYRange(-10, 10)

        # add legend
        self.legend = LegendItem(brush=fn.mkBrush(255, 255, 255, 150),
                                 labelTextColor='k',
                                 offset=(20, -20))
        self.legend.setParentItem(self.p.vb)
예제 #8
0
class SweepDataPlot(GraphicsView):

    GREEN = [0, 204, 153]
    BLUE = [100, 171, 246]
    RED = [221, 61, 53]
    PURPLE = [175, 122, 197]
    ASH = [52, 73, 94]
    GRAY = [178, 186, 187]

    COLORS = [BLUE, RED, GREEN, PURPLE, ASH, GRAY]

    if sys.platform == 'darwin':
        LW = 3
    else:
        LW = 1.5

    def __init__(self):
        GraphicsView.__init__(self)

        # create layout
        self.layout = pg.GraphicsLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(-1.)
        self.setBackground(None)
        self.setCentralItem(self.layout)

        # create axes and apply formatting
        axisItems = dict()

        for pos in ['bottom', 'left', 'top', 'right']:
            axisItems[pos] = AxisItem(orientation=pos, maxTickLength=-7)

        self.p = PlotItem(axisItems=axisItems)
        self.setTitle('Sweep data', fontScaling=1.3, color='k')
        self.layout.addItem(self.p)

        self.p.vb.setBackgroundColor('w')
        self.p.setContentsMargins(10, 10, 10, 10)

        for pos in ['bottom', 'left', 'top', 'right']:
            ax = self.p.getAxis(pos)
            ax.setZValue(0)  # draw on top of patch
            ax.setVisible(True)  # make all axes visible
            ax.setPen(width=self.LW * 2 / 3,
                      color=0.5)  # grey spines and ticks
            try:
                ax.setTextPen('k')  # black text
            except AttributeError:
                pass
            ax.setStyle(autoExpandTextSpace=True, tickTextOffset=4)

        self.p.getAxis('top').setTicks([])
        self.p.getAxis('top').setHeight(0)
        self.p.getAxis('right').setTicks([])

        self.x_axis = self.p.getAxis('bottom')
        self.y_axis = self.p.getAxis('left')

        self.x_axis.setLabel('Voltage', units='V', color='k', size='12pt')
        self.y_axis.setLabel('Current', units='A', color='k', size='12pt')
        self.y_axis.setStyle(tickTextWidth=35)

        # set auto range and mouse panning / zooming
        self.p.enableAutoRange(x=True, y=True)
        self.p.setLimits(xMin=-1e20, xMax=1e20, yMin=-1e20, yMax=1e20)

        def suggestPadding(axis):
            length = self.p.vb.width() if axis == 0 else self.p.vb.height()
            if length > 0:
                if axis == 0:
                    padding = 0
                else:
                    padding = np.clip(1. / (length**0.5), 0.02, 0.1)
            else:
                padding = 0.02
            return padding

        self.p.vb.suggestPadding = suggestPadding

        # set default ranges to start
        self.p.setXRange(-10, 10)
        self.p.setYRange(-10, 10)

        # add legend
        self.legend = LegendItem(brush=fn.mkBrush(255, 255, 255, 150),
                                 labelTextColor='k',
                                 offset=(20, -20))
        self.legend.setParentItem(self.p.vb)

    def clear(self):
        self.p.clear()  # clear current plot
        self.legend.clear()  # clear current legend

    def plot(self, sweep_data):
        self.clear()

        xdata = sweep_data.get_column(0)
        xdata_title = sweep_data.titles[0]
        ydata = sweep_data.values()[1:]

        # format plot according to sweep type
        unit = xdata_title.unit if xdata_title.has_unit() else 'a.u.'
        self.x_axis.setLabel(xdata_title.name, unit=unit)
        self.y_axis.setLabel('Current', unit='A')

        if sweep_data.params['sweep_type'] == 'transfer':
            self.setTitle('Transfer curve')
            self.p.setLogMode(x=False, y=True)
            self.legend.setOffset((20, -20))  # legend in bottom-left corner
            ydata = [np.abs(y) for y in ydata]

        elif sweep_data.params['sweep_type'] == 'output':
            self.setTitle('Output curve')
            self.p.setLogMode(x=False, y=False)
            self.legend.setOffset((-20, 20))  # legend in top-right corner
            ydata = [np.abs(y) for y in ydata]

        else:
            self.setTitle('Sweep curve')
            self.p.setLogMode(x=False, y=False)
            ydata = [np.abs(y) for y in ydata]

        # plot data
        self.lines = []
        for y, c in zip(ydata, itertools.cycle(self.COLORS)):
            p = self.p.plot(xdata, y, pen=fn.mkPen(color=c, width=self.LW))
            self.lines.append(p)

        # add legend
        for l, t in zip(self.lines, sweep_data.column_names[1:]):
            self.legend.addItem(l, str(t))

        self.p.autoRange()

    def setTitle(self, text, fontScaling=None, color=None, font=None):
        # work around pyqtplot which forces the title to be HTML
        if text is None:
            self.p.setTitle(None)  # clears title and hides title column
        else:
            self.p.setTitle(
                '')  # makes title column visible, sets placeholder text
            self.p.titleLabel.item.setPlainText(
                text)  # replace HTML with plain text

        if color is not None:
            color = fn.mkColor(color)
            self.p.titleLabel.item.setDefaultTextColor(color)

        if font is not None:
            self.p.titleLabel.item.setFont(font)

        if fontScaling is not None:
            font = self.p.titleLabel.item.font()
            defaultFontSize = QtWidgets.QLabel('test').font().pointSize()
            fontSize = round(defaultFontSize * fontScaling, 1)
            font.setPointSize(fontSize)
            self.p.titleLabel.item.setFont(font)
예제 #9
0
 def __init__(self, size=None, offset=None):
     LegendItem.__init__(self, size, offset)
예제 #10
0
    def __init__(self, main_loop):
        # noinspection PyArgumentList
        super(ProgramUI, self).__init__()
        uic.loadUi('ui/BrainGenDesktop.ui', self)
        # Setting application icon
        self.setWindowIcon(QIcon('icon/logo.png'))
        # Application main loop
        self.main_loop = main_loop
        # Getting software configuration from config.ini
        self.config = config_parser()
        self.config_com = self.config['COM_PORT']
        self.config_signal = self.config['SIGNAL']

        # Switch case for returned value from the generator
        self.response_switch = {'': config.gen_, 'aa': config.gen_aa}

        # Connect / disconnect button actions
        self.connection_btn.clicked.connect(self.gen_tgam_conn)
        # Set generator parameters button action
        self.signal_btn.clicked.connect(self.gen_signal_define)

        # Setting default values for signal amplitude and frequency from config.ini
        for signal in config.signal_input:
            getattr(self, signal).setValue(float(self.config_signal[signal]))

        # Activity plot style
        setConfigOption('background', '#FF000000')

        # Generating and displaying plots for EEG and Attention / Meditation rhythms
        for graph in config.graph_types:
            # Defining activity plot
            setattr(self, graph + '_drawing', PlotWidget())
            drawing = getattr(self, graph + '_drawing')
            drawing.setMenuEnabled(enableMenu=False)
            drawing.setMouseEnabled(x=False, y=False)
            drawing.showGrid(x=True, y=True)
            drawing.hideButtons()
            # Defining legend and applying it to the plot
            setattr(self, graph + '_legend', LegendItem(offset=(70, 30)))
            legend = getattr(self, graph + '_legend')
            legend.setParentItem(drawing.getPlotItem())

            for signal in getattr(config, graph + '_output'):
                # Defining activity curves and applying them to legend
                setattr(self, signal + '_curve', drawing.getPlotItem().plot())
                curve = getattr(self, signal + '_curve')
                legend.addItem(curve, ' '.join(signal.split('_')).title())
                # Curve checkbox view options
                getattr(self, signal + '_checkbox').clicked.connect(
                    lambda show, name=signal: self.graph_view_options(
                        show, name))

            # Setting activity box layout and adding activity plot to the program window
            setattr(self, graph + '_layout', QGridLayout())
            layout = getattr(self, graph + '_layout')
            graph_box = getattr(self, graph + '_graph')
            graph_box.setLayout(layout)
            layout.addWidget(drawing)
            # Setting the right-click context menu
            graph_box.setContextMenuPolicy(Qt.CustomContextMenu)
            graph_box.customContextMenuRequested.connect(
                lambda event, box=graph_box: self.graph_context_menu(
                    event, box))

        # Getting COM ports and filling interface with default values
        self.main_loop.create_task(self.async_get_ports())
        # Checking TGAM process
        self.tgam_checking = None

        # Initializing generator and TGAM serial connections in non-blocking mode
        self.serial_generator = Serial()
        self.serial_generator.timeout = 0
        self.serial_tgam = Serial()
        self.serial_tgam.timeout = 0
예제 #11
0
class Network(Base, metaclass=config.Singleton):
    """ Network performance measure """
    def __init__(self, base):
        super(Network, self).__init__(base)
        self._out_val = None
        self._inc_val = None

        self._plot()
        self._clear()

    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)

    def _set_value(self):
        """ Set send and receive value for the network performance curves """
        self._out_curve.setData(
            self._out_val,
            pen=mkPen(width=self._sw_config.net_perf_out_wd,
                      color=QColor(self._sw_config.net_perf_out_cl)))
        self._inc_curve.setData(
            self._inc_val,
            pen=mkPen(width=self._sw_config.net_perf_inc_wd,
                      color=QColor(self._sw_config.net_perf_inc_cl)))

    async def _load(self):
        """ Load the network performance measure - coroutine """
        if not self._sw_config.net_perf:
            return self._event.set()
        _old_out = 0
        _old_inc = 0
        while not self._event.is_set():
            _rev_out = net_io_counters().bytes_sent
            _rev_int = net_io_counters().bytes_recv
            if _old_out and _old_inc:
                self._out_val.append(_rev_out - _old_out)
                self._inc_val.append(_rev_int - _old_inc)
            self._set_value()
            _old_out = _rev_out
            _old_inc = _rev_int
            await sleep(self._sw_config.net_perf_tmo)

    def _popup_show(self, coordinate):
        """ Right-click popup menu in the graph area """
        self._menu_popup.exec_(self._base.net_perf_box.mapToGlobal(coordinate))

    def _clear(self):
        """ Clear the entire graph """
        self._out_val = deque([0] * self._sw_config.net_perf_len,
                              maxlen=self._sw_config.net_perf_len)
        self._inc_val = deque([0] * self._sw_config.net_perf_len,
                              maxlen=self._sw_config.net_perf_len)
        self._set_value()
예제 #12
0
@author: inox
"""
from pyaudio import paInt16, PyAudio
from struct import unpack
from pyqtgraph import GraphicsWindow, setConfigOptions, LegendItem, QtCore, QtGui
from numpy import fft, arange, split, argmax, floor
from scipy.signal import find_peaks as fpeaks

#Inicialización de ventana gráfica con los cuadros de visualización y el dicionario de trazas a graficar
win = GraphicsWindow(title="Analizador de Espectro")
win.setWindowTitle("Analizador de Espectro")
setConfigOptions(antialias=True, background='k')
scope = win.addPlot(title="Waveform", row=1, col=1)
span = win.addPlot(title="FFT", row=2, col=1)
traces = dict()
legend = LegendItem()


#Actualización (o inicialización) de las trazas de los cuadros de visualización
def set_plotdata(name, data_x, data_y):
    if name in traces:
        traces[name].setData(data_x, data_y)
    else:
        if name == 'waveform':
            traces[name] = scope.plot(pen='w', width=4)
            scope.setYRange(-2**(bits - 1), 2**(bits - 1), padding=0)
            scope.setXRange(t[0], t[-1], padding=0.00)
        if name == 'spectrum':
            traces[name] = span.plot(pen='c', width=4)
            span.setYRange(0, 500, padding=0)
            span.setXRange(F[0], 6e3, padding=0)