Giter VIP home page Giter VIP logo

bonej2's People

Contributors

alessandrofelder avatar ctrueden avatar gselzer avatar hinerm avatar imagejan avatar mdoube avatar rgaiacs avatar rimadoma avatar sjcross avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

bonej2's Issues

Can't easily save BoneJ results from table

BoneJ2 results are stored in a SharedTable called "BoneJ results" and displayed to the user (or not, if running headless).

There appears to be no programmatic way to save the results - commands from the File menu have no effect, and there is no 'save' method in the parent Table class.

It is possible to copy paste via the UI into a spreadsheet like LibreOffice Calc or into a text editor.

Users need a way to save table data via UI and scripts.

Test images for Calibrate SCANCO plugin

Need to ask @kkunzelm for suitable images to test the Calibrate SCANCO plugin. The .isq-files I've tried so far give a "File is not a SCANCO Medical DICOM" error, because String manufacturer is null. For this reason I haven't been able to complete the integration test.

Wrapper tests output console errors

When the test classes in org.bonej.wrapperPlugins are run together they print a huge list of errors to the console. All the tests still pass. The errors do not appear if you run the test suites individually. Somehow the ImageJ context may not get disposed..?

The list of errors:

[ECLIPSE HELPER] Indexing annotations...
[INFO] Overriding BoneJ2; identifier: command:wrapperPlugins.Help; jar: null
[INFO] Overriding BoneJ2; identifier: command:bonej.wrapperPlugins.Help; jar: null
[INFO] Overriding BoneJ2; identifier: command:Help; jar: null
[INFO] Overriding Analyse Skeleton; identifier: command:wrapperPlugins.AnalyseSkeletonWrapper; jar: null
[INFO] Overriding Analyse Skeleton; identifier: command:bonej.wrapperPlugins.AnalyseSkeletonWrapper; jar: null
[INFO] Overriding Analyse Skeleton; identifier: command:AnalyseSkeletonWrapper; jar: null
[INFO] Overriding Connectivity; identifier: command:wrapperPlugins.ConnectivityWrapper; jar: null
[INFO] Overriding Connectivity; identifier: command:bonej.wrapperPlugins.ConnectivityWrapper; jar: null
[INFO] Overriding Connectivity; identifier: command:ConnectivityWrapper; jar: null
[INFO] Overriding Skeletonise; identifier: command:wrapperPlugins.SkeletoniseWrapper; jar: null
[INFO] Overriding Skeletonise; identifier: command:bonej.wrapperPlugins.SkeletoniseWrapper; jar: null
[INFO] Overriding Skeletonise; identifier: command:SkeletoniseWrapper; jar: null
[INFO] Overriding Thickness; identifier: command:wrapperPlugins.ThicknessWrapper; jar: null
[INFO] Overriding Thickness; identifier: command:bonej.wrapperPlugins.ThicknessWrapper; jar: null
[INFO] Overriding Thickness; identifier: command:ThicknessWrapper; jar: null
[INFO] Overriding Triple Point Angles; identifier: command:wrapperPlugins.TriplePointAnglesWrapper; jar: null
[INFO] Overriding Triple Point Angles; identifier: command:bonej.wrapperPlugins.TriplePointAnglesWrapper; jar: null
[INFO] Overriding Triple Point Angles; identifier: command:TriplePointAnglesWrapper; jar: null
[INFO] Overriding Cuboid; identifier: command:Cuboid; jar: null
[INFO] Overriding Cuboid; identifier: command:bonej.testImages.Cuboid; jar: null
[INFO] Overriding Cuboid; identifier: command:testImages.Cuboid; jar: null
[INFO] Overriding Hollow cuboid; identifier: command:HollowCuboid; jar: null
[INFO] Overriding Hollow cuboid; identifier: command:bonej.testImages.HollowCuboid; jar: null
[INFO] Overriding Hollow cuboid; identifier: command:testImages.HollowCuboid; jar: null
[INFO] Overriding Wire-frame cuboid; identifier: command:WireFrameCuboid; jar: null
[INFO] Overriding Wire-frame cuboid; identifier: command:bonej.testImages.WireFrameCuboid; jar: null
[INFO] Overriding Wire-frame cuboid; identifier: command:testImages.WireFrameCuboid; jar: null
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Analyse Skeleton', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Analyse Skeleton', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Analyse Skeleton', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Analyse Skeleton', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Analyse Skeleton', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Analyse Skeleton', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Connectivity', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Connectivity', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Connectivity', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Connectivity', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Connectivity', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Connectivity', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Skeletonise', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Skeletonise', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Skeletonise', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Skeletonise', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Skeletonise', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Skeletonise', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Thickness', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Thickness', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Thickness', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Thickness', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Thickness', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Thickness', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Triple Point Angles', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Triple Point Angles', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Triple Point Angles', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Triple Point Angles', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: menu='Plugins > BoneJ > Triple Point Angles', priority=0.0, enabled=true, pluginType=Command
     ignored: menu='Plugins > BoneJ > Triple Point Angles', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: name='BoneJ2Help', menu='Help > About Plugins > BoneJ2', priority=0.0, enabled=true, pluginType=Command
     ignored: name='BoneJ2Help', menu='Help > About Plugins > BoneJ2', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: name='BoneJ2Help', menu='Help > About Plugins > BoneJ2', priority=0.0, enabled=true, pluginType=Command
     ignored: name='BoneJ2Help', menu='Help > About Plugins > BoneJ2', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: name='BoneJ2Help', menu='Help > About Plugins > BoneJ2', priority=0.0, enabled=true, pluginType=Command
     ignored: name='BoneJ2Help', menu='Help > About Plugins > BoneJ2', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: name='cuboid', menu='Plugins > Test Images > Cuboid', priority=0.0, enabled=true, pluginType=Command
     ignored: name='cuboid', menu='Plugins > Test Images > Cuboid', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: name='cuboid', menu='Plugins > Test Images > Cuboid', priority=0.0, enabled=true, pluginType=Command
     ignored: name='cuboid', menu='Plugins > Test Images > Cuboid', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: name='cuboid', menu='Plugins > Test Images > Cuboid', priority=0.0, enabled=true, pluginType=Command
     ignored: name='cuboid', menu='Plugins > Test Images > Cuboid', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: name='hollowCuboid', menu='Plugins > Test Images > Hollow cuboid', priority=0.0, enabled=true, pluginType=Command
     ignored: name='hollowCuboid', menu='Plugins > Test Images > Hollow cuboid', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: name='hollowCuboid', menu='Plugins > Test Images > Hollow cuboid', priority=0.0, enabled=true, pluginType=Command
     ignored: name='hollowCuboid', menu='Plugins > Test Images > Hollow cuboid', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: name='hollowCuboid', menu='Plugins > Test Images > Hollow cuboid', priority=0.0, enabled=true, pluginType=Command
     ignored: name='hollowCuboid', menu='Plugins > Test Images > Hollow cuboid', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: name='wireFrameCuboid', menu='Plugins > Test Images > Wire-frame cuboid', priority=0.0, enabled=true, pluginType=Command
     ignored: name='wireFrameCuboid', menu='Plugins > Test Images > Wire-frame cuboid', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: name='wireFrameCuboid', menu='Plugins > Test Images > Wire-frame cuboid', priority=0.0, enabled=true, pluginType=Command
     ignored: name='wireFrameCuboid', menu='Plugins > Test Images > Wire-frame cuboid', priority=0.0, enabled=true, pluginType=Command
[WARNING] ShadowMenu: menu item already exists:
    existing: name='wireFrameCuboid', menu='Plugins > Test Images > Wire-frame cuboid', priority=0.0, enabled=true, pluginType=Command
     ignored: name='wireFrameCuboid', menu='Plugins > Test Images > Wire-frame cuboid', priority=0.0, enabled=true, pluginType=Command
