Esempio n. 1
0
def output_graphs(filename: str, summary: ExpenseSummaryMatrix) -> None:
    plt.rcParams["figure.figsize"] = (11.69, 8.27)  # A4 size

    # Sort the categories from highest to lowest amount of expenses
    totals = summary.totals_by_category()
    summary.expenses = dict(
        sorted(summary.expenses.items(),
               key=lambda item: totals[item[0]],
               reverse=True))

    with PdfPages(filename, metadata={"Title": "SettleUpGraphs"}) as pdf:
        pdf.savefig(pie_chart_by_category(summary))
        pdf.savefig(bar_chart_by_category(summary))
        pdf.savefig(stacked_bar_chart_by_name(summary))
Esempio n. 2
0
def output_graphs(filename: str, summary: ExpenseSummaryMatrix) -> None:
    # Sort the categories from highest to lowest amount of expenses
    totals = summary.totals_by_category()
    summary.expenses = dict(
        sorted(summary.expenses.items(), key=lambda item: totals[item[0]], reverse=True)
    )

    grid = gridplot(
        [
            [pie_chart_by_category(summary)],
            [bar_chart_by_category(summary)],
            [stacked_bar_chart_by_name(summary)],
        ]
    )
    save(grid, title="SettleUpGraphs", filename=filename, resources=INLINE)
Esempio n. 3
0
def bar_chart_by_category(summary: ExpenseSummaryMatrix) -> Figure:
    totals = summary.totals_by_category()
    categories = list(totals.keys())

    data_source = {
        "category": categories,
        "amount": [totals[category] for category in categories],
    }
    data_source["color"] = color_palette(len(categories))

    chart = figure(
        title=i18n.t("title.by_category"),
        toolbar_location=None,
        tools="hover",
        tooltips="@amount{0,0.00}",
        x_range=categories,
        width=1000,
        height=600,
    )

    chart.vbar(x="category", top="amount", width=0.8, color="color", source=data_source)

    # Increase the font size
    chart.title.text_font_size = TITLE_FONT_SIZE
    chart.axis.major_label_text_font_size = LEGEND_FONT_SIZE

    # Make the graph more beautiful
    chart.y_range.start = 0  # Let the bars start at the bottom
    chart.x_range.range_padding = 0.1  # Add horizontal padding
    chart.xgrid.grid_line_color = None  # Hide the vertical grid lines
    chart.axis.minor_tick_line_color = None  # Hide all minor ticks
    chart.outline_line_color = None  # Hide the outline

    return chart
Esempio n. 4
0
def bar_chart_by_category(summary: ExpenseSummaryMatrix) -> Figure:
    totals = summary.totals_by_category()
    categories = list(totals.keys())
    amounts = [totals[category] for category in categories]

    fig, ax = plt.subplots()
    ax.bar(categories, amounts)
    ax.set_title(i18n.t("title.by_category"))
    add_value_labels(ax)

    return fig
Esempio n. 5
0
def pie_chart_by_category(summary: ExpenseSummaryMatrix) -> Figure:
    # Pie chart, where the slices will be ordered and plotted counter-clockwise:
    totals = summary.totals_by_category()
    categories = list(totals.keys())
    amounts = [totals[category] for category in categories]

    fig, ax = plt.subplots()
    patches, *_ = ax.pie(amounts, autopct="%1.1f%%")

    ax.set_title(i18n.t("title.by_category"))
    ax.legend(patches, categories)
    ax.axis(
        "equal")  # Equal aspect ratio ensures that pie is drawn as a circle.

    return fig
