Commit 809b9327 authored by Sanjay Yadav's avatar Sanjay Yadav

ENH: Enhancements in bar with circle styles.

parent 358198a4
Pipeline #32078 failed with stage
in 52 seconds
......@@ -14,9 +14,10 @@ import matplotlib.cm
from . import fontwidth
import matplotlib.colors
from . import color as _color
from collections import OrderedDict
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
from collections import OrderedDict
from orderedattrdict import AttrDict
from tornado.template import Template
from tornado.escape import to_unicode
from pptx.chart.data import ChartData
......@@ -205,7 +206,7 @@ def rect_css(shape, **kwargs):
chart_css(fill, kwargs, rectcss)
def add_text_to_shape(shape, text, **kwargs):
def add_text_to_shape(shape, textval, **kwargs):
"""Function to add text to shape."""
min_inc = 13000
pixel_inch = 10000
......@@ -214,7 +215,7 @@ def add_text_to_shape(shape, text, **kwargs):
paragraph = shape.text_frame.paragraphs[0]
paragraph.add_run()
for run in paragraph.runs:
run.text = text
run.text = textval
shape_txt = run.font
shape_txt = run.font.fill
shape_txt.solid()
......@@ -1005,23 +1006,47 @@ def bar_circle(shape, spec, data):
"""Function to plot bar chart with circles."""
spec = copy.deepcopy(spec['bar_circle'])
handler = data.pop('handler') if 'handler' in data else None
csskeys = ['bar-y', 'circle-y', 'circle-size', 'bar-category',
'circle-category', 'opacity', 'stroke']
for key in csskeys:
if isinstance(spec.get(key), (dict,)) and 'function' in spec[key]:
spec[key] = compile_function(spec, key, data, handler)
# Getting CSS
style = AttrDict()
common_css = copy.deepcopy(spec.get('style', {}))
for csskey in ['bar', 'circle']:
_style = common_css.pop(csskey, {})
for key, val in _style.items():
if isinstance(val, (dict,)) and 'function' in val:
_style[key] = compile_function(_style, key, data, handler)
style[csskey] = _style
for csskey in ['bar', 'circle']:
update_css = copy.deepcopy(common_css)
update_css.update(style[csskey])
for key, val in update_css.items():
if isinstance(val, (dict,)) and 'function' in val:
update_css[key] = compile_function(update_css, key, data, handler)
style[csskey] = update_css
# Loading data
bar_data = compile_function(spec, 'bardata', data, handler)
circle_data = compile_function(spec, 'circledata', data, handler)
bary = spec['bar-y']
circley = spec['circle-y']
circ_size = spec['circle-size']
bar_category = spec['bar-category']
circle_category = spec['circle-category']
style = copy.deepcopy(spec.get('style', {}))
for csskey in ['font-color', 'font-family', 'color', 'fill', 'font-size']:
if isinstance(style.get(csskey), (dict,)) and 'function' in style[csskey]:
style[csskey] = compile_function(style, csskey, data, handler)
bar_conf = copy.deepcopy(spec['bar'])
bar_data = compile_function(bar_conf, 'data', data, handler)
circle_conf = copy.deepcopy(spec['circle'])
circle_data = compile_function(circle_conf, 'data', data, handler)
for key in ['y', 'size', 'x', 'text']:
for config in [bar_conf, circle_conf]:
if isinstance(config.get(key), (dict,)) and 'function' in config[key]:
config[key] = compile_function(config, key, data, handler)
bary = bar_conf['y']
circley = circle_conf['y']
circ_size = circle_conf['size']
bar_category = bar_conf['x']
circle_category = circle_conf['x']
txt_props = ['font-color', 'font-family', 'color', 'fill',
'font-size', 'text', 'stroke', 'opacity']
for csskey in txt_props:
for key in ['bar', 'circle']:
if isinstance(style[key].get(csskey), (dict,)) and 'function' in style[key][csskey]:
style[key][csskey] = compile_function(style[key], csskey, data, handler)
scale = bar_data[bary].fillna(0).tolist() + circle_data[circley].fillna(0).tolist()
ymax = max(scale)
......@@ -1057,23 +1082,40 @@ def bar_circle(shape, spec, data):
left + row['x'] + row['width'] / 4.0,
top + shape.height,
row['width'] - row['width'] / 4.0, row['width'] - row['width'] / 2.0)
add_text_to_shape(txt, row['category'], **style)
_barcss = copy.deepcopy(style['bar'])
add_text_to_shape(txt, '{}'.format(row['category']), **_barcss)
for _barkey in txt_props:
if callable(_barcss.get(_barkey)):
_barcss[_barkey] = _barcss[_barkey](row)
if bar_conf.get('text'):
txt = parent.add_textbox(
left + row['x'] + row['width'] / 4.0,
top + row['y'],
row['width'] - row['width'] / 4.0, row['width'] - row['width'] / 4.0)
add_text_to_shape(txt, '{}%'.format(row[bary]), **style)
d = circle_data[circle_data[circle_category] == row['category']]
for i, circle in d.iterrows():
bar_txt = '{}%'.format(row[bary])
bar_txt = bar_conf['text'](row) if callable(bar_conf['text']) else bar_txt
add_text_to_shape(txt, bar_txt, **_barcss)
map_circ_data = circle_data[circle_data[circle_category] == row['category']]
for i, circle in map_circ_data.iterrows():
y = top + scale_data(circle[circley], 0, ymax, factor=row['width'])
y = y - (row['width'] / 2.0)
sz = scale_data(circle[circ_size], 0, d[circ_size].max(), factor=row['width'] / 2.0)
xaxis = left + row['x'] + (row['width'] / 2.0) - (sz / 2.0)
circle_size = scale_data(
circle[circ_size], 0, map_circ_data[circ_size].max(),
factor=row['width'] / 2.0)
xaxis = left + row['x'] + (row['width'] / 2.0) - (circle_size / 2.0)
cir = parent.add_shape(
MSO_SHAPE.OVAL, xaxis, y, sz, sz)
rect_css(cir, **{'fill': '#00441B', 'stroke': '#00441B', 'opacity': 0.7})
rect_css(_rect, **{'fill': '#cccccc', 'stroke': '#cccccc'})
MSO_SHAPE.OVAL, xaxis, y, circle_size, circle_size)
circle_style = copy.deepcopy(style['circle'])
for _key in ['fill', 'stroke', 'opacity']:
if callable(circle_style.get(_key)):
circle_style[_key] = circle_style[_key](circle)
rect_css(cir, **circle_style)
rect_css(_rect, **_barcss)
rect_css(shape, **{'fill': '#FBFBFB', 'stroke': '#FBFBFB'})
......
......@@ -7,13 +7,27 @@ data:
barcircle-config:
bar-circle:
bar_circle:
bardata: data['bardata']
circledata: data['circledata']
bar-y: FTE
circle-y: "Y"
circle-size: Size
bar-category: Region
circle-category: Category
bar:
data: data['bardata']
y: FTE
x: Region
text:
function: "lambda v: '{:.2f}'.format(v['FTE'])"
circle:
data: data['circledata']
y: "Y"
size: Size
x: Category
style:
bar:
font-size: 14
color: '#ff0000'
fill: '#1A9850'
stroke: '#cccccc'
opacity: 0.3
circle:
font-size: 14
color: '#000000'
opacity: 0.7
fill: '#FE9929'
stroke: '#00441B'
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment