예제 #1
0
    def __init__(self, spec):
        super().__init__(None)
        self.spec = spec
        self.chart = QChart()
        # self.chart.setTitle(str(self.spec.variables))
        # self.chart.legend().hide()

        for i in range(len(self.spec.variables)):
            series = QLineSeries()
            series.setColor(
                QColor(
                    self.spec.colors[i][0],
                    self.spec.colors[i][1],
                    self.spec.colors[i][2],
                ))
            series.setName(self.spec.variables[i])
            self.chart.addSeries(series)

        self.setMinimumWidth(400)
        self.setMinimumHeight(230)

        self.setChart(self.chart)
        self.setRenderHint(QPainter.Antialiasing)
        self.chart.createDefaultAxes()
        self.autoscale_y_axis = True
        if self.spec.min_y and self.spec.max_y:
            self.autoscale_y_axis = False
            self.chart.axes()[1].setRange(self.spec.min_y, self.spec.max_y)

        self._updates_per_second = 60
        self._data = []
        self._min = 0
        self._max = 0
예제 #2
0
    def _get_processor_chart(self):  # type: (Display) -> QChartView
        # Create pen
        pen = QLineSeries().pen()
        pen.setColor(Qt.red)
        pen.setWidthF(1)

        # Series
        self._processor_series = QLineSeries()
        self._processor_series.setPen(pen)
        self._processor_series.useOpenGL()

        # Chart
        self._processor_chart = QChart()
        self._processor_chart.legend().hide()
        self._processor_chart.addSeries(self._processor_series)
        self._processor_chart.createDefaultAxes()
        self._processor_chart.axisX().setMax(100)
        self._processor_chart.axisX().setMin(0)
        self._processor_chart.axisY().setMax(5000)
        self._processor_chart.axisY().setMin(0)

        self._processor_x_axis = QValueAxis()
        self._processor_x_axis.setLabelFormat('%i')
        self._processor_chart.setAxisX(self._processor_x_axis,
                                       self._processor_series)

        self._processor_y_axis = QLogValueAxis()
        self._processor_y_axis.setLabelFormat('%g')
        self._processor_y_axis.setBase(8)

        # Chart View
        view = QChartView(self._processor_chart)
        view.setRenderHint(QPainter.Antialiasing)
        view.setStyleSheet('margin: 0px; height: 250%; width: 400%;')
        return view
예제 #3
0
    def _get_connector_chart(self):  # type: (Display) -> QChartView
        # Create pen
        pen = QLineSeries().pen()
        pen.setColor(Qt.blue)
        pen.setWidthF(1)

        # Series
        self._connector_series = QLineSeries()
        self._connector_series.setPen(pen)
        self._connector_series.useOpenGL()

        # Chart
        self._connector_chart = QChart()
        self._connector_chart.legend().hide()
        self._connector_chart.addSeries(self._connector_series)
        self._connector_chart.createDefaultAxes()
        self._connector_chart.axisX().setMax(100)
        self._connector_chart.axisX().setMin(0)
        self._connector_chart.axisY().setMax(500)
        self._connector_chart.axisY().setMin(-500)

        # Chart View
        view = QChartView(self._connector_chart)
        view.setRenderHint(QPainter.Antialiasing)
        view.setStyleSheet('margin: 0px; height: 250%; width: 400%;')
        return view
 def add_new_data(self, data: dict):
     self.x += self.time.msec()
     self.time.start()
     if self.x > 10000:
         self.ax.setRange(self.x - 10000, self.x)
     for key in data:
         try:
             value = float(data[key])
         except ValueError:
             continue
         if value > self.ymax:
             self.ymax = value
             self.ay.setRange(self.ymin, self.ymax)
         elif value < self.ymin:
             self.ymin = value
             self.ay.setRange(self.ymin, self.ymax)
         if key in self.lines:
             if self.lines[key].__len__() >= 32:
                 # self.lines[key].replace(0,self.x, value)
                 self.lines[key].remove(0)
             # else:
             self.lines[key].append(self.x, value)
         else:
             # ls = QSplineSeries(self)
             ls = QLineSeries(self)
             ls.append(self.x, value)
             ls.setColor(
                 QColor(random.randint(0, 255), random.randint(0, 255),
                        random.randint(0, 255)))
             ls.setName(key)
             self.chart().addSeries(ls)
             self.chart().setAxisX(self.ax, ls)
             self.chart().setAxisY(self.ay, ls)
             self.lines[key] = ls
    def createSeries(self, dataArray):
        series = QLineSeries()
        for i in range(len(dataArray)):
            value = QPointF(i, dataArray[i][0])
            series.append(value)

        series.setColor(QColor(0, 255, 0))
        self.removeSeries()
        series.setName("灰度图")
        self.qchart.addSeries(series)

        self.lastSeries = series
예제 #6
0
    def addSeries(
            self, _x2idx: typing.Dict, _idx2x: list, _chart: QChart,
            _axis_x: QValueAxis, _axis_y: QValueAxis
    ):
        series = QLineSeries()
        series.setName(self.name)
        for x, y in zip(self.x_list, self.y_list):
            series.append(_x2idx[x], y)
        if self.color is not None:
            series.setColor(self.color)

        _chart.addSeries(series)
        _chart.setAxisX(_axis_x, series)
        _chart.setAxisY(_axis_y, series)

        if self.show_value:
            self.createShow()
