diff --git a/metroloSPIM/.classpath b/metroloSPIM/.classpath new file mode 100644 index 0000000000000000000000000000000000000000..698b6a5b7244de66c980138d80559422711ac7a4 --- /dev/null +++ b/metroloSPIM/.classpath @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> + <classpathentry kind="var" path="ICY_JAR"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="var" path="ICY_PLUGINS/adufour/blocks/Blocks.jar"/> + <classpathentry kind="var" path="ICY_PLUGINS/adufour/ezplug/EzPlug.jar"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/metroloSPIM/.gitignore b/metroloSPIM/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..be17b1e53c498ebd3551c5429e80c1c35d4dc916 --- /dev/null +++ b/metroloSPIM/.gitignore @@ -0,0 +1,2 @@ +/bin/ +*.jar \ No newline at end of file diff --git a/metroloSPIM/.project b/metroloSPIM/.project new file mode 100644 index 0000000000000000000000000000000000000000..4a6a4df15d4c5b109ff3a559f92ec1ca81249430 --- /dev/null +++ b/metroloSPIM/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>metroloSPIM</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/metroloSPIM/export.jardesc b/metroloSPIM/export.jardesc new file mode 100644 index 0000000000000000000000000000000000000000..67403f337ae1b80b9121259d170bcf1f99507692 --- /dev/null +++ b/metroloSPIM/export.jardesc @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="WINDOWS-1252" standalone="no"?> +<jardesc> + <jar path="metroloSPIM/metroloSPIM.jar"/> + <options buildIfNeeded="true" compress="true" descriptionLocation="/metroloSPIM/export.jardesc" exportErrors="false" exportWarnings="true" includeDirectoryEntries="true" overwrite="true" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/> + <storedRefactorings deprecationInfo="true" structuralOnly="false"/> + <selectedProjects/> + <manifest generateManifest="true" manifestLocation="/Icy-Kernel/META-INF/MANIFEST.MF" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true"> + <sealing sealJar="false"> + <packagesToSeal/> + <packagesToUnSeal/> + </sealing> + </manifest> + <selectedElements exportClassFiles="true" exportJavaFiles="true" exportOutputFolder="false"> + <javaElement handleIdentifier="=metroloSPIM/src"/> + </selectedElements> +</jardesc> diff --git a/metroloSPIM/src/plugins/adufour/metrolospim/ComputeQuadrants.java b/metroloSPIM/src/plugins/adufour/metrolospim/ComputeQuadrants.java new file mode 100644 index 0000000000000000000000000000000000000000..368111e384ac78cc477f9480f81fefa06f4308ce --- /dev/null +++ b/metroloSPIM/src/plugins/adufour/metrolospim/ComputeQuadrants.java @@ -0,0 +1,180 @@ +package plugins.adufour.metrolospim; + +import icy.canvas.IcyCanvas; +import icy.painter.Overlay; +import icy.plugin.abstract_.Plugin; +import icy.roi.ROI; +import icy.roi.ROI2D; +import icy.roi.ROIUtil; +import icy.sequence.Sequence; +import icy.util.GraphicsUtil; +import icy.util.ShapeUtil.BooleanOperator; +import icy.util.StringUtil; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.Arrays; + +import plugins.adufour.blocks.lang.Block; +import plugins.adufour.blocks.util.VarList; +import plugins.adufour.vars.lang.VarBoolean; +import plugins.adufour.vars.lang.VarDouble; +import plugins.adufour.vars.lang.VarSequence; +import plugins.kernel.roi.roi2d.ROI2DArea; +import plugins.kernel.roi.roi2d.ROI2DPolygon; + +public class ComputeQuadrants extends Plugin implements Block +{ + VarSequence input = new VarSequence("Sequence", null); + + VarBoolean splitExistingROI = new VarBoolean("Split ROI", true); + + Overlay overlay; + + VarDouble north = new VarDouble("North (%)", 0.0); + VarDouble east = new VarDouble("East (%)", 0.0); + VarDouble west = new VarDouble("West (%)", 0.0); + VarDouble south = new VarDouble("South (%)", 0.0); + + @Override + public void declareInput(VarList inputMap) + { + inputMap.add("sequence", input); + inputMap.add("split", splitExistingROI); + } + + @Override + public void declareOutput(VarList outputMap) + { + outputMap.add("north", north); + outputMap.add("east", east); + outputMap.add("west", west); + outputMap.add("south", south); + } + + @Override + public void run() + { + Sequence sequence = input.getValue(); + + // create each quadrant as a polygon + + int w = sequence.getWidth(); + int h = sequence.getHeight(); + + final ROI2DPolygon[] quadrants = new ROI2DPolygon[4]; + + // north + quadrants[0] = new ROI2DPolygon(new Point2D.Double(0, 0)); + quadrants[0].addPoint(new Point2D.Double(w / 2.0, -0.5 + h / 2.0), true); + quadrants[0].addPoint(new Point2D.Double(w, 0), true); + + // west + quadrants[1] = new ROI2DPolygon(new Point2D.Double(0, h - 0.5)); + quadrants[1].addPoint(new Point2D.Double(-0.5 + w / 2.0, h / 2.0), true); + quadrants[1].addPoint(new Point2D.Double(0, 0), true); + + // east + quadrants[2] = new ROI2DPolygon(new Point2D.Double(w + 0.5, 0)); + quadrants[2].addPoint(new Point2D.Double(0.5 + w / 2.0, h / 2.0), true); + quadrants[2].addPoint(new Point2D.Double(w + 0.5, h + 0.5), true); + + // south + quadrants[3] = new ROI2DPolygon(new Point2D.Double(w + 0.5, h + 0.5)); + quadrants[3].addPoint(new Point2D.Double(w / 2.0, 0.5 + h / 2.0), true); + quadrants[3].addPoint(new Point2D.Double(0, h + 0.5), true); + + for (ROI2DPolygon quadrant : quadrants) + quadrant.setColor(Color.blue); + + final double[] areas = new double[4]; + + // merge all existing sequence ROI into a single area + + ArrayList<ROI> rois = sequence.getROIs(); + if (rois.size() > 0) + { + ROI2D merge = (ROI2D) ROIUtil.merge(rois, BooleanOperator.OR); + ROI2DArea mergeArea = new ROI2DArea(merge.getBooleanMask(true)); + + double totalArea = mergeArea.getNumberOfPoints(); + + if (totalArea > 0) + { + // compute the surface ratio inside each quadrant + + for (int i = 0; i < 4; i++) + { + // intersect the quadrant with the total surface + areas[i] = ROIUtil.merge(Arrays.asList(quadrants[i], (ROI) mergeArea), BooleanOperator.AND).getNumberOfPoints(); + + // make it a ratio + areas[i] /= totalArea; + } + + for (int i = 0; i < 4; i++) + { + // set a gradual color in "restricted" HSV space + // => from blue (240', i.e. 2f/3f) to red (0', or 0f) + + // scale the areas to get a [2/3,0] interval + double hsv = (2.0 / 3.0) - (areas[i] * 2.0 / 3.0); + + quadrants[i].setColor(Color.getHSBColor((float) hsv, 1f, 1f)); + + // make it a percentage for display purposes + areas[i] *= 100; + } + } + } + + north.setValue(areas[0]); + west.setValue(areas[1]); + east.setValue(areas[2]); + south.setValue(areas[3]); + + // remove the overlay if it existed + if (overlay != null) sequence.removeOverlay(overlay); + + sequence.addOverlay(overlay = new Overlay("Quadrants") + { + @Override + public void paint(Graphics2D g, Sequence sequence, IcyCanvas canvas) + { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + float fontSize = (float) canvas.canvasToImageLogDeltaX(30); + g.setFont(new Font("Trebuchet MS", Font.BOLD, 10).deriveFont(fontSize)); + + double stroke = Math.max(canvas.canvasToImageLogDeltaX(2), canvas.canvasToImageLogDeltaY(2)); + + g.setStroke(new BasicStroke((float) stroke, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + + for (int i = 0; i < 4; i++) + { + ROI2DPolygon quadrant = quadrants[i]; + + Rectangle bounds = quadrant.getBounds(); + String text = StringUtil.toString(areas[i], 2) + "%"; + Dimension size = GraphicsUtil.getHintSize(g, text); + + int x = (int) bounds.getCenterX() - size.width / 2; + int y = (int) bounds.getCenterY() - size.height / 2; + + g.setColor(quadrant.getColor()); + + g.draw(quadrant); + + GraphicsUtil.drawHint(g, text, x, y, quadrant.getColor(), quadrant.getColor()); + } + } + }); + } +} diff --git a/metroloSPIM/src/plugins/adufour/metrolospim/Create3DRectangleROI.java b/metroloSPIM/src/plugins/adufour/metrolospim/Create3DRectangleROI.java new file mode 100644 index 0000000000000000000000000000000000000000..ccf98b1007b0f882c550eb44ac442a5a133a2c10 --- /dev/null +++ b/metroloSPIM/src/plugins/adufour/metrolospim/Create3DRectangleROI.java @@ -0,0 +1,83 @@ +package plugins.adufour.metrolospim; + +import icy.plugin.abstract_.Plugin; +import icy.type.point.Point3D; +import plugins.adufour.blocks.tools.roi.ROIBlock; +import plugins.adufour.blocks.util.VarList; +import plugins.adufour.roi.ROI3DRectangle; +import plugins.adufour.vars.lang.VarDoubleArrayNative; +import plugins.adufour.vars.lang.VarROIArray; +import plugins.adufour.vars.util.VarException; + +public class Create3DRectangleROI extends Plugin implements ROIBlock +{ + VarDoubleArrayNative xCenter = new VarDoubleArrayNative("Centers (X)", null); + + VarDoubleArrayNative yCenter = new VarDoubleArrayNative("Centers (Y)", null); + + VarDoubleArrayNative zCenter = new VarDoubleArrayNative("Centers (Z)", null); + + VarDoubleArrayNative xSize = new VarDoubleArrayNative("Width(s)", null); + + VarDoubleArrayNative ySize = new VarDoubleArrayNative("Height(s)", null); + + VarDoubleArrayNative zSize = new VarDoubleArrayNative("Depth(s)", null); + + VarROIArray roi = new VarROIArray("List of ROI"); + + @Override + public void declareInput(VarList inputMap) + { + inputMap.add("center (X)", xCenter); + inputMap.add("center (Y)", yCenter); + inputMap.add("center (Z)", zCenter); + inputMap.add("sizes (X)", xSize); + inputMap.add("sizes (Y)", ySize); + inputMap.add("sizes (Z)", zSize); + } + + @Override + public void declareOutput(VarList outputMap) + { + outputMap.add(roi); + } + + @Override + public void run() + { + int n = xCenter.size(); + if (n != yCenter.size() || n != zCenter.size()) throw new VarException("[Create 3D Rectangle ROI] The lists of centers don't have the same number of elements"); + + int nSize = xSize.size(); + if (nSize != ySize.size() || nSize != zSize.size()) throw new VarException("[Create 3D Rectangle ROI] The lists of sizes don't have the same number of elements"); + + if (nSize != 1 && nSize != n) throw new VarException("[Create 3D Rectangle ROI] The number of sizes must be equal to 1 or the number of centers"); + + for (int i = 0; i < n; i++) + { + // get the dimensions + double sizeX, sizeY, sizeZ; + + if (nSize == 1) + { + sizeX = xSize.getValue()[0]; + sizeY = ySize.getValue()[0]; + sizeZ = zSize.getValue()[0]; + } + else + { + sizeX = xSize.getValue()[i]; + sizeY = ySize.getValue()[i]; + sizeZ = zSize.getValue()[i]; + } + + // create the ROI + + double minX = xCenter.getValue()[i] - sizeX / 2; + double minY = yCenter.getValue()[i] - sizeY / 2; + double minZ = zCenter.getValue()[i] - sizeZ / 2; + + roi.add(new ROI3DRectangle(new Point3D.Double(minX, minY, minZ), new Point3D.Double(sizeX, sizeY, sizeZ))); + } + } +} diff --git a/metroloSPIM/src/plugins/adufour/metrolospim/CreatedScaledRectangleROI.java b/metroloSPIM/src/plugins/adufour/metrolospim/CreatedScaledRectangleROI.java new file mode 100644 index 0000000000000000000000000000000000000000..7a089cfadd68cc4b603a0fa536efc334bbdc4c9d --- /dev/null +++ b/metroloSPIM/src/plugins/adufour/metrolospim/CreatedScaledRectangleROI.java @@ -0,0 +1,84 @@ +package plugins.adufour.metrolospim; + +import icy.plugin.abstract_.Plugin; +import icy.roi.ROI; +import icy.roi.ROI2D; +import icy.roi.ROI3D; +import icy.type.point.Point3D; +import icy.type.rectangle.Rectangle5D; + +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import plugins.adufour.blocks.tools.roi.ROIBlock; +import plugins.adufour.blocks.util.VarList; +import plugins.adufour.roi.ROI3DRectangle; +import plugins.adufour.vars.lang.VarDouble; +import plugins.adufour.vars.lang.VarROIArray; +import plugins.kernel.roi.roi2d.ROI2DRectangle; +import plugins.kernel.roi.roi3d.ROI3DStack; + +public class CreatedScaledRectangleROI extends Plugin implements ROIBlock +{ + VarROIArray inROI = new VarROIArray("list of ROI"); + VarDouble scaleFactor = new VarDouble("scale", 2); + VarROIArray rescaledROI = new VarROIArray("list of rescaled ROI"); + + @Override + public void declareInput(VarList inputMap) + { + inputMap.add("input ROI", inROI); + inputMap.add("scale factor", scaleFactor); + } + + @Override + public void declareOutput(VarList outputMap) + { + outputMap.add("output ROI", rescaledROI); + } + + @SuppressWarnings("unchecked") + @Override + public void run() + { + double scale = scaleFactor.getValue(); + + for (ROI roi : inROI.getValue(true)) + { + if (roi instanceof ROI2D) + { + Rectangle2D r = ((ROI2D) roi).getBounds2D(); + Point2D.Double topLeft = new Point2D.Double(r.getMinX() * scale, r.getMinY() * scale); + Point2D.Double bottomRight = new Point2D.Double(r.getMaxX() * scale, r.getMaxY() * scale); + ROI2DRectangle rect = new ROI2DRectangle(topLeft, bottomRight); + rescaledROI.add(rect); + } + if (roi instanceof ROI3D) + { + Rectangle5D r5 = roi.getBounds5D(); + + if (roi instanceof ROI3DStack) + { + // recompute bounds (and headshoot Stephane) + boolean firstSlice = true; + for (ROI2D slice : (ROI3DStack<ROI2D>) roi) + { + if (firstSlice) + { + r5 = slice.computeBounds5D(); + firstSlice = false; + } + else r5.add(slice.getBounds5D()); + } + } + + Point3D.Double topLeftUp = new Point3D.Double(r5.getX() * scale, r5.getY() * scale, r5.getZ() * scale); + Point3D.Double bottomRightDown = new Point3D.Double(r5.getSizeX() * scale, r5.getSizeY() * scale, r5.getSizeZ() * scale); + ROI3DRectangle rect = new ROI3DRectangle(topLeftUp, bottomRightDown); + rescaledROI.add(rect); + } + else throw new UnsupportedOperationException("Warning: ROI of type " + roi.getClassName() + " are not currently supported"); + } + } + +} diff --git a/metroloSPIM/src/plugins/adufour/metrolospim/ExtractEquator.java b/metroloSPIM/src/plugins/adufour/metrolospim/ExtractEquator.java new file mode 100644 index 0000000000000000000000000000000000000000..fa3006e6e1679c510b888506d668c1eaee393fbc --- /dev/null +++ b/metroloSPIM/src/plugins/adufour/metrolospim/ExtractEquator.java @@ -0,0 +1,51 @@ +package plugins.adufour.metrolospim; + +import icy.plugin.abstract_.Plugin; +import icy.sequence.Sequence; +import icy.sequence.SequenceUtil; + +import java.awt.Rectangle; + +import plugins.adufour.blocks.lang.Block; +import plugins.adufour.blocks.util.VarList; +import plugins.adufour.vars.gui.model.IntegerRangeModel; +import plugins.adufour.vars.lang.VarInteger; +import plugins.adufour.vars.lang.VarSequence; +import plugins.kernel.roi.roi2d.ROI2DRectangle; + +public class ExtractEquator extends Plugin implements Block +{ + VarSequence seq = new VarSequence("input", null); + VarInteger thickness = new VarInteger("thickness (% of total height)", 20); + VarSequence equator = new VarSequence("equator", null); + + @Override + public void run() + { + Sequence in = seq.getValue(true); + + int newHeight = (int) (in.getHeight() / 100.0 * thickness.getValue()); + + int centerY = in.getSizeY() / 2; + int newY = centerY - newHeight / 2; + + ROI2DRectangle rectangle = new ROI2DRectangle(new Rectangle(0, newY, in.getSizeX(), newHeight)); + + equator.setValue(SequenceUtil.getSubSequence(in, rectangle)); + } + + @Override + public void declareInput(VarList inputMap) + { + inputMap.add("input sequence", seq); + thickness.setDefaultEditorModel(new IntegerRangeModel(20, 1, 100, 1)); + inputMap.add("thickness (% of height)", thickness); + } + + @Override + public void declareOutput(VarList outputMap) + { + outputMap.add("output equator", equator); + } + +} diff --git a/metroloSPIM/src/plugins/adufour/metrolospim/FitCircle.java b/metroloSPIM/src/plugins/adufour/metrolospim/FitCircle.java new file mode 100644 index 0000000000000000000000000000000000000000..3f09dbd8fa1d6f38abd9090f80616c50fdaa2b39 --- /dev/null +++ b/metroloSPIM/src/plugins/adufour/metrolospim/FitCircle.java @@ -0,0 +1,71 @@ +package plugins.adufour.metrolospim; + +import icy.plugin.abstract_.Plugin; +import icy.roi.ROI; +import icy.roi.ROI2D; + +import java.awt.Point; +import java.util.Arrays; + +import plugins.adufour.blocks.lang.Block; +import plugins.adufour.blocks.util.VarList; +import plugins.adufour.vars.lang.VarROIArray; +import plugins.kernel.roi.roi2d.ROI2DArea; +import plugins.kernel.roi.roi2d.ROI2DEllipse; +import plugins.kernel.roi.roi2d.ROI2DShape; + +/** + * @author Alexandre Dufour + */ +public class FitCircle extends Plugin implements Block +{ + VarROIArray roiArray = new VarROIArray("List of ROI"); + VarROIArray roiOUT = new VarROIArray("List of circles"); + + /** + * @see java.lang.Runnable#run() + */ + @Override + public void run() + { + for (ROI roi : roiArray.getValue()) + { + if (roi instanceof ROI2D) + { + ROI2DEllipse circle = new ROI2DEllipse(); + + if (roi instanceof ROI2DArea) + { + ROI2DArea area = (ROI2DArea) roi; + Point[] points = area.getBooleanMask(true).getContourPoints(); + circle.setToFitCircle(Arrays.asList(points)); + } + else if (roi instanceof ROI2DShape) + { + ROI2DShape shape = (ROI2DShape) roi; + circle.setToFitCircle(shape.getPoints()); + } + + roiOUT.add(circle); + } + } + } + + /** + * @see plugins.adufour.blocks.lang.Block#declareInput(plugins.adufour.blocks.util.VarList) + */ + @Override + public void declareInput(VarList inputMap) + { + inputMap.add("input ROI array", roiArray); + } + + /** + * @see plugins.adufour.blocks.lang.Block#declareOutput(plugins.adufour.blocks.util.VarList) + */ + @Override + public void declareOutput(VarList outputMap) + { + outputMap.add("output ROI array", roiOUT); + } +} diff --git a/metroloSPIM/src/plugins/adufour/metrolospim/GetROIMassCenter.java b/metroloSPIM/src/plugins/adufour/metrolospim/GetROIMassCenter.java new file mode 100644 index 0000000000000000000000000000000000000000..83a0be6479ea334401f11985a3399a26f095e195 --- /dev/null +++ b/metroloSPIM/src/plugins/adufour/metrolospim/GetROIMassCenter.java @@ -0,0 +1,74 @@ +package plugins.adufour.metrolospim; + +import icy.plugin.abstract_.Plugin; +import icy.roi.ROI; +import icy.roi.ROI2D; +import icy.type.rectangle.Rectangle5D; +import plugins.adufour.blocks.tools.roi.ROIBlock; +import plugins.adufour.blocks.util.VarList; +import plugins.adufour.vars.lang.VarDoubleArrayNative; +import plugins.adufour.vars.lang.VarROIArray; +import plugins.kernel.roi.roi3d.ROI3DStack; + +public class GetROIMassCenter extends Plugin implements ROIBlock +{ + VarROIArray roiArray = new VarROIArray("List of ROI"); + + VarDoubleArrayNative xCenter = new VarDoubleArrayNative("Centers (X)", null); + + VarDoubleArrayNative yCenter = new VarDoubleArrayNative("Centers (Y)", null); + + VarDoubleArrayNative zCenter = new VarDoubleArrayNative("Centers (Z)", null); + + @Override + public void declareInput(VarList inputMap) + { + inputMap.add("inputROI", roiArray); + } + + @Override + public void declareOutput(VarList outputMap) + { + outputMap.add("center (X)", xCenter); + outputMap.add("center (Y)", yCenter); + outputMap.add("center (Z)", zCenter); + } + + @SuppressWarnings("unchecked") + @Override + public void run() + { + int length = roiArray.size(); + + xCenter.setValue(new double[length]); + yCenter.setValue(new double[length]); + zCenter.setValue(new double[length]); + + int cpt = -1; + for (ROI roi : roiArray.getValue()) + { + cpt++; + + Rectangle5D r5 = roi.computeBounds5D(); + + if (roi instanceof ROI3DStack) + { + boolean firstSlice = true; + + for (ROI2D slice : (ROI3DStack<ROI2D>) roi) + { + if (firstSlice) + { + r5 = slice.computeBounds5D(); + firstSlice = false; + } + else r5.add(slice.getBounds5D()); + } + } + + xCenter.getValue()[cpt] = r5.getCenterX(); + yCenter.getValue()[cpt] = r5.getCenterY(); + zCenter.getValue()[cpt] = r5.getCenterZ(); + } + } +} diff --git a/metroloSPIM/src/plugins/adufour/metrolospim/MetroloSPIM.java b/metroloSPIM/src/plugins/adufour/metrolospim/MetroloSPIM.java new file mode 100644 index 0000000000000000000000000000000000000000..2291647e7d791ef927cd6b03a873fdcf7e89aab4 --- /dev/null +++ b/metroloSPIM/src/plugins/adufour/metrolospim/MetroloSPIM.java @@ -0,0 +1,9 @@ +package plugins.adufour.metrolospim; + +import icy.plugin.abstract_.Plugin; +import icy.plugin.interface_.PluginLibrary; + +public class MetroloSPIM extends Plugin implements PluginLibrary +{ + +} diff --git a/metroloSPIM/src/plugins/adufour/metrolospim/OrthogonalRotation.java b/metroloSPIM/src/plugins/adufour/metrolospim/OrthogonalRotation.java new file mode 100644 index 0000000000000000000000000000000000000000..0e1abae19e80cbc05657213420e070ab00755450 --- /dev/null +++ b/metroloSPIM/src/plugins/adufour/metrolospim/OrthogonalRotation.java @@ -0,0 +1,173 @@ +package plugins.adufour.metrolospim; + +import icy.image.IcyBufferedImage; +import icy.plugin.abstract_.Plugin; +import icy.sequence.Sequence; +import icy.type.DataType; + +import java.lang.reflect.Array; + +import plugins.adufour.blocks.tools.sequence.SequenceBlock; +import plugins.adufour.blocks.util.VarList; +import plugins.adufour.vars.lang.VarEnum; +import plugins.adufour.vars.lang.VarSequence; + +public class OrthogonalRotation extends Plugin implements SequenceBlock +{ + public enum Orientation + { + X_becomes_Y, Y_becomes_X, X_becomes_Z, Y_becomes_Z, Z_becomes_X, Z_becomes_Y + } + + VarSequence input = new VarSequence("Sequence", null); + + VarEnum<Orientation> orientation = new VarEnum<OrthogonalRotation.Orientation>("Orienation", Orientation.Z_becomes_Y); + + VarSequence output = new VarSequence("Rotated sequence", null); + + @Override + public void declareInput(VarList inputMap) + { + inputMap.add("input sequence", input); + inputMap.add("orientation", orientation); + } + + @Override + public void declareOutput(VarList outputMap) + { + outputMap.add("output sequence", output); + } + + @Override + public void run() + { + Sequence in = input.getValue(true); + Orientation or = orientation.getValue(true); + Sequence out = null; + + int sizeX = in.getSizeX(); + int sizeY = in.getSizeY(); + int sizeXY = sizeX * sizeY; + int sizeZ = in.getSizeZ(); + int sizeC = in.getSizeC(); + int sizeT = in.getSizeT(); + DataType dataType = in.getDataType_(); + + int startOffset = 0; + int sign = 1; + + switch (or) + { + case X_becomes_Y: + case Y_becomes_X: + + startOffset = (or == Orientation.X_becomes_Y ? sizeXY - sizeY : sizeY - 1); + sign = (or == Orientation.X_becomes_Y ? 1 : -1); + + // out has inverted XY dimensions + out = new Sequence(); + for (int t = 0; t < sizeT; t++) + for (int z = 0; z < sizeZ; z++) + out.setImage(t, z, new IcyBufferedImage(sizeY, sizeX, sizeC, dataType)); + + for (int t = 0; t < sizeT; t++) + for (int c = 0; c < sizeC; c++) + for (int z = 0; z < sizeZ; z++) + { + final Object in_XY = in.getDataXY(t, z, c); + final Object out_XY = out.getDataXY(t, z, c); + + // browse each line of the input and store in the output accordingly + + for (int j = 0; j < sizeY; j++) + { + int inOffset = j * sizeX; + int outOffset = startOffset + j * sign; + + for (int i = 0; i < sizeX; i++, inOffset++, outOffset -= sizeY * sign) + { + Array.set(out_XY, outOffset, Array.get(in_XY, inOffset)); + } + } + } + break; + + case X_becomes_Z: + case Z_becomes_X: + + startOffset = (or == Orientation.X_becomes_Z ? sizeZ - 1 : 0); + sign = (or == Orientation.X_becomes_Z ? -1 : 1); + + // out has inverted XZ dimensions + out = new Sequence(); + for (int t = 0; t < sizeT; t++) + for (int x = 0; x < sizeX; x++) + out.setImage(t, x, new IcyBufferedImage(sizeZ, sizeY, sizeC, dataType)); + + for (int t = 0; t < sizeT; t++) + for (int c = 0; c < sizeC; c++) + { + final Object out_Z_XY = out.getDataXYZ(t, c); + + for (int z = 0; z < sizeZ; z++) + { + final Object in_XY = in.getDataXY(t, z, c); + + // browse each line of the input and store in the output accordingly + + for (int j = 0; j < sizeY; j++) + { + int inOffset = j * sizeX; + int outOffset = startOffset + j * sizeZ + z * sign; + + for (int i = 0; i < sizeX; i++, inOffset++) + { + Object outSlice = Array.get(out_Z_XY, i); + Array.set(outSlice, outOffset, Array.get(in_XY, inOffset)); + } + } + } + } + break; + + case Y_becomes_Z: + case Z_becomes_Y: + + startOffset = (or == Orientation.Z_becomes_Y ? 0 : sizeY - 1); + sign = (or == Orientation.Z_becomes_Y ? 1 : -1); + + // out has inverted YZ dimensions + out = new Sequence(); + for (int t = 0; t < sizeT; t++) + for (int y = 0; y < sizeY; y++) + out.setImage(t, y, new IcyBufferedImage(sizeX, sizeZ, sizeC, dataType)); + + for (int t = 0; t < sizeT; t++) + for (int c = 0; c < sizeC; c++) + { + final Object out_Z_XY = out.getDataXYZ(t, c); + + for (int z = 0; z < sizeZ; z++) + { + final Object in_XY = in.getDataXY(t, z, c); + + int outOffset = (sizeZ - z - 1) * sizeX; + + // browse each line of the input and store in the output accordingly + for (int j = 0; j < sizeY; j++) + { + int inOffset = j * sizeX; + Object outSlice = Array.get(out_Z_XY, startOffset + j * sign); + + System.arraycopy(in_XY, inOffset, outSlice, outOffset, sizeX); + } + } + } + + break; + } + + out.dataChanged(); + output.setValue(out); + } +} diff --git a/metroloSPIM/src/plugins/adufour/metrolospim/ROI2DLineProfile.java b/metroloSPIM/src/plugins/adufour/metrolospim/ROI2DLineProfile.java new file mode 100644 index 0000000000000000000000000000000000000000..9a371314565cc59bf59f3ed43bcb949719af2272 --- /dev/null +++ b/metroloSPIM/src/plugins/adufour/metrolospim/ROI2DLineProfile.java @@ -0,0 +1,47 @@ +package plugins.adufour.metrolospim; + +import icy.image.IcyBufferedImage; +import icy.plugin.abstract_.Plugin; +import icy.type.collection.array.Array1DUtil; + +import java.awt.geom.Point2D; + +public class ROI2DLineProfile extends Plugin +{ + public static double[][] getSegmentProfile(Point2D p1, Point2D p2, IcyBufferedImage image) + { + int distance = (int) p1.distance(p2); + + double vx = (p2.getX() - p1.getX()) / distance; + double vy = (p2.getY() - p1.getY()) / distance; + + int nbComponent = image.getSizeC(); + double[][] data = new double[nbComponent][distance]; + + double x = p1.getX(); + double y = p1.getY(); + + for (int i = 0; i < distance; i++) + { + if (image.isInside((int) x, (int) y)) + { + for (int component = 0; component < nbComponent; component++) + { + data[component][i] = Array1DUtil.getValue(image.getDataXY(component), image.getOffset((int) x, (int) y), image.isSignedDataType()); + } + } + else + { + for (int component = 0; component < nbComponent; component++) + { + data[component][i] = 0.0D; + } + } + + x += vx; + y += vy; + } + + return data; + } +} diff --git a/metroloSPIM/src/plugins/adufour/metrolospim/RescaleSequence.java b/metroloSPIM/src/plugins/adufour/metrolospim/RescaleSequence.java new file mode 100644 index 0000000000000000000000000000000000000000..4a1d56187eefd8c4de3b563f8b0bcfdbad054561 --- /dev/null +++ b/metroloSPIM/src/plugins/adufour/metrolospim/RescaleSequence.java @@ -0,0 +1,158 @@ +package plugins.adufour.metrolospim; + +import icy.image.IcyBufferedImage; +import icy.image.IcyBufferedImageUtil; +import icy.image.IcyBufferedImageUtil.FilterType; +import icy.plugin.abstract_.Plugin; +import icy.sequence.Sequence; +import icy.system.SystemUtil; +import icy.type.DataType; +import icy.type.collection.array.Array1DUtil; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import plugins.adufour.blocks.tools.sequence.SequenceBlock; +import plugins.adufour.blocks.util.VarList; +import plugins.adufour.vars.gui.model.DoubleRangeModel; +import plugins.adufour.vars.lang.VarDouble; +import plugins.adufour.vars.lang.VarSequence; + +public class RescaleSequence extends Plugin implements SequenceBlock +{ + VarSequence varSeq = new VarSequence("Sequence", null); + VarDouble varScale = new VarDouble("Scale factor", 0.5); + + VarSequence varSeqRescaled = new VarSequence("Rescaled sequence", null); + + @Override + public void run() + { + Sequence in = varSeq.getValue(true); + final Sequence out = new Sequence("Rescaled " + in.getName()); + + final int newWidth = (int) (in.getSizeX() * varScale.getValue()); + final int newHeight = (int) (in.getSizeY() * varScale.getValue()); + final int newDepth = (int) (in.getSizeZ() * varScale.getValue()); + + final double scale = varScale.getValue(); + + final boolean downScale = (scale < 1.0); + + final double gridStep = 1 / scale; + + final int sizeT = in.getSizeT(); + final int sizeZ = in.getSizeZ(); + final int sizeC = in.getSizeC(); + final int sizeX = in.getSizeX(); + final DataType dataType = in.getDataType_(); + + if (downScale) + { + for (int t = 0; t < sizeT; t++) + for (int z = 0; z < newDepth; z++) + { + out.setImage(t, z, new IcyBufferedImage(newWidth, newHeight, sizeC, dataType)); + } + } + + ExecutorService service = Executors.newFixedThreadPool(SystemUtil.getAvailableProcessors()); + + ArrayList<Callable<Object>> tasks = new ArrayList<Callable<Object>>(sizeZ * sizeT); + + for (int t = 0; t < sizeT; t++) + { + for (int k = 0; k < newDepth; k++) + { + int slice = (int) (k * gridStep); + + if (downScale) + { + // optimize the process manually + + final Object _in = in.getDataXYC(t, slice); + final Object _out = out.getDataXYC(t, k); + + tasks.add(new Callable<Object>() + { + @Override + public Object call() + { + for (int c = 0; c < sizeC; c++) + { + Object _inXY = Array.get(_in, c); + Object _outXY = Array.get(_out, c); + double y = gridStep * 0.5; + + int off = 0; + for (int j = 0; j < newHeight; j++) + { + double x = gridStep * 0.5; + + for (int i = 0; i < newWidth; i++, off++) + { + double value = Array1DUtil.getValue(_inXY, (int) (x + y * sizeX), dataType); + Array1DUtil.setValue(_outXY, off, dataType, value); + x += gridStep; + + } + + y += gridStep; + } + } + return null; + } + }); + } + else + { + final IcyBufferedImage inSlice = in.getImage(t, slice); + final int outT = t; + final int outZ = k; + + tasks.add(new Callable<Object>() + { + @Override + public Object call() + { + out.setImage(outT, outZ, IcyBufferedImageUtil.scale(inSlice, newWidth, newHeight, FilterType.NEAREST)); + return null; + } + }); + } + } + } + + try + { + service.invokeAll(tasks); + } + catch (InterruptedException e) + { + } + finally + { + service.shutdownNow(); + } + + varSeqRescaled.setValue(out); + } + + @Override + public void declareInput(VarList inputMap) + { + inputMap.add("input sequence", varSeq); + varScale.setDefaultEditorModel(new DoubleRangeModel(0.5, 0.001, 1000.0, 0.001)); + inputMap.add("scale factor", varScale); + } + + @Override + public void declareOutput(VarList outputMap) + { + outputMap.add("output sequence", varSeqRescaled); + } + +} diff --git a/metroloSPIM/src/plugins/adufour/metrolospim/Sum.java b/metroloSPIM/src/plugins/adufour/metrolospim/Sum.java new file mode 100644 index 0000000000000000000000000000000000000000..a29aa5767fbc89c7692513a1ad4161d7813983b1 --- /dev/null +++ b/metroloSPIM/src/plugins/adufour/metrolospim/Sum.java @@ -0,0 +1,42 @@ +package plugins.adufour.metrolospim; + +import icy.plugin.abstract_.Plugin; +import icy.sequence.SequenceDataIterator; +import plugins.adufour.blocks.lang.Block; +import plugins.adufour.blocks.util.VarList; +import plugins.adufour.vars.lang.VarDouble; +import plugins.adufour.vars.lang.VarSequence; + +public class Sum extends Plugin implements Block +{ + VarSequence seq = new VarSequence("sequence", null); + VarDouble sum = new VarDouble("sum", 0); + + @Override + public void declareInput(VarList inputMap) + { + inputMap.add(seq); + } + + @Override + public void declareOutput(VarList outputMap) + { + outputMap.add(sum); + } + + @Override + public void run() + { + double d = 0; + + SequenceDataIterator it = new SequenceDataIterator(seq.getValue(true)); + while (!it.done()) + { + d += it.get(); + it.next(); + } + + sum.setValue(d); + } + +} diff --git a/metroloSPIM/src/plugins/adufour/roi/ROI3DRectangle.java b/metroloSPIM/src/plugins/adufour/roi/ROI3DRectangle.java new file mode 100644 index 0000000000000000000000000000000000000000..40c6233259719f07df5c1b6693881f0ee1d3a34c --- /dev/null +++ b/metroloSPIM/src/plugins/adufour/roi/ROI3DRectangle.java @@ -0,0 +1,128 @@ +package plugins.adufour.roi; + +import icy.canvas.Canvas2D; +import icy.canvas.IcyCanvas; +import icy.roi.ROI3D; +import icy.sequence.Sequence; +import icy.type.point.Point3D; +import icy.type.rectangle.Rectangle3D; + +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; + +import plugins.kernel.roi.roi2d.ROI2DRectangle; + +public class ROI3DRectangle extends ROI3D +{ + private final Rectangle3D bounds; + + private final ROI2DRectangle rectangleROI = new ROI2DRectangle(); + + public ROI3DRectangle() + { + bounds = new Rectangle3D.Double(0, 0, 0, 0, 0, 0); + } + + public ROI3DRectangle(Point3D topLeftUp, Point3D bottomRightDown) + { + this(new Rectangle3D.Double(topLeftUp.getX(), topLeftUp.getY(), topLeftUp.getZ(), bottomRightDown.getX(), bottomRightDown.getY(), bottomRightDown.getZ())); + } + + public ROI3DRectangle(Rectangle3D bounds) + { + this.bounds = bounds; + roiChanged(); + } + + /** + * @return a copy of the bounds of this ROI + */ + @Override + public Rectangle3D computeBounds3D() + { + return new Rectangle3D.Double(bounds.getX(), bounds.getY(), bounds.getZ(), bounds.getSizeX(), bounds.getSizeY(), bounds.getSizeZ()); + } + + @Override + protected ROIPainter createPainter() + { + return new ROI3DRectanglePainter(); + } + + @Override + public boolean contains(double x, double y, double z) + { + return bounds.contains(x, y, z); + } + + @Override + public boolean contains(double x, double y, double z, double sizeX, double sizeY, double sizeZ) + { + return bounds.contains(x, y, z, sizeX, sizeY, sizeZ); + } + + @Override + public boolean hasSelectedPoint() + { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean intersects(double x, double y, double z, double sizeX, double sizeY, double sizeZ) + { + return bounds.intersects(x, y, z, sizeX, sizeY, sizeZ); + } + + @Override + public double getPerimeter() + { + return bounds.getSizeX() * bounds.getSizeY() * 2 + bounds.getSizeX() * bounds.getSizeZ() * 2 + bounds.getSizeY() * bounds.getSizeZ() * 2; + } + + @Override + public double getVolume() + { + return bounds.getSizeX() * bounds.getSizeY() * bounds.getSizeZ(); + } + + @Override + public void roiChanged() + { + super.roiChanged(); + rectangleROI.setBounds2D(new Rectangle2D.Double(bounds.getX(), bounds.getY(), bounds.getSizeX(), bounds.getSizeY())); + rectangleROI.setZ((int) bounds.getZ()); + } + + public class ROI3DRectanglePainter extends ROIPainter + { + @Override + public void paint(Graphics2D g, Sequence sequence, IcyCanvas canvas) + { + super.paint(g, sequence, canvas); + + if (canvas instanceof Canvas2D) + { + ROIPainter overlay = rectangleROI.getOverlay(); +// if (!overlay.isAttached(sequence)) overlay. + + int z = canvas.getPositionZ(); + + if (z >= bounds.getZ() && z < bounds.getZ() + bounds.getSizeZ()) + { + rectangleROI.setZ(z); + overlay.paint(g, sequence, canvas); + } + } + else if (canvas.getClass().getSimpleName().equalsIgnoreCase("OrthoCanvas")) + { + + } + else + { +// rectangleROI.getPainter().detachFrom(sequence); + System.err.println("Unsupported canvas: " + canvas.getClass().getSimpleName()); + } + } + } +}