diff --git a/.gitignore b/.gitignore
index 3d47f986c41db29ec6dc0d5036bf760b3a1cf366..57f16fb67c1b1589981416b323d7a9debc728665 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,41 @@
-.idea/
+/build*
+/workspace
+setting.xml
+release/
 target/
-.settings/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+icy.log
+
+### IntelliJ IDEA ###
+.idea/
+*.iws
 *.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
 .project
-.classpath
\ No newline at end of file
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+**/.DS_Store
+Icon?
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index c87f039f6ba90873d278f98dcaf48f816197047b..cff32f46eb3e85b84872f2f0ddde035faf5c6f7e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,23 +6,21 @@
 
     <!-- Inherited Icy Parent POM -->
     <parent>
-		<artifactId>pom-icy</artifactId>
+        <artifactId>pom-icy</artifactId>
         <groupId>org.bioimageanalysis.icy</groupId>
-        <version>2.1.0</version>
-	</parent>
+        <version>3.0.0-a.1</version>
+    </parent>
 
     <!-- Project Information -->
     <artifactId>path-intensity-profiler</artifactId>
-    <version>1.2.3</version>
-
-    <packaging>jar</packaging>
+    <version>2.0.0-a.1</version>
 
     <name>Path Intensity Profiler</name>
     <description>
         This plugin will compute the intensity profile of ROI contour along Z (3D) and T (timelaps) dimension. It generates a workbook document containing all the intensity values which can be used to display graph or be saved as XLSX or CSV format.
         The plugin is compatible with Protocols.
     </description>
-    <url>http://icy.bioimageanalysis.org/plugin/path-intensity-profil/</url>
+    <url>https://icy.bioimageanalysis.org/plugin/path-intensity-profil/</url>
     <inceptionYear>2020</inceptionYear>
 
     <organization>
@@ -56,40 +54,24 @@
         </developer>
     </developers>
 
-    <!-- Project properties -->
-    <properties>
-
-    </properties>
-
-    <profiles>
-        <profile>
-            <id>icy-plugin</id>
-            <activation>
-                <activeByDefault>true</activeByDefault>
-            </activation>
-        </profile>
-    </profiles>
-
     <!-- List of project's dependencies -->
     <dependencies>
-        <!-- The core of Icy -->
         <dependency>
             <groupId>org.bioimageanalysis.icy</groupId>
-            <artifactId>icy-kernel</artifactId>
-			<version>${icy-kernel.version}</version>
+            <artifactId>kernel-extensions</artifactId>
         </dependency>
-
-        <!-- The EzPlug library, simplifies writing UI for Icy plugins. -->
         <dependency>
             <groupId>org.bioimageanalysis.icy</groupId>
             <artifactId>ezplug</artifactId>