Esempio n. 6
0
def pie_chart_by_category(summary: ExpenseSummaryMatrix) -> Figure:
    totals = summary.totals_by_category()
    categories = list(totals.keys())

    data_source = {
        "category": categories,
        "amount": [totals[category] for category in categories],
        "angle": [
            totals[category] / sum(totals.values()) * 2 * math.pi
            for category in categories
        ],
    }
    data_source["color"] = color_palette(len(categories))

    chart = figure(
        title=i18n.t("title.by_category"),
        toolbar_location=None,
        tools="hover",
        tooltips="@category: @amount{0,0.00}",
        x_range=(-1.7, 2.2),
        width=1000,
        height=600,
    )

    chart.wedge(
        x=0,
        y=0,
        radius=0.9,
        start_angle=cumsum("angle", include_zero=True),
        end_angle=cumsum("angle"),
        line_color="white",
        fill_color="color",
        legend_field="category",
        source=data_source,
    )

    # Increase the font size
    chart.title.text_font_size = TITLE_FONT_SIZE
    chart.legend.label_text_font_size = LEGEND_FONT_SIZE

    # Make the graph more beautiful
    chart.axis.axis_label = None  # Hide the axis labels
    chart.axis.visible = False  # Hide the axes
    chart.grid.grid_line_color = None  # Hide the grid
    chart.outline_line_color = None  # Hide the outline

    return chart
Esempio n. 7
0
def stacked_bar_chart_by_name(summary: ExpenseSummaryMatrix) -> Figure:
    categories = list(summary.expenses)
    names = sorted(summary.names())

    amounts = np.array([[0 for name in names]] +
                       [[summary.expenses[category][name] for name in names]
                        for category in categories])
    # Build the cumulative sums over the columns
    bar_heights = np.cumsum(amounts, axis=0)

    fig, ax = plt.subplots()
    for i, category in enumerate(categories):
        ax.bar(names, amounts[i + 1], bottom=bar_heights[i], label=category)
    ax.set_title(i18n.t("title.by_name_by_category"))
    add_value_labels(ax, last=len(names))
    ax.legend()

    return fig
Esempio n. 8
0
def stacked_bar_chart_by_name(summary: ExpenseSummaryMatrix) -> Figure:
    categories = list(summary.expenses)
    names = sorted(summary.names())

    data_source = {"names": names}
    data_source.update(
        {
            category: [summary.expenses[category][name] for name in names]
            for category in categories
        }
    )

    chart = figure(
        title=i18n.t("title.by_name_by_category"),
        toolbar_location=None,
        tools="hover",
        tooltips="$name: @$name{0,0.00}",
        x_range=names,
        width=1000,
        height=600,
    )

    chart.vbar_stack(
        categories,
        x="names",
        width=0.8,
        color=color_palette(len(categories)),
        source=data_source,
    )

    # Increase the font size
    chart.title.text_font_size = TITLE_FONT_SIZE
    chart.axis.major_label_text_font_size = LEGEND_FONT_SIZE

    # Make the graph more beautiful
    chart.y_range.start = 0  # Let the bars start at the bottom
    chart.x_range.range_padding = 0.1  # Add horizontal padding
    chart.xgrid.grid_line_color = None  # Hide the vertical grid lines
    chart.axis.minor_tick_line_color = None  # Hide all minor ticks
    chart.outline_line_color = None  # Hide the outline

    return chart
Esempio n. 9
0
        "-o",
        action="store",
        metavar="OUTPUT_FILE",
        dest="output_file",
        default=None,
        help='The output file (default: "SettleUpGraphs(.html|.pdf)")',
    )
    arguments = parser.parse_args()

    raw_transactions = RawTransaction.from_file(arguments.input_file)
    transactions = (
        Transaction.from_raw_transaction(raw)
        for raw in raw_transactions
        if raw.type != "transfer"
    )
    summary = ExpenseSummaryMatrix.from_transactions(transactions)

    i18n.load_path.append("translations")
    preferred_locale = locale.setlocale(locale.LC_MESSAGES, "")
    i18n.set("locale", arguments.language or preferred_locale[:2])
    # 'en' is automatically set as a fallback

    if arguments.translate_emojis:
        # Translate the emojis to text
        summary.expenses = {
            i18n.t("emoji." + (category or "none")): amounts
            for category, amounts in summary.expenses.items()
        }

    if arguments.backend == "bokeh":
        arguments.output_file = arguments.output_file or "SettleUpGraphs.html"