Skip to content

Commit

Permalink
Metrics: Add ACI, organize names...
Browse files Browse the repository at this point in the history
... While at it add missing metrics and cleanup imports/unused code
  • Loading branch information
tferr committed Aug 8, 2024
1 parent d2d071c commit 6ad4673
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 110 deletions.
38 changes: 35 additions & 3 deletions src/main/java/sc/fiji/snt/Path.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import org.apache.commons.math3.analysis.polynomials.PolynomialFunction;
import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction;
import org.apache.commons.math3.stat.StatUtils;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.apache.commons.math3.stat.regression.SimpleRegression;
import org.apache.commons.math3.util.MathUtils;
import org.scijava.util.ColorRGB;
Expand Down Expand Up @@ -399,6 +398,39 @@ public double getContraction() {
return eDistance / length;
}

/**
* Gets the fractal dimension of this path.
*
* @return the fractal dimension of this path or Double.NaN if this path has less than 5 nodes
*/
public double getFractalDimension() {
if (size() < 5) { // Must have at least 4 points after the start-node
return Double.NaN;
}
final List<Double> pathDists = new ArrayList<>();
final List<Double> eucDists = new ArrayList<>();
for (int i = 1; i < size(); i++) { //Start at the second node
double pDist = getNodeWithoutChecks(i).distanceTo(getNodeWithoutChecks(i - 1));
if (!pathDists.isEmpty()) {
double cumDist = pathDists.get(i - 2) + pDist;
pathDists.add(cumDist);
} else {
pathDists.add(pDist);
}
double eDist = getNodeWithoutChecks(i).distanceTo(getNodeWithoutChecks(0));
eucDists.add(eDist);
}
double numerator = 0.0;
for (int i = 0; i < eucDists.size(); i++) {
numerator += Math.log(1 + eucDists.get(i)) * Math.log(1 + pathDists.get(i));
}
double denominator = 0.0;
for (final double eucDist : eucDists) {
denominator += Math.log(1 + eucDist) * Math.log(1 + eucDist);
}
return (double) numerator / denominator;
}