-			<version>${ezplug.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.bioimageanalysis.icy</groupId>
+            <artifactId>protocols</artifactId>
         </dependency>
 
         <dependency>
             <groupId>org.bioimageanalysis.icy</groupId>
             <artifactId>workbooks</artifactId>
-			<version>${workbooks.version}</version>
         </dependency>
     </dependencies>
 
@@ -97,8 +79,7 @@
     <repositories>
         <repository>
             <id>icy</id>
-            <name>Icy's Nexus</name>
-            <url>https://icy-nexus.pasteur.fr/repository/Icy/</url>
+            <url>https://nexus-icy.pasteur.cloud/repository/icy/</url>
         </repository>
     </repositories>
 </project>
diff --git a/src/main/java/plugins/stef/roi/quantify/PathIntensityProfiler.java b/src/main/java/plugins/stef/roi/quantify/PathIntensityProfiler.java
index 462a5052e9994c91a15a127813fc07b7a494acc6..4d9beaeaa46d9c7efed2e5561bb576f9ad9d9522 100644
--- a/src/main/java/plugins/stef/roi/quantify/PathIntensityProfiler.java
+++ b/src/main/java/plugins/stef/roi/quantify/PathIntensityProfiler.java
@@ -1,30 +1,47 @@
-package plugins.stef.roi.quantify;
-
-import java.awt.Dimension;
-import java.awt.Point;
-import java.awt.geom.Point2D;
-import java.util.ArrayList;
-import java.util.List;
+/*
+ * Copyright (c) 2010-2024. Institut Pasteur.
+ *
+ * This file is part of Icy.
+ * Icy is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Icy is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Icy. If not, see <https://www.gnu.org/licenses/>.
+ */
 
-import javax.swing.JComponent;
+package plugins.stef.roi.quantify;
 
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-import icy.gui.dialog.MessageDialog;
-import icy.gui.frame.progress.FailedAnnounceFrame;
-import icy.math.Line3DIterator;
-import icy.math.MathUtil;
-import icy.roi.BooleanMask2D;
-import icy.roi.ROI;
-import icy.roi.ROI2D;
-import icy.roi.ROI3D;
-import icy.sequence.Sequence;
-import icy.system.IcyExceptionHandler;
-import icy.type.collection.CollectionUtil;
-import icy.type.geom.Line3D;
-import icy.type.point.Point3D;
-import icy.type.point.Point4D;
-import icy.type.rectangle.Rectangle5D;
+import org.bioimageanalysis.extension.kernel.roi.roi2d.*;
+import org.bioimageanalysis.extension.kernel.roi.roi3d.ROI3DLine;
+import org.bioimageanalysis.extension.kernel.roi.roi3d.ROI3DPoint;
+import org.bioimageanalysis.extension.kernel.roi.roi3d.ROI3DPolyLine;
+import org.bioimageanalysis.extension.kernel.roi.roi3d.ROI3DShape;
+import org.bioimageanalysis.icy.common.collection.CollectionUtil;
+import org.bioimageanalysis.icy.common.geom.line.Line3D;
+import org.bioimageanalysis.icy.common.geom.line.Line3DIterator;
+import org.bioimageanalysis.icy.common.geom.point.Point3D;
+import org.bioimageanalysis.icy.common.geom.point.Point4D;
+import org.bioimageanalysis.icy.common.geom.rectangle.Rectangle5D;
+import org.bioimageanalysis.icy.common.math.MathUtil;
+import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon;
+import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName;
+import org.bioimageanalysis.icy.gui.dialog.MessageDialog;
+import org.bioimageanalysis.icy.model.roi.ROI;
+import org.bioimageanalysis.icy.model.roi.ROI2D;
+import org.bioimageanalysis.icy.model.roi.ROI3D;
+import org.bioimageanalysis.icy.model.roi.mask.BooleanMask2D;
+import org.bioimageanalysis.icy.model.sequence.Sequence;
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import plugins.adufour.blocks.lang.Block;
 import plugins.adufour.blocks.util.VarList;
 import plugins.adufour.ezplug.EzGUI;
@@ -38,34 +55,31 @@ import plugins.adufour.vars.lang.VarWorkbook;
 import plugins.adufour.workbooks.IcySpreadSheet;
 import plugins.adufour.workbooks.Workbooks;
 import plugins.adufour.workbooks.Workbooks.WorkbookFormat;
-import plugins.kernel.roi.roi2d.ROI2DLine;
-import plugins.kernel.roi.roi2d.ROI2DPoint;
-import plugins.kernel.roi.roi2d.ROI2DPolyLine;
-import plugins.kernel.roi.roi2d.ROI2DPolygon;
-import plugins.kernel.roi.roi2d.ROI2DRectangle;
-import plugins.kernel.roi.roi2d.ROI2DShape;
-import plugins.kernel.roi.roi3d.ROI3DLine;
-import plugins.kernel.roi.roi3d.ROI3DPoint;
-import plugins.kernel.roi.roi3d.ROI3DPolyLine;
-import plugins.kernel.roi.roi3d.ROI3DShape;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
 
 /**
  * Path profiler plugin class.<br>
  * Computes intensity profil along path (contour for area ROI) for the given list of ROI and return result in XLSX workbook format
  * where we have one sheet per ROI.
- * 
- * @author Stephane
+ *
+ * @author Stephane Dallongeville
  */
-public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
-{
+@IcyPluginName("Path Intensity Profiler")
+@IcyPluginIcon(path = "/path-intensity-profiler.png")
+public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable {
     // VAR
     public final VarSequence varSequence;
     public final VarROIArray varRois;
     public final EzVarBoolean varRealUnit;
     public final VarWorkbook varWorkbook;
 
-    public PathIntensityProfiler()
-    {
+    public PathIntensityProfiler() {
         super();
 
         varSequence = new VarSequence("Sequence", null);
@@ -75,8 +89,7 @@ public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
     }
 
     @Override
-    protected void initialize()
-    {
+    protected void initialize() {
         final WorkbookEditor viewer = (WorkbookEditor) varWorkbook.createVarViewer();
 
         viewer.setEnabled(true);
@@ -90,71 +103,60 @@ public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
     }
 
     @Override
-    public void declareInput(VarList inputMap)
-    {
+    public void declareInput(@NotNull final VarList inputMap) {
         inputMap.add("sequence", varSequence);
         inputMap.add("rois", varRois);
         inputMap.add("realUnit", varRealUnit.getVariable());
     }
 
     @Override
-    public void declareOutput(VarList outputMap)
-    {
+    public void declareOutput(@NotNull final VarList outputMap) {
         outputMap.add("workbook", varWorkbook);
     }
 
     @Override
-    public void clean()
-    {
+    public void clean() {
         // set empty workbook to release resources
         varWorkbook.setValue(Workbooks.createEmptyWorkbook(WorkbookFormat.XLSX));
     }
 
     @Override
-    protected void execute()
-    {
+    protected void execute() {
         // set empty workbook by default (also release resources from previous run)
         varWorkbook.setValue(Workbooks.createEmptyWorkbook(WorkbookFormat.XLSX));
 
         // interactive mode (not in protocol)
-        if (!isHeadLess())
-        {
+        if (!isHeadLess()) {
             final Sequence seq = getActiveSequence();
 
             // set variables
-            if (seq != null)
-            {
+            if (seq != null) {
                 varSequence.setValue(seq);
                 varRois.setValue(seq.getROIs().toArray(new ROI[0]));
             }
-            else
-            {
+            else {
                 // inform user
-                MessageDialog.showDialog("You need to open an image containing ROI(s).",
-                        MessageDialog.INFORMATION_MESSAGE);
+                MessageDialog.showDialog("You need to open an image containing ROI(s).", MessageDialog.INFORMATION_MESSAGE);
                 return;
             }
         }
 
         final Sequence sequence = varSequence.getValue();
 
-        if (sequence != null)
-        {
+        if (sequence != null) {
             final ROI[] rois = varRois.getValue();
-            final List<ROI> validRois = new ArrayList<ROI>();
+            final List<ROI> validRois = new ArrayList<>();
 
             // we can only compute path intensity on path ROI or 2D ROI
-            for (ROI roi : rois)
-            {
+            for (final ROI roi : rois) {
                 if (roi instanceof ROI2D)
                     validRois.add(roi);
-                // else if ((roi instanceof ROI3DPoint) || (roi instanceof ROI3DLine) || (roi instanceof ROI3DPolyLine))
+                    // else if ((roi instanceof ROI3DPoint) || (roi instanceof ROI3DLine) || (roi instanceof ROI3DPolyLine))
                 else if (roi instanceof ROI3D)
                     validRois.add(roi);
             }
 
-            if (validRois.size() == 0)
-            {
+            if (validRois.isEmpty()) {
                 // inform user
                 if (!isHeadLess())
                     MessageDialog.showDialog(
@@ -167,25 +169,20 @@ public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
             if (!isHeadLess())
                 getUI().setProgressBarMessage("Computing...");
 
-            try
-            {
+            try {
                 // set result
                 varWorkbook.setValue(
-                        getPathIntensityProfil(sequence, validRois, varRealUnit.getValue().booleanValue(), getUI()));
+                        getPathIntensityProfil(sequence, validRois, varRealUnit.getValue(), getUI()));
             }
-            catch (IllegalArgumentException e)
-            {
-                IcyExceptionHandler.handleException(e, true);
+            catch (final IllegalArgumentException e) {
+                IcyLogger.error(this.getClass(), e);
             }
-            catch (InterruptedException e)
-            {
-                new FailedAnnounceFrame("Path intensity profile process interrupted..");
+            catch (final InterruptedException e) {
+                IcyLogger.error(this.getClass(), e, "Path intensity profile process interrupted.");
             }
-            finally
-            {
+            finally {
                 // interactive mode
-                if (!isHeadLess())
-                {
+                if (!isHeadLess()) {
                     getUI().setProgressBarMessage("Done");
                     getUI().setProgressBarValue(0);
                 }
@@ -195,13 +192,13 @@ public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
 
     /**
      * Computes intensity profil along path (contour for area ROI) for the given list of ROI.
-     * 
+     *
      * @return result in a XLSX workbook where we have one sheet per ROI.
      * @throws InterruptedException
      */
-    private static XSSFWorkbook getPathIntensityProfil(Sequence sequence, List<ROI> rois, boolean useRealUnit, EzGUI ui)
-            throws InterruptedException
-    {
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    private static XSSFWorkbook getPathIntensityProfil(final Sequence sequence, @NotNull final List<ROI> rois, final boolean useRealUnit, final EzGUI ui)
+            throws InterruptedException {
         final XSSFWorkbook result = (XSSFWorkbook) Workbooks.createEmptyWorkbook(WorkbookFormat.XLSX);
 
         // nothing to do
@@ -214,15 +211,13 @@ public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
 
         final Point4D.Double unitScale = new Point4D.Double();
 
-        if (useRealUnit)
-        {
+        if (useRealUnit) {
             unitScale.x = sequence.getPixelSizeX();
             unitScale.y = sequence.getPixelSizeY();
             unitScale.z = sequence.getPixelSizeZ();
             unitScale.t = sequence.getTimeInterval();
         }
-        else
-        {
+        else {
             unitScale.x = 1d;
             unitScale.y = 1d;
             unitScale.z = 1d;
@@ -233,11 +228,10 @@ public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
 
         int roiIndex = 0;
         // can process now
-        for (ROI roi : rois)
-        {
+        for (final ROI roi : rois) {
             // create a sheet for each ROI
             final IcySpreadSheet sh = new IcySpreadSheet(result.createSheet(
-                    String.format("S%04d - ", Integer.valueOf(roiIndex)) + roi.getName().replace(':', '_')));
+                    String.format("S%04d - ", roiIndex) + roi.getName().replace(':', '_')));
 
             // write columns headers
             int indCol = 0;
@@ -254,11 +248,9 @@ public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
             // start
             int row = 1;
 
-            for (int t = 0; t < sizeT; t++)
-            {
+            for (int t = 0; t < sizeT; t++) {
                 // in case of 2D ROI, we need to handle the specific T = -1 (ALL)
-                if (roi instanceof ROI2D)
-                {
+                if (roi instanceof ROI2D) {
                     final int roiT = ((ROI2D) roi).getT();
 
                     // ROI not on current T position ? --> next
@@ -266,8 +258,7 @@ public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
                         continue;
                 }
                 // in case of 3D ROI, we need to handle the specific T = -1 (ALL)
-                else if (roi instanceof ROI3D)
-                {
+                else if (roi instanceof ROI3D) {
                     final int roiT = ((ROI3D) roi).getT();
 
                     // ROI not on current T position ? --> next
@@ -278,11 +269,9 @@ public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
                 else if ((roiBounds.getMinT() > t) || (roiBounds.getMaxT() < t))
                     continue;
 
-                for (int z = 0; z < sizeZ; z++)
-                {
+                for (int z = 0; z < sizeZ; z++) {
                     // in case of 2D ROI, we need to handle the specific Z = -1 (ALL)
-                    if (roi instanceof ROI2D)
-                    {
+                    if (roi instanceof ROI2D) {
                         final int roiZ = ((ROI2D) roi).getZ();
 
                         // ROI not on current Z position ? --> next
@@ -300,15 +289,13 @@ public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
                     // point index
                     int ptIndex = 0;
 
-                    for (int c = 0, zStartRow = row; c < sizeC; c++)
-                    {
+                    for (int c = 0, zStartRow = row; c < sizeC; c++) {
                         // ROI does not contain current C position ? --> next
                         if ((roiBounds.getMinC() > c) || (roiBounds.getMaxC() < c))
                             continue;
 
                         // display progress
-                        if (ui != null)
-                        {
+                        if (ui != null) {
                             // compute progress bar avoid integer type loss
                             double progress = roiIndex;
                             progress *= sizeT * sizeZ * sizeC;
@@ -330,58 +317,58 @@ public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
                         // 3D line path ROI ?
                         if ((roi instanceof ROI3DPoint) || (roi instanceof ROI3DLine) || (roi instanceof ROI3DPolyLine))
                             pts = ((ROI3DShape) roi).getPoints();
-                        // 2D straight line path / area ROI (we shouldn't consider Arc / Ellipse shape ROI here) ?
+                            // 2D straight line path / area ROI (we shouldn't consider Arc / Ellipse shape ROI here) ?
                         else if ((roi instanceof ROI2DPoint) || (roi instanceof ROI2DLine)
                                 || (roi instanceof ROI2DPolyLine) || (roi instanceof ROI2DPolygon)
                                 || (roi instanceof ROI2DRectangle))
                             pts = ((ROI2DShape) roi).getPoints();
-                        else
-                        {
+                        else {
                             // initialize
-                            pts = new ArrayList();
+                            pts = new ArrayList<>();
                             // no link here
                             interpolate = false;
 
                             // 2D ROI so we can use the contour of the mask
-                            if (roi instanceof ROI2D)
-                            {
+                            if (roi instanceof ROI2D) {
                                 /// iterate over all component (separate object if any)
-                                for (BooleanMask2D mask : ((ROI2D) roi).getBooleanMask(true).getComponents())
+                                for (final BooleanMask2D mask : ((ROI2D) roi).getBooleanMask(true).getComponents())
                                     // add points in contour order
                                     pts.addAll(mask.getConnectedContourPoints());
                             }
                             // 3D ROI so we can use the surface area points
-                            else if (roi instanceof ROI3D)
-                            {
+                            else if (roi instanceof ROI3D) {
                                 // add points in whatever order
-                                pts.addAll(
-                                        CollectionUtil.asList(((ROI3D) roi).getBooleanMask(true).getContourPoints()));
+                                pts.addAll(CollectionUtil.asList(((ROI3D) roi).getBooleanMask(true).getContourPoints()));
                             }
                             // not supported
-                            else
-                            {
-
+                            else {
+                                IcyLogger.warn(PathIntensityProfiler.class, "Not supported.");
                             }
                         }
 
                         // control points that need interpolation in-between ?
-                        if (interpolate)
-                        {
+                        if (interpolate) {
                             // get the first obj
-                            Point3D startPt = getPoint3D(pts.get(0), z);
+                            Point3D startPt = getPoint3D(pts.getFirst(), z);
 
                             // specific case where we have only a single point
                             if (pts.size() == 1)
-                                writeRow(sh, row++, ptIndex++, t, c, sequence, startPt, unitScale);
-                            else
-                            {
+                                writeRow(
+                                        sh,
+                                        row++,
+                                        ptIndex++,
+                                        t,
+                                        c,
+                                        sequence,
+                                        Objects.requireNonNull(startPt),
+                                        unitScale
+                                );
+                            else {
                                 // otherwise we use a special way to interpolate through 2 controls points
-                                for (int i = 1; i < pts.size(); i++)
-                                {
+                                for (int i = 1; i < pts.size(); i++) {
                                     final Point3D endPt = getPoint3D(pts.get(i), z);
                                     // get line iterator
-                                    final Line3DIterator lineIt = new Line3DIterator(new Line3D(startPt, endPt), 1d,
-                                            false);
+                                    final Line3DIterator lineIt = new Line3DIterator(new Line3D(startPt, endPt), 1d, false);
 
                                     // iterate over line points
                                     while (lineIt.hasNext())
@@ -393,10 +380,18 @@ public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
                             }
                         }
                         // contour points ?
-                        else
-                        {
-                            for (int i = 0; i < pts.size(); i++)
-                                writeRow(sh, row++, ptIndex++, t, c, sequence, getPoint3D(pts.get(i), z), unitScale);
+                        else {
+                            for (final Object pt : pts)
+                                writeRow(
+                                        sh,
+                                        row++,
+                                        ptIndex++,
+                                        t,
+                                        c,
+                                        sequence,
+                                        Objects.requireNonNull(getPoint3D(pt, z)),
+                                        unitScale
+                                );
                         }
                     }
                 }
@@ -411,50 +406,45 @@ public class PathIntensityProfiler extends EzPlug implements Block, EzStoppable
 
     /**
      * Computes intensity profil along path (contour for area ROI) for the given list of ROI.<br>
-     * 
+     *
      * @return result in a XLSX workbook where we have one sheet per ROI.
      * @throws InterruptedException
      */
-    public static XSSFWorkbook getPathIntensityProfil(Sequence sequence, List<ROI> rois, boolean useRealUnit)
-            throws InterruptedException
-    {
+    public static XSSFWorkbook getPathIntensityProfil(final Sequence sequence, final List<ROI> rois, final boolean useRealUnit) throws InterruptedException {
         return getPathIntensityProfil(sequence, rois, useRealUnit, null);
     }
 
-    private static Point3D getPoint3D(Object obj, int curZ)
-    {
-        final Point3D result;
-
-        if (obj instanceof Point)
-        {
-            final Point pt2d = (Point) obj;
-            result = new Point3D.Double(pt2d.getX(), pt2d.getY(), curZ);
-        }
-        else if (obj instanceof Point2D)
-        {
-            final Point2D pt2d = (Point2D) obj;
-            result = new Point3D.Double(pt2d.getX(), pt2d.getY(), curZ);
-        }
-        else if (obj instanceof Point3D)
-            result = (Point3D) obj;
-        else
-            result = null;
-
-        return result;
+    private static @Nullable Point3D getPoint3D(final Object obj, final int curZ) {
+        return switch (obj) {
+            case final Point pt2d -> new Point3D.Double(pt2d.getX(), pt2d.getY(), curZ);
+            case final Point2D pt2d -> new Point3D.Double(pt2d.getX(), pt2d.getY(), curZ);
+            case final Point3D point3D -> point3D;
+            case null, default -> null;
+        };
     }
 
-    private static void writeRow(IcySpreadSheet sh, int row, int ind, int t, int c, Sequence sequence, Point3D pt,
-            Point4D unitScale)
-    {
-        sh.setValue(row, 0, Integer.valueOf(ind));
-        sh.setValue(row, 1, Double.valueOf(MathUtil.roundSignificant(pt.getX() * unitScale.getX(), 5, true)));
-        sh.setValue(row, 2, Double.valueOf(MathUtil.roundSignificant(pt.getY() * unitScale.getY(), 5, true)));
-        sh.setValue(row, 3, Double.valueOf(MathUtil.roundSignificant(pt.getZ() * unitScale.getZ(), 5, true)));
+    private static void writeRow(
+            @NotNull final IcySpreadSheet sh,
+            final int row,
+            final int ind,
+            final int t,
+            final int c,
+            final Sequence sequence,
+            @NotNull final Point3D pt,
+            @NotNull final Point4D unitScale
+    ) {
+        sh.setValue(row, 0, ind);
+        sh.setValue(row, 1, MathUtil.roundSignificant(pt.getX() * unitScale.getX(), 5, true));
+        sh.setValue(row, 2, MathUtil.roundSignificant(pt.getY() * unitScale.getY(), 5, true));
+        sh.setValue(row, 3, MathUtil.roundSignificant(pt.getZ() * unitScale.getZ(), 5, true));
         if (unitScale.getT() == 1d)
-            sh.setValue(row, 4, Integer.valueOf(t));
+            sh.setValue(row, 4, t);
         else
-            sh.setValue(row, 4, Double.valueOf(MathUtil.roundSignificant(t * unitScale.getT(), 5, true)));
-        sh.setValue(row, 5 + c, Double.valueOf(MathUtil
-                .roundSignificant(sequence.getDataInterpolated(t, pt.getZ(), c, pt.getY(), pt.getX()), 5, true)));
+            sh.setValue(row, 4, MathUtil.roundSignificant(t * unitScale.getT(), 5, true));
+        sh.setValue(row, 5 + c, MathUtil.roundSignificant(
+                sequence.getDataInterpolated(t, pt.getZ(), c, pt.getY(), pt.getX()),
+                5,
+                true
+        ));
     }
 }
diff --git a/src/main/resources/path-intensity-profiler.png b/src/main/resources/path-intensity-profiler.png
new file mode 100644
index 0000000000000000000000000000000000000000..db2f4ef1363e1fe984098fd2c948ebba18815e8c
Binary files /dev/null and b/src/main/resources/path-intensity-profiler.png differ