001package plugins.kernel.roi.descriptor.measure;
002
003import java.util.ArrayList;
004import java.util.HashMap;
005import java.util.List;
006import java.util.Map;
007
008import icy.plugin.abstract_.Plugin;
009import icy.plugin.interface_.PluginROIDescriptor;
010import icy.roi.ROI;
011import icy.roi.ROIDescriptor;
012import icy.roi.ROIIterator;
013import icy.sequence.Sequence;
014import icy.type.point.Point5D;
015import icy.type.rectangle.Rectangle5D;
016import plugins.kernel.roi.roi2d.ROI2DPoint;
017import plugins.kernel.roi.roi3d.ROI3DPoint;
018
019/**
020 * This {@link PluginROIDescriptor} implements the mass center ROI descriptors:<br/>
021 * <li>Mass center X (in pixel)</li><br/>
022 * <li>Mass center Y (in pixel)</li><br/>
023 * <li>Mass center C (in pixel)</li><br/>
024 * <li>Mass center Z (in pixel)</li><br/>
025 * <li>Mass center T (in pixel)</li>
026 * 
027 * @author Stephane
028 */
029public class ROIMassCenterDescriptorsPlugin extends Plugin implements PluginROIDescriptor
030{
031    public static final String ID_MASS_CENTER_X = ROIMassCenterXDescriptor.ID;
032    public static final String ID_MASS_CENTER_Y = ROIMassCenterYDescriptor.ID;
033    public static final String ID_MASS_CENTER_Z = ROIMassCenterZDescriptor.ID;
034    public static final String ID_MASS_CENTER_T = ROIMassCenterTDescriptor.ID;
035    public static final String ID_MASS_CENTER_C = ROIMassCenterCDescriptor.ID;
036
037    public static final ROIMassCenterXDescriptor massCenterXDescriptor = new ROIMassCenterXDescriptor();
038    public static final ROIMassCenterYDescriptor massCenterYDescriptor = new ROIMassCenterYDescriptor();
039    public static final ROIMassCenterZDescriptor massCenterZDescriptor = new ROIMassCenterZDescriptor();
040    public static final ROIMassCenterTDescriptor massCenterTDescriptor = new ROIMassCenterTDescriptor();
041    public static final ROIMassCenterCDescriptor massCenterCDescriptor = new ROIMassCenterCDescriptor();
042
043    /**
044     * Compute and returns the mass center of specified ROI.
045     */
046    public static Point5D computeMassCenter(ROI roi)
047    {
048        final Rectangle5D bounds = roi.getBounds5D();
049
050        // special case of empty bounds ? --> return position
051        if (bounds.isEmpty())
052            return bounds.getPosition();
053        // special case of single point ? --> return position
054        if ((roi instanceof ROI2DPoint) || (roi instanceof ROI3DPoint))
055            return bounds.getPosition();
056
057        final ROIIterator it = new ROIIterator(roi, true);
058        double x, y, z, t, c;
059        long numPts;
060
061        x = 0d;
062        y = 0d;
063        z = 0d;
064        t = 0d;
065        c = 0d;
066        numPts = 0;
067        while (!it.done())
068        {
069            x += it.getX();
070            y += it.getY();
071            z += it.getZ();
072            t += it.getT();
073            c += it.getC();
074
075            it.next();
076            numPts++;
077        }
078
079        if (numPts == 0)
080            return new Point5D.Double();
081
082        return new Point5D.Double(x / numPts, y / numPts, z / numPts, t / numPts, c / numPts);
083    }
084
085    @Override
086    public List<ROIDescriptor> getDescriptors()
087    {
088        final List<ROIDescriptor> result = new ArrayList<ROIDescriptor>();
089
090        result.add(massCenterXDescriptor);
091        result.add(massCenterYDescriptor);
092        result.add(massCenterZDescriptor);
093        result.add(massCenterTDescriptor);
094        result.add(massCenterCDescriptor);
095
096        return result;
097    }
098
099    @Override
100    public Map<ROIDescriptor, Object> compute(ROI roi, Sequence sequence) throws UnsupportedOperationException
101    {
102        final Map<ROIDescriptor, Object> result = new HashMap<ROIDescriptor, Object>();
103
104        try
105        {
106            // compute mass center descriptors
107            final Point5D massCenter = computeMassCenter(roi);
108
109            result.put(massCenterXDescriptor, Double.valueOf(ROIMassCenterXDescriptor.getMassCenterX(massCenter)));
110            result.put(massCenterYDescriptor, Double.valueOf(ROIMassCenterYDescriptor.getMassCenterY(massCenter)));
111            result.put(massCenterZDescriptor, Double.valueOf(ROIMassCenterZDescriptor.getMassCenterZ(massCenter)));
112            result.put(massCenterTDescriptor, Double.valueOf(ROIMassCenterTDescriptor.getMassCenterT(massCenter)));
113            result.put(massCenterCDescriptor, Double.valueOf(ROIMassCenterCDescriptor.getMassCenterC(massCenter)));
114        }
115        catch (Exception e)
116        {
117            final String mess = getClass().getSimpleName() + ": cannot compute descriptors for '" + roi.getName() + "'";
118            throw new UnsupportedOperationException(mess, e);
119        }
120
121        return result;
122    }
123}