svVascularize

svv.tree.Tree

Core Class v1.0.0

The Tree class defines a branching tree structure that is used to abstract the physical representation of the generated vascular network. It implements stochastic constructive optimization algorithms for growing vascular trees within defined domains.

Trees grow iteratively by adding vessels using optimized bifurcation placement, managing collision detection, and maintaining physiological constraints. The class provides export capabilities for 3D models, centerlines, and simulation-ready geometries.

Quick Example

from svv.tree import Tree
from svv.domain import Domain
import pyvista as pv

# Create domain from mesh
mesh = pv.read('tissue_region.stl')
domain = Domain(mesh)
domain.create()
domain.solve()
domain.build()

# Initialize tree
tree = Tree()
tree.set_domain(domain)

# Set root position
tree.set_root([0, 0, 0])  # Starting point

# Grow tree with n terminals
tree.n_add(100)  # Add 100 vessels

# Visualize
tree.show()

# Export results
solid_model = tree.export_solid()
centerlines, polys = tree.export_centerlines()

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 region
  • convexity_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 place
  • decay_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 each add() 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 path
  • shell_thickness (float): Wall thickness for hollow vessels
  • watertight (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 geometry
  • polys: Connectivity information

Visualization

show(**kwargs)

Display interactive 3D visualization of the tree.

Parameters

  • color (str): Vessel color (default: 'red')
  • plot_domain (bool): Display domain boundary
  • return_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