import holoviews as hv import pandas as pd from django.utils import timezone from math import pi from bokeh.models import HoverTool from bokeh.io import output_file, show from bokeh.plotting import figure from bokeh.transform import cumsum from bokeh.layouts import row, column from holoviews.operation import timeseries from dateutil.relativedelta import relativedelta from .models import Status, Mood, StatusActivity def moodstats(user): hv.extension("bokeh") tooltips = [("Date", "@date{%F %H:%M}"), ("Mood", "@name (@value)")] formatters = {"@date": "datetime"} hover = HoverTool(tooltips=tooltips, formatters=formatters) pointdict = {"date": [], "value": [], "color": [], "name": []} for status in Status.objects.filter(user=user): if status.mood: pointdict["date"].append(status.timestamp) pointdict["value"].append(status.mood.value) pointdict["color"].append(status.mood.color) pointdict["name"].append(status.mood.name) pointframe = pd.DataFrame.from_dict(pointdict) points = hv.Points(pointframe) points.opts( tools=[hover], color="color", cmap="Category20", line_color="black", size=25, width=600, height=400, show_grid=True, ) pointtuples = [ (pointdict["date"][i], pointdict["value"][i]) for i in range(len(pointdict["date"])) ] line = hv.Curve(pointtuples) maxval = Mood.objects.filter(user=user).latest("value").value maxy = maxval + max(maxval * 0.1, 1) maxx = timezone.now().timestamp() * 1000 minx = maxx - (60 * 60 * 24 * 7) * 1000 output = points * line * timeseries.rolling(line, rolling_window=7) output.opts(ylim=(0, maxy), xlim=(minx, maxx)) return output def activitystats(user): output = {} for status in Status.objects.filter(user=user): for activity in status.activity_set: if not activity in output.keys(): output[activity] = { "alltime": 0, "yearly": 0, "monthly": 0, "weekly": 0, } output[activity]["alltime"] += 1 if status.timestamp > timezone.now() - relativedelta(years=1): output[activity]["yearly"] += 1 if status.timestamp > timezone.now() - relativedelta(months=1): output[activity]["monthly"] += 1 if status.timestamp > timezone.now() - relativedelta(weeks=1): output[activity]["weekly"] += 1 return output def moodpies(user): hv.extension("bokeh") maxdate = timezone.now() weekly_moods = Status.objects.filter( user=user, timestamp__lte=maxdate, timestamp__gte=maxdate - relativedelta(weeks=1), ) monthly_moods = Status.objects.filter( user=user, timestamp__lte=maxdate, timestamp__gte=maxdate - relativedelta(months=1), ) yearly_moods = Status.objects.filter( user=user, timestamp__lte=maxdate, timestamp__gte=maxdate - relativedelta(years=1), ) weekly = dict() colors = [] for mood in Mood.objects.filter(user=user): weekly[mood.name] = 0 colors.append(mood.color) monthly, yearly = weekly.copy(), weekly.copy() for status in weekly_moods: if status.mood: weekly[status.mood.name] += 1 for status in monthly_moods: if status.mood: monthly[status.mood.name] += 1 for status in yearly_moods: if status.mood: yearly[status.mood.name] += 1 weekly_data = ( pd.Series(weekly).reset_index(name="value").rename(columns={"index": "mood"}) ) weekly_data["angle"] = weekly_data["value"] / weekly_data["value"].sum() * 2 * pi weekly_data["color"] = colors weekly_chart = figure( height=350, title="Weekly", toolbar_location=None, tools="hover", tooltips="@mood: @value", ) weekly_chart.axis.visible = False weekly_chart.wedge( x=0, y=1, radius=0.4, start_angle=cumsum("angle", include_zero=True), end_angle=cumsum("angle"), line_color="white", fill_color="color", legend_label="mood", source=weekly_data, ) monthly_data = ( pd.Series(monthly).reset_index(name="value").rename(columns={"index": "mood"}) ) monthly_data["angle"] = monthly_data["value"] / monthly_data["value"].sum() * 2 * pi monthly_data["color"] = colors monthly_chart = figure( height=350, title="Monthly", toolbar_location=None, tools="hover", tooltips="@mood: @value", ) monthly_chart.axis.visible = False monthly_chart.wedge( x=0, y=1, radius=0.4, start_angle=cumsum("angle", include_zero=True), end_angle=cumsum("angle"), line_color="white", fill_color="color", legend_label="mood", source=monthly_data, ) yearly_data = ( pd.Series(yearly).reset_index(name="value").rename(columns={"index": "mood"}) ) yearly_data["angle"] = yearly_data["value"] / yearly_data["value"].sum() * 2 * pi yearly_data["color"] = colors yearly_chart = figure( height=350, title="Yearly", toolbar_location=None, tools="hover", tooltips="@mood: @value", ) yearly_chart.axis.visible = False yearly_chart.wedge( x=0, y=1, radius=0.4, start_angle=cumsum("angle", include_zero=True), end_angle=cumsum("angle"), line_color="white", fill_color="color", legend_label="mood", source=yearly_data, ) return column(weekly_chart, monthly_chart, yearly_chart) def activitymood(activity): hv.extension("bokeh") tooltips = [("Date", "@date{%F %H:%M}"), ("Mood", "@name (@value)")] formatters = {"@date": "datetime"} hover = HoverTool(tooltips=tooltips, formatters=formatters) pointdict = {"date": [], "value": [], "color": [], "name": []} for statusactivity in StatusActivity.objects.filter(activity=activity): if statusactivity.status.mood: pointdict["date"].append(statusactivity.status.timestamp) pointdict["value"].append(statusactivity.status.mood.value) pointdict["color"].append(statusactivity.status.mood.color) pointdict["name"].append(statusactivity.status.mood.name) pointframe = pd.DataFrame.from_dict(pointdict) points = hv.Points(pointframe) points.opts( tools=[hover], color="color", cmap="Category20", line_color="black", size=25, width=600, height=400, show_grid=True, ) pointtuples = [ (pointdict["date"][i], pointdict["value"][i]) for i in range(len(pointdict["date"])) ] line = hv.Curve(pointtuples) maxval = Mood.objects.filter(user=activity.user).latest("value").value maxy = maxval + max(maxval * 0.1, 1) maxx = timezone.now().timestamp() * 1000 minx = maxx - (60 * 60 * 24 * 7) * 1000 output = points * line * timeseries.rolling(line, rolling_window=7) output.opts(ylim=(0, maxy), xlim=(minx, maxx)) return output def activitypies(activity): hv.extension("bokeh") maxdate = timezone.now() sa = StatusActivity.objects.filter(activity=activity) weekly = dict() colors = [] for mood in Mood.objects.filter(user=activity.user): weekly[mood.name] = 0 colors.append(mood.color) monthly, yearly = weekly.copy(), weekly.copy() for single in sa: if single.status.mood: if single.status.timestamp > timezone.now() - relativedelta(weeks=1): weekly[single.status.mood.name] += 1 if single.status.timestamp > timezone.now() - relativedelta(months=1): monthly[single.status.mood.name] += 1 if single.status.timestamp > timezone.now() - relativedelta(years=1): yearly[single.status.mood.name] += 1 weekly_data = ( pd.Series(weekly).reset_index(name="value").rename(columns={"index": "mood"}) ) weekly_data["angle"] = weekly_data["value"] / weekly_data["value"].sum() * 2 * pi weekly_data["color"] = colors weekly_chart = figure( height=350, title="Weekly", toolbar_location=None, tools="hover", tooltips="@mood: @value", ) weekly_chart.axis.visible = False weekly_chart.wedge( x=0, y=1, radius=0.4, start_angle=cumsum("angle", include_zero=True), end_angle=cumsum("angle"), line_color="white", fill_color="color", legend_label="mood", source=weekly_data, ) monthly_data = ( pd.Series(monthly).reset_index(name="value").rename(columns={"index": "mood"}) ) monthly_data["angle"] = monthly_data["value"] / monthly_data["value"].sum() * 2 * pi monthly_data["color"] = colors monthly_chart = figure( height=350, title="Monthly", toolbar_location=None, tools="hover", tooltips="@mood: @value", ) monthly_chart.axis.visible = False monthly_chart.wedge( x=0, y=1, radius=0.4, start_angle=cumsum("angle", include_zero=True), end_angle=cumsum("angle"), line_color="white", fill_color="color", legend_label="mood", source=monthly_data, ) yearly_data = ( pd.Series(yearly).reset_index(name="value").rename(columns={"index": "mood"}) ) yearly_data["angle"] = yearly_data["value"] / yearly_data["value"].sum() * 2 * pi yearly_data["color"] = colors yearly_chart = figure( height=350, title="Yearly", toolbar_location=None, tools="hover", tooltips="@mood: @value", ) yearly_chart.axis.visible = False yearly_chart.wedge( x=0, y=1, radius=0.4, start_angle=cumsum("angle", include_zero=True), end_angle=cumsum("angle"), line_color="white", fill_color="color", legend_label="mood", source=yearly_data, ) return column(weekly_chart, monthly_chart, yearly_chart)