Ejemplo n.º 1
0
   def __createChart(self):
      self.__chart = QChart()
      self.__chart.setTitle("简单函数曲线")
      self.ui.chartView.setChart(self.__chart)
      self.ui.chartView.setRenderHint(QPainter.Antialiasing)

      series0 =  QLineSeries()
      series0.setName("Sin曲线")
      series1 =  QLineSeries()
      series1.setName("Cos曲线")
      self.__curSeries=series0   #当前序列

      pen=QPen(Qt.red)
      pen.setStyle(Qt.DotLine)   #SolidLine, DashLine, DotLine, DashDotLine
      pen.setWidth(2)
      series0.setPen(pen)        #序列的线条设置

      pen.setStyle(Qt.SolidLine) #SolidLine, DashLine, DotLine, DashDotLine
      pen.setColor(Qt.blue)
      series1.setPen(pen)        #序列的线条设置

      self.__chart.addSeries(series0)
      self.__chart.addSeries(series1)

      axisX = QValueAxis()
      self.__curAxis=axisX       #当前坐标轴
      axisX.setRange(0, 10)      #设置坐标轴范围
      axisX.setLabelFormat("%.1f")  #标签格式
      axisX.setTickCount(11)        #主分隔个数
      axisX.setMinorTickCount(4)
      axisX.setTitleText("time(secs)")  #标题
      axisX.setGridLineVisible(True)
      axisX.setMinorGridLineVisible(False)

      axisY = QValueAxis()
      axisY.setRange(-2, 2)
      axisY.setLabelFormat("%.2f")     #标签格式
      axisY.setTickCount(5)
      axisY.setMinorTickCount(4)
      axisY.setTitleText("value")
      axisY.setGridLineVisible(True)
      axisY.setMinorGridLineVisible(False)

   ##      self.__chart.setAxisX(axisX, series0) #添加X坐标轴
   ##      self.__chart.setAxisX(axisX, series1) #添加X坐标轴
   ##      self.__chart.setAxisY(axisY, series0) #添加Y坐标轴
   ##      self.__chart.setAxisY(axisY, series1) #添加Y坐标轴

   ##另一种实现设置坐标轴的方法
      self.__chart.addAxis(axisX,Qt.AlignBottom) #坐标轴添加到图表,并指定方向
      self.__chart.addAxis(axisY,Qt.AlignLeft)

      series0.attachAxis(axisX)  #序列 series0 附加坐标轴
      series0.attachAxis(axisY)

      series1.attachAxis(axisX)  #序列 series1 附加坐标轴
      series1.attachAxis(axisY)
Ejemplo n.º 2
0
    def __createChart(self):
        self.__chart = QChart()
        self.ui.chartView.setChart(self.__chart)
        self.__chart.legend().setVisible(False)  #隐藏图例
        self.__chart.setMargins(QMargins(0, 0, 0, 0))  #把间距设置到最小

        #初始化线条数组
        series = [QLineSeries() for _ in range(15)]
        color = [
            '#FF88C2', '#FF8888', '#FFA488', '#FFBB66', '#FFDD55', '#FFFF77',
            '#DDFF77', '#BBFF66', '#66FF66', '#77FFCC', '#77FFEE', '#66FFFF',
            '#77DDFF', '#99BBFF', '#9999FF'
        ]

        #设置线条颜色形状
        pen = QPen()
        pen.setStyle(Qt.SolidLine)
        pen.setWidth(2)
        for i in range(15):
            pen.setColor(QColor(color[i]))
            series[i].setPen(pen)

        #向表格添加线条
        for i in range(15):
            self.__chart.addSeries(series[i])

        #设置坐标轴
        axisX = QValueAxis()
        #self.__curAxis=axisX       #当前坐标轴
        axisX.setRange(0, 200)  #设置坐标轴范围
        axisX.setLabelFormat("%d")  #标签格式
        axisX.setTickCount(5)  #主分隔个数
        axisX.setMinorTickCount(4)
        axisX.setGridLineVisible(True)
        axisX.setMinorGridLineVisible(False)

        axisY = QValueAxis()
        axisY.setRange(0, 1024)
        axisY.setLabelFormat("%d")  #标签格式
        axisY.setTickCount(5)
        axisY.setMinorTickCount(4)
        axisY.setGridLineVisible(True)
        axisY.setMinorGridLineVisible(False)

        self.__chart.addAxis(axisX, Qt.AlignBottom)  #坐标轴添加到图表,并指定方向
        self.__chart.addAxis(axisY, Qt.AlignLeft)

        for i in range(15):
            series[i].attachAxis(axisX)
            series[i].attachAxis(axisY)
