Skip to content

Inter–trabecular angles

Michael Doube edited this page Apr 21, 2022 · 2 revisions

This page documents technical specifications for the IntertrabecularAngleWrapper plugin. The tool can be used to study the geometry and morphology of trabecular bone. The functionality is based on the study by Reznikov et al (2016). The original code used in that study can be found here.

First IntertrabecularAngleWrapper skeletonises the input image by calling the Skeletonize3D plugin. Then it feeds the result to AnalyzeSkeleton, which creates an array of graphs (Graph[]) from the skeletons in the image. Each graph describes one skeleton. They consist of edges and vertices (or nodes). Each edge describes a branch in the skeleton and vertices the branching and end points.

A vertex is made of n points. That is, the Vertex class has an ArrayList<Point> member. Each 3D Point corresponds to a foreground voxel in the skeletonised image. In addition, a Vertex lists the edges or branches connected to it. For example, a triple point Vertex has three branches.

The Edge class contains two vertices: it's starting and end point. Between these points it has segments that are called "slabs". They are voxels that have exactly two neighbours in their 27-neighbourhood. The slabs of an Edge are stored in an ArrayList<Point>. Please note that a very short Edge may not have any slabs, i.e. the ArrayList may be null. Such an Edge has only the end points. Another special case is a circular Edge where the start and end point is the same Vertex.

The wrapper chooses the largest Graph (most vertices) returned by AnalyzeSkeleton_. The graph is then pruned. Pruning removes all loop, parallel and short edges from the graph. Loop edges have the same start end endpoint. Parallel edges are redundant connections between vertices that are already linked by other edges. That is, if v1 and v2 have n edges between them, pruning remove all but one of them. The distance between the endpoints of short edges are less than m, which is user defined. Short edges can be dead-ends, which don't lead to new sub-graphs. That is, they have exactly one end point that has only one branch - the edge itself. Dead-ends are removed from the graph. Short edges can also be deeper in the graph. In these cases the edge and its endpoints are removed, and a new vertex is placed in the middle of their coordinates. This new vertex connects to all of the edges previously connected to the removed endpoints. For example, if endpoint v1 connects to a, b & c, and v2 to d, b, & e, and the length of b < m, then pruning results in vertex v3 which has branches a, c, d and e.

The pruning has several options: iteration, clustering and minimum length. As mentioned before, minimum length controls the length of edges preserved in the pruning. Iteration controls if pruning performed again and again, until no more short edges remain. Each iteration can create new edges that are under the minimum length m.

Clustering controls how the pruning creates new vertices. If the option is true, then the algorithm starts from a certain vertex pair connected by a short edge, and then finds all vertices connected to them by short edges, before pruning and creating new a vertex. If clustering is false, then a new vertex is created every time a short edge is found. Consider a "triangle" of vertices v1, v2 and v3, where v1 is connected to v2, v2 to v3 and v3 to v1. Clustering finds all three, and prunes them into a single new vertex v4 at their center. Non-clustered pruning finds the pair v1 and v2 first, and then creates v4 at their centre. Then it finds v4 and v2, and creates v5 etc. The order in which pairs are found is not guaranteed, and it may affect the results. The non-clustering option was included the guarantee that the results are comparable with Reznikov et al.

IntertrabecularAngleWrapper

  • Menu path: Plugins>BoneJ>Inter-trabecular Angles
  • Duplicates the input image so that it doesn't get overwritten
  • Input
    • ImagePlus inputImage
    • int minimumValance
    • int maximumValance
    • int minimumTrabecularLength
    • int marginCutOff
    • boolean iteratePruning
    • boolean useClusters
    • boolean printCentroids
    • boolean printCulledEdgePercentages
    • boolean showSkeleton
  • Output
    • Table<DefaultColumn<String>, String> anglesTable
    • ResultsTable centroidTable
    • ResultsTable culledEdgePercentagesTable
    • ImagePlus skeletonImage
  • Calls
Setup dialog
  • Options
    • Minimum valence (int)
      • Label: Minimum valence
      • Widget: Slider, min: 3, max: 50, step: 1 = Theoretically there's no maximum valence, but to keep the slider usable, we set it at 50
      • Tooltip: Minimum number of outgoing branches needed for a trabecular node to be included in analysis
      • Callback to check that minimum valence <= maximum valence
    • Maximum valence (int)
      • Label: Maximum valence
      • Widget: Slider, min: 3, max: 50, step: 1 = Theoretically there's no maximum valence, but to keep the slider usable, we set it at 50
      • Tooltip: Maximum number of outgoing branches needed for a trabecular node to be included in analysis
      • Callback to check that minimum valence <= maximum valence
    • Minimum trabecular length (int)
      • Label: Minimum trabecular length (px)
      • Widget: Spinner-box, min:0, default 0, step: 1
      • Tooltip: Minimum length for a trabecula to be kept from being fused into a node
      • Defaults to 0
      • Value not saved (persist = false), because Real length
      • NB measures the distance from end-point to end-point (euclidean distance). Does not sum the length of all the slabs in an Edge.
    • Margin (int)
      • Label: Margin (px)
      • Widget: Spinner-box, min:0, default 0, step: 1
      • Tooltip: Nodes with centroids closer than this value to any image boundary will not be included in results
    • Iterate pruning (boolean)
      • Label: Iterate pruning
      • Widget: Checkbox
      • Tooltip: If true, iterates pruning as long as short edges remain. If false, pruning stops after a single pass
    • Use clusters (boolean)
      • Label: Use clusters
      • Widget: Checkbox
      • Tooltip: If true, considers connected components together as a cluster, otherwise only looks at single short edges (order-dependent!)
    • Print centroids (boolean)
      • Label: Print centroids
      • Widget: Checkbox
      • Tooltip: Print the centroids of vertices at both ends of each edge
    • Print culled edge percentages
      • Label: Print % culled edges
      • Widget: Checkbox
      • Tooltip: Print the percentage of each of the type of edges that were culled after calling analyseSkeleton
    • Show skeleton
      • Label: Show skeleton
      • Widget: Checkbox
      • Tooltip: Show skeletonisation
  • Other
    • Real length
      • Label: Calibrated minimum length
      • visibility: MESSAGE (non-interactive)
      • Shows Minimum trabecular length in the calibrated units of the input image
Messages
  • If the input image is null
    • show an error dialog
    • abort the run
  • If the input image is not 8-bit binary colour
    • show an error dialog
    • abort the run
    • this check is necessary as skeletonise crashes if condition is not met
  • If the input image has channels
    • show an error dialog
    • abort the run
  • If the input image has time frames
    • show an error dialog
    • abort the run
  • If the image has anisotropic voxel size
    • show a warning dialog if interactive or log message if headless
    • abort the run, if user clicks Cancel
  • If the image couldn't be skeletonised (Graph[] == null)
    • show an error dialog
    • abort the run
  • If the image contains more than one skeleton (Graph[].length > 1)
    • log a warning message (only largest graph is analyzed)
Results
  • Inter-trabecular angles (SharedTable)
    • All the angles (rad) between branches sorted into columns 3, 4, 5... by junction valence
  • Centroid table
    • An additional table of the centroids of end-point vertices of each edge
  • Culled edge percentages table
    • An additional table that lists the percentages of different types of edges pruned from the Graph in the analysis.
    • Types: loops, dead-ends, repeated edges (i.e. parallels), short edges
  • Skeleton image
    • Optionally show a copy of the skeleton image that intertrabecular angles worked on.
Differences from BoneJ1
  • Did not exist BoneJ1. This tool generalizes the idea of TriplePointAngles, and adds further tools to eliminate artefacts from the skeleton graph.