This notebook demonstrates integration of functionality from SNT with Python through pyimagej.
The context is the computation and rendering of the convex hull enclosing all axonal/dendritic terminal nodes.

In [1]:
import sys
!conda install --yes --prefix {sys.prefix} -c conda-forge pyimagej openjdk=8 scipy
In [2]:
import imagej
import numpy as np
from scipy.spatial import ConvexHull
In [3]:
# Initialize Fiji with GUI support.
ij = imagej.init('sc.fiji:fiji', headless=False)

from jnius import autoclass, cast
Added 463 JARs to the Java classpath.
In [4]:
# Import relevant SNT (Java) classes.
HashSet = autoclass('java.util.HashSet')
PointInImage = autoclass('sc.fiji.snt.util.PointInImage')
MouseLightLoader = autoclass('sc.fiji.snt.io.MouseLightLoader')
Tree = autoclass('sc.fiji.snt.Tree')
TreeAnalyzer = autoclass('sc.fiji.snt.analysis.TreeAnalyzer')
Viewer = autoclass('sc.fiji.snt.viewer.Viewer3D')
In [5]:
def convex_hull(tree):
        """Computes the convex hull of the input Tree
        and return a Java ArrayList containing the vertices 
        representing the hull.
        
        Returns:
            verts_java (ArrayList): The list containing the hull vertices.
        Args:
            tree (Tree): The SNT Tree object."""
        
        analyzer = TreeAnalyzer(tree)
        # Extract the end points from the tree as a java HashSet.
        tips_java_set = analyzer.getTips()
        # Convert to array to maintain ordering.
        tips_java_array = tips_java_set.toArray()

        # Convert to python list.
        tips_list = [[t.x, t.y, t.z] for t in tips_java_array]

        assert len(tips_list) == tips_java_set.size()

        # Find the convex hull of the end points.
        hull = ConvexHull(tips_list)
        
        print("The volume of the convex hull encapsulating all tip points is {} um^3".format(
            round(hull.volume, 2)))
        
        print("The area of the hull is {} um^2".format(round(hull.area, 2)))
        print()
        
        # Find original PointInImage objects to pass to Viewer3D.
        # This is less costly than re-constructing a new Java object for each vertex.
        verts_java = [tips_java_array[i] for i in hull.vertices]
        verts_java = ij.py.to_java(verts_java)
        
        return verts_java
In [6]:
def run():
    
    # Fetch swc from MouseLight database by ID.
    loader = MouseLightLoader('AA0100')
    if not loader.isDatabaseAvailable():
        print("Could not connect to ML database", "Error")
        return
    if not loader.idExists():
        print("Somewhow the specified id was not found", "Error")
        return

    tree_axon = loader.getTree('axon', None)
    tree_dendrites = loader.getTree('dendrite', None)
        
    verts_axon = convex_hull(tree_axon)
    verts_dendrites = convex_hull(tree_dendrites)

    # Visualize the result using SNT Viewer3D.
    viewer = Viewer()
    viewer.add(tree_axon)
    viewer.add(tree_dendrites)
    axon_hull = viewer.annotateSurface(verts_axon, "Axon Hull")
    dendrite_hull = viewer.annotateSurface(verts_dendrites, "Dendrite Hull")
    axon_hull.setColor("red")
    dendrite_hull.setColor("blue")
    viewer.show()
In [7]:
run()
The volume of the convex hull encapsulating all tip points is 208791575907.36 um^3
The area of the hull is 191199110.74 um^2

The volume of the convex hull encapsulating all tip points is 62095649.03 um^3
The area of the hull is 942390.38 um^2