8
8
9
9
10
10
def 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 ):
12
12
"""
13
13
Returns data for a quiver plot.
14
14
@@ -21,6 +21,9 @@ def create_quiver(x, y, u, v, scale=.1, arrow_scale=.3,
21
21
:param (float in [0,1]) arrow_scale: value multiplied to length of barb
22
22
to get length of arrowhead. Default = .3
23
23
: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.
24
27
:param kwargs: kwargs passed through plotly.graph_objs.Scatter
25
28
for more information on valid kwargs call
26
29
help(plotly.graph_objs.Scatter)
@@ -80,33 +83,69 @@ def create_quiver(x, y, u, v, scale=.1, arrow_scale=.3,
80
83
# Add title to layout
81
84
fig['layout'].update(title='Quiver Plot')
82
85
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
+
83
109
# Plot
84
110
py.plot(fig, filename='quiver')
85
111
```
86
112
"""
87
113
utils .validate_equal_length (x , y , u , v )
88
114
utils .validate_positive_scalars (arrow_scale = arrow_scale , scale = scale )
89
115
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 ,
95
125
y = barb_y + arrow_y ,
96
126
mode = 'lines' , ** kwargs )
97
127
98
- data = [quiver ]
99
- layout = graph_objs .Layout (hovermode = 'closest' )
128
+ data = [quiver_plot ]
100
129
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
+ )
102
140
141
+ return graph_objs .Figure (data = data , layout = layout )
103
142
104
143
class _Quiver (object ):
105
144
"""
106
145
Refer to FigureFactory.create_quiver() for docstring
107
146
"""
108
147
def __init__ (self , x , y , u , v ,
109
- scale , arrow_scale , angle , ** kwargs ):
148
+ scale , arrow_scale , angle , scaleratio = 1 , ** kwargs ):
110
149
try :
111
150
x = utils .flatten (x )
112
151
except exceptions .PlotlyError :
@@ -132,6 +171,7 @@ def __init__(self, x, y, u, v,
132
171
self .u = u
133
172
self .v = v
134
173
self .scale = scale
174
+ self .scaleratio = scaleratio
135
175
self .arrow_scale = arrow_scale
136
176
self .angle = angle
137
177
self .end_x = []
@@ -148,7 +188,7 @@ def scale_uv(self):
148
188
endpoints of the arrows so a smaller scale value will
149
189
result in less overlap of arrows.
150
190
"""
151
- self .u = [i * self .scale for i in self .u ]
191
+ self .u = [i * self .scale * self . scaleratio for i in self .u ]
152
192
self .v = [i * self .scale for i in self .v ]
153
193
154
194
def get_barbs (self ):
@@ -188,13 +228,13 @@ def get_quiver_arrows(self):
188
228
point1, endpoint, point2 y_values separated by a None to create
189
229
the barb of the arrow.
190
230
"""
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 )]
192
232
dif_y = [i - j for i , j in zip (self .end_y , self .y )]
193
233
194
234
# Get barb lengths(default arrow length = 30% barb length)
195
235
barb_len = [None ] * len (self .x )
196
236
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 ])
198
238
199
239
# Make arrow lengths
200
240
arrow_len = [None ] * len (self .x )
@@ -203,7 +243,7 @@ def get_quiver_arrows(self):
203
243
# Get barb angles
204
244
barb_ang = [None ] * len (self .x )
205
245
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 )
207
247
208
248
# Set angles to create arrow
209
249
ang1 = [i + self .angle for i in barb_ang ]
@@ -231,9 +271,9 @@ def get_quiver_arrows(self):
231
271
232
272
# Set coordinates to create arrow
233
273
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 )]
235
275
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 )]
237
277
point2_y = [i - j for i , j in zip (self .end_y , seg2_y )]
238
278
239
279
# Combine lists to create arrow
0 commit comments