Changeset 4836


Ignore:
Timestamp:
02/23/09 18:12:57 (11 years ago)
Author:
curtis
Message:

Slim Plotter improvements:

  • Changed export to create one file per wavelength with per-pixel fit data;
  • Started work on fixing individual fit parameters (not yet functional).
Location:
trunk/components/slim-plotter/src/loci/slim
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/components/slim-plotter/src/loci/slim/SlimPlotter.java

    r4745 r4836  
    1 // 
    21// SlimPlotter.java 
    32// 
     
    136135  // GUI components for numerical results 
    137136  private JTextField a1Param, t1Param, a2Param, t2Param, cParam, chi2; 
     137  private JCheckBox a1Fix, t1Fix, a2Fix, t2Fix, cFix; 
     138  private JButton set; 
     139  private Color floatColor, fixColor; 
    138140 
    139141  // other GUI components 
     
    512514      a1Param.setEditable(false); 
    513515      numbers.add(a1Param); 
     516      a1Fix = new JCheckBox("Fix"); 
     517      a1Fix.addItemListener(this); 
     518      numbers.add(a1Fix); 
    514519 
    515520      JLabel t1Label = new JLabel("t1"); 
     
    519524      t1Param.setEditable(false); 
    520525      numbers.add(t1Param); 
     526      t1Fix = new JCheckBox("Fix"); 
     527      t1Fix.addItemListener(this); 
     528      numbers.add(t1Fix); 
    521529 
    522530      JLabel a2Label = new JLabel("a2"); 
     
    526534      a2Param.setEditable(false); 
    527535      numbers.add(a2Param); 
     536      a2Fix = new JCheckBox("Fix"); 
     537      a2Fix.addItemListener(this); 
     538      numbers.add(a2Fix); 
    528539 
    529540      JLabel t2Label = new JLabel("t2"); 
     
    533544      t2Param.setEditable(false); 
    534545      numbers.add(t2Param); 
     546      t2Fix = new JCheckBox("Fix"); 
     547      t2Fix.addItemListener(this); 
     548      numbers.add(t2Fix); 
    535549 
    536550      JLabel cLabel = new JLabel("c"); 
     
    540554      cParam.setEditable(false); 
    541555      numbers.add(cParam); 
     556      cFix = new JCheckBox("Fix"); 
     557      cFix.addItemListener(this); 
     558      numbers.add(cFix); 
    542559 
    543560      JLabel chi2Label = new JLabel("chi^2"); 
     
    547564      chi2.setEditable(false); 
    548565      numbers.add(chi2); 
    549  
    550       SpringUtilities.makeCompactGrid(numbers, 6, 2, 0, 0, 4, 4); 
     566      set = new JButton("Fit"); 
     567      set.addActionListener(this); 
     568      numbers.add(set); 
     569 
     570      if (data.numExp < 2) { 
     571        a2Label.setEnabled(false); 
     572        a2Param.setEnabled(false); 
     573        a2Fix.setEnabled(false); 
     574        t2Label.setEnabled(false); 
     575        t2Param.setEnabled(false); 
     576        t2Fix.setEnabled(false); 
     577      } 
     578 
     579      fixColor = a1Param.getBackground(); 
     580      floatColor = a1Label.getBackground(); 
     581      a1Param.setBackground(floatColor); 
     582      t1Param.setBackground(floatColor); 
     583      a2Param.setBackground(floatColor); 
     584      t2Param.setBackground(floatColor); 
     585      cParam.setBackground(floatColor); 
     586      chi2.setBackground(floatColor); 
     587 
     588      SpringUtilities.makeCompactGrid(numbers, 6, 3, 0, 0, 4, 4); 
    551589 
    552590      colorWidget = new ColorWidget(vMap, "Decay Color Mapping"); 
     
    711749  } 
    712750 
     751  /** Exports fit data to a user-specified file. */ 
     752  public void exportData() { 
     753    // get output file from user 
     754    JFileChooser jc = new JFileChooser(System.getProperty("user.dir")); 
     755    jc.addChoosableFileFilter(new ExtensionFileFilter("txt", 
     756      "Text files")); 
     757    int rval = jc.showSaveDialog(exportData); 
     758    if (rval != JFileChooser.APPROVE_OPTION) return; 
     759    File file = jc.getSelectedFile(); 
     760    if (file == null) return; 
     761 
     762    String fileName = file.getPath(); 
     763    String baseName = fileName.toLowerCase().endsWith(".txt") ? 
     764      fileName.substring(0, fileName.length() - 4) : fileName; 
     765    File binnedFile = new File(baseName + ".txt"); 
     766 
     767    File[] ppFiles = new File[data.channels]; 
     768    for (int c=0; c<data.channels; c++) { 
     769      int wavelength = data.minWave + c * data.waveStep; 
     770      ppFiles[c] = new File(baseName + "-" + wavelength + "nm.txt"); 
     771    } 
     772 
     773    try { 
     774      // write currently displayed binned data to file 
     775      PrintWriter out = new PrintWriter(new FileWriter(binnedFile)); 
     776      out.println(data.timeBins + " x " + data.channels + 
     777        " (count=" + twoDPane.getROICount() + 
     778        ", percent=" + twoDPane.getROIPercent() + 
     779        ", maxVal=" + maxVal + ")"); 
     780      for (int c=0; c<data.channels; c++) { 
     781        for (int t=0; t<data.timeBins; t++) { 
     782          if (t > 0) out.print("\t"); 
     783          float s = samps[data.timeBins * c + t]; 
     784          int is = (int) s; 
     785          if (is == s) out.print(is); 
     786          else out.print(s); 
     787        } 
     788        out.println(); 
     789      } 
     790      out.close(); 
     791 
     792      // write full matrix of per-pixel fitted data 
     793      int roiCount = twoDPane.getROICount(); 
     794      int roiX = twoDPane.getROIX(); 
     795      int roiY = twoDPane.getROIY(); 
     796      boolean[][] mask = twoDPane.getROIMask(); 
     797      for (int c=0; c<data.channels; c++) { 
     798        out = new PrintWriter(new FileWriter(ppFiles[c])); 
     799        out.println("Wavelength\tY\tX\t" + 
     800          "iterations\ta1\tt1\t" + 
     801          "a2\tt2\tc\t" + 
     802          "chi^2 (reduced)\tchi^2 (raw)\t" + 
     803          "first\tlast\tin mask?\t" + 
     804          "a1 fixed?\tt1 fixed?\t" + 
     805          "a2 fixed?\tt2 fixed?\tc fixed?"); 
     806        int wavelength = data.minWave + c * data.waveStep; 
     807        ICurveFitter[][] curveFitters = data.curves[c].getCurves(); 
     808        for (int y=0; y<data.height; y++) { 
     809          for (int x=0; x<data.width; x++) { 
     810            ICurveFitter cf = curveFitters[y][x]; 
     811            int iter = cf.getIterations(); 
     812            double[][] curve = cf.getCurve(); 
     813            double a1 = curve[0][0]; 
     814            double t1 = curve[0][1]; 
     815            String a2 = data.numExp > 1 ? "" + curve[1][0] : ""; 
     816            String t2 = data.numExp > 1 ? "" + curve[1][1] : ""; 
     817            double cValue = data.numExp > 1 ? 
     818              curve[0][2] + curve[1][2] : curve[0][2]; 
     819            double reducedChi2 = cf.getReducedChiSquaredError(); 
     820            double rawChi2 = cf.getChiSquaredError(); 
     821            int first = cf.getFirst(); 
     822            int last = cf.getFirst(); 
     823            boolean inMask = roiCount == 1 ? 
     824              (y == roiY && x == roiX) : 
     825              (mask == null ? false : mask[y][x]); 
     826            boolean[][] fixed = cf.getFixed(); 
     827            boolean fixA1 = fixed[0][0]; 
     828            boolean fixT1 = fixed[0][1]; 
     829            String fixA2 = data.numExp > 1 ? yesNo(fixed[1][0]) : ""; 
     830            String fixT2 = data.numExp > 1 ? yesNo(fixed[1][1]) : ""; 
     831            boolean fixC = fixed[0][2]; 
     832            out.println(wavelength + "\t" + y + "\t" + x + "\t" + 
     833              iter + "\t" + a1 + "\t" + t1 + "\t" + 
     834              a2 + "\t" + t2 + "\t" + cValue + "\t" + 
     835              reducedChi2 + "\t" + rawChi2 + "\t" + 
     836              first + "\t" + last + "\t" + yesNo(inMask) + "\t" + 
     837              yesNo(fixA1) + "\t" + yesNo(fixT1) + "\t" + 
     838              fixA2 + "\t" + fixT2 + "\t" + yesNo(fixC)); 
     839          } 
     840        } 
     841        out.close(); 
     842      } 
     843    } 
     844    catch (IOException exc) { 
     845      JOptionPane.showMessageDialog(exportData, 
     846        "There was a problem writing the file: " + exc.getMessage(), 
     847        SlimData.TITLE, JOptionPane.ERROR_MESSAGE); 
     848    } 
     849  } 
     850 
    713851  // -- ActionListener methods -- 
    714852 
     
    737875    } 
    738876    else if (src == exportData) { 
    739       // get output file from user 
    740       JFileChooser jc = new JFileChooser(System.getProperty("user.dir")); 
    741       jc.addChoosableFileFilter(new ExtensionFileFilter("txt", 
    742         "Text files")); 
    743       int rval = jc.showSaveDialog(exportData); 
    744       if (rval != JFileChooser.APPROVE_OPTION) return; 
    745       File file = jc.getSelectedFile(); 
    746       if (file == null) return; 
    747  
    748       // write currently displayed binned data to file 
    749       try { 
    750         PrintWriter out = new PrintWriter(new FileWriter(file)); 
    751         out.println(data.timeBins + " x " + data.channels + 
    752           " (count=" + twoDPane.getROICount() + 
    753           ", percent=" + twoDPane.getROIPercent() + 
    754           ", maxVal=" + maxVal + ")"); 
    755         for (int c=0; c<data.channels; c++) { 
    756           for (int t=0; t<data.timeBins; t++) { 
    757             if (t > 0) out.print("\t"); 
    758             float s = samps[data.timeBins * c + t]; 
    759             int is = (int) s; 
    760             if (is == s) out.print(is); 
    761             else out.print(s); 
    762           } 
    763           out.println(); 
    764         } 
    765         out.close(); 
    766       } 
    767       catch (IOException exc) { 
    768         JOptionPane.showMessageDialog(exportData, 
    769           "There was a problem writing the file: " + exc.getMessage(), 
    770           SlimData.TITLE, JOptionPane.ERROR_MESSAGE); 
    771       } 
     877      exportData(); 
    772878    } 
    773879    else if (src == clearLog) { 
    774880      console.getTextArea().setText(""); 
     881    } 
     882    else if (src == set) { 
     883      // CTR TODO - apply manually typed values to all curves 
    775884    } 
    776885  } 
     
    855964      plotData(true, false, false); 
    856965    } 
     966    else if (src == a1Fix) fix(a1Fix, a1Param); 
     967    else if (src == t1Fix) fix(t1Fix, t1Param); 
     968    else if (src == a2Fix) fix(a2Fix, a2Param); 
     969    else if (src == t2Fix) fix(t2Fix, t2Param); 
     970    else if (src == cFix) fix(cFix, cParam); 
    857971  } 
    858972 
     
    14741588  } 
    14751589 
     1590  private void fix(JCheckBox box, JTextField field) { 
     1591    boolean fixed = box.isSelected(); 
     1592    field.setEditable(fixed); 
     1593    field.setBackground(fixed ? fixColor : floatColor); 
     1594    // CTR TODO - call CurveRenderer.setFixed(boolean[][]) 
     1595  } 
     1596 
     1597  private String yesNo(boolean value) { return value ? "yes" : "no"; } 
     1598 
    14761599  // -- Utility methods -- 
    14771600 
  • trunk/components/slim-plotter/src/loci/slim/fit/CurveCollection.java

    r4495 r4836  
    182182  } 
    183183 
     184  /** Sets which parameters should be fixed, versus allowed to converge. */ 
     185  public void setFixed(boolean[][] fixed) { 
     186    for (int d=0; d<curves.length; d++) { 
     187      for (int y=0; y<curves[d].length; y++) { 
     188        for (int x=0; x<curves[d][y].length; x++) { 
     189          curves[d][y][x].setFixed(fixed); 
     190        } 
     191      } 
     192    } 
     193  } 
     194 
     195  /** Gets which parameters should be fixed, versus allowed to converge. */ 
     196  public boolean[][] getFixed() { return curves[0][0][0].getFixed(); } 
     197 
    184198  // -- CurveReporter methods -- 
    185199 
  • trunk/components/slim-plotter/src/loci/slim/fit/CurveFitter.java

    r4640 r4836  
    4545  protected int[] curveData; 
    4646  protected double[][] curveEstimate; 
     47  protected boolean[][] curveFixed; 
    4748  protected int firstIndex; 
    4849  protected int lastIndex; 
     
    167168    components = numExp; 
    168169    curveEstimate = new double[numExp][3]; 
     170    curveFixed = new boolean[numExp][3]; 
    169171  } 
    170172 
    171173  /** Returns the number of exponentials to be fitted. */ 
    172174  public int getComponentCount() { return components; } 
     175 
     176  /* @see ICurveFitter#setFixed(boolean[][]) */ 
     177  public void setFixed(boolean[][] fixed) { 
     178    if (fixed.length != components) { 
     179      throw new IllegalArgumentException("Incorrect number of components."); 
     180    } 
     181    if (fixed[0].length != 3) { 
     182      throw new IllegalArgumentException( 
     183          "Incorrect number of elements per degree."); 
     184    } 
     185    curveFixed = fixed; 
     186  } 
     187 
     188  /* @see ICurveFitter#getFixed() */ 
     189  public boolean[][] getFixed() { return curveFixed; } 
    173190 
    174191  /** Initializes the curve fitter with a starting curve estimate. */ 
     
    183200    final double[] guess = {num / 10.0, num / 5.0}; 
    184201    for (int i=0; i<components; i++) { 
    185       curveEstimate[i][0] = (double) peak / components; 
    186       curveEstimate[i][1] = guess[i]; 
    187       curveEstimate[i][2] = 0; 
     202      if (!curveFixed[i][0]) 2urveEstimate[i][0] = (double) peak / components; 
     203      if (!curveFixed[i][1]) curveEstimate[i][1] = guess[i]; 
     204      if (!curveFixed[i][2]) curveEstimate[i][2] = 0; 
    188205    } 
    189206*/ 
     
    257274      } 
    258275      double mult = den == 0 ? max : num / den; 
    259       curveEstimate[0][0] = mult; 
    260       curveEstimate[0][1] = exp; 
    261       curveEstimate[0][2] = guessC + gap; 
     276      if (!curveFixed[0][0]) curveEstimate[0][0] = mult; 
     277      if (!curveFixed[0][1]) curveEstimate[0][1] = exp; 
     278      if (!curveFixed[0][2]) curveEstimate[0][2] = guessC + gap; 
    262279      if (DEBUG) { 
    263280        if (mult != mult || exp != exp || guessC != guessC) { 
     
    274291        if (curveData[i] < guessC) guessC = curveData[i]; 
    275292      } 
    276       curveEstimate[0][2] = guessC; 
    277       curveEstimate[1][2] = 0; 
     293      if (!curveFixed[0][2]) curveEstimate[0][2] = guessC; 
     294      if (!curveFixed[1][2]) curveEstimate[1][2] = 0; 
    278295 
    279296      // First, get a guess for the exponents. 
     
    291308        } 
    292309      } 
    293       curveEstimate[0][1] = high; 
    294       curveEstimate[1][1] = low; 
     310      if (!curveFixed[0][1]) curveEstimate[0][1] = high; 
     311      if (!curveFixed[1][1]) curveEstimate[1][1] = low; 
    295312 
    296313      double highA = 0.0d; 
     
    308325      //if (10.0 > lowA) lowA = 10.0; 
    309326      //if (20.0 > highA) highA = 20.0; 
    310       curveEstimate[0][0] = highA - lowA; 
    311       curveEstimate[1][0] = lowA; 
     327      if (!curveFixed[0][0]) curveEstimate[0][0] = highA - lowA; 
     328      if (!curveFixed[1][0]) curveEstimate[1][0] = lowA; 
    312329      // It seems like the low estimates are pretty good, usually. 
    313330      // It may be possible to get a better high estimate by subtracting out 
     
    354371      } 
    355372      double mult = den == 0 ? max : num / den; 
    356       curveEstimate[0][0] = mult; 
    357       curveEstimate[0][1] = exp; 
    358       curveEstimate[0][2] = guessC; 
     373      if (!curveFixed[0][0]) curveEstimate[0][0] = mult; 
     374      if (!curveFixed[0][1]) curveEstimate[0][1] = exp; 
     375      if (!curveFixed[0][2]) curveEstimate[0][2] = guessC; 
    359376    } 
    360377 
     
    435452      } 
    436453      if (components == 1) { 
    437         curveEstimate[0][0] = maxData - minData; 
    438         curveEstimate[0][1] = expguess; 
    439         curveEstimate[0][2] = minData; 
     454        if (!curveFixed[0][0]) curveEstimate[0][0] = maxData - minData; 
     455        if (!curveFixed[0][1]) curveEstimate[0][1] = expguess; 
     456        if (!curveFixed[0][2]) curveEstimate[0][2] = minData; 
    440457      } 
    441458      else { 
    442459        // 2 components 
    443         curveEstimate[0][0] = maxData * .8; 
    444         curveEstimate[0][1] = expguess; 
    445         curveEstimate[1][0] = maxData * .2; 
    446         curveEstimate[1][1] = expguess; 
    447         curveEstimate[0][2] = minData; 
     460        if (!curveFixed[0][0]) curveEstimate[0][0] = maxData * .8; 
     461        if (!curveFixed[0][1]) curveEstimate[0][1] = expguess; 
     462        if (!curveFixed[1][0]) curveEstimate[1][0] = maxData * .2; 
     463        if (!curveFixed[1][1]) curveEstimate[1][1] = expguess; 
     464        if (!curveFixed[0][2]) curveEstimate[0][2] = minData; 
    448465      } 
    449466      if (DEBUG) { 
  • trunk/components/slim-plotter/src/loci/slim/fit/CurveRenderer.java

    r4697 r4836  
    119119  } 
    120120 
     121  public void setFixed(boolean[][] fixed) { 
     122    curveData.setFixed(fixed); 
     123  } 
     124 
     125  public boolean[][] getFixed() { 
     126    return curveData.getFixed(); 
     127  } 
     128 
    121129  public abstract void setMask(boolean[][] mask); 
    122130 
  • trunk/components/slim-plotter/src/loci/slim/fit/GACurveFitter.java

    r4481 r4836  
    158158      } 
    159159    } 
     160 
     161    // ensure that fixed parameters do not change 
     162    for (int i = 0; i < newGeneration.length; i++) { 
     163      for (int j = 0; j < components; j++) { 
     164        for (int k = 0; k < 3; k++) { 
     165          if (curveFixed[j][k]) newGeneration[i][j][k] = curveEstimate[j][k]; 
     166        } 
     167      } 
     168    } 
     169 
     170    // compute best candidate 
    160171    geneticData = newGeneration; 
    161172    double total = 0.0d; 
  • trunk/components/slim-plotter/src/loci/slim/fit/ICurveFitter.java

    r4461 r4836  
    8888  int getComponentCount(); 
    8989 
     90  /** 
     91   * For each parameter, sets whether it should be fixed at the current value, 
     92   * or allowed to iterate toward an optimal value. 
     93   */ 
     94  void setFixed(boolean[][] fixed); 
     95 
     96  /** 
     97   * For each parameter, gets whether it should be fixed at the current value, 
     98   * or allowed to iterate toward an optimal value. 
     99   */ 
     100  boolean[][] getFixed(); 
     101 
    90102  /** Initializes the curve fitter with a starting curve estimate. */ 
    91103  void estimate(); 
  • trunk/components/slim-plotter/src/loci/slim/fit/ICurveRenderer.java

    r4697 r4836  
    6868  void setComponentCount(int numExp); 
    6969 
     70  void setFixed(boolean[][] fixed); 
     71 
     72  boolean[][] getFixed(); 
     73 
    7074  void setMask(boolean[][] mask); 
    7175 
  • trunk/components/slim-plotter/src/loci/slim/fit/LMCurveFitter.java

    r4641 r4836  
    7575  // -- ICurveFitter methods -- 
    7676 
    77   /** HACK - performs the actual fit. */ 
     77  /* @see ICurveFitter#iterate() */ 
    7878  public void iterate() { 
    7979    iterCount++; 
     
    9191  public int getIterations() { return iterCount; } 
    9292 
    93   /* @see CurveFitter#estimate() */ 
     93  /* @see ICurveFitter#estimate() */ 
    9494  public void estimate() { 
    9595    super.estimate(); 
     
    146146    public double getY(double x, double[] a) { 
    147147      double sum = 0; 
    148       for (int i=0; i<numExp; i++) { 
    149         int e = 2 * i; 
    150         sum += a[e] * Math.exp(-a[e + 1] * x); 
    151       } 
    152       sum += a[2 * numExp]; 
     148      for (int e=0; e<numExp; e++) { 
     149        double aTerm = a[2 * e]; 
     150        double bTerm = a[2 * e + 1]; 
     151        sum += aTerm * Math.exp(-bTerm * x); 
     152      } 
     153      double cTerm = a[2 * numExp]; 
     154      sum += cTerm; 
    153155      return sum; 
    154156    } 
    155157 
    156158    public double getPartialDerivate(double x, double[] a, int parameterIndex) { 
    157       if (parameterIndex == 2 * numExp) return 1; // c 
     159      if (parameterIndex == 2 * numExp) return 1; // c term 
    158160      int e = parameterIndex / 2; 
    159161      int off = parameterIndex % 2; 
     
    162164      switch (off) { 
    163165        case 0: 
    164             return Math.exp(-bTerm * x); // a 
     166            return Math.exp(-bTerm * x); // a term 
    165167        case 1: 
    166           return -aTerm * x * Math.exp(-bTerm * x); // b 
     168          return -aTerm * x * Math.exp(-bTerm * x); // b term 
    167169      } 
    168170      throw new RuntimeException("No such parameter index: " + 
  • trunk/components/slim-plotter/src/loci/slim/fit/RendererSwitcher.java

    r4697 r4836  
    142142  } 
    143143 
     144  public void setFixed(boolean[][] fixed) { 
     145    for (int i=0; i<renderers.length; i++) { 
     146      renderers[i].setFixed(fixed); 
     147    } 
     148  } 
     149 
     150  public boolean[][] getFixed() { 
     151    return renderers[c].getFixed(); 
     152  } 
     153 
    144154  public void setMask(boolean[][] mask) { 
    145155    for (int i=0; i<renderers.length; i++) { 
Note: See TracChangeset for help on using the changeset viewer.