88
99
1010def create_quiver (x , y , u , v , scale = .1 , arrow_scale = .3 ,
11- angle = math .pi / 9 , ** kwargs ):
11+ angle = math .pi / 9 , scaleratio = None , ** kwargs ):
1212 """
1313 Returns data for a quiver plot.
1414
@@ -21,6 +21,9 @@ def create_quiver(x, y, u, v, scale=.1, arrow_scale=.3,
2121 :param (float in [0,1]) arrow_scale: value multiplied to length of barb
2222 to get length of arrowhead. Default = .3
2323 :param (angle in radians) angle: angle of arrowhead. Default = pi/9
24+ :param (positive float) angle: the ratio between the scale of the y-axis
25+ and the scale of the x-axis (scale_y / scale_x). Default = None, the
26+ scale ratio is not fixed.
2427 :param kwargs: kwargs passed through plotly.graph_objs.Scatter
2528 for more information on valid kwargs call
2629 help(plotly.graph_objs.Scatter)
@@ -80,33 +83,69 @@ def create_quiver(x, y, u, v, scale=.1, arrow_scale=.3,
8083 # Add title to layout
8184 fig['layout'].update(title='Quiver Plot')
8285
86+ # Plot
87+ py.plot(fig, filename='quiver')
88+ ```
89+
90+ Example 4: Forcing a fix scale ratio to maintain the arrow length
91+ ```
92+ import plotly.plotly as py
93+ from plotly.figure_factory import create_quiver
94+
95+ import numpy as np
96+
97+ # Add data
98+ x,y = np.meshgrid(np.arange(0.5, 3.5, .5), np.arange(0.5, 4.5, .5))
99+ u = x
100+ v = y
101+ angle = np.arctan(v / u)
102+ norm = 0.25
103+ u = norm * np.cos(angle)
104+ v = norm * np.sin(angle)
105+
106+ # Create quiver with a fix scale ratio
107+ fig = create_quiver(x, y, u, v, scale = 1, scaleratio = 0.5)
108+
83109 # Plot
84110 py.plot(fig, filename='quiver')
85111 ```
86112 """
87113 utils .validate_equal_length (x , y , u , v )
88114 utils .validate_positive_scalars (arrow_scale = arrow_scale , scale = scale )
89115
90- barb_x , barb_y = _Quiver (x , y , u , v , scale ,
91- arrow_scale , angle ).get_barbs ()
92- arrow_x , arrow_y = _Quiver (x , y , u , v , scale ,
93- arrow_scale , angle ).get_quiver_arrows ()
94- quiver = graph_objs .Scatter (x = barb_x + arrow_x ,
116+ if scaleratio is None :
117+ quiver_obj = _Quiver (x , y , u , v , scale , arrow_scale , angle )
118+ else :
119+ quiver_obj = _Quiver (x , y , u , v , scale , arrow_scale , angle , scaleratio )
120+
121+ barb_x , barb_y = quiver_obj .get_barbs ()
122+ arrow_x , arrow_y = quiver_obj .get_quiver_arrows ()
123+
124+ quiver_plot = graph_objs .Scatter (x = barb_x + arrow_x ,
95125 y = barb_y + arrow_y ,
96126 mode = 'lines' , ** kwargs )
97127
98- data = [quiver ]
99- layout = graph_objs .Layout (hovermode = 'closest' )
128+ data = [quiver_plot ]
100129
101- return graph_objs .Figure (data = data , layout = layout )
130+ if scaleratio is None :
131+ layout = graph_objs .Layout (hovermode = 'closest' )
132+ else :
133+ layout = graph_objs .Layout (
134+ hovermode = 'closest' ,
135+ yaxis = dict (
136+ scaleratio = scaleratio ,
137+ scaleanchor = "x"
138+ )
139+ )
102140
141+ return graph_objs .Figure (data = data , layout = layout )
103142
104143class _Quiver (object ):
105144 """
106145 Refer to FigureFactory.create_quiver() for docstring
107146 """
108147 def __init__ (self , x , y , u , v ,
109- scale , arrow_scale , angle , ** kwargs ):
148+ scale , arrow_scale , angle , scaleratio = 1 , ** kwargs ):
110149 try :
111150 x = utils .flatten (x )
112151 except exceptions .PlotlyError :
@@ -132,6 +171,7 @@ def __init__(self, x, y, u, v,
132171 self .u = u
133172 self .v = v
134173 self .scale = scale
174+ self .scaleratio = scaleratio
135175 self .arrow_scale = arrow_scale
136176 self .angle = angle
137177 self .end_x = []
@@ -148,7 +188,7 @@ def scale_uv(self):
148188 endpoints of the arrows so a smaller scale value will
149189 result in less overlap of arrows.
150190 """
151- self .u = [i * self .scale for i in self .u ]
191+ self .u = [i * self .scale * self . scaleratio for i in self .u ]
152192 self .v = [i * self .scale for i in self .v ]
153193
154194 def get_barbs (self ):
@@ -188,13 +228,13 @@ def get_quiver_arrows(self):
188228 point1, endpoint, point2 y_values separated by a None to create
189229 the barb of the arrow.
190230 """
191- dif_x = [i - j for i , j in zip (self .end_x , self .x )]
231+ dif_x = [i - j for i , j in zip (self .end_x , self .x )]
192232 dif_y = [i - j for i , j in zip (self .end_y , self .y )]
193233
194234 # Get barb lengths(default arrow length = 30% barb length)
195235 barb_len = [None ] * len (self .x )
196236 for index in range (len (barb_len )):
197- barb_len [index ] = math .hypot (dif_x [index ], dif_y [index ])
237+ barb_len [index ] = math .hypot (dif_x [index ] / self . scaleratio , dif_y [index ])
198238
199239 # Make arrow lengths
200240 arrow_len = [None ] * len (self .x )
@@ -203,7 +243,7 @@ def get_quiver_arrows(self):
203243 # Get barb angles
204244 barb_ang = [None ] * len (self .x )
205245 for index in range (len (barb_ang )):
206- barb_ang [index ] = math .atan2 (dif_y [index ], dif_x [index ])
246+ barb_ang [index ] = math .atan2 (dif_y [index ], dif_x [index ] / self . scaleratio )
207247
208248 # Set angles to create arrow
209249 ang1 = [i + self .angle for i in barb_ang ]
@@ -231,9 +271,9 @@ def get_quiver_arrows(self):
231271
232272 # Set coordinates to create arrow
233273 for index in range (len (self .end_x )):
234- point1_x = [i - j for i , j in zip (self .end_x , seg1_x )]
274+ point1_x = [i - j * self . scaleratio for i , j in zip (self .end_x , seg1_x )]
235275 point1_y = [i - j for i , j in zip (self .end_y , seg1_y )]
236- point2_x = [i - j for i , j in zip (self .end_x , seg2_x )]
276+ point2_x = [i - j * self . scaleratio for i , j in zip (self .end_x , seg2_x )]
237277 point2_y = [i - j for i , j in zip (self .end_y , seg2_y )]
238278
239279 # Combine lists to create arrow
0 commit comments