Source code for guiqwt.styles

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

# pylint: disable=C0103

"""
guiqwt.styles
-------------

The `styles` module provides set of parameters (DataSet classes) to 
configure `plot items` and `plot tools`.

.. seealso::
        
    Module :py:mod:`guiqwt.plot`
        Module providing ready-to-use curve and image plotting widgets and 
        dialog boxes
    
    Module :py:mod:`guiqwt.curve`
        Module providing curve-related plot items and plotting widgets
        
    Module :py:mod:`guiqwt.image`
        Module providing image-related plot items and plotting widgets
        
    Module :py:mod:`guiqwt.tools`
        Module providing the `plot tools`
        
Reference
~~~~~~~~~

.. autoclass:: CurveParam
   :members:
   :inherited-members:
.. autoclass:: ErrorBarParam
   :members:
   :inherited-members:
.. autoclass:: GridParam
   :members:
   :inherited-members:
.. autoclass:: ImageParam
   :members:
   :inherited-members:
.. autoclass:: TrImageParam
   :members:
   :inherited-members:
.. autoclass:: ImageFilterParam
   :members:
   :inherited-members:
.. autoclass:: HistogramParam
   :members:
   :inherited-members:
.. autoclass:: Histogram2DParam
   :members:
   :inherited-members:
.. autoclass:: AxesParam
   :members:
   :inherited-members:
.. autoclass:: ImageAxesParam
   :members:
   :inherited-members:
.. autoclass:: LabelParam
   :members:
   :inherited-members:
.. autoclass:: LegendParam
   :members:
   :inherited-members:
.. autoclass:: ShapeParam
   :members:
   :inherited-members:
.. autoclass:: AnnotationParam
   :members:
   :inherited-members:
.. autoclass:: AxesShapeParam
   :members:
   :inherited-members:
.. autoclass:: RangeShapeParam
   :members:
   :inherited-members:
.. autoclass:: MarkerParam
   :members:
   :inherited-members:
.. autoclass:: FontParam
   :members:
   :inherited-members:
.. autoclass:: SymbolParam
   :members:
   :inherited-members:
.. autoclass:: LineStyleParam
   :members:
   :inherited-members:
.. autoclass:: BrushStyleParam
   :members:
   :inherited-members:
.. autoclass:: TextStyleParam
   :members:
   :inherited-members:
"""

import numpy as np

from guidata.qt.QtGui import (QPen, QBrush, QColor, QFont, QFontDialog,
                              QTransform)
from guidata.qt.QtCore import Qt, QSizeF, QPointF

from guidata.dataset.datatypes import (DataSet, ObjectItem, BeginGroup,
                                       EndGroup, Obj, DataSetGroup,
                                       BeginTabGroup, EndTabGroup,
                                       GetAttrProp, NotProp)
from guidata.dataset.dataitems import (ChoiceItem, BoolItem, FloatItem, IntItem,
                                       ImageChoiceItem, ColorItem, StringItem,
                                       ButtonItem, FloatArrayItem, TextItem)
from guidata.dataset.qtwidgets import DataSetEditLayout
from guidata.dataset.qtitemwidgets import DataSetWidget
from guidata.utils import update_dataset
from guidata.py3compat import to_text_string

# Local imports
from guiqwt.transitional import QwtPlot, QwtPlotCurve, QwtSymbol, QwtPlotMarker
from guiqwt.config import _
from guiqwt.colormap import get_colormap_list, build_icon_from_cmap_name

class ItemParameters(object):
    """Class handling QwtPlotItem-like parameters"""
    MULTISEL_DATASETS = []
    # Customizing tab display order:
    ENDING_PARAMETERS = ("CurveParam", "ErrorBarParam",
                         "ShapeParam", "LabelParam", "LegendParam",
                         "GridParam", "AxesParam")
    
    def __init__(self, multiselection=False):
        self.multiselection = multiselection
        self.paramdict = {}
        self.items = set()
        
    @classmethod
    def register_multiselection(cls, klass, klass_ms):
        """Register a DataSet couple: (DataSet, DataSet_for_MultiSelection)"""
        # Inserting element backwards because classes have to be registered
        # from children to parent (see 'add' method to fully understand why)
        cls.MULTISEL_DATASETS.insert(0, (klass, klass_ms))
        
    def __add(self, key, item, param):
        self.paramdict[key] = param
        self.items.add(item)
        
    def add(self, key, item, param):
        if self.multiselection:
            for klass, klass_ms in self.MULTISEL_DATASETS:
                if isinstance(param, klass):
                    title = param.get_title()
                    if key in self.paramdict and not title.endswith('s'):
                        title += 's'
                    param_ms = klass_ms(title=title,
                                        comment=param.get_comment(),
                                        icon=param.get_icon())
                    update_dataset(param_ms, param)
                    self.__add(key, item, param_ms)
                    return
        self.__add(key, item, param)
        
    def get(self, key):
        from copy import deepcopy
        return deepcopy(self.paramdict.get(key))
    
    def update(self, plot):
        #XXX: removed the following workaround as the associated bug can't be 
        # reproduced anymore with guiqwt 3. However, keeping the workaround 
        # here (commented) as it could become useful eventually.
        #-----
        #FIXME: without the following workaround, ImagePlot object aspect ratio
        # is changed when pressing button "Apply"
        # (see also guiqwt.image.ImagePlot.edit_axis_parameters)
#        from guiqwt.image import ImagePlot
#        if isinstance(plot, ImagePlot):
#            ratio = plot.get_current_aspect_ratio()
        #-----
        for item in self.items:
            item.set_item_parameters(self)
        plot.replot()
        #-----
#        if isinstance(plot, ImagePlot):
#            plot.set_aspect_ratio(ratio=ratio)
#            plot.replot()
        #-----
        plot.SIG_ITEMS_CHANGED.emit(plot)
    
    def edit(self, plot, title, icon):
        paramdict = self.paramdict.copy()
        ending_parameters = []
        for key in self.ENDING_PARAMETERS:
            if key in paramdict:
                ending_parameters.append(paramdict.pop(key))
        parameters = list(paramdict.values())+ending_parameters
        dset = DataSetGroup(parameters, title=title.rstrip('.'), icon=icon)
        if dset.edit(parent=plot, apply=lambda dset: self.update(plot)):
            self.update(plot)


LINESTYLES = {
              "-": "SolidLine",
              "--": "DashLine",
              ":": "DotLine",
              "-.": "DashDotLine",
              }
COLORS = {
          "r": "red",
          "g": "green",
          "b": "blue",
          "c": "cyan",
          "m": "magenta",
          "y": "yellow",
          "k": "black",
          "w": "white",
          "G": "gray",
          }
MARKERS = {
          "+": QwtSymbol.Cross,
          "o": QwtSymbol.Ellipse,
          "*": QwtSymbol.Star1,
          ".": QwtSymbol(QwtSymbol.Ellipse, QBrush(Qt.black),
                          QPen(Qt.black), QSizeF(3, 3)),
          "x": QwtSymbol.XCross,
          "s": QwtSymbol.Rect,
          "d": QwtSymbol.Diamond,
          "^": QwtSymbol.UTriangle,
          "v": QwtSymbol.DTriangle,
          ">": QwtSymbol.RTriangle,
          "<": QwtSymbol.LTriangle,
          "h": QwtSymbol.Star2,
          }
