Exemple #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.
        """
        self.slicedArray = self.collector.getSlicedArray()

        if not self._hasValidData():
            self._clearContents()
            raise InvalidDataError(
                "No data available or it does not contain real numbers")

        # -- Valid plot data from here on --

        # 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.
        self.slicedArray.replaceMaskedValueWithNan(
        )  # will convert data to float if int

        self.plotItem.clear()

        # Reset the axes ranges (via the config)
        if (reason == UpdateReason.RTI_CHANGED
                or reason == UpdateReason.COLLECTOR_COMBO_BOX):

            # self.config.yAxisRangeCti.setAutoRangeOn() doesn't work as refreshBlocked is True
            # TODO: can refreshBlocked maybe only block the signals to prevent loops?
            self.config.xAxisRangeCti.autoRangeCti.data = True
            self.config.yAxisRangeCti.autoRangeCti.data = True

        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)

        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)

        # Update the config tree from the (possibly) new state of the PgLinePlot1d inspector,
        # e.g. the axis range may have changed while drawing.
        self.config.updateTarget()
Exemple #2
0
    def transpose(self, *args, **kwargs):
        """ Transposes the array and mask separately

            :param awm: ArrayWithMask
            :return: copy/view with transposed
        """
        tdata = np.transpose(self.data, *args, **kwargs)
        tmask = np.transpose(self.mask, *args, **kwargs) if is_an_array(self.mask) else self.mask
        return ArrayWithMask(tdata, tmask, self.fill_value)
Exemple #3
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.
        """
        self.slicedArray = self.collector.getSlicedArray()

        if not self._hasValidData():
            self._clearContents()
            raise InvalidDataError("No data available or it does not contain real numbers")

        # -- Valid plot data from here on --

        # 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.
        self.slicedArray.replaceMaskedValueWithNan()  # will convert data to float if int

        self.plotItem.clear()

        # Reset the axes ranges (via the config)
        if (reason == UpdateReason.RTI_CHANGED or
            reason == UpdateReason.COLLECTOR_COMBO_BOX):

            # self.config.yAxisRangeCti.setAutoRangeOn() doesn't work as refreshBlocked is True
            # TODO: can refreshBlocked maybe only block the signals to prevent loops?
            self.config.xAxisRangeCti.autoRangeCti.data = True
            self.config.yAxisRangeCti.autoRangeCti.data = True

        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)

        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)

        # Update the config tree from the (possibly) new state of the PgLinePlot1d inspector,
        # e.g. the axis range may have changed while drawing.
        self.config.updateTarget()
Exemple #4
0
    def _cellMask(self, index):
        """ Returns the data mask of the cell at the index (without any string conversion)
        """
        row = index.row()
        col = index.column()
        if (row < 0 or row >= self.rowCount() or col < 0
                or col >= self.columnCount()):
            return None

        # The check above should have returned None if the sliced array is None
        assert self._slicedArray is not None, "Sanity check failed."

        nFields = len(self._fieldNames)
        mask = self._slicedArray.mask
        if is_an_array(mask):
            if self._separateFieldOrientation == Qt.Horizontal:
                maskValue = mask[row, col //
                                 nFields][self._fieldNames[col % nFields]]
            elif self._separateFieldOrientation == Qt.Vertical:
                maskValue = mask[row // nFields,
                                 col][self._fieldNames[row % nFields]]
            else:
                maskValue = mask[row, col]
        else:
            maskValue = mask

        # Here maskValue can still be a list in case of structured arrays. It can even still be
        # a numpy array in case of a structured array with sub arrays as fields
        if is_an_array(maskValue):
            allMasked = np.all(maskValue)
        else:
            try:
                allMasked = all(maskValue)
            except TypeError as ex:
                allMasked = bool(maskValue)

        return allMasked
Exemple #5
0
def _createFromObject(obj, *args, **kwargs):
    """ Creates an RTI given an object. Auto-detects which RTI class to return.
        The *args and **kwargs parameters are passed to the RTI constructor.
        It is therefor important that all memory RTIs accept the same parameters in the
        constructor (with exception of the FieldRti which is not auto-detected).
    """
    if is_a_sequence(obj):
        return SequenceRti(obj, *args, **kwargs)
    elif is_a_mapping(obj):
        return MappingRti(obj, *args, **kwargs)
    elif is_an_array(obj):
        return ArrayRti(obj, *args, **kwargs)
    elif isinstance(obj, bytearray):
        return ArrayRti(np.array(obj), *args, **kwargs)
    else:
        return ScalarRti(obj, *args, **kwargs)
