Skip to content

Commit 55b4d2f

Browse files
committed
ImgMath: changed IFunction interface eval method signature
to return the type at pixel rather than set it onto the temporary scrap type. Enables much improved performance for: * operations that don't alter the type, such as Max and Min. * images of the same type as the output image, for which the converter is not necessary. * the Compare class got fixed zero and one types, avoiding having to set one (true) or zero (for false) at every pixel. * the NumberSource class returns a fixed type, avoiding having to set it at every pixel.
1 parent 37ea55d commit 55b4d2f

File tree

23 files changed

+390
-221
lines changed

23 files changed

+390
-221
lines changed

src/main/java/net/imglib2/algorithm/math/Add.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,26 @@ private Add( final RealType< ? > scrap, final IFunction f1, final IFunction f2 )
2525
super( scrap, f1, f2 );
2626
}
2727

28-
@SuppressWarnings({ "rawtypes", "unchecked" })
28+
@SuppressWarnings({ "unchecked" })
2929
@Override
30-
public final void eval( final RealType output )
30+
public final RealType< ? > eval()
3131
{
32-
this.a.eval( output );
33-
this.b.eval( this.scrap );
34-
output.add( this.scrap );
32+
this.scrap.set( this.a.eval() );
33+
this.scrap.add( this.b.eval() );
34+
return this.scrap;
3535
}
3636

37-
@SuppressWarnings({ "rawtypes", "unchecked" })
37+
@SuppressWarnings({ "unchecked" })
3838
@Override
39-
public final void eval( final RealType output, final Localizable loc )
39+
public final RealType< ? > eval( final Localizable loc )
4040
{
41-
this.a.eval( output, loc );
42-
this.b.eval( this.scrap, loc );
43-
output.add( this.scrap );
41+
this.scrap.set( this.a.eval( loc ) );
42+
this.scrap.add( this.b.eval( loc ) );
43+
return this.scrap;
4444
}
4545

4646
@Override
47-
public Add reInit( final RealType<?> tmp, final Map<String, RealType<?>> bindings, final Converter<RealType<?>, RealType<?>> converter )
47+
public Add reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter<RealType<?>, RealType<?>> converter )
4848
{
4949
return new Add( tmp.copy(), this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ) );
5050
}

src/main/java/net/imglib2/algorithm/math/Compute.java

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import net.imglib2.algorithm.math.abstractions.IFunction;
1212
import net.imglib2.algorithm.math.abstractions.ITrinaryFunction;
1313
import net.imglib2.algorithm.math.abstractions.IUnaryFunction;
14+
import net.imglib2.algorithm.math.abstractions.ImgSource;
1415
import net.imglib2.algorithm.math.abstractions.Util;
1516
import net.imglib2.converter.Converter;
1617
import net.imglib2.type.numeric.RealType;
@@ -21,18 +22,35 @@ public class Compute
2122
private final IFunction operation;
2223
private final Converter< RealType< ? >, RealType< ? > > converter;
2324

