Skip to content

Commit

Permalink
Add rough timescale support. Closes #14.
Browse files Browse the repository at this point in the history
  • Loading branch information
onyxfish committed May 20, 2016
1 parent 776d59d commit bbb3d72
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 135 deletions.
2 changes: 2 additions & 0 deletions docs/api/scales.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ Scales
.. autoclass:: leather.Linear

.. autoclass:: leather.Ordinal

.. autoclass:: leather.Temporal
2 changes: 1 addition & 1 deletion docs/example2.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 18 additions & 4 deletions leather/data_types.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python

from datetime import date, datetime
from decimal import Decimal

import six
Expand All @@ -11,14 +12,27 @@ class DataType(object):
"""
@classmethod
def infer(cls, v):
if isinstance(v, Number.types):
return Number
elif isinstance(v, Text.types):
return Text
for t in [DateTime, Date, Number, Text]:
if isinstance(v, t.types):
return t

raise TypeError('No data type available for %s' % type(v))


class Date(DataType):
"""
Data representing dates.
"""
types = (date,)


class DateTime(DataType):
"""
Data representing dates with times.
"""
types = (datetime,)


class Number(DataType):
"""
Data representing numbers.
Expand Down
1 change: 1 addition & 0 deletions leather/scales/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
from leather.scales.base import Scale
from leather.scales.linear import Linear
from leather.scales.ordinal import Ordinal
from leather.scales.temporal import Temporal
27 changes: 25 additions & 2 deletions leather/scales/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/usr/bin/env python

from leather.data_types import Number, Text
from datetime import date, datetime

from leather.data_types import Date, DateTime, Number, Text
from leather.shapes import Bars, Columns


Expand All @@ -23,9 +25,30 @@ def infer(cls, series_list, dimension, data_type):
"""
from leather.scales.linear import Linear
from leather.scales.ordinal import Ordinal
from leather.scales.temporal import Temporal

# Default Time scale is Temporal
# Default Time scale is Temporal
if data_type is Date:
data_min = date.max
data_max = date.min

for series in series_list:
data_min = min(data_min, series.min(dimension))
data_max = max(data_max, series.max(dimension))

scale = Temporal(data_min, data_max)
elif data_type is DateTime:
data_min = datetime.max
data_max = datetime.min

for series in series_list:
data_min = min(data_min, series.min(dimension))
data_max = max(data_max, series.max(dimension))

scale = Temporal(data_min, data_max)
# Default Number scale is Linear
if data_type is Number:
elif data_type is Number:
force_zero = False
data_min = 0
data_max = 0
Expand Down
42 changes: 42 additions & 0 deletions leather/scales/temporal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env python

from datetime import date, datetime, time

from leather.scales.base import Scale


class Temporal(Scale):
"""
A scale that linearly maps date/datetime values from a domain to a range.
:param domain_min:
The minimum date/datetime of the input domain.
:param domain_max:
The maximum date/datetime of the input domain.
"""
def __init__(self, domain_min, domain_max):
self._min = domain_min
self._max = domain_max

def project(self, value, range_min, range_max):
"""
Project a value in this scale's domain to a target range.
"""
pos = (value - self._min) / (self._max - self._min)

return ((range_max - range_min) * pos) + range_min

def project_interval(self, value, range_min, range_max):
"""
Project a value in this scale's domain to an interval in the target
range. This is used for places :class:`.Bars` and :class:`.Columns`.
"""
raise NotImplementedError

def ticks(self, count):
"""
Generate a series of ticks for this scale.
"""
size = (self._max - self._min) / (count - 1)

return [self._min + (size * i) for i in range(count)]
138 changes: 10 additions & 128 deletions test.py
Original file line number Diff line number Diff line change
@@ -1,136 +1,18 @@
#!/usr/bin/env python

import random
from datetime import date, datetime

import leather

dot_data = [(random.randint(0, 250), random.randint(0, 250)) for i in range(100)]

def colorizer(x, y, i):
return 'rgb(%i, %i, %i)' % (x, y, 150)
data = [
(datetime(2010, 1, 1), 4),
(datetime(2011, 5, 4), 3),
(datetime(2012, 6, 1, 11), 5),
(datetime(2013, 1, 1), 6),
(datetime(2014, 12, 1), 10)
]

chart = leather.Chart('Well that was easy')
chart.add_dots(dot_data, color=colorizer)
chart = leather.Chart("X axis ftw")
chart.add_lines(data)
chart.to_svg('test.svg')

# dot_data = [
# (0, 3),
# (4, 5),
# (7, 9),
# (8, 4)
# ]
#
# line_data = [
# (0, 4),
# (1, 3),
# (2, 5),
# (5, 6),
# (9, 10)
# ]
#
# chart = leather.Chart()
# # chart.set_x_scale(leather.Linear(0, 20))
# chart.add_dots(dot_data)
# chart.add_lines(line_data)
# chart.to_svg('test.svg')

# bar_data = [
# (3, 'foo'),
# (5, 'bing blaarg murg'),
# (9, 'baz'),
# (4, 'blurg')
# ]
#
# def colorizer(x, y, i):
# if y == 'baz':
# return 'yellow'
# else:
# return 'blue'
#
# chart = leather.Chart('Bar charts are fun')
# chart.add_dots(bar_data, color=colorizer)
# chart.to_svg('test.svg')
#
# data = [[
# (0, 3),
# (4, 5),
# (7, 9),
# (8, 4)
# ], [
# (0, 4),
# (1, 3),
# (2, 5),
# (5, 6),
# (9, 10)
# ],[
# (0, 4),
# (1, 3),
# (2, 5),
# (5, 6),
# (9, 10)
# ]]
#
# grid = leather.Grid()
#
# chart = leather.Chart('Chart A')
# chart.add_lines(data[0])
# grid.add_chart(chart)
#
# chart = leather.Chart('Chart B')
# chart.add_dots(data[1])
# grid.add_chart(chart)
#
# chart = leather.Chart('Chart C')
# chart.add_dots(data[2])
# grid.add_chart(chart)
#
# grid.to_svg('test.svg')

# data = [[
# (0, 3),
# (4, 5),
# (7, 9),
# (8, 4)
# ], [
# (0, 4),
# (1, 3),
# (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)
# ]]
#
# lattice = leather.Lattice(data, leather.Lines('purple'), ['A', 'B', 'C', 'D'])
#
# lattice.to_svg('test.svg', 1200, 600)

# data = [
# (3, 1),
# (5, 3),
# (9, 12),
# (4, 15)
# ]
#
# chart = leather.Chart()
# chart.add_bars(data)
# chart.to_svg('test.svg')

# chart = leather.Chart()
# chart.set_x_scale(leather.Linear(0, 20))
# chart.set_x_axis(leather.Axis(ticks=5))
# chart.set_y_scale(leather.Linear(0, 20))
# chart.set_y_axis(leather.Axis(ticks=5))
# chart.add_dots(data)
#
# chart.to_svg('test.svg')

0 comments on commit bbb3d72

Please sign in to comment.