Skip to content

Commit 8ad33ef

Browse files
committed
ImgMath: solve issue with IF statement.
When an IF statement contained images within its THEN and ELSE, choosing one did not advance the iterators of the other. To ensure that image iterators are always advanced, redeclare the images as Var that read from a Let that has the IF statement in its body.
1 parent 55b4d2f commit 8ad33ef

File tree

22 files changed

+198
-49
lines changed

22 files changed

+198
-49
lines changed

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import net.imglib2.Localizable;
66
import net.imglib2.algorithm.math.abstractions.ABinaryFunction;
77
import net.imglib2.algorithm.math.abstractions.IFunction;
8+
import net.imglib2.algorithm.math.abstractions.IVar;
89
import net.imglib2.converter.Converter;
910
import net.imglib2.type.numeric.RealType;
1011

@@ -44,8 +45,12 @@ private Add( final RealType< ? > scrap, final IFunction f1, final IFunction f2 )
4445
}
4546

4647
@Override
47-
public Add reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter<RealType<?>, RealType<?>> converter )
48+
public Add reInit(
49+
final RealType< ? > tmp,
50+
final Map< String, RealType< ? > > bindings,
51+
final Converter<RealType<?>, RealType<?>> converter,
52+
Map< IVar, IFunction > imgSources )
4853
{
49-
return new Add( tmp.copy(), this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ) );
54+
return new Add( tmp.copy(), this.a.reInit( tmp, bindings, converter, imgSources ), this.b.reInit( tmp, bindings, converter, imgSources ) );
5055
}
5156
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public < O extends RealType< O > > RandomAccessibleInterval< O > into( final Ran
6767
final IFunction f = this.operation.reInit(
6868
target.randomAccess().get().createVariable(),
6969
new HashMap< String, RealType< ? > >(),
70-
this.converter );
70+
this.converter, null );
7171

7272
final boolean compatible_iteration_order = this.setup( f );
7373

@@ -183,6 +183,8 @@ else if ( op instanceof Var )
183183
throw new RuntimeException( msg );
184184
}
185185

186+
// Check ImgSource: if they are downstream of an If statement, they should be declared in a Let before that
187+
186188
return Util.compatibleIterationOrder( images );
187189
}
188190
}

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import net.imglib2.Localizable;
66
import net.imglib2.algorithm.math.abstractions.ABinaryFunction;
77
import net.imglib2.algorithm.math.abstractions.IFunction;
8+
import net.imglib2.algorithm.math.abstractions.IVar;
89
import net.imglib2.converter.Converter;
910
import net.imglib2.type.numeric.RealType;
1011

@@ -45,8 +46,12 @@ private Div( final RealType< ? > scrap, final IFunction f1, final IFunction f2 )
4546
}
4647

4748
@Override
48-
public Div reInit( final RealType<?> tmp, final Map<String, RealType<?>> bindings, final Converter<RealType<?>, RealType<?>> converter )
49+
public Div reInit(
50+
final RealType<?> tmp,
51+
final Map<String, RealType<?>> bindings,
52+
final Converter<RealType<?>, RealType<?>> converter,
53+
Map< IVar, IFunction > imgSources )
4954
{
50-
return new Div( tmp.copy(), this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ) );
55+
return new Div( tmp.copy(), this.a.reInit( tmp, bindings, converter, imgSources ), this.b.reInit( tmp, bindings, converter, imgSources ) );
5156
}
5257
}

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import net.imglib2.algorithm.math.abstractions.Compare;
66
import net.imglib2.algorithm.math.abstractions.IFunction;
7+
import net.imglib2.algorithm.math.abstractions.IVar;
78
import net.imglib2.converter.Converter;
89
import net.imglib2.type.numeric.RealType;
910

@@ -26,8 +27,12 @@ public final boolean compare( final RealType t1, final RealType t2 )
2627
}
2728