25+
/**
26+
* Prepare the operation for computation with a default converter.
27+
* The converter will be used only if necessary, that is, only if
28+
* the input image type is not the same or a sublclass of the output
29+
* image type as specified in the {@link Compute#into(RandomAccessibleInterval)}.
30+
*
31+
* @param operation
32+
*/
2433
public Compute( final IFunction operation )
2534
{
26-
this( operation,
27-
new Converter< RealType< ? >, RealType< ? > >()
35+
this( operation, new Converter< RealType< ? >, RealType< ? > >()
2836
{
2937
@Override
30-
public final void convert( final RealType< ? > input, final RealType< ? > output) {
38+
public final void convert( final RealType<?> input, RealType<?> output)
39+
{
3140
output.setReal( input.getRealDouble() );
3241
}
3342
});
3443
}
3544

45+
/**
46+
* Prepare the operation for computation.
47+
* The converter will be used only if necessary, that is, only if
48+
* the input image type is not the same or a sublclass of the output
49+
* image type as specified in the {@link Compute#into(RandomAccessibleInterval)}.
50+
*
51+
* @param operation
52+
* @param converter
53+
*/
3654
public Compute(
3755
final IFunction operation,
3856
final Converter< RealType< ? >, RealType< ? > > converter
@@ -42,39 +60,41 @@ public Compute(
4260
this.converter = converter;
4361
}
4462

63+
@SuppressWarnings({ "unchecked", "rawtypes" })
4564
public < O extends RealType< O > > RandomAccessibleInterval< O > into( final RandomAccessibleInterval< O > target )
4665
{
4766
// Recursive copy: initializes interval iterators and sets temporary computation holder
4867
final IFunction f = this.operation.reInit(
4968
target.randomAccess().get().createVariable(),
5069
new HashMap< String, RealType< ? > >(),
51-
converter );
70+
this.converter );
5271

5372
final boolean compatible_iteration_order = this.setup( f );
5473

5574
// Check compatible iteration order and dimensions
5675
if ( compatible_iteration_order )
5776
{
5877
// Evaluate function for every pixel
59-
for ( final O output : Views.iterable( target ) )
60-
f.eval( output );
78+
for ( final RealType output : Views.iterable( target ) )
79+
output.set( f.eval() );
6180
}
6281
else
6382
{
6483
// Incompatible iteration order
65-
final Cursor< O > cursor = Views.iterable( target ).cursor();
84+
final Cursor< RealType > cursor = ( Cursor< RealType > )Views.iterable( target ).cursor();
6685

6786
while ( cursor.hasNext() )
6887
{
6988
cursor.fwd();
70-
f.eval( cursor.get(), cursor );
89+
final RealType output = cursor.get();
90+
output.set( f.eval( cursor ) );
7191
}
7292
}
7393

7494
return target;
7595
}
7696

77-
@SuppressWarnings({ "rawtypes", "unchecked" })
97+
@SuppressWarnings({ "rawtypes" })
7898
private boolean setup( final IFunction f )
7999
{
80100
final LinkedList< IFunction > ops = new LinkedList<>();
@@ -101,10 +121,9 @@ private boolean setup( final IFunction f )
101121
cp.put( op, parent );
102122
parent = op;
103123

104-
if ( op instanceof IterableImgSource )
124+
if ( op instanceof ImgSource )
105125
{
106-
final IterableImgSource iis = ( IterableImgSource )op;
107-
images.addLast( iis.rai );
126+
images.addLast( ( ( ImgSource )op ).getRandomAccessibleInterval() );
108127
}
109128
else if ( op instanceof IUnaryFunction )
110129
{

src/main/java/net/imglib2/algorithm/math/Div.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,22 @@ private Div( final RealType< ? > scrap, final IFunction f1, final IFunction f2 )
2626
super( scrap, f1, f2 );
2727
}
2828

29-
@SuppressWarnings({ "rawtypes", "unchecked" })
29+
@SuppressWarnings({ "unchecked" })
3030
@Override
31-
public final void eval( final RealType output )
31+
public final RealType< ? > eval()
3232
{
33-
this.a.eval( output );
34-
this.b.eval( this.scrap );
35-
output.div( this.scrap );
33+
this.scrap.set( this.a.eval() );
34+
this.scrap.div( this.b.eval() );
35+
return this.scrap;
3636
}
3737

38-
@SuppressWarnings({ "rawtypes", "unchecked" })
38+
@SuppressWarnings({ "unchecked" })
3939
@Override
40-
public final void eval( final RealType output, final Localizable loc)
40+
public final RealType< ? > eval( final Localizable loc )
4141
{
42-
this.a.eval( output, loc );
43-
this.b.eval( this.scrap, loc );
44-
output.div( this.scrap );
42+
this.scrap.set( this.a.eval( loc ) );
43+
this.scrap.div( this.b.eval( loc ) );
44+
return this.scrap;
4545
}
4646

4747
@Override

src/main/java/net/imglib2/algorithm/math/Equal.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public final boolean compare( final RealType t1, final RealType t2 )
2626
}
2727

2828
@Override
29-
public Equal reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter< RealType< ? >, RealType< ? > > converter )
29+
public Equal reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter<RealType<?>, RealType<?>> converter )
3030
{
3131
return new Equal( tmp.copy(), this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ) );
3232
}