예제 #7
0
    def InitGui(self):
        self.setWindowTitle("Line Chart")
        self.setGeometry(100,200,800,600)

        series = QLineSeries()
        series.setColor(QColor('red'))

        seriesA = QLineSeries()
        seriesA.setColor(QColor('green'))



        for i in range(1,20):
            series.append(10*i,20+i*i*8-3*i)
            seriesA.append(10*i, 6-i*i*2+5*i)


        chart = QChart()
        chart.addSeries(series)
        chart.addSeries(seriesA)
        chart.setAnimationOptions(chart.SeriesAnimations)
        chart.setAnimationDuration(1000)
        chart.setTitle("Line Chart")
        chart.legend().setVisible(True)
        chart.legend().setAlignment(Qt.AlignBottom)



        view = QChartView(chart)
        view.setRenderHint(QPainter.Antialiasing)




        vbox = QVBoxLayout()
        vbox.addWidget(view)
        root = QWidget()
        root.setLayout(vbox)

        self.setCentralWidget(root)
        pass
    def create_rgb_Series(self, dataArray):

        series = []
        colors = [QColor(255, 0, 0), QColor(0, 255, 0), QColor(0, 0, 255)]
        names = ['红', '绿', '蓝']
        for i in range(len(dataArray)):
            serie = QLineSeries()
            for j in range(len(dataArray[i])):
                value = QPointF(j, dataArray[i][j][0])
                serie.append(value)
            serie.setColor(colors[i])
            serie.setName(names[i])
            series.append(serie)

        for ser in series:
            self.qchart.addSeries(ser)
            # 先将旧的rgb线移除

        self.removeSeries()

        self.lastSeries = series
    def setupChart(self):
        """Set up the GUI's graph series type, chart instance, chart axes, 
        and chart view widget."""
        random.seed(50) # Create seed for random numbers

        # Create the model instance and set the headers
        self.model = QStandardItemModel()
        self.model.setColumnCount(3)
        self.model.setHorizontalHeaderLabels(["Year", "Social Exp. %GDP", "Country"])

        # Collect x and y data values and labels from the CSV file
        xy_data_and_labels = self.loadCSVFile()

        # Create the individual lists for x, y and labels values
        x_values, y_values, labels = [], [], []
        # Append items to the corresponding lists
        for item in range(len(xy_data_and_labels)):
            x_values.append(xy_data_and_labels[item][0])
            y_values.append(xy_data_and_labels[item][1])
            labels.append(xy_data_and_labels[item][2])

        # Remove all duplicates from the labels list using list comprehension. 
        # This list will be used to create the labels in the chart's legend.
        set_of_labels = []
        [set_of_labels.append(x) for x in labels if x not in set_of_labels]  
    
        # Create chart object
        self.chart = QChart()
        self.chart.setTitle("Public Social Spending as a Share of GDP, 1880 to 2016")
        self.chart.legend().hide() # Hide legend at the start

        # Specify parameters for the x and y axes
        self.axis_x = QValueAxis()
        self.axis_x.setLabelFormat("%i")
        self.axis_x.setTickCount(10)
        self.axis_x.setRange(1880, 2016)
        self.chart.addAxis(self.axis_x, Qt.AlignBottom)

        self.axis_y = QValueAxis()
        self.axis_y.setLabelFormat("%i" + "%")
        self.axis_y.setRange(0, 40)
        self.chart.addAxis(self.axis_y, Qt.AlignLeft)

        # Create a Python dict to associate the labels with the individual line series
        series_dict = {}

        for label in set_of_labels:
            # Create labels from data and add them to a Python dictionary
            series_label = 'series_{}'.format(label)
            series_dict[series_label] = label # Create label value for each line series

        # For each of the keys in the dict, create a line series
        for keys in series_dict.keys():
            # Use get() to access the corresponding value for a key
            label = series_dict.get(keys)

            # Create line series instance and set its name and color values
            line_series = QLineSeries()
            line_series.setName(label)
            line_series.setColor(QColor(random.randint(10, 254), random.randint(10, 254), random.randint(10, 254)))

            # Append x and y coordinates to the series
            for value in range(len(xy_data_and_labels)):
                if line_series.name() == xy_data_and_labels[value][2]:
                    line_series.append(x_values[value], y_values[value])

                    # Create and add items to the model (for displaying the table)
                    items = [QStandardItem(str(item)) for item in xy_data_and_labels[value]]
                    color = line_series.pen().color()
                    for item in items:
                        item.setBackground(color)
                    self.model.insertRow(value, items)

            self.chart.addSeries(line_series)
            line_series.attachAxis(self.axis_x)
            line_series.attachAxis(self.axis_y)   

        # Create QChartView object for displaying the chart 
        self.chart_view = ChartView(self.chart)
        self.setCentralWidget(self.chart_view)
        def __init__(self, parent=None):
            super(Widget, self).__init__(parent)
            self.setWindowTitle('Financieële grafieken externe werken')
            self.setWindowIcon(QIcon('./images/logos/logo.jpg'))
            self.setWindowFlags(self.windowFlags() | Qt.WindowSystemMenuHint
                                | Qt.WindowMinMaxButtonsHint)

            grid = QGridLayout()
            grid.setSpacing(20)

            metadata = MetaData()
            resultaten = Table('resultaten', metadata,
                               Column('resID', Integer(), primary_key=True),
                               Column('statusweek', String),
                               Column('btotaal', Float),
                               Column('wtotaal', Float),
                               Column('betaald_bedrag', Float),
                               Column('meerminderwerk', Float),
                               Column('onderhandenwerk', Float),
                               Column('aanneemsom', Float),
                               Column('blonen', Float),
                               Column('wlonen', Float),
                               Column('bmaterialen', Float),
                               Column('wmaterialen', Float),
                               Column('bmaterieel', Float),
                               Column('wmaterieel', Float),
                               Column('bprojectkosten', Float),
                               Column('wprojectkosten', Float),
                               Column('binhuur', Float),
                               Column('winhuur', Float),
                               Column('bdiensten', Float),
                               Column('wdiensten', Float),
                               Column('bruto_winst', Float),
                               Column('boekweek', String))
            params = Table('params', metadata,
                           Column('paramID', Integer(), primary_key=True),
                           Column('tarief', String))
            engine = create_engine(
                'postgresql+psycopg2://postgres@localhost/bisystem')
            con = engine.connect()

            selpar1 = select([params]).where(params.c.paramID == 97)
            rppar1 = con.execute(selpar1).first()
            bo_incr = rppar1[1] / 52  #begrote omzet per week
            selpar2 = select([params]).where(params.c.paramID == 98)
            rppar2 = con.execute(selpar2).first()
            bw_incr = rppar2[1] / 52  #begrote winst per week

            jaar = jrwk[0:4]
            engine = create_engine(
                'postgresql+psycopg2://postgres@localhost/bisystem')
            con = engine.connect()
            selres = select([resultaten]).where(and_(resultaten.c.boekweek == jrwk,\
              resultaten.c.statusweek.like(jaar+'%'))).order_by(resultaten.c.statusweek)
            rpres = con.execute(selres)
            if keuze == '1':
                s1 = 2
                s2 = 3
                t1 = 'Kosten totaal begroot'
                t2 = 'Kosten totaal werkelijk'
                t3 = 'Kosten totaal '
                c1 = Qt.red
                c2 = Qt.blue
                ysch = 160000000
            elif keuze == '2':
                s1 = 8
                s2 = 9
                t1 = 'Lonen begroot'
                t2 = 'Lonen werkelijk'
                t3 = 'Lonen '
                c1 = Qt.green
                c2 = Qt.darkBlue
                ysch = 100000000
            elif keuze == '3':
                s1 = 10
                s2 = 11
                t1 = 'Materialen begroot'
                t2 = 'Materialen werkelijk'
                t3 = 'Materialen'
                c1 = Qt.cyan
                c2 = Qt.magenta
                ysch = 60000000
            elif keuze == '4':
                s1 = 12
                s2 = 13
                t1 = 'Materiëel begroot'
                t2 = 'Materiëel werkelijk'
                t3 = 'Materiëel '
                c1 = Qt.darkYellow
                c2 = Qt.darkGreen
                ysch = 20000000
            elif keuze == '5':
                s1 = 16
                s2 = 17
                t1 = 'Inhuur begroot'
                t2 = 'Inhuur werkelijk'
                t3 = 'Inhuur '
                c1 = Qt.darkBlue
                c2 = Qt.darkRed
                ysch = 30000000
            elif keuze == '6':
                s1 = 18
                s2 = 19
                t1 = 'Diensten begroot'
                t2 = 'Diensten werkelijk'
                t3 = 'Diensten '
                c1 = Qt.red
                c2 = Qt.blue
                ysch = 30000000
            elif keuze == '7':
                s1 = 14
                s2 = 15
                t1 = 'Projektkosten begroot'
                t2 = 'Projektkosten werkelijk'
                t3 = 'Projektkosten '
                c1 = Qt.darkYellow
                c2 = Qt.darkCyan
                ysch = 10000000
            elif keuze == '8':
                y3 = [
                    0,
                ]
                y3val = 0
                x1 = [
                    0,
                ]
                xval1 = 0
                # prognose winst
                for teller in range(0, 53):
                    y3val = y3val + bw_incr
                    y3 = y3 + [(y3val)]
                    xval1 = xval1 + 1
                    x1 = x1 + [(xval1)]
                s1 = 20
                s2 = 20
                t1 = 'Bruto winst prognose'
                t2 = 'Bruto winst actueel'
                t3 = 'Bruto winst - prognose / aktueel '
                c1 = Qt.darkCyan
                c2 = Qt.darkMagenta
                ysch = 20000000
            elif keuze == '9':
                s1 = 6
                s2 = 4
                t1 = 'Onderhandenwerk'
                t2 = 'Betaald bedrag'
                t3 = 'Onderhandenwerk - Betaald bedrag '
                c1 = Qt.yellow
                c2 = Qt.green
                ysch = 160000000
            elif keuze == 'A':
                y4 = [
                    0,
                ]
                y4val = 0
                x2 = [
                    0,
                ]
                xval2 = 0
                #prognose omzet
                for teller in range(0, 53):
                    y4val = y4val + bo_incr
                    y4 = y4 + [(y4val)]
                    xval2 = xval2 + 1
                    x2 = x2 + [(xval2)]
                s1 = 7
                s2 = 7
                t1 = 'Omzet prognose'
                t2 = 'Omzet aktueel'
                t3 = 'Omzet '
                c1 = Qt.red
                c2 = Qt.blue
                ysch = 160000000
            elif keuze == 'B':
                s1 = 20
                s2 = 5
                t1 = 'Bruto winst werkelijk'
                t2 = 'Meerminderwerk'
                t3 = 'Bruto winst werkelijk / Meerminderwerk '
                c1 = Qt.darkRed
                c2 = Qt.darkBlue
                ysch = 30000000

            x = [
                0,
            ]
            y1 = [
                0,
            ]
            y2 = [
                0,
            ]
            idx = 0
            yval1 = 0
            yval2 = 0
            for row in rpres:
                yval1 = y1[idx] + row[s1]
                y1 = y1 + [(yval1)]
                yval2 = y2[idx] + row[s2]
                y2 = y2 + [(yval2)]
                x = x + [(int(row[1][4:]))]
                idx += 1

            series1 = QLineSeries()
            if keuze == '8':
                for t, val in zip(x1, y3):
                    series1.append(int(t), val)
            elif keuze == 'A':
                for t, val in zip(x2, y4):
                    series1.append(int(t), val)
            else:
                for t, val in zip(x, y1):
                    series1.append(int(t), val)
            series2 = QLineSeries()
            for t, val in zip(x, y2):
                series2.append(int(t), val)

            chart = QChart()
            chart.addSeries(series1)
            chart.addSeries(series2)

            series1.setColor(QColor(c1))
            series2.setColor(QColor(c2))
            series1.setName(t1)
            series2.setName(t2)
            chart.legend().setVisible(True)

            font = QFont()
            font.setPixelSize(22)
            chart.setTitleFont(font)
            chart.setTitle(t3 + jaar)
            chart.setTitleBrush(QBrush(Qt.black))
            chart.legend().setLabelBrush(QColor(Qt.black))

            axisX = QCategoryAxis()
            axisY = QCategoryAxis()

            axisX.setTitleText('Jaar ' + jaar + ' - Weeknummers')
            axisX.setTitleBrush(QBrush(Qt.black))
            font = QFont("Sans Serif")
            axisX.setTitleFont(font)

            axisPen = QPen(QColor(100, 100, 100))  # 100,100,100
            axisPen.setWidth(3)
            axisX.setLinePen(axisPen)
            axisY.setLinePen(axisPen)

            axisBrush = QBrush(Qt.black)
            axisX.setLabelsBrush(axisBrush)
            axisY.setLabelsBrush(axisBrush)

            axisX.setGridLineVisible(False)
            axisY.setGridLineVisible(True)
            axisX.setShadesBrush(QBrush(QColor(245, 245, 245)))
            axisX.setShadesVisible(True)
            for x in range(1, 54):
                axisX.append(jaar + "-" + ("0" + str(x))[-2:], x)
            axisX.setRange(0, 53)
            axisX.setLabelsAngle(-90)

            axisY = QValueAxis()
            axisY.setTickCount(33)
            axisY.setTitleText("Bedragen in Euro")
            axisY.setTitleFont(font)
            axisY.setLabelFormat('%d')
            axisY.setTitleBrush(QBrush(Qt.black))
            axisY.setRange(0, ysch)  #disable for automatic Y scale
            #axisY.applyNiceNumbers() #enable by automatic Y scale

            Lfont = QFont("Sans Serif")
            Dfont = QFont("Sans Serif")
            Lfont.setPixelSize(10)
            Dfont.setPixelSize(10)
            axisX.setLabelsFont(Dfont)
            axisY.setLabelsFont(Lfont)

            axisPen = QPen(QColor('black'))
            axisPen = QPen()
            axisPen.setWidth(2)
            axisX.setLinePen(axisPen)
            axisX.setLabelsColor(QColor('black'))
            axisY.setLinePen(axisPen)
            axisY.setLabelsColor(QColor('black'))

            chart.addAxis(axisX, Qt.AlignBottom)
            series1.attachAxis(axisX)
            axisX.setLabelsAngle(-90)

            chart.addAxis(axisY, Qt.AlignLeft)
            series1.attachAxis(axisY)
            series2.attachAxis(axisY)

            self.chartView = QChartView(chart)
            self.chartView.setRenderHint(QPainter.Antialiasing)

            buttonPreview = QPushButton('Afdrukvoorbeeld')
            buttonPreview.clicked.connect(self.handle_preview)
            buttonPreview.setStyleSheet(
                "color: black;  background-color: gainsboro")
            buttonPrint = QPushButton('Printen')
            buttonPrint.clicked.connect(self.handle_print)
            buttonPrint.setStyleSheet(
                "color: black;  background-color: gainsboro")
            buttonSluit = QPushButton('Sluiten')
            buttonSluit.clicked.connect(lambda: sluit(self, m_email))
            buttonSluit.setStyleSheet(
                "color: black;  background-color: gainsboro")
            grid.addWidget(self.chartView, 0, 0, 0, 3)
            grid.addWidget(buttonSluit, 1, 0)
            grid.addWidget(buttonPrint, 1, 1)
            grid.addWidget(buttonPreview, 1, 2)

            self.setLayout(grid)
            self.setGeometry(200, 40, 1395, 930)
