diff --git a/pom.xml b/pom.xml index d9aaf852d5e665d833c768682bf98b05d19de732..d91741a3d48489814111077e8469a2936f3246be 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ </parent> <artifactId>filter-toolbox</artifactId> - <version>4.4.4</version> + <version>5.0.0</version> <packaging>jar</packaging> diff --git a/src/main/java/plugins/adufour/filtering/Convolution.java b/src/main/java/plugins/adufour/filtering/Convolution.java index dc0f062ac9202152cbb7e78772ecd91bb15f290e..806f3a66bf813f33d61be414df42d5e7d4ca7413 100644 --- a/src/main/java/plugins/adufour/filtering/Convolution.java +++ b/src/main/java/plugins/adufour/filtering/Convolution.java @@ -1,8 +1,22 @@ -package plugins.adufour.filtering; +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ -import java.util.ArrayList; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; +package plugins.adufour.filtering; import icy.image.IcyBufferedImage; import icy.sequence.Sequence; @@ -12,6 +26,10 @@ import plugins.adufour.vars.lang.Var; import plugins.adufour.vars.lang.VarBoolean; import plugins.adufour.vars.util.VarListener; +import java.util.ArrayList; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + public class Convolution extends Filter { /** * Convolve the input sequence with the given kernel with the specified edge condition. The @@ -26,16 +44,16 @@ public class Convolution extends Filter { * @param nbIter the number of filter iterations * @param stopFlag boolean */ - public static void convolve(Sequence input, Sequence kernel, boolean zeroEdges, int nbIter, VarBoolean stopFlag) { + public static void convolve(final Sequence input, final Sequence kernel, final boolean zeroEdges, final int nbIter, final VarBoolean stopFlag) { final Convolution c = new Convolution(); - final VarListener<Boolean> l = new VarListener<Boolean>() { + final VarListener<Boolean> l = new VarListener<>() { @Override - public void valueChanged(Var<Boolean> source, Boolean oldValue, Boolean newValue) { + public void valueChanged(final Var<Boolean> source, final Boolean oldValue, final Boolean newValue) { c.stopFlag.setValue(newValue); } @Override - public void referenceChanged(Var<Boolean> source, Var<? extends Boolean> oldReference, Var<? extends Boolean> newReference) { + public void referenceChanged(final Var<Boolean> source, final Var<? extends Boolean> oldReference, final Var<? extends Boolean> newReference) { } }; @@ -45,8 +63,8 @@ public class Convolution extends Filter { Convolution.service.shutdown(); } - public Sequence convolve(final Sequence sequence, Sequence kernel, final boolean zeroEdges, int nbIter) { - Sequence out = new Sequence(sequence.getName() + "_" + getDescriptor().getName()); + public Sequence convolve(final Sequence sequence, final Sequence kernel, final boolean zeroEdges, final int nbIter) { + final Sequence out = new Sequence(sequence.getName() + "_" + getDescriptor().getName()); final int width = sequence.getSizeX(); final int height = sequence.getSizeY(); @@ -68,7 +86,7 @@ public class Convolution extends Filter { // create an array of tasks for multi-thread processing // => rationale: one task per image line - ArrayList<Future<?>> tasks = new ArrayList<>(height); + final ArrayList<Future<?>> tasks = new ArrayList<>(height); convolution: for (int t = 0; t < frames; t++) { @@ -119,8 +137,8 @@ public class Convolution extends Filter { inZ = (depth * 2) - inZ - 1; } - Object in_XY = in_Z_XY[inZ]; - double[] k_XY = _kernel[kZ]; + final Object in_XY = in_Z_XY[inZ]; + final double[] k_XY = _kernel[kZ]; kXY = 0; @@ -182,7 +200,7 @@ public class Convolution extends Filter { } // end for(y) try { - for (Future<?> f : tasks) + for (final Future<?> f : tasks) f.get(); // at this point all tasks are done so we can store result back @@ -192,7 +210,7 @@ public class Convolution extends Filter { // it won't copy data but at least does the data changed out.setDataXY(t, z, c, out_XY); } - catch (InterruptedException | ExecutionException e) { + catch (final InterruptedException | ExecutionException e) { e.printStackTrace(); } diff --git a/src/main/java/plugins/adufour/filtering/Convolution1D.java b/src/main/java/plugins/adufour/filtering/Convolution1D.java index 7ce8dcd94876faf2b25e031831d6df57f8408b66..bba600bdd94d73af74b28a64c7bfa6f58c8fea90 100644 --- a/src/main/java/plugins/adufour/filtering/Convolution1D.java +++ b/src/main/java/plugins/adufour/filtering/Convolution1D.java @@ -1,9 +1,22 @@ -package plugins.adufour.filtering; +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ -import java.util.ArrayList; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; +package plugins.adufour.filtering; import icy.sequence.Sequence; import icy.system.SystemUtil; @@ -13,6 +26,11 @@ import icy.type.collection.array.Array1DUtil; import plugins.adufour.filtering.FilterToolbox.Axis; import plugins.adufour.vars.lang.VarBoolean; +import java.util.ArrayList; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + /** * Spatial convolution for separable 1D kernels. * @@ -31,7 +49,7 @@ public class Convolution1D { * @param kernel1D_Z the kernel to use for convolution along Z * @throws ConvolutionException if a kernel is too large w.r.t. the image size */ - public static void convolve(Sequence sequence, Sequence kernel1D_X, Sequence kernel1D_Y, Sequence kernel1D_Z) + public static void convolve(final Sequence sequence, final Sequence kernel1D_X, final Sequence kernel1D_Y, final Sequence kernel1D_Z) throws ConvolutionException { convolve(sequence, kernel1D_X, kernel1D_Y, kernel1D_Z, 1, new VarBoolean("stop", false)); } @@ -50,8 +68,8 @@ public class Convolution1D { * @param stopFlag boolean * @throws ConvolutionException if a kernel is too large w.r.t. the image size */ - public static void convolve(Sequence sequence, Sequence kernel1D_X, Sequence kernel1D_Y, Sequence kernel1D_Z, - int nbIter, VarBoolean stopFlag) throws ConvolutionException { + public static void convolve(final Sequence sequence, final Sequence kernel1D_X, final Sequence kernel1D_Y, final Sequence kernel1D_Z, + final int nbIter, final VarBoolean stopFlag) throws ConvolutionException { if (kernel1D_X == null && kernel1D_Y == null && kernel1D_Z == null) throw new IllegalArgumentException("Invalid argument: provide at least one non-null kernel"); @@ -84,8 +102,8 @@ public class Convolution1D { double[] kernelY = null; double[] kernelZ = null; - DataType type = sequence.getDataType_(); - double[][] z_xy = new double[sequence.getSizeZ()][sequence.getSizeX() * sequence.getSizeY()]; + final DataType type = sequence.getDataType_(); + final double[][] z_xy = new double[sequence.getSizeZ()][sequence.getSizeX() * sequence.getSizeY()]; sequence.beginUpdate(); try { @@ -140,7 +158,7 @@ public class Convolution1D { * @throws IllegalArgumentException if all kernels are null or if a kernel has even size * @throws ConvolutionException if a kernel is too large w.r.t. the image size */ - public static void convolve(Sequence sequence, double[] kernelX, double[] kernelY, double[] kernelZ) + public static void convolve(final Sequence sequence, final double[] kernelX, final double[] kernelY, final double[] kernelZ) throws IllegalArgumentException, ConvolutionException { if (kernelX == null && kernelY == null && kernelZ == null) throw new IllegalArgumentException("Invalid argument: provide at least one non-null kernel"); @@ -151,8 +169,8 @@ public class Convolution1D { if (kernelZ != null && kernelZ.length % 2 == 0) throw new IllegalArgumentException("Invalid argument: kernel along Z has even size"); - DataType type = sequence.getDataType_(); - double[][] z_xy = new double[sequence.getSizeZ()][sequence.getSizeX() * sequence.getSizeY()]; + final DataType type = sequence.getDataType_(); + final double[][] z_xy = new double[sequence.getSizeZ()][sequence.getSizeX() * sequence.getSizeY()]; sequence.beginUpdate(); try { @@ -199,13 +217,13 @@ public class Convolution1D { * @param array 2D array * @throws ConvolutionException if a kernel is too large w.r.t the image size */ - public static void convolve(double[][] array, int imageWidth, int imageHeight, double[] kernelX, double[] kernelY, - double[] kernelZ) throws ConvolutionException { - Processor service = new Processor(SystemUtil.getNumberOfCPUs() * 2); + public static void convolve(final double[][] array, final int imageWidth, final int imageHeight, final double[] kernelX, final double[] kernelY, + final double[] kernelZ) throws ConvolutionException { + final Processor service = new Processor(SystemUtil.getNumberOfCPUs() * 2); - int sliceSize = array[0].length; + final int sliceSize = array[0].length; - double[][] temp = new double[array.length][sliceSize]; + final double[][] temp = new double[array.length][sliceSize]; try { if (array.length == 1) { @@ -273,10 +291,10 @@ public class Convolution1D { } } } - catch (InterruptedException e) { + catch (final InterruptedException e) { Thread.currentThread().interrupt(); } - catch (ExecutionException e) { + catch (final ExecutionException e) { e.printStackTrace(); } finally { @@ -299,17 +317,17 @@ public class Convolution1D { * @param axis the axis along which to convolve * @throws ConvolutionException if a kernel is too large w.r.t. the image size */ - public static void convolve1D(double[][] input, double[][] output, int width, int height, double[] kernel, - Axis axis) throws ConvolutionException { - Processor service = new Processor(SystemUtil.getNumberOfCPUs() * 2); + public static void convolve1D(final double[][] input, final double[][] output, final int width, final int height, final double[] kernel, + final Axis axis) throws ConvolutionException { + final Processor service = new Processor(SystemUtil.getNumberOfCPUs() * 2); try { convolve1D(service, input, output, width, height, kernel, axis); } - catch (InterruptedException e) { + catch (final InterruptedException e) { Thread.currentThread().interrupt(); } - catch (ExecutionException e) { + catch (final ExecutionException e) { e.printStackTrace(); } finally { @@ -334,8 +352,8 @@ public class Convolution1D { * @throws ExecutionException Error in execution * @throws InterruptedException Interruption */ - public static void convolve1D(ExecutorService service, final double[][] input, final double[][] output, - final int width, final int height, final double[] kernel, Axis axis) + public static void convolve1D(final ExecutorService service, final double[][] input, final double[][] output, + final int width, final int height, final double[] kernel, final Axis axis) throws ConvolutionException, InterruptedException, ExecutionException { try { final int sliceSize = input[0].length; @@ -344,7 +362,7 @@ public class Convolution1D { switch (axis) { case X: { - ArrayList<Future<?>> tasks = new ArrayList<>(input.length); + final ArrayList<Future<?>> tasks = new ArrayList<>(input.length); for (int z = 0; z < input.length; z++) { final double[] inSlice = input[z]; @@ -357,8 +375,8 @@ public class Convolution1D { // store the offset of the first and last elements of the line // they will be used to compute mirror conditions - int xStartOffset = xy; - int xEndOffset = xy + width - 1; + final int xStartOffset = xy; + final int xEndOffset = xy + width - 1; // convolve the west border (mirror condition) @@ -378,7 +396,7 @@ public class Convolution1D { // convolve the central area until the east border - int eastBorder = width - kRadius; + final int eastBorder = width - kRadius; for (; x < eastBorder; x++, xy++) { double value = 0; @@ -409,7 +427,7 @@ public class Convolution1D { })); } - for (Future<?> task : tasks) + for (final Future<?> task : tasks) task.get(); } @@ -418,7 +436,7 @@ public class Convolution1D { case Y: { final int kRadiusY = kRadius * width; - ArrayList<Future<?>> tasks = new ArrayList<>(input.length); + final ArrayList<Future<?>> tasks = new ArrayList<>(input.length); for (int z = 0; z < input.length; z++) { final double[] in = input[z]; @@ -434,7 +452,7 @@ public class Convolution1D { for (; y < kRadius; y++) { for (int x = 0; x < width; x++, xy++) { - int yStartOffset = x; + final int yStartOffset = x; double value = 0; @@ -452,7 +470,7 @@ public class Convolution1D { // convolve the central area until the south border - int southBorder = height - kRadius; + final int southBorder = height - kRadius; for (; y < southBorder; y++) { for (int x = 0; x < width; x++, xy++) { @@ -470,7 +488,7 @@ public class Convolution1D { for (; y < height; y++) { for (int x = 0; x < width; x++, xy++) { - int yEndOffset = sliceSize - width + x; + final int yEndOffset = sliceSize - width + x; double value = 0; @@ -488,14 +506,14 @@ public class Convolution1D { })); } - for (Future<?> task : tasks) + for (final Future<?> task : tasks) task.get(); } break; case Z: { - ArrayList<Future<?>> tasks = new ArrayList<>(input.length); + final ArrayList<Future<?>> tasks = new ArrayList<>(input.length); int z = 0; for (; z < kRadius; z++) { @@ -522,7 +540,7 @@ public class Convolution1D { })); } - int bottomBorder = input.length - kRadius; + final int bottomBorder = input.length - kRadius; for (; z < bottomBorder; z++) { final double[] out = output[z]; @@ -570,14 +588,14 @@ public class Convolution1D { })); } - for (Future<?> task : tasks) + for (final Future<?> task : tasks) task.get(); } break; } } - catch (ExecutionException e) { + catch (final ExecutionException e) { if (e.getCause() instanceof ArrayIndexOutOfBoundsException) { throw new ConvolutionException("Filter size is too large along " + axis.name(), e); } @@ -585,10 +603,10 @@ public class Convolution1D { throw e; } } - catch (ArrayIndexOutOfBoundsException e) { + catch (final ArrayIndexOutOfBoundsException e) { throw new ConvolutionException("Filter size is too large along " + axis.name(), e); } - catch (RuntimeException e) { + catch (final RuntimeException e) { e.printStackTrace(); } } diff --git a/src/main/java/plugins/adufour/filtering/ConvolutionCL.java b/src/main/java/plugins/adufour/filtering/ConvolutionCL.java index 70d97bbe033056a6db614e7e8d8422f4276c9121..83974ced2e815bdeaf3eb900a98d870ee2ee57e5 100644 --- a/src/main/java/plugins/adufour/filtering/ConvolutionCL.java +++ b/src/main/java/plugins/adufour/filtering/ConvolutionCL.java @@ -1,77 +1,88 @@ -package plugins.adufour.filtering; +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; +package plugins.adufour.filtering; -import com.nativelibs4java.opencl.CLContext; -import com.nativelibs4java.opencl.CLEvent; -import com.nativelibs4java.opencl.CLException; -import com.nativelibs4java.opencl.CLFloatBuffer; -import com.nativelibs4java.opencl.CLKernel; +import com.nativelibs4java.opencl.*; import com.nativelibs4java.opencl.CLMem.MapFlags; import com.nativelibs4java.opencl.CLMem.Usage; -import com.nativelibs4java.opencl.CLProgram; -import com.nativelibs4java.opencl.CLQueue; - import icy.image.IcyBufferedImage; import icy.sequence.Sequence; import icy.type.DataType; import icy.type.collection.array.Array1DUtil; import plugins.adufour.vars.lang.VarBoolean; +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; + public class ConvolutionCL { public final CLProgram clProgram; public final CLContext clContext; public final CLQueue clQueue; public final CLEvent clEvent = null; - public ConvolutionCL(CLContext context, CLProgram program, CLQueue queue) { + public ConvolutionCL(final CLContext context, final CLProgram program, final CLQueue queue) { clContext = context; clQueue = queue; clProgram = program; } - public void convolve(Sequence input, Sequence kernel, boolean zeroEdge, int nbIter, VarBoolean stopFlag) throws CLException { - String funcName = zeroEdge ? "convolve2D" : "convolve2D_mirror"; + public void convolve(final Sequence input, final Sequence kernel, final boolean zeroEdge, final int nbIter, final VarBoolean stopFlag) throws CLException { + final String funcName = zeroEdge ? "convolve2D" : "convolve2D_mirror"; - CLKernel clKernel; + final CLKernel clKernel; clKernel = clProgram.createKernel(funcName); - int dataSize = input.getSizeX() * input.getSizeY(); + final int dataSize = input.getSizeX() * input.getSizeY(); CLEvent event; - float[] data = new float[dataSize]; + final float[] data = new float[dataSize]; - CLFloatBuffer cl_inBuffer = clContext.createFloatBuffer(Usage.Input, dataSize); + final CLFloatBuffer cl_inBuffer = clContext.createFloatBuffer(Usage.Input, dataSize); - double[] kernelDouble = kernel.getDataXYAsDouble(0, 0, 0); + final double[] kernelDouble = kernel.getDataXYAsDouble(0, 0, 0); - CLFloatBuffer cl_kBuffer = clContext.createFloatBuffer(Usage.Input, kernelDouble.length); - FloatBuffer fb_k = cl_kBuffer.map(clQueue, MapFlags.Write); - for (double d : kernelDouble) + final CLFloatBuffer cl_kBuffer = clContext.createFloatBuffer(Usage.Input, kernelDouble.length); + final FloatBuffer fb_k = cl_kBuffer.map(clQueue, MapFlags.Write); + for (final double d : kernelDouble) fb_k.put((float) d); fb_k.rewind(); event = cl_kBuffer.unmap(clQueue, fb_k); // create a "direct" float buffer - FloatBuffer outBuffer = ByteBuffer.allocateDirect(dataSize * 4).order(clContext.getByteOrder()).asFloatBuffer(); + final FloatBuffer outBuffer = ByteBuffer.allocateDirect(dataSize * 4).order(clContext.getByteOrder()).asFloatBuffer(); // share the reference directly with the GPU (no copy) - CLFloatBuffer cl_outBuffer = clContext.createFloatBuffer(Usage.Output, outBuffer, false); + final CLFloatBuffer cl_outBuffer = clContext.createFloatBuffer(Usage.Output, outBuffer, false); // set the kernel arguments in order clKernel.setArgs(cl_inBuffer, input.getSizeX(), input.getSizeY(), cl_kBuffer, kernel.getSizeX() >> 1, kernel.getSizeY() >> 1, cl_outBuffer); FloatBuffer fb; - DataType type = input.getDataType_(); + final DataType type = input.getDataType_(); input.beginUpdate(); try { for (int t = 0; t < input.getSizeT(); t++) { for (int z = 0; z < input.getSizeZ(); z++) { - IcyBufferedImage image = input.getImage(t, z); + final IcyBufferedImage image = input.getImage(t, z); for (int c = 0; c < input.getSizeC(); c++) { // convert image to float diff --git a/src/main/java/plugins/adufour/filtering/ConvolutionException.java b/src/main/java/plugins/adufour/filtering/ConvolutionException.java index 56133e268a9837e9a59a77730fd9e2ebf3dd594d..a5703a9dce1e63aeda3a0e410f761b7baa4ae248 100644 --- a/src/main/java/plugins/adufour/filtering/ConvolutionException.java +++ b/src/main/java/plugins/adufour/filtering/ConvolutionException.java @@ -1,7 +1,25 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; public class ConvolutionException extends Exception { - public ConvolutionException(String message, Throwable cause) { + public ConvolutionException(final String message, final Throwable cause) { super(message, cause); } } diff --git a/src/main/java/plugins/adufour/filtering/Filter.java b/src/main/java/plugins/adufour/filtering/Filter.java index ea27628ef3620b85ef0c71502371e3622b2f0d9c..7675a2816846e3e8a4315a89cfa362470027970d 100644 --- a/src/main/java/plugins/adufour/filtering/Filter.java +++ b/src/main/java/plugins/adufour/filtering/Filter.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; import icy.plugin.abstract_.Plugin; diff --git a/src/main/java/plugins/adufour/filtering/FilterToolbox.java b/src/main/java/plugins/adufour/filtering/FilterToolbox.java index 16168e70d764f5997c5612a1c1c8ae9d8e455d43..484b8730c086a5502c246e923ff5752bc913561a 100644 --- a/src/main/java/plugins/adufour/filtering/FilterToolbox.java +++ b/src/main/java/plugins/adufour/filtering/FilterToolbox.java @@ -1,38 +1,40 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; +import com.nativelibs4java.opencl.*; +import com.ochafik.io.ReadText; import icy.gui.frame.progress.FailedAnnounceFrame; import icy.image.IcyBufferedImage; import icy.sequence.DimensionId; import icy.sequence.Sequence; import icy.sequence.SequenceUtil; +import icy.system.IcyExceptionHandler; import icy.system.IcyHandledException; - -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; - -import plugins.adufour.ezplug.EzException; -import plugins.adufour.ezplug.EzGroup; -import plugins.adufour.ezplug.EzPlug; -import plugins.adufour.ezplug.EzStoppable; -import plugins.adufour.ezplug.EzVarBoolean; -import plugins.adufour.ezplug.EzVarDimensionPicker; -import plugins.adufour.ezplug.EzVarDouble; -import plugins.adufour.ezplug.EzVarDoubleArrayNative; -import plugins.adufour.ezplug.EzVarEnum; -import plugins.adufour.ezplug.EzVarInteger; -import plugins.adufour.ezplug.EzVarPlugin; -import plugins.adufour.ezplug.EzVarSequence; +import plugins.adufour.ezplug.*; import plugins.adufour.vars.lang.Var; import plugins.adufour.vars.lang.VarBoolean; import plugins.adufour.vars.util.VarListener; -import com.nativelibs4java.opencl.CLContext; -import com.nativelibs4java.opencl.CLException; -import com.nativelibs4java.opencl.CLProgram; -import com.nativelibs4java.opencl.CLQueue; -import com.nativelibs4java.opencl.JavaCL; -import com.ochafik.io.ReadText; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; public class FilterToolbox extends EzPlug implements EzStoppable { private final static int MAX_KERNEL_SIZE = 99; @@ -101,7 +103,7 @@ public class FilterToolbox extends EzPlug implements EzStoppable { input.addVarChangeListener((source, newValue) -> { if (newValue == null) return; - boolean is3D = newValue.getSizeZ() > 1; + final boolean is3D = newValue.getSizeZ() > 1; linearZ.setVisible(is3D); gaussianZ.setVisible(is3D); @@ -127,23 +129,24 @@ public class FilterToolbox extends EzPlug implements EzStoppable { useOpenCL.setVisible(false); context = JavaCL.createBestContext(); queue = context.createDefaultQueue(); - String programFile = ReadText.readText(ConvolutionCL.class.getResourceAsStream("Convolution.cl")); + final String programFile = ReadText.readText(ConvolutionCL.class.getResourceAsStream("Convolution.cl")); program = context.createProgram(programFile).build(); convolutionCL = new ConvolutionCL(context, program, queue); useOpenCL.setValue(true); useOpenCL.setVisible(true); } - catch (IOException e) { + catch (final IOException e) { System.out.println("Warning (FilterToolbox): unable to load the OpenCL code. Continuing in pure Java mode."); - e.printStackTrace(); + IcyExceptionHandler.showErrorMessage(e, false); } - catch (CLException | NoClassDefFoundError e) { + catch (final CLException | NoClassDefFoundError e) { System.out.println("Warning (FilterToolbox): unable to create the OpenCL context. Continuing in pure Java mode."); - e.printStackTrace(); + IcyExceptionHandler.showErrorMessage(e, false); } - catch (UnsatisfiedLinkError linkError) { + catch (final UnsatisfiedLinkError linkError) { // throw new EzException("Unable to load OpenCL drivers on this system", true); System.out.println("Warning (FilterToolbox): OpenCL drivers not found. Using basic Java implementation."); + IcyExceptionHandler.showErrorMessage(linkError, false); } filterType.addVisibilityTriggerTo(useOpenCL, FilterType.CLASSIC, FilterType.SEPARABLE); @@ -152,13 +155,13 @@ public class FilterToolbox extends EzPlug implements EzStoppable { addEzComponent(kernel1D); filterType.addVisibilityTriggerTo(kernel1D, FilterType.SEPARABLE); - EzGroup groupLinear = new EzGroup("Directions", linearX, linearY, linearZ, linearSeparable); + final EzGroup groupLinear = new EzGroup("Directions", linearX, linearY, linearZ, linearSeparable); addEzComponent(groupLinear); filterType.addVisibilityTriggerTo(groupLinear, FilterType.SEPARABLE); kernel1D.addVisibilityTriggerTo(linearSeparable, Kernels1D.CUSTOM); useOpenCL.addVisibilityTriggerTo(linearZ, false); - EzGroup groupGaussian = new EzGroup("Gaussian filter", gaussianX, gaussianY, gaussianZ); + final EzGroup groupGaussian = new EzGroup("Gaussian filter", gaussianX, gaussianY, gaussianZ); addEzComponent(groupGaussian); kernel1D.addVisibilityTriggerTo(groupGaussian, Kernels1D.CUSTOM_GAUSSIAN); useOpenCL.addVisibilityTriggerTo(gaussianZ, false); @@ -166,15 +169,15 @@ public class FilterToolbox extends EzPlug implements EzStoppable { addEzComponent(kernel2D); filterType.addVisibilityTriggerTo(kernel2D, FilterType.CLASSIC); - EzGroup gaborGroup = new EzGroup("Gabor 2D", gaborSigma, gaborKx, gaborKy, gaborSymmetric); + final EzGroup gaborGroup = new EzGroup("Gabor 2D", gaborSigma, gaborKx, gaborKy, gaborSymmetric); addEzComponent(gaborGroup); kernel2D.addVisibilityTriggerTo(gaborGroup, Kernels2D.CUSTOM_GABOR); - EzGroup customSequenceGroup = new EzGroup("Custom sequence", customKernel, customKernel_T, customKernel_Z, customKernel_C); + final EzGroup customSequenceGroup = new EzGroup("Custom sequence", customKernel, customKernel_T, customKernel_Z, customKernel_C); addEzComponent(customSequenceGroup); kernel2D.addVisibilityTriggerTo(customSequenceGroup, Kernels2D.CUSTOM_SEQUENCE); - EzGroup groupSelection = new EzGroup("Selection filter", selectionFilter, selectionRadiusX, selectionRadiusY, selectionRadiusZ); + final EzGroup groupSelection = new EzGroup("Selection filter", selectionFilter, selectionRadiusX, selectionRadiusY, selectionRadiusZ); addEzComponent(groupSelection); filterType.addVisibilityTriggerTo(groupSelection, FilterType.SELECTION); @@ -189,7 +192,7 @@ public class FilterToolbox extends EzPlug implements EzStoppable { kernel2D.addVisibilityTriggerTo(userKernelHeight, Kernels2D.CUSTOM); // first line of the kernel must always exist - EzVarDoubleArrayNative firstKernelLine = new EzVarDoubleArrayNative("Line 1", new double[][]{new double[]{1f, 1f, 1f}}, 0, true); + final EzVarDoubleArrayNative firstKernelLine = new EzVarDoubleArrayNative("Line 1", new double[][]{new double[]{1f, 1f, 1f}}, 0, true); kernelLines.add(firstKernelLine); addEzComponent(firstKernelLine); kernel1D.addVisibilityTriggerTo(firstKernelLine, Kernels1D.CUSTOM); @@ -198,11 +201,11 @@ public class FilterToolbox extends EzPlug implements EzStoppable { // other lines userKernelHeight.addVarChangeListener((source, newValue) -> { if (kernelLines.size() < newValue) { - int nbLines = kernelLines.size(); - int nbNewLines = newValue - nbLines; + final int nbLines = kernelLines.size(); + final int nbNewLines = newValue - nbLines; for (int i = 1; i <= nbNewLines; i++) { - int lineNumber = i + nbLines; - EzVarDoubleArrayNative newLine = new EzVarDoubleArrayNative("Line " + lineNumber, new double[][]{new double[]{1f, 1f, 1f}}, 0, true); + final int lineNumber = i + nbLines; + final EzVarDoubleArrayNative newLine = new EzVarDoubleArrayNative("Line " + lineNumber, new double[][]{new double[]{1f, 1f, 1f}}, 0, true); kernelLines.add(newLine); kernel2D.addVisibilityTriggerTo(newLine, Kernels2D.CUSTOM); addEzComponent(newLine); @@ -222,7 +225,7 @@ public class FilterToolbox extends EzPlug implements EzStoppable { public void execute() { stopFlag.setValue(false); - Sequence inSeq = input.getValue(true); + final Sequence inSeq = input.getValue(true); try { switch (filterType.getValue()) { case SEPARABLE: { @@ -237,34 +240,34 @@ public class FilterToolbox extends EzPlug implements EzStoppable { try { executeSelectionFilter(inSeq); } - catch (Exception e) { + catch (final Exception e) { throw new RuntimeException(e); } break; } } } - catch (InterruptedException e) { + catch (final InterruptedException e) { new FailedAnnounceFrame("Process interrupted !"); } - catch (CLException.OutOfHostMemory o) { + catch (final CLException.OutOfHostMemory o) { throw new IcyHandledException("Not enough memory to perform the filtering on the GPU. Disable OpenCL and retry."); } } - private void executeSelectionFilter(Sequence inSeq) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { - SelectionFilter filter = (SelectionFilter) selectionFilter.getValue().getPluginClass().getDeclaredConstructor().newInstance(); + private void executeSelectionFilter(final Sequence inSeq) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + final SelectionFilter filter = (SelectionFilter) selectionFilter.getValue().getPluginClass().getDeclaredConstructor().newInstance(); this.filter = filter; - filter.progress.addListener(new VarListener<Double>() { + filter.progress.addListener(new VarListener<>() { @Override - public void valueChanged(Var<Double> source, Double oldValue, Double newValue) { + public void valueChanged(final Var<Double> source, final Double oldValue, final Double newValue) { getUI().setProgressBarValue(newValue); } @Override - public void referenceChanged(Var<Double> source, Var<? extends Double> oldReference, Var<? extends Double> newReference) { + public void referenceChanged(final Var<Double> source, final Var<? extends Double> oldReference, final Var<? extends Double> newReference) { } }); @@ -280,8 +283,8 @@ public class FilterToolbox extends EzPlug implements EzStoppable { this.filter = null; } - private void executeClassic(Sequence inSeq) throws InterruptedException { - Kernels2D k2d = kernel2D.getValue(); + private void executeClassic(final Sequence inSeq) throws InterruptedException { + final Kernels2D k2d = kernel2D.getValue(); switch (kernel2D.getValue()) { case CUSTOM_GABOR: @@ -289,12 +292,12 @@ public class FilterToolbox extends EzPlug implements EzStoppable { break; case CUSTOM: { - ArrayList<Double> kernel1D = new ArrayList<>(); + final ArrayList<Double> kernel1D = new ArrayList<>(); for (int i = 0; i < userKernelHeight.getValue(); i++) - for (double d : kernelLines.get(i).getValue()) + for (final double d : kernelLines.get(i).getValue()) kernel1D.add(d); - double[] values = new double[kernel1D.size()]; + final double[] values = new double[kernel1D.size()]; for (int i = 0; i < kernel1D.size(); i++) values[i] = kernel1D.get(i); @@ -310,7 +313,7 @@ public class FilterToolbox extends EzPlug implements EzStoppable { // nothing to do (the filters should already be predefined) } - Sequence kernel = k2d.toSequence(); + final Sequence kernel = k2d.toSequence(); Sequence output = null; boolean openCL_failed = false; @@ -321,7 +324,7 @@ public class FilterToolbox extends EzPlug implements EzStoppable { convolutionCL.convolve(output, kernel, zeroEdge.getValue(), iterations.getValue(), stopFlag); openCL_failed = false; } - catch (Exception e) { + catch (final Exception e) { openCL_failed = true; e.printStackTrace(); System.err.println("WARNING: Unable to run in OpenCL mode. Switching to CPU mode."); @@ -331,14 +334,14 @@ public class FilterToolbox extends EzPlug implements EzStoppable { if (!useOpenCL.getValue() || openCL_failed) { final Convolution c = new Convolution(); this.filter = c; - final VarListener<Double> ld = new VarListener<Double>() { + final VarListener<Double> ld = new VarListener<>() { @Override - public void valueChanged(Var<Double> source, Double oldValue, Double newValue) { + public void valueChanged(final Var<Double> source, final Double oldValue, final Double newValue) { getUI().setProgressBarValue(newValue); } @Override - public void referenceChanged(Var<Double> source, Var<? extends Double> oldReference, Var<? extends Double> newReference) { + public void referenceChanged(final Var<Double> source, final Var<? extends Double> oldReference, final Var<? extends Double> newReference) { } }; @@ -348,13 +351,14 @@ public class FilterToolbox extends EzPlug implements EzStoppable { this.filter = null; } + assert output != null; output.setName(inSeq.getName() + " * " + kernel.getName()); output.updateChannelsBounds(true); addSequence(output); } - private void executeSeparable(Sequence inSeq) throws InterruptedException { - Kernels1D k1d = kernel1D.getValue(); + private void executeSeparable(final Sequence inSeq) throws InterruptedException { + final Kernels1D k1d = kernel1D.getValue(); Sequence kernelX = null, kernelY = null, kernelZ = null; @@ -382,7 +386,7 @@ public class FilterToolbox extends EzPlug implements EzStoppable { case GRADIENT: { linearSeparable.setValue(false); - Sequence kernel = k1d.toSequence(); + final Sequence kernel = k1d.toSequence(); if (linearX.getValue()) { kernelX = kernel; @@ -400,7 +404,7 @@ public class FilterToolbox extends EzPlug implements EzStoppable { break; case CUSTOM: { - Sequence kernel = k1d.createCustomKernel1D(kernelLines.get(0).getValue(), false).toSequence(); + final Sequence kernel = k1d.createCustomKernel1D(kernelLines.get(0).getValue(), false).toSequence(); if (linearX.getValue()) { kernelX = kernel; @@ -430,16 +434,18 @@ public class FilterToolbox extends EzPlug implements EzStoppable { else try { if (linearSeparable.getValue()) { // convolve the same data along all required directions sequentially - Sequence output = SequenceUtil.getCopy(inSeq); + final Sequence output = SequenceUtil.getCopy(inSeq); String newName = output.getName() + " * " + k1d.name() + " ("; if (linearX.getValue()) { + assert kernelX != null; convolutionCL.convolve(output, kernelX, zeroEdge.getValue(), iterations.getValue(), stopFlag); newName += 'X'; } if (linearY.getValue()) { // in OpenCL mode, the kernel along Y has to be vertical - Sequence kernelY_vertical = new Sequence(new IcyBufferedImage(1, kernelY.getSizeX(), 1, kernelY.getDataType_())); + assert kernelY != null; + final Sequence kernelY_vertical = new Sequence(new IcyBufferedImage(1, kernelY.getSizeX(), 1, kernelY.getDataType_())); System.arraycopy(kernelY.getDataXY(0, 0, 0), 0, kernelY_vertical.getDataXY(0, 0, 0), 0, kernelY.getSizeX()); convolutionCL.convolve(output, kernelY_vertical, zeroEdge.getValue(), iterations.getValue(), stopFlag); newName += 'Y'; @@ -453,16 +459,18 @@ public class FilterToolbox extends EzPlug implements EzStoppable { else { // convolve along each direction in separate sequences if (linearX.getValue()) { - Sequence output = SequenceUtil.getCopy(inSeq); + final Sequence output = SequenceUtil.getCopy(inSeq); + assert kernelX != null; convolutionCL.convolve(output, kernelX, zeroEdge.getValue(), iterations.getValue(), stopFlag); output.setName(output.getName() + " * " + k1d.name() + " (X)"); output.dataChanged(); addSequence(output); } if (linearY.getValue()) { - Sequence output = SequenceUtil.getCopy(inSeq); + final Sequence output = SequenceUtil.getCopy(inSeq); // in OpenCL mode, the kernel along Y has to be vertical - Sequence kernelY_vertical = new Sequence(new IcyBufferedImage(1, kernelY.getSizeX(), 1, kernelY.getDataType_())); + assert kernelY != null; + final Sequence kernelY_vertical = new Sequence(new IcyBufferedImage(1, kernelY.getSizeX(), 1, kernelY.getDataType_())); System.arraycopy(kernelY.getDataXY(0, 0, 0), 0, kernelY_vertical.getDataXY(0, 0, 0), 0, kernelY.getSizeX()); convolutionCL.convolve(output, kernelY_vertical, zeroEdge.getValue(), iterations.getValue(), stopFlag); output.setName(output.getName() + " * " + k1d.name() + " (Y)"); @@ -472,7 +480,7 @@ public class FilterToolbox extends EzPlug implements EzStoppable { // TODO Z } } - catch (Exception e) { + catch (final Exception e) { openCL_failed = true; e.printStackTrace(); System.err.println("WARNING: Unable to run in OpenCL mode. Continuing in CPU mode."); @@ -482,7 +490,7 @@ public class FilterToolbox extends EzPlug implements EzStoppable { if (!useOpenCL.getValue() || openCL_failed) { if (linearSeparable.getValue()) { try { - Sequence output = SequenceUtil.getCopy(inSeq); + final Sequence output = SequenceUtil.getCopy(inSeq); Convolution1D.convolve(output, kernelX, kernelY, kernelZ, iterations.getValue(), stopFlag); String newName = output.getName() + " * " + k1d.name() + " ("; if (kernelX != null) newName += 'X'; @@ -492,39 +500,39 @@ public class FilterToolbox extends EzPlug implements EzStoppable { output.dataChanged(); addSequence(output); } - catch (ConvolutionException e) { + catch (final ConvolutionException e) { throw new EzException(this, e.getMessage(), true); } } else { if (linearX.getValue()) try { - Sequence output = SequenceUtil.getCopy(inSeq); + final Sequence output = SequenceUtil.getCopy(inSeq); Convolution1D.convolve(output, kernelX, null, null, iterations.getValue(), stopFlag); output.setName(output.getName() + " * " + k1d.name() + " (X)"); output.dataChanged(); addSequence(output); } - catch (ConvolutionException e) { + catch (final ConvolutionException e) { throw new EzException(this, e.getMessage(), true); } if (linearY.getValue()) try { - Sequence output = SequenceUtil.getCopy(inSeq); + final Sequence output = SequenceUtil.getCopy(inSeq); Convolution1D.convolve(output, null, kernelY, null, iterations.getValue(), stopFlag); output.setName(output.getName() + " * " + k1d.name() + " (Y)"); output.dataChanged(); addSequence(output); } - catch (ConvolutionException e) { + catch (final ConvolutionException e) { throw new EzException(this, e.getMessage(), true); } if (linearZ.getValue()) try { - Sequence output = SequenceUtil.getCopy(inSeq); + final Sequence output = SequenceUtil.getCopy(inSeq); Convolution1D.convolve(output, null, null, kernelZ, iterations.getValue(), stopFlag); output.setName(output.getName() + " * " + k1d.name() + " (Z)"); output.dataChanged(); addSequence(output); } - catch (ConvolutionException e) { + catch (final ConvolutionException e) { throw new EzException(this, e.getMessage(), true); } } diff --git a/src/main/java/plugins/adufour/filtering/GaussianFilter.java b/src/main/java/plugins/adufour/filtering/GaussianFilter.java index c36edfc3d4453fad27c6befd457ad8f9f7fffdee..7b341d7cec9c8e7681f3f8e9137a92cc0924ad87 100644 --- a/src/main/java/plugins/adufour/filtering/GaussianFilter.java +++ b/src/main/java/plugins/adufour/filtering/GaussianFilter.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; import icy.gui.frame.progress.FailedAnnounceFrame; @@ -31,14 +49,14 @@ public class GaussianFilter extends Plugin implements Block, PluginBundled { try { output.setValue(filter(input.getValue(true), gX.getValue(), gY.getValue(), gZ.getValue())); } - catch (InterruptedException e) { + catch (final InterruptedException e) { new FailedAnnounceFrame("Process interrupted !"); } } @Override - public void declareInput(VarList inputMap) { - RangeModel<Double> constraint = new DoubleRangeModel(0.0, 0.0, 1000.0, 0.1); + public void declareInput(final VarList inputMap) { + final RangeModel<Double> constraint = new DoubleRangeModel(0.0, 0.0, 1000.0, 0.1); gX.setDefaultEditorModel(constraint); gY.setDefaultEditorModel(constraint); gZ.setDefaultEditorModel(constraint); @@ -49,7 +67,7 @@ public class GaussianFilter extends Plugin implements Block, PluginBundled { } @Override - public void declareOutput(VarList outputMap) { + public void declareOutput(final VarList outputMap) { outputMap.add("output", output); } @@ -66,20 +84,19 @@ public class GaussianFilter extends Plugin implements Block, PluginBundled { * @param sigmaY the standard deviation of the gaussian along the Y axis (set to 0 if not needed) * @param sigmaZ the standard deviation of the gaussian along the Z axis (set to 0 if not needed) * @return a filtered version of the input sequence - * @throws InterruptedException */ - public static Sequence filter(Sequence in, double sigmaX, double sigmaY, double sigmaZ) throws InterruptedException { - double[] gaussianX = Kernels1D.CUSTOM_GAUSSIAN.createGaussianKernel1D(sigmaX).getData(); - double[] gaussianY = Kernels1D.CUSTOM_GAUSSIAN.createGaussianKernel1D(sigmaY).getData(); - double[] gaussianZ = Kernels1D.CUSTOM_GAUSSIAN.createGaussianKernel1D(sigmaZ).getData(); + public static Sequence filter(final Sequence in, final double sigmaX, final double sigmaY, final double sigmaZ) throws InterruptedException { + final double[] gaussianX = Kernels1D.CUSTOM_GAUSSIAN.createGaussianKernel1D(sigmaX).getData(); + final double[] gaussianY = Kernels1D.CUSTOM_GAUSSIAN.createGaussianKernel1D(sigmaY).getData(); + final double[] gaussianZ = Kernels1D.CUSTOM_GAUSSIAN.createGaussianKernel1D(sigmaZ).getData(); - Sequence filtered = SequenceUtil.getCopy(in); + final Sequence filtered = SequenceUtil.getCopy(in); filtered.setName(in.getName() + "_filtered"); try { Convolution1D.convolve(filtered, gaussianX, gaussianY, gaussianZ == null ? null : filtered.getSizeZ() > 1 ? gaussianZ : null); } - catch (Exception e) { + catch (final Exception e) { throw new RuntimeException("GaussianFilter: " + e.getMessage()); } diff --git a/src/main/java/plugins/adufour/filtering/IKernel.java b/src/main/java/plugins/adufour/filtering/IKernel.java index d426108b3de1ae67e25cf7ccada35f990d882de1..04b6b2893bcb6db481d6674bc178c63921ebe016 100644 --- a/src/main/java/plugins/adufour/filtering/IKernel.java +++ b/src/main/java/plugins/adufour/filtering/IKernel.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; import icy.sequence.Sequence; diff --git a/src/main/java/plugins/adufour/filtering/Kernels1D.java b/src/main/java/plugins/adufour/filtering/Kernels1D.java index e7351a15f01969bd0fb56554d85533ec51e89462..83f2caad75bfe4e18f77f014db6d93968652fff3 100644 --- a/src/main/java/plugins/adufour/filtering/Kernels1D.java +++ b/src/main/java/plugins/adufour/filtering/Kernels1D.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; import icy.image.IcyBufferedImage; @@ -26,7 +44,7 @@ public enum Kernels1D implements IKernel { private final boolean isSeparable; - Kernels1D(double[] data, boolean isSeparable) { + Kernels1D(final double[] data, final boolean isSeparable) { this.data = data; this.isSeparable = isSeparable; } @@ -35,14 +53,16 @@ public enum Kernels1D implements IKernel { return isSeparable; } + @Override public Sequence toSequence() { - IcyBufferedImage kernelImage = new IcyBufferedImage(data.length, 1, 1, DataType.DOUBLE); + final IcyBufferedImage kernelImage = new IcyBufferedImage(data.length, 1, 1, DataType.DOUBLE); kernelImage.setDataXYAsDouble(0, data); - Sequence kernel = new Sequence(kernelImage); + final Sequence kernel = new Sequence(kernelImage); kernel.setName(this.toString()); return kernel; } + @Override public double[] getData() { return data; } @@ -54,16 +74,16 @@ public enum Kernels1D implements IKernel { * @param sigma the standard deviation of the gaussian * @return the kernel as a sequence, or null if sigma is 0 */ - public Kernels1D createGaussianKernel1D(double sigma) { + public Kernels1D createGaussianKernel1D(final double sigma) { if (sigma < 1.0e-10) { this.data = new double[]{1}; return this; } - double sigma2 = sigma * sigma; - int k = (int) Math.ceil(sigma * 3.0f); + final double sigma2 = sigma * sigma; + final int k = (int) Math.ceil(sigma * 3.0f); - int width = 2 * k + 1; + final int width = 2 * k + 1; this.data = new double[width]; @@ -79,7 +99,7 @@ public enum Kernels1D implements IKernel { * @param isNormalized true if the given values are already normalized to [0-1] * @return Sets the kernel values */ - public Kernels1D createCustomKernel1D(double[] data, boolean isNormalized) { + public Kernels1D createCustomKernel1D(final double[] data, final boolean isNormalized) { this.data = new double[data.length]; System.arraycopy(data, 0, this.data, 0, data.length); if (!isNormalized) @@ -91,12 +111,11 @@ public enum Kernels1D implements IKernel { * Normalizes the given kernel such that the values sum up to 1 * * @param data the kernel data in Z-XY order - * @return */ - private static double[] normalize(double[] data) { + private static double[] normalize(final double[] data) { double accu = 0; - for (double d : data) + for (final double d : data) accu += d; if (accu != 1 && accu != 0) { diff --git a/src/main/java/plugins/adufour/filtering/Kernels2D.java b/src/main/java/plugins/adufour/filtering/Kernels2D.java index 29d52ef55e2249fd65e5e3173958515120d7e40c..66a977af272068744463c11b9c4aa73492c6b75f 100644 --- a/src/main/java/plugins/adufour/filtering/Kernels2D.java +++ b/src/main/java/plugins/adufour/filtering/Kernels2D.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; import icy.image.IcyBufferedImage; @@ -94,7 +112,7 @@ public enum Kernels2D implements IKernel { private double[] data; - Kernels2D(int width, int height, double[] data) { + Kernels2D(final int width, final int height, final double[] data) { this.width = width; this.height = height; if (data != null) this.data = Kernels2D.normalize(data); @@ -107,8 +125,8 @@ public enum Kernels2D implements IKernel { * @param isSymmetric true if the values are symmetric (cosine), anti-symmetric (sine) otherwise * @return Creates an isotropic 2D Gabor kernel */ - public Kernels2D createGaborKernel2D(double sigma, double k_x, double k_y, boolean isSymmetric) { - int k = (int) Math.floor(sigma * 3.0); + public Kernels2D createGaborKernel2D(final double sigma, final double k_x, final double k_y, final boolean isSymmetric) { + final int k = (int) Math.floor(sigma * 3.0); this.width = 2 * k + 1; this.height = 2 * k + 1; @@ -135,12 +153,12 @@ public enum Kernels2D implements IKernel { * @param isNormalized true if the given values are already normalized to [0-1] * @return Sets the kernel values manually */ - public Kernels2D createCustomKernel2D(double[][] kernel, boolean isNormalized) { + public Kernels2D createCustomKernel2D(final double[][] kernel, final boolean isNormalized) { this.width = kernel.length; this.height = kernel[0].length; this.data = new double[width * height]; int offset = 0; - for (double[] line : kernel) { + for (final double[] line : kernel) { System.arraycopy(line, 0, this.data, offset, line.length); offset += line.length; } @@ -156,7 +174,7 @@ public enum Kernels2D implements IKernel { * @param width int * @param isNormalized true if the given values are already normalized to [0-1] */ - public Kernels2D createCustomKernel2D(double[] kernel, int width, int height, boolean isNormalized) { + public Kernels2D createCustomKernel2D(final double[] kernel, final int width, final int height, final boolean isNormalized) { this.width = width; this.height = height; this.data = new double[width * height]; @@ -171,9 +189,8 @@ public enum Kernels2D implements IKernel { * @param z the slice to take values from * @param c the channel to take values from * @return Sets the kernel values using the given sequence - * @throws InterruptedException */ - public Kernels2D createCustomKernel2D(Sequence kernel2D, int t, int z, int c) throws InterruptedException { + public Kernels2D createCustomKernel2D(final Sequence kernel2D, final int t, final int z, final int c) throws InterruptedException { this.width = kernel2D.getSizeX(); this.height = kernel2D.getSizeY(); if (width % 2 == 0 || height % 2 == 0) throw new IllegalArgumentException("Kernel sequence must have odd dimensions"); @@ -186,12 +203,11 @@ public enum Kernels2D implements IKernel { * Normalizes the given kernel such that the values sum up to 1 * * @param data the kernel data in Z-XY order - * @return */ - private static double[] normalize(double[] data) { + private static double[] normalize(final double[] data) { double sum = 0; - for (double d : data) + for (final double d : data) sum += d; if (sum != 1 && sum != 0) { @@ -204,13 +220,14 @@ public enum Kernels2D implements IKernel { @Override public Sequence toSequence() { - IcyBufferedImage kernelImage = new IcyBufferedImage(width, height, 1, DataType.DOUBLE); + final IcyBufferedImage kernelImage = new IcyBufferedImage(width, height, 1, DataType.DOUBLE); kernelImage.setDataXYAsDouble(0, data); - Sequence kernel = new Sequence(kernelImage); + final Sequence kernel = new Sequence(kernelImage); kernel.setName(this.toString()); return kernel; } + @Override public double[] getData() { return data; } diff --git a/src/main/java/plugins/adufour/filtering/LocalMax.java b/src/main/java/plugins/adufour/filtering/LocalMax.java index 31d80dc8e2605ef0cb0f1ccd525fb90d33a76c86..77f53f8eabad887d53553249ec14293720aae4e8 100644 --- a/src/main/java/plugins/adufour/filtering/LocalMax.java +++ b/src/main/java/plugins/adufour/filtering/LocalMax.java @@ -1,12 +1,30 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; public class LocalMax extends SelectionFilter { @Override - double process(double currentValue, double[] neighborhood, int neighborhoodSize) { + double process(final double currentValue, final double[] neighborhood, final int neighborhoodSize) { double defaultValue = 0.0; for (int i = 0; i < neighborhoodSize; i++) { - double d = neighborhood[i]; + final double d = neighborhood[i]; if (d > currentValue) return 0.0; if (defaultValue == 0.0 && d < currentValue) defaultValue = 1.0; } diff --git a/src/main/java/plugins/adufour/filtering/Max.java b/src/main/java/plugins/adufour/filtering/Max.java index 03bb73789580eea4a0c98bcb49e7cdf15ceb7114..931efe317b8f3636eacf4bcc13d31475df8b0e08 100644 --- a/src/main/java/plugins/adufour/filtering/Max.java +++ b/src/main/java/plugins/adufour/filtering/Max.java @@ -1,11 +1,29 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; public class Max extends SelectionFilter { @Override - double process(double currentValue, double[] neighborhood, int neighborhoodSize) { + double process(final double currentValue, final double[] neighborhood, final int neighborhoodSize) { double max = neighborhood[0]; for (int i = 1; i < neighborhoodSize; i++) { - double d = neighborhood[i]; + final double d = neighborhood[i]; if (d > max) max = d; } return max; diff --git a/src/main/java/plugins/adufour/filtering/Mean.java b/src/main/java/plugins/adufour/filtering/Mean.java index aa5b1745da8c9f7e6b7c72632bfaf5ad0f8157a4..8b7f1dd4d7a6d1c98397d0c4e5ca8815fc230207 100644 --- a/src/main/java/plugins/adufour/filtering/Mean.java +++ b/src/main/java/plugins/adufour/filtering/Mean.java @@ -1,8 +1,26 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; public class Mean extends SelectionFilter { @Override - double process(double currentValue, double[] neighborhood, int neighborhoodSize) { + double process(final double currentValue, final double[] neighborhood, final int neighborhoodSize) { double sum = neighborhood[0]; for (int i = 1; i < neighborhoodSize; i++) sum += neighborhood[i]; diff --git a/src/main/java/plugins/adufour/filtering/Median.java b/src/main/java/plugins/adufour/filtering/Median.java index a0b0ab036aa2696e7e0d1a4ae6290ad53c5a72f3..faeda645be6cb47b0d8b621a43a079567707863c 100644 --- a/src/main/java/plugins/adufour/filtering/Median.java +++ b/src/main/java/plugins/adufour/filtering/Median.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; public class Median extends SelectionFilter { @@ -10,8 +28,8 @@ public class Median extends SelectionFilter { * @return the k-th smallest value in the array */ @Override - double process(double currentValue, double[] data, int length) { - int k = length >> 1; + double process(final double currentValue, final double[] data, int length) { + final int k = length >> 1; int i, j, mid, l = 1; double a, temp; diff --git a/src/main/java/plugins/adufour/filtering/RemoveOutliers.java b/src/main/java/plugins/adufour/filtering/RemoveOutliers.java index a8868e0f182c88470e1032fa611612c420398e0f..42d3745d3c9d9816bbaf144b42f7c2945d8d5522 100644 --- a/src/main/java/plugins/adufour/filtering/RemoveOutliers.java +++ b/src/main/java/plugins/adufour/filtering/RemoveOutliers.java @@ -1,8 +1,26 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; public class RemoveOutliers extends SelectionFilter { @Override - double process(double currentValue, double[] neighborhood, int neighborHoodSize) { + double process(final double currentValue, final double[] neighborhood, final int neighborHoodSize) { double mean = 0, stdev2 = 0; // mean diff --git a/src/main/java/plugins/adufour/filtering/SelectionFilter.java b/src/main/java/plugins/adufour/filtering/SelectionFilter.java index 58d68086dd6b7f74af63a53a862c42ade9b1b883..32f5779f3c9ad13af4d7298831c4aae43b64d000 100644 --- a/src/main/java/plugins/adufour/filtering/SelectionFilter.java +++ b/src/main/java/plugins/adufour/filtering/SelectionFilter.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; import icy.image.IcyBufferedImage; @@ -32,8 +50,8 @@ public abstract class SelectionFilter extends Filter { * the input sequence will be internally converted to double precision. However the result will * be converted back to the same type as the given input sequence <i>with re-scaling</i>. */ - public Sequence filterSquare(Sequence sequence, int... radius) { - Sequence out = new Sequence(sequence.getOMEXMLMetadata()); + public Sequence filterSquare(final Sequence sequence, final int... radius) { + final Sequence out = new Sequence(sequence.getOMEXMLMetadata()); out.setName(sequence.getName() + "_" + getDescriptor().getName()); stopFlag.setValue(false); @@ -60,7 +78,7 @@ public abstract class SelectionFilter extends Filter { // create an array of tasks for multi-thread processing // => rationale: one task per image line - ArrayList<Future<?>> tasks = new ArrayList<>(height); + final ArrayList<Future<?>> tasks = new ArrayList<>(height); convolution: for (int t = 0; t < sequence.getSizeT(); t++) { @@ -90,7 +108,7 @@ public abstract class SelectionFilter extends Filter { // submit a new filtering task for the current line tasks.add(service.submit(() -> { - double[] neighborhood = new double[maxNeighbors]; + final double[] neighborhood = new double[maxNeighbors]; int inX, inY, inZ; int inXY, outXY = lineOffset; @@ -102,12 +120,12 @@ public abstract class SelectionFilter extends Filter { currentPixel = Array1DUtil.getValue(_inXY, outXY, type); int localNeighborHoodSize = 0; - int minXinclusive = Math.max(x - kWidth, 0); - int maxXexclusive = Math.min(x + kWidth + 1, width); + final int minXinclusive = Math.max(x - kWidth, 0); + final int maxXexclusive = Math.min(x + kWidth + 1, width); // browse the neighborhood along Z for (inZ = minZinclusive; inZ < maxZexclusive; inZ++) { - Object neighborSlice = in_Z_XY[inZ]; + final Object neighborSlice = in_Z_XY[inZ]; // browse the neighborhood along Y for (inY = minYinclusive; inY < maxYexclusive; inY++) { @@ -137,10 +155,10 @@ public abstract class SelectionFilter extends Filter { } // end for(y) try { - for (Future<?> f : tasks) + for (final Future<?> f : tasks) f.get(); } - catch (InterruptedException | ExecutionException e) { + catch (final InterruptedException | ExecutionException e) { Thread.currentThread().interrupt(); return out; } diff --git a/src/main/java/plugins/adufour/filtering/SelectionFilterBlock.java b/src/main/java/plugins/adufour/filtering/SelectionFilterBlock.java index 99f6b73b022e9cc3dfcbd4f609134a636e552938..780d134aec3b41295f0bc6c134a149ee2257e88d 100644 --- a/src/main/java/plugins/adufour/filtering/SelectionFilterBlock.java +++ b/src/main/java/plugins/adufour/filtering/SelectionFilterBlock.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; import icy.plugin.abstract_.Plugin; @@ -22,11 +40,11 @@ public class SelectionFilterBlock extends Plugin implements Block { @Override public void run() { - SelectionFilter selectionFilter; + final SelectionFilter selectionFilter; try { selectionFilter = filter.newInstance(); } - catch (Exception e) { + catch (final Exception e) { throw new RuntimeException("Unable to create the " + filter.getValueAsString() + " filter"); } @@ -34,7 +52,7 @@ public class SelectionFilterBlock extends Plugin implements Block { } @Override - public void declareInput(VarList inputMap) { + public void declareInput(final VarList inputMap) { inputMap.add("input sequence", input); inputMap.add("filter", filter); inputMap.add("filter radius (X)", radiusX.getVariable()); @@ -43,7 +61,7 @@ public class SelectionFilterBlock extends Plugin implements Block { } @Override - public void declareOutput(VarList outputMap) { + public void declareOutput(final VarList outputMap) { outputMap.add("filtered sequence", output); } diff --git a/src/main/java/plugins/adufour/filtering/StandardDeviation.java b/src/main/java/plugins/adufour/filtering/StandardDeviation.java index 06e254002107283af228f706da280797a331fced..7843e28df42c99b356453e41a3b27c76e9b62cad 100644 --- a/src/main/java/plugins/adufour/filtering/StandardDeviation.java +++ b/src/main/java/plugins/adufour/filtering/StandardDeviation.java @@ -1,8 +1,26 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; public class StandardDeviation extends SelectionFilter { @Override - double process(double currentValue, double[] neighborhood, int neighborHoodSize) { + double process(final double currentValue, final double[] neighborhood, final int neighborHoodSize) { double mean = 0, var = 0; for (int i = 0; i < neighborHoodSize; i++) diff --git a/src/main/java/plugins/adufour/filtering/Variance.java b/src/main/java/plugins/adufour/filtering/Variance.java index 85f74dbfd4e8adfbdae66b0e88085177614d1b66..f00f5591e1c001a49c9f89c405b4fc6db056ada5 100644 --- a/src/main/java/plugins/adufour/filtering/Variance.java +++ b/src/main/java/plugins/adufour/filtering/Variance.java @@ -1,8 +1,26 @@ +/* + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Icy is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Icy. If not, see <https://www.gnu.org/licenses/>. + */ + package plugins.adufour.filtering; public class Variance extends SelectionFilter { @Override - double process(double currentValue, double[] neighborhood, int neighborHoodSize) { + double process(final double currentValue, final double[] neighborhood, final int neighborHoodSize) { double mean = 0, var = 0; for (int i = 0; i < neighborHoodSize; i++)