[ERROR] Invalid op: ops.TriplePointAngles
[ERROR] Invalid op: bonej.ops.TriplePointAngles
[ERROR] Invalid op: TriplePointAngles
[ERROR] Invalid op: ops.CentroidLinAlg3d
[ERROR] Invalid op: bonej.ops.CentroidLinAlg3d
[ERROR] Invalid op: CentroidLinAlg3d
[ERROR] Invalid op: Cuboid
[ERROR] Invalid op: bonej.testImages.Cuboid
[ERROR] Invalid op: testImages.Cuboid
[ERROR] Invalid op: ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: bonej.ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: EulerCharacteristic
[ERROR] Invalid op: connectivity.EulerCharacteristic
[ERROR] Invalid op: ops.connectivity.EulerCorrection
[ERROR] Invalid op: bonej.ops.connectivity.EulerCorrection
[ERROR] Invalid op: EulerCorrection
[ERROR] Invalid op: connectivity.EulerCorrection
[ERROR] Invalid op: HollowCuboid
[ERROR] Invalid op: bonej.testImages.HollowCuboid
[ERROR] Invalid op: testImages.HollowCuboid
[ERROR] Invalid op: WireFrameCuboid
[ERROR] Invalid op: bonej.testImages.WireFrameCuboid
[ERROR] Invalid op: testImages.WireFrameCuboid
[ERROR] Invalid op: ops.TriplePointAngles
[ERROR] Invalid op: bonej.ops.TriplePointAngles
[ERROR] Invalid op: TriplePointAngles
[ERROR] Invalid op: ops.CentroidLinAlg3d
[ERROR] Invalid op: bonej.ops.CentroidLinAlg3d
[ERROR] Invalid op: CentroidLinAlg3d
[ERROR] Invalid op: Cuboid
[ERROR] Invalid op: bonej.testImages.Cuboid
[ERROR] Invalid op: testImages.Cuboid
[ERROR] Invalid op: ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: bonej.ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: EulerCharacteristic
[ERROR] Invalid op: connectivity.EulerCharacteristic
[ERROR] Invalid op: ops.connectivity.EulerCorrection
[ERROR] Invalid op: bonej.ops.connectivity.EulerCorrection
[ERROR] Invalid op: EulerCorrection
[ERROR] Invalid op: connectivity.EulerCorrection
[ERROR] Invalid op: HollowCuboid
[ERROR] Invalid op: bonej.testImages.HollowCuboid
[ERROR] Invalid op: testImages.HollowCuboid
[ERROR] Invalid op: WireFrameCuboid
[ERROR] Invalid op: bonej.testImages.WireFrameCuboid
[ERROR] Invalid op: testImages.WireFrameCuboid
[ERROR] Invalid op: ops.TriplePointAngles
[ERROR] Invalid op: bonej.ops.TriplePointAngles
[ERROR] Invalid op: TriplePointAngles
[ERROR] Invalid op: ops.CentroidLinAlg3d
[ERROR] Invalid op: bonej.ops.CentroidLinAlg3d
[ERROR] Invalid op: CentroidLinAlg3d
[ERROR] Invalid op: Cuboid
[ERROR] Invalid op: bonej.testImages.Cuboid
[ERROR] Invalid op: testImages.Cuboid
[ERROR] Invalid op: ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: bonej.ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: EulerCharacteristic
[ERROR] Invalid op: connectivity.EulerCharacteristic
[ERROR] Invalid op: ops.connectivity.EulerCorrection
[ERROR] Invalid op: bonej.ops.connectivity.EulerCorrection
[ERROR] Invalid op: EulerCorrection
[ERROR] Invalid op: connectivity.EulerCorrection
[ERROR] Invalid op: HollowCuboid
[ERROR] Invalid op: bonej.testImages.HollowCuboid
[ERROR] Invalid op: testImages.HollowCuboid
[ERROR] Invalid op: WireFrameCuboid
[ERROR] Invalid op: bonej.testImages.WireFrameCuboid
[ERROR] Invalid op: testImages.WireFrameCuboid
[ERROR] Invalid op: ops.TriplePointAngles
[ERROR] Invalid op: bonej.ops.TriplePointAngles
[ERROR] Invalid op: TriplePointAngles
[ERROR] Invalid op: ops.CentroidLinAlg3d
[ERROR] Invalid op: bonej.ops.CentroidLinAlg3d
[ERROR] Invalid op: CentroidLinAlg3d
[ERROR] Invalid op: Cuboid
[ERROR] Invalid op: bonej.testImages.Cuboid
[ERROR] Invalid op: testImages.Cuboid
[ERROR] Invalid op: ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: bonej.ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: EulerCharacteristic
[ERROR] Invalid op: connectivity.EulerCharacteristic
[ERROR] Invalid op: ops.connectivity.EulerCorrection
[ERROR] Invalid op: bonej.ops.connectivity.EulerCorrection
[ERROR] Invalid op: EulerCorrection
[ERROR] Invalid op: connectivity.EulerCorrection
[ERROR] Invalid op: HollowCuboid
[ERROR] Invalid op: bonej.testImages.HollowCuboid
[ERROR] Invalid op: testImages.HollowCuboid
[ERROR] Invalid op: WireFrameCuboid
[ERROR] Invalid op: bonej.testImages.WireFrameCuboid
[ERROR] Invalid op: testImages.WireFrameCuboid
[ERROR] Invalid op: ops.TriplePointAngles
[ERROR] Invalid op: bonej.ops.TriplePointAngles
[ERROR] Invalid op: TriplePointAngles
[ERROR] Invalid op: ops.CentroidLinAlg3d
[ERROR] Invalid op: bonej.ops.CentroidLinAlg3d
[ERROR] Invalid op: CentroidLinAlg3d
[ERROR] Invalid op: Cuboid
[ERROR] Invalid op: bonej.testImages.Cuboid
[ERROR] Invalid op: testImages.Cuboid
[ERROR] Invalid op: ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: bonej.ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: EulerCharacteristic
[ERROR] Invalid op: connectivity.EulerCharacteristic
[ERROR] Invalid op: ops.connectivity.EulerCorrection
[ERROR] Invalid op: bonej.ops.connectivity.EulerCorrection
[ERROR] Invalid op: EulerCorrection
[ERROR] Invalid op: connectivity.EulerCorrection
[ERROR] Invalid op: HollowCuboid
[ERROR] Invalid op: bonej.testImages.HollowCuboid
[ERROR] Invalid op: testImages.HollowCuboid
[ERROR] Invalid op: WireFrameCuboid
[ERROR] Invalid op: bonej.testImages.WireFrameCuboid
[ERROR] Invalid op: testImages.WireFrameCuboid
[ERROR] Invalid op: ops.TriplePointAngles
[ERROR] Invalid op: bonej.ops.TriplePointAngles
[ERROR] Invalid op: TriplePointAngles
[ERROR] Invalid op: ops.CentroidLinAlg3d
[ERROR] Invalid op: bonej.ops.CentroidLinAlg3d
[ERROR] Invalid op: CentroidLinAlg3d
[ERROR] Invalid op: Cuboid
[ERROR] Invalid op: bonej.testImages.Cuboid
[ERROR] Invalid op: testImages.Cuboid
[ERROR] Invalid op: ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: bonej.ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: EulerCharacteristic
[ERROR] Invalid op: connectivity.EulerCharacteristic
[ERROR] Invalid op: ops.connectivity.EulerCorrection
[ERROR] Invalid op: bonej.ops.connectivity.EulerCorrection
[ERROR] Invalid op: EulerCorrection
[ERROR] Invalid op: connectivity.EulerCorrection
[ERROR] Invalid op: HollowCuboid
[ERROR] Invalid op: bonej.testImages.HollowCuboid
[ERROR] Invalid op: testImages.HollowCuboid
[ERROR] Invalid op: WireFrameCuboid
[ERROR] Invalid op: bonej.testImages.WireFrameCuboid
[ERROR] Invalid op: testImages.WireFrameCuboid
[ERROR] Invalid op: ops.TriplePointAngles
[ERROR] Invalid op: bonej.ops.TriplePointAngles
[ERROR] Invalid op: TriplePointAngles
[ERROR] Invalid op: ops.CentroidLinAlg3d
[ERROR] Invalid op: bonej.ops.CentroidLinAlg3d
[ERROR] Invalid op: CentroidLinAlg3d
[ERROR] Invalid op: Cuboid
[ERROR] Invalid op: bonej.testImages.Cuboid
[ERROR] Invalid op: testImages.Cuboid
[ERROR] Invalid op: ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: bonej.ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: EulerCharacteristic
[ERROR] Invalid op: connectivity.EulerCharacteristic
[ERROR] Invalid op: ops.connectivity.EulerCorrection
[ERROR] Invalid op: bonej.ops.connectivity.EulerCorrection
[ERROR] Invalid op: EulerCorrection
[ERROR] Invalid op: connectivity.EulerCorrection
[ERROR] Invalid op: HollowCuboid
[ERROR] Invalid op: bonej.testImages.HollowCuboid
[ERROR] Invalid op: testImages.HollowCuboid
[ERROR] Invalid op: WireFrameCuboid
[ERROR] Invalid op: bonej.testImages.WireFrameCuboid
[ERROR] Invalid op: testImages.WireFrameCuboid
[ERROR] Invalid op: ops.TriplePointAngles
[ERROR] Invalid op: bonej.ops.TriplePointAngles
[ERROR] Invalid op: TriplePointAngles
[ERROR] Invalid op: ops.CentroidLinAlg3d
[ERROR] Invalid op: bonej.ops.CentroidLinAlg3d
[ERROR] Invalid op: CentroidLinAlg3d
[ERROR] Invalid op: Cuboid
[ERROR] Invalid op: bonej.testImages.Cuboid
[ERROR] Invalid op: testImages.Cuboid
[ERROR] Invalid op: ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: bonej.ops.connectivity.EulerCharacteristic
[ERROR] Invalid op: EulerCharacteristic
[ERROR] Invalid op: connectivity.EulerCharacteristic
[ERROR] Invalid op: ops.connectivity.EulerCorrection
[ERROR] Invalid op: bonej.ops.connectivity.EulerCorrection
[ERROR] Invalid op: EulerCorrection
[ERROR] Invalid op: connectivity.EulerCorrection
[ERROR] Invalid op: HollowCuboid
[ERROR] Invalid op: bonej.testImages.HollowCuboid
[ERROR] Invalid op: testImages.HollowCuboid
[ERROR] Invalid op: WireFrameCuboid
[ERROR] Invalid op: bonej.testImages.WireFrameCuboid
[ERROR] Invalid op: testImages.WireFrameCuboid

Process finished with exit code 0

Anisotropic pixel spacing check is too stringent

Describe the bug
Some plugins assume isotropic pixel spacing (Anisotropy, Local Thickness), so there is a check to make sure pixels are not spaced anisotropically. The check is too stringent, so that if the pixel spacing values are not precisely the same, the warning is shown.

