Exemple #1
0
class ColormapDialog(qt.QDialog):
    sigColormapChanged = qt.pyqtSignal(object)
    def __init__(self, parent=None, name="Colormap Dialog"):
        qt.QDialog.__init__(self, parent)
        self.setWindowTitle(name)
        self.title = name


        self.colormapList = ["Greyscale", "Reverse Grey", "Temperature",
                             "Red", "Green", "Blue", "Many"]

        # histogramData is tupel(bins, counts)
        self.histogramData = None

        # default values
        self.dataMin   = -10
        self.dataMax   = 10
        self.minValue  = 0
        self.maxValue  = 1

        self.colormapIndex  = 2
        self.colormapType   = 0

        self.autoscale   = False
        self.autoscale90 = False
        # main layout
        vlayout = qt.QVBoxLayout(self)
        vlayout.setContentsMargins(10, 10, 10, 10)
        vlayout.setSpacing(0)

        # layout 1 : -combo to choose colormap
        #            -autoscale button
        #            -autoscale 90% button
        hbox1    = qt.QWidget(self)
        hlayout1 = qt.QHBoxLayout(hbox1)
        vlayout.addWidget(hbox1)
        hlayout1.setContentsMargins(0, 0, 0, 0)
        hlayout1.setSpacing(10)

        # combo
        self.combo = qt.QComboBox(hbox1)
        for colormap in self.colormapList:
            self.combo.addItem(colormap)
        self.combo.activated[int].connect(self.colormapChange)
        hlayout1.addWidget(self.combo)

        # autoscale
        self.autoScaleButton = qt.QPushButton("Autoscale", hbox1)
        self.autoScaleButton.setCheckable(True)
        self.autoScaleButton.setAutoDefault(False)
        self.autoScaleButton.toggled[bool].connect(self.autoscaleChange)
        hlayout1.addWidget(self.autoScaleButton)

        # autoscale 90%
        self.autoScale90Button = qt.QPushButton("Autoscale 90%", hbox1)
        self.autoScale90Button.setCheckable(True)
        self.autoScale90Button.setAutoDefault(False)

        self.autoScale90Button.toggled[bool].connect(self.autoscale90Change)
        hlayout1.addWidget(self.autoScale90Button)

        # hlayout
        hbox0    = qt.QWidget(self)
        self.__hbox0 = hbox0
        hlayout0 = qt.QHBoxLayout(hbox0)
        hlayout0.setContentsMargins(0, 0, 0, 0)
        hlayout0.setSpacing(0)
        vlayout.addWidget(hbox0)
        #hlayout0.addStretch(10)

        self.buttonGroup = qt.QButtonGroup()
        g1 = qt.QCheckBox(hbox0)
        g1.setText("Linear")
        g2 = qt.QCheckBox(hbox0)
        g2.setText("Logarithmic")
        g3 = qt.QCheckBox(hbox0)
        g3.setText("Gamma")
        self.buttonGroup.addButton(g1, 0)
        self.buttonGroup.addButton(g2, 1)
        self.buttonGroup.addButton(g3, 2)
        self.buttonGroup.setExclusive(True)
        if self.colormapType == 1:
            self.buttonGroup.button(1).setChecked(True)
        elif self.colormapType == 2:
            self.buttonGroup.button(2).setChecked(True)
        else:
            self.buttonGroup.button(0).setChecked(True)
        hlayout0.addWidget(g1)
        hlayout0.addWidget(g2)
        hlayout0.addWidget(g3)
        vlayout.addWidget(hbox0)
        self.buttonGroup.buttonClicked[int].connect(self.buttonGroupChange)
        vlayout.addSpacing(20)

        hboxlimits = qt.QWidget(self)
        hboxlimitslayout = qt.QHBoxLayout(hboxlimits)
        hboxlimitslayout.setContentsMargins(0, 0, 0, 0)
        hboxlimitslayout.setSpacing(0)

        self.slider = None

        vlayout.addWidget(hboxlimits)

        vboxlimits = qt.QWidget(hboxlimits)
        vboxlimitslayout = qt.QVBoxLayout(vboxlimits)
        vboxlimitslayout.setContentsMargins(0, 0, 0, 0)
        vboxlimitslayout.setSpacing(0)
        hboxlimitslayout.addWidget(vboxlimits)

        # hlayout 2 : - min label
        #             - min texte
        hbox2    = qt.QWidget(vboxlimits)
        self.__hbox2 = hbox2
        hlayout2 = qt.QHBoxLayout(hbox2)
        hlayout2.setContentsMargins(0, 0, 0, 0)
        hlayout2.setSpacing(0)
        #vlayout.addWidget(hbox2)
        vboxlimitslayout.addWidget(hbox2)
        hlayout2.addStretch(10)

        self.minLabel  = qt.QLabel(hbox2)
        self.minLabel.setText("Minimum")
        hlayout2.addWidget(self.minLabel)

        hlayout2.addSpacing(5)
        hlayout2.addStretch(1)
        self.minText  = MyQLineEdit(hbox2)
        self.minText.setFixedWidth(150)
        self.minText.setAlignment(qt.Qt.AlignRight)
        self.minText.returnPressed[()].connect(self.minTextChanged)
        hlayout2.addWidget(self.minText)

        # hlayout 3 : - min label
        #             - min text
        hbox3    = qt.QWidget(vboxlimits)
        self.__hbox3 = hbox3
        hlayout3 = qt.QHBoxLayout(hbox3)
        hlayout3.setContentsMargins(0, 0, 0, 0)
        hlayout3.setSpacing(0)
        #vlayout.addWidget(hbox3)
        vboxlimitslayout.addWidget(hbox3)

        hlayout3.addStretch(10)
        self.maxLabel = qt.QLabel(hbox3)
        self.maxLabel.setText("Maximum")
        hlayout3.addWidget(self.maxLabel)

        hlayout3.addSpacing(5)
        hlayout3.addStretch(1)

        self.maxText = MyQLineEdit(hbox3)
        self.maxText.setFixedWidth(150)
        self.maxText.setAlignment(qt.Qt.AlignRight)

        self.maxText.returnPressed[()].connect(self.maxTextChanged)
        hlayout3.addWidget(self.maxText)


        # Graph widget for color curve...
        self.c = PlotWidget(self, backend=None)
        self.c.setGraphXLabel("Data Values")
        self.c.setInteractiveMode('select')

        self.marge = (abs(self.dataMax) + abs(self.dataMin)) / 6.0
        self.minmd = self.dataMin - self.marge
        self.maxpd = self.dataMax + self.marge

        self.c.setGraphXLimits(self.minmd, self.maxpd)
        self.c.setGraphYLimits(-11.5, 11.5)

        x = [self.minmd, self.dataMin, self.dataMax, self.maxpd]
        y = [-10, -10, 10, 10 ]
        self.c.addCurve(x, y,
                        legend="ConstrainedCurve",
                        color='black',
                        symbol='o',
                        linestyle='-')
        self.markers = []
        self.__x = x
        self.__y = y
        labelList = ["","Min", "Max", ""]
        for i in range(4):
            if i in [1, 2]:
                draggable = True
                color = "blue"
            else:
                draggable = False
                color = "black"
            #TODO symbol
            legend = "%d" % i
            self.c.addXMarker(x[i],
                              legend=legend,
                              text=labelList[i],
                              draggable=draggable,
                              color=color)
            self.markers.append((legend, ""))

        self.c.setMinimumSize(qt.QSize(250,200))
        vlayout.addWidget(self.c)

        self.c.sigPlotSignal.connect(self.chval)

        # colormap window can not be resized
        self.setFixedSize(vlayout.minimumSize())

    def plotHistogram(self, data=None):
        if data is not None:
            self.histogramData = data
        if self.histogramData is None:
            return False
        bins, counts = self.histogramData
        self.c.addCurve(bins, counts,
                        "Histogram",
                        color='darkYellow',
                        histogram='center',
                        yaxis='right',
                        fill=True)

    def _update(self):
        _logger.debug("colormap _update called")
        self.marge = (abs(self.dataMax) + abs(self.dataMin)) / 6.0
        self.minmd = self.dataMin - self.marge
        self.maxpd = self.dataMax + self.marge
        self.c.setGraphXLimits(self.minmd, self.maxpd)
        self.c.setGraphYLimits( -11.5, 11.5)

        self.__x = [self.minmd, self.dataMin, self.dataMax, self.maxpd]
        self.__y = [-10, -10, 10, 10]
        self.c.addCurve(self.__x, self.__y,
                        legend="ConstrainedCurve",
                        color='black',
                        symbol='o',
                        linestyle='-')
        self.c.clearMarkers()
        for i in range(4):
            if i in [1, 2]:
                draggable = True
                color = "blue"
            else:
                draggable = False
                color = "black"
            key = self.markers[i][0]
            label = self.markers[i][1]
            self.c.addXMarker(self.__x[i],
                              legend=key,
                              text=label,
                              draggable=draggable,
                              color=color)
        self.sendColormap()

    def buttonGroupChange(self, val):
        _logger.debug("buttonGroup asking to update colormap")
        self.setColormapType(val, update=True)
        self._update()

    def setColormapType(self, val, update=False):
        self.colormapType = val
        if self.colormapType == 1:
            self.buttonGroup.button(1).setChecked(True)
        elif self.colormapType == 2:
            self.buttonGroup.button(2).setChecked(True)
        else:
            self.colormapType = 0
            self.buttonGroup.button(0).setChecked(True)
        if update:
            self._update()

    def chval(self, ddict):
        _logger.debug("Received %s", ddict)
        if ddict['event'] == 'markerMoving':
            diam = int(ddict['label'])
            x = ddict['x']
            if diam == 1:
                self.setDisplayedMinValue(x)
            elif diam == 2:
                self.setDisplayedMaxValue(x)
        elif ddict['event'] == 'markerMoved':
            diam = int(ddict['label'])
            x = ddict['x']
            if diam == 1:
                self.setMinValue(x)
            if diam == 2:
                self.setMaxValue(x)

    """
    Colormap
    """
    def setColormap(self, colormap):
        self.colormapIndex = colormap
        if QTVERSION < '4.0.0':
            self.combo.setCurrentItem(colormap)
        else:
            self.combo.setCurrentIndex(colormap)

    def colormapChange(self, colormap):
        self.colormapIndex = colormap
        self.sendColormap()

    # AUTOSCALE
    """
    Autoscale
    """
    def autoscaleChange(self, val):
        self.autoscale = val
        self.setAutoscale(val)
        self.sendColormap()

    def setAutoscale(self, val):
        _logger.debug("setAutoscale called %s", val)
        if val:
            self.autoScaleButton.setChecked(True)
            self.autoScale90Button.setChecked(False)
            #self.autoScale90Button.setDown(False)
            self.setMinValue(self.dataMin)
            self.setMaxValue(self.dataMax)
            self.maxText.setEnabled(0)
            self.minText.setEnabled(0)
            self.c.setEnabled(False)
            #self.c.disablemarkermode()
        else:
            self.autoScaleButton.setChecked(False)
            self.autoScale90Button.setChecked(False)
            self.minText.setEnabled(1)
            self.maxText.setEnabled(1)
            self.c.setEnabled(True)
            #self.c.enablemarkermode()

    """
    set rangeValues to dataMin ; dataMax-10%
    """
    def autoscale90Change(self, val):
        self.autoscale90 = val
        self.setAutoscale90(val)
        self.sendColormap()

    def setAutoscale90(self, val):
        if val:
            self.autoScaleButton.setChecked(False)
            self.setMinValue(self.dataMin)
            self.setMaxValue(self.dataMax - abs(self.dataMax/10))
            self.minText.setEnabled(0)
            self.maxText.setEnabled(0)
            self.c.setEnabled(False)
        else:
            self.autoScale90Button.setChecked(False)
            self.minText.setEnabled(1)
            self.maxText.setEnabled(1)
            self.c.setEnabled(True)
            self.c.setFocus()



    # MINIMUM
    """
    change min value and update colormap
    """
    def setMinValue(self, val):
        v = float(str(val))
        self.minValue = v
        self.minText.setText("%g" % v)
        self.__x[1] = v
        key = self.markers[1][0]
        label = self.markers[1][1]
        self.c.addXMarker(v, legend=key, text=label, color="blue", draggable=True)
        self.c.addCurve(self.__x,
                        self.__y,
                        legend="ConstrainedCurve",
                        color='black',
                        symbol='o',
                        linestyle='-')
        self.sendColormap()

    """
    min value changed by text
    """
    def minTextChanged(self):
        text = str(self.minText.text())
        if not len(text):
            return
        val = float(text)
        self.setMinValue(val)
        if self.minText.hasFocus():
            self.c.setFocus()

    """
    change only the displayed min value
    """
    def setDisplayedMinValue(self, val):
        val = float(val)
        self.minValue = val
        self.minText.setText("%g"%val)
        self.__x[1] = val
        key = self.markers[1][0]
        label = self.markers[1][1]
        self.c.addXMarker(val, legend=key, text=label, color="blue", draggable=True)
        self.c.addCurve(self.__x, self.__y,
                        legend="ConstrainedCurve",
                        color='black',
                        symbol='o',
                        linestyle='-')
    # MAXIMUM
    """
    change max value and update colormap
    """
    def setMaxValue(self, val):
        v = float(str(val))
        self.maxValue = v
        self.maxText.setText("%g"%v)
        self.__x[2] = v
        key = self.markers[2][0]
        label = self.markers[2][1]
        self.c.addXMarker(v, legend=key, text=label, color="blue", draggable=True)
        self.c.addCurve(self.__x, self.__y,
                        legend="ConstrainedCurve",
                        color='black',
                        symbol='o',
                        linestyle='-')
        self.sendColormap()

    """
    max value changed by text
    """
    def maxTextChanged(self):
        text = str(self.maxText.text())
        if not len(text):return
        val = float(text)
        self.setMaxValue(val)
        if self.maxText.hasFocus():
            self.c.setFocus()

    """
    change only the displayed max value
    """
    def setDisplayedMaxValue(self, val):
        val = float(val)
        self.maxValue = val
        self.maxText.setText("%g"%val)
        self.__x[2] = val
        key = self.markers[2][0]
        label = self.markers[2][1]
        self.c.addXMarker(val, legend=key, text=label, color="blue", draggable=True)
        self.c.addCurve(self.__x, self.__y,
                        legend="ConstrainedCurve",
                        color='black',
                        symbol='o',
                        linestyle='-')


    # DATA values
    """
    set min/max value of data source
    """
    def setDataMinMax(self, minVal, maxVal, update=True):
        if minVal is not None:
            vmin = float(str(minVal))
            self.dataMin = vmin
        if maxVal is not None:
            vmax = float(str(maxVal))
            self.dataMax = vmax

        if update:
            # are current values in the good range ?
            self._update()

    def getColormap(self):
        if self.minValue > self.maxValue:
            vmax = self.minValue
            vmin = self.maxValue
        else:
            vmax = self.maxValue
            vmin = self.minValue
        cmap = [self.colormapIndex, self.autoscale,
                vmin, vmax,
                self.dataMin, self.dataMax,
                self.colormapType]
        return cmap

    """
    send 'ColormapChanged' signal
    """
    def sendColormap(self):
        _logger.debug("sending colormap")
        try:
            cmap = self.getColormap()
            self.sigColormapChanged.emit(cmap)
        except:
            sys.excepthook(sys.exc_info()[0],
                           sys.exc_info()[1],
                           sys.exc_info()[2])
