Commit dfb8c80e authored by Sanjay Yadav's avatar Sanjay Yadav

WIP: Custom bar wit circle and heatmap(table functionality WIP).

parent 478f74a2
Pipeline #30553 failed with stage
in 12 seconds
...@@ -14,6 +14,7 @@ import matplotlib.cm ...@@ -14,6 +14,7 @@ import matplotlib.cm
from . import fontwidth from . import fontwidth
import matplotlib.colors import matplotlib.colors
from . import color as _color from . import color as _color
from collections import OrderedDict
from pptx.dml.color import RGBColor from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN from pptx.enum.text import PP_ALIGN
from tornado.template import Template from tornado.template import Template
...@@ -198,8 +199,7 @@ def rect_css(shape, **kwargs): ...@@ -198,8 +199,7 @@ def rect_css(shape, **kwargs):
fill = shape.fill if key == 'fill' else shape.line.fill fill = shape.fill if key == 'fill' else shape.line.fill
rectcss = kwargs[key].rsplit('#')[-1].lower() rectcss = kwargs[key].rsplit('#')[-1].lower()
rectcss = rectcss + ('0' * (6 - len(rectcss))) rectcss = rectcss + ('0' * (6 - len(rectcss)))
fill.solid() chart_css(fill, kwargs, rectcss)
fill.fore_color.rgb = RGBColor.from_string(rectcss)
def add_text_to_shape(shape, text, font_size, txt_fill): def add_text_to_shape(shape, text, font_size, txt_fill):
...@@ -377,7 +377,7 @@ def _extract_tbl_properties(table, tbl_style, row_idx, rowtype): ...@@ -377,7 +377,7 @@ def _extract_tbl_properties(table, tbl_style, row_idx, rowtype):
text_dict = {} text_dict = {}
for row_text in row_text_tag: for row_text in row_text_tag:
row_txt_clr = table.rows[row_idx].cells[0]._tc.txBody.xpath(row_text) row_txt_clr = table.rows[row_idx].cells[0]._tc.txBody.xpath(row_text)
clr_key = '{}_{}'.format(rowtype, row_text.rsplit(':')[-1]) clr_key = '{}'.format(row_text.rsplit(':')[-1])
if len(row_txt_clr) > 0: if len(row_txt_clr) > 0:
text_dict[clr_key] = row_txt_clr[0].val text_dict[clr_key] = row_txt_clr[0].val
else: else:
...@@ -389,11 +389,11 @@ def _extract_tbl_properties(table, tbl_style, row_idx, rowtype): ...@@ -389,11 +389,11 @@ def _extract_tbl_properties(table, tbl_style, row_idx, rowtype):
info_txt.add_run() info_txt.add_run()
if info_txt.runs: if info_txt.runs:
info_txt = info_txt.runs[0].font info_txt = info_txt.runs[0].font
text_dict['{}{}'.format(rowtype, '_italic')] = info_txt.italic text_dict['bold'] = info_txt.bold
text_dict['{}{}'.format(rowtype, '_bold')] = info_txt.bold text_dict['italic'] = info_txt.italic
text_dict['{}{}'.format(rowtype, '_txt_size')] = info_txt.size text_dict['font-size'] = info_txt.size
text_dict['{}{}'.format(rowtype, '_font_name')] = info_txt.name text_dict['font-family'] = info_txt.name
text_dict['{}{}'.format(rowtype, '_underline')] = info_txt.underline text_dict['underline'] = info_txt.underline
# Cell properties information. # Cell properties information.
cell_info = ['./a:srgbClr', './a:schemeClr'] cell_info = ['./a:srgbClr', './a:schemeClr']
...@@ -493,6 +493,11 @@ def _table_css(shape, rowtype='header'): ...@@ -493,6 +493,11 @@ def _table_css(shape, rowtype='header'):
def table_cell_css(cell, paragraph, run, info): def table_cell_css(cell, paragraph, run, info):
"""Mak.""" """Mak."""
pixcel_to_inch = 10000 pixcel_to_inch = 10000
# if 'srgbClr' in info:
# rgb = table_style.get('{}_{}'.format(rowtype, 'srgbClr'))
# if 'schemeClr' in table_style:
# theme_color = table_style.get('{}_{}'.format(rowtype, 'schemeClr'))
if info.get('fill'): if info.get('fill'):
cell_fill = cell.fill cell_fill = cell.fill
cell_fill.solid() cell_fill.solid()
...@@ -500,7 +505,6 @@ def table_cell_css(cell, paragraph, run, info): ...@@ -500,7 +505,6 @@ def table_cell_css(cell, paragraph, run, info):
if info.get('text'): if info.get('text'):
text_style = info.get('text') text_style = info.get('text')
print(text_style.get('fill'))
if text_style.get('fill'): if text_style.get('fill'):
rows_text = run.font.fill rows_text = run.font.fill
rows_text.solid() rows_text.solid()
...@@ -650,11 +654,13 @@ def chart(shape, spec, data): ...@@ -650,11 +654,13 @@ def chart(shape, spec, data):
info['opacity']['function'] = info['opacity'] info['opacity']['function'] = info['opacity']
info['opacity'] = compile_function(info, 'opacity', data, handler) info['opacity'] = compile_function(info, 'opacity', data, handler)
if chart_name == 'scatter' and not info.get('color'):
series_names = [series.name for series in shape.chart.series]
info['color'] = dict(zip(series_names, _color.distinct(len(series_names))))
if info.get('color'): if info.get('color'):
for index, series in enumerate(shape.chart.series): for index, series in enumerate(shape.chart.series):
# fill_graph = info['color'][series.name].rsplit('#')[-1].lower() fill_graph = conver_color_code(info['color'].get(series.name, '#cccccc'))
# fill_graph = fill_graph + ('0' * (6 - len(fill_graph)))
fill_graph = conver_color_code(info['color'][series.name])
if chart_name == 'scatter': if chart_name == 'scatter':
fill = series.marker.format.fill fill = series.marker.format.fill
line_fill = series.marker.format.line.fill line_fill = series.marker.format.line.fill
...@@ -1103,6 +1109,7 @@ def custom_table(shape, spec, data): ...@@ -1103,6 +1109,7 @@ def custom_table(shape, spec, data):
tbl_style = _table_css(shape) tbl_style = _table_css(shape)
_height = row.height + height_margin _height = row.height + height_margin
y = top + (_height * row_num) y = top + (_height * row_num)
row_type = 'header' if row_num == 0 else 'cell'
for col_num, cell in enumerate(row.cells): for col_num, cell in enumerate(row.cells):
colname = data_cols[col_num] colname = data_cols[col_num]
_width = shape.table.columns[col_num].width _width = shape.table.columns[col_num].width
...@@ -1140,35 +1147,126 @@ def custom_table(shape, spec, data): ...@@ -1140,35 +1147,126 @@ def custom_table(shape, spec, data):
arrow_width + arrow_width * twenty_percent) arrow_width + arrow_width * twenty_percent)
rect_css(arrow, **{'fill': '#ffffff', 'stroke': '#ffffff'}) rect_css(arrow, **{'fill': '#ffffff', 'stroke': '#ffffff'})
for curr_cell in cell.text_frame.paragraphs: for paragraph in cell.text_frame.paragraphs:
if not curr_cell.text.strip(): if not paragraph.text.strip():
curr_cell.add_run() paragraph.add_run()
for run in curr_cell.runs: for run in paragraph.runs:
text_prop = tbl_style.get('text', {}) text_prop = tbl_style.get('text', {})
txt = colname if row_num == 0 else data[row_num - 1][colname] txt = colname if row_num == 0 else data[row_num - 1][colname]
curr_cell.alignment = PP_ALIGN.RIGHT run.text = '{}'.format(txt)
_table_text_css(run, text_prop, 'header', txt) paragraph.alignment = PP_ALIGN.RIGHT
text_prop.update(spec.get(row_type, {}))
table_cell_css(cell, paragraph, run, text_prop)
def register(funcname): # _table_text_css(run, text_prop, 'header', txt)
"""Registry function."""
registery = {
'text': text, def bar_circle(shape, spec, data):
'oval': oval, """Function to plot bar chart with circles."""
'image': image, spec = spec['bar_circle']
'chart': chart, bary = spec['bar-y']
'table': table, circley = spec['circle-y']
'sankey': sankey, bar_data = data[spec['bardata']]
'bullet': bullet, circle_data = data[spec['circledata']]
'treemap': treemap,
'replace': replace, scale = bar_data[bary].fillna(0).tolist() + circle_data[circley].fillna(0).tolist()
'rectangle': rectangle, ymax = max(scale)
'calendarmap': calendarmap,
'custom_table': custom_table, pixel_inch = 10000
} top = shape.top
if funcname not in registery: padding = spec('padding', 40) * pixel_inch
registery[funcname] = funcname left = shape.left + spec('padding-left', 4) * pixel_inch
return registery width = shape.width
# width = width - (width * 0.20)
ticks = width / float(len(bar_data) or 1)
height = scale_data(0, ymax, shape.height, bar_data[bary])
xpos = pd.np.arange(0, width, ticks)
pos = pd.DataFrame(OrderedDict([
('x', xpos),
('y', shape.height - height),
('width', ticks - padding),
('height', height),
('Category', bar_data['Region']),
(bary, bar_data[bary])
]))
# Handle negative values
neg = pos[(pos['height'] < 0)]
pos.loc[neg.index, 'height'] = -neg['height']
pos.loc[neg.index, 'y'] = neg['y'] + neg['height']
parent = shape._parent
for index, row in pos.iterrows():
_rect = rect(
parent, left + row['x'], top + row['y'], row['width'], row['height'])
txt = parent.add_textbox(
left + row['x'] + row['width'] / 4.0,
top + shape.height,
row['width'] - row['width'] / 4.0, row['width'] - row['width'] / 2.0)
font_size = 16
default_txt_color = '#000000'
add_text_to_shape(txt, row['Category'], font_size, default_txt_color)
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)
font_size = 16
default_txt_color = '#000000'
add_text_to_shape(txt, '{}%'.format(row[bary]), font_size, default_txt_color)
d = circle_data[circle_data['Category'] == row['Category']]
for i, circle in d.iterrows():
y = top + scale_data(0, ymax, row['width'], circle[circley]) - (row['width'] / 2.0)
sz = scale_data(0, d['Size'].max(), row['width'] / 2.0, circle['Size'])
xaxis = left + row['x'] + (row['width'] / 2.0) - (sz / 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'})
rect_css(shape, **{'fill': '#FBFBFB', 'stroke': '#FBFBFB'})
def heatgrid(shape, spec, data):
"""Create a heat grid."""
spec = spec['heatgrid']
top = shape.top
left = shape.left
width = shape.width
height = spec.get('height', 200000)
parent = shape._parent
shape.element.delete()
data = data[spec['data']]
names = data[spec['group']].unique().tolist()
hours = sorted(data[spec['range']].unique().tolist())
twenty_percent = (width * 0.15)
for idx, hour in enumerate(hours):
txt = parent.add_textbox(
left + ((width - twenty_percent) / len(hours)) * idx + twenty_percent,
top - height - 100000, ((width - twenty_percent) / len(hours)), height)
font_size = 14
default_txt_color = '#000000'
add_text_to_shape(txt, '{}'.format(hour).zfill(2), font_size, default_txt_color)
for index, name in enumerate(names):
d = data[data['name'] == name].reset_index()
w = (width - twenty_percent) / float(len(d))
for idx, row in d.iterrows():
_rect = rect(parent, left + (w * idx) + twenty_percent,
top + (height * index) + 100000 * index,
w - 50000, height)
rect_css(_rect, **{'fill': '#f0f000', 'stroke': '#cccccc'})
txt = parent.add_textbox(
left, top + (height * index) + 100000 * index,
w + twenty_percent, height)
font_size = 14
default_txt_color = '#000000'
add_text_to_shape(txt, name, font_size, default_txt_color)
cmdlist = { cmdlist = {
...@@ -1179,8 +1277,9 @@ cmdlist = { ...@@ -1179,8 +1277,9 @@ cmdlist = {
'table': table, 'table': table,
'sankey': sankey, 'sankey': sankey,
'bullet': bullet, 'bullet': bullet,
'treemap': treemap,
'replace': replace, 'replace': replace,
'treemap': treemap,
'heatgrid': heatgrid,
'rectangle': rectangle, 'rectangle': rectangle,
'calendarmap': calendarmap, 'calendarmap': calendarmap,
'custom_table': custom_table, 'custom_table': custom_table,
......
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