74 lines
2.4 KiB
Python
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)
|