MARKERSTYLES = {
                None: "NoLine",
                "-": "HLine",
                "|": "VLine",
                "+": "Cross",
                }


def style_generator(color_keys="bgrcmykG"):
    """Cycling through curve styles"""
    while True:
        for linestyle in sorted(LINESTYLES.keys()):
            for color in color_keys:
                yield color+linestyle

def update_style_attr(style, param):
    """Parse a MATLAB-like style string and
    update the color, linestyle, marker attributes of the param
    object
    """
    for marker in list(MARKERS.keys()):
        if marker in style:
            param.symbol.update_param(MARKERS[marker])
            break
    else:
        param.symbol.update_param(QwtSymbol.NoSymbol)
    for linestyle in list(LINESTYLES.keys()):
        if linestyle in style:
            param.line.style = LINESTYLES[linestyle]
            break
    else:
        param.line.style = "NoPen"
    for color in list(COLORS.keys()):
        if color in style:
            param.line.color = COLORS[color]
            param.symbol.facecolor = COLORS[color]
            param.symbol.edgecolor = COLORS[color]
            break


def build_reverse_map(lst, obj):
    dict = {}
    for idx, _name, _icon in lst:
        val = getattr(obj, idx)
        dict[val] = idx
    return dict

LINESTYLE_CHOICES = [("SolidLine", _("Solid line"), "solid.png"),
                     ("DashLine", _("Dashed line"), "dash.png"),
                     ("DotLine", _("Dotted line"), "dot.png"),
                     ("DashDotLine", _("Dash-dot line"), "dashdot.png"),
                     ("DashDotDotLine", _("Dash-dot-dot line"), "dashdotdot.png"),
                     ("NoPen", _("No line"), "none.png"),
                     ]
MARKER_CHOICES = [("Cross", _("Cross"), "cross.png"),
                  ("Ellipse", _("Ellipse"), "ellipse.png"),
                  ("Star1", _("Star"), "star.png"),
                  ("XCross", _("X-Cross"), "xcross.png"),
                  ("Rect", _("Square"), "square.png"),
                  ("Diamond", _("Diamond"), "diamond.png"),
                  ("UTriangle", _("Triangle"), "triangle_u.png"),
                  ("DTriangle", _("Triangle"), "triangle_d.png"),
                  ("RTriangle", _("Triangle"), "triangle_r.png"),
                  ("LTriangle", _("Triangle"), "triangle_l.png"),
                  ("Star2", _("Hexagon"), "hexagon.png"),
                  ("NoSymbol", _("No symbol"), "none.png"),
                  ]
CURVESTYLE_CHOICES = [("Lines", _("Lines"), "lines.png"),
                      ("Sticks", _("Sticks"), "sticks.png"),
                      ("Steps", _("Steps"), "steps.png"),
                      ("Dots", _("Dots"), "dots.png"),
                      ("NoCurve", _("No curve"), "none.png")
                      ]

BRUSHSTYLE_CHOICES = [
    ("NoBrush", _("No brush pattern"), "nobrush.png"),
    ("SolidPattern", _("Uniform color"), "solidpattern.png"),
    ("Dense1Pattern", _("Extremely dense brush pattern"), "dense1pattern.png"),
    ("Dense2Pattern", _("Very dense brush pattern"), "dense2pattern.png"),
    ("Dense3Pattern", _("Somewhat dense brush pattern"), "dense3pattern.png"),
    ("Dense4Pattern", _("Half dense brush pattern"), "dense4pattern.png"),
    ("Dense5Pattern", _("Somewhat sparse brush pattern"), "dense5pattern.png"),
    ("Dense6Pattern", _("Very sparse brush pattern"), "dense6pattern.png"),
    ("Dense7Pattern", _("Extremely sparse brush pattern"), "dense7pattern.png"),
    ("HorPattern", _("Horizontal lines"), "horpattern.png"),
    ("VerPattern", _("Vertical lines"), "verpattern.png"),
    ("CrossPattern", _("Crossing horizontal and vertical lines"),
     "crosspattern.png"),
    ("BDiagPattern", _("Backward diagonal lines"), "bdiagpattern.png"),
    ("FDiagPattern", _("Forward diagonal lines"), "fdiagpattern.png"),
    ("DiagCrossPattern", _("Crossing diagonal lines"), "diagcrosspattern.png"),
#    ("LinearGradientPattern", _("Linear gradient (set using a dedicated QBrush constructor)"), "none.png"),
#    ("ConicalGradientPattern", _("Conical gradient (set using a dedicated QBrush constructor)"), "none.png"),
#    ("RadialGradientPattern", _("Radial gradient (set using a dedicated QBrush constructor)"), "none.png"),
#    ("TexturePattern", _("Custom pattern (see QBrush::setTexture())"), "none.png"),
]

MARKERSTYLE_CHOICES = [("NoLine", _("None"), "none.png"),
                       ("HLine",  _("Horizontal"), "horiz_marker.png"),
                       ("VLine",  _("Vertical"), "vert_marker.png"),
                       ("Cross",  _("Cross"), "cross_marker.png"),
                       ]

MARKER_NAME = build_reverse_map(MARKER_CHOICES, QwtSymbol)
CURVESTYLE_NAME = build_reverse_map(CURVESTYLE_CHOICES, QwtPlotCurve)
LINESTYLE_NAME = build_reverse_map(LINESTYLE_CHOICES, Qt)
BRUSHSTYLE_NAME = build_reverse_map(BRUSHSTYLE_CHOICES, Qt)
MARKERSTYLE_NAME = build_reverse_map(MARKERSTYLE_CHOICES, QwtPlotMarker)


# ===================================================
# Common font parameters
# ===================================================
def _font_selection(param, item, value, parent):
    font = param.build_font()
    result, valid = QFontDialog.getFont(font, parent)
    if valid:
        param.update_param( result )
    