src/main/java/net/imglib2/algorithm/math/If.java

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import net.imglib2.algorithm.math.abstractions.ATrinaryFunction;
77
import net.imglib2.algorithm.math.abstractions.Compare;
88
import net.imglib2.algorithm.math.abstractions.IFunction;
9+
import net.imglib2.algorithm.math.optimizations.IfBoolean;
910
import net.imglib2.converter.Converter;
1011
import net.imglib2.type.numeric.RealType;
1112

@@ -22,37 +23,27 @@ protected If( final RealType< ? > scrap, final IFunction f1, final IFunction f2,
2223
}
2324

2425
@Override
25-
public void eval( final RealType< ? > output )
26+
public RealType< ? > eval()
2627
{
27-
this.a.eval( this.scrap );
28-
if ( 0 != this.scrap.getRealFloat() )
29-
{
28+
return 0 != this.a.eval().getRealFloat() ?
3029
// Then
31-
this.b.eval( output );
32-
} else
33-
{
30+
this.b.eval()
3431
// Else
35-
this.c.eval( output );
36-
}
32+
: this.c.eval();
3733
}
3834

3935
@Override
40-
public void eval( final RealType< ? > output, final Localizable loc )
36+
public RealType< ? > eval( final Localizable loc )
4137
{
42-
this.a.eval( this.scrap, loc );
43-
if ( 0 != this.scrap.getRealFloat() )
44-
{
45-
// Then
46-
this.b.eval( output, loc );
47-
} else
48-
{
49-
// Else
50-
this.c.eval( output, loc );
51-
}
38+
return 0 != this.a.eval().getRealFloat() ?
39+
// Then
40+
this.b.eval()
41+
// Else
42+
: this.c.eval();
5243
}
5344

