guiqwt.builder

guiqwt

Source code for guiqwt.builder

#
# Copyright © 2009-2010 CEA
# Pierre Raybaut
# Licensed under the terms of the CECILL License
# (see guiqwt/__init__.py for details)

# pylint: disable=C0103

"""
guiqwt.builder
--------------

The `builder` module provides a builder singleton class 
used to simplify the creation of plot items.

Example
~~~~~~~

Before creating any widget, a `QApplication` must be instantiated 
(that is a `Qt` internal requirement):
          
>>> import guidata
>>> app = guidata.qapplication()

that is mostly equivalent to the following (the only difference is that 
the `guidata` helper function also installs the `Qt` translation 
corresponding to the system locale):
          
>>> from PyQt4.QtGui import QApplication
>>> app = QApplication([])

now that a `QApplication` object exists, we may create the plotting widget:

>>> from guiqwt.plot import ImageWidget
>>> widget = ImageWidget()

create curves, images, histograms, etc. and attach them to the plot:

>>> from guiqwt.builder import make
>>> curve = make.mcure(x, y, 'r+')
>>> image = make.image(data)
>>> hist = make.histogram(data, 100)
>>> for item in (curve, image, hist):
...     widget.plot.add_item()

and then show the widget to screen:

>>> widget.show()
>>> app.exec_()

Reference
~~~~~~~~~

.. autoclass:: PlotItemBuilder
   :members:
"""

import os.path as osp

from numpy import arange, array, zeros, meshgrid, ndarray

# Local imports
from guiqwt.config import _, CONF, make_title
from guiqwt.baseplot import BasePlot
from guiqwt.curve import CurveItem, ErrorBarCurveItem, GridItem
from guiqwt.histogram import HistogramItem, lut_range_threshold
from guiqwt.image import (ImageItem, QuadGridItem, TrImageItem, XYImageItem,
                          Histogram2DItem, RGBImageItem, MaskedImageItem)
from guiqwt.shapes import (XRangeSelection, RectangleShape, EllipseShape,
                           SegmentShape, Marker)
from guiqwt.annotations import (AnnotatedRectangle, AnnotatedEllipse,
                                AnnotatedSegment)
from guiqwt.styles import (update_style_attr, CurveParam, ErrorBarParam,
                           style_generator, LabelParam, LegendParam, ImageParam,
                           TrImageParam, HistogramParam, Histogram2DParam,
                           RGBImageParam, MaskedImageParam, XYImageParam,
                           ImageFilterParam, MARKERS, COLORS, GridParam,
                           LineStyleParam, AnnotationParam, QuadGridParam,
                           LabelParamWithContents, MarkerParam)
from guiqwt.label import (LabelItem, LegendBoxItem, RangeComputation,
                          RangeComputation2d, DataInfoLabel, RangeInfo,
                          SelectedLegendBoxItem)

# default offset positions for anchors
ANCHOR_OFFSETS = {
                  "TL" : ( 5,  5),
                  "TR" : (-5,  5),
                  "BL" : ( 5, -5),
                  "BR" : (-5, -5),
                  "L"  : ( 5,  0),
                  "R"  : (-5,  0),
                  "T"  : ( 0,  5),
                  "B"  : ( 0, -5),
                  }

CURVE_COUNT = 0
HISTOGRAM_COUNT = 0
IMAGE_COUNT = 0
LABEL_COUNT = 0
HISTOGRAM2D_COUNT = 0

