Changeset 7206


Ignore:
Timestamp:
11/12/10 21:30:47 (9 years ago)
Author:
aivar
Message:

Added analysis plugin. Made gray scale a separate class.

File:
1 edited

Legend:

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

    r7168 r7206  
    3737import ij.IJ; 
    3838import ij.ImagePlus; 
    39 import ij.ImageStack; 
    4039import ij.gui.GenericDialog; 
    41 import ij.gui.ImageWindow; 
    42 import ij.gui.NonBlockingGenericDialog; 
    4340import ij.gui.Roi; 
    4441import ij.plugin.frame.RoiManager; 
    45 import ij.process.ByteProcessor; 
    4642import ij.process.ColorProcessor; 
    4743import ij.process.ImageProcessor; 
     
    5450import java.awt.Color; 
    5551import java.awt.Rectangle; 
    56 import java.awt.event.MouseEvent; 
    57 import java.awt.event.MouseListener; 
    58 import java.awt.image.ColorModel; 
    5952import java.util.ArrayList; 
    60 import java.util.HashMap; 
    61 import java.util.HashSet; 
    62 import java.util.List; 
    63 import java.util.Map; 
    64 import java.util.Set; 
    6553import java.util.prefs.Preferences; 
    6654 
    67 import javax.swing.JComponent; 
    6855import javax.swing.JFrame; 
    69 import javax.swing.JPanel; 
    7056 
    7157import loci.slim.colorizer.DataColorizer; 
     
    7460import loci.slim.ui.IUserInterfacePanelListener; 
    7561import loci.slim.ui.UserInterfacePanel; 
    76 import loci.common.DataTools; 
    7762import loci.curvefitter.CurveFitData; 
    7863import loci.curvefitter.GrayCurveFitter; 
     
    8368import loci.curvefitter.MarkwardtCurveFitter; 
    8469import loci.curvefitter.SLIMCurveFitter; 
    85 import loci.formats.ChannelSeparator; 
    86 import loci.formats.FormatException; 
    8770import loci.formats.FormatTools; 
    8871import loci.formats.IFormatReader; 
    89  
    90 import mpicbg.imglib.cursor.LocalizableByDimCursor; 
    91 import mpicbg.imglib.image.Image; 
    92 import mpicbg.imglib.type.numeric.RealType; 
    93  
    94  
    95 import mpicbg.imglib.container.Container; 
    96 import mpicbg.imglib.container.basictypecontainer.PlanarAccess; 
    97 import mpicbg.imglib.container.basictypecontainer.array.ArrayDataAccess; 
    98 import mpicbg.imglib.container.basictypecontainer.array.ByteArray; 
    99 import mpicbg.imglib.container.basictypecontainer.array.CharArray; 
    100 import mpicbg.imglib.container.basictypecontainer.array.DoubleArray; 
    101 import mpicbg.imglib.container.basictypecontainer.array.FloatArray; 
    102 import mpicbg.imglib.container.basictypecontainer.array.IntArray; 
    103 import mpicbg.imglib.container.basictypecontainer.array.LongArray; 
    104 import mpicbg.imglib.container.basictypecontainer.array.ShortArray; 
     72import loci.slim.analysis.SLIMAnalysis; 
     73 
    10574import mpicbg.imglib.container.planar.PlanarContainerFactory; 
    10675import mpicbg.imglib.cursor.Cursor; 
     
    10978import mpicbg.imglib.image.ImageFactory; 
    11079import mpicbg.imglib.type.numeric.RealType; 
    111 import mpicbg.imglib.type.numeric.integer.ByteType; 
    112 import mpicbg.imglib.type.numeric.integer.IntType; 
    113 import mpicbg.imglib.type.numeric.integer.ShortType; 
    114 import mpicbg.imglib.type.numeric.integer.UnsignedByteType; 
    115 import mpicbg.imglib.type.numeric.integer.UnsignedIntType; 
    116 import mpicbg.imglib.type.numeric.integer.UnsignedShortType; 
    11780import mpicbg.imglib.type.numeric.real.DoubleType; 
    118 import mpicbg.imglib.type.numeric.real.FloatType; 
    119  
     81 
     82 
     83//TODO tidy up SLIMProcessor 
    12084/** 
    121  * TODO 
    122  * 
    123  * <dl><dt><b>Source code:</b></dt> 
    124  * <dd><a href="http://dev.loci.wisc.edu/trac/java/browser/trunk/projects/slim-plugin/src/main/java/loci/SLIMProcessor.java">Trac</a>, 
    125  * <a href="http://dev.loci.wisc.edu/svn/java/trunk/projects/slim-plugin/src/main/java/loci/SLIMProcessor.java">SVN</a></dd></dl> 
     85 * SLIMProcessor is the main class of the SLIM Plugin.  It was originally just thrown 
     86 * together to get something working, with some code/techniques borrowed from SLIM Plotter. 
     87 * Parts of this code are ugly & experimental. 
    12688 * 
    12789 * @author Aivar Grislis grislis at wisc.edu 
     
    13597    private static final boolean USE_LAMBDA = false; 
    13698 
    137     // this affects how lifetimes are colorized: 
     99    // this affects how lifetimes are colorized: //TODO get rid of this 
    138100    private static final double MAXIMUM_LIFETIME = 0.075; // for fitting fake with Jaolho // for fitting brian with barber triple integral 100.0f X tau vs lambda issue here 
    139101 
     
    170132    IFormatReader m_reader; 
    171133 
    172     // Actual data values, dimensioned [channel][row][column][bin] 
     134    private Image<T> m_image; 
     135 
     136    // Actual data values, dimensioned [channel][row][column][bin] //TODO DEPRECATE 
    173137    protected int[][][][] m_data; 
    174138 
     
    177141 
    178142    private Image<DoubleType> m_fittedImage = null; 
    179     private int m_fittedComponents = 0; 
    180  
    181     // data parameters //TODO Curtis has these as protected 
     143    private int m_fittedParameterCount = 0; 
     144    boolean m_visibleFit = true; 
     145 
     146    // data parameters 
     147    private int m_channels; 
    182148    private int m_width; 
    183149    private int m_height; 
    184150    private int[] m_cLengths; 
    185151    private int m_timeBins; 
    186     private int m_channels; 
    187152    private int m_lifetimeIndex; 
    188153    private int m_spectraIndex; 
     
    211176    private FitFunction m_function; 
    212177 
     178    private SLIMAnalysis m_analysis; 
     179 
     180    private IGrayScaleImage m_grayScaleImage; 
     181    // user sets these from the grayScalePanel 
     182    private int m_channel; 
     183    private boolean m_fitAllChannels; 
     184 
     185    // current channel, x, y 
     186    private int m_xchannel; // channel to fit; -1 means fit all channels 
    213187    private int m_x; 
    214188    private int m_y; 
    215     private int m_channel; 
     189    private int m_xvisibleChannel; // channel being displayed; -1 means none 
    216190 
    217191    private double[] m_param = new double[7]; 
     
    227201 
    228202    public SLIMProcessor() { 
     203        m_analysis = new SLIMAnalysis(); 
    229204        m_quit = false; 
    230205        m_cancel = false; 
     
    236211        boolean success = false; 
    237212 
    238         if (newLoadData(image)) {             
     213        m_image = image; 
     214        if (newLoadData(image)) { 
    239215            // show the UI; do fits 
    240             IUserInterfacePanel uiPanel = new UserInterfacePanel(false); // using lambda 
    241             uiPanel.setX(0); 
    242             uiPanel.setY(0); 
    243             uiPanel.setStart(m_timeBins / 2); 
    244             uiPanel.setStop(m_timeBins - 1); 
    245             uiPanel.setThreshold(100); 
    246             uiPanel.setFunctionParameters(0, DEFAULT_SINGLE_EXP_PARAMS); 
    247             uiPanel.setFunctionParameters(1, DEFAULT_DOUBLE_EXP_PARAMS); 
    248             uiPanel.setFunctionParameters(2, DEFAULT_TRIPLE_EXP_PARAMS); 
    249             uiPanel.setFunctionParameters(3, DEFAULT_STRETCH_EXP_PARAMS); 
    250             uiPanel.setListener( 
    251                     new IUserInterfacePanelListener() { 
    252                         public void doFit() { 
    253                             m_cancel = false; 
    254                             m_fitInProgress = true; 
    255                         } 
    256  
    257                         public void cancelFit() { 
    258                             m_cancel = true; 
    259                         } 
    260  
    261                         public void quit() { 
    262                             m_quit = true; 
    263                         } 
    264  
    265                     } 
    266                 ); 
    267             uiPanel.getFrame().setLocationRelativeTo(null); 
    268             uiPanel.getFrame().setVisible(true); 
    269  
    270             // create a grayscale image from the data 
    271             createGlobalGrayScale("TITLE", uiPanel); 
    272  
    273             // loops infinitely; waits for UI 
    274             doFits(uiPanel); 
     216            doFits(); 
    275217        } 
    276218    } 
     
    282224     */ 
    283225    public void process(String arg) { 
    284         m_channel = 0; //TODO s/b a JSlider that controls current channel 
    285          
    286226        boolean success = false; 
    287227        if (showFileDialog(getFileFromPreferences())) { 
     
    291231            } 
    292232            else { 
    293                 if (newLoadData(loadImage(m_file))) { 
     233                m_image = loadImage(m_file); 
     234                if (newLoadData(m_image)) { 
    294235                    saveFileInPreferences(m_file); 
    295236                    success = true; 
     
    300241        if (success) { 
    301242            // show the UI; do fits 
    302             IUserInterfacePanel uiPanel = new UserInterfacePanel(USE_TAU); 
    303             uiPanel.setX(0); 
    304             uiPanel.setY(0); 
    305             uiPanel.setStart(m_timeBins / 2); 
    306             uiPanel.setStop(m_timeBins - 1); 
    307             uiPanel.setThreshold(100); 
    308             uiPanel.setFunctionParameters(0, DEFAULT_SINGLE_EXP_PARAMS); 
    309             uiPanel.setFunctionParameters(1, DEFAULT_DOUBLE_EXP_PARAMS); 
    310             uiPanel.setFunctionParameters(2, DEFAULT_TRIPLE_EXP_PARAMS); 
    311             uiPanel.setFunctionParameters(3, DEFAULT_STRETCH_EXP_PARAMS); 
    312             uiPanel.setListener( 
    313                 new IUserInterfacePanelListener() { 
    314                     public void doFit() { 
    315                         m_cancel = false; 
    316                         m_fitInProgress = true; 
    317                     } 
    318  
    319                     public void cancelFit() { 
    320                         m_cancel = true; 
    321                     } 
    322  
    323                     public void quit() { 
    324                         m_quit = true; 
    325                     } 
    326  
    327                 } 
    328             ); 
    329             uiPanel.getFrame().setLocationRelativeTo(null); 
    330             uiPanel.getFrame().setVisible(true); 
    331  
    332             // create a grayscale image from the data 
    333             createGlobalGrayScale("TITLE", uiPanel); 
    334  
    335             // loops infinitely; waits for UI 
    336             doFits(uiPanel); 
    337         } 
    338     } 
    339  
    340     /** 
     243            doFits(); 
     244        } 
     245    } 
     246 
     247    /** 
     248     * Creates a user interface panel.  Shows a grayscale 
     249     * version of the image. 
     250     * 
    341251     * Loops until quitting time and handles fit requests. 
    342252     * Fitting is driven by a button on the UI panel which 
     
    345255     * @param uiPanel 
    346256     */ 
    347     private void doFits(IUserInterfacePanel uiPanel) { 
     257    private void doFits() { 
     258        // show the UI; do fits 
     259        final IUserInterfacePanel uiPanel = new UserInterfacePanel(USE_TAU, m_analysis); 
     260        uiPanel.setX(0); 
     261        uiPanel.setY(0); 
     262        uiPanel.setStart(m_timeBins / 2); //TODO hokey 
     263        uiPanel.setStop(m_timeBins - 1); 
     264        uiPanel.setThreshold(100); 
     265        uiPanel.setFunctionParameters(0, DEFAULT_SINGLE_EXP_PARAMS); 
     266        uiPanel.setFunctionParameters(1, DEFAULT_DOUBLE_EXP_PARAMS); 
     267        uiPanel.setFunctionParameters(2, DEFAULT_TRIPLE_EXP_PARAMS); 
     268        uiPanel.setFunctionParameters(3, DEFAULT_STRETCH_EXP_PARAMS); 
     269        uiPanel.setListener( 
     270            new IUserInterfacePanelListener() { 
     271                public void doFit() { 
     272                    m_cancel = false; 
     273                    m_fitInProgress = true; 
     274                } 
     275 
     276                public void cancelFit() { 
     277                    m_cancel = true; 
     278                } 
     279 
     280                public void quit() { 
     281                    m_quit = true; 
     282                } 
     283 
     284            } 
     285        ); 
     286        uiPanel.getFrame().setLocationRelativeTo(null); 
     287        uiPanel.getFrame().setVisible(true); 
     288 
     289        // create a grayscale image from the data 
     290        m_grayScaleImage = new GrayScaleImage("TITLE", m_image); 
     291        m_grayScaleImage.setListener( 
     292            new ISelectListener() { 
     293                public void selected(int channel, int x, int y) { 
     294                    // just ignore clicks during a fit 
     295                    if (!m_fitInProgress) { 
     296                        synchronized (m_synchFit) { 
     297                            uiPanel.setX(x); 
     298                            uiPanel.setY(y); 
     299                            // fit on the pixel clicked 
     300                            fitPixel(uiPanel, x, y); 
     301                        } 
     302                    } 
     303                } 
     304            } 
     305        ); 
     306 
     307        // processing loop; waits for UI panel input 
    348308        while (!m_quit) { 
    349309            while (!m_fitInProgress) { 
     
    358318                } 
    359319            } 
     320 
     321            //uiPanel.enable(false); //TODO this might be better to be same as grayScalePanel 
     322            m_grayScaleImage.enable(false); 
     323 
    360324            // get settings of requested fit 
    361             getFitSettings(uiPanel); 
    362  
     325            getFitSettings(m_grayScaleImage, uiPanel); 
     326 
     327            // do the fit 
    363328            fitData(uiPanel); 
    364329 
    365330            m_fitInProgress = false; 
     331            //uiPanel.enable(true); 
     332            m_grayScaleImage.enable(true); 
    366333            uiPanel.reset(); 
    367334        } 
    368335    } 
    369336 
    370     private void getFitSettings(IUserInterfacePanel uiPanel) { 
    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(); 
     337    private void getFitSettings(IGrayScaleImage grayScalePanel, IUserInterfacePanel uiPanel) { 
     338        m_channel        = grayScalePanel.getChannel(); 
     339 
     340        m_region         = uiPanel.getRegion(); 
     341        m_algorithm      = uiPanel.getAlgorithm(); 
     342        m_function       = uiPanel.getFunction(); 
     343        m_fitAllChannels = uiPanel.getFitAllChannels(); 
     344 
     345        m_x              = uiPanel.getX(); 
     346        m_y              = uiPanel.getY(); 
     347        m_startBin       = uiPanel.getStart(); 
     348        m_stopBin        = uiPanel.getStop(); 
     349        m_threshold      = uiPanel.getThreshold(); 
     350 
     351        m_param          = uiPanel.getParameters(); 
     352        m_free           = uiPanel.getFree(); 
    384353    } 
    385354 
     
    429398        m_height = ImageUtils.getHeight(image); 
    430399        m_channels = ImageUtils.getNChannels(image); 
     400        //TODO this is broken; returns 1 when there are 16 channels; corrected below 
     401        System.out.println("ImageUtils.getNChannels returns " + m_channels); 
     402        if (dimensions.length > 3) { 
     403            m_channels = dimensions[3]; 
     404        } 
     405        System.out.println("corrected to " + m_channels); 
    431406        m_timeBins = ImageUtils.getDimSize(image, FormatTools.LIFETIME); 
    432407        System.out.println("timeBins is " + m_timeBins); 
     
    434409        xIndex = index++; 
    435410        yIndex = index++; 
     411        lifetimeIndex = index++; 
    436412        if (m_channels > 1) { 
    437             channelIndex = index++; 
     413            channelIndex = index; 
    438414        } 
    439415        else { 
    440416            channelIndex = null; 
    441417        } 
    442         lifetimeIndex = index; 
    443418 
    444419        System.out.println("width " + m_width + " height " + m_height + " timeBins " + m_timeBins + " channels " + m_channels); 
     
    458433                        cursor.moveTo(dimensions); 
    459434                        m_data[channel][y][x][bin] = (int) cursor.getType().getRealFloat(); 
    460                         m_data[channel][y][x][bin] /= 10.0f; //TODO in accordance with TRI2 
     435                        //TODO don't do this, screws up low photon count images...  m_data[channel][y][x][bin] /= 10.0f; //TODO in accordance with TRI2; HOLY COW!!!  ALSO int vs float??? why? 
    461436                    } 
    462437                } 
     
    483458 
    484459        // patch things up 
    485         m_timeRange = 10.0f / 64.0f; //TODO ARG this patches things up in accord with TRI2 for brian/gpl1.sdt; very odd value here 
     460        m_timeRange = 10.0f / 64.0f; //TODO ARG this patches things up in accord with TRI2 for brian/gpl1.sdt; very odd value here NOTE this was with photon counts all divided by 10.0f above! might have cancelled out. 
    486461        m_minWave = 400; 
    487462        m_waveStep = 10; 
     
    520495                lambda = 0.05 + x * 0.0005d; //0.0001 + x * .001; //0.5 + x * 0.01; // .002500 + x * .01; 
    521496                //System.out.println("lambda " + lambda + " color " + lambdaColorMap(MAXIMUM_LAMBDA, lambda)); 
    522                 dataColorizer.setData(x, y, lambda); 
     497                dataColorizer.setData(true, x, y, lambda); 
    523498                //imageProcessor.setColor(lifetimeColorMap(MAXIMUM_LIFETIME, lambda)); 
    524499                //imageProcessor.drawPixel(x, y); 
     
    555530        Preferences prefs = Preferences.userNodeForPackage(this.getClass()); 
    556531        prefs.put(FILE_KEY, file); 
    557     } 
    558  
    559     /** 
    560      * This dialog shows the parameters from the .sdt file and allows user 
    561      * to edit 
    562      * 
    563      * @return whether successful 
    564      */ 
    565     private boolean showParamsDialog() { 
    566         //TODO shouldn't UI be in separate class? 
    567         GenericDialog dialog = new GenericDialog("Parameters"); 
    568         dialog.addNumericField("Image width: ",         m_width,     0, 8, "pixels"); 
    569         dialog.addNumericField("Image height: ",        m_height,    0, 8, "pixels"); 
    570         dialog.addNumericField("Time bins: ",           m_timeBins,  0, 8, ""); 
    571         dialog.addNumericField("Channel count: ",       m_channels,  0, 8, ""); 
    572         dialog.addNumericField("Time range: ",          m_timeRange, 0, 8, "nanoseconds"); 
    573         dialog.addNumericField("Starting wavelength: ", m_minWave,   0, 8, "nanometers"); 
    574         dialog.addNumericField("Channel width: ",       m_waveStep,  0, 8, "nanometers"); 
    575         dialog.showDialog(); 
    576         if (dialog.wasCanceled()) { 
    577             return false; 
    578         } 
    579         m_width     = (int) dialog.getNextNumber(); 
    580         m_height    = (int) dialog.getNextNumber(); 
    581         m_timeBins  = (int) dialog.getNextNumber(); 
    582         m_channels  = (int) dialog.getNextNumber(); 
    583         m_timeRange = (int) dialog.getNextNumber(); 
    584         m_minWave   = (int) dialog.getNextNumber(); 
    585         m_waveStep  = (int) dialog.getNextNumber(); 
    586         return true; 
    587     } 
    588  
    589     /** 
    590      * This routine sums all of the photon data and creates a grayscale 
    591      * image for the data. 
    592      * 
    593      * @param uiPanel associated UI panel 
    594      * @return whether successful 
    595      */ 
    596     private boolean createGlobalGrayScale(String name, final IUserInterfacePanel uiPanel) { 
    597         int[][] pixels = new int[m_width][m_height]; 
    598         byte[] outPixels = new byte[m_width * m_height]; 
    599  
    600  
    601         ImageStack imageStack = new ImageStack(m_width, m_height, ColorModel.getRGBdefault(), null); 
    602         for (int c = 0; c < m_channels; ++c) { 
    603             // sum photon counts 
    604             int maxPixel = 0; 
    605             for (int x = 0; x < m_width; ++x) { 
    606                 for (int y = 0; y < m_height; ++y) { 
    607                     pixels[x][y] = 0; 
    608                     for (int b = 0; b < m_timeBins; ++b) { 
    609                         pixels[x][y] += m_data[c][y][x][b]; 
    610                     } 
    611                     if (pixels[x][y] > maxPixel) { 
    612                         maxPixel = pixels[x][y]; 
    613                     } 
    614                 } 
    615             } 
    616  
    617             // convert to grayscale 
    618             for (int x = 0; x < m_width; ++x) { 
    619                 for (int y = 0; y < m_height; ++y) { 
    620                     // flip y axis to correspond with Slim Plotter image 
    621                     outPixels[y * m_width + x] = (byte) (pixels[x][m_height - y - 1] * 255 / maxPixel); 
    622                 } 
    623             } 
    624  
    625             // add a slice 
    626             imageStack.addSlice("" + c, true, outPixels); 
    627         } 
    628         ImagePlus imagePlus = new ImagePlus(name + " GrayScale", imageStack); 
    629         imagePlus.show(); 
    630         m_grayscaleImageProcessor = imagePlus.getChannelProcessor(); 
    631  
    632         // hook up mouse listener 
    633         ImageWindow imageWindow = imagePlus.getWindow(); 
    634         m_grayscaleCanvas = imageWindow.getCanvas(); 
    635         m_grayscaleCanvas.addMouseListener( 
    636             new MouseListener() { 
    637                 public void mousePressed(MouseEvent e) {} 
    638                 public void mouseExited(MouseEvent e) {} 
    639                 public void mouseClicked(MouseEvent e) {} 
    640                 public void mouseEntered(MouseEvent e) {} 
    641   
    642                 public void mouseReleased(MouseEvent e) { 
    643                     // just ignore clicks during a fit 
    644                     if (!m_fitInProgress) { 
    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                         } 
    651                     } 
    652                 } 
    653             } 
    654         ); 
    655         return true; 
    656532    } 
    657533 
     
    681557            } 
    682558        } 
     559        m_analysis.doAnalysis(uiPanel.getAnalysis(), m_fittedImage, uiPanel.getRegion(), uiPanel.getFunction()); //TODO get from uiPanel or get from global?  re-evaluate approach here 
    683560    } 
    684561 
     
    687564     */ 
    688565    private void fitSummed(IUserInterfacePanel uiPanel) { 
    689         double params[] = uiPanel.getParameters(); 
     566        double params[] = uiPanel.getParameters(); //TODO go cumulative 
    690567         
    691568        // build the data 
     
    703580        } 
    704581        int photons = 0; 
    705         for (int y = 0; y < m_height; ++y) { 
    706             for (int x = 0; x < m_width; ++x) { 
    707                 for (int b = 0; b < m_timeBins; ++b) { 
    708                     yCount[b] += m_data[m_channel][y][x][b]; 
    709                     photons += m_data[m_channel][y][x][b]; 
    710                 } 
    711             } 
    712         } 
    713         System.out.println("SUMMED photons " + photons); 
     582         
     583        if (-1 == m_channel) { 
     584            // sum all of the channels 
     585            for (int channel = 0; channel < m_channels; ++channel) { 
     586                for (int y = 0; y < m_height; ++y) { 
     587                    for (int x = 0; x < m_width; ++x) { 
     588                        for (int b = 0; b < m_timeBins; ++b) { 
     589                            yCount[b] += m_data[channel][y][x][b]; 
     590                            photons += m_data[channel][y][x][b]; 
     591                        } 
     592                    } 
     593                } 
     594            } 
     595        } 
     596        else { 
     597            // sum selected channel 
     598            for (int y = 0; y < m_height; ++y) { 
     599                for (int x = 0; x < m_width; ++x) { 
     600                    for (int b = 0; b < m_timeBins; ++b) { 
     601                        yCount[b] += m_data[m_channel][y][x][b]; 
     602                        photons += m_data[m_channel][y][x][b]; 
     603                    } 
     604                } 
     605            }     
     606        } 
     607        System.out.println("Summed photons " + photons); 
     608 
    714609        curveFitData.setYCount(yCount); 
    715610        yFitted = new double[m_timeBins]; 
     
    842737    private void fitEachPixel(IUserInterfacePanel uiPanel) { 
    843738        long start = System.nanoTime(); 
     739        int pixelCount = 0; 
     740        int totalPixelCount = totalPixelCount(m_width, m_height, m_channels, m_fitAllChannels); 
     741        int pixelsToProcessCount = 0; 
    844742 
    845743        ICurveFitter curveFitter = getCurveFitter(uiPanel);      
     
    848746        boolean useFittedParams; 
    849747        LocalizableByDimCursor<DoubleType> cursor = null; 
    850         if (null == m_fittedImage || uiPanel.getComponents() != m_fittedComponents) { 
     748        if (null == m_fittedImage || uiPanel.getParameterCount() != m_fittedParameterCount) { 
    851749            // can't use previous results 
    852750            useFittedParams = false; 
    853             m_fittedComponents = uiPanel.getComponents(); 
    854             m_fittedImage = makeImage(100, 200, m_fittedComponents); 
     751            int channels = m_channels; 
     752            m_fittedParameterCount = uiPanel.getParameterCount(); 
     753            m_fittedImage = makeImage(channels, m_width, m_height, m_fittedParameterCount); 
    855754        } 
    856755        else { 
     
    867766        double yFitted[]; 
    868767 
     768    System.out.println("m_channel is " + m_channel); 
     769 
    869770        // special handling for visible channel 
    870         int visibleChannel = m_channel; //TODO somehow else; m_channel s/b 0 
    871         if (-1 != visibleChannel) { 
     771        if (m_visibleFit) { 
    872772            // show colorized image 
    873773            DataColorizer dataColorizer = new DataColorizer(m_width, m_height, m_algorithm + " Fitted Lifetimes"); 
     
    875775            ChunkyPixelEffectIterator pixelIterator = new ChunkyPixelEffectIterator(new ChunkyPixelTableImpl(), m_width, m_height); 
    876776 
    877             int pixelCount = 0; 
    878             int pixelsToProcessCount = 0; 
    879             while (pixelIterator.hasNext()) { 
    880                 ++pixelCount; 
     777            while (!m_cancel && pixelIterator.hasNext()) { 
    881778                if (m_cancel) { 
    882                     IJ.showProgress(0, 0); //TODO kludgy to have this here and also below 
     779                    IJ.showProgress(0, 0); //TODO kludgy to have this here and also below; get rid of this but make the dataColorizer go away regardless 
    883780                    dataColorizer.quit(); 
    884781                    cancelImageFit(); 
    885782                    return; 
    886783                } 
    887                 IJ.showProgress(pixelCount, m_height * m_width); 
     784                IJ.showProgress(++pixelCount, totalPixelCount); 
    888785                ChunkyPixel pixel = pixelIterator.next(); 
    889                 if (wantFitted(pixel.getX(), pixel.getY())) { 
     786                if (wantFitted(m_channel, pixel.getX(), pixel.getY())) { 
    890787                    curveFitData = new CurveFitData(); 
     788                    curveFitData.setChannel(m_channel); 
    891789                    curveFitData.setX(pixel.getX()); 
    892790                    curveFitData.setY(pixel.getY()); 
    893791                    curveFitData.setParams( 
    894792                            useFittedParams ? 
    895                                 getFittedParams(cursor, pixel.getX(), pixel.getY(), m_fittedComponents) : 
     793                                getFittedParams(cursor, m_channel, pixel.getX(), pixel.getY(), m_fittedParameterCount) : 
    896794                                params.clone()); 
    897795                    yCount = new double[m_timeBins]; 
    898796                    for (int b = 0; b < m_timeBins; ++b) { 
    899                         yCount[b] = m_data[visibleChannel][pixel.getY()][pixel.getX()][b]; 
     797                        yCount[b] = m_data[m_channel][pixel.getY()][pixel.getX()][b]; 
    900798                    } 
    901799                    curveFitData.setYCount(yCount); 
     
    905803                    pixelList.add(pixel); 
    906804 
    907  
     805                    // process the pixels 
    908806                    if (++pixelsToProcessCount >= PIXEL_COUNT) { 
     807                        pixelsToProcessCount = 0; 
    909808                        ICurveFitData[] data = curveFitDataList.toArray(new ICurveFitData[0]); 
     809                        curveFitDataList.clear(); 
    910810                        curveFitter.fitData(data, m_startBin, m_stopBin); 
    911811                        setFittedParamsFromData(cursor, data); 
    912                         colorizePixels(dataColorizer, m_height, data, pixelList.toArray(new ChunkyPixel[0])); 
    913  
    914                         curveFitDataList.clear(); 
     812                        colorizePixels(dataColorizer, m_height, m_channel, data, pixelList.toArray(new ChunkyPixel[0])); 
    915813                        pixelList.clear(); 
    916                         pixelsToProcessCount = 0; 
    917814                    } 
    918815                } 
    919816            } 
    920             if (!m_cancel && 0 < pixelsToProcessCount) { 
     817            // handle any leftover pixels 
     818            if (!m_cancel && pixelsToProcessCount > 0) { 
     819                pixelsToProcessCount = 0; 
    921820                ICurveFitData[] data = curveFitDataList.toArray(new ICurveFitData[0]); 
     821                curveFitDataList.clear(); 
    922822                curveFitter.fitData(data, m_startBin, m_stopBin); 
    923823                setFittedParamsFromData(cursor, data); 
    924                 colorizePixels(dataColorizer, m_height, data, pixelList.toArray(new ChunkyPixel[0])); 
     824                colorizePixels(dataColorizer, m_height, m_channel, data, pixelList.toArray(new ChunkyPixel[0])); 
    925825            } 
    926826        } 
     
    932832        } 
    933833  
    934         // any channels remaining? 
    935         if (-1 == visibleChannel || m_channels > 1) { 
    936             // fit rest of channels in expeditious way 
    937             Roi[] rois = getRois(); 
    938             // are there ROIs defined? 
    939             if (0 < rois.length) { 
    940                 for (Roi roi: rois) { 
    941                     // yes, use ROI bounding boxes to limit iteration 
    942                     Rectangle bounds = roi.getBounds(); 
    943                     for (int x = 0; x < bounds.width; ++x) { 
    944                         for (int y = 0; y < bounds.height; ++y) { 
    945                             if (roi.contains(bounds.x + x, bounds.y + y)) { 
    946                                 for (int channel = 0; channel < m_channels; ++channel) { 
    947                                     if (channel != visibleChannel) { 
    948                                         if (m_cancel) { 
    949                                             cancelImageFit(); 
    950                                             return; 
    951                                         } 
    952                                         if (wantFitted(bounds.x + x, bounds.y + y)) { 
    953                                             curveFitData = new CurveFitData(); 
    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()); 
    960                                             yCount = new double[m_timeBins]; 
    961                                             for (int b = 0; b < m_timeBins; ++b) { 
    962                                                 yCount[b] = m_data[channel][y][x][b]; 
    963                                             } 
    964                                             curveFitData.setYCount(yCount); 
    965                                             yFitted = new double[m_timeBins]; 
    966                                             curveFitData.setYFitted(yFitted); 
    967                                             curveFitDataList.add(curveFitData); 
    968                                         } 
    969                                     } 
    970                                 } 
    971                             } 
    972                         } 
     834        // any channels still to be fitted? 
     835        for (int channel : channelIndexArray(m_channel, m_channels, m_visibleFit, m_fitAllChannels)) { 
     836            for (int y = 0; y < m_height; ++y) { 
     837                for (int x = 0; x < m_width; ++x) { 
     838                    if (m_visibleFit) { 
     839                        IJ.showProgress(++pixelCount, totalPixelCount); 
    973840                    } 
    974                 } 
    975             } 
    976             else { 
    977                 // no ROIs, loop over entire image 
    978                 for (int channel = 0; channel < m_channels; ++channel) { 
    979                     if (channel != visibleChannel) { 
    980                         for (int y = 0; y < m_height; ++y) { 
    981                             for (int x = 0; x < m_width; ++x) { 
    982                                 if (m_cancel) { 
    983                                     cancelImageFit(); 
    984                                     return; 
    985                                 } 
    986                                 if (aboveThreshold(x, y)) { 
    987                                     curveFitData = new CurveFitData(); 
    988                                     curveFitData.setX(x); 
    989                                     curveFitData.setY(y); 
    990                                     curveFitData.setParams( 
    991                                             useFittedParams ? 
    992                                                 getFittedParams(cursor, x, y, m_fittedComponents) : 
    993                                                 params.clone()); 
    994                                     yCount = new double[m_timeBins]; 
    995                                     for (int b = 0; b < m_timeBins; ++b) { 
    996                                         yCount[b] = m_data[channel][y][x][b]; 
    997                                     } 
    998                                     curveFitData.setYCount(yCount); 
    999                                     yFitted = new double[m_timeBins]; 
    1000                                     curveFitData.setYFitted(yFitted); 
    1001                                     curveFitDataList.add(curveFitData); 
    1002                                 } 
    1003                             } 
    1004                         } 
     841  
     842                    if (wantFitted(channel, x, y)) { 
     843                         ++pixelsToProcessCount; 
     844                         curveFitData = new CurveFitData(); 
     845                         curveFitData.setChannel(channel); 
     846                         curveFitData.setX(x); 
     847                         curveFitData.setY(y); 
     848                         curveFitData.setParams( 
     849                             useFittedParams ? 
     850                                 getFittedParams(cursor, channel, x, y, m_fittedParameterCount) : 
     851                                 params.clone()); 
     852                         yCount = new double[m_timeBins]; 
     853                         for (int b = 0; b < m_timeBins; ++b) { 
     854                             yCount[b] = m_data[channel][y][x][b]; 
     855                         } 
     856                         curveFitData.setYCount(yCount); 
     857                         yFitted = new double[m_timeBins]; 
     858                         curveFitData.setYFitted(yFitted); 
     859                         curveFitDataList.add(curveFitData); 
    1005860                    } 
    1006  
    1007                 } 
    1008             } 
    1009         }      
    1010         //TODO break the fit up into chunks to lower memory requirements 
    1011         ICurveFitData dataArray[] = curveFitDataList.toArray(new ICurveFitData[0]); 
    1012         if (m_cancel) { 
    1013             cancelImageFit(); 
    1014             return; 
    1015         } 
    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", ""); 
     861                     
     862                    if (m_cancel) { 
     863                        cancelImageFit(); 
     864                        return; 
     865                    } 
     866                } 
     867                // every row, process pixels as needed 
     868                if (pixelsToProcessCount >= PIXEL_COUNT) { 
     869                    pixelsToProcessCount = 0; 
     870                    ICurveFitData[] data = curveFitDataList.toArray(new ICurveFitData[0]); 
     871                    curveFitDataList.clear(); 
     872                    curveFitter.fitData(data, m_startBin, m_stopBin); 
     873                    setFittedParamsFromData(cursor, data); 
     874                } 
     875            } 
     876        } 
     877        // handle any leftover pixels 
     878        if (pixelsToProcessCount > 0) { 
     879            ICurveFitData[] data = curveFitDataList.toArray(new ICurveFitData[0]); 
     880            curveFitter.fitData(data, m_startBin, m_stopBin); 
     881            setFittedParamsFromData(cursor, data); 
     882        } 
     883 
     884 
     885        uiPanel.setFittedParameterCount(m_fittedParameterCount); //TODO kind of strange since I got that info from uiPanel earlier...  This s/b reset(true) or something Also, it doesn't really do anything in uiPanel 
    1025886 
    1026887        long elapsed = System.nanoTime() - start; 
    1027888        System.out.println("nanoseconds " + elapsed); 
     889    } 
     890 
     891    /** 
     892     * Calculates the total number of pixels to fit.  Used for 
     893     * progress bar. 
     894     * 
     895     * @param channels 
     896     * @param fitAll 
     897     * @return 
     898     */ 
     899    private int totalPixelCount(int x, int y, int channels, boolean fitAll) { 
     900        int count = x * y; 
     901        if (fitAll) { 
     902            count *= channels; 
     903        } 
     904        return count; 
     905    } 
     906 
     907    /** 
     908     * Calculates an array of channel indices to iterate over. 
     909     * 
     910     * @param channel 
     911     * @param channels 
     912     * @param visibleFit 
     913     * @param fitAll 
     914     * @return 
     915     */ 
     916    private int[] channelIndexArray(int channel, int channels, boolean visibleFit, boolean fitAll) { 
     917        int returnValue[] = { }; 
     918        if (fitAll) { 
     919            returnValue = new int[visibleFit ? channels - 1 : channels]; 
     920            int i = 0; 
     921            for (int c = 0; c < channels; ++c) { 
     922                // skip visible; already processed 
     923                if (c != channel || !visibleFit) { 
     924                    returnValue[i++] = c; 
     925                } 
     926            } 
     927        } 
     928        else if (!visibleFit) { 
     929            // single channel, not processed yet 
     930            returnValue = new int[1]; 
     931            returnValue[0] = channel; 
     932        } 
     933        return returnValue; 
    1028934    } 
    1029935 
     
    1036942     * @return 
    1037943     */ 
    1038     private Image<DoubleType> makeImage(int width, int height, int components) { 
     944    private Image<DoubleType> makeImage(int channels, int width, int height, int parameters) { 
    1039945        Image<DoubleType> image = null; 
    1040946 
    1041947        // create image object 
    1042         int dim[] = { width, height, components }; //TODO when we keep chi square in image  ++components }; 
     948        int dim[] = { width, height, channels, parameters }; //TODO when we keep chi square in image  ++parameters }; 
    1043949        image = new ImageFactory<DoubleType>(new DoubleType(), new PlanarContainerFactory()).createImage(dim, "Fitted"); 
    1044950 
     
    1053959    } 
    1054960 
    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]; 
     961    private double[] getFittedParams(LocalizableByDimCursor<DoubleType> cursor, int channel, int x, int y, int count) { 
     962        double params[] = new double[count]; 
     963        int position[] = new int[4]; 
    1058964        position[0] = x; 
    1059965        position[1] = y; 
    1060         for (int i = 0; i < components; ++i) { 
    1061             position[2] = i; 
     966        position[2] = channel; 
     967        for (int i = 0; i < count; ++i) { 
     968            position[3] = i; 
    1062969            cursor.setPosition(position); 
    1063970            params[i] = cursor.getType().getRealDouble(); 
     
    1070977        double[] params; 
    1071978        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]; 
     979            setFittedParams(cursor, data.getChannel(), data.getX(), data.getY(), data.getParams()); 
     980        } 
     981    } 
     982 
     983    private void setFittedParams(LocalizableByDimCursor<DoubleType> cursor, int channel, int x, int y, double[] params) { 
     984        int position[] = new int[4]; 
    1078985        position[0] = x; 
    1079986        position[1] = y; 
     987        position[2] = channel; 
    1080988        for (int i = 0; i < params.length; ++i) { 
    1081             position[2] = i; 
     989            position[3] = i; 
    1082990            cursor.setPosition(position); 
    1083991            cursor.getType().set(params[i]); 
     
    1087995    private void cancelImageFit() { 
    1088996        m_fittedImage = null; 
    1089         m_fittedComponents = 0; 
     997        m_fittedParameterCount = 0; 
    1090998    } 
    1091999 
     
    10951003     * @param dataColorizer automatically sets colorization range and updates colorized image 
    10961004     * @param height passed in to fix a vertical orientation problem 
     1005     * @channel current channel 
    10971006     * @param data list of data corresponding to pixels to be fitted 
    10981007     * @param pixels parallel list of rectangles with which to draw the fitted pixel 
    10991008     */ 
    1100     void colorizePixels(DataColorizer dataColorizer, int height, ICurveFitData data[], ChunkyPixel pixels[]) { 
     1009    void colorizePixels(DataColorizer dataColorizer, int height, int channel, ICurveFitData data[], ChunkyPixel pixels[]) { 
    11011010 
    11021011        // draw as you go; 'chunky' pixels get smaller as the overall fit progresses 
     
    11261035            //Color color = lifetimeColorMap(MAXIMUM_LIFETIME, lifetime); 
    11271036            //imageProcessor.setColor(color); 
    1128  
    11291037            boolean firstTime = true; 
    11301038            for (int x = pixel.getX(); x < pixel.getX() + pixel.getWidth(); ++x) { 
    11311039                for (int y = pixel.getY(); y < pixel.getY() + pixel.getHeight(); ++y) { 
    1132                     if (wantFitted(x, y)) { 
     1040                    if (wantFitted(channel, x, y)) { 
    11331041                        // (flip vertically) 
    11341042                        dataColorizer.setData(firstTime, x, height - y - 1 , lifetime); 
     
    11441052     * Checks criterion for whether this pixel needs to get fitted or drawn. 
    11451053     * 
     1054     * @param channel 
    11461055     * @param x 
    11471056     * @param y 
    11481057     * @return whether to include or ignore this pixel 
    11491058     */ 
    1150     boolean wantFitted(int x, int y) { 
    1151         return (aboveThreshold(x, y) & isInROIs(x, y)); 
     1059    boolean wantFitted(int channel, int x, int y) { 
     1060        return (aboveThreshold(channel, x, y) & isInROIs(x, y)); 
    11521061    } 
    11531062 
     
    11551064     * Checks whether a given pixel is above threshold photon count value. 
    11561065     * 
     1066     * @param channel 
    11571067     * @param x 
    11581068     * @param y 
    11591069     * @return whether above threshold 
    11601070     */ 
    1161     boolean aboveThreshold(int x, int y) { 
    1162         //TODO should the threshold be the same for all channels? 
    1163         return (m_threshold <= m_grayscaleImageProcessor.getPixel(x, m_height - y - 1)); 
     1071    boolean aboveThreshold(int channel, int x, int y) { 
     1072        return (m_threshold <= m_grayScaleImage.getPixel(channel, x, m_height - y - 1)); 
    11641073    } 
    11651074 
Note: See TracChangeset for help on using the changeset viewer.