diff --git a/pom.xml b/pom.xml
index 07534cb08f3c819c6ce972a35d7a8b3c738d2bcb..061aebae96da6f0c541782c16fff159f0be21308 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
     </parent>
 
     <artifactId>connected-components</artifactId>
-    <version>4.8.9</version>
+    <version>5.0.0</version>
 
     <packaging>jar</packaging>
 
diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponent.java b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponent.java
index fe242f983ab038d1eb57080429822b3ac956a2ef..dfa7b47030215f8e49c7c3faae7119e5b189cbdd 100644
--- a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponent.java
+++ b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponent.java
@@ -1,12 +1,22 @@
-package plugins.adufour.connectedcomponents;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
+/*
+ * 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 javax.vecmath.Point3d;
-import javax.vecmath.Point3i;
-import javax.vecmath.Vector3d;
+package plugins.adufour.connectedcomponents;
 
 import icy.image.IcyBufferedImage;
 import icy.roi.ROI;
@@ -19,6 +29,13 @@ import plugins.kernel.roi.roi2d.ROI2DArea;
 import plugins.kernel.roi.roi3d.ROI3DArea;
 import plugins.nchenouard.spot.Detection;
 
+import javax.vecmath.Point3d;
+import javax.vecmath.Point3i;
+import javax.vecmath.Vector3d;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
 public class ConnectedComponent extends Detection implements Iterable<Point3i> {
     private int c = -1;
 
@@ -45,7 +62,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
     private final ArrayList<Point3i> points;
 
     /**
-     * the array of contour points of this object
+     * the array of this object contour points
      */
     private Point3i[] contourPoints;
 
@@ -62,13 +79,13 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      *
      * @param initialCapacity int
      */
