File: line_plot.py

package info (click to toggle)
python-vispy 0.15.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 8,868 kB
  • sloc: python: 59,799; javascript: 6,800; makefile: 69; sh: 6
file content (135 lines) | stat: -rw-r--r-- 4,882 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# -*- coding: utf-8 -*-
# Copyright (c) Vispy Development Team. All Rights Reserved.
# Distributed under the (new) BSD License. See LICENSE.txt for more info.

import numpy as np

from .line import LineVisual
from .markers import MarkersVisual
from .visual import CompoundVisual


class LinePlotVisual(CompoundVisual):
    """Visual displaying a plot line with optional markers.

    Parameters
    ----------
    data : array-like
        Arguments can be passed as ``(Y,)``, ``(X, Y)``, ``(X, Y, Z)`` or
        ``np.array((X, Y))``, ``np.array((X, Y, Z))``.
    color : instance of Color
        Color of the line.
    symbol : str
        Marker symbol to use.
    line_kind : str
        Kind of line to draw. For now, only solid lines (``'-'``)
        are supported.
    width : float
        Line width.
    marker_size : float
        Marker size. If `size == 0` markers will not be shown.
    edge_color : instance of Color
        Color of the marker edge.
    face_color : instance of Color
        Color of the marker face.
    edge_width : float
        Edge width of the marker.
    connect : str | array
        See LineVisual.
    **kwargs : keyword arguments
        Argements to pass to the super class.

    Examples
    --------
    All of these syntaxes will work:

        >>> LinePlotVisual(y_vals)
        >>> LinePlotVisual(x_vals, y_vals)
        >>> LinePlotVisual(xy_vals)

    See also
    --------
    LineVisual, MarkersVisual
    """

    _line_kwargs = ('color', 'width', 'connect')
    _marker_kwargs = ('edge_color', 'face_color', 'edge_width',
                      'marker_size', 'symbol')
    _valid_kwargs = set(_line_kwargs).union(set(_marker_kwargs))
    _kw_trans = dict(marker_size='size')

    def __init__(self, data=None, color='k', symbol=None, line_kind='-',
                 width=1., marker_size=10., edge_color='k', face_color='w',
                 edge_width=1., connect='strip'):
        if line_kind != '-':
            raise ValueError('Only solid lines currently supported')
        self._line = LineVisual(method='gl', antialias=False)
        self._markers = MarkersVisual()
        self._kwargs = {}
        CompoundVisual.__init__(self, [self._line, self._markers])
        self.set_data(data, color=color, symbol=symbol,
                      width=width, marker_size=marker_size,
                      edge_color=edge_color, face_color=face_color,
                      edge_width=edge_width, connect=connect)

    def set_data(self, data=None, **kwargs):
        """Set the line data

        Parameters
        ----------
        data : array-like
            The data.
        **kwargs : dict
            Keywoard arguments to pass to MarkerVisual and LineVisal.
        """
        bad_keys = set(kwargs) - self._valid_kwargs
        if bad_keys:
            raise TypeError("Invalid keyword arguments: {}".format(", ".join(bad_keys)))

        # remember these kwargs for future updates
        self._kwargs.update(kwargs)
        if data is None:
            pos = None
        else:
            if isinstance(data, tuple):
                pos = np.array(data).T.astype(np.float32)
            else:
                pos = np.atleast_1d(data).astype(np.float32)

            if pos.ndim == 1:
                pos = pos[:, np.newaxis]
            elif pos.ndim > 2:
                raise ValueError('data must have at most two dimensions')

            if pos.size == 0:
                pos = self._line.pos

                # if both args and keywords are zero, then there is no
                # point in calling this function.
                if len(self._kwargs) == 0:
                    raise TypeError("neither line points nor line properties"
                                    "are provided")
            elif pos.shape[1] == 1:
                x = np.arange(pos.shape[0], dtype=np.float32)[:, np.newaxis]
                pos = np.concatenate((x, pos), axis=1)
            # if args are empty, don't modify position
            elif pos.shape[1] > 3:
                raise TypeError("Too many coordinates given (%s; max is 3)."
                                % pos.shape[1])

        # todo: have both sub-visuals share the same buffers.
        line_kwargs = {}
        for k in self._line_kwargs:
            if k in self._kwargs:
                k_ = self._kw_trans[k] if k in self._kw_trans else k
                line_kwargs[k] = self._kwargs.get(k_)
        if pos is not None or len(line_kwargs) > 0:
            self._line.set_data(pos=pos, **line_kwargs)

        marker_kwargs = {}
        for k in self._marker_kwargs:
            if k in self._kwargs:
                k_ = self._kw_trans[k] if k in self._kw_trans else k
                marker_kwargs[k_] = self._kwargs.get(k)
        if pos is not None or len(marker_kwargs) > 0:
            self._markers.set_data(pos=pos, **marker_kwargs)