diff --git a/scijava-ops-image/src/main/java/org/scijava/ops/image/transform/project/project/DefaultProjectParallel.java b/scijava-ops-image/src/main/java/org/scijava/ops/image/transform/project/project/DefaultProjectParallel.java index 77ee0c60f..4494dc47d 100644 --- a/scijava-ops-image/src/main/java/org/scijava/ops/image/transform/project/project/DefaultProjectParallel.java +++ b/scijava-ops-image/src/main/java/org/scijava/ops/image/transform/project/project/DefaultProjectParallel.java @@ -36,6 +36,7 @@ import net.imglib2.loops.LoopBuilder; import net.imglib2.util.Intervals; +import net.imglib2.view.Views; import org.scijava.function.Computers; /** @@ -44,7 +45,7 @@ * @implNote op name='transform.project', priority='99.' */ public class DefaultProjectParallel implements - Computers.Arity3, Computers.Arity1, V>, Integer, RandomAccessibleInterval> + Computers.Arity3, Computers.Arity1, V>, Integer, RandomAccessibleInterval> { /** @@ -57,9 +58,8 @@ public class DefaultProjectParallel implements */ @Override public void compute(final RandomAccessibleInterval input, - Computers.Arity1, V> op, Integer dim, - final RandomAccessibleInterval output) - { + Computers.Arity1, V> op, Integer dim, + final RandomAccessibleInterval output) { // TODO this first check is too simple, but for now ok if (input.numDimensions() != output.numDimensions() + 1) // throw new IllegalArgumentException( @@ -69,22 +69,12 @@ public void compute(final RandomAccessibleInterval input, "ERROR: input image must contain dimension " + dim); LoopBuilder.setImages(output, Intervals.positions(output)).multiThreaded() - .forEachChunk(chunk -> { - var chunkRA = input.randomAccess(); - chunk.forEachPixel((pixel, position) -> { - for (var d = 0; d < input.numDimensions(); d++) { - if (d != dim) { - chunkRA.setPosition(position.getIntPosition(d - (d > dim ? 1 - : 0)), d); - } - } - - op.compute(new DimensionIterable(input.dimension(dim), dim, chunkRA), - pixel); - - }); - - return null; + .forEachPixel((pixel, position) -> { + var ra = input; + for (var d = 0; d < position.numDimensions(); d++) { + ra = Views.hyperSlice(ra, d < dim ? 0 : 1, position.getIntPosition(d)); + } + op.compute(ra, pixel); }); } diff --git a/scijava-ops-image/src/test/java/org/scijava/ops/image/transform/project/project/ProjectTest.java b/scijava-ops-image/src/test/java/org/scijava/ops/image/transform/project/ProjectTest.java similarity index 74% rename from scijava-ops-image/src/test/java/org/scijava/ops/image/transform/project/project/ProjectTest.java rename to scijava-ops-image/src/test/java/org/scijava/ops/image/transform/project/ProjectTest.java index 0bb4e0c47..18fa3a6e6 100644 --- a/scijava-ops-image/src/test/java/org/scijava/ops/image/transform/project/project/ProjectTest.java +++ b/scijava-ops-image/src/test/java/org/scijava/ops/image/transform/project/ProjectTest.java @@ -27,10 +27,14 @@ * #L% */ -package org.scijava.ops.image.transform.project.project; +package org.scijava.ops.image.transform.project; import static org.junit.jupiter.api.Assertions.assertEquals; +import net.imglib2.FinalInterval; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.view.Views; import org.scijava.ops.image.AbstractOpTest; import org.scijava.ops.image.util.TestImgGeneration; import net.imglib2.RandomAccess; @@ -50,7 +54,6 @@ public class ProjectTest extends AbstractOpTest { private Img in; private Img out1; private Img out2; - private Computers.Arity1, UnsignedByteType> op; @BeforeEach public void initImg() { @@ -70,18 +73,11 @@ public void initImg() { out1 = TestImgGeneration.unsignedByteArray(false, 10, 10); out2 = TestImgGeneration.unsignedByteArray(false, 10, 10); - - op = OpBuilder.matchComputer(ops, "stats.sum", - new Nil>() - {}, new Nil() {}); } @Test public void testProjector() { - // TODO: uncomment when this Op is ported (assuming it will be?) - // ops.run(DefaultProjectParallel.class, out1, in, op, PROJECTION_DIM); - // ops.run(DefaultProjectParallel.class, out2, in, op, PROJECTION_DIM); - // testEquality(out1, out2); + var op = ops.op("stats.sum").input(in).outType(UnsignedByteType.class).computer(); ops.op("transform.project").input(in, op, PROJECTION_DIM).output(out1) .compute(); @@ -90,6 +86,37 @@ public void testProjector() { testEquality(out1, out2); } + /** + * Ensures {@code "transform.project"} runs only within the passed interval. + */ + @Test + public void testInterval() { + // Set up img[x, y, z] = z + var input = ArrayImgs.unsignedBytes(10, 10, 10); + for(int x = 0; x < 10; x++) { + for(int y = 0; y < 10; y++) { + for(int z = 0; z < 10; z++) { + input.getAt(x, y, z).set(z); + } + } + } + // Create an interval containing 2<=z<=4 + var intervaled = Views.interval(input, new FinalInterval(new long[] {0, 0, 2}, new long[] {10, 10, 4})); + + // Project on the interval + var out = ArrayImgs.unsignedBytes(10, 10); + var op = ops.op("stats.sum").input(intervaled).outType(UnsignedByteType.class).computer(); + ops.op("transform.project").input(intervaled, op, PROJECTION_DIM).output(out).compute(); + + // Assert that the projection (summation) only covered z=2, z=3, z=4 + var outCursor = out.cursor(); + while (outCursor.hasNext()) { + // 2 + 3 + 4 = 9 + assertEquals(9, outCursor.next().get()); + } + + } + private void testEquality(final Img img1, final Img img2) {