diff --git a/vcs/Canvas.py b/vcs/Canvas.py index 302aa244b..08b9bf482 100644 --- a/vcs/Canvas.py +++ b/vcs/Canvas.py @@ -1995,6 +1995,14 @@ def drawline(self, name=None, ltype='solid', width=1, color=241, # noqa drawline.__doc__ = drawline.__doc__ % (xmldocs.name, xmldocs.color, xmldocs.priority, xmldocs.viewport, xmldocs.worldcoordinate, xmldocs.x_y_coords, xmldocs.projection) + def createerrorbars(self, name=None, source='default', etype=None, color=None): + return vcs.createerrorbars(name, source, etype, color) + createerrorbars.__doc__ = vcs.manageElements.createerrorbars.__doc__ + + def geterrorbars(self, name='default', etype=None, color=None): + return vcs.geterrorbars(name, etype, color) + geterrorbars.__doc__ = vcs.manageElements.geterrorbars.__doc__ + def createmarker(self, name=None, source='default', mtype=None, # noqa size=None, color=None, priority=1, viewport=None, worldcoordinate=None, diff --git a/vcs/VCS_validation_functions.py b/vcs/VCS_validation_functions.py index 1adadb513..b2f9f603f 100644 --- a/vcs/VCS_validation_functions.py +++ b/vcs/VCS_validation_functions.py @@ -300,7 +300,9 @@ def checkMarker(self, name, value): 'triangle_left_fill', 'triangle_right_fill', 'square_fill', - 'hurricane'] + 'hurricane', + 'error_x', + 'error_y'] for i in range(103): oks.append('w%.2i' % i) for i in range(19): @@ -346,6 +348,10 @@ def checkMarker(self, name, value): value = 'square_fill' elif value in ('hurricane', 18): value = 'hurricane' + elif value in ('error_x', 19): + value = 'error_x' + elif value in ('error_y', 20): + value = 'error_y' elif isinstance(value, str) and value[0] == "w" and int(value[1:]) in range(103): value = value elif value in range(100, 203): @@ -376,6 +382,47 @@ def checkMarkersList(self, name, value): return hvalue +def checkErrorBars(self, name, value): + import queries + checkName(self, name, value) + if (queries.iserrorbars(value) != 1): + checkedRaise( + self, + value, + ValueError, + 'The ' + + name + + ' value must be of type \'vcs.errorbars.Te\'.' + + ' Instead it is %s' % + type(value)) + return value + + +def checkErrorBarsType(self, name, value): + checkName(self, name, value) + oks = [ + 'x', + 'y', + 'xy'] + if ((value in oks) or (value in range(0, 3))): + if value in ('x', 0): + value = 'x' + elif value in ('y', 0): + value = 'y' + elif value in ('xy', 0): + value = 'xy' + else: + checkedRaise( + self, + value, + ValueError, + 'The ' + + name + + ' value must be in : %s. Instead, it is %s' % + (oks, value)) + return value + + def checkListElements(self, name, value, function): checkName(self, name, value) if not isinstance(value, (list, tuple)): diff --git a/vcs/VTKPlots.py b/vcs/VTKPlots.py index d3970c3cb..c7dd36378 100644 --- a/vcs/VTKPlots.py +++ b/vcs/VTKPlots.py @@ -81,6 +81,7 @@ def __init__(self, canvas, renWin=None, debug=False, bg=None, geometry=None): 'vtk_backend_grid', # vtkGeoTransform used for geographic transformation 'vtk_backend_geo', + 'error' ] self.numberOfPlotCalls = 0 self.renderWindowSize = None @@ -722,9 +723,13 @@ def plot(self, data1, data2, template, gtype, gname, bg, *args, **kargs): create_renderer=create_renderer) create_renderer = False elif gtype == "marker": + error = None + if kargs.get("error", None) is not None: + error = kargs["error"] if gm.priority != 0: actors = vcs2vtk.prepMarker(self.renWin, gm, - cmap=self.canvas.colormap) + cmap=self.canvas.colormap, + error=error) returned["vtk_backend_marker_actors"] = actors create_renderer = True for g, gs, pd, act, geo in actors: diff --git a/vcs/__init__.py b/vcs/__init__.py index b115bce37..0cb52968f 100755 --- a/vcs/__init__.py +++ b/vcs/__init__.py @@ -125,6 +125,7 @@ class VCSDeprecationWarning(DeprecationWarning): elements["textcombined"] = {} elements["line"] = {} elements["marker"] = {} +elements["errorbars"] = {} elements["fillarea"] = {} elements["font"] = {} elements["fontNumber"] = {} @@ -240,6 +241,7 @@ class VCSDeprecationWarning(DeprecationWarning): vector.Gv("default") streamline.Gs("default") marker.Tm("default") +errorbars.Te("default") meshfill.Gfm("default") colormap.Cp("default") displayplot.Dp("default") diff --git a/vcs/errorbars.py b/vcs/errorbars.py new file mode 100644 index 000000000..dc16fde83 --- /dev/null +++ b/vcs/errorbars.py @@ -0,0 +1,248 @@ +# +# Errorbars (Te) module +############################################################################### +# # +# Module: errorbars (Te) module # +# # +# Copyright: 2000, Regents of the University of California # +# This software may not be distributed to others without # +# permission of the author. # +# # +# Author: PCMDI Software Team # +# Lawrence Livermore NationalLaboratory: # +# support@pcmdi.llnl.gov # +# # +# Description: Python command/1d wrapper for VCS's errorbars object # +# # +# Version: 1.0 # +# # +############################################################################### +# +# +# +import VCS_validation_functions +import vcs +import genutil +from xmldocs import scriptdocs, listdoc + + +def process_src(nm, code): + + # Takes VCS script code (string) as input and generates oneD gm from it + try: + gm = Te(nm) + except: + gm = vcs.elements["errorbars"][nm] + # process attributes with = as assignment + for att in ["type", "color"]: + i = code.find(" %s(" % att) + if i == -1: + i = code.find(",%s(" % att) + if i > -1: + v = genutil.get_parenthesis_content(code[i:]) + setattr(gm, att, eval(v)) + + +############################################################################### +# # +# Errorbars (Te) Class. # +# # +############################################################################### +class Te(vcs.bestMatch): + + """ + The Errorbars object allows the manipulation of errorbar type, size and + color index. + + This class is used to define an error bars for 1D plots in VCS, or it can be + used to change some or all of the error bar attributes in an existing plot. + + .. describe:: Useful functions: + + .. code-block:: python + + # VCS canvas Constructor + x = vcs.init() + # mock data + data = "-1 -2 -1.34 -2 -1.1 -12.2".split() + data = numpy.array(data, dtype=numpy.float) + data = MV2.array(data) + # mock errors + error = "0.2 0.1 0.1 0.3 0.4 0.1".split() + error = numpy.array(error, dtype=numpy.float) + # Create default error bars + errorbars = vcs.createerrorbars('eb') + # Create a yx 1D plot + yx = vcs.createyxvsx() + yx.errorbars = errorbars + # plot + x.plot(data, yx, error) + + .. describe:: Create a new instance of errorbars: + + .. code-block:: python + + # Copies content of 'old' to 'new' + eb = a.createerrorbars('new', 'old') + # Copies content of 'default' to 'new' + eb = a.createerrorbars('new') + + .. describe:: Modify an existing errorbars: + + .. code-block:: python + + eb = a.geterrorbars('eb') + + .. describe:: Overview of errorbars attributes: + + * List all the errorbars attribute values: + + .. code-block:: python + + eb.list() + # Range from 1 to 256 + eb.color = 100 + # One of "x", "y" or "xy" + eb.type = "y" + + * Specify the errorbars type: + + .. code-block:: python + + eb.type = 'x' + eb.type = 'y' + + .. pragma: skip-doctest + """ + __slots__ = [ + 'name', + 's_name', + 'color', + 'type', + '_name', + '_color', + '_type' + ] + + def _getname(self): + return self._name + + def _setname(self, value): + value = VCS_validation_functions.checkname(self, 'name', value) + if value is not None: + self._name = value + name = property(_getname, _setname) + + def _getcolor(self): + return self._color + + def _setcolor(self, value): + if isinstance(value, int): + value = [value, ] + if value is not None: + value = VCS_validation_functions.checkColorList( + self, + 'color', + value) + self._color = value + color = property(_getcolor, _setcolor) + + def _gettype(self): + return self._type + + def _settype(self, value): + if value is not None: + value = VCS_validation_functions.checkErrorBarsType( + self, + 'type', + value) + self._type = value + type = property(_gettype, _settype) + + def __init__(self, Te_name, Te_name_src='default'): + if (Te_name is None): + raise ValueError('Must provide an errorbar name.') + self._name = Te_name + self.s_name = 'Te' + if Te_name == "default": + self._type = "y" + self._color = [0, 0, 0, 100] + else: + if isinstance(Te_name_src, Te): + Te_name_src = Te_name_src.name + if Te_name_src not in vcs.elements["errorbars"]: + raise ValueError( + "The errorbars object '%s' does not exist" % + Te_name_src) + src = vcs.elements["errorbars"][Te_name_src] + for att in ['type', 'color']: + setattr(self, att, getattr(src, att)) + # Ok now we need to stick it in the elements + vcs.elements["errorbars"][Te_name] = self + + def list(self): + if (self.name == '__removed_from_VCS__'): + raise ValueError('This instance has been removed from VCS.') + print "---------- ErrorBars (Te) member (attribute) listings ----------" + print "secondary method =", self.s_name + print "name =", self.name + print "type =", self.type + print "color =", self.color + list.__doc__ = listdoc.format(name="errorbars", parent="") + + def script(self, script_filename=None, mode=None): + if (script_filename is None): + raise ValueError( + 'Error - Must provide an output script file name.') + + if (mode is None): + mode = 'a' + elif (mode not in ('w', 'a')): + raise ValueError( + 'Error - Mode can only be "w" for replace or "a" for append.') + + # By default, save file in json + scr_type = script_filename.split(".") + if len(scr_type) == 1 or len(scr_type[-1]) > 5: + scr_type = "json" + if script_filename != "initial.attributes": + script_filename += ".json" + else: + scr_type = scr_type[-1] + if scr_type == '.scr': + raise vcs.VCSDeprecationWarning("scr script are no longer generated") + elif scr_type == "py": + mode = mode + '+' + py_type = script_filename[ + len(script_filename) - + 3:len(script_filename)] + if (py_type != '.py'): + script_filename = script_filename + '.py' + + # Write to file + fp = open(script_filename, mode) + if (fp.tell() == 0): # Must be a new file, so include below + fp.write("#####################################\n") + fp.write("# #\n") + fp.write("# Import and Initialize VCS #\n") + fp.write("# #\n") + fp.write("#############################\n") + fp.write("import vcs\n") + fp.write("v=vcs.init()\n\n") + + unique_name = '__Te__' + self.name + fp.write("#----------Errorbars (Te) member (attribute) listings ----------\n") + fp.write("tm_list=v.listelements('errorbars')\n") + fp.write("if ('%s' in tm_list):\n" % self.name) + fp.write(" %s = v.geterrorbars('%s')\n" % (unique_name, self.name)) + fp.write("else:\n") + fp.write(" %s = v.createerrorbars('%s')\n" % (unique_name, self.name)) + fp.write("%s.type = %s\n" % (unique_name, self.type)) + fp.write("%s.color = %s\n\n" % (unique_name, self.color)) + else: + # Json type + mode += "+" + f = open(script_filename, mode) + vcs.utils.dumpToJson(self, f) + f.close() + script.__doc__ = scriptdocs['errorbars'] diff --git a/vcs/manageElements.py b/vcs/manageElements.py index f0996ba3c..396e6e266 100644 --- a/vcs/manageElements.py +++ b/vcs/manageElements.py @@ -12,28 +12,29 @@ .. pragma: skip-doctest """ -import vcs +from error import vcsError import boxfill -import meshfill -import isofill -import isoline -import unified1D -import template -import projection import colormap +import dv3d +import errorbars import fillarea -import marker +import isofill +import isoline import line -import texttable -import textorientation +import marker +import meshfill +import projection +import random +import streamline +import template import textcombined +import textorientation +import texttable +import unified1D +import vcs import vector -import streamline -import xmldocs -import random -from error import vcsError import warnings -import dv3d +import xmldocs def check_name_source(name, source, typ): @@ -1016,6 +1017,72 @@ def getmarker(name='default', mtype=None, size=None, color=None, getmarker.__doc__ = getmarker.__doc__ % xmldocs.get_docs['marker'] # noqa +def createerrorbars(name=None, source='default', + etype='y', color=None): + """%s + + :param name: Name of created object + :type name: `str`_ + + :param source: An errorbars object, or string name of the errorbars + :type source: `str`_ + + :param mtype: Specifies the type of errorbars, i.e. "x", "y" or "xy" + :type mtype: `str`_ + + :param color: A color name from the `X11 Color Names list `_, + or an integer value from 0-255, or an RGB/RGBA tuple/list (e.g. (0,100,0), (100,100,0,50)) + :type color: `str`_ or int + + :returns: A secondary errorbars method + :rtype: vcs.errorbars.Te + """ + name, source = check_name_source(name, source, 'errorbars') + + eb = errorbars.Te(name, source) + if (etype is not None): + eb.type = etype + if (color is not None): + eb.color = color + return eb +createerrorbars.__doc__ = createerrorbars.__doc__ % xmldocs.create_docs['errorbars'] # noqa + + +def geterrorbars(name='default', etype=None, color=None): + """%s + + :param name: Name of created object + :type name: `str`_ + + :param source: An errorbars object, or string name of the errorbars + :type source: `str`_ + + :param mtype: Specifies the type of errorbars, i.e. "x", "y" or "xy" + :type mtype: `str`_ + + :param color: A color name from the `X11 Color Names list `_, + or an integer value from 0-255, or an RGB/RGBA tuple/list (e.g. (0,100,0), (100,100,0,50)) + :type color: `str`_ or int + + :returns: A secondary errorbars method + :rtype: vcs.errorbars.Te + """ + + # Check to make sure the argument passed in is a STRING + if not isinstance(name, str): + raise vcsError('The argument must be a string.') + + if name not in vcs.elements["errorbars"]: + raise ValueError("The errorbars object '%s' does not exists") + eb = vcs.elements["errorbars"][name] + if (etype is not None) and (eb.name != "default"): + eb.type = etype + if (color is not None) and (eb.name != "default"): + eb.color = color + return eb +geterrorbars.__doc__ = geterrorbars.__doc__ % xmldocs.get_docs['errorbars'] # noqa + + def createfillarea(name=None, source='default', style=None, index=None, color=None, priority=None, viewport=None, worldcoordinate=None, @@ -1770,6 +1837,10 @@ def removeTm(obj): return removeG(obj, "marker") +def remoteTe(obj): + return removeG(obj, "errorbars") + + def removeTf(obj): return removeG(obj, "fillarea") @@ -1864,6 +1935,8 @@ def removeobject(obj): msg = vcs.removeTl(obj.name) elif (obj.s_name == 'Tm'): msg = vcs.removeTm(obj.name) + elif (obj.s_name == 'Te'): + msg = vcs.removeTe(obj.name) elif (obj.s_name == 'Tf'): msg = vcs.removeTf(obj.name) elif (obj.s_name == 'Tt'): diff --git a/vcs/queries.py b/vcs/queries.py index d7566d650..e8b377314 100644 --- a/vcs/queries.py +++ b/vcs/queries.py @@ -42,6 +42,7 @@ import vector import streamline import line +import errorbars import marker import fillarea import texttable @@ -258,6 +259,8 @@ def issecondaryobject(sobj): 9.) projections + 10.) errorbars: errorbars type, color + :Example: .. doctest:: queries_issecondary @@ -289,7 +292,7 @@ def issecondaryobject(sobj): return 1 elif (isinstance(sobj, textcombined.Tc)): return 1 - elif (isinstance(sobj, marker.Tm)): + elif (isinstance(sobj, errorbars.Te)): return 1 elif (isinstance(sobj, projection.Proj)): return 1 @@ -435,6 +438,14 @@ def ismarker(obj): ismarker.__doc__ = xmldocs.is_docs['marker'] # noqa +def iserrorbars(obj): + if (isinstance(obj, errorbars.Te)): + return 1 + else: + return 0 +iserrorbars.__doc__ = xmldocs.is_docs['errorbars'] # noqa + + def isfillarea(obj): if (isinstance(obj, fillarea.Tf)): return 1 diff --git a/vcs/unified1D.py b/vcs/unified1D.py index ea72694ef..8e5a23597 100644 --- a/vcs/unified1D.py +++ b/vcs/unified1D.py @@ -64,6 +64,8 @@ def process_src(nm, code, typ): nm = "marker" elif nm == "datawc_tunits": nm = "datawc_timeunits" + elif nm == "Te": + nm = "errorbars" try: # int will be converted setattr(gm, nm, int(sp[1])) @@ -320,7 +322,9 @@ class G1d(vcs.bestMatch): %s %s %s - """ % (xmldocs.graphics_method_core, xmldocs.xaxisconvert, xmldocs.linedoc, xmldocs.markerdoc) + %s + """ % (xmldocs.graphics_method_core, xmldocs.xaxisconvert, xmldocs.linedoc, + xmldocs.markerdoc, xmldocs.errorbarsdoc) colormap = VCS_validation_functions.colormap __slots__ = [ '__doc__', @@ -334,6 +338,7 @@ class G1d(vcs.bestMatch): 'linecolor', 'linetype', 'linewidth', + 'errorbars', 'marker', 'markersize', 'markercolor', @@ -360,6 +365,7 @@ class G1d(vcs.bestMatch): '_linecolor', '_linetype', '_linewidth', + '_errorbars', '_marker', '_markersize', '_markercolor', @@ -624,6 +630,15 @@ def setLineAttributes(self, line): ''' vcs.setLineAttributes(self, line) + def _geterrorbars(self): + return self._errorbars + + def _seterrorbars(self, value): + if value is not None: + value = VCS_validation_functions.checkErrorBars(self, 'errorbars', value) + self._errorbars = value + errorbars = property(_geterrorbars, _seterrorbars) + def _getmarker(self): return self._marker @@ -723,6 +738,7 @@ def __init__(self, name, name_src='default'): self._linetype = 'solid' self._linecolor = (0.0, 0.0, 0.0, 100.0) self._linewidth = 1 + self._errorbars = None self._marker = 'dot' self._markercolor = (0.0, 0.0, 0.0, 100.0) self._markersize = 1 @@ -739,7 +755,8 @@ def __init__(self, name, name_src='default'): src = vcs.elements["1d"][name_src] for att in ['projection', 'colormap', 'xticlabels1', 'xticlabels2', 'xmtics1', 'xmtics2', 'yticlabels1', 'yticlabels2', 'ymtics1', 'ymtics2', 'datawc_y1', 'datawc_y2', 'datawc_x1', - 'datawc_x2', 'xaxisconvert', 'yaxisconvert', 'linetype', 'linecolor', 'linewidth', 'marker', + 'datawc_x2', 'xaxisconvert', 'yaxisconvert', 'linetype', + 'linecolor', 'linewidth', 'errorbars', 'marker', 'markercolor', 'markersize', 'datawc_timeunits', 'datawc_calendar', 'smooth', 'flip']: setattr(self, att, getattr(src, att)) # Ok now we need to stick in the elements @@ -930,6 +947,10 @@ def script(self, script_filename, mode='a'): fp.write("%s.markercolor = %s\n" % (unique_name, self.markercolor)) fp.write("%s.markersize = %s\n\n" % (unique_name, self.markersize)) fp.write("%s.flip = %s\n\n" % (unique_name, repr(self.flip))) + if self.errorbars is not None: + fp.write("%s.errorbars = %s\n\n" % (unique_name, repr(self.errorbars))) + else: + fp.write("%s.errorbars = %s\n\n" % (unique_name, self.errorbars)) if self.colormap is not None: fp.write("%s.colormap = %s\n\n" % (unique_name, repr(self.colormap))) else: diff --git a/vcs/utils.py b/vcs/utils.py index c76124b38..567cfec7d 100644 --- a/vcs/utils.py +++ b/vcs/utils.py @@ -12,31 +12,32 @@ .. _file: https://docs.python.org/2/library/functions.html?highlight=open#file """ # Adapted for numpy/ma/cdms2 by convertcdms.py -import numpy -import cdtime -import warnings -import vcs import boxfill +import cdms2 +import cdtime +import colormap +import errorbars +import fillarea +import genutil import isofill import isoline -import taylor +import json +import line +import marker +import numpy +import os import projection -import fillarea +import struct +import taylor +import tempfile import template -import texttable import textorientation -import line +import texttable import unified1D +import vcs import vector -import marker -import colormap -import json -import os -import tempfile -import cdms2 -import genutil import vtk -import struct +import warnings try: import vcsaddons hasVCSAddons = True @@ -508,6 +509,8 @@ def process_src_element(code): vector.process_src(nm, code) elif typ == "Tm": marker.process_src(nm, code) + elif typ == "Te": + errorbars.process_src(nm, code) elif typ == "C": colormap.process_src(nm, code) except Exception as err: @@ -986,6 +989,7 @@ def scriptrun(script): "Tt": "texttable", "To": "textorientation", "Tm": "marker", + "Te": "errorbars", "Tl": "line", "Gf3Dscalar": "3d_scalar", "Gf3DDualScalar": "3d_dual_scalar", diff --git a/vcs/vcs2vtk.py b/vcs/vcs2vtk.py index e0ef9a7bf..044bbc9c5 100644 --- a/vcs/vcs2vtk.py +++ b/vcs/vcs2vtk.py @@ -1647,6 +1647,52 @@ def prepGlyph(g, marker, index=0): pd.SetPolys(polys) pd.SetLines(lines) g.SetSourceData(pd) + elif t == "error_x": + # Points + pts = vtk.vtkPoints() + pts.SetNumberOfPoints(6) + pts.SetPoint(0, -0.5 * s, 0.0, 0.0) + pts.SetPoint(1, 0.5 * s, 0.0, 0.0) + pts.SetPoint(2, -0.5 * s, -0.1 * s, 0.0) + pts.SetPoint(3, -0.5 * s, 0.1 * s, 0.0) + pts.SetPoint(4, 0.5 * s, -0.1 * s, 0.0) + pts.SetPoint(5, 0.5 * s, 0.1 * s, 0.0) + # Lines + lines = vtk.vtkCellArray() + for i in range(3): + line = vtk.vtkLine() + line.GetPointIds().SetId(0, 2 * i) + line.GetPointIds().SetId(1, 2 * i + 1) + lines.InsertNextCell(line) + geo, pts = project(pts, marker.projection, marker.worldcoordinate) + # Add them together to a polydata + pd = vtk.vtkPolyData() + pd.SetPoints(pts) + pd.SetLines(lines) + g.SetSourceData(pd) + elif t == "error_y": + # Points + pts = vtk.vtkPoints() + pts.SetNumberOfPoints(6) + pts.SetPoint(0, 0.0, -0.5 * s, 0.0) + pts.SetPoint(1, 0.0, 0.5 * s, 0.0) + pts.SetPoint(2, -0.1 * s, -0.5 * s, 0.0) + pts.SetPoint(3, 0.1 * s, -0.5 * s, 0.0) + pts.SetPoint(4, -0.1 * s, 0.5 * s, 0.0) + pts.SetPoint(5, 0.1 * s, 0.5 * s, 0.0) + # Lines + lines = vtk.vtkCellArray() + for i in range(3): + line = vtk.vtkLine() + line.GetPointIds().SetId(0, 2 * i) + line.GetPointIds().SetId(1, 2 * i + 1) + lines.InsertNextCell(line) + geo, pts = project(pts, marker.projection, marker.worldcoordinate) + # Add them together to a polydata + pd = vtk.vtkPolyData() + pd.SetPoints(pts) + pd.SetLines(lines) + g.SetSourceData(pd) else: warnings.warn("unknown marker type: %s, using dot" % t) gs.SetGlyphTypeToCircle() @@ -1700,7 +1746,7 @@ def scaleMarkerGlyph(g, gs, pd, a): g.SetSourceConnection(glyphFixer.GetOutputPort()) -def prepMarker(renWin, marker, cmap=None): +def prepMarker(renWin, marker, cmap=None, error=None): n = prepPrimitive(marker) if n == 0: return [] @@ -1726,6 +1772,19 @@ def prepMarker(renWin, marker, cmap=None): gs, pd = prepGlyph(g, marker, index=i) g.SetInputData(markers) + # Set scalars if errorbars + if marker.type[i] in ['error_x', 'error_y'] and error is not None: + error += [0] * (N - len(error)) + err = vtk.vtkFloatArray() + err.SetName("Error") + err.SetNumberOfComponents(1) + err.SetNumberOfTuples(N) + for x in range(0, N): + err.SetTuple1(x, error[x]) + markers.GetPointData().SetScalars(err) + g.SetScaleModeToScaleByScalar() + g.SetColorModeToColorByScalar() + a = vtk.vtkActor() m = vtk.vtkPolyDataMapper() m.SetInputConnection(g.GetOutputPort()) diff --git a/vcs/vcsvtk/pipeline1d.py b/vcs/vcsvtk/pipeline1d.py index 7c3af7b6c..db4029c32 100644 --- a/vcs/vcsvtk/pipeline1d.py +++ b/vcs/vcsvtk/pipeline1d.py @@ -95,13 +95,30 @@ def plot(self, data1, data2, tmpl, grid, transform, **kargs): m._y = l.y m._viewport = l.viewport m._worldcoordinate = l.worldcoordinate + err_marker = None + if 'error' in kargs and kargs['error'] is not None: + errorbars = self._gm.errorbars + if errorbars is None: + errorbars = self._context().canvas.createerrorbars() + err_marker = self._context().canvas.createmarker() + err_marker.type = "error_%s" % errorbars.type + err_marker.color = [errorbars.color, ] + if self._gm.markersize > 0: + err_marker.size = self._gm.markersize + err_marker._x = l.x + err_marker._y = l.y + err_marker._viewport = l.viewport + err_marker._worldcoordinate = l.worldcoordinate if not (Y[:].min() > max(y1, y2) or Y[:].max() < min(y1, y2) or X[:].min() > max(x1, x2) or X[:].max() < min(x1, x2)): if l.priority > 0: self._context().canvas.plot(l, donotstoredisplay=True) - if self._gm.marker is not None and m.priority > 0: - self._context().canvas.plot(m, donotstoredisplay=True) + # if self._gm.marker is not None and m.priority > 0: + # self._context().canvas.plot(m, donotstoredisplay=True) + if err_marker is not None: + self._context().canvas.plot(err_marker, donotstoredisplay=True, + error=kargs['error']) ren2 = self._context().createRenderer() self._context().setLayer(ren2, l.priority) diff --git a/vcs/xmldocs.py b/vcs/xmldocs.py index 09c38b25e..241a0458d 100644 --- a/vcs/xmldocs.py +++ b/vcs/xmldocs.py @@ -422,7 +422,7 @@ def populate_docstrings(type_dict, target_dict, docstring, method): elif obj_name == '1d': d['sp_parent'] = "'default'" else: - sp_parent = 'default_'+obj_name+'_' + sp_parent = 'default_' + obj_name + '_' d['sp_parent'] = "'%s'" % sp_parent d['parent'] = d['sp_parent'] # From here to the end of the inner for loop is intended to be a section for specific use-cases for the template @@ -722,6 +722,14 @@ def populate_docstrings(type_dict, target_dict, docstring, method): "slabs": 0, "title": True, }, + "errorbars": { + "callable": False, + "parent": "default", + "parent2": "y", + "rtype": "vcs.errorbars.Te", + "slabs": 0, + "title": True, + }, "colormap": { "callable": False, "parent": "default", @@ -772,8 +780,8 @@ def populate_docstrings(type_dict, target_dict, docstring, method): # need this are the 1d family of objects and textcombined objects. If the object does have a sensible default, # (e.g. getboxfill()) this key should be an empty string. When providing a string to 'sp_parent', it should be # of format "'blah'" or '"blah"', and if multiple arguments are needed, they should be provided ('"blah", "blah"') -# 'tc' : no textcombined objects exist by default in VCS, so this key is for an entry that will create one when -# it is needed for an example. All other times, it will be an empty string. +# 'tc' : no textcombined objects exist by default in VCS, so this key is +# for an entry that will create one # it is needed for an example. All other times, it will be an empty string. # 'example' : this should be filled in with code examples in doctest format. Maintain indentation with the origin # docstring. Most of the time, this means 3 indents (12 spaces) from the left side is where all your doctest # lines should start. Look above, in populate_docstrings() to see what I'm tlaking about. @@ -1100,6 +1108,14 @@ def populate_docstrings(type_dict, target_dict, docstring, method): size of markers """ +errorbarsdoc = """ + Sets the error bar properties of the object. + + .. py:attribute:: errorbars (vcs.errorbars.Te) + + errorbars properties + + """ # noqa color_one_two_doc = """ .. py:attribute:: color_1 (float)