import holoviews as hv import pandas as pd from django.utils import timezone from math import pi from bokeh.models import HoverTool from bokeh.plotting import figure from bokeh.transform import cumsum from bokeh.layouts import 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 activity not 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") 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)