Changeset 4243


Ignore:
Timestamp:
07/23/08 15:56:01 (12 years ago)
Author:
curtis
Message:

Encapsulate core raw + derived data into SlimData class.

Location:
trunk/loci/slim
Files:
1 added
2 edited

Legend:

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

    r4241 r4243  
    4040import javax.swing.event.*; 
    4141import javax.swing.text.Document; 
    42 import loci.formats.in.SDTInfo; 
    43 import loci.formats.in.SDTReader; 
    44 import loci.formats.DataTools; 
    4542import loci.formats.gui.ExtensionFileFilter; 
    4643import loci.visbio.util.BreakawayPanel; 
     
    107104  // -- Fields -- 
    108105 
    109   /** Actual data values, dimensioned [channel][row][column][bin]. */ 
    110   private int[][][][] values; 
     106  /** Master data structure containing raw and derived SLIM data. */ 
     107  private SlimData data; 
    111108 
    112109  /** Current binned data values, dimensioned [channels * timeBins]. */ 
    113110  private float[] samps; 
    114  
    115   // data parameters 
    116   private int width, height; 
    117   private int channels, timeBins; 
    118   private float timeRange; 
    119   private int minWave, waveStep, maxWave; 
    120   private int numExp; 
    121   private boolean adjustPeaks, computeFWHMs, cutEnd; 
    122   private boolean useLMA; 
    123   private boolean[] cVisible; 
    124   private int maxPeak; 
    125111 
    126112  private float maxVal; 
     
    137123  private MenuItem menuViewSaveProj; 
    138124  private MenuItem menuViewLoadProj; 
    139  
    140   // GUI components for parameter dialog box 
    141   private JDialog paramDialog; 
    142   private JTextField wField, hField, tField, cField; 
    143   private JTextField trField, wlField, sField; 
    144   private JTextField fitField; 
    145   private JRadioButton gaChoice, lmChoice; 
    146   private JCheckBox peaksBox, fwhmBox, cutBox; 
    147125 
    148126  // GUI components for 2D pane 
     
    198176 
    199177    // progress estimate: 
    200     // * Reading data - 70% 
     178    // * Reading and processing data - 90% 
    201179    // * Creating types - 1% 
    202     // * Building displays - 7% 
    203     // * Constructing images - 14% 
    204     // * Adjusting peaks - 4% 
    205     // * Creating plots - 4% 
     180    // * Building displays - 6% 
     181    // * Creating plots - 3% 
    206182    ProgressMonitor progress = new ProgressMonitor(null, 
    207183      "Launching Slim Plotter", "Initializing", 0, 1000); 
     
    268244      } 
    269245 
    270       // read SDT file header 
    271       SDTReader reader = new SDTReader(); 
    272       reader.setId(file.getPath()); 
    273       width = reader.getSizeX(); 
    274       height = reader.getSizeY(); 
    275       timeBins = reader.getTimeBinCount(); 
    276       channels = reader.getChannelCount(); 
    277       SDTInfo info = reader.getInfo(); 
    278       reader.close(); 
    279       timeRange = 12.5f; 
    280       minWave = 400; 
    281       waveStep = 10; 
    282  
    283       // show dialog confirming data parameters 
    284       showParamDialog(); 
    285       if (cVisible == null) System.exit(0); // dialog canceled (closed with X) 
    286       maxWave = minWave + (channels - 1) * waveStep; 
    287  
    288246      // pop up progress monitor 
    289247      setProgress(progress, 1); // estimate: 0.1% 
    290248 
    291       // read pixel data 
    292       progress.setNote("Reading data"); 
    293       DataInputStream fin = new DataInputStream(new FileInputStream(file)); 
    294       fin.skipBytes(info.dataBlockOffs + 22); // skip to data 
    295       byte[] data = new byte[2 * channels * height * width * timeBins]; 
    296       int blockSize = 65536; 
    297       for (int off=0; off<data.length; off+=blockSize) { 
    298         int len = data.length - off; 
    299         if (len > blockSize) len = blockSize; 
    300         fin.readFully(data, off, len); 
    301         setProgress(progress, (int) (700L * 
    302           (off + blockSize) / data.length)); // estimate: 0% -> 70% 
    303       } 
    304       fin.close(); 
     249      // read data 
     250      data = new SlimData(file.getPath(), progress); 
    305251 
    306252      // create types 
    307253      progress.setNote("Creating types"); 
    308       types = new SlimTypes(width, height, channels, minWave, maxWave); 
    309       setProgress(progress, 710); // estimate: 71% 
     254      types = new SlimTypes(data.width, data.height, 
     255        data.channels, data.minWave, data.maxWave); 
     256      setProgress(progress, 910); // estimate: 91% 
    310257 
    311258      // plot intensity data in 2D display 
     
    313260 
    314261      // plot decay curves in 3D display 
    315       decayPlot = channels > 1 ? new DisplayImplJ3D("decay") : 
     262      decayPlot = data.channels > 1 ? new DisplayImplJ3D("decay") : 
    316263        new DisplayImplJ3D("decay", new TwoDDisplayRendererJ3D()); 
    317264      ScalarMap xMap = new ScalarMap(types.bType, Display.XAxis); 
    318265      ScalarMap yMap = new ScalarMap(types.cType, Display.YAxis); 
    319       DisplayRealType heightAxis = channels > 1 ? Display.ZAxis : Display.YAxis; 
     266      DisplayRealType heightAxis = data.channels > 1 ? 
     267        Display.ZAxis : Display.YAxis; 
    320268      zMap = new ScalarMap(types.vType, heightAxis); 
    321269      zMapFit = new ScalarMap(types.vTypeFit, heightAxis); 
     
    325273      vMapRes = new ScalarMap(types.vTypeRes, Display.RGB); 
    326274      decayPlot.addMap(xMap); 
    327       if (channels > 1) decayPlot.addMap(yMap); 
     275      if (data.channels > 1) decayPlot.addMap(yMap); 
    328276      decayPlot.addMap(zMap); 
    329277      decayPlot.addMap(zMapFit); 
     
    332280      //decayPlot.addMap(vMapFit); 
    333281      decayPlot.addMap(vMapRes); 
    334       setProgress(progress, 720); // estimate: 72% 
     282      setProgress(progress, 950); // estimate: 95% 
    335283 
    336284      decayRend = new DefaultRendererJ3D(); 
     
    338286      decayPlot.addReferences(decayRend, decayRef); 
    339287 
    340       if (computeFWHMs) { 
     288      if (data.computeFWHMs) { 
    341289        // add reference for full width half maxes 
    342290        fwhmRend = new DefaultRendererJ3D(); 
     
    349297      } 
    350298 
    351       if (adjustPeaks) { 
     299      if (data.adjustPeaks) { 
    352300        // add references for curve fitting 
    353301        fitRend = new DefaultRendererJ3D(); 
     
    364312        resRend.toggle(false); 
    365313      } 
    366       setProgress(progress, 750); // estimate: 75% 
    367  
    368       xMap.setRange(0, timeRange); 
    369       yMap.setRange(minWave, maxWave); 
     314      setProgress(progress, 960); // estimate: 96% 
     315 
     316      xMap.setRange(0, data.timeRange); 
     317      yMap.setRange(data.minWave, data.maxWave); 
    370318      AxisScale xScale = xMap.getAxisScale(); 
    371319      Font font = Font.decode("serif 24"); 
     
    388336      gmc.setTextureEnable(false); 
    389337      ProjectionControl pc = decayPlot.getProjectionControl(); 
    390       pc.setMatrix(channels > 1 ? MATRIX_3D : MATRIX_2D); 
     338      pc.setMatrix(data.channels > 1 ? MATRIX_3D : MATRIX_2D); 
    391339      pc.setAspectCartesian( 
    392340        new double[] {2, 1, 1}); 
    393       setProgress(progress, 780); // estimate: 78% 
    394  
    395       // convert byte data to unsigned shorts 
    396       progress.setNote("Constructing images"); 
    397       values = new int[channels][height][width][timeBins]; 
    398       for (int c=0; c<channels; c++) { 
    399         int oc = timeBins * width * height * c; 
    400         for (int h=0; h<height; h++) { 
    401           int oh = timeBins * width * h; 
    402           for (int w=0; w<width; w++) { 
    403             int ow = timeBins * w; 
    404             for (int t=0; t<timeBins; t++) { 
    405               int ndx = 2 * (oc + oh + ow + t); 
    406               int val = DataTools.bytesToInt(data, ndx, 2, true); 
    407               values[c][h][w][t] = val; 
    408             } 
    409           } 
    410           setProgress(progress, 780 + 140 * 
    411             (height * c + h + 1) / (channels * height)); // estimate: 78% -> 92% 
    412         } 
    413       } 
    414  
    415       // adjust peaks 
    416       if (adjustPeaks) { 
    417         progress.setNote("Adjusting peaks"); 
    418         int[] peaks = new int[channels]; 
    419         for (int c=0; c<channels; c++) { 
    420           int[] sum = new int[timeBins]; 
    421           for (int h=0; h<height; h++) { 
    422             for (int w=0; w<width; w++) { 
    423               for (int t=0; t<timeBins; t++) sum[t] += values[c][h][w][t]; 
    424             } 
    425           } 
    426           int peak = 0, ndx = 0; 
    427           for (int t=0; t<timeBins; t++) { 
    428             if (peak <= sum[t]) { 
    429               peak = sum[t]; 
    430               ndx = t; 
    431             } 
    432             else if (t > timeBins / 3) break; // HACK - too early to give up 
    433           } 
    434           peaks[c] = ndx; 
    435           setProgress(progress, 920 + 20 * 
    436             (c + 1) / channels); // estimate: 92% -> 94% 
    437         } 
    438         maxPeak = 0; 
    439         for (int c=0; c<channels; c++) { 
    440           if (maxPeak < peaks[c]) maxPeak = peaks[c]; 
    441         } 
    442         log("Aligning peaks to tmax = " + maxPeak); 
    443         for (int c=0; c<channels; c++) { 
    444           int shift = maxPeak - peaks[c]; 
    445           if (shift > 0) { 
    446             for (int h=0; h<height; h++) { 
    447               for (int w=0; w<width; w++) { 
    448                 for (int t=timeBins-1; t>=shift; t--) { 
    449                   values[c][h][w][t] = values[c][h][w][t - shift]; 
    450                 } 
    451                 for (int t=shift-1; t>=0; t--) values[c][h][w][t] = 0; 
    452               } 
    453             } 
    454             log("\tChannel #" + (c + 1) + ": tmax = " + peaks[c] + 
    455               " (shifting by " + shift + ")"); 
    456           } 
    457           setProgress(progress, 940 + 20 * 
    458             (c + 1) / channels); // estimate: 94% -> 96% 
    459         } 
    460  
    461         // add yellow line to indicate adjusted peak position 
    462         lineRend = new DefaultRendererJ3D(); 
    463         DataReferenceImpl peakRef = new DataReferenceImpl("peaks"); 
    464         float peakTime = (float) (maxPeak * timeRange / (timeBins - 1)); 
    465         peakRef.setData(new Gridded2DSet(types.bc, 
    466           new float[][] {{peakTime, peakTime}, {minWave, maxWave}}, 2)); 
    467         decayPlot.addReferences(lineRend, peakRef, new ConstantMap[] { 
    468           new ConstantMap(-1, Display.ZAxis), 
    469           new ConstantMap(0, Display.Blue), 
    470           //new ConstantMap(2, Display.LineWidth) 
    471         }); 
    472       } 
     341      setProgress(progress, 970); // estimate: 97% 
    473342 
    474343      // construct 2D pane 
     
    480349      masterWindow.setContentPane(masterPane); 
    481350 
    482       twoDPane = new TwoDPane(this, values, numExp, 
    483         useLMA ? LMCurveFitter.class : GACurveFitter.class, cVisible, types); 
     351      twoDPane = new TwoDPane(this, data, types); 
    484352 
    485353      MenuBar menubar = new MenuBar(); 
     
    568436      showBox.setToolTipText("Toggles visibility of bounding box"); 
    569437      showBox.addActionListener(this); 
    570       showLine = new JCheckBox("Line", adjustPeaks); 
     438      showLine = new JCheckBox("Line", data.adjustPeaks); 
    571439      showLine.setToolTipText( 
    572440        "Toggles visibility of aligned peaks indicator line"); 
    573       showLine.setEnabled(adjustPeaks); 
     441      showLine.setEnabled(data.adjustPeaks); 
    574442      showLine.addActionListener(this); 
    575443      showFit = new JCheckBox("Fit", false); 
    576444      showFit.setToolTipText("Toggles visibility of fitted curves"); 
    577       showFit.setEnabled(adjustPeaks); 
     445      showFit.setEnabled(data.adjustPeaks); 
    578446      showFit.addActionListener(this); 
    579447      showResiduals = new JCheckBox("Residuals", false); 
    580448      showResiduals.setToolTipText( 
    581449        "Toggles visibility of fitted curve residuals"); 
    582       showResiduals.setEnabled(adjustPeaks); 
     450      showResiduals.setEnabled(data.adjustPeaks); 
    583451      showResiduals.addActionListener(this); 
    584       showFWHMs = new JCheckBox("FWHMs", computeFWHMs); 
     452      showFWHMs = new JCheckBox("FWHMs", data.computeFWHMs); 
    585453      showFWHMs.setToolTipText("Toggles visibility of full width half maxes"); 
    586       showFWHMs.setEnabled(computeFWHMs); 
     454      showFWHMs.setEnabled(data.computeFWHMs); 
    587455      showFWHMs.addActionListener(this); 
    588456 
     
    594462      perspective.setToolTipText( 
    595463        "Displays 3D plot with a perspective projection"); 
    596       perspective.setEnabled(channels > 1); 
     464      perspective.setEnabled(data.channels > 1); 
    597465      parallel = new JRadioButton("Parallel", false); 
    598466      parallel.setToolTipText( 
    599467        "Displays 3D plot with a parallel (orthographic) projection"); 
    600       parallel.setEnabled(channels > 1); 
    601       dataSurface = new JRadioButton("Surface", channels > 1); 
     468      parallel.setEnabled(data.channels > 1); 
     469      dataSurface = new JRadioButton("Surface", data.channels > 1); 
    602470      dataSurface.setToolTipText("Displays raw data as a 2D surface"); 
    603       dataSurface.setEnabled(channels > 1); 
    604       dataLines = new JRadioButton("Lines", channels == 1); 
     471      dataSurface.setEnabled(data.channels > 1); 
     472      dataLines = new JRadioButton("Lines", data.channels == 1); 
    605473      dataLines.setToolTipText("Displays raw data as a series of lines"); 
    606       dataLines.setEnabled(channels > 1); 
     474      dataLines.setEnabled(data.channels > 1); 
    607475      fitSurface = new JRadioButton("Surface", false); 
    608476      fitSurface.setToolTipText("Displays fitted curves as a 2D surface"); 
    609       fitSurface.setEnabled(adjustPeaks && channels > 1); 
     477      fitSurface.setEnabled(data.adjustPeaks && data.channels > 1); 
    610478      fitLines = new JRadioButton("Lines", true); 
    611479      fitLines.setToolTipText("Displays fitted curves as a series of lines"); 
    612       fitLines.setEnabled(adjustPeaks && channels > 1); 
     480      fitLines.setEnabled(data.adjustPeaks && data.channels > 1); 
    613481      resSurface = new JRadioButton("Surface", false); 
    614482      resSurface.setToolTipText( 
    615483        "Displays fitted curve residuals as a 2D surface"); 
    616       resSurface.setEnabled(adjustPeaks && channels > 1); 
     484      resSurface.setEnabled(data.adjustPeaks && data.channels > 1); 
    617485      resLines = new JRadioButton("Lines", true); 
    618486      resLines.setToolTipText( 
    619487        "Displays fitted curve residuals as a series of lines"); 
    620       resLines.setEnabled(adjustPeaks && channels > 1); 
     488      resLines.setEnabled(data.adjustPeaks && data.channels > 1); 
    621489      colorHeight = new JRadioButton("Counts", true); 
    622490      colorHeight.setToolTipText( 
    623491        "Colorizes data according to the height (histogram count)"); 
    624       colorHeight.setEnabled(adjustPeaks && channels > 1); 
     492      colorHeight.setEnabled(data.adjustPeaks && data.channels > 1); 
    625493      colorTau = new JRadioButton("Lifetimes", false); 
    626494      colorTau.setToolTipText( 
    627495        "Colorizes data according to aggregate lifetime value"); 
    628       colorTau.setEnabled(adjustPeaks && channels > 1); 
     496      colorTau.setEnabled(data.adjustPeaks && data.channels > 1); 
    629497 
    630498      zOverride = new JCheckBox("", false); 
     
    805673  } 
    806674 
    807   /** Logs the given output to the appropriate location. */ 
    808   public void log(String msg) { 
    809     final String message = msg; 
    810     SwingUtilities.invokeLater(new Runnable() { 
    811       public void run() { System.err.println(message); } 
    812     }); 
    813   } 
    814  
    815675  // -- ActionListener methods -- 
    816676 
     
    930790      try { 
    931791        PrintWriter out = new PrintWriter(new FileWriter(file)); 
    932         out.println(timeBins + " x " + channels + 
     792        out.println(data.timeBins + " x " + data.channels + 
    933793          " (count=" + twoDPane.getROICount() + 
    934794          ", percent=" + twoDPane.getROIPercent() + 
    935795          ", maxVal=" + maxVal + ")"); 
    936         for (int c=0; c<channels; c++) { 
    937           for (int t=0; t<timeBins; t++) { 
     796        for (int c=0; c<data.channels; c++) { 
     797          for (int t=0; t<data.timeBins; t++) { 
    938798            if (t > 0) out.print("\t"); 
    939             float s = samps[timeBins * c + t]; 
     799            float s = samps[data.timeBins * c + t]; 
    940800            int is = (int) s; 
    941801            if (is == s) out.print(is); 
     
    958818        setWidgetTable(LUTS[Integer.parseInt(cmd.substring(3))]); 
    959819      } 
    960       else { // OK button 
    961         width = parse(wField.getText(), width); 
    962         height = parse(hField.getText(), height); 
    963         timeBins = parse(tField.getText(), timeBins); 
    964         channels = parse(cField.getText(), channels); 
    965         timeRange = parse(trField.getText(), timeRange); 
    966         minWave = parse(wlField.getText(), minWave); 
    967         waveStep = parse(sField.getText(), waveStep); 
    968         numExp = parse(fitField.getText(), numExp); 
    969         useLMA = lmChoice.isSelected(); 
    970         adjustPeaks = peaksBox.isSelected(); 
    971         computeFWHMs = fwhmBox.isSelected(); 
    972         cutEnd = cutBox.isSelected(); 
    973         cVisible = new boolean[channels]; 
    974         Arrays.fill(cVisible, true); 
    975         paramDialog.setVisible(false); 
    976       } 
    977820    } 
    978821  } 
     
    1006849      ProgressMonitor progress = new ProgressMonitor(null, "Plotting data", 
    1007850        "Calculating sums", 0, 
    1008         channels * timeBins + (doRefit ? channels : 0) + 1); 
     851        data.channels * data.timeBins + (doRefit ? data.channels : 0) + 1); 
    1009852      progress.setMillisToPopup(100); 
    1010853      progress.setMillisToDecideToPopup(50); 
     
    1032875      // calculate samples 
    1033876      int numChanVis = 0; 
    1034       for (int c=0; c<channels; c++) { 
    1035         if (cVisible[c]) numChanVis++; 
    1036       } 
    1037       samps = new float[numChanVis * timeBins]; 
     877      for (int c=0; c<data.channels; c++) { 
     878        if (data.cVisible[c]) numChanVis++; 
     879      } 
     880      samps = new float[numChanVis * data.timeBins]; 
    1038881      maxVal = 0; 
    1039882      float[] maxVals = new float[numChanVis]; 
    1040       for (int c=0, cc=0; c<channels; c++) { 
    1041         if (!cVisible[c]) continue; 
    1042         for (int t=0; t<timeBins; t++) { 
    1043           int ndx = timeBins * cc + t; 
     883      for (int c=0, cc=0; c<data.channels; c++) { 
     884        if (!data.cVisible[c]) continue; 
     885        for (int t=0; t<data.timeBins; t++) { 
     886          int ndx = data.timeBins * cc + t; 
    1044887          int sum = 0; 
    1045888          if (twoDPane.getROICount() == 1) { 
    1046889            int roiX = twoDPane.getROIX(); 
    1047890            int roiY = twoDPane.getROIY(); 
    1048             sum = values[c][roiY][roiX][t]; 
     891            sum = data.data[c][roiY][roiX][t]; 
    1049892          } 
    1050893          else { 
    1051894            boolean[][] roiMask = twoDPane.getROIMask(); 
    1052             for (int h=0; h<height; h++) { 
    1053               for (int w=0; w<width; w++) { 
    1054                 if (roiMask[h][w]) sum += values[c][h][w][t]; 
     895            for (int y=0; y<data.height; y++) { 
     896              for (int x=0; x<data.width; x++) { 
     897                if (roiMask[y][x]) sum += data.data[c][y][x][t]; 
    1055898              } 
    1056899            } 
     
    1069912      // full width half maxes 
    1070913      float[][][] fwhmLines = null; 
    1071       if (computeFWHMs) { 
     914      if (data.computeFWHMs) { 
    1072915        log("Calculating full width half maxes"); 
    1073         fwhmLines = new float[channels][3][2]; 
     916        fwhmLines = new float[data.channels][3][2]; 
    1074917        int grandTotal = 0; 
    1075         for (int c=0, cc=0; c<channels; c++) { 
    1076           if (!cVisible[c]) continue; 
     918        for (int c=0, cc=0; c<data.channels; c++) { 
     919          if (!data.cVisible[c]) continue; 
    1077920          // sum across all pixels 
    1078           int[] sums = new int[timeBins]; 
     921          int[] sums = new int[data.timeBins]; 
    1079922          int sumTotal = 0; 
    1080           for (int t=0; t<timeBins; t++) { 
     923          for (int t=0; t<data.timeBins; t++) { 
    1081924            if (twoDPane.getROICount() == 1) { 
    1082925              int roiX = twoDPane.getROIX(); 
    1083926              int roiY = twoDPane.getROIY(); 
    1084               sums[t] = values[c][roiY][roiX][t]; 
     927              sums[t] = data.data[c][roiY][roiX][t]; 
    1085928            } 
    1086929            else { 
    1087930              boolean[][] roiMask = twoDPane.getROIMask(); 
    1088               for (int h=0; h<height; h++) { 
    1089                 for (int w=0; w<width; w++) { 
    1090                   if (roiMask[h][w]) sums[t] += values[c][h][w][t]; 
     931              for (int y=0; y<data.height; y++) { 
     932                for (int x=0; x<data.width; x++) { 
     933                  if (roiMask[y][x]) sums[t] += data.data[c][y][x][t]; 
    1091934                } 
    1092935              } 
     
    1095938          } 
    1096939          int maxSum = 0; 
    1097           for (int t=0; t<timeBins; t++) if (sums[t] > maxSum) maxSum = sums[t]; 
     940          for (int t=0; t<data.timeBins; t++) if (sums[t] > maxSum) maxSum = sums[t]; 
    1098941          grandTotal += sumTotal; 
    1099942          // find full width half max 
    1100943          float half = maxSum / 2f; 
    1101944          float fwhm1 = Float.NaN, fwhm2 = Float.NaN; 
    1102           for (int t=0; t<timeBins-1; t++) { 
     945          for (int t=0; t<data.timeBins-1; t++) { 
    1103946            if (sums[t] <= half && sums[t + 1] >= half) { // upslope 
    1104947              float q = (half - sums[t]) / (sums[t + 1] - sums[t]); 
    1105               fwhm1 = timeRange * (t + q) / (timeBins - 1); // binsToNano 
     948              fwhm1 = data.timeRange * (t + q) / (data.timeBins - 1); // binsToNano 
    1106949            } 
    1107950            else if (sums[t] >= half && sums[t + 1] <= half) { // downslope 
    1108951              float q = (half - sums[t + 1]) / (sums[t] - sums[t + 1]); 
    1109               fwhm2 = timeRange * (t + 1 - q) / (timeBins - 1); // binsToNano 
     952              fwhm2 = data.timeRange * (t + 1 - q) / (data.timeBins - 1); // binsToNano 
    1110953            } 
    1111954            if (fwhm1 == fwhm1 && fwhm2 == fwhm2) break; 
     
    1113956          fwhmLines[c][0][0] = fwhm1; 
    1114957          fwhmLines[c][0][1] = fwhm2; 
    1115           fwhmLines[c][1][0] = fwhmLines[c][1][1] = minWave + c * waveStep; 
     958          fwhmLines[c][1][0] = fwhmLines[c][1][1] = 
     959            data.minWave + c * data.waveStep; 
    1116960          fwhmLines[c][2][0] = fwhmLines[c][2][1] = half; 
    1117961          String s = "#" + (c + 1); 
     
    1120964          log("\tChannel " + s + ": fwhm = " + (h2 - h1) + " ps"); 
    1121965          log("\t             counts = " + sumTotal); 
    1122           log("\t             peak = " + sums[maxPeak]); 
     966          log("\t             peak = " + sums[data.maxPeak]); 
    1123967          log("\t             center = " + ((h1 + h2) / 2) + " ps"); 
    1124968          log("\t             range = [" + h1 + ", " + h2 + "] ps"); 
     
    1131975      // curve fitting 
    1132976      double[][] fitResults = null; 
    1133       if (adjustPeaks && doRefit) { 
     977      if (data.adjustPeaks && doRefit) { 
    1134978        // perform exponential curve fitting: y(x) = a * e^(-b*t) + c 
    1135979        progress.setNote("Fitting curves"); 
    1136         fitResults = new double[channels][]; 
    1137         tau = new float[channels][numExp]; 
    1138         for (int c=0; c<channels; c++) Arrays.fill(tau[c], Float.NaN); 
    1139         int num = timeBins - maxPeak; 
     980        fitResults = new double[data.channels][]; 
     981        tau = new float[data.channels][data.numExp]; 
     982        for (int c=0; c<data.channels; c++) Arrays.fill(tau[c], Float.NaN); 
     983        int num = data.timeBins - data.maxPeak; 
    1140984 
    1141985        // HACK - cut off last 1500 ps from lifetime histogram, 
    1142986        // to improve accuracy of fit. 
    1143         if (cutEnd) { 
     987        if (data.cutEnd) { 
    1144988          int cutBins = (int) picoToBins(1500); 
    1145989          if (num > cutBins + 5) num -= cutBins; 
     
    1148992        StringBuffer equation = new StringBuffer(); 
    1149993        equation.append("y(t) = "); 
    1150         for (int i=0; i<numExp; i++) { 
     994        for (int i=0; i<data.numExp; i++) { 
    1151995          equation.append("a"); 
    1152996          equation.append(i + 1); 
     
    11581002        equation.append("c"); 
    11591003        log("Computing fit parameters: " + equation.toString()); 
    1160         int[] data = new int[num]; 
    1161         for (int c=0, cc=0; c<channels; c++) { 
    1162           if (!cVisible[c]) { 
     1004        int[] curveData = new int[num]; 
     1005        for (int c=0, cc=0; c<data.channels; c++) { 
     1006          if (!data.cVisible[c]) { 
    11631007            fitResults[c] = null; 
    11641008            continue; 
     
    11661010          log("\tChannel #" + (c + 1) + ":"); 
    11671011 
    1168           CurveFitter fitter; 
    1169           if (useLMA) fitter = new LMCurveFitter(); 
    1170           else fitter = new GACurveFitter(); 
     1012          CurveFitter fitter = 
     1013            CurveCollection.newCurveFitter(data.curveFitterClass); 
    11711014          for (int i=0; i<num; i++) { 
    1172             data[i] = (int) samps[timeBins * cc + maxPeak + i]; 
    1173           } 
    1174           fitter.setComponentCount(numExp); 
    1175           fitter.setData(data); 
     1015            curveData[i] = (int) samps[data.timeBins * cc + data.maxPeak + i]; 
     1016          } 
     1017          fitter.setComponentCount(data.numExp); 
     1018          fitter.setData(curveData); 
    11761019          fitter.estimate(); 
    11771020          for (int i=0; i<100; i++) fitter.iterate(); 
    11781021          double[][] results = fitter.getCurve(); 
    11791022          log("\t\tchi2=" + fitter.getReducedChiSquaredError()); 
    1180           for (int i=0; i<numExp; i++) { 
     1023          for (int i=0; i<data.numExp; i++) { 
    11811024            log("\t\ta" + (i + 1) + "=" + 
    11821025              (100 * results[i][0] / maxVals[cc]) + "%"); 
     
    11851028          } 
    11861029          log("\t\tc=" + results[0][2]); 
    1187           fitResults[c] = new double[2 * numExp + 1]; 
    1188           for (int i=0; i<numExp; i++) { 
     1030          fitResults[c] = new double[2 * data.numExp + 1]; 
     1031          for (int i=0; i<data.numExp; i++) { 
    11891032            int e = 2 * i; 
    11901033            fitResults[c][e] = results[i][0]; 
    11911034            fitResults[c][e + 1] = results[i][1]; 
    11921035          } 
    1193           fitResults[c][2 * numExp] = results[0][2]; 
     1036          fitResults[c][2 * data.numExp] = results[0][2]; 
    11941037 
    11951038          setProgress(progress, ++p, false); 
     
    12411084      try { 
    12421085        // construct domain set for 3D surface plots 
    1243         float[][] bcGrid = new float[2][timeBins * numChanVis]; 
    1244         for (int c=0, cc=0; c<channels; c++) { 
    1245           if (!cVisible[c]) continue; 
    1246           for (int t=0; t<timeBins; t++) { 
    1247             int ndx = timeBins * cc + t; 
    1248             bcGrid[0][ndx] = timeBins > 1 ? t * timeRange / (timeBins - 1) : 0; 
    1249             bcGrid[1][ndx] = channels > 1 ? 
    1250               c * (maxWave - minWave) / (channels - 1) + minWave : 0; 
     1086        float[][] bcGrid = new float[2][data.timeBins * numChanVis]; 
     1087        for (int c=0, cc=0; c<data.channels; c++) { 
     1088          if (!data.cVisible[c]) continue; 
     1089          for (int t=0; t<data.timeBins; t++) { 
     1090            int ndx = data.timeBins * cc + t; 
     1091            bcGrid[0][ndx] = data.timeBins > 1 ? t * data.timeRange / (data.timeBins - 1) : 0; 
     1092            bcGrid[1][ndx] = data.channels > 1 ? c * (data.maxWave - data.minWave) / (data.channels - 1) + data.minWave : 0; 
    12511093          } 
    12521094          cc++; 
    12531095        } 
    12541096        Gridded2DSet bcSet = new Gridded2DSet(types.bc, bcGrid, 
    1255           timeBins, numChanVis, null, types.bcUnits, null, false); 
     1097          data.timeBins, numChanVis, null, types.bcUnits, null, false); 
    12561098 
    12571099        // compile color values for 3D surface plot 
    1258         float[] colors = new float[numChanVis * timeBins]; 
    1259         for (int c=0, cc=0; c<channels; c++) { 
    1260           if (!cVisible[c]) continue; 
    1261           for (int t=0; t<timeBins; t++) { 
    1262             int ndx = timeBins * cc + t; 
     1100        float[] colors = new float[numChanVis * data.timeBins]; 
     1101        for (int c=0, cc=0; c<data.channels; c++) { 
     1102          if (!data.cVisible[c]) continue; 
     1103          for (int t=0; t<data.timeBins; t++) { 
     1104            int ndx = data.timeBins * cc + t; 
    12631105            colors[ndx] = doTauColors ? 
    12641106              (tau == null ? Float.NaN : tau[c][0]) : samps[ndx]; 
     
    12701112        if (fitResults != null) { 
    12711113          // compute finite sampling matching fitted exponentials 
    1272           fitSamps = new float[numChanVis * timeBins]; 
    1273           residuals = new float[numChanVis * timeBins]; 
    1274           for (int c=0, cc=0; c<channels; c++) { 
    1275             if (!cVisible[c]) continue; 
     1114          fitSamps = new float[numChanVis * data.timeBins]; 
     1115          residuals = new float[numChanVis * data.timeBins]; 
     1116          for (int c=0, cc=0; c<data.channels; c++) { 
     1117            if (!data.cVisible[c]) continue; 
    12761118            double[] q = fitResults[c]; 
    1277             for (int t=0; t<timeBins; t++) { 
    1278               int ndx = timeBins * cc + t; 
    1279               int et = t - maxPeak; // adjust for peak alignment 
     1119            for (int t=0; t<data.timeBins; t++) { 
     1120              int ndx = data.timeBins * cc + t; 
     1121              int et = t - data.maxPeak; // adjust for peak alignment 
    12801122              if (et < 0) fitSamps[ndx] = residuals[ndx] = 0; 
    12811123              else { 
    12821124                float sum = 0; 
    1283                 for (int i=0; i<numExp; i++) { 
     1125                for (int i=0; i<data.numExp; i++) { 
    12841126                  int e = 2 * i; 
    12851127                  sum += (float) (q[e] * Math.exp(-q[e + 1] * et)); 
    12861128                } 
    1287                 sum += (float) q[2 * numExp]; 
     1129                sum += (float) q[2 * data.numExp]; 
    12881130                fitSamps[ndx] = sum; 
    12891131                residuals[ndx] = samps[ndx] - fitSamps[ndx]; 
     
    13081150        if (fwhmLines != null) { 
    13091151          // construct "FWHMs" plot 
    1310           SampledSet[] fwhmSets = new SampledSet[channels]; 
    1311           for (int c=0; c<channels; c++) { 
     1152          SampledSet[] fwhmSets = new SampledSet[data.channels]; 
     1153          for (int c=0; c<data.channels; c++) { 
    13121154            if (doLog) { 
    13131155              // convert samples to log values for plotting 
     
    13191161              } 
    13201162            } 
    1321             if (channels > 1) { 
     1163            if (data.channels > 1) { 
    13221164              fwhmSets[c] = new Gridded3DSet(types.bcv, fwhmLines[c], 2); 
    13231165            } 
     
    14131255  // -- Helper methods -- 
    14141256 
    1415   private void showParamDialog() { 
    1416     paramDialog = new JDialog((Frame) null, "Slim Plotter", true); 
    1417     JPanel paramPane = new JPanel(); 
    1418     paramPane.setBorder(new EmptyBorder(10, 10, 10, 10)); 
    1419     paramDialog.setContentPane(paramPane); 
    1420     paramPane.setLayout(new GridLayout(13, 3)); 
    1421     wField = addRow(paramPane, "Image width", width, "pixels"); 
    1422     hField = addRow(paramPane, "Image height", height, "pixels"); 
    1423     tField = addRow(paramPane, "Time bins", timeBins, ""); 
    1424     cField = addRow(paramPane, "Channel count", channels, ""); 
    1425     trField = addRow(paramPane, "Time range", timeRange, "nanoseconds"); 
    1426     wlField = addRow(paramPane, "Starting wavelength", minWave, "nanometers"); 
    1427     sField = addRow(paramPane, "Channel width", waveStep, "nanometers"); 
    1428     fitField = addRow(paramPane, "Exponential fit", 1, "components"); 
    1429     JButton ok = new JButton("OK"); 
    1430     paramDialog.getRootPane().setDefaultButton(ok); 
    1431     ok.addActionListener(this); 
    1432     // row 8 
    1433     paramPane.add(new JLabel("Fit algorithm")); 
    1434     lmChoice = new JRadioButton("Levenberg-Marquardt"); 
    1435     gaChoice = new JRadioButton("Genetic", true); 
    1436     ButtonGroup group = new ButtonGroup(); 
    1437     group.add(lmChoice); 
    1438     group.add(gaChoice); 
    1439     paramPane.add(lmChoice); 
    1440     paramPane.add(gaChoice); 
    1441     // row 9 
    1442     paramPane.add(new JLabel()); 
    1443     paramPane.add(new JLabel()); 
    1444     paramPane.add(new JLabel()); 
    1445     // row 10, column 1 
    1446     peaksBox = new JCheckBox("Align peaks", true); 
    1447     peaksBox.setToolTipText("<html>Computes the peak of each spectral " + 
    1448       "channel, and aligns those peaks <br>to match by adjusting the " + 
    1449       "lifetime histograms. This option corrects<br>for skew across " + 
    1450       "channels caused by the multispectral detector's<br>variable system " + 
    1451       "response time between channels. This option must<br>be enabled to " + 
    1452       "perform exponential curve fitting.</html>"); 
    1453     paramPane.add(peaksBox); 
    1454     // row 10, column 2 
    1455     fwhmBox = new JCheckBox("Compute FWHMs", false); 
    1456     fwhmBox.setToolTipText( 
    1457       "<html>Computes the full width half max at each channel.</html>"); 
    1458     paramPane.add(fwhmBox); 
    1459     // row 10, column 3 
    1460     cutBox = new JCheckBox("Cut 1.5ns from fit", true); 
    1461     cutBox.setToolTipText("<html>When performing exponential curve " + 
    1462       "fitting, excludes the last 1.5 ns<br>from the computation. This " + 
    1463       "option is useful because the end of the <br>the lifetime histogram " + 
    1464       "sometimes drops off unexpectedly, skewing<br>the fit results.</html>"); 
    1465     paramPane.add(cutBox); 
    1466     // row 11 
    1467     paramPane.add(new JLabel()); 
    1468     paramPane.add(new JLabel()); 
    1469     paramPane.add(new JLabel()); 
    1470     // row 12 
    1471     paramPane.add(new JLabel()); 
    1472     paramPane.add(ok); 
    1473     paramDialog.pack(); 
    1474     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
    1475     Dimension ps = paramDialog.getSize(); 
    1476     paramDialog.setLocation((screenSize.width - ps.width) / 2, 
    1477       (screenSize.height - ps.height) / 2); 
    1478     paramDialog.setVisible(true); 
    1479   } 
    1480  
    14811257  /** Converts value in picoseconds to histogram bins. */ 
    14821258  private float picoToBins(float pico) { 
    1483     return (timeBins - 1) * pico / timeRange / 1000; 
     1259    return (data.timeBins - 1) * pico / data.timeRange / 1000; 
    14841260  } 
    14851261 
    14861262  /** Converts value in histogram bins to picoseconds. */ 
    14871263  private float binsToPico(float bins) { 
    1488     return 1000 * timeRange * bins / (timeBins - 1); 
     1264    return 1000 * data.timeRange * bins / (data.timeBins - 1); 
    14891265  } 
    14901266 
     
    15161292      // from 2D surface to 1D lines... 
    15171293      Linear1DSet timeSet = new Linear1DSet(types.bType, 0, 
    1518         timeRange, timeBins, null, new Unit[] {types.bcUnits[0]}, null); 
     1294        data.timeRange, data.timeBins, null, new Unit[] {types.bcUnits[0]}, null); 
    15191295      int numChanVis = 0; 
    1520       for (int c=0; c<channels; c++) { 
    1521         if (cVisible[c]) numChanVis++; 
     1296      for (int c=0; c<data.channels; c++) { 
     1297        if (data.cVisible[c]) numChanVis++; 
    15221298      } 
    15231299      float[][] cGrid = new float[1][numChanVis]; 
    1524       for (int c=0, cc=0; c<channels; c++) { 
    1525         if (!cVisible[c]) continue; 
    1526         cGrid[0][cc++] = channels > 1 ? 
    1527           c * (maxWave - minWave) / (channels - 1) + minWave : 0; 
     1300      for (int c=0, cc=0; c<data.channels; c++) { 
     1301        if (!data.cVisible[c]) continue; 
     1302        cGrid[0][cc++] = data.channels > 1 ? 
     1303          c * (data.maxWave - data.minWave) / (data.channels - 1) + data.minWave : 0; 
    15281304      } 
    15291305      Gridded1DSet waveSet = new Gridded1DSet(types.cType, 
     
    15831359  // -- Utility methods -- 
    15841360 
    1585   public static JTextField addRow(JPanel p, 
    1586     String label, double value, String unit) 
     1361  public static void setProgress(ProgressMonitor progress, int p) { 
     1362    setProgress(progress, p, true); 
     1363  } 
     1364 
     1365  public static void setProgress(ProgressMonitor progress, 
     1366    int base, int inc, double frac) 
    15871367  { 
    1588     p.add(new JLabel(label)); 
    1589     JTextField textField = new JTextField(value == (int) value ? 
    1590       ("" + (int) value) : ("" + value), 8); 
    1591     JPanel textFieldPane = new JPanel(); 
    1592     textFieldPane.setLayout(new BorderLayout()); 
    1593     textFieldPane.add(textField, BorderLayout.CENTER); 
    1594     textFieldPane.setBorder(new EmptyBorder(2, 3, 2, 3)); 
    1595     p.add(textFieldPane); 
    1596     p.add(new JLabel(unit)); 
    1597     return textField; 
    1598   } 
    1599  
    1600   public static int parse(String s, int last) { 
    1601     try { return Integer.parseInt(s); } 
    1602     catch (NumberFormatException exc) { return last; } 
    1603   } 
    1604  
    1605   public static float parse(String s, float last) { 
    1606     try { return Float.parseFloat(s); } 
    1607     catch (NumberFormatException exc) { return last; } 
    1608   } 
    1609  
    1610   private static void setProgress(ProgressMonitor progress, int p) { 
    1611     setProgress(progress, p, false); 
    1612   } 
    1613  
    1614   private static void setProgress(ProgressMonitor progress, 
     1368    setProgress(progress, (int) (base + (long) inc * frac)); 
     1369  } 
     1370 
     1371  public static void setProgress(ProgressMonitor progress, 
    16151372    int p, boolean quitOnCancel) 
    16161373  { 
    16171374    progress.setProgress(p); 
    16181375    if (quitOnCancel && progress.isCanceled()) System.exit(0); 
     1376  } 
     1377 
     1378  /** Logs the given output to the appropriate location. */ 
     1379  public static void log(String msg) { 
     1380    final String message = msg; 
     1381    SwingUtilities.invokeLater(new Runnable() { 
     1382      public void run() { System.err.println(message); } 
     1383    }); 
    16191384  } 
    16201385 
  • trunk/loci/slim/TwoDPane.java

    r4241 r4243  
    6868 
    6969  // data parameters 
    70   private int[][][][] data; 
    71   private int channels, width, height, timeBins; 
    72   private int numExp; 
    73   private Class curveFitterClass; 
    74   private boolean[] cVisible; 
     70  private SlimData data; 
    7571  private SlimTypes types; 
    7672 
     
    9692  // GUI components for image pane 
    9793  private JProgressBar progress; 
     94  private JButton startStopButton; 
    9895  private JRadioButton intensityMode, lifetimeMode; 
    9996  private JRadioButton projectionMode, emissionMode; 
     
    110107  // -- Constructor -- 
    111108 
    112   public TwoDPane(SlimPlotter slim, int[][][][] data, int numExp, 
    113     Class curveFitterClass, boolean[] cVisible, SlimTypes types) 
     109  public TwoDPane(SlimPlotter slim, SlimData data, SlimTypes types) 
    114110    throws VisADException, RemoteException 
    115111  { 
    116112    this.slim = slim; 
    117113    this.data = data; 
    118     this.cVisible = cVisible; 
    119114    this.types = types; 
    120115 
    121     channels = data.length; 
    122     width = data[0].length; 
    123     height = data[0][0].length; 
    124     timeBins = data[0][0][0].length; 
    125  
    126     this.numExp = numExp; 
    127     this.curveFitterClass = curveFitterClass; 
    128  
    129     roiCount = width * height; 
     116    roiCount = data.width * data.height; 
    130117    roiPercent = 100; 
    131118 
     
    152139 
    153140    // set up curve manipulation renderer 
    154     roiGrid = new float[2][width * height]; 
    155     roiMask = new boolean[height][width]; 
    156     for (int y=0; y<height; y++) { 
    157       for (int x=0; x<width; x++) { 
    158         int ndx = y * width + x; 
     141    roiGrid = new float[2][data.width * data.height]; 
     142    roiMask = new boolean[data.height][data.width]; 
     143    for (int y=0; y<data.height; y++) { 
     144      for (int x=0; x<data.width; x++) { 
     145        int ndx = y * data.width + x; 
    159146        roiGrid[0][ndx] = x; 
    160147        roiGrid[1][ndx] = y; 
     
    212199    progress = new JProgressBar(); 
    213200    progress.setStringPainted(true); 
    214     add(progress); 
     201 
     202    startStopButton = new JButton("Start"); 
     203    startStopButton.addActionListener(this); 
     204 
     205    JPanel progressPanel = new JPanel(); 
     206    progressPanel.setLayout(new BoxLayout(progressPanel, BoxLayout.X_AXIS)); 
     207    progressPanel.add(progress); 
     208    progressPanel.add(startStopButton); 
     209    add(progressPanel); 
    215210 
    216211    JPanel viewModePane = new JPanel(); 
     
    284279    validColor = minField.getBackground(); 
    285280 
    286     cSlider = new JSlider(1, channels, 1); 
     281    cSlider = new JSlider(1, data.channels, 1); 
    287282    cSlider.setToolTipText( 
    288283      "Selects the channel to display in the 2D image plot above"); 
    289284    cSlider.setSnapToTicks(true); 
    290     cSlider.setMajorTickSpacing(channels / 4); 
     285    cSlider.setMajorTickSpacing(data.channels / 4); 
    291286    cSlider.setMinorTickSpacing(1); 
    292287    cSlider.setPaintTicks(true); 
    293288    cSlider.addChangeListener(this); 
    294289    cSlider.setBorder(new EmptyBorder(8, 5, 8, 5)); 
    295     cSlider.setEnabled(channels > 1); 
     290    cSlider.setEnabled(data.channels > 1); 
    296291    sliderPane.add(cSlider); 
    297292    cToggle = new JCheckBox("", true); 
     
    299294      "Toggles the selected channel's visibility in the 3D data plot"); 
    300295    cToggle.addActionListener(this); 
    301     cToggle.setEnabled(channels > 1); 
     296    cToggle.setEnabled(data.channels > 1); 
    302297    sliderPane.add(cToggle); 
    303298 
     
    307302 
    308303    // set up lifetime curve fitting threads for per-pixel lifetime analysis 
    309     curveRenderers = new Renderer[channels]; 
    310     curveThreads = new Thread[channels]; 
    311     for (int c=0; c<channels; c++) { 
    312       CurveCollection cc = new CurveCollection(data[c], 
    313         curveFitterClass, BIN_RADIUS); 
    314       curveRenderers[c] = new BurnInRenderer(cc); 
    315       curveRenderers[c].setComponentCount(numExp); 
     304    curveRenderers = new Renderer[data.channels]; 
     305    curveThreads = new Thread[data.channels]; 
     306    for (int c=0; c<data.channels; c++) { 
     307      curveRenderers[c] = new BurnInRenderer(data.curves[c]); 
     308      curveRenderers[c].setComponentCount(data.numExp); 
     309      curveRenderers[c].setMaxIterations(100); 
    316310      curveThreads[c] = new Thread(curveRenderers[c], "Lifetime-" + c); 
    317311      curveThreads[c].setPriority(Thread.MIN_PRIORITY); 
     
    319313    int delay = 100; // TODO - make this a UI option (FPS) 
    320314    lifetimeRefresh = new Timer(delay, this); 
    321     for (int c=0; c<channels; c++) curveThreads[c].start(); 
     315    for (int c=0; c<data.channels; c++) curveThreads[c].start(); 
    322316    lifetimeRefresh.start(); 
    323317  } 
     
    336330  public void actionPerformed(ActionEvent e) { 
    337331    Object src = e.getSource(); 
    338     if (src == cToggle) { 
     332    if (src == startStopButton) { 
     333      // TODO 
     334      if (startStopButton.getText().equals("Start")) { 
     335        // begin lifetime computation 
     336        startStopButton.setText("Stop"); 
     337      } 
     338      else { 
     339        // terminate lifetime computation 
     340        startStopButton.setText("Start"); 
     341      } 
     342    } 
     343    else if (src == cToggle) { 
    339344      // toggle visibility of this channel 
    340345      int c = cSlider.getValue() - 1; 
    341       cVisible[c] = !cVisible[c]; 
     346      data.cVisible[c] = !data.cVisible[c]; 
    342347      slim.plotData(true, true, false); 
    343348    } 
     
    347352    else if (src == emissionMode) doEmissionSpectrum(); 
    348353    else { 
    349       // timer event - update lifetime display 
     354      // timer event - update progress bar and lifetime display 
    350355      int c = cSlider.getValue() - 1; 
    351       // update progress bar 
    352       progress.setMaximum(curveRenderers[c].getMaxProgress()); 
    353       progress.setValue(curveRenderers[c].getCurrentProgress()); 
    354       progress.setString( 
    355         "Iteration " + curveRenderers[c].getCurrentIterations() + 
    356         "/" + curveRenderers[c].getTotalIterations() + "; " + 
    357         curveRenderers[c].getSubsampleLevel() + " steps until total burn-in"); 
     356 
     357      int curProg = curveRenderers[c].getCurrentProgress(); 
     358      int maxProg = curveRenderers[c].getMaxProgress(); 
     359      int curIter = curveRenderers[c].getCurrentIterations(); 
     360      int maxIter = curveRenderers[c].getMaxIterations(); 
     361      int subLevel = curveRenderers[c].getSubsampleLevel(); 
     362      progress.setMaximum(maxProg); 
     363      progress.setValue(curProg); 
     364      progress.setString(curProg == maxProg ? 
     365        "Iteration " + curIter + "/" + maxIter : 
     366        "Estimating; " + subLevel + " steps until total burn-in"); 
    358367 
    359368      if (lifetimeMode.isSelected()) { 
     
    382391      catch (RemoteException exc) { exc.printStackTrace(); } 
    383392      cToggle.removeActionListener(this); 
    384       cToggle.setSelected(cVisible[c]); 
     393      cToggle.setSelected(data.cVisible[c]); 
    385394      cToggle.addActionListener(this); 
    386395    } 
     
    415424          roiX = roiY = 0; 
    416425          roiCount = 0; 
    417           for (int y=0; y<height; y++) { 
    418             for (int x=0; x<width; x++) { 
    419               int ndx = y * width + x; 
     426          for (int y=0; y<data.height; y++) { 
     427            for (int x=0; x<data.width; x++) { 
     428              int ndx = y * data.width + x; 
    420429              roiMask[y][x] = tri[ndx] >= 0; 
    421430              if (roiMask[y][x]) { 
     
    426435            } 
    427436          } 
    428           roiPercent = 100000 * roiCount / (width * height) / 1000.0; 
     437          roiPercent = 100000 * roiCount / (data.width * data.height) / 1000.0; 
    429438          slim.plotData(true, true, true); 
    430439        } 
     
    461470    roiY = (int) Math.round(domain[1]); 
    462471    if (roiX < 0) roiX = 0; 
    463     if (roiX >= width) roiX = width - 1; 
     472    if (roiX >= data.width) roiX = data.width - 1; 
    464473    if (roiY < 0) roiY = 0; 
    465     if (roiY >= height) roiY = height - 1; 
     474    if (roiY >= data.height) roiY = data.height - 1; 
    466475    roiCount = 1; 
    467476    slim.plotData(true, rescale, refit); 
     
    513522        intensityMin = intensityMax = 0; 
    514523        maxChan = 0; 
    515         for (int c=0; c<channels; c++) { 
    516           float[][] samples = new float[1][width * height]; 
    517           for (int y=0; y<height; y++) { 
    518             for (int x=0; x<width; x++) { 
     524        for (int c=0; c<data.channels; c++) { 
     525          float[][] samples = new float[1][data.width * data.height]; 
     526          for (int y=0; y<data.height; y++) { 
     527            for (int x=0; x<data.width; x++) { 
    519528              int sum = 0; 
    520               for (int t=0; t<timeBins; t++) sum += data[c][y][x][t]; 
     529              for (int t=0; t<data.timeBins; t++) sum += data.data[c][y][x][t]; 
    521530              if (sum > intensityMax) { 
    522531                intensityMax = sum; 
    523532                maxChan = c; 
    524533              } 
    525               samples[0][width * y + x] = sum; 
     534              samples[0][data.width * y + x] = sum; 
    526535            } 
    527536          } 
     
    551560        lifetimeField = new FieldImpl(types.cxyvFunc, types.cSet); 
    552561        lifetimeMin = lifetimeMax = 0; 
    553         for (int c=0; c<channels; c++) { 
    554           float[][] samples = new float[1][width * height]; 
    555           for (int h=0; h<height; h++) { 
    556             for (int w=0; w<width; w++) { 
     562        for (int c=0; c<data.channels; c++) { 
     563          float[][] samples = new float[1][data.width * data.height]; 
     564          for (int h=0; h<data.height; h++) { 
     565            for (int w=0; w<data.width; w++) { 
    557566              // TODO 
    558567              float val = 100 * (float) (Math.cos(w/10.0) * Math.sin(h/10.0)); 
    559               samples[0][width * h + w] = val; 
     568              samples[0][data.width * h + w] = val; 
    560569              if (val < lifetimeMin) lifetimeMin = (int) Math.floor(val); 
    561570              if (val > lifetimeMax) lifetimeMax = (int) Math.ceil(val); 
Note: See TracChangeset for help on using the changeset viewer.