Ejemplo n.º 3
0
class XChartProbit(QChart):
    def __init__(self, parent=None):
        super(QChart, self).__init__(parent)

        # Class Vars
        self.activeDistr = 'lognorm'
        self.knowndistr = distr._distrnames()
        self.data = dict()

        # Axis Setup
        self.axisX = QValueAxis()
        self.axisY = QValueAxis()

        self.axisX.setLabelsVisible(False)
        self.axisX.setTickCount(2)
        self.axisX.setTitleText("Series Fractional Probability")
        self.axisY.setTitleText("Value")
        self.setAxesMinMax(-3, 3, 0.01, 1.5)

        self.axisX.setMinorGridLineVisible(False)
        self.axisX.setGridLineVisible(False)

        # define the default grid colour to grey
        self.setGridColor(110, 110, 110)

        self.setActiveProbit(self.activeDistr)
        self.plotAreaChanged.connect(self.onPlotSizeChanged)
        # method needed for axes change to redraw grid lines

    def addLinearReg(self, seriesname):
        x = self.data[seriesname]['X'], y = self.data[seriesname][seriesname]
        # adds a linear regression line for a data set x,y
        slope, intercept, r_value, p_value, std_err = linregress(x, y)
        xmin = distr.distrppf(self.activeDistr, 0.01)
        xmax = distr.distrppf(self.activeDistr, 0.99)
        ymin = slope * xmin + intercept
        ymax = slope * xmax + intercept
        data = dict()
        data['X'] = [xmin, xmax]
        data['LinearReg'] = [ymin, ymax]
        lines = XLineSeries(data, xkey='X', openGL=True)

        self.addSeries(lines[0])
        self.setAxes(lines[0])

    def loadSeries(self, arr, name):
        # takes a list/array arr
        y = array(arr).copy()
        y.sort()
        self.data[name] = y
        self.redrawChart()

    def plotSeries(self, name):
        nsamp = len(self.data[name])
        # add data to temport dictionary
        tdict = dict()
        if self.activeScale == 'log10':
            tdict[name] = log10(self.data[name])
        elif self.activeScale == 'linear':
            tdict[name] = self.data[name]
        tdict['X'] = distr.distrppf(self.activeProbit, [
            percentileofscore(self.data[name], self.data[name][i]) / 100.00001
            for i in range(0, nsamp)
        ])
        series = XScatterSeries(tdict, xkey='X', openGL=True)
        self.addSeries(series[0])
        self.setAxes(series[0])

    def _replotData(self):
        for key in self.data.keys():
            self.pl

    def axesMinMax(self):
        # returns a length 4 list of the axes min and max values [x1,x2,y1,y2]
        return [
            self.axisX.min(),
            self.axisX.max(),
            self.axisY.min(),
            self.axisY.max()
        ]

    def redrawChart(self):
        self.removeAllSeries()
        self._removeHorizontalGridLabels()
        self.resetAxes()
        self._drawVerticalGridLines()
        if self.activeScale == 'log10':
            self.axisY.setLabelsVisible(False)
            self.axisY.setTickCount(1)
            self.setTitle("Log Probit Plot")
            self.axisY.setMinorGridLineVisible(False)
            self.axisY.setGridLineVisible(False)
            self._drawHorizontalGridLine()
            self._drawHorizontalLabels()
            self._drawHorizontalGridlLabels()
        elif self.activeScale == 'linear':
            self.axisY.setLabelsVisible(True)
            self.axisY.setTickCount(10)
            self.setTitle("Probit Plot")
            self.axisY.setMinorGridLineVisible(True)
            self.axisY.setGridLineVisible(True)

        for serkey in self.data.keys():
            self.plotSeries(serkey)

    def resetAxes(self):
        ymins = []
        ymaxs = []
        for key in self.data.keys():
            ymins.append(min(self.data[key]))
            ymaxs.append(max(self.data[key]))
        try:
            ymin = min(ymins)
            ymax = max(ymaxs)
        except ValueError:
            ymin = 1.1
            ymax = 2

        xmin = distr.distrppf(self.activeProbit, 0.001)
        xmax = distr.distrppf(self.activeProbit, 0.999)
        if self.activeScale == 'linear':
            yscal = 0.1 * (ymax - ymin)
            self.setAxesMinMax(xmin, xmax, ymin - yscal, ymax + yscal)
        elif self.activeScale == 'log10':
            yscal = 0.1 * (log10(ymax) - log10(ymin))
            self.setAxesMinMax(xmin, xmax, log10(ymin), log10(ymax))
            #self.setAxesMinMax(xmin,xmax,log10(ymin)-yscal,log10(ymax)+yscal*0.1)

    def setGridColor(self, r, g, b):
        # sets the colour of the background grid
        self.gridcolor = QColor(r, g, b)

    def setActiveProbit(self, type):
        if type in self.knowndistr:
            self.activeDistr = type
            if type == 'norm':
                self.activeProbit = 'norm'
                self.activeScale = 'linear'
            elif type == 'lognorm':
                self.activeProbit = 'norm'
                self.activeScale = 'log10'
        #self.redrawChart()

    def setActiveScale(self, newscale):
        self.activeScale = newscale

    def setAxes(self, series):
        # assigns a series to the chart default axes
        self.setAxisX(self.axisX, series)
        self.setAxisY(self.axisY, series)

    def setAxesMinMax(self, x1, x2, y1, y2):
        # sets the min max values in X and Y
        self.axisX.setMin(x1)
        self.axisX.setMax(x2)
        self.axisY.setMin(y1)
        self.axisY.setMax(y2)

    def _drawHorizontalLabels(self):
        xmin = self.axisX.min()
        xmax = self.axisX.max()
        axisScale = 1 / (xmax - xmin
                         )  # scaler for plotted axis (reduces to 0-1.0)
        # calculate probit values to scale from grid lines insert min and max values to scale correctly
        vlabx = distr.distrppf(self.activeProbit, self.vgridx)
        vlabx = insert(vlabx, 0, xmin)
        vlabx = insert(vlabx, len(vlabx), xmax)
        vlabx = (
            vlabx - xmin
        ) * axisScale  #scale the probit value to ratios of the Xaxis length
        paw = self.plotArea().width()
        pah = self.plotArea().height()  #find the plot width and height
        # find plot bottom left corner X and Y
        pblx = self.plotArea().bottomLeft().x()
        pbly = self.plotArea().bottomLeft().y()
        # offset from axix by 10 pixels -> may need to automate this offset in future
        pbly_lab = pbly + 10
        # calculate the position on the chart in x plane with which to place each label.
        pblx = [pblx + int(paw * x) for x in vlabx[1:-1]]
        try:
            self.hlabels
        except AttributeError:
            self.hlabels = []
            for i, labx in enumerate(
                    pblx):  #run through labels and create and position them
                # label text based on P scale
                ltext = 'P' + '%02d' % round(100.0 * (1.0 - self.vgridx[i]))
                self.hlabels.append(self.scene().addText(ltext))

        for i, labx in enumerate(
                pblx):  #run through labels and create and position them
            self.hlabels[i].setPos(
                labx - 0.5 * self.hlabels[i].boundingRect().width(),
                pbly)  #centre on tick marks

    def _drawVerticalGridLines(self):
        self.vgridx = arange(0.05, 1.0, 0.05)
        self.vgridx = insert(self.vgridx, 0, [0.01, 0.02])
        self.vgridx = insert(self.vgridx, len(self.vgridx), [0.98, 0.99])
        vgridy = [self.axisY.min(), self.axisY.max()]
        self.vgridseries = []
        for val in self.vgridx:
            line = 'P' + '%02d' % round(100.0 * (1.0 - val))
            tdict = {
                'X': [distr.distrppf(self.activeProbit, val)] * 2,
                line: vgridy
            }
            self.vgridseries = self.vgridseries + XLineSeries(
                tdict, xkey='X', openGL=True)
        for i, line in enumerate(self.vgridseries):
            pen = line.pen()
            pen.setColor(self.gridcolor)
            pen.setWidthF(0.4), line.setPen(pen)
            line.setPointLabelsVisible(True)
            self.addSeries(line)
            self.setAxes(line)
            self.legend().markers(line)[0].setVisible(False)

    def _drawHorizontalGridLine(self):
        # calculate xmin and xmax points for lines to completely cross graph
        hgridx = [
            distr.distrppf(self.activeProbit, 0.0001) - 1,
            distr.distrppf(self.activeProbit, 0.9999) + 1
        ]
        # calculate log scale for lines y values
        self.hgridy = self._logrange(10**self.axisY.min(),
                                     10**self.axisY.max(),
                                     base=10)
        self.hgridseries = []
        # create a line series for each lines and add to list
        for val in self.hgridy:
            line = '%d' % val
            tdict = {'X': hgridx, line: [log10(val)] * 2}
            self.hgridseries = self.hgridseries + XLineSeries(
                tdict, xkey='X', openGL=True)
        # add each of the series to the grid with special formatting
        for i, line in enumerate(self.hgridseries):
            pen = line.pen()
            pen.setColor(self.gridcolor)
            pen.setWidthF(0.4), line.setPen(pen)
            self.addSeries(line)
            self.setAxes(line)
            self.legend().markers(line)[0].setVisible(False)

    def _drawHorizontalGridlLabels(self):
        ymin = self.axisY.min()
        ymax = self.axisY.max()
        axisScale = 1 / (ymax - ymin
                         )  # scaler for plotted axis (reduces to 0-1.0)
        # calculate base10 values to scale from grid lines insert min and max values to scale correctly
        vlaby = log10(self.hgridy)
        vlaby = insert(vlaby, 0, ymin)
        vlaby = insert(vlaby, len(vlaby), ymax)
        vlaby = (
            vlaby - ymin
        ) * axisScale  # scale the probit value to ratios of the Xaxis length
        paw = self.plotArea().width()
        pah = self.plotArea().height()  # find the plot width and height
        # find plot bottom left corner X and Y
        pblx = self.plotArea().bottomLeft().x()
        pbly = self.plotArea().bottomLeft().y()
        # offset from axix by 10 pixels -> may need to automate this offset in future
        pblx_lab = pblx - 10
        # calculate the position on the chart in y plane with which to place each label.
        pbly = [pbly - int(pah * y) for y in vlaby[1:-1]]
        self.vlabels = []
        for i, labx in enumerate(
                pbly):  # run through labels and create and position them
            # label text based on P scale
            ltext = str(self.hgridy[i])
            self.vlabels.append(self.scene().addText(ltext))

        for i, laby in enumerate(
                pbly):  #run through labels and create and position them
            # label text based on P scale
            self.vlabels[i].setPos(
                pblx - self.vlabels[i].boundingRect().width() - 10,
                laby - 0.5 *
                self.vlabels[i].boundingRect().height())  #centre on tick marks

    def _removeHorizontalGridLine(self):
        for ser in self.hgridseries:
            self.removeSeries(ser)

    def _removeVerticalGridLine(self):
        for ser in self.vgridseries:
            self.removeSeries(ser)

    def _removeHorizontalGridLabels(self):
        try:
            for lab in self.vlabels:
                self.scene().removeItem(lab)
        except AttributeError:
            pass

    def _logrange(self, min, max, base=10):
        if min <= 0:
            min += max / (base**10)
        y = 1
        bpow = base
        if min < base:
            while min < bpow:
                y -= 1
                bpow = pow(base, y)
        else:
            while min > bpow:
                y += 1
                bpow = pow(base, y)
        out = array([])
        while bpow < max:
            y += 1
            bpown = pow(base, y)
            out = append(out, arange(bpow, bpown, bpow))
            bpow = bpown
        i = 0
        j = 0
        for ind, val in enumerate(out):
            if val <= min:
                i = ind
            if val <= max:
                j = ind
        return out[i:j + 1]

    @pyqtSlot()
    def onPlotSizeChanged(self):
        #reset position of labels
        self.redrawChart()