← 输入框|github.com|刷新
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions docs/ops/doc/WritingYourOwnOpPackage.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,49 @@ You'll find this page organized into two broad sections. The first section descr

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

### Fostering reproduciblity

[Determinism](https://en.wikipedia.org/wiki/Deterministic_algorithm) is a valuable aspect of scientific computing, as our goal is to facilitate reproducible science. As many powerful algorithms behave non-deterministically, due to factors such as internal state or parallel processing, 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:

```java
/**
* A simple noise adder
* @param input the input data
* @implNote op name="filter.addNoise" type=Inplace
*/
public static void addNoise(double[] data) {
Random r = new Random();
for(int i = 0; i < data.length; i++) {
// Add a number in [-0.5, 0.5)
data[i] += (r.nextDouble() - 0.5);
}
}
```

We can make it deterministic by adding an `@Nullable` `seed` parameter, with a default value if the user does not pass one:

```java
/**
* A simple noise adder
* @param input the input data
* @param seed the seed to the {@link java.util.Random}
* @implNote op name="filter.addNoise" type=Inplace
*/
public static void addNoise(double[] data, @Nullable Long seed) {
// use default seed if not provided
if (seed == null) {
seed = 0xdeadbeef;
}
Random r = new Random(seed);
for(int i = 0; i < data.length; i++) {
// Add a number in [-0.5, 0.5)
data[i] += (r.nextDouble() - 0.5);
}
}
```

These small steps give workflows the best chance to return consistent results every time, even years later!

### Using Dependencies

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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,12 @@
* An Op is an algorithm adhering to the following traits:
* </p>
* <ol>
* <li>Ops are stateless and deterministic - with no internal state, calling an
* Op two times on the same inputs will produce the same output.</li>
* <li>Ops are named - this name conveys an Op's purpose, and allows us to find
* all Ops implementing a particular operation</li>
* <li>Ops have a number of input and output parameters, each defined by a
* type</li>
* <li>Ops adhere to a {@link java.lang.FunctionalInterface}, defining how it
* operates</li>
* </ol>
* <p>
* Using the name and the combination of input and output parameters, we can
Expand Down Expand Up @@ -151,10 +153,11 @@
* and SciJava Ops will take care to call the correct Op based on the concrete
* inputs provided.</li>
* <li>Result-equivalence, and therefore reproducibility, in Ops, is guaranteed
* within an OpEnvironment and a set of input objects, but not just for Op
* calls. This allows us to ensure reproducible pipelines, but also allows us to
* introduce new Ops into the pipeline or to run pipelines on different inputs
* without changing the pipeline itself.</li>
* within an OpEnvironment and a set of input objects, when <b>deterministic</b>
* algorithms are used. Cognizance of algorithm determinism allows users to
* create reproducible pipelines, however determinism is <b>not</b> a
* requirement for Ops, as it would preclude many valuable algorithms from
* becoming an Op.</li>
* </ol>
*/

Expand Down