Changeset 7168


Ignore:
Timestamp:
11/05/10 21:46:01 (9 years ago)
Author:
aivar
Message:

Switched to tau from lambda. Added stretched exponential fitting. Enabled cumulative fitting. Launch VisAD. Tidied up.

File:
1 edited

Legend:

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

    r7138 r7168  
    9292import mpicbg.imglib.type.numeric.RealType; 
    9393 
     94 
     95import mpicbg.imglib.container.Container; 
     96import mpicbg.imglib.container.basictypecontainer.PlanarAccess; 
     97import mpicbg.imglib.container.basictypecontainer.array.ArrayDataAccess; 
     98import mpicbg.imglib.container.basictypecontainer.array.ByteArray; 
     99import mpicbg.imglib.container.basictypecontainer.array.CharArray; 
     100import mpicbg.imglib.container.basictypecontainer.array.DoubleArray; 
     101import mpicbg.imglib.container.basictypecontainer.array.FloatArray; 
     102import mpicbg.imglib.container.basictypecontainer.array.IntArray; 
     103import mpicbg.imglib.container.basictypecontainer.array.LongArray; 
     104import mpicbg.imglib.container.basictypecontainer.array.ShortArray; 
     105import mpicbg.imglib.container.planar.PlanarContainerFactory; 
     106import mpicbg.imglib.cursor.Cursor; 
     107import mpicbg.imglib.cursor.LocalizableByDimCursor; 
     108import mpicbg.imglib.image.Image; 
     109import mpicbg.imglib.image.ImageFactory; 
     110import mpicbg.imglib.type.numeric.RealType; 
     111import mpicbg.imglib.type.numeric.integer.ByteType; 
     112import mpicbg.imglib.type.numeric.integer.IntType; 
     113import mpicbg.imglib.type.numeric.integer.ShortType; 
     114import mpicbg.imglib.type.numeric.integer.UnsignedByteType; 
     115import mpicbg.imglib.type.numeric.integer.UnsignedIntType; 
     116import mpicbg.imglib.type.numeric.integer.UnsignedShortType; 
     117import mpicbg.imglib.type.numeric.real.DoubleType; 
     118import mpicbg.imglib.type.numeric.real.FloatType; 
     119 
    94120/** 
    95121 * TODO 
     
    106132    private static final String LIFETIME = "Lifetime"; 
    107133    private static final String CHANNELS = "Channels"; 
     134    private static final boolean USE_TAU = true; 
     135    private static final boolean USE_LAMBDA = false; 
    108136 
    109137    // this affects how lifetimes are colorized: 
     
    126154    private static final double[] DEFAULT_DOUBLE_EXP_PARAMS = { 50.0, 0.5, 50, 0.25, 0.5 }; 
    127155    private static final double[] DEFAULT_TRIPLE_EXP_PARAMS = { 40.0, 0.5, 30.0, 0.25, 30, 0.10, 0.5 }; 
     156    private static final double[] DEFAULT_STRETCH_EXP_PARAMS = { 100.0, 0.5, 0.5, 0.5 }; 
    128157 
    129158    private Object m_synchFit = new Object(); 
     
    146175    private ImageProcessor m_grayscaleImageProcessor; 
    147176    private Canvas m_grayscaleCanvas; 
     177 
     178    private Image<DoubleType> m_fittedImage = null; 
     179    private int m_fittedComponents = 0; 
    148180 
    149181    // data parameters //TODO Curtis has these as protected 
     
    215247            uiPanel.setFunctionParameters(1, DEFAULT_DOUBLE_EXP_PARAMS); 
    216248            uiPanel.setFunctionParameters(2, DEFAULT_TRIPLE_EXP_PARAMS); 
     249            uiPanel.setFunctionParameters(3, DEFAULT_STRETCH_EXP_PARAMS); 
    217250            uiPanel.setListener( 
    218251                    new IUserInterfacePanelListener() { 
     
    241274            doFits(uiPanel); 
    242275        } 
    243  
    244      /*       while (true) { 
    245                 // ask what kind fo fit 
    246                 if (!showFitDialog()) { 
    247                     break; 
    248                 } 
    249                 // ask for fit parameters 
    250                 if (!showFitParamsDialog()) { 
    251                     break; 
    252                 } 
    253                 fitData(); 
    254             } 
    255         } */ 
    256         /* 
    257         m_width = ImageUtils.getWidth(image); 
    258         m_height = ImageUtils.getHeight(image); 
    259         m_timeBins = ImageUtils.getDimSize(image, FormatTools.LIFETIME, 0); 
    260          
    261         m_data = new int[m_channels][m_height][m_width][m_timeBins]; 
    262         final LocalizableByDimCursor<?> cursor = image.createLocalizableByDimCursor(); 
    263         int x, y, bin, channel; 
    264         for (channel = 0; channel < m_channels; ++channel) { 
    265             if (null != channelIndex) { 
    266                 dimensions[channelIndex] = channel; 
    267             } 
    268             for (y = 0; y < m_height; ++y) { 
    269                 dimensions[yIndex] = y; 
    270                 for (x = 0; x < m_width; ++x) { 
    271                     dimensions[xIndex] = x; 
    272                     for (bin = 0; bin < m_timeBins; ++bin) { 
    273                         dimensions[lifetimeIndex] = bin; 
    274                         cursor.moveTo(dimensions); 
    275                         m_data[channel][y][x][bin] = (int) cursor.getType().getRealFloat(); 
    276                         if (m_data[channel][y][x][bin] > 100 && ++m_debug < 100) { 
    277                             System.out.println("m_data " + m_data[channel][y][x][bin] + " cursor " + cursor.getType().getRealFloat()); 
    278                         } 
    279                     } 
    280                 } 
    281             } 
    282         } 
    283  
    284         // patch things up 
    285         m_timeRange = 10.0f; 
    286         m_minWave = 400; 
    287         m_waveStep = 10; 
    288         */ 
    289276    } 
    290277 
     
    313300        if (success) { 
    314301            // show the UI; do fits 
    315             IUserInterfacePanel uiPanel = new UserInterfacePanel(false); // using lambda 
     302            IUserInterfacePanel uiPanel = new UserInterfacePanel(USE_TAU); 
    316303            uiPanel.setX(0); 
    317304            uiPanel.setY(0); 
     
    322309            uiPanel.setFunctionParameters(1, DEFAULT_DOUBLE_EXP_PARAMS); 
    323310            uiPanel.setFunctionParameters(2, DEFAULT_TRIPLE_EXP_PARAMS); 
     311            uiPanel.setFunctionParameters(3, DEFAULT_STRETCH_EXP_PARAMS); 
    324312            uiPanel.setListener( 
    325313                new IUserInterfacePanelListener() { 
     
    352340    /** 
    353341     * Loops until quitting time and handles fit requests. 
    354      * Fitting is driven by a button on the UI panel. 
     342     * Fitting is driven by a button on the UI panel which 
     343     * sets the global m_fitInProgress. 
    355344     * 
    356345     * @param uiPanel 
     
    372361            getFitSettings(uiPanel); 
    373362 
    374             fitData(uiPanel); //TODO currently also diddles with m_fitInProgress; uses synch block 
     363            fitData(uiPanel); 
    375364 
    376365            m_fitInProgress = false; 
     
    380369 
    381370    private void getFitSettings(IUserInterfacePanel uiPanel) { 
    382         m_region = uiPanel.getRegion(); 
    383         m_algorithm = uiPanel.getAlgorithm(); 
    384         m_function = uiPanel.getFunction(); 
    385  
    386         m_x = uiPanel.getX(); 
    387         m_y = uiPanel.getY(); 
    388         m_startBin = uiPanel.getStart(); 
    389         m_stopBin = uiPanel.getStop(); 
    390         m_threshold = uiPanel.getThreshold(); 
    391  
    392         int components = uiPanel.getComponents(); 
    393         m_param = uiPanel.getParameters(); 
    394         m_free = uiPanel.getFree(); 
     371        m_region       = uiPanel.getRegion(); 
     372        m_algorithm    = uiPanel.getAlgorithm(); 
     373        m_function     = uiPanel.getFunction(); 
     374 
     375        m_x            = uiPanel.getX(); 
     376        m_y            = uiPanel.getY(); 
     377        m_startBin     = uiPanel.getStart(); 
     378        m_stopBin      = uiPanel.getStop(); 
     379        m_threshold    = uiPanel.getThreshold(); 
     380 
     381        int components = uiPanel.getComponents(); //TODO warum? 
     382        m_param        = uiPanel.getParameters(); 
     383        m_free         = uiPanel.getFree(); 
    395384    } 
    396385 
     
    436425        int[] dimensions = image.getDimensions(); 
    437426        System.out.println("dimensions size is " + dimensions.length); 
    438         /* 
    439         Map map = dimensionMap(image.getName()); 
    440         Integer xIndex, yIndex, lifetimeIndex, channelIndex; 
    441         xIndex = (Integer) map.get(X); 
    442         yIndex = (Integer) map.get(Y); 
    443         lifetimeIndex = (Integer) map.get(LIFETIME); 
    444         if (null != xIndex && null != yIndex && null != lifetimeIndex) { 
    445             m_width = dimensions[xIndex]; 
    446             m_height = dimensions[yIndex]; 
    447             m_timeBins = dimensions[lifetimeIndex]; 
    448         } 
    449         else { 
    450             System.out.println("Can't find dimensions of .sdt Image " + image.getName()); 
    451             return false; 
    452         } 
    453         m_channels = 1; 
    454         channelIndex = (Integer) map.get(CHANNELS); 
    455         if (null != channelIndex) { 
    456             System.out.println("Do have channel dimension"); 
    457             m_channels = dimensions[channelIndex]; 
    458         } 
    459         else System.out.println("Don't have channel dimension"); 
    460         */ 
    461427        Integer xIndex, yIndex, lifetimeIndex, channelIndex; 
    462428        m_width = ImageUtils.getWidth(image); 
     
    505471        //cursor.close(); 
    506472 
     473        //TODO from a former version: 
     474     //TODO won't compile with my version of the jar: Number timeBase = (Number) m_reader.getGlobalMetadata().get("time base"); 
     475     //TODO fix: 
     476         //   Number timeBase = null; 
     477         //   m_timeRange = timeBase == null ? Float.NaN : timeBase.floatValue(); 
     478         ////   if (m_timeRange != m_timeRange) m_timeRange = 10.0f; 
     479         //   m_minWave = 400; 
     480         //   m_waveStep = 10; 
     481            //m_binRadius = 3; 
     482 
     483 
    507484        // patch things up 
    508485        m_timeRange = 10.0f / 64.0f; //TODO ARG this patches things up in accord with TRI2 for brian/gpl1.sdt; very odd value here 
     
    511488 
    512489        return true; 
    513     } 
    514  
    515     /* 
    516      * This method parses a string of the format: 
    517      * "Name [X Y Timebins]" and builds a map with 
    518      * the dimensions 'X', 'Y', and 'Timebins' mapped 
    519      * to the dimension indices. 
    520      * 
    521      * Temporary kludge. 
    522      */ 
    523     private Map<String, Integer> dimensionMap(String name) { 
    524         System.out.println("name is " + name); 
    525         Map<String, Integer> map = new HashMap<String, Integer>(); 
    526         int startIndex = name.indexOf('[') + 1; 
    527         int endIndex = name.indexOf(']'); 
    528         String coded = name.substring(startIndex, endIndex); 
    529         String dimensions[] = coded.split(" "); 
    530         int index = 0; 
    531         for (String dimension : dimensions) { 
    532             map.put(dimension, index++); 
    533         } 
    534         return map; 
    535     } 
    536  
    537     /** 
    538      * Loads the .sdt file. 
    539      * Based on the loci.slim.SlimData constructor. 
    540      * 
    541      * @param file 
    542      * @return whether successful 
    543      */ 
    544     private boolean loadFile(String file) { 
    545         if (m_fakeData) return true; 
    546         boolean status = false; 
    547         try { 
    548             // read file header 
    549             m_reader = new ChannelSeparator(); 
    550             m_reader.setId(file); 
    551             m_width = m_reader.getSizeX(); 
    552             m_height = m_reader.getSizeY(); 
    553             m_cLengths = m_reader.getChannelDimLengths(); 
    554             String[] cTypes = m_reader.getChannelDimTypes(); 
    555             m_timeBins = m_channels = 1; 
    556             m_lifetimeIndex = m_spectraIndex = -1; 
    557             for (int i=0; i<cTypes.length; i++) { 
    558                 if (cTypes[i].equals(FormatTools.LIFETIME)) { 
    559                     m_timeBins = m_cLengths[i]; 
    560                     m_lifetimeIndex = i; 
    561                 } 
    562                 else if (cTypes[i].equals(FormatTools.SPECTRA)) { 
    563                     m_channels = m_cLengths[i]; 
    564                     m_spectraIndex = i; 
    565                 } 
    566                 else if (m_lifetimeIndex < 0 && cTypes[i].equals(FormatTools.CHANNEL)) { 
    567                     m_timeBins = m_cLengths[i]; 
    568                     m_lifetimeIndex = i; 
    569                 } 
    570             } 
    571             m_little = m_reader.isLittleEndian(); 
    572             m_pixelType = m_reader.getPixelType(); 
    573             m_bpp = FormatTools.getBytesPerPixel(m_pixelType); 
    574             m_floating = FormatTools.isFloatingPoint(m_pixelType); 
    575  
    576      //TODO won't compile with my version of the jar: Number timeBase = (Number) m_reader.getGlobalMetadata().get("time base"); 
    577      //TODO fix: 
    578             Number timeBase = null; 
    579             m_timeRange = timeBase == null ? Float.NaN : timeBase.floatValue(); 
    580             if (m_timeRange != m_timeRange) m_timeRange = 10.0f; 
    581             m_minWave = 400; 
    582             m_waveStep = 10; 
    583             //m_binRadius = 3; 
    584             status = true; 
    585         } 
    586         catch (Exception e) { 
    587  
    588         } 
    589         return status; 
    590490    } 
    591491 
     
    688588 
    689589    /** 
    690      * Loads the data from the .sdt file. 
    691      * Based on loci.slim.SlimData constructor. 
    692      * 
    693      * @return whether successful 
    694      */ 
    695     private boolean loadData() { 
    696         boolean success = false; 
    697         try { 
    698             byte[] plane = new byte[m_bpp * m_height * m_width]; 
    699             m_data = new int[m_channels][m_height][m_width][m_timeBins]; 
    700             int imageCount = m_reader.getImageCount(); 
    701             for (int i=0; i<imageCount; i++) { 
    702                 int[] zct = m_reader.getZCTCoords(i); 
    703                 if (zct[0] != 0 || zct[2] != 0) { 
    704                     continue; // process only first Z and T 
    705                 } 
    706                 int[] sub = FormatTools.rasterToPosition(m_cLengths, zct[1]); 
    707                 int c = m_spectraIndex < 0 ? 0 : sub[m_spectraIndex]; 
    708                 int t = m_lifetimeIndex < 0 ? 0 : sub[m_lifetimeIndex]; 
    709                 m_reader.openBytes(i, plane, 0, 0, m_width, m_height); 
    710                 for (int y=0; y<m_height; y++) { 
    711                     for (int x=0; x<m_width; x++) { 
    712                         int index = m_bpp * (y * m_width + x); 
    713                         int val; 
    714                         if (m_pixelType == FormatTools.FLOAT) { 
    715                             val = (int) DataTools.bytesToFloat(plane, index, m_bpp, m_little); 
    716                         } 
    717                         else if (m_pixelType == FormatTools.DOUBLE) { 
    718                             val = (int) DataTools.bytesToDouble(plane, index, m_bpp, m_little); 
    719                         } 
    720                         else if (!m_floating) { 
    721                             val = DataTools.bytesToInt(plane, index, m_bpp, m_little); 
    722                         } 
    723                         else { 
    724                             throw new FormatException("Unsupported pixel type: " + 
    725                                 FormatTools.getPixelTypeString(m_pixelType)); 
    726                         } 
    727                         m_data[c][y][x][t] = val; 
    728                     } 
    729                 } 
    730             } 
    731             m_reader.close(); 
    732             success = true; 
    733         } 
    734         catch (Exception e) { 
    735         } 
    736         return success; 
    737     } 
    738  
    739     /** 
    740590     * This routine sums all of the photon data and creates a grayscale 
    741591     * image for the data. 
     
    779629        imagePlus.show(); 
    780630        m_grayscaleImageProcessor = imagePlus.getChannelProcessor(); 
    781         /* 
    782         int maxPixel = 0; 
    783         for (int x = 0; x < m_width; ++x) { 
    784             for (int y = 0; y < m_height; ++y) { 
    785                 pixels[x][y] = 0; 
    786                 for (int c = 0; c < m_channels; ++c) { 
    787                     for (int b = 0; b < m_timeBins; ++b) { 
    788                         //System.out.println("x " + x + " y " + y + " c " + c + " b " + b); 
    789                         pixels[x][y] += m_data[c][y][x][b]; 
    790                     } 
    791                 } 
    792                 if (pixels[x][y] > maxPixel) { 
    793                     maxPixel = pixels[x][y]; 
    794                 } 
    795             } 
    796         } 
    797  
    798         ImageProcessor imageProcessor = new ByteProcessor(m_width, m_height); 
    799         ImagePlus imagePlus = new ImagePlus(name + " GrayScale", imageProcessor); 
    800         byte[] outPixels = (byte[]) imageProcessor.getPixels(); 
    801         for (int x = 0; x < m_width; ++x) { 
    802             for (int y = 0; y < m_height; ++y) { 
    803                 // flip y axis to correspond with Slim Plotter image 
    804                 outPixels[y * m_width + x] = (byte) (pixels[x][m_height - y - 1] * 255 / maxPixel); 
    805             } 
    806         } 
    807         imagePlus.show(); 
    808         m_grayscaleImageProcessor = imageProcessor; //TODO for now 
    809 */ 
     631 
    810632        // hook up mouse listener 
    811633        ImageWindow imageWindow = imagePlus.getWindow(); 
     
    821643                    // just ignore clicks during a fit 
    822644                    if (!m_fitInProgress) { 
    823                         uiPanel.setX(e.getX()); 
    824                         uiPanel.setY(e.getY()); 
    825                         fitPixel(uiPanel, e.getX(), e.getY()); 
     645                        synchronized (m_synchFit) { 
     646                            uiPanel.setX(e.getX()); 
     647                            uiPanel.setY(e.getY()); 
     648                            // fit on the pixel clicked 
     649                            fitPixel(uiPanel, e.getX(), e.getY()); 
     650                        } 
    826651                    } 
    827652                } 
     
    831656    } 
    832657 
    833     /** 
    834      * This dialog box collects settings relating to the fit.  Pressing OK 
    835      * starts the fit, Cancel cancels the whole plugin. 
    836      * 
    837      * @return 
    838      */ 
    839     private boolean XshowFitDialog() { 
    840         NonBlockingGenericDialog dialog = new NonBlockingGenericDialog("Fit Type"); 
    841         dialog.addChoice( 
    842             "Region", 
    843             new String[] { "Sum all", "Sum each ROI", "Single pixel", "Each pixel" }, 
    844             "Each pixel"); 
    845         dialog.addChoice( 
    846             "Algorithm", 
    847             new String[] { "Jaolho", /*"Akutan",*/ "old Barber RLD", "old Barber LMA", "Markwardt", "Barber NR RLD", "Barber NR LMA", "SLIMCurve RLD", "SLIMCurve LMA" }, 
    848             "Jaolho"); 
    849         dialog.addChoice( 
    850             "Function", 
    851             new String[] { "Single Exponential", "Double Exponential", "Triple Exponential", "Stretched Exponential" }, 
    852             "Single Exponential"); 
    853         dialog.showDialog(); 
    854         if (dialog.wasCanceled()) { 
    855             return false; 
    856         } 
    857         m_region = FitRegion.class.getEnumConstants()[dialog.getNextChoiceIndex()]; 
    858         m_algorithm = FitAlgorithm.class.getEnumConstants()[dialog.getNextChoiceIndex()]; 
    859         m_function = FitFunction.class.getEnumConstants()[dialog.getNextChoiceIndex()]; 
    860         return true; 
    861     } 
    862  
    863     // The following was an attempt to drive the fitting process from the OK button on the 
    864     // Fit Dialog. 
    865 /*    private class MyDialogListener implements DialogListener { 
    866         public boolean dialogItemChanged(GenericDialog dialog, AWTEvent e) { 
    867             if (dialog.equals(m_fitDialog)) { 
    868                 if (dialog.wasCanceled()) { 
    869                     System.out.println("Dialgo canceled"); 
    870                     m_done = true; 
    871                 } 
    872                 else if (dialog.wasOKed()) { 
    873                     System.out.println("Dialog okayed"); 
    874                     m_region = FitRegion.class.getEnumConstants()[dialog.getNextChoiceIndex()]; 
    875                     m_algorithm = FitAlgorithm.class.getEnumConstants()[dialog.getNextChoiceIndex()]; 
    876                     m_function = FitFunction.class.getEnumConstants()[dialog.getNextChoiceIndex()]; 
    877  
    878                     // ask for fit parameters 
    879                     if (showFitParamsDialog()) { 
    880                         System.out.println("ABOUT TO FIT"); 
    881                         fitData(); 
    882                         showFitDialog(); // probably not the best way to do this 
    883                     } 
    884                     else System.out.println("FIT PARAMS DIALOG CACNELLDE"); 
    885                 } 
    886                 else System.out.println("NOT CANCELLED OR OKAYED<, SOMETHING ELSE"); 
    887             } 
    888             return true; 
    889         } 
    890     }*///TODO unfortunately NonBlockingGenericDialog doesn't call this for OK or Cancel button! 
    891  
    892     /** 
    893      * This dialog box collects settings for the current fit. 
    894      * 
    895      * @return 
    896      */ 
    897     private boolean XshowFitParamsDialog() { 
    898         GenericDialog dialog = new GenericDialog("Fit Params"); 
    899         if (FitRegion.POINT == m_region) { 
    900             dialog.addNumericField("X", m_x, 0); 
    901             dialog.addNumericField("Y", m_y, 0); 
    902         } 
    903         switch (m_function) { 
    904             /* 
    905             case SINGLE_EXPONENTIAL: 
    906                 dialog.addNumericField("A", m_fitA1, 5); 
    907                 dialog.addCheckbox("Fix", m_fitA1fixed); 
    908                 dialog.addNumericField("" + LAMBDA, m_fitT1, 5); 
    909                 dialog.addCheckbox("Fix", m_fitT1fixed); 
    910                 dialog.addNumericField("C", m_fitC, 5); 
    911                 dialog.addCheckbox("Fix", m_fitCfixed); 
    912                 break; 
    913             case DOUBLE_EXPONENTIAL: 
    914                 dialog.addNumericField("A1", m_fitA1, 5); 
    915                 dialog.addCheckbox("Fix", m_fitA1fixed); 
    916                 dialog.addNumericField("" + LAMBDA + "1", m_fitT1, 5); 
    917                 dialog.addCheckbox("Fix", m_fitT1fixed); 
    918                 dialog.addNumericField("A2", m_fitA2, 5); 
    919                 dialog.addCheckbox("Fix", m_fitA2fixed); 
    920                 dialog.addNumericField("" + LAMBDA + "2", m_fitT2, 5); 
    921                 dialog.addCheckbox("Fix", m_fitT2fixed); 
    922                 dialog.addNumericField("C", m_fitC, 5); 
    923                 dialog.addCheckbox("Fix", m_fitCfixed); 
    924                 break; 
    925             case TRIPLE_EXPONENTIAL: 
    926                 dialog.addNumericField("A1", m_fitA1, 5); 
    927                 dialog.addCheckbox("Fix", m_fitA1fixed); 
    928                 dialog.addNumericField("" + LAMBDA + "1", m_fitT1, 5); 
    929                 dialog.addCheckbox("Fix", m_fitT1fixed); 
    930                 dialog.addNumericField("A2", m_fitA2, 5); 
    931                 dialog.addCheckbox("Fix", m_fitA2fixed); 
    932                 dialog.addNumericField("" + LAMBDA + "2", m_fitT2, 5); 
    933                 dialog.addCheckbox("Fix", m_fitT2fixed); 
    934                 dialog.addNumericField("A3", m_fitA3, 5); 
    935                 dialog.addCheckbox("Fix", m_fitA3fixed); 
    936                 dialog.addNumericField("" + LAMBDA + "3", m_fitT3, 5); 
    937                 dialog.addCheckbox("Fix", m_fitT3fixed); 
    938                 dialog.addNumericField("C", m_fitC, 5); 
    939                 dialog.addCheckbox("Fix", m_fitCfixed); 
    940                 break; 
    941             case STRETCHED_EXPONENTIAL: 
    942                 break; 
    943             */ 
    944             case SINGLE_EXPONENTIAL: 
    945                 dialog.addNumericField("A", 
    946                         m_param[0], 5); 
    947                 dialog.addCheckbox("Fix", 
    948                         !m_free[0]); 
    949                 dialog.addNumericField("" + LAMBDA, 
    950                         m_param[1], 5); 
    951                 dialog.addCheckbox("Fix", 
    952                         !m_free[1]); 
    953                 dialog.addNumericField("C", 
    954                         m_param[2], 5); 
    955                 dialog.addCheckbox("Fix", 
    956                         !m_free[2]); 
    957                 break; 
    958             case DOUBLE_EXPONENTIAL: 
    959                 dialog.addNumericField("A" + SUB_1, 
    960                         m_param[0], 5); 
    961                 dialog.addCheckbox("Fix", 
    962                         !m_free[0]); 
    963                 dialog.addNumericField("" + LAMBDA + SUB_1, 
    964                         m_param[1], 5); 
    965                 dialog.addCheckbox("Fix", 
    966                         !m_free[1]); 
    967                 dialog.addNumericField("A" + SUB_2, 
    968                         m_param[2], 5); 
    969                 dialog.addCheckbox("Fix", 
    970                         !m_free[2]); 
    971                 dialog.addNumericField("" + LAMBDA + SUB_2, 
    972                         m_param[3], 5); 
    973                 dialog.addCheckbox("Fix", 
    974                         !m_free[3]); 
    975                 dialog.addNumericField("C", 
    976                         m_param[4], 5); 
    977                 dialog.addCheckbox("Fix", 
    978                         !m_free[4]); 
    979                 break; 
    980             case TRIPLE_EXPONENTIAL: 
    981                 dialog.addNumericField("A" + SUB_1, 
    982                         m_param[0], 5); 
    983                 dialog.addCheckbox("Fix", 
    984                         !m_free[0]); 
    985                 dialog.addNumericField("" + LAMBDA + SUB_1, 
    986                         m_param[1], 5); 
    987                 dialog.addCheckbox("Fix", 
    988                         !m_free[1]); 
    989                 dialog.addNumericField("A" + SUB_2, 
    990                         m_param[2], 5); 
    991                 dialog.addCheckbox("Fix", 
    992                         !m_free[2]); 
    993                 dialog.addNumericField("" + LAMBDA + SUB_2, 
    994                         m_param[3], 5); 
    995                 dialog.addCheckbox("Fix", 
    996                         !m_free[3]); 
    997                 dialog.addNumericField("A" + SUB_3, 
    998                         m_param[4], 5); 
    999                 dialog.addCheckbox("Fix", 
    1000                         !m_free[4]); 
    1001                 dialog.addNumericField("" + LAMBDA + SUB_3, 
    1002                         m_param[5], 5); 
    1003                 dialog.addCheckbox("Fix", 
    1004                         !m_free[5]); 
    1005                 dialog.addNumericField("C", 
    1006                         m_param[6], 5); 
    1007                 dialog.addCheckbox("Fix", 
    1008                         !m_free[6]); 
    1009                 break; 
    1010             case STRETCHED_EXPONENTIAL: 
    1011                 break; 
    1012  
    1013         } 
    1014         if (0 == m_stopBin) { 
    1015             m_stopBin = m_timeBins - 1; 
    1016         } 
    1017         dialog.addNumericField("Start", m_startBin, 0, 2, "bins"); 
    1018         dialog.addNumericField("Stop", m_stopBin, 0, 2, "bins"); 
    1019         dialog.addNumericField("Start X", m_startX, 0, 2, "bins"); 
    1020         dialog.addNumericField("Threshold", m_threshold, 0, 2, "photons"); 
    1021         dialog.addNumericField("" + CHI + SQUARE + " Target", m_chiSqTarget, 0, 2, null); 
    1022         dialog.showDialog(); 
    1023         if (dialog.wasCanceled()) { 
    1024             return false; 
    1025         } 
    1026         if (FitRegion.POINT == m_region) { 
    1027             m_x = (int) dialog.getNextNumber(); 
    1028             m_y = (int) dialog.getNextNumber(); 
    1029         } 
    1030         switch (m_function) { 
    1031             case SINGLE_EXPONENTIAL: 
    1032                 m_param[0] = dialog.getNextNumber(); 
    1033                 m_free[0] = !dialog.getNextBoolean(); 
    1034                 m_param[1] = dialog.getNextNumber(); 
    1035                 m_free[1] = !dialog.getNextBoolean(); 
    1036                 m_param[2] = dialog.getNextNumber(); 
    1037                 m_free[2] = !dialog.getNextBoolean(); 
    1038                 break; 
    1039             case DOUBLE_EXPONENTIAL: 
    1040                 m_param[0] = dialog.getNextNumber(); 
    1041                 m_free[0] = !dialog.getNextBoolean(); 
    1042                 m_param[1] = dialog.getNextNumber(); 
    1043                 m_free[1] = !dialog.getNextBoolean(); 
    1044                 m_param[2] = dialog.getNextNumber(); 
    1045                 m_free[2] = !dialog.getNextBoolean(); 
    1046                 m_param[3] = dialog.getNextNumber(); 
    1047                 m_free[3] = !dialog.getNextBoolean(); 
    1048                 m_param[4] = dialog.getNextNumber(); 
    1049                 m_free[4] = !dialog.getNextBoolean(); 
    1050                 break; 
    1051             case TRIPLE_EXPONENTIAL: 
    1052                 m_param[0] = dialog.getNextNumber(); 
    1053                 m_free[0] = !dialog.getNextBoolean(); 
    1054                 m_param[1] = dialog.getNextNumber(); 
    1055                 m_free[1] = !dialog.getNextBoolean(); 
    1056                 m_param[2] = dialog.getNextNumber(); 
    1057                 m_free[2] = !dialog.getNextBoolean(); 
    1058                 m_param[3] = dialog.getNextNumber(); 
    1059                 m_free[3] = !dialog.getNextBoolean(); 
    1060                 m_param[4] = dialog.getNextNumber(); 
    1061                 m_free[4] = !dialog.getNextBoolean(); 
    1062                 m_param[5] = dialog.getNextNumber(); 
    1063                 m_free[5] = !dialog.getNextBoolean(); 
    1064                 m_param[6] = dialog.getNextNumber(); 
    1065                 m_free[6] = !dialog.getNextBoolean(); 
    1066                break; 
    1067             case STRETCHED_EXPONENTIAL: 
    1068                 break; 
    1069         } 
    1070         m_startBin = (int) dialog.getNextNumber(); 
    1071         m_stopBin  = (int) dialog.getNextNumber(); 
    1072         m_startX = (int) dialog.getNextNumber(); 
    1073         m_threshold = (int) dialog.getNextNumber(); 
    1074       //  m_chiSqTarget = (double) dialog.getNextNumber(); 
    1075         return true; 
    1076     } 
    1077  
     658    /* 
     659     * Fits the data as requested by UI. 
     660     */ 
    1078661    private void fitData(IUserInterfacePanel uiPanel) { 
    1079662        // only one fit at a time 
    1080663        synchronized (m_synchFit) { 
    1081             // disable mouse click pixel fits 
    1082             m_fitInProgress = true; 
    1083              
    1084664            switch (m_region) { 
    1085665                case SUMMED: 
     
    1100680                    break; 
    1101681            } 
    1102             m_fitInProgress = false; 
    1103682        } 
    1104683    } 
     
    1140719        // do the fit 
    1141720        ICurveFitData dataArray[] = curveFitDataList.toArray(new ICurveFitData[0]); 
    1142         doFit(uiPanel, dataArray); 
     721        getCurveFitter(uiPanel).fitData(dataArray, m_startBin, m_stopBin); 
    1143722 
    1144723        // show decay and update UI parameters 
     
    1188767        // do the fit 
    1189768        ICurveFitData dataArray[] = curveFitDataList.toArray(new ICurveFitData[0]); 
    1190         doFit(uiPanel, dataArray); 
     769        getCurveFitter(uiPanel).fitData(dataArray, m_startBin, m_stopBin); 
    1191770         
    1192771        showDecayGraph(uiPanel, dataArray); 
     
    1245824        // do the fit 
    1246825        ICurveFitData dataArray[] = curveFitDataList.toArray(new ICurveFitData[0]); 
    1247         doFit(uiPanel, dataArray); 
     826        getCurveFitter(uiPanel).fitData(dataArray, m_startBin, m_stopBin); 
    1248827         
    1249828        showDecayGraph(uiPanel, dataArray); 
     
    1263842    private void fitEachPixel(IUserInterfacePanel uiPanel) { 
    1264843        long start = System.nanoTime(); 
    1265          
     844 
     845        ICurveFitter curveFitter = getCurveFitter(uiPanel);      
    1266846        double params[] = uiPanel.getParameters(); 
     847 
     848        boolean useFittedParams; 
     849        LocalizableByDimCursor<DoubleType> cursor = null; 
     850        if (null == m_fittedImage || uiPanel.getComponents() != m_fittedComponents) { 
     851            // can't use previous results 
     852            useFittedParams = false; 
     853            m_fittedComponents = uiPanel.getComponents(); 
     854            m_fittedImage = makeImage(100, 200, m_fittedComponents); 
     855        } 
     856        else { 
     857            // ask UI whether to use previous results 
     858            useFittedParams = uiPanel.refineFit(); 
     859        } 
     860        cursor = m_fittedImage.createLocalizableByDimCursor(); 
    1267861         
    1268862        // build the data 
     
    1288882                    IJ.showProgress(0, 0); //TODO kludgy to have this here and also below 
    1289883                    dataColorizer.quit(); 
     884                    cancelImageFit(); 
    1290885                    return; 
    1291886                } 
     
    1294889                if (wantFitted(pixel.getX(), pixel.getY())) { 
    1295890                    curveFitData = new CurveFitData(); 
    1296                     curveFitData.setParams(params.clone()); 
     891                    curveFitData.setX(pixel.getX()); 
     892                    curveFitData.setY(pixel.getY()); 
     893                    curveFitData.setParams( 
     894                            useFittedParams ? 
     895                                getFittedParams(cursor, pixel.getX(), pixel.getY(), m_fittedComponents) : 
     896                                params.clone()); 
    1297897                    yCount = new double[m_timeBins]; 
    1298898                    for (int b = 0; b < m_timeBins; ++b) { 
     
    1307907 
    1308908                    if (++pixelsToProcessCount >= PIXEL_COUNT) { 
    1309                         processPixels(uiPanel, dataColorizer, m_height, curveFitDataList.toArray(new ICurveFitData[0]), pixelList.toArray(new ChunkyPixel[0])); 
     909                        ICurveFitData[] data = curveFitDataList.toArray(new ICurveFitData[0]); 
     910                        curveFitter.fitData(data, m_startBin, m_stopBin); 
     911                        setFittedParamsFromData(cursor, data); 
     912                        colorizePixels(dataColorizer, m_height, data, pixelList.toArray(new ChunkyPixel[0])); 
     913 
    1310914                        curveFitDataList.clear(); 
    1311915                        pixelList.clear(); 
     
    1315919            } 
    1316920            if (!m_cancel && 0 < pixelsToProcessCount) { 
    1317                 processPixels(uiPanel, dataColorizer, m_height, curveFitDataList.toArray(new ICurveFitData[0]), pixelList.toArray(new ChunkyPixel[0])); 
     921                ICurveFitData[] data = curveFitDataList.toArray(new ICurveFitData[0]); 
     922                curveFitter.fitData(data, m_startBin, m_stopBin); 
     923                setFittedParamsFromData(cursor, data); 
     924                colorizePixels(dataColorizer, m_height, data, pixelList.toArray(new ChunkyPixel[0])); 
    1318925            } 
    1319926        } 
     
    1321928            IJ.showProgress(0, 0); //TODO the code below s/b showing progress also 
    1322929           // dataColorizer.quit(); //TODO no longer visible in this code 
     930            cancelImageFit(); 
    1323931            return; 
    1324932        } 
     
    1339947                                    if (channel != visibleChannel) { 
    1340948                                        if (m_cancel) { 
     949                                            cancelImageFit(); 
    1341950                                            return; 
    1342951                                        } 
    1343952                                        if (wantFitted(bounds.x + x, bounds.y + y)) { 
    1344953                                            curveFitData = new CurveFitData(); 
    1345                                             curveFitData.setParams(params.clone()); 
     954                                            curveFitData.setX(bounds.x + x); 
     955                                            curveFitData.setY(bounds.y + y); 
     956                                            curveFitData.setParams( 
     957                                                    useFittedParams ? 
     958                                                        getFittedParams(cursor, bounds.x + x, bounds.y + y, m_fittedComponents) : 
     959                                                        params.clone()); 
    1346960                                            yCount = new double[m_timeBins]; 
    1347961                                            for (int b = 0; b < m_timeBins; ++b) { 
     
    1367981                            for (int x = 0; x < m_width; ++x) { 
    1368982                                if (m_cancel) { 
     983                                    cancelImageFit(); 
    1369984                                    return; 
    1370985                                } 
    1371986                                if (aboveThreshold(x, y)) { 
    1372987                                    curveFitData = new CurveFitData(); 
    1373                                     curveFitData.setParams(params.clone()); 
     988                                    curveFitData.setX(x); 
     989                                    curveFitData.setY(y); 
     990                                    curveFitData.setParams( 
     991                                            useFittedParams ? 
     992                                                getFittedParams(cursor, x, y, m_fittedComponents) : 
     993                                                params.clone()); 
    1374994                                    yCount = new double[m_timeBins]; 
    1375995                                    for (int b = 0; b < m_timeBins; ++b) { 
     
    13911011        ICurveFitData dataArray[] = curveFitDataList.toArray(new ICurveFitData[0]); 
    13921012        if (m_cancel) { 
     1013            cancelImageFit(); 
    13931014            return; 
    13941015        } 
    1395         doFit(uiPanel, dataArray); 
    1396         //TODO save results 
     1016        // do the fit 
     1017        curveFitter.fitData(dataArray, m_startBin, m_stopBin); 
     1018        // save the fitted information 
     1019        setFittedParamsFromData(cursor, dataArray); 
     1020 
     1021        uiPanel.setFittedComponents(m_fittedComponents); //TODO kind of strange since I got that info from uiPanel earlier...  This s/b reset(true) or something 
     1022 
     1023        ImagePlus imp = ImageUtils.createImagePlus(m_fittedImage, "Fitted results"); 
     1024        IJ.runPlugIn(imp, "imagej.visad.VisADPlugin", ""); 
    13971025 
    13981026        long elapsed = System.nanoTime() - start; 
     
    14011029 
    14021030    /** 
    1403      * Processes (fits) a batch of pixels. 
     1031     * Helper routine to create imglib.Image to store fitted results. 
     1032     * 
     1033     * @param width 
     1034     * @param height 
     1035     * @param components 
     1036     * @return 
     1037     */ 
     1038    private Image<DoubleType> makeImage(int width, int height, int components) { 
     1039        Image<DoubleType> image = null; 
     1040 
     1041        // create image object 
     1042        int dim[] = { width, height, components }; //TODO when we keep chi square in image  ++components }; 
     1043        image = new ImageFactory<DoubleType>(new DoubleType(), new PlanarContainerFactory()).createImage(dim, "Fitted"); 
     1044 
     1045        // initialize image 
     1046        Cursor<DoubleType> cursor = image.createCursor(); 
     1047        while (cursor.hasNext()) { 
     1048            cursor.fwd(); 
     1049            cursor.getType().set(Double.NaN); 
     1050        } 
     1051 
     1052        return image; 
     1053    } 
     1054 
     1055    private double[] getFittedParams(LocalizableByDimCursor<DoubleType> cursor, int x, int y, int components) { 
     1056        double params[] = new double[components]; 
     1057        int position[] = new int[3]; 
     1058        position[0] = x; 
     1059        position[1] = y; 
     1060        for (int i = 0; i < components; ++i) { 
     1061            position[2] = i; 
     1062            cursor.setPosition(position); 
     1063            params[i] = cursor.getType().getRealDouble(); 
     1064        } 
     1065        return params; 
     1066    } 
     1067 
     1068    private void setFittedParamsFromData(LocalizableByDimCursor<DoubleType> cursor, ICurveFitData dataArray[]) { 
     1069        int x, y; 
     1070        double[] params; 
     1071        for (ICurveFitData data : dataArray) { 
     1072            setFittedParams(cursor, data.getX(), data.getY(), data.getParams()); 
     1073        } 
     1074    } 
     1075 
     1076    private void setFittedParams(LocalizableByDimCursor<DoubleType> cursor, int x, int y, double[] params) { 
     1077        int position[] = new int[3]; 
     1078        position[0] = x; 
     1079        position[1] = y; 
     1080        for (int i = 0; i < params.length; ++i) { 
     1081            position[2] = i; 
     1082            cursor.setPosition(position); 
     1083            cursor.getType().set(params[i]); 
     1084        } 
     1085    } 
     1086 
     1087    private void cancelImageFit() { 
     1088        m_fittedImage = null; 
     1089        m_fittedComponents = 0; 
     1090    } 
     1091 
     1092    /** 
     1093     * Visibly processes a batch of pixels. 
    14041094     * 
    14051095     * @param dataColorizer automatically sets colorization range and updates colorized image 
     
    14081098     * @param pixels parallel list of rectangles with which to draw the fitted pixel 
    14091099     */ 
    1410     void processPixels(IUserInterfacePanel uiPanel, DataColorizer dataColorizer, int height, ICurveFitData data[], ChunkyPixel pixels[]) { 
    1411         doFit(uiPanel, data); 
    1412         //TODO save results 
     1100    void colorizePixels(DataColorizer dataColorizer, int height, ICurveFitData data[], ChunkyPixel pixels[]) { 
    14131101 
    14141102        // draw as you go; 'chunky' pixels get smaller as the overall fit progresses 
     
    15731261 
    15741262    /* 
    1575      * Helper function for the fit.  Does the actual fit. 
    1576      *  
    1577      * @param dataArray array of data to fit 
    1578      */ 
    1579     //TODO shouldn't be creating many curveFitters for each chunk of pixels. 
    1580     //TODO s/b a mechanism to add these curve fit libraries? 
    1581     private void doFit(IUserInterfacePanel uiPanel, ICurveFitData dataArray[]) { 
    1582         // do the fit 
     1263     * Gets the appropriate curve fitter for the current fit. 
     1264     * 
     1265     * @param uiPanel has curve fitter selection 
     1266     */ 
     1267    private ICurveFitter getCurveFitter(IUserInterfacePanel uiPanel) { 
    15831268        ICurveFitter curveFitter = null; 
    15841269        switch (uiPanel.getAlgorithm()) { 
     
    16131298        curveFitter.setXInc(m_timeRange); 
    16141299        curveFitter.setFree(uiPanel.getFree()); 
    1615         curveFitter.fitData(dataArray, m_startBin, m_stopBin); 
     1300        return curveFitter; 
    16161301    } 
    16171302 
Note: See TracChangeset for help on using the changeset viewer.