To Reproduce
Unzip and open the attached image
binary_trabeculae_small.tif.zip
Run Plugins > BoneJ > Anisotropy

Expected behavior
Anisotropy should complain only if pixel spacing is anisotropic outside a certain threshold (e.g. 0.01 or 0.001).

This method in AnisotropyWrapper is the problem:

private boolean isCalibrationIsotropic() {
		final Optional<String> commonUnit = getSpatialUnit(inputImage, unitService);
		if (!commonUnit.isPresent()) {
			return false;
		}
		final String unit = commonUnit.get();
		return spatialAxisStream(inputImage).map(axis -> unitService.value(axis
			.averageScale(0, 1), axis.unit(), unit)).distinct().count() == 1;
	}

Result inserter puts data on first empty row when it should be on new row

When a BoneJ2 trabecular analysis plugin completes, it should add its results to the first line with a Label that matches the image title, unless a new column has just been created, in which case all the data should go on the same new row and all the preceding empty rows should be left empty or a placeholder value e.g. NaN entered.

Steps to reproduce (Fiji with BoneJ cuneiform-experimental)
Unzip & Open binary_noise.tif.zip
Run Plugins > BoneJ > Anisotropy (Directions 20, Lines 100, Sampling 1) show radii unchecked
Run Plugins > BoneJ > Anisotropy (Directions 20, Lines 100, Sampling 1) show radii checked

Expected behaviour: on second run, the radii should be added to the second row of the results table
Current behaviour: radii are added to the first row of the results table.

Adding the dependency to sc.iview:sciview creates lots of duplicate classes

Adding dependency to the sc.iview:sciview to wrapperPlugins (in branch sciview) Maven artefact causes a massive list of duplicate dependency errors while trying to build the project (see list below).

I've tried to add exclusions, for example

<dependency>
  <groupId>com.google.android.tools</groupId>
  <artifactId>dx</artifactId>
  <exclusions>
    <exclusion>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </exclusion>
  </exclusions>
</dependency>

but they haven't helped.

