Beispiel #1
0
 def __init__(self, linetype=gr.LINETYPE_SOLID, markertype=gr.MARKERTYPE_DOT,
              linecolor=None, markercolor=1):
     self._linetype, self._markertype = linetype, markertype
     self._linecolor, self._markercolor = linecolor, markercolor
     if linecolor is None:
         self._linecolor = ColorIndexGenerator.nextColorIndex()
     else:
         self._linecolor = linecolor
Beispiel #2
0
    def __init__(self, parent, window, timeaxis=False):
        InteractiveGRWidget.__init__(self, parent)
        NicosPlot.__init__(self, window, timeaxis=timeaxis)

        self.timeaxis = timeaxis or (self.axescls == NicosTimePlotAxes)
        self.leftTurnedLegend = True
        self.statusMessage = None
        self.mouselocation = None
        self._cursor = self.cursor()
        self._mouseSelEnabled = self.getMouseSelectionEnabled()
        self._markertype = gr.MARKERTYPE_OMARK

        dictPrintType = dict(gr.PRINT_TYPE)
        for prtype in [gr.PRINT_JPEG, gr.PRINT_TIF]:
            dictPrintType.pop(prtype)
        self._saveTypes = (";;".join(dictPrintType.values()) + ";;" +
                           ";;".join(gr.GRAPHIC_TYPE.values()))
        self._saveName = None
        self._color = ColorIndexGenerator()
        self._plot = Plot(viewport=(.1, .85, .15, .88))
        self._plot.setLegendWidth(0.05)
        self._axes = self.axescls(viewport=self._plot.viewport)
        self._axes.backgroundColor = 0
        self._plot.addAxes(self._axes)
        self._plot.title = self.titleString()
        self.addPlot(self._plot)

        guiConn = GUIConnector(self)
        guiConn.connect(LegendEvent.ROI_CLICKED, self.on_legendItemClicked,
                        LegendEvent)
        guiConn.connect(ROIEvent.ROI_CLICKED, self.on_roiItemClicked, ROIEvent)
        guiConn.connect(MouseEvent.MOUSE_PRESS, self.on_fitPicker_selected)
        guiConn.connect(MouseEvent.MOUSE_MOVE, self.on_mouseMove)
        self.logXinDomain.connect(self.on_logXinDomain)
        self.logYinDomain.connect(self.on_logYinDomain)
        self.setLegend(True)
        self.updateDisplay()