예제 #11
0
class RectZoomMoveView(QChartView):
    """
    Filter data to be displayed in rectangular body
    """

    rangeSig = pyqtSignal(list)

    def __init__(self, parent=None):
        super(RectZoomMoveView, self).__init__(parent)
        self.setChart(QChart())
        self.chart().setMargins(QMargins(5, 5, 5, 5))
        self.chart().setContentsMargins(-10, -10, -10, -10)
        self.chart().setTitle(" ")
        self.relationState = True

        # Define two rectangles for background and drawing respectively
        self.parentRect = QGraphicsRectItem(self.chart())

        self.parentRect.setFlag(QGraphicsItem.ItemClipsChildrenToShape, True)
        self.parentRect.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
        self.RangeItem = RectRangeItem(parent=self.parentRect)
        self.RangeItem.setZValue(998)
        pen = QPen(Qt.gray)
        pen.setWidth(1)
        self.parentRect.setPen(pen)
        self.parentRect.setZValue(997)

        self.scene().addItem(self.parentRect)
        self.scene().addItem(self.RangeItem)

        self.RangeItem.hide()
        self.m_chartRectF = QRectF()
        self.m_rubberBandOrigin = QPointF(0, 0)
        self.dataLength = 0

        self.RangeItem.selectedChange.connect(self.changeFromRectItem)

        self.BtnsWidget = ViewButtonsWidget(self)
        self.BtnsWidget.refreshBtn.clicked.connect(self.updateView)
        self.BtnsWidget.RelationSig.connect(self.setRelationState)
        self.BtnsWidget.dateRangeEdit.dateRangeSig.connect(self.changDateRect)

    def changDateRect(self, daterange):
        if self.chartTypes == "Bar":
            v = 3
        else:
            v = 2
        l = len(self.RangeItem.rangePoints)
        if l > 2:
            try:
                num = self.mintimeData.date().daysTo(daterange[0])
                left = self.RangeItem.rangePoints[num]
                num = self.mintimeData.date().daysTo(daterange[1])
                right = self.RangeItem.rangePoints[num]
                rect = self.chart().plotArea()
                rect.setLeft(left)
                rect.setRight(right)
            except:
                rect = self.chart().plotArea()
            self.RangeItem.setRect(rect)
            self.RangeItem.updateHandlesPos()
        else:
            try:
                num = self.mintimeData.date().daysTo(daterange[0])
                left = self.RangeItem.rangePoints[num]
                num = self.mintimeData.date().daysTo(daterange[0])
                right = self.RangeItem.rangePoints[num]
                rect = self.chart().plotArea()
                rect.setLeft(left)
                rect.setRight(right)
            except:
                rect = self.chart().plotArea()
            self.RangeItem.setRect(rect)
            self.RangeItem.updateHandlesPos()

    def lineSpace(self, start, end, num):
        res = []
        if self.chartTypes == "Bar":
            step = (end - start) / (num)
            for i in range(num + 2):
                res.append(start + i * step)
        else:
            step = (end - start) / (num - 1)
            for i in range(num + 1):
                res.append(start + i * step)
        return res

    def getRangePoints(self):
        count = self.zoomSeries.count()
        rect = self.chart().plotArea()
        left = rect.left()
        right = rect.right()
        if count == 0:
            self.RangeItem.rangePoints = [left, right]
        else:
            # Get coordinate position for each node
            self.RangeItem.rangePoints = self.lineSpace(left, right, count)

    def setRangeColor(self, color):
        self.RangeItem.setRangeColor(color)

    def setRelationState(self, state):
        self.relationState = state

    def initSeries(self, chartTypes="Bar"):
        self.chartTypes = chartTypes
        axisX = QDateTimeAxis()
        axisX.setFormat("yyyy-MM-dd")
        self.zoomSeries = QLineSeries(self.chart())
        self.chart().addSeries(self.zoomSeries)
        self.chart().setAxisY(QValueAxis(), self.zoomSeries)
        self.chart().setAxisX(axisX, self.zoomSeries)
        self.initView()

    def clearAll(self):
        # Clear all series and axes
        self.chart().removeAllSeries()
        axess = self.chart().axes()
        for axes in axess:
            self.chart().removeAxis(axes)

    def setData(self, timeData, valueData, chartTypes="Bar"):
        axisX = QDateTimeAxis()
        axisX.setFormat("yyyy-MM-dd")

        if self.chartTypes == "Bar":
            # Clear all series
            self.clearAll()
            self.zoomSeries = QLineSeries(self.chart())
            barSeries = QBarSeries(self.chart())
            barset = QBarSet("data")
            barSeries.setBarWidth(0.8)
            barSeries.append(barset)
            for td, vd in zip(timeData, valueData):
                self.zoomSeries.append(td.toMSecsSinceEpoch(), vd)
            barset.append(valueData)
            self.zoomSeries.hide()
            self.chart().addSeries(self.zoomSeries)
            self.chart().addSeries(barSeries)
            self.chart().setAxisY(QValueAxis(), self.zoomSeries)
            axisX.setRange(min(timeData), max(timeData))
            self.chart().setAxisX(axisX, self.zoomSeries)
        elif self.chartTypes == "Scatter":
            # Clear all series
            self.clearAll()
            self.zoomSeries = QLineSeries(self.chart())
            scattSeries = QScatterSeries(self.chart())
            scattSeries.setMarkerSize(8)

            for td, vd in zip(timeData, valueData):
                self.zoomSeries.append(td.toMSecsSinceEpoch(), vd)
                scattSeries.append(td.toMSecsSinceEpoch(), vd)
            self.zoomSeries.hide()
            self.chart().addSeries(self.zoomSeries)
            self.chart().addSeries(scattSeries)
            self.chart().setAxisY(QValueAxis(), self.zoomSeries)
            axisX.setRange(min(timeData), max(timeData))
            self.chart().setAxisX(axisX, self.zoomSeries)
        elif self.chartTypes in ["Line", "PLine"]:
            self.clearAll()
            if self.chartTypes == "Line":
                self.zoomSeries = QLineSeries(self.chart())
            else:
                self.zoomSeries = QSplineSeries(self.chart())
            for td, vd in zip(timeData, valueData):
                self.zoomSeries.append(td.toMSecsSinceEpoch(), vd)
            self.chart().addSeries(self.zoomSeries)

            self.chart().setAxisY(QValueAxis(), self.zoomSeries)
            axisX.setRange(min(timeData), max(timeData))
            self.chart().setAxisX(axisX, self.zoomSeries)
        elif self.chartTypes == "Area":

            self.clearAll()
            self.zoomSeries = QLineSeries()
            self.zoomSeries.setColor(QColor("#666666"))
            for td, vd in zip(timeData, valueData):
                self.zoomSeries.append(td.toMSecsSinceEpoch(), vd)

            areaSeries = QAreaSeries(self.zoomSeries, None)

            self.chart().addSeries(self.zoomSeries)
            self.chart().addSeries(areaSeries)
            self.chart().setAxisY(QValueAxis(), areaSeries)
            axisX.setRange(min(timeData), max(timeData))
            self.chart().setAxisX(axisX, areaSeries)
            self.zoomSeries.hide()
        self.mintimeData = min(timeData)
        self.maxtimeData = max(timeData)
        self.BtnsWidget.dateRangeEdit.setDateRange([
            self.mintimeData.toString("yyyy-MM-dd"),
            self.maxtimeData.toString("yyyy-MM-dd"),
        ])
        self.updateView()

    def resetView(self):

        rect = self.chart().plotArea()
        self.parentRect.setRect(rect)
        topRight = self.chart().plotArea().topRight()
        x = int(topRight.x())
        y = int(topRight.y())
        self.BtnsWidget.setGeometry(QRect(x - 420, 0, 420, 23))
        self.RangeItem.setRect(rect)
        self.RangeItem.show()
        self.save_current_rubber_band()
        self.RangeItem.updateHandlesPos()
        self.apply_nice_numbers()
        self.getRangePoints()
        self.sendRang()

    def initView(self):
        self.RangeItem.hide()
        # Hide y-axis
        if self.chart().axisY():
            self.chart().axisY().setVisible(False)
        if self.chart().axisX():
            self.chart().axisX().setGridLineVisible(False)
        self.m_chartRectF = QRectF()
        self.m_rubberBandOrigin = QPointF(0, 0)
        self.getRangePoints()

    def updateView(self):
        self.RangeItem.hide()
        # Hide y-axis
        if self.chart().axisY():
            self.chart().axisY().setVisible(False)
        if self.chart().axisX():
            self.chart().axisX().setGridLineVisible(False)
        self.m_chartRectF = QRectF()
        self.m_rubberBandOrigin = QPointF(0, 0)
        self.resetView()

    # Map points to chart
    def point_to_chart(self, pnt):
        scene_point = self.mapToScene(pnt)
        chart_point = self.chart().mapToValue(scene_point)
        return chart_point

    # Map chart to points
    def chart_to_view_point(self, char_coord):
        scene_point = self.chart().mapToPosition(char_coord)
        view_point = self.mapFromScene(scene_point)
        return view_point

    # Save positions of rectangles
    def save_current_rubber_band(self):
        rect = self.RangeItem.rect()

        chart_top_left = self.point_to_chart(rect.topLeft().toPoint())
        self.m_chartRectF.setTopLeft(chart_top_left)

        chart_bottom_right = self.point_to_chart(rect.bottomRight().toPoint())
        self.m_chartRectF.setBottomRight(chart_bottom_right)

    # Respond to change in positions of rectangles
    def changeFromRectItem(self, rectIndex):
        self.save_current_rubber_band()
        self.sendRang(rectIndex)

    def sendRang(self, rectIndex=[]):

        if self.RangeItem.rect() != self.parentRect.rect():
            self.BtnsWidget.setPalActive()
        else:
            self.BtnsWidget.setPalDisActive()
        if self.chartTypes == "Bar":
            v = 3
        else:
            v = 2
        if rectIndex == []:
            maxData = QDateTime.fromMSecsSinceEpoch(
                self.zoomSeries.at(len(self.RangeItem.rangePoints) - v).x())
            minData = QDateTime.fromMSecsSinceEpoch(self.zoomSeries.at(0).x())
        else:
            minData = max(rectIndex[0], 0)
            maxData = min(rectIndex[1], len(self.RangeItem.rangePoints) - v)
            minData = QDateTime.fromMSecsSinceEpoch(
                self.zoomSeries.at(minData).x())
            maxData = QDateTime.fromMSecsSinceEpoch(
                self.zoomSeries.at(maxData).x())

        if minData > maxData:
            if self.RangeItem.handleSelected is None:
                self.resetView()
        else:
            self.BtnsWidget.dateRangeEdit.setDate([
                minData.toString("yyyy-MM-dd"),
                maxData.toString("yyyy-MM-dd")
            ])
            if self.relationState:
                self.rangeSig.emit([
                    minData.toString("yyyy-MM-dd HH:mm:ss"),
                    maxData.toString("yyyy-MM-dd HH:mm:ss"),
                ])

    # Change positions of rectangles in scaling
    def resizeEvent(self, event):
        super().resizeEvent(event)
        rect = self.chart().plotArea()
        self.parentRect.setRect(rect)
        self.getRangePoints()
        topRight = self.chart().plotArea().topRight()
        x = int(topRight.x())
        y = int(topRight.y())
        self.BtnsWidget.setGeometry(QRect(x - 420, 0, 420, 23))
        if self.RangeItem.isVisible():
            self.restore_rubber_band()
            self.save_current_rubber_band()
            self.RangeItem.updateHandlesPos()
        else:
            self.RangeItem.setRect(self.parentRect.rect())
            self.RangeItem.show()
            self.RangeItem.setRect(self.parentRect.rect())
            self.save_current_rubber_band()
            self.RangeItem.updateHandlesPos()
        self.apply_nice_numbers()

    # Restore to original positions of rectangles
    def restore_rubber_band(self):
        view_top_left = self.chart_to_view_point(self.m_chartRectF.topLeft())
        view_bottom_right = self.chart_to_view_point(
            self.m_chartRectF.bottomRight())

        self.m_rubberBandOrigin = view_top_left
        height = self.chart().plotArea().height()
        rect = QRectF()
        rect.setTopLeft(view_top_left)
        rect.setBottomRight(view_bottom_right)
        rect.setHeight(height)
        self.RangeItem.setRect(rect)

    # Adjust display coordinates of axes automatically
    def apply_nice_numbers(self):
        axes_list = self.chart().axes()
        for value_axis in axes_list:
            if value_axis:
                pass