2829
@Override
29-
public Equal reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter<RealType<?>, RealType<?>> converter )
30+
public Equal reInit(
31+
final RealType< ? > tmp,
32+
final Map< String, RealType< ? > > bindings,
33+
final Converter<RealType<?>, RealType<?>> converter,
34+
final Map< IVar, IFunction > imgSources )
3035
{
31-
return new Equal( tmp.copy(), this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ) );
36+
return new Equal( tmp.copy(), this.a.reInit( tmp, bindings, converter, imgSources ), this.b.reInit( tmp, bindings, converter, imgSources ) );
3237
}
3338
}

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import net.imglib2.algorithm.math.abstractions.Compare;
66
import net.imglib2.algorithm.math.abstractions.IFunction;
7+
import net.imglib2.algorithm.math.abstractions.IVar;
78
import net.imglib2.converter.Converter;
89
import net.imglib2.type.numeric.RealType;
910

@@ -25,8 +26,12 @@ public final boolean compare( final RealType t1, final RealType t2 )
2526
}
2627

2728
@Override
28-
public GreaterThan reInit( final RealType<?> tmp, final Map<String, RealType<?>> bindings, final Converter<RealType<?>, RealType<?>> converter )
29+
public GreaterThan reInit(
30+
final RealType<?> tmp,
31+
final Map<String, RealType<?>> bindings,
32+
final Converter<RealType<?>, RealType<?>> converter,
33+
Map< IVar, IFunction > imgSources )
2934
{
30-
return new GreaterThan( tmp.copy(), this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ) );
35+
return new GreaterThan( tmp.copy(), this.a.reInit( tmp, bindings, converter, imgSources ), this.b.reInit( tmp, bindings, converter, imgSources ) );
3136
}
3237
}

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

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package net.imglib2.algorithm.math;
22

3+
import java.util.HashMap;
34
import java.util.Map;
45

56
import net.imglib2.Localizable;
67
import net.imglib2.algorithm.math.abstractions.ATrinaryFunction;
78
import net.imglib2.algorithm.math.abstractions.Compare;
89
import net.imglib2.algorithm.math.abstractions.IFunction;
10+
import net.imglib2.algorithm.math.abstractions.IVar;
911
import net.imglib2.algorithm.math.optimizations.IfBoolean;
1012
import net.imglib2.converter.Converter;
1113
import net.imglib2.type.numeric.RealType;
@@ -23,7 +25,7 @@ protected If( final RealType< ? > scrap, final IFunction f1, final IFunction f2,
2325
}
2426