class PlotItemBuilder(object):
[docs] """ This is just a bare class used to regroup a set of factory functions in a single object """ def __init__(self): self.style = style_generator() def gridparam(self, background=None,
[docs] major_enabled=None, minor_enabled=None, major_style=None, minor_style=None): """ Make `guiqwt.styles.GridParam` instance * background = canvas background color * major_enabled = tuple (major_xenabled, major_yenabled) * minor_enabled = tuple (minor_xenabled, minor_yenabled) * major_style = tuple (major_xstyle, major_ystyle) * minor_style = tuple (minor_xstyle, minor_ystyle) Style: tuple (style, color, width) """ gridparam = GridParam(title=_("Grid"), icon="lin_lin.png") gridparam.read_config(CONF, "plot", "grid") if background is not None: gridparam.background = background if major_enabled is not None: gridparam.maj_xenabled, gridparam.maj_yenabled = major_enabled if minor_enabled is not None: gridparam.min_xenabled, gridparam.min_yenabled = minor_enabled if major_style is not None: style = LineStyleParam() linestyle, color, style.width = major_style style.set_style_from_matlab(linestyle) style.color = COLORS.get(color, color) # MATLAB-style if minor_style is not None: style = LineStyleParam() linestyle, color, style.width = minor_style style.set_style_from_matlab(linestyle) style.color = COLORS.get(color, color) # MATLAB-style return gridparam def grid(self, background=None, major_enabled=None, minor_enabled=None,
[docs] major_style=None, minor_style=None): """ Make a grid `plot item` (`guiqwt.curve.GridItem` object) * background = canvas background color * major_enabled = tuple (major_xenabled, major_yenabled) * minor_enabled = tuple (minor_xenabled, minor_yenabled) * major_style = tuple (major_xstyle, major_ystyle) * minor_style = tuple (minor_xstyle, minor_ystyle) Style: tuple (style, color, width) """ gridparam = self.gridparam(background, major_enabled, minor_enabled, major_style, minor_style) return GridItem(gridparam) def __set_curve_axes(self, curve, xaxis, yaxis):
"""Set curve axes""" for axis in (xaxis, yaxis): if axis not in BasePlot.AXIS_NAMES: raise RuntimeError("Unknown axis %s" % axis) curve.setXAxis(BasePlot.AXIS_NAMES[xaxis]) curve.setYAxis(BasePlot.AXIS_NAMES[yaxis]) def __set_baseparam(self, param, color, linestyle, linewidth, marker, markersize, markerfacecolor, markeredgecolor): """Apply parameters to a `guiqwt.styles.CurveParam` or `guiqwt.styles.MarkerParam` instance""" if color is not None: color = COLORS.get(color, color) # MATLAB-style param.line.color = color if linestyle is not None: param.line.set_style_from_matlab(linestyle) if linewidth is not None: param.line.width = linewidth if marker is not None: if marker in MARKERS: param.symbol.update_param(MARKERS[marker]) # MATLAB-style else: param.symbol.marker = marker if markersize is not None: param.symbol.size = markersize if markerfacecolor is not None: markerfacecolor = COLORS.get(markerfacecolor, markerfacecolor) # MATLAB-style param.symbol.facecolor = markerfacecolor if markeredgecolor is not None: markeredgecolor = COLORS.get(markeredgecolor, markeredgecolor) # MATLAB-style param.symbol.edgecolor = markeredgecolor def __set_param(self, param, title, color, linestyle, linewidth, marker, markersize, markerfacecolor, markeredgecolor, shade, fitted, curvestyle, curvetype, baseline): """Apply parameters to a `guiqwt.styles.CurveParam` instance""" self.__set_baseparam(param, color, linestyle, linewidth, marker, markersize, markerfacecolor, markeredgecolor) if title: param.label = title if shade is not None: param.shade = shade if fitted is not None: param.fitted = fitted if curvestyle is not None: param.curvestyle = curvestyle if curvetype is not None: param.curvetype = curvetype if baseline is not None: param.baseline = baseline def __get_arg_triple_plot(self, args): """Convert MATLAB-like arguments into x, y, style""" def get_x_y_from_data(data): if isinstance(data, (tuple, list)): data = array(data) if len(data.shape) == 1 or 1 in data.shape: x = arange(data.size) y = data else: x = arange(len(data[:, 0])) y = [data[:, i] for i in range(len(data[0, :]))] return x, y if len(args) == 1: if isinstance(args[0], basestring): x = array((), float) y = array((), float) style = args[0] else: x, y = get_x_y_from_data(args[0]) if isinstance(y, ndarray): style = self.style.next() else: style = [self.style.next() for yi in y] elif len(args) == 2: a1, a2 = args if isinstance(a2, basestring): x, y = get_x_y_from_data(a1) style = a2 else: x = a1 y = a2 style = self.style.next() elif len(args)==3: x, y, style = args else: raise TypeError("Wrong number of arguments") if isinstance(x, (list, tuple)): x = array(x) if isinstance(y, (list, tuple)): y = array(y) return x, y, style def __get_arg_triple_errorbar(self, args): """Convert MATLAB-like arguments into x, y, style""" if len(args)==2: y, dy = args x = arange(len(y)) dx = zeros(len(y)) style = self.style.next() elif len(args)==3: a1, a2, a3 = args if isinstance(a3, basestring): y, dy = a1, a2 x = arange(len(y)) dx = zeros(len(y)) style = a3 else: x, y, dy = args dx = zeros(len(y)) style = self.style.next() elif len(args)==4: a1, a2, a3, a4 = args if isinstance(a4, basestring): x, y, dy = a1, a2, a3 dx = zeros(len(y)) style = a4 else: x, y, dx, dy = args style = self.style.next() elif len(args)==5: x, y, dx, dy, style = args else: raise TypeError("Wrong number of arguments") return x, y, dx, dy, style def mcurve(self, *args, **kwargs):
[docs] """ Make a curve `plot item` based on MATLAB-like syntax (may returns a list of curves if data contains more than one signal) (:py:class:`guiqwt.curve.CurveItem` object) Example: mcurve(x, y, 'r+') """ x, y, style = self.__get_arg_triple_plot(args) if isinstance(y, ndarray): y = [y] if not isinstance(style, list): style = [style] if len(y) > len(style): style = [style[0]]*len(y) basename = _("Curve") curves = [] for yi, stylei in zip(y, style): param = CurveParam(title=basename, icon='curve.png') if "label" in kwargs: param.label = kwargs.pop("label") else: global CURVE_COUNT CURVE_COUNT += 1 param.label = make_title(basename, CURVE_COUNT) update_style_attr(stylei, param) curves.append(self.pcurve(x, yi, param, **kwargs)) if len(curves) == 1: return curves[0] else: return curves def pcurve(self, x, y, param, xaxis="bottom", yaxis="left"):
[docs] """ Make a curve `plot item` based on a `guiqwt.styles.CurveParam` instance (:py:class:`guiqwt.curve.CurveItem` object) Usage: pcurve(x, y, param) """ curve = CurveItem(param) curve.set_data(x, y) curve.update_params() self.__set_curve_axes(curve, xaxis, yaxis) return curve def curve(self, x, y, title=u"",
[docs] color=None, linestyle=None, linewidth=None, marker=None, markersize=None, markerfacecolor=None, markeredgecolor=None, shade=None, fitted=None, curvestyle=None, curvetype=None, baseline=None, xaxis="bottom", yaxis="left"): """ Make a curve `plot item` from x, y, data (:py:class:`guiqwt.curve.CurveItem` object) * x: 1D NumPy array * y: 1D NumPy array * color: curve color name * linestyle: curve line style (MATLAB-like string or attribute name from the :py:class:`PyQt4.QtCore.Qt.PenStyle` enum (i.e. "SolidLine" "DashLine", "DotLine", "DashDotLine", "DashDotDotLine" or "NoPen") * linewidth: line width (pixels) * marker: marker shape (MATLAB-like string or attribute name from the :py:class:`PyQt4.Qwt5.QwtSymbol.Style` enum (i.e. "Cross", "Ellipse", "Star1", "XCross", "Rect", "Diamond", "UTriangle", "DTriangle", "RTriangle", "LTriangle", "Star2" or "NoSymbol") * markersize: marker size (pixels) * markerfacecolor: marker face color name * markeredgecolor: marker edge color name * shade: 0 <= float <= 1 (curve shade) * fitted: boolean (fit curve to data) * curvestyle: attribute name from the :py:class:`PyQt4.Qwt5.QwtPlotCurve.CurveStyle` enum (i.e. "Lines", "Sticks", "Steps", "Dots" or "NoCurve") * curvetype: attribute name from the :py:class:`PyQt4.Qwt5.QwtPlotCurve.CurveType` enum (i.e. "Yfx" or "Xfy") * baseline (float: default=0.0): the baseline is needed for filling the curve with a brush or the Sticks drawing style. The interpretation of the baseline depends on the curve type (horizontal line for "Yfx", vertical line for "Xfy") * xaxis, yaxis: X/Y axes bound to curve Examples: curve(x, y, marker='Ellipse', markerfacecolor='#ffffff') which is equivalent to (MATLAB-style support): curve(x, y, marker='o', markerfacecolor='w') """ basename = _("Curve") param = CurveParam(title=basename, icon='curve.png') if not title: global CURVE_COUNT CURVE_COUNT += 1 title = make_title(basename, CURVE_COUNT) self.__set_param(param, title, color, linestyle, linewidth, marker, markersize, markerfacecolor, markeredgecolor, shade, fitted, curvestyle, curvetype, baseline) return self.pcurve(x, y, param, xaxis, yaxis) def merror(self, *args, **kwargs):
[docs] """ Make an errorbar curve `plot item` based on MATLAB-like syntax (:py:class:`guiqwt.curve.ErrorBarCurveItem` object) Example: mcurve(x, y, 'r+') """ x, y, dx, dy, style = self.__get_arg_triple_errorbar(args) basename = _("Curve") curveparam = CurveParam(title=basename, icon='curve.png') errorbarparam = ErrorBarParam(title=_("Error bars"), icon='errorbar.png') if "label" in kwargs: curveparam.label = kwargs["label"] else: global CURVE_COUNT CURVE_COUNT += 1 curveparam.label = make_title(basename, CURVE_COUNT) update_style_attr(style, curveparam) errorbarparam.color = curveparam.line.color return self.perror(x, y, dx, dy, curveparam, errorbarparam) def perror(self, x, y, dx, dy, curveparam, errorbarparam,
[docs] xaxis="bottom", yaxis="left"): """ Make an errorbar curve `plot item` based on a `guiqwt.styles.ErrorBarParam` instance (:py:class:`guiqwt.curve.ErrorBarCurveItem` object) * x: 1D NumPy array * y: 1D NumPy array * dx: None, or scalar, or 1D NumPy array * dy: None, or scalar, or 1D NumPy array * curveparam: `guiqwt.styles.CurveParam` object * errorbarparam: `guiqwt.styles.ErrorBarParam` object * xaxis, yaxis: X/Y axes bound to curve Usage: perror(x, y, dx, dy, curveparam, errorbarparam) """ curve = ErrorBarCurveItem(curveparam, errorbarparam) curve.set_data(x, y, dx, dy) curve.update_params() self.__set_curve_axes(curve, xaxis, yaxis) return curve def error(self, x, y, dx, dy, title=u"",
[docs] color=None, linestyle=None, linewidth=None, errorbarwidth=None, errorbarcap=None, errorbarmode=None, errorbaralpha=None, marker=None, markersize=None, markerfacecolor=None, markeredgecolor=None, shade=None, fitted=None, curvestyle=None, curvetype=None, baseline=None, xaxis="bottom", yaxis="left"): """ Make an errorbar curve `plot item` (:py:class:`guiqwt.curve.ErrorBarCurveItem` object) * x: 1D NumPy array * y: 1D NumPy array * dx: None, or scalar, or 1D NumPy array * dy: None, or scalar, or 1D NumPy array * color: curve color name * linestyle: curve line style (MATLAB-like string or attribute name from the :py:class:`PyQt4.QtCore.Qt.PenStyle` enum (i.e. "SolidLine" "DashLine", "DotLine", "DashDotLine", "DashDotDotLine" or "NoPen") * linewidth: line width (pixels) * marker: marker shape (MATLAB-like string or attribute name from the :py:class:`PyQt4.Qwt5.QwtSymbol.Style` enum (i.e. "Cross", "Ellipse", "Star1", "XCross", "Rect", "Diamond", "UTriangle", "DTriangle", "RTriangle", "LTriangle", "Star2" or "NoSymbol") * markersize: marker size (pixels) * markerfacecolor: marker face color name * markeredgecolor: marker edge color name * shade: 0 <= float <= 1 (curve shade) * fitted: boolean (fit curve to data) * curvestyle: attribute name from the :py:class:`PyQt4.Qwt5.QwtPlotCurve.CurveStyle` enum (i.e. "Lines", "Sticks", "Steps", "Dots" or "NoCurve") * curvetype: attribute name from the :py:class:`PyQt4.Qwt5.QwtPlotCurve.CurveType` enum (i.e. "Yfx" or "Xfy") * baseline (float: default=0.0): the baseline is needed for filling the curve with a brush or the Sticks drawing style. The interpretation of the baseline depends on the curve type (horizontal line for "Yfx", vertical line for "Xfy") * xaxis, yaxis: X/Y axes bound to curve Examples:: error(x, y, None, dy, marker='Ellipse', markerfacecolor='#ffffff') which is equivalent to (MATLAB-style support): error(x, y, None, dy, marker='o', markerfacecolor='w') """ basename = _("Curve") curveparam = CurveParam(title=basename, icon='curve.png') errorbarparam = ErrorBarParam(title=_("Error bars"), icon='errorbar.png') if not title: global CURVE_COUNT CURVE_COUNT += 1 curveparam.label = make_title(basename, CURVE_COUNT) self.__set_param(curveparam, title, color, linestyle, linewidth, marker, markersize, markerfacecolor, markeredgecolor, shade, fitted, curvestyle, curvetype, baseline) errorbarparam.color = curveparam.line.color if errorbarwidth is not None: errorbarparam.width = errorbarwidth if errorbarcap is not None: errorbarparam.cap = errorbarcap if errorbarmode is not None: errorbarparam.mode = errorbarmode if errorbaralpha is not None: errorbarparam.alpha = errorbaralpha return self.perror(x, y, dx, dy, curveparam, errorbarparam, xaxis, yaxis) def histogram(self, data, bins=None, logscale=None,
[docs] title=u"", color=None, xaxis="bottom", yaxis="left"): """ Make 1D Histogram `plot item` (:py:class:`guiqwt.histogram.HistogramItem` object) * data (1D NumPy array) * bins: number of bins (int) * logscale: Y-axis scale (bool) """ basename = _("Histogram") histparam = HistogramParam(title=basename, icon='histogram.png') curveparam = CurveParam(_("Curve"), icon='curve.png') curveparam.read_config(CONF, "histogram", "curve") if not title: global HISTOGRAM_COUNT HISTOGRAM_COUNT += 1 title = make_title(basename, HISTOGRAM_COUNT) curveparam.label = title if color is not None: curveparam.line.color = color if bins is not None: histparam.n_bins = bins if logscale is not None: histparam.logscale = logscale return self.phistogram(data, curveparam, histparam, xaxis, yaxis) def phistogram(self, data, curveparam, histparam,
[docs] xaxis="bottom", yaxis="left"): """ Make 1D histogram `plot item` (:py:class:`guiqwt.histogram.HistogramItem` object) based on a `guiqwt.styles.CurveParam` and `guiqwt.styles.HistogramParam` instances Usage: phistogram(data, curveparam, histparam) """ hist = HistogramItem(curveparam, histparam) hist.update_params() hist.set_hist_data(data) self.__set_curve_axes(hist, xaxis, yaxis) return hist def __set_image_param(self, param, title, alpha_mask, alpha, interpolation,
**kwargs): if title: param.label = title else: global IMAGE_COUNT IMAGE_COUNT += 1 param.label = make_title(_("Image"), IMAGE_COUNT) if alpha_mask is not None: assert isinstance(alpha_mask, bool) param.alpha_mask = alpha_mask if alpha is not None: assert (0.0 <= alpha <= 1.0) param.alpha = alpha interp_methods = {'nearest': 0, 'linear': 1, 'antialiasing': 5} param.interpolation = interp_methods[interpolation] for key, val in kwargs.items(): if val is not None: setattr(param, key, val) def _get_image_data(self, data, filename, title, to_grayscale): if data is None: assert filename is not None from guiqwt import io data = io.imread(filename, to_grayscale=to_grayscale) if title is None and filename is not None: title = osp.basename(filename) return data, filename, title @staticmethod def compute_bounds(data, pixel_size, center_on):
[docs] """Return image bounds from *pixel_size* (scalar or tuple)""" if not isinstance(pixel_size, (tuple, list)): pixel_size = [pixel_size, pixel_size] dx, dy = pixel_size xmin, ymin = 0., 0. xmax, ymax = data.shape[1]*dx, data.shape[0]*dy if center_on is not None: xc, yc = center_on dx, dy = .5*(xmax-xmin)-xc, .5*(ymax-ymin)-yc xmin -= dx xmax -= dx ymin -= dy ymax -= dy return xmin, xmax, ymin, ymax def image(self, data=None, filename=None, title=None, alpha_mask=None,
[docs] alpha=None, background_color=None, colormap=None, xdata=[None, None], ydata=[None, None], pixel_size=None, center_on=None, interpolation='linear', eliminate_outliers=None, xformat='%.1f', yformat='%.1f', zformat='%.1f'): """ Make an image `plot item` from data (:py:class:`guiqwt.image.ImageItem` object or :py:class:`guiqwt.image.RGBImageItem` object if data has 3 dimensions) """ assert isinstance(xdata, (tuple, list)) and len(xdata) == 2 assert isinstance(ydata, (tuple, list)) and len(ydata) == 2 param = ImageParam(title=_("Image"), icon='image.png') data, filename, title = self._get_image_data(data, filename, title, to_grayscale=True) if data.ndim == 3: return self.rgbimage(data=data, filename=filename, title=title, alpha_mask=alpha_mask, alpha=alpha) assert data.ndim == 2, "Data must have 2 dimensions" if pixel_size is None: assert center_on is None, "Ambiguous parameters: both `center_on`"\ " and `xdata`/`ydata` were specified" xmin, xmax = xdata ymin, ymax = ydata else: xmin, xmax, ymin, ymax = self.compute_bounds(data, pixel_size, center_on) self.__set_image_param(param, title, alpha_mask, alpha, interpolation, background=background_color, colormap=colormap, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, xformat=xformat, yformat=yformat, zformat=zformat) image = ImageItem(data, param) image.set_filename(filename) if eliminate_outliers is not None: image.set_lut_range(lut_range_threshold(image, 256, eliminate_outliers)) return image def maskedimage(self, data=None, mask=None, filename=None, title=None,
[docs] alpha_mask=False, alpha=1.0, xdata=[None, None], ydata=[None, None], pixel_size=None, center_on=None, background_color=None, colormap=None, show_mask=False, fill_value=None, interpolation='linear', eliminate_outliers=None, xformat='%.1f', yformat='%.1f', zformat='%.1f'): """ Make a masked image `plot item` from data (:py:class:`guiqwt.image.MaskedImageItem` object) """ assert isinstance(xdata, (tuple, list)) and len(xdata) == 2 assert isinstance(ydata, (tuple, list)) and len(ydata) == 2 param = MaskedImageParam(title=_("Image"), icon='image.png') data, filename, title = self._get_image_data(data, filename, title, to_grayscale=True) assert data.ndim == 2, "Data must have 2 dimensions" if pixel_size is None: assert center_on is None, "Ambiguous parameters: both `center_on`"\ " and `xdata`/`ydata` were specified" xmin, xmax = xdata ymin, ymax = ydata else: xmin, xmax, ymin, ymax = self.compute_bounds(data, pixel_size, center_on) self.__set_image_param(param, title, alpha_mask, alpha, interpolation, background=background_color, colormap=colormap, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, show_mask=show_mask, fill_value=fill_value, xformat=xformat, yformat=yformat, zformat=zformat) image = MaskedImageItem(data, mask, param) image.set_filename(filename) if eliminate_outliers is not None: image.set_lut_range(lut_range_threshold(image, 256, eliminate_outliers)) return image def rgbimage(self, data=None, filename=None, title=None,
[docs] alpha_mask=False, alpha=1.0, xdata=[None, None], ydata=[None, None], pixel_size=None, center_on=None, interpolation='linear'): """ Make a RGB image `plot item` from data (:py:class:`guiqwt.image.RGBImageItem` object) """ assert isinstance(xdata, (tuple, list)) and len(xdata) == 2 assert isinstance(ydata, (tuple, list)) and len(ydata) == 2 param = RGBImageParam(title=_("Image"), icon='image.png') data, filename, title = self._get_image_data(data, filename, title, to_grayscale=False) assert data.ndim == 3, "RGB data must have 3 dimensions" if pixel_size is None: assert center_on is None, "Ambiguous parameters: both `center_on`"\ " and `xdata`/`ydata` were specified" xmin, xmax = xdata ymin, ymax = ydata else: xmin, xmax, ymin, ymax = self.compute_bounds(data, pixel_size, center_on) self.__set_image_param(param, title, alpha_mask, alpha, interpolation, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax) image = RGBImageItem(data, param) image.set_filename(filename) return image def quadgrid(self, X, Y, Z, filename=None, title=None, alpha_mask=None,
[docs] alpha=None, background_color=None, colormap=None, interpolation='linear'): """ Make a pseudocolor `plot item` of a 2D array (:py:class:`guiqwt.image.QuadGridItem` object) """ param = QuadGridParam(title=_("Image"), icon='image.png') self.__set_image_param(param, title, alpha_mask, alpha, interpolation, colormap=colormap) image = QuadGridItem(X, Y, Z, param) return image def pcolor(self, *args, **kwargs):
[docs] """ Make a pseudocolor `plot item` of a 2D array based on MATLAB-like syntax (:py:class:`guiqwt.image.QuadGridItem` object) Examples: pcolor(C) pcolor(X, Y, C) """ if len(args) == 1: Z, = args M, N = Z.shape X, Y = meshgrid(arange(N, dtype=Z.dtype), arange(M, dtype=Z.dtype)) elif len(args) == 3: X, Y, Z = args else: raise RuntimeError("1 or 3 non-keyword arguments expected") return self.quadgrid(X, Y, Z, **kwargs) def trimage(self, data=None, filename=None, title=None, alpha_mask=None,
[docs] alpha=None, background_color=None, colormap=None, x0=0.0, y0=0.0, angle=0.0, dx=1.0, dy=1.0, interpolation='linear', eliminate_outliers=None, xformat='%.1f', yformat='%.1f', zformat='%.1f'): """ Make a transformable image `plot item` (image with an arbitrary affine transform) (:py:class:`guiqwt.image.TrImageItem` object) * data: 2D NumPy array (image pixel data) * filename: image filename (if data is not specified) * title: image title (optional) * x0, y0: position * angle: angle (radians) * dx, dy: pixel size along X and Y axes * interpolation: 'nearest', 'linear' (default), 'antialiasing' (5x5) """ param = TrImageParam(title=_("Image"), icon='image.png') data, filename, title = self._get_image_data(data, filename, title, to_grayscale=True) self.__set_image_param(param, title, alpha_mask, alpha, interpolation, background=background_color, colormap=colormap, x0=x0, y0=y0, angle=angle, dx=dx, dy=dy, xformat=xformat, yformat=yformat, zformat=zformat) image = TrImageItem(data, param) image.set_filename(filename) if eliminate_outliers is not None: image.set_lut_range(lut_range_threshold(image, 256, eliminate_outliers)) return image def xyimage(self, x, y, data, title=None, alpha_mask=None, alpha=None,
[docs] background_color=None, colormap=None, interpolation='linear', eliminate_outliers=None, xformat='%.1f', yformat='%.1f', zformat='%.1f'): """ Make an xyimage `plot item` (image with non-linear X/Y axes) from data (:py:class:`guiqwt.image.XYImageItem` object) * x: 1D NumPy array * y: 1D NumPy array * data: 2D NumPy array (image pixel data) * title: image title (optional) * interpolation: 'nearest', 'linear' (default), 'antialiasing' (5x5) """ param = XYImageParam(title=_("Image"), icon='image.png') self.__set_image_param(param, title, alpha_mask, alpha, interpolation, background=background_color, colormap=colormap, xformat=xformat, yformat=yformat, zformat=zformat) image = XYImageItem(x, y, data, param) if eliminate_outliers is not None: image.set_lut_range(lut_range_threshold(image, 256, eliminate_outliers)) return image def imagefilter(self, xmin, xmax, ymin, ymax,
[docs] imageitem, filter, title=None): """ Make a rectangular area image filter `plot item` (:py:class:`guiqwt.image.ImageFilterItem` object) * xmin, xmax, ymin, ymax: filter area bounds * imageitem: An imageitem instance * filter: function (x, y, data) --> data """ param = ImageFilterParam(_("Filter"), icon="funct.png") param.xmin, param.xmax, param.ymin, param.ymax = xmin, xmax, ymin, ymax if title is not None: param.label = title filt = imageitem.get_filter(filter, param) _m, _M = imageitem.get_lut_range() filt.set_lut_range([_m, _M]) return filt def histogram2D(self, X, Y, NX=None, NY=None, logscale=None,
[docs] title=None, transparent=None, Z=None, computation=-1,interpolation=0): """ Make a 2D Histogram `plot item` (:py:class:`guiqwt.image.Histogram2DItem` object) * X: data (1D array) * Y: data (1D array) * NX: Number of bins along x-axis (int) * NY: Number of bins along y-axis (int) * logscale: Z-axis scale (bool) * title: item title (string) * transparent: enable transparency (bool) """ basename = _("2D Histogram") param = Histogram2DParam(title=basename, icon='histogram2d.png') if NX is not None: param.nx_bins = NX if NY is not None: param.ny_bins = NY if logscale is not None: param.logscale = int(logscale) if title is not None: param.label = title else: global HISTOGRAM2D_COUNT HISTOGRAM2D_COUNT += 1 param.label = make_title(basename, HISTOGRAM2D_COUNT) if transparent is not None: param.transparent = transparent param.computation = computation param.interpolation = interpolation return Histogram2DItem(X, Y, param, Z=Z) def label(self, text, g, c, anchor, title=""):
[docs] """ Make a label `plot item` (:py:class:`guiqwt.label.LabelItem` object) * text: label text (string) * g: position in plot coordinates (tuple) or relative position (string) * c: position in canvas coordinates (tuple) * anchor: anchor position in relative position (string) * title: label name (optional) Examples:: make.label("Relative position", (x[0], y[0]), (10, 10), "BR") make.label("Absolute position", "R", (0,0), "R") """ basename = _("Label") param = LabelParamWithContents(basename, icon='label.png') param.read_config(CONF, "plot", "label") if title: param.label = title else: global LABEL_COUNT LABEL_COUNT += 1 param.label = make_title(basename, LABEL_COUNT) if isinstance(g, tuple): param.abspos = False param.xg, param.yg = g else: param.abspos = True param.absg = g if c is None: c = ANCHOR_OFFSETS[anchor] param.xc, param.yc = c param.anchor = anchor return LabelItem(text, param) def legend(self, anchor='TR', c=None, restrict_items=None):
[docs] """ Make a legend `plot item` (:py:class:`guiqwt.label.LegendBoxItem` or :py:class:`guiqwt.label.SelectedLegendBoxItem` object) * anchor: legend position in relative position (string) * c (optional): position in canvas coordinates (tuple) * restrict_items (optional): - None: all items are shown in legend box - []: no item shown - [item1, item2]: item1, item2 are shown in legend box """ param = LegendParam(_("Legend"), icon='legend.png') param.read_config(CONF, "plot", "legend") param.abspos = True param.absg = anchor param.anchor = anchor if c is None: c = ANCHOR_OFFSETS[anchor] param.xc, param.yc = c if restrict_items is None: return LegendBoxItem(param) else: return SelectedLegendBoxItem(param, restrict_items) def range(self, xmin, xmax):
return XRangeSelection(xmin, xmax) def vcursor(self, x, label=None, constraint_cb=None,
[docs] movable=True, readonly=False): """ Make a vertical cursor `plot item` Convenient function to make a vertical marker (:py:class:`guiqwt.shapes.Marker` object) """ if label is None: label_cb = lambda x, y: '' else: label_cb = lambda x, y: label % x return self.marker(position=(x, 0), markerstyle='|', label_cb=label_cb, constraint_cb=constraint_cb, movable=movable, readonly=readonly) def hcursor(self, y, label=None, constraint_cb=None,
[docs] movable=True, readonly=False): """ Make an horizontal cursor `plot item` Convenient function to make an horizontal marker (:py:class:`guiqwt.shapes.Marker` object) """ if label is None: label_cb = lambda x, y: '' else: label_cb = lambda x, y: label % y return self.marker(position=(0, y), markerstyle='-', label_cb=label_cb, constraint_cb=constraint_cb, movable=movable, readonly=readonly) def xcursor(self, x, y, label=None, constraint_cb=None,
[docs] movable=True, readonly=False): """ Make an cross cursor `plot item` Convenient function to make an cross marker (:py:class:`guiqwt.shapes.Marker` object) """ if label is None: label_cb = lambda x, y: '' else: label_cb = lambda x, y: label % (x, y) return self.marker(position=(x, y), markerstyle='+', label_cb=label_cb, constraint_cb=constraint_cb, movable=movable, readonly=readonly) def marker(self, position=None, label_cb=None, constraint_cb=None,
[docs] movable=True, readonly=False, markerstyle=None, markerspacing=None, color=None, linestyle=None, linewidth=None, marker=None, markersize=None, markerfacecolor=None, markeredgecolor=None): """ Make a marker `plot item` (:py:class:`guiqwt.shapes.Marker` object) * position: tuple (x, y) * label_cb: function with two arguments (x, y) returning a string * constraint_cb: function with two arguments (x, y) returning a tuple (x, y) according to the marker constraint * movable: if True (default), marker will be movable * readonly: if False (default), marker can be deleted * markerstyle: '+', '-', '|' or None * markerspacing: spacing between text and marker line * color: marker color name * linestyle: marker line style (MATLAB-like string or attribute name from the :py:class:`PyQt4.QtCore.Qt.PenStyle` enum (i.e. "SolidLine" "DashLine", "DotLine", "DashDotLine", "DashDotDotLine" or "NoPen") * linewidth: line width (pixels) * marker: marker shape (MATLAB-like string or attribute name from the :py:class:`PyQt4.Qwt5.QwtSymbol.Style` enum (i.e. "Cross", "Ellipse", "Star1", "XCross", "Rect", "Diamond", "UTriangle", "DTriangle", "RTriangle", "LTriangle", "Star2" or "NoSymbol") * markersize: marker size (pixels) * markerfacecolor: marker face color name * markeredgecolor: marker edge color name """ param = MarkerParam(_("Marker"), icon='marker.png') param.read_config(CONF, "plot", "marker/cursor") if color or linestyle or linewidth or marker or markersize or \ markerfacecolor or markeredgecolor: param.line = param.sel_line param.symbol = param.sel_symbol param.text = param.sel_text self.__set_baseparam(param, color, linestyle, linewidth, marker, markersize, markerfacecolor, markeredgecolor) param.sel_line = param.line param.sel_symbol = param.symbol param.sel_text = param.text if markerstyle: param.set_markerstyle(markerstyle) if markerspacing: param.spacing = markerspacing if not movable: param.symbol.marker = param.sel_symbol.marker = "NoSymbol" marker = Marker(label_cb=label_cb, constraint_cb=constraint_cb, markerparam=param) if position is not None: x, y = position marker.set_pos(x, y) marker.set_readonly(readonly) if not movable: marker.set_movable(False) marker.set_resizable(False) return marker def __shape(self, shapeclass, x0, y0, x1, y1, title=None):
shape = shapeclass(x0, y0, x1, y1) shape.set_style("plot", "shape/drag") if title is not None: shape.setTitle(title) return shape def rectangle(self, x0, y0, x1, y1, title=None):
[docs] """ Make a rectangle shape `plot item` (:py:class:`guiqwt.shapes.RectangleShape` object) * x0, y0, x1, y1: rectangle coordinates * title: label name (optional) """ return self.__shape(RectangleShape, x0, y0, x1, y1, title) def ellipse(self, x0, y0, x1, y1, title=None):
[docs] """ Make an ellipse shape `plot item` (:py:class:`guiqwt.shapes.EllipseShape` object) * x0, y0, x1, y1: ellipse x-axis coordinates * title: label name (optional) """ shape = EllipseShape(x0, y0, x1, y1) shape.set_style("plot", "shape/drag") if title is not None: shape.setTitle(title) return shape def circle(self, x0, y0, x1, y1, title=None):
[docs] """ Make a circle shape `plot item` (:py:class:`guiqwt.shapes.EllipseShape` object) * x0, y0, x1, y1: circle diameter coordinates * title: label name (optional) """ return self.ellipse(x0, y0, x1, y1, title=title) def segment(self, x0, y0, x1, y1, title=None):
[docs] """ Make a segment shape `plot item` (:py:class:`guiqwt.shapes.SegmentShape` object) * x0, y0, x1, y1: segment coordinates * title: label name (optional) """ return self.__shape(SegmentShape, x0, y0, x1, y1, title) def __get_annotationparam(self, title, subtitle):
param = AnnotationParam(_("Annotation"), icon="annotation.png") if title is not None: param.title = title if subtitle is not None: param.subtitle = subtitle return param def __annotated_shape(self, shapeclass, x0, y0, x1, y1, title, subtitle): param = self.__get_annotationparam(title, subtitle) shape = shapeclass(x0, y0, x1, y1, param) shape.set_style("plot", "shape/drag") return shape def annotated_rectangle(self, x0, y0, x1, y1, title=None, subtitle=None):
[docs] """ Make an annotated rectangle `plot item` (:py:class:`guiqwt.annotations.AnnotatedRectangle` object) * x0, y0, x1, y1: rectangle coordinates * title, subtitle: strings """ return self.__annotated_shape(AnnotatedRectangle, x0, y0, x1, y1, title, subtitle) def annotated_ellipse(self, x0, y0, x1, y1, ratio,
[docs] title=None, subtitle=None): """ Make an annotated ellipse `plot item` (:py:class:`guiqwt.annotations.AnnotatedEllipse` object) * x0, y0, x1, y1: ellipse rectangle coordinates * ratio: ratio between y-axis and x-axis lengths * title, subtitle: strings """ param = self.__get_annotationparam(title, subtitle) shape = AnnotatedEllipse(x0, y0, x1, y1, ratio, param) shape.set_style("plot", "shape/drag") return shape def annotated_circle(self, x0, y0, x1, y1, ratio,
[docs] title=None, subtitle=None): """ Make an annotated circle `plot item` (:py:class:`guiqwt.annotations.AnnotatedCircle` object) * x0, y0, x1, y1: circle diameter coordinates * title, subtitle: strings """ return self.annotated_ellipse(x0, y0, x1, y1, 1., title, subtitle) def annotated_segment(self, x0, y0, x1, y1, title=None, subtitle=None):
[docs] """ Make an annotated segment `plot item` (:py:class:`guiqwt.annotations.AnnotatedSegment` object) * x0, y0, x1, y1: segment coordinates * title, subtitle: strings """ return self.__annotated_shape(AnnotatedSegment, x0, y0, x1, y1, title, subtitle) def info_label(self, anchor, comps, title=None):
[docs] """ Make an info label `plot item` (:py:class:`guiqwt.label.DataInfoLabel` object) """ basename = _("Computation") param = LabelParam(basename, icon='label.png') param.read_config(CONF, "plot", "info_label") if title is not None: param.label = title else: global LABEL_COUNT LABEL_COUNT += 1 param.label = make_title(basename, LABEL_COUNT) param.abspos = True param.absg = anchor param.anchor = anchor c = ANCHOR_OFFSETS[anchor] param.xc, param.yc = c return DataInfoLabel(param, comps) def range_info_label(self, range, anchor, label,
[docs] function=None, title=None): """ Make an info label `plot item` showing an XRangeSelection object infos Default function is `lambda x, dx: (x, dx)`. Example: ------- x = linspace(-10, 10, 10) y = sin(sin(sin(x))) range = make.range(-2, 2) disp = make.range_info_label(range, 'BL', u"x = %.1f ± %.1f cm", lambda x, dx: (x, dx)) (:py:class:`guiqwt.label.DataInfoLabel` object) (see example: :py:mod:`guiqwt.tests.computations`) """ info = RangeInfo(label, range, function) return make.info_label(anchor, info, title=title) def computation(self, range, anchor, label, curve, function, title=None):
[docs] """ Make a computation label `plot item` (:py:class:`guiqwt.label.DataInfoLabel` object) (see example: :py:mod:`guiqwt.tests.computations`) """ if title is None: title = curve.curveparam.label return self.computations(range, anchor, [ (curve, label, function) ], title=title) def computations(self, range, anchor, specs, title=None):
[docs] """ Make computation labels `plot item` (:py:class:`guiqwt.label.DataInfoLabel` object) (see example: :py:mod:`guiqwt.tests.computations`) """ comps = [] same_curve = True curve0 = None for curve, label, function in specs: comp = RangeComputation(label, curve, range, function) comps.append(comp) if curve0 is None: curve0 = curve same_curve = same_curve and curve is curve0 if title is None and same_curve: title = curve.curveparam.label return self.info_label(anchor, comps, title=title) def computation2d(self, rect, anchor, label, image, function, title=None):
[docs] """ Make a 2D computation label `plot item` (:py:class:`guiqwt.label.RangeComputation2d` object) (see example: :py:mod:`guiqwt.tests.computations`) """ return self.computations2d(rect, anchor, [ (image, label, function) ], title=title) def computations2d(self, rect, anchor, specs, title=None):
[docs] """ Make 2D computation labels `plot item` (:py:class:`guiqwt.label.RangeComputation2d` object) (see example: :py:mod:`guiqwt.tests.computations`) """ comps = [] same_image = True image0 = None for image, label, function in specs: comp = RangeComputation2d(label, image, rect, function) comps.append(comp) if image0 is None: image0 = image same_image = same_image and image is image0 if title is None and same_image: title = image.imageparam.label return self.info_label(anchor, comps, title=title) make = PlotItemBuilder()