diff --git a/.gitignore b/.gitignore
index bf678dd154daf5cd3c5fdf5b9c22738fed75066a..57f16fb67c1b1589981416b323d7a9debc728665 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,41 @@
-.idea/
+/build*
+/workspace
+setting.xml
+release/
 target/
-bin/
-.settings/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+icy.log
+
+### IntelliJ IDEA ###
+.idea/
+*.iws
 *.iml
-.project
+*.ipr
+
+### Eclipse ###
+.apt_generated
 .classpath
-SpotDetectorBlock.jar
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+**/.DS_Store
+Icon?
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 09473f6e1f70e7f03bcff948afb091559ba4754e..09d18711bba5f10926e702873342253475421082 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,13 +7,11 @@
     <parent>
 		<artifactId>pom-icy</artifactId>
         <groupId>org.bioimageanalysis.icy</groupId>
-        <version>2.1.2</version>
+        <version>3.0.0-a.1</version>
 	</parent>
 
     <artifactId>spot-detector-block</artifactId>
-    <version>1.0.0</version>
-
-    <packaging>jar</packaging>
+    <version>2.0.0-a.1</version>
 
     <name>Spot Detector block</name>
     <description>
@@ -21,6 +19,14 @@
     </description>
 
     <dependencies>
+        <dependency>
+            <groupId>org.bioimageanalysis.icy</groupId>
+            <artifactId>ezplug</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bioimageanalysis.icy</groupId>
+            <artifactId>protocols</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.bioimageanalysis.icy</groupId>
             <artifactId>spot-detector</artifactId>
@@ -30,7 +36,7 @@
     <repositories>
         <repository>
             <id>icy</id>
-            <url>https://icy-nexus.pasteur.fr/repository/Icy/</url>
+            <url>https://nexus-icy.pasteur.cloud/repository/icy/</url>
         </repository>
     </repositories>
 </project>
