Skip to content

Commit 5359adc

Browse files
committed
ParameterConversion: More small fixes
1 parent 8118fcc commit 5359adc

1 file changed

Lines changed: 15 additions & 15 deletions

File tree

docs/ops/doc/ParameterConversion.rst

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Suppose we have a ``Function`` Op that inherently operates on ``RandomAccessible
3737
// convolve convolve convolve //
3838
}
3939
40-
This Op might work well, however if users have a small kernel that is *only* used for this Op, they may find it frustrating to represent that data as a ``RandomAccessibleInterval``. Fortunately, SciJava Ops allows us to write ``engine.convert`` Ops, so users can pass their data in a data structure more convenient for them.
40+
Suppose a user wants to use this Op with a small, fixed kernel, which for ease is written as a ``double[][]``. Without additional aid, they'd have to manually convert their ``double[][]`` into a ``RandomAccessibleInterval<DoubleType>``, requiring knowledge of how to do that and baking extra boilerplate into their workflow:
4141

4242

4343
.. code-block:: java
@@ -60,12 +60,12 @@ This Op might work well, however if users have a small kernel that is *only* use
6060
.outType(new Nil<RandomAccessibleInterval<DoubleType>>() {}) //
6161
.apply();
6262
63-
In this case, users might find it nicer to specify their kernel as a ``double[][]``, which is easier for users to construct. The only step for us as the developer is to tell SciJava Ops that it can convert ``double[][]``\ s to ``RandomAccessibleInterval<DoubleType>``\ s, which we do with ``engine.convert`` Ops.
63+
Ideally, the user could just pass their ``double[][]`` to their Op matching call directly. Parameter conversion enables this, through the use of ``engine.convert`` Ops written by developers.
6464

6565
An ``engine.convert`` Op
6666
==============================
6767

68-
All ``engine.convert`` Ops are simple ``Function``\ s, that take as input the user argument to the Op, and return a *translation* of that data into the type expected by Ops. In our case, we want to convert *from* the user's ``double[][]`` into a ``RandomAccessibleInterval<DoubleType>``:
68+
All ``engine.convert`` Ops are simple ``Function``\ s that are given user arguments and return a *translation* of that data into the type expected by the Op. For our example ``Function``, we want to convert *from* the user's ``double[][]`` into a ``RandomAccessibleInterval<DoubleType>``:
6969

7070
.. code-block:: java
7171
@@ -88,7 +88,7 @@ All ``engine.convert`` Ops are simple ``Function``\ s, that take as input the us
8888
return img;
8989
}
9090
91-
This Op, discovered through the SciJava Ops Indexer, is enables the execution pattern we want.
91+
Using this ``engine.convert`` Op, SciJava Ops can match our ``filter.convolve`` Op to the user's data, **without explicit translation**.
9292

9393
.. code-block:: java
9494
@@ -108,19 +108,18 @@ This Op, discovered through the SciJava Ops Indexer, is enables the execution pa
108108
109109
At runtime, the Op matcher will invoke the following steps:
110110

111-
* The ``Img<DoubleType> input`` is left alone, as it is a ``RandomAccessibleInterval<DoubleType>``
111+
* The ``Img<DoubleType> input`` is left alone, as it is already of the type expected by the Op.
112112
* The ``double[][] kernel`` is converted to a ``RandomAccessibleInterval<DoubleType> kernel1`` using our ``engine.convert`` Op.
113-
* The Op convolves ``input1`` with ``kernel1``, returning an ``Img<DoubleType>``
114-
* The ``RandomAccessibleInterval<DoubleType> output1`` is converted to a ``double[][] output2``
115-
* Nothing is returned
113+
* The Op convolves ``input1`` with ``kernel1``, returning an ``Img<DoubleType> output1``
114+
* The ``Img<DoubleType> input1`` is left alone and returned to the user, as it is already of the type expected by the user.
116115

117116

118117
Adding efficiency
119118
=================
120119

121120
While the above ``engine.convert`` Op is *functional*, it may not be *fast* as the data size increases. This is due to the **copy** inherent in its execution, as the ``ArrayImg`` contains new data structures.
122121

123-
In such cases, devising methods to *wrap* the user arguments, instead of *copying* it, will maximize performance and wow your users. In our case, we can refine our ``engine.convert`` Op to wrap user data, using the ``DoubleAccess`` interface of ImgLib2:
122+
In such cases, devising methods to instead *wrap* user arguments will maximize performance and wow your users. In our case, we can refine our ``engine.convert`` Op to wrap user data, using the ``DoubleAccess`` interface of ImgLib2:
124123