예제 #12
0
class Widget(QWidget):
    def __init__(self):
        super().__init__()
        self.setMinimumSize(800, 600)

        self.setWindowTitle("Rectifier")

        self.chartView = QChartView()
        self.chart = self.chartView.chart()
        self.series = QLineSeries()
        self.series2 = QLineSeries()
        self.series2.setColor(QColor('red'))

        # for i in range(-90, 90):  # rectifier
        #     x = i * pi / 50
        #     print('x', x)
        #     y = sin(x)
        #     print('y', abs(y))
        #     self.series.append(x, abs(y))

        x = [None] * 400
        for n in range(-200, 200):
            t = n / 100
            if t >= -2 and t <= -1:
                x[n] = 0
            elif t >= -1 and t <= 1:
                x[n] = 1
            elif t >= 1 and t <= 2:
                x[n] = 0
            self.series2.append(t, x[n])

        self.chart.addSeries(self.series)
        self.chart.addSeries(self.series2)

        self.chart.legend().hide()

        def format_axis(axis, min_value, max_value, step):
            for s in axis.categoriesLabels():
                axis.remove(s)
            axis.setStartValue(min_value)
            for i in range(ceil(min_value / step),
                           floor(max_value / step) + 1):
                v = i * step
                axis.append('%s' % v, v)
            axis.setRange(min_value, max_value)
            grid_pen = QPen(QColor('silver'))
            grid_pen.setDashPattern([1, 1, 1, 1, 0, 0, 0, 0])
            #grid_pen.setDashPattern([1, 1, 0, 0])
            axis.setGridLinePen(grid_pen)

        self.chart.createDefaultAxes()

        self.chart.axisX().setRange(-5, 5)
        self.chart.axisX().setGridLineVisible(False)
        self.chartAxisX = QCategoryAxis(
            labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue,
            startValue=0.0)
        self.chart.setAxisX(self.chartAxisX)
        format_axis(self.chartAxisX, -5, 5, 1)

        self.chart.axisY().setRange(-0.1, 1.3)
        self.chartAxisY = QCategoryAxis(
            labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue,
            startValue=0.0)
        self.chart.setAxisY(self.chartAxisY)
        format_axis(self.chartAxisY, -0.1, 1.3, 1)

        self.layout = QGridLayout(self)
        self.layout.addWidget(self.chartView, 1, 1)
        self.chartView.show()
        self.setLayout(self.layout)