-    public ConnectedComponent(int initialCapacity) {
+    public ConnectedComponent(final int initialCapacity) {
         super(0, 0, 0, 0);
         this.points = new ArrayList<>(initialCapacity);
         coordsSum = new Point3d();
     }
 
-    void addPointInternal(Point3i point) {
+    void addPointInternal(final Point3i point) {
         points.add(point);
 
         // accumulate coordinates to compute the mass center
@@ -84,7 +101,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      *
      * @param point the point to add
      */
-    public void addPoint(Point3i point) {
+    public void addPoint(final Point3i point) {
         addPointInternal(point);
         updateDetectionCoords();
     }
@@ -95,7 +112,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      *
      * @param point the point to add
      */
-    void removePointInternal(Point3i point) {
+    void removePointInternal(final Point3i point) {
         if (!points.remove(point))
             return;
 
@@ -116,39 +133,26 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
     }
 
     /**
-     * @return true is the object touches the image edge along X
+     * @return true, if the object touches the image edge along X
      */
     public boolean isOnEdgeX() {
         return onEdgeX;
     }
 
     /**
-     * @return true is the object touches the image edge along Y
+     * @return true, if the object touches the image edge along Y
      */
     public boolean isOnEdgeY() {
         return onEdgeY;
     }
 
     /**
-     * @return true is the object touches the image edge along Z (always true for 2D images)
+     * @return true, if the object touches the image edge along Z (always true for 2D images)
      */
     public boolean isOnEdgeZ() {
         return onEdgeZ;
     }
 
-    /**
-     * Computes the bounding box of this component, and stores the result into the given arguments
-     *
-     * @param start the first corner of the bounding box in X-Y-Z order (Upper-Left hand-Top)
-     * @param end   the second corner of the bounding box in X-Y-Z order (Lower-Right hand-Bottom)
-     * @deprecated Use {@link ConnectedComponentDescriptor#computeBoundingBox(ConnectedComponent, Point3i, Point3i)}
-     * instead
-     */
-    @Deprecated
-    public void computeBoundingBox(Point3i start, Point3i end) {
-        shapeDescriptor.computeBoundingBox(this, start, end);
-    }
-
     /**
      * Computes the average intensity of the component on each channel of the given sequence, at the
      * time point where this component was found
@@ -156,7 +160,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      * @param sequence Sequence
      * @return an array containing the average intensity of the component in each band
      */
-    public double[] computeMeanIntensity(Sequence sequence) {
+    public double[] computeMeanIntensity(final Sequence sequence) {
         return computeMeanIntensity(sequence, t);
     }
 
@@ -168,13 +172,13 @@ 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(Sequence sequence, int t) {
-        double[] intensitySum = new double[sequence.getSizeC()];
+    public double[] computeMeanIntensity(final Sequence sequence, final int t) {
+        final double[] intensitySum = new double[sequence.getSizeC()];
 
-        for (Point3i point : points) {
-            int offsetXY = point.x + point.y * sequence.getSizeX();
+        for (final Point3i point : points) {
+            final int offsetXY = point.x + point.y * sequence.getSizeX();
 
-            Object dataCXY = sequence.getDataXYC(t, point.z);
+            final Object dataCXY = sequence.getDataXYC(t, point.z);
 
             for (int c = 0; c < intensitySum.length; c++)
                 intensitySum[c] += Array1DUtil.getValue(((Object[]) dataCXY)[c], offsetXY,
@@ -193,7 +197,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      * @param sequence Sequence
      * @return an array containing the average intensity of the component in each band
      */
-    public double[] computeMinIntensity(Sequence sequence) {
+    public double[] computeMinIntensity(final Sequence sequence) {
         return computeMinIntensity(sequence, t);
     }
 
@@ -205,17 +209,17 @@ 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[] computeMinIntensity(Sequence sequence, int t) {
-        double[] minIntensity = new double[sequence.getSizeC()];
+    public double[] computeMinIntensity(final Sequence sequence, final int t) {
+        final double[] minIntensity = new double[sequence.getSizeC()];
         Arrays.fill(minIntensity, Double.MAX_VALUE);
 
-        for (Point3i point : points) {
-            int offsetXY = point.x + point.y * sequence.getSizeX();
+        for (final Point3i point : points) {
+            final int offsetXY = point.x + point.y * sequence.getSizeX();
 
-            Object dataCXY = sequence.getImage(t, point.z).getDataXYC();
+            final Object dataCXY = sequence.getImage(t, point.z).getDataXYC();
 
             for (int c = 0; c < minIntensity.length; c++) {
-                double val = Array1DUtil.getValue(((Object[]) dataCXY)[c], offsetXY,
+                final double val = Array1DUtil.getValue(((Object[]) dataCXY)[c], offsetXY,
                         sequence.getDataType_().isSigned());
                 if (val < minIntensity[c])
                     minIntensity[c] = val;
@@ -231,7 +235,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      * @param sequence Sequence
      * @return an array containing the average intensity of the component in each band
      */
-    public double[] computeMaxIntensity(Sequence sequence) {
+    public double[] computeMaxIntensity(final Sequence sequence) {
         return computeMaxIntensity(sequence, t);
     }
 
@@ -243,16 +247,16 @@ 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(Sequence sequence, int t) {
-        double[] maxIntensity = new double[sequence.getSizeC()];
+    public double[] computeMaxIntensity(final Sequence sequence, final int t) {
+        final double[] maxIntensity = new double[sequence.getSizeC()];
 
-        for (Point3i point : points) {
-            int offsetXY = point.x + point.y * sequence.getSizeX();
+        for (final Point3i point : points) {
+            final int offsetXY = point.x + point.y * sequence.getSizeX();
 
-            Object dataCXY = sequence.getImage(t, point.z).getDataXYC();
+            final Object dataCXY = sequence.getImage(t, point.z).getDataXYC();
 
             for (int c = 0; c < maxIntensity.length; c++) {
-                double val = Array1DUtil.getValue(((Object[]) dataCXY)[c], offsetXY,
+                final double val = Array1DUtil.getValue(((Object[]) dataCXY)[c], offsetXY,
                         sequence.getDataType_().isSigned());
                 if (val > maxIntensity[c])
                     maxIntensity[c] = val;
@@ -262,20 +266,20 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
     }
 
     /**
-     * Computes the closest euclidean distance between any two points of this component and the
+     * Computes the closest Euclidean distance between any two points of this component and the
      * given component
      *
      * @param component the component to compute the distance to
      * @return double
      */
-    public double distanceTo(ConnectedComponent component) {
+    public double distanceTo(final ConnectedComponent component) {
         double distance = Double.MAX_VALUE;
-        for (Point3i srcPt : this) {
-            Vector3d srcV = new Vector3d(srcPt.x, srcPt.y, srcPt.z);
-            for (Point3i dstPt : component) {
-                Vector3d dstV = new Vector3d(dstPt.x, dstPt.y, dstPt.z);
+        for (final Point3i srcPt : this) {
+            final Vector3d srcV = new Vector3d(srcPt.x, srcPt.y, srcPt.z);
+            for (final Point3i dstPt : component) {
+                final Vector3d dstV = new Vector3d(dstPt.x, dstPt.y, dstPt.z);
                 dstV.sub(srcV);
-                double length = dstV.length();
+                final double length = dstV.length();
                 if (length < distance)
                     distance = length;
             }
@@ -297,27 +301,28 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      * Computes the major axis of the object, which is the vector between the two most distant
      * points of this component. Note that the result vector orientation is meaningless if the
      * component is spherical.<br>
-     * NOTE: this is an potentially expensive operation: O(N log N)
+     * NOTE: this is a potentially expensive operation: O(N log N)
      *
      * @return 3D Vector
      */
     public Vector3d getMajorAxis() {
         double maxDist = 0;
 
-        Vector3d vector = new Vector3d();
-        Point3d pid = new Point3d(), pjd = new Point3d();
+        final Vector3d vector = new Vector3d();
+        final Point3d pid = new Point3d();
+        final Point3d pjd = new Point3d();
 
-        int n = points.size();
+        final int n = points.size();
         for (int i = 0; i < n - 1; i++) {
-            Point3i pi = points.get(i);
+            final Point3i pi = points.get(i);
             pid.set(pi.x, pi.y, pi.z);
 
             for (int j = i + 1; j < n; j++) {
-                Point3i pj = points.get(j);
+                final Point3i pj = points.get(j);
                 pjd.set(pj.x, pj.y, pj.z);
 
                 // compare the squared distance to save the square root operation
-                double dist = pid.distanceSquared(pjd);
+                final double dist = pid.distanceSquared(pjd);
 
                 if (dist > maxDist) {
                     maxDist = dist;
@@ -330,7 +335,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
     }
 
     void updateDetectionCoords() {
-        double factor = 1.0 / getSize();
+        final double factor = 1.0 / getSize();
         x = coordsSum.x * factor;
         y = coordsSum.y * factor;
         z = coordsSum.z * factor;
@@ -382,11 +387,11 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      * @param point 3D Point
      * @return double
      */
-    public double getMaxDistanceTo(Point3d point) {
+    public double getMaxDistanceTo(final Point3d point) {
         double maxDist = 0;
 
-        for (Point3i p : this) {
-            double dist = point.distance(new Point3d(p.x, p.y, p.z));
+        for (final Point3i p : this) {
+            final double dist = point.distance(new Point3d(p.x, p.y, p.z));
             if (dist > maxDist)
                 maxDist = dist;
         }
@@ -414,18 +419,19 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      * @param outputSequence (set to null if not wanted) an output sequence to receive the extracted contour
      * @return An array containing all the contour pixels of this component
      */
-    public Point3i[] getContourPoints(Sequence outputSequence) {
+    public Point3i[] getContourPoints(final Sequence outputSequence) {
         if (contourPoints == null) {
-            ArrayList<Point3i> list = new ArrayList<>(getSize() / 2);
+            final ArrayList<Point3i> list = new ArrayList<>(getSize() / 2);
 
-            Point3i min = new Point3i(), max = new Point3i();
+            final Point3i min = new Point3i();
+            final Point3i max = new Point3i();
             shapeDescriptor.computeBoundingBox(this, min, max);
 
-            Sequence mask = toSequence();
+            final Sequence mask = toSequence();
             final boolean outputVolatile;
-            int w = mask.getSizeX();
-            int h = mask.getSizeY();
-            int d = mask.getSizeZ();
+            final int w = mask.getSizeX();
+            final int h = mask.getSizeY();
+            final int d = mask.getSizeZ();
 
             byte[][] outputMask = null;
 
@@ -443,16 +449,16 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
             else
                 outputVolatile = false;
 
-            byte[][] mask_z_xy = mask.getDataXYZAsByte(0, 0);
+            final byte[][] mask_z_xy = mask.getDataXYZAsByte(0, 0);
 
-            Point3i localP = new Point3i();
+            final Point3i localP = new Point3i();
 
             if (min.z != max.z) {
                 mainLoop:
-                for (Point3i p : points) {
+                for (final Point3i p : points) {
                     localP.sub(p, min);
 
-                    int xy = localP.y * w + localP.x;
+                    final int xy = localP.y * w + localP.x;
 
                     if (localP.x == 0 || localP.y == 0 || localP.x == w - 1 || localP.y == h - 1 || localP.z == 0
                             || localP.z == d - 1) {
@@ -462,7 +468,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
                         continue;
                     }
 
-                    for (byte[] z : new byte[][]{mask_z_xy[localP.z - 1], mask_z_xy[localP.z],
+                    for (final byte[] z : new byte[][]{mask_z_xy[localP.z - 1], mask_z_xy[localP.z],
                             mask_z_xy[localP.z + 1]})
                         if (z[xy - w] == 0 || z[xy - 1] == 0 || z[xy + 1] == 0 || z[xy + w] == 0 || z[xy - w - 1] == 0
                                 || z[xy - w + 1] == 0 || z[xy + w - 1] == 0 || z[xy + w + 1] == 0) {
@@ -479,10 +485,10 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
                 }
             }
             else {
-                for (Point3i p : points) {
+                for (final Point3i p : points) {
                     localP.sub(p, min);
 
-                    int xy = localP.y * w + localP.x;
+                    final int xy = localP.y * w + localP.x;
 
                     if (localP.x == 0 || localP.y == 0 || localP.x == w - 1 || localP.y == h - 1) {
                         list.add(p);
@@ -491,7 +497,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
                         continue;
                     }
 
-                    byte[] z = mask_z_xy[localP.z];
+                    final byte[] z = mask_z_xy[localP.z];
 
                     if (z[xy - w] == 0 || z[xy - 1] == 0 || z[xy + 1] == 0 || z[xy + w] == 0)
                     // || z[xy - w - 1] == 0
@@ -510,7 +516,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
             if ((outputSequence != null) && outputVolatile)
                 outputSequence.setVolatile(true);
 
-            contourPoints = list.toArray(new Point3i[list.size()]);
+            contourPoints = list.toArray(new Point3i[0]);
         }
 
         return contourPoints;
@@ -521,12 +527,12 @@ 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(ConnectedComponent component) {
-        int thisSize = getSize();
-        int componentSize = component.getSize();
+    public boolean intersects(final ConnectedComponent component) {
+        final int thisSize = getSize();
+        final int componentSize = component.getSize();
 
-        Point3i thisPt = new Point3i();
-        Point3i componentPt = new Point3i();
+        final Point3i thisPt = new Point3i();
+        final Point3i componentPt = new Point3i();
 
         for (int i = 0; i < thisSize; i++) {
             thisPt.set(points.get(i));
@@ -546,12 +552,12 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      * @param component ConnectedComponent
      * @return ConnectedComponent
      */
-    public ConnectedComponent intersection(ConnectedComponent component) {
-        ConnectedComponent intersection = new ConnectedComponent(0);
+    public ConnectedComponent intersection(final ConnectedComponent component) {
+        final ConnectedComponent intersection = new ConnectedComponent(0);
 
         // construct the intersection
-        for (Point3i srcPt : this)
-            for (Point3i dstPt : component) {
+        for (final Point3i srcPt : this)
+            for (final Point3i dstPt : component) {
                 if (srcPt.equals(dstPt)) {
                     intersection.addPointInternal(srcPt);
                     break;
@@ -574,23 +580,23 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      * @param c     int
      * @param value double
      */
-    public void paintOnSequence(Sequence s, int t, int c, double value) throws InterruptedException {
+    public void paintOnSequence(final Sequence s, final int t, final int c, final double value) throws InterruptedException {
         DataIteratorUtil.set(new SequenceDataIterator(s, toROI(), true, -1, t, c), value);
     }
 
-    public void setC(int c) {
+    public void setC(final int c) {
         this.c = c;
     }
 
     /**
-     * @return a region of interest of type area representing this connected component
+     * @return a ROI of type area representing this connected component
      */
     public ROI toROI() {
         int z = 0;
 
-        ROI3DArea area3D = new ROI3DArea();
+        final ROI3DArea area3D = new ROI3DArea();
         area3D.beginUpdate();
-        for (Point3i pt : this) {
+        for (final Point3i pt : this) {
             z = pt.z;
             area3D.addPoint(pt.x, pt.y, pt.z);
         }
@@ -601,7 +607,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
             return area3D;
 
         // if there is only a single slice, z will tell us
-        ROI2DArea area2D = area3D.getSlice(z);
+        final ROI2DArea area2D = area3D.getSlice(z);
         area2D.setZ(z);
 
         return area2D;
@@ -614,33 +620,35 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> {
      * @return Sequence
      */
     public Sequence toSequence() {
-        Sequence seq = new Sequence();
+        final Sequence seq = new Sequence();
 
         // get the bounding box first
 
-        Point3i start = new Point3i(), end = new Point3i();
+        final Point3i start = new Point3i();
+        final Point3i end = new Point3i();
 
-        computeBoundingBox(start, end);
+        shapeDescriptor.computeBoundingBox(this, start, end);
 
         // initialize the sequence
 
-        int depth = 1 + end.z - start.z;
-        int height = 1 + end.y - start.y;
-        int width = 1 + end.x - start.x;
+        final int depth = 1 + end.z - start.z;
+        final int height = 1 + end.y - start.y;
+        final int width = 1 + end.x - start.x;
 
         for (int z = 0; z < depth; z++)
             seq.setImage(0, z, new IcyBufferedImage(width, height, 1, DataType.UBYTE));
 
         // force non volatile
-        boolean v = seq.isVolatile();
+        final boolean v = seq.isVolatile();
         seq.setVolatile(false);
         try {
             // fill up the created sequence
-            byte[][] z_xy = seq.getDataXYZAsByte(0, 0);
+            final byte[][] z_xy = seq.getDataXYZAsByte(0, 0);
 
-            for (Point3i point : points)
+            for (final Point3i point : points)
                 z_xy[point.z - start.z][(point.y - start.y) * width + (point.x - start.x)] = (byte) 1;
-        } finally {
+        }
+        finally {
             // restore volatile state
             seq.setVolatile(v);
         }
diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponentDescriptor.java b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponentDescriptor.java
index 21b6d2aaa1f58f944c366b5b3acf02743a432e35..6c7a7fde7cf2bfed3917cbc817302d7245bd9537 100644
--- a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponentDescriptor.java
+++ b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponentDescriptor.java
@@ -1,15 +1,22 @@
-package plugins.adufour.connectedcomponents;
-
-import java.awt.geom.Point2D;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+/*
+ * 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 javax.vecmath.Point2d;
-import javax.vecmath.Point3d;
-import javax.vecmath.Point3i;
-import javax.vecmath.SingularMatrixException;
-import javax.vecmath.Vector3d;
+package plugins.adufour.connectedcomponents;
 
 import Jama.EigenvalueDecomposition;
 import Jama.Matrix;
@@ -25,6 +32,12 @@ import plugins.adufour.quickhull.QuickHull3D;
 import plugins.adufour.vars.lang.Var;
 import plugins.adufour.vars.lang.VarDouble;
 
+import javax.vecmath.*;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
 public class ConnectedComponentDescriptor extends Plugin implements PluginBundled, Block {
     Var<ConnectedComponent> varCC = new Var<>("Connected component", ConnectedComponent.class);
 
@@ -46,12 +59,12 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
     }
 
     @Override
-    public void declareInput(VarList inputMap) {
+    public void declareInput(final VarList inputMap) {
         inputMap.add("component", varCC);
     }
 
     @Override
-    public void declareOutput(VarList outputMap) {
+    public void declareOutput(final VarList outputMap) {
         outputMap.add("perimeter", perimeter);
         outputMap.add("long diameter", longAxis);
         outputMap.add("short diameter", shortAxis);
@@ -62,14 +75,14 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
 
     @Override
     public void run() {
-        ConnectedComponent cc = varCC.getValue();
+        final ConnectedComponent cc = varCC.getValue();
 
         if (cc == null)
             return;
 
         perimeter.setValue(computePerimeter(cc, null, null));
 
-        double[] ellipseDimensions = computeEllipseDimensions(cc);
+        final double[] ellipseDimensions = computeEllipseDimensions(cc);
 
         longAxis.setValue(ellipseDimensions[0] * 2);
         shortAxis.setValue(ellipseDimensions[1] * 2);
@@ -83,12 +96,12 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      * @return a triplet representing the radius of the best fitting ellipse (the third value is 0
      * for 2D objects)
      */
-    public double[] computeEllipseDimensions(ConnectedComponent cc) {
-        double[] axes = new double[3];
+    public double[] computeEllipseDimensions(final ConnectedComponent cc) {
+        final double[] axes = new double[3];
 
         try {
             if (is2D(cc)) {
-                Point2d radii = new Point2d();
+                final Point2d radii = new Point2d();
                 computeEllipse(cc, null, radii, null, null);
                 if (radii.x > radii.y) {
                     axes[0] = radii.x;
@@ -100,14 +113,14 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
                 }
             }
             else {
-                Point3d radii = new Point3d();
+                final Point3d radii = new Point3d();
                 computeEllipse(cc, null, radii, null, null);
                 axes[0] = radii.x;
                 axes[1] = radii.y;
                 axes[2] = radii.z;
             }
         }
-        catch (Exception e) {
+        catch (final Exception e) {
             // Do nothing
         }
 
@@ -121,7 +134,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      * @param minBounds the first corner of the bounding box in X-Y-Z order (Upper-Left hand-Top)
      * @param maxBounds the second corner of the bounding box in X-Y-Z order (Lower-Right hand-Bottom)
      */
-    public void computeBoundingBox(ConnectedComponent cc, Point3i minBounds, Point3i maxBounds) {
+    public void computeBoundingBox(final ConnectedComponent cc, final Point3i minBounds, final Point3i maxBounds) {
         if (minBounds != null) {
             minBounds.x = Integer.MAX_VALUE;
             minBounds.y = Integer.MAX_VALUE;
@@ -134,7 +147,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
             maxBounds.z = 0;
         }
 
-        for (Point3i point : cc) {
+        for (final Point3i point : cc) {
             if (minBounds != null) {
                 minBounds.x = Math.min(minBounds.x, point.x);
                 minBounds.y = Math.min(minBounds.y, point.y);
@@ -155,7 +168,7 @@ 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(ConnectedComponent cc, Point3d bsCenter, VarDouble bsRadius) {
+    public void computeBoundingSphere(final ConnectedComponent cc, final Point3d bsCenter, final VarDouble bsRadius) {
         bsCenter.set(cc.getMassCenter());
         bsRadius.setValue(cc.getMaxDistanceTo(bsCenter));
     }
@@ -168,20 +181,21 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      *                       extracted contour
      * @return The 3D perimeter (or 3D surface) of this component
      */
-    public double computePerimeter(ConnectedComponent cc, ArrayList<Point3i> contourPoints, Sequence outputSequence) {
+    public double computePerimeter(final ConnectedComponent cc, final ArrayList<Point3i> contourPoints, final Sequence outputSequence) {
         double perimeter = 0;
 
         if (contourPoints != null)
             contourPoints.ensureCapacity(cc.getSize() / 2);
 
-        Point3i min = new Point3i(), max = new Point3i();
+        final Point3i min = new Point3i();
+        final Point3i max = new Point3i();
         computeBoundingBox(cc, min, max);
 
-        Sequence mask = cc.toSequence();
+        final Sequence mask = cc.toSequence();
         final boolean outputVolatile;
-        int w = mask.getSizeX();
-        int h = mask.getSizeY();
-        int d = mask.getSizeZ();
+        final int w = mask.getSizeX();
+        final int h = mask.getSizeY();
+        final int d = mask.getSizeZ();
 
         byte[][] outputMask = null;
 
@@ -199,19 +213,19 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
         else
             outputVolatile = false;
 
-        byte[][] mask_z_xy = mask.getDataXYZAsByte(0, 0);
+        final byte[][] mask_z_xy = mask.getDataXYZAsByte(0, 0);
 
-        Point3i localP = new Point3i();
+        final Point3i localP = new Point3i();
 
         // count the edges and corners in 2D/3D
         double a = 0, b = 0;
 
-        for (Point3i p : cc) {
+        for (final Point3i p : cc) {
             localP.sub(p, min);
 
-            int xy = localP.y * w + localP.x;
+            final int xy = localP.y * w + localP.x;
 
-            byte[] z = mask_z_xy[localP.z];
+            final byte[] z = mask_z_xy[localP.z];
 
             int nbEdges = 0;
 
@@ -277,11 +291,11 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      * @param cc the input component
      * @return 1 for a perfect circle (or sphere), and lower than 1 otherwise
      */
-    public double computeSphericity(ConnectedComponent cc) {
-        double dim = is2D(cc) ? 2.0 : 3.0;
+    public double computeSphericity(final ConnectedComponent cc) {
+        final double dim = is2D(cc) ? 2.0 : 3.0;
 
-        double area = cc.getSize();
-        double peri = computePerimeter(cc, null, null);
+        final double area = cc.getSize();
+        final double peri = computePerimeter(cc, null, null);
 
         // some verification code
         //
@@ -298,7 +312,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
         //
         // end of the verification code
 
-        double sph = (Math.pow(Math.PI, 1.0 / dim) / peri) * Math.pow(area * dim * 2, (dim - 1) / dim);
+        final double sph = (Math.pow(Math.PI, 1.0 / dim) / peri) * Math.pow(area * dim * 2, (dim - 1) / dim);
 
         // adjust final rounding off errors (sphericity is always below 1)
         return Math.min(1.0, sph);
@@ -313,25 +327,25 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      * @return the ratio b/a, where a and b are the two first largest ellipse radii (there are only
      * two in 2D)
      */
-    public double computeEccentricity(ConnectedComponent cc) {
+    public double computeEccentricity(final ConnectedComponent cc) {
         if (is2D(cc)) {
             try {
-                Point2d radii = new Point2d();
+                final Point2d radii = new Point2d();
                 computeEllipse(cc, null, radii, null, null);
                 return radii.x / radii.y;
             }
-            catch (RuntimeException e) {
+            catch (final RuntimeException e) {
                 // error during the ellipse computation
                 return Double.NaN;
             }
         }
         else {
-            Point3d radii = new Point3d();
+            final Point3d radii = new Point3d();
             try {
                 computeEllipse(cc, null, radii, null, null);
                 return radii.x / radii.y;
             }
-            catch (Exception e) {
+            catch (final Exception e) {
                 return Double.NaN;
             }
         }
@@ -342,8 +356,8 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      * @return The hull ratio, measured as the ratio between the object volume and its convex hull
      * (envelope)
      */
-    public double computeHullRatio(ConnectedComponent cc) {
-        double hull = computeConvexAreaAndVolume(cc)[1];
+    public double computeHullRatio(final ConnectedComponent cc) {
+        final double hull = computeConvexAreaAndVolume(cc)[1];
 
         return hull == 0.0 ? 0.0 : Math.min(1.0, cc.getSize() / hull);
     }
@@ -354,8 +368,9 @@ 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(ConnectedComponent cc) {
-        int i = 0, n = cc.getSize();
+    public double[] computeConvexAreaAndVolume(final ConnectedComponent cc) {
+        int i = 0;
+        final int n = cc.getSize();
         if (n == 1)
             return new double[]{0.0, 1.0};
 
@@ -365,7 +380,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
         if (is2D(cc)) {
             List<Point2D> points = new ArrayList<>();
 
-            for (Point3i p : cc)
+            for (final Point3i p : cc)
                 points.add(new Point2D.Double(p.x, p.y));
 
             if (points.size() > 4)
@@ -387,23 +402,23 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
         }
         else
             try {
-                Point3d[] points = new Point3d[n];
+                final Point3d[] points = new Point3d[n];
 
-                for (Point3i p : cc)
+                for (final Point3i p : cc)
                     points[i++] = new Point3d(p.x, p.y, p.z);
 
-                QuickHull3D qhull = new QuickHull3D(points);
-                int[][] hullFaces = qhull.getFaces();
-                Point3d[] hullPoints = qhull.getVertices();
+                final QuickHull3D qhull = new QuickHull3D(points);
+                final int[][] hullFaces = qhull.getFaces();
+                final Point3d[] hullPoints = qhull.getVertices();
 
-                Vector3d v12 = new Vector3d();
-                Vector3d v13 = new Vector3d();
-                Vector3d cross = new Vector3d();
+                final Vector3d v12 = new Vector3d();
+                final Vector3d v13 = new Vector3d();
+                final Vector3d cross = new Vector3d();
 
-                for (int[] face : hullFaces) {
-                    Point3d p1 = hullPoints[face[0]];
-                    Point3d p2 = hullPoints[face[1]];
-                    Point3d p3 = hullPoints[face[2]];
+                for (final int[] face : hullFaces) {
+                    final Point3d p1 = hullPoints[face[0]];
+                    final Point3d p2 = hullPoints[face[1]];
+                    final Point3d p3 = hullPoints[face[2]];
 
                     v12.sub(p2, p1);
                     v13.sub(p3, p1);
@@ -415,7 +430,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
                     area += contour * cross.x * (p1.x + p2.x + p3.x);
                 }
             }
-            catch (IllegalArgumentException e) {
+            catch (final IllegalArgumentException e) {
                 // less than 4 points, or coplanarity detected
                 return new double[]{n, n};
             }
@@ -432,17 +447,17 @@ 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(ConnectedComponent cc, int p, int q, int r) {
+    public double computeGeometricMoment(final ConnectedComponent cc, final int p, final int q, final int r) {
         double moment = 0;
 
-        Point3d center = cc.getMassCenter();
+        final Point3d center = cc.getMassCenter();
 
         if (is2D(cc)) {
-            for (Point3i point : cc)
+            for (final Point3i point : cc)
                 moment += Math.pow(point.x - center.x, p) * Math.pow(point.y - center.y, q);
         }
         else {
-            for (Point3i point : cc)
+            for (final Point3i point : cc)
                 moment += Math.pow(point.x - center.x, p) * Math.pow(point.y - center.y, q)
                         * Math.pow(point.z - center.z, r);
         }
@@ -461,22 +476,22 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      * @param equation     (set to null if not wanted) an array of size 9 containing the calculated ellipsoid
      *                     equation
      * @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)
+     * @throws SingularMatrixException  if the component is flat (i.e., lies in a 2D plane)
      */
-    public void computeEllipse(ConnectedComponent cc, Point3d center, Point3d radii, Vector3d[] eigenVectors,
-                               double[] equation) throws IllegalArgumentException {
-        int nPoints = cc.getSize();
+    public void computeEllipse(final 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");
         }
 
-        Point3i[] points = cc.getPoints();
+        final Point3i[] points = cc.getPoints();
 
-        double[][] d = new double[nPoints][9];
+        final double[][] d = new double[nPoints][9];
         for (int i = 0; i < nPoints; i++) {
-            double x = points[i].x;
-            double y = points[i].y;
-            double z = points[i].z;
+            final double x = points[i].x;
+            final double y = points[i].y;
+            final double z = points[i].z;
             d[i][0] = (x * x);
             d[i][1] = (y * y);
             d[i][2] = (z * z);
@@ -488,32 +503,32 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
             d[i][8] = (2.0D * z);
         }
 
-        Matrix D = new Matrix(d);
-        Matrix ones = ones(nPoints, 1);
+        final Matrix D = new Matrix(d);
+        final Matrix ones = ones(nPoints, 1);
 
-        Matrix V;
+        final Matrix V;
         try {
             V = D.transpose().times(D).inverse().times(D.transpose().times(ones));
         }
-        catch (RuntimeException e) {
+        catch (final RuntimeException e) {
             throw new SingularMatrixException("The component is most probably flat (i.e. lies in a 2D plane)");
         }
 
-        double[] v = V.getColumnPackedCopy();
+        final double[] v = V.getColumnPackedCopy();
 
-        double[][] a = {{v[0], v[3], v[4], v[6]}, {v[3], v[1], v[5], v[7]}, {v[4], v[5], v[2], v[8]},
+        final double[][] a = {{v[0], v[3], v[4], v[6]}, {v[3], v[1], v[5], v[7]}, {v[4], v[5], v[2], v[8]},
                 {v[6], v[7], v[8], -1.0D}};
-        Matrix A = new Matrix(a);
-        Matrix C = A.getMatrix(0, 2, 0, 2).times(-1.0D).inverse().times(V.getMatrix(6, 8, 0, 0));
-        Matrix T = Matrix.identity(4, 4);
+        final Matrix A = new Matrix(a);
+        final Matrix C = A.getMatrix(0, 2, 0, 2).times(-1.0D).inverse().times(V.getMatrix(6, 8, 0, 0));
+        final Matrix T = Matrix.identity(4, 4);
         T.setMatrix(3, 3, 0, 2, C.transpose());
-        Matrix R = T.times(A.times(T.transpose()));
-        double r33 = R.get(3, 3);
-        Matrix R02 = R.getMatrix(0, 2, 0, 2);
-        EigenvalueDecomposition E = new EigenvalueDecomposition(R02.times(-1.0D / r33));
-        Matrix eVal = E.getD();
-        Matrix eVec = E.getV();
-        Matrix diagonal = diag(eVal);
+        final Matrix R = T.times(A.times(T.transpose()));
+        final double r33 = R.get(3, 3);
+        final Matrix R02 = R.getMatrix(0, 2, 0, 2);
+        final EigenvalueDecomposition E = new EigenvalueDecomposition(R02.times(-1.0D / r33));
+        final Matrix eVal = E.getD();
+        final Matrix eVec = E.getV();
+        final Matrix diagonal = diag(eVal);
 
         if (radii != null)
             radii.set(Math.sqrt(1.0D / diagonal.get(0, 0)), Math.sqrt(1.0D / diagonal.get(1, 0)),
@@ -543,15 +558,15 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
      *                 calculated algebraic parameters of the fitting ellipse: <i>ax</i><sup>2</sup> + 2
      *                 <i>bxy</i> + <i>cy</i><sup>2</sup> +2<i>dx</i> + 2<i>fy</i> + <i>g</i> = 0. The
      *                 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)
+     * @throws RuntimeException if the ellipse calculation fails (e.g., if a singular matrix is detected)
      */
-    public void computeEllipse(ConnectedComponent cc, Point2d center, Point2d radii, VarDouble angle, double[] equation)
+    public void computeEllipse(final ConnectedComponent cc, final Point2d center, final Point2d radii, final VarDouble angle, final double[] equation)
             throws RuntimeException {
-        Point3i[] points = cc.getPoints();
-        Point3d ccenter = cc.getMassCenter();
+        final Point3i[] points = cc.getPoints();
+        final Point3d ccenter = cc.getMassCenter();
 
-        double[][] d1 = new double[cc.getSize()][3];
-        double[][] d2 = new double[cc.getSize()][3];
+        final double[][] d1 = new double[cc.getSize()][3];
+        final double[][] d2 = new double[cc.getSize()][3];
 
         for (int i = 0; i < d1.length; i++) {
             final double xixC = points[i].x - ccenter.x;
@@ -566,33 +581,33 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
             d2[i][2] = 1;
         }
 
-        Matrix D1 = new Matrix(d1);
-        Matrix D2 = new Matrix(d2);
+        final Matrix D1 = new Matrix(d1);
+        final Matrix D2 = new Matrix(d2);
 
-        Matrix S1 = D1.transpose().times(D1);
+        final Matrix S1 = D1.transpose().times(D1);
 
-        Matrix S2 = D1.transpose().times(D2);
+        final Matrix S2 = D1.transpose().times(D2);
 
-        Matrix S3 = D2.transpose().times(D2);
+        final Matrix S3 = D2.transpose().times(D2);
 
-        Matrix T = (S3.inverse().times(-1)).times(S2.transpose());
+        final Matrix T = (S3.inverse().times(-1)).times(S2.transpose());
 
-        Matrix M = S1.plus(S2.times(T));
+        final Matrix M = S1.plus(S2.times(T));
 
-        double[][] m = M.getArray();
-        double[][] n = {{m[2][0] / 2, m[2][1] / 2, m[2][2] / 2}, {-m[1][0], -m[1][1], -m[1][2]},
+        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}};
 
-        Matrix N = new Matrix(n);
+        final Matrix N = new Matrix(n);
 
-        EigenvalueDecomposition E = N.eig();
-        Matrix eVec = E.getV();
+        final EigenvalueDecomposition E = N.eig();
+        final Matrix eVec = E.getV();
 
-        Matrix R1 = eVec.getMatrix(0, 0, 0, 2);
-        Matrix R2 = eVec.getMatrix(1, 1, 0, 2);
-        Matrix R3 = eVec.getMatrix(2, 2, 0, 2);
+        final Matrix R1 = eVec.getMatrix(0, 0, 0, 2);
+        final Matrix R2 = eVec.getMatrix(1, 1, 0, 2);
+        final Matrix R3 = eVec.getMatrix(2, 2, 0, 2);
 
-        Matrix cond = (R1.times(4)).arrayTimes(R3).minus(R2.arrayTimes(R2));
+        final Matrix cond = (R1.times(4)).arrayTimes(R3).minus(R2.arrayTimes(R2));
 
         int _f = 0;
         for (int i = 0; i < 3; i++) {
@@ -601,16 +616,16 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
                 break;
             }
         }
-        Matrix A1 = eVec.getMatrix(0, 2, _f, _f);
+        final Matrix A1 = eVec.getMatrix(0, 2, _f, _f);
 
         Matrix A = new Matrix(6, 1);
         A.setMatrix(0, 2, 0, 0, A1);
         A.setMatrix(3, 5, 0, 0, T.times(A1));
 
         double[] ell = A.getColumnPackedCopy();
-        double a4 = ell[3] - 2 * ell[0] * ccenter.x - ell[1] * ccenter.y;
-        double a5 = ell[4] - 2 * ell[2] * ccenter.y - ell[1] * ccenter.x;
-        double a6 = ell[5] + ell[0] * ccenter.x * ccenter.x + ell[2] * ccenter.y * ccenter.y
+        final double a4 = ell[3] - 2 * ell[0] * ccenter.x - ell[1] * ccenter.y;
+        final double a5 = ell[4] - 2 * ell[2] * ccenter.y - ell[1] * ccenter.x;
+        final double a6 = ell[5] + ell[0] * ccenter.x * ccenter.x + ell[2] * ccenter.y * ccenter.y
                 + ell[1] * ccenter.x * ccenter.y - ell[3] * ccenter.x - ell[4] * ccenter.y;
         A.set(3, 0, a4);
         A.set(4, 0, a5);
@@ -669,26 +684,26 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle
             angle.setValue(phi);
     }
 
-    public boolean is2D(ConnectedComponent cc) {
-        Point3i minBB = new Point3i();
-        Point3i maxBB = new Point3i();
+    public boolean is2D(final ConnectedComponent cc) {
+        final Point3i minBB = new Point3i();
+        final Point3i maxBB = new Point3i();
         computeBoundingBox(cc, minBB, maxBB);
 
         return minBB.z == maxBB.z;
     }
 
-    private Matrix diag(Matrix matrix) {
-        int min = Math.min(matrix.getRowDimension(), matrix.getColumnDimension());
-        double[][] diag = new double[min][1];
+    private Matrix diag(final 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++) {
             diag[i][0] = matrix.get(i, i);
         }
         return new Matrix(diag);
     }
 
-    private Matrix ones(int m, int n) {
-        double[][] array = new double[m][n];
-        for (double[] row : array)
+    private 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);
         return new Matrix(array, m, n);
     }
diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents.java b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents.java
index cc010e02f83e48fd49ad57dd26a145412bad063a..baa1be66e19d65f8cec8b8421c9d65bfbd72f340 100644
--- a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents.java
+++ b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents.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.connectedcomponents;
 
 import java.io.File;
@@ -97,7 +115,7 @@ public class ConnectedComponents extends EzPlug implements Block {
          */
         public final Comparator<ConnectedComponent> comparator;
 
-        Sorting(Comparator<ConnectedComponent> comparator) {
+        Sorting(final Comparator<ConnectedComponent> comparator) {
             this.comparator = comparator;
         }
     }
@@ -141,7 +159,7 @@ public class ConnectedComponents extends EzPlug implements Block {
         addEzComponent(input);
         input.addVarChangeListener((source, newValue) -> {
             if (newValue != null) {
-                boolean doZ = newValue.getSizeZ() > 1;
+                final boolean doZ = newValue.getSizeZ() > 1;
                 discardEdgesZ.setValue(doZ);
                 discardEdgesZ.setVisible(doZ);
             }
@@ -192,7 +210,7 @@ public class ConnectedComponents extends EzPlug implements Block {
     }
 
     @Override
-    public void declareInput(VarList inputMap) {
+    public void declareInput(final VarList inputMap) {
         inputMap.add("input", input.getVariable());
         inputMap.add("method", extractionMethod.getVariable());
         inputMap.add("value", background.getVariable());
@@ -207,7 +225,7 @@ public class ConnectedComponents extends EzPlug implements Block {
     }
 
     @Override
-    public void declareOutput(VarList outputMap) {
+    public void declareOutput(final VarList outputMap) {
         outputMap.add("labeled sequence", outputSequence);
         outputMap.add("objects", outputCCs);
         outputMap.add("list of extracted ROI", outputROIs);
@@ -215,34 +233,34 @@ public class ConnectedComponents extends EzPlug implements Block {
 
     @Override
     protected void execute() {
-        ArrayList<ConnectedComponent> componentsList = new ArrayList<>();
-        Map<Integer, List<ConnectedComponent>> componentsMap;
+        final ArrayList<ConnectedComponent> componentsList = new ArrayList<>();
+        final Map<Integer, List<ConnectedComponent>> componentsMap;
 
-        int min = boundSize.getValue() ? minSize.getValue() : 0;
-        int max = boundSize.getValue() ? maxSize.getValue() : Integer.MAX_VALUE;
+        final int min = boundSize.getValue() ? minSize.getValue() : 0;
+        final int max = boundSize.getValue() ? maxSize.getValue() : Integer.MAX_VALUE;
 
-        Sequence output = new Sequence();
+        final Sequence output = new Sequence();
 
-        Sequence inputSequence = input.getValue(true);
+        final Sequence inputSequence = input.getValue(true);
         if (inputSequence.getSizeT() == 0)
             throw new VarException(input.getVariable(), "Cannot extract connected components from an emtpy sequence !");
 
         // never remove objects touching the Z edge in 2D (that would remove... everything!)
-        boolean discardEdgesAlongZ = (inputSequence.getSizeZ() > 1 && discardEdgesZ.getValue());
+        final boolean discardEdgesAlongZ = (inputSequence.getSizeZ() > 1 && discardEdgesZ.getValue());
 
         try {
             if (extractionMethod.getValue() == ExtractionType.ROI) {
-                int width = inputSequence.getWidth();
-                int height = inputSequence.getHeight();
+                final int width = inputSequence.getWidth();
+                final int height = inputSequence.getHeight();
 
                 //Sequence labeledSequence = new Sequence(inputSequence.getMetadata());
-                Sequence labeledSequence = new Sequence(inputSequence.getOMEXMLMetadata());
+                final Sequence labeledSequence = new Sequence(inputSequence.getOMEXMLMetadata());
                 for (int t = 0; t < inputSequence.getSizeT(); t++)
                     for (int z = 0; z < inputSequence.getSizeZ(); z++)
                         labeledSequence.setImage(t, z, new IcyBufferedImage(width, height, 1, DataType.USHORT));
 
                 short cpt = 1;
-                for (ROI roi : inputSequence.getROIs())
+                for (final ROI roi : inputSequence.getROIs())
                     DataIteratorUtil.set(new SequenceDataIterator(labeledSequence, roi, true), cpt++ & 0xffff);
 
                 componentsMap = extractConnectedComponents(labeledSequence, 0, ExtractionType.BACKGROUND_LABELED,
@@ -254,7 +272,7 @@ public class ConnectedComponents extends EzPlug implements Block {
                         discardEdgesAlongZ, min, max, output);
             }
         }
-        catch (InterruptedException e) {
+        catch (final InterruptedException e) {
             new FailedAnnounceFrame(e.getMessage());
             return;
         }
@@ -262,7 +280,7 @@ public class ConnectedComponents extends EzPlug implements Block {
         outputSequence.setValue(output);
 
         int nbObjects = 0;
-        for (List<ConnectedComponent> ccs : componentsMap.values()) {
+        for (final List<ConnectedComponent> ccs : componentsMap.values()) {
             nbObjects += ccs.size();
             componentsList.addAll(ccs);
         }
@@ -280,58 +298,58 @@ public class ConnectedComponents extends EzPlug implements Block {
         }
 
         if (exportSwPool.getValue()) {
-            DetectionResult result = convertToDetectionResult(componentsMap, input.getValue());
-            SwimmingObject object = new SwimmingObject(result, "Set of " + nbObjects + " connected components");
+            final DetectionResult result = convertToDetectionResult(componentsMap, input.getValue());
+            final SwimmingObject object = new SwimmingObject(result, "Set of " + nbObjects + " connected components");
             Icy.getMainInterface().getSwimmingPool().add(object);
         }
 
         if (exportROI.getValue() || outputROIs.isReferenced()) {
             if (output.getSizeZ() > 1) {
-                ArrayList<ROI3DArea> rois = new ArrayList<>(componentsMap.size());
+                final ArrayList<ROI3DArea> rois = new ArrayList<>(componentsMap.size());
 
                 int ccID = 1;
 
-                for (List<ConnectedComponent> ccs : componentsMap.values())
-                    for (ConnectedComponent cc : ccs) {
-                        ROI3DArea area = new ROI3DArea();
+                for (final List<ConnectedComponent> ccs : componentsMap.values())
+                    for (final ConnectedComponent cc : ccs) {
+                        final ROI3DArea area = new ROI3DArea();
                         area.setName("Object #" + ccID++);
                         area.beginUpdate();
-                        for (Point3i pt : cc)
+                        for (final Point3i pt : cc)
                             area.addPoint(pt.x, pt.y, pt.z);
                         area.setT(cc.getT());
                         area.endUpdate();
                         rois.add(area);
                     }
 
-                outputROIs.setValue(rois.toArray(new ROI3DArea[rois.size()]));
+                outputROIs.setValue(rois.toArray(new ROI3DArea[0]));
             }
             else {
-                ArrayList<ROI2DArea> rois = new ArrayList<>(componentsMap.size());
+                final ArrayList<ROI2DArea> rois = new ArrayList<>(componentsMap.size());
 
-                for (List<ConnectedComponent> ccs : componentsMap.values())
-                    for (ConnectedComponent cc : ccs) {
-                        ROI2DArea area = new ROI2DArea();
+                for (final List<ConnectedComponent> ccs : componentsMap.values())
+                    for (final ConnectedComponent cc : ccs) {
+                        final ROI2DArea area = new ROI2DArea();
                         area.beginUpdate();
-                        for (Point3i pt : cc)
+                        for (final Point3i pt : cc)
                             area.addPoint(pt.x, pt.y);
                         area.setT(cc.getT());
                         area.endUpdate();
                         rois.add(area);
                     }
 
-                outputROIs.setValue(rois.toArray(new ROI2DArea[rois.size()]));
+                outputROIs.setValue(rois.toArray(new ROI2DArea[0]));
             }
 
             if (exportROI.getValue()) {
                 // replace all ROI on the input by the new ones
-                Sequence in = input.getValue();
+                final Sequence in = input.getValue();
 
                 in.beginUpdate();
 
-                for (ROI roi : input.getValue().getROIs())
+                for (final ROI roi : input.getValue().getROIs())
                     in.removeROI(roi);
 
-                for (ROI roi : outputROIs.getValue())
+                for (final ROI roi : outputROIs.getValue())
                     in.addROI(roi);
 
                 in.endUpdate();
@@ -342,7 +360,7 @@ public class ConnectedComponents extends EzPlug implements Block {
             int page = 1;
 
             WritableSheet sheet;
-            WritableWorkbook workbook;
+            final WritableWorkbook workbook;
 
             try {
                 File f = exportExcelFile.getValue(true);
@@ -351,14 +369,14 @@ public class ConnectedComponents extends EzPlug implements Block {
                 workbook = XLSUtil.createWorkbook(f);
                 sheet = XLSUtil.createNewPage(workbook, "Page " + page);
             }
-            catch (Exception e) {
+            catch (final Exception e) {
                 throw new IcyHandledException(e.getMessage());
             }
 
-            Sequence s = input.getValue();
-            Point4d resolution = new Point4d(s.getPixelSizeX(), s.getPixelSizeY(), s.getPixelSizeZ(),
+            final Sequence s = input.getValue();
+            final Point4d resolution = new Point4d(s.getPixelSizeX(), s.getPixelSizeY(), s.getPixelSizeZ(),
                     s.getTimeInterval());
-            double voxelSize = resolution.x * resolution.y * resolution.z;
+            final double voxelSize = resolution.x * resolution.y * resolution.z;
             String res = "Sequence resolution:";
             res += " X=" + StringUtil.toStringEx(resolution.x, 5);
             res += ", Y=" + StringUtil.toStringEx(resolution.y, 5);
@@ -397,12 +415,12 @@ public class ConnectedComponents extends EzPlug implements Block {
             XLSUtil.setCellString(sheet, 27, 1, "convex perimeter");
             XLSUtil.setCellString(sheet, 28, 1, "convex volume");
 
-            ConnectedComponentDescriptor shapeDescriptor = new ConnectedComponentDescriptor();
+            final ConnectedComponentDescriptor shapeDescriptor = new ConnectedComponentDescriptor();
             int cpt = 2;
-            for (Integer time : componentsMap.keySet())
-                for (ConnectedComponent cc : componentsMap.get(time)) {
-                    boolean is2D = shapeDescriptor.is2D(cc);
-                    Point3d center = cc.getMassCenter();
+            for (final Integer time : componentsMap.keySet())
+                for (final ConnectedComponent cc : componentsMap.get(time)) {
+                    final boolean is2D = shapeDescriptor.is2D(cc);
+                    final Point3d center = cc.getMassCenter();
                     center.x *= resolution.x;
                     center.y *= resolution.y;
                     center.z *= resolution.z;
@@ -414,13 +432,13 @@ public class ConnectedComponents extends EzPlug implements Block {
                     XLSUtil.setCellNumber(sheet, 5, cpt, shapeDescriptor.computePerimeter(cc, null, null));
                     XLSUtil.setCellNumber(sheet, 6, cpt, cc.getSize() * voxelSize);
                     XLSUtil.setCellNumber(sheet, 7, cpt, shapeDescriptor.computeSphericity(cc));
-                    double[] radiuses = shapeDescriptor.computeEllipseDimensions(cc);
+                    final double[] radiuses = shapeDescriptor.computeEllipseDimensions(cc);
                     XLSUtil.setCellNumber(sheet, 8, cpt, radiuses[0]);
                     XLSUtil.setCellNumber(sheet, 9, cpt, radiuses[1]);
                     XLSUtil.setCellNumber(sheet, 10, cpt, radiuses[2]);
                     XLSUtil.setCellNumber(sheet, 11, cpt, shapeDescriptor.computeEccentricity(cc));
 
-                    double[] contour_area = shapeDescriptor.computeConvexAreaAndVolume(cc);
+                    final double[] contour_area = shapeDescriptor.computeConvexAreaAndVolume(cc);
                     XLSUtil.setCellNumber(sheet, 12, cpt, contour_area[1] == 0.0 ? 0.0 : Math.min(1.0, cc.getSize() / contour_area[1]));
                     XLSUtil.setCellNumber(sheet, 13, cpt, shapeDescriptor.computeGeometricMoment(cc, 1, 0, 0));
                     XLSUtil.setCellNumber(sheet, 14, cpt, shapeDescriptor.computeGeometricMoment(cc, 0, 1, 0));
@@ -469,7 +487,7 @@ public class ConnectedComponents extends EzPlug implements Block {
             try {
                 XLSUtil.saveAndClose(workbook);
             }
-            catch (Exception e) {
+            catch (final Exception e) {
                 throw new IcyHandledException(e.getMessage());
             }
         }
@@ -504,10 +522,10 @@ public class ConnectedComponents extends EzPlug implements Block {
          * Creates a new label with the given value. If no parent is set to this label, the given
          * value will be the final one
          *
-         * @param value   the pixel value
-         * @param label   the label value
+         * @param value the pixel value
+         * @param label the label value
          */
-        Label(double value, int label) {
+        Label(final double value, final int label) {
             this.imageValue = value;
             this.targetLabelValue = label;
         }
@@ -532,7 +550,7 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ExtractionType
      * @see ConnectedComponent
      */
-    public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(Sequence inputSequence, Sequence labeledSequence) {
+    public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(final Sequence inputSequence, final Sequence labeledSequence) {
         return extractConnectedComponents(inputSequence, false, 0, Integer.MAX_VALUE, labeledSequence);
     }
 
@@ -550,7 +568,7 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ExtractionType
      * @see ConnectedComponent
      */
-    public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(Sequence inputSequence, int minSize, int maxSize, Sequence labeledSequence) {
+    public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(final Sequence inputSequence, final int minSize, final int maxSize, final Sequence labeledSequence) {
         return extractConnectedComponents(inputSequence, false, minSize, maxSize, labeledSequence);
     }
 
@@ -569,7 +587,7 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ExtractionType
      * @see ConnectedComponent
      */
-    public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(Sequence inputSequence, boolean isInputLabeled, int minSize, int maxSize, Sequence labeledSequence) {
+    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);
@@ -591,7 +609,7 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ExtractionType
      * @see ConnectedComponent
      */
-    public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(Sequence inputSequence, double value, ExtractionType type, int minSize, int maxSize, Sequence labeledSequence) {
+    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);
     }
 
@@ -618,31 +636,31 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ConnectedComponent
      */
     public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(
-            Sequence inputSequence, double value, ExtractionType type, boolean noEdgeX, boolean noEdgeY, boolean noEdgeZ, int minSize, int maxSize, Sequence labeledSequence
+            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 !");
 
-        int width = inputSequence.getSizeX();
-        int height = inputSequence.getSizeY();
+        final int width = inputSequence.getSizeX();
+        final int height = inputSequence.getSizeY();
 
         if (labeledSequence == null)
             labeledSequence = new Sequence();
 
-        Map<Integer, List<ConnectedComponent>> componentsMap = new TreeMap<>();
+        final Map<Integer, List<ConnectedComponent>> componentsMap = new TreeMap<>();
 
         for (int t = 0; t < inputSequence.getSizeT(); t++) {
             for (int z = 0; z < inputSequence.getSizeZ(); z++)
                 labeledSequence.setImage(t, z, new IcyBufferedImage(width, height, 1, DataType.UINT));
 
-            VolumetricImage volIN = inputSequence.getVolumetricImage(t);
-            VolumetricImage volOUT = labeledSequence.getVolumetricImage(t);
+            final VolumetricImage volIN = inputSequence.getVolumetricImage(t);
+            final VolumetricImage volOUT = labeledSequence.getVolumetricImage(t);
 
-            List<ConnectedComponent> components = extractConnectedComponents(volIN, value, type, noEdgeX, noEdgeY,
+            final List<ConnectedComponent> components = extractConnectedComponents(volIN, value, type, noEdgeX, noEdgeY,
                     noEdgeZ, minSize, maxSize, volOUT);
 
             // int cpt=1;
-            for (ConnectedComponent cc : components) {
+            for (final ConnectedComponent cc : components) {
                 cc.setT(t);
                 // System.out.println(t + "\t" + cpt++ + "\t" + (int)cc.getMassCenter().x + "\t" +
                 // (int)cc.getMassCenter().y);
@@ -679,7 +697,7 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ConnectedComponent
      */
     public static List<ConnectedComponent> extractConnectedComponents(
-            VolumetricImage stack, double value, ExtractionType type, boolean noEdgeX, boolean noEdgeY, boolean noEdgeZ, int minSize, int maxSize
+            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());
     }
@@ -710,18 +728,18 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @see ConnectedComponent
      */
     public static List<ConnectedComponent> extractConnectedComponents(
-            VolumetricImage stack, double value, ExtractionType type, boolean noEdgeX, boolean noEdgeY, boolean noEdgeZ, int minSize, int maxSize, final VolumetricImage labeledStack
+            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
     ) throws NullPointerException {
-        int width = stack.getFirstImage().getSizeX();
-        int height = stack.getFirstImage().getSizeY();
-        int depth = stack.getSize();
+        final int width = stack.getFirstImage().getSizeX();
+        final int height = stack.getFirstImage().getSizeY();
+        final int depth = stack.getSize();
 
-        int[] neighborLabelValues = new int[13];
+        final int[] neighborLabelValues = new int[13];
         int neighborhoodSize = 0;
 
-        boolean extractUserValue = (type == ExtractionType.VALUE);
+        final boolean extractUserValue = (type == ExtractionType.VALUE);
 
-        Label[] labels = new Label[width * height * depth];
+        final Label[] labels = new Label[width * height * depth];
 
         // first image pass: naive labeling with simple backward neighborhood
 
@@ -736,14 +754,14 @@ public class ConnectedComponents extends EzPlug implements Block {
 
             final IcyBufferedImage currentSliceImage = labeledStack.getImage(z);
             // retrieve the direct pointer to the current slice
-            int[] _labelsInCurrentSlice = currentSliceImage.getDataXYAsInt(0);
+            final int[] _labelsInCurrentSlice = currentSliceImage.getDataXYAsInt(0);
             // retrieve a direct pointer to the previous slice
-            int[] _labelsInUpperSlice = (z == 0) ? null : labeledStack.getImage(z - 1).getDataXYAsInt(0);
+            final int[] _labelsInUpperSlice = (z == 0) ? null : labeledStack.getImage(z - 1).getDataXYAsInt(0);
 
             int voxelOffset = 0;
 
-            Object inputData = stack.getImage(z).getDataXY(0);
-            DataType dataType = stack.getImage(z).getDataType_();
+            final Object inputData = stack.getImage(z).getDataXY(0);
+            final DataType dataType = stack.getImage(z).getDataType_();
 
             for (int y = 0; y < height; y++) {
                 onEdgeY = (y == 0 || y == height - 1);
@@ -751,9 +769,9 @@ public class ConnectedComponents extends EzPlug implements Block {
                 for (int x = 0; x < width; x++, voxelOffset++) {
                     onEdgeX = (x == 0 || x == width - 1);
 
-                    double pixelValue = Array1DUtil.getValue(inputData, voxelOffset, dataType);
+                    final double pixelValue = Array1DUtil.getValue(inputData, voxelOffset, dataType);
 
-                    boolean pixelEqualsUserValue = (pixelValue == value);
+                    final boolean pixelEqualsUserValue = (pixelValue == value);
 
                     // do not process the current pixel if:
                     // - extractUserValue is true and pixelEqualsUserValue is false
@@ -794,7 +812,7 @@ public class ConnectedComponents extends EzPlug implements Block {
                             }
                         }
                         else {
-                            int north = voxelOffset - width;
+                            final int north = voxelOffset - width;
 
                             if (x == 0) {
                                 // e n n
@@ -830,7 +848,7 @@ public class ConnectedComponents extends EzPlug implements Block {
                     }
                     else {
                         if (y == 0) {
-                            int south = voxelOffset + width;
+                            final int south = voxelOffset + width;
 
                             if (x == 0) {
                                 // e e e | e e e
@@ -871,7 +889,7 @@ public class ConnectedComponents extends EzPlug implements Block {
                             }
                         }
                         else if (y == height - 1) {
-                            int north = voxelOffset - width;
+                            final int north = voxelOffset - width;
 
                             if (x == 0) {
                                 // e n n | e n n
@@ -919,8 +937,8 @@ public class ConnectedComponents extends EzPlug implements Block {
                             }
                         }
                         else {
-                            int north = voxelOffset - width;
-                            int south = voxelOffset + width;
+                            final int north = voxelOffset - width;
+                            final int south = voxelOffset + width;
 
                             if (x == 0) {
                                 // e n n | e n n
@@ -938,8 +956,8 @@ public class ConnectedComponents extends EzPlug implements Block {
                                 neighborhoodSize = 8;
                             }
                             else if (x == width - 1) {
-                                int northwest = north - 1;
-                                int west = voxelOffset - 1;
+                                final int northwest = north - 1;
+                                final int west = voxelOffset - 1;
 
                                 // n n e | n n e
                                 // n n e | n x e
@@ -957,11 +975,11 @@ public class ConnectedComponents extends EzPlug implements Block {
                                 neighborhoodSize = 9;
                             }
                             else {
-                                int northwest = north - 1;
-                                int west = voxelOffset - 1;
-                                int northeast = north + 1;
-                                int southwest = south - 1;
-                                int southeast = south + 1;
+                                final int northwest = north - 1;
+                                final int west = voxelOffset - 1;
+                                final int northeast = north + 1;
+                                final int southwest = south - 1;
+                                final int southeast = south + 1;
 
                                 // n n n | n n n
                                 // n n n | n x .
@@ -994,7 +1012,7 @@ public class ConnectedComponents extends EzPlug implements Block {
                     // and assign that minimum label right now
 
                     for (int i = 0; i < neighborhoodSize; i++) {
-                        int neighborLabelValue = neighborLabelValues[i];
+                        final int neighborLabelValue = neighborLabelValues[i];
 
                         // zero labels are not interesting...
                         if (neighborLabelValue == 0)
@@ -1027,19 +1045,19 @@ public class ConnectedComponents extends EzPlug implements Block {
                         // -> change their value to currentVoxelLabelValue
                         // -> change their target to currentVoxelLabel
 
-                        Label currentVoxelLabel = labels[currentVoxelLabelValue];
+                        final Label currentVoxelLabel = labels[currentVoxelLabelValue];
 
                         for (int i = 0; i < neighborhoodSize; i++) {
-                            int neighborLabelValue = neighborLabelValues[i];
+                            final int neighborLabelValue = neighborLabelValues[i];
 
                             if (neighborLabelValue > currentVoxelLabelValue) {
-                                Label label = labels[neighborLabelValue];
+                                final Label label = labels[neighborLabelValue];
 
                                 if (type == ExtractionType.BACKGROUND_LABELED && label.imageValue != pixelValue)
                                     continue;
 
-                                int finalLabelValue = label.getFinalLabelValue();
-                                Label finalLabel = labels[finalLabelValue];
+                                final int finalLabelValue = label.getFinalLabelValue();
+                                final Label finalLabel = labels[finalLabelValue];
 
                                 if (currentVoxelLabel.targetLabelValue == finalLabelValue)
                                     continue;
@@ -1072,7 +1090,7 @@ public class ConnectedComponents extends EzPlug implements Block {
         // end of the first pass, all pixels have a label
         // (though might not be unique within a given component)
 
-        HashMap<Integer, ConnectedComponent> componentsMap = new HashMap<>();
+        final HashMap<Integer, ConnectedComponent> componentsMap = new HashMap<>();
 
         // fusion strategy: fuse higher labels with lower ones
         // "highestKnownLabel" holds the highest known label
@@ -1081,14 +1099,14 @@ public class ConnectedComponents extends EzPlug implements Block {
         int finalLabel = 0;
 
         for (int labelValue = highestKnownLabel; labelValue > 0; labelValue--) {
-            Label label = labels[labelValue];
+            final Label label = labels[labelValue];
 
-            int targetLabelValue = label.targetLabelValue;
+            final int targetLabelValue = label.targetLabelValue;
 
             if (targetLabelValue < labelValue) {
                 // label should be fused to targetLabel
 
-                Label targetLabel = labels[targetLabelValue];
+                final Label targetLabel = labels[targetLabelValue];
 
                 // -> add label's size to targetLabel
                 targetLabel.size += label.size;
@@ -1126,7 +1144,7 @@ public class ConnectedComponents extends EzPlug implements Block {
 
                     // -> add this label to the list of valid labels
 
-                    ConnectedComponent component = new ConnectedComponent(label.size);
+                    final ConnectedComponent component = new ConnectedComponent(label.size);
                     component.onEdgeX = label.onEdgeX;
                     component.onEdgeY = label.onEdgeY;
                     component.onEdgeZ = label.onEdgeZ;
@@ -1139,7 +1157,7 @@ public class ConnectedComponents extends EzPlug implements Block {
 
         for (int z = 0; z < depth; z++) {
             final IcyBufferedImage sliceImage = labeledStack.getImage(z);
-            int[] _outputSlice = sliceImage.getDataXYAsInt(0);
+            final int[] _outputSlice = sliceImage.getDataXYAsInt(0);
 
             int pixelOffset = 0;
 
@@ -1171,13 +1189,13 @@ public class ConnectedComponents extends EzPlug implements Block {
         return new ArrayList<>(componentsMap.values());
     }
 
-    public static DetectionResult convertToDetectionResult(Map<Integer, List<ConnectedComponent>> detections, Sequence sequence) {
+    public static DetectionResult convertToDetectionResult(final Map<Integer, List<ConnectedComponent>> detections, final Sequence sequence) {
 
-        DetectionResult detectionResult = new DetectionResult();
-        for (Integer t : detections.keySet())
-            for (ConnectedComponent cc : detections.get(t)) {
+        final DetectionResult detectionResult = new DetectionResult();
+        for (final Integer t : detections.keySet())
+            for (final ConnectedComponent cc : detections.get(t)) {
                 // TODO: add points information
-                Spot spot = new Spot(cc.getMassCenter().x, cc.getMassCenter().y, cc.getMassCenter().z);
+                final Spot spot = new Spot(cc.getMassCenter().x, cc.getMassCenter().y, cc.getMassCenter().z);
                 detectionResult.addDetection(t, spot);
             }
 
@@ -1194,37 +1212,38 @@ public class ConnectedComponents extends EzPlug implements Block {
      * @param components Map of List of ConnectedComponent
      * @param comparator Comparator of ConnectedComponents
      */
-    public static void createLabeledSequence(Sequence output, Map<Integer, List<ConnectedComponent>> components, Comparator<ConnectedComponent> comparator) {
+    public static void createLabeledSequence(final Sequence output, final Map<Integer, List<ConnectedComponent>> components, final Comparator<ConnectedComponent> comparator) {
         if (comparator == null)
             return;
 
-        int width = output.getSizeX();
-        int[] ids = new int[output.getSizeC()];
+        final int width = output.getSizeX();
+        final int[] ids = new int[output.getSizeC()];
         Arrays.fill(ids, 1);
 
-        for (Integer t : components.keySet()) {
+        for (final Integer t : components.keySet()) {
             for (int c = 0; c < output.getSizeC(); c++) {
                 // retrieve all objects in that channel
-                ArrayList<ConnectedComponent> cComponents = new ArrayList<>();
-                for (ConnectedComponent cc : components.get(t)) {
+                final ArrayList<ConnectedComponent> cComponents = new ArrayList<>();
+                for (final ConnectedComponent cc : components.get(t)) {
                     if (cc.getC() == -1 || cc.getC() == c)
                         cComponents.add(cc);
                 }
 
-                ConnectedComponent[] ccs = cComponents.toArray(new ConnectedComponent[cComponents.size()]);
+                final ConnectedComponent[] ccs = cComponents.toArray(new ConnectedComponent[0]);
                 Arrays.sort(ccs, comparator);
 
                 final boolean outputVolatile = output.isVolatile();
                 try {
-                    int[][] data = output.getDataXYZAsInt(t, c);
+                    final int[][] data = output.getDataXYZAsInt(t, c);
 
-                    for (ConnectedComponent cc : ccs) {
-                        for (Point3i pt : cc) {
+                    for (final ConnectedComponent cc : ccs) {
+                        for (final Point3i pt : cc) {
                             data[pt.z][pt.y * width + pt.x] = ids[c];
                         }
                         ids[c]++;
                     }
-                } finally {
+                }
+                finally {
                     // restore back volatile state
                     output.setVolatile(outputVolatile);
                 }