Skip to content

Commit

Permalink
Retire TreeAnalyzer in favor of TreeStatistics (breaking change)
Browse files Browse the repository at this point in the history
  • Loading branch information
tferr committed Oct 31, 2024
1 parent 043acd6 commit 2156da2
Show file tree
Hide file tree
Showing 42 changed files with 2,852 additions and 3,077 deletions.
10 changes: 5 additions & 5 deletions notebooks/2_convex_hull.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"metadata": {},
"source": [
"## Imports\n",
"We'll need to 1) import Python modules; 2) initalize ij from local Fiji installation, and 3) import all relevant SNT (Java) classes: [AllenCompartment](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/annotation/AllenCompartment.html), [AllenUtils](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/annotation/AllenUtils.html), [Annotation3D](https://javadoc.scijava.org/SNT/sc/fiji/snt/viewer/Annotation3D.html), [ConvexHull2D](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/analysis/ConvexHull2D.html), [ConvexHull3D](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/analysis/ConvexHull3D.html), [MouseLightLoader](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/io/MouseLightLoader.html), [PointInImage](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/util/PointInImage.html), [Tree](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/Tree.html), [TreeAnalyzer](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/analysis/TreeAnalyzer.html), [Viewer3D](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/viewer/Viewer3D.html):"
"We'll need to 1) import Python modules; 2) initalize ij from local Fiji installation, and 3) import all relevant SNT (Java) classes: [AllenCompartment](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/annotation/AllenCompartment.html), [AllenUtils](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/annotation/AllenUtils.html), [Annotation3D](https://javadoc.scijava.org/SNT/sc/fiji/snt/viewer/Annotation3D.html), [ConvexHull2D](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/analysis/ConvexHull2D.html), [ConvexHull3D](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/analysis/ConvexHull3D.html), [MouseLightLoader](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/io/MouseLightLoader.html), [PointInImage](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/util/PointInImage.html), [Tree](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/Tree.html), [TreeStatistics](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/analysis/TreeStatistics.html), [Viewer3D](https://javadoc.scijava.org/SNT/index.html?sc/fiji/snt/viewer/Viewer3D.html):"
]
},
{
Expand Down Expand Up @@ -57,7 +57,7 @@
"NodeStatistics = jimport('sc.fiji.snt.analysis.NodeStatistics')\n",
"PointInImage = jimport('sc.fiji.snt.util.PointInImage')\n",
"Tree = jimport('sc.fiji.snt.Tree')\n",
"TreeAnalyzer = jimport('sc.fiji.snt.analysis.TreeAnalyzer')\n",
"TreeStatistics = jimport('sc.fiji.snt.analysis.TreeStatistics')\n",
"Viewer2D = jimport('sc.fiji.snt.viewer.Viewer2D')\n",
"Viewer3D = jimport('sc.fiji.snt.viewer.Viewer3D')"
]
Expand Down Expand Up @@ -93,13 +93,13 @@
" of axon terminal nodes and returns a collection containing \n",
" these nodes as well as the id of the relevant AllenCompartment\"\"\"\n",
" \n",
" # Use TreeAnalyzer to extract the terminal nodes from the Tree.\n",
" # Use TreeStatistics to extract the terminal nodes from the Tree.\n",
" # Instantiate a NodeStatistics instance and retrieve a list of the endpoints for\n",
" # each target brain region (a BrainAnnotation) in a dictionary, where the keys are\n",
" # the brain annotations. Since this neuron was fetched from the MouseLight database,\n",
" # the annotations are instances of the AllenCompartment Class\n",
" # https://morphonets.github.io/SNT/sc/fiji/snt/annotation/BrainAnnotation.html\n",
" tips = TreeAnalyzer(tree).getTips()\n",
" tips = TreeStatistics(tree).getTips()\n",
" node_stats = NodeStatistics(tips)\n",
" compartment_dict = node_stats.getAnnotatedNodes()\n",
"\n",
Expand Down Expand Up @@ -127,7 +127,7 @@
"source": [
"# Load the reconstruction from the MouseLight database, fetching just the axon\n",
"tree_axon = get_axon('AA1044')\n",
"print(tree_axon.getLabel(), \":\", len(TreeAnalyzer(tree_axon).getTips()), \"terminals\")"
"print(tree_axon.getLabel(), \":\", len(TreeStatistics(tree_axon).getTips()), \"terminals\")"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion notebooks/5_performance_testing.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"PointInImage = jimport('sc.fiji.snt.util.PointInImage')\n",
"MouseLightLoader = jimport('sc.fiji.snt.io.MouseLightLoader')\n",
"Tree = jimport('sc.fiji.snt.Tree')\n",
"TreeAnalyzer = jimport('sc.fiji.snt.analysis.TreeAnalyzer')\n",
"TreeStatistics = jimport('sc.fiji.snt.analysis.TreeStatistics')\n",
"Color = jimport('org.scijava.util.Colors')\n",
"Viewer = jimport('sc.fiji.snt.viewer.Viewer3D')"
]
Expand Down
6 changes: 3 additions & 3 deletions notebooks/7_timelapse_segmentation.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@
"id": "52cc4ec2",
"metadata": {},
"source": [
"We can also measure [Trees](https://javadoc.scijava.org/SNT/sc/fiji/snt/Tree.html) with the [TreeAnalyzer](https://javadoc.scijava.org/SNT/sc/fiji/snt/analysis/TreeAnalyzer.html) and [MultiTreeStatistics](https://javadoc.scijava.org/SNT/sc/fiji/snt/analysis/MultiTreeStatistics.html) classes, and plot measurements as a function of time."
"We can also measure [Trees](https://javadoc.scijava.org/SNT/sc/fiji/snt/Tree.html) with [TreeStatistics](https://javadoc.scijava.org/SNT/sc/fiji/snt/analysis/TreeStatistics.html) and [MultiTreeStatistics](https://javadoc.scijava.org/SNT/sc/fiji/snt/analysis/MultiTreeStatistics.html) classes, and plot measurements as a function of time."
]
},
{
Expand All @@ -365,15 +365,15 @@
}
],
"source": [
"TreeAnalyzer = jimport(\"sc.fiji.snt.analysis.TreeAnalyzer\")\n",
"TreeStatistics = jimport(\"sc.fiji.snt.analysis.TreeStatistics\")\n",
"MultiTreeStatistics = jimport(\"sc.fiji.snt.analysis.MultiTreeStatistics\")\n",
"\n",
"def plot_metric(root_nodes, metric, ax):\n",
" # Plot the measurements for each lineage\n",
" for i, r in enumerate(roots):\n",
" lineage_trees = lineage_to_trees(get_descendants(r))\n",
" xs = np.arange(r.frame, r.frame + len(lineage_trees))\n",
" ys = [TreeAnalyzer(tree).getMetric(metric) for tree in lineage_trees]\n",
" ys = [TreeStatistics(tree).getMetric(metric) for tree in lineage_trees]\n",
" ax.set_title(f\"{metric} vs Time\")\n",
" ax.set_ylabel(f\"{metric}\")\n",
" ax.set_xlabel(\"Frame\")\n",
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/sc/fiji/snt/Path.java
Original file line number Diff line number Diff line change
Expand Up @@ -3087,7 +3087,7 @@ protected boolean removeChangeListener(PathChangeListener listener) {
return changeListeners.remove(listener);
}

// FIXME: Implementing hasCode() and equals() breaks current TreeAnalyzer tests
// FIXME: Implementing hasCode() and equals() breaks current TreeStatistics tests
// @Override
// public int hashCode() {
// return Objects.hash(id, points, name, order, swcType, treeLabel);
Expand Down
12 changes: 6 additions & 6 deletions src/main/java/sc/fiji/snt/PathManagerUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -1915,12 +1915,12 @@ private void removeOrReapplyDefaultTag(final Collection<Path> paths, final Strin
}
break;
case "Extension Angle...":
case PathAnalyzer.PATH_EXT_ANGLE_XY:
case PathAnalyzer.PATH_EXT_ANGLE_XZ:
case PathAnalyzer.PATH_EXT_ANGLE_ZY:
case PathAnalyzer.PATH_EXT_ANGLE_REL_XY:
case PathAnalyzer.PATH_EXT_ANGLE_REL_XZ:
case PathAnalyzer.PATH_EXT_ANGLE_REL_ZY:
case PathStatistics.PATH_EXT_ANGLE_XY:
case PathStatistics.PATH_EXT_ANGLE_XZ:
case PathStatistics.PATH_EXT_ANGLE_ZY:
case PathStatistics.PATH_EXT_ANGLE_REL_XY:
case PathStatistics.PATH_EXT_ANGLE_REL_XZ:
case PathStatistics.PATH_EXT_ANGLE_REL_ZY:
paths.forEach(p -> p.setName(p.getName().replaceAll(" ?\\[" + SYM_ANGLE + "\\d+.\\d+]|\\[" + SYM_ANGLE + "NaN]", "")));
if (reapply) {
final boolean relative = cmd.toLowerCase().contains("rel");
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/sc/fiji/snt/SNTService.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
import ij.ImagePlus;
import sc.fiji.snt.analysis.PathProfiler;
import sc.fiji.snt.analysis.SNTTable;
import sc.fiji.snt.analysis.TreeAnalyzer;
import sc.fiji.snt.analysis.TreeStatistics;
import sc.fiji.snt.analysis.graph.DirectedWeightedGraph;
import sc.fiji.snt.gui.GuiUtils;
Expand Down Expand Up @@ -340,15 +339,15 @@ public Tree getTree() {
}

/**
* Returns a {@link TreeAnalyzer} instance constructed from current Paths.
* Returns a {@link TreeStatistics} instance constructed from current Paths.
*
* @param selectedPathsOnly If true only selected paths will be considered
* @return the TreeAnalyzer instance
* @return the TreeStatistics instance
* @throws UnsupportedOperationException if SNT is not running
*/
public TreeAnalyzer getAnalyzer(final boolean selectedPathsOnly) {
public TreeStatistics getAnalyzer(final boolean selectedPathsOnly) {
accessActiveInstance(false);
final TreeAnalyzer tAnalyzer = new TreeAnalyzer(getTree(selectedPathsOnly));
final TreeStatistics tAnalyzer = new TreeStatistics(getTree(selectedPathsOnly));
tAnalyzer.setContext(getContext());
tAnalyzer.setTable(getTable(), PathManagerUI.TABLE_TITLE);
return tAnalyzer;
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/sc/fiji/snt/SNTUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
import org.scijava.util.ColorRGB;
import org.scijava.util.Types;
import sc.fiji.snt.analysis.SNTTable;
import sc.fiji.snt.analysis.TreeAnalyzer;
import sc.fiji.snt.analysis.TreeStatistics;
import sc.fiji.snt.analysis.sholl.ShollUtils;
import sc.fiji.snt.event.SNTEvent;
import sc.fiji.snt.gui.*;
Expand Down Expand Up @@ -2669,7 +2669,7 @@ private JMenuBar createMenuBar() {
final Tree tree = getPathManager().getSingleTree();
if (tree == null) return;
try {
final TreeAnalyzer ta = new TreeAnalyzer(tree);
final TreeStatistics ta = new TreeStatistics(tree);
ta.setContext(plugin.getContext());
if (ta.getParsedTree().isEmpty()) {
guiUtils.error("None of the selected paths could be measured.");
Expand Down
12 changes: 6 additions & 6 deletions src/main/java/sc/fiji/snt/Tree.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import ij.ImagePlus;
import ij.ImageStack;
import ij.measure.Calibration;
import sc.fiji.snt.analysis.TreeAnalyzer;
import sc.fiji.snt.analysis.TreeStatistics;
import sc.fiji.snt.analysis.graph.DirectedWeightedGraph;
import sc.fiji.snt.hyperpanes.MultiDThreePanes;
import sc.fiji.snt.io.MouseLightLoader;
Expand Down Expand Up @@ -1773,7 +1773,7 @@ else if (isZY)
if (centroid) {
refPath = tree.get(0).createPath();
refPath.addNode(tree.getRoot());
final Set<PointInImage> tips = new TreeAnalyzer(tree).getTips();
final Set<PointInImage> tips = new TreeStatistics(tree).getTips();
tips.remove(tree.getRoot());
if (!tips.isEmpty()) refPath.addNode(SNTPoint.average(tips));
} else {
Expand Down Expand Up @@ -1814,7 +1814,7 @@ public static void main(final String[] args) {
//final Tree tree = new Tree("/home/tferr/Downloads/test_swc.swc");
final Tree tree = new SNTService().demoTree("fractal");
tree.swapAxes(Z_AXIS, Y_AXIS);
TreeAnalyzer analyzer = new TreeAnalyzer(tree);
TreeStatistics analyzer = new TreeStatistics(tree);
System.out.println("Creating graph...");

DirectedWeightedGraph graph = tree.getGraph();
Expand All @@ -1831,7 +1831,7 @@ public static void main(final String[] args) {
MouseLightLoader loader = new MouseLightLoader("AA0174");
Tree refSubTree = loader.getTree("axon");
DirectedWeightedGraph refGraph = refSubTree.getGraph();
TreeAnalyzer refAnalyzer = new TreeAnalyzer(refSubTree);
TreeStatistics refAnalyzer = new TreeStatistics(refSubTree);

System.out.println("Creating Subtree...");
Tree aTree = tree.subTree("axon");
Expand All @@ -1846,7 +1846,7 @@ public static void main(final String[] args) {
System.out.println("Avg time (all runs): " + SNTUtils.formatDouble(total % 1000 /nTimes, 4));

graph = aTree.getGraph();
analyzer = new TreeAnalyzer(aTree);
analyzer = new TreeStatistics(aTree);
System.out.println("Subtree properties:");
System.out.println("Label: \t\t" + aTree.getLabel());
System.out.println("nPaths: \t\t" + analyzer.getNPaths() + "/" + refAnalyzer.getNPaths());
Expand All @@ -1858,7 +1858,7 @@ public static void main(final String[] args) {
System.out.println("Branches: \t\t" + analyzer.getBranches().size() + "/" + refAnalyzer.getBranches().size());

// Did the filtering affect original tree?
analyzer = new TreeAnalyzer(tree);
analyzer = new TreeStatistics(tree);
graph = tree.getGraph();
System.out.println("\nOriginal Tree Before/After Filtering:");
System.out.println("Label: \t\t" + tree.getLabel());
Expand Down
1 change: 1 addition & 0 deletions src/main/java/sc/fiji/snt/analysis/AbstractConvexHull.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.Collection;

/**
* Parent class for convex hull analysis
* @author Cameron Arshadi
*/
public abstract class AbstractConvexHull {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/sc/fiji/snt/analysis/ConvexHull3D.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.Collection;

/**
* Convex hull analysis in 3D.
* @author Cameron Arshadi
*/
public class ConvexHull3D extends AbstractConvexHull {
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/sc/fiji/snt/analysis/GroupedTreeStatistics.java
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@ void compute(final Collection<BrainAnnotation> annotations, final Collection<Tre
for (final Tree tree : trees) {
if (tree == null)
continue;
final TreeAnalyzer analyzer = new TreeAnalyzer(tree);
final TreeStatistics analyzer = new TreeStatistics(tree);
final boolean includeChildren = annotation.getOntologyDepth() > 0;
double value;
switch (normFeature) {
Expand All @@ -841,12 +841,12 @@ void compute(final Collection<BrainAnnotation> annotations, final Collection<Tre
: analyzer.getCableLength(annotation, includeChildren);
break;
case N_BRANCH_POINTS:
value = (normalize) ? analyzer.getNbranchPointsNorm(annotation, includeChildren)
: analyzer.getNbranchPoints(annotation, includeChildren);
value = (normalize) ? analyzer.getNBranchPointsNorm(annotation, includeChildren)
: analyzer.getNBranchPoints(annotation, includeChildren);
break;
case N_TIPS:
value = (normalize) ? analyzer.getNtipsNorm(annotation, includeChildren)
: analyzer.getNtips(annotation, includeChildren);
value = (normalize) ? analyzer.getNTipsNorm(annotation, includeChildren)
: analyzer.getNTips(annotation, includeChildren);
break;
default:
throw new IllegalArgumentException("Unrecognized feature");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ private void mapInternal(final String measurement, final ColorTable colorTable)
super.map(measurement, colorTable);
if (Arrays.asList(MULTI_TREE_FLAGS).contains(measurement)) {
for (final MappedTree mt : mappedTrees) {
final TreeAnalyzer analyzer = new TreeAnalyzer(mt.tree);
final TreeStatistics analyzer = new TreeStatistics(mt.tree);
switch (measurement) {
case ASSIGNED_VALUE:
integerScale = false;
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/sc/fiji/snt/analysis/NodeStatistics.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@
import sc.fiji.snt.util.PointInImage;

/**
* Computes summary and descriptive statistics from a Collection of nodes.
* Computes summary and descriptive statistics from a Collection of nodes, including convenience methods to plot
* distributions of such data.
*
* @author Tiago Ferreira
* @param <T>
*/
public class NodeStatistics <T extends PointInImage> {

Expand Down Expand Up @@ -614,7 +614,7 @@ public static void main(final String[] args) {
hist.annotate("Free text");
hist.show();
final MouseLightLoader loader = new MouseLightLoader("AA0001");
final TreeAnalyzer analyzer = new TreeAnalyzer(loader.getTree("axon"));
final TreeStatistics analyzer = new TreeStatistics(loader.getTree("axon"));
final NodeStatistics<?> nStats = new NodeStatistics<>(analyzer.getTips());
final SNTChart plot = nStats.getAnnotatedFrequencyHistogram(6, "ratio", analyzer.tree);
plot.annotateCategory("CA1", "Not showing");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,23 @@
import sc.fiji.snt.TreeProperties;

/*
* A flavor of TreeStatistics that does not do graph conversions, ensuring paths
* can be measured independently of their connectivity.
* A flavor of TreeStatistics that does not do graph conversions, ensuring paths can be measured independently of
* their connectivity.
*/
public class PathAnalyzer extends TreeStatistics {
public class PathStatistics extends TreeStatistics {

/** Flag for {@value #N_CHILDREN} analysis. */
public static final String N_CHILDREN = "No. of children";

public PathAnalyzer(Collection<Path> paths, String label) {
public PathStatistics(Collection<Path> paths, String label) {
super(new Tree(paths));
tree.setLabel(label);
final String unit = paths.iterator().next().getCalibration().getUnit();
if (paths.stream().allMatch(p -> p.getCalibration().getUnit().equals(unit)))
tree.getProperties().setProperty(TreeProperties.KEY_SPATIAL_UNIT, unit);
}

public PathAnalyzer(final Path path) {
public PathStatistics(final Path path) {
this(Collections.singleton(path), path.getName());
}

Expand All @@ -64,10 +64,10 @@ public int getNBranches() {
}

@Override
public Number getMetric(final String metric) throws IllegalArgumentException {
public Number getMetric(final String metric) throws UnknownMetricException {
if ("Path ID".equalsIgnoreCase(metric))
return (tree.size() == 1) ? tree.list().get(0).getID() : Double.NaN;
return getMetricInternal(getNormalizedMeasurement(metric));
return super.getMetric(metric);
}

@Override
Expand Down Expand Up @@ -185,7 +185,7 @@ public Number getMetric(final String metric, final Path path) throws UnknownMetr
// we can recycle the logic behind #assembleStats(). Since, all
// getBranches() related code has been (hopefully) overridden, this will
// effectively retrieve the single-value metric for this path.
final PathAnalyzer analyzer = new PathAnalyzer(path);
final PathStatistics analyzer = new PathStatistics(path);
final SummaryStatistics dummy = new SummaryStatistics();
analyzer.assembleStats(new StatisticsInstance(dummy), metric);
return dummy.getMax(); // since N=1, same as the value itself
Expand All @@ -199,7 +199,7 @@ public void measureIndividualPaths(final Collection<String> metrics, final boole
final int row = getNextRow(path.getName());
table.set(getCol("SWC Type(s)"), row, Path.getSWCtypeName(path.getSWCType(), true)); // plural heading for consistency with other commands
measuringMetrics.forEach(metric -> {
table.set(getCol(metric), row, new PathAnalyzer(path).getMetric(metric, path));
table.set(getCol(metric), row, new PathStatistics(path).getMetric(metric, path));
});
});
if (summarize && table instanceof SNTTable) {
Expand Down
Loading

0 comments on commit 2156da2

Please sign in to comment.