Exemple #2
0
class ColormapDialog(QDialog):

    sigColormapChanged = pyqtSignal(object)

    def __init__(self, parent=None, name="Colormap Dialog"):
        QDialog.__init__(self, parent)
        self.setWindowTitle(name)
        self.title = name

        self.colormapList = [
            'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds', 'YlOrBr',
            'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu', 'GnBu', 'PuBu', 'YlGnBu',
            'PuBuGn', 'BuGn', 'YlGn'
        ]

        # histogramData is tupel(bins, counts)
        self.histogramData = None

        # default values
        self.dataMin = -10
        self.dataMax = 10
        self.minValue = 0
        self.maxValue = 1

        self.colormapIndex = 2
        self.colormapType = 0

        self.autoscale = False
        self.autoscale90 = False
        # main layout
        vlayout = QVBoxLayout(self)
        vlayout.setContentsMargins(10, 10, 10, 10)
        vlayout.setSpacing(0)

        # layout 1 : -combo to choose colormap
        #            -autoscale button
        #            -autoscale 90% button
        hbox1 = QWidget(self)
        hlayout1 = QHBoxLayout(hbox1)
        vlayout.addWidget(hbox1)
        hlayout1.setContentsMargins(0, 0, 0, 0)
        hlayout1.setSpacing(10)

        # combo
        self.combo = QComboBox(hbox1)
        for colormap in self.colormapList:
            self.combo.addItem(colormap)
        self.combo.activated[int].connect(self.colormapChange)
        hlayout1.addWidget(self.combo)

        # autoscale
        self.autoScaleButton = QPushButton("Autoscale", hbox1)
        self.autoScaleButton.setCheckable(True)
        self.autoScaleButton.setAutoDefault(False)
        self.autoScaleButton.toggled[bool].connect(self.autoscaleChange)
        hlayout1.addWidget(self.autoScaleButton)

        # autoscale 90%
        self.autoScale90Button = QPushButton("Autoscale 90%", hbox1)
        self.autoScale90Button.setCheckable(True)
        self.autoScale90Button.setAutoDefault(False)

        self.autoScale90Button.toggled[bool].connect(self.autoscale90Change)
        hlayout1.addWidget(self.autoScale90Button)

        # hlayout
        hbox0 = QWidget(self)
        self.__hbox0 = hbox0
        hlayout0 = QHBoxLayout(hbox0)
        hlayout0.setContentsMargins(0, 0, 0, 0)
        hlayout0.setSpacing(0)
        vlayout.addWidget(hbox0)
        #hlayout0.addStretch(10)

        self.buttonGroup = QButtonGroup()
        g1 = QCheckBox(hbox0)
        g1.setText("Linear")
        g2 = QCheckBox(hbox0)
        g2.setText("Logarithmic")
        g3 = QCheckBox(hbox0)
        g3.setText("Gamma")
        self.buttonGroup.addButton(g1, 0)
        self.buttonGroup.addButton(g2, 1)
        self.buttonGroup.addButton(g3, 2)
        self.buttonGroup.setExclusive(True)
        if self.colormapType == 1:
            self.buttonGroup.button(1).setChecked(True)
        elif self.colormapType == 2:
            self.buttonGroup.button(2).setChecked(True)
        else:
            self.buttonGroup.button(0).setChecked(True)
        hlayout0.addWidget(g1)
        hlayout0.addWidget(g2)
        hlayout0.addWidget(g3)
        vlayout.addWidget(hbox0)
        self.buttonGroup.buttonClicked[int].connect(self.buttonGroupChange)
        vlayout.addSpacing(20)

        hboxlimits = QWidget(self)
        hboxlimitslayout = QHBoxLayout(hboxlimits)
        hboxlimitslayout.setContentsMargins(0, 0, 0, 0)
        hboxlimitslayout.setSpacing(0)

        self.slider = None

        vlayout.addWidget(hboxlimits)

        vboxlimits = QWidget(hboxlimits)
        vboxlimitslayout = QVBoxLayout(vboxlimits)
        vboxlimitslayout.setContentsMargins(0, 0, 0, 0)
        vboxlimitslayout.setSpacing(0)
        hboxlimitslayout.addWidget(vboxlimits)

        # hlayout 2 : - min label
        #             - min texte
        hbox2 = QWidget(vboxlimits)
        self.__hbox2 = hbox2
        hlayout2 = QHBoxLayout(hbox2)
        hlayout2.setContentsMargins(0, 0, 0, 0)
        hlayout2.setSpacing(0)
        #vlayout.addWidget(hbox2)
        vboxlimitslayout.addWidget(hbox2)
        hlayout2.addStretch(10)

        self.minLabel = QLabel(hbox2)
        self.minLabel.setText("Minimum")
        hlayout2.addWidget(self.minLabel)

        hlayout2.addSpacing(5)
        hlayout2.addStretch(1)
        self.minText = MyQLineEdit(hbox2)
        self.minText.setFixedWidth(150)
        self.minText.setAlignment(QtCore.Qt.AlignRight)
        self.minText.returnPressed[()].connect(self.minTextChanged)
        hlayout2.addWidget(self.minText)

        # hlayout 3 : - min label
        #             - min text
        hbox3 = QWidget(vboxlimits)
        self.__hbox3 = hbox3
        hlayout3 = QHBoxLayout(hbox3)
        hlayout3.setContentsMargins(0, 0, 0, 0)
        hlayout3.setSpacing(0)
        #vlayout.addWidget(hbox3)
        vboxlimitslayout.addWidget(hbox3)

        hlayout3.addStretch(10)
        self.maxLabel = QLabel(hbox3)
        self.maxLabel.setText("Maximum")
        hlayout3.addWidget(self.maxLabel)

        hlayout3.addSpacing(5)
        hlayout3.addStretch(1)

        self.maxText = MyQLineEdit(hbox3)
        self.maxText.setFixedWidth(150)
        self.maxText.setAlignment(QtCore.Qt.AlignRight)

        self.maxText.returnPressed[()].connect(self.maxTextChanged)
        hlayout3.addWidget(self.maxText)

        # Graph widget for color curve...
        self.c = PlotWidget(self, backend=None)
        self.c.setGraphXLabel("Data Values")
        self.c.setInteractiveMode('select')

        self.marge = (abs(self.dataMax) + abs(self.dataMin)) / 6.0
        self.minmd = self.dataMin - self.marge
        self.maxpd = self.dataMax + self.marge

        self.c.setGraphXLimits(self.minmd, self.maxpd)
        self.c.setGraphYLimits(-11.5, 11.5)

        x = [self.minmd, self.dataMin, self.dataMax, self.maxpd]
        y = [-10, -10, 10, 10]
        self.c.addCurve(x,
                        y,
                        legend="ConstrainedCurve",
                        color='black',
                        symbol='o',
                        linestyle='-')
        self.markers = []
        self.__x = x
        self.__y = y
        labelList = ["", "Min", "Max", ""]
        for i in range(4):
            if i in [1, 2]:
                draggable = True
                color = "blue"
            else:
                draggable = False
                color = "black"
            #TODO symbol
            legend = "%d" % i
            self.c.addXMarker(x[i],
                              legend=legend,
                              text=labelList[i],
                              draggable=draggable,
                              color=color)
            self.markers.append((legend, ""))

        self.c.setMinimumSize(QSize(250, 200))
        vlayout.addWidget(self.c)

        self.c.sigPlotSignal.connect(self.chval)

        # colormap window can not be resized
        self.setFixedSize(vlayout.minimumSize())
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")
        vlayout.addWidget(self.buttonBox)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

    def plotHistogram(self, data=None):
        if data is not None:
            self.histogramData = data
        if self.histogramData is None:
            return False
        bins, counts = self.histogramData
        self.c.addCurve(bins,
                        counts,
                        "Histogram",
                        color='darkYellow',
                        histogram='center',
                        yaxis='right',
                        fill=True)

    def _update(self):
        _logger.debug("colormap _update called")
        self.marge = (abs(self.dataMax) + abs(self.dataMin)) / 6.0
        self.minmd = self.dataMin - self.marge
        self.maxpd = self.dataMax + self.marge
        self.c.setGraphXLimits(self.minmd, self.maxpd)
        self.c.setGraphYLimits(-11.5, 11.5)

        self.__x = [self.minmd, self.dataMin, self.dataMax, self.maxpd]
        self.__y = [-10, -10, 10, 10]
        self.c.addCurve(self.__x,
                        self.__y,
                        legend="ConstrainedCurve",
                        color='black',
                        symbol='o',
                        linestyle='-')
        self.c.clearMarkers()
        for i in range(4):
            if i in [1, 2]:
                draggable = True
                color = "blue"
            else:
                draggable = False
                color = "black"
            key = self.markers[i][0]
            label = self.markers[i][1]
            self.c.addXMarker(self.__x[i],
                              legend=key,
                              text=label,
                              draggable=draggable,
                              color=color)
        self.sendColormap()

    def buttonGroupChange(self, val):
        _logger.debug("buttonGroup asking to update colormap")
        self.setColormapType(val, update=True)
        self._update()

    def setColormapType(self, val, update=False):
        self.colormapType = val
        if self.colormapType == 1:
            self.buttonGroup.button(1).setChecked(True)
        elif self.colormapType == 2:
            self.buttonGroup.button(2).setChecked(True)
        else:
            self.colormapType = 0
            self.buttonGroup.button(0).setChecked(True)
        if update:
            self._update()

    def chval(self, ddict):
        _logger.debug("Received %s", ddict)
        if ddict['event'] == 'markerMoving':
            diam = int(ddict['label'])
            x = ddict['x']
            if diam == 1:
                self.setDisplayedMinValue(x)
            elif diam == 2:
                self.setDisplayedMaxValue(x)
        elif ddict['event'] == 'markerMoved':
            diam = int(ddict['label'])
            x = ddict['x']
            if diam == 1:
                self.setMinValue(x)
            if diam == 2:
                self.setMaxValue(x)

    """
    Colormap
    """

    def setColormap(self, colormap):
        self.colormapIndex = colormap
        if QTVERSION < '4.0.0':
            self.combo.setCurrentItem(colormap)
        else:
            self.combo.setCurrentIndex(colormap)

    def colormapChange(self, colormap):
        self.colormapIndex = colormap
        self.sendColormap()

    # AUTOSCALE
    """
    Autoscale
    """

    def autoscaleChange(self, val):
        self.autoscale = val
        self.setAutoscale(val)
        self.sendColormap()

    def setAutoscale(self, val):
        _logger.debug("setAutoscale called %s", val)
        if val:
            self.autoScaleButton.setChecked(True)
            self.autoScale90Button.setChecked(False)
            #self.autoScale90Button.setDown(False)
            self.setMinValue(self.dataMin)
            self.setMaxValue(self.dataMax)
            self.maxText.setEnabled(0)
            self.minText.setEnabled(0)
            self.c.setEnabled(False)
            #self.c.disablemarkermode()
        else:
            self.autoScaleButton.setChecked(False)
            self.autoScale90Button.setChecked(False)
            self.minText.setEnabled(1)
            self.maxText.setEnabled(1)
            self.c.setEnabled(True)
            #self.c.enablemarkermode()

    """
    set rangeValues to dataMin ; dataMax-10%
    """

    def autoscale90Change(self, val):
        self.autoscale90 = val
        self.setAutoscale90(val)
        self.sendColormap()

    def setAutoscale90(self, val):
        if val:
            self.autoScaleButton.setChecked(False)
            self.setMinValue(self.dataMin)
            self.setMaxValue(self.dataMax - abs(self.dataMax / 10))
            self.minText.setEnabled(0)
            self.maxText.setEnabled(0)
            self.c.setEnabled(False)
        else:
            self.autoScale90Button.setChecked(False)
            self.minText.setEnabled(1)
            self.maxText.setEnabled(1)
            self.c.setEnabled(True)
            self.c.setFocus()

    # MINIMUM
    """
    change min value and update colormap
    """

    def setMinValue(self, val):
        v = float(str(val))
        self.minValue = v
        self.minText.setText("%g" % v)
        self.__x[1] = v
        key = self.markers[1][0]
        label = self.markers[1][1]
        self.c.addXMarker(v,
                          legend=key,
                          text=label,
                          color="blue",
                          draggable=True)
        self.c.addCurve(self.__x,
                        self.__y,
                        legend="ConstrainedCurve",
                        color='black',
                        symbol='o',
                        linestyle='-')
        self.sendColormap()

    """
    min value changed by text
    """

    def minTextChanged(self):
        text = str(self.minText.text())
        if not len(text):
            return
        val = float(text)
        self.setMinValue(val)
        if self.minText.hasFocus():
            self.c.setFocus()

    """
    change only the displayed min value
    """

    def setDisplayedMinValue(self, val):
        val = float(val)
        self.minValue = val
        self.minText.setText("%g" % val)
        self.__x[1] = val
        key = self.markers[1][0]
        label = self.markers[1][1]
        self.c.addXMarker(val,
                          legend=key,
                          text=label,
                          color="blue",
                          draggable=True)
        self.c.addCurve(self.__x,
                        self.__y,
                        legend="ConstrainedCurve",
                        color='black',
                        symbol='o',
                        linestyle='-')

    # MAXIMUM
    """
    change max value and update colormap
    """

    def setMaxValue(self, val):
        v = float(str(val))
        self.maxValue = v
        self.maxText.setText("%g" % v)
        self.__x[2] = v
        key = self.markers[2][0]
        label = self.markers[2][1]
        self.c.addXMarker(v,
                          legend=key,
                          text=label,
                          color="blue",
                          draggable=True)
        self.c.addCurve(self.__x,
                        self.__y,
                        legend="ConstrainedCurve",
                        color='black',
                        symbol='o',
                        linestyle='-')
        self.sendColormap()

    """
    max value changed by text
    """

    def maxTextChanged(self):
        text = str(self.maxText.text())
        if not len(text): return
        val = float(text)
        self.setMaxValue(val)
        if self.maxText.hasFocus():
            self.c.setFocus()

    """
    change only the displayed max value
    """

    def setDisplayedMaxValue(self, val):
        val = float(val)
        self.maxValue = val
        self.maxText.setText("%g" % val)
        self.__x[2] = val
        key = self.markers[2][0]
        label = self.markers[2][1]
        self.c.addXMarker(val,
                          legend=key,
                          text=label,
                          color="blue",
                          draggable=True)
        self.c.addCurve(self.__x,
                        self.__y,
                        legend="ConstrainedCurve",
                        color='black',
                        symbol='o',
                        linestyle='-')

    # DATA values
    """
    set min/max value of data source
    """

    def setDataMinMax(self, minVal, maxVal, update=True):
        if minVal is not None:
            vmin = float(str(minVal))
            self.dataMin = vmin
        if maxVal is not None:
            vmax = float(str(maxVal))
            self.dataMax = vmax

        if update:
            # are current values in the good range ?
            self._update()

    def getColormap(self):

        if self.minValue > self.maxValue:
            vmax = self.minValue
            vmin = self.maxValue
        else:
            vmax = self.maxValue
            vmin = self.minValue
        cmap = [
            self.colormapIndex, self.autoscale, vmin, vmax, self.dataMin,
            self.dataMax, self.colormapType
        ]
        return cmap if self.exec_() else None

    """
    send 'ColormapChanged' signal
    """

    def sendColormap(self):
        _logger.debug("sending colormap")
        try:
            cmap = self.getColormap()
            self.sigColormapChanged.emit(cmap)
        except:
            sys.excepthook(sys.exc_info()[0],
                           sys.exc_info()[1],
                           sys.exc_info()[2])

    def colormapListToDict(colormapList):
        """Convert colormap from this dialog to :class:`PlotBackend`.
        :param colormapList: Colormap as returned by :meth:`getColormap`.
        :type colormapList: list or tuple
        :return: Colormap as used in :class:`PlotBackend`.
        :rtype: dict
        """
        index, autoscale, vMin, vMax, dataMin, dataMax, cmapType = colormapList
        # Warning, gamma cmapType is not supported in plot backend
        # Here it is silently replaced by linear as the default colormap
        return {
            'name': _COLORMAP_NAMES[index],
            'autoscale': autoscale,
            'vmin': vMin,
            'vmax': vMax,
            'normalization': 'log' if cmapType == 1 else 'linear',
            'colors': 256
        }

    def getColormap_name(self):
        self.getColormap()
        return _COLORMAP_NAMES[self.colormapIndex]

    def getColor(self):
        return _COLOR_NAMES[self.colormapIndex]

    def colormapDictToList(colormapDict):
        """Convert colormap from :class:`PlotBackend` to this dialog.
        :param dict colormapDict: Colormap as used in :class:`PlotBackend`.
        :return: Colormap as returned by :meth:`getColormap`.
        :rtype: list
        """
        cmapIndex = _COLORMAP_NAMES.index(colormapDict['name'])
        cmapType = 1 if colormapDict['normalization'].startswith('log') else 0
        return [
            cmapIndex,
            colormapDict['autoscale'],
            colormapDict['vmin'],
            colormapDict['vmax'],
            0,  # dataMin is not defined in PlotBackend colormap
            0,  # dataMax is not defined in PlotBackend colormap
            cmapType
        ]