[WARNING] Rule 3: org.apache.maven.plugins.enforcer.BanDuplicateClasses failed with message:
No Duplicate Classes Allowed!
- For duplicate transitive dependencies, add dependency exclusions.
- For duplications between direct dependencies, resolve or add
  ignored classes to this rule's configuration.

  Found in:
    junit:junit:jar:4.9:test
    com.google.android.tools:dx:jar:1.7:compile
  Duplicate classes:
    junit/framework/TestSuite$1.class
    junit/framework/TestSuite.class
    junit/textui/TestRunner.class
    junit/runner/Version.class
    junit/textui/ResultPrinter.class
    junit/extensions/TestSetup$1.class
    junit/framework/TestFailure.class
    junit/framework/TestListener.class
    junit/framework/TestCase.class
    junit/extensions/ActiveTestSuite.class
    junit/framework/ComparisonFailure.class
    junit/framework/Test.class
    junit/runner/BaseTestRunner.class
    junit/framework/TestResult.class
    junit/extensions/TestDecorator.class
    junit/extensions/RepeatedTest.class
    junit/extensions/TestSetup.class
    junit/framework/Assert.class
    junit/runner/TestRunListener.class
    junit/framework/AssertionFailedError.class
    junit/extensions/ActiveTestSuite$1.class
    junit/framework/Protectable.class
    junit/framework/TestResult$1.class

  Found in:
    com.nativelibs4java:javacl:jar:1.0.0-RC4:compile
    com.nativelibs4java:nativelibs4java-utils:jar:1.6:compile
  Duplicate classes:
    com/nativelibs4java/util/Cache.class
    com/nativelibs4java/util/EnumValues.class
    com/nativelibs4java/util/ValuedEnum.class
    com/nativelibs4java/util/ValuedEnums.class
    com/nativelibs4java/util/IOUtils.class
    com/nativelibs4java/util/EnumValues$Cache.class
    com/nativelibs4java/util/NIOUtils.class
    com/nativelibs4java/util/EnumValue.class
    com/nativelibs4java/util/Pair.class
    com/nativelibs4java/util/ImageUtils.class

  Found in:
    com.nativelibs4java:javacl:jar:1.0.0-RC4:compile
    com.nativelibs4java:bridj:jar:0.7.0:compile
  Duplicate classes:
    org/bridj/Platform$DeleteFiles.class
    org/bridj/IntValuedEnum.class
    org/bridj/SolidRanges$Builder.class
    org/bridj/cpp/com/COMRuntime$VARIANTTypeInfo.class
    org/bridj/relocated/org/objectweb/asm/signature/SignatureWriter.class
    org/bridj/dyncall/DyncallLibrary$DCstruct.class
    org/bridj/Platform.class
    org/bridj/cpp/CPPRuntime$CPPTypeInfo.class
    org/bridj/cpp/com/OLEAutomationLibrary.class
    org/bridj/Platform$1.class
    org/bridj/StringList.class
    org/bridj/cpp/com/IUnknown.class
    org/bridj/relocated/org/objectweb/asm/MethodVisitor.class
    org/bridj/util/ProcessUtils$Kernel32.class
    org/bridj/cpp/com/COMRuntime$1.class
    org/bridj/DefaultNativeList.class
    org/bridj/BridJ$CastingType.class
    org/bridj/CommonPointerIOs$10.class
    org/bridj/NativeList.class
    org/bridj/CommonPointerIOs$1.class
    org/bridj/cpp/CPPRuntime$3.class
    org/bridj/ann/Virtual.class
    org/bridj/CommonPointerIOs$8.class
    org/bridj/jawt/JAWT$Lock_callback.class
    org/bridj/cpp/com/OLEAutomationLibrary$IErrorInfo.class
    org/bridj/BridJ.class
    org/bridj/CommonPointerIOs$TypedPointerPointerIO.class
    org/bridj/CommonPointerIOs$IntValuedEnumPointerIO.class
    org/bridj/ann/Template.class
    org/bridj/CommonPointerIOs$PointerPointerIO.class
    org/bridj/jawt/JAWTUtils$LockedComponentRunnable.class
    org/bridj/ann/Convention.class
    org/bridj/demangling/Demangler$JavaTypeRef.class
    org/bridj/cpp/CPPObject.class
    org/bridj/cpp/com/CLSID.class
    org/bridj/jawt/JAWT$GetDrawingSurface_callback.class
    org/bridj/CallbackNativeImplementer.class
    org/bridj/TypedPointer.class
    org/bridj/cpp/com/OLEAutomationLibrary$METHODDATA.class
    org/bridj/ValuedEnum.class
    org/bridj/cpp/com/COMCallableWrapper.class
    org/bridj/cpp/com/OLEAutomationLibrary$ICreateTypeLib2.class
    org/bridj/util/BytecodeAnalyzer.class
    org/bridj/jawt/JAWT.class
    org/bridj/relocated/org/objectweb/asm/Item.class
    org/bridj/objc/ObjectiveCRuntime$1.class
    org/bridj/Pointer$2$1.class
    org/bridj/CommonPointerIOs$3.class
    org/bridj/Pointer$3.class
    org/bridj/cpp/com/COMRuntime$VARIANTTypeInfo$1.class
    org/bridj/relocated/org/objectweb/asm/Edge.class
    org/bridj/cpp/com/OLEAutomationLibrary$NUMPARSE.class
    org/bridj/NativeEntities$Builder.class
    org/bridj/cpp/com/IID.class
    org/bridj/CommonPointerIOs$6.class
    org/bridj/SizeT.class
    org/bridj/Pointer$Releaser.class
    org/bridj/EllipsisHelper.class
    org/bridj/objc/ObjCBlock.class
    org/bridj/cpp/CPPRuntime$5.class
    org/bridj/ann/Ptr.class
    org/bridj/demangling/Demangler$IdentLike.class
    org/bridj/util/BytecodeAnalyzer$1.class
    org/bridj/StructCustomizer.class
    org/bridj/cpp/com/VARIANT.class
    org/bridj/Pointer$1.class
    org/bridj/cpp/com/OLEAutomationLibrary$PARAMDATA.class
    org/bridj/cpp/com/VARIANT$__VARIANT_NAME_1_union.class
    org/bridj/TimeT$timeval_customizer.class
    org/bridj/demangling/Demangler$TypeRef.class
    org/bridj/CRuntime$CTypeInfo.class
    org/bridj/ann/Union.class
    org/bridj/NativeEntities.class
    org/bridj/CRuntime$1.class
    org/bridj/relocated/org/objectweb/asm/ByteVector.class
    org/bridj/util/BytecodeAnalyzer$2.class
    org/bridj/relocated/org/objectweb/asm/signature/SignatureReader.class
    org/bridj/cpp/com/shell/ITaskbarList3$THUMBBUTTONMASK.class
    org/bridj/CallIO$NativeObjectHandler.class
    org/bridj/CallIO$TypedPointerIO.class
    org/bridj/jawt/JAWT_DrawingSurface$FreeDrawingSurfaceInfo_callback.class
    org/bridj/Pointer$DisorderedPointer.class
    org/bridj/cpp/com/shell/IShellFolder.class
    org/bridj/relocated/org/objectweb/asm/AnnotationWriter.class
    org/bridj/ann/Namespace.class
    org/bridj/WindowsError.class
    org/bridj/Pointer$4$1.class
    org/bridj/jawt/JAWT_DrawingSurface$Unlock_callback.class
    org/bridj/demangling/VC9Demangler$DemanglingOp.class
    org/bridj/relocated/org/objectweb/asm/Handle.class
    org/bridj/ann/Runtime.class
    org/bridj/relocated/org/objectweb/asm/MethodWriter.class
    org/bridj/ann/Struct.class
    org/bridj/demangling/VC9Demangler$AccessLevelAndStorageClass.class
    org/bridj/relocated/org/objectweb/asm/Attribute.class
    org/bridj/MethodCallInfo$1.class
    org/bridj/PointerLRUCache.class
    org/bridj/CallIO$GenericPointerHandler.class
    org/bridj/CallIO.class
    org/bridj/objc/SEL.class
    org/bridj/SignalConstants.class
    org/bridj/CallIO$Utils$1.class
    org/bridj/cpp/com/SAFEARRAYBOUND.class
    org/bridj/demangling/VC9Demangler$1.class
    org/bridj/relocated/org/objectweb/asm/ClassWriter.class
    org/bridj/cpp/com/shell/ITaskbarList3$THUMBBUTTON.class
    org/bridj/objc/NSAutoreleasePool.class
    org/bridj/demangling/Demangler$Symbol.class
    org/bridj/FlagSet.class
    org/bridj/objc/ObjectiveCRuntime$2$1.class
    org/bridj/objc/NSMethodSignature.class
    org/bridj/objc/ObjectiveCRuntime$2.class
    org/bridj/jawt/JAWT_DrawingSurfaceInfo.class
    org/bridj/CommonPointerIOs.class
    org/bridj/BridJ$Switch.class
    org/bridj/cpp/com/VARENUM.class
    org/bridj/demangling/Demangler$FunctionTypeRef.class
    org/bridj/StructFieldDescription.class
    org/bridj/jawt/JAWTUtils$1.class
    org/bridj/objc/ObjCJNI.class
    org/bridj/Pointer.class
    org/bridj/demangling/Demangler$Constant.class
    org/bridj/util/ClassDefiner.class
    org/bridj/util/Tuple.class
    org/bridj/NativeLibrary.class
    org/bridj/StructIO.class
    org/bridj/cpp/com/OLEAutomationLibrary$SYSTEMTIME.class
    org/bridj/cpp/com/OLEAutomationLibrary$ITypeLib.class
    org/bridj/TimeT.class
    org/bridj/cpp/com/shell/ITaskbarList.class
    org/bridj/util/JNIUtils.class
    org/bridj/cpp/com/IRecordInfo.class
    org/bridj/cpp/com/OLEAutomationLibrary$CUSTDATAITEM.class
    org/bridj/objc/ObjCDelegate.class
    org/bridj/cpp/com/GUID.class
    org/bridj/TimeT$timeval.class
    org/bridj/CommonPointerIOs$StructPointerIO.class
    org/bridj/DyncallStructs.class
    org/bridj/demangling/Demangler$NamespaceRef.class
    org/bridj/cpp/com/VARIANT$__VARIANT_NAME_1_union$__tagVARIANT$__VARIANT_NAME_3_union$__tagBRECORD.class
    org/bridj/demangling/Demangler$DemanglingException.class
    org/bridj/cpp/com/OLEAutomationLibrary$DISPPARAMS.class
    org/bridj/EllipsisHelper$1.class
    org/bridj/util/AnnotationUtils.class
    org/bridj/jawt/JAWT$FreeDrawingSurface_callback.class
    org/bridj/jawt/JawtLibrary$JNIEnv.class
    org/bridj/demangling/Demangler$ClassRef.class
    org/bridj/ann/DisableDirect.class
    org/bridj/jawt/JAWT_Rectangle.class
    org/bridj/cpp/com/OLEAutomationLibrary$SYSKIND.class
    org/bridj/cpp/CPPRuntime$MethodTypeVariableExtractor.class
    org/bridj/ann/Alignment.class
    org/bridj/demangling/Demangler$MemberRef.class
    org/bridj/cpp/com/VARIANT$__VARIANT_NAME_1_union$__tagVARIANT$__VARIANT_NAME_3_union.class
    org/bridj/NativeObjectInterface.class
    org/bridj/cpp/com/COMRuntime$COINIT.class
    org/bridj/jawt/JAWTUtils.class
    org/bridj/objc/NSCalendar.class
    org/bridj/NativeConstants.class
    org/bridj/ann/Constructor.class
    org/bridj/ComplexDouble.class
    org/bridj/dyncall/DyncallLibrary$DCCallVM.class
    org/bridj/Pointer$7.class
    org/bridj/FlagSet$IntFlagSet.class
    org/bridj/CommonPointerIOs$2.class
    org/bridj/demangling/Demangler.class
    org/bridj/ann/SetsLastError.class
    org/bridj/cpp/CPPRuntime$MemoryOperators.class
    org/bridj/relocated/org/objectweb/asm/ClassReader.class
    org/bridj/StructUtils.class
    org/bridj/Pointer$3$1.class
    org/bridj/BridJRuntime.class
    org/bridj/cpp/com/OLEAutomationLibrary$CALLCONV.class
    org/bridj/Callback.class
    org/bridj/jawt/JAWT_DrawingSurface$GetDrawingSurfaceInfo_callback.class
    org/bridj/CommonPointerIOs$7.class
    org/bridj/cpp/CPPRuntime$4.class
    org/bridj/demangling/Demangler$Ident.class
    org/bridj/dyncall/DyncallLibrary.class
    org/bridj/cpp/com/CY.class
    org/bridj/GenericCallback.class
    org/bridj/Pointer$OrderedPointer.class
    org/bridj/jawt/JAWT_DrawingSurface.class
    org/bridj/DefaultNativeList$1.class
    org/bridj/cpp/com/shell/ITaskbarList3$RECT.class
    org/bridj/CallbackNativeImplementer$1.class
    org/bridj/jawt/JAWT$GetComponent_callback.class
    org/bridj/objc/NSDictionary.class
    org/bridj/LastError.class
    org/bridj/cpp/CPPType.class
    org/bridj/Platform$2.class
    org/bridj/cpp/com/OLEAutomationLibrary$EXCEPINFO.class
    org/bridj/cpp/com/OLEAutomationLibrary$ICreateErrorInfo.class
    org/bridj/objc/ObjCProxy.class
    org/bridj/cpp/com/IDispatch$DISPPARAMS.class
    org/bridj/ann/CLong.class
    org/bridj/CommonPointerIOs$11.class
    org/bridj/OSGiBundleActivator.class
    org/bridj/util/BytecodeAnalyzer$3.class
    org/bridj/objc/Selector.class
    org/bridj/demangling/GCC4Demangler.class
    org/bridj/cpp/com/RECT.class
    org/bridj/cpp/com/IDispatch.class
    org/bridj/util/ConcurrentCache.class
    org/bridj/CommonPointerIOs$PointerArrayIO.class
    org/bridj/HeadersReconstructor.class
    org/bridj/NativeEntities$CBInfo.class
    org/bridj/objc/NSInvocation.class
    org/bridj/relocated/org/objectweb/asm/FieldVisitor.class
    org/bridj/JNI.class
    org/bridj/cpp/com/OLEAutomationLibrary$INTERFACEDATA.class
    org/bridj/CommonPointerIOs$4.class
    org/bridj/Pointer$StringType.class
    org/bridj/cpp/CPPRuntime$6.class
    org/bridj/DynamicCallback.class
    org/bridj/PlatformSupport.class
    org/bridj/cpp/com/OLEAutomationLibrary$ICreateTypeLib.class
    org/bridj/StructFieldDeclaration.class
    org/bridj/cpp/CPPRuntime$ClassTypeVariableExtractor.class
    org/bridj/cpp/com/OLELibrary.class
    org/bridj/CRuntime$MethodCallInfoBuilder.class
    org/bridj/cpp/com/OLEAutomationLibrary$REGKIND.class
    org/bridj/DynamicFunctionFactory.class
    org/bridj/cpp/com/shell/ITaskbarList3$THUMBBUTTONFLAGS.class
    org/bridj/NativeConstants$CallbackType.class
    org/bridj/cpp/CPPRuntime$7.class
    org/bridj/demangling/Demangler$SpecialName.class
    org/bridj/CommonPointerIOs$CallbackPointerIO.class
    org/bridj/Pointer$2.class
    org/bridj/BridJRuntime$TypeInfo.class
    org/bridj/NativeConstants$ValueType.class
    org/bridj/NativeError.class
    org/bridj/cpp/com/OLEAutomationLibrary$DATE.class
    org/bridj/ann/Bits.class
    org/bridj/util/BytecodeAnalyzer$EmptyVisitor.class
    org/bridj/Version.class
    org/bridj/DyncallStructs$1.class
    org/bridj/StructUtils$1.class
    org/bridj/util/Pair.class
    org/bridj/demangling/Demangler$2.class
    org/bridj/CallIO$Utils.class
    org/bridj/ann/Array.class
    org/bridj/cpp/CPPRuntime$VTable.class
    org/bridj/cpp/CPPRuntime$1.class
    org/bridj/CLong.class
    org/bridj/jawt/JAWT$Unlock_callback.class
    org/bridj/DynamicFunction.class
    org/bridj/Pointer$4.class
    org/bridj/cpp/com/COMRuntime$4.class
    org/bridj/ann/Symbol.class
    org/bridj/util/ASMUtils$1.class
    org/bridj/CommonPointerIOs$5.class
    org/bridj/objc/ObjCClass.class
    org/bridj/cpp/com/COMRuntime.class
    org/bridj/PointerIO.class
    org/bridj/cpp/com/shell/ITaskbarList3$TbpFlag.class
    org/bridj/SolidRanges.class
    org/bridj/cpp/CPPRuntime$VirtMeth.class
    org/bridj/CallbackInterface.class
    org/bridj/DefaultPointer.class
    org/bridj/Pointer$5.class
    org/bridj/ann/Optional.class
    org/bridj/relocated/org/objectweb/asm/Label.class
    org/bridj/ann/Field.class
    org/bridj/cpp/com/shell/ITaskbarList2.class
    org/bridj/JNI$1.class
    org/bridj/cpp/com/SAFEARRAY.class
    org/bridj/cpp/com/COMRuntime$5.class
    org/bridj/objc/NSObject.class
    org/bridj/BridJ$1.class
    org/bridj/cpp/com/OLEAutomationLibrary$UDATE.class
    org/bridj/util/DefaultParameterizedType.class
    org/bridj/CRuntime.class
    org/bridj/jawt/JawtLibrary.class
    org/bridj/cpp/com/shell/IShellWindows.class
    org/bridj/cpp/com/DECIMAL.class
    org/bridj/cpp/com/ITypeInfo.class
    org/bridj/ann/Library.class
    org/bridj/demangling/Demangler$PointerTypeRef.class
    org/bridj/relocated/org/objectweb/asm/signature/SignatureVisitor.class
    org/bridj/Pointer$FreeReleaser.class
    org/bridj/ann/Name.class
    org/bridj/cpp/com/OLEAutomationLibrary$CUSTDATA.class
    org/bridj/StructDescription.class
    org/bridj/cpp/com/shell/ITaskbarList3.class
    org/bridj/objc/NSNumber.class
    org/bridj/demangling/Demangler$3.class
    org/bridj/util/ProcessUtils$LibC.class
    org/bridj/relocated/org/objectweb/asm/Handler.class
    org/bridj/cpp/com/COMRuntime$3.class
    org/bridj/relocated/org/objectweb/asm/ClassVisitor.class
    org/bridj/WinExceptionsConstants.class
    org/bridj/relocated/org/objectweb/asm/Frame.class
    org/bridj/cpp/com/COMRuntime$1$1.class
    org/bridj/StructObject.class
    org/bridj/util/Utils.class
    org/bridj/CommonPointerIOs$9.class
    org/bridj/jawt/JAWT_DrawingSurface$Lock_callback.class
    org/bridj/demangling/GCC4Demangler$1.class
    org/bridj/NativeObject.class
    org/bridj/Pointer$6.class
    org/bridj/AbstractIntegral.class
    org/bridj/demangling/VC9Demangler$AnonymousTemplateArg.class
    org/bridj/util/ASMUtils.class
    org/bridj/cpp/CPPRuntime$2.class
    org/bridj/Pointer$ListType.class
    org/bridj/objc/FoundationLibrary.class
    org/bridj/objc/NSString.class
    org/bridj/cpp/CPPRuntime.class
    org/bridj/cpp/com/VARIANT$__VARIANT_NAME_1_union$__tagVARIANT.class
    org/bridj/NativeLibrary$SymbolAccepter.class
    org/bridj/CommonPointerIOs$NativeObjectPointerIO.class
    org/bridj/ann/Convention$Style.class
    org/bridj/util/StringUtils.class
    org/bridj/cpp/com/IDispatch$EXCEPINFO.class
    org/bridj/demangling/Demangler$TemplateArg.class
    org/bridj/demangling/Demangler$1.class
    org/bridj/objc/IMP.class
    org/bridj/demangling/VC9Demangler$CVClassModifier.class
    org/bridj/AbstractBridJRuntime.class
    org/bridj/relocated/org/objectweb/asm/FieldWriter.class
    org/bridj/cpp/com/COMRuntime$2.class
    org/bridj/ann/JNIBound.class
    org/bridj/cpp/CPPRuntime$CPPDestructor.class
    org/bridj/util/ProcessUtils.class
    org/bridj/relocated/org/objectweb/asm/Type.class
    org/bridj/SignalError.class
    org/bridj/objc/ObjectiveCRuntime.class
    org/bridj/relocated/org/objectweb/asm/Opcodes.class
    org/bridj/MethodCallInfo.class
    org/bridj/demangling/Demangler$Annotations.class
    org/bridj/Pointer$8.class
    org/bridj/demangling/VC9Demangler.class
    org/bridj/relocated/org/objectweb/asm/AnnotationVisitor.class
    org/bridj/objc/ObjCObject.class
    org/bridj/ann/Forwardable.class
    org/bridj/cpp/com/IClassFactory.class
    org/bridj/util/JNIUtils$NativeMethodsCache.class

  Found in:
    com.nativelibs4java:opencl4java:jar:1.0.0-RC4:compile
    com.nativelibs4java:javacl:jar:1.0.0-RC4:compile
  Duplicate classes:
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clReleaseDeviceEXT_fn.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clGetGLContextInfoKHR_fn.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clRetainDeviceEXT_fn.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$_cl_context.class
    com/nativelibs4java/opencl/library/OpenCLLibrary.class
    com/nativelibs4java/opencl/library/cl_image_format.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$_cl_kernel.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clLinkProgram_arg1_callback.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clBuildProgram_arg1_callback.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$_cl_command_queue.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$_cl_event.class
    com/nativelibs4java/opencl/library/cl_buffer_region.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$cl_context.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$cl_device_id.class
    com/nativelibs4java/opencl/library/OpenGLContextUtils.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clIcdGetPlatformIDsKHR_fn.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clSetMemObjectDestructorAPPLE_arg1_callback.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$_cl_program.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$cl_mem.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clEnqueueNativeKernel_arg1_callback.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clSetEventCallback_arg1_callback.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$cl_event.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$_cl_platform_id.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$cl_kernel.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clCompileProgram_arg1_callback.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clCreateContextFromType_arg1_callback.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$cl_GLsync.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clSetPrintfCallback_arg1_callback.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$cl_sampler.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$_cl_mem.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$_cl_device_id.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clCreateContext_arg1_callback.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$_cl_sampler.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$cl_program.class
    com/nativelibs4java/opencl/library/cl_image_desc.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$cl_command_queue.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clCreateSubDevicesEXT_fn.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$__GLsync.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$cl_platform_id.class
    com/nativelibs4java/opencl/library/IOpenCLLibrary$clSetMemObjectDestructorCallback_arg1_callback.class

  Found in:
    com.nativelibs4java:javacl:jar:1.0.0-RC4:compile
    com.nativelibs4java:ochafik-util:jar:0.12:compile
    com.nativelibs4java:javacl-core:jar:1.0.0-RC4:compile
  Duplicate classes:
    com/ochafik/util/string/StringUtils.class

  Found in:
    com.nativelibs4java:javacl:jar:1.0.0-RC4:compile
    com.nativelibs4java:javacl-core:jar:1.0.0-RC4:compile
  Duplicate classes:
    com/nativelibs4java/opencl/CLException$DeviceNotAvailable.class
    com/nativelibs4java/opencl/ImageIOUtils$ImageInfo$ImageDataSetter.class
    com/nativelibs4java/opencl/CLImageFormat.class
    com/nativelibs4java/opencl/CLMem$1.class
    com/nativelibs4java/opencl/CLQueue$NativeKernel.class
    com/nativelibs4java/opencl/CLException$InvalidValue.class
    com/nativelibs4java/opencl/ImageIOUtils$1.class
    com/nativelibs4java/opencl/CLDevice$1.class
    com/nativelibs4java/opencl/CLException$ExecStatusErrorForEventsInWaitList.class
    com/nativelibs4java/opencl/ImageIOUtils$ImageInfo$ImageDataGetter.class
    com/nativelibs4java/opencl/CLImageFormat$ChannelDataType.class
    com/nativelibs4java/opencl/CLEvent$3.class
    com/nativelibs4java/opencl/CLMem.class
    com/nativelibs4java/opencl/ImageIOUtils$11.class
    com/nativelibs4java/opencl/CLException$MemCopyOverlap.class
    com/nativelibs4java/opencl/CLException$InvalidEventWaitList.class
    com/nativelibs4java/opencl/CLException$InvalidQueueProperties.class
    com/nativelibs4java/opencl/CLException$InvalidGlobalWorkSize.class
    com/nativelibs4java/opencl/ImageIOUtils$6.class
    com/nativelibs4java/opencl/CLException$InvalidArgValue.class
    com/nativelibs4java/opencl/CLKernel$2.class
    com/nativelibs4java/opencl/CLPlatform$DeviceFeature$4.class
    com/nativelibs4java/opencl/CLException$BuildProgramFailure.class
    com/nativelibs4java/opencl/CLException$InvalidLinkerOptions.class
    com/nativelibs4java/opencl/ReusablePointers.class
    com/nativelibs4java/opencl/CLException$InvalidWorkDimension.class
    com/nativelibs4java/opencl/CLException$MemObjectAllocationFailure.class
    com/nativelibs4java/opencl/JavaCL$OpenCLProbeLibrary$1.class
    com/nativelibs4java/opencl/CLEvent.class
    com/nativelibs4java/opencl/CLException$InvalidSampler.class
    com/nativelibs4java/opencl/ImageIOUtils$3.class
    com/nativelibs4java/opencl/CLEvent$CommandExecutionStatus.class
    com/nativelibs4java/opencl/CLProgram$1.class
    com/nativelibs4java/opencl/CLException$InvalidProperty.class
    com/nativelibs4java/opencl/CLMem$MapFlags.class
    com/nativelibs4java/opencl/CLException$InvalidKernelArgs.class
    com/nativelibs4java/opencl/CLException$InvalidDevice.class
    com/nativelibs4java/opencl/CLException$MapFailure.class
    com/nativelibs4java/opencl/CLException$CLTypedException.class
    com/nativelibs4java/opencl/CLPlatform$DeviceFeature$1.class
    com/nativelibs4java/opencl/CLException$MisalignedSubBufferOffset.class
    com/nativelibs4java/opencl/CLMem$DestructorCallback.class
    com/nativelibs4java/opencl/CLException$InvalidKernelDefinition.class
    com/nativelibs4java/opencl/CLEvent$EventCallback.class
    com/nativelibs4java/opencl/CLMem$Usage.class
    com/nativelibs4java/opencl/ImageIOUtils$4.class
    com/nativelibs4java/opencl/LocalSize.class
    com/nativelibs4java/opencl/CLException$InvalidGLObject.class
    com/nativelibs4java/opencl/CLException$InvalidGLContextApple.class
    com/nativelibs4java/opencl/CLImageFormat$ChannelOrder.class
    com/nativelibs4java/opencl/CLException$CLVersionException.class
    com/nativelibs4java/opencl/PlatformUtils.class
    com/nativelibs4java/opencl/CLException$CompilerNotAvailable.class
    com/nativelibs4java/opencl/CLException$InvalidWorkItemSize.class
    com/nativelibs4java/opencl/CLException$InvalidEvent.class
    com/nativelibs4java/opencl/CLImage.class
    com/nativelibs4java/opencl/ImageIOUtils$5.class
    com/nativelibs4java/opencl/CLPlatform$DeviceFeature.class
    com/nativelibs4java/opencl/CLException$InvalidContext.class
    com/nativelibs4java/opencl/CLException$OutOfHostMemory.class
    com/nativelibs4java/opencl/ImageIOUtils$8.class
    com/nativelibs4java/opencl/CLUserEvent.class
    com/nativelibs4java/opencl/CLDevice$QueueProperties.class
    com/nativelibs4java/opencl/CLImageFormat$1.class
    com/nativelibs4java/opencl/CLException$InvalidImageFormatDescriptor.class
    com/nativelibs4java/opencl/CLImage2D.class
    com/nativelibs4java/opencl/CLException$ErrorCode.class
    com/nativelibs4java/opencl/CLException$InvalidHostPtr.class
    com/nativelibs4java/opencl/CLDevice$PartitionType.class
    com/nativelibs4java/opencl/CLMem$GLObjectType.class
    com/nativelibs4java/opencl/ReusablePointer.class
    com/nativelibs4java/opencl/CLException$InvalidImageSize.class
    com/nativelibs4java/opencl/CLException$InvalidImageDescriptor.class
    com/nativelibs4java/opencl/CLDevice$LocalMemType.class
    com/nativelibs4java/opencl/CLDevice$FpConfig.class
    com/nativelibs4java/opencl/ImageIOUtils$ImageInfo.class
    com/nativelibs4java/opencl/CLException$LinkerNotAvailable.class
    com/nativelibs4java/opencl/ImageIOUtils$9.class
    com/nativelibs4java/opencl/CLException$InvalidKernelName.class
    com/nativelibs4java/opencl/CLPlatform$ContextProperties.class
    com/nativelibs4java/opencl/CLImage$1.class
    com/nativelibs4java/opencl/CLException$InvalidBufferSize.class
    com/nativelibs4java/opencl/CLDevice$GlobalMemCacheType.class
    com/nativelibs4java/opencl/InfoName.class
    com/nativelibs4java/opencl/CLException$InvalidArgIndex.class
    com/nativelibs4java/opencl/CLMem$Flags.class
    com/nativelibs4java/opencl/JavaCL.class
    com/nativelibs4java/opencl/CLException$InvalidMemObject.class
    com/nativelibs4java/opencl/CLBuildException.class
    com/nativelibs4java/opencl/ImageIOUtils$7.class
    com/nativelibs4java/opencl/CLKernel.class
    com/nativelibs4java/opencl/CLException.class
    com/nativelibs4java/opencl/CLPlatform$DeviceComparator.class
    com/nativelibs4java/opencl/CLKernel$3.class
    com/nativelibs4java/opencl/CLQueue.class
    com/nativelibs4java/opencl/CLAbstractEntity.class
    com/nativelibs4java/opencl/CLEvent$2.class
    com/nativelibs4java/opencl/CLException$InvalidProgram.class
    com/nativelibs4java/opencl/CLException$InvalidOperation.class
    com/nativelibs4java/opencl/CLPlatform$DeviceFeature$5.class
    com/nativelibs4java/opencl/CLException$InvalidCompilerOptions.class
    com/nativelibs4java/opencl/CLProgram.class
    com/nativelibs4java/opencl/ByteOrderHack.class
    com/nativelibs4java/opencl/CLProgram$2.class
    com/nativelibs4java/opencl/CLException$ProfilingInfoNotAvailable.class
    com/nativelibs4java/opencl/CLPlatform$DeviceFeature$3.class
    com/nativelibs4java/opencl/CLQueue$1.class
    com/nativelibs4java/opencl/CLDevice$ExecutionCapability.class
    com/nativelibs4java/opencl/CLEvent$CommandType.class
    com/nativelibs4java/opencl/CLImage3D.class
    com/nativelibs4java/opencl/CLException$InvalidPlatform.class
    com/nativelibs4java/opencl/CLSampler$FilterMode.class
    com/nativelibs4java/opencl/JavaCL$1.class
    com/nativelibs4java/opencl/CLException$InvalidMipLevel.class
    com/nativelibs4java/opencl/ImageIOUtils$10.class
    com/nativelibs4java/opencl/ImageIOUtils$2.class
    com/nativelibs4java/opencl/CLException$DevicePartitionFailed.class
    com/nativelibs4java/opencl/CLMem$ObjectType.class
    com/nativelibs4java/opencl/CLMem$2.class
    com/nativelibs4java/opencl/CLMem$GLObjectInfo.class
    com/nativelibs4java/opencl/CLSampler$AddressingMode.class
    com/nativelibs4java/opencl/CLException$InvalidWorkGroupSize.class
    com/nativelibs4java/opencl/CLException$InvalidBuildOptions.class
    com/nativelibs4java/opencl/CLBuffer.class
    com/nativelibs4java/opencl/CLPlatform$DeviceFeature$2.class
    com/nativelibs4java/opencl/CLPlatform$1.class
    com/nativelibs4java/opencl/CLMem$Migration.class
    com/nativelibs4java/opencl/CLException$InvalidGLShareGroupReference.class
    com/nativelibs4java/opencl/CLContext$GLTextureTarget.class
    com/nativelibs4java/opencl/CLException$InvalidProgramExecutable.class
    com/nativelibs4java/opencl/ReusablePointers$1.class
    com/nativelibs4java/opencl/CLPlatform.class
    com/nativelibs4java/opencl/CLAbstractUserProgram.class
    com/nativelibs4java/opencl/CLEvent$1.class
    com/nativelibs4java/opencl/CLDevice$Type.class
    com/nativelibs4java/opencl/CLContext.class
    com/nativelibs4java/opencl/CLDevice.class
    com/nativelibs4java/opencl/CLPlatform$DeviceFeature$6.class
    com/nativelibs4java/opencl/CLSampler$1.class
    com/nativelibs4java/opencl/CLEvent$4.class
    com/nativelibs4java/opencl/CLException$KernelArgInfoNotAvailable.class
    com/nativelibs4java/opencl/CLException$InvalidDeviceType.class
    com/nativelibs4java/opencl/CLException$InvalidGlobalOffset.class
    com/nativelibs4java/opencl/CLException$InvalidArgSize.class
    com/nativelibs4java/opencl/CLException$InvalidBinary.class
    com/nativelibs4java/opencl/CLException$InvalidKernel.class
    com/nativelibs4java/opencl/ImageIOUtils.class
    com/nativelibs4java/opencl/JavaCL$OpenCLProbeLibrary.class
    com/nativelibs4java/opencl/CLPlatform$DeviceFeature$9.class
    com/nativelibs4java/opencl/CLException$OutOfResources.class
    com/nativelibs4java/opencl/PlatformUtils$PlatformKind.class
    com/nativelibs4java/opencl/CLKernel$1.class
    com/nativelibs4java/opencl/CLInfoGetter.class
    com/nativelibs4java/opencl/CLSampler.class
    com/nativelibs4java/opencl/CLDevice$AffinityDomain.class
    com/nativelibs4java/opencl/CLContext$1.class
    com/nativelibs4java/opencl/CLException$ImageFormatMismatch.class
    com/nativelibs4java/opencl/CLPlatform$DeviceFeature$8.class
    com/nativelibs4java/opencl/CLException$InvalidDevicePartitionCount.class
    com/nativelibs4java/opencl/CLException$LinkProgramFailure.class
    com/nativelibs4java/opencl/CLException$CompileProgramFailure.class
    com/nativelibs4java/opencl/CLPlatform$DeviceFeature$7.class
    com/nativelibs4java/opencl/CLException$InvalidCommandQueue.class

