diff --git a/pom.xml b/pom.xml
index 107ccb9feff3336eba517ca04d328fd3cec64b6a..d7827329d567dc7eee839ff9cea5f39b754e5b37 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,11 +7,11 @@
     <parent>
         <groupId>org.bioimageanalysis.icy</groupId>
         <artifactId>pom-icy</artifactId>
-        <version>3.0.0-a.1</version>
+        <version>3.0.0-a.3</version>
     </parent>
 
     <artifactId>connected-components</artifactId>
-    <version>5.0.0-a.1</version>
+    <version>5.0.0-a.2</version>
 
     <name>ConnectedComponents</name>
     <description>
@@ -47,12 +47,4 @@
             <artifactId>jama</artifactId>
         </dependency>
     </dependencies>
-
-    <repositories>
-        <repository>
-            <id>icy</id>
-            <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/adufour/connectedcomponents/ConnectedComponent.java b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponent.java
index fa8fa12154b7508e4079ba0d7f4cee12fcd6db53..9187727616c3debf5ee26b87ca72c40c4228793b 100644
--- a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponent.java
+++ b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2024. Institut Pasteur.
+ * Copyright (c) 2010-2025. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,7 +18,6 @@
 
 package plugins.adufour.connectedcomponents;
 
-
 import org.bioimageanalysis.extension.kernel.roi.roi2d.ROI2DArea;
 import org.bioimageanalysis.extension.kernel.roi.roi3d.ROI3DArea;
 import org.bioimageanalysis.icy.common.collection.array.Array1DUtil;
@@ -174,7 +173,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      * @param t        int
      * @return an array containing the average intensity of the component in each band
      */
-    public double[] computeMeanIntensity(final Sequence sequence, final int t) {
+    public double[] computeMeanIntensity(final @NotNull Sequence sequence, final int t) {
         final double[] intensitySum = new double[sequence.getSizeC()];
 
         for (final Point3i point : points) {
@@ -249,7 +248,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      * @param t        int
      * @return an array containing the average intensity of the component in each band
      */
-    public double[] computeMaxIntensity(final Sequence sequence, final int t) {
+    public double[] computeMaxIntensity(final @NotNull Sequence sequence, final int t) {
         final double[] maxIntensity = new double[sequence.getSizeC()];
 
         for (final Point3i point : points) {
@@ -529,7 +528,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      * @return true if this component intersects (e.g. has at least one voxel overlapping with) the
      * specified component
      */
-    public boolean intersects(final ConnectedComponent component) {
+    public boolean intersects(final @NotNull ConnectedComponent component) {
         final int thisSize = getSize();
         final int componentSize = component.getSize();
 
diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponentDescriptor.java b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponentDescriptor.java
index abe0eeb05d47329ff0d3a403bada3671896933b6..b681d04c55ef603d023e3292de01c414b3ee88ce 100644
--- a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponentDescriptor.java
+++ b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponentDescriptor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2024. Institut Pasteur.
+ * Copyright (c) 2010-2025. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -22,9 +22,12 @@ import Jama.EigenvalueDecomposition;
 import Jama.Matrix;
 import org.bioimageanalysis.icy.common.type.DataType;
 import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin;
-import org.bioimageanalysis.icy.extension.plugin.interface_.PluginBundled;
+import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon;
+import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName;
 import org.bioimageanalysis.icy.model.image.IcyBufferedImage;
 import org.bioimageanalysis.icy.model.sequence.Sequence;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
 import plugins.adufour.blocks.lang.Block;
 import plugins.adufour.blocks.util.VarList;
 import plugins.adufour.quickhull.QuickHull2D;
@@ -38,7 +41,9 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-public class ConnectedComponentDescriptor extends Plugin implements PluginBundled, Block {
+@IcyPluginName("Connected Components Block")
+@IcyPluginIcon(path = "/plugins/adufour/connectedcomponents/Connected_Components.png")
+public class ConnectedComponentDescriptor extends Plugin implements Block {
     Var<ConnectedComponent> varCC = new Var<>("Connected component", ConnectedComponent.class);
 
     VarDouble perimeter = new VarDouble("perimeter", 0.0);
@@ -54,17 +59,12 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
     VarDouble shortAxisZ = new VarDouble("short diameter (Z)", 0.0);
 
     @Override
-    public String getMainPluginClassName() {
-        return ConnectedComponents.class.getName();
-    }
-
-    @Override
-    public void declareInput(final VarList inputMap) {
+    public void declareInput(final @NotNull VarList inputMap) {
         inputMap.add("component", varCC);
     }
 
     @Override
-    public void declareOutput(final VarList outputMap) {
+    public void declareOutput(final @NotNull VarList outputMap) {
         outputMap.add("perimeter", perimeter);
         outputMap.add("long diameter", longAxis);
         outputMap.add("short diameter", shortAxis);
@@ -168,7 +168,11 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      * @param bsCenter the computed center of the bounding sphere
      * @param bsRadius the computed radius of the bounding sphere
      */
-    public void computeBoundingSphere(final ConnectedComponent cc, final Point3d bsCenter, final VarDouble bsRadius) {
+    public void computeBoundingSphere(
+            final @NotNull ConnectedComponent cc,
+            final @NotNull Point3d bsCenter,
+            final @NotNull VarDouble bsRadius
+    ) {
         bsCenter.set(cc.getMassCenter());
         bsRadius.setValue(cc.getMaxDistanceTo(bsCenter));
     }
@@ -181,7 +185,11 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      *                       extracted contour
      * @return The 3D perimeter (or 3D surface) of this component
      */
-    public double computePerimeter(final ConnectedComponent cc, final ArrayList<Point3i> contourPoints, final Sequence outputSequence) {
+    public double computePerimeter(
+            final ConnectedComponent cc,
+            final ArrayList<Point3i> contourPoints,
+            final Sequence outputSequence
+    ) {
         double perimeter = 0;
 
         if (contourPoints != null)
@@ -368,7 +376,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      * object. The 2 values are returned together because their computation is simultaneous
      * (in the 3D case only)
      */
-    public double[] computeConvexAreaAndVolume(final ConnectedComponent cc) {
+    public double[] computeConvexAreaAndVolume(final @NotNull ConnectedComponent cc) {
         int i = 0;
         final int n = cc.getSize();
         if (n == 1)
@@ -447,7 +455,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      * @param r  the moment order along Z (set to 0 if the object is 2D)
      * @return the geometric moment
      */
-    public double computeGeometricMoment(final ConnectedComponent cc, final int p, final int q, final int r) {
+    public double computeGeometricMoment(final @NotNull ConnectedComponent cc, final int p, final int q, final int r) {
         double moment = 0;
 
         final Point3d center = cc.getMassCenter();
@@ -478,8 +486,13 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      * @throws IllegalArgumentException if the number of points in the component is too low (minimum is 9)
      * @throws SingularMatrixException  if the component is flat (i.e., lies in a 2D plane)
      */
-    public void computeEllipse(final ConnectedComponent cc, final Point3d center, final Point3d radii, final Vector3d[] eigenVectors,
-                               final double[] equation) throws IllegalArgumentException {
+    public void computeEllipse(
+            final @NotNull ConnectedComponent cc,
+            final Point3d center,
+            final Point3d radii,
+            final Vector3d[] eigenVectors,
+            final double[] equation
+    ) throws IllegalArgumentException {
         final int nPoints = cc.getSize();
         if (nPoints < 9) {
             throw new IllegalArgumentException("Too few points; need at least 9 to calculate a unique ellipsoid");
@@ -560,8 +573,13 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      *                 vector <b>A</b> represented in the array is normed, so that ||<b>A</b>||=1.
      * @throws RuntimeException if the ellipse calculation fails (e.g., if a singular matrix is detected)
      */
-    public void computeEllipse(final ConnectedComponent cc, final Point2d center, final Point2d radii, final VarDouble angle, final double[] equation)
-            throws RuntimeException {
+    public void computeEllipse(
+            final @NotNull ConnectedComponent cc,
+            final Point2d center,
+            final Point2d radii,
+            final VarDouble angle,
+            final double[] equation
+    ) throws RuntimeException {
         final Point3i[] points = cc.getPoints();
         final Point3d ccenter = cc.getMassCenter();
 
@@ -595,8 +613,11 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
         final Matrix M = S1.plus(S2.times(T));
 
         final double[][] m = M.getArray();
-        final double[][] n = {{m[2][0] / 2, m[2][1] / 2, m[2][2] / 2}, {-m[1][0], -m[1][1], -m[1][2]},
-                {m[0][0] / 2, m[0][1] / 2, m[0][2] / 2}};
+        final double[][] n = {
+                {m[2][0] / 2, m[2][1] / 2, m[2][2] / 2},
+                {-m[1][0], -m[1][1], -m[1][2]},
+                {m[0][0] / 2, m[0][1] / 2, m[0][2] / 2}
+        };
 
         final Matrix N = new Matrix(n);
 
@@ -692,7 +713,8 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
         return minBB.z == maxBB.z;
     }
 
-    private Matrix diag(final Matrix matrix) {
+    @Contract("_ -> new")
+    private @NotNull Matrix diag(final @NotNull Matrix matrix) {
         final int min = Math.min(matrix.getRowDimension(), matrix.getColumnDimension());
         final double[][] diag = new double[min][1];
         for (int i = 0; i < min; i++) {
@@ -701,7 +723,8 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
         return new Matrix(diag);
     }
 
-    private Matrix ones(final int m, final int n) {
+    @Contract("_, _ -> new")
+    private @NotNull Matrix ones(final int m, final int n) {
         final double[][] array = new double[m][n];
         for (final double[] row : array)
             Arrays.fill(row, 1.0);
diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents.java b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents.java
index f8113aab490c93a7ff99014e453cf3371815f2e1..2d6690ea376171c8ffc2530ac411438654dae07c 100644
--- a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents.java
+++ b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2024. Institut Pasteur.
+ * Copyright (c) 2010-2025. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -40,6 +40,8 @@ import org.bioimageanalysis.icy.model.sequence.SequenceDataIterator;
 import org.bioimageanalysis.icy.model.sequence.VolumetricImage;
 import org.bioimageanalysis.icy.model.swimmingPool.SwimmingObject;
 import org.bioimageanalysis.icy.system.IcyHandledException;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
 import plugins.adufour.blocks.lang.Block;
 import plugins.adufour.blocks.util.VarList;
 import plugins.adufour.ezplug.*;
@@ -58,7 +60,7 @@ import java.io.IOException;
 import java.util.*;
 
 @IcyPluginName("Connected Components")
-@IcyPluginIcon(path = "/icon/Connected_Components.png")
+@IcyPluginIcon(path = "/plugins/adufour/connectedcomponents/Connected_Components.png")
 public class ConnectedComponents extends EzPlug implements Block {
     /**
      * List of extraction methods suitable for the Connected Components plugin
@@ -517,6 +519,7 @@ public class ConnectedComponents extends EzPlug implements Block {
          * @param value the pixel value
          * @param label the label value
          */
+        @Contract(pure = true)
         Label(final double value, final int label) {
             this.imageValue = value;
             this.targetLabelValue = label;
@@ -525,6 +528,7 @@ public class ConnectedComponents extends EzPlug implements Block {
         /**
          * Retrieves the final object label (recursively)
          */
+        @Contract(pure = true)
         int getFinalLabelValue() {
             return targetLabel == null ? targetLabelValue : targetLabel.getFinalLabelValue();
         }
@@ -542,7 +546,11 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ExtractionType
      * @see ConnectedComponent
      */
-    public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(final Sequence inputSequence, final Sequence labeledSequence) {
+    @Contract("null, _ -> fail")
+    public static @NotNull Map<Integer, List<ConnectedComponent>> extractConnectedComponents(
+            final Sequence inputSequence,
+            final Sequence labeledSequence
+    ) {
         return extractConnectedComponents(inputSequence, false, 0, Integer.MAX_VALUE, labeledSequence);
     }
 
@@ -560,7 +568,13 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ExtractionType
      * @see ConnectedComponent
      */
-    public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(final Sequence inputSequence, final int minSize, final int maxSize, final Sequence labeledSequence) {
+    @Contract("null, _, _, _ -> fail")
+    public static @NotNull Map<Integer, List<ConnectedComponent>> extractConnectedComponents(
+            final Sequence inputSequence,
+            final int minSize,
+            final int maxSize,
+            final Sequence labeledSequence
+    ) {
         return extractConnectedComponents(inputSequence, false, minSize, maxSize, labeledSequence);
     }
 
@@ -579,10 +593,22 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ExtractionType
      * @see ConnectedComponent
      */
-    public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(final Sequence inputSequence, final boolean isInputLabeled, final int minSize, final int maxSize, final Sequence labeledSequence) {
-        return extractConnectedComponents(inputSequence, 0,
-                isInputLabeled ? ExtractionType.BACKGROUND_LABELED : ExtractionType.BACKGROUND, minSize, maxSize,
-                labeledSequence);
+    @Contract("null, _, _, _, _ -> fail")
+    public static @NotNull Map<Integer, List<ConnectedComponent>> extractConnectedComponents(
+            final Sequence inputSequence,
+            final boolean isInputLabeled,
+            final int minSize,
+            final int maxSize,
+            final Sequence labeledSequence
+    ) {
+        return extractConnectedComponents(
+                inputSequence,
+                0,
+                isInputLabeled ? ExtractionType.BACKGROUND_LABELED : ExtractionType.BACKGROUND,
+                minSize,
+                maxSize,
+                labeledSequence
+        );
     }
 
     /**
@@ -601,8 +627,26 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ExtractionType
      * @see ConnectedComponent
      */
-    public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(final Sequence inputSequence, final double value, final ExtractionType type, final int minSize, final int maxSize, final Sequence labeledSequence) {
-        return extractConnectedComponents(inputSequence, value, type, false, false, false, minSize, maxSize, labeledSequence);
+    @Contract("null, _, _, _, _, _ -> fail")
+    public static @NotNull Map<Integer, List<ConnectedComponent>> extractConnectedComponents(
+            final Sequence inputSequence,
+            final double value,
+            final ExtractionType type,
+            final int minSize,
+            final int maxSize,
+            final Sequence labeledSequence
+    ) {
+        return extractConnectedComponents(
+                inputSequence,
+                value,
+                type,
+                false,
+                false,
+                false,
+                minSize,
+                maxSize,
+                labeledSequence
+        );
     }
 
     /**
@@ -627,8 +671,17 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ExtractionType
      * @see ConnectedComponent
      */
-    public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(
-            final Sequence inputSequence, final double value, final ExtractionType type, final boolean noEdgeX, final boolean noEdgeY, final boolean noEdgeZ, final int minSize, final int maxSize, Sequence labeledSequence
+    @Contract("null, _, _, _, _, _, _, _, _ -> fail")
+    public static @NotNull Map<Integer, List<ConnectedComponent>> extractConnectedComponents(
+            final Sequence inputSequence,
+            final double value,
+            final ExtractionType type,
+            final boolean noEdgeX,
+            final boolean noEdgeY,
+            final boolean noEdgeZ,
+            final int minSize,
+            final int maxSize,
+            Sequence labeledSequence
     ) {
         if (inputSequence == null || inputSequence.getSizeT() == 0)
             throw new IllegalArgumentException("Cannot extract connected components from an empty sequence !");
@@ -688,10 +741,28 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ExtractionType
      * @see ConnectedComponent
      */
-    public static List<ConnectedComponent> extractConnectedComponents(
-            final VolumetricImage stack, final double value, final ExtractionType type, final boolean noEdgeX, final boolean noEdgeY, final boolean noEdgeZ, final int minSize, final int maxSize
+    @Contract("_, _, _, _, _, _, _, _ -> new")
+    public static @NotNull List<ConnectedComponent> extractConnectedComponents(
+            final VolumetricImage stack,
+            final double value,
+            final ExtractionType type,
+            final boolean noEdgeX,
+            final boolean noEdgeY,
+            final boolean noEdgeZ,
+            final int minSize,
+            final int maxSize
     ) {
-        return extractConnectedComponents(stack, value, type, noEdgeX, noEdgeY, noEdgeZ, minSize, maxSize, new VolumetricImage());
+        return extractConnectedComponents(
+                stack,
+                value,
+                type,
+                noEdgeX,
+                noEdgeY,
+                noEdgeZ,
+                minSize,
+                maxSize,
+                new VolumetricImage()
+        );
     }
 
     /**
@@ -719,8 +790,17 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ExtractionType
      * @see ConnectedComponent
      */
-    public static List<ConnectedComponent> extractConnectedComponents(
-            final VolumetricImage stack, final double value, final ExtractionType type, final boolean noEdgeX, final boolean noEdgeY, final boolean noEdgeZ, final int minSize, final int maxSize, final VolumetricImage labeledStack
+    @Contract("_, _, _, _, _, _, _, _, _ -> new")
+    public static @NotNull List<ConnectedComponent> extractConnectedComponents(
+            final @NotNull VolumetricImage stack,
+            final double value,
+            final ExtractionType type,
+            final boolean noEdgeX,
+            final boolean noEdgeY,
+            final boolean noEdgeZ,
+            final int minSize,
+            final int maxSize,
+            final VolumetricImage labeledStack
     ) throws NullPointerException {
         final int width = stack.getFirstImage().getSizeX();
         final int height = stack.getFirstImage().getSizeY();
@@ -1181,8 +1261,10 @@ public class ConnectedComponents extends EzPlug implements Block {
         return new ArrayList<>(componentsMap.values());
     }
 
-    public static DetectionResult convertToDetectionResult(final Map<Integer, List<ConnectedComponent>> detections, final Sequence sequence) {
-
+    public static @NotNull DetectionResult convertToDetectionResult(
+            final @NotNull Map<Integer, List<ConnectedComponent>> detections,
+            final Sequence sequence
+    ) {
         final DetectionResult detectionResult = new DetectionResult();
         for (final Integer t : detections.keySet())
             for (final ConnectedComponent cc : detections.get(t)) {
@@ -1204,7 +1286,11 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @param components Map of List of ConnectedComponent
      * @param comparator Comparator of ConnectedComponents
      */
-    public static void createLabeledSequence(final Sequence output, final Map<Integer, List<ConnectedComponent>> components, final Comparator<ConnectedComponent> comparator) {
+    public static void createLabeledSequence(
+            final Sequence output,
+            final Map<Integer, List<ConnectedComponent>> components,
+            final Comparator<ConnectedComponent> comparator
+    ) {
         if (comparator == null)
             return;
 
diff --git a/src/main/resources/icon/Connected_Components.png b/src/main/resources/plugins/adufour/connectedcomponents/Connected_Components.png
similarity index 100%
rename from src/main/resources/icon/Connected_Components.png
rename to src/main/resources/plugins/adufour/connectedcomponents/Connected_Components.png