Skip to content
Mikhael-Danilov edited this page Jun 20, 2019 · 3 revisions

Embedding Veusz in Python programs

Veusz can be used as a Python module for plotting data. There are two ways to use the module: (1) with an older path-based Veusz commands, used in Veusz saved document files or (2) using an object-oriented interface. With the old style method the user uses a unix-path inspired API to navigate the widget tree and add or manipulate widgets. With the new style interface, the user navigates the tree with attributes of the Root object to access Nodes. The new interface is likely to be easier to use unless you are directly translating saved files.

Older path-based interface

"""An example embedding program. Veusz needs to be installed into
the Python path for this to work (use setup.py)

This animates a sin plot, then finishes
"""

import time
import numpy
import veusz.embed as veusz

# construct a Veusz embedded window
# many of these can be opened at any time
g = veusz.Embedded('window title')
g.EnableToolbar()

# construct the plot
g.To( g.Add('page') )
g.To( g.Add('graph') )
g.Add('xy', marker='tiehorz', MarkerFill__color='green')

# this stops intelligent axis extending
g.Set('x/autoExtend', False)
g.Set('x/autoExtendZero', False)

# zoom out
g.Zoom(0.8)

# loop, changing the values of the x and y datasets
for i in range(10):
    x = numpy.arange(0+i/2., 7.+i/2., 0.05)
    y = numpy.sin(x)
    g.SetData('x', x)
    g.SetData('y', y)

    # wait to animate the graph
    time.sleep(2)

# let the user see the final result
print "Waiting for 10 seconds"
time.sleep(10)
print "Done!"

# close the window (this is not strictly necessary)
g.Close()

The embed interface has the methods listed in the command line interface listed in the Veusz manual https://veusz.github.io/docs/manual

Multiple Windows are supported by creating more than one Embedded object. Other useful methods include:

  • WaitForClose() - wait until window has closed
  • GetClick() - return a list of (axis, value) tuples where the user clicks on a graph
  • ResizeWndow(width, height) - resize window to be width x height pixels
  • SetUpdateInterval(interval) - set update interval in ms or 0 to disable
  • MoveToPage(page) - display page given (starting from 1)
  • IsClosed() - has the page been closed
  • Zoom(factor) - set zoom level (float) or 'page', 'width', 'height'
  • Close() - close window
  • SetAntiAliasing(enable) - enable or disable antialiasing
  • EnableToolbar(enable=True) - enable plot toolbar
  • StartSecondView(name='Veusz') - start a second view onto the document of the current Embedded object. Returns a new Embedded object.

New-style object interface

In versions of Veusz >1.8 is a new style of object interface, which makes it easier to construct the widget tree. Each widget, group of settings or setting is stored as a Node object, or its subclass, in a tree. The root document widget can be accessed with the Root object. The dot operator "." finds children inside other nodes. In Veusz some widgets can contain other widgets (Root, pages, graphs, grids). Widgets contain setting nodes, accessed as attributes. Widgets can also contain groups of settings, again accessed as attributes.

An example tree for a document (not complete) might look like this

Root
\-- page1                     (page widget)
    \-- graph1                (graph widget)
        \--  x                (axis widget)
        \--  y                (axis widget)
        \-- function          (function widget)
    \-- grid1                 (grid widget)
        \-- graph2            (graph widget)
            \-- xy1           (xy widget)
                \-- xData     (setting)
                \-- yData     (setting)
                \-- PlotLine  (setting group)
                    \-- width (setting)
                    ...
                ...
            \-- x             (axis widget)
            \-- y             (axis widget)
        \-- graph3            (graph widget)
            \-- contour1      (contour widget)
            \-- x             (axis widget)
            \-- y             (axis widget)

Here the user could access the xData setting node of the xy1 widget using Root.page1.graph2.xy1.xData. To actually read or modify the value of a setting, you should get or set the val property of the setting node. The line width could be changed like this

graph = embed.Root.page1.graph2
graph.xy1.PlotLine.width.val = '2pt'

For instance, this constructs a simple x-squared plot which changes to x-cubed:

import veusz.embed as veusz
import time

#  open a new window and return a new Embedded object
embed = veusz.Embedded('window title')
#  make a new page, but adding a page widget to the root widget
page = embed.Root.Add('page')
#  add a new graph widget to the page
graph = page.Add('graph')
#  add a function widget to the graph. The Add() method can take a list of settings
#  to set after widget creation. Here, "function='x**2'" is equivalent to
#  function.function.val = 'x**2'
function = graph.Add('function', function='x**2')

