Basics¶
In order to build any synthetic vascular network(s), you will need to define at least three components:
the perfusion domain in which the network(s) is built
seed point(s) where the vascular network(s) is initiated
the size of the vascular network(s)
By default if no seed points are given, vascular networks will be randomly seeded along the surface boundary of the perfusion domain. Likewise if no tree size is given, vascular networks will be initiated and dynamically grown. Therefore if the seed points and/or size of the vascular networks are unknown, the toolkit will make basic assumptions on the backend to fill in the missing information. The only component SVT cannot assume is the perfusion domain. This must be supplied by the user.
Defining a Perfusion Domain¶
In this section, we will cover the basics of creating a perfusion domain object necessary for generating a vascular network with SVT. The most basic method for defining a perfusion domain relies on point-wise data along the boundary. To create an example domain, we will use Pyvista to obtain boundary points and normals for a simple cube volume.
1import pyvista as pv
2import svcco
3
4# Define some set of points along a cube boundary
5cube = pv.Cube().triangulate().subdivide(4)
6
7# Create a domain instance
8surf = svcco.surface()
9
10# Assign points and normals to the domain object
11surf.set_data(cube.points,cube.point_normals)
12
13# Solve the domain geometry to obtain an implicit representation
14surf.solve()
15
16# Build the implicit domain
17surf.build(q=3)
To visualize the perfusion domain object, we can call svcco.plot_volume(surf)
to render some number of isocontours for the implicit funciton defining our domain.
Below shows only one isocontour of the implicit cube domain near the boundary of the
domain.
In this example, we provided the point-wise normal vectors associated with the cube since we already know the normals for our domain boundary. It is not always the case that normal information will be available. Therefore, point-wise normal vectors do not need to be provided by the user in order to create perfusion domain. However, providing them allows for fast solving of the implicit function defining the domain and can generally improve accuracy at the boundary if a domain has sharp edges.
Note
Providing normal vector information at points is not required for perfusion
domain objects, but it can improve performance during the solve()
and
build()
stages, especially if the domain is only C0 continuous.
We can demonstrate this this same process without including normal vector information below:
1import pyvista as pv
2import svcco
3
4# Define some set of points along a cube boundary
5cube = pv.Cube().triangulate().subdivide(4)
6
7# Create a domain instance
8surf = svcco.surface()
9
10# Assign points and normals to the domain object
11surf.set_data(cube.points)
12
13# Solve the domain geometry to obtain an implicit representation
14surf.solve()
15
16# Build the implicit domain
17surf.build(q=3)
Of course, defining perfusion domains through point arrays can be cumbersome and
not immediately available for many geometry files, especially STL files which are
common for 3D fabrication. Often complex geometries are represented as mesh files
of varying quality. To handle these types of files for perfusion domain creation,
we can use the load()
method to import and clean a mesh geometry file prior to
implicit domain creation.
1import svcco
2
3# Define a domain instance
4surf = svcco.surface()
5
6# Use the load method to import a geometry
7surf.load('/path/to/file')
8
9# Solve the domain geometry to obtain an implicit representation
10surf.solve()
11
12# Build the implicit domain
13surf.build(q=3)
Note
If the load()
method accepts a string parameter for a file path to supported
mesh files. If no arguments are provided, the method will open a file navigator window
for the user to select a file through an easy-to-use interface.
For more information and advanced features of the perfusion domain svcco.surface()
class, please refer to the documentation in implicit module.
Building a Vascular Tree within a Domain¶
After defining an appropriate perfusion domain object, users can build a synthetic vascular network. We will demonstrate a build of a simple vascular tree within the cube domain presented above. By default, the standard unit system for building synthetic vasculature is in centimeter-gram-second units (cgs). This will be important to remember when assigning physical parameters to vascular networks and for downstream applications.
1import svcco
2
3# Define a tree instance
4t = svcco.tree()
5
6# Assign a perfusion domain object
7t.set_boundary(surf)
8
9# Set the root vessel for the tree, if no parameters are given this
10# root will be randomly placed on the boundary
11t.set_root()
12
13# Add some number of vessels to the tree
14t.n_add(100)