|
11 | 11 | import net.imglib2.algorithm.math.abstractions.IFunction; |
12 | 12 | import net.imglib2.algorithm.math.abstractions.ITrinaryFunction; |
13 | 13 | import net.imglib2.algorithm.math.abstractions.IUnaryFunction; |
14 | | -import net.imglib2.algorithm.math.abstractions.ImgSource; |
| 14 | +import net.imglib2.algorithm.math.abstractions.OFunction; |
15 | 15 | import net.imglib2.algorithm.math.abstractions.Util; |
16 | 16 | import net.imglib2.converter.Converter; |
17 | 17 | import net.imglib2.type.numeric.RealType; |
|
20 | 20 | public class Compute |
21 | 21 | { |
22 | 22 | private final IFunction operation; |
23 | | - private final Converter< RealType< ? >, RealType< ? > > converter; |
| 23 | + private final boolean compatible_iteration_order; |
24 | 24 |
|
25 | 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)}. |
| 26 | + * Validate the {@param operation}. |
30 | 27 | * |
31 | 28 | * @param operation |
32 | 29 | */ |
33 | 30 | public Compute( final IFunction operation ) |
34 | 31 | { |
35 | | - this( operation, new Converter< RealType< ? >, RealType< ? > >() |
36 | | - { |
37 | | - @Override |
38 | | - public final void convert( final RealType<?> input, RealType<?> output) |
39 | | - { |
40 | | - output.setReal( input.getRealDouble() ); |
41 | | - } |
42 | | - }); |
| 32 | + this.operation = operation; |
| 33 | + |
| 34 | + // Throw RuntimeException as needed to indicate incorrect construction |
| 35 | + this.compatible_iteration_order = this.validate( this.operation ); |
43 | 36 | } |
44 | | - |
| 37 | + |
45 | 38 | /** |
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)}. |
| 39 | + * Execute the computation and store the result into the {@code target}. |
| 40 | + * The computation is done using {@code Type}-based math, with the {@code Type} |
| 41 | + * of the {@code target} defining the specific math implementation and numerical |
| 42 | + * precision that will be used. |
50 | 43 | * |
51 | | - * @param operation |
52 | | - * @param converter |
| 44 | + * @param target The {@code {@link RandomAccessibleInterval} into which to store the computation; |
| 45 | + * note its {@code Type} determines the precision of the computation and the specific |
| 46 | + * implementation of the mathematical operations. |
| 47 | + * @return The {@code target}. |
53 | 48 | */ |
54 | | - public Compute( |
55 | | - final IFunction operation, |
56 | | - final Converter< RealType< ? >, RealType< ? > > converter |
57 | | - ) |
| 49 | + public < O extends RealType< O > > RandomAccessibleInterval< O > into( final RandomAccessibleInterval< O > target ) |
58 | 50 | { |
59 | | - this.operation = operation; |
60 | | - this.converter = converter; |
| 51 | + return this.into( target, null ); |
61 | 52 | } |
62 | 53 |
|
63 | | - @SuppressWarnings({ "unchecked", "rawtypes" }) |
64 | | - public RandomAccessibleInterval< ? extends RealType< ? > > into( final RandomAccessibleInterval< ? extends RealType< ? > > target ) |
| 54 | + /** |
| 55 | + * Execute the mathematical operations and store the result into the given {@code RandomAccessibleInterval}. |
| 56 | + * |
| 57 | + * @param target The {@code {@link RandomAccessibleInterval} into which to store the computation; |
| 58 | + * note its {@code Type} determines the precision of the computation and the specific |
| 59 | + * implementation of the mathematical operations. |
| 60 | + * |
| 61 | + * @param converter The {@code Converter} that transfers all input {@code Type} to the {@code Type} |
| 62 | + * of the {@code target}; when null, will create one that uses double floating-point |
| 63 | + * precision; but note that if the {@code Type} of an input {@code RandomAccessibleInterval} |
| 64 | + * is the same as that of the {@code target}, the converter will not be used. |
| 65 | + * |
| 66 | + * @return The {@code target}. |
| 67 | + */ |
| 68 | + public < O extends RealType< O > > RandomAccessibleInterval< O > into( |
| 69 | + final RandomAccessibleInterval< O > target, |
| 70 | + Converter< RealType< ? >, O > converter |
| 71 | + ) |
65 | 72 | { |
| 73 | + if ( null == converter ) |
| 74 | + converter = new Converter< RealType< ? >, O >() |
| 75 | + { |
| 76 | + @Override |
| 77 | + public final void convert( final RealType< ? > input, final O output) |
| 78 | + { |
| 79 | + output.setReal( input.getRealDouble() ); |
| 80 | + } |
| 81 | + }; |
| 82 | + |
66 | 83 | // Recursive copy: initializes interval iterators and sets temporary computation holder |
67 | | - final IFunction f = this.operation.reInit( |
| 84 | + final OFunction< O > f = this.operation.reInit( |
68 | 85 | target.randomAccess().get().createVariable(), |
69 | | - new HashMap< String, RealType< ? > >(), |
70 | | - this.converter, null ); |
71 | | - |
72 | | - final boolean compatible_iteration_order = this.setup( f ); |
| 86 | + new HashMap< String, O >(), |
| 87 | + converter, null ); |
73 | 88 |
|
74 | 89 | // Check compatible iteration order and dimensions |
75 | 90 | if ( compatible_iteration_order ) |
76 | 91 | { |
77 | 92 | // Evaluate function for every pixel |
78 | | - for ( final RealType output : Views.iterable( target ) ) |
| 93 | + for ( final O output : Views.iterable( target ) ) |
79 | 94 | output.set( f.eval() ); |
80 | 95 | } |
81 | 96 | else |
82 | 97 | { |
83 | 98 | // Incompatible iteration order |
84 | | - final Cursor< ? extends RealType< ? > > cursor = Views.iterable( target ).cursor(); |
| 99 | + final Cursor< O > cursor = Views.iterable( target ).cursor(); |
85 | 100 |
|
86 | 101 | while ( cursor.hasNext() ) |
87 | 102 | { |
88 | 103 | cursor.fwd(); |
89 | | - final RealType output = cursor.get(); |
90 | | - output.set( f.eval( cursor ) ); |
| 104 | + cursor.get().set( f.eval( cursor ) ); |
91 | 105 | } |
92 | 106 | } |
93 | 107 |
|
94 | 108 | return target; |
95 | 109 | } |
96 | 110 |
|
97 | | - @SuppressWarnings({ "rawtypes" }) |
98 | | - private boolean setup( final IFunction f ) |
| 111 | + private boolean validate( final IFunction f ) |
99 | 112 | { |
100 | 113 | final LinkedList< IFunction > ops = new LinkedList<>(); |
101 | 114 | ops.add( f ); |
@@ -123,7 +136,7 @@ private boolean setup( final IFunction f ) |
123 | 136 |
|
124 | 137 | if ( op instanceof ImgSource ) |
125 | 138 | { |
126 | | - images.addLast( ( ( ImgSource )op ).getRandomAccessibleInterval() ); |
| 139 | + images.addLast( ( ( ImgSource< ? > )op ).getRandomAccessibleInterval() ); |
127 | 140 | } |
128 | 141 | else if ( op instanceof IUnaryFunction ) |
129 | 142 | { |
|
0 commit comments