Example #1
0
    def _drawContents(self, reason=None, initiator=None):
        """ Draws the plot contents from the sliced array of the collected repo tree item.

            The reason parameter is used to determine if the axes will be reset (the initiator
            parameter is ignored). See AbstractInspector.updateContents for their description.
        """

        # If auto-reset is true, reset config complete or partially, depending on the mode.
        if self._resetRequired(reason, initiator):
            self.resetConfig()

        self.crossPlotRow = None  # reset because the sliced array shape may change
        self.crossPlotCol = None  # idem dito

        gridLayout = self.graphicsLayoutWidget.ci.layout  # A QGraphicsGridLayout

        if self.config.horCrossPlotCti.configValue:
            gridLayout.setRowStretchFactor(ROW_HOR_LINE, 1)
            if not self.horPlotAdded:
                self.graphicsLayoutWidget.addItem(self.horCrossPlotItem,
                                                  ROW_HOR_LINE, COL_HOR_LINE)
                self.horPlotAdded = True
                gridLayout.activate()
        else:
            gridLayout.setRowStretchFactor(ROW_HOR_LINE, 0)
            if self.horPlotAdded:
                self.graphicsLayoutWidget.removeItem(self.horCrossPlotItem)
                self.horPlotAdded = False
                gridLayout.activate()

        if self.config.verCrossPlotCti.configValue:
            gridLayout.setColumnStretchFactor(COL_VER_LINE, 1)
            if not self.verPlotAdded:
                self.graphicsLayoutWidget.addItem(self.verCrossPlotItem,
                                                  ROW_VER_LINE, COL_VER_LINE)
                self.verPlotAdded = True
                gridLayout.activate()
        else:
            gridLayout.setColumnStretchFactor(COL_VER_LINE, 0)
            if self.verPlotAdded:
                self.graphicsLayoutWidget.removeItem(self.verCrossPlotItem)
                self.verPlotAdded = False
                gridLayout.activate()

        slicedArray = self.collector.getSlicedArray()
        if slicedArray is None:
            self._clearContents()
            raise InvalidDataError()  # Don't show message, to common.
        elif not array_has_real_numbers(slicedArray.data):
            self._clearContents()
            raise InvalidDataError("Selected item contains {} data.".format(
                array_kind_label(slicedArray.data)))
        else:
            self.slicedArray = slicedArray

        # -- Valid plot data from here on --

        if self.config.crossPlotGroupCti.checkState != Qt.Unchecked:
            tempPlotDataItem = self.config.crossPenCti.createPlotDataItem()
            if tempPlotDataItem.opts['pen'] is None and tempPlotDataItem.opts[
                    'symbol'] is None:
                self.sigShowMessage.emit(
                    "The cross-hair pen 'line' and 'symbol' config options are both unchecked!"
                )

        numElem = np.prod(self.slicedArray.data.shape)
        if numElem == 0:
            self.sigShowMessage.emit(
                "Current slice is empty.")  # Not expected to happen.
        elif numElem == 1:
            self.sigShowMessage.emit(
                "Current slice contains only a single data point.")

        # PyQtGraph doesn't handle masked arrays so we convert the masked values to Nans. Missing
        # data values are replaced by NaNs. The PyQtGraph image plot shows this as the color at the
        # lowest end of the color scale. Unfortunately we cannot choose a missing-value color, but
        # at least the Nans do not influence for the histogram and color range.
        # We don't update self.slicedArray here because the data probe should still be able to
        # print the actual value.
        imageArray = replaceMaskedValueWithFloat(self.slicedArray.data,
                                                 self.slicedArray.mask,
                                                 np.nan,
                                                 copyOnReplace=True)

        # Replace infinite value with Nans because PyQtGraph fails on them. Note that the CTIs of
        # the cross plots (e.g. horCrossPlotRangeCti) are still connected to self.slicedArray, so
        # if the cross section consists of only infs, they may not able to update the autorange.
        # A warning is issued in that case.
        # We don't update self.slicedArray here because the data probe should still be able to
        # print the actual value.
        imageArray = replaceMaskedValueWithFloat(imageArray,
                                                 np.isinf(
                                                     self.slicedArray.data),
                                                 np.nan,
                                                 copyOnReplace=True)

        # PyQtGraph uses the following dimension order: T, X, Y, Color.
        # We need to transpose the slicedArray ourselves because axes = {'x':1, 'y':0}
        # doesn't seem to do anything.
        imageArray = imageArray.transpose()

        # Set the _wasIntegerData to True if the original data type was a signed or unsigned. This
        # allows the ArgosColorLegendItem to make histogram bins as if it were an integer
        self.imageItem._wasIntegerData = self.slicedArray.data.dtype.kind in 'ui'
        self.imageItem.setAutoDownsample(
            self.config.autoDownSampleCti.configValue)
        self.imageItem.setImage(
            imageArray, autoLevels=False)  # Do after _wasIntegerData is set!

        self.imagePlotItem.setRectangleZoomOn(
            self.config.zoomModeCti.configValue)

        # Always use pan mode in the cross plots. Rectangle zoom is akward there and it's nice to
        # still be able to pan.
        #self.horCrossPlotItem.setRectangleZoomOn(self.config.zoomModeCti.configValue)
        #self.verCrossPlotItem.setRectangleZoomOn(self.config.zoomModeCti.configValue)

        self.horCrossPlotItem.invertX(self.config.xFlippedCti.configValue)
        self.verCrossPlotItem.invertY(self.config.yFlippedCti.configValue)

        self.probeLabel.setVisible(self.config.probeCti.configValue)

        self.titleLabel.setText(
            self.configValue('title').format(**self.collector.rtiInfo))

        # self.config.logBranch()
        self.config.updateTarget()
