Commit c12dbdbc authored by Sanjay Yadav's avatar Sanjay Yadav

ENH: Fixed bullet charts text.

parent f042d3cb
Pipeline #32480 passed with stage
in 1 minute and 10 seconds
......@@ -782,15 +782,10 @@ def bullet(shape, spec, data):
if text:
text = compile_function({'text': spec['text']}, 'text', data, handler)
# if isinstance(spec['data'], (dict,)) and 'function' in spec['data']:
spec['data'] = compile_function(spec, 'data', data, handler)
gradient = spec.get('gradient', 'RdYlGn')
# if isinstance(gradient, (dict,)) and 'function' in gradient:
# gradient = compile_function(spec, 'gradient', data, handler)
shapes = shape._parent
shape._sp.delete()
# lo = np.nanmin([data, target, poor, average, good])
lo = spec.get('lo', 0)
hi = spec.get('hi', np.nanmax([spec['data'], spec['target'], spec['poor'],
spec['average'], spec['good']]))
......@@ -837,15 +832,14 @@ def bullet(shape, spec, data):
rect_css(data_rect, **{'fill': fill, 'stroke': stroke or fill})
if text:
data_text = text(spec['data'])
parent = data_rect._parent
_factor = 1.25
text_width_height = _width if orient == 'vertical' else _hight
_xaxis = x + (_width / 4.0) if orient == 'vertical' else x + scaled - (_hight * _factor)
parent = parent.add_textbox(_xaxis, yaxis, text_width_height, text_width_height)
data_txt_style = style.get('data', {})
data_txt_style['color'] = data_txt_style.get('color', _color.contrast(fill))
add_text_to_shape(parent, data_text, **data_txt_style)
for paragraph in data_rect.text_frame.paragraphs:
if not paragraph.text.strip():
paragraph.add_run()
for run in paragraph.runs:
run.text = '{}'.format(text(spec['data']))
utils.apply_text_css(run, paragraph, **data_txt_style)
if not np.isnan(spec['target']):
line_hight = 10000
......@@ -863,14 +857,102 @@ def bullet(shape, spec, data):
handler = data.get('handler')
target_text = text(spec['target'])
parent = target_line._parent
yaxis = yaxis - (_width / 2) if orient == 'vertical' else yaxis + (_hight / 5.0)
text_width_height = _width if orient == 'vertical' else _hight
parent = parent.add_textbox(xaxis, yaxis, text_width_height, text_width_height)
yaxis = yaxis - (_width / 2) if orient == 'vertical' else yaxis - (_hight / 4.0)
txt_width = _width if orient == 'vertical' else _hight
parent = parent.add_textbox(xaxis + line_hight, yaxis, txt_width, txt_width)
target_txt_style = style.get('target', {})
target_txt_style['color'] = target_txt_style.get('color', _color.contrast(fill))
add_text_to_shape(parent, target_text, **target_txt_style)
def heatgrid(shape, spec, data):
"""Create a heat grid."""
spec = copy.deepcopy(spec['heatgrid'])
top = shape.top
left = shape.left
width = shape.width
pixel_inch = 10000
default_height = 20
height = spec.get('cell-height', default_height) * pixel_inch
parent = shape._parent
shape.element.delete()
# Loading config
handler = data.pop('handler') if 'handler' in data else None
for key in ['row', 'column', 'value']:
if isinstance(spec[key], (dict,)) and 'function' in spec[key]:
spec[key] = compile_function(spec, key, data, handler)
# Loading data
data = compile_function(spec, 'data', data, handler)
data = data.sort_values(by=[spec['column']])
rows = data[spec['row']].unique().tolist()
columns = sorted(data[spec['column']].unique().tolist())
left_margin = (width * spec.get('left-margin', 0.15))
padding = spec.get('style', {}).get('padding', 10)
padding = padding * pixel_inch
styles = copy.deepcopy(spec.get('style', {}))
if styles.get('gradient'):
_min, _max = data[spec['value']].min(), data[spec['value']].max()
# Compiling style elements if required
for key in ['gradient', 'color', 'fill', 'font-size', 'font-family']:
if isinstance(styles.get(key), (dict,)) and 'function' in styles[key]:
styles[key] = compile_function(styles, key, data, handler)
# Calculating cell's width based on config
_width = (width - left_margin) / float(len(columns)) / pixel_inch
_width = spec.get('cell-width', _width) * pixel_inch
# Adding Columns to the HeatGrid.
for idx, column in enumerate(columns):
txt = parent.add_textbox(
left + _width * idx + left_margin, top - height - padding, _width, height)
add_text_to_shape(txt, '{}'.format(column), **styles)
# Cell width
for index, row in enumerate(rows):
_data = data[data[spec['row']] == row].dropna()
if len(_data) < len(columns):
_data = pd.merge(
_data, pd.DataFrame({spec['column']: list(columns)}),
left_on=spec['column'], right_on=spec['column'], how='outer')
_data = _data.sort_values(by=[spec['column']]).reset_index(drop=True)
for _idx, _row in _data.iterrows():
style = copy.deepcopy(styles)
# Adding cells
xaxis = left + (_width * _idx) + left_margin
yaxis = top + (height * index) + padding * index
_rect = rect(parent, xaxis, yaxis, _width - padding, height)
# Adding color gradient to cell if gradient is True
if style.get('gradient'):
grad_txt = scale_data(_row[spec['value']], _min, _max)
gradient = matplotlib.cm.get_cmap(spec['style']['gradient'])
style['fill'] = matplotlib.colors.to_hex(gradient(grad_txt))
style['color'] = _color.contrast(style['fill'])
if np.isnan(_row[spec['value']]) and spec.get('na-color'):
style['fill'] = spec.get('na-color')
style['color'] = _color.contrast(style['fill'])
rect_css(_rect, **style)
# Adding text to cells if required.
if spec.get('text'):
spec['text'] = compile_function(spec, 'text', data, handler)
_txt = parent.add_textbox(xaxis, yaxis, _width - padding, height)
cell_txt = '{}'.format(_row[spec['value']])
if callable(spec['text']):
cell_txt = spec['text'](_row)
if np.isnan(_row[spec['value']]) and spec.get('na-text'):
cell_txt = spec.get('na-text')
add_text_to_shape(_txt, cell_txt, **style)
# Adding row's text in left side
txt = parent.add_textbox(
left, top + (height * index) + padding * index,
_width + left_margin, height)
add_text_to_shape(txt, row, **styles)
def css(shape, spec, data):
"""Function to modify a rectangle's property in PPT."""
pxl_to_inch = 10000
......@@ -1115,94 +1197,6 @@ def bar_circle(shape, spec, data):
rect_css(shape, **{'fill': '#FBFBFB', 'stroke': '#FBFBFB'})
def heatgrid(shape, spec, data):
"""Create a heat grid."""
spec = copy.deepcopy(spec['heatgrid'])
top = shape.top
left = shape.left
width = shape.width
pixel_inch = 10000
default_height = 20
height = spec.get('cell-height', default_height) * pixel_inch
parent = shape._parent
shape.element.delete()
# Loading config
handler = data.pop('handler') if 'handler' in data else None
for key in ['row', 'column', 'value']:
if isinstance(spec[key], (dict,)) and 'function' in spec[key]:
spec[key] = compile_function(spec, key, data, handler)
# Loading data
data = compile_function(spec, 'data', data, handler)
data = data.sort_values(by=[spec['column']])
rows = data[spec['row']].unique().tolist()
columns = sorted(data[spec['column']].unique().tolist())
left_margin = (width * spec.get('left-margin', 0.15))
padding = spec.get('style', {}).get('padding', 10)
padding = padding * pixel_inch
styles = copy.deepcopy(spec.get('style', {}))
if styles.get('gradient'):
_min, _max = data[spec['value']].min(), data[spec['value']].max()
# Compiling style elements if required
for key in ['gradient', 'color', 'fill', 'font-size', 'font-family']:
if isinstance(styles.get(key), (dict,)) and 'function' in styles[key]:
styles[key] = compile_function(styles, key, data, handler)
# Calculating cell's width based on config
_width = (width - left_margin) / float(len(columns)) / pixel_inch
_width = spec.get('cell-width', _width) * pixel_inch
# Adding Columns to the HeatGrid.
for idx, column in enumerate(columns):
txt = parent.add_textbox(
left + _width * idx + left_margin, top - height - padding, _width, height)
add_text_to_shape(txt, '{}'.format(column), **styles)
# Cell width
for index, row in enumerate(rows):
_data = data[data[spec['row']] == row].dropna()
if len(_data) < len(columns):
_data = pd.merge(
_data, pd.DataFrame({spec['column']: list(columns)}),
left_on=spec['column'], right_on=spec['column'], how='outer')
_data = _data.sort_values(by=[spec['column']]).reset_index(drop=True)
for _idx, _row in _data.iterrows():
style = copy.deepcopy(styles)
# Adding cells
xaxis = left + (_width * _idx) + left_margin
yaxis = top + (height * index) + padding * index
_rect = rect(parent, xaxis, yaxis, _width - padding, height)
# Adding color gradient to cell if gradient is True
if style.get('gradient'):
grad_txt = scale_data(_row[spec['value']], _min, _max)
gradient = matplotlib.cm.get_cmap(spec['style']['gradient'])
style['fill'] = matplotlib.colors.to_hex(gradient(grad_txt))
style['color'] = _color.contrast(style['fill'])
if np.isnan(_row[spec['value']]) and spec.get('na-color'):
style['fill'] = spec.get('na-color')
style['color'] = _color.contrast(style['fill'])
rect_css(_rect, **style)
# Adding text to cells if required.
if spec.get('text'):
spec['text'] = compile_function(spec, 'text', data, handler)
_txt = parent.add_textbox(xaxis, yaxis, _width - padding, height)
cell_txt = '{}'.format(_row[spec['value']])
if callable(spec['text']):
cell_txt = spec['text'](_row)
if np.isnan(_row[spec['value']]) and spec.get('na-text'):
cell_txt = spec.get('na-text')
add_text_to_shape(_txt, cell_txt, **style)
# Adding row's text in left side
txt = parent.add_textbox(
left, top + (height * index) + padding * index,
_width + left_margin, height)
add_text_to_shape(txt, row, **styles)
cmdlist = {
'css': css,
'text': text,
......
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