Changeset 2662
 Timestamp:
 04/24/07 13:19:36 (13 years ago)
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

trunk/loci/apps/slim/SlimPlotter.java
r2650 r2662 5 5 /* 6 6 Coded in 2006@year@ by Curtis Rueden, with suggestions from 7 Long Yan, Steve Trier, Kraig Kumfer and Paolo Provenzano.7 Long Yan, Steve Trier, Kraig Kumfer, Paolo Provenzano and Tony Collins. 8 8 Permission is granted to use this code for anything. 9 9 */ … … 95 95 private float timeRange; 96 96 private int minWave, waveStep, maxWave; 97 private boolean adjustPeaks, c utEnd;97 private boolean adjustPeaks, computeFWHMs, cutEnd; 98 98 private boolean[] cVisible; 99 99 private int maxPeak; … … 118 118 private JDialog paramDialog; 119 119 private JTextField wField, hField, tField, cField, trField, wlField, sField; 120 private JCheckBox peaksBox, cutBox;120 private JCheckBox peaksBox, fwhmBox, cutBox; 121 121 122 122 // GUI components for intensity pane … … 142 142 private JSpinner numCurves; 143 143 private JCheckBox showData, showScale; 144 private JCheckBox showBox, showLine , showFWHMs;144 private JCheckBox showBox, showLine; 145 145 private JCheckBox showFit, showResiduals; 146 private JCheckBox showFWHMs; 146 147 private JCheckBox zOverride; 147 148 private JTextField zScaleValue; … … 155 156 private Unit[] bcUnits; 156 157 private RealType bType, cType; 157 private RealTupleType bc, b cv;158 private RealTupleType bc, bv, bcv; 158 159 private FunctionType bcvFunc, bcvFuncFit, bcvFuncRes; 159 160 private ScalarMap zMap, zMapFit, zMapRes, vMap, vMapFit, vMapRes; 160 161 private DataRenderer decayRend, fitRend, resRend, lineRend, fwhmRend; 161 private DataReferenceImpl decayRef, f itRef, resRef;162 private DataReferenceImpl decayRef, fwhmRef, fitRef, resRef; 162 163 private DisplayImpl iPlot, decayPlot; 163 164 private ScalarMap intensityMap; … … 262 263 paramPane.setBorder(new EmptyBorder(10, 10, 10, 10)); 263 264 paramDialog.setContentPane(paramPane); 264 paramPane.setLayout(new GridLayout(1 1, 3));265 paramPane.setLayout(new GridLayout(12, 3)); 265 266 wField = addRow(paramPane, "Image width", width, "pixels"); 266 267 hField = addRow(paramPane, "Image height", height, "pixels"); … … 284 285 paramPane.add(new JLabel()); 285 286 paramPane.add(new JLabel()); 286 // row 8 287 // row 9 288 fwhmBox = new JCheckBox("Compute FWHMs", false); 289 fwhmBox.setToolTipText( 290 "<html>Computes the full width half max at each channel.</html>"); 291 paramPane.add(fwhmBox); 292 paramPane.add(new JLabel()); 293 paramPane.add(new JLabel()); 294 // row 10 287 295 cutBox = new JCheckBox("Cut 1.5ns from fit", true); 288 296 cutBox.setToolTipText("<html>When performing exponential curve " + … … 293 301 paramPane.add(new JLabel()); 294 302 paramPane.add(new JLabel()); 295 // row 1 0303 // row 11 296 304 paramPane.add(new JLabel()); 297 305 paramPane.add(new JLabel()); 298 306 paramPane.add(new JLabel()); 299 // row 1 1307 // row 12 300 308 paramPane.add(new JLabel()); 301 309 paramPane.add(ok); … … 348 356 minWave, maxWave, channels, null, new Unit[] {nm}, null); 349 357 bc = new RealTupleType(bType, cType); 358 bv = new RealTupleType(bType, vType); 350 359 bcv = new RealTupleType(bType, cType, vType); 351 360 RealType vType2 = RealType.getRealType("value"); … … 397 406 } 398 407 final DataReferenceImpl curveRef = new DataReferenceImpl("curve"); 399 UnionSet dummyCurve = new UnionSet( xy,new Gridded2DSet[] {408 UnionSet dummyCurve = new UnionSet(new Gridded2DSet[] { 400 409 new Gridded2DSet(xy, new float[][] {{0}, {0}}, 1) 401 410 }); … … 453 462 decayRef = new DataReferenceImpl("decay"); 454 463 decayPlot.addReferences(decayRend, decayRef); 464 465 if (computeFWHMs) { 466 // add reference for full width half maxes 467 fwhmRend = new DefaultRendererJ3D(); 468 fwhmRef = new DataReferenceImpl("fwhm"); 469 decayPlot.addReferences(fwhmRend, fwhmRef, new ConstantMap[] { 470 new ConstantMap(0, Display.Red), 471 new ConstantMap(0, Display.Blue), 472 //new ConstantMap(2, Display.LineWidth) 473 }); 474 } 475 455 476 if (adjustPeaks) { 477 // add references for curve fitting 456 478 fitRend = new DefaultRendererJ3D(); 457 479 fitRef = new DataReferenceImpl("fit"); 458 480 decayPlot.addReferences(fitRend, fitRef, new ConstantMap[] { 459 new ConstantMap(1 .0, Display.Red),460 new ConstantMap(1 .0, Display.Green),461 new ConstantMap(1 .0, Display.Blue)481 new ConstantMap(1, Display.Red), 482 new ConstantMap(1, Display.Green), 483 new ConstantMap(1, Display.Blue) 462 484 }); 463 485 fitRend.toggle(false); … … 582 604 " (shifting by " + shift + ")"); 583 605 } 584 setProgress(progress, 940 + 10 * 585 (c + 1) / channels); // estimate: 94% > 95% 586 if (progress.isCanceled()) System.exit(0); 587 } 588 log("Calculating full width half maxes"); 589 float[] half = new float[channels]; 590 float[] fwhm1 = new float[channels], fwhm2 = new float[channels]; 591 for (int c=0; c<channels; c++) { 592 // sum across all pixels 593 int[] sum = new int[timeBins]; 594 for (int h=0; h<height; h++) { 595 for (int w=0; w<width; w++) { 596 for (int t=0; t<timeBins; t++) sum[t] += values[c][h][w][t]; 597 } 598 } 599 // find full width half max 600 half[c] = sum[maxPeak] / 2f; 601 fwhm1[c] = fwhm2[c] = Float.NaN; 602 boolean up = true; 603 for (int t=0; t<timeBins1; t++) { 604 if (sum[t] <= half[c] && sum[t + 1] >= half[c]) { // upslope 605 // System.out.println("Found upslope: t=" + t + ", low=" + sum[t] + ", hi=" + sum[t+1]);//TEMP 606 float q = (half[c]  sum[t]) / (sum[t + 1]  sum[t]); 607 fwhm1[c] = timeRange * (t + q) / timeBins; // binsToNano 608 } 609 else if (sum[t] >= half[c] && sum[t + 1] <= half[c]) { // downslope 610 // System.out.println("Found downslope: t=" + t + ", low=" + sum[t] + ", hi=" + sum[t+1]);//TEMP 611 float q = (half[c]  sum[t + 1]) / (sum[t]  sum[t + 1]); 612 fwhm2[c] = timeRange * (t + 1  q) / timeBins; // binsToNano 613 } 614 // else System.out.println("Unsuitable: t=" + t + ", low=" + sum[t] + ", hi=" + sum[t+1]);//TEMP 615 if (fwhm1[c] == fwhm1[c] && fwhm2[c] == fwhm2[c]) break; 616 } 617 String s = "#" + (c + 1); 618 while (s.length() < 3) s = " " + s; 619 float h1 = 1000 * fwhm1[c], h2 = 1000 * fwhm2[c]; 620 log("\tChannel " + s + ": fwhm = " + (h2  h1) + " ps"); 621 log("\t peak = " + sum[maxPeak]); 622 log("\t center = " + ((h1 + h2) / 2) + " ps"); 623 log("\t range = [" + h1 + ", " + h2 + "] ps"); 624 setProgress(progress, 950 + 10 * 625 (c + 1) / channels); // estimate: 95% > 96% 606 setProgress(progress, 940 + 20 * 607 (c + 1) / channels); // estimate: 94% > 96% 626 608 if (progress.isCanceled()) System.exit(0); 627 609 } … … 630 612 lineRend = new DefaultRendererJ3D(); 631 613 DataReferenceImpl peakRef = new DataReferenceImpl("peaks"); 632 float peakTime = (float) (maxPeak * timeRange / timeBins);614 float peakTime = (float) (maxPeak * timeRange / (timeBins  1)); 633 615 peakRef.setData(new Gridded2DSet(bc, 634 616 new float[][] {{peakTime, peakTime}, {minWave, maxWave}}, 2)); … … 638 620 //new ConstantMap(2, Display.LineWidth) 639 621 }); 640 641 // add green lines to indicate full width half maxes642 fwhmRend = new DefaultRendererJ3D();643 DataReferenceImpl fwhmRef = new DataReferenceImpl("fwhm");644 Gridded3DSet[] fwhmSets = new Gridded3DSet[channels];645 for (int c=0; c<channels; c++) {646 float wave = minWave + c * waveStep;647 float[][] fwhmLines = {648 {fwhm1[c], fwhm2[c]},649 {wave, wave},650 {half[c], half[c]}651 };652 fwhmSets[c] = new Gridded3DSet(bcv, fwhmLines, 2);653 }654 fwhmRef.setData(new UnionSet(bcv, fwhmSets));655 decayPlot.addReferences(fwhmRend, fwhmRef, new ConstantMap[] {656 new ConstantMap(0, Display.Red),657 new ConstantMap(0, Display.Blue),658 //new ConstantMap(2, Display.LineWidth)659 });660 fwhmRend.toggle(false);661 622 } 662 623 … … 830 791 showLine.setEnabled(adjustPeaks); 831 792 showLine.addActionListener(this); 832 showFWHMs = new JCheckBox("FWHMs", false);833 showFWHMs.setToolTipText("Toggles visibility of full width half maxes");834 showFWHMs.setEnabled(adjustPeaks);835 showFWHMs.addActionListener(this);836 793 showFit = new JCheckBox("Fit", false); 837 794 showFit.setToolTipText("Toggles visibility of fitted curves"); … … 843 800 showResiduals.setEnabled(adjustPeaks); 844 801 showResiduals.addActionListener(this); 802 showFWHMs = new JCheckBox("FWHMs", computeFWHMs); 803 showFWHMs.setToolTipText("Toggles visibility of full width half maxes"); 804 showFWHMs.setEnabled(computeFWHMs); 805 showFWHMs.addActionListener(this); 845 806 846 807 linear = new JRadioButton("Linear", true); … … 933 894 showPanel.add(showBox); 934 895 showPanel.add(showLine); 935 showPanel.add(showFWHMs);936 896 showPanel.add(showFit); 937 897 showPanel.add(showResiduals); 898 showPanel.add(showFWHMs); 938 899 939 900 JPanel scalePanel = new JPanel(); … … 1156 1117 else if (src == showData) decayRend.toggle(showData.isSelected()); 1157 1118 else if (src == showLine) lineRend.toggle(showLine.isSelected()); 1158 else if (src == showFWHMs) fwhmRend.toggle(showFWHMs.isSelected());1159 1119 else if (src == showBox) { 1160 1120 try { decayPlot.getDisplayRenderer().setBoxOn(showBox.isSelected()); } … … 1174 1134 resRend.toggle(showResiduals.isSelected()); 1175 1135 } 1136 else if (src == showFWHMs) fwhmRend.toggle(showFWHMs.isSelected()); 1176 1137 else if (src == zOverride) { 1177 1138 boolean manual = zOverride.isSelected(); … … 1227 1188 waveStep = parse(sField.getText(), waveStep); 1228 1189 adjustPeaks = peaksBox.isSelected(); 1190 computeFWHMs = fwhmBox.isSelected(); 1229 1191 cutEnd = cutBox.isSelected(); 1230 1192 cVisible = new boolean[channels]; … … 1362 1324 AxisScale zScale = zMap.getAxisScale(); 1363 1325 Hashtable hash = new Hashtable(); 1364 for (int i=1; i<=maxVal; i*=BASE) { 1365 hash.put(new Double(Math.log(i) / BASE_LOG), "" + i); 1326 for (int i=1, v=1; v<=maxVal; i++, v*=BASE) { 1327 hash.put(new Double(Math.log(v) / BASE_LOG), 1328 i > 3 ? "1e" + i : "" + v); 1366 1329 } 1367 1330 try { … … 1403 1366 } 1404 1367 1368 // full width half maxes 1369 float[][][] fwhmLines = null; 1370 if (computeFWHMs) { 1371 log("Calculating full width half maxes"); 1372 fwhmLines = new float[channels][3][2]; 1373 for (int c=0, cc=0; c<channels; c++) { 1374 if (!cVisible[c]) continue; 1375 // sum across all pixels 1376 int[] sums = new int[timeBins]; 1377 for (int t=0; t<timeBins; t++) { 1378 if (roiCount == 1) sums[t] = values[c][roiY][roiX][t]; 1379 else { 1380 for (int h=0; h<height; h++) { 1381 for (int w=0; w<width; w++) { 1382 if (roiMask[h][w]) sums[t] += values[c][h][w][t]; 1383 } 1384 } 1385 } 1386 } 1387 int maxSum = 0; 1388 for (int t=0; t<timeBins; t++) if (sums[t] > maxSum) maxSum = sums[t]; 1389 // find full width half max 1390 float half = maxSum / 2f; 1391 float fwhm1 = Float.NaN, fwhm2 = Float.NaN; 1392 boolean up = true; 1393 for (int t=0; t<timeBins1; t++) { 1394 if (sums[t] <= half && sums[t + 1] >= half) { // upslope 1395 float q = (half  sums[t]) / (sums[t + 1]  sums[t]); 1396 fwhm1 = timeRange * (t + q) / (timeBins  1); // binsToNano 1397 } 1398 else if (sums[t] >= half && sums[t + 1] <= half) { // downslope 1399 float q = (half  sums[t + 1]) / (sums[t]  sums[t + 1]); 1400 fwhm2 = timeRange * (t + 1  q) / (timeBins  1); // binsToNano 1401 } 1402 if (fwhm1 == fwhm1 && fwhm2 == fwhm2) break; 1403 } 1404 fwhmLines[c][0][0] = fwhm1; 1405 fwhmLines[c][0][1] = fwhm2; 1406 fwhmLines[c][1][0] = fwhmLines[c][1][1] = minWave + c * waveStep; 1407 fwhmLines[c][2][0] = fwhmLines[c][2][1] = half; 1408 String s = "#" + (c + 1); 1409 while (s.length() < 3) s = " " + s; 1410 float h1 = 1000 * fwhm1, h2 = 1000 * fwhm2; 1411 log("\tChannel " + s + ": fwhm = " + (h2  h1) + " ps"); 1412 log("\t peak = " + sums[maxPeak]); 1413 log("\t center = " + ((h1 + h2) / 2) + " ps"); 1414 log("\t range = [" + h1 + ", " + h2 + "] ps"); 1415 if (plotCanceled) break; 1416 cc++; 1417 } 1418 } 1419 1420 // curve fitting 1405 1421 double[][] fitResults = null; 1406 1422 int numExp = ((Integer) numCurves.getValue()).intValue(); … … 1592 1608 decayRef.setData(doDataLines ? makeLines(ff) : ff); 1593 1609 1610 if (fwhmLines != null) { 1611 // construct "FWHMs" plot 1612 SampledSet[] fwhmSets = new SampledSet[channels]; 1613 for (int c=0; c<channels; c++) { 1614 if (doLog) { 1615 // convert samples to log values for plotting 1616 // this is done AFTER any computations involving samples (above) 1617 for (int i=0; i<fwhmLines[c].length; i++) { 1618 for (int j=0; j<fwhmLines[c][i].length; i++) { 1619 fwhmLines[c][i][j] = linearToLog(fwhmLines[c][i][j]); 1620 } 1621 } 1622 } 1623 if (channels > 1) { 1624 fwhmSets[c] = new Gridded3DSet(bcv, fwhmLines[c], 2); 1625 } 1626 else { 1627 fwhmSets[c] = new Gridded2DSet(bv, 1628 new float[][] {fwhmLines[c][0], fwhmLines[c][2]}, 2); 1629 } 1630 } 1631 fwhmRef.setData(new UnionSet(fwhmSets)); 1632 } 1633 1594 1634 if (fitSamps != null) { 1595 1635 // construct "Fit" plot … … 1675 1715 /** Converts value in picoseconds to histogram bins. */ 1676 1716 private float picoToBins(float pico) { 1677 return timeBins* pico / timeRange / 1000;1717 return (timeBins  1) * pico / timeRange / 1000; 1678 1718 } 1679 1719 1680 1720 /** Converts value in histogram bins to picoseconds. */ 1681 1721 private float binsToPico(float bins) { 1682 return 1000 * timeRange * bins / timeBins;1722 return 1000 * timeRange * bins / (timeBins  1); 1683 1723 } 1684 1724
Note: See TracChangeset
for help on using the changeset viewer.