Exemple #6
0
def dataSetMissingValue(exdirDataset):
    """ Returns the missingData given a Exdir dataset

        Looks for one of the following attributes: _FillValue, missing_value, MissingValue,
        missingValue. Returns None if these attributes are not found.
    """
    attributes = exdirDataset.attrs.to_dict()
    if not attributes:
        return None  # a premature optimization :-)

    for key in ('missing_value', 'MissingValue', 'missingValue', 'FillValue',
                '_FillValue'):
        if key in attributes:
            missingDataValue = attributes[key]
            if is_an_array(missingDataValue) and len(missingDataValue) == 1:
                return missingDataValue[
                    0]  # In case of HDF-EOS and NetCDF files
            else:
                return missingDataValue
    return None
Exemple #7
0
    def data(self, index, role=Qt.DisplayRole):
        """ Returns the data at an index for a certain role
        """
        try:
            if role == Qt.DisplayRole:
                return to_string(self._cellValue(index),
                                 masked=self._cellMask(index),
                                 decode_bytes=self.encoding,
                                 maskFormat=self.maskFormat,
                                 strFormat=self.strFormat,
                                 intFormat=self.intFormat,
                                 numFormat=self.numFormat,
                                 otherFormat=self.otherFormat)

            elif role == Qt.FontRole:
                #assert self._font, "Font undefined"
                return self._font

            elif role == Qt.TextColorRole:
                masked = self._cellMask(index)
                if not is_an_array(masked) and masked:
                    return self.missingColor
                else:
                    return self.dataColor

            elif role == Qt.TextAlignmentRole:
                if self.horAlignment == ALIGN_SMART:
                    cellContainsNumber = isinstance(self._cellValue(index),
                                                    numbers.Number)
                    horAlign = Qt.AlignRight if cellContainsNumber else Qt.AlignLeft
                    return horAlign | self.verAlignment
                else:
                    return self.horAlignment | self.verAlignment

            else:
                return None
        except Exception as ex:
            logger.error("Slot is not exception-safe.")
            logger.exception(ex)
            if DEBUGGING:
                raise
Exemple #8
0
def dataSetMissingValue(h5Dataset):
    """ Returns the missingData given a HDF-5 dataset

        Looks for one of the following attributes: _FillValue, missing_value, MissingValue,
        missingValue. Returns None if these attributes are not found.

        HDF-EOS and NetCDF files seem to put the attributes in 1-element arrays. So if the
        attribute contains an array of one element, that first element is returned here.
    """
    attributes = h5Dataset.attrs
    if not attributes:
        return None # a premature optimization :-)

    for key in ('missing_value', 'MissingValue', 'missingValue', 'FillValue', '_FillValue'):
        if key in attributes:
            missingDataValue = attributes[key]
            if is_an_array(missingDataValue) and len(missingDataValue) == 1:
                return missingDataValue[0] # In case of HDF-EOS and NetCDF files
            else:
                return missingDataValue
    return None
