1
1
#!/usr/bin/env python
2
- """Module for creating Sankey diagrams using matplotlib
2
+ """
3
+ Module for creating Sankey diagrams using matplotlib
3
4
"""
4
5
__author__ = "Kevin L. Davies"
5
6
__credits__ = ["Yannick Copin" ]
40
41
from matplotlib .patches import PathPatch
41
42
from matplotlib .transforms import Affine2D
42
43
from matplotlib import verbose
44
+ from matplotlib import docstring
43
45
44
46
# Angles [deg/90]
45
47
RIGHT = 0
49
51
50
52
51
53
class Sankey :
52
- """Sankey diagram in matplotlib
54
+ """
55
+ Sankey diagram in matplotlib
53
56
54
- "Sankey diagrams are a specific type of flow diagram, in which the width of
55
- the arrows is shown proportionally to the flow quantity. They are typically
56
- used to visualize energy or material or cost transfers between processes."
57
+ Sankey diagrams are a specific type of flow diagram, in which
58
+ the width of the arrows is shown proportionally to the flow
59
+ quantity. They are typically used to visualize energy or
60
+ material or cost transfers between processes.
61
+ `Wikipedia (6/1/2011) <http://en.wikipedia.org/wiki/Sankey_diagram>`_
57
62
58
- --http://en.wikipedia.org/wiki/Sankey_diagram, accessed 6/1/2011
59
63
"""
60
64
def _arc (self , quadrant = 0 , cw = True , radius = 1 , center = (0 ,0 )):
61
65
"""
62
- call signature::
63
-
64
- _arc(quadrant=0, cw=True, radius=1, center=(0,0))
65
-
66
66
Return the codes and vertices for a rotated, scaled, and translated
67
67
90 degree arc.
68
68
@@ -115,7 +115,8 @@ def _arc(self, quadrant=0, cw=True, radius=1, center=(0,0)):
115
115
np .tile (center , (ARC_VERTICES .shape [0 ], 1 )))
116
116
117
117
def _add_input (self , path , angle , flow , length ):
118
- """Add an input to a path and return its tip and label locations.
118
+ """
119
+ Add an input to a path and return its tip and label locations.
119
120
"""
120
121
if angle is None :
121
122
return [0 , 0 ], [0 , 0 ]
@@ -161,7 +162,8 @@ def _add_input(self, path, angle, flow, length):
161
162
return dip , label_location
162
163
163
164
def _add_output (self , path , angle , flow , length ):
164
- """Append an output to a path and return its tip and label locations.
165
+ """
166
+ Append an output to a path and return its tip and label locations.
165
167
166
168
Note: *flow* is negative for an output.
167
169
"""
@@ -215,7 +217,8 @@ def _add_output(self, path, angle, flow, length):
215
217
return tip , label_location
216
218
217
219
def _revert (self , path , first_action = Path .LINETO ):
218
- """A path is not simply revertable by path[::-1] since the code
220
+ """
221
+ A path is not simply revertable by path[::-1] since the code
219
222
specifies an action to take from the **previous** point.
220
223
"""
221
224
reverse_path = []
@@ -231,16 +234,11 @@ def _revert(self, path, first_action=Path.LINETO):
231
234
#path[2] = path[2][::-1]
232
235
#return path
233
236
237
+ @docstring .dedent_interpd
234
238
def add (self , patchlabel = '' , f
8000
lows = np .array ([1.0 ,- 1.0 ]), orientations = [0 ,0 ],
235
239
labels = '' , trunklength = 1.0 , pathlengths = 0.25 , prior = None ,
236
240
connect = (0 ,0 ), rotation = 0 , ** kwargs ):
237
241
"""
238
- call signature::
239
-
240
- add(patchlabel='', flows=np.array([1.0,-1.0]), orientations=[0,0],
241
- labels='', trunklength=1.0, pathlengths=0.25, prior=None,
242
- connect=(0,0), rotation=0, **kwargs)
243
-
244
242
Add a simple Sankey diagram with flows at the same hierarchical level.
245
243
246
244
Return value is the instance of :class:`Sankey`.
@@ -252,7 +250,7 @@ def add(self, patchlabel='', flows=np.array([1.0,-1.0]), orientations=[0,0],
252
250
=============== ==========================================================
253
251
*patchlabel* label to be placed at the center of the diagram
254
252
Note: *label* (not *patchlabel*) will be passed to
255
- the patch through **kwargs and can be used to create
253
+ the patch through ` **kwargs` and can be used to create
256
254
an entry in the legend.
257
255
*flows* array of flow values
258
256
By convention, inputs are positive and outputs are
@@ -297,9 +295,11 @@ def add(self, patchlabel='', flows=np.array([1.0,-1.0]), orientations=[0,0],
297
295
=============== ==========================================================
298
296
299
297
Valid kwargs are :meth:`matplotlib.patches.PathPatch` arguments:
300
- %(PathPatch)s
301
- As examples, *fill*=False and *label*="A legend entry". By default,
302
- *facecolor*='#bfd1d4' (light blue) and *lineweight*=0.5.
298
+
299
+ %(Patch)s
300
+
301
+ As examples, `fill=False` and `label='A legend entry'`. By default,
302
+ *facecolor*='#bfd1d4'` (light blue) and *linewidth*=0.5.
303
303
304
304
The indexing parameters (*prior* and *connect*) are zero-based.
305
305
@@ -508,7 +508,7 @@ def add(self, patchlabel='', flows=np.array([1.0,-1.0]), orientations=[0,0],
508
508
label_locations = np .zeros ((n ,2 ))
509
509
# Add the top-side inputs and outputs from the middle outwards.
510
510
for i , (angle , is_input , spec ) \
511
- in enumerate (zip (angles , are_inputs ,
511
+ in enumerate (zip (angles , are_inputs ,
512
512
zip (scaled_flows , pathlengths ))):
513
513
if angle == DOWN and is_input :
514
514
tips [i ,:], label_locations [i ,:] = self ._add_input (ulpath , angle ,
@@ -655,10 +655,6 @@ def _get_angle(a, r):
655
655
656
656
def finish (self ):
657
657
"""
658
- call signature::
659
-
660
- finish()
661
-
662
658
Adjust the axes and return a list of information about the Sankey
663
659
subdiagram(s).
664
660
@@ -707,15 +703,7 @@ def __init__(self, ax=None, scale=1.0, unit='', format='%G', gap=0.25,
707
703
radius = 0.1 , shoulder = 0.03 , offset = 0.15 , head_angle = 100 ,
708
704
margin = 0.4 , tolerance = 1e-6 , ** kwargs ):
709
705
"""
710
- call signature::
711
-
712
- Sankey(ax=None, scale=1.0, unit='', format='%G', gap=0.25, radius=0.1,
713
- shoulder=0.03, offset=0.15, head_angle=100, margin=0.4,
714
- tolerance=1e-6, **kwargs)
715
-
716
- Create a new Sankey diagram.
717
-
718
- Return value is an instance of :class:`Sankey`.
706
+ Create a new Sankey instance.
719
707
720
708
Optional keyword arguments:
721
709
@@ -758,21 +746,28 @@ def __init__(self, ax=None, scale=1.0, unit='', format='%G', gap=0.25,
758
746
that there is consistent alignment and formatting.
759
747
760
748
If :class:`Sankey` is instantiated with any keyword arguments other than
761
- those explicitly listed above (**kwargs), they will be passed to
749
+ those explicitly listed above (` **kwargs` ), they will be passed to
762
750
:meth:`add`, which will create the first subdiagram.
763
751
764
752
In order to draw a complex Sankey diagram, create an instance of
765
- :class:`Sankey` by calling it without any kwargs:
766
- >>> sankey = Sankey()
767
- Then add simple Sankey sub-diagrams:
768
- >>> sankey.add() # 1
769
- >>> sankey.add() # 2
770
- >>> #...
771
- >>> sankey.add() # n
772
- Finally, create the full diagram:
773
- >>> sankey.finish()
774
- Or, instead, simply daisy-chain those calls:
775
- >>> Sankey().add().add... .add().finish()
753
+ :class:`Sankey` by calling it without any kwargs::
754
+
755
+ sankey = Sankey()
756
+
757
+ Then add simple Sankey sub-diagrams::
758
+
759
+ sankey.add() # 1
760
+ sankey.add() # 2
761
+ #...
762
+ sankey.add() # n
763
+
764
+ Finally, create the full diagram::
765
+
766
+ sankey.finish()
767
+
768
+ Or, instead, simply daisy-chain those calls::
769
+
770
+ Sankey().add().add... .add().finish()
776
771
777
772
.. seealso::
778
773
0 commit comments