Example #2
0
 def _hasValidData(self):
     """ Returns True if the inspector has data that can be plotted.
     """
     return self.slicedArray is not None and array_has_real_numbers(
         self.slicedArray.data)
Example #3
0
 def _hasValidData(self):
     """ Returns True if the inspector has data that can be plotted.
     """
     return self.slicedArray is not None and array_has_real_numbers(self.slicedArray.data)
Example #4
0
    def _drawContents(self, reason=None, initiator=None):
        """ Draws the plot contents from the sliced array of the collected repo tree item.

            The reason parameter is used to determine if the axes will be reset (the initiator
            parameter is ignored). See AbstractInspector.updateContents for their description.
        """

        # If auto-reset is true, reset config complete or partially, depending on the mode.
        if self._resetRequired(reason, initiator):
            self.resetConfig()

        self.slicedArray = self.collector.getSlicedArray()

        slicedArray = self.collector.getSlicedArray()
        if slicedArray is None:
            self._clearContents()
            raise InvalidDataError()  # Don't show message, to common.
        elif not array_has_real_numbers(slicedArray.data):
            self._clearContents()
            raise InvalidDataError("Selected item contains {} data.".format(
                array_kind_label(slicedArray.data)))
        else:
            self.slicedArray = slicedArray

        # -- Valid plot data from here on --

        numElem = np.prod(self.slicedArray.data.shape)
        if numElem == 0:
            self.sigShowMessage.emit(
                "Current slice is empty.")  # Not expected to happen.
        elif numElem == 1:
            self.sigShowMessage.emit(
                "Current slice contains only a single data point.")

        # PyQtGraph doesn't handle masked arrays so we convert the masked values to Nans (missing
        # data values are replaced by NaNs). The PyQtGraph line plot omits the Nans, which is great.
        # Update: in newer version of Qt the Nans are no longer printed, see PyQtGraph issue 1057,
        # https://github.com/pyqtgraph/pyqtgraph/issues/1057
        # When showing lines we therefore don't replace the Nans and let the setData connect parameter be responsible
        # for omitting the masked data. When showing only symbols the masked values are replaced. When both symbols
        # wnd lines are shown the resulting plot is incorrect as the masked values are not replaced and thus displayed
        # as point. This is unfortunate but can't be helped until the issue is resolved in PyQtGraph.
        if not self.config.plotDataItemCti.lineCti.configValue:
            self.slicedArray.replaceMaskedValueWithNan(
            )  # will convert data to float if int

        self.plotItem.clear()

        self.titleLabel.setText(
            self.configValue('title').format(**self.collector.rtiInfo))

        connected = np.isfinite(self.slicedArray.data)
        if is_an_array(self.slicedArray.mask):
            connected = np.logical_and(connected, ~self.slicedArray.mask)
        else:
            connected = np.zeros_like(
                self.slicedArray.data) if self.slicedArray.mask else connected

        plotDataItem = self.config.plotDataItemCti.createPlotDataItem()
        plotDataItem.setData(self.slicedArray.data, connect=connected)

        if plotDataItem.opts['pen'] is None and plotDataItem.opts[
                'symbol'] is None:
            self.sigShowMessage.emit(
                "The 'line' and 'symbol' config options are both unchecked!")

        self.plotItem.addItem(plotDataItem)

        if self.config.probeCti.configValue:
            self.probeLabel.setVisible(True)
            self.plotItem.addItem(self.crossLineVerShadow, ignoreBounds=True)
            self.plotItem.addItem(self.crossLineVertical, ignoreBounds=True)
            self.plotItem.addItem(self.probeDataItem, ignoreBounds=True)
            self.probeDataItem.setSymbolBrush(
                QtGui.QBrush(self.config.plotDataItemCti.penColor))
            self.probeDataItem.setSymbolSize(10)
        else:
            self.probeLabel.setVisible(False)

        self.plotItem.setRectangleZoomOn(self.config.zoomModeCti.configValue)

        self.config.updateTarget()