Skip to content

Commit a747966

Browse files
committed
CallingOps: make various minor improvements
1 parent 02d05a9 commit a747966

1 file changed

Lines changed: 18 additions & 18 deletions

File tree

docs/ops/doc/CallingOps.md

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# Calling Ops with the `OpBuilder`
22

3-
Use of the Ops framework centers on a process of matching Op requests are to function implementations based on the parameters provided. The easiest way to make these queries is to use the `OpBuilder` syntax, which follows the [builder pattern](https://refactoring.guru/design-patterns/builder) to assemble the required components of an Op matching request from a particular `OpEnvironment`.
3+
Use of the Ops framework centers on a process of matching Op requests to algorithm implementations based on the parameters provided. The easiest way to make these queries is to use the `OpBuilder` syntax, which follows the [builder pattern](https://refactoring.guru/design-patterns/builder) to assemble the required components of an Op matching request from a particular `OpEnvironment`.
44

5-
In this page we start after having [identified a Gaussian Blur Op](SearchingForOps) that we would like to use. We assume we already have created an `OpEnvironment`, named `ops`, as well as the input image to blur, and a pre-allocated output image for the result - `inImage` and `outImage`, respectively.
5+
In this page, we start after having [identified a Gaussian Blur Op](SearchingForOps) that we would like to use. We assume we already have created an `OpEnvironment` named `ops`, as well as the input image to blur, and a pre-allocated output image for the result—`inImage` and `outImage`, respectively.
66

7-
**Note:** we are incrementally building one line of code in this example. Running an intermediate step simply returns an appropriate builder that knows what has been set so far, and which step is next. If you're following along in an IDE or script editor, the code you actually *run* would be the last step, once our builder call is fully constructed.
7+
**Note:** we are incrementally constructing one line of code in this example. Running an intermediate step simply returns an appropriate builder that knows what has been set so far, and which step is next. If you're following along in an IDE or script editor, the code you actually *run* would be the last step, once our builder call is fully constructed.
88

99
## Specifying the name with `.op()`
1010

11-
From the `OpEnvironment`, an `OpBuilder` chain is initialized with the `OpEnvironment.op(String)` method, which describes the name of the Op that we ultimately want to call:
11+
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

1313
```groovy
1414
ops.op("filter.gauss")
@@ -18,49 +18,49 @@ ops.op("filter.gauss")
1818

1919
With the name established in the `OpBuilder` chain, we can then specify our input(s) with the `.input()` method.
2020

21-
For this Gaussian blur, we have two inputs: `inImage` is the image we want to blur, and a `double` as our sigma parameter:
21+
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

2323
```groovy
2424
ops.op("filter.gauss").input(inImage, 2.0)
2525
```
2626

2727
## Passing an output buffer with `.output()`
2828

29-
After specifying inputs, we provide preallocated outputs using the `.output()` method.
29+
After specifying inputs, we provide a preallocated output container using the `.output()` method.
3030

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

3333
```groovy
3434
ops.op("filter.gauss").input(inImage, 2.0).output(outImage)
3535
```
3636

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

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

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

45-
In the call to `compute()`, the `OpEnvironment` will use the components of the `OpBuilder` syntax to:
46-
* Match an Op based on the name provided, as well as the types of the provided input and output `Object`s
47-
* Execute the Op on the provided input and output `Object`s.
45+
In the call to `compute()`, the `OpEnvironment` will use all of the parameters provided to:
46+
* Match an Op based on the name provided, as well as the types of the provided input and output objects
47+
* Execute the Op on the provided input and output objects.
4848

4949
After this step, `outImage` will contain the results of the Gaussian blur on `inImage`.
5050

5151
## Variations on use
5252

53-
### Using `Function` or `InPlace`
53+
### Using a *function* or *inplace* Op
5454

55-
Calling our Gaussian blur as a `Computer` above is great when we have pre-allocated output, but for other scenarios we can request Ops as `Functions` or `InPlaces`.
55+
Calling our Gaussian blur as a *computer* above is great when we have pre-allocated output, but for other scenarios we can request Ops as *functions* or *inplaces*.
5656

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

5959
```groovy
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`). 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* that will be modified:
6464

6565
```
6666
# Modify the first input in-place
@@ -74,11 +74,11 @@ Note that although the final method call changes for each mode of operation, *th
7474
ops.op("filter.gauss").input(inImage, 2.0).compute()
7575
```
7676

77-
A key takeaway from this section is that how you **request** the Op does not necessarily need to match how the Op is **implemented**. `Functions` and `Computers` should be largely interchangeable. For the 1.0.0 release we do not have the necessary converters to go between `InPlaces` and the other paradigms, but it is on our [development roadmap](https://github.com/scijava/scijava/issues/47)!
77+
A key takeaway from this section is that how you **request** the Op does not necessarily need to match how the Op is **implemented**. *Functions* and *computers* should be largely interchangeable, thanks to the Ops engine's adaptation subsystem. For the 1.0.0 release we do not have the necessary adapters to go between *inplaces* and the other paradigms, but it is on our [development roadmap](https://github.com/scijava/scijava/issues/47)!
7878

7979
### Repeating execution
8080

81-
When you want to call an Op many times on different inputs, the `OpBuilder` syntax can be modified 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()`, `.mutate#()`):
81+
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

8383
```groovy
8484
var gaussOp = ops.op("filter.gauss").input(inImage, 2.0).output(outImage).computer()
@@ -131,7 +131,7 @@ Generally speaking, op requests are **cached**, meaning repeated OpBuilder calls
131131

132132
### Solution 2: Avoid using wildcards
133133

134-
If you *know* that your `Img` will always contain unsigned byte values, for example, define your variable as an `Img<UnsignedByteType>` rather than using `Img<?>`.
134+
If you know that your `Img` will always contain unsigned byte values, for example, define your variable as an `Img<UnsignedByteType>` rather than using `Img<?>`.
135135

136136
### Solution 3: Use raw casts (not type-safe!)
137137

0 commit comments

Comments
 (0)