예제 #13
0
class AmzHistoryChart(QWidget):
    """A chart that graphs the history of an AmazonListing's sales rank, price, and number of offers."""

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

        self.dbsession = Session()
        self.context_menu_actions = []
        self._avg_pointspan = 0
        self._max_points = 100
        self.source = None
        self.history = None

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

        # Set up the chart
        self.chart_view = QChartView(self)
        self.chart_view.setRenderHint(QPainter.Antialiasing)
        self.chart_view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.chart_view.customContextMenuRequested.connect(self.context_menu)

        self.chart = QChart()
        self.chart.legend().hide()
        self.chart.setFlags(QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsSelectable)
        self.chart.installEventFilter(self)
        self.chart_view.setChart(self.chart)

        self.layout().addWidget(self.chart_view)

        # Create the axes
        rcolor = QColor(50, 130, 220)
        pcolor = QColor(0, 200, 0)
        ocolor = QColor(255, 175, 0)

        self.timeAxis = QDateTimeAxis()
        self.timeAxis.setFormat('M/dd hh:mm')
        self.timeAxis.setTitleText('Date/Time')
        self.chart.addAxis(self.timeAxis, Qt.AlignBottom)

        self.timeAxis.minChanged.connect(self.on_timeaxis_min_changed)

        self.rankAxis = QValueAxis()
        self.rankAxis.setLabelFormat('%\'i')
        self.rankAxis.setTitleText('Sales Rank')
        self.rankAxis.setLinePenColor(rcolor)
        self.rankAxis.setLabelsColor(rcolor)
        self.chart.addAxis(self.rankAxis, Qt.AlignLeft)

        self.priceAxis = QValueAxis()
        self.priceAxis.setLabelFormat('$%.2f')
        self.priceAxis.setTitleText('Price')
        self.priceAxis.setLinePenColor(pcolor)
        self.priceAxis.setLabelsColor(pcolor)
        self.chart.addAxis(self.priceAxis, Qt.AlignRight)

        # Create the series
        self.rankLine = QLineSeries()
        self.chart.addSeries(self.rankLine)
        self.rankLine.attachAxis(self.timeAxis)
        self.rankLine.attachAxis(self.rankAxis)
        self.rankLine.setColor(rcolor)

        self.priceLine = QLineSeries()
        self.chart.addSeries(self.priceLine)
        self.priceLine.attachAxis(self.timeAxis)
        self.priceLine.attachAxis(self.priceAxis)
        self.priceLine.setColor(pcolor)

        self.salesPoints = QScatterSeries()
        self.chart.addSeries(self.salesPoints)
        self.salesPoints.attachAxis(self.timeAxis)
        self.salesPoints.attachAxis(self.rankAxis)
        self.salesPoints.setColor(ocolor)

    def add_context_action(self, action):
        """Add an action to the chart's context menu."""
        self.context_menu_actions.append(action)

    def add_context_actions(self, actions):
        """Adds all action in an iterable."""
        self.context_menu_actions.extend(actions)

    def remove_context_action(self, action):
        """Removes an action from the chart's context menu."""
        self.context_menu_actions.remove(action)

    def context_menu(self, point):
        """Show a context menu on the chart."""
        menu = QMenu(self)
        menu.addActions(self.context_menu_actions)

        point = self.chart_view.viewport().mapToGlobal(point)
        menu.popup(point)

    def set_source(self, source):
        """Set the source listing for the graph."""
        self.source = source

        # Update the chart
        self.rankLine.clear()
        self.priceLine.clear()
        self.salesPoints.clear()
        self.history = None

        start_date = datetime.utcnow() - timedelta(days=5)
        self.load_history_from(start_date)

        self.reset_axes()

    def load_history_from(self, start_date=datetime.utcfromtimestamp(0)):
        """Load history data from start-present."""
        if not self.source:
            self._avg_pointspan = 0
            return

        # Get the earliest point already in the chart
        points = self.rankLine.pointsVector()

        if points:
            # The chart is drawn right-to-left, so the last point is the earliest point
            earliest_msecs = points[-1].x()
            earliest = datetime.fromtimestamp(earliest_msecs / 1000, timezone.utc)

            if earliest <= start_date:
                return

        else:
            earliest = datetime.now(timezone.utc)

        # Get the product history stats if we don't already have them
        if self.history is None:
            self.history = dbhelpers.ProductHistoryStats(self.dbsession, self.source.id)

        # Start adding points to the chart
        last_row = None
        for row in self.dbsession.query(AmzProductHistory).\
                                  filter(AmzProductHistory.amz_listing_id == self.source.id,
                                         AmzProductHistory.timestamp > start_date.replace(tzinfo=None),
                                         AmzProductHistory.timestamp < earliest.replace(tzinfo=None)).\
                                  order_by(AmzProductHistory.timestamp.desc()):

            # SqlAlchemy returns naive timestamps
            time = row.timestamp.replace(tzinfo=timezone.utc).timestamp() * 1000

            self.rankLine.append(time, row.salesrank or 0)
            self.priceLine.append(time, row.price or 0)

            if last_row:
                # It's possible for salesrank to be None
                try:
                    slope = (last_row.salesrank - row.salesrank) / (last_row.timestamp.timestamp() - row.timestamp.timestamp())
                    if slope < -0.3:
                        self.salesPoints.append(last_row.timestamp.replace(tzinfo=timezone.utc).timestamp() * 1000,
                                                last_row.salesrank)
                except (TypeError, AttributeError):
                    pass

            last_row = row

        # Calculate the average span between points
        spans = 0
        for p1, p2 in itertools.zip_longest(itertools.islice(points, 0, None, 2), itertools.islice(points, 1, None, 2)):
            if p1 and p2: spans += abs(p1.x() - p2.x())

        self._avg_pointspan = spans // 2

    def on_timeaxis_min_changed(self, min):
        """Respond to a change in the time axis' minimum value."""
        # toTime_t() converts to UTC automatically
        utc_min = datetime.fromtimestamp(min.toTime_t(), timezone.utc)
        self.load_history_from(start_date=utc_min - timedelta(days=1))

    def reset_axes(self):
        """Resets the chart axes."""
        r = self.rankLine.pointsVector()
        p = self.priceLine.pointsVector()

        # If there is only one data point, set the min and max to the day before and the day after
        if len(r) == 1:
            tmin = QDateTime.fromMSecsSinceEpoch(r[0].x(), Qt.LocalTime).addDays(-1)
            tmax = QDateTime.fromMSecsSinceEpoch(r[0].x(), Qt.LocalTime).addDays(+1)
        else:
            tmin = min(r, key=lambda pt: pt.x(), default=QPointF(QDateTime.currentDateTime().addDays(-1).toMSecsSinceEpoch(), 0)).x()
            tmax = max(r, key=lambda pt: pt.x(), default=QPointF(QDateTime.currentDateTime().addDays(+1).toMSecsSinceEpoch(), 0)).x()
            tmin = QDateTime.fromMSecsSinceEpoch(tmin, Qt.LocalTime)
            tmax = QDateTime.fromMSecsSinceEpoch(tmax, Qt.LocalTime)

        self.timeAxis.setMin(tmin)
        self.timeAxis.setMax(tmax)

        # Find the min and max values of the series
        min_point = lambda pts: min(pts, key=lambda pt: pt.y(), default=QPointF(0, 0))
        max_point = lambda pts: max(pts, key=lambda pt: pt.y(), default=QPointF(0, 0))

        rmin = min_point(r)
        rmax = max_point(r)
        pmin = min_point(p)
        pmax = max_point(p)

        # Scale the mins and maxes to 'friendly' values
        scalemin = lambda v, step: ((v - step / 2) // step) * step
        scalemax = lambda v, step: ((v + step / 2) // step + 1) * step

        # The the axis bounds

        rmin = max(scalemin(rmin.y(), 1000), 0)
        rmax = scalemax(rmax.y(), 1000)
        pmin = max(scalemin(pmin.y(), 5), 0)
        pmax = scalemax(pmax.y(), 5)

        self.rankAxis.setMin(rmin)
        self.rankAxis.setMax(rmax)
        self.priceAxis.setMin(pmin)
        self.priceAxis.setMax(pmax)

    def eventFilter(self, watched, event):
        """Intercept and handle mouse events."""
        if event.type() == QEvent.GraphicsSceneWheel and event.orientation() == Qt.Vertical:
            factor = 0.95 if event.delta() < 0 else 1.05
            self.chart.zoom(factor)
            return True

        if event.type() == QEvent.GraphicsSceneMouseDoubleClick:
            self.chart.zoomReset()
            self.reset_axes()
            return True

        if event.type() == QEvent.GraphicsSceneMouseMove:
            delta = event.pos() - event.lastPos()
            self.chart.scroll(-delta.x(), delta.y())
            return True

        return False