Skip to content

Commit df947d0

Browse files
committedNov 20, 2024·
Revise blocks API
* Instead of delegating execution to BlockProcessor, UnaryBlockOperator takes care of chaining operations now: The new compute(BlockSupplier source, Interval, Object dest) method handles source interval computation, getting source data, and computing result in one go, instead of the sequential BlockProcessor API. This is much nicer. It enables pass-through operators (Convert.Identity or logging for example). It should also be easier now to extend the API to keep data on the GPU for sequences of GPU operators. * The copy/compute API all operate on Interval now. Other signatures have been removed for simplicity. With the new BlockInterval class from imglib2 core, unnecessarily converting between int[] and long[] is usually avoided.
1 parent 77fa2c6 commit df947d0

22 files changed

+476
-749
lines changed
 

‎src/main/java/net/imglib2/algorithm/blocks/AbstractBlockProcessor.java

+18-32
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,8 @@
3535

3636
import static net.imglib2.util.Util.safeInt;
3737

38-
import java.util.Arrays;
39-
4038
import net.imglib2.Interval;
41-
import net.imglib2.algorithm.blocks.util.BlockProcessorSourceInterval;
39+
import net.imglib2.blocks.BlockInterval;
4240
import net.imglib2.blocks.TempArray;
4341
import net.imglib2.type.PrimitiveType;
4442
import net.imglib2.util.Intervals;
@@ -51,12 +49,12 @@
5149
* adaptable number of dimensions (such as converters), see {@link
5250
* AbstractDimensionlessBlockProcessor}.
5351
* <p>
54-
* {@link BlockProcessor#getSourcePos() getSourcePos()}, {@link
55-
* BlockProcessor#getSourceSize() getSourceSize()}, and {@link
56-
* BlockProcessor#getSourceInterval() getSourceInterval()} are implemented to
57-
* return the {@code protected} fields {@code long[] sourcePos} and {@code
58-
* }int[] sourceSize}. The {@code }protected} method {@code }int sourceLength()}
59-
* can be used to get the number of elements in the source interval.
52+
* A {@link BlockInterval} of the desired number of dimensions is exposed
53+
* through {@link #getSourceInterval()}. (For convenience, {@code min} and
54+
* {@code dimensions} of the interval are also exposed through the {@code
55+
* protected} fields {@link #sourcePos} and {@link #sourceSize}.) The {@code
56+
* protected} method {@link #sourceLength()} returns the number of elements in
57+
* the source interval.
6058
* <p>
6159
* {@link BlockProcessor#getSourceBuffer() getSourceBuffer()} is implemented
6260
* according to the {@code sourcePrimitiveType} specified at construction.
@@ -70,53 +68,41 @@ public abstract class AbstractBlockProcessor< I, O > implements BlockProcessor<
7068
{
7169
private final TempArray< I > tempArray;
7270

71+
private final BlockInterval sourceInterval;
72+
7373
protected final long[] sourcePos;
7474

7575
protected final int[] sourceSize;
7676

77-
private final BlockProcessorSourceInterval sourceInterval = new BlockProcessorSourceInterval( this );
78-
7977
protected AbstractBlockProcessor( final PrimitiveType sourcePrimitiveType, final int numSourceDimensions )
8078
{
8179
tempArray = TempArray.forPrimitiveType( sourcePrimitiveType );
82-
sourcePos = new long[ numSourceDimensions ];
83-
sourceSize = new int[ numSourceDimensions ];
80+
sourceInterval = new BlockInterval( numSourceDimensions );
81+
sourcePos = sourceInterval.min();
82+
sourceSize = sourceInterval.size();
8483
}
8584

8685
protected AbstractBlockProcessor( final AbstractBlockProcessor< I, O > proc )
8786
{
8887
tempArray = proc.tempArray.newInstance();
89-
final int numSourceDimensions = proc.sourcePos.length;
90-
sourcePos = new long[ numSourceDimensions ];
91-
sourceSize = new int[ numSourceDimensions ];
88+
sourceInterval = new BlockInterval( proc.sourceInterval.numDimensions() );
89+
sourcePos = sourceInterval.min();
90+
sourceSize = sourceInterval.size();
9291
}
9392

9493
protected int sourceLength()
9594
{
96-
return safeInt( Intervals.numElements( sourceSize ) );
95+
return safeInt( Intervals.numElements( sourceInterval ) );
9796
}
9897

9998
@Override
10099
public void setTargetInterval( final Interval interval )
101100
{
102-
interval.min( sourcePos );
103-
Arrays.setAll( sourceSize, d -> safeInt( interval.dimension( d ) ) );
104-
}
105-
106-
@Override
107-
public long[] getSourcePos()
108-
{
109-
return sourcePos;
110-
}
111-
112-
@Override
113-
public int[] getSourceSize()
114-
{
115-
return sourceSize;
101+
sourceInterval.setFrom( interval );
116102
}
117103

118104
@Override
119-
public Interval getSourceInterval()
105+
public BlockInterval getSourceInterval()
120106
{
121107
return sourceInterval;
122108
}

‎src/main/java/net/imglib2/algorithm/blocks/AbstractBlockSupplier.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
import java.util.function.Supplier;
3737

38+
import net.imglib2.Interval;
3839
import net.imglib2.type.NativeType;
3940
import net.imglib2.util.CloseableThreadLocal;
4041

@@ -68,9 +69,9 @@ public int numDimensions()
6869
}
6970

7071
@Override
71-
public void copy( final long[] srcPos, final Object dest, final int[] size )
72+
public void copy( final Interval interval, final Object dest )
7273
{
73-
threadSafeSupplier.get().copy( srcPos, dest, size );
74+
threadSafeSupplier.get().copy( interval, dest );
7475
}
7576

7677
@Override

‎src/main/java/net/imglib2/algorithm/blocks/AbstractDimensionlessBlockProcessor.java

+16-38
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,8 @@
3535

3636
import static net.imglib2.util.Util.safeInt;
3737

38-
import java.util.Arrays;
39-
4038
import net.imglib2.Interval;
41-
import net.imglib2.algorithm.blocks.util.BlockProcessorSourceInterval;
39+
import net.imglib2.blocks.BlockInterval;
4240
import net.imglib2.blocks.TempArray;
4341
import net.imglib2.type.PrimitiveType;
4442
import net.imglib2.util.Intervals;
@@ -50,12 +48,10 @@
5048
* number of dimensions (such as converters). For {@code BlockProcessor} with a
5149
* fixed number of source dimensions, see {@link AbstractBlockProcessor}.
5250
* <p>
53-
* {@link BlockProcessor#getSourcePos() getSourcePos()}, {@link
54-
* BlockProcessor#getSourceSize() getSourceSize()}, and {@link
55-
* BlockProcessor#getSourceInterval() getSourceInterval()} are implemented to
56-
* return the {@code protected} fields {@code long[] sourcePos} and {@code
57-
* }int[] sourceSize}. The {@code }protected} method {@code }int sourceLength()}
58-
* can be used to get the number of elements in the source interval.
51+
* A {@link BlockInterval} is exposed through {@link #getSourceInterval()}
52+
* (after {@link #setTargetInterval} has been called). The {@code protected}
53+
* method {@link #sourceLength()} returns the number of elements in the source
54+
* interval.
5955
* <p>
6056
* {@link BlockProcessor#getSourceBuffer() getSourceBuffer()} is implemented
6157
* according to the {@code sourcePrimitiveType} specified at construction.
@@ -69,11 +65,7 @@ public abstract class AbstractDimensionlessBlockProcessor< I, O > implements Blo
6965
{
7066
private final TempArray< I > tempArray;
7167

72-
protected long[] sourcePos;
73-
74-
protected int[] sourceSize;
75-
76-
private final BlockProcessorSourceInterval sourceInterval = new BlockProcessorSourceInterval( this );
68+
protected BlockInterval sourceInterval;
7769

7870
protected AbstractDimensionlessBlockProcessor( final PrimitiveType sourcePrimitiveType )
7971
{
@@ -88,50 +80,36 @@ protected AbstractDimensionlessBlockProcessor( final AbstractDimensionlessBlockP
8880
@Override
8981
public void setTargetInterval( final Interval interval )
9082
{
91-
updateNumSourceDimsensions( interval.numDimensions() );
92-
interval.min( sourcePos );
93-
Arrays.setAll( sourceSize, d -> safeInt( interval.dimension( d ) ) );
83+
updateNumSourceDimensions( interval.numDimensions() );
84+
sourceInterval.setFrom( interval );
9485
}
9586

9687
/**
97-
* Re-allocates {@code sourcePos} and {@code sourceSize} arrays if they do
98-
* not already exist and have {@code length==n}.
88+
* Re-allocates {@code sourceInterval} if it does not already exist and
89+
* match {@code numDimensions()==n}.
9990
*
10091
* @param n
10192
* new number of source dimensions
10293
*
103-
* @return {@code true} if {@code sourcePos} and {@code sourceSize} arrays were re-allocated
94+
* @return {@code true} if {@code sourceInterval} was re-allocated
10495
*/
105-
protected boolean updateNumSourceDimsensions( final int n )
96+
protected boolean updateNumSourceDimensions( final int n )
10697
{
107-
if ( sourcePos == null || sourcePos.length != n )
98+
if ( sourceInterval == null || sourceInterval.numDimensions() != n )
10899
{
109-
sourcePos = new long[ n ];
110-
sourceSize = new int[ n ];
100+
sourceInterval = new BlockInterval( n );
111101
return true;
112102
}
113103
return false;
114104
}
115105

116106
protected int sourceLength()
117107
{
118-
return safeInt( Intervals.numElements( sourceSize ) );
119-
}
120-
121-
@Override
122-
public long[] getSourcePos()
123-
{
124-
return sourcePos;
125-
}
126-
127-
@Override
128-
public int[] getSourceSize()
129-
{
130-
return sourceSize;
108+
return safeInt( Intervals.numElements( sourceInterval ) );
131109
}
132110

133111
@Override
134-
public Interval getSourceInterval()
112+
public BlockInterval getSourceInterval()
135113
{
136114
return sourceInterval;
137115
}

‎src/main/java/net/imglib2/algorithm/blocks/NoOpUnaryBlockOperator.java renamed to ‎src/main/java/net/imglib2/algorithm/blocks/AbstractUnaryBlockOperator.java

+27-31
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
* %%
1212
* Redistribution and use in source and binary forms, with or without
1313
* modification, are permitted provided that the following conditions are met:
14-
*
14+
*
1515
* 1. Redistributions of source code must retain the above copyright notice,
1616
* this list of conditions and the following disclaimer.
1717
* 2. Redistributions in binary form must reproduce the above copyright notice,
1818
* this list of conditions and the following disclaimer in the documentation
1919
* and/or other materials provided with the distribution.
20-
*
20+
*
2121
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2222
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2323
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -33,65 +33,61 @@
3333
*/
3434
package net.imglib2.algorithm.blocks;
3535

36-
import java.util.function.Supplier;
37-
3836
import net.imglib2.type.NativeType;
39-
import net.imglib2.util.Cast;
40-
import net.imglib2.util.CloseableThreadLocal;
4137

4238
/**
43-
* Does nothing. This should be eliminated when concatenating through
44-
* {@link UnaryBlockOperator#andThen(UnaryBlockOperator)} or {@link BlockSupplier#andThen(UnaryBlockOperator)}.
39+
* Abstract implementation of {@link UnaryBlockOperator}.
40+
* Takes care of source/target type/dimensionality boilerplate.
4541
*
42+
* @param <S>
43+
* source type
4644
* @param <T>
45+
* target type
4746
*/
48-
public class NoOpUnaryBlockOperator< S extends NativeType< S >, T extends NativeType< T > > implements UnaryBlockOperator< S, T >
47+
public abstract class AbstractUnaryBlockOperator< S extends NativeType< S >, T extends NativeType< T > > implements UnaryBlockOperator< S, T >
4948
{
50-
@Override
51-
public < I, O > BlockProcessor< I, O > blockProcessor()
49+
private final S sourceType;
50+
private final T targetType;
51+
private final int numSourceDimensions;
52+
private final int numTargetDimensions;
53+
54+
protected AbstractUnaryBlockOperator( S sourceType, T targetType, int numSourceDimensions, int numTargetDimensions )
5255
{
53-
throw new UnsupportedOperationException();
56+
this.sourceType = sourceType;
57+
this.targetType = targetType;
58+
this.numSourceDimensions = numSourceDimensions;
59+
this.numTargetDimensions = numTargetDimensions;
5460
}
5561

56-
@Override
57-
public < U extends NativeType< U > > UnaryBlockOperator< S, U > andThen( UnaryBlockOperator< T, U > op )
62+
protected AbstractUnaryBlockOperator( AbstractUnaryBlockOperator< S, T > op )
5863
{
59-
return Cast.unchecked( op );
64+
this.sourceType = op.sourceType;
65+
this.targetType = op.targetType;
66+
this.numSourceDimensions = op.numSourceDimensions;
67+
this.numTargetDimensions = op.numTargetDimensions;
6068
}
6169

6270
@Override
6371
public S getSourceType()
6472
{
65-
throw new UnsupportedOperationException();
73+
return sourceType;
6674
}
6775

6876
@Override
6977
public T getTargetType()
7078
{
71-
throw new UnsupportedOperationException();
79+
return targetType;
7280
}
7381

7482
@Override
7583
public int numSourceDimensions()
7684
{
77-
return 0;
85+
return numSourceDimensions;
7886
}
7987

8088
@Override
8189
public int numTargetDimensions()
8290
{
83-
return 0;
84-
}
85-
86-
@Override
87-
public UnaryBlockOperator< S, T > independentCopy()
88-
{
89-
return this;
90-
}
91-
92-
@Override
93-
public UnaryBlockOperator< S, T > threadSafe()
94-
{
95-
return this;
91+
return numTargetDimensions;
9692
}
9793
}

0 commit comments

Comments
 (0)