Skip to content

Commit

Permalink
Improve Python tests and their coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
Radonirinaunimi committed Oct 20, 2024
1 parent b41d304 commit a46a9fb
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 119 deletions.
14 changes: 14 additions & 0 deletions pineappl_py/src/evolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@ pub struct PyEvolveInfo {

#[pymethods]
impl PyEvolveInfo {
/// Constructor.
#[new]
#[must_use]
pub const fn new(fac1: Vec<f64>, pids1: Vec<i32>, x1: Vec<f64>, ren1: Vec<f64>) -> Self {
Self {
evolve_info: EvolveInfo {
fac1,
pids1,
x1,
ren1,
},
}
}

/// Squared factorization scales of the `Grid`.
#[getter]
fn fac1<'py>(&self, py: Python<'py>) -> Bound<'py, PyArray1<f64>> {
Expand Down
56 changes: 0 additions & 56 deletions pineappl_py/src/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,62 +319,6 @@ impl PyGrid {
.unwrap())
}

/// Evolve grid with one single EKO.
///
/// # Panics
/// TODO
///
/// # Errors
/// TODO
///
/// Parameters
/// ----------
/// slices : Iterable
/// list of (PyOperatorSliceInfo, 5D array) describing each convolution
/// order_mask : numpy.ndarray(bool)
/// boolean mask to activate orders
/// xi : (float, float)
/// factorization and renormalization variation
/// ren1 : numpy.ndarray(float)
/// list of renormalization scales
/// alphas : numpy.ndarray(float)
/// list with :math:`\alpha_s(Q2)` for the process scales
///
/// Returns
/// -------
/// PyFkTable :
/// produced FK table
pub fn evolve_with_slice_iter<'py>(
&self,
slices: &Bound<'py, PyIterator>,
order_mask: Vec<bool>,
xi: (f64, f64, f64),
ren1: Vec<f64>,
alphas: Vec<f64>,
) -> PyResult<PyFkTable> {
Ok(self
.grid
.evolve(
vec![slices.into_iter().map(|slice| {
let (info, op) = slice
.unwrap()
.extract::<(PyOperatorSliceInfo, PyReadonlyArray4<f64>)>()
.unwrap();
Ok::<_, std::io::Error>((
info.info,
// TODO: avoid copying
CowArray::from(op.as_array().to_owned()),
))
})],
&order_mask,
xi,
&AlphasTable { ren1, alphas },
)
.map(|fk_table| PyFkTable { fk_table })
// TODO: avoid unwrap and convert `Result` into `PyResult`
.unwrap())
}

/// Load from file.
///
/// # Panics
Expand Down
10 changes: 10 additions & 0 deletions pineappl_py/src/subgrid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ impl PyMu2 {
fn set_fac(&mut self, value: f64) {
self.mu2.fac = value;
}

#[getter]
const fn frg(&self) -> f64 {
self.mu2.frg
}

#[setter]
fn set_frg(&mut self, value: f64) {
self.mu2.frg = value;
}
}

/// PyO3 wrapper to :rustdoc:`pineappl::subgrid::SubgridEnum <subgrid/struct.SubgridEnum.html>`
Expand Down
43 changes: 40 additions & 3 deletions pineappl_py/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,57 @@
import pytest
import subprocess


class PDF:
def xfxQ(self, pid, x, q):
return self.xfxQ2(pid, x, q**2)

def xfxQ2(self, pid, x, q2):
if pid in range(-6, 6):
return x * (1 - x)
else:
return 0.0

def xfxQ(self, pid, x, q):
return self.xfxQ2(pid, x, q**2)

def alphasQ(self, q):
return 1.0

# Define the Toy Polarized PDF set
def polarized_pdf(self, pid, x, q2):
return 2.0

# Define the Toy Unpolarized PDF set
def unpolarized_pdf(self, pid, x, q2):
return 1.0


@pytest.fixture
def pdf():
return PDF()


@pytest.fixture
def download_objects(tmp_path_factory):
def _download_fk(objname: str) -> None:
download_dir = tmp_path_factory.mktemp("data")
file_path = download_dir / f"{objname}"
args = [
"wget",
"--no-verbose",
"--no-clobber",
"-P",
f"{download_dir}",
f"https://data.nnpdf.science/pineappl/test-data/{objname}",
]

