Skip to content

Commit 8439a41

Browse files
authored
Merge pull request #116 from scijava/scijava-ops-image/add-parameter-constraints
Add parameter constraints from ImageJ Ops
2 parents 61ca449 + 649908f commit 8439a41

37 files changed

+664
-979
lines changed

scijava-ops-engine/src/main/java/org/scijava/ops/engine/eval/DefaultEval.java

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

3434
import org.scijava.function.Functions;
3535
import org.scijava.ops.api.OpEnvironment;
36+
import org.scijava.ops.spi.Nullable;
3637
import org.scijava.ops.spi.Op;
3738
import org.scijava.ops.spi.OpClass;
3839

@@ -49,7 +50,7 @@
4950
*/
5051
@OpClass(names = "eval")
5152
public class DefaultEval implements
52-
Functions.Arity3<String, Map<String, Object>, OpEnvironment, Object>, Op
53+
Functions.Arity3<String, OpEnvironment, Map<String, ?>, Object>, Op
5354
{
5455

5556
/**
@@ -61,9 +62,11 @@ public class DefaultEval implements
6162
* @return the output
6263
*/
6364
@Override
64-
public Object apply(final String input, final Map<String, Object> vars,
65-
final OpEnvironment ops)
66-
{
65+
public Object apply( //
66+
final String input, //
67+
final OpEnvironment ops, //
68+
@Nullable final Map<String, ?> vars //
69+
) {
6770
OpEvaluator e = new OpEvaluator(ops);
6871
if (vars != null) e.setAll(vars);
6972
return e.evaluate(input);

scijava-ops-engine/src/test/java/org/scijava/ops/engine/eval/EvalTest.java

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,25 @@ public void testMath() {
6262
vars.put("b", 3);
6363
vars.put("c", 5);
6464

65-
// TODO: can we use ops.run here?
66-
Functions.Arity3<String, Map<String, Object>, OpEnvironment, Object> evaluator =
67-
ops.op("eval", //
68-
new Nil<>()
69-
{}, //
70-
new Nil[] { new Nil<String>() {}, new Nil<Map<String, Object>>() {}, new Nil<OpEnvironment>() {} }, //
71-
new Nil<>()
72-
{} //
73-
);
65+
var evaluator = ops.ternary("eval") //
66+
.input("a+c", ops, vars) //
67+
.function();
7468

75-
assertEquals(7., evaluator.apply("a+c", vars, ops));
76-
assertEquals(3., evaluator.apply("c-a", vars, ops));
77-
assertEquals(6., evaluator.apply("a*b", vars, ops));
78-
assertEquals(2.5, evaluator.apply("c/a", vars, ops));
79-
assertEquals(1., evaluator.apply("c%a", vars, ops));
80-
assertEquals(17., evaluator.apply("a+b*c", vars, ops));
69+
assertEquals(7., evaluator.apply("a+c", ops, vars));
70+
assertEquals(3., evaluator.apply("c-a", ops, vars));
71+
assertEquals(6., evaluator.apply("a*b", ops, vars));
72+
assertEquals(2.5, evaluator.apply("c/a", ops, vars));
73+
assertEquals(1., evaluator.apply("c%a", ops, vars));
74+
assertEquals(17., evaluator.apply("a+b*c", ops, vars));
75+
}
76+
77+
@Test
78+
public void testMathWithoutVars() {
79+
var result = ops.binary("eval") //
80+
.input("5+2", ops) //
81+
.apply();
82+
83+
assertEquals(7., result);
8184
}
8285

8386
}

scijava-ops-image/src/main/java/org/scijava/ops/image/coloc/maxTKendallTau/MTKT.java

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,8 @@
3131

3232
import java.util.Collections;
3333
import java.util.Random;
34-
import java.util.function.BiFunction;
3534
import java.util.function.Function;
3635

37-
import org.scijava.ops.image.coloc.ColocUtil;
38-
import org.scijava.ops.image.coloc.IntArraySorter;
39-
import org.scijava.ops.image.coloc.MergeSort;
4036
import net.imglib2.RandomAccess;
4137
import net.imglib2.RandomAccessibleInterval;
4238
import net.imglib2.histogram.Histogram1d;
@@ -45,10 +41,13 @@
4541
import net.imglib2.util.Intervals;
4642
import net.imglib2.util.Util;
4743
import net.imglib2.view.Views;
48-
4944
import org.scijava.collections.IntArray;
5045
import org.scijava.function.Computers;
5146
import org.scijava.function.Functions;
47+
import org.scijava.ops.image.coloc.ColocUtil;
48+
import org.scijava.ops.image.coloc.IntArraySorter;
49+
import org.scijava.ops.image.coloc.MergeSort;
50+
import org.scijava.ops.spi.Nullable;
5251
import org.scijava.ops.spi.OpDependency;
5352

5453
/**
@@ -86,7 +85,7 @@ public class MTKT<T extends RealType<T>, U extends RealType<U>>
8685
* @return the output
8786
*/
8887
@Override
89-
public Double apply(final RandomAccessibleInterval<T> image1, final RandomAccessibleInterval<U> image2, final Long seed) {
88+
public Double apply(final RandomAccessibleInterval<T> image1, final RandomAccessibleInterval<U> image2, @Nullable Long seed) {
9089
// check image sizes
9190
// TODO: Add these checks to conforms().
9291
if (!Intervals.equalDimensions(image1, image2)) {
@@ -98,6 +97,13 @@ public Double apply(final RandomAccessibleInterval<T> image1, final RandomAccess
9897
}
9998
final int n = (int) n1;
10099

100+
// Check nullable seed
101+
if (seed == null) {
102+
// NB the original seed used in ImageJ Ops was an integer, 0x893023421.
103+
// To preserve the same value without casting, we need this value.
104+
seed = 0xffff_ffff_8930_2341L;
105+
}
106+
101107
// compute thresholds
102108
final double thresh1 = thresholdT(image1);
103109
final double thresh2 = thresholdU(image2);
@@ -142,8 +148,8 @@ static <T extends RealType<T>, U extends RealType<U>> double[][] rankTransformat
142148
double[][] finalRanks = new double[rn][2];
143149
for (int i = 0; i < rn; i++) {
144150
final int index = validIndex.getValue(i);
145-
finalRanks[i][0] = Math.floor(rankIndex1[index]);
146-
finalRanks[i][1] = Math.floor(rankIndex2[index]);
151+
finalRanks[i][0] = rankIndex1[index];
152+
finalRanks[i][1] = rankIndex2[index];
147153
}
148154
return finalRanks;
149155
}
@@ -245,29 +251,3 @@ static double calculateKendallTau(final double[][] rank,
245251
}
246252

247253
}
248-
249-
/**
250-
*@implNote op names='coloc.maxTKendallTau'
251-
*/
252-
class MTKTSimple<T extends RealType<T>, U extends RealType<U>>
253-
implements BiFunction<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, Double>
254-
{
255-
256-
@OpDependency(name = "coloc.maxTKendallTau")
257-
private Functions.Arity3<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, Long, Double> colocOp;
258-
259-
private long seed = 0x89302341;
260-
261-
/**
262-
* TODO
263-
*
264-
* @param image1
265-
* @param image2
266-
* @return the output
267-
*/
268-
@Override
269-
public Double apply(RandomAccessibleInterval<T> image1, RandomAccessibleInterval<U> image2) {
270-
return colocOp.apply(image1, image2, seed);
271-
}
272-
273-
}

scijava-ops-image/src/main/java/org/scijava/ops/image/coloc/pValue/DefaultPValue.java

Lines changed: 25 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
import org.scijava.concurrent.Parallelization;
4040
import org.scijava.function.Computers;
41+
import org.scijava.ops.spi.Nullable;
4142
import org.scijava.ops.spi.OpDependency;
4243

4344
import org.scijava.ops.image.coloc.ShuffledView;
@@ -69,15 +70,29 @@ public class DefaultPValue<T extends RealType<T>, U extends RealType<U>> impleme
6970
* @param image2 the second image
7071
* @param op the op
7172
* @param nrRandomizations the number of randomizations
72-
* @param psfSize the psf size
73+
* @param psfSize Size of blocks for random shufflings.
7374
* @param seed the seed
7475
* @param output the output
7576
*/
7677
@Override
77-
public void compute(final RandomAccessibleInterval<T> image1, final RandomAccessibleInterval<U> image2,
78-
final BiFunction<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, Double> op,
79-
final Integer nrRandomizations, final Dimensions psfSize, final Long seed,
80-
final PValueResult output) {
78+
public void compute( //
79+
final RandomAccessibleInterval<T> image1, //
80+
final RandomAccessibleInterval<U> image2, //
81+
final BiFunction<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, Double> op, //
82+
@Nullable Integer nrRandomizations, //
83+
@Nullable Dimensions psfSize, //
84+
@Nullable Long seed, //
85+
final PValueResult output //
86+
) {
87+
// Check nullable arguments
88+
if (nrRandomizations == null) {
89+
nrRandomizations = 100;
90+
}
91+
// NB psfSize null-check is in blockSize method
92+
if (seed == null) {
93+
seed = 0x27372034L;
94+
}
95+
8196
final int[] blockSize = blockSize(image1, psfSize);
8297
final RandomAccessibleInterval<T> trimmedImage1 = trim(image1, blockSize);
8398
final RandomAccessibleInterval<U> trimmedImage2 = trim(image2, blockSize);
@@ -101,15 +116,17 @@ public void compute(final RandomAccessibleInterval<T> image1, final RandomAccess
101116
List<Integer> params = IntStream.rangeClosed(0, numTasks - 1) //
102117
.boxed().collect(Collectors.toList());
103118

119+
// NB final variable needed for use in lambda
120+
final Integer nr = nrRandomizations;
104121
Consumer<Integer> task = (t) -> {
105-
int offset = t * nrRandomizations / numTasks;
106-
int count = (t + 1) * nrRandomizations / numTasks - offset;
122+
int offset = t * nr / numTasks;
123+
int count = (t + 1) * nr / numTasks - offset;
107124
// a new one per thread and each needs its own seed
108125
final ShuffledView<T> shuffled = new ShuffledView<>(trimmedImage1, blockSize, seeds[offset]);
109126
Img<T> buffer = Util.getSuitableImgFactory(shuffled, type1).create(shuffled);
110127
for (int i = 0; i < count; i++) {
111128
int index = offset + i;
112-
if (index >= nrRandomizations)
129+
if (index >= nr)
113130
break;
114131
if (i > 0)
115132
shuffled.shuffleBlocks(seeds[index]);
@@ -181,57 +198,3 @@ private static <V> RandomAccessibleInterval<V> trim(final RandomAccessibleInterv
181198
return Views.interval(image, min, max);
182199
}
183200
}
184-
185-
/**
186-
*@implNote op names='coloc.pValue'
187-
*/
188-
class PValueSimpleWithRandomizations<T extends RealType<T>, U extends RealType<U>> implements
189-
Computers.Arity4<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, BiFunction<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, Double>, Integer, PValueResult> {
190-
191-
@OpDependency(name = "coloc.pValue")
192-
private Computers.Arity6<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, BiFunction<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, Double>, Integer, Dimensions, Long, PValueResult> pValueOp;
193-
194-
/**
195-
* TODO
196-
*
197-
* @param image1 the first image
198-
* @param image2 the second image
199-
* @param op the op
200-
* @param nrRandomizations the number of randomizations
201-
* @param output the result
202-
*/
203-
@Override
204-
public void compute(RandomAccessibleInterval<T> image1, RandomAccessibleInterval<U> image2,
205-
BiFunction<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, Double> op, Integer nrRandomizations, PValueResult output) {
206-
Long defaultSeed = 0x27372034L;
207-
pValueOp.compute(image1, image2, op, nrRandomizations, null, defaultSeed, output);
208-
}
209-
210-
}
211-
212-
/**
213-
*@implNote op names='coloc.pValue'
214-
*/
215-
class PValueSimple<T extends RealType<T>, U extends RealType<U>> implements
216-
Computers.Arity3<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, BiFunction<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, Double>, PValueResult> {
217-
218-
@OpDependency(name = "coloc.pValue")
219-
private Computers.Arity4<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, BiFunction<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, Double>, Integer, PValueResult> pValueOp;
220-
221-
/**
222-
* TODO
223-
*
224-
* @param image1 the first image
225-
* @param image2 the second image
226-
* @param op the op
227-
* @param output the result
228-
*/
229-
@Override
230-
public void compute(RandomAccessibleInterval<T> image1, RandomAccessibleInterval<U> image2,
231-
BiFunction<RandomAccessibleInterval<T>, RandomAccessibleInterval<U>, Double> op,
232-
PValueResult output) {
233-
Integer defaultNumberRandomizations = 100;
234-
pValueOp.compute(image1, image2, op, defaultNumberRandomizations, output);
235-
}
236-
237-
}

scijava-ops-image/src/main/java/org/scijava/ops/image/deconvolve/RichardsonLucyF.java renamed to scijava-ops-image/src/main/java/org/scijava/ops/image/deconvolve/PadAndRichardsonLucy.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
* @param <C>
6262
* @implNote op names='deconvolve.richardsonLucy', priority='100.'
6363
*/
64-
public class RichardsonLucyF<I extends RealType<I> & NativeType<I>, O extends RealType<O> & NativeType<O>, K extends RealType<K> & NativeType<K>, C extends ComplexType<C> & NativeType<C>>
64+
public class PadAndRichardsonLucy<I extends RealType<I> & NativeType<I>, O extends RealType<O> & NativeType<O>, K extends RealType<K> & NativeType<K>, C extends ComplexType<C> & NativeType<C>>
6565
implements
6666
Functions.Arity10<RandomAccessibleInterval<I>, RandomAccessibleInterval<K>, O, C, Integer, Boolean, Boolean, long[], OutOfBoundsFactory<I, RandomAccessibleInterval<I>>, OutOfBoundsFactory<K, RandomAccessibleInterval<K>>, RandomAccessibleInterval<O>> {
6767

@@ -196,15 +196,24 @@ private void computeFilter(final RandomAccessibleInterval<I> input,
196196
@Override
197197
public RandomAccessibleInterval<O> apply(RandomAccessibleInterval<I> input, RandomAccessibleInterval<K> kernel,
198198
O outType, C complexType, Integer maxIterations,
199-
Boolean nonCirculant, Boolean accelerate,
199+
@Nullable Boolean nonCirculant, @Nullable Boolean accelerate,
200200
@Nullable long[] borderSize,
201201
@Nullable OutOfBoundsFactory<I, RandomAccessibleInterval<I>> obfInput,
202202
@Nullable OutOfBoundsFactory<K, RandomAccessibleInterval<K>> obfKernel)
203203
{
204204
if (obfInput == null)
205205
obfInput = new OutOfBoundsConstantValueFactory<>(Util.getTypeFromInterval(input).createVariable());
206206

207-
this.nonCirculant = nonCirculant;
207+
if (nonCirculant == null) {
208+
this.nonCirculant = false;
209+
}
210+
else {
211+
this.nonCirculant = nonCirculant;
212+
}
213+
214+
if (accelerate == null) {
215+
accelerate = false;
216+
}
208217
this.maxIterations = maxIterations;
209218

210219
RandomAccessibleInterval<O> output = outputCreator.apply(input, outType);

scijava-ops-image/src/main/java/org/scijava/ops/image/deconvolve/RichardsonLucyTVF.java renamed to scijava-ops-image/src/main/java/org/scijava/ops/image/deconvolve/PadAndRichardsonLucyTV.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
* @param <C>
6464
* @implNote op names='deconvolve.richardsonLucyTV', priority='100.'
6565
*/
66-
public class RichardsonLucyTVF<I extends RealType<I> & NativeType<I>, O extends RealType<O> & NativeType<O>, K extends RealType<K> & NativeType<K>, C extends ComplexType<C> & NativeType<C>>
66+
public class PadAndRichardsonLucyTV<I extends RealType<I> & NativeType<I>, O extends RealType<O> & NativeType<O>, K extends RealType<K> & NativeType<K>, C extends ComplexType<C> & NativeType<C>>
6767
implements Functions.Arity11<RandomAccessibleInterval<I>, RandomAccessibleInterval<K>, O, C, Integer, Boolean, Boolean, Float, long[], OutOfBoundsFactory<I, RandomAccessibleInterval<I>>, OutOfBoundsFactory<K, RandomAccessibleInterval<K>>, RandomAccessibleInterval<O>> {
6868

6969
@OpDependency(name = "deconvolve.richardsonLucyUpdate")

0 commit comments

Comments
 (0)