Throw exceptions in a consistent manner

The code in the Modern modules of BoneJ should throw exceptions in a consistent manner.

Exceptions related to user-input, I/O and other areas where exceptions are to be expected, should be caught with a catch block. The user should be informed of the error, and the stack trace logged with a call to LogService.trace(). This way the exception info can be viewed by selecting Edit > Options > ImageJ2... and setting SciJava log level to TRACE if need be. Normally the user shouldn't see these kinds of exceptions. See issue #82.

NullPointer, IllegalArgument and other exceptions that result from programmer errors should not be caught. Otherwise these bugs might go unnoticed. These exceptions should only be thrown if they otherwise wouldn't already happen in the scope, or when they add new information about valid behaviour or data. Some examples:

// Example 1
public static char initial(final String name) {
  // Throwing a NullPointerException would be redundant,
  // because the next line will throw it if name == null 
  return name.charAt(0);
}
// Example 2
public class Employee {
  private String name;

  public String getName() { return name; }

  public void setName(final String name) throws NullPointerException {
    // Exception is thrown, because otherwise there's no telling when the null name field
    // would cause trouble
    if (name == null)
      throw new NullPointerException("Name cannot be null!");
    this.name = name;    
  }
}
// Example 3
public void setRadius(final double r) {
  // Exception thrown, because it adds a new constraint for valid data
  if (r <= 0) 
    throw new IllegalArgumentException("Radius must be positive!");
  radius = r;
}
// Example 4
public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, 
    THURSDAY, FRIDAY, SATURDAY 
}

