From 75eaf861ea81a105c2cf896038c1f38f3878612a Mon Sep 17 00:00:00 2001 From: mdoube Date: Mon, 11 May 2026 16:42:42 +0200 Subject: [PATCH 01/11] Mark the legacy ResultInserter as deprecated --- Legacy/util/src/main/java/org/bonej/util/ResultInserter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Legacy/util/src/main/java/org/bonej/util/ResultInserter.java b/Legacy/util/src/main/java/org/bonej/util/ResultInserter.java index 161e4451..583cb9fb 100644 --- a/Legacy/util/src/main/java/org/bonej/util/ResultInserter.java +++ b/Legacy/util/src/main/java/org/bonej/util/ResultInserter.java @@ -43,6 +43,7 @@ * * @author Michael Doube */ +@Deprecated public final class ResultInserter { private static final ResultInserter INSTANCE = new ResultInserter(); From 04ddef991d5a14f596e78e6aeb1f62c1e5311b8b Mon Sep 17 00:00:00 2001 From: mdoube Date: Tue, 12 May 2026 10:36:06 +0200 Subject: [PATCH 02/11] Let legacy plugins see the scijava SharedTable and other utilities --- Legacy/bonej/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Legacy/bonej/pom.xml b/Legacy/bonej/pom.xml index b6917fc8..67d5c9b8 100644 --- a/Legacy/bonej/pom.xml +++ b/Legacy/bonej/pom.xml @@ -105,6 +105,12 @@ ${project.version} + + org.bonej + bonej-utilities + ${project.version} + + net.imagej From c0135c96dbf703edc8fffcedf6b44f3854059713 Mon Sep 17 00:00:00 2001 From: mdoube Date: Tue, 12 May 2026 12:18:20 +0200 Subject: [PATCH 03/11] Give legacy plugins access to the modern plugin apis --- Legacy/bonej/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Legacy/bonej/pom.xml b/Legacy/bonej/pom.xml index 67d5c9b8..bd5231d4 100644 --- a/Legacy/bonej/pom.xml +++ b/Legacy/bonej/pom.xml @@ -110,6 +110,12 @@ bonej-utilities ${project.version} + + + org.bonej + bonej-plugins + ${project.version} + From 1ae2edf31aa752edeb94abde6ace1a19db88d9a0 Mon Sep 17 00:00:00 2001 From: mdoube Date: Tue, 12 May 2026 12:20:48 +0200 Subject: [PATCH 04/11] Put a light scijava wrapper on legacy Connectivity Let the command finder index the plugin like a modern plugin Use the modern BoneJ result table All calculation and data types are IJ1 / primitive --- .../java/org/bonej/plugins/Connectivity.java | 33 ++++++++++++++----- .../bonej/src/main/resources/plugins.config | 2 -- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/Legacy/bonej/src/main/java/org/bonej/plugins/Connectivity.java b/Legacy/bonej/src/main/java/org/bonej/plugins/Connectivity.java index e63d490f..ce8f2ac0 100644 --- a/Legacy/bonej/src/main/java/org/bonej/plugins/Connectivity.java +++ b/Legacy/bonej/src/main/java/org/bonej/plugins/Connectivity.java @@ -34,7 +34,11 @@ import org.bonej.util.ImageCheck; import org.bonej.util.Multithreader; -import org.bonej.util.ResultInserter; +//import org.bonej.util.ResultInserter; +import org.bonej.utilities.SharedTable; +import org.bonej.wrapperPlugins.BoneJCommand; +import org.scijava.command.Command; +import org.scijava.plugin.Plugin; import ij.IJ; import ij.ImagePlus; @@ -98,7 +102,8 @@ *

* */ -public class Connectivity implements PlugIn { +@Plugin(type = Command.class, menuPath = "Plugins>BoneJ>Connectivity>Connectivity") +public class Connectivity extends BoneJCommand implements PlugIn { private final static int[] EULER_LUT = fillEulerLUT(); @@ -109,8 +114,19 @@ public class Connectivity implements PlugIn { private int height = 0; /** working image depth */ - private int depth = 0; + private int depth = 0; + /** + * Modern scijava Plugin entry point. Calls the Legacy {@link #run(String)} method + */ + @Override + public void run() { + run(""); + } + + /** + * Legacy ImageJ1 plugin + */ @Override public void run(final String arg) { final ImagePlus imp = IJ.getImage(); @@ -132,12 +148,11 @@ public void run(final String arg) { + "particles or enclosed cavities.\n\n" + "Try running Purify prior to Connectivity."); } - final ResultInserter ri = ResultInserter.getInstance(); - ri.setResultInRow(imp, "Euler ch.", sumEuler); - ri.setResultInRow(imp, "Δ(χ)", deltaChi); - ri.setResultInRow(imp, "Connectivity", connectivity); - ri.setResultInRow(imp, "Conn.D (" + imp.getCalibration().getUnit() + "^-3)", connDensity); - ri.updateTable(); + SharedTable.add(imp.getTitle(), "Euler ch.", sumEuler); + SharedTable.add(imp.getTitle(), "Δ(χ)", deltaChi); + SharedTable.add(imp.getTitle(), "Connectivity", connectivity); + SharedTable.add(imp.getTitle(), "Conn.D (" + imp.getCalibration().getUnit() + "^-3)", connDensity); + resultsTable = SharedTable.getTable(); return; } diff --git a/Legacy/bonej/src/main/resources/plugins.config b/Legacy/bonej/src/main/resources/plugins.config index 3ceb1524..4a94d87d 100644 --- a/Legacy/bonej/src/main/resources/plugins.config +++ b/Legacy/bonej/src/main/resources/plugins.config @@ -33,8 +33,6 @@ Plugins>BoneJ>Analyze, "Calibrate SCANCO", org.bonej.plugins.DensityCalibrator(" Plugins>BoneJ>Analyze, "Orientation", org.bonej.plugins.Orienteer Plugins>BoneJ>Analyze, "Particle Analyser", org.bonej.plugins.ParticleCounter -Plugins>BoneJ>Connectivity, "Connectivity", org.bonej.plugins.Connectivity - Plugins>BoneJ, "Fit Sphere", org.bonej.plugins.SphereFitter Plugins>BoneJ, "Moments of Inertia", org.bonej.plugins.Moments Plugins>BoneJ, "Purify", org.bonej.plugins.Purify From 7a24d3186d5fbdc7ff5afc6fbe9e0fa5c70d4513 Mon Sep 17 00:00:00 2001 From: mdoube Date: Tue, 12 May 2026 13:50:17 +0200 Subject: [PATCH 05/11] Remove commented code --- Legacy/bonej/src/main/java/org/bonej/plugins/Connectivity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Legacy/bonej/src/main/java/org/bonej/plugins/Connectivity.java b/Legacy/bonej/src/main/java/org/bonej/plugins/Connectivity.java index ce8f2ac0..b630b13c 100644 --- a/Legacy/bonej/src/main/java/org/bonej/plugins/Connectivity.java +++ b/Legacy/bonej/src/main/java/org/bonej/plugins/Connectivity.java @@ -34,7 +34,6 @@ import org.bonej.util.ImageCheck; import org.bonej.util.Multithreader; -//import org.bonej.util.ResultInserter; import org.bonej.utilities.SharedTable; import org.bonej.wrapperPlugins.BoneJCommand; import org.scijava.command.Command; From ac154bc1716cc8e20d13c600b5afd3ced6d68e34 Mon Sep 17 00:00:00 2001 From: mdoube Date: Tue, 12 May 2026 13:57:23 +0200 Subject: [PATCH 06/11] Use scijava table for Moments of Inertia --- .../main/java/org/bonej/plugins/Moments.java | 65 +++++++++++-------- .../bonej/src/main/resources/plugins.config | 1 - 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/Legacy/bonej/src/main/java/org/bonej/plugins/Moments.java b/Legacy/bonej/src/main/java/org/bonej/plugins/Moments.java index a138cb97..212fda79 100644 --- a/Legacy/bonej/src/main/java/org/bonej/plugins/Moments.java +++ b/Legacy/bonej/src/main/java/org/bonej/plugins/Moments.java @@ -43,10 +43,13 @@ import org.bonej.util.ImageCheck; import org.bonej.util.MatrixUtils; import org.bonej.util.Multithreader; -import org.bonej.util.ResultInserter; import org.bonej.util.ThresholdGuesser; import org.jogamp.vecmath.Color3f; import org.jogamp.vecmath.Point3f; +import org.bonej.utilities.SharedTable; +import org.bonej.wrapperPlugins.BoneJCommand; +import org.scijava.command.Command; +import org.scijava.plugin.Plugin; import Jama.EigenvalueDecomposition; import Jama.Matrix; @@ -71,7 +74,8 @@ * * @author Michael Doube */ -public class Moments implements PlugIn, DialogListener { +@Plugin(type = Command.class, menuPath = "Plugins>BoneJ>Moments of Inertia") +public class Moments extends BoneJCommand implements PlugIn, DialogListener { private boolean fieldUpdated; private Calibration cal; @@ -110,6 +114,14 @@ public boolean dialogItemChanged(final GenericDialog gd, final AWTEvent e) { // conversion coefficient from mm^5 to kg.m² = 1.8*10^-12 // double cc = 1.8*Math.pow(10, -12); + /** + * Modern scijava Plugin entry point. Calls the Legacy {@link #run(String)} method + */ + @Override + public void run() { + run(""); + } + @Override public void run(final String arg) { final ImagePlus imp = IJ.getImage(); @@ -187,33 +199,32 @@ public void run(final String arg) { final double[] moments = (double[]) momentResults[1]; final String units = imp.getCalibration().getUnits(); - final ResultInserter ri = ResultInserter.getInstance(); - ri.setResultInRow(imp, "Xc (" + units + ")", centroid[0]); - ri.setResultInRow(imp, "Yc (" + units + ")", centroid[1]); - ri.setResultInRow(imp, "Zc (" + units + ")", centroid[2]); - ri.setResultInRow(imp, "Vol (" + units + "³)", moments[0]); - ri.setResultInRow(imp, "Mass (g)", moments[1]); - ri.setResultInRow(imp, "Icxx (kg.m²)", moments[2]); - ri.setResultInRow(imp, "Icyy (kg.m²)", moments[3]); - ri.setResultInRow(imp, "Iczz (kg.m²)", moments[4]); - ri.setResultInRow(imp, "Icxy (kg.m²)", moments[5]); - ri.setResultInRow(imp, "Icxz (kg.m²)", moments[6]); - ri.setResultInRow(imp, "Icyz (kg.m²)", moments[7]); - ri.setResultInRow(imp, "I1 (kg.m²)", E.getD().get(2, 2)); - ri.setResultInRow(imp, "I2 (kg.m²)", E.getD().get(1, 1)); - ri.setResultInRow(imp, "I3 (kg.m²)", E.getD().get(0, 0)); + SharedTable.add(imp.getTitle(), "Xc (" + units + ")", centroid[0]); + SharedTable.add(imp.getTitle(), "Yc (" + units + ")", centroid[1]); + SharedTable.add(imp.getTitle(), "Zc (" + units + ")", centroid[2]); + SharedTable.add(imp.getTitle(), "Vol (" + units + "³)", moments[0]); + SharedTable.add(imp.getTitle(), "Mass (g)", moments[1]); + SharedTable.add(imp.getTitle(), "Icxx (kg.m²)", moments[2]); + SharedTable.add(imp.getTitle(), "Icyy (kg.m²)", moments[3]); + SharedTable.add(imp.getTitle(), "Iczz (kg.m²)", moments[4]); + SharedTable.add(imp.getTitle(), "Icxy (kg.m²)", moments[5]); + SharedTable.add(imp.getTitle(), "Icxz (kg.m²)", moments[6]); + SharedTable.add(imp.getTitle(), "Icyz (kg.m²)", moments[7]); + SharedTable.add(imp.getTitle(), "I1 (kg.m²)", E.getD().get(2, 2)); + SharedTable.add(imp.getTitle(), "I2 (kg.m²)", E.getD().get(1, 1)); + SharedTable.add(imp.getTitle(), "I3 (kg.m²)", E.getD().get(0, 0)); if (doVerboseUnitVectors) { - ri.setResultInRow(imp, "vX0", E.getV().get(0, 0)); - ri.setResultInRow(imp, "vY0", E.getV().get(1, 0)); - ri.setResultInRow(imp, "vZ0", E.getV().get(2, 0)); - ri.setResultInRow(imp, "vX1", E.getV().get(0, 1)); - ri.setResultInRow(imp, "vY1", E.getV().get(1, 1)); - ri.setResultInRow(imp, "vZ1", E.getV().get(2, 1)); - ri.setResultInRow(imp, "vX2", E.getV().get(0, 2)); - ri.setResultInRow(imp, "vY2", E.getV().get(1, 2)); - ri.setResultInRow(imp, "vZ2", E.getV().get(2, 2)); + SharedTable.add(imp.getTitle(), "vX0", E.getV().get(0, 0)); + SharedTable.add(imp.getTitle(), "vY0", E.getV().get(1, 0)); + SharedTable.add(imp.getTitle(), "vZ0", E.getV().get(2, 0)); + SharedTable.add(imp.getTitle(), "vX1", E.getV().get(0, 1)); + SharedTable.add(imp.getTitle(), "vY1", E.getV().get(1, 1)); + SharedTable.add(imp.getTitle(), "vZ1", E.getV().get(2, 1)); + SharedTable.add(imp.getTitle(), "vX2", E.getV().get(0, 2)); + SharedTable.add(imp.getTitle(), "vY2", E.getV().get(1, 2)); + SharedTable.add(imp.getTitle(), "vZ2", E.getV().get(2, 2)); } - ri.updateTable(); + resultsTable = SharedTable.getTable(); if (doAlign) alignToPrincipalAxes(imp, E.getV(), centroid, startSlice, endSlice, min, max, doAxes).show(); diff --git a/Legacy/bonej/src/main/resources/plugins.config b/Legacy/bonej/src/main/resources/plugins.config index 4a94d87d..fb516b5a 100644 --- a/Legacy/bonej/src/main/resources/plugins.config +++ b/Legacy/bonej/src/main/resources/plugins.config @@ -34,7 +34,6 @@ Plugins>BoneJ>Analyze, "Orientation", org.bonej.plugins.Orienteer Plugins>BoneJ>Analyze, "Particle Analyser", org.bonej.plugins.ParticleCounter Plugins>BoneJ, "Fit Sphere", org.bonej.plugins.SphereFitter -Plugins>BoneJ, "Moments of Inertia", org.bonej.plugins.Moments Plugins>BoneJ, "Purify", org.bonej.plugins.Purify Plugins>BoneJ, "Slice Geometry", org.bonej.plugins.SliceGeometry From a5ba150905e9ad300623df75603fb113e71de76f Mon Sep 17 00:00:00 2001 From: mdoube Date: Tue, 12 May 2026 14:22:49 +0200 Subject: [PATCH 07/11] Use scijava SharedTable for SphereFitter --- .../java/org/bonej/plugins/SphereFitter.java | 27 +++++++++++++------ .../bonej/src/main/resources/plugins.config | 1 - 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Legacy/bonej/src/main/java/org/bonej/plugins/SphereFitter.java b/Legacy/bonej/src/main/java/org/bonej/plugins/SphereFitter.java index d7247af9..ccf3545c 100644 --- a/Legacy/bonej/src/main/java/org/bonej/plugins/SphereFitter.java +++ b/Legacy/bonej/src/main/java/org/bonej/plugins/SphereFitter.java @@ -39,7 +39,10 @@ import org.bonej.geometry.FitSphere; import org.bonej.util.DialogModifier; import org.bonej.util.ImageCheck; -import org.bonej.util.ResultInserter; +import org.bonej.utilities.SharedTable; +import org.bonej.wrapperPlugins.BoneJCommand; +import org.scijava.command.Command; +import org.scijava.plugin.Plugin; import ij.IJ; import ij.ImagePlus; @@ -61,7 +64,8 @@ * * @author Michael Doube and Angelo Tardugno */ -public class SphereFitter implements PlugIn, DialogListener { +@Plugin(type = Command.class, menuPath = "Plugins>BoneJ>Fit Sphere") +public class SphereFitter extends BoneJCommand implements PlugIn, DialogListener { @Override public boolean dialogItemChanged(final GenericDialog gd, final AWTEvent e) { @@ -80,6 +84,14 @@ public boolean dialogItemChanged(final GenericDialog gd, final AWTEvent e) { return true; } + /** + * Modern scijava Plugin entry point. Calls the Legacy {@link #run(String)} method + */ + @Override + public void run() { + run(""); + } + @Override public void run(final String arg) { final ImagePlus imp = IJ.getImage(); @@ -152,12 +164,11 @@ public void run(final String arg) { } final String units = imp.getCalibration().getUnits(); - final ResultInserter ri = ResultInserter.getInstance(); - ri.setResultInRow(imp, "X centroid (" + units + ")", sphereDim[0]); - ri.setResultInRow(imp, "Y centroid (" + units + ")", sphereDim[1]); - ri.setResultInRow(imp, "Z centroid (" + units + ")", sphereDim[2]); - ri.setResultInRow(imp, "Radius (" + units + ")", sphereDim[3]); - ri.updateTable(); + SharedTable.add(imp.getTitle(), "X centroid (" + units + ")", sphereDim[0]); + SharedTable.add(imp.getTitle(), "Y centroid (" + units + ")", sphereDim[1]); + SharedTable.add(imp.getTitle(), "Z centroid (" + units + ")", sphereDim[2]); + SharedTable.add(imp.getTitle(), "Radius (" + units + ")", sphereDim[3]); + resultsTable = SharedTable.getTable(); if (doCopy) copySphere(imp, padding, cropFactor, sphereDim).show(); if (doInnerCube) copyInnerCube(imp, cropFactor, sphereDim).show(); diff --git a/Legacy/bonej/src/main/resources/plugins.config b/Legacy/bonej/src/main/resources/plugins.config index fb516b5a..a48b5fd3 100644 --- a/Legacy/bonej/src/main/resources/plugins.config +++ b/Legacy/bonej/src/main/resources/plugins.config @@ -33,7 +33,6 @@ Plugins>BoneJ>Analyze, "Calibrate SCANCO", org.bonej.plugins.DensityCalibrator(" Plugins>BoneJ>Analyze, "Orientation", org.bonej.plugins.Orienteer Plugins>BoneJ>Analyze, "Particle Analyser", org.bonej.plugins.ParticleCounter -Plugins>BoneJ, "Fit Sphere", org.bonej.plugins.SphereFitter Plugins>BoneJ, "Purify", org.bonej.plugins.Purify Plugins>BoneJ, "Slice Geometry", org.bonej.plugins.SliceGeometry From 3af3fac0016fb1f92388c47fa0281885a5afbdf0 Mon Sep 17 00:00:00 2001 From: mdoube Date: Tue, 12 May 2026 15:08:30 +0200 Subject: [PATCH 08/11] Use scijava SharedTable for Purify --- .../main/java/org/bonej/plugins/Purify.java | 30 ++++++++++++------- .../bonej/src/main/resources/plugins.config | 1 - 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/Legacy/bonej/src/main/java/org/bonej/plugins/Purify.java b/Legacy/bonej/src/main/java/org/bonej/plugins/Purify.java index 73ca5227..76e97cbb 100644 --- a/Legacy/bonej/src/main/java/org/bonej/plugins/Purify.java +++ b/Legacy/bonej/src/main/java/org/bonej/plugins/Purify.java @@ -40,7 +40,11 @@ import ij.ImagePlus; import ij.ImageStack; import ij.gui.GenericDialog; -import ij.measure.ResultsTable; + +import org.bonej.utilities.SharedTable; +import org.bonej.wrapperPlugins.BoneJCommand; +import org.scijava.command.Command; +import org.scijava.plugin.Plugin; import ij.plugin.PlugIn; /** @@ -66,8 +70,17 @@ * @author Michael Doube * @version 1.0 */ -public class Purify implements PlugIn { +@Plugin(type = Command.class, menuPath = "Plugins>BoneJ>Purify") +public class Purify extends BoneJCommand implements PlugIn { + /** + * Modern scijava Plugin entry point. Calls the Legacy {@link #run(String)} method + */ + @Override + public void run() { + run(""); + } + @Override public void run(final String arg) { final ImagePlus imp = IJ.getImage(); @@ -108,15 +121,12 @@ public void run(final String arg) { * @param duration time elapsed in purifying. * @param imp the purified image. */ - private static void showResults(final double duration, final ImagePlus imp) + private void showResults(final double duration, final ImagePlus imp) { - final ResultsTable rt = ResultsTable.getResultsTable(); - rt.incrementCounter(); - rt.addLabel(imp.getTitle()); - rt.addValue("Threads", Runtime.getRuntime().availableProcessors()); - rt.addValue("Slices", imp.getImageStackSize()); - rt.addValue("Duration (s)", duration); - rt.show("Results"); + SharedTable.add(imp.getTitle(), "Purify Threads", Runtime.getRuntime().availableProcessors()); + SharedTable.add(imp.getTitle(), "Slices", imp.getImageStackSize()); + SharedTable.add(imp.getTitle(), "Duration (s)", duration); + resultsTable = SharedTable.getTable(); } /** diff --git a/Legacy/bonej/src/main/resources/plugins.config b/Legacy/bonej/src/main/resources/plugins.config index a48b5fd3..ed7f6820 100644 --- a/Legacy/bonej/src/main/resources/plugins.config +++ b/Legacy/bonej/src/main/resources/plugins.config @@ -33,7 +33,6 @@ Plugins>BoneJ>Analyze, "Calibrate SCANCO", org.bonej.plugins.DensityCalibrator(" Plugins>BoneJ>Analyze, "Orientation", org.bonej.plugins.Orienteer Plugins>BoneJ>Analyze, "Particle Analyser", org.bonej.plugins.ParticleCounter -Plugins>BoneJ, "Purify", org.bonej.plugins.Purify Plugins>BoneJ, "Slice Geometry", org.bonej.plugins.SliceGeometry Image>Stacks, "Check Voxel Depth", org.bonej.plugins.VoxelDepthChecker From 4e1bc00d9900eb7d8b7ca6ba9194a12d6c0ad4db Mon Sep 17 00:00:00 2001 From: mdoube Date: Tue, 12 May 2026 17:09:41 +0200 Subject: [PATCH 09/11] Use the shared table for particle analyser Clears the table on each call, does not append. --- .../org/bonej/plugins/ParticleCounter.java | 128 ++++++++++-------- .../bonej/src/main/resources/plugins.config | 1 - 2 files changed, 68 insertions(+), 61 deletions(-) diff --git a/Legacy/bonej/src/main/java/org/bonej/plugins/ParticleCounter.java b/Legacy/bonej/src/main/java/org/bonej/plugins/ParticleCounter.java index 190a0c2f..029f1a27 100644 --- a/Legacy/bonej/src/main/java/org/bonej/plugins/ParticleCounter.java +++ b/Legacy/bonej/src/main/java/org/bonej/plugins/ParticleCounter.java @@ -40,7 +40,11 @@ import org.bonej.menuWrappers.ThicknessHelper; import org.bonej.util.DialogModifier; import org.bonej.util.ImageCheck; +import org.bonej.utilities.SharedTable; +import org.bonej.wrapperPlugins.BoneJCommand; import org.jogamp.vecmath.Point3f; +import org.scijava.command.Command; +import org.scijava.plugin.Plugin; import Jama.EigenvalueDecomposition; @@ -49,7 +53,6 @@ import ij.gui.DialogListener; import ij.gui.GenericDialog; import ij.measure.Calibration; -import ij.measure.ResultsTable; import ij.plugin.PlugIn; import ij3d.Image3DUniverse; import sc.fiji.analyzeSkeleton.SkeletonResult; @@ -64,9 +67,9 @@ * * @author Michael Doube */ -public class ParticleCounter implements PlugIn, DialogListener { +@Plugin(type = Command.class, menuPath = "Plugins>BoneJ>Analyze>Particle Analyser") +public class ParticleCounter extends BoneJCommand implements PlugIn, DialogListener { - /* (non-Javadoc) * @see ij.gui.DialogListener#dialogItemChanged(ij.gui.GenericDialog, java.awt.AWTEvent) */ @@ -96,6 +99,14 @@ public boolean dialogItemChanged(final GenericDialog gd, final AWTEvent e) { return true; } + /** + * Modern scijava Plugin entry point. Calls the Legacy {@link #run(String)} method + */ + @Override + public void run() { + run(""); + } + /* (non-Javadoc) * @see ij.plugin.PlugIn#run(java.lang.String) */ @@ -292,54 +303,52 @@ public void run(final String arg) { } // Show numerical results - final ResultsTable rt = new ResultsTable(); + SharedTable.reset(); for (int i = 1; i < volumes.length; i++) { if (volumes[i] > 0) { - rt.incrementCounter(); - rt.addLabel(imp.getTitle()); - rt.addValue("ID", i); - rt.addValue("Vol. (" + units + "³)", volumes[i]); - rt.addValue("x Cent (" + units + ")", centroids[i][0]); - rt.addValue("y Cent (" + units + ")", centroids[i][1]); - rt.addValue("z Cent (" + units + ")", centroids[i][2]); + SharedTable.add(imp.getTitle(),"ID", i); + SharedTable.add(imp.getTitle(),"Vol. (" + units + "³)", volumes[i]); + SharedTable.add(imp.getTitle(),"x Cent (" + units + ")", centroids[i][0]); + SharedTable.add(imp.getTitle(),"y Cent (" + units + ")", centroids[i][1]); + SharedTable.add(imp.getTitle(),"z Cent (" + units + ")", centroids[i][2]); if (doAlignedBoxes) { - rt.addValue("Box x (" + units + ")", alignedBoxes[i][0]); - rt.addValue("Box y (" + units + ")", alignedBoxes[i][1]); - rt.addValue("Box z (" + units + ")", alignedBoxes[i][2]); - rt.addValue("Box l0 (" + units + ")", alignedBoxes[i][3]); - rt.addValue("Box l1 (" + units + ")", alignedBoxes[i][4]); - rt.addValue("Box l2 (" + units + ")", alignedBoxes[i][5]); + SharedTable.add(imp.getTitle(),"Box x (" + units + ")", alignedBoxes[i][0]); + SharedTable.add(imp.getTitle(),"Box y (" + units + ")", alignedBoxes[i][1]); + SharedTable.add(imp.getTitle(),"Box z (" + units + ")", alignedBoxes[i][2]); + SharedTable.add(imp.getTitle(),"Box l0 (" + units + ")", alignedBoxes[i][3]); + SharedTable.add(imp.getTitle(),"Box l1 (" + units + ")", alignedBoxes[i][4]); + SharedTable.add(imp.getTitle(),"Box l2 (" + units + ")", alignedBoxes[i][5]); } if (doSurfaceArea) { - rt.addValue("SA (" + units + "²)", surfaceAreas[i]); + SharedTable.add(imp.getTitle(),"SA (" + units + "²)", surfaceAreas[i]); } if (doFeret) { - rt.addValue("Feret (" + units + ")", ferets[i][0]); - rt.addValue("FeretAx (" + units + ")", ferets[i][1]); - rt.addValue("FeretAy (" + units + ")", ferets[i][2]); - rt.addValue("FeretAz (" + units + ")", ferets[i][3]); - rt.addValue("FeretBx (" + units + ")", ferets[i][4]); - rt.addValue("FeretBy (" + units + ")", ferets[i][5]); - rt.addValue("FeretBz (" + units + ")", ferets[i][6]); + SharedTable.add(imp.getTitle(),"Feret (" + units + ")", ferets[i][0]); + SharedTable.add(imp.getTitle(),"FeretAx (" + units + ")", ferets[i][1]); + SharedTable.add(imp.getTitle(),"FeretAy (" + units + ")", ferets[i][2]); + SharedTable.add(imp.getTitle(),"FeretAz (" + units + ")", ferets[i][3]); + SharedTable.add(imp.getTitle(),"FeretBx (" + units + ")", ferets[i][4]); + SharedTable.add(imp.getTitle(),"FeretBy (" + units + ")", ferets[i][5]); + SharedTable.add(imp.getTitle(),"FeretBz (" + units + ")", ferets[i][6]); } if (doSurfaceVolume) { - rt.addValue("Encl. Vol. (" + units + "³)", surfaceVolumes[i]); + SharedTable.add(imp.getTitle(),"Encl. Vol. (" + units + "³)", surfaceVolumes[i]); } if (doMoments) { final EigenvalueDecomposition E = eigens[i]; - rt.addValue("I1", E.getD().get(2, 2)); - rt.addValue("I2", E.getD().get(1, 1)); - rt.addValue("I3", E.getD().get(0, 0)); - rt.addValue("vX", E.getV().get(0, 0)); - rt.addValue("vY", E.getV().get(1, 0)); - rt.addValue("vZ", E.getV().get(2, 0)); + SharedTable.add(imp.getTitle(),"I1", E.getD().get(2, 2)); + SharedTable.add(imp.getTitle(),"I2", E.getD().get(1, 1)); + SharedTable.add(imp.getTitle(),"I3", E.getD().get(0, 0)); + SharedTable.add(imp.getTitle(),"vX", E.getV().get(0, 0)); + SharedTable.add(imp.getTitle(),"vY", E.getV().get(1, 0)); + SharedTable.add(imp.getTitle(),"vZ", E.getV().get(2, 0)); if (doVerboseUnitVectors) { - rt.addValue("vX1", E.getV().get(0, 1)); - rt.addValue("vY1", E.getV().get(1, 1)); - rt.addValue("vZ1", E.getV().get(2, 1)); - rt.addValue("vX2", E.getV().get(0, 2)); - rt.addValue("vY2", E.getV().get(1, 2)); - rt.addValue("vZ2", E.getV().get(2, 2)); + SharedTable.add(imp.getTitle(),"vX1", E.getV().get(0, 1)); + SharedTable.add(imp.getTitle(),"vY1", E.getV().get(1, 1)); + SharedTable.add(imp.getTitle(),"vZ1", E.getV().get(2, 1)); + SharedTable.add(imp.getTitle(),"vX2", E.getV().get(0, 2)); + SharedTable.add(imp.getTitle(),"vY2", E.getV().get(1, 2)); + SharedTable.add(imp.getTitle(),"vZ2", E.getV().get(2, 2)); } } if (doSkeletons) { @@ -353,18 +362,18 @@ public void run(final String arg) { branchesLength = skeletonResults[i].getAverageBranchLength()[0] * nBranches; } - rt.addValue("n Branches", nBranches); - rt.addValue("Branches length ("+units+")", branchesLength); + SharedTable.add(imp.getTitle(),"n Branches", nBranches); + SharedTable.add(imp.getTitle(),"Branches length ("+units+")", branchesLength); } if (doEulerCharacters) { - rt.addValue("Euler (χ)", eulerCharacters[i][0]); - rt.addValue("Holes (β1)", eulerCharacters[i][1]); - rt.addValue("Cavities (β2)", eulerCharacters[i][2]); + SharedTable.add(imp.getTitle(),"Euler (χ)", eulerCharacters[i][0]); + SharedTable.add(imp.getTitle(),"Holes (β1)", eulerCharacters[i][1]); + SharedTable.add(imp.getTitle(),"Cavities (β2)", eulerCharacters[i][2]); } if (doThickness) { - rt.addValue("Thickness (" + units + ")", thick[i][0]); - rt.addValue("SD Thickness (" + units + ")", thick[i][1]); - rt.addValue("Max Thickness (" + units + ")", thick[i][2]); + SharedTable.add(imp.getTitle(),"Thickness (" + units + ")", thick[i][0]); + SharedTable.add(imp.getTitle(),"SD Thickness (" + units + ")", thick[i][1]); + SharedTable.add(imp.getTitle(),"Max Thickness (" + units + ")", thick[i][2]); } if (doEllipsoids) { final double[] rad; @@ -380,25 +389,24 @@ public void run(final String arg) { rad = (double[]) el[1]; unitV = (double[][]) el[2]; } - rt.addValue("Major radius (" + units + ")", rad[0]); - rt.addValue("Int. radius (" + units + ")", rad[1]); - rt.addValue("Minor radius (" + units + ")", rad[2]); + SharedTable.add(imp.getTitle(),"Major radius (" + units + ")", rad[0]); + SharedTable.add(imp.getTitle(),"Int. radius (" + units + ")", rad[1]); + SharedTable.add(imp.getTitle(),"Minor radius (" + units + ")", rad[2]); if (doVerboseUnitVectors) { - rt.addValue("V00", unitV[0][0]); - rt.addValue("V01", unitV[0][1]); - rt.addValue("V02", unitV[0][2]); - rt.addValue("V10", unitV[1][0]); - rt.addValue("V11", unitV[1][1]); - rt.addValue("V12", unitV[1][2]); - rt.addValue("V20", unitV[2][0]); - rt.addValue("V21", unitV[2][1]); - rt.addValue("V22", unitV[2][2]); + SharedTable.add(imp.getTitle(),"V00", unitV[0][0]); + SharedTable.add(imp.getTitle(),"V01", unitV[0][1]); + SharedTable.add(imp.getTitle(),"V02", unitV[0][2]); + SharedTable.add(imp.getTitle(),"V10", unitV[1][0]); + SharedTable.add(imp.getTitle(),"V11", unitV[1][1]); + SharedTable.add(imp.getTitle(),"V12", unitV[1][2]); + SharedTable.add(imp.getTitle(),"V20", unitV[2][0]); + SharedTable.add(imp.getTitle(),"V21", unitV[2][1]); + SharedTable.add(imp.getTitle(),"V22", unitV[2][2]); } } - rt.updateResults(); } } - rt.show("Results"); + resultsTable = SharedTable.getTable(); // Show resulting image stacks if (doParticleImage) { diff --git a/Legacy/bonej/src/main/resources/plugins.config b/Legacy/bonej/src/main/resources/plugins.config index ed7f6820..19e9b6cd 100644 --- a/Legacy/bonej/src/main/resources/plugins.config +++ b/Legacy/bonej/src/main/resources/plugins.config @@ -31,7 +31,6 @@ Plugins>BoneJ>Analyze, "Calibrate SCANCO", org.bonej.plugins.DensityCalibrator("scanco") Plugins>BoneJ>Analyze, "Orientation", org.bonej.plugins.Orienteer -Plugins>BoneJ>Analyze, "Particle Analyser", org.bonej.plugins.ParticleCounter Plugins>BoneJ, "Slice Geometry", org.bonej.plugins.SliceGeometry From 156a227e66d47569b0cae0a61fe156cce2f6c66a Mon Sep 17 00:00:00 2001 From: mdoube Date: Tue, 12 May 2026 18:07:45 +0200 Subject: [PATCH 10/11] Slice Geometry uses the modern shared table --- .../java/org/bonej/plugins/SliceGeometry.java | 98 ++++++++++--------- .../bonej/src/main/resources/plugins.config | 2 - 2 files changed, 53 insertions(+), 47 deletions(-) diff --git a/Legacy/bonej/src/main/java/org/bonej/plugins/SliceGeometry.java b/Legacy/bonej/src/main/java/org/bonej/plugins/SliceGeometry.java index da5a8263..fdb0a350 100644 --- a/Legacy/bonej/src/main/java/org/bonej/plugins/SliceGeometry.java +++ b/Legacy/bonej/src/main/java/org/bonej/plugins/SliceGeometry.java @@ -43,8 +43,12 @@ import org.bonej.util.DialogModifier; import org.bonej.util.ImageCheck; import org.bonej.util.ThresholdGuesser; +import org.bonej.utilities.SharedTable; +import org.bonej.wrapperPlugins.BoneJCommand; import org.jogamp.vecmath.Color3f; import org.jogamp.vecmath.Point3f; +import org.scijava.command.Command; +import org.scijava.plugin.Plugin; import customnode.CustomPointMesh; import ij.IJ; @@ -56,7 +60,6 @@ import ij.gui.Roi; import ij.gui.Wand; import ij.measure.Calibration; -import ij.measure.ResultsTable; import ij.plugin.Duplicator; import ij.plugin.PlugIn; import ij.process.ByteProcessor; @@ -73,8 +76,8 @@ * * @author Michael Doube */ - -public class SliceGeometry implements PlugIn, DialogListener { +@Plugin(type = Command.class, menuPath = "Plugins>BoneJ>Slice Geometry") +public class SliceGeometry extends BoneJCommand implements PlugIn, DialogListener { private Calibration cal; private int al; @@ -197,6 +200,14 @@ public boolean dialogItemChanged(final GenericDialog gd, final AWTEvent e) { return true; } + /** + * Modern scijava Plugin entry point. Calls the Legacy {@link #run(String)} method + */ + @Override + public void run() { + run(""); + } + @Override public void run(final String arg) { final ImagePlus imp = IJ.getImage(); @@ -319,43 +330,40 @@ else if (roi.getType() != Roi.RECTANGLE) { // TODO locate centroids of multiple sections in a single plane - final ResultsTable rt = ResultsTable.getResultsTable(); - if (clearResults) rt.reset(); + if (clearResults) SharedTable.reset(); final String title = imp.getTitle(); for (int s = startSlice; s <= endSlice; s++) { - rt.incrementCounter(); - rt.addLabel(title); - rt.addValue("Bone Code", boneID); - rt.addValue("Slice", s); - rt.addValue("CSA (" + units + "²)", cortArea[s]); - rt.addValue("X cent. (" + units + ")", sliceCentroids[0][s]); - rt.addValue("Y cent. (" + units + ")", sliceCentroids[1][s]); - rt.addValue("Density", meanDensity[s]); - rt.addValue("wX cent. (" + units + ")", weightedCentroids[0][s]); - rt.addValue("wY cent. (" + units + ")", weightedCentroids[1][s]); - rt.addValue("Theta (rad)", theta[s]); - rt.addValue("R1 (" + units + ")", maxRadMax[s]); - rt.addValue("R2 (" + units + ")", maxRadMin[s]); - rt.addValue("Imin (" + units + "^4)", Imin[s]); - rt.addValue("Imax (" + units + "^4)", Imax[s]); - rt.addValue("Ipm (" + units + "^4)", Ipm[s]); - rt.addValue("Zmin (" + units + "³)", Zmin[s]); - rt.addValue("Zmax (" + units + "³)", Zmax[s]); - rt.addValue("Zpol (" + units + "³)", Zpol[s]); - rt.addValue("Feret Min (" + units + ")", feretMin[s]); - rt.addValue("Feret Max (" + units + ")", feretMax[s]); - rt.addValue("Feret Angle (rad)", feretAngle[s]); - rt.addValue("Perimeter (" + units + ")", perimeter[s]); + SharedTable.add(title, "Bone Code", boneID); + SharedTable.add(title, "Slice", s); + SharedTable.add(title, "CSA (" + units + "²)", cortArea[s]); + SharedTable.add(title, "X cent. (" + units + ")", sliceCentroids[0][s]); + SharedTable.add(title, "Y cent. (" + units + ")", sliceCentroids[1][s]); + SharedTable.add(title, "Density", meanDensity[s]); + SharedTable.add(title, "wX cent. (" + units + ")", weightedCentroids[0][s]); + SharedTable.add(title, "wY cent. (" + units + ")", weightedCentroids[1][s]); + SharedTable.add(title, "Theta (rad)", theta[s]); + SharedTable.add(title, "R1 (" + units + ")", maxRadMax[s]); + SharedTable.add(title, "R2 (" + units + ")", maxRadMin[s]); + SharedTable.add(title, "Imin (" + units + "^4)", Imin[s]); + SharedTable.add(title, "Imax (" + units + "^4)", Imax[s]); + SharedTable.add(title, "Ipm (" + units + "^4)", Ipm[s]); + SharedTable.add(title, "Zmin (" + units + "³)", Zmin[s]); + SharedTable.add(title, "Zmax (" + units + "³)", Zmax[s]); + SharedTable.add(title, "Zpol (" + units + "³)", Zpol[s]); + SharedTable.add(title, "Feret Min (" + units + ")", feretMin[s]); + SharedTable.add(title, "Feret Max (" + units + ")", feretMax[s]); + SharedTable.add(title, "Feret Angle (rad)", feretAngle[s]); + SharedTable.add(title, "Perimeter (" + units + ")", perimeter[s]); if (doThickness3D) { - rt.addValue("Max Thick 3D (" + units + ")", maxCortThick3D[s]); - rt.addValue("Mean Thick 3D (" + units + ")", meanCortThick3D[s]); - rt.addValue("SD Thick 3D (" + units + ")", stdevCortThick3D[s]); + SharedTable.add(title, "Max Thick 3D (" + units + ")", maxCortThick3D[s]); + SharedTable.add(title, "Mean Thick 3D (" + units + ")", meanCortThick3D[s]); + SharedTable.add(title, "SD Thick 3D (" + units + ")", stdevCortThick3D[s]); } if (doThickness2D) { - rt.addValue("Max Thick 2D (" + units + ")", maxCortThick2D[s]); - rt.addValue("Mean Thick 2D (" + units + ")", meanCortThick2D[s]); - rt.addValue("SD Thick 2D (" + units + ")", stdevCortThick2D[s]); + SharedTable.add(title, "Max Thick 2D (" + units + ")", maxCortThick2D[s]); + SharedTable.add(title, "Mean Thick 2D (" + units + ")", meanCortThick2D[s]); + SharedTable.add(title, "SD Thick 2D (" + units + ")", stdevCortThick2D[s]); } if (!doOriented || orienteer == null) { continue; @@ -364,20 +372,20 @@ else if (roi.getType() != Roi.RECTANGLE) { if (dirs == null) { continue; } - rt.addValue(dirs[0] + " (rad)", orienteer.getOrientation(imp, dirs[0])); - rt.addValue(dirs[2] + " (rad)", orienteer.getOrientation(imp, dirs[2])); - rt.addValue("I" + dirs[0] + dirs[1] + "(" + units + "^4)", I1[s]); - rt.addValue("I" + dirs[2] + dirs[3] + "(" + units + "^4)", I2[s]); - rt.addValue("Z" + dirs[0] + dirs[1] + "(" + units + "³)", Z1[s]); - rt.addValue("Z" + dirs[2] + dirs[3] + "(" + units + "³)", Z2[s]); - rt.addValue("R" + dirs[0] + dirs[1] + "(" + units + ")", maxRad2[s]); - rt.addValue("R" + dirs[2] + dirs[3] + "(" + units + ")", maxRad1[s]); - rt.addValue("D" + dirs[0] + dirs[1] + "(" + units + ")", + SharedTable.add(title, dirs[0] + " (rad)", orienteer.getOrientation(imp, dirs[0])); + SharedTable.add(title, dirs[2] + " (rad)", orienteer.getOrientation(imp, dirs[2])); + SharedTable.add(title, "I" + dirs[0] + dirs[1] + "(" + units + "^4)", I1[s]); + SharedTable.add(title, "I" + dirs[2] + dirs[3] + "(" + units + "^4)", I2[s]); + SharedTable.add(title, "Z" + dirs[0] + dirs[1] + "(" + units + "³)", Z1[s]); + SharedTable.add(title, "Z" + dirs[2] + dirs[3] + "(" + units + "³)", Z2[s]); + SharedTable.add(title, "R" + dirs[0] + dirs[1] + "(" + units + ")", maxRad2[s]); + SharedTable.add(title, "R" + dirs[2] + dirs[3] + "(" + units + ")", maxRad1[s]); + SharedTable.add(title, "D" + dirs[0] + dirs[1] + "(" + units + ")", principalDiameter[s]); - rt.addValue("D" + dirs[2] + dirs[3] + "(" + units + ")", + SharedTable.add(title, "D" + dirs[2] + dirs[3] + "(" + units + ")", secondaryDiameter[s]); } - rt.show("Results"); + resultsTable = SharedTable.getTable(); if (doAxes || doCentroids) { if (!doCopy) { diff --git a/Legacy/bonej/src/main/resources/plugins.config b/Legacy/bonej/src/main/resources/plugins.config index 19e9b6cd..626fdaba 100644 --- a/Legacy/bonej/src/main/resources/plugins.config +++ b/Legacy/bonej/src/main/resources/plugins.config @@ -32,7 +32,5 @@ Plugins>BoneJ>Analyze, "Calibrate SCANCO", org.bonej.plugins.DensityCalibrator("scanco") Plugins>BoneJ>Analyze, "Orientation", org.bonej.plugins.Orienteer -Plugins>BoneJ, "Slice Geometry", org.bonej.plugins.SliceGeometry - Image>Stacks, "Check Voxel Depth", org.bonej.plugins.VoxelDepthChecker Image>Stacks, "Delete Slice Range", org.bonej.plugins.DeleteSliceRange From 8bc50940c97a0c444c8a5cbdbc084e268bd81264 Mon Sep 17 00:00:00 2001 From: mdoube Date: Wed, 13 May 2026 08:58:20 +0200 Subject: [PATCH 11/11] Remove legacy ResultInserter --- .../java/org/bonej/util/ResultInserter.java | 109 ------------------ 1 file changed, 109 deletions(-) delete mode 100644 Legacy/util/src/main/java/org/bonej/util/ResultInserter.java diff --git a/Legacy/util/src/main/java/org/bonej/util/ResultInserter.java b/Legacy/util/src/main/java/org/bonej/util/ResultInserter.java deleted file mode 100644 index 583cb9fb..00000000 --- a/Legacy/util/src/main/java/org/bonej/util/ResultInserter.java +++ /dev/null @@ -1,109 +0,0 @@ -/*- - * #%L - * Utility classes for BoneJ1 plugins - * %% - * Copyright (C) 2015 - 2026 Michael Doube, BoneJ developers - * %% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * #L% - */ - - -package org.bonej.util; - -import ij.ImagePlus; -import ij.measure.ResultsTable; - -/** - * Receive results from analytic methods and insert them into the Results table - * in a sensible way. - *

- * Each image gets a line; measurements of different types are added to the same - * line; repeat measurements on same image go on a new line. - *

- * - * @author Michael Doube - */ -@Deprecated -public final class ResultInserter { - - private static final ResultInserter INSTANCE = new ResultInserter(); - private static ResultsTable rt; - - private ResultInserter() {} - - /** - * Finds the first available space for a result, avoiding lots of empty space - * when measurements of different types are made on the same image - * - * @param imp ImagePlus - * @param colHeading column heading - * @param value value to insert - */ - // TODO use a table other than the system Results table - public void setResultInRow(final ImagePlus imp, final String colHeading, - final double value) - { - final String title = imp.getTitle(); - - // search for the last value that contains the image title - // and contains no value for the heading - for (int row = rt.getCounter()-1; row >= 0; row--) { - if (rt.getLabel(row) == null) { - rt.setLabel(title, row); - } - if (rt.getLabel(row).equals(title)) { - // there could be no column called colHeading - if (!rt.columnExists(rt.getColumnIndex(colHeading))) { - // in which case, just insert the value - rt.setValue(colHeading, row, value); - return; - } // but if there is, it might or might not have data in it - final Double currentValue = rt.getValue(colHeading, row); - if (currentValue.equals(Double.NaN)) { - rt.setValue(colHeading, row, value); - return; - } - // look for another row with the right title - } - } - // we got to the end of the table without finding a space to insert - // the value, so make a new row for it - rt.incrementCounter(); - rt.addLabel(title); - rt.addValue(colHeading, value); - } - - /** - * Show the table - */ - public void updateTable() { - final String table = "Results"; - rt.show(table); - } - - public static ResultInserter getInstance() { - rt = ResultsTable.getResultsTable(); - rt.setNaNEmptyCells(true); - return INSTANCE; - } -}