Exemple #9
0
    def mouseMoved(self, viewPos):
        """ Updates the probe text with the values under the cursor.
            Draws a vertical line and a symbol at the position of the probe.
        """
        try:
            check_class(viewPos, QtCore.QPointF)
            show_data_point = False  # shows the data point as a circle in the cross hair plots
            self.crossPlotRow, self.crossPlotCol = None, None

            self.probeLabel.setText(
                "<span style='color: #808080'>No data at cursor</span>")
            self.crossLineHorizontal.setVisible(False)
            self.crossLineVertical.setVisible(False)
            self.crossLineHorShadow.setVisible(False)
            self.crossLineVerShadow.setVisible(False)

            self.horCrossPlotItem.clear()
            self.verCrossPlotItem.clear()

            if self.slicedArray is not None and self.viewBox.sceneBoundingRect(
            ).contains(viewPos):

                # Calculate the row and column at the cursor.
                scenePos = self.viewBox.mapSceneToView(viewPos)
                row, col = round(scenePos.y()), round(scenePos.x())
                row, col = int(row), int(col)  # Needed in Python 2
                nRows, nCols = self.slicedArray.shape

                if (0 <= row < nRows) and (0 <= col < nCols):
                    self.viewBox.setCursor(Qt.CrossCursor)

                    self.crossPlotRow, self.crossPlotCol = row, col
                    index = tuple([row, col])
                    valueStr = to_string(self.slicedArray.data[index],
                                         masked=self.slicedArray.maskAt(index),
                                         maskFormat='&lt;masked&gt;')

                    txt = "({}, {}) = ({:d}, {:d}) {} {} = {}".format(
                        self.collector.rtiInfo['x-dim'],
                        self.collector.rtiInfo['y-dim'], col, row, RIGHT_ARROW,
                        self.collector.rtiInfo['name'], valueStr)
                    self.probeLabel.setText(txt)

                    # Show cross section at the cursor pos in the line plots
                    if self.config.horCrossPlotCti.configValue:
                        self.crossLineHorShadow.setVisible(True)
                        self.crossLineHorizontal.setVisible(True)
                        self.crossLineHorShadow.setPos(row)
                        self.crossLineHorizontal.setPos(row)

                        # Line plot of cross section row.
                        # First determine which points are connected or separated by masks/nans.
                        rowData = self.slicedArray.data[row, :]
                        connected = np.isfinite(rowData)
                        if is_an_array(self.slicedArray.mask):
                            connected = np.logical_and(
                                connected, ~self.slicedArray.mask[row, :])
                        else:
                            connected = (np.zeros_like(rowData) if
                                         self.slicedArray.mask else connected)

                        # Replace mask by Nans. Only doing when not showing lines to hack around PyQtGraph issue 1057
                        # See comment in PgLinePlot1d._drawContents for a more detailed explanation
                        # TODO: reuse imageItem data array when this hack is no longer necessary
                        if not self.config.crossPenCti.lineCti.configValue:
                            rowData = replaceMaskedValueWithFloat(
                                rowData,
                                np.logical_not(connected),
                                np.nan,
                                copyOnReplace=True)

                        # Replace infinite value with nans because PyQtGraph can't handle them
                        rowData = replaceMaskedValueWithFloat(
                            rowData,
                            np.isinf(rowData),
                            np.nan,
                            copyOnReplace=True)

                        horPlotDataItem = self.config.crossPenCti.createPlotDataItem(
                        )
                        # TODO: try to use connect='finite' when the hack above is no longer necessary. In that case
                        # test with array_masked test data
                        horPlotDataItem.setData(rowData, connect=connected)
                        self.horCrossPlotItem.addItem(horPlotDataItem)

                        # Vertical line in hor-cross plot
                        crossLineShadow90 = pg.InfiniteLine(
                            angle=90, movable=False, pen=self.crossShadowPen)
                        crossLineShadow90.setPos(col)
                        self.horCrossPlotItem.addItem(crossLineShadow90,
                                                      ignoreBounds=True)
                        crossLine90 = pg.InfiniteLine(angle=90,
                                                      movable=False,
                                                      pen=self.crossPen)
                        crossLine90.setPos(col)
                        self.horCrossPlotItem.addItem(crossLine90,
                                                      ignoreBounds=True)

                        if show_data_point:
                            crossPoint90 = pg.PlotDataItem(
                                symbolPen=self.crossPen)
                            crossPoint90.setSymbolBrush(
                                QtGui.QBrush(self.config.crossPenCti.penColor))
                            crossPoint90.setSymbolSize(10)
                            crossPoint90.setData((col, ), (rowData[col], ))
                            self.horCrossPlotItem.addItem(crossPoint90,
                                                          ignoreBounds=True)

                        self.config.horCrossPlotRangeCti.updateTarget(
                        )  # update auto range
                        del rowData  # defensive programming

                    if self.config.verCrossPlotCti.configValue:
                        self.crossLineVerShadow.setVisible(True)
                        self.crossLineVertical.setVisible(True)
                        self.crossLineVerShadow.setPos(col)
                        self.crossLineVertical.setPos(col)

                        # Line plot of cross section row.
                        # First determine which points are connected or separated by masks/nans.
                        colData = self.slicedArray.data[:, col]
                        connected = np.isfinite(colData)
                        if is_an_array(self.slicedArray.mask):
                            connected = np.logical_and(
                                connected, ~self.slicedArray.mask[:, col])
                        else:
                            connected = (np.zeros_like(colData) if
                                         self.slicedArray.mask else connected)

                        # Replace mask by Nans. Only doing when not showing lines to hack around PyQtGraph issue 1057
                        # See comment in PgLinePlot1d._drawContents for a more detailed explanation
                        if not self.config.crossPenCti.lineCti.configValue:
                            colData = replaceMaskedValueWithFloat(
                                colData,
                                np.logical_not(connected),
                                np.nan,
                                copyOnReplace=True)

                        # Replace infinite value with nans because PyQtGraph can't handle them
                        colData = replaceMaskedValueWithFloat(
                            colData,
                            np.isinf(colData),
                            np.nan,
                            copyOnReplace=True)

                        verPlotDataItem = self.config.crossPenCti.createPlotDataItem(
                        )
                        verPlotDataItem.setData(colData,
                                                np.arange(nRows),
                                                connect=connected)
                        self.verCrossPlotItem.addItem(verPlotDataItem)

                        # Horizontal line in ver-cross plot
                        crossLineShadow0 = pg.InfiniteLine(
                            angle=0, movable=False, pen=self.crossShadowPen)
                        crossLineShadow0.setPos(row)
                        self.verCrossPlotItem.addItem(crossLineShadow0,
                                                      ignoreBounds=True)
                        crossLine0 = pg.InfiniteLine(angle=0,
                                                     movable=False,
                                                     pen=self.crossPen)
                        crossLine0.setPos(row)
                        self.verCrossPlotItem.addItem(crossLine0,
                                                      ignoreBounds=True)

                        if show_data_point:
                            crossPoint0 = pg.PlotDataItem(
                                symbolPen=self.crossPen)
                            crossPoint0.setSymbolBrush(
                                QtGui.QBrush(self.config.crossPenCti.penColor))
                            crossPoint0.setSymbolSize(10)
                            crossPoint0.setData((colData[row], ), (row, ))
                            self.verCrossPlotItem.addItem(crossPoint0,
                                                          ignoreBounds=True)

                        self.config.verCrossPlotRangeCti.updateTarget(
                        )  # update auto range
                        del colData  # defensive programming

        except Exception as ex:
            # In contrast to _drawContents, this function is a slot and thus must not throw
            # exceptions. The exception is logged. Perhaps we should clear the cross plots, but
            # this could, in turn, raise exceptions.
            if DEBUGGING:
                raise
            else:
                logger.exception(ex)
