This page is designed to help Ops users understand the SciJava Ops concepts powering the framework.
An algorithm is a mathematical routine that transforms, interrogate, or refines input values into output values. Algorithms are used throughout scientific computing, and the fundamental purpose of SciJava Ops is to facilitate their application.
We do that by providing a framework for consistently defining and invoking algorithm implementations as Ops. Ops have:
- a name, establishing its purpose. An Op's name describes what the Op does, but not how the Op does it.
- An Op adding two numbers would be named
math.add, as would an Op adding two images - 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.
- An Op adding two numbers would be named
- a number of inputs and outputs, defined by language-specific types.
- A
math.addOp might take two JavaIntegerinputs and return a JavaIntegeroutput - A
filter.convolveOp might take two OpenCVMatinputs, storing the convolved result into an OpenCVMatoutput buffer.
- A
- behavior adhering to one of the three Op types defined below.
Computer Ops accept any number of immutable inputs and exactly one mutable container as parameters. When the algorithm they define is executed, the result is stored within the container parameter, overwriting its contents. The initial contents of the container do not affect computation.
For example, consider the following pseudocode, which populates a list of integers (outList) with the elementwise addition of an integer constant (value) to a provided list of integers (inList):
math.add(inList: list[int], value: int, outList: list[int]):
outList.clear()
for i in 1..size(inList):
outList[i] = inList[i] + value
Function Ops accept any number of immutable inputs as parameters. When the algorithm they define is executed, the result is returned as a new output to the user.
For example, consider the following pseudocode, which creates a list of integers from the elementwise addition of an integer constant (value) to the provided list of integers (inList):
math.add(inList: list[int], value: int) -> list[int]:
outList = list()
for i in 1..size(inList):
outList[i] = inList[i] + value
return outList
An advantage of Functions is their convenience. However, output creation can be expensive and unnecessary if the Op is called many times.
Inplace Ops accept any number of input parameters, exactly one of which is mutable. When the algorithm they define is executed, the mutable parameter is modified as a result of computation.
For example, consider the following pseudocode, which modifies a provided list of integers (inList) by adding an integer constant (value) to each element:
math.add(inList: list[int], value: int):
for i in 1..size(inList):
inList[i] = inList[i] + value
An advantage of Inplaces is both the convenience and savings (in time and memory) of not creating an output. On the other hand, the input data is lost through computation, and some algorithms require the input to remain unmodified (e.g. for neighborhood calculations).
The Op environment collects all available Ops, and serves as a gateway for accessing their functionality. Obtaining an OpEnvironment is the first step for any Ops use.
With an OpEnvironment, users can:
- Find Ops, using the
OpEnvironment.help()API (see Searching For Ops) - Execute Ops, using the
OpEnvironment.op()API (see Calling Ops)
The OpBuilder constructs an Op request piece-by-piece using many function calls. The name Op Builder draws upon the builder pattern it follows, and an Op Builder construction is started via the method OpEnvironment.op().
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 for a tutorial on the Op Builder!