Esempio n. 1
0
    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)
Esempio n. 2
0
    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)
Esempio n. 3
0
    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)
Esempio n. 4
0
    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)