time.sleep(2)
function.function.val = 'x**3'
#  this is the same if the widgets have the default names
embed.Root.page1.graph1.function1.function.val = 'x**3'

If the document contains a page called "page1" then Root.page1 is the object representing the page. Similarly, Root.page1.graph1 is a graph called graph1 in the page. You can also use dictionary-style indexing to get child widgets, e.g. Root['page1']['graph1']. This style is easier to use if the names of widgets contain spaces or if widget names shadow methods or properties of the Node object, i.e. if you do not control the widget names.

Widget nodes can contain as children other widgets, groups of settings, or settings. Groups of settings can contain child settings. Settings cannot contain other nodes. Here are the useful operations of Nodes:

class Node(object):
  """properties:
    path - return path to object in document, e.g. /page1/graph1/function1
    type - type of node: "widget", "settinggroup" or "setting"
    name - name of this node, e.g. "graph1"
    children - a generator to return all the child Nodes of this Node, e.g.
      for c in Root.children:
        print c.path
    children_widgets - generator to return child widget Nodes of this Node
    children_settinggroups - generator for child setting groups of this Node
    children_settings - a generator to get the child settings
    childnames - return a list of the names of the children of this Node
    childnames_widgets - return a list of the names of the child widgets
    childnames_settinggroups - return a list of the names of the setting groups
    childnames_settings - return a list of the names of the settings
    parent - return the Node corresponding to the parent widget of this Node

    __getattr__ - get a child Node with name given, e.g. Root.page1
    __getitem__ - get a child Node with name given, e.g. Root['page1']
  """

  def fromPath(self, path):
     """Returns a new Node corresponding to the path given, e.g. '/page1/graph1'"""

class SettingNode(Node):
    """A node which corresponds to a setting. Extra properties:
    val - get or set the setting value corresponding to this value, e.g.
     Root.page1.graph1.leftMargin.val = '2cm'
    """

class SettingGroupNode(Node):
    """A node corresponding to a setting group. No extra properties."""

class WidgetNode(Node):
    """A node corresponding to a widget.

       property:
         widgettype - get Veusz type of widget

       Methods are below."""

    def WalkWidgets(self, widgettype=None):
        """Generator to walk widget tree and get widgets below this
        WidgetNode of type given.

        widgettype is a Veusz widget type name or None to get all
        widgets."""

    def Add(self, widgettype, *args, **args_opt):
        """Add a widget of the type given, returning the Node instance.
        """

    def Rename(self, newname):
        """Renames widget to name given.
        Existing Nodes corresponding to children are no longer valid."""

    def Action(self, action):
        """Applies action on widget."""

    def Remove(self):
        """Removes a widget and its children.
        Existing Nodes corresponding to children are no longer valid."""

Note that Nodes are temporary objects which are created on the fly. A real widget in Veusz can have several different WidgetNode objects. The operators == and != can test whether a Node points to the same widget, setting or setting group.

Here is an example to set all functions in the document to be x**2:

for n in Root.WalkWidgets(widgettype='function'):
  n.function.val = 'x**2'

Translating old to new style

Here is an example how you might translate the old to new style interface (this is taken from the sin.vsz example)

# old (from saved document file)
Add('page', name='page1')
To('page1')
Add('graph', name='graph1', autoadd=False)
To('graph1')
Add('axis', name='x')
To('x')
Set('label', '\\italic{x}')
To('..')
Add('axis', name='y')
To('y')
Set('label', 'sin \\italic{x}')
Set('direction', 'vertical')
To('..')
Add('xy', name='xy1')
To('xy1')
Set('MarkerFill/color', 'cyan')
To('..')
Add('function', name='function1')
To('function1')
Set('function', 'sin(x)')
Set('Line/color', 'red')
To('..')
To('..')
To('..')
# new (in python)
import veusz.embed
embed = veusz.embed.Embedded('window title')

page = embed.Root.Add('page')
# note: autoAdd=False stops graph automatically adding own axes (used in saved files)
graph = page.Add('graph', autoadd=False)
x = graph.Add('axis', name='x')
x.label.val = '\\italic{x}'
y = graph.Add('axis', name='y')
y.direction.val = 'vertical'
xy = graph.Add('xy')
xy.MarkerFill.color.val = 'cyan'
func = graph.Add('function')
func.function.val = 'sin(x)'
func.Line.color.val = 'red'