Skip to content

Commit 862f848

Browse files
elevanshinerm
authored andcommitted
Refactor deconvolution namespace
- Create the accelerator Op only in one place (RichardsonLucyC.java). - Use copy.rai op in VectorAccelerator. - Add copyright info to AccelerationState.java
1 parent c74feb7 commit 862f848

File tree

7 files changed

+71
-61
lines changed

7 files changed

+71
-61
lines changed

scijava-ops-image/src/main/java/org/scijava/ops/image/deconvolve/AccelerationState.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,32 @@
1+
/*
2+
* #%L
3+
* ImageJ2 software for multidimensional image processing and analysis.
4+
* %%
5+
* Copyright (C) 2014 - 2023 ImageJ2 developers.
6+
* %%
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
* #L%
28+
*/
29+
130
package org.scijava.ops.image.deconvolve;
231

332
import net.imglib2.RandomAccessibleInterval;

scijava-ops-image/src/main/java/org/scijava/ops/image/deconvolve/PadAndRichardsonLucy.java

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ public class PadAndRichardsonLucy<I extends RealType<I> & NativeType<I>, O exten
7979
@OpDependency(name = "math.multiply")
8080
private Computers.Arity2<RandomAccessibleInterval<O>, RandomAccessibleInterval<O>, RandomAccessibleInterval<O>> multiplyOp;
8181

82-
@OpDependency(name = "deconvolve.accelerate")
83-
private Inplaces.Arity1<AccelerationState<O>> accelerator;
84-
8582
// TODO: can this go in AbstractFFTFilterF?
8683
@OpDependency(name = "create.img")
8784
private BiFunction<Dimensions, O, RandomAccessibleInterval<O>> outputCreator;
@@ -98,7 +95,7 @@ public class PadAndRichardsonLucy<I extends RealType<I> & NativeType<I>, O exten
9895
@OpDependency(name = "deconvolve.richardsonLucy")
9996
private Computers.Arity12<RandomAccessibleInterval<I>, RandomAccessibleInterval<K>, //
10097
RandomAccessibleInterval<C>, RandomAccessibleInterval<C>, Boolean, //
101-
Boolean, C, Integer, Inplaces.Arity1<AccelerationState<O>>, //
98+
Boolean, C, Integer, Boolean, //
10299
Computers.Arity1<RandomAccessibleInterval<O>, RandomAccessibleInterval<O>>, //
103100
List<Inplaces.Arity1<RandomAccessibleInterval<O>>>, //
104101
RandomAccessibleInterval<O>, RandomAccessibleInterval<O>> richardsonLucyOp;
@@ -136,17 +133,17 @@ public class PadAndRichardsonLucy<I extends RealType<I> & NativeType<I>, O exten
136133

137134
return (input, kernel, out) -> {
138135
richardsonLucyOp.compute(input, kernel, fftImg, fftKernel, true, true,
139-
complexType, maxIterations, accelerate ? accelerator : null,
140-
computeEstimateOp, list, firstGuess.apply(raiExtendedInput, Util
141-
.getTypeFromInterval(out), out), out);
136+
complexType, maxIterations, accelerate, computeEstimateOp, list,
137+
firstGuess.apply(raiExtendedInput, Util.getTypeFromInterval(out),
138+
out), out);
142139
};
143140
}
144141

145142
// return a richardson lucy computer
146143
return (input, kernel, out) -> {
147144
richardsonLucyOp.compute(input, kernel, fftImg, fftKernel, true, true,
148-
complexType, maxIterations, accelerate ? accelerator : null,
149-
computeEstimateOp, null, null, out);
145+
complexType, maxIterations, accelerate, computeEstimateOp, null, null,
146+
out);
150147
};
151148
}
152149

@@ -241,9 +238,8 @@ else if (nonCirculant) {
241238
}
242239

243240
// default to no acceleration
244-
if (accelerate == null) {
245-
accelerate = false;
246-
}
241+
if (accelerate == null) accelerate = false;
242+
247243
this.maxIterations = maxIterations;
248244

249245
RandomAccessibleInterval<O> output = outputCreator.apply(input, outType);

scijava-ops-image/src/main/java/org/scijava/ops/image/deconvolve/PadAndRichardsonLucyTV.java

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,6 @@ public class PadAndRichardsonLucyTV<I extends RealType<I> & NativeType<I>, O ext
8383
@OpDependency(name = "deconvolve.firstGuess")
8484
private Functions.Arity3<RandomAccessibleInterval<I>, O, Dimensions, RandomAccessibleInterval<O>> firstGuess;
8585

86-
@OpDependency(name = "deconvolve.accelerate")
87-
private Inplaces.Arity1<AccelerationState<O>> accelerator;
88-
8986
// TODO: can this go in AbstractFFTFilterF?
9087
@OpDependency(name = "create.img")
9188
private BiFunction<Dimensions, O, RandomAccessibleInterval<O>> outputCreator;
@@ -102,7 +99,7 @@ public class PadAndRichardsonLucyTV<I extends RealType<I> & NativeType<I>, O ext
10299
@OpDependency(name = "deconvolve.richardsonLucy")
103100
private Computers.Arity12<RandomAccessibleInterval<I>, RandomAccessibleInterval<K>, //
104101
RandomAccessibleInterval<C>, RandomAccessibleInterval<C>, Boolean, //
105-
Boolean, C, Integer, Inplaces.Arity1<AccelerationState<O>>, //
102+
Boolean, C, Integer, Boolean, //
106103
Computers.Arity1<RandomAccessibleInterval<O>, RandomAccessibleInterval<O>>, //
107104
List<Inplaces.Arity1<RandomAccessibleInterval<O>>>, RandomAccessibleInterval<O>, //
108105
RandomAccessibleInterval<O>> richardsonLucyOp;
@@ -119,7 +116,7 @@ public class PadAndRichardsonLucyTV<I extends RealType<I> & NativeType<I>, O ext
119116
createFilterComputer(RandomAccessibleInterval<I> raiExtendedInput,
120117
RandomAccessibleInterval<K> raiExtendedKernel,
121118
RandomAccessibleInterval<C> fftImg, RandomAccessibleInterval<C> fftKernel,
122-
RandomAccessibleInterval<O> output)
119+
boolean accelerate, RandomAccessibleInterval<O> output)
123120
{
124121

125122
final C complexType = Util.getTypeFromInterval(fftImg).createVariable();
@@ -147,15 +144,15 @@ public class PadAndRichardsonLucyTV<I extends RealType<I> & NativeType<I>, O ext
147144

148145
return (input, kernel, out) -> {
149146
richardsonLucyOp.compute(input, kernel, fftImg, fftKernel, true, true,
150-
complexType, maxIterations, accelerator, computeEstimateOp, list, fg
147+
complexType, maxIterations, accelerate, computeEstimateOp, list, fg
151148
.apply(raiExtendedInput), out);
152149
};
153150
}
154151

155152
// return a richardson lucy computer
156153
return (input, kernel, out) -> {
157154
richardsonLucyOp.compute(input, kernel, fftImg, fftKernel, true, true,
158-
complexType, maxIterations, accelerator, computeEstimateOp, null, null,
155+
complexType, maxIterations, accelerate, computeEstimateOp, null, null,
159156
out);
160157
};
161158
}
@@ -166,7 +163,8 @@ public class PadAndRichardsonLucyTV<I extends RealType<I> & NativeType<I>, O ext
166163
*/
167164
public void computeFilter(final RandomAccessibleInterval<I> input,
168165
final RandomAccessibleInterval<K> kernel,
169-
RandomAccessibleInterval<O> output, long[] paddedSize, C complexType)
166+
RandomAccessibleInterval<O> output, long[] paddedSize, C complexType,
167+
boolean accelerate)
170168
{
171169

172170
RandomAccessibleInterval<C> fftInput = createOp.apply(new FinalDimensions(
@@ -180,7 +178,8 @@ public void computeFilter(final RandomAccessibleInterval<I> input,
180178
// memory
181179
// for the FFTs
182180
Computers.Arity2<RandomAccessibleInterval<I>, RandomAccessibleInterval<K>, RandomAccessibleInterval<O>> filter =
183-
createFilterComputer(input, kernel, fftInput, fftKernel, output);
181+
createFilterComputer(input, kernel, fftInput, fftKernel, accelerate,
182+
output);
184183

185184
filter.compute(input, kernel, output);
186185
}
@@ -203,7 +202,7 @@ public void computeFilter(final RandomAccessibleInterval<I> input,
203202
@Override
204203
public RandomAccessibleInterval<O> apply(RandomAccessibleInterval<I> input,
205204
RandomAccessibleInterval<K> kernel, O outType, C complexType,
206-
Integer maxIterations, Boolean nonCirculant, Boolean accelerate,
205+
Integer maxIterations, @Nullable Boolean nonCirculant, @Nullable Boolean accelerate,
207206
Float regularizationFactor, @Nullable long[] borderSize,
208207
@Nullable OutOfBoundsFactory<I, RandomAccessibleInterval<I>> obfInput)
209208
{
@@ -230,6 +229,9 @@ else if (nonCirculant) {
230229
}
231230
}
232231

232+
// default to no acceleration
233+
if (accelerate == null) accelerate = false;
234+
233235
this.maxIterations = maxIterations;
234236
this.regularizationFactor = regularizationFactor;
235237

@@ -264,7 +266,8 @@ else if (nonCirculant) {
264266
RandomAccessibleInterval<K> paddedKernel = padKernelOp.apply(kernel,
265267
new FinalDimensions(paddedSize));
266268

267-
computeFilter(paddedInput, paddedKernel, output, paddedSize, complexType);
269+
computeFilter(paddedInput, paddedKernel, output, paddedSize, complexType,
270+
accelerate);
268271

269272
return output;
270273
}

scijava-ops-image/src/main/java/org/scijava/ops/image/deconvolve/RichardsonLucyC.java

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
public class RichardsonLucyC<I extends RealType<I>, O extends RealType<O>, K extends RealType<K>, C extends ComplexType<C>>
6262
implements
6363
Computers.Arity12<RandomAccessibleInterval<I>, RandomAccessibleInterval<K>, RandomAccessibleInterval<C>, //
64-
RandomAccessibleInterval<C>, Boolean, Boolean, C, Integer, Inplaces.Arity1<AccelerationState<O>>, //
64+
RandomAccessibleInterval<C>, Boolean, Boolean, C, Integer, Boolean, //
6565
Computers.Arity1<RandomAccessibleInterval<O>, RandomAccessibleInterval<O>>, //
6666
List<Inplaces.Arity1<RandomAccessibleInterval<O>>>, RandomAccessibleInterval<O>, RandomAccessibleInterval<O>> {
6767

@@ -77,6 +77,9 @@ public class RichardsonLucyC<I extends RealType<I>, O extends RealType<O>, K ext
7777
RandomAccessibleInterval<O> //
7878
> rlCorrectionOp;
7979

80+
@OpDependency(name = "deconvolve.accelerate")
81+
private Inplaces.Arity1<AccelerationState<O>> accelerator;
82+
8083
@OpDependency(name = "create.img")
8184
private BiFunction<Interval, O, Img<O>> createOp;
8285

@@ -107,8 +110,7 @@ public class RichardsonLucyC<I extends RealType<I>, O extends RealType<O>, K ext
107110
* been calculated. If true, the FFT will be taken on the kernel.
108111
* @param complexType An instance of the type to be used in the Fourier space.
109112
* @param maxIterations Maximum number of iterations to perform.
110-
* @param accelerator An op which implements an acceleration strategy (takes a
111-
* larger step at each iteration).
113+
* @param accelerate indicates whether or not to use acceleration
112114
* @param updateOp Op that computes Richardson Lucy update, can be overridden
113115
* to implement variations of the algorithm (like RichardsonLucyTV).
114116
* @param iterativePostProcessingOps A list of optional constraints that are
@@ -129,17 +131,12 @@ public void compute(RandomAccessibleInterval<I> in, //
129131
Boolean performKernelFFT, //
130132
C complexType, //
131133
Integer maxIterations, //
132-
@Nullable Inplaces.Arity1<AccelerationState<O>> accelerator, //
134+
@Nullable Boolean accelerate, //
133135
@Nullable Computers.Arity1<RandomAccessibleInterval<O>, RandomAccessibleInterval<O>> updateOp, //
134136
@Nullable List<Inplaces.Arity1<RandomAccessibleInterval<O>>> iterativePostProcessingOps, //
135137
@Nullable RandomAccessibleInterval<O> raiExtendedEstimate, //
136138
RandomAccessibleInterval<O> out //
137139
) {
138-
139-
// If the accelerator is null, make a No-op placeholder
140-
if (accelerator == null) {
141-
accelerator = (t) -> {};
142-
}
143140
// If the update Op is null, use the default
144141
if (updateOp == null) {
145142
updateOp = this.updateOp;
@@ -164,11 +161,11 @@ public void compute(RandomAccessibleInterval<I> in, //
164161
// perform fft of psf
165162
fftKernelOp.compute(kernel, fftKernel);
166163

167-
// -- perform iterations --
168-
169164
// create acceleration state
170165
AccelerationState<O> state = new AccelerationState<>(raiExtendedEstimate);
171166

167+
// -- perform iterations --
168+
172169
for (int i = 0; i < maxIterations; i++) {
173170

174171
// create reblurred by convolving kernel with estimate
@@ -189,9 +186,9 @@ public void compute(RandomAccessibleInterval<I> in, //
189186
for (Inplaces.Arity1<RandomAccessibleInterval<O>> pp : iterativePostProcessingOps) {
190187
pp.mutate(raiExtendedEstimate);
191188
}
192-
189+
193190
// accelerate the algorithm by taking a larger step
194-
accelerator.mutate(state);
191+
if (accelerate) accelerator.mutate(state);
195192
}
196193

197194
// -- copy crop padded back to original size

scijava-ops-image/src/main/java/org/scijava/ops/image/deconvolve/VectorAccelerator.java

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import net.imglib2.util.Util;
4141
import net.imglib2.view.Views;
4242

43+
import org.scijava.function.Computers;
4344
import org.scijava.function.Inplaces;
4445
import org.scijava.ops.spi.OpDependency;
4546

@@ -56,6 +57,9 @@ public class VectorAccelerator<T extends RealType<T>> implements
5657
Inplaces.Arity1<AccelerationState<T>>
5758
{
5859

60+
@OpDependency(name = "copy.rai")
61+
private Computers.Arity1<RandomAccessibleInterval<T>, RandomAccessibleInterval<T>> copyOp;
62+
5963
@OpDependency(name = "create.img")
6064
private BiFunction<Dimensions, T, Img<T>> create;
6165

@@ -122,14 +126,14 @@ private void accelerate(AccelerationState<T> state) {
122126
// TODO: Revisit where initialization should be done
123127
initialize(state);
124128

125-
Copy(xk_estimate, state.yk_prediction);
129+
copyOp.compute(xk_estimate, state.yk_prediction);
126130
}
127131

128132
// make a copy of the estimate to use as previous next time
129-
Copy(xk_estimate, state.xkm1_previous);
133+
copyOp.compute(xk_estimate, state.xkm1_previous);
130134

131135
// HACK: TODO: look over how to transfer the memory
132-
Copy(state.yk_prediction, state.yk_iterated);
136+
copyOp.compute(state.yk_prediction, state.yk_iterated);
133137
}
134138

135139
private double computeAccelerationFactor(AccelerationState<T> state) {
@@ -173,23 +177,6 @@ private double DotProduct(final Img<T> image1, final Img<T> image2) {
173177
return dotProduct;
174178
}
175179

176-
// TODO replace with Op
177-
// copy a into b
178-
private void Copy(RandomAccessibleInterval<T> a,
179-
RandomAccessibleInterval<T> b)
180-
{
181-
182-
final Cursor<T> cursorA = Views.iterable(a).cursor();
183-
final Cursor<T> cursorB = Views.iterable(b).cursor();
184-
185-
while (cursorA.hasNext()) {
186-
cursorA.fwd();
187-
cursorB.fwd();
188-
189-
cursorB.get().set(cursorA.get());
190-
}
191-
}
192-
193180
// TODO replace with op.
194181
private void Subtract(RandomAccessibleInterval<T> a,
195182
RandomAccessibleInterval<T> input, RandomAccessibleInterval<T> output)

scijava-ops-image/src/test/java/org/scijava/ops/image/OpRegressionTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public class OpRegressionTest {
4242

4343
@Test
4444
public void opDiscoveryRegressionIT() {
45-
long expected = 1921;
45+
long expected = 1923;
4646
long actual = ops.infos().size();
4747
assertEquals(expected, actual);
4848
}

scijava-ops-image/src/test/java/org/scijava/ops/image/deconvolve/DeconvolveTest.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ convolved, kernel, new FloatType(), new ComplexFloatType(), 10, true,
158158

159159
// find a RichardsonLucyC op
160160
Computers.Arity12<RandomAccessibleInterval<FloatType>, RandomAccessibleInterval<FloatType>, RandomAccessibleInterval<ComplexFloatType>, //
161-
RandomAccessibleInterval<ComplexFloatType>, Boolean, Boolean, ComplexFloatType, Integer, Inplaces.Arity1<AccelerationState<FloatType>>, //
161+
RandomAccessibleInterval<ComplexFloatType>, Boolean, Boolean, ComplexFloatType, Integer, Boolean, //
162162
Computers.Arity1<RandomAccessibleInterval<FloatType>, RandomAccessibleInterval<FloatType>>, //
163163
List<Inplaces.Arity1<RandomAccessibleInterval<FloatType>>>, RandomAccessibleInterval<FloatType>, RandomAccessibleInterval<FloatType>> deconvolveOpC =
164164
ops.op("deconvolve.richardsonLucy", new Nil<>()
@@ -174,9 +174,7 @@ convolved, kernel, new FloatType(), new ComplexFloatType(), 10, true,
174174
new Nil<Boolean>()
175175
{}, new Nil<Boolean>() {}, new Nil<ComplexFloatType>() {}, //
176176
new Nil<Integer>()
177-
{},
178-
new Nil<Inplaces.Arity1<AccelerationState<FloatType>>>()
179-
{}, //
177+
{}, new Nil<Boolean>() {}, //
180178
new Nil<Computers.Arity1<RandomAccessibleInterval<FloatType>, RandomAccessibleInterval<FloatType>>>()
181179
{}, //
182180
new Nil<List<Inplaces.Arity1<RandomAccessibleInterval<FloatType>>>>()

0 commit comments

Comments
 (0)