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 ij.plugin.frame.Fitter;
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 = Calibration.EXP_RECOVERY+1;   //don't set to CurveFitter.fitList.length; Calibration can't cope with it
	private String curveFitError;
	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;
	private static boolean showPlotFlagSaved = true;
	private boolean showPlotFlag;
	private static String unitSaved = Calibration.DEFAULT_VALUE_UNIT;
	private CurveFitter curveFitter;
	
	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 (unit == Calibration.DEFAULT_VALUE_UNIT)
		    unit = unitSaved;
		if (function==Calibration.NONE)
			defaultChoice=NONE;
		else if (functionmax) {
			    String title = (bitDepth==8?"8-bit":"16-bit") + " Calibration";
				String msg = "Measured (uncalibrated) values in the left\ncolumn must be in the range 0-";
				IJ.error(title, msg+max+".");
				return false;
			}
		}
		return true;
	}

	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);
		if (cf.getStatus() == Minimizer.INITIALIZATION_FAILURE) {
		    curveFitError = cf.getStatusString();
		    return null;
		}
        if (IJ.debugMode) IJ.log(cf.getResultString());
		int np = cf.getNumParams();
		double[] p = cf.getParams();
		fitGoodness = IJ.d2s(cf.getRSquared(),6);
		curveFitter = cf;
		double[] parameters = new double[np];
		for (int i=0; i0&&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,10));
			drawLabel(plot, "b="+IJ.d2s(p[1],6,10));
			if (np>=3)
				drawLabel(plot, "c="+IJ.d2s(p[2],6,10));
			if (np>=4)
				drawLabel(plot, "d="+IJ.d2s(p[3],6,10));
			if (np>=5)
				drawLabel(plot, "e="+IJ.d2s(p[4],6,10));
			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; iMAX_STANDARDS)
			count = MAX_STANDARDS;
		String s = "";
		for (int i=0; i='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; i1)) {
			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 

Ads help maintain this website.