package cz.cuni.lf1.lge.ThunderSTORM.calibration; import static cz.cuni.lf1.lge.ThunderSTORM.util.MathProxy.abs; import static cz.cuni.lf1.lge.ThunderSTORM.util.MathProxy.sqrt; import static cz.cuni.lf1.lge.ThunderSTORM.util.MathProxy.sqr; import static cz.cuni.lf1.lge.ThunderSTORM.util.MathProxy.pow; import java.util.Arrays; import java.util.Locale; import org.apache.commons.math3.analysis.ParametricUnivariateFunction; import javax.swing.*; /** * A squared polynomial function y = w0*sqrt(1 + ((z-c)/d)^2 + a*((z-c)/d)^3 + b*((z-c)/d)^4) * * Note: to avoid problems with over-fitting, the third degree of the polynomial is set to zero and the fourth degree is forced non-negative * * TODO: this can be solved using regularization put on parameters `a` and `b`, but at the moment * I am not sure how to do it in a simple way using the Apache Commons Math library */ public class DefocusFunctionSqrt extends DefocusFunction { public static final String name = "Huang '08"; public DefocusFunctionSqrt() { } @Override public String getName() { return name; } @Override public JPanel getOptionsPanel() { return null; } @Override public DefocusFunction getImplementation() { return this; } public DefocusFunctionSqrt(double w0, double a, double b, double c, double d, boolean scaledToNm) { super(w0, a, b, c, d, scaledToNm); } @Override public double[] transformParams(double[] params) { double [] trans = Arrays.copyOf(params, params.length); trans[2] = 0; return trans; } @Override public double[] transformParamsInverse(double[] params) { double [] trans = Arrays.copyOf(params, params.length); trans[2] = 0; trans[3] = sqrt(abs(params[3])); return trans; } public DefocusFunctionSqrt(double[] params, boolean scaledToNm) { super(params[0], params[2], params[3], params[1], params[4], scaledToNm); } @Override public double value(double z, double w0, double a, double b, double c, double d) { double xsubx0 = z - c; return 0.5*w0*sqrt(1 + sqr(xsubx0/d) + a*pow(xsubx0/d,3) + b*pow(xsubx0/d,4)); } @Override public ParametricUnivariateFunction getFittingFunction() { return new ParametricUnivariateFunction() { @Override public double value(double x, double... params) { double[] trans = transformParams(params); return DefocusFunctionSqrt.this.value(x, trans[0], trans[2], trans[3], trans[1], trans[4]); } @Override public double[] gradient(double x, double... params) { double[] trans = transformParams(params); double xsubx0 = x - trans[1]; double[] gradients = new double[5]; // Partial derivatives of: w0*sqrt(1 + ((z-c)/d)^2 + a*((z-c)/d)^3 + b*((z-c)/d)^4) double dd = sqrt(1 + sqr(xsubx0/trans[4]) + trans[2]*pow(xsubx0/trans[4],3) + trans[3]*pow(xsubx0/trans[4],4)); gradients[0] = 0.50*dd; gradients[1] = 0.25*trans[0]*(-2*xsubx0/sqr(trans[4]) - 3*trans[2]*sqr(xsubx0)/pow(trans[4],3) - 4*trans[3]*pow(xsubx0,3)/pow(trans[4],4))/dd; gradients[2] = 0.25*trans[0]*pow(xsubx0,3)/pow(trans[4],3)/dd; gradients[3] = 0.25*trans[0]*pow(xsubx0,4)/pow(trans[4],4)/dd; gradients[4] = 0.25*trans[0]*(-2*sqr(xsubx0)/pow(trans[4],3) - 3*trans[2]*pow(xsubx0,3)/pow(trans[4],4) - 4*trans[3]*pow(xsubx0,4)/pow(trans[4],5))/dd; return gradients; } }; } @Override public double[] getInitialParams(double xmin, double ymin) { return new double[]{1, xmin, 1e-2, ymin, 400}; } @Override public DefocusFunction getNewInstance(double w0, double a, double b, double c, double d, boolean scaledToNm) { return new DefocusFunctionSqrt(w0, a, b, c, d, scaledToNm); } @Override public DefocusFunction getNewInstance(double[] params, boolean scaledToNm) { return new DefocusFunctionSqrt(params, scaledToNm); } @Override public DefocusCalibration getCalibration() { return new DaostormCalibration(); } @Override public DefocusCalibration getCalibration(double angle, Homography.TransformationMatrix biplaneTransformation, DefocusFunction polynomS1Final, DefocusFunction polynomS2Final) { return new DaostormCalibration(angle, biplaneTransformation, polynomS1Final, polynomS2Final); } @Override public String toString() { return String.format(Locale.ENGLISH, "%e*sqrt(1 + ((z%+g)/%e)^2 %+e*((z%+g)/%e)^3 %+e*((z%+g)/%e)^4)", w0, -c, d, a, -c, d, b, -c, d); } }