Exemple #10
0
 def checkIsConsistent(self):
     """ Raises a ConsistencyError if the mask has an incorrect shape.
     """
     if is_an_array(self.mask) and self.mask.shape != self.data.shape:
         raise ConsistencyError("Shape mismatch mask={}, data={}"
                                .format(self.mask.shape != self.data.shape))
Exemple #11
0
    def mouseMoved(self, viewPos):
        """ Updates the probe text with the values under the cursor.
            Draws a vertical line and a symbol at the position of the probe.
        """
        try:
            check_class(viewPos, QtCore.QPointF)
            show_data_point = False # shows the data point as a circle in the cross hair plots
            self.crossPlotRow, self.crossPlotCol = None, None

            self.probeLabel.setText("<span style='color: #808080'>no data at cursor</span>")
            self.crossLineHorizontal.setVisible(False)
            self.crossLineVertical.setVisible(False)
            self.crossLineHorShadow.setVisible(False)
            self.crossLineVerShadow.setVisible(False)

            self.horCrossPlotItem.clear()
            self.verCrossPlotItem.clear()

            if (self._hasValidData() and self.slicedArray is not None
                and self.viewBox.sceneBoundingRect().contains(viewPos)):

                # Calculate the row and column at the cursor. We use math.floor because the pixel
                # corners of the image lie at integer values (and not the centers of the pixels).
                scenePos = self.viewBox.mapSceneToView(viewPos)
                row, col = math.floor(scenePos.y()), math.floor(scenePos.x())
                row, col = int(row), int(col) # Needed in Python 2
                nRows, nCols = self.slicedArray.shape

                if (0 <= row < nRows) and (0 <= col < nCols):
                    self.viewBox.setCursor(Qt.CrossCursor)

                    self.crossPlotRow, self.crossPlotCol = row, col
                    index = tuple([row, col])
                    valueStr = to_string(self.slicedArray[index],
                                         masked=self.slicedArray.maskAt(index),
                                         maskFormat='&lt;masked&gt;')
                    txt = "pos = ({:d}, {:d}), value = {}".format(row, col, valueStr)
                    self.probeLabel.setText(txt)

                    # Show cross section at the cursor pos in the line plots
                    if self.config.horCrossPlotCti.configValue:
                        self.crossLineHorShadow.setVisible(True)
                        self.crossLineHorizontal.setVisible(True)
                        self.crossLineHorShadow.setPos(row)
                        self.crossLineHorizontal.setPos(row)

                        # Line plot of cross section row.
                        # First determine which points are connected or separated by masks/nans.
                        rowData = self.slicedArray.data[row, :]
                        connected = np.isfinite(rowData)
                        if is_an_array(self.slicedArray.mask):
                            connected = np.logical_and(connected, ~self.slicedArray.mask[row, :])
                        else:
                            connected = (np.zeros_like(rowData)
                                         if self.slicedArray.mask else connected)

                        # Replace infinite value with nans because PyQtGraph can't handle them
                        rowData = replaceMaskedValueWithFloat(rowData, np.isinf(rowData),
                                                              np.nan, copyOnReplace=True)

                        horPlotDataItem = self.config.crossPenCti.createPlotDataItem()
                        horPlotDataItem.setData(rowData, connect=connected)
                        self.horCrossPlotItem.addItem(horPlotDataItem)

                        # Vertical line in hor-cross plot
                        crossLineShadow90 = pg.InfiniteLine(angle=90, movable=False,
                                                            pen=self.crossShadowPen)
                        crossLineShadow90.setPos(col)
                        self.horCrossPlotItem.addItem(crossLineShadow90, ignoreBounds=True)
                        crossLine90 = pg.InfiniteLine(angle=90, movable=False, pen=self.crossPen)
                        crossLine90.setPos(col)
                        self.horCrossPlotItem.addItem(crossLine90, ignoreBounds=True)

                        if show_data_point:
                            crossPoint90 = pg.PlotDataItem(symbolPen=self.crossPen)
                            crossPoint90.setSymbolBrush(QtGui.QBrush(self.config.crossPenCti.penColor))
                            crossPoint90.setSymbolSize(10)
                            crossPoint90.setData((col,), (rowData[col],))
                            self.horCrossPlotItem.addItem(crossPoint90, ignoreBounds=True)

                        self.config.horCrossPlotRangeCti.updateTarget() # update auto range
                        del rowData # defensive programming

                    if self.config.verCrossPlotCti.configValue:
                        self.crossLineVerShadow.setVisible(True)
                        self.crossLineVertical.setVisible(True)
                        self.crossLineVerShadow.setPos(col)
                        self.crossLineVertical.setPos(col)

                        # Line plot of cross section row.
                        # First determine which points are connected or separated by masks/nans.
                        colData = self.slicedArray.data[:, col]
                        connected = np.isfinite(colData)
                        if is_an_array(self.slicedArray.mask):
                            connected = np.logical_and(connected, ~self.slicedArray.mask[:, col])
                        else:
                            connected = (np.zeros_like(colData)
                                         if self.slicedArray.mask else connected)

                        # Replace infinite value with nans because PyQtGraph can't handle them
                        colData = replaceMaskedValueWithFloat(colData, np.isinf(colData),
                                                              np.nan, copyOnReplace=True)

                        verPlotDataItem = self.config.crossPenCti.createPlotDataItem()
                        verPlotDataItem.setData(colData, np.arange(nRows), connect=connected)
                        self.verCrossPlotItem.addItem(verPlotDataItem)

                        # Horizontal line in ver-cross plot
                        crossLineShadow0 = pg.InfiniteLine(angle=0, movable=False,
                                                           pen=self.crossShadowPen)
                        crossLineShadow0.setPos(row)
                        self.verCrossPlotItem.addItem(crossLineShadow0, ignoreBounds=True)
                        crossLine0 = pg.InfiniteLine(angle=0, movable=False, pen=self.crossPen)
                        crossLine0.setPos(row)
                        self.verCrossPlotItem.addItem(crossLine0, ignoreBounds=True)

                        if show_data_point:
                            crossPoint0 = pg.PlotDataItem(symbolPen=self.crossPen)
                            crossPoint0.setSymbolBrush(QtGui.QBrush(self.config.crossPenCti.penColor))
                            crossPoint0.setSymbolSize(10)
                            crossPoint0.setData((colData[row],), (row,))
                            self.verCrossPlotItem.addItem(crossPoint0, ignoreBounds=True)

                        self.config.verCrossPlotRangeCti.updateTarget() # update auto range
                        del colData # defensive programming

        except Exception as ex:
            # In contrast to _drawContents, this function is a slot and thus must not throw
            # exceptions. The exception is logged. Perhaps we should clear the cross plots, but
            # this could, in turn, raise exceptions.
            if DEBUGGING:
                raise
            else:
                logger.exception(ex)
Exemple #12
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()