Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 24 additions & 30 deletions bindings/pyroot/pythonizations/test/tf_pycallables.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
Cppyy that creates a C++ wrapper to invoke the Python callable.
"""

import unittest
import math
import unittest

import ROOT

Expand All @@ -23,14 +23,17 @@ class pyf_tf1_callable:
def __call__(self, x, p):
return p[0] * x[0] + p[1]


def pyf_func(x, pars):
return pars[0] * x[0] * x[2] + x[1] * pars[1]


def pyf_tf1_gauss(x, p):
return p[0] * 1.0 / math.sqrt(2.0 * math.pi * p[2]**2) * math.exp(-(x[0] - p[1])**2 / 2.0 / p[2]**2)
return p[0] * 1.0 / math.sqrt(2.0 * math.pi * p[2] ** 2) * math.exp(-((x[0] - p[1]) ** 2) / 2.0 / p[2] ** 2)


def pyf_tf1_coulomb(x, p):
return p[1] * x[0] * x[1] / (p[0]**2) * math.exp(-p[2] / p[0])
return p[1] * x[0] * x[1] / (p[0] ** 2) * math.exp(-p[2] / p[0])


class TF1(unittest.TestCase):
Expand Down Expand Up @@ -73,24 +76,23 @@ def test_callable(self):
for x in [0.0, -1.0, 42.0]:
self.assertEqual(f.Eval(x), pycallable([x], [par1, par2]))


def test_fitgauss(self):
"""
Test fitting a histogram to a Python function
"""
# Gaus function
f = ROOT.TF1("tf1_fitgauss", pyf_tf1_gauss, -4, 4, 3)
f.SetParameter(0, 10.0) # scale
f.SetParameter(1, -1.0) # mean
f.SetParameter(2, 2.0) # standard deviation
f.SetParameter(0, 10.0) # scale
f.SetParameter(1, -1.0) # mean
f.SetParameter(2, 2.0) # standard deviation

# Sample gauss in histogram
h = ROOT.TH1F("h", "test", 100, -4, 4)
h.FillRandom("gaus", 100000)
h.Scale(1.0 / 100000.0 * 100.0 / 8.0) # Normalize as density
h.Scale(1.0 / 100000.0 * 100.0 / 8.0) # Normalize as density

# Fit to histogram and get parameters
h.Fit( f, "0Q" )
h.Fit(f, "0Q")
scale = f.GetParameter(0)
mean = f.GetParameter(1)
std = f.GetParameter(2)
Expand All @@ -108,27 +110,23 @@ def test_evalpar(self):
rtf1_coulomb = ROOT.TF1("my_func", pyf_tf1_coulomb, -10, 10)

# x dataset: 5 pairs of particle charges
x = np.array([
[1.0, 10, 2.0],
[1.5, 10, 2.5],
[2.0, 10, 3.0],
[2.5, 10, 3.5],
[3.0, 10, 4.0]
])

params = np.array([
[1.0], # Distance between charges r
[8.99e9], # Coulomb constant k (in N·m²/C²)
[0.1] # Additional factor for modulation
])
x = np.array([[1.0, 10, 2.0], [1.5, 10, 2.5], [2.0, 10, 3.0], [2.5, 10, 3.5], [3.0, 10, 4.0]])

params = np.array(
[
1.0, # Distance between charges r
8.99e9, # Coulomb constant k (in N·m²/C²)
0.1, # Additional factor for modulation
]
)

# Slice to avoid the dummy column of 10's
res = rtf1_coulomb.EvalPar(x[:, ::2], params)

for i in range(len(x)):
expected_value = pyf_tf1_coulomb(x[i, ::2], params)
self.assertEqual(res[i], expected_value)

def test_evalpar_dynamic(self):
"""
Test the 2D NumPy pythonizations with dynamic TF1 data dimensions
Expand All @@ -139,12 +137,9 @@ def test_evalpar_dynamic(self):
rtf1_func = ROOT.TF1("my_func", pyf_func, -10, 10)

# x dataset with ndims 3
x = np.array([[2., 2, 1],
[1., 2, 3],
[2., 2, 1],
[4., 3, 2]])
x = np.array([[2.0, 2, 1], [1.0, 2, 3], [2.0, 2, 1], [4.0, 3, 2]])

pars = np.array([2., 3.])
pars = np.array([2.0, 3.0])
res = rtf1_func.EvalPar(x, pars)

for i in range(len(x)):
Expand Down Expand Up @@ -204,6 +199,5 @@ def test_params(self):
self.assertEqual(f.Eval(*x), pyf_tf2_params(x, [par1, par2, par3, par4]))


if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

4 changes: 2 additions & 2 deletions tutorials/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -349,9 +349,9 @@ else()
# Keras tutorials. This mirrors the logic in tmva/sofie/test/CMakeLists.txt.
# TODO: make sure we also support the newest Keras
set(unsupported_keras_version "3.5.0")
if (NOT DEFINED ROOT_KERAS_VERSION)
if (ROOT_KERAS_FOUND AND NOT DEFINED ROOT_KERAS_VERSION)
message(WARNING "Keras found, but version unknown — cannot verify compatibility.")
elseif (NOT ROOT_KERAS_VERSION VERSION_LESS ${unsupported_keras_version})
elseif (ROOT_KERAS_FOUND AND NOT ROOT_KERAS_VERSION VERSION_LESS ${unsupported_keras_version})
message(WARNING "Keras version ${ROOT_KERAS_VERSION} is too new for the SOFIE Keras parser (only supports < ${unsupported_keras_version}). Corresponding tutorials will not be tested.")
set(keras_unsupported TRUE)
endif()
Expand Down
Loading