Source code for qudi.util.widgets.plotting.plot_item

# -*- coding: utf-8 -*-

"""
This file contains modified pyqtgraph.ImageItem subclasses for data visualization.

Copyright (c) 2021, the qudi developers. See the AUTHORS.md file at the top-level directory of this
distribution and on <https://github.com/Ulm-IQO/qudi-core/>

This file is part of qudi.

Qudi is free software: you can redistribute it and/or modify it under the terms of
the GNU Lesser General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.

Qudi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with qudi.
If not, see <https://www.gnu.org/licenses/>.
"""

__all__ = ['DataImageItem', 'XYPlotItem']

import numpy as np
from typing import Union, Optional, Tuple
from PySide2 import QtCore
from pyqtgraph import ImageItem as _ImageItem
from pyqtgraph import PlotDataItem as _PlotDataItem

from qudi.util.colordefs import ColorScaleInferno as _Colorscale
from qudi.util.colordefs import QudiPalette as _QudiPalette


[docs] class XYPlotItem(_PlotDataItem): """ Extension of pg.PlotDataItem with default qudi style plot options """
[docs] def __init__(self, *args, **kwargs) -> None: super().__init__() self.opts['pen'] = _QudiPalette.c1 self.opts['symbolPen'] = _QudiPalette.c1 self.opts['symbolBrush'] = _QudiPalette.c1 self.setData(*args, **kwargs)
[docs] class DataImageItem(_ImageItem): """ Extension of pg.ImageItem with percentile level scaling and image size adjustment """
[docs] def __init__(self, image=None, **kwargs): # Change default color scale to qudi default if kwargs.get('lut', None) is None: kwargs['lut'] = _Colorscale().lut super().__init__(image, **kwargs) self._percentiles = None
@property def percentiles(self) -> Union[None, Tuple[float, float]]: return self._percentiles def set_percentiles(self, percentiles: Union[None, Tuple[float, float]]) -> None: """ Set percentile range to clip image color level scaling. """ if percentiles is not None: percentiles = (min(percentiles), max(percentiles)) if percentiles != self._percentiles: self._percentiles = percentiles if self.image is not None: masked_image = np.ma.masked_invalid(self.image).compressed() if masked_image.size > 0: self.setLevels(self._get_percentile_levels(masked_image)) def set_image_extent(self, extent: Tuple[Tuple[float, float], Tuple[float, float]], adjust_for_px_size: Optional[bool] = True ) -> None: """ Scales the image to a certain value range. By default, the resulting extent will be a bit larger, so that each pixel center corresponds to the respective xy coordinate. """ if adjust_for_px_size is None: adjust_for_px_size = True if len(extent) != 2: raise ValueError('Image extent must be float sequence of length 2') if len(extent[0]) != 2 or len(extent[1]) != 2: raise TypeError('Image extent for each axis must be sequence of length 2.') if self.image is not None: x_min, x_max = min(extent[0]), max(extent[0]) y_min, y_max = min(extent[1]), max(extent[1]) if adjust_for_px_size: if self.image.shape[0] > 1 and self.image.shape[1] > 1: half_px_x = (x_max - x_min) / (2 * (self.image.shape[0] - 1)) half_px_y = (y_max - y_min) / (2 * (self.image.shape[1] - 1)) x_min -= half_px_x x_max += half_px_x y_min -= half_px_y y_max += half_px_y self.setRect(QtCore.QRectF(x_min, y_min, x_max - x_min, y_max - y_min)) def set_image(self, image=None, **kwargs): """ vpg.ImageItem method override to apply optional filter when setting image data. """ if image is None: self.clear() else: masked_image = np.ma.masked_invalid(image).compressed() if masked_image.size > 0: kwargs['levels'] = kwargs.get('levels', self._get_percentile_levels(masked_image)) self.setImage(image=image, **kwargs) else: self.clear() def _get_percentile_levels(self, image) -> Tuple[float, float]: if self._percentiles is None: min_value = np.min(image) max_value = np.max(image) else: min_value = np.percentile(image, self._percentiles[0]) max_value = np.percentile(image, self._percentiles[1]) return min_value, max_value