def insert(self) -> None: """ This is a standing barchart (bar goes up) """ if DEBUG: print("Adding a column chart!") # Fix sizing size_w, size_h, dpi = utils.convert_plt_size(self.section) plt.figure(figsize=(size_w, size_h), dpi=dpi) data = self.section.contents objects = [i['name'] for i in data] y_axis = [i for i in range(len(objects))] x_axis = [i['data'][0] for i in data] colors = get_colors(self.section.layout, objects) rects = plt.bar(y_axis, x_axis, align='center', alpha=DEFAULT_BAR_ALPHA, width=DEFAULT_BAR_WIDTH, color=colors) ax = plt.gca() remove_plot_borders(ax) # Fix the legend values to be "some_value (some_number)" instead of # just "some_value" ledgend_keys = [ CHART_LABEL_NONE_STRING if i == '' else i for i in objects ] fixed_legends = [ f'{v} ({x_axis[i]})' for i, v in enumerate(ledgend_keys) ] # Move legend legend_location = 'upper center' legend_location_relative_to_graph = (0.5, -0.35) a = ax.legend(rects, fixed_legends, loc=legend_location, bbox_to_anchor=legend_location_relative_to_graph, handlelength=0.7) self.section = change_legend_vertical_alignment(self.section, top=3) set_legend_style(a, self.section.layout[LEGEND_STYLE]) ax.set_xlim(-len(objects), len(objects)) set_axis_font(ax) plt.xticks(y_axis, objects) plt.title(self.section.extra['title'], **self.style['title']) plt_b64 = utils.plt_t0_b64(plt) s = Section('image', plt_b64, {}, {'should_shrink': True}) image.invoke(self.cell_object, s)
def insert(self): if DEBUG: print('Adding pie chart: ...') size_w, size_h, dpi = utils.convert_plt_size(self.section) fig, ax = plt.subplots(figsize=(size_w, size_h), dpi=dpi, subplot_kw=dict(aspect="equal")) data = [int(i['data'][0]) for i in self.section.contents] objects = [i['name'] for i in self.section.contents] # Fix the unassigned key: objects = [i if i != "" else "Unassigned" for i in objects] # Generate the default colors colors = get_colors(self.section.layout, objects) unassigned_color = 'darkgrey' # If we have predefined colors, use them if 'legend' in self.section.layout and self.section.layout['legend']: for i in self.section.layout['legend']: if 'color' in i: colors.append(i['color']) elif 'fill' in i: colors.append(i['fill']) color_keys = {} for i, k in enumerate(objects): color_keys[k] = colors[i] if k == 'Unassigned': color_keys['Unassigned'] = unassigned_color final_colors = [color_keys[k] for k in objects] wedges, texts = ax.pie(data, colors=final_colors, startangle=90, pctdistance=0.85, textprops=dict(color="w"), radius=1) keys_with_numbers = ['{}: {}'.format(k, data[i]) for i, k in enumerate(objects)] # legend_location_relative_to_graph = (1, 0, 0.5, 1) # legend_location = self.section.layout['legendStyle'] legend_location = 'upper center' legend_location_relative_to_graph = (0.5, 0) legend = ax.legend(wedges, keys_with_numbers, title="", loc=legend_location, bbox_to_anchor=legend_location_relative_to_graph, handlelength=0.7 ) set_legend_style(legend, self.section.layout[LEGEND_STYLE]) set_axis_font(ax) ax.set_title(self.section.extra['title'], **self.style['title']) circle = plt.Circle((0, 0), 0.7, fc='white') ax.add_artist(circle) plt_b64 = utils.plt_t0_b64(plt) s = Section('image', plt_b64, {}, {'should_shrink': True}) image.invoke(self.cell_object, s)
def insert(self): """ This is a bar chart on the side (bar goes right) """ if DEBUG: print("Adding a bar chart") # Fix sizing size_w, size_h, dpi = utils.convert_plt_size(self.section, self.cell_object) plt.figure(figsize=(size_w, size_h), dpi=dpi) data = self.section.contents x_axis = None if any([True for i in data if 'groups' in i and i['groups']]): # Note for future maintainer, I really really... hate stacked # bar charts, it made this file look like hell. I hope you cope # with matplotlib's shitt* implementation. # May the force be with you :pray: # Create the stacks agg = [] y_axis = [i['name'] for i in data] max_labels_stacked = [] for v in data: names = [i['name'] for i in v['groups']] max_labels_stacked = list(set(max_labels_stacked) | set(names)) labels = sorted(max_labels_stacked) colors = get_colors(self.section.layout, labels) for v in data: current_labels = {i['name']: i['data'][0] for i in v['groups']} cols = [] for l in labels: if l in current_labels: cols.append(current_labels[l]) else: cols.append(0) agg.append(cols) stacked = [i for i in zip(*agg)] # Draw each stack rects = [ plt.barh(y_axis, stacked[0], DEFAULT_BAR_WIDTH, color=colors.pop(0)) ] for i in range(1, len(stacked)): left_padding = [sum(i) for i in zip(*stacked[:i])] rects.append( plt.barh(y_axis, stacked[i], DEFAULT_BAR_WIDTH, left=left_padding, color=colors.pop(0))) ax = plt.gca() legend_location = 'upper center' legend_location_relative_to_graph = (0.5, -0.35) a = ax.legend(rects, labels, loc=legend_location, bbox_to_anchor=legend_location_relative_to_graph, handlelength=0.7) else: objects = [i['name'] for i in data] colors = get_colors(self.section.layout, objects) y_axis = [i for i in range(len(objects))] x_axis = [i['data'][0] for i in data] # Fix height of bar when only one present if len(objects) == 1: plt.margins(y=2) rects = plt.barh(y_axis, width=x_axis, align='center', alpha=DEFAULT_BAR_ALPHA, color=colors, height=DEFAULT_BAR_WIDTH) # Fix the legend values to be "some_value (some_number)" instead of # just "some_value" ledgend_keys = [ CHART_LABEL_NONE_STRING if i == '' else i for i in objects ] fixed_legends = [ f'{v} ({x_axis[i]})' for i, v in enumerate(ledgend_keys) ] # Create and move the legend outside ax = plt.gca() legend_location = 'upper center' legend_location_relative_to_graph = (0.5, -0.35) a = ax.legend(rects, fixed_legends, loc=legend_location, bbox_to_anchor=legend_location_relative_to_graph, handlelength=0.7) ax.set_yticklabels([]) # Style the axis and labels self.section = change_legend_vertical_alignment(self.section, top=1) set_legend_style(a, self.section.layout[LEGEND_STYLE]) # Fix the axises set_axis_font(ax) ax.set_yticks(y_axis) ax.set_xlabel('') ax.invert_yaxis() # labels read top-to-bottom # Fix the xaxis ratio to fit biggest element if x_axis: ax.set_xlim(0, max(x_axis) + X_AXIS_PADDING) # Remove the bottom labels remove_plot_borders(ax) plt.tick_params(bottom='off') plt.title(self.section.extra['title'], **self.style['title']) plt_b64 = utils.plt_t0_b64(plt, (size_w, size_h), dpi) s = Section('image', plt_b64, {}, {'should_shrink': True}) image.invoke(self.cell_object, s)
def insert(self): if DEBUG: print("Adding line chart...") # Fix sizing size_w, size_h, dpi = utils.convert_plt_size(self.section, self.cell_object) figure(num=2, figsize=(size_w, size_h), dpi=dpi, constrained_layout=False) data = self.section.contents fix_data(data) # Make the groups look like: # groups = { # 'Type A': { # dates: ['2000', '2001', '2002'] # values: ['1', '2', '3'] # } # 'Type B': { # dates: ['2000', '2001', '2002'], # values : ['4', '5', '6'] # } groups = fix_data(data) # Fix empty key if '' in groups.keys(): groups['None'] = groups.pop('') # Generate the default colors colors = get_colors(self.section.layout, groups.keys()) unassigned_color = 'darkgrey' # If we have predefined colors, use them if 'legend' in self.section.layout and self.section.layout['legend']: for i in self.section.layout['legend']: if 'color' in i: colors.append(i['color']) elif 'fill' in i: colors.append(i['fill']) color_keys = {} for i, k in enumerate(groups.keys()): color_keys[k] = colors[i] if k == 'Unassigned': color_keys['Unassigned'] = unassigned_color final_colors = {k: color_keys[k] for k in groups.keys()} # Plot the lines for group, line in groups.items(): x_axis = line['dates'] y_axis = line['values'] plt.plot(x_axis, y_axis, marker='', color=final_colors[group], linewidth=2) # Create and move the legend outside ax = plt.gca() # Auto rotate the labels remove_plot_borders(ax) legend_location = 'upper center' legend_location_relative_to_graph = (0.5, -0.35) handles = [plt.Rectangle((0, 0), 1, 1, fc=final_colors[i]) for i in groups.keys()] legend = ax.legend(handles, [i for i in groups.keys()], loc=legend_location, bbox_to_anchor=legend_location_relative_to_graph, handlelength=0.7, handleheight=0.7, ncol=2) self.section = change_legend_vertical_alignment(self.section, top=1) # Set max ticks in xaxis to be MAX_AXIS_LABELS set_legend_max_count(ax, self.cell_object) set_legend_style(legend, self.section.layout[LEGEND_STYLE]) set_axis_font(ax) ax.set_title(self.section.extra['title'], **self.style['title']) # Add to docx as image plt_b64 = utils.plt_t0_b64(plt, (size_w, size_h), dpi) s = Section('image', plt_b64, {}, {'should_shrink': True}) image.invoke(self.cell_object, s)