Skip to content

Commit

Permalink
Basic lattice.
Browse files Browse the repository at this point in the history
  • Loading branch information
onyxfish committed May 18, 2016
1 parent cb01c52 commit 057228a
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 10 deletions.
2 changes: 2 additions & 0 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ NO:
* Maps
* No ticks/grid
* 3D / multi-dimensional charts
* Annotations

MAYBE:

* Side-by-side bars
* Stacked bars
* Curved lines
* Wrapping labels
1 change: 1 addition & 0 deletions leather/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from leather.axis import Axis
from leather.chart import Chart
from leather.grid import Grid
from leather.lattice import Lattice
from leather.legend import Legend
from leather.scales.linear import LinearScale
from leather.scales.ordinal import OrdinalScale
Expand Down
79 changes: 79 additions & 0 deletions leather/lattice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env python

from leather.chart import Chart
from leather.data_types import Number, Text
from leather.grid import Grid
from leather.scales.linear import LinearScale
from leather.scales.ordinal import OrdinalScale
from leather.series import Series
from leather.utils import X, Y


class Lattice(object):
"""
A grid of charts with synchronized scales.
:param data:
A sequence of chart data sequences.
"""
def __init__(self, data, shape):
self._data = data
self._shape = shape

def _validate_dimension(self, dimension, chart_series):
scale = None
axis = None

data_type = chart_series[0].types[dimension]

for series in chart_series[1:]:
if series.types[dimension] is not data_type:
raise TypeError('All series must have the same data types.')

# Default Number scale is Linear
if data_type is Number:
data_min = min([series.min(dimension) for series in chart_series])
data_max = max([series.max(dimension) for series in chart_series])

scale = LinearScale(data_min, data_max)
# Default Text scale is Ordinal
elif data_type is Text:
scale_values = None

for series in chart_series:
if not scale_values:
scale_values = series.values(dimension)
continue

if series.values(dimension) != scale_values:
raise ValueError('Mismatched series scales')

scale = OrdinalScale(scale_values)

return (scale, axis)

def to_svg(self, path, width=1200, height=1200):
"""
Render the grid to an SVG.
"""
chart_series = []

for seq in self._data:
chart_series.append(Series(seq))

x_scale, x_axis = self._validate_dimension(X, chart_series)
y_scale, y_axis = self._validate_dimension(Y, chart_series)

grid = Grid()

for series in chart_series:
chart = Chart()
chart.set_x_scale(x_scale)
chart.set_y_scale(y_scale)
chart.set_x_axis(x_axis)
chart.set_y_axis(y_axis)
chart.add_series(series, self._shape)

grid.add_chart(chart)

grid.to_svg(path, width, height)
49 changes: 39 additions & 10 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,28 @@
# chart.add_dot(dot_data)
# chart.to_svg('test.svg')

# data = [[
# (0, 3),
# (4, 5),
# (7, 9),
# (8, 4)
# ], [
# (0, 4),
# (1, 3),
# (2, 5),
# (5, 6),
# (9, 10)
# ]]
#
# grid = leather.Grid()
#
# for series in data:
# chart = leather.Chart()
# chart.add_line(series)
# grid.add_chart(chart)
#
# grid.to_svg('test.svg', 1200, 600)

data = [[
(0, 3),
(4, 5),
Expand All @@ -50,16 +72,23 @@
], [
(0, 4),
(1, 3),
(2, 5),
(5, 6),
(9, 10)
(2, 3),
(10, 7),
(15, 5)
], [
(0, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8)
], [
(4, 4),
(6, 3),
(7, 5),
(8, 6),
(12, 10)
]]

grid = leather.Grid()

for series in data:
chart = leather.Chart()
chart.add_line(series)
grid.add_chart(chart)
lattice = leather.Lattice(data, leather.Line())

grid.to_svg('test.svg', 1200, 600)
lattice.to_svg('test.svg', 1200, 600)

0 comments on commit 057228a

Please sign in to comment.