[docs]class FontParam(DataSet): family = StringItem(_("Family"), default="default") _choose = ButtonItem(_("Choose font"), _font_selection, default=None).set_pos(col=1) size = IntItem(_("Size in point"), default=12) bold = BoolItem(_("Bold"), default=False).set_pos(col=1) italic = BoolItem(_("Italic"), default=False).set_pos(col=2) def update_param(self, font): self.family = str(font.family()) self.size = font.pointSize() self.bold = bool(font.bold()) self.italic = bool(font.italic()) def build_font(self): font = QFont(self.family) font.setPointSize( self.size ) font.setBold( self.bold ) font.setItalic( self.italic ) return font
class FontItemWidget(DataSetWidget): klass = FontParam class FontItem(ObjectItem): """Item holding a LineStyleParam""" klass = FontParam DataSetEditLayout.register(FontItem, FontItemWidget) # =================================================== # Common Qwt symbol parameters # ===================================================
[docs]class SymbolParam(DataSet): marker = ImageChoiceItem(_("Style"), MARKER_CHOICES, default="NoSymbol") size = IntItem(_("Size"), default=9) edgecolor = ColorItem(_("Border"), default="gray") facecolor = ColorItem(_("Background color"), default="yellow") alpha = FloatItem(_("Background alpha"), default=1., min=0, max=1) def update_param(self, symb): if not isinstance(symb, QwtSymbol): # check if this is still needed #raise RuntimeError assert isinstance(symb, QwtSymbol.Style) self.marker = MARKER_NAME[symb] return self.marker = MARKER_NAME[symb.style()] self.size = symb.size().width() self.edgecolor = str(symb.pen().color().name()) self.facecolor = str(symb.brush().color().name()) def build_symbol(self): marker_type = getattr(QwtSymbol, self.marker) color = QColor(self.facecolor) color.setAlphaF(self.alpha) marker = QwtSymbol(marker_type, QBrush(color), QPen(QColor(self.edgecolor)), QSizeF(self.size, self.size)) return marker def update_symbol(self, obj): obj.setSymbol(self.build_symbol())
class SymbolItemWidget(DataSetWidget): klass = SymbolParam class SymbolItem(ObjectItem): """Item holding a SymbolParam""" klass = SymbolParam DataSetEditLayout.register(SymbolItem, SymbolItemWidget) # =================================================== # Common line style parameters # ===================================================
[docs]class LineStyleParam(DataSet): style = ImageChoiceItem(_("Style"), LINESTYLE_CHOICES, default="SolidLine") color = ColorItem(_("Color"), default="black") width = FloatItem(_("Width"), default=1., min=0) def update_param(self, pen): self.width = pen.widthF() self.color = str(pen.color().name()) self.style = LINESTYLE_NAME[pen.style()] def build_pen(self): linecolor = QColor(self.color) style = getattr(Qt, self.style) pen = QPen(linecolor, self.width, style) return pen
[docs] def set_style_from_matlab(self, linestyle): """Eventually convert MATLAB-like linestyle into Qt linestyle""" linestyle = LINESTYLES.get(linestyle, linestyle) # MATLAB-style if linestyle == '': # MATLAB-style linestyle = 'NoPen' self.style = linestyle
class LineStyleItemWidget(DataSetWidget): klass = LineStyleParam class LineStyleItem(ObjectItem): """Item holding a LineStyleParam""" klass = LineStyleParam DataSetEditLayout.register(LineStyleItem, LineStyleItemWidget) # =================================================== # Common brush style parameters # ===================================================
[docs]class BrushStyleParam(DataSet): style = ImageChoiceItem(_("Style"), BRUSHSTYLE_CHOICES, default="SolidPattern") color = ColorItem(_("Color"), default="black") alpha = FloatItem(_("Alpha"), default=1.0) angle = FloatItem(_("Angle"), default=0., min=0) sx = FloatItem(_("sx"), default=1., min=0) sy = FloatItem(_("sy"), default=1., min=0) def update_param(self, brush): from math import pi, sqrt, atan2 tr = brush.transform() pt = tr.map( QPointF(1.0, 0.0) ) self.sx = sqrt(pt.x()**2+pt.y()**2) self.angle = 180*atan2(pt.y(), pt.x())/pi pt = tr.map( QPointF(0.0, 1.0) ) self.sy = sqrt(pt.x()**2+pt.y()**2) col = brush.color() self.color = str(col.name()) self.alpha = col.alphaF() self.style = BRUSHSTYLE_NAME[brush.style()] def build_brush(self): color = QColor(self.color) color.setAlphaF(self.alpha) brush = QBrush(color, getattr(Qt, self.style)) tr = QTransform() tr = tr.scale(self.sx, self.sy) tr = tr.rotate(self.angle) brush.setTransform(tr) return brush
class BrushStyleItemWidget(DataSetWidget): klass = BrushStyleParam class BrushStyleItem(ObjectItem): """Item holding a LineStyleParam""" klass = BrushStyleParam DataSetEditLayout.register(BrushStyleItem, BrushStyleItemWidget) # =================================================== # QwtText parameters # ===================================================
[docs]class TextStyleParam(DataSet): font = FontItem(_("Font")) textcolor = ColorItem(_("Text color"), default="blue") background_color = ColorItem(_("Background color"), default="white") background_alpha = FloatItem(_("Background alpha"), default=0.5, min=0, max=1)
[docs] def update_param(self, obj): """obj: QwtText instance""" self.font.update_param( obj.font() ) self.textcolor = obj.color().name() color = obj.backgroundBrush().color() self.background_color = color.name() self.background_alpha = color.alphaF()
[docs] def update_text(self, obj): """obj: QwtText instance""" obj.setColor( QColor(self.textcolor) ) color = QColor(self.background_color) color.setAlphaF(self.background_alpha) obj.setBackgroundBrush( QBrush(color) ) font = self.font.build_font() obj.setFont(font)
class TextStyleItemWidget(DataSetWidget): klass = TextStyleParam class TextStyleItem(ObjectItem): """Item holding a TextStyleParam""" klass = TextStyleParam DataSetEditLayout.register(TextStyleItem, TextStyleItemWidget) # =================================================== # Grid parameters # ===================================================
[docs]class GridParam(DataSet): background = ColorItem(_("Background color"), default="white") maj = BeginGroup(_("Major grid") ) maj_xenabled = BoolItem(_("X Axis"), default=True) maj_yenabled = BoolItem(_("Y Axis"), default=True).set_pos(col=1) maj_line = LineStyleItem(_("Line")) _maj = EndGroup("end group") min = BeginGroup(_("Minor grid")) min_xenabled = BoolItem(_("X Axis"), default=False) min_yenabled = BoolItem(_("Y Axis"), default=False).set_pos(col=1) min_line = LineStyleItem(_("Line")) _min = EndGroup("fin groupe") def update_param(self, grid): plot = grid.plot() if plot is not None: self.background = str(plot.canvasBackground().color().name()) self.maj_xenabled = grid.xEnabled() self.maj_yenabled = grid.yEnabled() self.maj_line.update_param( grid.majorPen() ) self.min_xenabled = grid.xMinEnabled() self.min_yenabled = grid.yMinEnabled() self.min_line.update_param( grid.minorPen() ) def update_grid(self, grid): plot = grid.plot() if plot is not None: plot.blockSignals(True) # Avoid unwanted calls of update_param # triggered by the setter methods below plot.setCanvasBackground( QColor(self.background) ) grid.enableX(self.maj_xenabled) grid.enableY(self.maj_yenabled) grid.setPen( self.maj_line.build_pen() ) grid.enableXMin(self.min_xenabled) grid.enableYMin(self.min_yenabled) grid.setMinorPen( self.min_line.build_pen() ) grid.setTitle(self.get_title()) if plot is not None: plot.blockSignals(False)
# =================================================== # Axes style parameters # =================================================== class AxeStyleParam(DataSet): title = StringItem(_("Title"), default="") unit = StringItem(_("Unit"), default="") color = ColorItem(_("Color"), default="black").set_pos(col=1) title_font = FontItem(_("Title font")) ticks_font = FontItem(_("Values font")) # =================================================== # Axes parameters # =================================================== class AxisParam(DataSet): scale = ChoiceItem(_("Scale"), [("lin", _("linear")), ("log", _("logarithmic"))], default="lin") vmin = FloatItem("Min", help=_("Lower axis limit")) vmax = FloatItem("Max", help=_("Upper axis limit")) def update_param(self, plot, axis_id): self.scale = plot.get_axis_scale(axis_id) axis = plot.axisScaleDiv(axis_id) self.vmin = axis.lowerBound() self.vmax = axis.upperBound() def update_axis(self, plot, axis_id): plot.enableAxis(axis_id, True) plot.set_axis_scale(axis_id, self.scale, autoscale=False) plot.setAxisScale(axis_id, self.vmin, self.vmax) plot.disable_unused_axes() class AxisItemWidget(DataSetWidget): klass = AxisParam class AxisItem(ObjectItem): klass = AxisParam DataSetEditLayout.register(AxisItem, AxisItemWidget)
[docs]class AxesParam(DataSet): xaxis_id = ChoiceItem(_("X-axis position"), [(QwtPlot.xBottom, _("bottom")), (QwtPlot.xTop, _("top"))], default=QwtPlot.xBottom) xaxis = AxisItem(_("X Axis")) yaxis_id = ChoiceItem(_("Y-axis position"), [(QwtPlot.yLeft, _("left")), (QwtPlot.yRight, _("right"))], default=QwtPlot.yLeft) yaxis = AxisItem(_("Y Axis")) def update_param(self, item): plot = item.plot() self.xaxis_id = item.xAxis() self.xaxis.update_param(plot, self.xaxis_id) self.yaxis_id = item.yAxis() self.yaxis.update_param(plot, self.yaxis_id) def update_axes(self, item): plot = item.plot() plot.grid.setAxes(self.xaxis_id, self.yaxis_id) item.setXAxis(self.xaxis_id) self.xaxis.update_axis(plot, self.xaxis_id) item.setYAxis(self.yaxis_id) self.yaxis.update_axis(plot, self.yaxis_id)
[docs]class ImageAxesParam(DataSet): xparams = BeginGroup(_("X Axis") ) xmin = FloatItem("x|min", help=_("Lower x-axis limit")) xmax = FloatItem("x|max", help=_("Upper x-axis limit")) _xparams = EndGroup("end X") yparams = BeginGroup(_("Y Axis") ) ymin = FloatItem("y|min", help=_("Lower y-axis limit")) ymax = FloatItem("y|max", help=_("Upper y-axis limit")) _yparams = EndGroup("end Y") zparams = BeginGroup(_("Z Axis") ) zmin = FloatItem("z|min", help=_("Lower z-axis limit")) zmax = FloatItem("z|max", help=_("Upper z-axis limit")) _zparams = EndGroup("end Z") def update_param(self, item): plot = item.plot() xaxis = plot.axisScaleDiv(item.xAxis()) self.xmin = xaxis.lowerBound() self.xmax = xaxis.upperBound() yaxis = plot.axisScaleDiv(item.yAxis()) self.ymin = yaxis.lowerBound() self.ymax = yaxis.upperBound() self.zmin, self.zmax = item.min, item.max def update_axes(self, item): plot = item.plot() plot.set_plot_limits(self.xmin, self.xmax, self.ymin, self.ymax) item.set_lut_range([self.zmin, self.zmax]) plot.update_colormap_axis(item)
# =================================================== # Label parameters # ===================================================
[docs]class LabelParam(DataSet): _multiselection = False _legend = False _no_contents = True label = StringItem(_("Title"), default="") \ .set_prop("display", hide=GetAttrProp("_multiselection")) _styles = BeginTabGroup("Styles") #-------------------------------------------------------------- Contents tab ___cont = BeginGroup(_("Contents")).set_prop("display", icon="label.png", hide=GetAttrProp("_no_contents")) contents = TextItem("").set_prop("display", hide=GetAttrProp("_no_contents")) ___econt = EndGroup(_("Contents")).set_prop("display", hide=GetAttrProp("_no_contents")) #---------------------------------------------------------------- Symbol tab symbol = SymbolItem(_("Symbol")).set_prop("display", icon="diamond.png", hide=GetAttrProp("_legend")) #---------------------------------------------------------------- Border tab border = LineStyleItem(_("Border"), default=Obj(color="#cbcbcb"), help=_("set width to 0 to disable") ).set_prop("display", icon="dashdot.png") #------------------------------------------------------------------ Text tab ___text = BeginGroup(_("Text")).set_prop("display", icon="font.png") font = FontItem(_("Text font")) color = ColorItem(_("Text color"), default="#000000") bgcolor = ColorItem(_("Background color"), default="#ffffff") bgalpha = FloatItem(_("Background transparency"), min=0.0, max=1.0, default=0.8) ___etext = EndGroup(_("Text")) #-------------------------------------------------------------- Position tab ___position = BeginGroup(_("Position")).set_prop("display", icon="move.png") _begin_anchor = BeginGroup(_("Position relative to anchor")) \ .set_prop("display", hide=GetAttrProp("_multiselection")) anchor = ChoiceItem(_("Corner"), [("TL", _("Top left") ), ("TR", _("Top right") ), ("BL", _("Bottom left") ), ("BR", _("Bottom right") ), ("L", _("Left") ), ("R", _("Right") ), ("T", _("Top") ), ("B", _("Bottom") ), ("C", _("Center") ),], default="TL", help=_("Label position relative to anchor point")) \ .set_prop("display", hide=GetAttrProp("_multiselection")) xc = IntItem(_("ΔX"), default=5, help=_("Horizontal offset (pixels) relative to anchor point"))\ .set_prop("display", hide=GetAttrProp("_multiselection")) yc = IntItem(_("ΔY"), default=5, help=_("Vertical offset (pixels) relative to anchor point") ).set_pos(col=1).set_prop("display", hide=GetAttrProp("_multiselection")) _end_anchor = EndGroup(_("Anchor")) \ .set_prop("display", hide=GetAttrProp("_multiselection")) _begin_anchorpos = BeginGroup(_("Anchor position")) \ .set_prop("display", hide=GetAttrProp("_multiselection")) _abspos_prop = GetAttrProp("abspos") abspos = BoolItem(text=_("Attach to canvas"), label=_("Anchor"), default=True ).set_prop("display", store=_abspos_prop) \ .set_prop("display", hide=GetAttrProp("_multiselection")) xg = FloatItem(_("X"), default=0.0, help=_("X-axis position in canvas coordinates") ).set_prop("display", active=NotProp(_abspos_prop)) \ .set_prop("display", hide=GetAttrProp("_multiselection")) yg = FloatItem(_("Y"), default=0.0, help=_("Y-axis position in canvas coordinates") ).set_pos(col=1) \ .set_prop("display", active=NotProp(_abspos_prop)) \ .set_prop("display", hide=GetAttrProp("_multiselection")) move_anchor = ChoiceItem(_("Interact"), ((True, _("moving object changes anchor position")), (False, _("moving object changes label position"))), default=True ).set_prop("display", active=NotProp(_abspos_prop)) \ .set_prop("display", hide=GetAttrProp("_multiselection")) absg = ChoiceItem(_("Position"), [("TL", _("Top left") ), ("TR", _("Top right") ), ("BL", _("Bottom left") ), ("BR", _("Bottom right") ), ("L", _("Left") ), ("R", _("Right") ), ("T", _("Top") ), ("B", _("Bottom") ), ("C", _("Center") ),], default="TL", help=_("Absolute position on canvas") ).set_prop("display", active=_abspos_prop) \ .set_prop("display", hide=GetAttrProp("_multiselection")) _end_anchorpos = EndGroup(_("Anchor position")) \ .set_prop("display", hide=GetAttrProp("_multiselection")) ___eposition = EndGroup(_("Position")) #----------------------------------------------------------------------- End _endstyles = EndTabGroup("Styles") def update_param(self, obj): # The following is necessary only for shape labels: # when shape is just created (and not yet moved), we need to update # these attributes if self.abspos: self.absg = obj.G else: self.xg, self.yg = obj.G self.xc, self.yc = obj.C def update_label(self, obj): if not self._multiselection: if self.abspos: obj.G = self.absg else: obj.G = (self.xg, self.yg) obj.C = self.xc, self.yc obj.anchor = self.anchor obj.move_anchor = self.move_anchor obj.setTitle(self.label) obj.marker = self.symbol.build_symbol() obj.border_pen = self.border.build_pen() obj.set_text_style(self.font.build_font(), self.color) color = QColor(self.bgcolor) color.setAlphaF(self.bgalpha) obj.bg_brush = QBrush(color)
class LabelParam_MS(LabelParam): _multiselection = True ItemParameters.register_multiselection(LabelParam, LabelParam_MS)
[docs]class LegendParam(LabelParam): _legend = True label = StringItem(_("Title"), default="").set_prop("display", hide=True) def update_label(self, obj): super(LegendParam, self).update_label(obj) if not self._multiselection: obj.setTitle(self.get_title())
class LegendParam_MS(LegendParam): _multiselection = True ItemParameters.register_multiselection(LegendParam, LegendParam_MS) class LabelParamWithContents(LabelParam): _no_contents = False def __init__(self, title=None, comment=None, icon=''): self.plain_text = None super(LabelParamWithContents, self).__init__(title, comment, icon) def update_param(self, obj): super(LabelParamWithContents, self).update_param(obj) self.contents = self.plain_text = obj.get_plain_text() def update_label(self, obj): super(LabelParamWithContents, self).update_label(obj) if self.plain_text is not None and self.contents != self.plain_text: text = self.contents.replace('\n', '<br>') obj.set_text(text) class LabelParamWithContents_MS(LabelParamWithContents): _multiselection = True ItemParameters.register_multiselection(LabelParamWithContents, LabelParamWithContents_MS) # =================================================== # Curve parameters # ===================================================
[docs]class CurveParam(DataSet): _multiselection = False label = StringItem(_("Title"), default="").set_prop("display", hide=GetAttrProp("_multiselection")) line = LineStyleItem(_("Line")) symbol = SymbolItem(_("Symbol")) shade = FloatItem(_("Shadow"), default=0, min=0, max=1) curvestyle = ImageChoiceItem(_("Curve style"), CURVESTYLE_CHOICES, default="Lines") baseline = FloatItem(_("Baseline"), default=0.) def update_param(self, curve): self.label = to_text_string(curve.title().text()) self.symbol.update_param(curve.symbol()) self.line.update_param(curve.pen()) self.curvestyle = CURVESTYLE_NAME[curve.style()] self.baseline = curve.baseline() def update_curve(self, curve): plot = curve.plot() if plot is not None: plot.blockSignals(True) # Avoid unwanted calls of update_param # triggered by the setter methods below if not self._multiselection: # Non common parameters curve.setTitle(self.label) curve.setPen(self.line.build_pen()) # Brush linecolor = QColor(self.line.color) linecolor.setAlphaF(self.shade) brush = QBrush(linecolor) if not self.shade: brush.setStyle(Qt.NoBrush) curve.setBrush(brush) # Symbol self.symbol.update_symbol( curve ) # Curve style, type and baseline curve.setStyle(getattr(QwtPlotCurve, self.curvestyle)) curve.setBaseline(self.baseline) if plot is not None: plot.blockSignals(False)
class CurveParam_MS(CurveParam): _multiselection = True ItemParameters.register_multiselection(CurveParam, CurveParam_MS) # =================================================== # ErrorBar Curve parameters # ===================================================
[docs]class ErrorBarParam(DataSet): mode = ChoiceItem(_("Display"), default=0, choices=[_("error bars with caps (x, y)"), _("error area (y)")], help=_("Note: only y-axis error bars are shown in " "error area mode\n(width and cap parameters " "will also be ignored)")) color = ColorItem(_("Color"), default="darkred") alpha = FloatItem(_("Alpha"), default=.9, min=0, max=1, help=_("Error bar transparency")) width = FloatItem(_("Width"), default=1.0, min=1) cap = IntItem(_("Cap"), default=4, min=0) ontop = BoolItem(_("set to foreground"), _("Visibility"), default=False) def update_param(self, curve): color = curve.errorPen.color() self.color = str(color.name()) self.alpha = color.alphaF() self.width = curve.errorPen.widthF() self.cap = curve.errorCap self.ontop = curve.errorOnTop def update_curve(self, curve): color = QColor(self.color) color.setAlphaF(self.alpha) curve.errorPen = QPen(color, self.width) curve.errorBrush = QBrush(color) curve.errorCap = self.cap curve.errorOnTop = self.ontop
# =================================================== # Image parameters # =================================================== def _create_choices(): choices = [] for cmap_name in get_colormap_list(): choices.append((cmap_name, cmap_name, build_icon_from_cmap_name)) return choices class BaseImageParam(DataSet): _multiselection = False label = StringItem(_("Image title"), default=_("Image")) \ .set_prop("display", hide=GetAttrProp("_multiselection")) alpha_mask = BoolItem(_("Use image level as alpha"), _("Alpha channel"), default=False) alpha = FloatItem(_("Global alpha"), default=1.0, min=0, max=1, help=_("Global alpha value")) _hide_colormap = False colormap = ImageChoiceItem(_("Colormap"), _create_choices(), default="jet" ).set_prop("display", hide=GetAttrProp("_hide_colormap")) interpolation = ChoiceItem(_("Interpolation"), [(0, _("None (nearest pixel)")), (1, _("Linear interpolation")), (2, _("2x2 antialiasing filter")), (3, _("3x3 antialiasing filter")), (5, _("5x5 antialiasing filter"))], default=0, help=_("Image interpolation type")) _formats = BeginGroup(_("Statistics string formatting")) xformat = StringItem(_("X-Axis"), default=r'%.1f') yformat = StringItem(_("Y-Axis"), default=r'%.1f') zformat = StringItem(_("Z-Axis"), default=r'%.1f') _end_formats = EndGroup(_("Statistics string formatting")) def update_param(self, image): self.label = to_text_string(image.title().text()) self.colormap = image.get_color_map_name() interpolation = image.get_interpolation() mode = interpolation[0] from guiqwt.image import INTERP_NEAREST, INTERP_LINEAR if mode == INTERP_NEAREST: self.interpolation = 0 elif mode == INTERP_LINEAR: self.interpolation = 1 else: size = interpolation[1].shape[0] self.interpolation = size def update_image(self, image): plot = image.plot() if plot is not None: plot.blockSignals(True) # Avoid unwanted calls of update_param # triggered by the setter methods below image.setTitle(self.label) image.set_color_map(self.colormap) size = self.interpolation from guiqwt.image import INTERP_NEAREST, INTERP_LINEAR, INTERP_AA if size == 0: mode = INTERP_NEAREST elif size == 1: mode = INTERP_LINEAR else: mode = INTERP_AA image.set_interpolation(mode, size) if plot is not None: plot.blockSignals(False) class QuadGridParam(DataSet): _multiselection = False label = StringItem(_("Image title"), default=_("Image")) \ .set_prop("display", hide=GetAttrProp("_multiselection")) alpha_mask = BoolItem(_("Use image level as alpha"), _("Alpha channel"), default=False) alpha = FloatItem(_("Global alpha"), default=1.0, min=0, max=1, help=_("Global alpha value")) _hide_colormap = False colormap = ImageChoiceItem(_("Colormap"), _create_choices(), default="jet" ).set_prop("display", hide=GetAttrProp("_hide_colormap")) interpolation = ChoiceItem(_("Interpolation"), [ (0, _("Quadrangle interpolation")), (1, _("Flat")), ], default=0, help=_("Image interpolation type, " "Flat mode use fixed u,v " "interpolation parameters")) uflat = FloatItem(_("Fixed U interpolation parameter"), default=0.5, min=0., max=1., help=_("For flat mode only")) vflat = FloatItem(_("Fixed V interpolation parameter"), default=0.5, min=0., max=1., help=_("For flat mode only")) grid = BoolItem(_("Show grid"), default=False) gridcolor = ColorItem(_("Grid lines color"), default="black") def update_param(self, image): self.label = to_text_string(image.title().text()) self.colormap = image.get_color_map_name() interp, uflat, vflat = image.interpolate self.interpolation = interp self.uflat = uflat self.vflat = vflat self.grid = image.grid def update_image(self, image): plot = image.plot() if plot is not None: plot.blockSignals(True) # Avoid unwanted calls of update_param # triggered by the setter methods below image.setTitle(self.label) image.set_color_map(self.colormap) image.interpolate = (self.interpolation, self.uflat, self.vflat) image.grid = self.grid # TODO : gridcolor if plot is not None: plot.blockSignals(False) class RawImageParam(BaseImageParam): _hide_background = False background = ColorItem(_("Background color"), default="#000000" ).set_prop("display", hide=GetAttrProp("_hide_background")) def update_param(self, image): super(RawImageParam, self).update_param(image) self.background = str(QColor(image.bg_qcolor).name()) def update_image(self, image): super(RawImageParam, self).update_image(image) plot = image.plot() if plot is not None: plot.blockSignals(True) # Avoid unwanted calls of update_param # triggered by the setter methods below image.set_background_color(self.background) if plot is not None: plot.blockSignals(False) class RawImageParam_MS(RawImageParam): _multiselection = True ItemParameters.register_multiselection(RawImageParam, RawImageParam_MS) class XYImageParam(RawImageParam): pass class XYImageParam_MS(XYImageParam): _multiselection = True ItemParameters.register_multiselection(XYImageParam, XYImageParam_MS)
[docs]class ImageParam(RawImageParam): _xdata = BeginGroup(_("Image placement along X-axis")) xmin = FloatItem(_("x|min"), default=None) xmax = FloatItem(_("x|max"), default=None) _end_xdata = EndGroup(_("Image placement along X-axis")) _ydata = BeginGroup(_("Image placement along Y-axis")) ymin = FloatItem(_("y|min"), default=None) ymax = FloatItem(_("y|max"), default=None) _end_ydata = EndGroup(_("Image placement along Y-axis")) def update_param(self, image): super(ImageParam, self).update_param(image) self.xmin = image.xmin if self.xmin is None: self.xmin = 0. self.ymin = image.ymin if self.ymin is None: self.ymin = 0. if image.is_empty(): shape = (0, 0) else: shape = image.data.shape self.xmax = image.xmax if self.xmax is None: self.xmax = float(shape[1]) self.ymax = image.ymax if self.ymax is None: self.ymax = float(shape[0]) def update_image(self, image): super(ImageParam, self).update_image(image) plot = image.plot() if plot is not None: plot.blockSignals(True) # Avoid unwanted calls of update_param # triggered by the setter methods below image.xmin = self.xmin image.xmax = self.xmax image.ymin = self.ymin image.ymax = self.ymax image.update_bounds() image.update_border() if plot is not None: plot.blockSignals(False)
class ImageParam_MS(ImageParam): _multiselection = True ItemParameters.register_multiselection(ImageParam, ImageParam_MS) class RGBImageParam(ImageParam): _hide_background = True _hide_colormap = True def update_image(self, image): super(RGBImageParam, self).update_image(image) plot = image.plot() if plot is not None: plot.blockSignals(True) # Avoid unwanted calls of update_param # triggered by the setter methods below image.recompute_alpha_channel() if plot is not None: plot.blockSignals(False) class RGBImageParam_MS(RGBImageParam): _multiselection = True ItemParameters.register_multiselection(RGBImageParam, RGBImageParam_MS) class MaskedImageParam(ImageParam): g_mask = BeginGroup(_("Mask")) filling_value = FloatItem(_("Filling value")) show_mask = BoolItem(_("Show image mask"), default=False) alpha_masked = FloatItem(_("Masked area alpha"), default=.7, min=0, max=1) alpha_unmasked = FloatItem(_("Unmasked area alpha"), default=0., min=0, max=1) _g_mask = EndGroup(_("Mask")) def update_image(self, image): super(MaskedImageParam, self).update_image(image) plot = image.plot() if plot is not None: plot.blockSignals(True) # Avoid unwanted calls of update_param # triggered by the setter methods below image.update_mask() if plot is not None: plot.blockSignals(False) class MaskedImageParam_MS(MaskedImageParam): _multiselection = True ItemParameters.register_multiselection(MaskedImageParam, MaskedImageParam_MS)
[docs]class ImageFilterParam(BaseImageParam): label = StringItem(_("Title"), default=_("Filter")) g1 = BeginGroup(_("Bounds")) xmin = FloatItem(_("x|min")) xmax = FloatItem(_("x|max")) ymin = FloatItem(_("y|min")) ymax = FloatItem(_("y|max")) _g1 = EndGroup("sub-group") use_source_cmap = BoolItem(_("Use image colormap and level"), _("Color map"), default=True) def update_param(self, obj): self.xmin, self.ymin, self.xmax, self.ymax = obj.border_rect.get_rect() self.use_source_cmap = obj.use_source_cmap super(ImageFilterParam, self).update_param(obj) def update_imagefilter(self, imagefilter): m, M = imagefilter.get_lut_range() set_range = False if not self.use_source_cmap and imagefilter.use_source_cmap: set_range = True imagefilter.use_source_cmap = self.use_source_cmap if set_range: imagefilter.set_lut_range([m, M]) self.update_image(imagefilter) imagefilter.border_rect.set_rect(self.xmin, self.ymin, self.xmax, self.ymax)
[docs]class TrImageParam(RawImageParam): _crop = BeginGroup(_("Crop") ).set_prop("display", hide=GetAttrProp("_multiselection")) crop_left = IntItem(_("Left"), default=0) crop_right = IntItem(_("Right"), default=0) crop_top = IntItem(_("Top"), default=0) crop_bottom = IntItem(_("Bottom"), default=0) _end_crop = EndGroup(_("Cropping") ).set_prop("display", hide=GetAttrProp("_multiselection")) _ps = BeginGroup(_("Pixel size") ).set_prop("display", hide=GetAttrProp("_multiselection")) dx = FloatItem(_("Width (dx)"), default=1.0) dy = FloatItem(_("Height (dy)"), default=1.0) _end_ps = EndGroup(_("Pixel size") ).set_prop("display", hide=GetAttrProp("_multiselection")) _pos = BeginGroup(_("Translate, rotate and flip")) pos_x0 = FloatItem(_("x<sub>CENTER</sub>"), default=0.0 ).set_prop("display", hide=GetAttrProp("_multiselection")) hflip = BoolItem(_("Flip horizontally"), default=False ).set_prop("display", col=1) pos_y0 = FloatItem(_("y<sub>CENTER</sub>"), default=0.0 ).set_prop("display", hide=GetAttrProp("_multiselection")) vflip = BoolItem(_("Flip vertically"), default=False ).set_prop("display", col=1) pos_angle = FloatItem(_("θ (°)"), default=0.0).set_prop("display", col=0) _end_pos = EndGroup(_("Translate, rotate and flip")) def update_param(self, image): super(TrImageParam, self).update_param(image) # we don't get crop info from the image because # its not easy to extract from the transform # and TrImageItem keeps it's crop information # directly in this DataSet def update_image(self, image): RawImageParam.update_image(self, image) plot = image.plot() if plot is not None: plot.blockSignals(True) # Avoid unwanted calls of update_param # triggered by the setter methods below image.set_transform(*self.get_transform()) if plot is not None: plot.blockSignals(False) def get_transform(self): return (self.pos_x0, self.pos_y0, self.pos_angle*np.pi/180, self.dx, self.dy, self.hflip, self.vflip) def set_transform(self, x0, y0, angle, dx=1.0, dy=1.0, hflip=False, vflip=False): self.pos_x0 = x0 self.pos_y0 = y0 self.pos_angle = angle*180/np.pi self.dx = dx self.dy = dy self.hflip = hflip self.vflip = vflip def set_crop(self, left, top, right, bottom): self.crop_left = left self.crop_right = right self.crop_top = top self.crop_bottom = bottom def get_crop(self): return (self.crop_left, self.crop_top, self.crop_right, self.crop_bottom)
class TrImageParam_MS(TrImageParam): _multiselection = True ItemParameters.register_multiselection(TrImageParam, TrImageParam_MS) # =================================================== # Histogram parameters # ===================================================
[docs]class HistogramParam(DataSet): n_bins = IntItem(_("Bins"), default=100, min=1, help=_("Number of bins")) logscale = BoolItem(_("logarithmic"), _("Y-axis scale"), default=False) def update_param(self, obj): self.n_bins = obj.get_bins() self.logscale = obj.get_logscale() def update_hist(self, hist): hist.set_bins(self.n_bins) hist.set_logscale(self.logscale)
# =================================================== # Histogram 2D parameters # ===================================================
[docs]class Histogram2DParam(BaseImageParam): """Histogram""" _multiselection = False label = StringItem(_("Title"), default=_("Histogram")) \ .set_prop("display", hide=GetAttrProp("_multiselection")) nx_bins = IntItem(_("X-axis bins"), default=100, min=1, help=_("Number of bins along x-axis")) ny_bins = IntItem(_("Y-axis bins"), default=100, min=1, help=_("Number of bins along y-axis")) logscale = BoolItem(_("logarithmic"), _("Z-axis scale"), default=False) computation = ChoiceItem(_("Computation"), [(-1, _("Bin count")), (0, _("Maximum value")), (1, _("Mininum value")), (2, _("Sum")), (3, _("Product")), (4, _("Average")), ], default=-1, help=_("Bin count : counts the number of points per bin,\n" "For max, min, sum, product, average, compute the " "function of a third parameter (one by default)")) auto_lut = BoolItem(_("Automatic LUT range"), default=True, help=_("Automatically adapt color scale " "when panning, zooming")) background = ColorItem(_("Background color"), default="transparent", help=_("Background color when no data is present")) def update_param(self, obj): super(Histogram2DParam, self).update_param(obj) self.logscale = obj.logscale self.nx_bins, self.ny_bins = obj.nx_bins, obj.ny_bins def update_histogram(self, histogram): histogram.logscale = int(self.logscale) histogram.set_background_color(self.background) histogram.set_bins(self.nx_bins, self.ny_bins) self.update_image(histogram)
class Histogram2DParam_MS(Histogram2DParam): _multiselection = True ItemParameters.register_multiselection(Histogram2DParam, Histogram2DParam_MS) # =================================================== # Shape parameters # ===================================================
[docs]class MarkerParam(DataSet): _styles = BeginTabGroup("Styles") #------------------------------------------------------------------ Line tab ___line = BeginGroup(_("Line")).set_prop("display", icon="dashdot.png") line = LineStyleItem(_("Line (not selected)")) sel_line = LineStyleItem(_("Line (selected)")) ___eline = EndGroup(_("Line")) #---------------------------------------------------------------- Symbol tab ___sym = BeginGroup(_("Symbol")).set_prop("display", icon="diamond.png") symbol = SymbolItem(_("Symbol (not selected)")) sel_symbol = SymbolItem(_("Symbol (selected)")) ___esym = EndGroup(_("Symbol")) #------------------------------------------------------------------ Text tab ___text = BeginGroup(_("Text")).set_prop("display", icon="font.png") text = TextStyleItem(_("Text (not selected)")) sel_text = TextStyleItem(_("Text (selected)")) ___etext = EndGroup(_("Text")) #----------------------------------------------------------------------- End _endstyles = EndTabGroup("Styles") markerstyle = ImageChoiceItem(_("Line style"), MARKERSTYLE_CHOICES, default="NoLine") spacing = IntItem(_("Spacing"), default=10, min=0) def update_param(self, obj): self.symbol.update_param(obj.symbol()) self.text.update_param(obj.label()) self.line.update_param(obj.linePen()) self.markerstyle = MARKERSTYLE_NAME[obj.lineStyle()] self.spacing = obj.spacing() def update_marker(self, obj): if obj.selected: line = self.sel_line symb = self.sel_symbol text = self.sel_text else: line = self.line symb = self.symbol text = self.text symb.update_symbol(obj) label = obj.label() text.update_text(label) obj.setLabel(label) obj.setLinePen(line.build_pen()) obj.setLineStyle(getattr(QwtPlotMarker, self.markerstyle)) obj.setSpacing(self.spacing) obj.update_label()
[docs] def set_markerstyle(self, style): """ Set marker line style style: * convenient values: '+', '-', '|' or None * `QwtPlotMarker.NoLine`, `QwtPlotMarker.Vertical`, ... """ self.markerstyle = MARKERSTYLES.get(style, style)
[docs]class ShapeParam(DataSet): label = StringItem(_("Title"), default="") _styles = BeginTabGroup("Styles") #------------------------------------------------------------------ Line tab ___line = BeginGroup(_("Line")).set_prop("display", icon="dashdot.png") line = LineStyleItem(_("Line (not selected)")) sel_line = LineStyleItem(_("Line (selected)")) ___eline = EndGroup(_("Line")) #---------------------------------------------------------------- Symbol tab ___sym = BeginGroup(_("Symbol")).set_prop("display", icon="diamond.png") symbol = SymbolItem(_("Symbol (not selected)")) sel_symbol = SymbolItem(_("Symbol (selected)")) ___esym = EndGroup(_("Symbol")) #------------------------------------------------------------------ Fill tab ___fill = BeginGroup(_("Fill pattern")).set_prop("display", icon="dense6pattern.png") fill = BrushStyleItem(_("Fill pattern (not selected)")) sel_fill = BrushStyleItem(_("Fill pattern (selected)")) ___efill = EndGroup(_("Fill pattern")) #----------------------------------------------------------------------- End _endstyles = EndTabGroup("Styles") readonly = BoolItem(_("Read-only shape"), default=False, help=_("Read-only shapes can't be removed from " "the item list panel")) private = BoolItem(_("Private shape"), default=False, help=_("Private shapes are not shown in " "the item list panel")).set_pos(col=1) def update_param(self, obj): self.label = to_text_string(obj.title().text()) self.line.update_param(obj.pen) self.symbol.update_param(obj.symbol) self.fill.update_param(obj.brush) self.sel_line.update_param(obj.sel_pen) self.sel_symbol.update_param(obj.sel_symbol) self.sel_fill.update_param(obj.sel_brush) self.readonly = obj.is_readonly() self.private = obj.is_private() def update_shape(self, obj): plot = obj.plot() if plot is not None: plot.blockSignals(True) # Avoid unwanted calls of update_param # triggered by the setter methods below obj.setTitle(self.label) obj.pen = self.line.build_pen() obj.symbol = self.symbol.build_symbol() obj.brush = self.fill.build_brush() obj.sel_pen = self.sel_line.build_pen() obj.sel_symbol = self.sel_symbol.build_symbol() obj.sel_brush = self.sel_fill.build_brush() obj.set_readonly(self.readonly) obj.set_private(self.private) if plot is not None: plot.blockSignals(False)
[docs]class AxesShapeParam(DataSet): arrow_angle = FloatItem(_("Arrow angle (°)"), min=0, max=90, nonzero=True) arrow_size = FloatItem(_("Arrow size (%)"), min=0, max=100, nonzero=True) _styles = BeginTabGroup("Styles") #------------------------------------------------------------------ Line tab ___line = BeginGroup(_("Line")).set_prop("display", icon="dashdot.png") xarrow_pen = LineStyleItem(_("Line (X-Axis)")) yarrow_pen = LineStyleItem(_("Line (Y-Axis)")) ___eline = EndGroup(_("Line")) #------------------------------------------------------------------ Fill tab ___fill = BeginGroup(_("Fill pattern")).set_prop("display", icon="dense6pattern.png") xarrow_brush = BrushStyleItem(_("Fill pattern (X-Axis)")) yarrow_brush = BrushStyleItem(_("Fill pattern (Y-Axis)")) ___efill = EndGroup(_("Fill pattern")) #----------------------------------------------------------------------- End _endstyles = EndTabGroup("Styles") def update_param(self, obj): self.arrow_angle = obj.arrow_angle self.arrow_size = obj.arrow_size self.xarrow_pen.update_param(obj.x_pen) self.yarrow_pen.update_param(obj.y_pen) self.xarrow_brush.update_param(obj.x_brush) self.yarrow_brush.update_param(obj.y_brush) def update_axes(self, obj): obj.arrow_angle = self.arrow_angle obj.arrow_size = self.arrow_size obj.x_pen = self.xarrow_pen.build_pen() obj.x_brush = self.xarrow_brush.build_brush() obj.y_pen = self.yarrow_pen.build_pen() obj.y_brush = self.yarrow_brush.build_brush()
[docs]class AnnotationParam(DataSet): show_label = BoolItem(_("Show annotation"), default=True) show_computations = BoolItem(_("Show informations on area " "covered by this shape"), default=True) title = StringItem(_("Title"), default="") subtitle = StringItem(_("Subtitle"), default="") format = StringItem(_("String formatting"), default="%.1f") uncertainty = FloatItem(_("Uncertainty"), default=0., min=0., max=1., help=_("Measurement relative uncertainty") ).set_pos(col=1) transform_matrix = FloatArrayItem(_("Transform matrix"), default=np.eye(3, dtype=float)) readonly = BoolItem(_("Read-only shape"), default=False, help=_("Read-only shapes can't be removed from " "the item list panel")) private = BoolItem(_("Private shape"), default=False, help=_("Private shapes are not shown in " "the item list panel")).set_pos(col=1) def update_param(self, obj): self.show_label = obj.is_label_visible() self.show_computations = obj.area_computations_visible self.title = to_text_string(obj.title().text()) self.readonly = obj.is_readonly() self.private = obj.is_private() def update_annotation(self, obj): plot = obj.plot() if plot is not None: plot.blockSignals(True) # Avoid unwanted calls of update_param # triggered by the setter methods below obj.setTitle(self.title) obj.set_label_visible(self.show_label) obj.area_computations_visible = self.show_computations obj.update_label() obj.set_readonly(self.readonly) obj.set_private(self.private) if plot is not None: plot.blockSignals(False)
# =================================================== # Range selection parameters # ===================================================
[docs]class RangeShapeParam(DataSet): _styles = BeginTabGroup("Styles") #------------------------------------------------------------------ Line tab ___line = BeginGroup(_("Line")).set_prop("display", icon="dashdot.png") line = LineStyleItem(_("Line (not selected)")) sel_line = LineStyleItem(_("Line (selected)")) ___eline = EndGroup(_("Line")) #---------------------------------------------------------------- Symbol tab ___symbol = BeginGroup(_("Symbol")).set_prop("display", icon="diamond.png") symbol = SymbolItem(_("Symbol (not selected)")) sel_symbol = SymbolItem(_("Symbol (selected)")) ___esymbol = EndGroup(_("Symbol")) #------------------------------------------------------------------ Fill tab ___fill = BeginGroup(_("Fill")).set_prop("display", icon="dense6pattern.png") fill = ColorItem(_("Fill color")) shade = FloatItem(_("Shade"), default = .05, min=0, max=1) ___efill = EndGroup(_("Fill")) #----------------------------------------------------------------------- End _endstyles = EndTabGroup("Styles") def update_param(self, range): self.line.update_param(range.pen) self.sel_line.update_param(range.sel_pen) self.fill = range.brush.color().name() self.shade = range.brush.color().alphaF() self.symbol.update_param(range.symbol) self.sel_symbol.update_param(range.sel_symbol) def update_range(self, range): range.pen = self.line.build_pen() range.sel_pen = self.sel_line.build_pen() col = QColor(self.fill) col.setAlphaF(self.shade) range.brush = QBrush(col) range.symbol = self.symbol.build_symbol() range.sel_symbol = self.sel_symbol.build_symbol()