From 2d3f3d26f72466321d64cadf485f9532b0bb4dc6 Mon Sep 17 00:00:00 2001 From: bogovicj Date: Mon, 15 Aug 2022 11:42:28 -0400 Subject: [PATCH 1/5] feat: add RealStackCompositeView * with a test --- .../composite/RealStackCompositeView.java | 251 ++++++++++++++++++ .../composite/RealStackCompositeTest.java | 62 +++++ 2 files changed, 313 insertions(+) create mode 100644 src/main/java/net/imglib2/view/composite/RealStackCompositeView.java create mode 100644 src/test/java/net/imglib2/view/composite/RealStackCompositeTest.java diff --git a/src/main/java/net/imglib2/view/composite/RealStackCompositeView.java b/src/main/java/net/imglib2/view/composite/RealStackCompositeView.java new file mode 100644 index 000000000..dea38cf37 --- /dev/null +++ b/src/main/java/net/imglib2/view/composite/RealStackCompositeView.java @@ -0,0 +1,251 @@ +package net.imglib2.view.composite; + +import java.util.Arrays; + +import net.imglib2.Localizable; +import net.imglib2.RealInterval; +import net.imglib2.RealLocalizable; +import net.imglib2.RealRandomAccess; +import net.imglib2.RealRandomAccessible; +import net.imglib2.View; + +/** + * {@link RealStackCompositeView} converts an array of {@link RealRandomAccessible}s + * of T into a RealRandomAccessible of {@link Composite} of T. + *

+ * This view has the same dimensionality as each source RealRandomAccessible, and + * the i-th value of the composite of the output is the value of the i-th input source. + * + * @author John Bogovic + */ +public class RealStackCompositeView< T > implements RealRandomAccessible>, View +{ + protected final int n; + + protected final int nd; + + protected final RealRandomAccessible< T >[] sources; + + protected final RealRandomAccess< Composite< T > > access; + + /** + * Creates a RealStackCompositeView. Every input {@link RealRandomAccessible} must + * have the same dimensionality, and be of the same type. + * + * @param sources the list of RealRandomAccessibles + */ + @SuppressWarnings( "unchecked" ) + public RealStackCompositeView( final RealRandomAccessible< T >... sources ) + { + this.sources = sources; + n = sources.length; + nd = sources.length > 0 ? sources[0].numDimensions() : 0; + access = new CompositeRealRandomAccess(); + } + + public class CompositeRealRandomAccess implements RealRandomAccess< Composite< T > >, Composite< T > + { + final protected RealRandomAccess< T >[] sourceAccesses; + + final protected long p; + + @SuppressWarnings( "unchecked" ) + public CompositeRealRandomAccess() + { + p = 0; + sourceAccesses = new RealRandomAccess[ n ]; + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ] = sources[ i ].realRandomAccess(); + } + + @SuppressWarnings( "unchecked" ) + protected CompositeRealRandomAccess( final CompositeRealRandomAccess other ) + { + p = 0; + sourceAccesses = new RealRandomAccess[ n ]; + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ] = other.sourceAccesses[i].copy(); + } + + @Override + public int numDimensions() + { + return nd; + } + + @Override + public Composite< T > get() + { + return this; + } + + @Override + public CompositeRealRandomAccess copy() + { + return new CompositeRealRandomAccess( this ); + } + + @Override + public double getDoublePosition( int d ) + { + return sourceAccesses[0].getDoublePosition( d ); + } + + @Override + public void move( float distance, int d ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance, d ) ); + } + + @Override + public void move( double distance, int d ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance, d ) ); + } + + @Override + public void move( RealLocalizable distance ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance ) ); + } + + @Override + public void move( float[] distance ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance ) ); + } + + @Override + public void move( double[] distance ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance ) ); + } + + @Override + public void setPosition( RealLocalizable position ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position ) ); + } + + @Override + public void setPosition( float[] position ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position ) ); + } + + @Override + public void setPosition( double[] position ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position ) ); + } + + @Override + public void setPosition( float position, int d ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position, d ) ); + } + + @Override + public void setPosition( double position, int d ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position, d ) ); + } + + @Override + public void fwd( int d ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.fwd( d ) ); + } + + @Override + public void bck( int d ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.bck( d ) ); + } + + @Override + public void move( int distance, int d ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance, d ) ); + } + + @Override + public void move( long distance, int d ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance, d ) ); + } + + @Override + public void move( Localizable distance ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance ) ); + } + + @Override + public void move( int[] distance ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance ) ); + } + + @Override + public void move( long[] distance ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance ) ); + } + + @Override + public void setPosition( Localizable position ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position ) ); + } + + @Override + public void setPosition( int[] position ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position ) ); + } + + @Override + public void setPosition( long[] position ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position ) ); + } + + @Override + public void setPosition( int position, int d ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position, d ) ); + } + + @Override + public void setPosition( long position, int d ) + { + Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position, d ) ); + } + + @Override + public T get( long i ) + { + return sourceAccesses[ (int)i ].get(); + } + } + + @Override + public int numDimensions() + { + return nd; + } + + @Override + public RealRandomAccess< Composite< T > > realRandomAccess() + { + return access; + } + + @Override + public RealRandomAccess< Composite< T > > realRandomAccess( RealInterval interval ) + { + return realRandomAccess(); + } + +} diff --git a/src/test/java/net/imglib2/view/composite/RealStackCompositeTest.java b/src/test/java/net/imglib2/view/composite/RealStackCompositeTest.java new file mode 100644 index 000000000..07fd40d5d --- /dev/null +++ b/src/test/java/net/imglib2/view/composite/RealStackCompositeTest.java @@ -0,0 +1,62 @@ +package net.imglib2.view.composite; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +import net.imglib2.RealRandomAccess; +import net.imglib2.RealRandomAccessible; +import net.imglib2.position.FunctionRealRandomAccessible; +import net.imglib2.type.numeric.integer.IntType; +import net.imglib2.type.numeric.real.DoubleType; +import net.imglib2.util.ConstantUtils; + +public class RealStackCompositeTest +{ + private static final double EPS = 1e-9; + + int N = 5; + RealRandomAccessible[] sources; + + @SuppressWarnings( "unchecked" ) + @Before + public void before() throws Exception + { + sources = new RealRandomAccessible[ N ]; + for( int i = 0; i < N; i++ ) + { + final int j = i; + sources[i] = new FunctionRealRandomAccessible<>( 1, + ( x, v ) -> { v.set( j * x.getDoublePosition( 0 ) ); }, + DoubleType::new ); + } + } + + @Test + public final void test() + { + RealStackCompositeView rimg = new RealStackCompositeView<>( sources ); + assertEquals( "ndims", 1, rimg.numDimensions() ); + + RealRandomAccess> access = rimg.realRandomAccess(); + for( int i = 0; i < N; i++ ) + assertEquals( 0, access.get().get( i ).get(), EPS ); + + double p = 10; + access.setPosition( p, 0 ); + for( int i = 0; i < N; i++ ) + assertEquals( i * p, access.get().get( i ).get(), EPS ); + + p++; + access.fwd( 0 ); + for( int i = 0; i < N; i++ ) + assertEquals( i * p, access.get().get( i ).get(), EPS ); + + p -= 2; + access.move( -2, 0 ); + for( int i = 0; i < N; i++ ) + assertEquals( i * p, access.get().get( i ).get(), EPS ); + + } +} From eb78cb30eac51e0611ce020517af655da3e6be1c Mon Sep 17 00:00:00 2001 From: bogovicj Date: Mon, 15 Aug 2022 12:05:50 -0400 Subject: [PATCH 2/5] test: add another RealStackCompositeTest test --- .../composite/RealStackCompositeTest.java | 73 ++++++++++++++++++- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/src/test/java/net/imglib2/view/composite/RealStackCompositeTest.java b/src/test/java/net/imglib2/view/composite/RealStackCompositeTest.java index 07fd40d5d..125a03924 100644 --- a/src/test/java/net/imglib2/view/composite/RealStackCompositeTest.java +++ b/src/test/java/net/imglib2/view/composite/RealStackCompositeTest.java @@ -16,13 +16,15 @@ public class RealStackCompositeTest { private static final double EPS = 1e-9; - int N = 5; - RealRandomAccessible[] sources; + private int N = 5; + private RealRandomAccessible[] sources; + private RealRandomAccessible[] sources2; @SuppressWarnings( "unchecked" ) @Before public void before() throws Exception { + // 1d sources = new RealRandomAccessible[ N ]; for( int i = 0; i < N; i++ ) { @@ -31,10 +33,20 @@ public void before() throws Exception ( x, v ) -> { v.set( j * x.getDoublePosition( 0 ) ); }, DoubleType::new ); } + + // 2d + sources2 = new RealRandomAccessible[ N ]; + for( int i = 0; i < N; i++ ) + { + final int j = i; + sources2[i] = new FunctionRealRandomAccessible<>( 2, + ( x, v ) -> { v.set( j * x.getDoublePosition( 0 ) + x.getDoublePosition( 1 )); }, + DoubleType::new ); + } } @Test - public final void test() + public final void test1d() { RealStackCompositeView rimg = new RealStackCompositeView<>( sources ); assertEquals( "ndims", 1, rimg.numDimensions() ); @@ -43,20 +55,75 @@ public final void test() for( int i = 0; i < N; i++ ) assertEquals( 0, access.get().get( i ).get(), EPS ); + // test setPosition double p = 10; access.setPosition( p, 0 ); for( int i = 0; i < N; i++ ) assertEquals( i * p, access.get().get( i ).get(), EPS ); + // test fwd p++; access.fwd( 0 ); for( int i = 0; i < N; i++ ) assertEquals( i * p, access.get().get( i ).get(), EPS ); + // test move p -= 2; access.move( -2, 0 ); for( int i = 0; i < N; i++ ) assertEquals( i * p, access.get().get( i ).get(), EPS ); } + + @Test + public final void test2d() + { + RealStackCompositeView rimg = new RealStackCompositeView<>( sources2 ); + assertEquals( "ndims", 2, rimg.numDimensions() ); + + RealRandomAccess> access = rimg.realRandomAccess(); + for( int i = 0; i < N; i++ ) + assertEquals( 0, access.get().get( i ).get(), EPS ); + + double x = 10; + double y = 2; + double[] pa = new double[]{x,y}; + + // test setPosition + access.setPosition( x, 0 ); + access.setPosition( y, 1 ); + for( int i = 0; i < N; i++ ) + assertEquals( i * x + y, access.get().get( i ).get(), EPS ); + + // test setPosition + x = 11; pa[0] = x; + y = 3; pa[1] = y; + access.setPosition( pa ); + for( int i = 0; i < N; i++ ) + assertEquals( i * x + y, access.get().get( i ).get(), EPS ); + + // test fwd + x++; + access.fwd( 0 ); + for( int i = 0; i < N; i++ ) + assertEquals( i * x + y, access.get().get( i ).get(), EPS ); + + y++; + access.fwd( 1 ); + for( int i = 0; i < N; i++ ) + assertEquals( i * x + y, access.get().get( i ).get(), EPS ); + + // test move + x -= 2.5; + access.move( -2.5, 0 ); + for( int i = 0; i < N; i++ ) + assertEquals( i * x + y, access.get().get( i ).get(), EPS ); + + // test move + y -= 0.7; + access.move( -0.7, 1 ); + for( int i = 0; i < N; i++ ) + assertEquals( i * x + y, access.get().get( i ).get(), EPS ); + + } } From d256e3cc3ba94ef57e0a22712abdf080a0d3fdbd Mon Sep 17 00:00:00 2001 From: bogovicj Date: Mon, 15 Aug 2022 13:13:29 -0400 Subject: [PATCH 3/5] fix: RealStackCompositeView doc and clean up * enforce at least one source --- .../view/composite/RealStackCompositeView.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/imglib2/view/composite/RealStackCompositeView.java b/src/main/java/net/imglib2/view/composite/RealStackCompositeView.java index dea38cf37..d1a9bde2e 100644 --- a/src/main/java/net/imglib2/view/composite/RealStackCompositeView.java +++ b/src/main/java/net/imglib2/view/composite/RealStackCompositeView.java @@ -10,11 +10,11 @@ import net.imglib2.View; /** - * {@link RealStackCompositeView} converts an array of {@link RealRandomAccessible}s + * A {@link RealStackCompositeView} converts an array of {@link RealRandomAccessible}s * of T into a RealRandomAccessible of {@link Composite} of T. *

* This view has the same dimensionality as each source RealRandomAccessible, and - * the i-th value of the composite of the output is the value of the i-th input source. + * at every position, the i-th value of the composite is the value for the i-th input source. * * @author John Bogovic */ @@ -37,9 +37,10 @@ public class RealStackCompositeView< T > implements RealRandomAccessible... sources ) { + assert( sources.length > 0 ); this.sources = sources; n = sources.length; - nd = sources.length > 0 ? sources[0].numDimensions() : 0; + nd = sources[0].numDimensions(); access = new CompositeRealRandomAccess(); } @@ -47,12 +48,9 @@ public class CompositeRealRandomAccess implements RealRandomAccess< Composite< T { final protected RealRandomAccess< T >[] sourceAccesses; - final protected long p; - @SuppressWarnings( "unchecked" ) public CompositeRealRandomAccess() { - p = 0; sourceAccesses = new RealRandomAccess[ n ]; for ( int i = 0; i < n; i++ ) sourceAccesses[ i ] = sources[ i ].realRandomAccess(); @@ -61,7 +59,6 @@ public CompositeRealRandomAccess() @SuppressWarnings( "unchecked" ) protected CompositeRealRandomAccess( final CompositeRealRandomAccess other ) { - p = 0; sourceAccesses = new RealRandomAccess[ n ]; for ( int i = 0; i < n; i++ ) sourceAccesses[ i ] = other.sourceAccesses[i].copy(); From 1f8f4b8cebd31888608ffab1bfbf95e1db732f06 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 20 Sep 2023 16:43:48 -0400 Subject: [PATCH 4/5] add access modes to RealStackCompositeView * test both access modes --- .../composite/RealStackCompositeView.java | 341 +++++++++++++++--- .../composite/RealStackCompositeTest.java | 32 +- 2 files changed, 309 insertions(+), 64 deletions(-) diff --git a/src/main/java/net/imglib2/view/composite/RealStackCompositeView.java b/src/main/java/net/imglib2/view/composite/RealStackCompositeView.java index d1a9bde2e..7a9daddc3 100644 --- a/src/main/java/net/imglib2/view/composite/RealStackCompositeView.java +++ b/src/main/java/net/imglib2/view/composite/RealStackCompositeView.java @@ -1,55 +1,84 @@ package net.imglib2.view.composite; -import java.util.Arrays; - import net.imglib2.Localizable; import net.imglib2.RealInterval; import net.imglib2.RealLocalizable; import net.imglib2.RealRandomAccess; import net.imglib2.RealRandomAccessible; import net.imglib2.View; +import net.imglib2.view.StackView.StackAccessMode; /** * A {@link RealStackCompositeView} converts an array of {@link RealRandomAccessible}s * of T into a RealRandomAccessible of {@link Composite} of T. *

* This view has the same dimensionality as each source RealRandomAccessible, and - * at every position, the i-th value of the composite is the value for the i-th input source. + * at every position, the i-th value of the composite is the value for the i-th input RealRandomAccessible. * * @author John Bogovic */ public class RealStackCompositeView< T > implements RealRandomAccessible>, View { - protected final int n; - - protected final int nd; + protected final int n, nd; protected final RealRandomAccessible< T >[] sources; - protected final RealRandomAccess< Composite< T > > access; + private final StackAccessMode stackAccessMode; /** * Creates a RealStackCompositeView. Every input {@link RealRandomAccessible} must * have the same dimensionality, and be of the same type. - * + * * @param sources the list of RealRandomAccessibles + * @param stackAccessMode the mode */ - @SuppressWarnings( "unchecked" ) - public RealStackCompositeView( final RealRandomAccessible< T >... sources ) + public RealStackCompositeView( final RealRandomAccessible< T >[] sources, StackAccessMode stackAccessMode ) { assert( sources.length > 0 ); this.sources = sources; n = sources.length; nd = sources[0].numDimensions(); - access = new CompositeRealRandomAccess(); + this.stackAccessMode = stackAccessMode; + } + + /** + * Creates a RealStackCompositeView. Every input {@link RealRandomAccessible} must + * have the same dimensionality, and be of the same type. Uses the DEFAULT + * {@link StackAccessMode}. + * + * @param sources the list of RealRandomAccessibles + */ + public RealStackCompositeView( final RealRandomAccessible< T >[] sources ) + { + this( sources, StackAccessMode.DEFAULT ); } - public class CompositeRealRandomAccess implements RealRandomAccess< Composite< T > >, Composite< T > + @Override + public int numDimensions() + { + return nd; + } + + @Override + public RealRandomAccess< Composite > realRandomAccess() + { + return stackAccessMode == StackAccessMode.MOVE_ALL_SLICE_ACCESSES ? + new CompositeRealRandomAccessMoveAll() : + new CompositeRealRandomAccessDefault(); + } + + @Override + public RealRandomAccess< Composite > realRandomAccess( RealInterval interval ) + { + return realRandomAccess(); + } + + public class CompositeRealRandomAccessMoveAll implements RealRandomAccess< Composite >, Composite { final protected RealRandomAccess< T >[] sourceAccesses; @SuppressWarnings( "unchecked" ) - public CompositeRealRandomAccess() + public CompositeRealRandomAccessMoveAll() { sourceAccesses = new RealRandomAccess[ n ]; for ( int i = 0; i < n; i++ ) @@ -57,7 +86,7 @@ public CompositeRealRandomAccess() } @SuppressWarnings( "unchecked" ) - protected CompositeRealRandomAccess( final CompositeRealRandomAccess other ) + protected CompositeRealRandomAccessMoveAll( final CompositeRealRandomAccessMoveAll other ) { sourceAccesses = new RealRandomAccess[ n ]; for ( int i = 0; i < n; i++ ) @@ -67,19 +96,19 @@ protected CompositeRealRandomAccess( final CompositeRealRandomAccess other ) @Override public int numDimensions() { - return nd; + return n; } @Override - public Composite< T > get() + public Composite get() { return this; } @Override - public CompositeRealRandomAccess copy() + public CompositeRealRandomAccessMoveAll copy() { - return new CompositeRealRandomAccess( this ); + return new CompositeRealRandomAccessMoveAll( this ); } @Override @@ -91,133 +120,155 @@ public double getDoublePosition( int d ) @Override public void move( float distance, int d ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance, d ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].move( distance, d ); } @Override public void move( double distance, int d ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance, d ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].move( distance, d ); } @Override public void move( RealLocalizable distance ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].move( distance ); } @Override public void move( float[] distance ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].move( distance ); } @Override public void move( double[] distance ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].move( distance ); } @Override public void setPosition( RealLocalizable position ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].setPosition( position ); } @Override public void setPosition( float[] position ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].setPosition( position ); } @Override public void setPosition( double[] position ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].setPosition( position ); } @Override public void setPosition( float position, int d ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position, d ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].setPosition( position, d ); } @Override public void setPosition( double position, int d ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position, d ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].setPosition( position, d ); } @Override public void fwd( int d ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.fwd( d ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].fwd( d ); } @Override public void bck( int d ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.bck( d ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].bck( d ); } @Override public void move( int distance, int d ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance, d ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].move( distance, d ); } @Override public void move( long distance, int d ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance, d ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].move( distance, d ); } @Override public void move( Localizable distance ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].move( distance ); } @Override public void move( int[] distance ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].move( distance ); } @Override public void move( long[] distance ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.move( distance ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].move( distance ); } @Override public void setPosition( Localizable position ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].setPosition( position ); } @Override public void setPosition( int[] position ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].setPosition( position ); } @Override public void setPosition( long[] position ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].setPosition( position ); } @Override public void setPosition( int position, int d ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position, d ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].setPosition( position, d ); } @Override public void setPosition( long position, int d ) { - Arrays.stream( sourceAccesses ).forEach( x -> x.setPosition( position, d ) ); + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ].setPosition( position, d ); } @Override @@ -227,22 +278,206 @@ public T get( long i ) } } - @Override - public int numDimensions() + public class CompositeRealRandomAccessDefault implements RealRandomAccess< Composite >, Composite { - return nd; - } + final protected RealRandomAccess< T >[] sourceAccesses; - @Override - public RealRandomAccess< Composite< T > > realRandomAccess() - { - return access; - } + protected int currentIndex = 0; - @Override - public RealRandomAccess< Composite< T > > realRandomAccess( RealInterval interval ) - { - return realRandomAccess(); + protected RealRandomAccess< T > currentAccess; + + @SuppressWarnings( "unchecked" ) + public CompositeRealRandomAccessDefault() + { + sourceAccesses = new RealRandomAccess[ n ]; + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ] = sources[ i ].realRandomAccess(); + + currentIndex = 0; + currentAccess = sourceAccesses[ currentIndex ]; + } + + @SuppressWarnings( "unchecked" ) + protected CompositeRealRandomAccessDefault( final CompositeRealRandomAccessDefault other ) + { + sourceAccesses = new RealRandomAccess[ n ]; + for ( int i = 0; i < n; i++ ) + sourceAccesses[ i ] = other.sourceAccesses[i].copy(); + + currentIndex = other.currentIndex; + currentAccess = sourceAccesses[currentIndex]; + } + + @Override + public int numDimensions() + { + return n; + } + + @Override + public Composite get() + { + return this; + } + + @Override + public CompositeRealRandomAccessDefault copy() + { + return new CompositeRealRandomAccessDefault( this ); + } + + @Override + public double getDoublePosition( int d ) + { + return sourceAccesses[0].getDoublePosition( d ); + } + + @Override + public void move( float distance, int d ) + { + currentAccess.move( distance, d ); + } + + @Override + public void move( double distance, int d ) + { + currentAccess.move( distance, d ); + } + + @Override + public void move( RealLocalizable distance ) + { + currentAccess.move( distance ); + } + + @Override + public void move( float[] distance ) + { + for ( int i = 0; i < n; i++ ) + currentAccess.move( distance ); + } + + @Override + public void move( double[] distance ) + { + currentAccess.move( distance ); + } + + @Override + public void setPosition( RealLocalizable position ) + { + currentAccess.setPosition( position ); + } + + @Override + public void setPosition( float[] position ) + { + currentAccess.setPosition( position ); + } + + @Override + public void setPosition( double[] position ) + { + currentAccess.setPosition( position ); + } + + @Override + public void setPosition( float position, int d ) + { + currentAccess.setPosition( position, d ); + } + + @Override + public void setPosition( double position, int d ) + { + currentAccess.setPosition( position, d ); + } + + @Override + public void fwd( int d ) + { + currentAccess.fwd( d ); + } + + @Override + public void bck( int d ) + { + currentAccess.bck( d ); + } + + @Override + public void move( int distance, int d ) + { + currentAccess.move( distance, d ); + } + + @Override + public void move( long distance, int d ) + { + currentAccess.move( distance, d ); + } + + @Override + public void move( Localizable distance ) + { + currentAccess.move( distance ); + } + + @Override + public void move( int[] distance ) + { + currentAccess.move( distance ); + } + + @Override + public void move( long[] distance ) + { + currentAccess.move( distance ); + } + + @Override + public void setPosition( Localizable position ) + { + currentAccess.setPosition( position ); + } + + @Override + public void setPosition( int[] position ) + { + currentAccess.setPosition( position ); + } + + @Override + public void setPosition( long[] position ) + { + currentAccess.setPosition( position ); + } + + @Override + public void setPosition( int position, int d ) + { + currentAccess.setPosition( position, d ); + } + + @Override + public void setPosition( long position, int d ) + { + currentAccess.setPosition( position, d ); + } + + @Override + public T get( long i ) + { + if( i == currentIndex ) + return currentAccess.get(); + else + { + sourceAccesses[(int)i].setPosition(currentAccess); + currentAccess = sourceAccesses[(int)i]; + currentIndex = (int)i; + return currentAccess.get(); + } + } } } diff --git a/src/test/java/net/imglib2/view/composite/RealStackCompositeTest.java b/src/test/java/net/imglib2/view/composite/RealStackCompositeTest.java index 125a03924..76325c96e 100644 --- a/src/test/java/net/imglib2/view/composite/RealStackCompositeTest.java +++ b/src/test/java/net/imglib2/view/composite/RealStackCompositeTest.java @@ -8,9 +8,8 @@ import net.imglib2.RealRandomAccess; import net.imglib2.RealRandomAccessible; import net.imglib2.position.FunctionRealRandomAccessible; -import net.imglib2.type.numeric.integer.IntType; import net.imglib2.type.numeric.real.DoubleType; -import net.imglib2.util.ConstantUtils; +import net.imglib2.view.StackView.StackAccessMode; public class RealStackCompositeTest { @@ -48,46 +47,57 @@ public void before() throws Exception @Test public final void test1d() { - RealStackCompositeView rimg = new RealStackCompositeView<>( sources ); + test1dHelper("default", new RealStackCompositeView<>(sources)); + test1dHelper("moveAll", new RealStackCompositeView<>(sources, StackAccessMode.MOVE_ALL_SLICE_ACCESSES)); + } + + protected final void test1dHelper( String accessMode, RealStackCompositeView rimg ) + { assertEquals( "ndims", 1, rimg.numDimensions() ); - RealRandomAccess> access = rimg.realRandomAccess(); + final RealRandomAccess> access = rimg.realRandomAccess(); for( int i = 0; i < N; i++ ) - assertEquals( 0, access.get().get( i ).get(), EPS ); + assertEquals( accessMode, 0, access.get().get( i ).get(), EPS ); // test setPosition double p = 10; access.setPosition( p, 0 ); for( int i = 0; i < N; i++ ) - assertEquals( i * p, access.get().get( i ).get(), EPS ); + assertEquals( accessMode, i * p, access.get().get( i ).get(), EPS ); + + // test setPosition 2 + p = 4; + access.setPosition( p, 0 ); + for( int i = 0; i < N; i++ ) + assertEquals( accessMode, i * p, access.get().get( i ).get(), EPS ); // test fwd p++; access.fwd( 0 ); for( int i = 0; i < N; i++ ) - assertEquals( i * p, access.get().get( i ).get(), EPS ); + assertEquals( accessMode, i * p, access.get().get( i ).get(), EPS ); // test move p -= 2; access.move( -2, 0 ); for( int i = 0; i < N; i++ ) - assertEquals( i * p, access.get().get( i ).get(), EPS ); + assertEquals( accessMode, i * p, access.get().get( i ).get(), EPS ); } @Test public final void test2d() { - RealStackCompositeView rimg = new RealStackCompositeView<>( sources2 ); + final RealStackCompositeView rimg = new RealStackCompositeView<>( sources2 ); assertEquals( "ndims", 2, rimg.numDimensions() ); - RealRandomAccess> access = rimg.realRandomAccess(); + final RealRandomAccess> access = rimg.realRandomAccess(); for( int i = 0; i < N; i++ ) assertEquals( 0, access.get().get( i ).get(), EPS ); double x = 10; double y = 2; - double[] pa = new double[]{x,y}; + final double[] pa = new double[]{x,y}; // test setPosition access.setPosition( x, 0 ); From 672e2840004ba33974b2cf7f652d8abe4cda2581 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 20 Sep 2023 16:44:19 -0400 Subject: [PATCH 5/5] add convenience methods to Views for RealStackCompositeView --- src/main/java/net/imglib2/view/Views.java | 31 +++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/main/java/net/imglib2/view/Views.java b/src/main/java/net/imglib2/view/Views.java index 9b1ac8bc0..ff1e3aaa4 100644 --- a/src/main/java/net/imglib2/view/Views.java +++ b/src/main/java/net/imglib2/view/Views.java @@ -82,6 +82,7 @@ import net.imglib2.view.composite.InterleaveView; import net.imglib2.view.composite.NumericComposite; import net.imglib2.view.composite.RealComposite; +import net.imglib2.view.composite.RealStackCompositeView; /** * Create light-weight views into {@link RandomAccessible RandomAccessibles}. @@ -1137,6 +1138,36 @@ public static < T > RandomAccessibleInterval< T > stack( final StackAccessMode s return new StackView<>( Arrays.asList( hyperslices ), stackAccessMode ); } + /** + * Form a {@link RealRandomAccessible} of {@link Composite}s from n + * {@link RealRandomAccessible}s. + * + * @param stackAccessMode + * describes how a {@link RealRandomAccess} on the output + * {@link RealRandonAccessible} maps position changes into + * position changes of the underlying {@link RealRandomAccess}es. + * @param components + * a list of n-dimensional {@link RealRandomAccessible}s + * @return + */ + public static < T > RealRandomAccessible> realComposite( final StackAccessMode stackAccessMode, final RealRandomAccessible< T >... components) + { + return new RealStackCompositeView( components, stackAccessMode ); + } + + /** + * Form a {@link RealRandomAccessible} of {@link Composite}s from n + * {@link RealRandomAccessible}s. + * + * @param components + * a list of n-dimensional {@link RealRandomAccessible}s + * @return + */ + public static < T > RealRandomAccessible> realComposite( final RealRandomAccessible< T >... components) + { + return new RealStackCompositeView( components ); + } + /** * Positive shear transform of a RandomAccessible using * {@link ShearTransform}, i.e. c[ shearDimension ] = c[ shearDimension ] +