001package plugins.kernel.roi.descriptor.measure;
002
003import icy.plugin.abstract_.Plugin;
004import icy.plugin.interface_.PluginROIDescriptor;
005import icy.roi.ROI;
006import icy.roi.ROIDescriptor;
007import icy.sequence.Sequence;
008import icy.type.rectangle.Rectangle5D;
009
010import java.util.ArrayList;
011import java.util.HashMap;
012import java.util.List;
013import java.util.Map;
014
015/**
016 * This {@link PluginROIDescriptor} implements the following basic measures ROI descriptors:<br/>
017 * <li>Contour (in pixel)</li><br/>
018 * <li>Interior (in pixel)</li><br/>
019 * <li>Perimeter (pixel size unit - 2D ROI only)</li><br/>
020 * <li>Surface Area (pixel size unit - 3D ROI only)</li><br/>
021 * <li>Area (pixel size unit - 2D ROI only)</li><br/>
022 * <li>Volume (pixel size unit - 3D ROI only)</li><br/>
023 * 
024 * @author Stephane
025 */
026public class ROIBasicMeasureDescriptorsPlugin extends Plugin implements PluginROIDescriptor
027{
028    public static final String ID_CONTOUR = ROIContourDescriptor.ID;
029    public static final String ID_INTERIOR = ROIInteriorDescriptor.ID;
030    public static final String ID_PERIMETER = ROIPerimeterDescriptor.ID;
031    public static final String ID_AREA = ROIAreaDescriptor.ID;
032    public static final String ID_SURFACE_AREA = ROISurfaceAreaDescriptor.ID;
033    public static final String ID_VOLUME = ROIVolumeDescriptor.ID;
034
035    public static final ROIContourDescriptor contourDescriptor = new ROIContourDescriptor();
036    public static final ROIInteriorDescriptor interiorDescriptor = new ROIInteriorDescriptor();
037    public static final ROIPerimeterDescriptor perimeterDescriptor = new ROIPerimeterDescriptor();
038    public static final ROIAreaDescriptor areaDescriptor = new ROIAreaDescriptor();
039    public static final ROISurfaceAreaDescriptor surfaceAreaDescriptor = new ROISurfaceAreaDescriptor();
040    public static final ROIVolumeDescriptor volumeDescriptor = new ROIVolumeDescriptor();
041
042    /**
043     * Calculate the multiplier factor depending the wanted dimension information.
044     */
045    public static double getMultiplierFactor(Sequence sequence, ROI roi, int dim)
046    {
047        final int dimRoi = roi.getDimension();
048
049        // cannot give this information for this roi
050        if (dimRoi > dim)
051            return 0d;
052
053        final Rectangle5D boundsRoi = roi.getBounds5D();
054        double mul = 1d;
055
056        switch (dim)
057        {
058            case 5:
059                if (dimRoi == 4)
060                {
061                    final int sizeC = sequence.getSizeC();
062
063                    if ((boundsRoi.getSizeC() == Double.POSITIVE_INFINITY) && (sizeC > 1))
064                        mul *= sizeC;
065                    // cannot give this information for this roi
066                    else
067                        mul = 0d;
068                }
069            case 4:
070                if (dimRoi == 3)
071                {
072                    final int sizeT = sequence.getSizeT();
073
074                    if ((boundsRoi.getSizeT() == Double.POSITIVE_INFINITY) && (sizeT > 1))
075                        mul *= sizeT;
076                    // cannot give this information for this roi
077                    else
078                        mul = 0d;
079                }
080            case 3:
081                if (dimRoi == 2)
082                {
083                    final int sizeZ = sequence.getSizeZ();
084
085                    if ((boundsRoi.getSizeZ() == Double.POSITIVE_INFINITY) && (sizeZ > 1))
086                        mul *= sizeZ;
087                    // cannot give this information for this roi
088                    else
089                        mul = 0d;
090                }
091            case 2:
092                if (dimRoi == 1)
093                {
094                    final int sizeY = sequence.getSizeY();
095
096                    if ((boundsRoi.getSizeY() == Double.POSITIVE_INFINITY) && (sizeY > 1))
097                        mul *= sizeY;
098                    // cannot give this information for this roi
099                    else
100                        mul = 0d;
101                }
102        }
103
104        return mul;
105    }
106
107    @Override
108    public List<ROIDescriptor> getDescriptors()
109    {
110        final List<ROIDescriptor> result = new ArrayList<ROIDescriptor>();
111
112        result.add(contourDescriptor);
113        result.add(interiorDescriptor);
114        result.add(perimeterDescriptor);
115        result.add(areaDescriptor);
116        result.add(surfaceAreaDescriptor);
117        result.add(volumeDescriptor);
118
119        return result;
120    }
121
122    @Override
123    public Map<ROIDescriptor, Object> compute(ROI roi, Sequence sequence) throws UnsupportedOperationException
124    {
125        final Map<ROIDescriptor, Object> result = new HashMap<ROIDescriptor, Object>();
126
127        // use the contour and interior to compute others descriptors
128        final double contour = ROIContourDescriptor.computeContour(roi);
129        final double interior = ROIInteriorDescriptor.computeInterior(roi);
130
131        result.put(contourDescriptor, Double.valueOf(contour));
132        result.put(interiorDescriptor, Double.valueOf(interior));
133
134        int notComputed = 0;
135
136        try
137        {
138            result.put(perimeterDescriptor, Double.valueOf(ROIPerimeterDescriptor.computePerimeter(roi, sequence)));
139        }
140        catch (UnsupportedOperationException e)
141        {
142            result.put(perimeterDescriptor, null);
143            notComputed++;
144        }
145        try
146        {
147            result.put(areaDescriptor, Double.valueOf(ROIAreaDescriptor.computeArea(interior, roi, sequence)));
148        }
149        catch (UnsupportedOperationException e)
150        {
151            result.put(areaDescriptor, null);
152            notComputed++;
153        }
154        try
155        {
156            result.put(surfaceAreaDescriptor,
157                    Double.valueOf(ROISurfaceAreaDescriptor.computeSurfaceArea(roi, sequence)));
158        }
159        catch (UnsupportedOperationException e)
160        {
161            result.put(surfaceAreaDescriptor, null);
162            notComputed++;
163        }
164        try
165        {
166            result.put(volumeDescriptor, Double.valueOf(ROIVolumeDescriptor.computeVolume(interior, roi, sequence)));
167        }
168        catch (UnsupportedOperationException e)
169        {
170            result.put(volumeDescriptor, null);
171            notComputed++;
172        }
173
174        if (notComputed == 4)
175        {
176            throw new UnsupportedOperationException(getClass().getSimpleName()
177                    + ": cannot compute any of the descriptors for '" + roi.getName() + "'");
178        }
179
180        return result;
181    }
182}