Package ij.plugin.filter

Source Code of ij.plugin.filter.Calibrator

package ij.plugin.filter;
import ij.*;
import ij.gui.*;
import ij.process.*;
import ij.measure.*;
import ij.util.*;
import ij.io.*;
import ij.plugin.TextReader;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import java.io.*;


/** Implements the Analyze/Calibrate command. */
public class Calibrator implements PlugInFilter, Measurements, ActionListener {

  private static final String NONE = "None";
  private static final String INVERTER = "Pixel Inverter";
  private static final String UNCALIBRATED_OD = "Uncalibrated OD";
  private static final String CUSTOM = "Custom";
  private static boolean showSettings;
  private boolean global1, global2;
    private ImagePlus imp;
  private int choiceIndex;
  private String[] functions;
  private  int nFits = CurveFitter.fitList.length;
  private int spacerIndex = nFits+1;
  private int inverterIndex = nFits+2;
  private int odIndex = nFits+3;
  private int customIndex = nFits+4;
  private static String xText = "";
  private static String yText = "";
  private static boolean importedValues;
  private String unit;
  private double lx=0.02, ly=0.1;
  private int oldFunction;
  private String sumResiduals, fitGoodness;
  private Button open, save;
  private GenericDialog gd;
 
  public int setup(String arg, ImagePlus imp) {
    this.imp = imp;
    IJ.register(Calibrator.class);
    return DOES_ALL-DOES_RGB+NO_CHANGES;
  }

  public void run(ImageProcessor ip) {
    global1 = imp.getGlobalCalibration()!=null;
    if (!showDialog(imp))
      return;
    if (choiceIndex==customIndex) {
      showPlot(null, null, imp.getCalibration(), null);
      return;
    } else if (imp.getType()==ImagePlus.GRAY32) {
      if (choiceIndex==0)
        imp.getCalibration().setValueUnit(unit);
      else
        IJ.error("Calibrate", "Function must be \"None\" for 32-bit images,\nbut you can change the Unit.");
    } else
      calibrate(imp);
  }

  public boolean showDialog(ImagePlus imp) {
    String defaultChoice;
    Calibration cal = imp.getCalibration();
    functions = getFunctionList(cal.getFunction()==Calibration.CUSTOM);
    int function = cal.getFunction();
    oldFunction = function;
    double[] p = cal.getCoefficients();
    unit = cal.getValueUnit();
    if (function==Calibration.NONE)
      defaultChoice=NONE;
    else if (function<nFits&&function==Calibration.STRAIGHT_LINE&&p!=null&& p[0]==255.0&&p[1]==-1.0)
      defaultChoice=INVERTER;
    else if (function<nFits)
      defaultChoice = CurveFitter.fitList[function];
    else if (function==Calibration.UNCALIBRATED_OD)
      defaultChoice=UNCALIBRATED_OD;
    else if (function==Calibration.CUSTOM)
      defaultChoice=CUSTOM;
    else
      defaultChoice=NONE;
     
    String tmpText = getMeans();
    if (!importedValues && !tmpText.equals("")) 
      xText = tmpText; 
    gd = new GenericDialog("Calibrate...");
    gd.addChoice("Function:", functions, defaultChoice);
    gd.addStringField("Unit:", unit, 16);
    gd.addTextAreas(xText, yText, 20, 14);
    //gd.addMessage("Left column contains uncalibrated measured values,\n right column contains known values (e.g., OD).");
    gd.addPanel(makeButtonPanel(gd));
    gd.addCheckbox("Global calibration", global1);
    //gd.addCheckbox("Show Simplex Settings", showSettings);
    gd.addHelp(IJ.URL+"/docs/menus/analyze.html#cal");
    gd.showDialog();
    if (gd.wasCanceled())
      return false;
    else {
      choiceIndex = gd.getNextChoiceIndex();
      unit = gd.getNextString();
      xText = gd.getNextText();
      yText = gd.getNextText();
      global2 = gd.getNextBoolean();
      //showSettings = gd.getNextBoolean();
      return true;
    }
  }

