diff --git a/src/main/java/sc/fiji/snt/analysis/ConvexHullAnalyzer.java b/src/main/java/sc/fiji/snt/analysis/ConvexHullAnalyzer.java index 391269db..4c063c1c 100644 --- a/src/main/java/sc/fiji/snt/analysis/ConvexHullAnalyzer.java +++ b/src/main/java/sc/fiji/snt/analysis/ConvexHullAnalyzer.java @@ -103,7 +103,7 @@ public Map getAnalysis() { if (isComputable()) { initHull(); metrics.put(BOUNDARY_SIZE, hull.boundarySize()); - metrics.put(BOXIVITY, (tree.is3D()) ? Double.NaN : computeBoxivity(hull)); + metrics.put(BOXIVITY, computeBoxivity(hull)); metrics.put(ELONGATION, computeElongation(hull)); metrics.put(ROUNDNESS, computeRoundness(hull)); metrics.put(SIZE, hull.size()); @@ -185,13 +185,18 @@ else if (hull instanceof ConvexHull2D) throw new IllegalArgumentException("Unsupported type:" + hull.getClass()); } - protected double computeBoxivity(final AbstractConvexHull hull) { // FIXME this does not work in 3D?? - if (hull instanceof ConvexHull3D) - return opService.geom().boxivity(((ConvexHull3D) hull).getMesh()).getRealDouble(); - else if (hull instanceof ConvexHull2D) - return opService.geom().boxivity(((ConvexHull2D) hull).getPolygon()).getRealDouble(); - else - throw new IllegalArgumentException("Unsupported type:" + hull.getClass()); + protected double computeBoxivity(final AbstractConvexHull hull) { + try { + if (hull instanceof ConvexHull3D) + return opService.geom().boxivity(((ConvexHull3D) hull).getMesh()).getRealDouble(); + else if (hull instanceof ConvexHull2D) + return opService.geom().boxivity(((ConvexHull2D) hull).getPolygon()).getRealDouble(); + } catch (final IllegalArgumentException iae) { + // BUG: No matching 'net.imagej.ops.Ops$Geometric$SmallestEnclosingBoundingBox/net.imagej.ops.special.function.UnaryFunctionOp' op + iae.printStackTrace(); + return Double.NaN; + } + throw new IllegalArgumentException("Unsupported type:" + hull.getClass()); } protected RealLocalizable computeCentroid(final AbstractConvexHull hull) { @@ -243,6 +248,16 @@ public Tree getTree() { return tree; } + /** + * Returns the physical unit associated with the specified metric. + * @param metric the supported metric to be queried (case-sensitive) + * @return physical unit + * @see #supportedMetrics() + */ + public String getUnit(final String metric) { + return new TreeStatistics(tree).getUnit(metric); + } + public static void main(final String[] args) throws InterruptedException { final ImageJ ij = new ImageJ(); final SNTService sntService = ij.context().getService(SNTService.class); diff --git a/src/main/java/sc/fiji/snt/gui/MeasureUI.java b/src/main/java/sc/fiji/snt/gui/MeasureUI.java index aa82b08e..d19aba06 100644 --- a/src/main/java/sc/fiji/snt/gui/MeasureUI.java +++ b/src/main/java/sc/fiji/snt/gui/MeasureUI.java @@ -720,6 +720,10 @@ private void measureTree(final Tree tree) { } final String unit = tStats.getUnit(metric); final String metricHeader = (unit.length() > 1) ? metric + " (" + unit + ")" : metric; + if (summaryStatistics.getN() < 1) { + table.set(metricHeader, tree.getLabel(), "Err"); + continue; + } if (summaryStatistics.getN() == 1 ) { table.set(metricHeader + " [Single value]", tree.getLabel(), summaryStatistics.getSum()); continue; diff --git a/src/main/java/sc/fiji/snt/plugin/ConvexHullCmd.java b/src/main/java/sc/fiji/snt/plugin/ConvexHullCmd.java index 362f7517..4f77110d 100644 --- a/src/main/java/sc/fiji/snt/plugin/ConvexHullCmd.java +++ b/src/main/java/sc/fiji/snt/plugin/ConvexHullCmd.java @@ -57,6 +57,7 @@ @Plugin(type = Command.class, visible = false, label = "Convex Hull Analysis...") public class ConvexHullCmd extends ContextCommand { + private static final String TOOLTIP = "See imagej.net/plugins/snt/metrics/"; @Parameter private SNTService sntService; @@ -88,16 +89,19 @@ public class ConvexHullCmd extends ContextCommand { @Parameter(label = "Measurements:", required = false, visibility = ItemVisibility.MESSAGE) private String HEADER2; - @Parameter(label = "Boundary Size") + @Parameter(label = "Boundary Size", description = TOOLTIP) private boolean doBoundarySize; - @Parameter(label = "Main Elongation") + @Parameter(label = "Boxivity", description = TOOLTIP) + private boolean doBoxivity; + + @Parameter(label = "Main Elongation", description = TOOLTIP) private boolean doMainElongation; - @Parameter(label = "Roundness") + @Parameter(label = "Roundness", description = TOOLTIP) private boolean doRoundness; - @Parameter(label = "Size") + @Parameter(label = "Size", description = TOOLTIP) private boolean doSize; @Override @@ -132,7 +136,7 @@ private void run(final Tree tree) { if (splitByType) { axon = tree.subTree("axon"); dendrite = tree.subTree("dendrite"); - if (axon.isEmpty() && dendrite.isEmpty()) { + if ( (axon == null || axon.isEmpty()) && (dendrite == null || dendrite.isEmpty()) ) { splitByType = false; axon = tree; } @@ -191,7 +195,7 @@ private void run(final Tree tree) { if (!table.isEmpty()) { final List> displays = displayService.getDisplays(table); if (displays != null && !displays.isEmpty()) { - displays.forEach(d -> d.update()); + displays.forEach(Display::update); } else { displayService.createDisplay("SNT Measurements", table); } @@ -215,19 +219,19 @@ private void addHullToRecViewer(final AbstractConvexHull hull, final String iden private void measure(final ConvexHullAnalyzer analyzer, final SNTTable table, final String rowLabel) { try { table.insertRow(rowLabel); - final String unit = (String) analyzer.getTree().getProperties().getOrDefault(Tree.KEY_SPATIAL_UNIT, - "? units"); - final boolean is3D = analyzer.getHull() instanceof ConvexHull3D; if (doSize) - table.appendToLastRow("Convex hull: Size (" + unit + ((is3D) ? "^3" : "^2") + ")", analyzer.getSize()); + table.appendToLastRow(String.format("Convex hull: Size (%s)", analyzer.getUnit("Convex hull: Size")), + analyzer.getSize()); if (doBoundarySize) - table.appendToLastRow("Convex hull: Boundary size (" + unit + ((is3D) ? "^2" : "") + ")", - analyzer.getBoundarySize()); + table.appendToLastRow(String.format("Convex hull: Boundary size (%s)", analyzer.getUnit("Convex hull: Boundary size")), + analyzer.getBoundarySize()); + if (doBoxivity) + table.appendToLastRow("Convex hull: Boxivity", analyzer.getBoxivity()); if (doRoundness) table.appendToLastRow("Convex hull: Roundness", analyzer.getRoundness()); if (doMainElongation) - table.appendToLastRow("Convex hull: Boundary size (" + unit + ")", - analyzer.getElongation()); + table.appendToLastRow(String.format("Convex hull: Elongation (%s)", analyzer.getUnit("Convex hull: Elongation")), + analyzer.getElongation()); } catch (final IndexOutOfBoundsException | IllegalArgumentException ex) { ex.printStackTrace(); }