try:
_ = subprocess.run(
args,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
return file_path
except OSError as error:
msg = f"Failed to execute the command {args}."
raise EnvironmentError(msg) from error

return _download_fk
14 changes: 13 additions & 1 deletion pineappl_py/tests/test_evolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import numpy as np
from pineappl.boc import Channel, Kinematics
from pineappl.convolutions import Conv, ConvType
from pineappl.evolution import OperatorSliceInfo
from pineappl.evolution import OperatorSliceInfo, EvolveInfo
from pineappl.grid import Grid, Order
from pineappl.interpolation import Interp
from pineappl.pids import PidBasis
Expand Down Expand Up @@ -61,6 +61,18 @@ def fake_grid(
kinematics=kinematics,
)

def test_evolveinfo(self):
evinfo = EvolveInfo(
fac1=[0.5, 1.0, 2.0],
pids1=[-2, 0, 2],
x1=[1e-3, 0.5, 1],
ren1=[0.5, 1.0, 2.0],
)
np.testing.assert_array_equal(evinfo.fac1, [0.5, 1.0, 2.0])
np.testing.assert_array_equal(evinfo.pids1, [-2, 0, 2])
np.testing.assert_array_equal(evinfo.x1, [1e-3, 0.5, 1.0])
np.testing.assert_array_equal(evinfo.fac1, [0.5, 1.0, 2.0])

def test_with_one_eko(self):
# Define convolution types and the initial state hadrons
# We consider an initial state Polarized Proton
Expand Down
105 changes: 53 additions & 52 deletions pineappl_py/tests/test_fk_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,17 @@
"""

import numpy as np
import pytest
import subprocess
import tempfile
from pineappl.boc import Channel, Kinematics
from pineappl.convolutions import Conv, ConvType
from pineappl.fk_table import FkTable
from pineappl.fk_table import FkTable, FkAssumptions
from pineappl.grid import Grid, Order
from pineappl.import_subgrid import ImportSubgridV1
from pineappl.interpolation import Interp
from pineappl.pids import PidBasis
from typing import List


@pytest.fixture
def download_fktable(tmp_path_factory):
def _download_fk(fkname: str) -> None:
download_dir = tmp_path_factory.mktemp("data")
file_path = download_dir / f"{fkname}"
args = [
"wget",
"--no-verbose",
"--no-clobber",
"-P",
f"{download_dir}",
f"https://data.nnpdf.science/pineappl/test-data/{fkname}",
]

try:
_ = subprocess.run(
args,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
return file_path
except OSError as error:
msg = f"Failed to execute the command {args}."
raise EnvironmentError(msg) from error

return _download_fk


class TestFkTable:
def fake_grid(
self,
Expand Down Expand Up @@ -121,7 +92,11 @@ def test_convolve(self):
np.array([1.0]),
)
g.set_subgrid(0, 0, 0, subgrid.into())
fk = FkTable(g) # Convert Grid -> FkTable

# Convert the Grid -> FkTable
fk = FkTable(g)

# Test a simple convolution of the FK table
np.testing.assert_allclose(
fk.convolve(
pdg_convs=[h_conv],
Expand All @@ -137,38 +112,72 @@ def test_convolve(self):
[5e7 / 9999, 0.0],
)

# Test writing/dumping the FK table into disk
with tempfile.TemporaryDirectory() as tmpdir:
fk.write(f"{tmpdir}/toy_fktable.pineappl")
fk.write_lz4(f"{tmpdir}/toy_fktable.pineappl.lz4")

def test_fktable(
self,
download_objects,
fkname: str = "FKTABLE_CMSTTBARTOT8TEV-TOPDIFF8TEVTOT.pineappl.lz4",
):
fk_table = download_objects(f"{fkname}")
fk = FkTable.read(fk_table)

assert fk.table().shape == (1, 51, 34, 34)
np.testing.assert_allclose(fk.muf2(), 2.7224999999999997)

# Check the various aspects of the Bins
assert fk.bins() == 1
np.testing.assert_allclose(fk.bin_normalizations(), [1.0])
np.testing.assert_allclose(fk.bin_right(dimension=0), [1.0])
np.testing.assert_allclose(fk.bin_left(dimension=0), [0.0])

# Check the various aspects of the Channels
channels = fk.channels()
assert len(channels) == 51
assert [21, 200] in channels

# Check the contents of the x-grid
x_grid = fk.x_grid()
assert x_grid.size == 34
np.testing.assert_allclose(x_grid[0], 1.57456056e-04)

# Test FK optimization
assumption = FkAssumptions("Nf6Sym")
fk.optimize(assumption)

def test_unpolarized_convolution(
self,
download_fktable,
fkname: str = "CMSTTBARTOT8TEV-TOPDIFF8TEVTOT.pineappl.lz4",
pdf,
download_objects,
fkname: str = "FKTABLE_CMSTTBARTOT8TEV-TOPDIFF8TEVTOT.pineappl.lz4",
):
"""Check the convolution of an actual FK table that involves two
symmetrical unpolarized protons:
"""
expected_results = [3.72524538e04]
fk_table = download_fktable(f"{fkname}")
fk_table = download_objects(f"{fkname}")
fk = FkTable.read(fk_table)

# Convolution object of the 1st hadron - Polarized
h = ConvType(polarized=False, time_like=False)
h_conv = Conv(conv_type=h, pid=2212)

# Define the Toy Unpolarized PDF set
def _unpolarized_pdf(pid, x, q2):
return 1.0

np.testing.assert_allclose(
fk.convolve(
pdg_convs=[h_conv, h_conv],
xfxs=[_unpolarized_pdf, _unpolarized_pdf],
xfxs=[pdf.unpolarized_pdf, pdf.unpolarized_pdf],
),
expected_results,
)

def test_polarized_convolution(
self,
download_fktable,
fkname: str = "GRID_STAR_WMWP_510GEV_WM-AL-POL.pineappl.lz4",
pdf,
download_objects,
fkname: str = "FKTABLE_STAR_WMWP_510GEV_WM-AL-POL.pineappl.lz4",
):
"""Check the convolution of an actual FK table that involves two
different initial states:
Expand All @@ -183,7 +192,7 @@ def test_polarized_convolution(
-5.67594297e5,
+6.59245015e4,
]
fk_table = download_fktable(f"{fkname}")
fk_table = download_objects(f"{fkname}")
fk = FkTable.read(fk_table)

# Convolution object of the 1st hadron - Polarized
Expand All @@ -194,18 +203,10 @@ def test_polarized_convolution(
h2 = ConvType(polarized=False, time_like=False)
h2_conv = Conv(conv_type=h2, pid=2212)

# Define the Toy Polarized PDF set
def _polarized_pdf(pid, x, q2):
return 2.0

# Define the Toy Unpolarized PDF set
def _unpolarized_pdf(pid, x, q2):
return 1.0

np.testing.assert_allclose(
fk.convolve(
pdg_convs=[h1_conv, h2_conv],
xfxs=[_polarized_pdf, _unpolarized_pdf],
xfxs=[pdf.polarized_pdf, pdf.unpolarized_pdf],
),
expected_results,
)
Loading

0 comments on commit a46a9fb

Please sign in to comment.