\ No newline at end of file
diff --git a/src/main/java/plugins/fab/waveletspotdetectorblock/WaveletSpotDetectorBlock.java b/src/main/java/plugins/fab/waveletspotdetectorblock/WaveletSpotDetectorBlock.java
index 2b51f70b230e50d5f823e484c5df8c594f33178a..fb6d307f01ae622b20b42f8b91050a14e0201f57 100644
--- a/src/main/java/plugins/fab/waveletspotdetectorblock/WaveletSpotDetectorBlock.java
+++ b/src/main/java/plugins/fab/waveletspotdetectorblock/WaveletSpotDetectorBlock.java
@@ -1,70 +1,91 @@
-package plugins.fab.waveletspotdetectorblock;
+/*
+ * Copyright (c) 2010-2024. 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;
+package plugins.fab.waveletspotdetectorblock;
 
-import icy.plugin.abstract_.Plugin;
-import icy.roi.ROI;
-import icy.roi.ROI2D;
-import icy.sequence.Sequence;
-import icy.sequence.SequenceUtil;
-import icy.system.thread.ThreadUtil;
+import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin;
+import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon;
+import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName;
+import org.bioimageanalysis.icy.model.roi.ROI;
+import org.bioimageanalysis.icy.model.roi.ROI2D;
+import org.bioimageanalysis.icy.model.sequence.Sequence;
+import org.bioimageanalysis.icy.model.sequence.SequenceUtil;
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
+import org.bioimageanalysis.icy.system.thread.ThreadUtil;
+import org.jetbrains.annotations.NotNull;
 import plugins.adufour.blocks.lang.Block;
 import plugins.adufour.blocks.util.VarList;
-import plugins.adufour.vars.lang.VarBoolean;
-import plugins.adufour.vars.lang.VarEnum;
-import plugins.adufour.vars.lang.VarInteger;
-import plugins.adufour.vars.lang.VarROIArray;
-import plugins.adufour.vars.lang.VarSequence;
+import plugins.adufour.vars.lang.*;
 import plugins.adufour.vars.util.VarException;
 import plugins.fab.spotDetector.DetectionSpot;
 import plugins.fab.spotDetector.detector.DetectionToROI;
 import plugins.fab.spotDetector.detector.UDWTScale;
 import plugins.fab.spotDetector.detector.UDWTWaveletCore;
 
-public class WaveletSpotDetectorBlock extends Plugin implements Block
-{
+import java.util.ArrayList;
 
-    enum detectionMethodEnum
-    {
+@IcyPluginName("Wavelet Spot Detector")
+@IcyPluginIcon(path = "/spot-detector-block.png")
+public class WaveletSpotDetectorBlock extends Plugin implements Block {
+    enum detectionMethodEnum {
         BRIGHT_SPOT, DARK_SPOT
     }
 
-    VarSequence inputSequenceVar = new VarSequence("input Sequence", null);
-    VarEnum<detectionMethodEnum> detectionMethod = new VarEnum<detectionMethodEnum>("Spot to detect",
-        detectionMethodEnum.BRIGHT_SPOT);
+    VarSequence inputSequenceVar = new VarSequence("Input Sequence", null);
+    VarEnum<detectionMethodEnum> detectionMethod = new VarEnum<>("Spot to detect", detectionMethodEnum.BRIGHT_SPOT);
     VarBoolean computeWATConsideringROIBoolean = new VarBoolean("Compute WAT considering ROI", false);
     VarSequence inputSequenceROIVar = new VarSequence("ROIs from sequence for WAT", null);
     VarBoolean force2DWaveletVar = new VarBoolean("Force 2D Wavelets", false);
     VarROIArray inputROIForMask = new VarROIArray("ROIs for detection mask", null);
 
-    VarBoolean[] useScaleBoolean = {new VarBoolean("Scale 1", false), new VarBoolean("Scale 2", true),
-        new VarBoolean("Scale 3", false), new VarBoolean("Scale 4", false), new VarBoolean("Scale 5", false)};
-
-    VarInteger[] scaleParameter = {new VarInteger("Th. scale 1:", 100), new VarInteger("Th. scale 2:", 100),
-        new VarInteger("Th. scale 3:", 100), new VarInteger("Th. scale 4:", 100), new VarInteger("Th. scale 5:", 100)};
-
-    VarSequence outSequence = new VarSequence("output Sequence", null);
-    VarSequence denoisedSequence = new VarSequence("denoised Sequence", null);
+    VarBoolean[] useScaleBoolean = {
+            new VarBoolean("Scale 1", false),
+            new VarBoolean("Scale 2", true),
+            new VarBoolean("Scale 3", false),
+            new VarBoolean("Scale 4", false),
+            new VarBoolean("Scale 5", false)
+    };
+
+    VarInteger[] scaleParameter = {
+            new VarInteger("Th. scale 1:", 100),
+            new VarInteger("Th. scale 2:", 100),
+            new VarInteger("Th. scale 3:", 100),
+            new VarInteger("Th. scale 4:", 100),
+            new VarInteger("Th. scale 5:", 100)
+    };
+
+    //VarSequence outSequence = new VarSequence("output Sequence", null);
+    //VarSequence denoisedSequence = new VarSequence("denoised Sequence", null);
     VarSequence binarySpotSequence = new VarSequence("binary Spot Sequence", null);
     VarROIArray detectionAsROIOut = new VarROIArray("detection as ROIs", null);
 
     @Override
-    public void run()
-    {
-
+    public void run() {
         // test if input sequence has only 1 channel.
 
         Sequence inputSequence = inputSequenceVar.getValue();
 
-        if (inputSequence == null)
-        {
-            throw new VarException("The input sequence must be set");
+        if (inputSequence == null) {
+            throw new VarException(inputSequenceVar, "The input sequence must be set");
         }
 
-        if (inputSequence.getSizeC() != 1)
-        {
-            throw new VarException(
-                "The input sequence must contain only 1 channel. Please use 'Extract Channel' prior to the WaveletBlock");
+        if (inputSequence.getSizeC() != 1) {
+            throw new VarException(inputSequenceVar, "The input sequence must contain only 1 channel. Please use 'Extract Channel' prior to the WaveletBlock");
         }
 
         // inputChannelVar
@@ -75,38 +96,26 @@ public class WaveletSpotDetectorBlock extends Plugin implements Block
 
         boolean detectNegative;
 
-        if (detectionMethod.getValue() == detectionMethodEnum.BRIGHT_SPOT)
-        {
-            detectNegative = false;
-        }
-        else
-        {
-            detectNegative = true;
-        }
+        detectNegative = detectionMethod.getValue() != detectionMethodEnum.BRIGHT_SPOT;
 
         boolean computeWATwithROI = computeWATConsideringROIBoolean.getValue();
 
         // copy ROI from input sequence to the computation sequence
         Sequence inputComputationSequence;
 
-        try
-        {
+        try {
             inputComputationSequence = SequenceUtil.getCopy(inputSequence);
         }
-        catch (InterruptedException ex)
-        {
+        catch (InterruptedException ex) {
             // interrupt process
             return;
         }
 
-        if (inputSequenceROIVar.getValue() != null)
-        {
-            for (ROI2D roi : inputSequenceROIVar.getValue().getROI2Ds())
-            {
+        if (inputSequenceROIVar.getValue() != null) {
+            for (ROI2D roi : inputSequenceROIVar.getValue().getROI2Ds()) {
                 ROI2D roiCopy = (ROI2D) roi.getCopy();
 
-                if (roiCopy != null)
-                {
+                if (roiCopy != null) {
                     inputComputationSequence.addROI(roiCopy);
                 }
             }
@@ -116,73 +125,63 @@ public class WaveletSpotDetectorBlock extends Plugin implements Block
 
         // create UDWTScale Parameter list.
 
-        final ArrayList<UDWTScale> UDWTScaleArrayList = new ArrayList<UDWTScale>();
+        final ArrayList<UDWTScale> UDWTScaleArrayList = new ArrayList<>();
 
         // System.out.println("Block debug.");
 
-        ThreadUtil.invokeNow(new Runnable()
-        {
-
-            @Override
-            public void run()
-            {
-
-                for (int i = 0; i < 5; i++)
-                {
-                    // System.out.println( "Scale enabled #" +i +" : " + useScaleBoolean[i].getValue() );
-                    UDWTScale scale = new UDWTScale(i + 1, useScaleBoolean[i].getValue(), scaleParameter[i].getValue());
-                    UDWTScaleArrayList.add(scale);
-                }
+        ThreadUtil.invokeNow(() -> {
+            for (int i = 0; i < 5; i++) {
+                // System.out.println( "Scale enabled #" +i +" : " + useScaleBoolean[i].getValue() );
+                UDWTScale scale = new UDWTScale(i + 1, useScaleBoolean[i].getValue(), scaleParameter[i].getValue());
+                UDWTScaleArrayList.add(scale);
             }
         });
 
         // Perform detection.
 
-        try
-        {
-            ArrayList<DetectionSpot> detectionResult = waveletCore.computeDetection(true, UDWTScaleArrayList, inputComputationSequence,
-                detectNegative, computeWATwithROI, force2DWaveletVar.getValue());
+        try {
+            ArrayList<DetectionSpot> detectionResult = waveletCore.computeDetection(
+                    true,
+                    UDWTScaleArrayList,
+                    inputComputationSequence,
+                    detectNegative,
+                    computeWATwithROI,
+                    force2DWaveletVar.getValue()
+            );
 
-        // System.out.println( "ROI Mask : " + inputROIForMask.getValue() );
+            // System.out.println( "ROI Mask : " + inputROIForMask.getValue() );
 
-        // Filter spot with ROIs.
-            if (inputROIForMask.getValue().length != 0)
-            {
-                ArrayList<DetectionSpot> detectionResultCopy = new ArrayList<DetectionSpot>(detectionResult);
+            // Filter spot with ROIs.
+            if (inputROIForMask.getValue().length != 0) {
+                ArrayList<DetectionSpot> detectionResultCopy = new ArrayList<>(detectionResult);
 
                 detectionList:
-                for (DetectionSpot spot : detectionResultCopy)
-                {
+                for (DetectionSpot spot : detectionResultCopy) {
                     // Point2D spotCoordinates = new Point2D.Double( spot.getMassCenter().x , spot.getMassCenter().y );
                     // spot.getMassCenter()
 
                     ROI detectionAsROI = null;
 
-                    try
-                    {
-                        ArrayList<DetectionSpot> detectionList = new ArrayList<DetectionSpot>();
+                    try {
+                        ArrayList<DetectionSpot> detectionList = new ArrayList<>();
                         detectionList.add(spot);
-                        detectionAsROI = DetectionToROI.convertDetectionToROI(detectionList).get(0);
+                        detectionAsROI = DetectionToROI.convertDetectionToROI(detectionList).getFirst();
                     }
-                    catch (NullPointerException e)
-                    {
-                        System.err.println("Error in spot to ROI conversion");
+                    catch (NullPointerException e) {
+                        IcyLogger.error(this.getClass(), "Error in spot to ROI conversion.");
                     }
 
-                    if (detectionAsROI == null)
-                    {
-                        System.err.println("Can't convert spot to ROI. spot=" + spot);
+                    if (detectionAsROI == null) {
+                        IcyLogger.error(this.getClass(), "Can't convert spot to ROI. spot=" + spot);
                         continue;
                     }
 
                     // System.out.println( "spot as ROI to test: " + detectionAsROI.getBounds5D() );
 
-                    for (ROI roi : inputROIForMask.getValue())
-                    {
+                    for (ROI roi : inputROIForMask.getValue()) {
                         // System.out.println( "roi contenant: " + roi.getBounds5D() );
 
-                        if (roi.contains(detectionAsROI))
-                        {
+                        if (roi.contains(detectionAsROI)) {
                             // System.out.println("contains");
                             continue detectionList;
                         }
@@ -200,10 +199,8 @@ public class WaveletSpotDetectorBlock extends Plugin implements Block
             {
                 Sequence binarySequence = waveletCore.getBinarySequence();
 
-                if (inputSequenceROIVar.getValue() != null)
-                {
-                    for (ROI2D roi : inputSequenceROIVar.getValue().getROI2Ds())
-                    {
+                if (inputSequenceROIVar.getValue() != null) {
+                    for (ROI2D roi : inputSequenceROIVar.getValue().getROI2Ds()) {
                         // System.out.println("roi:"+roi);
                         String name = roi.getName();
 
@@ -221,52 +218,44 @@ public class WaveletSpotDetectorBlock extends Plugin implements Block
             // output detection as ROI
             {
                 ArrayList<ROI> roiList = DetectionToROI.convertDetectionToROI(detectionResult);
-                ROI roi[] = new ROI[roiList.size()];
+                ROI[] roi = new ROI[roiList.size()];
                 int i = 0;
-                for (ROI roiCandidate : roiList)
-                {
+                for (ROI roiCandidate : roiList) {
                     roi[i] = roiCandidate;
                     i++;
                 }
                 detectionAsROIOut.setValue(roi);
             }
         }
-        catch (InterruptedException e)
-        {
+        catch (InterruptedException e) {
             // protocols process interrupted
             Thread.currentThread().interrupt();
         }
     }
 
     @Override
-    public void declareInput(VarList inputMap)
-    {
-
-        inputMap.add(inputSequenceVar);
-        inputMap.add(detectionMethod);
-        inputMap.add("input Sequence ROIs", inputSequenceROIVar);
-        inputMap.add(computeWATConsideringROIBoolean);
-        inputMap.add(inputROIForMask);
-
-        for (int i = 0; i < 5; i++)
-        {
-            inputMap.add(useScaleBoolean[i]);
+    public void declareInput(@NotNull VarList inputMap) {
+        inputMap.add("input-sequence", inputSequenceVar);
+        inputMap.add("detection-method", detectionMethod);
+        inputMap.add("input-sequence-rois", inputSequenceROIVar);
+        inputMap.add("compute-wat-considering-roi", computeWATConsideringROIBoolean);
+        inputMap.add("input-roi-for-mask", inputROIForMask);
+
+        for (int i = 0; i < 5; i++) {
+            inputMap.add("use-scale-" + i, useScaleBoolean[i]);
         }
-        for (int i = 0; i < 5; i++)
-        {
-            inputMap.add(scaleParameter[i]);
+        for (int i = 0; i < 5; i++) {
+            inputMap.add("scale-value-" + i, scaleParameter[i]);
         }
-        inputMap.add(force2DWaveletVar);
+        inputMap.add("force-2d-wavelet", force2DWaveletVar);
     }
 
     @Override
-    public void declareOutput(VarList outputMap)
-    {
-
+    public void declareOutput(@NotNull VarList outputMap) {
         // outputMap.add( outSequence );
         // outputMap.add( denoisedSequence );
-        outputMap.add(binarySpotSequence);
-        outputMap.add(detectionAsROIOut);
+        outputMap.add("Binary Spot Sequence", binarySpotSequence);
+        outputMap.add("Detection as ROI", detectionAsROIOut);
 
     }
 
diff --git a/src/main/resources/spot-detector-block.png b/src/main/resources/spot-detector-block.png
new file mode 100644
index 0000000000000000000000000000000000000000..fc0a7455a4c58ab68ab497d0e1ad058e45c28cc4
Binary files /dev/null and b/src/main/resources/spot-detector-block.png differ