Exemple #3
0
class RGBCorrelatorGraph(qt.QWidget):
    sigProfileSignal = qt.pyqtSignal(object)

    def __init__(self,
                 parent=None,
                 backend=None,
                 selection=False,
                 aspect=True,
                 colormap=False,
                 imageicons=False,
                 standalonesave=True,
                 standalonezoom=True,
                 profileselection=False,
                 polygon=False):
        qt.QWidget.__init__(self, parent)
        self.mainLayout = qt.QVBoxLayout(self)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setSpacing(0)
        self._keepDataAspectRatioFlag = False
        self.graph = PlotWidget(parent=self, backend=backend)
        self.graph.setGraphXLabel("Column")
        self.graph.setGraphYLabel("Row")
        self.graph.setYAxisAutoScale(True)
        self.graph.setXAxisAutoScale(True)
        plotArea = self.graph.getWidgetHandle()
        plotArea.setContextMenuPolicy(qt.Qt.CustomContextMenu)
        plotArea.customContextMenuRequested.connect(self._zoomBack)

        self._buildToolBar(selection,
                           colormap,
                           imageicons,
                           standalonesave,
                           standalonezoom=standalonezoom,
                           profileselection=profileselection,
                           aspect=aspect,
                           polygon=polygon)

        if profileselection:
            if len(self._pickerSelectionButtons):
                self.graph.sigPlotSignal.connect(\
                    self._graphPolygonSignalReceived)
                self._pickerSelectionWidthValue.valueChanged[int].connect( \
                             self.setPickerSelectionWith)

        self.saveDirectory = os.getcwd()
        self.mainLayout.addWidget(self.graph)

    def sizeHint(self):
        return qt.QSize(1.5 * qt.QWidget.sizeHint(self).width(),
                        qt.QWidget.sizeHint(self).height())

    def _buildToolBar(self,
                      selection=False,
                      colormap=False,
                      imageicons=False,
                      standalonesave=True,
                      standalonezoom=True,
                      profileselection=False,
                      aspect=False,
                      polygon=False):
        self.solidCircleIcon = qt.QIcon(qt.QPixmap(IconDict["solidcircle"]))
        self.solidEllipseIcon = qt.QIcon(qt.QPixmap(IconDict["solidellipse"]))
        self.colormapIcon = qt.QIcon(qt.QPixmap(IconDict["colormap"]))
        self.selectionIcon = qt.QIcon(qt.QPixmap(IconDict["normal"]))
        self.zoomResetIcon = qt.QIcon(qt.QPixmap(IconDict["zoomreset"]))
        self.polygonIcon = qt.QIcon(qt.QPixmap(IconDict["polygon"]))
        self.printIcon = qt.QIcon(qt.QPixmap(IconDict["fileprint"]))
        self.saveIcon = qt.QIcon(qt.QPixmap(IconDict["filesave"]))
        self.xAutoIcon = qt.QIcon(qt.QPixmap(IconDict["xauto"]))
        self.yAutoIcon = qt.QIcon(qt.QPixmap(IconDict["yauto"]))
        self.hFlipIcon = qt.QIcon(qt.QPixmap(IconDict["gioconda16mirror"]))
        self.imageIcon = qt.QIcon(qt.QPixmap(IconDict["image"]))
        self.eraseSelectionIcon = qt.QIcon(qt.QPixmap(IconDict["eraseselect"]))
        self.rectSelectionIcon = qt.QIcon(qt.QPixmap(IconDict["boxselect"]))
        self.brushSelectionIcon = qt.QIcon(qt.QPixmap(IconDict["brushselect"]))
        self.brushIcon = qt.QIcon(qt.QPixmap(IconDict["brush"]))
        self.additionalIcon = qt.QIcon(qt.QPixmap(
            IconDict["additionalselect"]))
        self.hLineIcon = qt.QIcon(qt.QPixmap(IconDict["horizontal"]))
        self.vLineIcon = qt.QIcon(qt.QPixmap(IconDict["vertical"]))
        self.lineIcon = qt.QIcon(qt.QPixmap(IconDict["diagonal"]))
        self.copyIcon = silx_icons.getQIcon("edit-copy")

        self.toolBar = qt.QWidget(self)
        self.toolBarLayout = qt.QHBoxLayout(self.toolBar)
        self.toolBarLayout.setContentsMargins(0, 0, 0, 0)
        self.toolBarLayout.setSpacing(0)
        self.mainLayout.addWidget(self.toolBar)
        #Autoscale
        if standalonezoom:
            tb = self._addToolButton(self.zoomResetIcon, self.__zoomReset,
                                     'Auto-Scale the Graph')
        else:
            tb = self._addToolButton(self.zoomResetIcon, None,
                                     'Auto-Scale the Graph')
        self.zoomResetToolButton = tb
        #y Autoscale
        tb = self._addToolButton(self.yAutoIcon,
                                 self._yAutoScaleToggle,
                                 'Toggle Autoscale Y Axis (On/Off)',
                                 toggle=True,
                                 state=True)
        tb.setDown(True)

        self.yAutoScaleToolButton = tb
        tb.setDown(True)

        #x Autoscale
        tb = self._addToolButton(self.xAutoIcon,
                                 self._xAutoScaleToggle,
                                 'Toggle Autoscale X Axis (On/Off)',
                                 toggle=True,
                                 state=True)
        self.xAutoScaleToolButton = tb
        tb.setDown(True)

        #Aspect ratio
        if aspect:
            self.aspectButton = self._addToolButton(self.solidCircleIcon,
                                                    self._aspectButtonSignal,
                                                    'Keep data aspect ratio',
                                                    toggle=False)
            self.aspectButton.setChecked(False)

        #colormap
        if colormap:
            tb = self._addToolButton(self.colormapIcon, None,
                                     'Change Colormap')
            self.colormapToolButton = tb

        #flip
        tb = self._addToolButton(self.hFlipIcon, None, 'Flip Horizontal')
        self.hFlipToolButton = tb

        #save
        if standalonesave:
            tb = self._addToolButton(self.saveIcon, self._saveIconSignal,
                                     'Save Graph')
        else:
            tb = self._addToolButton(self.saveIcon, None, 'Save')
        self.saveToolButton = tb

        self.copyToolButton = self._addToolButton(self.copyIcon,
                                                  self._copyIconSignal,
                                                  "Copy graph to clipboard")

        #Selection
        if selection:
            tb = self._addToolButton(self.selectionIcon,
                                     None,
                                     'Toggle Selection Mode',
                                     toggle=True,
                                     state=False)
            tb.setDown(False)
            self.selectionToolButton = tb
        #image selection icons
        if imageicons:
            tb = self._addToolButton(self.imageIcon, None, 'Reset')
            self.imageToolButton = tb

            tb = self._addToolButton(self.eraseSelectionIcon, None,
                                     'Erase Selection')
            self.eraseSelectionToolButton = tb

            tb = self._addToolButton(self.rectSelectionIcon, None,
                                     'Rectangular Selection')
            self.rectSelectionToolButton = tb

            tb = self._addToolButton(self.brushSelectionIcon, None,
                                     'Brush Selection')
            self.brushSelectionToolButton = tb

            tb = self._addToolButton(self.brushIcon, None, 'Select Brush')
            self.brushToolButton = tb

            if polygon:
                tb = self._addToolButton(
                    self.polygonIcon, None,
                    'Polygon selection\nRight click to finish')
                self.polygonSelectionToolButton = tb

            tb = self._addToolButton(self.additionalIcon, None,
                                     'Additional Selections Menu')
            self.additionalSelectionToolButton = tb
        else:
            if polygon:
                tb = self._addToolButton(
                    self.polygonIcon, None,
                    'Polygon selection\nRight click to finish')
                self.polygonSelectionToolButton = tb
            self.imageToolButton = None
        #picker selection
        self._pickerSelectionButtons = []
        if profileselection:
            self._profileSelection = True
            self._polygonSelection = False
            self._pickerSelectionButtons = []
            if self._profileSelection:
                tb = self._addToolButton(self.hLineIcon,
                                         self._hLineProfileClicked,
                                         'Horizontal Profile Selection',
                                         toggle=True,
                                         state=False)
                self.hLineProfileButton = tb
                self._pickerSelectionButtons.append(tb)

                tb = self._addToolButton(self.vLineIcon,
                                         self._vLineProfileClicked,
                                         'Vertical Profile Selection',
                                         toggle=True,
                                         state=False)
                self.vLineProfileButton = tb
                self._pickerSelectionButtons.append(tb)

                tb = self._addToolButton(self.lineIcon,
                                         self._lineProfileClicked,
                                         'Line Profile Selection',
                                         toggle=True,
                                         state=False)
                self.lineProfileButton = tb
                self._pickerSelectionButtons.append(tb)

                self._pickerSelectionWidthLabel = qt.QLabel(self.toolBar)
                self._pickerSelectionWidthLabel.setText("W:")
                self.toolBar.layout().addWidget(
                    self._pickerSelectionWidthLabel)
                self._pickerSelectionWidthValue = qt.QSpinBox(self.toolBar)
                self._pickerSelectionWidthValue.setMinimum(0)
                self._pickerSelectionWidthValue.setMaximum(1000)
                self._pickerSelectionWidthValue.setValue(1)
                self.toolBar.layout().addWidget(
                    self._pickerSelectionWidthValue)
                #tb = self._addToolButton(None,
                #                     self._lineProfileClicked,
                #                     'Line Profile Selection',
                #                     toggle=True,
                #                     state=False)
                #tb.setText = "W:"
                #self.lineWidthProfileButton = tb
                #self._pickerSelectionButtons.append(tb)
            if self._polygonSelection:
                _logger.info("Polygon selection not implemented yet")
        #hide profile selection buttons
        if imageicons:
            for button in self._pickerSelectionButtons:
                button.hide()

        self.infoWidget = qt.QWidget(self.toolBar)
        self.infoWidget.mainLayout = qt.QHBoxLayout(self.infoWidget)
        self.infoWidget.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.infoWidget.mainLayout.setSpacing(0)
        self.infoWidget.label = qt.QLabel(self.infoWidget)
        self.infoWidget.label.setText("X = ???? Y = ???? Z = ????")
        self.infoWidget.mainLayout.addWidget(self.infoWidget.label)
        self.toolBarLayout.addWidget(self.infoWidget)
        self.infoWidget.hide()

        self.toolBarLayout.addWidget(qt.HorizontalSpacer(self.toolBar))

        # ---print
        self.printPreview = SingletonPrintPreviewToolButton(parent=self,
                                                            plot=self.graph)
        self.printPreview.setIcon(self.printIcon)
        self.toolBarLayout.addWidget(self.printPreview)

    def _aspectButtonSignal(self):
        _logger.debug("_aspectButtonSignal")
        if self._keepDataAspectRatioFlag:
            self.keepDataAspectRatio(False)
        else:
            self.keepDataAspectRatio(True)

    def keepDataAspectRatio(self, flag=True):
        if flag:
            self._keepDataAspectRatioFlag = True
            self.aspectButton.setIcon(self.solidEllipseIcon)
            self.aspectButton.setToolTip("Set free data aspect ratio")
        else:
            self._keepDataAspectRatioFlag = False
            self.aspectButton.setIcon(self.solidCircleIcon)
            self.aspectButton.setToolTip("Keep data aspect ratio")
        self.graph.setKeepDataAspectRatio(self._keepDataAspectRatioFlag)

    def showInfo(self):
        self.infoWidget.show()

    def hideInfo(self):
        self.infoWidget.hide()

    def setInfoText(self, text):
        self.infoWidget.label.setText(text)

    def setMouseText(self, text=""):
        try:
            if len(text):
                qt.QToolTip.showText(self.cursor().pos(), text, self,
                                     qt.QRect())
            else:
                qt.QToolTip.hideText()
        except:
            _logger.warning("Error trying to show mouse text <%s>" % text)

    def focusOutEvent(self, ev):
        qt.QToolTip.hideText()

    def infoText(self):
        return self.infoWidget.label.text()

    def setXLabel(self, label="Column"):
        return self.graph.setGraphXLabel(label)

    def setYLabel(self, label="Row"):
        return self.graph.setGraphYLabel(label)

    def getXLabel(self):
        return self.graph.getGraphXLabel()

    def getYLabel(self):
        return self.graph.getGraphYLabel()

    def hideImageIcons(self):
        if self.imageToolButton is None: return
        self.imageToolButton.hide()
        self.eraseSelectionToolButton.hide()
        self.rectSelectionToolButton.hide()
        self.brushSelectionToolButton.hide()
        self.brushToolButton.hide()
        if hasattr(self, "polygonSelectionToolButton"):
            self.polygonSelectionToolButton.hide()
        self.additionalSelectionToolButton.hide()

    def showImageIcons(self):
        if self.imageToolButton is None: return
        self.imageToolButton.show()
        self.eraseSelectionToolButton.show()
        self.rectSelectionToolButton.show()
        self.brushSelectionToolButton.show()
        self.brushToolButton.show()
        if hasattr(self, "polygonSelectionToolButton"):
            self.polygonSelectionToolButton.show()
        self.additionalSelectionToolButton.show()

    def _hLineProfileClicked(self):
        for button in self._pickerSelectionButtons:
            if button != self.hLineProfileButton:
                button.setChecked(False)

        if self.hLineProfileButton.isChecked():
            self._setPickerSelectionMode("HORIZONTAL")
        else:
            self._setPickerSelectionMode(None)

    def _vLineProfileClicked(self):
        for button in self._pickerSelectionButtons:
            if button != self.vLineProfileButton:
                button.setChecked(False)
        if self.vLineProfileButton.isChecked():
            self._setPickerSelectionMode("VERTICAL")
        else:
            self._setPickerSelectionMode(None)

    def _lineProfileClicked(self):
        for button in self._pickerSelectionButtons:
            if button != self.lineProfileButton:
                button.setChecked(False)
        if self.lineProfileButton.isChecked():
            self._setPickerSelectionMode("LINE")
        else:
            self._setPickerSelectionMode(None)

    def setPickerSelectionWith(self, intValue):
        self._pickerSelectionWidthValue.setValue(intValue)
        #get the current mode
        mode = "NONE"
        for button in self._pickerSelectionButtons:
            if button.isChecked():
                if button == self.hLineProfileButton:
                    mode = "HORIZONTAL"
                elif button == self.vLineProfileButton:
                    mode = "VERTICAL"
                elif button == self.lineProfileButton:
                    mode = "LINE"
        ddict = {}
        ddict['event'] = "profileWidthChanged"
        ddict['pixelwidth'] = self._pickerSelectionWidthValue.value()
        ddict['mode'] = mode
        self.sigProfileSignal.emit(ddict)

    def hideProfileSelectionIcons(self):
        if not len(self._pickerSelectionButtons):
            return
        for button in self._pickerSelectionButtons:
            button.setChecked(False)
            button.hide()
        self._pickerSelectionWidthLabel.hide()
        self._pickerSelectionWidthValue.hide()
        if self.graph.getInteractiveMode()['mode'] == 'draw':
            self.graph.setInteractiveMode('select')

    def showProfileSelectionIcons(self):
        if not len(self._pickerSelectionButtons):
            return
        for button in self._pickerSelectionButtons:
            button.show()
        self._pickerSelectionWidthLabel.show()
        self._pickerSelectionWidthValue.show()

    def getPickerSelectionMode(self):
        if not len(self._pickerSelectionButtons):
            return None
        if self.hLineProfileButton.isChecked():
            return "HORIZONTAL"
        if self.vLineProfileButton.isChecked():
            return "VERTICAL"
        if self.lineProfileButton.isChecked():
            return "LINE"
        return None

    def _setPickerSelectionMode(self, mode=None):
        if mode is None:
            self.graph.setInteractiveMode('zoom')
        else:
            if mode == "HORIZONTAL":
                shape = "hline"
            elif mode == "VERTICAL":
                shape = "vline"
            else:
                shape = "line"
            self.graph.setInteractiveMode('draw', shape=shape, label=mode)
        ddict = {}
        if mode is None:
            mode = "NONE"
        ddict['event'] = "profileModeChanged"
        ddict['mode'] = mode
        self.sigProfileSignal.emit(ddict)

    def _graphPolygonSignalReceived(self, ddict):
        _logger.debug("PolygonSignal Received")
        for key in ddict.keys():
            _logger.debug("%s: %s", key, ddict[key])

        if ddict['event'] not in ['drawingProgress', 'drawingFinished']:
            return
        label = ddict['parameters']['label']
        if label not in ['HORIZONTAL', 'VERTICAL', 'LINE']:
            return
        ddict['mode'] = label
        ddict['pixelwidth'] = self._pickerSelectionWidthValue.value()
        self.sigProfileSignal.emit(ddict)

    def _addToolButton(self,
                       icon,
                       action,
                       tip,
                       toggle=None,
                       state=None,
                       position=None):
        tb = qt.QToolButton(self.toolBar)
        if icon is not None:
            tb.setIcon(icon)
        tb.setToolTip(tip)
        if toggle is not None:
            if toggle:
                tb.setCheckable(1)
                if state is not None:
                    if state:
                        tb.setChecked(state)
                else:
                    tb.setChecked(False)
        if position is not None:
            self.toolBarLayout.insertWidget(position, tb)
        else:
            self.toolBarLayout.addWidget(tb)
        if action is not None:
            tb.clicked.connect(action)
        return tb

    def __zoomReset(self):
        self._zoomReset()

    def _zoomReset(self, replot=None):
        _logger.debug("_zoomReset")
        if self.graph is not None:
            self.graph.resetZoom()

    def _yAutoScaleToggle(self):
        if self.graph is not None:
            self.yAutoScaleToolButton.setDown(
                not self.graph.isYAxisAutoScale())
            self.graph.setYAxisAutoScale(not self.graph.isYAxisAutoScale())

    def _xAutoScaleToggle(self):
        if self.graph is not None:
            self.xAutoScaleToolButton.setDown(
                not self.graph.isXAxisAutoScale())
            self.graph.setXAxisAutoScale(not self.graph.isXAxisAutoScale())

    def _copyIconSignal(self):
        pngFile = BytesIO()
        self.graph.saveGraph(pngFile, fileFormat='png')
        pngFile.flush()
        pngFile.seek(0)
        pngData = pngFile.read()
        pngFile.close()
        image = qt.QImage.fromData(pngData, 'png')
        qt.QApplication.clipboard().setImage(image)

    def _saveIconSignal(self):
        self.saveDirectory = PyMcaDirs.outputDir

        fileTypeList = [
            "Image *.png", "Image *.jpg", "ZoomedImage *.png",
            "ZoomedImage *.jpg", "Widget *.png", "Widget *.jpg"
        ]

        outfile = qt.QFileDialog(self)
        outfile.setModal(1)
        outfile.setWindowTitle("Output File Selection")
        if hasattr(qt, "QStringList"):
            strlist = qt.QStringList()
        else:
            strlist = []
        for f in fileTypeList:
            strlist.append(f)
        if hasattr(outfile, "setFilters"):
            outfile.setFilters(strlist)
        else:
            outfile.setNameFilters(strlist)
        outfile.setFileMode(outfile.AnyFile)
        outfile.setAcceptMode(qt.QFileDialog.AcceptSave)
        outfile.setDirectory(self.saveDirectory)
        ret = outfile.exec_()

        if not ret:
            return
        if hasattr(outfile, "selectedFilter"):
            filterused = qt.safe_str(outfile.selectedFilter()).split()
        else:
            filterused = qt.safe_str(outfile.selectedNameFilter()).split()
        filetype = filterused[0]
        extension = filterused[1]

        outstr = qt.safe_str(outfile.selectedFiles()[0])

        try:
            outputFile = os.path.basename(outstr)
        except:
            outputFile = outstr
        outputDir = os.path.dirname(outstr)
        self.saveDirectory = outputDir
        PyMcaDirs.outputDir = outputDir

        #always overwrite for the time being
        if len(outputFile) < len(extension[1:]):
            outputFile += extension[1:]
        elif outputFile[-4:] != extension[1:]:
            outputFile += extension[1:]
        outputFile = os.path.join(outputDir, outputFile)
        if os.path.exists(outputFile):
            try:
                os.remove(outputFile)
            except:
                qt.QMessageBox.critical(self, "Save Error",
                                        "Cannot overwrite existing file")
                return

        if filetype.upper() == "IMAGE":
            self.saveGraphImage(outputFile, original=True)
        elif filetype.upper() == "ZOOMEDIMAGE":
            self.saveGraphImage(outputFile, original=False)
        else:
            self.saveGraphWidget(outputFile)

    def saveGraphImage(self, filename, original=False):
        format_ = filename[-3:].upper()
        activeImage = self.graph.getActiveImage()
        rgbdata = activeImage.getRgbaImageData()
        # silx to pymca scale convention (a + b x)
        xScale = activeImage.getOrigin()[0], activeImage.getScale()[0]
        yScale = activeImage.getOrigin()[1], activeImage.getScale()[1]
        if original:
            # save whole image
            bgradata = numpy.array(rgbdata, copy=True)
            bgradata[:, :, 0] = rgbdata[:, :, 2]
            bgradata[:, :, 2] = rgbdata[:, :, 0]
        else:
            shape = rgbdata.shape[:2]
            xmin, xmax = self.graph.getGraphXLimits()
            ymin, ymax = self.graph.getGraphYLimits()
            # save zoomed image, for that we have to get the limits
            r0, c0 = convertToRowAndColumn(xmin,
                                           ymin,
                                           shape,
                                           xScale=xScale,
                                           yScale=yScale,
                                           safe=True)
            r1, c1 = convertToRowAndColumn(xmax,
                                           ymax,
                                           shape,
                                           xScale=xScale,
                                           yScale=yScale,
                                           safe=True)
            row0 = int(min(r0, r1))
            row1 = int(max(r0, r1))
            col0 = int(min(c0, c1))
            col1 = int(max(c0, c1))
            if row1 < shape[0]:
                row1 += 1
            if col1 < shape[1]:
                col1 += 1
            tmpArray = rgbdata[row0:row1, col0:col1, :]
            bgradata = numpy.array(tmpArray, copy=True, dtype=rgbdata.dtype)
            bgradata[:, :, 0] = tmpArray[:, :, 2]
            bgradata[:, :, 2] = tmpArray[:, :, 0]
        if self.graph.isYAxisInverted():
            qImage = qt.QImage(bgradata, bgradata.shape[1], bgradata.shape[0],
                               qt.QImage.Format_ARGB32)
        else:
            qImage = qt.QImage(bgradata, bgradata.shape[1], bgradata.shape[0],
                               qt.QImage.Format_ARGB32).mirrored(False, True)
        pixmap = qt.QPixmap.fromImage(qImage)
        if pixmap.save(filename, format_):
            return
        else:
            qt.QMessageBox.critical(self, "Save Error",
                                    "%s" % sys.exc_info()[1])
            return

    def saveGraphWidget(self, filename):
        format_ = filename[-3:].upper()
        if hasattr(qt.QPixmap, "grabWidget"):
            # Qt4
            pixmap = qt.QPixmap.grabWidget(self.graph.getWidgetHandle())
        else:
            # Qt5
            pixmap = self.graph.getWidgetHandle().grab()
        if pixmap.save(filename, format_):
            return
        else:
            qt.QMessageBox.critical(self, "Save Error",
                                    "%s" % sys.exc_info()[1])
            return

    def setSaveDirectory(self, wdir):
        if os.path.exists(wdir):
            self.saveDirectory = wdir
            return True
        else:
            return False

    def selectColormap(self):
        qt.QMessageBox.information(self, "Open", "Not implemented (yet)")

    def _zoomBack(self, pos):
        self.graph.getLimitsHistory().pop()
