def testDataRangeLeftRight(self):
        """right+left axis range"""

        plot = PlotWidget(backend='none')

        xData_l = numpy.arange(10) - 0.9  # range : -0.9 , 8.1
        yData_l = numpy.arange(10) - 1.9  # range : -1.9 , 7.1
        plot.addCurve(x=xData_l, y=yData_l, legend='plot_l', yaxis='left')

        xData_r = numpy.arange(10) - 4.9  # range : -4.9 , 4.1
        yData_r = numpy.arange(10) - 6.9  # range : -6.9 , 2.1
        plot.addCurve(x=xData_r, y=yData_r, legend='plot_r', yaxis='right')

        for logX, logY in ((False, False), (True, False), (True, True),
                           (False, True), (False, False)):
            with self.subTest(logX=logX, logY=logY):
                plot.getXAxis()._setLogarithmic(logX)
                plot.getYAxis()._setLogarithmic(logY)
                dataRange = plot.getDataRange()
                xRangeL, yRangeL = self._getRanges([xData_l, yData_l],
                                                   [logX, logY])
                xRangeR, yRangeR = self._getRanges([xData_r, yData_r],
                                                   [logX, logY])
                xRangeLR = self._getRangesMinmax([xRangeL, xRangeR])
                self.assertSequenceEqual(dataRange.x, xRangeLR)
                self.assertSequenceEqual(dataRange.y, yRangeL)
                self.assertSequenceEqual(dataRange.yright, yRangeR)
    def testDataRangeImageNegativeScaleY(self):
        """image data range, negative scale"""

        origin = (-10, 25)
        scale = (3., -8.)
        image = numpy.arange(100.).reshape(20, 5)

        plot = PlotWidget(backend='none')
        plot.addImage(image, origin=origin, scale=scale)

        xRange = numpy.array([0., image.shape[1] * scale[0]]) + origin[0]
        yRange = numpy.array([0., image.shape[0] * scale[1]]) + origin[1]
        yRange.sort()  # negative scale!

        ranges = {
            (False, False): (xRange, yRange),
            (True, False): (None, None),
            (True, True): (None, None),
            (False, True): (None, None)
        }

        for logX, logY in ((False, False), (True, False), (True, True),
                           (False, True), (False, False)):
            with self.subTest(logX=logX, logY=logY):
                plot.getXAxis()._setLogarithmic(logX)
                plot.getYAxis()._setLogarithmic(logY)
                dataRange = plot.getDataRange()
                xRange, yRange = ranges[logX, logY]
                self.assertTrue(numpy.array_equal(dataRange.x, xRange),
                                msg='{0} != {1}'.format(dataRange.x, xRange))
                self.assertTrue(numpy.array_equal(dataRange.y, yRange),
                                msg='{0} != {1}'.format(dataRange.y, yRange))
                self.assertIsNone(dataRange.yright)
    def testDataRangeRight(self):
        """right axis range"""

        plot = PlotWidget(backend='none')
        xData = numpy.arange(10) - 4.9  # range : -4.9 , 4.1
        yData = numpy.arange(10) - 6.9  # range : -6.9 , 2.1
        plot.addCurve(x=xData,
                      y=yData,
                      legend='plot_0',
                      yaxis='right')

        for logX, logY in ((False, False),
                           (True, False),
                           (True, True),
                           (False, True),
                           (False, False)):
            with self.subTest(logX=logX, logY=logY):
                plot.getXAxis()._setLogarithmic(logX)
                plot.getYAxis()._setLogarithmic(logY)
                dataRange = plot.getDataRange()
                xRange, yRange = self._getRanges([xData, yData],
                                                 [logX, logY])
                self.assertSequenceEqual(dataRange.x, xRange)
                self.assertIsNone(dataRange.y)
                self.assertSequenceEqual(dataRange.yright, yRange)
    def testDataRangeImageNegativeScaleY(self):
        """image data range, negative scale"""

        origin = (-10, 25)
        scale = (3., -8.)
        image = numpy.arange(100.).reshape(20, 5)

        plot = PlotWidget(backend='none')
        plot.addImage(image,
                      origin=origin, scale=scale)

        xRange = numpy.array([0., image.shape[1] * scale[0]]) + origin[0]
        yRange = numpy.array([0., image.shape[0] * scale[1]]) + origin[1]
        yRange.sort()  # negative scale!

        ranges = {(False, False): (xRange, yRange),
                  (True, False): (None, None),
                  (True, True): (None, None),
                  (False, True): (None, None)}

        for logX, logY in ((False, False),
                           (True, False),
                           (True, True),
                           (False, True),
                           (False, False)):
            with self.subTest(logX=logX, logY=logY):
                plot.getXAxis()._setLogarithmic(logX)
                plot.getYAxis()._setLogarithmic(logY)
                dataRange = plot.getDataRange()
                xRange, yRange = ranges[logX, logY]
                self.assertTrue(numpy.array_equal(dataRange.x, xRange),
                                msg='{0} != {1}'.format(dataRange.x, xRange))
                self.assertTrue(numpy.array_equal(dataRange.y, yRange),
                                msg='{0} != {1}'.format(dataRange.y, yRange))
                self.assertIsNone(dataRange.yright)
    def testDataRangeRight(self):
        """right axis range"""

        plot = PlotWidget(backend='none')
        xData = numpy.arange(10) - 4.9  # range : -4.9 , 4.1
        yData = numpy.arange(10) - 6.9  # range : -6.9 , 2.1
        plot.addCurve(x=xData,
                      y=yData,
                      legend='plot_0',
                      yaxis='right')

        for logX, logY in ((False, False),
                           (True, False),
                           (True, True),
                           (False, True),
                           (False, False)):
            with self.subTest(logX=logX, logY=logY):
                plot.getXAxis()._setLogarithmic(logX)
                plot.getYAxis()._setLogarithmic(logY)
                dataRange = plot.getDataRange()
                xRange, yRange = self._getRanges([xData, yData],
                                                 [logX, logY])
                self.assertSequenceEqual(dataRange.x, xRange)
                self.assertIsNone(dataRange.y)
                self.assertSequenceEqual(dataRange.yright, yRange)
    def testDataRangeCurveImage(self):
        """right+left+image axis range"""

        # overlapping ranges :
        # image sets x min and y max
        # plot_left sets y min
        # plot_right sets x max (and yright)
        plot = PlotWidget(backend='none')

        origin = (-10, 5)
        scale = (3., 8.)
        image = numpy.arange(100.).reshape(20, 5)

        plot.addImage(image,
                      origin=origin, scale=scale, legend='image')

        xData_l = numpy.arange(10) - 0.9  # range : -0.9 , 8.1
        yData_l = numpy.arange(10) - 1.9  # range : -1.9 , 7.1
        plot.addCurve(x=xData_l,
                      y=yData_l,
                      legend='plot_l',
                      yaxis='left')

        xData_r = numpy.arange(10) + 4.1  # range : 4.1 , 13.1
        yData_r = numpy.arange(10) - 0.9  # range : -0.9 , 8.1
        plot.addCurve(x=xData_r,
                      y=yData_r,
                      legend='plot_r',
                      yaxis='right')

        imgXRange = numpy.array([0., image.shape[1] * scale[0]]) + origin[0]
        imgYRange = numpy.array([0., image.shape[0] * scale[1]]) + origin[1]

        for logX, logY in ((False, False),
                           (True, False),
                           (True, True),
                           (False, True),
                           (False, False)):
            with self.subTest(logX=logX, logY=logY):
                plot.getXAxis()._setLogarithmic(logX)
                plot.getYAxis()._setLogarithmic(logY)
                dataRange = plot.getDataRange()
                xRangeL, yRangeL = self._getRanges([xData_l, yData_l],
                                                   [logX, logY])
                xRangeR, yRangeR = self._getRanges([xData_r, yData_r],
                                                   [logX, logY])
                if logX or logY:
                    xRangeLR = self._getRangesMinmax([xRangeL, xRangeR])
                else:
                    xRangeLR = self._getRangesMinmax([xRangeL,
                                                      xRangeR,
                                                      imgXRange])
                    yRangeL = self._getRangesMinmax([yRangeL, imgYRange])
                self.assertSequenceEqual(dataRange.x, xRangeLR)
                self.assertSequenceEqual(dataRange.y, yRangeL)
                self.assertSequenceEqual(dataRange.yright, yRangeR)
    def testDataRangeCurveImage(self):
        """right+left+image axis range"""

        # overlapping ranges :
        # image sets x min and y max
        # plot_left sets y min
        # plot_right sets x max (and yright)
        plot = PlotWidget(backend='none')

        origin = (-10, 5)
        scale = (3., 8.)
        image = numpy.arange(100.).reshape(20, 5)

        plot.addImage(image,
                      origin=origin, scale=scale, legend='image')

        xData_l = numpy.arange(10) - 0.9  # range : -0.9 , 8.1
        yData_l = numpy.arange(10) - 1.9  # range : -1.9 , 7.1
        plot.addCurve(x=xData_l,
                      y=yData_l,
                      legend='plot_l',
                      yaxis='left')

        xData_r = numpy.arange(10) + 4.1  # range : 4.1 , 13.1
        yData_r = numpy.arange(10) - 0.9  # range : -0.9 , 8.1
        plot.addCurve(x=xData_r,
                      y=yData_r,
                      legend='plot_r',
                      yaxis='right')

        imgXRange = numpy.array([0., image.shape[1] * scale[0]]) + origin[0]
        imgYRange = numpy.array([0., image.shape[0] * scale[1]]) + origin[1]

        for logX, logY in ((False, False),
                           (True, False),
                           (True, True),
                           (False, True),
                           (False, False)):
            with self.subTest(logX=logX, logY=logY):
                plot.getXAxis()._setLogarithmic(logX)
                plot.getYAxis()._setLogarithmic(logY)
                dataRange = plot.getDataRange()
                xRangeL, yRangeL = self._getRanges([xData_l, yData_l],
                                                   [logX, logY])
                xRangeR, yRangeR = self._getRanges([xData_r, yData_r],
                                                   [logX, logY])
                if logX or logY:
                    xRangeLR = self._getRangesMinmax([xRangeL, xRangeR])
                else:
                    xRangeLR = self._getRangesMinmax([xRangeL,
                                                      xRangeR,
                                                      imgXRange])
                    yRangeL = self._getRangesMinmax([yRangeL, imgYRange])
                self.assertSequenceEqual(dataRange.x, xRangeLR)
                self.assertSequenceEqual(dataRange.y, yRangeL)
                self.assertSequenceEqual(dataRange.yright, yRangeR)
    def testPlotTitleLabels(self):
        """Create a Plot and set the labels"""

        plot = PlotWidget(backend='none')

        title, xlabel, ylabel = 'the title', 'x label', 'y label'
        plot.setGraphTitle(title)
        plot.getXAxis().setLabel(xlabel)
        plot.getYAxis().setLabel(ylabel)

        self.assertEqual(plot.getGraphTitle(), title)
        self.assertEqual(plot.getXAxis().getLabel(), xlabel)
        self.assertEqual(plot.getYAxis().getLabel(), ylabel)
    def testPlotTitleLabels(self):
        """Create a Plot and set the labels"""

        plot = PlotWidget(backend='none')

        title, xlabel, ylabel = 'the title', 'x label', 'y label'
        plot.setGraphTitle(title)
        plot.getXAxis().setLabel(xlabel)
        plot.getYAxis().setLabel(ylabel)

        self.assertEqual(plot.getGraphTitle(), title)
        self.assertEqual(plot.getXAxis().getLabel(), xlabel)
        self.assertEqual(plot.getYAxis().getLabel(), ylabel)
    def testDataRangeNoPlot(self):
        """empty plot data range"""

        plot = PlotWidget(backend='none')

        for logX, logY in ((False, False), (True, False), (True, True),
                           (False, True), (False, False)):
            with self.subTest(logX=logX, logY=logY):
                plot.getXAxis()._setLogarithmic(logX)
                plot.getYAxis()._setLogarithmic(logY)
                dataRange = plot.getDataRange()
                self.assertIsNone(dataRange.x)
                self.assertIsNone(dataRange.y)
                self.assertIsNone(dataRange.yright)
    def testDataRangeNoPlot(self):
        """empty plot data range"""

        plot = PlotWidget(backend='none')

        for logX, logY in ((False, False),
                           (True, False),
                           (True, True),
                           (False, True),
                           (False, False)):
            with self.subTest(logX=logX, logY=logY):
                plot.getXAxis()._setLogarithmic(logX)
                plot.getYAxis()._setLogarithmic(logY)
                dataRange = plot.getDataRange()
                self.assertIsNone(dataRange.x)
                self.assertIsNone(dataRange.y)
                self.assertIsNone(dataRange.yright)
    def testDataRangeLeftRight(self):
        """right+left axis range"""

        plot = PlotWidget(backend='none')

        xData_l = numpy.arange(10) - 0.9  # range : -0.9 , 8.1
        yData_l = numpy.arange(10) - 1.9  # range : -1.9 , 7.1
        plot.addCurve(x=xData_l,
                      y=yData_l,
                      legend='plot_l',
                      yaxis='left')

        xData_r = numpy.arange(10) - 4.9  # range : -4.9 , 4.1
        yData_r = numpy.arange(10) - 6.9  # range : -6.9 , 2.1
        plot.addCurve(x=xData_r,
                      y=yData_r,
                      legend='plot_r',
                      yaxis='right')

        for logX, logY in ((False, False),
                           (True, False),
                           (True, True),
                           (False, True),
                           (False, False)):
            with self.subTest(logX=logX, logY=logY):
                plot.getXAxis()._setLogarithmic(logX)
                plot.getYAxis()._setLogarithmic(logY)
                dataRange = plot.getDataRange()
                xRangeL, yRangeL = self._getRanges([xData_l, yData_l],
                                                   [logX, logY])
                xRangeR, yRangeR = self._getRanges([xData_r, yData_r],
                                                   [logX, logY])
                xRangeLR = self._getRangesMinmax([xRangeL, xRangeR])
                self.assertSequenceEqual(dataRange.x, xRangeLR)
                self.assertSequenceEqual(dataRange.y, yRangeL)
                self.assertSequenceEqual(dataRange.yright, yRangeR)