Beispiel #3
0
class NicosGrPlot(NicosPlot, InteractiveGRWidget):

    axescls = NicosPlotAxes
    HAS_AUTOSCALE = True
    SAVE_EXT = '.svg'

    def __init__(self, parent, window, timeaxis=False):
        InteractiveGRWidget.__init__(self, parent)
        NicosPlot.__init__(self, window, timeaxis=timeaxis)

        self.timeaxis = timeaxis or (self.axescls == NicosTimePlotAxes)
        self.leftTurnedLegend = True
        self.statusMessage = None
        self.mouselocation = None
        self._cursor = self.cursor()
        self._mouseSelEnabled = self.getMouseSelectionEnabled()
        self._markertype = gr.MARKERTYPE_OMARK

        dictPrintType = dict(gr.PRINT_TYPE)
        for prtype in [gr.PRINT_JPEG, gr.PRINT_TIF]:
            dictPrintType.pop(prtype)
        self._saveTypes = (";;".join(dictPrintType.values()) + ";;" +
                           ";;".join(gr.GRAPHIC_TYPE.values()))
        self._saveName = None
        self._color = ColorIndexGenerator()
        self._plot = Plot(viewport=(.1, .85, .15, .88))
        self._plot.setLegendWidth(0.05)
        self._axes = self.axescls(viewport=self._plot.viewport)
        self._axes.backgroundColor = 0
        self._plot.addAxes(self._axes)
        self._plot.title = self.titleString()
        self.addPlot(self._plot)

        guiConn = GUIConnector(self)
        guiConn.connect(LegendEvent.ROI_CLICKED, self.on_legendItemClicked,
                        LegendEvent)
        guiConn.connect(ROIEvent.ROI_CLICKED, self.on_roiItemClicked, ROIEvent)
        guiConn.connect(MouseEvent.MOUSE_PRESS, self.on_fitPicker_selected)
        guiConn.connect(MouseEvent.MOUSE_MOVE, self.on_mouseMove)
        self.logXinDomain.connect(self.on_logXinDomain)
        self.logYinDomain.connect(self.on_logYinDomain)
        self.setLegend(True)
        self.updateDisplay()

    def xtickCallBack(self, x, y, _svalue, value):
        gr.setcharup(-1. if self.leftTurnedLegend else 1., 1.)
        gr.settextalign(
            gr.TEXT_HALIGN_RIGHT if self.leftTurnedLegend else
            gr.TEXT_HALIGN_LEFT, gr.TEXT_VALIGN_TOP)
        dx = .015
        timeVal = time.localtime(value)
        gr.text(x + (dx if self.leftTurnedLegend else -dx), y,
                time.strftime(DATEFMT, timeVal))
        gr.text(x - (dx if self.leftTurnedLegend else -dx), y,
                time.strftime(TIMEFMT, timeVal))
        gr.setcharup(0., 1.)

    def setAutoScaleFlags(self, xflag, yflag):
        mask = 0x0
        if xflag:
            mask |= PlotAxes.SCALE_X
        if yflag:
            mask |= PlotAxes.SCALE_Y
        self.setAutoScale(mask)

    def setBackgroundColor(self, color):
        pass  # not implemented

    def setFonts(self, font, bold, larger):
        pass  # not implemented

    def updateDisplay(self):
        self._plot.title = self.titleString()
        if self.subTitleString():
            self._plot.subTitle = self.subTitleString()
        self._plot.xlabel = self.xaxisName()
        self._plot.ylabel = self.yaxisName()
        if self.normalized:
            self._plot.ylabel += " (norm: %s)" % self.normalized

        self.plotcurves = []
        self.addAllCurves()
        if self.timeaxis:
            self._plot.viewport = (.1, .85, .18, .88)
            self._axes.setXtickCallback(self.xtickCallBack)
            self._plot.offsetXLabel = -.08

        scale = self.yaxisScale()
        if scale:
            axes = self._plot.getAxes(0)
            curwin = axes.getWindow()
            if not curwin:
                curwin = [0, 1, scale[0], scale[1]]
                curves = axes.getCurves()
                xmins = []
                xmaxs = []
                for c in curves:
                    if c.visible:
                        xmins.append(min(c.x))
                        xmaxs.append(max(c.x))
                if xmins and xmaxs:
                    curwin[0] = min(xmins)
                    curwin[1] = max(xmaxs)
            axes.setWindow(curwin[0], curwin[1], scale[0], scale[1])
        InteractiveGRWidget.update(self)

    def isLegendEnabled(self):
        return self._plot.isLegendEnabled()

    def setLegend(self, on):
        self._plot.setLegend(on)
        self.update()

    def isLogScaling(self, idx=0):
        axes = self._plot.getAxes(idx)
        return (axes.scale & gr.OPTION_Y_LOG if axes is not None else False)

    def isLogXScaling(self, idx=0):
        axes = self._plot.getAxes(idx)
        return (axes.scale & gr.OPTION_X_LOG if axes is not None else False)

    def setLogScale(self, on):
        self._plot.setLogY(on, rescale=True)
        self.update()

    def setLogXScale(self, on):
        self._plot.setLogX(on, rescale=True)
        self.update()

    def isErrorBarEnabled(self):
        axes = self._plot.getAxes(0)
        if axes:
            curves = axes.getCurves()
            if curves:
                return curves[0].isErrorBarEnabled(1)
        return False

    def setErrorBarEnabled(self, flag):
        for axis in self._plot.getAxes():
            for curve in axis.getCurves():
                curve.setErrorBarEnabled(flag)
        self.update()

    def setSymbols(self, on):
        markertype = self._markertype if on else gr.MARKERTYPE_DOT
        for axis in self._plot.getAxes():
            for curve in axis.getCurves():
                curve.markertype = markertype
        self.hasSymbols = on
        self.update()

    def setLines(self, on):
        linetype = None
        if on:
            linetype = gr.LINETYPE_SOLID
        for axis in self._plot.getAxes():
            for curve in axis.getCurves():
                curve.linetype = linetype
        self.hasLines = on
        self.update()

    def unzoom(self):
        self._plot.reset()
        self.update()

    def on_logXinDomain(self, flag):
        if not flag:
            self._plot.setLogX(flag)
            self.update()

    def on_logYinDomain(self, flag):
        if not flag:
            self.setLogScale(flag)

    def on_legendItemClicked(self, event):
        if event.getButtons() & MouseEvent.LEFT_BUTTON:
            event.curve.visible = not event.curve.visible
            if event.curve._parent:
                event.curve._parent.disabled = not event.curve._parent.disabled
            self.update()

    def on_roiItemClicked(self, event):
        if event.getButtons() & MouseEvent.RIGHT_BUTTON:
            if isinstance(event.roi.reference, FitResult):
                menu = QMenu(self)
                actionClipboard = QAction("Copy fit values to clipboard", menu)
                menu.addAction(actionClipboard)
                p0dc = event.getDC()
                selectedItem = menu.exec_(
                    self.mapToGlobal(QPoint(p0dc.x, p0dc.y)))
                if selectedItem == actionClipboard:
                    res = event.roi.reference
                    text = '\n'.join(
                        (n + '\t' if n else '\t') +
                        (v + '\t' if isinstance(v, string_types) else '%g\t' %
                         v) +
                        (dv if isinstance(dv, string_types) else '%g' % dv)
                        for (n, v, dv) in res.label_contents)
                    QApplication.clipboard().setText(text)

    def on_mouseMove(self, event):
        if event.getWindow():  # inside plot
            self.mouselocation = event
            wc = event.getWC(self._plot.viewport)
            if self.statusMessage:
                msg = "%s (X = %g, Y = %g)" % (self.statusMessage, wc.x, wc.y)
            else:
                msg = "X = %g, Y = %g" % (wc.x, wc.y)
            self.window.statusBar.showMessage(msg)
        else:
            self.window.statusBar.clearMessage()

    def addPlotCurve(self, plotcurve, replot=False):
        existing_curve = next((c for c in self._axes.getCurves()
                               if c._parent is plotcurve._parent), None)
        if existing_curve and not replot:
            existing_curve.visible = plotcurve.visible
            existing_curve.legend = plotcurve.legend
            existing_curve.setUpdateXCallback(None)
            existing_curve.setUpdateYCallback(None)
            # update curve
            existing_curve.x, existing_curve.y = plotcurve.x, plotcurve.y
            if plotcurve.errorBar1 and existing_curve.errorBar1:
                mcolor = existing_curve.errorBar1.markercolor
                existing_curve.errorBar1 = plotcurve.errorBar1
                existing_curve.errorBar1.markercolor = mcolor
            else:
                existing_curve.errorBar1 = plotcurve.errorBar1
            if plotcurve.errorBar2 and existing_curve.errorBar2:
                mcolor = existing_curve.errorBar2.markercolor
                existing_curve.errorBar2 = plotcurve.errorBar2
                existing_curve.errorBar2.markercolor = mcolor
            else:
                existing_curve.errorBar2 = plotcurve.errorBar2
            if existing_curve not in self.plotcurves:
                self.plotcurves.append(existing_curve)
        else:
            color = self._color.getNextColorIndex()
            plotcurve.linecolor = color
            plotcurve.markercolor = color
            plotcurve.markertype = self._markertype if self.hasSymbols \
                else gr.MARKERTYPE_DOT
            if plotcurve.errorBar1:
                plotcurve.errorBar1.markercolor = color
            if plotcurve.errorBar2:
                plotcurve.errorBar2.markercolor = color
            self._axes.addCurves(plotcurve)
            self.plotcurves.append(plotcurve)

    def savePlot(self):
        saveName = None
        dialog = QFileDialog(self, "Select file name", "", self._saveTypes)
        dialog.selectNameFilter(gr.PRINT_TYPE[gr.PRINT_PDF])
        dialog.setOption(dialog.HideNameFilterDetails, False)
        dialog.setAcceptMode(QFileDialog.AcceptSave)
        if dialog.exec_() == QDialog.Accepted:
            path = dialog.selectedFiles()[0]
            if path:
                _p, suffix = os.path.splitext(path)
                if suffix:
                    suffix = suffix.lower()
                else:
                    # append selected name filter suffix (filename extension)
                    nameFilter = dialog.selectedNameFilter()
                    for k, v in gr.PRINT_TYPE.items():
                        if v == nameFilter:
                            suffix = '.' + k
                            path += suffix
                            break
                if suffix and (suffix[1:] in gr.PRINT_TYPE
                               or suffix[1:] in gr.GRAPHIC_TYPE):
                    self.save(path)
                    saveName = os.path.basename(path)
                    self._saveName = saveName
                else:
                    raise Exception("Unsupported file format")
        return saveName

    def printPlot(self):
        self.printDialog("Nicos-" +
                         self._saveName if self._saveName else "untitled")
        return True

    @property
    def plot(self):
        """Get current gr.pygr.Plot object."""
        return self._plot

    def _save(self, extension=".pdf"):
        fd, pathname = tempfile.mkstemp(extension)
        self.save(pathname)
        os.close(fd)
        return pathname

    def saveQuietly(self):
        return self._save(".svg")

    def _getCurveData(self, curve):
        errBar1 = curve.errorBar1
        return [curve.x, curve.y, errBar1.dpos if errBar1 else None]

    def _getCurveLegend(self, curve):
        return curve.legend

    def _isCurveVisible(self, curve):
        return curve.visible

    def setVisibility(self, item, on):
        item.visible = on
        if item._parent:
            item._parent.disabled = not on

    def _enterFitMode(self):
        self.window.statusBar.showMessage(self.statusMessage)
        self._cursor = self.cursor()
        self.setCursor(QCursor(Qt.CrossCursor))
        self._mouseSelEnabled = self.getMouseSelectionEnabled()
        self.setMouseSelectionEnabled(False)

    def _fitRequestPick(self, paramname):
        self.statusMessage = 'Fitting: Click on %s' % paramname
        self.window.statusBar.showMessage(self.statusMessage)

    def _leaveFitMode(self):
        self.fitter = None
        self.statusMessage = None
        self.setCursor(self._cursor)
        self.setMouseSelectionEnabled(self._mouseSelEnabled)

    def _plotFit(self, res):
        color = self._color.getNextColorIndex()
        resultcurve = NicosPlotCurve(res.curve_x,
                                     res.curve_y,
                                     legend=res._title,
                                     linecolor=color,
                                     markercolor=color)
        self.addPlotCurve(resultcurve, True)
        resultcurve.markertype = gr.MARKERTYPE_DOT
        self.window.statusBar.showMessage("Fitting complete")

        text = '\n'.join(
            (n + ': ' if n else '') +
            (v if isinstance(v, string_types) else '%g' % v) +
            (dv if isinstance(dv, string_types) else ' +/- %g' % dv)
            for (n, v, dv) in res.label_contents)
        grtext = Text(res.label_x,
                      res.label_y,
                      text,
                      self._axes,
                      .012,
                      hideviewport=False)
        resultcurve.dependent.append(grtext)
        coord = CoordConverter(self._axes.sizex, self._axes.sizey,
                               self._axes.getWindow())
        roi = RegionOfInterest(reference=res,
                               regionType=RegionOfInterest.TEXT,
                               axes=self._axes)
        for nxi, nyi in zip(*grtext.getBoundingBox()):
            coord.setNDC(nxi, nyi)
            roi.append(coord.getWC(self._axes.viewport))
        self._plot.addROI(roi)
        self.update()

    def on_fitPicker_selected(self, point):
        if self.fitter and point.getButtons() & MouseEvent.LEFT_BUTTON and \
                point.getWindow():
            p = point.getWC(self._plot.viewport)
            self.fitter.addPick((p.x, p.y))

    def _modifyCurve(self, curve, op):
        new_y = [
            eval(op, {
                'x': v1,
                'y': v2
            }) for (v1, v2) in zip(curve.x, curve.y)
        ]
        if curve.errorBar1:
            curve.errorBar1.y = new_y
        if curve.errorBar2:
            curve.errorBar2.y = new_y
        curve.y = new_y

    def setMarkerType(self, markertype):
        self._markertype = markertype