/usr/lib/python3/dist-packages/leather/lattice.py is in python3-leather 0.3.3-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | #!/usr/bin/env python
from leather.axis import Axis
from leather.chart import Chart
from leather.data_types import Date, DateTime
from leather.grid import Grid
from leather.scales import Scale, Linear
from leather.series import Series
from leather.shapes import Line
from leather import theme
from leather.utils import X, Y
class Lattice(object):
"""
A grid of charts with synchronized shapes, scales, and axes.
Lattice only supports graphing a single series of data.
:param shape:
An instance of :class:`.Shape` to use to render all series. Defaults
to :class:`.Line` if not specified.
"""
def __init__(self, shape=None):
self._shape = shape or Line()
self._series = []
self._types = [None, None]
self._scales = [None, None]
self._axes = [None, None]
def set_x_scale(self, scale):
"""
Set the X :class:`.Scale` for this lattice.
"""
self._scales[X] = scale
def set_y_scale(self, scale):
"""
See :meth:`.Lattice.set_x_scale`.
"""
self._scales[Y] = scale
def add_x_scale(self, domain_min, domain_max):
"""
Create and add a :class:`.Scale`.
If the provided domain values are :class:`date` or :class:`datetime`
then a :class:`.Temporal` scale will be created, otherwise it will
:class:`.Linear`.
If you want to set a custom scale class use :meth:`.Lattice.set_x_scale`
instead.
"""
scale_type = Linear
if isinstance(domain_min, Date.types) or isinstance(domain_min, DateTime.types):
scale_type = Temporal
self.set_x_scale(scale_type(domain_min, domain_max))
def add_y_scale(self, domain_min, domain_max):
"""
See :meth:`.Lattice.add_x_scale`.
"""
scale_type = Linear
if isinstance(domain_min, Date.types) or isinstance(domain_min, DateTime.types):
scale_type = Temporal
self.set_y_scale(scale_type(domain_min, domain_max))
def set_x_axis(self, axis):
"""
Set an :class:`.Axis` class for this lattice.
"""
self._axes[X] = axis
def set_y_axis(self, axis):
"""
See :meth:`.Lattice.set_x_axis`.
"""
self._axes[Y] = axis
def add_x_axis(self, ticks=None, tick_formatter=None, name=None):
"""
Create and add an X :class:`.Axis`.
If you want to set a custom axis class use :meth:`.Lattice.set_x_axis`
instead.
"""
self._axes[X] = Axis(ticks=ticks, tick_formatter=tick_formatter, name=name)
def add_y_axis(self, ticks=None, tick_formatter=None, name=None):
"""
See :meth:`.Lattice.add_x_axis`.
"""
self._axes[Y] = Axis(ticks=ticks, tick_formatter=tick_formatter, name=name)
def add_one(self, data, x=None, y=None, title=None):
"""
Add a data series to this lattice.
:param data:
A sequence of data suitable for constructing a :class:`.Series`,
or a sequence of such objects.
:param x:
See :class:`.Series`.
:param y:
See :class:`.Series`.
:param title:
A title to render above this chart.
"""
series = Series(data, x=x, y=y, name=title)
for dimension in [X, Y]:
if self._types[dimension]:
if series._types[dimension] is not self._types[dimension]:
raise TypeError('All data series must have the same data types.')
else:
self._types[dimension] = series._types[dimension]
self._shape.validate_series(series)
self._series.append(series)
def add_many(self, data, x=None, y=None, titles=None):
"""
Same as :meth:`.Lattice.add_one` except :code:`data` is a list of data
series to be added simultaneously.
See :meth:`.Lattice.add_one` for other arguments.
Note that :code:`titles` is a sequence of titles that must be the same
length as :code:`data`.
"""
for i, d in enumerate(data):
title = titles[i] if titles else None
self.add_one(d, x=x, y=y, title=title)
def to_svg(self, path=None, width=None, height=None):
"""
Render the lattice to an SVG.
See :class:`.Grid` for additional documentation.
"""
layers = [(s, self._shape) for s in self._series]
if not self._scales[X]:
self._scales[X] = Scale.infer(layers, X, self._types[X])
if not self._scales[Y]:
self._scales[Y]= Scale.infer(layers, Y, self._types[Y])
if not self._axes[X]:
self._axes[X] = Axis()
if not self._axes[Y]:
self._axes[Y] = Axis()
grid = Grid()
for i, series in enumerate(self._series):
chart = Chart(title=series.name)
chart.set_x_scale(self._scales[X])
chart.set_y_scale(self._scales[Y])
chart.set_x_axis(self._axes[X])
chart.set_y_axis(self._axes[Y])
chart.add_series(series, self._shape)
grid.add_one(chart)
return grid.to_svg(path, width, height)
|