2527
@Override
26-
public RealType< ? > eval()
28+
public final RealType< ? > eval()
2729
{
2830
return 0 != this.a.eval().getRealFloat() ?
2931
// Then
@@ -33,7 +35,7 @@ protected If( final RealType< ? > scrap, final IFunction f1, final IFunction f2,
3335
}
3436

3537
@Override
36-
public RealType< ? > eval( final Localizable loc )
38+
public final RealType< ? > eval( final Localizable loc )
3739
{
3840
return 0 != this.a.eval().getRealFloat() ?
3941
// Then
@@ -43,14 +45,42 @@ protected If( final RealType< ? > scrap, final IFunction f1, final IFunction f2,
4345
}
4446

4547
@Override
46-
public If reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter<RealType<?>, RealType<?>> converter )
48+
public IFunction reInit(
49+
final RealType< ? > tmp,
50+
final Map< String, RealType< ? > > bindings,
51+
final Converter<RealType<?>, RealType<?>> converter,
52+
final Map< IVar, IFunction > imgSources )
4753
{
54+
// Fix: if there is an ImgSource among the children of then (this.b) or else (this.c),
55+
// replace them with a Var, reading from a Let inserted as a parent of this If,
56+
// in order to guarantee that their iterators are advanced.
57+
final Map< IVar, IFunction > imgS;
58+
if ( null == imgSources )
59+
imgS = new HashMap<>();
60+
else
61+
imgS = imgSources; // There is an upstream If
62+
4863
// Optimization: reInit as IfBoolean if the first argument is a Compare.
4964
// Avoids having to set the output to 1 (true) or 0 (false),
5065
// and then having to read it out and compare it to zero to make a boolean,
5166
// instead returning a boolean directly.
67+
final IFunction instance;
5268
if ( this.a instanceof Compare )
53-
return new IfBoolean( tmp.copy(), ( Compare ) this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ), this.c.reInit( tmp, bindings, converter ) );
54-
return new If( tmp.copy(), this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ), this.c.reInit( tmp, bindings, converter ) );
69+
instance = new IfBoolean( tmp.copy(), ( Compare ) this.a.reInit( tmp, bindings, converter, imgS ),
70+
this.b.reInit( tmp, bindings, converter, imgS ), this.c.reInit( tmp, bindings, converter, imgS ) );
71+
else
72+
instance = new If( tmp.copy(), this.a.reInit( tmp, bindings, converter, imgSources ),
73+
this.b.reInit( tmp, bindings, converter, imgS ), this.c.reInit( tmp, bindings, converter, imgS ) );
74+
75+
// Check if there was an upstream If, which has preference, or there aren't any imgSource downstream
76+
if ( null != imgSources || imgS.isEmpty() )
77+
return instance;
78+
79+
// Return a Let that declares all Vars in imgS, recursively, and places this If as the innermost body
80+
Let let = null;
81+
for ( final Map.Entry< IVar, IFunction > e : imgS.entrySet() )
82+
let = new Let( e.getKey().getScrap(), e.getKey().getName(), e.getValue(), null == let ? instance : let );
83+
84+
return let;
5585
}
56-
}
86+
};

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

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
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.IVar;
1011
import net.imglib2.algorithm.math.abstractions.ImgSource;
1112
import net.imglib2.algorithm.math.optimizations.IterableImgSourceDirect;
1213
import net.imglib2.converter.Converter;
13-
import net.imglib2.type.Type;
1414
import net.imglib2.type.numeric.RealType;
1515
import net.imglib2.view.Views;
1616

17-
public class IterableImgSource< I extends RealType< I > > implements IFunction, ImgSource< I >
17+
public class IterableImgSource< I extends RealType< I > > implements ImgSource< I >
1818
{
1919
private final RandomAccessibleInterval< I > rai;
2020
private final Iterator< I > it;
@@ -52,13 +52,29 @@ private IterableImgSource( final RealType< ? > scrap, final Converter< RealType<
5252
}
5353

5454
@Override
55-
public IFunction reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter< RealType< ? >, RealType< ? > > converter )
55+
public IFunction reInit(
56+
final RealType< ? > tmp,
57+
final Map< String, RealType< ? > > bindings,
58+
final Converter< RealType< ? >, RealType< ? > > converter,
59+
final Map< IVar, IFunction > imgSources )
5660
{
5761
// Optimization: if input image type is the same or a subclass of
5862
// the output image time (represented here by tmp), then avoid the converter.
63+
final ImgSource< ? > s;
5964
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 );
65+
s = new IterableImgSourceDirect< I >( this.rai );
66+
else
67+
s = new IterableImgSource< I >( tmp.copy(), converter, this.rai );
68+
69+
// Addressing "If" branching: replace with a Var
70+
if ( null != imgSources )
71+
{
72+
final Var var = new Var( tmp.copy(), "#imgSource#" + imgSources.size() );
73+
imgSources.put( var, s );
74+
return var;
75+
}
76+
77+
return ( IFunction )s;
6278
}
6379

6480
@Override

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import net.imglib2.algorithm.math.abstractions.Compare;
66
import net.imglib2.algorithm.math.abstractions.IFunction;
7+
import net.imglib2.algorithm.math.abstractions.IVar;
78
import net.imglib2.converter.Converter;
89
import net.imglib2.type.numeric.RealType;
910

