Using a Python script to generate Cumulative Flow Diagrams

Cumulative Flow Diagram is a graphical tool used extensively in Lean and Agile projects. It is used to track project progress, visualize work in progress (WIP) and obtain understanding of issues with the project including bottlenecks & scope changes.

CFD generated using Spyder 2 IDE with matplotlib and numpy modules
CFD generated using Spyder 2 IDE with matplotlib and numpy modules

Burn Up and Burn Down charts are much more commonly used by Agile teams than Cumulative Flow Diagrams (CFD) because they can be easily plotted on a white board using a marker pen. In the case of CFDs, it is not easy to plot it manually on a white board  and so many teams therefore, have to procure software, even when the team is co-located just for the sake of generating plots.

There is a way to plot CFDs using excel described here, but to automate it we need to script it. This article describes a very simple way to generate CFDs using a python script.

The input to this script is hard-coded in the form of arrays for each status, but these can be easily replaced by variables input from a web form.

The Kanban flow for this specific case has Requirements, Development, Testing, Verification and Done indicated by the arrays features_req, features_dev, features_tst, features_vfy and features_dne which contain the values from Week 1 (W1) to Week 12 (W12). The arrays are as below which forms a matrix.


 #Weeks ->     W1,W2,W3,W4,W5,W6,W7,W8,W9,W10,W11, W12
features_req = [1, 1, 4, 3, 1, 1, 0, 0, 0, 0,  0,   0]
features_dev = [0, 1, 2, 2, 3, 2, 2, 1, 1, 0,  0,   0]
features_tst = [0, 0, 0, 1, 1, 2, 2, 2, 1, 2,  0,   0]
features_vfy = [0, 0, 0, 0, 1, 1, 2, 2, 3, 1,  2,   0]
features_dne = [0, 0, 0, 0, 0, 0, 0, 1, 1, 3,  4,   6]


I will describe in detail the data (above) giving examples of the Kanban board for that week.

The Board has just one feature request in the first week.
Kanban Board – Week 1

The status of the board for a week should be read in vertical for that week. e.g. For week 1, there is just one feature request as indicated by the values in the column for W1 (Week 1) -> 1,0,0,0,0.

Kanban Board - Week 2
Kanban Board – Week 2

For Week 2, a new feature request has been made which arrives in the first column (Requirements). The first feature request has now been pulled into the development stage and is been worked on. So the column for W2 (Week 2) has the values -> 1,1,0,0,0

Kanban Board - Week 3
Kanban Board – Week 3

In the third week (Week 3), four feature requests have come into the first column (Requirements), the one request which had come in the last week is moved to Development so that you now have a total of two features in development. So the column W3 has the values -> 4,2,0,0,0.

Kanban Board - Week 12
Kanban Board – Week 12

The last column in the matrix has the values for Week 12 (W12), which is 0,0,0,0,6 and the corresponding Kanban board shows all the items (6) in the Done column.

This basically means that there is one-to-one correspondence between the column for that week and the Kanban board columns. It is straight forward to construct this matrix for your specific use case even to have a similar web form constructed to feed in the data representing the Kanban board.

The script uses python with matplotlib and numpy. The plot was generated using iPython in Spyder2 IDE. The script is as below.

import numpy as np
from matplotlib import pyplot as plt

weeks = np.arange(1,13,1)
#Weeks -> W1,W2,W3,W4,W5,W6,W7,W8,W9,W10,W11, W12
features_req = [1, 1, 4, 3, 1, 1, 0, 0, 0, 0, 0, 0]
features_dev = [0, 1, 2, 2, 3, 2, 2, 1, 1, 0, 0, 0]
features_tst = [0, 0, 0, 1, 1, 2, 2, 2, 1, 2, 0, 0]
features_vfy = [0, 0, 0, 0, 1, 1, 2, 2, 3, 1, 2, 0]
features_dne = [0, 0, 0, 0, 0, 0, 0, 1, 1, 3, 4, 6]
features = np.row_stack((features_dne, features_vfy, features_tst,
features_dev, features_req))

fig, ax = plt.subplots()
ax.stackplot(weeks, features)

# Add relevant y and x labels and text to the plot
plt.title('Cumulative Flow Diagram')
ax.set_ylabel('Features')
ax.set_xlabel('Weeks')
ax.set_xlim(1, 12)
ax.set_ylim(0, 6)

plt.show()

You can download it from here.