Constructor
Tree()
Initialize an empty tree structure. The tree must be configured with a domain and root before growth.
Attributes
Core Data Structures
Attribute | Type | Description |
---|---|---|
data |
TreeData | Main data structure containing vessel geometry and properties |
parameters |
TreeParameters | Configuration parameters for tree growth |
vessel_map |
TreeMap | Mapping of vessel connectivity and hierarchy |
domain |
Domain | Spatial domain constraining tree growth |
connectivity |
np.ndarray | Connectivity matrix for vessel segments |
Tree Properties
Attribute | Type | Description |
---|---|---|
n_terminals |
int | Current number of terminal vessels |
segment_count |
int | Total number of vessel segments |
tree_scale |
float | Total tree volume scale factor |
characteristic_length |
float | Characteristic length from domain |
physical_clearance |
float | Minimum physical spacing between vessels |
convex |
bool | Whether domain is treated as convex |
Internal Structures
Attribute | Type | Description |
---|---|---|
kdtm |
KDTreeManager | KD-tree for spatial queries |
hnsw_tree |
USearchTree | HNSW index for fast nearest neighbor search |
times |
dict | Performance timing statistics |
Setup Methods
set_domain(domain, convexity_tolerance=1e-2)
Set the spatial domain for tree growth.
Parameters
domain
(Domain): Domain object defining growth regionconvexity_tolerance
(float): Tolerance for convexity check
Notes
The domain must have its implicit function built before setting. The method automatically determines if the domain is convex, which affects collision detection strategies.
set_root(*args, inplace=True, **kwargs)
Set the root vessel of the tree.
Parameters
*args
: Variable arguments- Single argument: starting point (3D coordinates)
- Two arguments: starting point and direction vector
inplace
(bool): Modify tree in place**kwargs
: Additional parameters for root configuration
Notes
When direction is provided, the root becomes "clamped" with fixed orientation.
Growth Methods
add(inplace=True, **kwargs)
Add a single vessel to the tree using optimized bifurcation placement.
Parameters
inplace
(bool): Modify tree in placedecay_probability
(float, default=0.9): Probability decay for revisiting regions**kwargs
: Additional growth parameters
Returns
- If
inplace=True
: None - If
inplace=False
: Tuple of modification data
Algorithm
The method uses constructive constrained optimization (CCO) to find optimal bifurcation points that minimize total tree volume while maintaining flow constraints.
n_add(n, **kwargs)
Add multiple vessels to the tree.
Parameters
n
(int): Number of vessels to add**kwargs
: Parameters passed to eachadd()
call
Notes
Shows a progress bar during growth. Each vessel is added sequentially with the tree structure updated after each addition.
Export Methods
export_solid(outdir=None, shell_thickness=0.0, watertight=False, **kwargs)
Export tree as a 3D solid model.
Parameters
outdir
(str, optional): Output directory pathshell_thickness
(float): Wall thickness for hollow vesselswatertight
(bool): Create watertight mesh with smooth junctions
Returns
model
(pv.PolyData): 3D mesh of the vascular tree
export_centerlines(outdir=None, **kwargs)
Export tree centerlines for simulation or analysis.
Returns
centerlines
(pv.PolyData): Centerline geometrypolys
: Connectivity information
Visualization
show(**kwargs)
Display interactive 3D visualization of the tree.
Parameters
color
(str): Vessel color (default: 'red')plot_domain
(bool): Display domain boundaryreturn_plotter
(bool): Return the PyVista plotter instead of showing**kwargs
: Additional PyVista plotting parameters
Examples
Basic Tree Generation
from svv.tree import Tree
from svv.domain import Domain
import numpy as np
import pyvista as pv
# Create spherical domain
sphere = pv.Sphere(radius=10.0, center=(0, 0, 0))
domain = Domain(sphere)
domain.create()
domain.solve()
domain.build(resolution=30)
# Initialize and configure tree
tree = Tree()
tree.set_domain(domain)
tree.parameters.radius_exponent = 2.0 # Murray's law
tree.parameters.length_exponent = 1.0
# Set root at center
tree.set_root([0, 0, 0])
# Grow tree
tree.n_add(50)
# Show statistics
print(f"Terminals: {tree.n_terminals}")
print(f"Segments: {tree.segment_count}")
print(f"Tree scale: {tree.tree_scale:.3f}")
# Visualize
tree.show(color='royalblue', plot_domain=True)
Constrained Growth with Physical Clearance
# Set minimum vessel spacing
tree = Tree()
tree.physical_clearance = 0.5 # mm minimum spacing
tree.set_domain(domain)
# Root with fixed direction
start_point = [0, 0, -5]
direction = [0, 0, 1]
tree.set_root(start_point, direction)
# Grow with custom parameters
for i in range(100):
tree.add(decay_probability=0.95)
# Check growth progress
if i % 20 == 0:
print(f"Step {i}: {tree.n_terminals} terminals")
# Export results
solid = tree.export_solid(watertight=True)
solid.save('vascular_tree.stl')
Export for Simulation
# Generate tree
tree = Tree()
tree.set_domain(domain)
tree.set_root([0, 0, 0])
tree.n_add(100)
# Export centerlines with radius data
centerlines, connectivity = tree.export_centerlines()
# Add flow properties
centerlines['flow_rate'] = np.zeros(centerlines.n_points)
centerlines['pressure'] = np.ones(centerlines.n_points) * 80 # mmHg
# Save for simulation
centerlines.save('tree_centerlines.vtp')
# Export solid model
solid = tree.export_solid(
watertight=True,
shell_thickness=0.1 # Create hollow vessels
)
solid.save('tree_solid.stl')
# Access raw data for custom processing
vessel_data = tree.data # TreeData object
vessel_map = tree.vessel_map # Connectivity information
Performance Considerations
Spatial Indexing: The Tree class uses multiple spatial data structures for efficient collision detection: KD-trees for exact nearest neighbor queries and HNSW (Hierarchical Navigable Small World) graphs for approximate nearest neighbor search in high-dimensional spaces.
Memory Management: Trees preallocate memory in chunks (default 4 million segments) to avoid repeated allocations during growth. This significantly improves performance for large trees.
Convexity: Non-convex domains require additional collision checks which can slow
growth. The tree automatically switches to convex mode after repeated failures in non-convex regions
(controlled by parameters.max_nonconvex_count
).
Timing Analysis
Access detailed timing information through the times
attribute:
# After growing tree
import pandas as pd
# Convert timing data to DataFrame
timing_df = pd.DataFrame(tree.times)
# Analyze performance bottlenecks
print("Average times (ms):")
for key in ['vessels', 'collision', 'local_optimization']:
if key in tree.times and tree.times[key]:
avg_time = np.mean(tree.times[key]) * 1000
print(f"{key}: {avg_time:.2f}")
See Also
svv.domain.Domain
- Spatial domains for tree growthsvv.forest.Forest
- Collections of multiple trees