Skip to content

Instantly share code, notes, and snippets.

@zeimusu
Forked from t2ru/gantt
Last active August 29, 2015 14:14
Show Gist options
  • Save zeimusu/4025ca704680eed12083 to your computer and use it in GitHub Desktop.
Save zeimusu/4025ca704680eed12083 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime as dt
import numpy
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.dates as md
import locale
from functools import reduce
locale.setlocale(locale.LC_ALL, "")
matplotlib.rcParams['font.family']='sans'
today = '2014-01-01'
#task pl_start pl_end ac_start ac_end progress
data = """
A 2012-11-01 2012-12-31 2012-11-01 2012-12-31 1
B 2013-01-01 2013-03-14 2013-01-01 2013-03-14 1
C 2013-03-15 2014-04-30 2013-03-15 - .7
D 2013-05-01 2013-06-30 2013-05-01 2013-06-30 1
E 2013-07-01 2013-08-31 2013-07-01 2013-08-31 1
F1 2013-09-01 2013-10-31 2013-09-01 2013-10-31 1
F2 2013-09-01 2014-01-17 2013-09-01 - .8
F3 2013-09-01 2014-01-30 2013-09-01 - .8
F4 2013-09-01 2014-03-31 2013-09-01 - .6
G1 2013-11-01 2013-11-27 2013-11-01 2013-11-27 1
G2 2013-11-01 2014-01-17 2013-11-01 - .8
L 2013-11-28 2013-12-19 2013-11-28 - 0
M 2013-11-28 2014-01-17 2013-11-28 - .6
N 2013-12-04 2014-03-02 2013-12-04 - .3
O 2013-12-20 2014-01-17 2013-12-20 - .3
P 2013-12-20 2014-02-16 2013-12-20 - .2
Q 2014-01-05 2014-01-13 2013-12-25 - 1
R 2014-01-18 2014-01-30 2013-12-18 - .5
S 2014-01-31 2014-03-31 - - 0
T 2014-03-01 2014-04-28 - - 0
"""
datefmt = "%Y-%m-%d"
today = dt.datetime.strptime(today, datefmt)
data = [x.split() for x in data.split('\n')]
data = [x for x in data if len(x) == 6]
data = [{
'label': x[0],
'planned_start': dt.datetime.strptime(x[1], datefmt),
'planned_end': dt.datetime.strptime(x[2], datefmt) + dt.timedelta(1),
'actual_start': today if x[3] == '-' else
dt.datetime.strptime(x[3], datefmt),
'actual_end': today if x[4] == '-' else
dt.datetime.strptime(x[4], datefmt) + dt.timedelta(1),
'progress': float(x[5]),
} for x in data]
for x in data:
s = x['planned_start']
e = x['planned_end']
r = x['progress']
x.update(progress_date=s+(e-s)*r)
for x in data:
s = x['actual_start']
e = x['actual_end']
x.update(actual_end=e if e > s else s)
fig, ax = plt.subplots()
ax.hlines(
[x - 0.2 for x in range(len(data))],
[x['planned_start'] for x in data],
[x['planned_end'] for x in data],
linewidth=3, color='black', label='plan')
ax.hlines(
[x for x in range(len(data))],
[x['planned_start'] for x in data],
[x['progress_date'] for x in data],
linewidth=3, color='blue', label='Progress')
ax.hlines(
[x + 0.2 for x in range(len(data))],
[x['actual_start'] for x in data],
[x['actual_end'] for x in data],
linewidth=3, color='red', label='Performance')
def is_lightening(x, today):
p = x['progress']
return p > 0 and p < 1 \
or p > 0 and x['progress_date'] > today \
or p < 1 and x['progress_date'] < today
lightening = [
[(today, idx - 0.5), (today, idx - 0.3),
(x['progress_date'] if is_lightening(x, today) else today, idx),
(today, idx + 0.3), (today, idx + 0.5)]
for idx, x in enumerate(data)]
lightening = reduce(lambda x, y: x + y, lightening)
ax.plot(
[x[0] for x in lightening],
[x[1] for x in lightening],
linewidth=1, color='blue')
ax.xaxis.set_major_formatter(md.DateFormatter('%Y-%m'))
ax.xaxis.set_major_locator(md.MonthLocator())
ax.xaxis.set_minor_locator(md.WeekdayLocator(byweekday=md.MO))
ax.xaxis.grid(b=True)
ax.yaxis.set_ticklabels([x['label'] for x in data])
ax.yaxis.set_ticks([idx for idx, x in enumerate(data)])
ax.yaxis.grid(b=True)
ax.set_ylim(len(data), -1)
ax.legend(loc='lower left')
fig.autofmt_xdate()
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment