You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/ops/doc/ParameterConversion.rst
+15-15Lines changed: 15 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,7 +37,7 @@ Suppose we have a ``Function`` Op that inherently operates on ``RandomAccessible
37
37
// convolve convolve convolve //
38
38
}
39
39
40
-
This Op might work well, however if users have a smallkernel 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:
41
41
42
42
43
43
.. code-block:: java
@@ -60,12 +60,12 @@ This Op might work well, however if users have a small kernel that is *only* use
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.
64
64
65
65
An ``engine.convert`` Op
66
66
==============================
67
67
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>``:
69
69
70
70
.. code-block:: java
71
71
@@ -88,7 +88,7 @@ All ``engine.convert`` Ops are simple ``Function``\ s, that take as input the us
88
88
return img;
89
89
}
90
90
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**.
92
92
93
93
.. code-block:: java
94
94
@@ -108,19 +108,18 @@ This Op, discovered through the SciJava Ops Indexer, is enables the execution pa
108
108
109
109
At runtime, the Op matcher will invoke the following steps:
110
110
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.
112
112
* 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.
116
115
117
116
118
117
Adding efficiency
119
118
=================
120
119
121
120
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.
122
121
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:
124
123
125
124
.. code-block:: java
126
125
@@ -171,13 +170,12 @@ Now, imagine that the user wished to execute the Op using **only** ``double[][]`
171
170
{ 1/9, 1/9, 1/9} //
172
171
};
173
172
174
-
// Ideal case - no need to wrap to Img
175
173
double[][] result = ops.op("filter.convolve") //
176
174
.input(in, kernel) //
177
175
.outType(double[][].class) //
178
176
.apply();
179
177
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[][]``:
181
179
182
180
.. code-block:: java
183
181
@@ -210,10 +208,12 @@ When the user tries to invoke our ``filter.convolve`` ``Function`` Op on all ``d
210
208
#. The output ``RandomAccessibleInterval<DoubleType>`` is converted into a ``double[][]`` using our ``engine.convert(in: RandomAccessibleInterval<DoubleType>) -> double[][]`` Op.
211
209
#. The **converted** ``double[][]`` output is returned to the user.
212
210
211
+
The result is offering to the user a ``filter.convolve(input: double[][], kernel: double[][]) -> double[][]`` Op, even though we never wrote one!
212
+
213
213
Converting ``Computer`` and ``Inplace`` outputs
214
214
===============================================
215
215
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``.
217
217
218
218
.. code-block:: java
219
219
@@ -233,7 +233,7 @@ Consider our ``filter.convolve`` Op example, instead written as a ``Computer``.
233
233
// convolve convolve convolve //
234
234
}
235
235
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:
237
237
238
238
.. code-block:: java
239
239
@@ -248,9 +248,9 @@ If we want to call this Op using *only* ``double[][]``\ s, as so, we will certai
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.
252
252
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**.
254
254
255
255
Below is an ``engine.copy`` Op that would store the converted Op's output ``double[][]`` back into the user's Object:
0 commit comments