dbt-selly/dbt-env/lib/python3.8/site-packages/leather/shapes/bars.py

80 lines
2.2 KiB
Python
Raw Normal View History

2022-03-22 15:13:27 +00:00
#!/usr/bin/env python
import xml.etree.ElementTree as ET
import six
from leather.data_types import Number, Text
from leather.series import CategorySeries
from leather.shapes.base import Shape
from leather import theme
from leather.utils import X, Y
class Bars(Shape):
"""
Render a series of data as bars.
:param fill_color:
The color to fill the bars. You may also specify a
:func:`.style_function`.
"""
def __init__(self, fill_color=None):
self._fill_color = fill_color
def validate_series(self, series):
"""
Verify this shape can be used to render a given series.
"""
if isinstance(series, CategorySeries):
raise ValueError('Bars can not be used to render CategorySeries.')
if series.data_type(X) is not Number:
raise ValueError('Bars only support Number values for the Y axis.')
if series.data_type(Y) is not Text:
raise ValueError('Bars only support Text values for the X axis.')
def to_svg(self, width, height, x_scale, y_scale, series, palette):
"""
Render bars to SVG elements.
"""
group = ET.Element('g')
group.set('class', 'series bars')
zero_x = x_scale.project(0, 0, width)
if self._fill_color:
fill_color = self._fill_color
else:
fill_color = next(palette)
for d in series.data():
if d.x is None or d.y is None:
continue
y1, y2 = y_scale.project_interval(d.y, height, 0)
proj_x = x_scale.project(d.x, 0, width)
if d.x < 0:
bar_x = proj_x
bar_width = zero_x - proj_x
else:
bar_x = zero_x
bar_width = proj_x - zero_x
if callable(fill_color):
color = fill_color(d)
else:
color = fill_color
group.append(ET.Element('rect',
x=six.text_type(bar_x),
y=six.text_type(y2),
width=six.text_type(bar_width),
height=six.text_type(y1 - y2),
fill=color
))
return group