EllipsoidFactorWrapper extends BoneJCommand { @Override public void run() { inputAsBitType = Common.toBitTypeImgPlus(opService, inputImage); int totalEllipsoids = 0; List<ImgPlus> outputList = null; final EllipsoidFactorErrorTracking errorTracking = new EllipsoidFactorErrorTracking(opService); int counter = 0; for(int i = 0; i<runs; i++) { final List<QuickEllipsoid> ellipsoids = runEllipsoidOptimisation(inputImage); if (ellipsoids.isEmpty()) { cancelMacroSafe(this, NO_ELLIPSOIDS_FOUND); return; } statusService.showStatus("Ellipsoid Factor: assigning EF to foreground voxels..."); final long start = System.currentTimeMillis(); final Img<IntType> ellipsoidIdentityImage = assignEllipsoidIDs(inputAsBitType, ellipsoids); final long stop = System.currentTimeMillis(); logService.info("Found maximal ellipsoids in " + (stop - start) + " ms"); final List<ImgPlus> currentOutputList = (List<ImgPlus>) opService.run(EllipsoidFactorOutputGenerator.class, ellipsoidIdentityImage, ellipsoids, showSecondaryImages); if(outputList!=null) { outputList = sumOutput(outputList, currentOutputList, counter); final Map<String, Double> errors = errorTracking.calculate(outputList.get(0)); errors.forEach((stat,value) -> logService.info(stat+": "+value.toString())); SharedTable.add(inputImage.getName(),"median change "+i,errors.get("Median")); SharedTable.add(inputImage.getName(),"maximum change "+i,errors.get("Max")); } else{ outputList = currentOutputList; SharedTable.add(inputImage.getName(),"median change "+i,2); SharedTable.add(inputImage.getName(),"maximum change "+i,2); } counter++; totalEllipsoids += ellipsoids.size(); } if (totalEllipsoids == 0) { cancelMacroSafe(this, NO_ELLIPSOIDS_FOUND); return; } if(runs>1) { outputList = divideOutput(outputList, runs); } ellipsoidFactorOutputImages = outputList; final double voxelVolume = ElementUtil.calibratedSpatialElementSize(inputImage, unitService); for(final ImgPlus imgPlus : ellipsoidFactorOutputImages) { if(imgPlus.numDimensions()>=3) { for(int dim = 0; dim<3; dim++) { imgPlus.setAxis(inputImage.axis(dim), dim); } if("Volume".equals(imgPlus.getName())) { final Cursor<RealType> cursor = imgPlus.cursor(); cursor.forEachRemaining(c -> { c.mul(voxelVolume); }); imgPlus.setChannelMaximum(0,imgPlus.getChannelMaximum(0)*voxelVolume); } } } final ImgPlus EF = ellipsoidFactorOutputImages.get(0); final double numberOfForegroundVoxels = countTrue(inputAsBitType); final double numberOfAssignedVoxels = countAssignedVoxels(EF); final double fillingPercentage = 100.0 * (numberOfAssignedVoxels / numberOfForegroundVoxels); DescriptiveStatistics stats = new DescriptiveStatistics(); final Cursor<FloatType> cursor = EF.cursor(); while(cursor.hasNext()){ cursor.fwd(); final double value = cursor.get().getRealDouble(); if(!Double.isNaN(value)){ stats.addValue(value); } } final double median = stats.getPercentile(50); SharedTable.add(inputImage.getName(), "Median EF", median); final double max = stats.getMax(); SharedTable.add(inputImage.getName(), "Max EF", max); final double min = stats.getMin(); SharedTable.add(inputImage.getName(), "Min EF", min); addResults(totalEllipsoids, fillingPercentage); statusService.showStatus("Ellipsoid Factor completed"); reportUsage(); }  @Override void run();  }
@Category(org.bonej.wrapperPlugins.SlowWrapperTest.class) @Test public void testCancelledRunDoesNotReport() throws ExecutionException, InterruptedException { final DefaultLinearAxis xAxis = new DefaultLinearAxis(Axes.X, "", 1.0); final DefaultLinearAxis yAxis = new DefaultLinearAxis(Axes.Y, "", 1.0); final DefaultLinearAxis zAxis = new DefaultLinearAxis(Axes.Z, "", 1.0); final Img<UnsignedByteType> img = ArrayImgs.unsignedBytes(5, 5, 5); final ImgPlus<UnsignedByteType> empty = new ImgPlus<>(img, "", xAxis, yAxis, zAxis); final CommandModule module = command().run( EllipsoidFactorWrapper.class, true, "inputImage", empty, "nVectors", 100, "vectorIncrement", 0.435, "skipRatio", 1, "contactSensitivity", 10, "maxIterations", 100, "maxDrift", 1.73, "minimumSemiAxis", 1.0, "runs", 1, "weightedAverageN", 1, "seedOnDistanceRidge", true, "distanceThreshold", 0.6, "seedOnTopologyPreserving", false).get(); final String reason = module.getCancelReason(); assertEquals("EF should have cancelled because there are no ellipsoids in an empty image", EllipsoidFactorWrapper.NO_ELLIPSOIDS_FOUND, reason); verify(MOCK_REPORTER, timeout(1000).times(0)).reportEvent(anyString()); }
@Category(org.bonej.wrapperPlugins.SlowWrapperTest.class) @Test public void testSuccessfulRunReports() throws ExecutionException, InterruptedException { final DefaultLinearAxis xAxis = new DefaultLinearAxis(Axes.X, "", 1.0); final DefaultLinearAxis yAxis = new DefaultLinearAxis(Axes.Y, "", 1.0); final DefaultLinearAxis zAxis = new DefaultLinearAxis(Axes.Z, "", 1.0); final Img<UnsignedByteType> img = createSphereImg(); final ImgPlus<UnsignedByteType> imgPlus = new ImgPlus<>(img, "Sphere", xAxis, yAxis, zAxis); final CommandModule module = command().run( EllipsoidFactorWrapper.class, true, "inputImage", imgPlus, "nVectors", 100, "vectorIncrement", 0.435, "skipRatio", 1, "contactSensitivity", 10, "maxIterations", 100, "maxDrift", 1.73, "minimumSemiAxis", 1.0, "runs", 1, "weightedAverageN", 1, "seedOnDistanceRidge", true, "distanceThreshold", 0.6, "seedOnTopologyPreserving", false).get(); assertFalse("Sanity check failed: method cancelled", module.isCanceled()); verify(MOCK_REPORTER, timeout(1000)).reportEvent(anyString()); }