From 3e4f3137bf6f20ad19171dc6d5d93fb7fd47b2b9 Mon Sep 17 00:00:00 2001 From: Frank Sauerburger <f.sauerburger@cern.ch> Date: Thu, 1 Aug 2019 12:57:09 +0200 Subject: [PATCH] Implement PDFs --- nnfwtbn/tests/test_toydata.py | 80 ++++++++++++++++++++++++++++++++++- nnfwtbn/toydata.py | 36 ++++++++++++++++ 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/nnfwtbn/tests/test_toydata.py b/nnfwtbn/tests/test_toydata.py index a67fecb..4ffa540 100644 --- a/nnfwtbn/tests/test_toydata.py +++ b/nnfwtbn/tests/test_toydata.py @@ -1,7 +1,7 @@ import unittest import numpy as np -from nnfwtbn.toydata import rand +from nnfwtbn.toydata import rand, ipdf_gluon, ipdf_quark class ToyDataTestBase(unittest.TestCase): @@ -51,3 +51,81 @@ class ToyDataTestBase(unittest.TestCase): self.assertAlmostEqual(a, 0.90141859) self.assertAlmostEqual(b, 0.85225178) self.assertAlmostEqual(c, 0.93632300) + + def test_pdf_gluon_pos(self): + """ + Check that the pdf is always positive. + """ + N = 100 + for i in range(N): + self.assertTrue(ipdf_gluon(i / N, 1 / N) >= 0) + + + def test_pdf_gluon_normalized(self): + """ + Check that the pdf is normalized. + """ + self.assertAlmostEqual(ipdf_gluon(0, 1), 1) + + def test_pdf_gluon_max(self): + """ + Check that the pdf has it's maximum at x=0. + """ + N = 100 + bins = np.empty(N) + for i in range(N): + bins[i] = ipdf_gluon(i / N, 1 / N) + + self.assertEqual(np.argmax(bins), 0) + + + def test_pdf_gluon_at_1(self): + """ + Check that the pdf vanishes at x=1. + """ + d = 1e-4 + self.assertAlmostEqual(ipdf_gluon(1 - d, d), 0) + + def test_pdf_quark_pos(self): + """ + Check that the pdf is always positive. + """ + N = 100 + for i in range(N): + self.assertTrue(ipdf_quark(i / N, 1 / N) >= 0) + + + def test_pdf_quark_normalized(self): + """ + Check that the pdf is normalized. + """ + self.assertAlmostEqual(ipdf_quark(0, 1), 1) + + def test_pdf_quark_max(self): + """ + Check that the pdf has it's maximum at x=0. + """ + N = 100 + bins = np.empty(N) + for i in range(N): + bins[i] = ipdf_quark(i / N, 1 / N) + + self.assertEqual(np.argmax(bins), 0) + + + def test_pdf_quark_at_1(self): + """ + Check that the pdf vanishes at x=1. + """ + d = 1e-9 + self.assertAlmostEqual(ipdf_quark(1 - d, d), 0) + + def test_pdf_quark_peak(self): + """ + Check that there is a peak at x=0.5. + """ + d = 1e-4 + self.assertGreater( + ipdf_quark(0.5, d), + ipdf_quark(0.3, d) + ) diff --git a/nnfwtbn/toydata.py b/nnfwtbn/toydata.py index 2dffb59..068e48f 100644 --- a/nnfwtbn/toydata.py +++ b/nnfwtbn/toydata.py @@ -5,7 +5,9 @@ module does not rely on external random number generators (seeding numpy might break user code). """ +import math import numpy as np +from scipy.integrate import quad from numba import njit @njit @@ -31,3 +33,37 @@ def rand(size=1, seed=1991): output[i] = (a * output[i - 1] + c) % m return output / m + +def ipdf_gluon(x, dx): + """ + Grossly simplification of the integrated parton distribution function of a + proton for gluons. The method returns the probability to find a gluon + within the proton carrying a momentum fraction between x and x + dx. + + The pdf is normalized to unity. + >>> '%.4f' % ipdf_gluon(0, 1) + '1.0000' + """ + def pdf(x): + return 7 * (x - 1)**6 + + return quad(pdf, x, x + dx)[0] + +def ipdf_quark(x, dx): + """ + Grossly simplification of the integrated parton distribution function of a + proton for quarks (there is only a single quark flavor). The method + returns the probability to find a gluon within the proton carrying a + momentum fraction between x and x + dx. + + The quark pdf has a bump at x=0.5. + + The pdf is normalized to unity. + >>> '%.4f' % ipdf_quark(0, 1) + '1.0000' + """ + def pdf(x): + return 0.6 * 7 * (x - 1)**6 \ + + 0.4 / (20 * math.atan(5) * ((x - 0.5)**2 + 0.01)) + + return quad(pdf, x, x + dx)[0] -- GitLab