public String dayName(final Day currentDay) {
  switch(currentDay) {
      case SUNDAY: 
        return "Sunday";
      ...
      case MONDAY:
        return "Monday";
      default:
        // Exception thrown, because code has entered a bad path
        throw new RuntimeException("Somebody forgot to cover all valid cases!");
  }
}

Code that migrates from BoneJ to the framework should follow the exception conventions presented there.

SharedTable.getTable() should return a copy

The method getTable() in SharedTable should return a copy, and not a reference to the actual Table instance held by the singleton class.

When fixed add test that verifies that method does not return a reference

  assertNotSame(SharedTable.getTable(), SharedTable.getTable());

AnisotropyWrapper stops working after pom-scijava 19.0.0

When upgrading pom-scijava parent version in wrapperPlugins/pom the Anisotropy command starts to fail with "Anisotropy could not be calculated - ellipsoid fitting failed" error on every run. Due the random nature of the method I haven't been able to pinpoint the exact version where bug is introduced, but fitting starts to fail much more often in pom-scijava-19.1.1 and every time in 19.2.0 or newer.

Steps to reproduce:
Case 2 in the manual test

Rename packages and artefacts in Modern

Rename packages and maven artefacts so that they're clear and consistent

  • Package org.bonej.wrapperPlugins -> org.bonej.commands
  • Artefact org.bonej.wrapperPlugins -> org.bonej.commands
    • Final name to bonej-commands
  • Artefact org.bonej.utilities
    • Final name to bonej-utilities
  • Artefact org.bonej.ops
    • Final name to bonej-ops
  • Artefact org.bonej.bonej-legacy-plugins -> org.bonej.legacy-plugins
    • Final name to bonej-legacy-plugins
  • Artefact org.bonej.bonej-legacy-util -> org.bonej.legacy-utilities
    • Final name to bonej-legacy-utilities