  /** Creates a panel containing "Open..." and "Save..." buttons. */
  Panel makeButtonPanel(GenericDialog gd) {
    Panel buttons = new Panel();
      buttons.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 0));
    open = new Button("Open...");
    open.addActionListener(this);
    buttons.add(open);
    save = new Button("Save...");
    save.addActionListener(this);
    buttons.add(save);
    return buttons;
  }
 
  public void calibrate(ImagePlus imp) {
    Calibration cal = imp.getCalibration();
    Calibration calOrig = cal.copy();
    int function = Calibration.NONE;
    boolean is16Bits = imp.getType()==ImagePlus.GRAY16;
    double[] parameters = null;
    double[] x=null, y=null;
    boolean zeroClip=false;
    if (choiceIndex<=0) {
      if (oldFunction==Calibration.NONE&&!yText.equals("")&&!xText.equals(""))
        IJ.error("Calibrate", "Please select a function");
      function = Calibration.NONE;
    } else if (choiceIndex<=nFits) {
      function = choiceIndex - 1;
      x = getData(xText);
      y = getData(yText);
      if (!cal.calibrated() || y.length!=0 || function!=oldFunction) {
        parameters = doCurveFitting(x, y, function);
        if (parameters==null)
          return;
      }
      if (!is16Bits && function!=Calibration.STRAIGHT_LINE) {
        zeroClip = true;
        for (int i=0; i<y.length; i++)
          if (y[i]<0.0) zeroClip = false;
      }
    } else if (choiceIndex==inverterIndex) {
      function = Calibration.STRAIGHT_LINE;
      parameters = new double[2];
      if (is16Bits)
        parameters[0] = 65535;
      else
        parameters[0] = 255;
      parameters[1] = -1.0;
      unit = "Inverted Gray Value";
    } else if (choiceIndex==odIndex) {
      if (is16Bits) {
        IJ.error("Calibrate", "Uncalibrated OD is not supported on 16-bit images.");
        return;
      }
      function = Calibration.UNCALIBRATED_OD;
      unit = "Uncalibrated OD";
    }
    cal.setFunction(function, parameters, unit, zeroClip);
    if (!cal.equals(calOrig))
      imp.setCalibration(cal);
    imp.setGlobalCalibration(global2?cal:null);
    if (global2 || global2!=global1)
      WindowManager.repaintImageWindows();
    else
      imp.repaintWindow();
    if (global2 && global2!=global1)
      FileOpener.setShowConflictMessage(true);
    if (function!=Calibration.NONE)
      showPlot(x, y, cal, fitGoodness);
  }

  double[] doCurveFitting(double[] x, double[] y, int fitType) {
    if (x.length!=y.length || y.length==0) {
      IJ.error("Calibrate",
        "To create a calibration curve, the left column must\n"
        +"contain a list of measured mean pixel values and the\n"
        +"right column must contain the same number of calibration\n"
        +"standard values. Use the Measure command to add mean\n"
        +"pixel value measurements to the left column.\n"
        +" \n"
        +"    Left column: "+x.length+" values\n"
        +"    Right column: "+y.length+" values\n"
        );
      return null;
    }
    int n = x.length;
    double xmin=0.0,xmax;
    if (imp.getType()==ImagePlus.GRAY16)
      xmax=65535.0;
    else
      xmax=255.0;
    double[] a = Tools.getMinMax(y);
    double ymin=a[0], ymax=a[1];
    CurveFitter cf = new CurveFitter(x, y);
    cf.doFit(fitType, showSettings);
    int np = cf.getNumParams();
    double[] p = cf.getParams();
    fitGoodness = IJ.d2s(cf.getRSquared(),6);
    double[] parameters = new double[np];
    for (int i=0; i<np; i++)
      parameters[i] = p[i];
    return parameters;                 
  }
 
  void showPlot(double[] x, double[] y, Calibration cal, String rSquared) {
    if (!cal.calibrated() || (IJ.macroRunning()&&Macro.getOptions()!=null))
      return;
    int xmin,xmax,range;
    float[] ctable = cal.getCTable();
    if (ctable.length==256) { //8-bit image
      xmin = 0;
      xmax = 255;
    } else // 16-bit image
      xmin = 0;
      xmax = 65535;
    }
    range = 256;
    float[] px = new float[range];
    float[] py = new float[range];
    for (int i=0; i<range; i++)
      px[i]=(float)((i/255.0)*xmax);
    for (int i=0; i<range; i++)
      py[i]=ctable[(int)px[i]];
    double[] a = Tools.getMinMax(py);
    double ymin = a[0];
    double ymax = a[1];
    int fit = cal.getFunction();
    String unit = cal.getValueUnit();
    Plot plot = new Plot("Calibration Function","pixel value",unit,px,py);
    plot.setLimits(xmin,xmax,ymin,ymax);
    if (x!=null&&y!=null&&x.length>0&&y.length>0)
      plot.addPoints(x, y, PlotWindow.CIRCLE);
    double[] p = cal.getCoefficients();
    if (fit<=Calibration.LOG2) {
      drawLabel(plot, CurveFitter.fList[fit]);
      ly += 0.04;
    }
    if (p!=null) {
      int np = p.length;
      drawLabel(plot, "a="+IJ.d2s(p[0],6));
      drawLabel(plot, "b="+IJ.d2s(p[1],6));
      if (np>=3)
        drawLabel(plot, "c="+IJ.d2s(p[2],6));
      if (np>=4)
        drawLabel(plot, "d="+IJ.d2s(p[3],6));
      if (np>=5)
        drawLabel(plot, "e="+IJ.d2s(p[4],6));
      ly += 0.04;
    }
    if (rSquared!=null)
      {drawLabel(plot, "R^2="+rSquared); rSquared=null;}
    plot.show();
  }

  void drawLabel(Plot plot, String label) {
    plot.addLabel(lx, ly, label);
    ly += 0.08;
  }
 

  double sqr(double x) {return x*x;}

  String[] getFunctionList(boolean custom) {
    int n = nFits+4;
    if (custom) n++;
    String[] list = new String[n];
    list[0] = NONE;
    for (int i=0; i<nFits; i++)
      list[1+i] = CurveFitter.fitList[i];
    list[spacerIndex] = "-";
    list[inverterIndex] = INVERTER;
    list[odIndex] = UNCALIBRATED_OD;
    if (custom)
      list[customIndex] = CUSTOM;
    return list;
   }
 
  String getMeans() {
    float[] umeans = Analyzer.getUMeans();
    int count = Analyzer.getCounter();
    if (umeans==null || count==0)
      return "";
    if (count>MAX_STANDARDS)
      count = MAX_STANDARDS;
    String s = "";
    for (int i=0; i<count; i++)
      s += IJ.d2s(umeans[i],2)+"\n";
    importedValues = false;
    return s;
  }

  double[] getData(String xData) {
    int len = xData.length();
    StringBuffer sb = new StringBuffer(len);
    for (int i=0; i<len; i++) {
      char c = xData.charAt(i);
      if ((c>='0'&&c<='9') || c=='-'  || c=='.' || c==',' || c=='\n' || c=='\r' || c==' ')
        sb.append(c);
    }
    xData = sb.toString();

    StringTokenizer st = new StringTokenizer(xData);
    int nTokens = st.countTokens();
    if (nTokens<1)
      return new double[0];
    int n = nTokens;
    double data[] = new double[n];
    for (int i=0; i<n; i++) {
      data[i] = getNum(st);
    }
    return data;
  }
 
  double getNum(StringTokenizer st) {
    Double d;
    String token = st.nextToken();
    try {d = new Double(token);}
    catch (NumberFormatException e){d = null;}
    if (d!=null)
      return(d.doubleValue());
    else
      return 0.0;
  }
 
  void save() {
    TextArea ta1 = gd.getTextArea1();
    TextArea ta2 = gd.getTextArea2();
    ta1.selectAll();
    String text1 = ta1.getText();
    ta1.select(0, 0);
    ta2.selectAll();
    String text2 = ta2.getText();
    ta2.select(0, 0);
    double[] x = getData(text1);
    double[] y = getData(text2);
    SaveDialog sd = new SaveDialog("Save as Text...", "calibration", ".txt");
    String name = sd.getFileName();
    if (name == null)
      return;
    String directory = sd.getDirectory();
    PrintWriter pw = null;
    try {
      FileOutputStream fos = new FileOutputStream(directory+name);
      BufferedOutputStream bos = new BufferedOutputStream(fos);
      pw = new PrintWriter(bos);
    }
    catch (IOException e) {
      IJ.error("" + e);
      return;
    }
    IJ.wait(250)// give system time to redraw ImageJ window
    int n = Math.max(x.length, y.length);
    for (int i=0; i<n; i++) {
      String xs = x.length==0?"":i<x.length?""+x[i]:"0";
      String ys = y.length==0?"":i<y.length?""+y[i]:"0";
      pw.println(xs + "\t"+ ys);
    }
    pw.close();
  }
 
  void open() {
    OpenDialog od = new OpenDialog("Open Calibration...", "");
    String directory = od.getDirectory();
    String name = od.getFileName();
    if (name==null)
      return;
    String path = directory + name;
    TextReader tr = new TextReader();
    ImageProcessor ip = tr.open(path);
    if (ip==null)
      return;
    int width = ip.getWidth();
    int height = ip.getHeight();
    if (!((width==1||width==2)&&height>1)) {
      IJ.error("Calibrate", "This appears to not be a one or two column text file");
      return;
    }
    StringBuffer sb = new StringBuffer();
    for (int i=0; i<height; i++) {
      sb.append(""+ip.getPixelValue(0, i));
      sb.append("\n");
    }
    String s1=null, s2=null;
    if (width==2) {
      s1 = new String(sb);
      sb = new StringBuffer();
      for (int i=0; i<height; i++) {
        sb.append(""+ip.getPixelValue(1, i));
        sb.append("\n");
      }
      s2 = new String(sb);
    } else
      s2 = new String(sb);
    if (s1!=null) {
      TextArea ta1 = gd.getTextArea1();
      ta1.selectAll();
      ta1.setText(s1);
    }
    TextArea ta2 = gd.getTextArea2();
    ta2.selectAll();
    ta2.setText(s2);
    importedValues = true;
  }

  public void actionPerformed(ActionEvent e) {
    Object source = e.getSource();
    if (source==save)
      save();
    else if (source==open)
      open();
  }

}
TOP

Related Classes of ij.plugin.filter.Calibrator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.