|
| 1 | +# Concepts |
| 2 | + |
| 3 | +This page is designed to help *Ops users* understand the SciJava Ops concepts powering the framework. |
| 4 | + |
| 5 | +## Ops |
| 6 | +An **algorithm** is a mathematical routine that transforms, interrogate, or refines input values into output values, and are used throughout scientific computing. |
| 7 | + |
| 8 | +SciJava Ops attempts to abstract algorithm implementations into a more abstract, language independent form, called an **Op**. Ops have: |
| 9 | +* a **name**, defining its purpose. An Op's name describes *what* the Op does, but not *how* the Op does it. |
| 10 | + * An Op adding two Java `Integer`s would be named `math.add` |
| 11 | + * An Op convolving an image with a kernel might be named `filter.convolve`, *regardless* of whether it performs that convolution in the physical or frequency domain. |
| 12 | +* a number of **inputs** and **outputs**, defined by language-specific **types**. |
| 13 | + * A `math.add` Op might take two Java `Integer` inputs and return a Java `Integer` output |
| 14 | + * A `filter.convolve` Op might take two OpenCV `Mat` inputs, storing the convolved result into an OpenCV `Mat` output *buffer*. |
| 15 | +* behavior adhering to a **functional interface** defined below. |
| 16 | + |
| 17 | +## Computers |
| 18 | + |
| 19 | +A **Computer** accepts `n` immutable inputs and a **container** as input parameters. Their singular method, `compute()`, executes an algorithm and *stores the result within* the container parameter, overwriting its contents. |
| 20 | + |
| 21 | +For example, consider the following pseudocode, which replaces the contents of a list of integers `outList` with the elementwise addition of integer `val` to the list of integers `inList`: |
| 22 | +```text |
| 23 | +math.add(inList: list[int], val: int, outList: list[int]): |
| 24 | + outList.clear() |
| 25 | + for i in 1..size(inList): |
| 26 | + outList[i] = inList[i] + val |
| 27 | + |
| 28 | +``` |
| 29 | + |
| 30 | +## Functions |
| 31 | + |
| 32 | +A **Function** accepts `n` immutable inputs as parameters. Their singular method, `apply()`, executes an algorithm and *returns* a new output object to the user. |
| 33 | + |
| 34 | +For example, consider the following pseudocode, which returns a list of integers with the elementwise addition of integer `val` to the list of integers `inList`: |
| 35 | +```text |
| 36 | +math.add(inList: list[int], val: int) -> list[int]: |
| 37 | + outList = list() |
| 38 | + for i in 1..size(inList): |
| 39 | + outList[i] = inList[i] + val |
| 40 | + return outList |
| 41 | +``` |
| 42 | + |
| 43 | +Creating a new output object on every execution is a double-edged sword: on one hand, it can be convenient to delegate creation to the Op. On the other hand, output creation can be expensive and unnecessary if the Op is called many times. |
| 44 | + |
| 45 | +## Inplaces |
| 46 | + |
| 47 | +A **Inplace** accepts `n` input parameters, **only one** of which is mutable. Their singular method, `mutate()`, executes an algorithm and *overwrites* the single mutable parameter with the algorithm results. |
| 48 | + |
| 49 | +For example, consider the following pseudocode, which mutates a list of integers `inList` by adding the integer `val` to each: |
| 50 | +```text |
| 51 | +math.add(inList: list[int], val: int): |
| 52 | + for i in 1..size(inList): |
| 53 | + inList[i] = inList[i] + val |
| 54 | +``` |
| 55 | + |
| 56 | +A major advantage of Inplaces is the efficiency gained by the absence of an output buffer. On the other hand, the input data is lost through computation. |
| 57 | + |
| 58 | +## OpEnvironment |
| 59 | + |
| 60 | +The Op environment collects all available Ops, and provides access to their functionality. `OpEnvironment` objects are instantiated using the line shown below, and once created will contain all available Ops: |
| 61 | +```java |
| 62 | +OpEnvironment ops = OpEnvironment.build(); |
| 63 | +``` |
| 64 | + |
| 65 | +With an `OpEnvironment`, users can: |
| 66 | +* Find Ops, using the `OpEnvironment.help()` API (see [Searching For Ops](SearchingForOps.md)) |
| 67 | +* Execute Ops, using the `OpEnvironment.op()` API (see [Calling Ops](CallingOps.md), and the `OpBuilder` section below.) |
| 68 | + |
| 69 | +## OpBuilder |
| 70 | + |
| 71 | +The `OpBuilder` constructs an Op request piece-by-piece using many function calls. The name Op Builder draws upon the [builder pattern](https://refactoring.guru/design-patterns/builder) it follows, and an Op Builder construction is started via the method `OpEnvironment.op()`. |
| 72 | + |
| 73 | +The Op Builder syntax is extremely powerful, as learning to use it enables the execution of any Op in the Op environment, regardless of the language or library that it comes from. See [Calling Ops](CallingOps.md) for a tutorial on the Op Builder! |
0 commit comments