ImportPlugins - veusz/veusz GitHub Wiki

Import plugins

Veusz supports user defined plugins for loading data from arbitrary files. If you have a special data format for loading then a plugin is a perfect way to get the data quickly into Veusz. To load the plugin, add it to the Plugins tab in the Preferences dialog box, giving the filename for the plugin. Alternatively, you can provide the --plugin command line option to load a plugin when starting Veusz.

A plugin consists of a class which inherits from veusz.plugins.ImportPlugin. For Veusz versions of 1.13 or earlier, an instance of this class should be appended to veusz.plugins.importpluginregistry, but this usage is deprecated. For Veusz versions of 1.14 or later, then the class itself should be added to the registry list.

The new class should redefine the members name (name of the plugin, shown in the import dialog), author and description. The most important member is doImport(self, params) which does the import and returns a list of datasets (ImportDataset1D, ImportDataset2D and ImportDatasetText objects):

class ImportDataset1D(object):
    """Return 1D dataset."""
    def __init__(self, name, data=None, serr=None, perr=None, nerr=None):
        """1D dataset
        name: name of dataset
        data: data in dataset: list of floats or numpy 1D array
        serr: (optional) symmetric errors on data: list or numpy array
        perr: (optional) positive errors on data: list or numpy array
        nerr: (optional) negative errors on data: list or numpy array

        If errors are returned for data implement serr or nerr and perr.
        nerr should be negative values if used.
        perr should be positive values if used.
        """

class ImportDataset2D(object):
    """Return 2D dataset."""
    def __init__(self, name, data, rangex=None, rangey=None):
        """2D dataset.
        name: name of dataset
        data: 2D numpy array of values or list of lists of floats
        rangex: optional tuple with X range of data (min, max)
        rangey: optional tuple with Y range of data (min, max)
        """

class ImportDatasetText(object):
    """Return a text dataset (only available in Veusz 1.9 or greater)."""
    def __init__(self, name, data):
        """A text dataset
        name: name of dataset
        data: data in dataset: list of strings
        """

In fact these are aliases to Dataset1D, Dataset2D and DatasetText classes (PluginDatasetTypes), which should be used with Veusz 1.9 or greater.

The parameters passed to doImport in params are the object:

class ImportPluginParams(object):
    """Parameters to plugin are passed in this object."""
    def __init__(self, filename, encoding, field_results):
        self.filename = filename
        self.encoding = encoding
        self.field_results = field_results

    def openFileWithEncoding(self):
        """Helper to open filename but respecting encoding."""

The attributes are filename (filename to import), encoding (character encoding to use for reading if appropriate) and field_results (dict of values from the fields of the plugin). params also includes a useful openFileWithEncoding method which returns a file object with reads text from the filename with the encoding requested by the user.

The class can also include a getPreview(self, params) member for returning a preview view of the file (by default the first 4kb of text). This should read the file in the parameters and return a tuple (text, ok), where text is the text to display and ok is a boolean saying whether the import should be allowed.

If the plugin wants to receive input from the user it can define a fields member which is a list of ImportField objects. There are various possible field types possible:

class Field(object):
    """A class to represent an input field on the dialog or command line."""
    def __init__(self, name, descr=None, default=None):
        """name: name of field
        descr: description to show to user
        default: default value."""

class FieldBool(ImportField):
    """A check box on the dialog."""

class FieldText(ImportField):
    """Text entry on the dialog."""

class FieldFloat(ImportField):
    """Enter a floating point number."""

class FieldCombo(ImportField):
    """Drop-down combobox on dialog."""
    def __init__(self, name, descr=None, default=None, items=(),
                 editable=True):
        """name: name of field
        descr: description to show to user
        default: default value
        items: items in drop-down box
        editable: whether user can enter their own value."""

The attribute name of Field objects must follow the http://docs.python.org/reference/lexical_analysis.html#identifiers for identifiers.

In versions of Veusz 1.9 or greater, this list is a lot longer; also, some options have been deprecated. See PluginFields.

Promotion

If the plugin is important, the plugin author may want it to occupy its own tab in the plugin dialog. If so, the plugin should set the attribute promote_tab to be the text label of the tab in the import data dialog box. This attribute is only used in Veusz 1.13 or greater.

File extensions

Veusz can automatically select the plugin in the import dialog box if the user selects a file with a supported file extension. If your plugin supports a particular file extension, set the attribute file_extensions to be a set of supported extensions. This attribute is only used in Veusz 1.13 or greater.

Example plugin

This is a plugin which reads unformatted numbers from a file. The user can give the name for the dataset (name field). There are also options to invert the input data (invert checkbox), multiply the values by a figure (mult float field) or subtract a value (subtract combo drop down list).

from veusz.plugins import *

class ImportPluginExample(ImportPlugin):
    """An example plugin for reading a set of unformatted numbers
    from a file."""

    name = "Example plugin"
    author = "Jeremy Sanders"
    description = "Reads a list of numbers in a text file"

    # Uncomment this line for the plugin to get its own tab
    #promote_tab='Example'

    file_extensions = set(['.example'])

    def __init__(self):
        ImportPlugin.__init__(self)
        self.fields = [
            ImportFieldText("name", descr="Dataset name", default="name"),
            ImportFieldCheck("invert", descr="invert values"),
            ImportFieldFloat("mult", descr="Multiplication factor", default=1),
            ImportFieldCombo("subtract", items=("0", "1", "2"),
                             editable=False, default="0")
            ]

    def doImport(self, params):
        """Actually import data
        params is a ImportPluginParams object.
        Return a list of ImportDataset1D, ImportDataset2D objects
        """
        f = params.openFileWithEncoding()
        data = []
        mult = params.field_results["mult"]
        sub = float(params.field_results["subtract"])
        if params.field_results["invert"]:
            mult *= -1
        for line in f:
            data += [float(x)*mult-sub for x in line.split()]

        return [ImportDataset1D(params.field_results["name"], data)]

# add the class to the registry. An instance also works, but is deprecated
importpluginregistry.append(ImportPluginExample)
⚠️ **GitHub.com Fallback** ⚠️