Changeset 7216 for branches


Ignore:
Timestamp:
11/16/10 20:32:10 (10 years ago)
Author:
aivar
Message:

Added logic to calculate nearest two digit values for minimum and maximum. Added color bars. Fixed things in general.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/maven/projects/slim-plugin/src/main/java/loci/slim/analysis/plugins/Display.java

    r7209 r7216  
    3535package loci.slim.analysis.plugins; 
    3636 
    37 import ij.IJ; 
    3837import ij.ImagePlus; 
    39 import ij.gui.GenericDialog; 
    4038import ij.gui.MessageDialog; 
    41 import ij.gui.Roi; 
    42 import ij.plugin.frame.RoiManager; 
    4339import ij.process.ColorProcessor; 
    4440import java.awt.Color; 
    4541 
    46 import java.io.FileWriter; 
    47 import java.io.IOException; 
    48 import java.util.prefs.*; 
     42import java.math.BigDecimal; 
     43import java.math.MathContext; 
     44import java.math.RoundingMode; 
    4945 
    5046import loci.slim.SLIMProcessor.FitFunction; 
     
    5551import loci.slim.colorizer.IColorize; 
    5652 
    57 import mpicbg.imglib.image.Image; 
    58 import mpicbg.imglib.type.numeric.real.DoubleType; 
    59 import mpicbg.imglib.container.planar.PlanarContainerFactory; 
    60 import mpicbg.imglib.cursor.Cursor; 
    6153import mpicbg.imglib.cursor.LocalizableByDimCursor; 
    6254import mpicbg.imglib.image.Image; 
    63 import mpicbg.imglib.image.ImageFactory; 
    6455import mpicbg.imglib.type.numeric.RealType; 
    6556import mpicbg.imglib.type.numeric.real.DoubleType; 
     
    7364public class Display implements ISLIMAnalyzer { 
    7465    private static final Character TAU = 'T'; //TODO IJ doesn't handle Unicode, was: = '\u03c4'; 
     66    private static final String T = "" + TAU; 
    7567    private static final String T1 = "" + TAU + '1'; 
    7668    private static final String T2 = "" + TAU + '2'; 
     
    8274    private static final String T2_T3 = "" + TAU + "2/" + TAU + '3'; 
    8375    private static final String T3_T2 = "" + TAU + "3/" + TAU + '2'; 
     76    private static final String A = "A"; 
    8477    private static final String A1 = "A1"; 
    8578    private static final String A2 = "A2"; 
     
    9386    private static final String C = "C"; 
    9487 
    95     private static int TOP_OFFSET = 20; 
    96     private static int SIDE_OFFSET = 10; 
    97     private static int BOTTOM_OFFSET = 20; 
    98     private static int TEXT_OFFSET = 10; 
     88    private static final boolean MIN = true; 
     89    private static final boolean MAX = false; 
     90 
     91    private static final int TOP_OFFSET = 20; 
     92    private static final int SIDE_OFFSET = 10; 
     93    private static final int BOTTOM_OFFSET = 20; 
     94    private static final int TEXT_OFFSET = 18; 
     95    private static final int BAR_HEIGHT = 3; 
     96 
     97    private Color m_bar[]; 
     98    String m_minText; 
     99    String m_maxText; 
    99100 
    100101    /** 
     
    102103     */ 
    103104    private static enum Formula { 
     105        T_FORMULA(T, 2), 
    104106        T1_FORMULA(T1, 2), 
    105107        T2_FORMULA(T2, 4), 
     
    111113        T2_T3_FORMULA(T2_T3, 4, 6), 
    112114        T3_T2_FORMULA(T3_T2, 6, 4), 
     115        A_FORMULA(A, 1), 
    113116        A1_FORMULA(A1, 1), 
    114117        A2_FORMULA(A2, 3), 
     
    129132 
    130133        /** 
    131          * Simple formula, just use a given parameter. 
     134         * Constructor.  Simple formula, just use a given parameter, specified 
     135         * by index. 
    132136         * 
    133137         * @param index 
     
    140144 
    141145        /** 
    142          * Divisor formula, divide first parameter specified by index by second. 
     146         * Constructor.  Divisor formula, divide first parameter specified by 
     147         * index by second parameter specified by index. 
    143148         * 
    144149         * @param dividendIndex 
     
    152157        } 
    153158 
     159        /** 
     160         * Returns the displayable String name. 
     161         * 
     162         * @return 
     163         */ 
    154164        private String getName() { 
    155165            return m_name; 
    156166        } 
    157167 
     168        /** 
     169         * Returns an array of indices to be used in the formula.  An array 
     170         * of one index specifies a parameter to be used as is.  An array with 
     171         * two indices means the first parameter is divided by the second. 
     172         * 
     173         * @return 
     174         */ 
    158175        private int[] getIndices() { 
    159176            return m_indices; 
     
    161178    } 
    162179 
    163     public Display() { 
    164     } 
    165  
     180    /** 
     181     * Main method of ISLIMAnalyzer. 
     182     * 
     183     * @param image 
     184     * @param region 
     185     * @param function 
     186     */ 
    166187    public void analyze(Image<DoubleType> image, FitRegion region, FitFunction function) { 
    167         boolean combineMinMax = true; 
     188        boolean combineMinMax = true; //false; //TODO needs to be set from UI. 
    168189 
    169190        // is this plugin appropriate for current data? 
     
    173194            return; 
    174195        } 
     196 
     197        // look at image dimensions 
    175198        int dimensions[] = image.getDimensions(); 
     199        //TODO for debugging only 
    176200        for (int i = 0; i < dimensions.length; ++i) { 
    177201            System.out.println("dim " + i + " " + dimensions[i]); 
     
    186210        int params   = dimensions[pIndex]; 
    187211 
     212        // get appropriate formula for image dimensions 
    188213        Formula formulas[] = null; 
    189214        switch (function) { 
    190215            case SINGLE_EXPONENTIAL: 
    191                 formulas = new Formula[] { Formula.A1_FORMULA, Formula.T1_FORMULA, Formula.C_FORMULA }; //TODO these three formulas are just for testing. 
     216                formulas = new Formula[] { Formula.A_FORMULA, Formula.T_FORMULA, Formula.C_FORMULA }; //TODO these three formulas are just for testing. 
    192217                break; 
    193218            case DOUBLE_EXPONENTIAL: 
     
    200225                break; 
    201226        } 
     227 
     228        // build display cells 
    202229        DisplayCell cells[][] = new DisplayCell[channels][formulas.length]; 
    203  
    204230        int cellX = 0, cellY = 0; 
    205231        int cellWidth = width + 2 * SIDE_OFFSET; 
     
    208234            cellY = 0; 
    209235            for (int f = 0; f < formulas.length; ++f) { 
    210                 cells[c][f] = new DisplayCell(formulas[f], cellX, cellY, width, height); 
     236                cells[c][f] = new DisplayCell("" + (c + 1), formulas[f], cellX, cellY, width, height); 
    211237                cellY += cellHeight; 
    212238            } 
     
    216242        int totalHeight = cellY; 
    217243 
    218         int dim[] = new int[4]; 
     244        // traverse the image 
     245        final LocalizableByDimCursor<?> cursor = image.createLocalizableByDimCursor(); 
     246        int dimForCursor[] = new int[4]; 
    219247        double paramArray[] = new double[params]; 
    220         double minValue, maxValue; 
    221         final LocalizableByDimCursor<?> cursor = image.createLocalizableByDimCursor(); 
     248 
     249        // keep track of minimum and maximum values per formula 
     250        double minValue[] = new double[formulas.length]; 
     251        double maxValue[] = new double[formulas.length]; 
     252        initMinMax(minValue, maxValue); 
     253 
     254        // get the parameters for each pixel, 
    222255        for (int c = 0; c < channels; ++c) { 
    223             dim[cIndex] = c; 
     256            dimForCursor[cIndex] = c; 
     257 
    224258            for (int y = 0; y < height; ++y) { 
    225                 dim[yIndex] = y; 
     259                dimForCursor[yIndex] = y; 
     260 
    226261                for (int x = 0; x < width; ++x) { 
    227                     dim[xIndex] = x; 
     262                    dimForCursor[xIndex] = x; 
     263 
     264                    // get the fitted parameters for c, y, x 
    228265                    for (int p = 0; p < params; ++p) { 
    229                         dim[pIndex] = p; 
    230                         cursor.moveTo(dim); 
     266                        dimForCursor[pIndex] = p; 
     267 
     268                        // get the fitted parameter 
     269                        cursor.moveTo(dimForCursor); 
    231270                        paramArray[p] = ((RealType) cursor.getType()).getRealFloat(); 
    232271                    } 
    233                     minValue = Double.MAX_VALUE; 
    234                     maxValue = 0.0; 
     272 
     273                    // calculate for this c, y, x pixel 
    235274                    for (int f = 0; f < formulas.length; ++f) { 
     275                        // accumulate minimum and maximum results for all pixels 
     276                        cells[c][f].setMin(minValue[f]); 
     277                        cells[c][f].setMax(maxValue[f]); 
     278 
     279                        // do the calculation 
    236280                        cells[c][f].calculate(x, y, paramArray); 
    237                         if (combineMinMax) { 
    238                             if (cells[c][f].getMin() < minValue) { 
    239                                 minValue = cells[c][f].getMin(); 
    240                             } 
    241                             if (cells[c][f].getMax() > maxValue) { 
    242                                 maxValue = cells[c][f].getMax(); 
    243                             } 
    244                         } 
    245                     } 
    246                     if (combineMinMax) { 
    247                         for (int f = 0; f < formulas.length; ++f) { 
    248                             cells[c][f].setMin(minValue); 
    249                             cells[c][f].setMax(maxValue); 
    250                         } 
    251                     } 
     281 
     282                        minValue[f] = cells[c][f].getMin(); 
     283                        maxValue[f] = cells[c][f].getMax(); 
     284 
     285                    } // f loop 
     286 
     287                } // x loop 
     288 
     289            } // y loop 
     290 
     291            if (!combineMinMax) { 
     292                // save minimum and maximum results for each formula for each channel 
     293                for (int f = 0; f < formulas.length; ++f) { 
     294                    Converter minConverter = new Converter(MIN, minValue[f]); 
     295                    Converter maxConverter = new Converter(MAX, maxValue[f]); 
     296                    double minimumValue = minConverter.getValue(); 
     297                    double maximumValue = maxConverter.getValue(); 
     298                    String minimumText = minConverter.getText(); 
     299                    String maximumText = maxConverter.getText(); 
     300 
     301                    cells[c][f].setMin(minimumValue); 
     302                    cells[c][f].setMax(maximumValue); 
     303                    cells[c][f].setMinText(minimumText); 
     304                    cells[c][f].setMaxText(maximumText); 
    252305                } 
    253             } 
    254         } 
    255  
     306                // reset minimum and maximum for each formula 
     307                initMinMax(minValue, maxValue); 
     308            } 
     309        } 
     310 
     311        // display cell data 
    256312        ColorProcessor outputProcessor = new ColorProcessor(totalWidth, totalHeight); 
    257313        outputProcessor.setAntialiasedText(true); 
     
    261317 
    262318        IColorize colorizer = new FiveColorColorize(Color.BLUE, Color.CYAN, Color.GREEN, Color.YELLOW, Color.RED); 
    263         for (int c = 0; c < channels; ++c) { 
    264             for (int f = 0; f < formulas.length; ++f) { 
    265                 cells[c][f].display(outputProcessor, colorizer); 
     319        for (int f = 0; f < formulas.length; ++f) { 
     320            if (combineMinMax) { 
     321                // save minimum and maximum results for all channels 
     322                Converter minConverter = new Converter(MIN, minValue[f]); 
     323                Converter maxConverter = new Converter(MAX, maxValue[f]); 
     324                double minimumValue = minConverter.getValue(); 
     325                double maximumValue = maxConverter.getValue(); 
     326                String minimumText = minConverter.getText(); 
     327                String maximumText = maxConverter.getText(); 
     328                for (int c = 0; c < channels; ++c) { 
     329                    cells[c][f].setMin(minimumValue); 
     330                    cells[c][f].setMax(maximumValue); 
     331                    cells[c][f].setMinText(minimumText); 
     332                    cells[c][f].setMaxText(maximumText); 
     333                    cells[c][f].display(outputProcessor, colorizer); 
     334                } 
     335 
     336            } 
     337            else { 
     338                // minimum and maximum results already saved 
     339                for (int c = 0; c < channels; ++c) { 
     340                    cells[c][f].display(outputProcessor, colorizer); 
     341                } 
    266342            } 
    267343        } 
     
    269345    } 
    270346 
     347    private void initMinMax(double minValue[], double maxValue[]) { 
     348        for (int i = 0; i < minValue.length; ++i) { 
     349            minValue[i] = Double.MAX_VALUE; 
     350            maxValue[i] = 0.0; 
     351        } 
     352    } 
     353 
     354    /** 
     355     * Inner class.  Builds a maximum or minimum value, rounding and 
     356     * formatting appropriately. 
     357     */ 
     358    private class Converter { 
     359        double m_value; 
     360        String m_text; 
     361 
     362        private Converter(boolean min, double value) { 
     363            MathContext context = new MathContext(2, min ? RoundingMode.FLOOR : RoundingMode.CEILING); 
     364            BigDecimal bigDecimalValue = BigDecimal.valueOf(value).round(context); 
     365            m_value = bigDecimalValue.doubleValue(); 
     366            m_text = bigDecimalValue.toEngineeringString(); 
     367        } 
     368 
     369        /** 
     370         * Gets the rounded value. 
     371         * 
     372         * @return rounded value 
     373         */ 
     374        private double getValue() { 
     375            return m_value; 
     376        } 
     377 
     378        /** 
     379         * Gets the formatted string representation of value. 
     380         * 
     381         * @return formatted string 
     382         */ 
     383        private String getText() { 
     384            return m_text; 
     385        } 
     386    } 
     387 
     388 
     389    /** 
     390     * Inner class.  Calculates and accumulates data for a given cell of the display. 
     391     */ 
    271392    private class DisplayCell { 
    272         Formula m_formula; 
    273         int m_x; 
    274         int m_y; 
    275         int m_width; 
    276         int m_height; 
    277         double m_value[][]; 
    278         double m_max = 0.0; 
    279         double m_min = Double.MAX_VALUE; 
    280  
    281         private DisplayCell(Formula formula, int x, int y, int width, int height) { 
     393        private String m_label; 
     394        private Formula m_formula; 
     395        private int m_x; 
     396        private int m_y; 
     397        private int m_width; 
     398        private int m_height; 
     399        private double m_value[][]; 
     400        private double m_max = 0.0; 
     401        private double m_min = Double.MAX_VALUE; 
     402 
     403        /** 
     404         * Creates a display cell. 
     405         * 
     406         * @param label for this channel 
     407         * @param formula to use for calculations 
     408         * @param x leftmost coordinate of the cell 
     409         * @param y uppermost coordinate of the cell 
     410         * @param width of the colorized data image 
     411         * @param height of the colorized data image 
     412         */ 
     413        private DisplayCell(String label, Formula formula, int x, int y, int width, int height) { 
     414            m_label   = label; 
    282415            m_formula = formula; 
    283             m_x = x; 
    284             m_y = y; 
    285             m_width = width; 
    286             m_height = height; 
     416            m_x       = x; 
     417            m_y       = y; 
     418            m_width   = width; 
     419            m_height  = height; 
    287420            m_value = new double[width][height]; 
    288421        } 
    289422 
     423        /** 
     424         * Applies the cell's formula to a set of parameters for a given pixel. 
     425         * 
     426         * @param x of current colorized data image pixel 
     427         * @param y of current colorized data image pixel 
     428         * @param parameters data for this pixel 
     429         */ 
    290430        private void calculate(int x, int y, double[] parameters) { 
    291431            double result = 0.0; 
     
    306446        } 
    307447 
     448        /** 
     449         * Gets minimum calculated value. 
     450         * 
     451         * @return 
     452         */ 
    308453        private double getMin() { 
    309454            return m_min; 
    310455        } 
    311456 
     457        /** 
     458         * Sets minimum value.  Used to initialize the minimum value and to 
     459         * set the final minimum value. 
     460         * 
     461         * @param min 
     462         */ 
    312463        private void setMin(double min) { 
    313464            m_min = min; 
    314465        } 
    315466 
     467        /** 
     468         * Sets the formatted String representation of the final minimum value. 
     469         * 
     470         * @param minText 
     471         */ 
     472        private void setMinText(String minText) { 
     473            m_minText = minText; 
     474        } 
     475 
     476        /** 
     477         * Gets maximum calculated value. 
     478         * 
     479         * @return 
     480         */ 
    316481        private double getMax() { 
    317482            return m_max; 
    318483        } 
    319484 
     485        /** 
     486         * Sets maximum value.  Used to initialize the maximum value and to 
     487         * set the final maximum value. 
     488         * 
     489         * @param max 
     490         */ 
    320491        private void setMax(double max) { 
    321492            m_max = max; 
    322493        } 
    323494 
     495        /** 
     496         * Sets the formatted String representation of the final maximum value. 
     497         * 
     498         * @param maxText 
     499         */ 
     500        private void setMaxText(String maxText) { 
     501            m_maxText = maxText; 
     502        } 
     503 
     504        /** 
     505         * Displays the colorized data image, color bar, and labelling. 
     506         *  
     507         * @param processor  
     508         * @param colorize 
     509         */ 
    324510        private void display(ColorProcessor processor, IColorize colorize) { 
     511            // set up color bar one time 
     512            if (null == m_bar) { 
     513                m_bar = colorize.bar(m_width); //TODO each cell makes it's own bar; that doesn't make sense 
     514            } 
     515 
     516            // label at top 
    325517            processor.setColor(Color.WHITE); 
    326518            processor.moveTo(m_x + SIDE_OFFSET, m_y + TEXT_OFFSET); 
    327519            processor.drawString(m_formula.getName()); 
    328             String channelName = "440nm"; 
    329             int width = processor.getStringWidth(channelName); 
    330             processor.moveTo(m_x + m_width - width, m_y + TEXT_OFFSET); 
    331             processor.drawString(channelName); 
     520            int width = processor.getStringWidth(m_label); 
     521            processor.moveTo(m_x + SIDE_OFFSET + m_width - width, m_y + TEXT_OFFSET); 
     522            processor.drawString(m_label); 
     523 
     524            // draw image 
    332525            for (int x = 0; x < m_width; ++x) { 
    333526                for (int y = 0; y < m_height; ++y) { 
     
    336529                } 
    337530            } 
     531 
     532            // draw color bar 
     533            int barX = m_x + SIDE_OFFSET; 
     534            int barY = m_y + TOP_OFFSET + m_height; 
     535            for (int x = barX; x < barX + m_width; ++x) { 
     536                processor.setColor(m_bar[x - barX]); 
     537                for (int y = barY; y < barY + BAR_HEIGHT; ++y) { 
     538                    processor.drawPixel(x, y); 
     539                } 
     540            } 
     541 
     542            // label color bar 
     543            processor.setColor(Color.WHITE); 
     544            processor.moveTo(barX, barY + TEXT_OFFSET); 
     545            processor.drawString(m_minText); 
     546            width = processor.getStringWidth(m_maxText); 
     547            processor.moveTo(barX + m_width - width, barY + TEXT_OFFSET); 
     548            processor.drawString(m_maxText); 
    338549        } 
    339550    } 
Note: See TracChangeset for help on using the changeset viewer.