001/** 002 * 003 */ 004package plugins.kernel.roi.descriptor.measure; 005 006import icy.math.UnitUtil; 007import icy.math.UnitUtil.UnitPrefix; 008import icy.roi.ROI; 009import icy.roi.ROIDescriptor; 010import icy.sequence.Sequence; 011import icy.sequence.SequenceEvent; 012import icy.sequence.SequenceEvent.SequenceEventSourceType; 013import icy.util.StringUtil; 014 015/** 016 * Perimeter ROI descriptor class (see {@link ROIDescriptor}) 017 * 018 * @author Stephane 019 */ 020public class ROIPerimeterDescriptor extends ROIDescriptor 021{ 022 public static final String ID = "Perimeter"; 023 024 public ROIPerimeterDescriptor() 025 { 026 super(ID, "Perimeter", Double.class); 027 } 028 029 @Override 030 public String getDescription() 031 { 032 return "Perimeter"; 033 } 034 035 @Override 036 public String getUnit(Sequence sequence) 037 { 038 if (sequence != null) 039 return sequence.getBestPixelSizeUnit(2, 1).toString() + "m"; 040 041 return UnitPrefix.MICRO.toString() + "m"; 042 } 043 044 @Override 045 public boolean needRecompute(SequenceEvent change) 046 { 047 final SequenceEventSourceType sourceType = change.getSourceType(); 048 049 if (sourceType == SequenceEventSourceType.SEQUENCE_DATA) 050 return true; 051 if (sourceType == SequenceEventSourceType.SEQUENCE_META) 052 { 053 final String metaName = (String) change.getSource(); 054 055 return StringUtil.isEmpty(metaName) || StringUtil.equals(metaName, Sequence.ID_PIXEL_SIZE_X) 056 || StringUtil.equals(metaName, Sequence.ID_PIXEL_SIZE_Y) 057 || StringUtil.equals(metaName, Sequence.ID_PIXEL_SIZE_Z); 058 } 059 060 return false; 061 } 062 063 @Override 064 public Object compute(ROI roi, Sequence sequence) throws UnsupportedOperationException 065 { 066 return Double.valueOf(computePerimeter(roi, sequence)); 067 } 068 069 /** 070 * Computes and returns the perimeter expressed in the unit of the descriptor (see {@link #getUnit(Sequence)}) for 071 * the specified ROI.<br> 072 * It may thrown an <code>UnsupportedOperationException</code> if the operation is not supported for that ROI. 073 * 074 * @param roi 075 * the ROI on which we want to compute the perimeter 076 * @param sequence 077 * the sequence from which the pixel size can be retrieved 078 * @return the perimeter expressed in the unit of the descriptor (see {@link #getUnit(Sequence)}) 079 * @throws UnsupportedOperationException 080 * if the operation is not supported for this ROI 081 */ 082 public static double computePerimeter(ROI roi, Sequence sequence) throws UnsupportedOperationException 083 { 084 if (sequence == null) 085 throw new UnsupportedOperationException("Cannot compute Perimeter with null Sequence parameter !"); 086 087 final UnitPrefix bestUnit = sequence.getBestPixelSizeUnit(2, 1); 088 final double length = roi.getLength(sequence); 089 090 return UnitUtil.getValueInUnit(length, UnitPrefix.MICRO, bestUnit, 1); 091 } 092 093 // /** 094 // * Computes and returns the perimeter from a given number of contour points expressed in the 095 // * unit of the descriptor (see {@link #getUnit(Sequence)}) for the specified sequence and ROI.<br> 096 // * It may returns <code>Double.Nan</code> if the operation is not supported for that ROI. 097 // * 098 // * @param contourPoints 099 // * the number of contour points (override the ROI value) 100 // * @param roi 101 // * the ROI we want to compute the perimeter 102 // * @param sequence 103 // * the input sequence used to retrieve operation unit by using pixel size 104 // * information. 105 // * @return the perimeter 106 // * @throws UnsupportedOperationException 107 // * if the operation is not supported for this ROI 108 // */ 109 // static double computePerimeter(double contourPoints, ROI roi, Sequence sequence) 110 // throws UnsupportedOperationException 111 // { 112 // return ROIContourDescriptor.computeContour(contourPoints, roi, sequence, 2); 113 // } 114}