Skip to content

Commit

Permalink
WIP localizing stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
tpietzsch committed Sep 30, 2023
1 parent 0b4c6b9 commit 60a56af
Show file tree
Hide file tree
Showing 5 changed files with 798 additions and 0 deletions.
165 changes: 165 additions & 0 deletions src/main/java/net/imglib2/stream/Streams.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package net.imglib2.stream;

import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import net.imglib2.IterableInterval;
import net.imglib2.IterableRealInterval;
import net.imglib2.LocalizableSampler;
import net.imglib2.RealLocalizableSampler;

public class Streams
{
public static < T > Stream< RealLocalizableSampler< T > > localizable( IterableRealInterval< T > interval )
{
return StreamSupport.stream( new RealLocalizableSamplerWrapper<>( interval.spliterator() ), false );
}

public static < T > Stream< LocalizableSampler< T > > localizable( IterableInterval< T > interval )
{
return StreamSupport.stream( new LocalizableSamplerWrapper<>( interval.spliterator() ), false );
}

static class RealLocalizableSamplerWrapper< T > implements Spliterator< RealLocalizableSampler< T > >, RealLocalizableSampler< T >
{
private final RealLocalizableSpliterator< T > delegate;

RealLocalizableSamplerWrapper( final RealLocalizableSpliterator< T > delegate )
{
this.delegate = delegate;
}

@Override
public double getDoublePosition( final int d )
{
return delegate.getDoublePosition( d );
}

@Override
public int numDimensions()
{
return delegate.numDimensions();
}

@Override
public T get()
{
return delegate.get();
}

@Override
public RealLocalizableSamplerWrapper< T > copy()
{
return new RealLocalizableSamplerWrapper<>( delegate.copy() );
}

@Override
public void forEachRemaining( final Consumer< ? super RealLocalizableSampler< T > > action )
{
delegate.forEachRemaining( () -> action.accept( this ) );
}

@Override
public boolean tryAdvance( final Consumer< ? super RealLocalizableSampler< T > > action )
{
if ( delegate.tryAdvance() )
{
action.accept( this );
return true;
}
else
return false;
}

@Override
public Spliterator< RealLocalizableSampler< T > > trySplit()
{
final RealLocalizableSpliterator< T > prefix = delegate.trySplit();
return prefix == null ? null : new RealLocalizableSamplerWrapper<>( prefix );
}

@Override
public long estimateSize()
{
return delegate.estimateSize();
}

@Override
public int characteristics()
{
return delegate.characteristics();
}
}

static class LocalizableSamplerWrapper< T > implements Spliterator< LocalizableSampler< T > >, LocalizableSampler< T >
{
private final LocalizableSpliterator< T > delegate;

LocalizableSamplerWrapper( final LocalizableSpliterator< T > delegate )
{
this.delegate = delegate;
}

@Override
public long getLongPosition( final int d )
{
return delegate.getLongPosition( d );
}

@Override
public int numDimensions()
{
return delegate.numDimensions();
}

@Override
public T get()
{
return delegate.get();
}

@Override
public LocalizableSamplerWrapper< T > copy()
{
return new LocalizableSamplerWrapper<>( delegate.copy() );
}

@Override
public void forEachRemaining( final Consumer< ? super LocalizableSampler< T > > action )
{
delegate.forEachRemaining( () -> action.accept( this ) );
}

@Override
public boolean tryAdvance( final Consumer< ? super LocalizableSampler< T > > action )
{
if ( delegate.tryAdvance() )
{
action.accept( this );
return true;
}
else
return false;
}

@Override
public Spliterator< LocalizableSampler< T > > trySplit()
{
final LocalizableSpliterator< T > prefix = delegate.trySplit();
return prefix == null ? null : new LocalizableSamplerWrapper<>( prefix );
}

@Override
public long estimateSize()
{
return delegate.estimateSize();
}

@Override
public int characteristics()
{
return delegate.characteristics();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package net.imglib2.stream;

import java.util.Comparator;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import net.imglib2.Localizable;
import net.imglib2.LocalizableSampler;
import net.imglib2.img.Img;
import net.imglib2.img.array.ArrayImgs;
import net.imglib2.type.numeric.integer.IntType;
import net.imglib2.util.Util;

/**
* TODO javadoc
*/
public class CursorSamplerSpliteratorPlayground
{
public static void main( String[] args )
{
Img< IntType > img = ArrayImgs.ints( 5, 5 );
Streams.localizable( img ).forEach( s ->
s.get().set( s.getIntPosition( 0 ) ) );

Streams.localizable( img ).forEach( adapt(
( pos, t ) -> t.set( ( int ) ( pos.x() + pos.y() ) )
) );

img.getAt( 2, 2 ).set( 9 );

for ( int y = 0; y < 5; ++y )
{
for ( int x = 0; x < 5; ++x )
{
System.out.print( img.getAt( x, y ).get() + ", " );
}
System.out.println();
}

final Optional< LocalizableSampler< IntType > > max2 = Streams.localizable( img )
.filter( c -> c.getIntPosition( 0) % 2 == 1 )
.map( LocalizableSampler::copy )
.max( Comparator.comparingInt( c -> c.get().get() ) );
System.out.println( "max at " + Util.printCoordinates( max2.get() ) );


BinaryOperator< LocalizableSampler< IntType > > max_accumulate = ( result, element ) -> {
if ( result == null || result.get().compareTo( element.get() ) <= 0 )
return element.copy();
else
return result;
};

final Optional< LocalizableSampler< IntType > > reduce = Streams.localizable( img )
.parallel()
.filter( c -> c.getIntPosition( 0) % 2 == 1 )
.reduce( max_accumulate );
System.out.println( "max at " + Util.printCoordinates( reduce.get() ) );

}





public static class Pos
{
Localizable l;

Pos of( Localizable l )
{
this.l = l;
return this;
}

public long x()
{
return l.getLongPosition( 0 );
}

public long y()
{
return l.getLongPosition( 1 );
}
}

static < T > Consumer< LocalizableSampler< T > > adapt( BiConsumer< Pos, T > consumer )
{
final Pos pos = new Pos();
return tCursor -> {
consumer.accept( pos.of( tCursor ), tCursor.get() );
};
}
}
119 changes: 119 additions & 0 deletions src/test/java/net/imglib2/stream/LocalizingBenchmark.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package net.imglib2.stream;

import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import net.imglib2.Cursor;
import net.imglib2.img.Img;
import net.imglib2.img.cell.CellImgFactory;
import net.imglib2.type.numeric.integer.IntType;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

@State( Scope.Benchmark )
@Warmup( iterations = 5, time = 100, timeUnit = TimeUnit.MILLISECONDS )
@Measurement( iterations = 10, time = 100, timeUnit = TimeUnit.MILLISECONDS )
@BenchmarkMode( Mode.AverageTime )
@OutputTimeUnit( TimeUnit.MILLISECONDS )
@Fork( 1 )
public class LocalizingBenchmark
{
private final Img< IntType > img;

public LocalizingBenchmark()
{
final long[] dimensions = { 2000, 200, 10 };
// img = ArrayImgs.ints( dimensions );
// img = PlanarImgs.ints( dimensions );
img = new CellImgFactory<>( new IntType(), 64 ).create( dimensions );
Random random = new Random( 1L );
img.forEach( t -> t.set( random.nextInt( 1000 ) ) );
}

@Benchmark
public long benchmarkStream()
{
long sum = Streams.localizable( img )
.mapToLong( s -> s.get().get()
+ s.getIntPosition( 0 )
// + s.getIntPosition( 1 )
// + s.getIntPosition( 2 )
).sum();
return sum;
}

@Benchmark
public long benchmarkParallelStream()
{
long sum = Streams.localizable( img )
.parallel()
.mapToLong( s -> s.get().get()
+ s.getIntPosition( 0 )
// + s.getIntPosition( 1 )
// + s.getIntPosition( 2 )
).sum();
return sum;
}

static class Sum implements Consumer< Cursor< IntType > >
{
private long sum;

@Override
public void accept( final Cursor< IntType > s )
{
sum += s.get().get()
+ s.getIntPosition( 0 );
// + s.getIntPosition( 1 )
// + s.getIntPosition( 2 );
}

public long get()
{
return sum;
}
}

@Benchmark
public long benchmarkCursor()
{
final Sum sum = new Sum();
final Cursor< IntType > it = img.cursor();
while ( it.hasNext() )
{
it.fwd();
sum.accept( it );
}
return sum.get();
}

@Benchmark
public long benchmarkLocalizingCursor()
{
final Sum sum = new Sum();
final Cursor< IntType > it = img.localizingCursor();
while ( it.hasNext() )
{
it.fwd();
sum.accept( it );
}
return sum.get();
}

public static void main( String... args ) throws RunnerException
{
Options options = new OptionsBuilder().include( LocalizingBenchmark.class.getSimpleName() ).build();
new Runner( options ).run();
}
}
Loading

0 comments on commit 60a56af

Please sign in to comment.