From ca5f3cf664bf27ee97e404fce5cdde53a20809b9 Mon Sep 17 00:00:00 2001 From: juacrumar Date: Mon, 15 Apr 2024 10:31:48 +0200 Subject: [PATCH 1/8] expose bins and lumi --- pineappl_py/pineappl/fk_table.py | 38 ++++++++++++++++++++++++++++++++ pineappl_py/src/fk_table.rs | 10 +++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/pineappl_py/pineappl/fk_table.py b/pineappl_py/pineappl/fk_table.py index 813f7a7b6..91a7080c4 100644 --- a/pineappl_py/pineappl/fk_table.py +++ b/pineappl_py/pineappl/fk_table.py @@ -1,3 +1,5 @@ +import numpy as np + from .pineappl import PyFkTable, PyFkAssumptions from .utils import PyWrapper @@ -50,6 +52,42 @@ def optimize(self, assumptions = "Nf6Ind"): assumptions = FkAssumptions(assumptions) return self._raw.optimize(assumptions._raw) + def convolute_with_one( + self, + pdg_id, + xfx, + bin_indices=np.array([], dtype=np.uint64), + lumi_mask=np.array([], dtype=bool), + ): + r"""Convolute FkTable with a pdf. + + Parameters + ---------- + pdg_id : int + PDG Monte Carlo ID of the hadronic particle `xfx` is the PDF for + xfx : callable + lhapdf like callable with arguments `pid, x, Q2` returning x*pdf for :math:`x`-grid + bin_indices : sequence(int) + A list with the indices of the corresponding bins that should be calculated. An + empty list means that all orders should be calculated. + lumi_mask : sequence(bool) + Mask for selecting specific luminosity channels. The value `True` means the + corresponding channel is included. An empty list corresponds to all channels being + enabled. + + Returns + ------- + list(float) : + cross sections for all bins, for each scale-variation tuple (first all bins, then + the scale variation) + """ + return self.raw.convolute_with_one( + pdg_id, + xfx, + np.array(bin_indices), + np.array(lumi_mask), + ) + class FkAssumptions(PyWrapper): """ diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index f03d1c793..17781aba1 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -2,7 +2,7 @@ use pineappl::fk_table::{FkAssumptions, FkTable}; use pineappl::grid::Grid; use pineappl::lumi::LumiCache; -use numpy::{IntoPyArray, PyArray1, PyArray4}; +use numpy::{IntoPyArray, PyArray1, PyArray4, PyReadonlyArray1}; use pyo3::prelude::*; use std::collections::HashMap; @@ -218,13 +218,19 @@ impl PyFkTable { &self, pdg_id: i32, xfx: &PyAny, + bin_indices: PyReadonlyArray1, + lumi_mask: PyReadonlyArray1, py: Python<'py>, ) -> &'py PyArray1 { let mut xfx = |id, x, q2| f64::extract(xfx.call1((id, x, q2)).unwrap()).unwrap(); let mut alphas = |_| 1.0; let mut lumi_cache = LumiCache::with_one(pdg_id, &mut xfx, &mut alphas); self.fk_table - .convolute(&mut lumi_cache, &[], &[]) + .convolute( + &mut lumi_cache, + &bin_indices.to_vec().unwrap(), + &lumi_mask.to_vec().unwrap(), + ) .into_pyarray(py) } From c42be0349f9c5093c59ca3742b22ce3cab43ee48 Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Tue, 16 Apr 2024 13:26:53 +0200 Subject: [PATCH 2/8] fix: Add signature to provide defaults --- pineappl_py/src/fk_table.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index 17781aba1..a74e26a65 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -214,6 +214,7 @@ impl PyFkTable { /// ------- /// numpy.ndarray(float) : /// cross sections for all bins + #[pyo3(signature = (pdf_id, xfx, bin_indices = pyarray![].readonly(), lumi_cache = pyarray![].readonly()))] pub fn convolute_with_one<'py>( &self, pdg_id: i32, From 9bace31c4b91d7cba4902d84ae94360515cb138f Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Tue, 16 Apr 2024 14:04:00 +0200 Subject: [PATCH 3/8] fix: Provide default values using options --- pineappl_py/src/fk_table.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index a74e26a65..946cd6803 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -214,24 +214,30 @@ impl PyFkTable { /// ------- /// numpy.ndarray(float) : /// cross sections for all bins - #[pyo3(signature = (pdf_id, xfx, bin_indices = pyarray![].readonly(), lumi_cache = pyarray![].readonly()))] + #[pyo3(signature = (pdg_id, xfx, bin_indices = None, lumi_mask= None))] pub fn convolute_with_one<'py>( &self, pdg_id: i32, xfx: &PyAny, - bin_indices: PyReadonlyArray1, - lumi_mask: PyReadonlyArray1, + bin_indices: Option>, + lumi_mask: Option>, py: Python<'py>, ) -> &'py PyArray1 { let mut xfx = |id, x, q2| f64::extract(xfx.call1((id, x, q2)).unwrap()).unwrap(); let mut alphas = |_| 1.0; let mut lumi_cache = LumiCache::with_one(pdg_id, &mut xfx, &mut alphas); + let bin_indices = if let Some(b) = bin_indices { + b.to_vec().unwrap() + } else { + vec![] + }; + let lumi_mask = if let Some(l) = lumi_mask { + l.to_vec().unwrap() + } else { + vec![] + }; self.fk_table - .convolute( - &mut lumi_cache, - &bin_indices.to_vec().unwrap(), - &lumi_mask.to_vec().unwrap(), - ) + .convolute(&mut lumi_cache, &bin_indices, &lumi_mask) .into_pyarray(py) } From e327ccdb100f3513c0863a963a3779c74a5de50b Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Tue, 16 Apr 2024 14:08:24 +0200 Subject: [PATCH 4/8] fix: Simplify default application --- pineappl_py/src/fk_table.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index 946cd6803..7ab06c778 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -226,18 +226,12 @@ impl PyFkTable { let mut xfx = |id, x, q2| f64::extract(xfx.call1((id, x, q2)).unwrap()).unwrap(); let mut alphas = |_| 1.0; let mut lumi_cache = LumiCache::with_one(pdg_id, &mut xfx, &mut alphas); - let bin_indices = if let Some(b) = bin_indices { - b.to_vec().unwrap() - } else { - vec![] - }; - let lumi_mask = if let Some(l) = lumi_mask { - l.to_vec().unwrap() - } else { - vec![] - }; self.fk_table - .convolute(&mut lumi_cache, &bin_indices, &lumi_mask) + .convolute( + &mut lumi_cache, + &bin_indices.map_or(vec![], |b| b.to_vec().unwrap()), + &lumi_mask.map_or(vec![], |l| l.to_vec().unwrap()), + ) .into_pyarray(py) } From b3c480a9382686fca7f67b3ef0fc7d714a7c46f0 Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Tue, 16 Apr 2024 14:09:52 +0200 Subject: [PATCH 5/8] refactor: Use Rust version of convolute_with_one --- pineappl_py/pineappl/fk_table.py | 38 -------------------------------- 1 file changed, 38 deletions(-) diff --git a/pineappl_py/pineappl/fk_table.py b/pineappl_py/pineappl/fk_table.py index 91a7080c4..813f7a7b6 100644 --- a/pineappl_py/pineappl/fk_table.py +++ b/pineappl_py/pineappl/fk_table.py @@ -1,5 +1,3 @@ -import numpy as np - from .pineappl import PyFkTable, PyFkAssumptions from .utils import PyWrapper @@ -52,42 +50,6 @@ def optimize(self, assumptions = "Nf6Ind"): assumptions = FkAssumptions(assumptions) return self._raw.optimize(assumptions._raw) - def convolute_with_one( - self, - pdg_id, - xfx, - bin_indices=np.array([], dtype=np.uint64), - lumi_mask=np.array([], dtype=bool), - ): - r"""Convolute FkTable with a pdf. - - Parameters - ---------- - pdg_id : int - PDG Monte Carlo ID of the hadronic particle `xfx` is the PDF for - xfx : callable - lhapdf like callable with arguments `pid, x, Q2` returning x*pdf for :math:`x`-grid - bin_indices : sequence(int) - A list with the indices of the corresponding bins that should be calculated. An - empty list means that all orders should be calculated. - lumi_mask : sequence(bool) - Mask for selecting specific luminosity channels. The value `True` means the - corresponding channel is included. An empty list corresponds to all channels being - enabled. - - Returns - ------- - list(float) : - cross sections for all bins, for each scale-variation tuple (first all bins, then - the scale variation) - """ - return self.raw.convolute_with_one( - pdg_id, - xfx, - np.array(bin_indices), - np.array(lumi_mask), - ) - class FkAssumptions(PyWrapper): """ From b5ee51d2af670f0e66521c1bdc52e754dd5d2c06 Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Tue, 16 Apr 2024 14:17:28 +0200 Subject: [PATCH 6/8] feat: Add fk table constructor --- pineappl_py/src/fk_table.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index 7ab06c778..40eb5983d 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -11,6 +11,8 @@ use std::io::BufReader; use std::path::PathBuf; use std::str::FromStr; +use crate::grid::PyGrid; + /// PyO3 wrapper to :rustdoc:`pineappl::fk_table::FkTable ` /// /// *Usage*: `pineko`, `yadism` @@ -38,6 +40,13 @@ impl PyFkAssumptions { #[pymethods] impl PyFkTable { + #[new] + pub fn new(grid: PyGrid) -> Self { + Self { + fk_table: FkTable::try_from(grid.grid), + } + } + #[staticmethod] pub fn read(path: PathBuf) -> Self { Self { From 8f036e5882cfa8fc3be2354f5595d37514cd91a7 Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Tue, 16 Apr 2024 14:17:49 +0200 Subject: [PATCH 7/8] test: Copy convolution test for fk table from grid one --- pineappl_py/tests/test_fk_table.py | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 pineappl_py/tests/test_fk_table.py diff --git a/pineappl_py/tests/test_fk_table.py b/pineappl_py/tests/test_fk_table.py new file mode 100644 index 000000000..88fdddb3f --- /dev/null +++ b/pineappl_py/tests/test_fk_table.py @@ -0,0 +1,40 @@ +import numpy as np + +import pineappl + + +class TestFkTable: + def fake_grid(self, bins=None): + lumis = [pineappl.lumi.LumiEntry([(1, 21, 0.1)])] + orders = [pineappl.grid.Order(3, 0, 0, 0)] + bin_limits = np.array([1e-7, 1e-3, 1] if bins is None else bins, dtype=float) + subgrid_params = pineappl.subgrid.SubgridParams() + g = pineappl.grid.Grid.create(lumis, orders, bin_limits, subgrid_params) + return g + + def test_convolute_with_one(self): + g = self.fake_grid() + + # DIS grid + xs = np.linspace(0.5, 1.0, 5) + vs = xs.copy() + subgrid = pineappl.import_only_subgrid.ImportOnlySubgridV1( + vs[np.newaxis, :, np.newaxis], + np.array([90.0]), + xs, + np.array([1.0]), + ) + g.set_subgrid(0, 0, 0, subgrid) + fk = pineappl.fk_table.FkTable(g) + np.testing.assert_allclose( + fk.convolute_with_one(2212, lambda pid, x, q2: 0.0, lambda q2: 0.0), + [0.0] * 2, + ) + np.testing.assert_allclose( + fk.convolute_with_one(2212, lambda pid, x, q2: 1, lambda q2: 1.0), + [5e6 / 9999, 0.0], + ) + np.testing.assert_allclose( + fk.convolute_with_one(2212, lambda pid, x, q2: 1, lambda q2: 2.0), + [2**3 * 5e6 / 9999, 0.0], + ) From 4c67a2c0822dbcdcff4e49a596c93fd689461fa9 Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Tue, 16 Apr 2024 14:18:44 +0200 Subject: [PATCH 8/8] fix: Add forgotten unwrap --- pineappl_py/src/fk_table.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index 40eb5983d..f561b5353 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -43,7 +43,7 @@ impl PyFkTable { #[new] pub fn new(grid: PyGrid) -> Self { Self { - fk_table: FkTable::try_from(grid.grid), + fk_table: FkTable::try_from(grid.grid).unwrap(), } }