diff --git a/.gitignore b/.gitignore index 0f33221ba14c994d1054744f7a310805a27ac78d..57f16fb67c1b1589981416b323d7a9debc728665 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,41 @@ -.idea/ -.settings/ -bin/ -build/ +/build* +/workspace +setting.xml +release/ target/ -workspace/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +icy.log + +### IntelliJ IDEA ### +.idea/ +*.iws *.iml -*.jar +*.ipr + +### Eclipse ### +.apt_generated .classpath +.factorypath .project -export.jardesc -setting.xml -**/.DS_Store \ 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 ead22e35eb3aabd014d4ca56628b0fea88bdd849..02ef00b45202ec3ecf88bb23a6853aa569993f21 100644 --- a/pom.xml +++ b/pom.xml @@ -5,11 +5,11 @@ <parent> <groupId>org.bioimageanalysis.icy</groupId> <artifactId>pom-icy</artifactId> - <version>2.2.0</version> + <version>3.0.0-a.1</version> </parent> <artifactId>roi-statistics</artifactId> - <version>6.0.0</version> + <version>6.0.0-a.1</version> <name>ROI Statistics</name> <description> @@ -18,36 +18,68 @@ </description> <dependencies> + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>kernel-extensions</artifactId> + </dependency> + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>quickhull</artifactId> + </dependency> + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>3d-mesh-roi</artifactId> + </dependency> <dependency> <groupId>org.bioimageanalysis.icy</groupId> <artifactId>vecmath</artifactId> </dependency> <dependency> <groupId>org.bioimageanalysis.icy</groupId> - <artifactId>active-contours</artifactId> + <artifactId>jama</artifactId> </dependency> <dependency> <groupId>org.bioimageanalysis.icy</groupId> - <artifactId>convexify</artifactId> + <artifactId>ezplug</artifactId> </dependency> <dependency> <groupId>org.bioimageanalysis.icy</groupId> - <artifactId>sequence-blocks</artifactId> + <artifactId>convexify</artifactId> </dependency> <dependency> <groupId>org.bioimageanalysis.icy</groupId> - <artifactId>spot-tracking</artifactId> + <artifactId>protocols</artifactId> </dependency> <dependency> <groupId>org.bioimageanalysis.icy</groupId> <artifactId>workbooks</artifactId> </dependency> + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>icy-jmath</artifactId> + </dependency> + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>track-manager</artifactId> + </dependency> + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>active-contours</artifactId> + </dependency> + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>spot-detection-utilities</artifactId> + </dependency> + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>spot-tracking</artifactId> + </dependency> </dependencies> <repositories> <repository> <id>icy</id> - <url>https://icy-nexus.pasteur.fr/repository/Icy/</url> + <url>https://nexus-icy.pasteur.cloud/repository/icy/</url> </repository> </repositories> </project> \ No newline at end of file diff --git a/src/main/java/plugins/adufour/roi/ROIConvexHullDescriptor.java b/src/main/java/plugins/adufour/roi/ROIConvexHullDescriptor.java index cae4e71671ab09681b3c7913552290e94696571c..13791ba8c0baaf47c205b2eee0c4e4c63df2860a 100644 --- a/src/main/java/plugins/adufour/roi/ROIConvexHullDescriptor.java +++ b/src/main/java/plugins/adufour/roi/ROIConvexHullDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,20 +18,22 @@ package plugins.adufour.roi; -import icy.plugin.abstract_.Plugin; -import icy.plugin.interface_.PluginBundled; -import icy.plugin.interface_.PluginROIDescriptor; -import icy.roi.ROI; -import icy.roi.ROI2D; -import icy.roi.ROI3D; -import icy.roi.ROIDescriptor; -import icy.sequence.Sequence; -import icy.type.point.Point3D; +import org.bioimageanalysis.extension.kernel.roi.roi2d.ROI2DRectShape; +import org.bioimageanalysis.icy.common.geom.point.Point3D; +import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName; +import org.bioimageanalysis.icy.extension.plugin.interface_.PluginROIDescriptor; +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.ROIDescriptor; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.system.logging.IcyLogger; import plugins.adufour.quickhull.QuickHull2D; import plugins.adufour.quickhull.QuickHull3D; import plugins.adufour.roi.mesh.Vertex3D; import plugins.adufour.roi.mesh.polygon.ROI3DPolygonalMesh; -import plugins.kernel.roi.roi2d.ROI2DRectShape; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; @@ -42,7 +44,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -public class ROIConvexHullDescriptor extends Plugin implements PluginROIDescriptor, PluginBundled { +@IcyPluginName("ROI Convex Hull Descriptor") +@IcyPluginIcon(path = "/roi-stat.png") +public class ROIConvexHullDescriptor extends Plugin implements PluginROIDescriptor { public static class ROIConvexity extends ROIDescriptor { protected ROIConvexity() { super("Convexity", Double.class); @@ -85,9 +89,7 @@ public class ROIConvexHullDescriptor extends Plugin implements PluginROIDescript if (roi.getNumberOfPoints() < 4) return 100; - if (roi instanceof ROI2D) { - final ROI2D r2 = (ROI2D) roi; - + if (roi instanceof final ROI2D r2) { final Point[] pts = r2.getBooleanMask(true).getContourPoints(); if (pts.length < 4) @@ -105,7 +107,7 @@ public class ROIConvexHullDescriptor extends Plugin implements PluginROIDescript // contour = sum( sqrt[ (x[i] - x[i-1])^2 + (y[i] - y[i-1])^2 ] ) // area = 0.5 * sum( (x[i-1] * y[i]) - (y[i-1] * x[i]) ) - Point2D p1 = points.get(points.size() - 1), p2; + Point2D p1 = points.getLast(), p2; for (final Point2D point : points) { p2 = point; @@ -118,8 +120,7 @@ public class ROIConvexHullDescriptor extends Plugin implements PluginROIDescript else if (roi instanceof ROI3D) { final Point3d[] points; - if (roi instanceof ROI3DPolygonalMesh) { - final ROI3DPolygonalMesh mesh = (ROI3DPolygonalMesh) roi; + if (roi instanceof final ROI3DPolygonalMesh mesh) { // Tuple3d res = mesh.getPixelSize(); points = new Point3d[mesh.getNumberOfVertices(true)]; @@ -174,11 +175,11 @@ public class ROIConvexHullDescriptor extends Plugin implements PluginROIDescript } } catch (final RuntimeException e) { - System.err.println("Warning while computing the convexity of " + roi.getName() + ": " + e.getMessage()); + IcyLogger.warn(ROIConvexity.class, e, "Warning while computing the convexity of " + roi.getName()); } } else { - System.err.println("WARNING: cannot compute the convexity of a " + roi.getClassName()); + IcyLogger.warn(ROIConvexity.class, "WARNING: cannot compute the convexity of a " + roi.getClassName()); return Double.NaN; } @@ -202,9 +203,4 @@ public class ROIConvexHullDescriptor extends Plugin implements PluginROIDescript map.put(convexity, convexity.compute(roi, sequence)); return map; } - - @Override - public String getMainPluginClassName() { - return ROIMeasures.class.getName(); - } } diff --git a/src/main/java/plugins/adufour/roi/ROIEllipsoidFittingDescriptor.java b/src/main/java/plugins/adufour/roi/ROIEllipsoidFittingDescriptor.java index 7a0b1b99628fec681dddf16aa644a3fb18ebe094..0bc83ab72ad511352c5ad588f69a064d92c3d2f6 100644 --- a/src/main/java/plugins/adufour/roi/ROIEllipsoidFittingDescriptor.java +++ b/src/main/java/plugins/adufour/roi/ROIEllipsoidFittingDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -20,19 +20,19 @@ package plugins.adufour.roi; import Jama.EigenvalueDecomposition; import Jama.Matrix; -import icy.math.MathUtil; -import icy.math.UnitUtil; -import icy.plugin.abstract_.Plugin; -import icy.plugin.interface_.PluginBundled; -import icy.plugin.interface_.PluginROIDescriptor; -import icy.roi.ROI; -import icy.roi.ROI2D; -import icy.roi.ROI3D; -import icy.roi.ROIDescriptor; -import icy.sequence.Sequence; -import icy.type.point.Point3D; +import org.bioimageanalysis.icy.common.geom.point.Point3D; +import org.bioimageanalysis.icy.common.math.MathUtil; +import org.bioimageanalysis.icy.common.math.UnitUtil; +import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName; +import org.bioimageanalysis.icy.extension.plugin.interface_.PluginROIDescriptor; +import org.bioimageanalysis.icy.model.roi.*; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.system.logging.IcyLogger; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; import plugins.adufour.vars.lang.VarDouble; -import plugins.kernel.roi.descriptor.measure.ROIMassCenterDescriptorsPlugin; import javax.vecmath.*; import java.awt.*; @@ -40,7 +40,9 @@ import java.awt.geom.Point2D; import java.util.List; import java.util.*; -public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDescriptor, PluginBundled { +@IcyPluginName("ROI Ellipsoid Fitting Descriptor") +@IcyPluginIcon(path = "/roi-stat.png") +public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDescriptor { public static class ROIFirstDiameter extends ROIDescriptor { protected ROIFirstDiameter() { super("1st Diameter", Double.class); @@ -175,7 +177,7 @@ public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDe * @return The first (or major) principle axis of the best fitting ellipse * @throws InterruptedException if thread was interrupted */ - public static Vector3d computeFirstAxis(final ROI roi, final Sequence sequence) throws InterruptedException { + public static @NotNull Vector3d computeFirstAxis(final ROI roi, final Sequence sequence) throws InterruptedException { final double[] ellipse = computeOrientation(roi, sequence); return new Vector3d(ellipse[3], ellipse[4], ellipse[5]); } @@ -210,7 +212,7 @@ public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDe * @return The second principle axis of the best fitting ellipse * @throws InterruptedException if thread was interrupted */ - public static Vector3d computeSecondAxis(final ROI roi, final Sequence sequence) throws InterruptedException { + public static @NotNull Vector3d computeSecondAxis(final ROI roi, final Sequence sequence) throws InterruptedException { final double[] ellipse = computeOrientation(roi, sequence); return new Vector3d(ellipse[6], ellipse[7], ellipse[8]); } @@ -245,7 +247,7 @@ public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDe * @return The third principle axis of the best fitting ellipse * @throws InterruptedException if thread was interrupted */ - public static Vector3d computeThirdAxis(final ROI roi, final Sequence sequence) throws InterruptedException { + public static @NotNull Vector3d computeThirdAxis(final ROI roi, final Sequence sequence) throws InterruptedException { if (roi instanceof ROI2D) return new Vector3d(); @@ -457,6 +459,7 @@ public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDe * @param ellipse ellipse orientation * @return The elongation ratio of the X-Y plane */ + @Contract(pure = true) public static double computeElongation(final double[] ellipse) { if (ellipse == null) return Double.NaN; @@ -503,6 +506,7 @@ public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDe * @param ellipse ellipse orientation * @return The 3D flatness ratio of the Y-Z plane */ + @Contract(pure = true) public static double computeFlatness3D(final double[] ellipse) { if (ellipse == null) return Double.NaN; @@ -567,7 +571,8 @@ public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDe return map; } - private static String getUnit(final Sequence sequence) { + @Contract(pure = true) + private static @NotNull String getUnit(final Sequence sequence) { if (sequence == null) return "px"; @@ -596,7 +601,7 @@ public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDe * </ul> * @throws InterruptedException if thread was interrupted */ - public static double[] computeOrientation(final ROI roi, final Sequence sequence) throws InterruptedException { + public static double @NotNull [] computeOrientation(final ROI roi, final Sequence sequence) throws InterruptedException { final double[] ellipse = new double[12]; if (roi instanceof ROI2D) { @@ -661,7 +666,7 @@ public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDe } } else { - System.err.println("Cannot compute ellipse dimensions for ROI of type: " + roi.getClassName()); + IcyLogger.error(ROIEllipsoidFittingDescriptor.class, "Cannot compute ellipse dimensions for ROI of type: " + roi.getClassName()); Arrays.fill(ellipse, Double.NaN); } @@ -695,7 +700,7 @@ public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDe * @throws InterruptedException * @throws SingularMatrixException if the component is flat (i.e. lies in a 2D plane) */ - private static void fitEllipse(final ROI3D cc, final Point3d radii, final Vector3d[] eigenVectors, final double[] equation) throws IllegalArgumentException, InterruptedException { + private static void fitEllipse(final @NotNull ROI3D cc, final Point3d radii, final Vector3d[] eigenVectors, final double[] equation) throws IllegalArgumentException, InterruptedException { final Point3D.Integer[] points = cc.getBooleanMask(true).getContourPoints(); if (points.length < 9) { @@ -789,7 +794,7 @@ public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDe * @throws InterruptedException */ private static void fitEllipse( - final ROI2D roi, + final @NotNull ROI2D roi, final Point2d center, final Point2d radii, final VarDouble angle, @@ -801,7 +806,7 @@ public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDe if (points.length < 4) return; - final Point2D ccenter = ROIMassCenterDescriptorsPlugin.computeMassCenter(roi).toPoint2D(); + final Point2D ccenter = ROIUtil.computeMassCenter(roi).toPoint2D(); final double cx = ccenter.getX(); final double cy = ccenter.getY(); @@ -924,7 +929,8 @@ public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDe } } - private static Matrix diag(final Matrix matrix) { + @Contract("_ -> new") + private static @NotNull Matrix diag(final @NotNull Matrix matrix) { final int min = Math.min(matrix.getRowDimension(), matrix.getColumnDimension()); final double[][] diag = new double[min][1]; for (int i = 0; i < min; i++) { @@ -933,15 +939,11 @@ public class ROIEllipsoidFittingDescriptor extends Plugin implements PluginROIDe return new Matrix(diag); } - private static Matrix ones(final int m, final int n) { + @Contract("_, _ -> new") + private static @NotNull Matrix ones(final int m, final int n) { final double[][] array = new double[m][n]; for (final double[] row : array) Arrays.fill(row, 1.0); return new Matrix(array, m, n); } - - @Override - public String getMainPluginClassName() { - return ROIMeasures.class.getName(); - } } diff --git a/src/main/java/plugins/adufour/roi/ROIFeretDiameterDescriptor.java b/src/main/java/plugins/adufour/roi/ROIFeretDiameterDescriptor.java index 859adbbbd24c2450255f8cbecad69ddc92ccd240..49960e391e27238cab596fb10d448aec012750ee 100644 --- a/src/main/java/plugins/adufour/roi/ROIFeretDiameterDescriptor.java +++ b/src/main/java/plugins/adufour/roi/ROIFeretDiameterDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,19 +18,21 @@ package plugins.adufour.roi; -import icy.math.UnitUtil; -import icy.plugin.abstract_.Plugin; -import icy.plugin.interface_.PluginBundled; -import icy.plugin.interface_.PluginROIDescriptor; -import icy.roi.ROI; -import icy.roi.ROI2D; -import icy.roi.ROI3D; -import icy.roi.ROIDescriptor; -import icy.sequence.Sequence; -import icy.type.point.Point3D; +import org.bioimageanalysis.extension.kernel.roi.roi2d.ROI2DRectShape; +import org.bioimageanalysis.icy.common.geom.point.Point3D; +import org.bioimageanalysis.icy.common.math.UnitUtil; +import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName; +import org.bioimageanalysis.icy.extension.plugin.interface_.PluginROIDescriptor; +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.ROIDescriptor; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.system.logging.IcyLogger; import plugins.adufour.roi.mesh.Vertex3D; import plugins.adufour.roi.mesh.polygon.ROI3DPolygonalMesh; -import plugins.kernel.roi.roi2d.ROI2DRectShape; import javax.vecmath.Point3d; import java.awt.*; @@ -41,7 +43,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -public class ROIFeretDiameterDescriptor extends Plugin implements PluginROIDescriptor, PluginBundled { +@IcyPluginName("ROI Feret Diameter Descriptor") +@IcyPluginIcon(path = "/roi-stat.png") +public class ROIFeretDiameterDescriptor extends Plugin implements PluginROIDescriptor { public static class ROIFeretDiameter extends ROIDescriptor { protected ROIFeretDiameter() { super("Max Feret diameter", Double.class); @@ -153,7 +157,7 @@ public class ROIFeretDiameterDescriptor extends Plugin implements PluginROIDescr maxDistance = Math.sqrt(maxDistance); } else { - System.err.println("Cannot compute Max. Feret diameter for ROI of type: " + roi.getClassName()); + IcyLogger.error(ROIFeretDiameter.class, "Cannot compute Max. Feret diameter for ROI of type: " + roi.getClassName()); maxDistance = 0.0d; } @@ -176,9 +180,4 @@ public class ROIFeretDiameterDescriptor extends Plugin implements PluginROIDescr map.put(feretDiameter, feretDiameter.compute(roi, sequence)); return map; } - - @Override - public String getMainPluginClassName() { - return ROIMeasures.class.getName(); - } } diff --git a/src/main/java/plugins/adufour/roi/ROIHaralickTextureDescriptor.java b/src/main/java/plugins/adufour/roi/ROIHaralickTextureDescriptor.java index cb2273e4658354da269f4adaec7ff496aa35c1f4..514218d691696226af1781e28aec7755392aeebb 100644 --- a/src/main/java/plugins/adufour/roi/ROIHaralickTextureDescriptor.java +++ b/src/main/java/plugins/adufour/roi/ROIHaralickTextureDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,25 +18,29 @@ package plugins.adufour.roi; -import icy.image.IcyBufferedImage; -import icy.image.IcyBufferedImageUtil; -import icy.math.ArrayMath; -import icy.plugin.abstract_.Plugin; -import icy.plugin.interface_.PluginBundled; -import icy.plugin.interface_.PluginROIDescriptor; -import icy.roi.BooleanMask2D; -import icy.roi.ROI; -import icy.roi.ROI2D; -import icy.roi.ROIDescriptor; -import icy.sequence.Sequence; -import icy.type.DataType; +import org.bioimageanalysis.icy.common.math.ArrayMath; +import org.bioimageanalysis.icy.common.type.DataType; +import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName; +import org.bioimageanalysis.icy.extension.plugin.interface_.PluginROIDescriptor; +import org.bioimageanalysis.icy.model.image.IcyBufferedImage; +import org.bioimageanalysis.icy.model.image.IcyBufferedImageUtil; +import org.bioimageanalysis.icy.model.roi.ROI; +import org.bioimageanalysis.icy.model.roi.ROI2D; +import org.bioimageanalysis.icy.model.roi.ROIDescriptor; +import org.bioimageanalysis.icy.model.roi.mask.BooleanMask2D; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -public class ROIHaralickTextureDescriptor extends Plugin implements PluginROIDescriptor, PluginBundled { +@IcyPluginName("ROI Haralick Texture Descriptor") +@IcyPluginIcon(path = "/roi-stat.png") +public class ROIHaralickTextureDescriptor extends Plugin implements PluginROIDescriptor { private static abstract class ROIHaralickDescriptor extends ROIDescriptor { protected final int step; @@ -211,7 +215,7 @@ public class ROIHaralickTextureDescriptor extends Plugin implements PluginROIDes * (see {@link #getDescriptors()}) for a full list * @throws InterruptedException */ - public static Map<ROIDescriptor, Object> computeHaralickFeatures(final Sequence sequence, final ROI2D roi, final int step) throws InterruptedException { + public static @NotNull Map<ROIDescriptor, Object> computeHaralickFeatures(final Sequence sequence, final @NotNull ROI2D roi, final int step) throws InterruptedException { final int c = roi.getC(); if (c == -1) throw new UnsupportedOperationException("Texture can only be calculated on a single channel"); @@ -295,10 +299,10 @@ public class ROIHaralickTextureDescriptor extends Plugin implements PluginROIDes * input region of interest (ROI) * @throws InterruptedException */ - private static IcyBufferedImage buildGLCM(final IcyBufferedImage image, final ROI2D roi, final int step) throws InterruptedException { + private static @NotNull IcyBufferedImage buildGLCM(final @NotNull IcyBufferedImage image, final ROI2D roi, final int step) throws InterruptedException { // Rescale to [0-255] if necessary IcyBufferedImage imByte = null; - if (image.getDataType_() == DataType.UBYTE) { + if (image.getDataType() == DataType.UBYTE) { imByte = image; } else { @@ -372,9 +376,4 @@ public class ROIHaralickTextureDescriptor extends Plugin implements PluginROIDes return coocImage; } - - @Override - public String getMainPluginClassName() { - return ROIMeasures.class.getName(); - } } diff --git a/src/main/java/plugins/adufour/roi/ROIMeasures.java b/src/main/java/plugins/adufour/roi/ROIMeasures.java index 15a2b8ddbfff02fabcf3eaa7f389f20cc5bce63f..aeb14a080833245e3ddc223e89bca872d4f0f0ca 100644 --- a/src/main/java/plugins/adufour/roi/ROIMeasures.java +++ b/src/main/java/plugins/adufour/roi/ROIMeasures.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,31 +18,35 @@ package plugins.adufour.roi; -import icy.file.FileUtil; -import icy.gui.main.GlobalSequenceListener; -import icy.main.Icy; -import icy.plugin.PluginLauncher; -import icy.plugin.PluginLoader; -import icy.preferences.XMLPreferences; -import icy.roi.*; -import icy.roi.ROIEvent.ROIEventType; -import icy.sequence.Sequence; -import icy.sequence.SequenceDataIterator; -import icy.sequence.SequenceEvent; -import icy.sequence.SequenceEvent.SequenceEventSourceType; -import icy.sequence.SequenceListener; -import icy.system.IcyExceptionHandler; -import icy.system.SystemUtil; -import icy.system.thread.Processor; -import icy.system.thread.ThreadUtil; -import icy.type.point.Point3D; -import icy.type.point.Point5D; -import icy.type.rectangle.Rectangle5D; -import icy.util.StringUtil; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.WorkbookUtil; +import org.bioimageanalysis.extension.kernel.roi.descriptor.measure.ROIContourDescriptor; +import org.bioimageanalysis.extension.kernel.roi.descriptor.measure.ROIInteriorDescriptor; +import org.bioimageanalysis.icy.Icy; +import org.bioimageanalysis.icy.common.geom.point.Point5D; +import org.bioimageanalysis.icy.common.geom.point.Point3D; +import org.bioimageanalysis.icy.common.geom.rectangle.Rectangle5D; +import org.bioimageanalysis.icy.common.string.StringUtil; +import org.bioimageanalysis.icy.extension.plugin.PluginLauncher; +import org.bioimageanalysis.icy.extension.plugin.PluginLoader; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName; +import org.bioimageanalysis.icy.gui.listener.GlobalSequenceListener; +import org.bioimageanalysis.icy.io.FileUtil; +import org.bioimageanalysis.icy.model.roi.*; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.model.sequence.SequenceDataIterator; +import org.bioimageanalysis.icy.model.sequence.SequenceEvent; +import org.bioimageanalysis.icy.model.sequence.SequenceListener; +import org.bioimageanalysis.icy.system.SystemUtil; +import org.bioimageanalysis.icy.system.logging.IcyLogger; +import org.bioimageanalysis.icy.system.preferences.XMLPreferences; +import org.bioimageanalysis.icy.system.thread.Processor; +import org.bioimageanalysis.icy.system.thread.ThreadUtil; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; import plugins.adufour.blocks.tools.roi.ROIBlock; import plugins.adufour.blocks.util.VarList; import plugins.adufour.ezplug.EzDialog; @@ -65,8 +69,6 @@ import plugins.adufour.vars.util.VarReferencingPolicy; import plugins.adufour.workbooks.IcySpreadSheet; import plugins.adufour.workbooks.Workbooks; import plugins.kernel.roi.descriptor.measure.ROIBasicMeasureDescriptorsPlugin; -import plugins.kernel.roi.descriptor.measure.ROIContourDescriptor; -import plugins.kernel.roi.descriptor.measure.ROIInteriorDescriptor; import plugins.kernel.roi.descriptor.measure.ROIMassCenterDescriptorsPlugin; import javax.swing.*; @@ -85,8 +87,9 @@ import java.util.concurrent.Future; * @author Alexandre Dufour * @author Daniel Gonzalez */ +@IcyPluginName("ROI Measures") +@IcyPluginIcon(path = "/roi-stat.png") public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListener, SequenceListener, ROIListener { - /** * Measures available for this plugin. * <b>Note:</b> The id is used when loading and saving parameters. @@ -121,6 +124,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe final int id; final String unit; + @Contract(pure = true) Measures(final String name, final int id, final String unit) { this.name = name; this.id = id; @@ -129,31 +133,39 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe boolean selected = true; + @SuppressWarnings("UnstableApiUsage") + @Contract(mutates = "this") public void toggleSelection() { selected = !selected; } + @SuppressWarnings("UnstableApiUsage") + @Contract(mutates = "this") public void setSelected(final boolean value) { selected = value; } + @Contract(pure = true) @Override public String toString() { return name; } - public String toHeader() { + public @NotNull String toHeader() { return name + (hasUnit() ? " (" + getUnit() + ")" : ""); } + @Contract(pure = true) public boolean hasUnit() { return unit != null && !unit.isEmpty(); } + @Contract(pure = true) public String getUnit() { return unit; } + @Contract(pure = true) public boolean isSelected() { return selected; } @@ -226,7 +238,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe } @Override - public void declareInput(final VarList inputMap) { + public void declareInput(final @NotNull VarList inputMap) { measureSelector.setReferencingPolicy(VarReferencingPolicy.NONE); inputMap.add("measures", measureSelector); inputMap.add("Regions of interest", rois); @@ -234,7 +246,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe } @Override - public void declareOutput(final VarList outputMap) { + public void declareOutput(final @NotNull VarList outputMap) { outputMap.add("Workbook", book); } @@ -271,7 +283,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe book.setValue(wbs); } catch (final IOException e) { - IcyExceptionHandler.showErrorMessage(e, true); + IcyLogger.error(this.getClass(), e); } //book.setValue(wb = Workbooks.createEmptyWorkbook()); } @@ -293,7 +305,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe // try retrieving the sequence attached to the first ROI final List<Sequence> sequences = rois.getValue()[0].getSequences(); if (!sequences.isEmpty()) - sequenceOfInterest = sequences.get(0); + sequenceOfInterest = sequences.getFirst(); } if (sequenceOfInterest == null) { @@ -418,7 +430,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe return; } catch (final Exception e) { - IcyExceptionHandler.showErrorMessage(e, true); + IcyLogger.error(this.getClass(), e); return; } @@ -433,7 +445,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe } } - private void updateStatistics(final ROI roi) { + private void updateStatistics(final @NotNull ROI roi) { final Workbook wb = book.getValue(); for (final Sequence sequenceOfInterest : roi.getSequences()) @@ -452,13 +464,13 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe } } - private static String colorToString(final Color color) { + private static @NotNull String colorToString(final @NotNull Color color) { return (StringUtil.toHexaString(color.getAlpha(), 2) + StringUtil.toHexaString(color.getRed(), 2) + StringUtil.toHexaString(color.getGreen(), 2) + StringUtil.toHexaString(color.getBlue(), 2)) .toUpperCase(); } - private void updateWorkbook(final Workbook wb, final IcySpreadSheet sheet, final int rowID, final List<Object> measures, final boolean updateInterface) { + private void updateWorkbook(final Workbook wb, final IcySpreadSheet sheet, final int rowID, final @NotNull List<Object> measures, final boolean updateInterface) { for (int colID = 0; colID < measures.size(); colID++) { final Object value = measures.get(colID); @@ -474,7 +486,9 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe book.valueChanged(book, null, book.getValue()); } - private Callable<List<Object>> createUpdater(final Sequence sequenceOfInterest, final ROI roi2Update) { + @SuppressWarnings("resource") + @Contract(pure = true) + private @NotNull Callable<List<Object>> createUpdater(final Sequence sequenceOfInterest, final ROI roi2Update) { return () -> { final List<Object> measures = new ArrayList<>(); final List<Measures> measuresToCalculate = new ArrayList<>(); @@ -493,7 +507,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe || Measures.T_CENTER.isSelected() || Measures.C_CENTER.isSelected() || Measures.X_GLOBAL_CENTER.isSelected() || Measures.Y_GLOBAL_CENTER.isSelected() || Measures.Z_GLOBAL_CENTER.isSelected()) { - center = ROIMassCenterDescriptorsPlugin.computeMassCenter(roi); + center = ROIUtil.computeMassCenter(roi); globalCenter = center.toPoint3D(); if (sequenceOfInterest != null) { globalCenter.setX(sequenceOfInterest.getPositionX() @@ -596,7 +610,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe // we don't want to spam output with these errors if (!haralickErrors.contains(mess)) { haralickErrors.add(mess); - System.err.println(mess); + IcyLogger.error(this.getClass(), ex); } } } @@ -866,8 +880,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe if (sequenceOfInterest == null) measures.add("NA"); else { - final double mul = ROIBasicMeasureDescriptorsPlugin - .getMultiplierFactor(sequenceOfInterest, roi, 2); + final double mul = ROIUtil.getMultiplierFactor(sequenceOfInterest, roi, 2); // 0 means the operation is not supported for this ROI if (mul == 0d) @@ -888,8 +901,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe if (sequenceOfInterest == null) measures.add("NA"); else { - final double mul1 = ROIBasicMeasureDescriptorsPlugin - .getMultiplierFactor(sequenceOfInterest, roi, 3); + final double mul1 = ROIUtil.getMultiplierFactor(sequenceOfInterest, roi, 3); // 0 means the operation is not supported for this ROI if (mul1 == 0d) @@ -902,16 +914,19 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe } break; case INTENSITY_X: + Objects.requireNonNull(intensityCenters); for (int c = 0; c < sizeC; c++) { measures.add(intensityCenters[c].getX()); } break; case INTENSITY_Y: + Objects.requireNonNull(intensityCenters); for (int c = 0; c < sizeC; c++) { measures.add(intensityCenters[c].getY()); } break; case INTENSITY_Z: + Objects.requireNonNull(intensityCenters); for (int c = 0; c < sizeC; c++) { measures.add(intensityCenters[c].getZ()); } @@ -931,7 +946,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe // MAIN LISTENER // @Override - public void sequenceOpened(final Sequence openedSequence) { + public void sequenceOpened(final @NotNull Sequence openedSequence) { openedSequence.addListener(this); for (final ROI roi : openedSequence.getROIs()) roi.addListener(this); @@ -944,7 +959,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe } @Override - public void sequenceClosed(final Sequence closedSequence) { + public void sequenceClosed(final @NotNull Sequence closedSequence) { closedSequence.removeListener(this); for (final ROI roi : closedSequence.getROIs()) roi.removeListener(this); @@ -963,12 +978,12 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe // SEQUENCE LISTENER // @Override - public void sequenceChanged(final SequenceEvent sequenceEvent) { - if (sequenceEvent.getSourceType() == SequenceEventSourceType.SEQUENCE_DATA) { + public void sequenceChanged(final @NotNull SequenceEvent sequenceEvent) { + if (sequenceEvent.getSourceType() == SequenceEvent.SequenceEventSourceType.SEQUENCE_DATA) { updateStatistics(sequenceEvent.getSequence()); } - else if (sequenceEvent.getSourceType() == SequenceEventSourceType.SEQUENCE_ROI) { + else if (sequenceEvent.getSourceType() == SequenceEvent.SequenceEventSourceType.SEQUENCE_ROI) { final ROI roi = (ROI) sequenceEvent.getSource(); switch (sequenceEvent.getType()) { @@ -991,7 +1006,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe if (roi == null) { // multiple ROIs have been removed - System.err.println("[ROI Statistics] Warning: potential memory leak"); + IcyLogger.warn(this.getClass(), "Warning: potential memory leak"); } else { roi.removeListener(this); @@ -1021,9 +1036,9 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe } @Override - public void roiChanged(final ROIEvent event) { - if (event.getType() == ROIEventType.ROI_CHANGED - || event.getType() == ROIEventType.PROPERTY_CHANGED && (event.getPropertyName().equalsIgnoreCase("name") + public void roiChanged(final @NotNull ROIEvent event) { + if (event.getType() == ROIEvent.ROIEventType.ROI_CHANGED + || event.getType() == ROIEvent.ROIEventType.PROPERTY_CHANGED && (event.getPropertyName().equalsIgnoreCase("name") || event.getPropertyName().equalsIgnoreCase("color"))) { updateStatistics(event.getSource()); // this is mandatory since sheet modification cannot be detected @@ -1049,8 +1064,9 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe setNameVisible(false); } + @Contract(" -> new") @Override - protected JButton createEditorComponent() { + protected @NotNull JButton createEditorComponent() { if (getEditorComponent() != null) deactivateListeners(); @@ -1074,6 +1090,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe getEditorComponent().removeActionListener(listener); } + @Contract(pure = true) @Override protected void updateInterfaceValue() { // nothing to do (it's just a button with a name) @@ -1103,8 +1120,9 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe addListener(gui); } + @Contract(" -> new") @Override - public VarEditor<Long> createVarEditor() { + public @NotNull VarEditor<Long> createVarEditor() { return new ButtonVarEditor(this); } @@ -1241,6 +1259,7 @@ public class ROIMeasures extends EzPlug implements ROIBlock, GlobalSequenceListe } } + @SuppressWarnings("resource") public static void main(final String[] args) { Icy.main(args); diff --git a/src/main/java/plugins/adufour/roi/ROIRoundnessDescriptor.java b/src/main/java/plugins/adufour/roi/ROIRoundnessDescriptor.java index 2da0b4c20c644619f2e297ea137f7fcce24dd623..ab3da3b883174c5319f4c341af234f5a13073894 100644 --- a/src/main/java/plugins/adufour/roi/ROIRoundnessDescriptor.java +++ b/src/main/java/plugins/adufour/roi/ROIRoundnessDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,19 +18,18 @@ package plugins.adufour.roi; -import icy.plugin.abstract_.Plugin; -import icy.plugin.interface_.PluginBundled; -import icy.plugin.interface_.PluginROIDescriptor; -import icy.roi.ROI; -import icy.roi.ROI2D; -import icy.roi.ROI3D; -import icy.roi.ROIDescriptor; -import icy.sequence.Sequence; -import icy.type.point.Point3D; -import icy.type.point.Point5D; +import org.bioimageanalysis.extension.kernel.roi.roi2d.ROI2DEllipse; +import org.bioimageanalysis.icy.common.geom.point.Point3D; +import org.bioimageanalysis.icy.common.geom.point.Point5D; +import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName; +import org.bioimageanalysis.icy.extension.plugin.interface_.PluginROIDescriptor; +import org.bioimageanalysis.icy.model.roi.*; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.system.logging.IcyLogger; import plugins.adufour.roi.ROISphericityDescriptor.ROISphericity; import plugins.kernel.roi.descriptor.measure.ROIMassCenterDescriptorsPlugin; -import plugins.kernel.roi.roi2d.ROI2DEllipse; import javax.vecmath.Point3d; import java.awt.*; @@ -41,7 +40,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -public class ROIRoundnessDescriptor extends Plugin implements PluginROIDescriptor, PluginBundled { +@IcyPluginName("ROI Roundness Descriptor") +@IcyPluginIcon(path = "/roi-stat.png") +public class ROIRoundnessDescriptor extends Plugin implements PluginROIDescriptor { public static class ROIRoundness extends ROIDescriptor { public ROIRoundness() { super("Roundness", Double.class); @@ -111,7 +112,7 @@ public class ROIRoundnessDescriptor extends Plugin implements PluginROIDescripto public static double computeRoundness(final ROI roi) throws InterruptedException { double minDistance = Double.MAX_VALUE, maxDistance = 0.0d; - final Point5D center = ROIMassCenterDescriptorsPlugin.computeMassCenter(roi); + final Point5D center = ROIUtil.computeMassCenter(roi); if (roi instanceof ROI2D) { if (roi instanceof ROI2DEllipse) { @@ -146,7 +147,7 @@ public class ROIRoundnessDescriptor extends Plugin implements PluginROIDescripto } } else { - System.err.println("Cannot compute roundness for ROI of type: " + roi.getClassName()); + IcyLogger.error(ROIRoundness.class, "Cannot compute roundness for ROI of type: " + roi.getClassName()); return Double.NaN; } @@ -171,9 +172,4 @@ public class ROIRoundnessDescriptor extends Plugin implements PluginROIDescripto map.put(roundness, roundness.compute(roi, sequence)); return map; } - - @Override - public String getMainPluginClassName() { - return ROIMeasures.class.getName(); - } } diff --git a/src/main/java/plugins/adufour/roi/ROISphericityDescriptor.java b/src/main/java/plugins/adufour/roi/ROISphericityDescriptor.java index ce81dae99ada3e5ace4648070bf8218847e13283..a3edb221c15a602c969df1d16ddba6d9014d29e6 100644 --- a/src/main/java/plugins/adufour/roi/ROISphericityDescriptor.java +++ b/src/main/java/plugins/adufour/roi/ROISphericityDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,21 +18,25 @@ package plugins.adufour.roi; -import icy.plugin.abstract_.Plugin; -import icy.plugin.interface_.PluginBundled; -import icy.plugin.interface_.PluginROIDescriptor; -import icy.roi.ROI; -import icy.roi.ROI2D; -import icy.roi.ROI3D; -import icy.roi.ROIDescriptor; -import icy.sequence.Sequence; +import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName; +import org.bioimageanalysis.icy.extension.plugin.interface_.PluginROIDescriptor; +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.ROIDescriptor; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.system.logging.IcyLogger; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -public class ROISphericityDescriptor extends Plugin implements PluginROIDescriptor, PluginBundled { +@IcyPluginName("ROI Sphericity Descriptor") +@IcyPluginIcon(path = "/roi-stat.png") +public class ROISphericityDescriptor extends Plugin implements PluginROIDescriptor { public static class ROISphericity extends ROIDescriptor { public ROISphericity() { super("Sphericity", Double.class); @@ -101,7 +105,7 @@ public class ROISphericityDescriptor extends Plugin implements PluginROIDescript dim = 3.0d; } else { - System.err.println("Cannot compute sphericity for ROI of type: " + roi.getClassName()); + IcyLogger.error(ROISphericity.class, "Cannot compute sphericity for ROI of type: " + roi.getClassName()); return Double.NaN; } @@ -147,9 +151,4 @@ public class ROISphericityDescriptor extends Plugin implements PluginROIDescript map.put(sphericity, sphericity.compute(roi, sequence)); return map; } - - @Override - public String getMainPluginClassName() { - return ROIMeasures.class.getName(); - } } diff --git a/src/main/java/plugins/adufour/roi/ROIStatisticsTrackProcessor.java b/src/main/java/plugins/adufour/roi/ROIStatisticsTrackProcessor.java index 67bab6d97090fb64902dd5d6394fb1cd6515f531..0b799703683c7afdc023d7e9c1a438fa37f29abe 100644 --- a/src/main/java/plugins/adufour/roi/ROIStatisticsTrackProcessor.java +++ b/src/main/java/plugins/adufour/roi/ROIStatisticsTrackProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,15 +18,14 @@ package plugins.adufour.roi; -import icy.file.FileUtil; -import icy.gui.dialog.SaveDialog; -import icy.gui.frame.progress.AnnounceFrame; -import icy.gui.util.GuiUtil; -import icy.plugin.interface_.PluginBundled; -import icy.roi.ROIDescriptor; -import icy.sequence.Sequence; -import icy.system.IcyExceptionHandler; import org.apache.poi.ss.usermodel.Workbook; +import org.bioimageanalysis.icy.gui.GuiUtil; +import org.bioimageanalysis.icy.gui.dialog.SaveDialog; +import org.bioimageanalysis.icy.gui.frame.progress.AnnounceFrame; +import org.bioimageanalysis.icy.io.FileUtil; +import org.bioimageanalysis.icy.model.roi.ROIDescriptor; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.system.logging.IcyLogger; import org.math.plot.Plot2DPanel; import plugins.adufour.blocks.tools.io.WorkbookToFile; import plugins.adufour.blocks.tools.io.WorkbookToFile.MergePolicy; @@ -42,12 +41,7 @@ import javax.swing.*; import java.awt.*; import java.io.IOException; -public class ROIStatisticsTrackProcessor extends PluginTrackManagerProcessor implements PluginBundled { - @Override - public String getMainPluginClassName() { - return ROIMeasures.class.getName(); - } - +public class ROIStatisticsTrackProcessor extends PluginTrackManagerProcessor { private final JButton exportButton = new JButton("Export to XLS..."); private final VarSequence sequence = new VarSequence("Sequence", null); @@ -134,8 +128,13 @@ public class ROIStatisticsTrackProcessor extends PluginTrackManagerProcessor imp final Sequence seq = trackPool.getDisplaySequence(); try { - ROITrackStatistics.buildPlot(trackPool.getTrackGroupList(), seq, channel.getValue(), - ROIDescriptor.getDescriptor(roiDescriptor.getValue()), plotPanel); + ROITrackStatistics.buildPlot( + trackPool.getTrackGroupList(), + seq, + channel.getValue(), + ROIDescriptor.getDescriptor(roiDescriptor.getValue()), + plotPanel + ); if (!plotPanel.getPlots().isEmpty()) { chartPanel.add(plotPanel); @@ -148,7 +147,7 @@ public class ROIStatisticsTrackProcessor extends PluginTrackManagerProcessor imp } } catch (final Exception e) { - IcyExceptionHandler.showErrorMessage(e, true); + IcyLogger.error(this.getClass(), e, "Cannot compute descriptor."); chartPanel.add(new JLabel("Cannot compute descriptor: " + e.getMessage())); exportButton.setEnabled(false); } @@ -172,7 +171,7 @@ public class ROIStatisticsTrackProcessor extends PluginTrackManagerProcessor imp // Restore last used folder final String xlsFolder = getPreferencesRoot().get("xlsFolder", null); - final String path = SaveDialog.chooseFile("Export statistics", xlsFolder, name, ".xls"); + final String path = SaveDialog.chooseFile("Export statistics", xlsFolder, name, ".xlsx"); // canceled if (path == null) @@ -191,7 +190,7 @@ public class ROIStatisticsTrackProcessor extends PluginTrackManagerProcessor imp } } catch (final IOException e) { - IcyExceptionHandler.showErrorMessage(e, true); + IcyLogger.error(this.getClass(), e, "Cannot export statistics."); } finally { message.close(); diff --git a/src/main/java/plugins/adufour/roi/ROITrackStatistics.java b/src/main/java/plugins/adufour/roi/ROITrackStatistics.java index 6cf461327622b5e244c5e29dbc6c6a6844046d9a..0e49661fd2f3ac703549af816da7e0571e5e664f 100644 --- a/src/main/java/plugins/adufour/roi/ROITrackStatistics.java +++ b/src/main/java/plugins/adufour/roi/ROITrackStatistics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,15 +18,21 @@ package plugins.adufour.roi; -import icy.plugin.abstract_.Plugin; -import icy.plugin.interface_.PluginBundled; -import icy.roi.ROI; -import icy.roi.ROI2D; -import icy.roi.ROI3D; -import icy.roi.ROIDescriptor; -import icy.sequence.Sequence; -import icy.type.collection.CollectionUtil; import org.apache.poi.ss.usermodel.Workbook; +import org.bioimageanalysis.extension.kernel.roi.roi2d.ROI2DArea; +import org.bioimageanalysis.extension.kernel.roi.roi2d.ROI2DPoint; +import org.bioimageanalysis.extension.kernel.roi.roi3d.ROI3DArea; +import org.bioimageanalysis.extension.kernel.roi.roi3d.ROI3DPoint; +import org.bioimageanalysis.icy.common.collection.CollectionUtil; +import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName; +import org.bioimageanalysis.icy.model.roi.ROI; +import org.bioimageanalysis.icy.model.roi.ROI2D; +import org.bioimageanalysis.icy.model.roi.ROI3D; +import org.bioimageanalysis.icy.model.roi.ROIDescriptor; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.jetbrains.annotations.NotNull; import org.math.plot.Plot2DPanel; import org.math.plot.plots.Plot; import plugins.adufour.activecontours.ActiveContour; @@ -39,10 +45,6 @@ import plugins.adufour.workbooks.IcySpreadSheet; import plugins.adufour.workbooks.Workbooks; import plugins.fab.trackmanager.TrackGroup; import plugins.fab.trackmanager.TrackSegment; -import plugins.kernel.roi.roi2d.ROI2DArea; -import plugins.kernel.roi.roi2d.ROI2DPoint; -import plugins.kernel.roi.roi3d.ROI3DArea; -import plugins.kernel.roi.roi3d.ROI3DPoint; import plugins.nchenouard.particletracking.DetectionSpotTrack; import plugins.nchenouard.particletracking.legacytracker.SpotTrack; import plugins.nchenouard.spot.Detection; @@ -55,15 +57,22 @@ import java.util.List; * * @author Stephane Dallongeville */ -public class ROITrackStatistics extends Plugin implements ROIBlock, PluginBundled { +@IcyPluginName("ROI Track Statistics") +@IcyPluginIcon(path = "/roi-stat.png") +public class ROITrackStatistics extends Plugin implements ROIBlock { /** * Build the plot describing the {@link ROIDescriptor} evolution along given input tracks * * @throws InterruptedException * @throws UnsupportedOperationException */ - public static void buildPlot(final List<TrackGroup> trackGroups, final Sequence sequence, final int channel, final ROIDescriptor descriptor, final Plot2DPanel plotPanel) - throws UnsupportedOperationException, InterruptedException { + public static void buildPlot( + final @NotNull List<TrackGroup> trackGroups, + final Sequence sequence, + final int channel, + final @NotNull ROIDescriptor descriptor, + final @NotNull Plot2DPanel plotPanel + ) throws UnsupportedOperationException, InterruptedException { final int sizeZ = (sequence != null) ? sequence.getSizeZ() : 1; final double timeInterval = (sequence != null) ? sequence.getTimeInterval() : 1d; @@ -178,7 +187,7 @@ public class ROITrackStatistics extends Plugin implements ROIBlock, PluginBundle /** * Build and return the workbook describing the {@link ROIDescriptor} evolution along given input tracks */ - public static Workbook getWorkBook(final Sequence sequence, final String name, final Plot2DPanel plotPanel) { + public static @NotNull Workbook getWorkBook(final Sequence sequence, final String name, final Plot2DPanel plotPanel) { final Workbook wb = Workbooks.createEmptyWorkbook(); final IcySpreadSheet sheet = Workbooks.getSheet(wb, name); @@ -225,7 +234,7 @@ public class ROITrackStatistics extends Plugin implements ROIBlock, PluginBundle } @Override - public void declareInput(final VarList inputMap) { + public void declareInput(final @NotNull VarList inputMap) { inputMap.add("trackgroup", tracks); inputMap.add("sequence", sequence); inputMap.add("channel", channel); @@ -233,7 +242,7 @@ public class ROITrackStatistics extends Plugin implements ROIBlock, PluginBundle } @Override - public void declareOutput(final VarList outputMap) { + public void declareOutput(final @NotNull VarList outputMap) { outputMap.add("workbook", workbook); } @@ -268,9 +277,4 @@ public class ROITrackStatistics extends Plugin implements ROIBlock, PluginBundle Thread.currentThread().interrupt(); } } - - @Override - public String getMainPluginClassName() { - return ROIMeasures.class.getName(); - } } diff --git a/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterDescriptorsPlugin.java b/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterDescriptorsPlugin.java index ea06b9881703bf3b7ff3926994d650bee18a2496..b60eb673452e624321c2f97f3b75e94979948b78 100644 --- a/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterDescriptorsPlugin.java +++ b/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterDescriptorsPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,16 +18,20 @@ package plugins.adufour.roi.intensitycenter; -import icy.plugin.abstract_.Plugin; -import icy.plugin.interface_.PluginROIDescriptor; -import icy.roi.ROI; -import icy.roi.ROIDescriptor; -import icy.sequence.Sequence; -import icy.sequence.SequenceDataIterator; -import icy.type.point.Point3D; -import icy.type.rectangle.Rectangle5D; -import plugins.kernel.roi.roi2d.ROI2DPoint; -import plugins.kernel.roi.roi3d.ROI3DPoint; +import org.bioimageanalysis.extension.kernel.roi.roi2d.ROI2DPoint; +import org.bioimageanalysis.extension.kernel.roi.roi3d.ROI3DPoint; +import org.bioimageanalysis.icy.common.geom.point.Point3D; +import org.bioimageanalysis.icy.common.geom.rectangle.Rectangle5D; +import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName; +import org.bioimageanalysis.icy.extension.plugin.interface_.PluginROIDescriptor; +import org.bioimageanalysis.icy.model.roi.ROI; +import org.bioimageanalysis.icy.model.roi.ROIDescriptor; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.model.sequence.SequenceDataIterator; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; @@ -41,6 +45,8 @@ import java.util.Map; * * @author Daniel Felipe Gonzalez Obando */ +@IcyPluginName("ROI Intensity Center Descriptor") +@IcyPluginIcon(path = "/roi-stat.png") public class ROIIntensityCenterDescriptorsPlugin extends Plugin implements PluginROIDescriptor { public static final String ID_MASS_CENTER_X = ROIIntensityCenterXDescriptor.ID; public static final String ID_MASS_CENTER_Y = ROIIntensityCenterYDescriptor.ID; @@ -58,7 +64,8 @@ public class ROIIntensityCenterDescriptorsPlugin extends Plugin implements Plugi * @return Position of the intensity center. * @throws InterruptedException If the thread is interrupted during the descriptors computation. */ - public static Point3D computeIntensityCenter(final ROI roi, final Sequence sequence) throws InterruptedException { + @Contract("_, _ -> new") + public static @NotNull Point3D computeIntensityCenter(final @NotNull ROI roi, final Sequence sequence) throws InterruptedException { final Rectangle5D bounds = roi.getBounds5D(); // special case of empty bounds ? --> return position @@ -142,5 +149,4 @@ public class ROIIntensityCenterDescriptorsPlugin extends Plugin implements Plugi return result; } - } diff --git a/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterXDescriptor.java b/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterXDescriptor.java index f97178f8c9708d866172dad3b69d9ce3b49bfb20..fd462e2268f2dac04c747371e7ed814afac5e0a1 100644 --- a/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterXDescriptor.java +++ b/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterXDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,12 +18,12 @@ package plugins.adufour.roi.intensitycenter; -import icy.roi.ROI; -import icy.roi.ROIDescriptor; -import icy.sequence.Sequence; -import icy.sequence.SequenceEvent; -import icy.sequence.SequenceEvent.SequenceEventSourceType; -import icy.type.point.Point3D; +import org.bioimageanalysis.icy.common.geom.point.Point3D; +import org.bioimageanalysis.icy.model.roi.ROI; +import org.bioimageanalysis.icy.model.roi.ROIDescriptor; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.model.sequence.SequenceEvent; +import org.jetbrains.annotations.NotNull; public class ROIIntensityCenterXDescriptor extends ROIDescriptor { public static final String ID = "Intensity center X"; @@ -48,8 +48,8 @@ public class ROIIntensityCenterXDescriptor extends ROIDescriptor { } @Override - public boolean needRecompute(final SequenceEvent change) { - return (change.getSourceType() == SequenceEventSourceType.SEQUENCE_DATA); + public boolean needRecompute(final @NotNull SequenceEvent change) { + return (change.getSourceType() == SequenceEvent.SequenceEventSourceType.SEQUENCE_DATA); } @Override diff --git a/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterYDescriptor.java b/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterYDescriptor.java index 8e55be667384fcaa4084a688976b7203e742082d..b6eab030f6737e1e4310ccd900f5843f3f72163b 100644 --- a/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterYDescriptor.java +++ b/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterYDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,12 +18,12 @@ package plugins.adufour.roi.intensitycenter; -import icy.roi.ROI; -import icy.roi.ROIDescriptor; -import icy.sequence.Sequence; -import icy.sequence.SequenceEvent; -import icy.sequence.SequenceEvent.SequenceEventSourceType; -import icy.type.point.Point3D; +import org.bioimageanalysis.icy.common.geom.point.Point3D; +import org.bioimageanalysis.icy.model.roi.ROI; +import org.bioimageanalysis.icy.model.roi.ROIDescriptor; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.model.sequence.SequenceEvent; +import org.jetbrains.annotations.NotNull; public class ROIIntensityCenterYDescriptor extends ROIDescriptor { public static final String ID = "Intensity center Y"; @@ -48,8 +48,8 @@ public class ROIIntensityCenterYDescriptor extends ROIDescriptor { } @Override - public boolean needRecompute(final SequenceEvent change) { - return (change.getSourceType() == SequenceEventSourceType.SEQUENCE_DATA); + public boolean needRecompute(final @NotNull SequenceEvent change) { + return (change.getSourceType() == SequenceEvent.SequenceEventSourceType.SEQUENCE_DATA); } @Override diff --git a/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterZDescriptor.java b/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterZDescriptor.java index 55ad85310f11b58f306b439bb47eee5ca0c2ccec..ecae5f7d67dc588f250bd8fc520cda24262d1a42 100644 --- a/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterZDescriptor.java +++ b/src/main/java/plugins/adufour/roi/intensitycenter/ROIIntensityCenterZDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,12 +18,12 @@ package plugins.adufour.roi.intensitycenter; -import icy.roi.ROI; -import icy.roi.ROIDescriptor; -import icy.sequence.Sequence; -import icy.sequence.SequenceEvent; -import icy.sequence.SequenceEvent.SequenceEventSourceType; -import icy.type.point.Point3D; +import org.bioimageanalysis.icy.common.geom.point.Point3D; +import org.bioimageanalysis.icy.model.roi.ROI; +import org.bioimageanalysis.icy.model.roi.ROIDescriptor; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.model.sequence.SequenceEvent; +import org.jetbrains.annotations.NotNull; public class ROIIntensityCenterZDescriptor extends ROIDescriptor { public static final String ID = "Intensity center Z"; @@ -48,8 +48,8 @@ public class ROIIntensityCenterZDescriptor extends ROIDescriptor { } @Override - public boolean needRecompute(final SequenceEvent change) { - return (change.getSourceType() == SequenceEventSourceType.SEQUENCE_DATA); + public boolean needRecompute(final @NotNull SequenceEvent change) { + return (change.getSourceType() == SequenceEvent.SequenceEventSourceType.SEQUENCE_DATA); } @Override diff --git a/src/main/resources/roi-stat.png b/src/main/resources/roi-stat.png new file mode 100644 index 0000000000000000000000000000000000000000..cefa2397373f100d897d68f81231284f3e2aaccc Binary files /dev/null and b/src/main/resources/roi-stat.png differ