Reduce the number of modules

This issue needs extensive discussion before it is decided how to approach it or if it's an issue at all.

Originally BoneJ was divided into several different modules, because even though we always planned to migrate as much code as possible to imagej-ops and other core artefacts, we thought there was also going to BoneJ specific utilities and ops that wouldn't fit elsewhere. Having them in different modules would allow others to just depend on them without having to also download the wrapper plug-ins i.e. Commands. This structure was also thought to make migration easier, because components only depended on each other through Maven.

The real deciding question is: after most of BoneJ has been modernized, is there going to be enough code to warrant separate modules, and more complex maintenance? We were always aiming to eventually do away with the modules under Legacy, but will we need ops, utilities and wrapperPlugins in Modern? If there is going to be code too specific to be added to a pre-existing artefact in the ecosystem, will it still be valuable enough for other developers to offer it in a library module of its own?

Try FindBugs Maven plugin

Try adding the FindBugs plugin to the project's Maven build cycle, and see if the static analysis it performs helps to discover potential bugs

Conversion issues with composite images

Skeletonise, AnalyseSkeleton, Thickness and TriplePointAngles crash if you try to run them with a composite binary image. This is because the input Dataset doesn't get converted into a byte
ImagePlus which these plugins need. Also the types of the output images needs to be changed from Dataset because they don't show as composite to the user.

How to produce a composite binary image

  1. Open HeLa Cells image (File>Open Samples>HeLa Cells)
  2. Binarise image (Process>Binary>Make Binary)

NaN values break Results table order

If you try to insert NaN values into to Results table with ResultsInserter it breaks the ordering of the values. This is because NaN values indicate an empty cell. Need to use another special value to indicate an actual erroneous result.

Remove explicit dependency to `imagej-maven-plugin:0.6.0`

We'll need to depend on this older version until this issue in the newer version(s) has been solved. The dependency can be dropped, and the project can use the version declared in the parent BOM once pom-scijava declares a dependency on a version of the plugin where the bug's been fixed, or we find another way to solve the issue.

Reverting Mockito to use PowerMockito

Should we revert Mockito from 2.x.x-beta to Mockito 1.10.x? PowerMockito enables you to mock static methods, and it doesn't support Mockito 2 that well yet.

BoneJ doesn't work "out-of-the-box" with vanilla ImageJ

The last version of vanilla ImageJ was released May 2nd 2016. Since then technology has changed so that BoneJ doesn't work with it any more. This is mainly due changes in sc.fiji.3D_Viewer - in how meshes and rendering works. BoneJ installation works with Fiji straight out of the box, because it comes with the necessary (native) libraries. There are several possible solutions:

  1. Encourage people to download BoneJ on FIJI
  2. Wait for next version vanilla ImageJ, and see if that fixes the problem
  3. (Not sure about this one) Add a custom script to deliver native libraries with BoneJ as discussed here, and/or add dependencies on the update site. This might create problems with the update system though.

Automate GUI testing with macros

You could automate simple GUI tests specified in the integration tests by writing macros. Simple things like verifying that an error message pops up, when the user tries to run a plugin with a wrong kind of image. For example "Verify that the ConnectivityWrapper plugin shows an error message if the user tries to run it with a non binary image".

There might be a way to automate the running of these test macros, but even having them around as manually runnable files would help in testing that everything still works after changes.

Null image shows wrong error message

When you try to run the plugins with no images open, the user sees the wrong error message: "A ImgPlus is required but none exist". They should see a clearer "No image open" message.

The plugins check for null in the "validater" (sic) method of their image parameters. At least with the legacy UI execution of a plugin doesn't get this far before it's stopped with the wrong message. However, the tests for proper cancel messages still pass. Thus the issue probably originates from some kind of automatic conversion going on with the legacy UI. This can be fixed by checking for null in the initializer of a @parameter. The validater should then check for other properties of the image

NoClassDefFoundError when initializing SciView

SciView works when launched from IntelliJ, but when when it's installed into a local copy of Fiji with mvn -Dimagej.app.directory=/path/ -Ddelete.other.versions=true clean install then plug-in crashes with

[ERROR] Module threw error
java.lang.NoClassDefFoundError: com/jogamp/opengl/math/FloatUtil
	at cleargl.GLMatrix.setIdentity(GLMatrix.java:41)
	at cleargl.GLMatrix.getIdentity(GLMatrix.java:46)
	at graphics.scenery.Node.<init>(Node.kt:73)
	at graphics.scenery.Scene.<init>(Scene.kt:11)
	at graphics.scenery.SceneryBase.<init>(SceneryBase.kt:39)
	at sc.iview.SciView.<init>(SciView.java:48)
	at sc.iview.DefaultSciViewService.getOrCreateActiveSciView(DefaultSciViewService.java:110)
	at org.bonej.wrapperPlugins.SurfaceFractionWrapper.renderSurfaces(SurfaceFractionWrapper.java:201)
	at org.bonej.wrapperPlugins.SurfaceFractionWrapper.run(SurfaceFractionWrapper.java:125)
	at org.scijava.command.CommandModule.run(CommandModule.java:199)
	at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66)
	at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: com.jogamp.opengl.math.FloatUtil
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 18 more

when it tries to initialize SciView.

Steps to reproduce

  1. git clone commit a91a706
  2. Build and deploy packages to Fiji mvn -Dimagej.app.directory=/path/ -Ddelete.other.versions=true clean install
  3. Launch Fiji
  4. File > Open Samples > Bat Cochlea Volume
  5. Plugins > BoneJ > Fraction > Surface fraction
  6. Tick Render bone mesh

Connectivity is very slow

Processing a 512ร—512ร—512 image on my 40-core workstation takes about 30 seconds instead of ~1 sec that the BoneJ1 version takes. BoneJ2 version needs multithreading - currently runs on one core.

Anisotropy is affected too much by stochastic effects