125124
.. code-block:: java
126125
@@ -171,13 +170,12 @@ Now, imagine that the user wished to execute the Op using **only** ``double[][]`
171170
{ 1/9, 1/9, 1/9} //
172171
};
173172
174-
// Ideal case - no need to wrap to Img
175173
double[][] result = ops.op("filter.convolve") //
176174
.input(in, kernel) //
177175
.outType(double[][].class) //
178176
.apply();
179177
180-
Looking back at our :ref:`original Op<original-op>`, we would have to write an *additional* converter, to turn the output ``RandomAccessibleInterval<DoubleType>`` into a ``double[][]``:
178+
Looking back at our :ref:`original Op<original-op>`, we would have to write an *additional* converter to turn the output ``RandomAccessibleInterval<DoubleType>`` back into a ``double[][]``:
181179

182180
.. code-block:: java
183181
@@ -210,10 +208,12 @@ When the user tries to invoke our ``filter.convolve`` ``Function`` Op on all ``d
210208
#. The output ``RandomAccessibleInterval<DoubleType>`` is converted into a ``double[][]`` using our ``engine.convert(in: RandomAccessibleInterval<DoubleType>) -> double[][]`` Op.
211209
#. The **converted** ``double[][]`` output is returned to the user.
212210

211+
The result is offering to the user a ``filter.convolve(input: double[][], kernel: double[][]) -> double[][]`` Op, even though we never wrote one!
212+
213213
Converting ``Computer`` and ``Inplace`` outputs
214214
===============================================
215215

216-
Consider our ``filter.convolve`` Op example, instead written as a ``Computer``.
216+
Finally, consider our ``filter.convolve`` Op example, instead written as a ``Computer``.
217217

218218
.. code-block:: java
219219
@@ -233,7 +233,7 @@ Consider our ``filter.convolve`` Op example, instead written as a ``Computer``.
233233
// convolve convolve convolve //
234234
}
235235
236-
If we want to call this Op using *only* ``double[][]``\ s, as so, we will certainly need the ``engine.convert(in: double[][]) -> RandomAccessibleInterval<DoubleType>`` Op and the ``engine.convert(in: RandomAccessibleInterval<DoubleType>) -> double[][]`` Op we wrote above:
236+
Suppose that again the user wants to call this Op using *only* ``double[][]``\ s:
237237

238238
.. code-block:: java
239239
@@ -248,9 +248,9 @@ If we want to call this Op using *only* ``double[][]``\ s, as so, we will certai
248248
249249
ops.op("filter.convolve").input(in, kernel).output(result).apply();
250250
251-
However, if we follow the same procedure with :ref:`Functions <function-output>`, the user will not see the output in their ``result`` object. This is because many ``engine.convert`` Ops (including the one we wrote :ref:`above <function-output>` for our ``RandomAccessibleInterval``, and the original converter we wrote for the input ``double[][]``\ s), make *deep copies* instead of wrapping the user arguments. Indeed, SciJava Ops cannot guarantee that ``engine.convert`` Ops wrap user arguments, so without an additional step parameter conversion would not work for output buffers.
251+
We will certainly need the ``engine.convert(in: double[][]) -> RandomAccessibleInterval<DoubleType>`` Op and the ``engine.convert(in: RandomAccessibleInterval<DoubleType>) -> double[][]`` Op we wrote above, however if we follow the same procedure with :ref:`Functions <function-output>`, the user will not see the output in their ``result`` object. This is because many ``engine.convert`` Ops (including the original converter we wrote for the input ``double[][]``\ s) make *deep copies* instead of wrapping the user arguments.
252252

253-
SciJava Ops remedies the situation by, after invoking the original Op and converting the output, calling an ``engine.copy`` Op to store the converted output *back into the user's object*. Thus, **if you want to enable parameter conversion on** ``Computer``\ **s or** ``Inplace``\ **s, you'll need** ``engine.copy`` **Ops too**.
253+
Indeed, SciJava Ops cannot guarantee that ``engine.convert`` Ops wrap user arguments, so without an additional step parameter conversion would not work for output buffers. SciJava Ops remedies the situation by calling an ``engine.copy`` Op to store the converted output *back into the user's object*. **If you want to enable parameter conversion on** ``Computer``\ **s or** ``Inplace``\ **s, you'll need** ``engine.copy`` **Ops too**.
254254

255255
Below is an ``engine.copy`` Op that would store the converted Op's output ``double[][]`` back into the user's Object:
256256

0 commit comments

Comments
 (0)