Skip to content

Commit 36fd044

Browse files
committed
Add Op determinism as a best practice
1 parent ddcfe63 commit 36fd044

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

docs/ops/doc/WritingYourOwnOpPackage.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,49 @@ You'll find this page organized into two broad sections. The first section descr
88

99
SciJava Ops is designed for modularity, extensibility, and granularity - you can exploit these aspects by adhering to the following guidelines when writing Ops:
1010

11+
### Fostering reproduciblity
12+
13+
[Determinism](https://en.wikipedia.org/wiki/Deterministic_algorithm) is a valuable aspect of scientific computing, as it is necessary for reproducible science. As many powerful algorithms, due to internal state or parallel processing, behave non-deterministically SciJava Ops does not require Ops be deterministic, however if your Op can be deterministic, we highly recommend you make it so. Consider the following algorithm:
14+
15+
```java
16+
/**
17+
* A simple noise adder
18+
* @param input the input data
19+
* @implNote op name="filter.addNoise" type=Inplace
20+
*/
21+
public static void addNoise(double[] data) {
22+
Random r = new Random();
23+
for(int i = 0; i < data.length; i++) {
24+
// Add a number in [-0.5, 0.5)
25+
data[i] += (r.nextDouble() - 0.5);
26+
}
27+
}
28+
```
29+
30+
We can make it deterministic by adding an `@Nullable` `seed` parameter, with a default value if the user does not pass one:
31+
32+
```java
33+
/**
34+
* A simple noise adder
35+
* @param input the input data
36+
* @param seed the seed to the {@link java.util.Random}
37+
* @implNote op name="filter.addNoise" type=Inplace
38+
*/
39+
public static void addNoise(double[] data, @Nullable Long seed) {
40+
// use default seed if not provided
41+
if (seed == null) {
42+
seed = 0xdeadbeef;
43+
}
44+
Random r = new Random(seed);
45+
for(int i = 0; i < data.length; i++) {
46+
// Add a number in [-0.5, 0.5)
47+
data[i] += (r.nextDouble() - 0.5);
48+
}
49+
}
50+
```
51+
52+
These small steps ensure that user workflows return the same result every time, even years later!
53+
1154
### Using Dependencies
1255

1356
If you are writing an Op that performs many intermediate operations, there's a good chance someone else has written (and even optimized) some or all of them.

0 commit comments

Comments
 (0)