Class LoopBuilder<T>
LoopBuilder provides an easy way to write fast loops on
RandomAccessibleIntervals. For example, this is a loop that
calculates the sum of two images:
RandomAccessibleInterval<DoubleType> imageA = ...
RandomAccessibleInterval<DoubleType> imageB = ...
RandomAccessibleInterval<DoubleType> sum = ...
LoopBuilder.setImages(imageA, imageB, sum).forEachPixel(
(a, b, s) -> {
s.setReal(a.getRealDouble() + b.getRealDouble());
}
);
The RandomAccessibleIntervals imageA, imageB and
sum must have equal dimensions, but the bounds of there
Intervals can differ.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interfacestatic interfacestatic interfacestatic interfacestatic interface -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final Dimensionsprivate final RandomAccessibleInterval<?>[]private TaskExecutorprivate boolean -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate booleanallCursorsAreFast(List<IterableInterval<?>> iterableIntervals) private static booleanprivate voidprivate booleancursorIsFast(IterableInterval<?> image) private List<IterableInterval<?>> private List<IterableInterval<?>> LoopBuildermight use any iteration order to execute the loop.flatIterationOrder(boolean value) If false,LoopBuildermight use any iteration order to execute the loop.<R> List<R> forEachChunk(Function<LoopBuilder.Chunk<T>, R> action) This method is similar toforEachPixel(T)but more flexible when multi threading is used.voidforEachPixel(T action) private List<IterableInterval<?>> private static RandomAccess<?> initRandomAccess(RandomAccessibleInterval<?> image) private static voidBy defaultLoopBuilderruns the loop without multi-threading.multiThreaded(boolean multiThreaded) multiThreaded(TaskExecutor taskExecutor) By defaultLoopBuilderruns the loop without multi-threading.(package private) static <T,R> R runOnChunkUsingCursors(List<IterableInterval<?>> iterableIntervals, Function<LoopBuilder.Chunk<T>, R> chunkAction, long offset, long numElements) (package private) static <T,R> R runOnChunkUsingRandomAccesses(RandomAccessibleInterval[] images, Function<LoopBuilder.Chunk<T>, R> chunkAction, Interval subInterval) private <R> List<R> runUsingCursors(List<IterableInterval<?>> iterableIntervals, Function<LoopBuilder.Chunk<T>, R> chunkAction) private <R> List<R> runUsingRandomAccesses(Function<LoopBuilder.Chunk<T>, R> chunkAction) static <A> LoopBuilder<Consumer<A>> static <A,B> LoopBuilder <BiConsumer<A, B>> static <A,B, C> LoopBuilder <LoopBuilder.TriConsumer<A, B, C>> setImages(RandomAccessibleInterval<A> a, RandomAccessibleInterval<B> b, RandomAccessibleInterval<C> c) static <A,B, C, D> LoopBuilder <LoopBuilder.FourConsumer<A, B, C, D>> setImages(RandomAccessibleInterval<A> a, RandomAccessibleInterval<B> b, RandomAccessibleInterval<C> c, RandomAccessibleInterval<D> d) static <A,B, C, D, E>
LoopBuilder<LoopBuilder.FiveConsumer<A, B, C, D, E>> setImages(RandomAccessibleInterval<A> a, RandomAccessibleInterval<B> b, RandomAccessibleInterval<C> c, RandomAccessibleInterval<D> d, RandomAccessibleInterval<E> e) static <A,B, C, D, E, F>
LoopBuilder<LoopBuilder.SixConsumer<A, B, C, D, E, F>> setImages(RandomAccessibleInterval<A> a, RandomAccessibleInterval<B> b, RandomAccessibleInterval<C> c, RandomAccessibleInterval<D> d, RandomAccessibleInterval<E> e, RandomAccessibleInterval<F> f)
-
Field Details
-
dimensions
-
images
-
taskExecutor
-
useFlatIterationOrder
private boolean useFlatIterationOrder
-
-
Constructor Details
-
LoopBuilder
-
-
Method Details
-
setImages
- See Also:
-
setImages
public static <A,B> LoopBuilder<BiConsumer<A,B>> setImages(RandomAccessibleInterval<A> a, RandomAccessibleInterval<B> b) - See Also:
-
setImages
public static <A,B, LoopBuilder<LoopBuilder.TriConsumer<A,C> B, setImagesC>> (RandomAccessibleInterval<A> a, RandomAccessibleInterval<B> b, RandomAccessibleInterval<C> c) - See Also:
-
setImages
public static <A,B, LoopBuilder<LoopBuilder.FourConsumer<A,C, D> B, setImagesC, D>> (RandomAccessibleInterval<A> a, RandomAccessibleInterval<B> b, RandomAccessibleInterval<C> c, RandomAccessibleInterval<D> d) - See Also:
-
setImages
public static <A,B, LoopBuilder<LoopBuilder.FiveConsumer<A,C, D, E> B, setImagesC, D, E>> (RandomAccessibleInterval<A> a, RandomAccessibleInterval<B> b, RandomAccessibleInterval<C> c, RandomAccessibleInterval<D> d, RandomAccessibleInterval<E> e) - See Also:
-
setImages
public static <A,B, LoopBuilder<LoopBuilder.SixConsumer<A,C, D, E, F> B, setImagesC, D, E, F>> (RandomAccessibleInterval<A> a, RandomAccessibleInterval<B> b, RandomAccessibleInterval<C> c, RandomAccessibleInterval<D> d, RandomAccessibleInterval<E> e, RandomAccessibleInterval<F> f) - See Also:
-
forEachPixel
- See Also:
-
forEachChunk
This method is similar toforEachPixel(T)but more flexible when multi threading is used.The following example calculates the sum of the pixel values of an image. Multi threading is used to improve performance. The image is split into chunks. The chunks are processed in parallel by multiple threads. A variable of
IntTypeis used to calculate the sum, butIntTypeis not thread safe. It's therefore necessary to have one sum variable per chunk. This can be realized as follows:List<IntType> listOfSums = LoopBuilder.setImages( image ).multithreaded().forEachChunk( chunk -> { IntType sum = new IntType(); chunk.forEach( pixel -> sum.add( pixel ) ): return sum; } ); IntType totalSum = new IntType(); listOfSums.forEach( sum -> totalSum.add( sum ); return totalSum; -
allCursorsAreFast
-
cursorIsFast
-
multiThreaded
By defaultLoopBuilderruns the loop without multi-threading. Calling this method allowsLoopBuilderto use multi-threading for optimal performance.Usually, if this method is used,
LoopBuilderwill indeed use multi-threading. But that's not always the case. TheParallelizationclass can still be used to explicitly run the code single-threaded.Here is a small example for a copy method with enabled multi-threading.
This method usually runs multi-threaded. Which means good performance. But sometimes, a user might want to run the code single-threaded. There's no need to write a second single-threaded version of our copy method. Thepublic void copy( RandomAccessibleInterval<T> source, RandomAccessibleInterval<T> target) { LoopBuilder.setImages( source, target ).multiThreaded().forEachPixel( ( s, t ) -> t.set( s ) ); }Parallelizationclass allows the user to run the code single-threaded:
WARNING: You need to make sure that the action passed toParallelization.runSingleThreaded( () -> { copy( source, target ); } );forEachPixel(T)is thread safe.- See Also:
-
multiThreaded
-
multiThreaded
By defaultLoopBuilderruns the loop without multi-threading. Calling this method causes LoopBuilder to use the givenTaskExecutorfor multi-threading.WARNING: You need to make sure that your operation is thread safe.
-
flatIterationOrder
LoopBuildermight use any iteration order to execute the loop. Calling this method will causeLoopBuilderto use flat iteration order, when executing the loop.WARNING: Don't use multi-threading if you want to have flat iteration order.
-
flatIterationOrder
If false,LoopBuildermight use any iteration order to execute the loop.If true,
LoopBuilderwill use flat iteration order, and multi threading is disabled.WARNING: Don't use multi-threading if you want to have flat iteration order.
- See Also:
-
checkDimensions
private void checkDimensions() -
runUsingRandomAccesses
-
runOnChunkUsingRandomAccesses
static <T,R> R runOnChunkUsingRandomAccesses(RandomAccessibleInterval[] images, Function<LoopBuilder.Chunk<T>, R> chunkAction, Interval subInterval) -
initRandomAccess
-
imagesAsIterableIntervals
-
runUsingCursors
private <R> List<R> runUsingCursors(List<IterableInterval<?>> iterableIntervals, Function<LoopBuilder.Chunk<T>, R> chunkAction) -
runOnChunkUsingCursors
static <T,R> R runOnChunkUsingCursors(List<IterableInterval<?>> iterableIntervals, Function<LoopBuilder.Chunk<T>, R> chunkAction, long offset, long numElements) -
jumpFwd
-
equalIterationOrderIterableIntervals
-
flatIterableIntervals
-
allEqual
-