5445
@Override
55-
public If reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter< RealType< ? >, RealType< ? > > converter )
46+
public If reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter<RealType<?>, RealType<?>> converter )
5647
{
5748
// Optimization: reInit as IfBoolean if the first argument is a Compare.
5849
// Avoids having to set the output to 1 (true) or 0 (false),

src/main/java/net/imglib2/algorithm/math/IterableImgSource.java

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,46 +7,63 @@
77
import net.imglib2.RandomAccess;
88
import net.imglib2.RandomAccessibleInterval;
99
import net.imglib2.algorithm.math.abstractions.IFunction;
10+
import net.imglib2.algorithm.math.abstractions.ImgSource;
11+
import net.imglib2.algorithm.math.optimizations.IterableImgSourceDirect;
1012
import net.imglib2.converter.Converter;
13+
import net.imglib2.type.Type;
1114
import net.imglib2.type.numeric.RealType;
1215
import net.imglib2.view.Views;
1316

14-
public class IterableImgSource< I extends RealType< I > > implements IFunction
17+
public class IterableImgSource< I extends RealType< I > > implements IFunction, ImgSource< I >
1518
{
16-
final RandomAccessibleInterval< I > rai;
19+
private final RandomAccessibleInterval< I > rai;
1720
private final Iterator< I > it;
1821
private final RandomAccess< I > ra;
1922
private Converter< RealType< ? >, RealType< ? > > converter;
23+
private final RealType< ? > scrap;
2024

2125
public IterableImgSource( final RandomAccessibleInterval< I > rai )
2226
{
23-
this( null, rai );
27+
this( null, null, rai );
2428
}
2529

26-
private IterableImgSource( final Converter< RealType< ? >, RealType< ? > > converter, final RandomAccessibleInterval< I > rai )
30+
private IterableImgSource( final RealType< ? > scrap, final Converter< RealType< ? >, RealType< ? > > converter, final RandomAccessibleInterval< I > rai )
2731
{
2832
this.rai = rai;
2933
this.it = Views.iterable( rai ).iterator();
3034
this.ra = rai.randomAccess();
3135
this.converter = converter;
36+
this.scrap = scrap;
3237
}
3338

3439
@Override
35-
public void eval( final RealType< ? > output )
40+
public RealType< ? > eval()
3641
{
37-
this.converter.convert( this.it.next(), output );
42+
this.converter.convert( this.it.next(), this.scrap );
43+
return this.scrap;
3844
}
3945

4046
@Override
41-
public void eval( final RealType< ? > output, final Localizable loc )
47+
public RealType< ? > eval( final Localizable loc )
4248
{
4349
this.ra.setPosition( loc );
44-
this.converter.convert( this.ra.get(), output );
50+
this.converter.convert( this.ra.get(), this.scrap );
51+
return this.scrap;
4552
}
4653

4754
@Override
48-
public IterableImgSource< I > reInit( final RealType<?> tmp, final Map<String, RealType<?>> bindings, final Converter<RealType<?>, RealType<?>> converter )
55+
public IFunction reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter< RealType< ? >, RealType< ? > > converter )
4956
{
50-
return new IterableImgSource< I >( converter, this.rai );
57+
// Optimization: if input image type is the same or a subclass of
58+
// the output image time (represented here by tmp), then avoid the converter.
59+
if ( tmp.getClass().isAssignableFrom( this.rai.randomAccess().get().getClass() ) )
60+
return new IterableImgSourceDirect< I >( this.rai );
61+
return new IterableImgSource< I >( tmp.copy(), converter, this.rai );
62+
}
63+
64+
@Override
65+
public RandomAccessibleInterval< I > getRandomAccessibleInterval()
66+
{
67+
return this.rai;
5168
}
5269
}

src/main/java/net/imglib2/algorithm/math/Let.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ public final class Let implements IFunction, IBinaryFunction
1515
private final String varName;
1616
private final IFunction varValue;
1717
private final IFunction body;
18-
private final RealType< ? > scrap;
18+
@SuppressWarnings("rawtypes")
19+
private final RealType scrap;
1920

2021
public Let( final String varName, final Object varValue, final Object body )
2122
{
@@ -68,24 +69,28 @@ private Let( final RealType< ? > scrap, final String varName, final IFunction va
6869
this.body = body;
6970
}
7071

72+
@SuppressWarnings("unchecked")
7173
@Override
72-
public void eval( final RealType< ? > output )
74+
public final RealType< ? > eval()
7375
{
7476
// Evaluate the varValue into this.scrap, which is shared with all Vars of varName
75-
this.varValue.eval( this.scrap );
77+
this.scrap.set( this.varValue.eval() );
7678
// The body may contain Vars that will use this.varValue via this.scrap
77-
this.body.eval( output );
79+
return this.body.eval();
7880
}
7981

82+
@SuppressWarnings("unchecked")
8083
@Override
81-
public void eval( final RealType< ? > output, final Localizable loc)
84+
public final RealType< ? > eval( final Localizable loc)
8285
{
83-
this.varValue.eval( this.scrap, loc );
84-
this.body.eval( output, loc );
86+
// Evaluate the varValue into this.scrap, which is shared with all Vars of varName
87+
this.scrap.set( this.varValue.eval( loc ) );
88+
// The body may contain Vars that will use this.varValue via this.scrap
89+
return this.body.eval( loc );
8590
}
8691

8792
@Override
88-
public Let reInit( final RealType<?> tmp, final Map<String, RealType<?>> bindings, final Converter<RealType<?>, RealType<?>> converter )
93+
public Let reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter< RealType< ? >, RealType< ? > > converter )
8994
{
9095
final RealType< ? > scrap = tmp.copy();
9196
final Map< String, RealType< ? > > rebind = new HashMap<>( bindings );

0 commit comments

Comments
 (0)