Skip to content

Commit b3917b2

Browse files
authored
Merge pull request #250 from scijava/pr-249-feedback
Make further updates based on feedback from PR #249
2 parents 3b3f3b2 + 3648c07 commit b3917b2

File tree

1 file changed

+22
-18
lines changed

1 file changed

+22
-18
lines changed

docs/ops/doc/CallingOps.md

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ In this page, we start after having [identified a Gaussian Blur Op](SearchingFor
1010

1111
From the `OpEnvironment`, an `OpBuilder` chain is initialized with the `op(String)` method, which describes the name of the Op that we ultimately want to call:
1212

13-
```groovy
13+
```java
1414
ops.op("filter.gauss")
1515
```
1616

@@ -20,7 +20,7 @@ With the name established in the `OpBuilder` chain, we can then specify our inpu
2020

2121
For this Gaussian blur, we have two inputs: `inImage` is the image we want to blur, and a `double` value as our sigma parameter:
2222

23-
```groovy
23+
```java
2424
ops.op("filter.gauss").input(inImage, 2.0)
2525
```
2626

@@ -30,15 +30,15 @@ After specifying inputs, we provide a preallocated output container using the `.
3030

3131
For our Gaussian blur, we will pass our output image `outImage` as a receptacle for the result:
3232

33-
```groovy
33+
```java
3434
ops.op("filter.gauss").input(inImage, 2.0).output(outImage)
3535
```
3636

3737
## Computing with `.compute()`
3838

3939
With all of our desired Op's inputs and output now specified, we can run it with the `.compute()` method.
4040

41-
```groovy
41+
```java
4242
ops.op("filter.gauss").input(inImage, 2.0).output(outImage).compute()
4343
```
4444

@@ -56,21 +56,21 @@ Calling our Gaussian blur as a *computer* above is great when we have pre-alloca
5656

5757
*Functions* are used when we want to *create* the final output, indicated by ending the builder with `.apply()`:
5858

59-
```groovy
59+
```java
6060
var outImage = ops.op("filter.gauss").input(inImage, 2.0).apply()
6161
```
6262

63-
*Inplaces* are used when we want to destructively modify one of the existing inputs (which is explicitly forbidden by *computers*; a *computer* Op's output should be a different object from all of its inputs). We indicate this by the `mutate#()` method, where the `#` corresponds to the *parameter index* that will be modified:
63+
*Inplaces* are used when we want to destructively modify one of the existing inputs (which is explicitly forbidden by *computers*; a *computer* Op's output should be a different object from all of its inputs). We indicate this by the `mutate#()` method, where the `#` corresponds to the *parameter index* (starting from 1 for the first parameter) that will be modified:
6464

65-
```
66-
# Modify the first input in-place
65+
```java
66+
// Modify the first input in-place
6767
ops.op("filter.gauss").input(inImage, 2.0).mutate1()
6868
```
6969

7070
Note that although the final method call changes for each mode of operation, *this is based on the path taken through the `OpBuilder` chain*. For example, we cannot call the `compute()` method if we haven't provided an `.output()`:
7171

72-
```
73-
# Does not compute
72+
```java
73+
// Does not compute
7474
ops.op("filter.gauss").input(inImage, 2.0).compute()
7575
```
7676

@@ -80,22 +80,26 @@ A key takeaway from this section is that how you **request** the Op does not nec
8080

8181
When you want to call an Op many times on different inputs, the `OpBuilder` can be used to return the *Op* itself, instead of performing the computation. Instead of calling the `.compute()` function at the end of our `OpBuilder` chain, we can use the `.computer()` method (or `.inplace()` or `.function()`, as appropriate) to get back the matched Op, which can then be reused via its `.compute()` method (or `.apply()` or `.mutate#()`, respectively):
8282

83-
```groovy
84-
var gaussOp = ops.op("filter.gauss").input(inImage, 2.0).output(outImage).computer()
85-
gaussOp.compute(inImage, 2.0, outImage1)
86-
gaussOp.compute(inImage, 5.0, outImage2)
83+
```java
84+
var gaussOp = ops.op("filter.gauss").input(inImage, 2.0).output(outImage).computer();
85+
gaussOp.compute(inImage, 2.0, outImage1);
86+
gaussOp.compute(inImage, 5.0, outImage2);
8787
```
8888

8989
While we do pass concrete inputs and outputs in this example, they are essentially just being used to reason about the desired *types* - which we'll cover in the next section.
9090

9191
*Note that the default `OpEnvironment` implementations cache Op requests* - this means that repeated `OpBuilder` requests targeting the same action will be faster than the original matching call.
9292

93-
### Matching with classes
93+
### Matching with types/classes
9494

9595
In addition to the `.input()` and `.output()` builder steps, there are parallel `.inType()` and `.outType()`
9696
methods. These accept either a `Class` or a `Nil` - the latter allowing retention of generic types.
97+
These methods makes it possible to search for an Op without actually having an instance of the objects
98+
you (eventually) plan to operate upon. For example, you might want to look up the `filter.gauss` Op that
99+
would be used to smooth an `ImgPlus` by a particular `double` value, without actually having an `ImgPlus`
100+
image available to pass to the builder request:
97101

98-
```groovy
102+
```java
99103
var computer = ops.op("filter.gauss").inType(ImgPlus.class, Double.class).outType(ImgPlus.class).computer()
100104
```
101105

@@ -106,7 +110,7 @@ not been concretely specified yet. This is very sensible when we want to re-use
106110
We can also use the `.outType()` methods to add type safety to our `Function` calls:
107111

108112
```java
109-
Img outImage = ops.op("filter.gauss").input(inImage, 2.0).outType(Img.class).apply();
113+
Img outImage = ops.op("filter.gauss").input(inImage, 2.0).outType(Img.class).apply()
110114
```
111115

112116
## Common Pitfalls: Wildcards
@@ -124,7 +128,7 @@ gaussOp.compute(inImage, 2.0, outImage);
124128
If you don't need to save the Op to a variable, *just [call it directly](#computing-with-compute)*:
125129

126130
```java
127-
ops.op("filter.gauss").input(inImage, 2.0).output(outImage).compute();
131+
ops.op("filter.gauss").input(inImage, 2.0).output(outImage).compute()
128132
```
129133

130134
Generally speaking, op requests are **cached**, meaning repeated OpBuilder calls that directly execute Ops will **not** significantly decrease performance.

0 commit comments

Comments
 (0)