diff options
author | Ben Sima <ben@bsima.me> | 2018-12-12 14:11:48 -0800 |
---|---|---|
committer | Ben Sima <ben@bsima.me> | 2018-12-12 14:11:48 -0800 |
commit | 0a96d4a7eb89c23488ea945281ca7e75124cb64d (patch) | |
tree | 45da093002f47c78034cc4239c1caca9f7f22da3 /org-chart.py | |
parent | e2ce71b7fe5450099b84705a222bf1134247019f (diff) |
Add org-chart.py
Diffstat (limited to 'org-chart.py')
-rwxr-xr-x | org-chart.py | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/org-chart.py b/org-chart.py new file mode 100755 index 0000000..67a3883 --- /dev/null +++ b/org-chart.py @@ -0,0 +1,60 @@ +#! /usr/bin/env nix-shell +#! nix-shell -i python -p "python3.withPackages(p: [p.matplotlib])" + +import re +import sys +import math +import argparse +import fileinput +import matplotlib.pyplot as plt + +# Complex regex that grabs two match groups: category and %, but it ignores rows +# with a headline that starts with "\_", thereby selecting only the top-level +# agenda items. +clocktable_row = re.compile( + r"^\|\s*\|\s(\w*(?!.*\_)).*\|.*\s+(\d+\.\d)\s\|$", + re.MULTILINE, +) + +if __name__ == '__main__': + cli = argparse.ArgumentParser(description='Generate a pie chart from your org agenda clocktable') + cli.add_argument('infile', type=argparse.FileType('r'), nargs='?', default='-') + cli.add_argument('outfile', type=argparse.FileType('w'), nargs='?', default=None) + args = cli.parse_args() + + content = args.infile.read() + matches = re.finditer(clocktable_row, content) + + slices = {} + for m in matches: + if m.group(1) == "ALL": continue + k = m.group(1) + v = float(m.group(2)) + if k not in slices: + slices[k] = v + else: + slices[k] += v + + # Round up b/c of floating point arithmetic + total = math.ceil(sum(slices.values())) + if total != 100: + print("Warning: Sum of the slices is {} but it should be 100!".format(total)) + + fig, ax = plt.subplots() + wedges, texts, autotexts = ax.pie( + slices.values(), + labels = slices.keys(), + autopct='%1.1f%%', + textprops=dict(color="w")) + + ax.legend(wedges, slices.keys(), title="Categories", loc="center left", + bbox_to_anchor=(0, 0, 0.5, 1)) + + ax.axis('equal') # Equal aspect ratio ensures pie is drawn as a circle + plt.setp(autotexts, size=8, weight="bold") + ax.set_title("How I spent my time") + + if args.outfile is None: + plt.show() + else: + plt.savefig(args.outfile.name) |