|
@@ -14,6 +14,7 @@ from bottle import (
|
|
|
)
|
|
|
import matplotlib.pyplot as plt
|
|
|
import matplotlib
|
|
|
+import numpy as np
|
|
|
from pandas import DataFrame
|
|
|
import seaborn as sns
|
|
|
from psycopg import Connection
|
|
@@ -37,7 +38,7 @@ matplotlib.use('agg')
|
|
|
plot_style = {
|
|
|
"lines.color": "#ffffff",
|
|
|
"patch.edgecolor": "#ffffff",
|
|
|
- "text.color": "#000000",
|
|
|
+ "text.color": "#ffffff",
|
|
|
"axes.facecolor": "#7f7f7f",
|
|
|
"axes.edgecolor": "#ffffff",
|
|
|
"axes.labelcolor": "#ffffff",
|
|
@@ -208,34 +209,57 @@ def volume_internal(conn: Connection[TupleRow], path: str, query: FormsDict):
|
|
|
plt.style.use("dark_background")
|
|
|
plt.rcParams.update(plot_style)
|
|
|
plt.rcParams.update({"grid.linewidth":0.2, "grid.alpha":0.5})
|
|
|
- plt.figure(figsize=[16, 9], layout="tight")
|
|
|
- axes = pivot.plot.pie(subplots=True, figsize=(11, 5), labeldistance=1.1, autopct='%.0f', pctdistance=0.8, rotatelabels=False)
|
|
|
-
|
|
|
- for ax, title in zip(axes, (
|
|
|
- f'Expenditure ($)',
|
|
|
- f'Quantity ({unit})',
|
|
|
- )):
|
|
|
+ svg = []
|
|
|
+ for title, col, (pre, fmt, suf) in zip((
|
|
|
+ f"Expenditure ${pivot['price'].sum():0.2f}",
|
|
|
+ f"Quantity {pivot['quantity'].sum():0.1f} {unit}",
|
|
|
+ ), (
|
|
|
+ 'price',
|
|
|
+ 'quantity'
|
|
|
+ ), [
|
|
|
+ ('$', "{0:0.2f}", ''),
|
|
|
+ ('', "{0:0.1f}", f' {unit}')
|
|
|
+ ]):
|
|
|
+ plt.figure(figsize=[16, 9], layout="tight")
|
|
|
+ ax = plt.axes()
|
|
|
+ wedges, *_ = ax.pie(pivot[col].values, startangle=90)
|
|
|
+ bbox_props = dict(boxstyle="square,pad=0.3", lw=0.72, fc='#5f5f5f', ec=plot_style["axes.edgecolor"])
|
|
|
+ kw = dict(arrowprops=dict(arrowstyle="-"),
|
|
|
+ bbox=bbox_props, zorder=0, va="center")
|
|
|
+ for i, p in enumerate(wedges):
|
|
|
+ ang = (p.theta2 - p.theta1)/2. + p.theta1
|
|
|
+ y = np.sin(np.deg2rad(ang))
|
|
|
+ x = np.cos(np.deg2rad(ang))
|
|
|
+ horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))]
|
|
|
+ connectionstyle = f"angle,angleA=0,angleB={ang}"
|
|
|
+ kw["arrowprops"].update({"connectionstyle": connectionstyle})
|
|
|
+ label = pivot.index[i]
|
|
|
+ val = pivot.loc[label, col]
|
|
|
+ label = f"{label} {pre}{fmt.format(val)}{suf} ({val*100/pivot[col].sum():0.1f}%)"
|
|
|
+ ax.annotate(label, xy=(x, y), xytext=(1.35*np.sign(x), 1.4*y),
|
|
|
+ horizontalalignment=horizontalalignment, **kw)
|
|
|
ax.set_title(title)
|
|
|
xlabel=''
|
|
|
ylabel=''
|
|
|
ax.legend().set_visible(False)
|
|
|
- ax.legend().set_visible(False)
|
|
|
|
|
|
ax.set_xlabel(xlabel, fontsize="14")
|
|
|
ax.set_ylabel(ylabel, fontsize="14")
|
|
|
ax.axes.tick_params(labelsize="12", which='both')
|
|
|
|
|
|
- progress.update({ "stage": "Rendering chart", "percent": "50"})
|
|
|
- yield template("done") + template("progress", **progress)
|
|
|
-
|
|
|
- f = StringIO()
|
|
|
- plt.savefig(f, format='svg')
|
|
|
+ progress.update({ "stage": "Rendering chart", "percent": "50"})
|
|
|
+ yield template("done") + template("progress", **progress)
|
|
|
+
|
|
|
+ f = StringIO()
|
|
|
+ plt.savefig(f, format='svg')
|
|
|
+ svg.append(f.getvalue())
|
|
|
+
|
|
|
progress.update({ "stage": "Done", "percent": "100" })
|
|
|
yield template("done") + template("progress", **progress)
|
|
|
|
|
|
form = get_form(action, 'post', _filter, organic, data)
|
|
|
|
|
|
- yield template("trend", end=True, form=form, svg=f.getvalue())
|
|
|
+ yield template("volume", end=True, form=form, svg=svg)
|
|
|
|
|
|
except HTTPError as e:
|
|
|
if 'data' not in locals():
|