ElementUtil { public static <T extends AnnotatedSpace<CalibratedAxis>> double calibratedSpatialElementSize(final T space, final UnitService unitService) { final Optional<String> optional = AxisUtils.getSpatialUnit(space, unitService); if (!optional.isPresent() || hasNonLinearSpatialAxes(space)) { return Double.NaN; } final double elementSize = spatialAxisStream(space).map(a -> a.averageScale( 0, 1)).reduce((x, y) -> x * y).orElse(0.0); final String outputUnit = optional.get().replaceFirst("^µ[mM]$", "um"); if (outputUnit.isEmpty()) { return elementSize; } final List<CalibratedAxis> axes = spatialAxisStream(space).collect( Collectors.toList()); double unitCoeff = 1.0; for (int i = 1; i < axes.size(); i++) { final String inputUnit = axes.get(i).unit().replaceFirst("^µ[mM]$", "um"); final double conversion = unitService.value(1.0, inputUnit, outputUnit); unitCoeff *= conversion; } return elementSize * unitCoeff; } private  ElementUtil(); static double calibratedSpatialElementSize(final T space, final UnitService unitService); static boolean isBinary(
		final IterableInterval<T> interval);  }
@Test public void testCalibratedSpatialElementSize() { final double[][] scales = { { 20.0, 4.0, 1.0 }, { 20.0, 1.0, 4.0 }, { 4.0, 20.0, 1.0 } }; final String[][] units = { { "mm", "cm", "m" }, { "m", "cm", "mm" }, { "µm", "µm", "µm" } }; final double[] expected = { 800_000, 0.0008, 80.0 }; final Img<ByteType> img = ArrayImgs.bytes(1, 1, 1); final ImgPlus<ByteType> imgPlus = new ImgPlus<>(img); for (int i = 0; i < scales.length; i++) { final CalibratedAxis xAxis = new DefaultLinearAxis(Axes.X, units[i][0], scales[i][0]); final CalibratedAxis yAxis = new DefaultLinearAxis(Axes.Y, units[i][1], scales[i][1]); final CalibratedAxis zAxis = new DefaultLinearAxis(Axes.Z, units[i][2], scales[i][2]); imgPlus.setAxis(xAxis, 0); imgPlus.setAxis(yAxis, 1); imgPlus.setAxis(zAxis, 2); final double elementSize = ElementUtil.calibratedSpatialElementSize( imgPlus, unitService); assertEquals("Element size is incorrect", expected[i], elementSize, 1e-12); } }
@Test(expected = IllegalArgumentException.class) public void testCalibratedSpatialElementSizeThrowsIAEIfNoSpatialAxes() { final DefaultLinearAxis cAxis = new DefaultLinearAxis(Axes.CHANNEL); final Img<DoubleType> img = IMAGE_J.op().create().img(new int[] { 3 }); final ImgPlus<DoubleType> imgPlus = new ImgPlus<>(img, "Test image", cAxis); ElementUtil.calibratedSpatialElementSize(imgPlus, unitService); }
@Test public void testCalibratedSpatialElementSizeNoUnits() { final DefaultLinearAxis xAxis = new DefaultLinearAxis(Axes.X, 20.0); final DefaultLinearAxis yAxis = new DefaultLinearAxis(Axes.Y, 4.0); final DefaultLinearAxis zAxis = new DefaultLinearAxis(Axes.Z, 1.0); final Img<ByteType> img = ArrayImgs.bytes(1, 1, 1); final ImgPlus<ByteType> imgPlus = new ImgPlus<>(img, "", xAxis, yAxis, zAxis); final double elementSize = ElementUtil.calibratedSpatialElementSize(imgPlus, unitService); assertEquals("Element size is incorrect", 80.0, elementSize, 1e-12); }
@Test public void testCalibratedSpatialElementSizeNonLinearAxis() { final DefaultLinearAxis xAxis = new DefaultLinearAxis(Axes.X); final PowerAxis yAxis = new PowerAxis(Axes.Y, 2); final Img<DoubleType> img = IMAGE_J.op().create().img(new int[] { 10, 10 }); final ImgPlus<DoubleType> imgPlus = new ImgPlus<>(img, "Test image", xAxis, yAxis); final double result = ElementUtil.calibratedSpatialElementSize(imgPlus, unitService); assertTrue("Size should be NaN when space has nonlinear axes", Double.isNaN( result)); }
@Test(expected = NullPointerException.class) public void testCalibratedSpatialElementSizeThrowsNPIfENullSpace() { ElementUtil.calibratedSpatialElementSize(null, unitService); }
@Test(expected = NullPointerException.class) public void testCalibratedSpatialElementSizeThrowsNPEIfNullUnitService() { final DefaultLinearAxis xAxis = new DefaultLinearAxis(Axes.X, "mm"); final DefaultLinearAxis yAxis = new DefaultLinearAxis(Axes.Y, "mm"); final DefaultLinearAxis zAxis = new DefaultLinearAxis(Axes.Z, "kg"); final Img<ByteType> img = ArrayImgs.bytes(1, 1, 1); final ImgPlus<ByteType> imgPlus = new ImgPlus<>(img, "", xAxis, yAxis, zAxis); ElementUtil.calibratedSpatialElementSize(imgPlus, null); }
@Test public void testCalibratedSpatialElementSizeUnitsInconvertible() { final DefaultLinearAxis xAxis = new DefaultLinearAxis(Axes.X, "cm"); final DefaultLinearAxis yAxis = new DefaultLinearAxis(Axes.Y, ""); final Img<DoubleType> img = IMAGE_J.op().create().img(new int[] { 10, 10 }); final ImgPlus<DoubleType> imgPlus = new ImgPlus<>(img, "Test image", xAxis, yAxis); final double result = ElementUtil.calibratedSpatialElementSize(imgPlus, unitService); assertEquals("Size should be NaN if unit inconvertible", Double.NaN, result, 1e-12); }