class RGBCorrelatorGraph(qt.QWidget):
    sigProfileSignal = qt.pyqtSignal(object)

    def __init__(self, parent = None, backend=None, selection=False, aspect=True,
                 colormap=False,
                 imageicons=False, standalonesave=True, standalonezoom=True,
                 profileselection=False, polygon=False):
        qt.QWidget.__init__(self, parent)
        self.mainLayout = qt.QVBoxLayout(self)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setSpacing(0)
        self._keepDataAspectRatioFlag = False
        self.graph = PlotWidget(parent=self, backend=backend)
        self.graph.setGraphXLabel("Column")
        self.graph.setGraphYLabel("Row")
        self.graph.setYAxisAutoScale(True)
        self.graph.setXAxisAutoScale(True)
        plotArea = self.graph.getWidgetHandle()
        plotArea.setContextMenuPolicy(qt.Qt.CustomContextMenu)
        plotArea.customContextMenuRequested.connect(self._zoomBack)

        self._buildToolBar(selection, colormap, imageicons,
                           standalonesave,
                           standalonezoom=standalonezoom,
                           profileselection=profileselection,
                           aspect=aspect,
                           polygon=polygon)

        if profileselection:
            if len(self._pickerSelectionButtons):
                self.graph.sigPlotSignal.connect(\
                    self._graphPolygonSignalReceived)
                self._pickerSelectionWidthValue.valueChanged[int].connect( \
                             self.setPickerSelectionWith)

        self.saveDirectory = os.getcwd()
        self.mainLayout.addWidget(self.graph)

    def sizeHint(self):
        return qt.QSize(1.5 * qt.QWidget.sizeHint(self).width(),
                        qt.QWidget.sizeHint(self).height())

    def _buildToolBar(self, selection=False, colormap=False,
                      imageicons=False, standalonesave=True,
                      standalonezoom=True, profileselection=False,
                      aspect=False, polygon=False):
        self.solidCircleIcon = qt.QIcon(qt.QPixmap(IconDict["solidcircle"]))
        self.solidEllipseIcon = qt.QIcon(qt.QPixmap(IconDict["solidellipse"]))
        self.colormapIcon   = qt.QIcon(qt.QPixmap(IconDict["colormap"]))
        self.selectionIcon = qt.QIcon(qt.QPixmap(IconDict["normal"]))
        self.zoomResetIcon = qt.QIcon(qt.QPixmap(IconDict["zoomreset"]))
        self.polygonIcon = qt.QIcon(qt.QPixmap(IconDict["polygon"]))
        self.printIcon	= qt.QIcon(qt.QPixmap(IconDict["fileprint"]))
        self.saveIcon	= qt.QIcon(qt.QPixmap(IconDict["filesave"]))
        self.xAutoIcon	= qt.QIcon(qt.QPixmap(IconDict["xauto"]))
        self.yAutoIcon	= qt.QIcon(qt.QPixmap(IconDict["yauto"]))
        self.hFlipIcon	= qt.QIcon(qt.QPixmap(IconDict["gioconda16mirror"]))
        self.imageIcon     = qt.QIcon(qt.QPixmap(IconDict["image"]))
        self.eraseSelectionIcon = qt.QIcon(qt.QPixmap(IconDict["eraseselect"]))
        self.rectSelectionIcon  = qt.QIcon(qt.QPixmap(IconDict["boxselect"]))
        self.brushSelectionIcon = qt.QIcon(qt.QPixmap(IconDict["brushselect"]))
        self.brushIcon          = qt.QIcon(qt.QPixmap(IconDict["brush"]))
        self.additionalIcon     = qt.QIcon(qt.QPixmap(IconDict["additionalselect"]))
        self.hLineIcon     = qt.QIcon(qt.QPixmap(IconDict["horizontal"]))
        self.vLineIcon     = qt.QIcon(qt.QPixmap(IconDict["vertical"]))
        self.lineIcon     = qt.QIcon(qt.QPixmap(IconDict["diagonal"]))
        self.copyIcon     = silx_icons.getQIcon("edit-copy")

        self.toolBar = qt.QWidget(self)
        self.toolBarLayout = qt.QHBoxLayout(self.toolBar)
        self.toolBarLayout.setContentsMargins(0, 0, 0, 0)
        self.toolBarLayout.setSpacing(0)
        self.mainLayout.addWidget(self.toolBar)
        #Autoscale
        if standalonezoom:
            tb = self._addToolButton(self.zoomResetIcon,
                            self.__zoomReset,
                            'Auto-Scale the Graph')
        else:
            tb = self._addToolButton(self.zoomResetIcon,
                            None,
                            'Auto-Scale the Graph')
        self.zoomResetToolButton = tb
        #y Autoscale
        tb = self._addToolButton(self.yAutoIcon,
                            self._yAutoScaleToggle,
                            'Toggle Autoscale Y Axis (On/Off)',
                            toggle = True, state=True)
        tb.setDown(True)

        self.yAutoScaleToolButton = tb
        tb.setDown(True)

        #x Autoscale
        tb = self._addToolButton(self.xAutoIcon,
                            self._xAutoScaleToggle,
                            'Toggle Autoscale X Axis (On/Off)',
                            toggle = True, state=True)
        self.xAutoScaleToolButton = tb
        tb.setDown(True)

        #Aspect ratio
        if aspect:
            self.aspectButton = self._addToolButton(self.solidCircleIcon,
                                                    self._aspectButtonSignal,
                                                    'Keep data aspect ratio',
                                                    toggle=False)
            self.aspectButton.setChecked(False)

        #colormap
        if colormap:
            tb = self._addToolButton(self.colormapIcon,
                                     None,
                                     'Change Colormap')
            self.colormapToolButton = tb

        #flip
        tb = self._addToolButton(self.hFlipIcon,
                                 None,
                                 'Flip Horizontal')
        self.hFlipToolButton = tb


        #save
        if standalonesave:
            tb = self._addToolButton(self.saveIcon,
                                 self._saveIconSignal,
                                 'Save Graph')
        else:
            tb = self._addToolButton(self.saveIcon,
                                 None,
                                 'Save')
        self.saveToolButton = tb

        self.copyToolButton = self._addToolButton(self.copyIcon,
                                                  self._copyIconSignal,
                                                  "Copy graph to clipboard")

        #Selection
        if selection:
            tb = self._addToolButton(self.selectionIcon,
                                None,
                                'Toggle Selection Mode',
                                toggle = True,
                                state = False)
            tb.setDown(False)
            self.selectionToolButton = tb
        #image selection icons
        if imageicons:
            tb = self._addToolButton(self.imageIcon,
                                     None,
                                     'Reset')
            self.imageToolButton = tb

            tb = self._addToolButton(self.eraseSelectionIcon,
                                     None,
                                     'Erase Selection')
            self.eraseSelectionToolButton = tb

            tb = self._addToolButton(self.rectSelectionIcon,
                                     None,
                                     'Rectangular Selection')
            self.rectSelectionToolButton = tb

            tb = self._addToolButton(self.brushSelectionIcon,
                                     None,
                                     'Brush Selection')
            self.brushSelectionToolButton = tb

            tb = self._addToolButton(self.brushIcon,
                                     None,
                                     'Select Brush')
            self.brushToolButton = tb

            if polygon:
                tb = self._addToolButton(self.polygonIcon,
                                     None,
                        'Polygon selection\nRight click to finish')
                self.polygonSelectionToolButton = tb

            tb = self._addToolButton(self.additionalIcon,
                                     None,
                                     'Additional Selections Menu')
            self.additionalSelectionToolButton = tb
        else:
            if polygon:
                tb = self._addToolButton(self.polygonIcon,
                                     None,
                        'Polygon selection\nRight click to finish')
                self.polygonSelectionToolButton = tb
            self.imageToolButton = None
        #picker selection
        self._pickerSelectionButtons = []
        if profileselection:
            self._profileSelection = True
            self._polygonSelection = False
            self._pickerSelectionButtons = []
            if self._profileSelection:
                tb = self._addToolButton(self.hLineIcon,
                                     self._hLineProfileClicked,
                                     'Horizontal Profile Selection',
                                     toggle=True,
                                     state=False)
                self.hLineProfileButton = tb
                self._pickerSelectionButtons.append(tb)

                tb = self._addToolButton(self.vLineIcon,
                                     self._vLineProfileClicked,
                                     'Vertical Profile Selection',
                                     toggle=True,
                                     state=False)
                self.vLineProfileButton = tb
                self._pickerSelectionButtons.append(tb)

                tb = self._addToolButton(self.lineIcon,
                                     self._lineProfileClicked,
                                     'Line Profile Selection',
                                     toggle=True,
                                     state=False)
                self.lineProfileButton = tb
                self._pickerSelectionButtons.append(tb)

                self._pickerSelectionWidthLabel = qt.QLabel(self.toolBar)
                self._pickerSelectionWidthLabel.setText("W:")
                self.toolBar.layout().addWidget(self._pickerSelectionWidthLabel)
                self._pickerSelectionWidthValue = qt.QSpinBox(self.toolBar)
                self._pickerSelectionWidthValue.setMinimum(0)
                self._pickerSelectionWidthValue.setMaximum(1000)
                self._pickerSelectionWidthValue.setValue(1)
                self.toolBar.layout().addWidget(self._pickerSelectionWidthValue)
                #tb = self._addToolButton(None,
                #                     self._lineProfileClicked,
                #                     'Line Profile Selection',
                #                     toggle=True,
                #                     state=False)
                #tb.setText = "W:"
                #self.lineWidthProfileButton = tb
                #self._pickerSelectionButtons.append(tb)
            if self._polygonSelection:
                _logger.info("Polygon selection not implemented yet")
        #hide profile selection buttons
        if imageicons:
            for button in self._pickerSelectionButtons:
                button.hide()

        self.infoWidget = qt.QWidget(self.toolBar)
        self.infoWidget.mainLayout = qt.QHBoxLayout(self.infoWidget)
        self.infoWidget.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.infoWidget.mainLayout.setSpacing(0)
        self.infoWidget.label = qt.QLabel(self.infoWidget)
        self.infoWidget.label.setText("X = ???? Y = ???? Z = ????")
        self.infoWidget.mainLayout.addWidget(self.infoWidget.label)
        self.toolBarLayout.addWidget(self.infoWidget)
        self.infoWidget.hide()

        self.toolBarLayout.addWidget(qt.HorizontalSpacer(self.toolBar))

        # ---print
        self.printPreview = SingletonPrintPreviewToolButton(parent=self,
                                                            plot=self.graph)
        self.printPreview.setIcon(self.printIcon)
        self.toolBarLayout.addWidget(self.printPreview)

    def _aspectButtonSignal(self):
        _logger.debug("_aspectButtonSignal")
        if self._keepDataAspectRatioFlag:
            self.keepDataAspectRatio(False)
        else:
            self.keepDataAspectRatio(True)

    def keepDataAspectRatio(self, flag=True):
        if flag:
            self._keepDataAspectRatioFlag = True
            self.aspectButton.setIcon(self.solidEllipseIcon)
            self.aspectButton.setToolTip("Set free data aspect ratio")
        else:
            self._keepDataAspectRatioFlag = False
            self.aspectButton.setIcon(self.solidCircleIcon)
            self.aspectButton.setToolTip("Keep data aspect ratio")
        self.graph.setKeepDataAspectRatio(self._keepDataAspectRatioFlag)

    def showInfo(self):
        self.infoWidget.show()

    def hideInfo(self):
        self.infoWidget.hide()

    def setInfoText(self, text):
        self.infoWidget.label.setText(text)

    def setMouseText(self, text=""):
        try:
            if len(text):
                qt.QToolTip.showText(self.cursor().pos(),
                                     text, self, qt.QRect())
            else:
                qt.QToolTip.hideText()
        except:
            _logger.warning("Error trying to show mouse text <%s>" % text)

    def focusOutEvent(self, ev):
        qt.QToolTip.hideText()

    def infoText(self):
        return self.infoWidget.label.text()

    def setXLabel(self, label="Column"):
        return self.graph.setGraphXLabel(label)

    def setYLabel(self, label="Row"):
        return self.graph.setGraphYLabel(label)

    def getXLabel(self):
        return self.graph.getGraphXLabel()

    def getYLabel(self):
        return self.graph.getGraphYLabel()

    def hideImageIcons(self):
        if self.imageToolButton is None:return
        self.imageToolButton.hide()
        self.eraseSelectionToolButton.hide()
        self.rectSelectionToolButton.hide()
        self.brushSelectionToolButton.hide()
        self.brushToolButton.hide()
        if hasattr(self, "polygonSelectionToolButton"):
            self.polygonSelectionToolButton.hide()
        self.additionalSelectionToolButton.hide()

    def showImageIcons(self):
        if self.imageToolButton is None:return
        self.imageToolButton.show()
        self.eraseSelectionToolButton.show()
        self.rectSelectionToolButton.show()
        self.brushSelectionToolButton.show()
        self.brushToolButton.show()
        if hasattr(self, "polygonSelectionToolButton"):
            self.polygonSelectionToolButton.show()
        self.additionalSelectionToolButton.show()

    def _hLineProfileClicked(self):
        for button in self._pickerSelectionButtons:
            if button != self.hLineProfileButton:
                button.setChecked(False)

        if self.hLineProfileButton.isChecked():
            self._setPickerSelectionMode("HORIZONTAL")
        else:
            self._setPickerSelectionMode(None)

    def _vLineProfileClicked(self):
        for button in self._pickerSelectionButtons:
            if button != self.vLineProfileButton:
                button.setChecked(False)
        if self.vLineProfileButton.isChecked():
            self._setPickerSelectionMode("VERTICAL")
        else:
            self._setPickerSelectionMode(None)

    def _lineProfileClicked(self):
        for button in self._pickerSelectionButtons:
            if button != self.lineProfileButton:
                button.setChecked(False)
        if self.lineProfileButton.isChecked():
            self._setPickerSelectionMode("LINE")
        else:
            self._setPickerSelectionMode(None)

    def setPickerSelectionWith(self, intValue):
        self._pickerSelectionWidthValue.setValue(intValue)
        #get the current mode
        mode = "NONE"
        for button in self._pickerSelectionButtons:
            if button.isChecked():
                if button == self.hLineProfileButton:
                    mode = "HORIZONTAL"
                elif button == self.vLineProfileButton:
                    mode = "VERTICAL"
                elif button == self.lineProfileButton:
                    mode = "LINE"
        ddict = {}
        ddict['event'] = "profileWidthChanged"
        ddict['pixelwidth'] = self._pickerSelectionWidthValue.value()
        ddict['mode'] = mode
        self.sigProfileSignal.emit(ddict)

    def hideProfileSelectionIcons(self):
        if not len(self._pickerSelectionButtons):
            return
        for button in self._pickerSelectionButtons:
            button.setChecked(False)
            button.hide()
        self._pickerSelectionWidthLabel.hide()
        self._pickerSelectionWidthValue.hide()
        if self.graph.getInteractiveMode()['mode'] == 'draw':
            self.graph.setInteractiveMode('select')

    def showProfileSelectionIcons(self):
        if not len(self._pickerSelectionButtons):
            return
        for button in self._pickerSelectionButtons:
            button.show()
        self._pickerSelectionWidthLabel.show()
        self._pickerSelectionWidthValue.show()

    def getPickerSelectionMode(self):
        if not len(self._pickerSelectionButtons):
            return None
        if self.hLineProfileButton.isChecked():
            return "HORIZONTAL"
        if self.vLineProfileButton.isChecked():
            return "VERTICAL"
        if self.lineProfileButton.isChecked():
            return "LINE"
        return None

    def _setPickerSelectionMode(self, mode=None):
        if mode is None:
            self.graph.setInteractiveMode('zoom')
        else:
            if mode == "HORIZONTAL":
                shape = "hline"
            elif mode == "VERTICAL":
                shape = "vline"
            else:
                shape = "line"
            self.graph.setInteractiveMode('draw',
                                          shape=shape,
                                          label=mode)
        ddict = {}
        if mode is None:
            mode = "NONE"
        ddict['event'] = "profileModeChanged"
        ddict['mode'] = mode
        self.sigProfileSignal.emit(ddict)

    def _graphPolygonSignalReceived(self, ddict):
        _logger.debug("PolygonSignal Received")
        for key in ddict.keys():
            _logger.debug("%s: %s", key, ddict[key])

        if ddict['event'] not in ['drawingProgress', 'drawingFinished']:
            return
        label = ddict['parameters']['label']
        if label not in ['HORIZONTAL', 'VERTICAL', 'LINE']:
            return
        ddict['mode'] = label
        ddict['pixelwidth'] = self._pickerSelectionWidthValue.value()
        self.sigProfileSignal.emit(ddict)

    def _addToolButton(self, icon, action, tip, toggle=None, state=None, position=None):
        tb      = qt.QToolButton(self.toolBar)
        if icon is not None:
            tb.setIcon(icon)
        tb.setToolTip(tip)
        if toggle is not None:
            if toggle:
                tb.setCheckable(1)
                if state is not None:
                    if state:
                        tb.setChecked(state)
                else:
                    tb.setChecked(False)
        if position is not None:
            self.toolBarLayout.insertWidget(position, tb)
        else:
            self.toolBarLayout.addWidget(tb)
        if action is not None:
            tb.clicked.connect(action)
        return tb

    def __zoomReset(self):
        self._zoomReset()

    def _zoomReset(self, replot=None):
        _logger.debug("_zoomReset")
        if self.graph is not None:
            self.graph.resetZoom()

    def _yAutoScaleToggle(self):
        if self.graph is not None:
            self.yAutoScaleToolButton.setDown(
                    not self.graph.isYAxisAutoScale())
            self.graph.setYAxisAutoScale(
                    not self.graph.isYAxisAutoScale())

    def _xAutoScaleToggle(self):
        if self.graph is not None:
            self.xAutoScaleToolButton.setDown(
                    not self.graph.isXAxisAutoScale())
            self.graph.setXAxisAutoScale(
                    not self.graph.isXAxisAutoScale())

    def _copyIconSignal(self):
        pngFile = BytesIO()
        self.graph.saveGraph(pngFile, fileFormat='png')
        pngFile.flush()
        pngFile.seek(0)
        pngData = pngFile.read()
        pngFile.close()
        image = qt.QImage.fromData(pngData, 'png')
        qt.QApplication.clipboard().setImage(image)

    def _saveIconSignal(self):
        self.saveDirectory = PyMcaDirs.outputDir

        fileTypeList = ["Image *.png",
                        "Image *.jpg",
                        "ZoomedImage *.png",
                        "ZoomedImage *.jpg",
                        "Widget *.png",
                        "Widget *.jpg"]

        outfile = qt.QFileDialog(self)
        outfile.setModal(1)
        outfile.setWindowTitle("Output File Selection")
        if hasattr(qt, "QStringList"):
            strlist = qt.QStringList()
        else:
            strlist = []
        for f in fileTypeList:
            strlist.append(f)
        if hasattr(outfile, "setFilters"):
            outfile.setFilters(strlist)
        else:
            outfile.setNameFilters(strlist)
        outfile.setFileMode(outfile.AnyFile)
        outfile.setAcceptMode(qt.QFileDialog.AcceptSave)
        outfile.setDirectory(self.saveDirectory)
        ret = outfile.exec_()

        if not ret:
            return
        if hasattr(outfile, "selectedFilter"):
            filterused = qt.safe_str(outfile.selectedFilter()).split()
        else:
            filterused = qt.safe_str(outfile.selectedNameFilter()).split()
        filetype = filterused[0]
        extension = filterused[1]

        outstr = qt.safe_str(outfile.selectedFiles()[0])

        try:
            outputFile = os.path.basename(outstr)
        except:
            outputFile = outstr
        outputDir  = os.path.dirname(outstr)
        self.saveDirectory = outputDir
        PyMcaDirs.outputDir = outputDir

        #always overwrite for the time being
        if len(outputFile) < len(extension[1:]):
            outputFile += extension[1:]
        elif outputFile[-4:] != extension[1:]:
            outputFile += extension[1:]
        outputFile = os.path.join(outputDir, outputFile)
        if os.path.exists(outputFile):
            try:
                os.remove(outputFile)
            except:
                qt.QMessageBox.critical(self, "Save Error",
                                        "Cannot overwrite existing file")
                return

        if filetype.upper() == "IMAGE":
            self.saveGraphImage(outputFile, original=True)
        elif filetype.upper() == "ZOOMEDIMAGE":
            self.saveGraphImage(outputFile, original=False)
        else:
            self.saveGraphWidget(outputFile)

    def saveGraphImage(self, filename, original=False):
        format_ = filename[-3:].upper()
        activeImage = self.graph.getActiveImage()
        rgbdata = activeImage.getRgbaImageData()
        # silx to pymca scale convention (a + b x)
        xScale = activeImage.getOrigin()[0], activeImage.getScale()[0]
        yScale = activeImage.getOrigin()[1], activeImage.getScale()[1]
        if original:
            # save whole image
            bgradata = numpy.array(rgbdata, copy=True)
            bgradata[:, :, 0] = rgbdata[:, :, 2]
            bgradata[:, :, 2] = rgbdata[:, :, 0]
        else:
            shape = rgbdata.shape[:2]
            xmin, xmax = self.graph.getGraphXLimits()
            ymin, ymax = self.graph.getGraphYLimits()
            # save zoomed image, for that we have to get the limits
            r0, c0 = convertToRowAndColumn(xmin, ymin, shape, xScale=xScale, yScale=yScale, safe=True)
            r1, c1 = convertToRowAndColumn(xmax, ymax, shape, xScale=xScale, yScale=yScale, safe=True)
            row0 = int(min(r0, r1))
            row1 = int(max(r0, r1))
            col0 = int(min(c0, c1))
            col1 = int(max(c0, c1))
            if row1 < shape[0]:
                row1 += 1
            if col1 < shape[1]:
                col1 += 1
            tmpArray = rgbdata[row0:row1, col0:col1, :]
            bgradata = numpy.array(tmpArray, copy=True, dtype=rgbdata.dtype)
            bgradata[:, :, 0] = tmpArray[:, :, 2]
            bgradata[:, :, 2] = tmpArray[:, :, 0]
        if self.graph.isYAxisInverted():
            qImage = qt.QImage(bgradata, bgradata.shape[1], bgradata.shape[0],
                               qt.QImage.Format_ARGB32)
        else:
            qImage = qt.QImage(bgradata, bgradata.shape[1], bgradata.shape[0],
                               qt.QImage.Format_ARGB32).mirrored(False, True)
        pixmap = qt.QPixmap.fromImage(qImage)
        if pixmap.save(filename, format_):
            return
        else:
            qt.QMessageBox.critical(self, "Save Error",
                                    "%s" % sys.exc_info()[1])
            return
    
    def saveGraphWidget(self, filename):
        format_ = filename[-3:].upper()
        if hasattr(qt.QPixmap, "grabWidget"):
            # Qt4
            pixmap = qt.QPixmap.grabWidget(self.graph.getWidgetHandle())
        else:
            # Qt5
            pixmap = self.graph.getWidgetHandle().grab()
        if pixmap.save(filename, format_):
            return
        else:
            qt.QMessageBox.critical(self, "Save Error", "%s" % sys.exc_info()[1])
            return

    def setSaveDirectory(self, wdir):
        if os.path.exists(wdir):
            self.saveDirectory = wdir
            return True
        else:
            return False

    def selectColormap(self):
        qt.QMessageBox.information(self, "Open", "Not implemented (yet)")

    def _zoomBack(self, pos):
        self.graph.getLimitsHistory().pop()