@@ -99,6 +99,7 @@ def __init__(
9999 window_size ,
100100 lut ,
101101 background_color = "black" ,
102+ spline_subdiv = 16 ,
102103 ):
103104 self .streamlines_xyz = streamlines_xyz
104105 self .color_values = color_values
@@ -113,6 +114,7 @@ def __init__(
113114
114115 # thickness state
115116 self .linewidth = max (1.0 , float (line_width )) # used for both line and tube
117+ self .spline_subdiv = spline_subdiv
116118
117119 self .scale_bar = None
118120 self .scale_bar_on = False
@@ -154,11 +156,12 @@ def _build_pipeline(self):
154156 self .streamlines_xyz ,
155157 colors = self .flat_vals ,
156158 linewidth = self .linewidth ,
157- spline_subdiv = 0 ,
159+ spline_subdiv = self . spline_subdiv ,
158160 lookup_colormap = self .lut ,
159- lod = False , # <—
160- lod_points = 20000 , # optional, tune
161- lod_points_size = 2 , # optional, tune
161+ tube_sides = 20 ,
162+ # lod=False, # <—
163+ # lod_points=20000, # optional, tune
164+ # lod_points_size=2, # optional, tune
162165 )
163166 else :
164167 self .actor0 = actor .line (
@@ -169,14 +172,16 @@ def _build_pipeline(self):
169172 )
170173
171174 self .scene .add (self .actor0 )
175+ self ._style_streamline_actor ()
176+
172177
173178 # fast actor for interaction (cheap line rendering)
174179 self .actor_fast = actor .line (
175180 self .streamlines_xyz ,
176181 colors = self .flat_vals , # pass scalars
177182 linewidth = 1.0 , # very light
178183 lookup_colormap = self .lut ,
179- lod = False , # make it deterministic
184+ # lod=False, # make it deterministic
180185 fake_tube = True , # a bit of shading to hint tubes
181186 )
182187 self .actor_fast .SetVisibility (False )
@@ -200,6 +205,14 @@ def _build_pipeline(self):
200205 self .mapper0 = self .actor0 .GetMapper ()
201206 self .mapper0 .RemoveAllClippingPlanes () # start with clipping off
202207
208+ def _style_streamline_actor (self ):
209+ prop = self .actor0 .GetProperty ()
210+ prop .SetInterpolationToPhong ()
211+ prop .SetAmbient (0.1 )
212+ prop .SetDiffuse (0.95 )
213+ prop .SetSpecular (0.25 )
214+ prop .SetSpecularPower (12 )
215+
203216 def _add_scalar_bar (self ):
204217 self .scene .add (
205218 fury .actor .scalar_bar (lookup_table = self .lut , title = "Angle (deg)" )
@@ -270,11 +283,12 @@ def _rebuild_unclipped_actor(self):
270283 self .streamlines_xyz ,
271284 colors = self .flat_vals ,
272285 linewidth = self .linewidth ,
273- spline_subdiv = 0 ,
286+ spline_subdiv = self .spline_subdiv ,
287+ tube_sides = 20 ,
274288 lookup_colormap = self .lut ,
275- lod = False , # <—
276- lod_points = 20000 , # optional, tune
277- lod_points_size = 2 , # optional, tune
289+ # lod=False, # <—
290+ # lod_points=20000, # optional, tune
291+ # lod_points_size=2, # optional, tune
278292 )
279293 else :
280294 self .actor0 = actor .line (
@@ -285,6 +299,9 @@ def _rebuild_unclipped_actor(self):
285299 )
286300
287301 self .scene .add (self .actor0 )
302+ self ._style_streamline_actor ()
303+
304+
288305 self .mapper0 = self .actor0 .GetMapper ()
289306 if clipping_on :
290307 self .mapper0 .RemoveAllClippingPlanes ()
@@ -462,6 +479,12 @@ def run(self, interactive: bool, screenshot_path: str | None):
462479 self .showm .iren .AddObserver ("KeyPressEvent" , self ._on_keypress )
463480
464481 self .scene .reset_camera ()
482+
483+ self .scene .azimuth (15 )
484+ self .scene .elevation (10 )
485+ self .scene .zoom (1.1 )
486+
487+
465488 print (
466489 "Keys: O toggle plane, H hide gizmo, I flip side, R reset plane, +/- thickness, B background, S scale bar, P save PNG"
467490 )
@@ -494,6 +517,7 @@ def show_streamlines(
494517 | None = None ,
495518 colormap = None ,
496519 background_color : str | tuple [float , float , float ] = "black" ,
520+ spline_subdiv : int = 16 ,
497521):
498522 print (f"Initial number of streamlines: { len (streamlines_xyz )} " )
499523
@@ -547,6 +571,17 @@ def show_streamlines(
547571 color_values = [color_values [i ] for i in keep_idx ]
548572
549573 print (f"Final number of streamlines to render: { len (streamlines_xyz )} " )
574+ points_per_streamline = np .array (
575+ [len (streamline ) for streamline in streamlines_xyz ], dtype = float
576+ )
577+ avg_points_per_streamline = float (np .mean (points_per_streamline ))
578+ std_points_per_streamline = float (np .std (points_per_streamline ))
579+ print (
580+ f"Average points per streamline: { avg_points_per_streamline :.1f} +/- "
581+ f"{ std_points_per_streamline :.1f} "
582+ "(more points usually means more detail, but heavier rendering)."
583+ )
584+
550585 if not color_values :
551586 raise ValueError ("No color arrays after filtering." )
552587
@@ -578,6 +613,7 @@ def show_streamlines(
578613 window_size ,
579614 lut ,
580615 background_color = background_color ,
616+ spline_subdiv = spline_subdiv ,
581617 )
582618 viewer .run (interactive = interactive , screenshot_path = screenshot_path )
583619
0 commit comments