@@ -25,7 +26,11 @@ public final boolean compare( final RealType t1, final RealType t2 )
2526
}
2627

2728
@Override
28-
public LessThan reInit( final RealType<?> tmp, final Map<String, RealType<?>> bindings, final Converter<RealType<?>, RealType<?>> converter ) {
29-
return new LessThan( tmp.copy(), this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ) );
29+
public LessThan reInit(
30+
final RealType<?> tmp,
31+
final Map<String, RealType<?>> bindings,
32+
final Converter<RealType<?>, RealType<?>> converter,
33+
final Map< IVar, IFunction > imgSources ) {
34+
return new LessThan( tmp.copy(), this.a.reInit( tmp, bindings, converter, imgSources ), this.b.reInit( tmp, bindings, converter, imgSources ) );
3035
}
3136
}

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import net.imglib2.Localizable;
77
import net.imglib2.algorithm.math.abstractions.IBinaryFunction;
88
import net.imglib2.algorithm.math.abstractions.IFunction;
9+
import net.imglib2.algorithm.math.abstractions.IVar;
910
import net.imglib2.algorithm.math.abstractions.Util;
1011
import net.imglib2.converter.Converter;
1112
import net.imglib2.type.numeric.RealType;
@@ -61,7 +62,7 @@ static private final Object[] fixAndValidate( final Object[] obs )
6162
return obs2;
6263
}
6364

64-
private Let( final RealType< ? > scrap, final String varName, final IFunction varValue, final IFunction body )
65+
protected Let( final RealType< ? > scrap, final String varName, final IFunction varValue, final IFunction body )
6566
{
6667
this.scrap = scrap;
6768
this.varName = varName;
@@ -90,12 +91,16 @@ private Let( final RealType< ? > scrap, final String varName, final IFunction va
9091
}
9192

9293
@Override
93-
public Let reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter< RealType< ? >, RealType< ? > > converter )
94+
public Let reInit(
95+
final RealType< ? > tmp,
96+
final Map< String, RealType< ? > > bindings,
97+
final Converter< RealType< ? >, RealType< ? > > converter,
98+
final Map< IVar, IFunction > imgSources )
9499
{
95100
final RealType< ? > scrap = tmp.copy();
96101
final Map< String, RealType< ? > > rebind = new HashMap<>( bindings );
97102
rebind.put( this.varName, scrap );
98-
return new Let( scrap, this.varName, this.varValue.reInit( tmp, rebind, converter ), this.body.reInit( tmp, rebind, converter ) );
103+
return new Let( scrap, this.varName, this.varValue.reInit( tmp, rebind, converter, imgSources ), this.body.reInit( tmp, rebind, converter, imgSources ) );
99104
}
100105

101106
@Override

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import net.imglib2.Localizable;
66
import net.imglib2.algorithm.math.abstractions.ABinaryFunction;
77
import net.imglib2.algorithm.math.abstractions.IFunction;
8+
import net.imglib2.algorithm.math.abstractions.IVar;
89
import net.imglib2.converter.Converter;
910
import net.imglib2.type.numeric.RealType;
1011

@@ -44,8 +45,12 @@ private Max( final RealType< ? > scrap, final IFunction f1, final IFunction f2 )
4445
}
4546

4647
@Override
47-
public Max reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter< RealType< ? >, RealType< ? > > converter )
48+
public Max reInit(
49+
final RealType< ? > tmp,
50+
final Map< String, RealType< ? > > bindings,
51+
final Converter< RealType< ? >, RealType< ? > > converter,
52+
final Map< IVar, IFunction > imgSources )
4853
{
49-
return new Max( tmp.copy(), this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ) );
54+
return new Max( tmp.copy(), this.a.reInit( tmp, bindings, converter, imgSources ), this.b.reInit( tmp, bindings, converter, imgSources ) );
5055
}
5156
}

0 commit comments

Comments
 (0)