The way AnisotropyWrapper operates is too finicky and easily affected by random effects. After more extensive testing, the success of ellipsoid fitting seems to be more down to luck than the actual paramaters (although cutting down the number of lines by say an order of magnitude seems to lower the chances).

TriplePointAngles produces NaN angles

TriplePointAngles produces NaN angles with certain images:

Steps to reproduce

  1. Open "mri-stack.tif" (File>Open Samples>MRI stack)
  2. Binarize the image (Process>Binary>Make binary)
  3. Click "OK"
  4. Run Triple Point Angles (Plugins>BoneJ>Triple Point Angles)
  5. Set "Measurement mode" to "Opposite vertex"
  6. Click "OK"

Particle Analyser produces negative Enclosed Volume

Enclosed volume is the volume calculated from the surface mesh.

In BoneJ2 the legacy particle analyser code reports negative enclosed volume. (Fiji with BoneJ installed from the update site)

Steps to reproduce:
Open bat cochlea sample image
Run Plugins > BoneJ > Analyze > Particle Analyser with the default settings

Perhaps the surface mesh is produced inside out.

This is the code that does the enclosed volume calculation:

private static double[] getSurfaceVolume(
		final Collection<List<Point3f>> surfacePoints)
	{
		return surfacePoints.stream().mapToDouble(p -> {
			if (p == null) {
				return 0;
			}
			final CustomTriangleMesh mesh = new CustomTriangleMesh(p);
			return mesh.getVolume();
		}).toArray();
	}

Anisotropy fail on Fiji 1.52g

Hi all,
I just create a sample binary image stack, and the Anisotropy module failed.
The steps are:

  1. import a image stack into Fiji
  2. Click on BoneJ - Anisotropy
  3. click the Recommended minimum, which sets 2000 directions, 100 Lines per dimension and 1 Sampling increment.
  4. See error in Log and nothing was calculated.
    Please see:
    http://imglf5.nosdn0.126.net/img/M3B0VGdGQVdIRGlGMHFHME9zQ1EraDJkYXlGRWVOeUphekpqQmo1VXM3TXYvcUtZcVd3MGJRPT0.png?imageView&thumbnail=2801y1551&type=png&quality=96&stripmeta=0

Log:

[Fri Sep 28 23:12:55 BST 2018] [ERROR] [] Module threw error
java.lang.NoClassDefFoundError: net/imagej/ops/stats/regression/leastSquares/Quadric
at org.bonej.wrapperPlugins.AnisotropyWrapper.matchOps(AnisotropyWrapper.java:271)
at org.bonej.wrapperPlugins.AnisotropyWrapper.run(AnisotropyWrapper.java:193)
at org.scijava.command.CommandModule.run(CommandModule.java:199)
at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168)
at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127)
at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66)
at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassNotFoundException: net.imagej.ops.stats.regression.leastSquares.Quadric
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 11 more
[Fri Sep 28 23:14:15 BST 2018] [ERROR] [] Module threw error
java.lang.NoClassDefFoundError: net/imagej/ops/stats/regression/leastSquares/Quadric
at org.bonej.wrapperPlugins.AnisotropyWrapper.matchOps(AnisotropyWrapper.java:271)
at org.bonej.wrapperPlugins.AnisotropyWrapper.run(AnisotropyWrapper.java:193)
at org.scijava.command.CommandModule.run(CommandModule.java:199)
at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168)
at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127)
at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66)
at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
[Fri Sep 28 23:19:23 BST 2018] [ERROR] [] Module threw error
java.lang.NoClassDefFoundError: net/imagej/ops/stats/regression/leastSquares/Quadric
at org.bonej.wrapperPlugins.AnisotropyWrapper.matchOps(AnisotropyWrapper.java:271)
at org.bonej.wrapperPlugins.AnisotropyWrapper.run(AnisotropyWrapper.java:193)
at org.scijava.command.CommandModule.run(CommandModule.java:199)
at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168)
at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127)
at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66)
at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
[Fri Sep 28 23:25:56 BST 2018] [ERROR] [] Module threw error
java.lang.NoClassDefFoundError: net/imagej/ops/stats/regression/leastSquares/Quadric
at org.bonej.wrapperPlugins.AnisotropyWrapper.matchOps(AnisotropyWrapper.java:271)
at org.bonej.wrapperPlugins.AnisotropyWrapper.run(AnisotropyWrapper.java:193)
at org.scijava.command.CommandModule.run(CommandModule.java:199)
at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168)
at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127)
at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66)
at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
[Fri Sep 28 23:26:29 BST 2018] [ERROR] [] Module threw error
java.lang.NoClassDefFoundError: net/imagej/ops/stats/regression/leastSquares/Quadric
at org.bonej.wrapperPlugins.AnisotropyWrapper.matchOps(AnisotropyWrapper.java:271)
at org.bonej.wrapperPlugins.AnisotropyWrapper.run(AnisotropyWrapper.java:193)
at org.scijava.command.CommandModule.run(CommandModule.java:199)
at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168)
at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127)
at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66)
at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

Environment

  • Win10
  • Java version 1.8.0_172 (64-bit)
  • BoneJ is updated through Fiji update.

Log exceptions at command level with LogService

If exceptions happen when running commands, log them with logService.trace() so that users don't normally see them, but that they can be used for debugging if needed. This concerns "expected" exceptions like IOException. An unexpected ArrayIndexOutOfBoundsExceptions or such should still bubble up to the UI, because that's a sign of a bug we need to solve.

SharedTable sorts alphabetically but shouldn't sort at all

SharedTable sorts rows and columns alphabetically, but this is a change in behaviour from the Results table and also BoneJ1's results inserter. Sorting while inserting has no practical necessity and makes the code difficult to maintain.

Columns and rows should be created in the order that results are produced by plugins.

SharedTable uses String for numerical data storage

SharedTable uses String for numerical data storage.

This is inefficient because a char is stored for every numeral in the value. It might not scale very well for tables containing a lot of data.

It may be a compromise position because image titles are Strings, and it might not be allowed to have one column of String and the rest Double in the table. On the other hand it is possible to set a String row header, but that has to be unique, so multiple rows using the same image title would have to be disambiguated with e.g. a suffix like ImageTitle, ImageTitle.1, ImageTitle.2 and so on.

Alternatively, could it be possible to declare the Table to contain data of type Object so that cells could contain String or Double without restriction?

Show progress bar when wrappers are running

For each wrapper plug-in show the progress bar with statusService.showProgress(completed, tasks); in an appropriate manner. If the tasks are quick you could show progress with "1 / n subspaces processed". Otherwise you could show progress for each sub-space with "1 / n processing completed" like in Anisotropy.

Create a separate repo of the mavenized BoneJ1 code

The mavenized BoneJ1 code should be uploaded to a different repo for future safekeeping from where it can easily be cloned. The mavenization branch in this repository will eventually be merged into the master branch, and the development will continue. The mavenized BoneJ1 could be used as a basis for the automatic builds for different platforms mentioned in the forum.

Thickness produces extra rows in the result table

Describe the bug
When Thickness completes, it adds two new rows to the result table:
ImageTitle_Tb.Th
Image Title_Tb.Sp

To Reproduce
Steps to reproduce the behavior:

  1. Open an image
  2. Run Plugins > BoneJ > Thickness

Expected behavior
Results should be entered in the row with label according to the original input image

Screenshots
screenshot from 2018-09-04 09-31-51

Environment

  • OS: Ubuntu 16.04
  • Java version: 1.8.0_172 (Oracle)
  • Fiji updated today
  • BoneJ2 5e3be0c

Separate tests into unit and regression tests

Many of the unit tests in legacy BoneJ code are heavy, and take several seconds to execute. They're also quite not granular enough. Unit tests in BoneJ2 are going to be automatically run as a part of the project's Jenkins build every time a commit is made to the master branch. Their role is to be constantly run to check that nothing has been broken when the code's been changed. Thus slow and heavy tests are not feasible.

These cumbersome tests could be converted into regression tests that are only occasionally run to check that plugins still produce same outputs. The key tool here would be the Failsafe plugin for Maven. It can be used to run certain tests only at verification and integration-test phases, i.e. not every time the project is built.

Also after separating the tests it would be easier to surmise which plugins need more unit tests.

Rename `IsoSurfaceWrapper` to `SurfaceAreaWrapper`

This plug-in is about measuring the surface area of a bone mesh. The option to save an .stl file is just an additional feature. In the future it can removed, when Fiji ships with SciView, which can handle stl files.

CommonTest.testToBitTypeImgPlus throws NullPointerException

The test throws a NullPointerException here. Ultimately the cause is that the field ij1Helper in net.imagej.legacy.LegacyService is null. However, the exception only happens if the test is run from Maven! When I run the test in IntelliJ, it passes.

Steps to reproduce

  • Depend on pom-scijava:21.0.0 or newer
    • Specifically, he problem appears at scijava-common:2.70.0
  • Depend on imagej-legacy (run time)
    • The issue doesn't appear if you don't have this dependency
  • Remove the @Ignore annotation from the aforementioned test if necessary
  • Run mvn test

Isosurface naming clash

The ThreeDViewer plugin also has a command Isosurface which clashes with the BoneJ command. If you click BoneJ>Isosurface it's the ThreeDViewer command that gets called

BoneJ legacy tests abuse the GUI

Because some unit tests in the legacy BoneJ code invoke the GUI, they cannot be run on the project's Jenkins server. Either make these tests integration tests, or use Mockito to mock the calls to GUI.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.