This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
eodb/eodb/events/management/commands/punchcard.py

74 lines
2.4 KiB
Python

import matplotlib.pyplot as plt
import numpy as np
from .common import GraphCommand
class Command(GraphCommand):
def handle(self, *args, **options):
infos = {}
for i in range(7):
for j in range(24):
infos[(i, j)] = 0
def hour_shift(x):
x = x - 4
if x < 0:
x += 24
return x
for commit in self.get_events(options):
coords = (
self.get_event_datetime(commit, options).weekday(),
hour_shift(self.get_event_datetime(commit, options)).hour))
infos[coords] = infos[coords] + 1
draw_punchcard(infos,
ax2_ticks=list(range(4, 24)) + list(range(4)))
self.plot(options)
# https://stackoverflow.com/a/14850998
def draw_punchcard(infos,
ax1=range(7),
ax2=range(24),
ax1_ticks=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
ax2_ticks=range(24),
ax1_label='Day',
ax2_label='Hour'):
# - infos: Dictionary of quantities to display.
# They are indexed by key of type (val1,val2) with
# val1 included in ax1 and val2 included in ax2.
# build the array which contains the values
data = np.zeros((len(ax1),len(ax2)))
for key in infos:
data[key[0],key[1]] = infos[key]
data = data/float(np.max(data))
# shape ratio
r = float(data.shape[1])/data.shape[0]
# Draw the punchcard (create one circle per element)
# Ugly normalisation allows to obtain perfect circles instead of ovals....
for y in range(data.shape[0]):
for x in range(data.shape[1]):
circle = plt.Circle((x/float(data.shape[1]-1)*(data.shape[0]-1),y/r),
data[y][x]/float(data.shape[1])*data.shape[0]/2)
plt.gca().add_artist(circle)
plt.ylim(0-0.5, data.shape[0]-0.5)
plt.xlim(0, data.shape[0])
plt.yticks(np.arange(0,len(ax1)/r-.1,1/r), ax1_ticks)
xt = np.linspace(0, len(ax1)-1, len(ax2))
plt.xticks(xt, ax2_ticks)
plt.xlabel(ax2_label)
plt.ylabel(ax1_label)
plt.gca().invert_yaxis()
# make sure the axes are equal, and resize the canvas to fit the plot
plt.axis('equal')
plt.axis([-1, 7, 7/r, -1])
scale = 1 #0.5
plt.gcf().set_size_inches(data.shape[1]*scale,data.shape[0]*scale, forward=True)