Author: [log in to unmask] Date: Thu Dec 4 17:24:25 2014 New Revision: 1649 Log: Add implementation of landau distribution (in my user area for now but will be moved). Added: java/trunk/users/src/main/java/org/hps/users/jeremym/LandauFunction.java java/trunk/users/src/main/java/org/hps/users/jeremym/LandauPdf.java java/trunk/users/src/test/java/org/hps/users/jeremym/LandauTest.java Added: java/trunk/users/src/main/java/org/hps/users/jeremym/LandauFunction.java ============================================================================= --- java/trunk/users/src/main/java/org/hps/users/jeremym/LandauFunction.java (added) +++ java/trunk/users/src/main/java/org/hps/users/jeremym/LandauFunction.java Thu Dec 4 17:24:25 2014 @@ -0,0 +1,50 @@ +package org.hps.users.jeremym; + +import hep.aida.ref.function.AbstractIFunction; + +public class LandauFunction extends AbstractIFunction { + + LandauPdf landauPdf = new LandauPdf(); + + public LandauFunction() { + this(""); + } + + public LandauFunction(String title) { + + super(); + + variableNames = new String[1]; + variableNames[0] = "x0"; + + parameterNames = new String[2]; + parameterNames[0] = "mean"; + parameterNames[1] = "sigma"; + + init(title); + } + + @Override + public double value(double[] v) { + return landauPdf.getValue(v[0]); + } + + @Override + public void setParameter(String key, double value) throws IllegalArgumentException { + super.setParameter(key, value); + if (key.equals("mean")) { + System.out.println("set mean = " + value); + landauPdf.setMean(value); + } else if (key.equals("sigma")) { + System.out.println("set sigma = " + value); + landauPdf.setSigma(value); + } + } + + @Override + public void setParameters(double[] parameters) throws IllegalArgumentException { + super.setParameters(parameters); + landauPdf.setMean(parameters[0]); + landauPdf.setSigma(parameters[1]); + } +} Added: java/trunk/users/src/main/java/org/hps/users/jeremym/LandauPdf.java ============================================================================= --- java/trunk/users/src/main/java/org/hps/users/jeremym/LandauPdf.java (added) +++ java/trunk/users/src/main/java/org/hps/users/jeremym/LandauPdf.java Thu Dec 4 17:24:25 2014 @@ -0,0 +1,98 @@ +package org.hps.users.jeremym; + + +/** + * <p> + * Landau Probability Distribution + * <p> + * Copied from math/mathcore/src/ProbFuncMathCore.cxx::landau_pdf in ROOT (version 5.34.18). + */ +public class LandauPdf { + + static final double[] p1 = { 0.4259894875, -0.1249762550, 0.03984243700, -0.006298287635, 0.001511162253 }; + static final double[] q1 = { 1.0, -0.3388260629, 0.09594393323, -0.01608042283, 0.003778942063 }; + + static final double[] p2 = { 0.1788541609, 0.1173957403, 0.01488850518, -0.001394989411, 0.0001283617211 }; + static final double[] q2 = { 1.0, 0.7428795082, 0.3153932961, 0.06694219548, 0.008790609714 }; + + static final double[] p3 = { 0.1788544503, 0.09359161662, 0.006325387654, 0.00006611667319, -0.000002031049101 }; + static final double[] q3 = { 1.0, 0.6097809921, 0.2560616665, 0.04746722384, 0.006957301675 }; + + static final double[] p4 = { 0.9874054407, 118.6723273, 849.2794360, -743.7792444, 427.0262186 }; + static final double[] q4 = { 1.0, 106.8615961, 337.6496214, 2016.712389, 1597.063511 }; + + static final double[] p5 = { 1.003675074, 167.5702434, 4789.711289, 21217.86767, -22324.94910 }; + static final double[] q5 = { 1.0, 156.9424537, 3745.310488, 9834.698876, 66924.28357 }; + + static final double[] p6 = { 1.000827619, 664.9143136, 62972.92665, 475554.6998, -5743609.109 }; + static final double[] q6 = { 1.0, 651.4101098, 56974.73333, 165917.4725, -2815759.939 }; + + static final double[] a1 = { 0.04166666667, -0.01996527778, 0.02709538966 }; + static final double[] a2 = { -1.845568670, -4.284640743 }; + + protected double sigma = 0; + protected double mean = 0; + + public LandauPdf(double mean, double sigma) { + this.mean = mean; + this.sigma = sigma; + } + + public LandauPdf() { + } + + public double getValue(double x) { + return getValue(x, mean, sigma); + } + + public void setSigma(double sigma) { + this.sigma = sigma; + } + + public void setMean(double mean) { + this.mean = mean; + } + + /** + * + * @param x The free variable. + * @param sigma The sigma (width) of the distribution. + * @param mean The mean of the distribution. + * @return The value of the Landau distribution at x. + */ + static double getValue(double x, double mean, double sigma) { + // LANDAU pdf : algorithm from CERNLIB G110 denlan same algorithm is used in GSL + if (sigma <= 0) + return 0; + double v = (x - mean) / sigma; + double u, ue, us, denlan; + if (v < -5.5) { + u = Math.exp(v + 1.0); + if (u < 1e-10) + return 0.0; + ue = Math.exp(-1 / u); + us = Math.sqrt(u); + denlan = 0.3989422803 * (ue / us) * (1 + (a1[0] + (a1[1] + a1[2] * u) * u) * u); + } else if (v < -1) { + u = Math.exp(-v - 1); + denlan = Math.exp(-u) * Math.sqrt(u) * (p1[0] + (p1[1] + (p1[2] + (p1[3] + p1[4] * v) * v) * v) * v) / (q1[0] + (q1[1] + (q1[2] + (q1[3] + q1[4] * v) * v) * v) * v); + } else if (v < 1) { + denlan = (p2[0] + (p2[1] + (p2[2] + (p2[3] + p2[4] * v) * v) * v) * v) / (q2[0] + (q2[1] + (q2[2] + (q2[3] + q2[4] * v) * v) * v) * v); + } else if (v < 5) { + denlan = (p3[0] + (p3[1] + (p3[2] + (p3[3] + p3[4] * v) * v) * v) * v) / (q3[0] + (q3[1] + (q3[2] + (q3[3] + q3[4] * v) * v) * v) * v); + } else if (v < 12) { + u = 1 / v; + denlan = u * u * (p4[0] + (p4[1] + (p4[2] + (p4[3] + p4[4] * u) * u) * u) * u) / (q4[0] + (q4[1] + (q4[2] + (q4[3] + q4[4] * u) * u) * u) * u); + } else if (v < 50) { + u = 1 / v; + denlan = u * u * (p5[0] + (p5[1] + (p5[2] + (p5[3] + p5[4] * u) * u) * u) * u) / (q5[0] + (q5[1] + (q5[2] + (q5[3] + q5[4] * u) * u) * u) * u); + } else if (v < 300) { + u = 1 / v; + denlan = u * u * (p6[0] + (p6[1] + (p6[2] + (p6[3] + p6[4] * u) * u) * u) * u) / (q6[0] + (q6[1] + (q6[2] + (q6[3] + q6[4] * u) * u) * u) * u); + } else { + u = 1 / (v - v * Math.log(v) / (v + 1)); + denlan = u * u * (1 + (a2[0] + a2[1] * u) * u); + } + return denlan / sigma; + } +} Added: java/trunk/users/src/test/java/org/hps/users/jeremym/LandauTest.java ============================================================================= --- java/trunk/users/src/test/java/org/hps/users/jeremym/LandauTest.java (added) +++ java/trunk/users/src/test/java/org/hps/users/jeremym/LandauTest.java Thu Dec 4 17:24:25 2014 @@ -0,0 +1,117 @@ +package org.hps.users.jeremym; + +import hep.aida.IFitFactory; +import hep.aida.IFitResult; +import hep.aida.IFitter; +import hep.aida.IFunction; +import hep.aida.IPlotter; +import hep.aida.IProfile1D; +import hep.aida.ref.fitter.FitResult; + +import java.io.IOException; +import java.util.Random; +import java.util.logging.Level; +import java.util.logging.Logger; + +import junit.framework.TestCase; + +import org.lcsim.util.aida.AIDA; + +/** + * <p> + * Test of Landau distribution functions ported from C++ and originally defined in the file + * <p> + * mathcore/src/ProbFuncMathCore.cxx + * <p> + * within ROOT (version 5.34.18). + */ +public class LandauTest extends TestCase { + + static double[] p1 = { 0.4259894875, -0.1249762550, 0.03984243700, -0.006298287635, 0.001511162253 }; + static double[] q1 = { 1.0, -0.3388260629, 0.09594393323, -0.01608042283, 0.003778942063 }; + + static double[] p2 = { 0.1788541609, 0.1173957403, 0.01488850518, -0.001394989411, 0.0001283617211 }; + static double[] q2 = { 1.0, 0.7428795082, 0.3153932961, 0.06694219548, 0.008790609714 }; + + static double[] p3 = { 0.1788544503, 0.09359161662, 0.006325387654, 0.00006611667319, -0.000002031049101 }; + static double[] q3 = { 1.0, 0.6097809921, 0.2560616665, 0.04746722384, 0.006957301675 }; + + static double[] p4 = { 0.9874054407, 118.6723273, 849.2794360, -743.7792444, 427.0262186 }; + static double[] q4 = { 1.0, 106.8615961, 337.6496214, 2016.712389, 1597.063511 }; + + static double[] p5 = { 1.003675074, 167.5702434, 4789.711289, 21217.86767, -22324.94910 }; + static double[] q5 = { 1.0, 156.9424537, 3745.310488, 9834.698876, 66924.28357 }; + + static double[] p6 = { 1.000827619, 664.9143136, 62972.92665, 475554.6998, -5743609.109 }; + static double[] q6 = { 1.0, 651.4101098, 56974.73333, 165917.4725, -2815759.939 }; + + static double[] a1 = { 0.04166666667, -0.01996527778, 0.02709538966 }; + static double[] a2 = { -1.845568670, -4.284640743 }; + + public void testLandauDistribution() { + AIDA aida = AIDA.defaultInstance(); + double mean = 10.0; + double sigma = 2.0; + + LandauPdf landauPdf = new LandauPdf(); + landauPdf.setMean(mean); + landauPdf.setSigma(sigma); + + Random random = new Random(); + + IProfile1D profile = aida.profile1D("Landau P1D", 50, -0.5, 49.5); + for (int i = 0; i < 100; i++) { + for (int x = 0; x < 2000; x++) { + double xVal = x / 10; + double landauVal = landauPdf.getValue(xVal); + double smearedLandau = landauVal * (1.0 + 0.1 * random.nextGaussian()); + profile.fill(xVal, smearedLandau); + } + } + + IPlotter plotter = aida.analysisFactory().createPlotterFactory().create(); + plotter.createRegion(); + plotter.region(0).plot(profile); + + LandauFunction landau = new LandauFunction(); + //IFunctionFactory functionFactory = aida.analysisFactory().createFunctionFactory(null); + IFitFactory fitFactory = aida.analysisFactory().createFitFactory(); + //functionFactory.catalog().add("landau", landau); + + landau.setParameter("sigma", sigma + 0.1); + landau.setParameter("mean", mean + 0.1); + + IFitter fitter = fitFactory.createFitter(); + + Logger minuitLogger = Logger.getLogger("org.freehep.math.minuit"); + minuitLogger.setLevel(Level.ALL); + minuitLogger.info("minuit logger test"); + + IFitResult fitResult = fitter.fit(profile, landau); + + IFunction fittedFunction = fitResult.fittedFunction(); + + plotter.region(0).plot(fittedFunction); + + System.out.println(); + System.out.println("fitted parameters"); + for (String fittedParameterName : fitResult.fittedParameterNames()) { + System.out.println(fittedParameterName + " = " + fitResult.fittedParameter(fittedParameterName)); + } + System.out.println("fit status = " + fitResult.fitStatus()); + + System.out.println(); + System.out.println("fitted function"); + for (String parameterName : fittedFunction.parameterNames()) { + System.out.println(parameterName + " = " + fittedFunction.parameter(parameterName)); + } + + ((FitResult)fitResult).printResult(); + + try { + plotter.writeToFile("Landau.png"); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +}