2222
2323def streamplot (axes , x , y , u , v , density = 1 , linewidth = None , color = None ,
2424 cmap = None , norm = None , arrowsize = 1 , arrowstyle = '-|>' ,
25- minlength = 0.1 , transform = None , zorder = None , start_points = None ):
25+ minlength = 0.1 , transform = None , zorder = None , start_points = None ,
26+ maxlength = 4.0 , integration_direction = 'both' ):
2627 """Draws streamlines of a vector flow.
2728
2829 *x*, *y* : 1d arrays
@@ -58,6 +59,10 @@ def streamplot(axes, x, y, u, v, density=1, linewidth=None, color=None,
5859 In data coordinates, the same as the ``x`` and ``y`` arrays.
5960 *zorder* : int
6061 any number
62+ *maxlength* : float
63+ Maximum length of streamline in axes coordinates.
64+ *integration_direction* : ['forward', 'backward', 'both']
65+ Integrate the streamline in forward, backward or both directions.
6166
6267 Returns:
6368
@@ -95,6 +100,15 @@ def streamplot(axes, x, y, u, v, density=1, linewidth=None, color=None,
95100 line_kw = {}
96101 arrow_kw = dict (arrowstyle = arrowstyle , mutation_scale = 10 * arrowsize )
97102
103+ if integration_direction not in ['both' , 'forward' , 'backward' ]:
104+ errstr = ("Integration direction '%s' not recognised. "
105+ "Expected 'both', 'forward' or 'backward'." %
106+ integration_direction )
107+ raise ValueError (errstr )
108+
109+ if integration_direction == 'both' :
110+ maxlength /= 2.
111+
98112 use_multicolor_lines = isinstance (color , np .ndarray )
99113 if use_multicolor_lines :
100114 if color .shape != grid .shape :
@@ -126,7 +140,8 @@ def streamplot(axes, x, y, u, v, density=1, linewidth=None, color=None,
126140 u = np .ma .masked_invalid (u )
127141 v = np .ma .masked_invalid (v )
128142
129- integrate = get_integrator (u , v , dmap , minlength )
143+ integrate = get_integrator (u , v , dmap , minlength , maxlength ,
144+ integration_direction )
130145
131146 trajectories = []
132147 if start_points is None :
@@ -401,7 +416,7 @@ class TerminateTrajectory(Exception):
401416# Integrator definitions
402417#========================
403418
404- def get_integrator (u , v , dmap , minlength ):
419+ def get_integrator (u , v , dmap , minlength , maxlength , integration_direction ):
405420
406421 # rescale velocity onto grid-coordinates for integrations.
407422 u , v = dmap .data2grid (u , v )
@@ -435,17 +450,27 @@ def integrate(x0, y0):
435450 resulting trajectory is None if it is shorter than `minlength`.
436451 """
437452
453+ stotal , x_traj , y_traj = 0. , [], []
454+
438455 try :
439456 dmap .start_trajectory (x0 , y0 )
440457 except InvalidIndexError :
441458 return None
442- sf , xf_traj , yf_traj = _integrate_rk12 (x0 , y0 , dmap , forward_time )
443- dmap .reset_start_point (x0 , y0 )
444- sb , xb_traj , yb_traj = _integrate_rk12 (x0 , y0 , dmap , backward_time )
445- # combine forward and backward trajectories
446- stotal = sf + sb
447- x_traj = xb_traj [::- 1 ] + xf_traj [1 :]
448- y_traj = yb_traj [::- 1 ] + yf_traj [1 :]
459+ if integration_direction in ['both' , 'backward' ]:
460+ s , xt , yt = _integrate_rk12 (x0 , y0 , dmap , backward_time , maxlength )
461+ stotal += s
462+ x_traj += xt [::- 1 ]
463+ y_traj += yt [::- 1 ]
464+
465+ if integration_direction in ['both' , 'forward' ]:
466+ dmap .reset_start_point (x0 , y0 )
467+ s , xt , yt = _integrate_rk12 (x0 , y0 , dmap , forward_time , maxlength )
468+ if len (x_traj ) > 0 :
469+ xt = xt [1 :]
470+ yt = yt [1 :]
471+ stotal += s
472+ x_traj += xt
473+ y_traj += yt
449474
450475 if stotal > minlength :
451476 return x_traj , y_traj
@@ -456,7 +481,7 @@ def integrate(x0, y0):
456481 return integrate
457482
458483
459- def _integrate_rk12 (x0 , y0 , dmap , f ):
484+ def _integrate_rk12 (x0 , y0 , dmap , f , maxlength ):
460485 """2nd-order Runge-Kutta algorithm with adaptive step size.
461486
462487 This method is also referred to as the improved Euler's method, or Heun's
@@ -532,7 +557,7 @@ def _integrate_rk12(x0, y0, dmap, f):
532557 dmap .update_trajectory (xi , yi )
533558 except InvalidIndexError :
534559 break
535- if (stotal + ds ) > 2 :
560+ if (stotal + ds ) > maxlength :
536561 break
537562 stotal += ds
538563
0 commit comments