/**
* Gets the length of this Path
*
Expand All @@ -419,8 +451,8 @@ public double getLength() {
/*
* Computes the angle between the specified node and its two flanking neighbors.
* <p>
* If A being the specified node, B its previous neighbor, and C is subsequent neighbor, computes the angle
* between the vectors BA, and BC.
* With B being the specified node, A its previous neighbor, and C is subsequent neighbor, computes the angle
* between the vectors AB, and BC.
* </p>
* @return the angle in degrees (0-360 range) or Double.NaN if specified node does not have sufficient neighbors
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import net.imagej.display.ColorTables;
import net.imglib2.display.ColorTable;

import org.checkerframework.checker.units.qual.A;
import sc.fiji.snt.SNTUtils;
import sc.fiji.snt.Tree;
import sc.fiji.snt.annotation.AllenCompartment;
Expand Down
35 changes: 4 additions & 31 deletions src/main/java/sc/fiji/snt/analysis/TreeAnalyzer.java
Original file line number Diff line number Diff line change
Expand Up @@ -1301,41 +1301,14 @@ public double getAvgPartitionAsymmetry() throws IllegalArgumentException {
*
* @return a list containing the fractal dimension of each branch
* @see StrahlerAnalyzer#getBranches()
* @see Path#getFractalDimension()
* @throws IllegalArgumentException if the tree contains multiple roots or loops
*/
public List<Double> getFractalDimension() throws IllegalArgumentException {
final List<Path> branches = getBranches();
final List<Double> fractalDims = new ArrayList<>();
for (final Path b : branches) {
// Must have at least 4 points after the start-node in a branch
if (b.size() < 5) {
continue;
}
final List<Double> pathDists = new ArrayList<>();
final List<Double> eucDists = new ArrayList<>();
// Start at the second node in the branch
for (int i = 1; i < b.size(); i++) {
double pDist = b.getNode(i).distanceTo(b.getNode(i-1));
if (!pathDists.isEmpty()) {
double cumDist = pathDists.get(i-2) + pDist;
pathDists.add(cumDist);
}
else {
pathDists.add(pDist);
}
double eDist = b.getNode(i).distanceTo(b.getNode(0));
eucDists.add(eDist);
}
double numerator = 0.0;
for (int i = 0; i < eucDists.size(); i++) {
numerator += Math.log(1 + eucDists.get(i)) * Math.log(1 + pathDists.get(i));
}
double denominator = 0.0;
for (int i = 0; i < eucDists.size(); i++) {
denominator += Math.log(1 + eucDists.get(i)) * Math.log(1 + eucDists.get(i));
}
double fDim = (double) numerator / denominator;
fractalDims.add(fDim);
for (final Path b : getBranches()) {
final double fDim = b.getFractalDimension();
if (!Double.isNaN(fDim)) fractalDims.add(fDim);
}
return fractalDims;
}
Expand Down
150 changes: 88 additions & 62 deletions src/main/java/sc/fiji/snt/analysis/TreeStatistics.java

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/main/java/sc/fiji/snt/gui/MeasureUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ public boolean isCellEditable(final int row, final int column) {
// Enlarge default width of first column. Another option would be to have all
// columns to auto-fit at all times, e.g., https://stackoverflow.com/a/25570812.
// Maybe that would be better?
final String prototypeMetric = TreeStatistics.TERMINAL_EXTENSION_ANGLE_XY;
final String prototypeMetric = TreeStatistics.GRAPH_DIAMETER_ANGLE_XY;
for (int i = 0; i < statsTable.getColumnCount(); ++i) {
final int width = SwingUtilities.computeStringWidth(statsTable.getFontMetrics(statsTable.getFont()),
(i == 0) ? prototypeMetric : MEAN);
Expand Down
1 change: 0 additions & 1 deletion src/main/java/sc/fiji/snt/gui/SWCExportDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,6 @@ public void setCollapsed(final boolean collapse) {
private CollapsiblePanel warningPanel() {
final JLabel label = GuiUtils.leftAlignedLabel("<HTML>The following data is not stored in SWC files:" //
+ "<ul>" //
+ " <li>Image properties</li>"//
+ " <li><i>Fits</i>: Path refinements that do not override original nodes</li>"//
+ " <li><i>Fills</i>: All types</li>"//
+ " <li>Channel and frame position of path(s)</li>"//
Expand Down
1 change: 0 additions & 1 deletion src/main/java/sc/fiji/snt/plugin/GroupAnalyzerCmd.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/sc/fiji/snt/plugin/PathAnalyzerCmd.java
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public void run() {
metrics.add(PathAnalyzer.CONVEX_HULL_ELONGATION);
metrics.add(PathAnalyzer.CONVEX_HULL_ROUNDNESS);
}
if (fractalDimension) metrics.add(PathAnalyzer.BRANCH_FRACTAL_DIMENSION); // will be computed for paths
if (fractalDimension) metrics.add(PathAnalyzer.PATH_FRACTAL_DIMENSION);
if (nBranchPoints) metrics.add(PathAnalyzer.N_BRANCH_POINTS);
if (pathContraction) metrics.add(PathAnalyzer.PATH_CONTRACTION);
if (pathFragmentation) metrics.add(PathAnalyzer.N_PATH_NODES);
Expand Down
9 changes: 0 additions & 9 deletions src/main/java/sc/fiji/snt/plugin/TreeMapperCmd.java
Original file line number Diff line number Diff line change
Expand Up @@ -200,15 +200,6 @@ private void removeColorCoding() {
statusService.showStatus("Color code removed...");
}

private boolean isLargeData() {
long sum = 0;
for (final Tree tree : trees) {
sum += tree.getNodesCount();
if (sum > 10000) return true;
}
return false;
}

/* IDE debug method **/
public static void main(final String[] args) throws IOException {
final ImageJ ij = new ImageJ();
Expand Down

0 comments on commit 6ad4673

Please sign in to comment.