Changeset 1854


Ignore:
Timestamp:
11/27/06 15:58:02 (14 years ago)
Author:
curtis
Message:

Add option to override Z axis scale; more work on tau colorization option.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/loci/apps/slim/SlimPlotter.java

    r1841 r1854  
    3434 
    3535/** A tool for visualization of spectral lifetime data. */ 
    36 public class SlimPlotter implements ActionListener, 
    37   ChangeListener, DisplayListener, Runnable, WindowListener 
     36public class SlimPlotter implements ActionListener, ChangeListener, 
     37  DisplayListener, DocumentListener, Runnable, WindowListener 
    3838{ 
    3939 
     
    9494  private JRadioButton fitSurface, fitLines; 
    9595  private JRadioButton resSurface, resLines; 
     96  private JRadioButton colorHeight, colorTau; 
     97  private JSpinner numCurves; 
    9698  private JCheckBox showData, showScale; 
    9799  private JCheckBox showBox, showLine; 
    98100  private JCheckBox showFit, showResiduals; 
    99   private JSpinner numCurves; 
     101  private JCheckBox zOverride; 
     102  private JTextField zScaleValue; 
    100103  private JButton exportData; 
    101104 
     
    557560    intensityPane.add(sliderPane, BorderLayout.SOUTH); 
    558561    cSlider = new JSlider(1, channels, 1); 
     562    cSlider.setToolTipText( 
     563      "Selects the channel to display in the 2D intensity plot above"); 
    559564    cSlider.setSnapToTicks(true); 
    560565    cSlider.setMajorTickSpacing(channels / 4); 
     
    565570    sliderPane.add(cSlider); 
    566571    cToggle = new JCheckBox("", true); 
     572    cToggle.setToolTipText( 
     573      "Toggles the selected channel's visibility in the 3D data plot"); 
    567574    cToggle.addActionListener(this); 
    568575    sliderPane.add(cToggle); 
     
    581588 
    582589    decayLabel = new JLabel("Decay curve for all pixels"); 
     590    decayLabel.setToolTipText( 
     591      "Displays information about the selected region of interest"); 
    583592    decayPane.add(decayLabel, BorderLayout.NORTH); 
    584593 
     
    588597 
    589598    linear = new JRadioButton("Linear", true); 
     599    linear.setToolTipText("Plots 3D data with a linear scale"); 
    590600    log = new JRadioButton("Log", false); 
     601    log.setToolTipText("Plots 3D data with a logarithmic scale"); 
    591602    perspective = new JRadioButton("Perspective", true); 
     603    perspective.setToolTipText( 
     604      "Displays 3D plot with a perspective projection"); 
    592605    parallel = new JRadioButton("Parallel", false); 
     606    parallel.setToolTipText( 
     607      "Displays 3D plot with a parallel (orthographic) projection"); 
    593608    dataSurface = new JRadioButton("Surface", true); 
     609    dataSurface.setToolTipText("Displays raw data as a 2D surface"); 
    594610    dataLines = new JRadioButton("Lines", false); 
     611    dataLines.setToolTipText("Displays raw data as a series of lines"); 
    595612    fitSurface = new JRadioButton("Surface", false); 
     613    fitSurface.setToolTipText("Displays fitted curves as a 2D surface"); 
    596614    fitLines = new JRadioButton("Lines", true); 
     615    fitLines.setToolTipText("Displays fitted curves as a series of lines"); 
    597616    resSurface = new JRadioButton("Surface", false); 
     617    resSurface.setToolTipText( 
     618      "Displays fitted curve residuals as a 2D surface"); 
    598619    resLines = new JRadioButton("Lines", true); 
     620    resLines.setToolTipText( 
     621      "Displays fitted curve residuals as a series of lines"); 
     622    colorHeight = new JRadioButton("Counts", true); 
     623    colorHeight.setToolTipText( 
     624      "Colorizes data according to the height (histogram count)"); 
     625    colorTau = new JRadioButton("Lifetimes", false); 
     626    colorTau.setToolTipText( 
     627      "Colorizes data according to aggregate lifetime value"); 
     628 
     629    numCurves = new JSpinner(new SpinnerNumberModel(1, 1, 9, 1)); 
     630    numCurves.setToolTipText("Number of components in exponential fit"); 
     631    numCurves.setMaximumSize(numCurves.getPreferredSize()); 
     632    numCurves.addChangeListener(this); 
    599633 
    600634    JPanel showPanel = new JPanel(); 
     
    603637 
    604638    showData = new JCheckBox("Data", true); 
     639    showData.setToolTipText("Toggles visibility of raw data"); 
    605640    showData.addActionListener(this); 
    606641    showPanel.add(showData); 
    607642    showScale = new JCheckBox("Scale", true); 
     643    showScale.setToolTipText("Toggles visibility of scale bars"); 
    608644    showScale.addActionListener(this); 
    609645    showPanel.add(showScale); 
    610646    showBox = new JCheckBox("Box", true); 
     647    showBox.setToolTipText("Toggles visibility of bounding box"); 
    611648    showBox.addActionListener(this); 
    612649    showPanel.add(showBox); 
    613650    showLine = new JCheckBox("Line", adjustPeaks); 
     651    showLine.setToolTipText( 
     652      "Toggles visibility of aligned peaks indicator line"); 
    614653    showLine.setEnabled(adjustPeaks); 
    615654    showLine.addActionListener(this); 
    616655    showPanel.add(showLine); 
    617656    showFit = new JCheckBox("Fit", false); 
     657    showFit.setToolTipText("Toggles visibility of fitted curves"); 
    618658    showFit.setEnabled(adjustPeaks); 
    619659    showFit.addActionListener(this); 
    620660    showPanel.add(showFit); 
    621661    showResiduals = new JCheckBox("Residuals", false); 
     662    showResiduals.setToolTipText( 
     663      "Toggles visibility of fitted curve residuals"); 
    622664    showResiduals.setEnabled(adjustPeaks); 
    623665    showResiduals.addActionListener(this); 
    624666    showPanel.add(showResiduals); 
    625667 
    626     numCurves = new JSpinner(new SpinnerNumberModel(1, 1, 9, 1)); 
    627     numCurves.setMaximumSize(numCurves.getPreferredSize()); 
    628     numCurves.addChangeListener(this); 
     668    JPanel scalePanel = new JPanel(); 
     669    scalePanel.setBorder(new TitledBorder("Z Scale Override")); 
     670    scalePanel.setLayout(new BoxLayout(scalePanel, BoxLayout.X_AXIS)); 
     671 
     672    zOverride = new JCheckBox("", false); 
     673    zOverride.setToolTipText("Toggles manual override of Z axis scale (Count)"); 
     674    zOverride.addActionListener(this); 
     675    scalePanel.add(zOverride); 
     676    zScaleValue = new JTextField(9); 
     677    zScaleValue.setToolTipText("Overridden Z axis scale value"); 
     678    zScaleValue.setEnabled(false); 
     679    zScaleValue.getDocument().addDocumentListener(this); 
     680    scalePanel.add(zScaleValue); 
    629681 
    630682    exportData = new JButton("Export"); 
     683    exportData.setToolTipText( 
     684      "Exports the selected ROI's raw data to a text file"); 
    631685    exportData.addActionListener(this); 
    632686 
    633     progress.setProgress(99); // estimate: 99% 
     687    progress.setProgress(990); // estimate: 99% 
    634688    if (progress.isCanceled()) System.exit(0); 
    635689 
     
    658712    options1.add(makeRadioPanel("Fit", fitSurface, fitLines)); 
    659713    options1.add(makeRadioPanel("Residuals", resSurface, resLines)); 
     714    options1.add(makeRadioPanel("Colors", colorHeight, colorTau)); 
    660715//    options1.add(numCurves); 
    661716    JPanel options2 = new JPanel(); 
    662717    options2.setLayout(new BoxLayout(options2, BoxLayout.X_AXIS)); 
    663718    options2.add(showPanel); 
     719    options2.add(scalePanel); 
    664720    options2.add(Box.createHorizontalStrut(5)); 
    665721    options2.add(exportData); 
     
    681737    progress.setProgress(1000); 
    682738    progress.close(); 
    683     plotData(true, true); 
     739    plotData(true, true, true); 
    684740 
    685741    try { Thread.sleep(200); } 
     
    692748  private Thread plotThread; 
    693749  private boolean plotCanceled; 
    694   private boolean doRescale, doRefit; 
     750  private boolean doRecalc, doRescale, doRefit; 
    695751 
    696752  /** Plots the data in a separate thread. */ 
    697   public void plotData(final boolean rescale, final boolean refit) { 
     753  public void plotData(final boolean recalc, 
     754    final boolean rescale, final boolean refit) 
     755  { 
    698756    final SlimPlotter sp = this; 
    699757    new Thread("PlotSpawner") { 
     
    706764            catch (InterruptedException exc) { exc.printStackTrace(); } 
    707765          } 
     766          sp.doRecalc = recalc; 
    708767          sp.doRescale = rescale; 
    709768          sp.doRefit = refit; 
     
    726785    if (roiY >= height) roiY = height - 1; 
    727786    roiCount = 1; 
    728     plotData(rescale, refit); 
     787    plotData(true, rescale, refit); 
    729788  } 
    730789 
     
    746805      int c = cSlider.getValue() - 1; 
    747806      cVisible[c] = !cVisible[c]; 
    748       plotData(true, false); 
    749     } 
    750     else if (src == dataSurface || src == dataLines) plotData(false, false); 
     807      plotData(true, true, false); 
     808    } 
     809    else if (src == linear || src == log) plotData(true, true, true); 
     810    else if (src == dataSurface || src == dataLines || 
     811      src == colorHeight || src == colorTau) 
     812    { 
     813      plotData(true, false, false); 
     814    } 
    751815    else if (src == fitSurface || src == fitLines || 
    752816      src == resSurface || src == resLines) 
    753817    { 
    754       plotData(false, true); 
    755     } 
    756     else if (src == linear || src == log) plotData(true, true); 
     818      plotData(true, false, true); 
     819    } 
    757820    else if (src == perspective || src == parallel) { 
    758821      try { 
     
    781844    else if (src == showResiduals) { 
    782845      resRend.toggle(showResiduals.isSelected()); 
     846    } 
     847    else if (src == zOverride) { 
     848      boolean manual = zOverride.isSelected(); 
     849      zScaleValue.setEnabled(manual); 
     850      if (!manual) plotData(true, true, false); 
    783851    } 
    784852    else if (src == exportData) { 
     
    843911      cToggle.addActionListener(this); 
    844912    } 
    845     else if (src == numCurves) plotData(false, true); 
     913    else if (src == numCurves) plotData(true, false, true); 
    846914  } 
    847915 
     
    887955          } 
    888956          roiPercent = 100000 * roiCount / (width * height) / 1000.0; 
    889           plotData(true, true); 
     957          plotData(true, true, true); 
    890958        } 
    891959      } 
     
    907975  } 
    908976 
     977  // -- DocumentListener methods -- 
     978 
     979  public void changedUpdate(DocumentEvent e) { updateZAxis(); } 
     980  public void insertUpdate(DocumentEvent e) { updateZAxis(); } 
     981  public void removeUpdate(DocumentEvent e) { updateZAxis(); } 
     982 
    909983  // -- Runnable methods -- 
    910984 
    911985  public void run() { 
    912     ProgressMonitor progress = new ProgressMonitor(null, "Plotting data", 
    913       "Calculating sums", 0, 
    914       channels * timeBins + (doRefit ? channels : 0) + 1); 
    915     progress.setMillisToPopup(100); 
    916     progress.setMillisToDecideToPopup(50); 
    917     int p = 0; 
    918     if (roiCount == 1) { 
    919       decayLabel.setText("Decay curve for " + "(" + roiX + ", " + roiY + ")"); 
    920     } 
    921     else { 
    922       decayLabel.setText("Decay curve for " + roiCount + 
    923         " pixels (" + roiPercent + "%)"); 
    924     } 
    925     boolean doDataLines = dataLines.isSelected(); 
    926     boolean doFitLines = fitLines.isSelected(); 
    927     boolean doResLines = resLines.isSelected(); 
    928     boolean doLog = log.isSelected(); 
    929  
    930     // calculate samples 
    931     int numChanVis = 0; 
    932     for (int c=0; c<channels; c++) { 
    933       if (cVisible[c]) numChanVis++; 
    934     } 
    935     samps = new float[numChanVis * timeBins]; 
    936     maxVal = 0; 
    937     for (int c=0, cc=0; c<channels; c++) { 
    938       if (!cVisible[c]) continue; 
    939       for (int t=0; t<timeBins; t++) { 
    940         int ndx = timeBins * cc + t; 
    941         int sum = 0; 
    942         if (roiCount == 1) sum = values[c][roiY][roiX][t]; 
    943         else { 
    944           for (int h=0; h<height; h++) { 
    945             for (int w=0; w<width; w++) { 
    946               if (roiMask[h][w]) sum += values[c][h][w][t]; 
    947             } 
    948           } 
    949         } 
    950         samps[ndx] = sum; 
    951         if (doLog) samps[ndx] = (float) Math.log(samps[ndx] + 1); 
    952         if (samps[ndx] > maxVal) maxVal = samps[ndx]; 
    953         progress.setProgress(++p); 
    954         if (progress.isCanceled()) plotCanceled = true; 
    955         if (plotCanceled) break; 
    956       } 
    957       if (plotCanceled) break; 
    958       cc++; 
    959     } 
    960  
    961     double[][] fitResults = null; 
    962     int numExp = ((Integer) numCurves.getValue()).intValue(); 
    963     if (adjustPeaks && doRefit) { 
    964       // perform exponential curve fitting: y(x) = a * e^(-b*t) + c 
    965       progress.setNote("Fitting curves"); 
    966       fitResults = new double[channels][]; 
    967       ExpFunction func = new ExpFunction(numExp); 
    968       float[] params = new float[3 * numExp]; 
    969       if (numExp == 1) { 
    970         params[0] = maxVal; 
    971         params[1] = 1; 
    972         params[2] = 0; 
    973       } 
    974       else if (numExp == 2) { 
    975         params[0] = maxVal / 2; 
    976         params[1] = 0.8f; 
    977         params[2] = 0; 
    978         params[0] = maxVal / 2; 
    979         params[1] = 2; 
    980         params[2] = 0; 
    981       } 
    982 //      for (int i=0; i<numExp; i++) { 
    983 //        // initial guess for (a, b, c) 
    984 //        int e = 3 * i; 
    985 //        params[e] = (numExp - i) * maxVal / (numExp + 1); 
    986 //        params[e + 1] = 1; 
    987 //        params[e + 2] = 0; 
    988 //      } 
    989       int num = timeBins - maxPeak; 
    990       float[] xVals = new float[num]; 
    991       for (int i=0; i<num; i++) xVals[i] = i; 
    992       float[] yVals = new float[num]; 
    993       float[] weights = new float[num]; 
    994       Arrays.fill(weights, 1); // no weighting 
    995       log("Computing fit parameters: y(t) = a * e^(-t/" + TAU + ") + c"); 
    996       for (int c=0, cc=0; c<channels; c++) { 
    997         if (!cVisible[c]) { 
    998           fitResults[c] = null; 
    999           continue; 
    1000         } 
    1001         log("\tChannel #" + (c + 1) + ":"); 
    1002         System.arraycopy(samps, timeBins * cc + maxPeak, yVals, 0, num); 
    1003         LMA lma = null; 
    1004         lma = new LMA(func, params, new float[][] {xVals, yVals}, 
    1005           weights, new JAMAMatrix(params.length, params.length)); 
    1006         lma.fit(); 
    1007         log("\t\titerations=" + lma.iterationCount); 
    1008         log("\t\tchi2=" + lma.chi2); 
    1009         for (int i=0; i<numExp; i++) { 
    1010           int e = 3 * i; 
    1011           log("\t\ta" + i + "=" + lma.parameters[e]); 
    1012           log("\t\t" + TAU + i + "=" + (1 / lma.parameters[e + 1])); 
    1013           log("\t\tc" + i + "=" + lma.parameters[e + 2]); 
    1014         } 
    1015         fitResults[c] = lma.parameters; 
    1016         progress.setProgress(++p); 
    1017         cc++; 
    1018       } 
    1019     } 
    1020  
    1021     try { 
    1022       // construct domain set for 3D surface plots 
    1023       float[][] bcGrid = new float[2][timeBins * numChanVis]; 
     986    if (doRecalc) { 
     987      ProgressMonitor progress = new ProgressMonitor(null, "Plotting data", 
     988        "Calculating sums", 0, 
     989        channels * timeBins + (doRefit ? channels : 0) + 1); 
     990      progress.setMillisToPopup(100); 
     991      progress.setMillisToDecideToPopup(50); 
     992      int p = 0; 
     993      if (roiCount == 1) { 
     994        decayLabel.setText("Decay curve for " + "(" + roiX + ", " + roiY + ")"); 
     995      } 
     996      else { 
     997        decayLabel.setText("Decay curve for " + roiCount + 
     998          " pixels (" + roiPercent + "%)"); 
     999      } 
     1000      boolean doLog = log.isSelected(); 
     1001      boolean doDataLines = dataLines.isSelected(); 
     1002      boolean doFitLines = fitLines.isSelected(); 
     1003      boolean doResLines = resLines.isSelected(); 
     1004      boolean doTauColors = colorTau.isSelected(); 
     1005 
     1006      // calculate samples 
     1007      int numChanVis = 0; 
     1008      for (int c=0; c<channels; c++) { 
     1009        if (cVisible[c]) numChanVis++; 
     1010      } 
     1011      samps = new float[numChanVis * timeBins]; 
     1012      maxVal = 0; 
    10241013      for (int c=0, cc=0; c<channels; c++) { 
    10251014        if (!cVisible[c]) continue; 
    10261015        for (int t=0; t<timeBins; t++) { 
    10271016          int ndx = timeBins * cc + t; 
    1028           bcGrid[0][ndx] = t * timeRange / (timeBins - 1); 
    1029           bcGrid[1][ndx] = c * (maxWave - minWave) / (channels - 1) + minWave; 
    1030         } 
     1017          int sum = 0; 
     1018          if (roiCount == 1) sum = values[c][roiY][roiX][t]; 
     1019          else { 
     1020            for (int h=0; h<height; h++) { 
     1021              for (int w=0; w<width; w++) { 
     1022                if (roiMask[h][w]) sum += values[c][h][w][t]; 
     1023              } 
     1024            } 
     1025          } 
     1026          samps[ndx] = sum; 
     1027          if (doLog) samps[ndx] = (float) Math.log(samps[ndx] + 1); 
     1028          if (samps[ndx] > maxVal) maxVal = samps[ndx]; 
     1029          progress.setProgress(++p); 
     1030          if (progress.isCanceled()) plotCanceled = true; 
     1031          if (plotCanceled) break; 
     1032        } 
     1033        if (plotCanceled) break; 
    10311034        cc++; 
    10321035      } 
    1033       Gridded2DSet bcSet = new Gridded2DSet(bc, bcGrid, 
    1034         timeBins, numChanVis, null, bcUnits, null, false); 
    1035  
    1036       // compile color values for 3D surface plot 
    1037       float[] colors = new float[numChanVis * timeBins]; 
    1038       for (int c=0, cc=0; c<channels; c++) { 
    1039         if (!cVisible[c]) continue; 
    1040         for (int t=0; t<timeBins; t++) { 
    1041           int ndx = timeBins * c + t; 
    1042           colors[ndx] = samps[ndx]; // CTR TODO: use Tau value for this channel 
    1043         } 
    1044         cc++; 
    1045       } 
    1046  
    1047       // construct "Data" plot 
    1048       FlatField ff = new FlatField(bcvFunc, bcSet); 
    1049       ff.setSamples(new float[][] {samps, colors}, false); 
    1050       decayRef.setData(doDataLines ? makeLines(ff) : ff); 
    1051  
    1052       if (fitResults != null) { 
    1053         // compute finite sampling matching fitted exponentials 
    1054         float[] fitSamps = new float[numChanVis * timeBins]; 
    1055         float[] residuals = new float[numChanVis * timeBins]; 
     1036 
     1037      double[][] fitResults = null; 
     1038      int numExp = ((Integer) numCurves.getValue()).intValue(); 
     1039      float[][] tau = new float[channels][numExp]; 
     1040      for (int c=0; c<channels; c++) Arrays.fill(tau[c], Float.NaN); 
     1041      if (adjustPeaks && doRefit) { 
     1042        // perform exponential curve fitting: y(x) = a * e^(-b*t) + c 
     1043        progress.setNote("Fitting curves"); 
     1044        fitResults = new double[channels][]; 
     1045        ExpFunction func = new ExpFunction(numExp); 
     1046        float[] params = new float[3 * numExp]; 
     1047        if (numExp == 1) { 
     1048          params[0] = maxVal; 
     1049          params[1] = 1; 
     1050          params[2] = 0; 
     1051        } 
     1052        else if (numExp == 2) { 
     1053          params[0] = maxVal / 2; 
     1054          params[1] = 0.8f; 
     1055          params[2] = 0; 
     1056          params[0] = maxVal / 2; 
     1057          params[1] = 2; 
     1058          params[2] = 0; 
     1059        } 
     1060  //      for (int i=0; i<numExp; i++) { 
     1061  //        // initial guess for (a, b, c) 
     1062  //        int e = 3 * i; 
     1063  //        params[e] = (numExp - i) * maxVal / (numExp + 1); 
     1064  //        params[e + 1] = 1; 
     1065  //        params[e + 2] = 0; 
     1066  //      } 
     1067        int num = timeBins - maxPeak; 
     1068        float[] xVals = new float[num]; 
     1069        for (int i=0; i<num; i++) xVals[i] = i; 
     1070        float[] yVals = new float[num]; 
     1071        float[] weights = new float[num]; 
     1072        Arrays.fill(weights, 1); // no weighting 
     1073        log("Computing fit parameters: y(t) = a * e^(-t/" + TAU + ") + c"); 
     1074        for (int c=0, cc=0; c<channels; c++) { 
     1075          if (!cVisible[c]) { 
     1076            fitResults[c] = null; 
     1077            continue; 
     1078          } 
     1079          log("\tChannel #" + (c + 1) + ":"); 
     1080          System.arraycopy(samps, timeBins * cc + maxPeak, yVals, 0, num); 
     1081          LMA lma = null; 
     1082          lma = new LMA(func, params, new float[][] {xVals, yVals}, 
     1083            weights, new JAMAMatrix(params.length, params.length)); 
     1084          lma.fit(); 
     1085          log("\t\titerations=" + lma.iterationCount); 
     1086          log("\t\tchi2=" + lma.chi2); 
     1087          for (int i=0; i<numExp; i++) { 
     1088            int e = 3 * i; 
     1089            log("\t\ta" + i + "=" + lma.parameters[e]); 
     1090            tau[c][i] = (float) (1 / lma.parameters[e + 1]); 
     1091            log("\t\t" + TAU + i + "=" + tau[c][i]); 
     1092            log("\t\tc" + i + "=" + lma.parameters[e + 2]); 
     1093          } 
     1094          fitResults[c] = lma.parameters; 
     1095          progress.setProgress(++p); 
     1096          cc++; 
     1097        } 
     1098      } 
     1099 
     1100      try { 
     1101        // construct domain set for 3D surface plots 
     1102        float[][] bcGrid = new float[2][timeBins * numChanVis]; 
    10561103        for (int c=0, cc=0; c<channels; c++) { 
    10571104          if (!cVisible[c]) continue; 
    1058           double[] q = fitResults[c]; 
    10591105          for (int t=0; t<timeBins; t++) { 
    10601106            int ndx = timeBins * cc + t; 
    1061             int et = t - maxPeak; // adjust for peak alignment 
    1062             if (et < 0) fitSamps[ndx] = residuals[ndx] = 0; 
    1063             else { 
    1064               float sum = 0; 
    1065               for (int i=0; i<numExp; i++) { 
    1066                 int e = 3 * i; 
    1067                 sum += (float) (q[e] * Math.exp(-q[e + 1] * et) + q[e + 2]); 
    1068               } 
    1069               fitSamps[ndx] = sum; 
    1070               residuals[ndx] = samps[ndx] - fitSamps[ndx]; 
    1071             } 
     1107            bcGrid[0][ndx] = t * timeRange / (timeBins - 1); 
     1108            bcGrid[1][ndx] = c * (maxWave - minWave) / (channels - 1) + minWave; 
    10721109          } 
    10731110          cc++; 
    10741111        } 
    1075  
    1076         // construct "Fit" plot 
    1077         FlatField fit = new FlatField(bcvFuncFit, bcSet); 
    1078         fit.setSamples(new float[][] {fitSamps}, false); 
    1079         fitRef.setData(doFitLines ? makeLines(fit) : fit); 
    1080  
    1081         // construct "Residuals" plot 
    1082         FlatField res = new FlatField(bcvFuncRes, bcSet); 
    1083         res.setSamples(new float[][] {residuals}, false); 
    1084         resRef.setData(doResLines ? makeLines(res) : res); 
    1085       } 
    1086  
    1087       if (doRescale) { 
    1088         float max = maxVal == 0 ? 1 : maxVal; 
    1089         zMap.setRange(0, max); 
    1090         zMapFit.setRange(0, max); 
    1091         zMapRes.setRange(0, max); 
    1092         vMap.setRange(0, max); 
     1112        Gridded2DSet bcSet = new Gridded2DSet(bc, bcGrid, 
     1113          timeBins, numChanVis, null, bcUnits, null, false); 
     1114 
     1115        // compile color values for 3D surface plot 
     1116        float[] colors = new float[numChanVis * timeBins]; 
     1117        for (int c=0, cc=0; c<channels; c++) { 
     1118          if (!cVisible[c]) continue; 
     1119          for (int t=0; t<timeBins; t++) { 
     1120            int ndx = timeBins * c + t; 
     1121            colors[ndx] = doTauColors ? tau[c][0] : samps[ndx]; 
     1122          } 
     1123          cc++; 
     1124        } 
     1125 
     1126        // construct "Data" plot 
     1127        FlatField ff = new FlatField(bcvFunc, bcSet); 
     1128        ff.setSamples(new float[][] {samps, colors}, false); 
     1129        decayRef.setData(doDataLines ? makeLines(ff) : ff); 
     1130 
     1131        if (fitResults != null) { 
     1132          // compute finite sampling matching fitted exponentials 
     1133          float[] fitSamps = new float[numChanVis * timeBins]; 
     1134          float[] residuals = new float[numChanVis * timeBins]; 
     1135          for (int c=0, cc=0; c<channels; c++) { 
     1136            if (!cVisible[c]) continue; 
     1137            double[] q = fitResults[c]; 
     1138            for (int t=0; t<timeBins; t++) { 
     1139              int ndx = timeBins * cc + t; 
     1140              int et = t - maxPeak; // adjust for peak alignment 
     1141              if (et < 0) fitSamps[ndx] = residuals[ndx] = 0; 
     1142              else { 
     1143                float sum = 0; 
     1144                for (int i=0; i<numExp; i++) { 
     1145                  int e = 3 * i; 
     1146                  sum += (float) (q[e] * Math.exp(-q[e + 1] * et) + q[e + 2]); 
     1147                } 
     1148                fitSamps[ndx] = sum; 
     1149                residuals[ndx] = samps[ndx] - fitSamps[ndx]; 
     1150              } 
     1151            } 
     1152            cc++; 
     1153          } 
     1154 
     1155          // construct "Fit" plot 
     1156          FlatField fit = new FlatField(bcvFuncFit, bcSet); 
     1157          fit.setSamples(new float[][] {fitSamps}, false); 
     1158          fitRef.setData(doFitLines ? makeLines(fit) : fit); 
     1159 
     1160          // construct "Residuals" plot 
     1161          FlatField res = new FlatField(bcvFuncRes, bcSet); 
     1162          res.setSamples(new float[][] {residuals}, false); 
     1163          resRef.setData(doResLines ? makeLines(res) : res); 
     1164        } 
     1165      } 
     1166      catch (Exception exc) { exc.printStackTrace(); } 
     1167      progress.setProgress(++p); 
     1168      progress.close(); 
     1169    } 
     1170 
     1171    if (doRescale) { 
     1172      float d = Float.NaN; 
     1173      boolean manual = zOverride.isSelected(); 
     1174      if (manual) { 
     1175        try { d = Float.parseFloat(zScaleValue.getText()); } 
     1176        catch (NumberFormatException exc) { } 
     1177      } 
     1178      else { 
     1179        zScaleValue.getDocument().removeDocumentListener(this); 
     1180        zScaleValue.setText("" + maxVal); 
     1181        zScaleValue.getDocument().addDocumentListener(this); 
     1182      } 
     1183      float maxZ = d == d ? d : (maxVal == 0 ? 1 : maxVal); 
     1184      try { 
     1185        zMap.setRange(0, maxZ); 
     1186        zMapFit.setRange(0, maxZ); 
     1187        zMapRes.setRange(0, maxZ); 
     1188        //vMap.setRange(0, max); 
    10931189        //vMapFit.setRange(0, max); 
    10941190        //vMapRes.setRange(0, max); 
    1095         //decayPlot.reAutoScale(); 
    1096       } 
    1097     } 
    1098     catch (Exception exc) { exc.printStackTrace(); } 
    1099     progress.setProgress(++p); 
    1100     progress.close(); 
     1191        decayPlot.reAutoScale(); 
     1192      } 
     1193      catch (Exception exc) { exc.printStackTrace(); } 
     1194    } 
    11011195    plotThread = null; 
    11021196  } 
     
    11611255  } 
    11621256 
     1257  private void updateZAxis() { 
     1258    float f = Float.NaN; 
     1259    try { f = Float.parseFloat(zScaleValue.getText()); } 
     1260    catch (NumberFormatException exc) { } 
     1261    if (f == f) plotData(false, true, false); 
     1262  } 
     1263 
    11631264  // -- Utility methods -- 
    11641265 
Note: See TracChangeset for help on using the changeset viewer.