6 import matplotlib.pyplot as plt
7 from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
11 from cStringIO import StringIO
12 from pylons import request, response
14 from bluechips.lib.base import *
15 import bluechips.lib.totals
16 from bluechips import model
17 from bluechips.model import meta, orm, User, Expenditure, Split, Transfer
21 def get_share(transaction, user):
22 if type(transaction) == Expenditure:
23 amount = transaction.share(user)
24 if transaction.spender == user:
25 amount -= transaction.amount
28 if user == transaction.debtor:
29 return -transaction.amount
30 elif user == transaction.creditor:
31 return transaction.amount
33 return model.types.Currency(0)
35 class GraphController(BaseController):
38 Create a plot showing the net balance for each user over the
42 users = meta.Session.query(User).filter(User.resident==True).all()
43 expenditures = meta.Session.query(Expenditure).\
44 options(orm.eagerload_all(Expenditure.splits, Split.user)).\
46 transfers = meta.Session.query(Transfer).\
47 options(orm.eagerload(Transfer.debtor, Transfer.creditor)).\
50 transactions = expenditures + transfers
51 transactions.sort(key=lambda x: x.date)
55 dates = [t.date for t in transactions]
57 totals[u.name] = np.cumsum([get_share(t,u) for t in transactions])
61 canvas = FigureCanvas(fig)
62 ax = fig.add_subplot(1,1,1)
63 ax.set_color_cycle(plt.cm.jet(np.linspace(0,1,len(users))))
66 for u,y in totals.items():
67 lines[u] = plt.step(dates,totals[u], label=u, lw=2)
72 ax.set_xlim(xmin=datetime.date.today()-datetime.timedelta(days=365))
74 fig.autofmt_xdate(rotation=30)
75 ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter("%h"))
76 ax.set_yticklabels(map(lambda x: '%s$%i'%('-' if x<0 else '',abs(x)//100),
77 ax.yaxis.get_majorticklocs()))
81 canvas.print_figure(s)
82 response.headers['Content-Type'] = 'image/png'
84 # print t1-t0, t2-t1, t3-t2, t4-t3
88 ruser = request.environ['user']
96 eps = model.types.Currency("2.00")
97 net = bluechips.lib.totals.debts().items()
98 net.sort(key=lambda x: x[1])
99 for user, amount in net:
101 debtors.append(user.name)
103 explode_debt.append(0.1 if user == ruser else 0)
105 creditors.append(user.name)
106 credits.append(-amount)
107 explode_credit.append(0.1 if user == ruser else 0)
109 fig = plt.figure(figsize=(6,3))
110 canvas = FigureCanvas(fig)
112 ax1 = fig.add_axes([0.05,0.1,0.4,0.8])
114 explode=explode_debt,
116 colors=plt.cm.YlOrRd(np.linspace(0.05,0.95,len(debtors))))
117 ax1.set_title('Debtors')
119 ax2 = fig.add_axes([0.55,0.1,0.4,0.8])
121 explode=explode_credit,
123 colors=plt.cm.Blues(np.linspace(0.05,0.95,len(creditors))))
124 ax2.set_title('Creditors')
126 # ax.legend(loc='best')
129 # ax.set_xlim(xmin=datetime.date.today()-datetime.timedelta(days=365))
130 # ax.set_ylim(ymin=0)
131 # fig.autofmt_xdate(rotation=30)
132 # ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter("%h"))
133 # ax.set_yticklabels(map(lambda x: '%s$%i'%('-' if x<0 else '',abs(x)//100),
134 # ax.yaxis.get_majorticklocs()))
137 canvas.print_figure(s, dpi=72)
138 response.headers['Content-Type'] = 'image/png'