@@ -62,6 +62,129 @@ class Sankey:
62
62
`Wikipedia (6/1/2011) <http://en.wikipedia.org/wiki/Sankey_diagram>`_
63
63
64
64
"""
65
+
66
+ def __init__ (self , ax = None , scale = 1.0 , unit = '' , format = '%G' , gap = 0.25 ,
67
+ radius = 0.1 , shoulder = 0.03 , offset = 0.15 , head_angle = 100 ,
68
+ margin = 0.4 , tolerance = 1e-6 , ** kwargs ):
69
+ """
70
+ Create a new Sankey instance.
71
+
72
+ Optional keyword arguments:
73
+
74
+ =============== ===================================================
75
+ Field Description
76
+ =============== ===================================================
77
+ *ax* axes onto which the data should be plotted
78
+ If *ax* isn't provided, new axes will be created.
79
+ *scale* scaling factor for the flows
80
+ *scale* sizes the width of the paths in order to
81
+ maintain proper layout. The same scale is applied
82
+ to all subdiagrams. The value should be chosen
83
+ such that the product of the scale and the sum of
84
+ the inputs is approximately 1.0 (and the product of
85
+ the scale and the sum of the outputs is
86
+ approximately -1.0).
87
+ *unit* string representing the physical unit associated
88
+ with the flow quantities
89
+ If *unit* is None, then none of the quantities are
90
+ labeled.
91
+ *format* a Python number formatting string to be used in
92
+ labeling the flow as a quantity (i.e., a number
93
+ times a unit, where the unit is given)
94
+ *gap* space between paths that break in/break away
95
+ to/from the top or bottom
96
+ *radius* inner radius of the vertical paths
97
+ *shoulder* size of the shoulders of output arrowS
98
+ *offset* text offset (from the dip or tip of the arrow)
99
+ *head_angle* angle of the arrow heads (and negative of the angle
100
+ of the tails) [deg]
101
+ *margin* minimum space between Sankey outlines and the edge
102
+ of the plot area
103
+ *tolerance* acceptable maximum of the magnitude of the sum of
104
+ flows
105
+ The magnitude of the sum of connected flows cannot
106
+ be greater than *tolerance*.
107
+ =============== ===================================================
108
+
109
+ The optional arguments listed above are applied to all subdiagrams so
110
+ that there is consistent alignment and formatting.
111
+
112
+ If :class:`Sankey` is instantiated with any keyword arguments other
113
+ than those explicitly listed above (``**kwargs``), they will be passed
114
+ to :meth:`add`, which will create the first subdiagram.
115
+
116
+ In order to draw a complex Sankey diagram, create an instance of
117
+ :class:`Sankey` by calling it without any kwargs::
118
+
119
+ sankey = Sankey()
120
+
121
+ Then add simple Sankey sub-diagrams::
122
+
123
+ sankey.add() # 1
124
+ sankey.add() # 2
125
+ #...
126
+ sankey.add() # n
127
+
128
+ Finally, create the full diagram::
129
+
130
+ sankey.finish()
131
+
132
+ Or, instead, simply daisy-chain those calls::
133
+
134
+ Sankey().add().add... .add().finish()
135
+
136
+ .. seealso::
137
+
138
+ :meth:`add`
139
+ :meth:`finish`
140
+
141
+
142
+ **Examples:**
143
+
144
+ .. plot:: mpl_examples/api/sankey_demo_basics.py
145
+ """
146
+ # Check the arguments.
147
+ assert gap >= 0 , (
148
+ "The gap is negative.\n This isn't allowed because it "
149
+ "would cause the paths to overlap." )
150
+ assert radius <= gap , (
151
+ "The inner radius is greater than the path spacing.\n "
152
+ "This isn't allowed because it would cause the paths to overlap." )
153
+ assert head_angle >= 0 , (
154
+ "The angle is negative.\n This isn't allowed "
155
+ "because it would cause inputs to look like "
156
+ "outputs and vice versa." )
157
+ assert tolerance >= 0 , (
158
+ "The tolerance is negative.\n It must be a magnitude." )
159
+
160
+ # Create axes if necessary.
161
+ if ax is None :
162
+ import matplotlib .pyplot as plt
163
+ fig = plt .figure ()
164
+ ax = fig .add_subplot (1 , 1 , 1 , xticks = [], yticks = [])
165
+
166
+ self .diagrams = []
167
+
168
+ # Store the inputs.
169
+ self .ax = ax
170
+ self .unit = unit
171
+ self .format = format
172
+ self .scale = scale
173
+ self .gap = gap
174
+ self .radius = radius
175
+ self .shoulder = shoulder
176
+ self .offset = offset
177
+ self .margin = margin
178
+ self .pitch = np .tan (np .pi * (1 - head_angle / 180.0 ) / 2.0 )
179
+ self .tolerance = tolerance
180
+
181
+ # Initialize the vertices of tight box around the diagram(s).
182
+ self .extent = np .array ((np .inf , - np .inf , np .inf , - np .inf ))
183
+
184
+ # If there are any kwargs, create the first subdiagram.
185
+ if len (kwargs ):
186
+ self .add (** kwargs )
187
+
65
188
def _arc (self , quadrant = 0 , cw = True , radius = 1 , center = (0 , 0 )):
66
189
"""
67
190
Return the codes and vertices for a rotated, scaled, and translated
@@ -558,7 +681,7 @@ def add(self, patchlabel='', flows=None, orientations=None, labels='',
558
681
llpath [- 1 ][1 ][1 ]]))
559
682
has_left_input = True
560
683
tip , label_location = self ._add_input (llpath , angle , * spec )
561
- tips [n - i - 1 , :], = tip
684
+ tips [n - i - 1 , :] = tip
562
685
label_locations [n - i - 1 , :] = label_location
563
686
# Add the right-side outputs from the top downwards.
564
687
has_right_output = False
@@ -722,124 +845,4 @@ def finish(self):
722
845
self .ax .set_aspect ('equal' , adjustable = 'datalim' )
723
846
return self .diagrams
724
847
725
- def __init__ (self , ax = None , scale = 1.0 , unit = '' , format = '%G' , gap = 0.25 ,
726
- radius = 0.1 , shoulder = 0.03 , offset = 0.15 , head_angle = 100 ,
727
- margin = 0.4 , tolerance = 1e-6 , ** kwargs ):
728
- """
729
- Create a new Sankey instance.
730
-
731
- Optional keyword arguments:
732
-
733
- =============== ===================================================
734
- Field Description
735
- =============== ===================================================
736
- *ax* axes onto which the data should be plotted
737
- If *ax* isn't provided, new axes will be created.
738
- *scale* scaling factor for the flows
739
- *scale* sizes the width of the paths in order to
740
- maintain proper layout. The same scale is applied
741
- to all subdiagrams. The value should be chosen
742
- such that the product of the scale and the sum of
743
- the inputs is approximately 1.0 (and the product of
744
- the scale and the sum of the outputs is
745
- approximately -1.0).
746
- *unit* string representing the physical unit associated
747
- with the flow quantities
748
- If *unit* is None, then none of the quantities are
749
- labeled.
750
- *format* a Python number formatting string to be used in
751
- labeling the flow as a quantity (i.e., a number
752
- times a unit, where the unit is given)
753
- *gap* space between paths that break in/break away
754
- to/from the top or bottom
755
- *radius* inner radius of the vertical paths
756
- *shoulder* size of the shoulders of output arrowS
757
- *offset* text offset (from the dip or tip of the arrow)
758
- *head_angle* angle of the arrow heads (and negative of the angle
759
- of the tails) [deg]
760
- *margin* minimum space between Sankey outlines and the edge
761
- of the plot area
762
- *tolerance* acceptable maximum of the magnitude of the sum of
763
- flows
764
- The magnitude of the sum of connected flows cannot
765
- be greater than *tolerance*.
766
- =============== ===================================================
767
-
768
- The optional arguments listed above are applied to all subdiagrams so
769
- that there is consistent alignment and formatting.
770
-
771
- If :class:`Sankey` is instantiated with any keyword arguments other
772
- than those explicitly listed above (``**kwargs``), they will be passed
773
- to :meth:`add`, which will create the first subdiagram.
774
-
775
- In order to draw a complex Sankey diagram, create an instance of
776
- :class:`Sankey` by calling it without any kwargs::
777
-
778
- sankey = Sankey()
779
-
780
- Then add simple Sankey sub-diagrams::
781
-
782
- sankey.add() # 1
783
- sankey.add() # 2
784
- #...
785
- sankey.add() # n
786
-
787
- Finally, create the full diagram::
788
-
789
- sankey.finish()
790
-
791
- Or, instead, simply daisy-chain those calls::
792
-
793
- Sankey().add().add... .add().finish()
794
-
795
- .. seealso::
796
-
797
- :meth:`add`
798
- :meth:`finish`
799
-
800
848
801
- **Examples:**
802
-
803
- .. plot:: mpl_examples/api/sankey_demo_basics.py
804
- """
805
- # Check the arguments.
806
- assert gap >= 0 , (
807
- "The gap is negative.\n This isn't allowed because it "
808
- "would cause the paths to overlap." )
809
- assert radius <= gap , (
810
- "The inner radius is greater than the path spacing.\n "
811
- "This isn't allowed because it would cause the paths to overlap." )
812
- assert head_angle >= 0 , (
813
- "The angle is negative.\n This isn't allowed "
814
- "because it would cause inputs to look like "
815
- "outputs and vice versa." )
816
- assert tolerance >= 0 , (
817
- "The tolerance is negative.\n It must be a magnitude." )
818
-
819
- # Create axes if necessary.
820
- if ax is None :
821
- import matplotlib .pyplot as plt
822
- fig = plt .figure ()
823
- ax = fig .add_subplot (1 , 1 , 1 , xticks = [], yticks = [])
824
-
825
- self .diagrams = []
826
-
827
- # Store the inputs.
828
- self .ax = ax
829
- self .unit = unit
830
- self .format = format
831
- self .scale = scale
832
- self .gap = gap
833
- self .radius = radius
834
- self .shoulder = shoulder
835
- self .offset = offset
836
- self .margin = margin
837
- self .pitch = np .tan (np .pi * (1 - head_angle / 180.0 ) / 2.0 )
838
- self .tolerance = tolerance
839
-
840
- # Initialize the vertices of tight box around the diagram(s).
841
- self .extent = np .array ((np .inf , - np .inf , np .inf , - np .inf ))
842
-
843
- # If there are any kwargs, create the first subdiagram.
844
- if len (kwargs ):
845
- self .add (** kwargs )
0 commit comments