22"""
33Module for creating Sankey diagrams using matplotlib
44"""
5+ from __future__ import print_function
56__author__ = "Kevin L. Davies"
67__credits__ = ["Yannick Copin" ]
78__license__ = "BSD"
1213# http://matplotlib.org/examples/api/sankey_demo_old.html
1314# Modifications by Kevin Davies ([email protected] ) 6/3/2011: 1415# --Used arcs for the curves (so that the widths of the paths are uniform)
15- # --Converted the function to a class and created methods to join
16- # multiple simple Sankey diagrams
16+ # --Converted the function to a class and created methods to join multiple
17+ # simple Sankey diagrams
1718# --Provided handling for cases where the total of the inputs isn't 100
1819# Now, the default layout is based on the assumption that the inputs sum to
1920# 1. A scaling parameter can be used in other cases.
2930# inputs/outputs are now specified via an orientation of 0, and there may
3031# be several of each.
3132# --Added assertions to catch common calling errors
32- # -Added the physical unit as a string argument to be used in the labels, so
33+ # - -Added the physical unit as a string argument to be used in the labels, so
3334# that the values of the flows can usually be applied automatically
3435# --Added an argument for a minimum magnitude below which flows are not shown
3536# --Added a tapered trunk in the case that the flows do not sum to 0
@@ -395,10 +396,10 @@ def add(self, patchlabel='', flows=None, orientations=None, labels='',
395396 *orientations* == 0, inputs will break in from the
396397 left and outputs will break away to the right.
397398 *labels* list of specifications of the labels for the flows
398- Each value may be None (no labels), '' (just label
399- the quantities), or a labeling string. If a single
400- value is provided, it will be applied to all flows.
401- If an entry is a non-empty string, then the
399+ Each value may be * None* (no labels), '' (just
400+ label the quantities), or a labeling string. If a
401+ single value is provided, it will be applied to all
402+ flows. If an entry is a non-empty string, then the
402403 quantity for the corresponding flow will be shown
403404 below the string. However, if the *unit* of the
404405 main diagram is None, then quantities are never
@@ -417,7 +418,7 @@ def add(self, patchlabel='', flows=None, orientations=None, labels='',
417418 *connect* a (prior, this) tuple indexing the flow of the
418419 prior diagram and the flow of this diagram which
419420 should be connected
420- If this is the first diagram or *prior* is None,
421+ If this is the first diagram or *prior* is * None* ,
421422 *connect* will be ignored.
422423 *rotation* angle of rotation of the diagram [deg]
423424 *rotation* is ignored if this diagram is connected
@@ -460,7 +461,7 @@ def add(self, patchlabel='', flows=None, orientations=None, labels='',
460461 if rotation is None :
461462 rotation = 0
462463 else :
463- # In the code below, angles are expressed in deg/90
464+ # In the code below, angles are expressed in deg/90.
464465 rotation /= 90.0
465466 if orientations is None :
466467 orientations = [0 , 0 ]
@@ -741,10 +742,10 @@ def _get_angle(a, r):
741742 kwds = dict (s = patchlabel , ha = 'center' , va = 'center' )
742743 text = self .ax .text (* offset , ** kwds )
743744 if False : # Debug
744- print "llpath\n " , llpath
745- print "ulpath\n " , self ._revert (ulpath )
746- print "urpath\n " , urpath
747- print "lrpath\n " , self ._revert (lrpath )
745+ print ( "llpath\n " , llpath )
746+ print ( "ulpath\n " , self ._revert (ulpath ) )
747+ print ( "urpath\n " , urpath )
748+ print ( "lrpath\n " , self ._revert (lrpath ) )
748749 xs , ys = zip (* vertices )
749750 self .ax .plot (xs , ys , 'go-' )
750751 patch = PathPatch (Path (vertices , codes ),
@@ -755,22 +756,18 @@ def _get_angle(a, r):
755756 self .ax .add_patch (patch )
756757
757758 # Add the path labels.
758- for i , (number , angle ) in enumerate (zip (flows , angles )):
759- if labels [i ] is None or angle is None :
760- labels [i ] = ''
759+ texts = []
760+ for number , angle , label , location in zip (flows , angles , labels ,
761+ label_locations ):
762+ if label is None or angle is None :
763+ label = ''
761764 elif self .unit is not None :
762765 quantity = self .format % abs (number ) + self .unit
763- if labels [i ] != '' :
764- labels [i ] += "\n "
765- labels [i ] += quantity
766- texts = []
767- for i , (label , location ) in enumerate (zip (labels , label_locations )):
768- if label :
769- s = label
770- else :
771- s = ''
766+ if label != '' :
767+ label += "\n "
768+ label += quantity
772769 texts .append (self .ax .text (x = location [0 ], y = location [1 ],
773- s = s ,
770+ s = label ,
774771 ha = 'center' , va = 'center' ))
775772 # Text objects are placed even they are empty (as long as the magnitude
776773 # of the corresponding flow is larger than the tolerance) in case the
@@ -820,7 +817,7 @@ def finish(self):
820817 (DOWN), and an output from the top side will have
821818 an angle of 1 (UP). If a flow has been skipped
822819 (because its magnitude is less than *tolerance*),
823- then its angle will be None.
820+ then its angle will be * None* .
824821 *tips* array in which each row is an [x, y] pair
825822 indicating the positions of the tips (or "dips") of
826823 the flow paths
@@ -844,5 +841,3 @@ def finish(self):
844841 self .extent [3 ] + self .margin ])
845842 self .ax .set_aspect ('equal' , adjustable = 'datalim' )
846843 return self .diagrams
847-
848-
0 commit comments