class _ImagePreview(qt.QWidget):
    """Provide a preview of the selected image"""

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

        self.__data = None
        self.__plot = PlotWidget(self)
        self.__plot.setAxesDisplayed(False)
        self.__plot.setKeepDataAspectRatio(True)
        layout = qt.QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.__plot)
        self.setLayout(layout)

    def resizeEvent(self, event):
        self.__updateConstraints()
        return qt.QWidget.resizeEvent(self, event)

    def sizeHint(self):
        return qt.QSize(200, 200)

    def plot(self):
        return self.__plot

    def setData(self, data, fromDataSelector=False):
        if data is None:
            self.clear()
            return

        resetzoom = not fromDataSelector
        previousImage = self.data()
        if previousImage is not None and data.shape != previousImage.shape:
            resetzoom = True

        self.__plot.addImage(legend="data", data=data, resetzoom=resetzoom)
        self.__data = data
        self.__updateConstraints()

    def __updateConstraints(self):
        """
        Update the constraints depending on the size of the widget
        """
        image = self.data()
        if image is None:
            return
        size = self.size()
        if size.width() == 0 or size.height() == 0:
            return

        heightData, widthData = image.shape

        widthContraint = heightData * size.width() / size.height()
        if widthContraint > widthData:
            heightContraint = heightData
        else:
            heightContraint = heightData * size.height() / size.width()
            widthContraint = widthData

        midWidth, midHeight = widthData * 0.5, heightData * 0.5
        heightContraint, widthContraint = heightContraint * 0.5, widthContraint * 0.5

        axis = self.__plot.getXAxis()
        axis.setLimitsConstraints(midWidth - widthContraint, midWidth + widthContraint)
        axis = self.__plot.getYAxis()
        axis.setLimitsConstraints(midHeight - heightContraint, midHeight + heightContraint)

    def __imageItem(self):
        image = self.__plot.getImage("data")
        return image

    def data(self):
        if self.__data is not None:
            if hasattr(self.__data, "name"):
                # in case of HDF5
                if self.__data.name is None:
                    # The dataset was closed
                    self.__data = None
        return self.__data

    def colormap(self):
        image = self.__imageItem()
        if image is not None:
            return image.getColormap()
        return self.__plot.getDefaultColormap()

    def setColormap(self, colormap):
        self.__plot.setDefaultColormap(colormap)

    def clear(self):
        self.__data = None
        image = self.__imageItem()
        if image is not None:
            self.__plot.removeImage(legend="data")