From be2b473e97e81e1ec79f94a044452eb4b125ddb7 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Tue, 6 Aug 2024 09:16:08 +0200 Subject: [PATCH 01/51] removes pineappl_py/pineappl layer --- pineappl_py/pineappl/__init__.py | 2 - pineappl_py/pineappl/bin.py | 20 - pineappl_py/pineappl/fk_table.py | 68 ---- pineappl_py/pineappl/grid.py | 392 -------------------- pineappl_py/pineappl/import_only_subgrid.py | 48 --- pineappl_py/pineappl/lumi.py | 16 - pineappl_py/pineappl/subgrid.py | 16 - pineappl_py/pineappl/utils.py | 19 - 8 files changed, 581 deletions(-) delete mode 100644 pineappl_py/pineappl/__init__.py delete mode 100644 pineappl_py/pineappl/bin.py delete mode 100644 pineappl_py/pineappl/fk_table.py delete mode 100644 pineappl_py/pineappl/grid.py delete mode 100644 pineappl_py/pineappl/import_only_subgrid.py delete mode 100644 pineappl_py/pineappl/lumi.py delete mode 100644 pineappl_py/pineappl/subgrid.py delete mode 100644 pineappl_py/pineappl/utils.py diff --git a/pineappl_py/pineappl/__init__.py b/pineappl_py/pineappl/__init__.py deleted file mode 100644 index 6b35e954..00000000 --- a/pineappl_py/pineappl/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .pineappl import version as __version__ -from . import bin, fk_table, grid, import_only_subgrid, lumi, subgrid diff --git a/pineappl_py/pineappl/bin.py b/pineappl_py/pineappl/bin.py deleted file mode 100644 index 99395ac8..00000000 --- a/pineappl_py/pineappl/bin.py +++ /dev/null @@ -1,20 +0,0 @@ -import numpy as np - -from .pineappl import PyBinRemapper -from .utils import PyWrapper - - -class BinRemapper(PyWrapper): - """ - Python wrapper object for :class:`~pineappl.pineappl.PyBinRemapper`. - - Parameters - ---------- - normalizations : sequence(float) - list with normalizations - limits : list(tuple(float,float)) - all bin limits as a flat list - """ - - def __init__(self, normalizations, limits): - self._raw = PyBinRemapper(np.array(normalizations), limits) diff --git a/pineappl_py/pineappl/fk_table.py b/pineappl_py/pineappl/fk_table.py deleted file mode 100644 index 2634a523..00000000 --- a/pineappl_py/pineappl/fk_table.py +++ /dev/null @@ -1,68 +0,0 @@ -from .pineappl import PyFkTable, PyFkAssumptions -from .utils import PyWrapper - - -class FkTable(PyWrapper): - """Python wrapper object to interface - :class:`~pineappl.pineappl.PyFkTable`. - - Parameters - ---------- - pyfktable : PyFkTable - raw wrapper object - """ - - def __init__(self, pyfktable): - self._raw = pyfktable - - @classmethod - def from_grid(cls, grid): - return cls(PyFkTable(grid.raw)) - - @classmethod - def read(cls, path): - """Load an existing grid from file. - - Convenience wrapper for :meth:`pineappl.pineappl.PyFkTable.read()`. - - Parameters - ---------- - path : pathlike - file path - - Returns - ------- - FkTable - grid object - """ - return cls(PyFkTable.read(path)) - - def optimize(self, assumptions="Nf6Ind"): - """Optimize FK table storage. - - In order to perform any relevant optimization, assumptions are needed, and they are passed - as parameters to the function. - - Parameters - ---------- - assumptions : FkAssumptions or str - assumptions about the FkTable properties, declared by the user, deciding which - optimizations are possible - """ - if not isinstance(assumptions, FkAssumptions): - assumptions = FkAssumptions(assumptions) - return self._raw.optimize(assumptions._raw) - - -class FkAssumptions(PyWrapper): - """Python wrapper object to interface - :class:`~pineappl.pineappl.PyFkAssumptions`. - - Parameters - ---------- - assumption : str - assumption identifier - """ - - def __init__(self, assumption): - self._raw = PyFkAssumptions(assumption) diff --git a/pineappl_py/pineappl/grid.py b/pineappl_py/pineappl/grid.py deleted file mode 100644 index 2f962d94..00000000 --- a/pineappl_py/pineappl/grid.py +++ /dev/null @@ -1,392 +0,0 @@ -import numpy as np - -from .fk_table import FkTable -from .pineappl import PyGrid, PyOrder, PyOperatorSliceInfo, PyPidBasis -from .utils import PyWrapper - - -class Order(PyWrapper): - r"""Python wrapper object to interface :class:`~pineappl.pineappl.PyOrder`. - - Parameters - ---------- - alphas : int - power of :math:`\alpha_s` - alpha : int - power of :math:`\alpha` - logxir : int - power of :math:`\log(\xi_r)` - logxif : int - power of :math:`\log(\xi_f)` - """ - - def __init__(self, alphas, alpha, logxir, logxif): - self._raw = PyOrder(alphas, alpha, logxir, logxif) - - @staticmethod - def create_mask(orders, max_as, max_al, logs): - r""" - Return a mask suitable to pass as the `order_mask` parameter of - :meth:`Grid.convolve`. - - Parameters - ---------- - orders : list(Order) - list of available orders - max_as : int - maximum power of :math:`\alpha_s` - max_al : int - maximum power of :math:`\alpha` - logs : bool - whether to include log grids or not - - Returns - ------- - list(bool) - boolean mask - - """ - return PyOrder.create_mask([o._raw for o in orders], max_as, max_al, logs) - - -class Grid(PyWrapper): - r"""Python wrapper object to interface :class:`~pineappl.pineappl.PyGrid`. - - To create an object, you should call either :meth:`create` - or :meth:`read`. - - Parameters - ---------- - pygrid : PyGrid - raw wrapper object - """ - - def __init__(self, pygrid): - self._raw = pygrid - - @classmethod - def create(cls, lumi, orders, bin_limits, subgrid_params): - """Create a grid object from its ingredients. - - Parameters - --------- - lumi : list(LumiEntry) - List of active luminosities - orders: list(Order) - List of available orders - bin_limits: sequence(float) - Bin limits - subgrid_params : SubgridParams - subgrid parameters - """ - lumi = [lentry.raw for lentry in lumi] - orders = [o.raw for o in orders] - return cls(PyGrid(lumi, orders, np.array(bin_limits), subgrid_params.raw)) - - def subgrid(self, order, bin_, lumi): - """Retrieve the subgrid at the given position. - - Convenience wrapper for :meth:`pineappl.pineappl.PyGrid.set_subgrid()`. - - Parameters - ---------- - order : int - index of order - bin_ : int - index of bin - lumi : int - index of luminosity - - Returns - ------- - subgrid : Subgrid - subgrid content - """ - return self.raw.subgrid(order, bin_, lumi) - - def __getitem__(self, key): - """Retrieve the subgrid at the given position. - - Syntactic sugar for :meth:`subgrid` - - Parameters - ---------- - key : (int, int, int) - a 3-element integers tuple, consisting in `(order, bin, lumi)` - - Returns - ------- - subgrid : Subgrid - subgrid content - """ - if len(key) != 3: - raise ValueError("A tuple with `(order, bin, lumi)` is required as key.") - - return self.subgrid(*key) - - def set_subgrid(self, order, bin_, lumi, subgrid): - """Set the subgrid at the given position. - - Convenience wrapper for :meth:`pineappl.pineappl.PyGrid.set_subgrid()`. - - Parameters - ---------- - order : int - index of order - bin_ : int - index of bin - lumi : int - index of luminosity - subgrid : ImportOnlySubgridV1 - subgrid content - """ - self.raw.set_subgrid(order, bin_, lumi, subgrid.into()) - - def __setitem__(self, key, subgrid): - """Set the subgrid at the given position. - - Syntactic sugar for :meth:`set_subgrid` - - Parameters - ---------- - key : (int, int, int) - a 3-element integers tuple, consisting in `(order, bin, lumi)` - subgrid : ImportOnlySubgridV1 - subgrid content - """ - if len(key) != 3: - raise ValueError("A tuple with `(order, bin, lumi)` is required as key.") - - self.set_subgrid(*key, subgrid) - - def set_remapper(self, remapper): - """Set the normalizations. - - Convenience wrapper for :meth:`pineappl.pineappl.PyGrid.set_remapper()`. - - Parameters - ---------- - remapper: BinRemapper - Remapper object - """ - self.raw.set_remapper(remapper.raw) - - def orders(self): - """Extract the available perturbative orders and scale variations. - - Convenience wrapper for :meth:`pineappl.pineappl.PyGrid.orders()`. - - Parameters - ---------- - list(Order) : - list with perturbative orders and scale variations - """ - return [Order(*pyorder.as_tuple()) for pyorder in self.raw.orders()] - - def convolve_with_one( - self, - pdg_id, - xfx, - alphas, - order_mask=np.array([], dtype=bool), - bin_indices=np.array([], dtype=np.uint64), - lumi_mask=np.array([], dtype=bool), - xi=((1.0, 1.0),), - ): - r"""Convolute grid with 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 - alphas : callable - lhapdf like callable with arguments `Q2` returning :math:`\alpha_s` - order_mask : sequence(bool) - Mask for selecting specific orders. The value `True` means the corresponding order - is included. An empty list corresponds to all orders being enabled. - 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. - xi : list((float, float)) - A list with the scale variation factors that should be used to calculate - scale-varied results. The first entry of a tuple corresponds to the variation of - the renormalization scale, the second entry to the variation of the factorization - scale. If only results for the central scale are need the list should contain - `(1.0, 1.0)`. - - Returns - ------- - list(float) : - cross sections for all bins, for each scale-variation tuple (first all bins, then - the scale variation) - """ - return self.raw.convolve_with_one( - pdg_id, - xfx, - alphas, - np.array(order_mask), - np.array(bin_indices), - np.array(lumi_mask), - xi, - ) - - def convolve_with_two( - self, - pdg_id1, - xfx1, - pdg_id2, - xfx2, - alphas, - order_mask=np.array([], dtype=bool), - bin_indices=np.array([], dtype=np.uint64), - lumi_mask=np.array([], dtype=bool), - xi=((1.0, 1.0),), - ): - r"""Convolute grid with two pdfs. - - Parameters - ---------- - pdg_id1 : int - PDG Monte Carlo ID of the hadronic particle `xfx1` is the PDF for - xfx1 : callable - lhapdf like callable with arguments `pid, x, Q2` returning x*pdf for :math:`x`-grid - pdg_id2 : int - PDG Monte Carlo ID of the hadronic particle `xfx2` is the PDF for - xfx2 : callable - lhapdf like callable with arguments `pid, x, Q2` returning x*pdf for :math:`x`-grid - alphas : callable - lhapdf like callable with arguments `Q2` returning :math:`\alpha_s` - order_mask : sequence(bool) - Mask for selecting specific orders. The value `True` means the corresponding order - is included. An empty list corresponds to all orders being enabled. - 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. - xi : list((float, float)) - A list with the scale variation factors that should be used to calculate - scale-varied results. The first entry of a tuple corresponds to the variation of - the renormalization scale, the second entry to the variation of the factorization - scale. If only results for the central scale are need the list should contain - `(1.0, 1.0)`. - - Returns - ------- - list(float) : - cross sections for all bins, for each scale-variation tuple (first all bins, then - the scale variation) - """ - return self.raw.convolve_with_two( - pdg_id1, - xfx1, - pdg_id2, - xfx2, - alphas, - np.array(order_mask), - np.array(bin_indices), - np.array(lumi_mask), - xi, - ) - - def evolve( - self, - operators, - mur2_grid, - alphas_values, - lumi_id_types="pdg_mc_ids", - order_mask=(), - xi=(1.0, 1.0), - ): - """Create an FKTable with the EKO. - - Convenience wrapper for :meth:`pineappl.pineappl.PyGrid.evolve()`. - - Parameters - ---------- - operators : dict - EKO Output - mur2_grid : list[float] - renormalization scales - alphas_values : list[float] - alpha_s values associated to the renormalization scales - lumi_id_types : str - kind of lumi types (e.g. "pdg_mc_ids" for flavor basis, "evol" - for evolution basis) - order_mask : list(bool) - Mask for selecting specific orders. The value `True` means the corresponding order - is included. An empty list corresponds to all orders being enabled. - xi : (float, float) - A tuple with the scale variation factors that should be used. - The first entry of a tuple corresponds to the variation of - the renormalization scale, the second entry to the variation of the factorization - scale. If only results for the central scale are need the tuple should be - `(1.0, 1.0)`. - - Returns - ------ - PyFkTable : - raw grid as an FKTable - """ - operator_grid = np.array( - [op["operators"] for op in operators["Q2grid"].values()] - ) - q2grid = list(operators["Q2grid"].keys()) - return FkTable( - self.raw.evolve( - np.array(operator_grid), - operators["q2_ref"], - np.array(operators["inputpids"], dtype=np.int32), - np.array(operators["inputgrid"]), - np.array(q2grid, dtype=np.float64), - np.array(operators["targetpids"], dtype=np.int32), - np.array(operators["targetgrid"]), - np.array(mur2_grid, dtype=np.float64), - np.array(alphas_values, dtype=np.float64), - xi, - lumi_id_types, - np.array(order_mask, dtype=bool), - ) - ) - - @classmethod - def read(cls, path): - """Load an existing grid from file. - - Convenience wrapper for :meth:`pineappl.pineappl.PyGrid.read()`. - - Parameters - ---------- - path : pathlike - file path - - Returns - ------- - Grid - grid object - """ - return cls(PyGrid.read(path)) - - def merge(self, other: "Grid"): - """Merge a second grid in the current one.""" - self.raw.merge(other.raw) - - def delete_bins(self, bin_indices): - """Delete bins. - - Repeated bins and those exceeding length are ignored. - - Parameters - ---------- - bin_indices : sequence(int) - list of indices of bins to removed - """ - self.raw.delete_bins(np.array(bin_indices, dtype=np.uint)) diff --git a/pineappl_py/pineappl/import_only_subgrid.py b/pineappl_py/pineappl/import_only_subgrid.py deleted file mode 100644 index 912015b0..00000000 --- a/pineappl_py/pineappl/import_only_subgrid.py +++ /dev/null @@ -1,48 +0,0 @@ -import numpy as np - -from .pineappl import PyImportOnlySubgridV1 -from .pineappl import PyImportOnlySubgridV2 -from .utils import PyWrapper - - -class ImportOnlySubgridV1(PyWrapper): - """ - Python wrapper object to :class:`~pineappl.pineappl.PyImportOnlySubgridV1`. - - Parameters - ---------- - array : numpy.ndarray(float, dim=3) - 3-dimensional subgrid content - q2_grid : sequence(float) - scale grid - x1_grid : sequence(float) - interpolation grid for :math:`x_1` - x2_grid : sequence(float) - interpolation grid for :math:`x_2` - """ - - def __init__(self, array, q2_grid, x1_grid, x2_grid): - self._raw = PyImportOnlySubgridV1( - np.array(array), np.array(q2_grid), np.array(x1_grid), np.array(x2_grid) - ) - -class ImportOnlySubgridV2(PyWrapper): - """ - Python wrapper object to :class:`~pineappl.pineappl.PyImportOnlySubgridV2`. - - Parameters - ---------- - array : numpy.ndarray(float, dim=3) - 3-dimensional subgrid content - mu2_grid : sequence(float) - scale grid - x1_grid : sequence(float) - interpolation grid for :math:`x_1` - x2_grid : sequence(float) - interpolation grid for :math:`x_2` - """ - - def __init__(self, array, mu2_grid, x1_grid, x2_grid): - self._raw = PyImportOnlySubgridV2( - np.array(array), mu2_grid, np.array(x1_grid), np.array(x2_grid) - ) diff --git a/pineappl_py/pineappl/lumi.py b/pineappl_py/pineappl/lumi.py deleted file mode 100644 index ff0ad280..00000000 --- a/pineappl_py/pineappl/lumi.py +++ /dev/null @@ -1,16 +0,0 @@ -from .pineappl import PyLumiEntry -from .utils import PyWrapper - - -class LumiEntry(PyWrapper): - """ - Python wrapper object to :class:`~pineappl.pineappl.PyLumiEntry`. - - Parameters - ---------- - lumis : list(tuple(int,int,float)) - sequence describing a luminosity function. - """ - - def __init__(self, lumis): - self._raw = PyLumiEntry(lumis) diff --git a/pineappl_py/pineappl/subgrid.py b/pineappl_py/pineappl/subgrid.py deleted file mode 100644 index 00a5b25d..00000000 --- a/pineappl_py/pineappl/subgrid.py +++ /dev/null @@ -1,16 +0,0 @@ -from .pineappl import PySubgridParams, PyMu2 -from .utils import PyWrapper - - -class SubgridParams(PyWrapper): - """ - Python wrapper object to :class:`~pineappl.pineappl.PySubgridParams`. - """ - - def __init__(self): - self._raw = PySubgridParams() - -class Mu2(PyWrapper): - - def __init__(self, ren, fac): - self._raw = PyMu2(ren, fac) diff --git a/pineappl_py/pineappl/utils.py b/pineappl_py/pineappl/utils.py deleted file mode 100644 index bc9a984f..00000000 --- a/pineappl_py/pineappl/utils.py +++ /dev/null @@ -1,19 +0,0 @@ -class PyWrapper: - """ - Python wrapper helper to delegate function calls to the underlying - raw object. - """ - - _raw = None - - @property - def raw(self): - """Raw PyO3 object""" - return self._raw - - def __getattr__(self, name): - """Delegate function calls down.""" - if name[0] != "_": - return self._raw.__getattribute__(name) - else: - raise AttributeError From 7f981447cb52a8a543b128eeb46ad02435cdc3c3 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Tue, 6 Aug 2024 11:40:22 +0200 Subject: [PATCH 02/51] add custom names to structs --- pineappl_py/src/bin.rs | 2 +- pineappl_py/src/fk_table.rs | 4 ++-- pineappl_py/src/grid.rs | 8 ++++---- pineappl_py/src/import_only_subgrid.rs | 4 ++-- pineappl_py/src/lumi.rs | 2 +- pineappl_py/src/subgrid.rs | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pineappl_py/src/bin.rs b/pineappl_py/src/bin.rs index f23038b6..82aa7d94 100644 --- a/pineappl_py/src/bin.rs +++ b/pineappl_py/src/bin.rs @@ -6,7 +6,7 @@ use pyo3::prelude::*; /// PyO3 wrapper to :rustdoc:`pineappl::bin::BinRemapper ` /// /// **Usage**: `yadism` -#[pyclass] +#[pyclass(name = "BinRemapper")] #[derive(Clone)] #[repr(transparent)] pub struct PyBinRemapper { diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index ec43717e..e488f648 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -16,13 +16,13 @@ use crate::grid::PyGrid; /// PyO3 wrapper to :rustdoc:`pineappl::fk_table::FkTable ` /// /// *Usage*: `pineko`, `yadism` -#[pyclass] +#[pyclass(name = "FkTable")] #[repr(transparent)] pub struct PyFkTable { pub(crate) fk_table: FkTable, } -#[pyclass] +#[pyclass(name = "FkAssumptions")] #[repr(transparent)] pub struct PyFkAssumptions { pub(crate) fk_assumptions: FkAssumptions, diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index f89c22da..3640b5a9 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -28,7 +28,7 @@ use pyo3::types::PyIterator; /// PyO3 wrapper to :rustdoc:`pineappl::grid::Order ` /// /// **Usage**: `yadism` -#[pyclass] +#[pyclass(name = "Order")] #[repr(transparent)] pub struct PyOrder { pub(crate) order: Order, @@ -36,7 +36,7 @@ pub struct PyOrder { // TODO: should probably be in a different module // TODO: rename to `PidBasis` -#[pyclass] +#[pyclass(name = "PidBasis")] #[derive(Clone)] pub enum PyPidBasis { Pdg, @@ -54,7 +54,7 @@ impl From for PidBasis { // TODO: should probably be in a different module // TODO: rename to `OperatorSliceInfo` -#[pyclass] +#[pyclass(name = "OperatorSliceInfo")] #[derive(Clone)] pub struct PyOperatorSliceInfo { info: OperatorSliceInfo, @@ -152,7 +152,7 @@ impl PyOrder { /// PyO3 wrapper to :rustdoc:`pineappl::grid::Grid ` /// /// **Usage**: `yadism`, `pineko`, FKTable interface -#[pyclass] +#[pyclass(name = "Grid")] #[repr(transparent)] #[derive(Clone)] pub struct PyGrid { diff --git a/pineappl_py/src/import_only_subgrid.rs b/pineappl_py/src/import_only_subgrid.rs index 47333379..5758fcf7 100644 --- a/pineappl_py/src/import_only_subgrid.rs +++ b/pineappl_py/src/import_only_subgrid.rs @@ -10,7 +10,7 @@ use pyo3::prelude::*; /// PyO3 wrapper to :rustdoc:`pineappl::import_only_subgrid::ImportOnlySubgridV2 ` /// /// **Usage**: `pineko` -#[pyclass] +#[pyclass(name = "ImportOnlySubgridV2")] #[derive(Clone)] #[repr(transparent)] pub struct PyImportOnlySubgridV2 { @@ -71,7 +71,7 @@ impl PyImportOnlySubgridV2 { /// PyO3 wrapper to :rustdoc:`pineappl::import_only_subgrid::ImportOnlySubgridV1 ` /// /// **Usage**: `yadism` -#[pyclass] +#[pyclass(name = "ImportOnlySubgridV1")] #[derive(Clone)] #[repr(transparent)] pub struct PyImportOnlySubgridV1 { diff --git a/pineappl_py/src/lumi.rs b/pineappl_py/src/lumi.rs index cb0d4e73..7328fa8a 100644 --- a/pineappl_py/src/lumi.rs +++ b/pineappl_py/src/lumi.rs @@ -11,7 +11,7 @@ use pyo3::prelude::*; /// 1. the PDG id of the first incoming parton /// 2. the PDG id of the second parton /// 3. a numerical factor that will multiply the result for this specific combination. -#[pyclass] +#[pyclass(name = "LumiEntry")] #[repr(transparent)] pub struct PyLumiEntry { pub(crate) lumi_entry: Channel, diff --git a/pineappl_py/src/subgrid.rs b/pineappl_py/src/subgrid.rs index e9085c96..076f4454 100644 --- a/pineappl_py/src/subgrid.rs +++ b/pineappl_py/src/subgrid.rs @@ -7,7 +7,7 @@ use pyo3::prelude::*; /// PyO3 wrapper to :rustdoc:`pineappl::subgrid::SubgridParams ` /// /// **Usage**: `yadism` -#[pyclass] +#[pyclass(name = "SubgridParams")] #[repr(transparent)] pub struct PySubgridParams { pub(crate) subgrid_params: SubgridParams, @@ -146,7 +146,7 @@ impl PySubgridParams { } /// PyO3 wrapper to :rustdoc:`pineappl::subgrid::Mu2 ` -#[pyclass] +#[pyclass(name = "Mu2")] #[repr(transparent)] pub struct PyMu2 { pub mu2: Mu2, @@ -185,7 +185,7 @@ impl PyMu2 { } /// PyO3 wrapper to :rustdoc:`pineappl::subgrid::SubgridEnum ` -#[pyclass] +#[pyclass(name = "SubgridEnum")] #[derive(Clone)] #[repr(transparent)] pub struct PySubgridEnum { From 5aa3772da7e96d2bcd3b907c7826ade8c5f27222 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Wed, 7 Aug 2024 15:43:37 +0200 Subject: [PATCH 03/51] [working py interface] probably to be reverted --- pineappl_py/src/grid.rs | 26 ++++++++++--------- pineappl_py/tests/test_bin.py | 5 ++-- pineappl_py/tests/test_fk_table.py | 18 +++++++------- pineappl_py/tests/test_grid.py | 40 ++++++++++++++---------------- pineappl_py/tests/test_lumi.py | 5 ++-- pineappl_py/tests/test_sugrid.py | 39 +++++++++++++++-------------- 6 files changed, 66 insertions(+), 67 deletions(-) diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 3640b5a9..50f56753 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -383,15 +383,16 @@ impl PyGrid { /// numpy.ndarray(float) : /// cross sections for all bins, for each scale-variation tuple (first all bins, then /// the scale variation) + #[pyo3(signature = (pdg_id, xfx, alphas, order_mask = None, bin_indices = None, lumi_mask= None, xi = None))] pub fn convolve_with_one<'py>( &self, pdg_id: i32, xfx: &Bound<'py, PyAny>, alphas: &Bound<'py, PyAny>, - order_mask: PyReadonlyArray1, - bin_indices: PyReadonlyArray1, - lumi_mask: PyReadonlyArray1, - xi: Vec<(f64, f64)>, + order_mask: Option>, + bin_indices: Option>, + lumi_mask: Option>, + xi: Option>, py: Python<'py>, ) -> Bound<'py, PyArray1> { let mut xfx = |id, x, q2| xfx.call1((id, x, q2)).unwrap().extract().unwrap(); @@ -401,10 +402,10 @@ impl PyGrid { self.grid .convolve( &mut lumi_cache, - &order_mask.to_vec().unwrap(), - &bin_indices.to_vec().unwrap(), - &lumi_mask.to_vec().unwrap(), - &xi, + &order_mask.map_or(vec![], |b| b.to_vec().unwrap()), + &bin_indices.map_or(vec![], |c| c.to_vec().unwrap()), + &lumi_mask.map_or(vec![], |d| d.to_vec().unwrap()), + &xi.map_or(vec![(1.0, 1.0)], |m| m), ) .into_pyarray_bound(py) } @@ -447,6 +448,7 @@ impl PyGrid { /// numpy.ndarray(float) : /// cross sections for all bins, for each scale-variation tuple (first all bins, then /// the scale variation) + #[pyo3(signature = (pdg_id1, xfx1, pdg_id2, xfx2, alphas, order_mask = None, bin_indices = None, lumi_mask= None, xi = None))] pub fn convolve_with_two<'py>( &self, pdg_id1: i32, @@ -469,10 +471,10 @@ impl PyGrid { self.grid .convolve( &mut lumi_cache, - &order_mask.to_vec().unwrap(), - &bin_indices.to_vec().unwrap(), - &lumi_mask.to_vec().unwrap(), - &xi, + &order_mask.map_or(vec![], |b| b.to_vec().unwrap()), + &bin_indices.map_or(vec![], |c| c.to_vec().unwrap()), + &lumi_mask.map_or(vec![], |d| d.to_vec().unwrap()), + &xi.map_or(vec![(1.0, 1.0)], |m| m), ) .into_pyarray_bound(py) } diff --git a/pineappl_py/tests/test_bin.py b/pineappl_py/tests/test_bin.py index e8484a92..3feecd48 100644 --- a/pineappl_py/tests/test_bin.py +++ b/pineappl_py/tests/test_bin.py @@ -5,10 +5,9 @@ class TestBinRemapper: def test_init(self): - br = pineappl.bin.BinRemapper(np.array([1.0]), [(2, 3)]) + br = pineappl.BinRemapper(np.array([1.0]), [(2, 3)]) - assert isinstance(br, pineappl.bin.BinRemapper) - assert isinstance(br.raw, pineappl.pineappl.PyBinRemapper) + assert isinstance(br, pineappl.BinRemapper) with pytest.raises(AttributeError): br._bla() diff --git a/pineappl_py/tests/test_fk_table.py b/pineappl_py/tests/test_fk_table.py index 4f9455e2..dcef8c5e 100644 --- a/pineappl_py/tests/test_fk_table.py +++ b/pineappl_py/tests/test_fk_table.py @@ -5,11 +5,11 @@ class TestFkTable: def fake_grid(self, bins=None): - lumis = [pineappl.lumi.LumiEntry([(1, 21, 1.0)])] - orders = [pineappl.grid.Order(0, 0, 0, 0)] + lumis = [pineappl.LumiEntry([(1, 21, 1.0)])] + orders = [pineappl.Order(0, 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) + subgrid_params = pineappl.SubgridParams() + g = pineappl.Grid(lumis, orders, bin_limits, subgrid_params) return g def test_convolve_with_one(self): @@ -18,14 +18,14 @@ def test_convolve_with_one(self): # DIS grid xs = np.linspace(0.5, 1.0, 5) vs = xs.copy() - subgrid = pineappl.import_only_subgrid.ImportOnlySubgridV1( + subgrid = pineappl.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.from_grid(g) + g.set_subgrid(0, 0, 0, subgrid.into()) + fk = pineappl.FkTable(g) np.testing.assert_allclose( fk.convolve_with_one(2212, lambda pid, x, q2: 0.0), [0.0] * 2, @@ -35,8 +35,8 @@ def test_convolve_with_one(self): [5e7 / 9999, 0.0], ) - info = pineappl.grid.PyOperatorSliceInfo( - 1.0, [], [], 1.0, [], [], pineappl.grid.PyPidBasis.Pdg + info = pineappl.OperatorSliceInfo( + 1.0, [], [], 1.0, [], [], pineappl.PidBasis.Pdg ) # TODO: write a better test diff --git a/pineappl_py/tests/test_grid.py b/pineappl_py/tests/test_grid.py index 83ad810a..38d37f3d 100644 --- a/pineappl_py/tests/test_grid.py +++ b/pineappl_py/tests/test_grid.py @@ -7,26 +7,24 @@ class TestOrder: def test_init(self): args = (2, 1, 0, 1) - o = pineappl.grid.Order(*args) + o = pineappl.Order(*args) - assert isinstance(o, pineappl.grid.Order) - assert isinstance(o.raw, pineappl.pineappl.PyOrder) + assert isinstance(o, pineappl.Order) assert o.as_tuple() == args class TestGrid: def fake_grid(self, bins=None): - lumis = [pineappl.lumi.LumiEntry([(1, 21, 0.1)])] - orders = [pineappl.grid.Order(3, 0, 0, 0)] + lumis = [pineappl.LumiEntry([(1, 21, 0.1)])] + orders = [pineappl.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) + subgrid_params = pineappl.SubgridParams() + g = pineappl.Grid(lumis, orders, bin_limits, subgrid_params) return g def test_init(self): g = self.fake_grid() - assert isinstance(g, pineappl.grid.Grid) - assert isinstance(g.raw, pineappl.pineappl.PyGrid) + assert isinstance(g, pineappl.Grid) # orders assert len(g.orders()) == 1 assert g.orders()[0].as_tuple() == (3, 0, 0, 0) @@ -37,22 +35,22 @@ def test_set_subgrid(self): # DIS grid xs = np.linspace(0.1, 1.0, 5) vs = np.random.rand(len(xs)) - subgrid = pineappl.import_only_subgrid.ImportOnlySubgridV1( + subgrid = pineappl.ImportOnlySubgridV1( vs[np.newaxis, :, np.newaxis], np.array([90.0]), np.array(xs), np.array([1.0]), ) - g.set_subgrid(0, 0, 0, subgrid) + g.set_subgrid(0, 0, 0, subgrid.into()) # let's mix it for fun with an hadronic one x1s = np.linspace(0.1, 1, 2) x2s = np.linspace(0.5, 1, 2) Q2s = np.linspace(10, 20, 2) - subgrid = pineappl.import_only_subgrid.ImportOnlySubgridV1( + subgrid = pineappl.ImportOnlySubgridV1( np.random.rand(len(Q2s), len(x1s), len(x2s)), Q2s, x1s, x2s ) - g.set_subgrid(0, 1, 0, subgrid) + g.set_subgrid(0, 1, 0, subgrid.into()) g.optimize() def test_set_key_value(self): @@ -64,16 +62,16 @@ def test_set_key_value(self): def test_bins(self): g = self.fake_grid() # 1D - normalizations = [1.0] * 2 + normalizations = np.array([1.0, 1.0]) limits = [(1, 1), (2, 2)] - remapper = pineappl.bin.BinRemapper(normalizations, limits) + remapper = pineappl.BinRemapper(normalizations, limits) g.set_remapper(remapper) assert g.bin_dimensions() == 1 np.testing.assert_allclose(g.bin_left(0), [1, 2]) np.testing.assert_allclose(g.bin_right(0), [1, 2]) # 2D limits = [(1, 2), (2, 3), (2, 4), (3, 5)] - remapper = pineappl.bin.BinRemapper(normalizations, limits) + remapper = pineappl.BinRemapper(normalizations, limits) g.set_remapper(remapper) assert g.bin_dimensions() == 2 np.testing.assert_allclose(g.bin_left(0), [1, 2]) @@ -87,13 +85,13 @@ def test_convolve_with_one(self): # DIS grid xs = np.linspace(0.5, 1.0, 5) vs = xs.copy() - subgrid = pineappl.import_only_subgrid.ImportOnlySubgridV1( + subgrid = pineappl.ImportOnlySubgridV1( vs[np.newaxis, :, np.newaxis], np.array([90.0]), xs, np.array([1.0]), ) - g.set_subgrid(0, 0, 0, subgrid) + g.set_subgrid(0, 0, 0, subgrid.into()) np.testing.assert_allclose( g.convolve_with_one(2212, lambda pid, x, q2: 0.0, lambda q2: 0.0), [0.0] * 2, @@ -112,9 +110,9 @@ def test_io(self, tmp_path): p = tmp_path / "test.pineappl" p.write_text("") g.write(str(p)) - gg = pineappl.grid.Grid.read(p) - assert isinstance(gg, pineappl.grid.Grid) - _ = pineappl.grid.Grid.read(str(p)) + gg = pineappl.Grid.read(p) + assert isinstance(gg, pineappl.Grid) + _ = pineappl.Grid.read(str(p)) def test_fill(self): g = self.fake_grid() diff --git a/pineappl_py/tests/test_lumi.py b/pineappl_py/tests/test_lumi.py index 2e466227..763f8d0a 100644 --- a/pineappl_py/tests/test_lumi.py +++ b/pineappl_py/tests/test_lumi.py @@ -3,7 +3,6 @@ class TestLumiEntry: def test_init(self): - le = pineappl.lumi.LumiEntry([(2, 2, 0.5)]) + le = pineappl.LumiEntry([(2, 2, 0.5)]) - assert isinstance(le, pineappl.lumi.LumiEntry) - assert isinstance(le.raw, pineappl.pineappl.PyLumiEntry) + assert isinstance(le, pineappl.LumiEntry) diff --git a/pineappl_py/tests/test_sugrid.py b/pineappl_py/tests/test_sugrid.py index d5b7aeb5..11469321 100644 --- a/pineappl_py/tests/test_sugrid.py +++ b/pineappl_py/tests/test_sugrid.py @@ -6,19 +6,18 @@ class TestSubgridParams: def test_init(self): - sp = pineappl.subgrid.SubgridParams() - - assert isinstance(sp, pineappl.subgrid.SubgridParams) - assert isinstance(sp.raw, pineappl.pineappl.PySubgridParams) + sp = pineappl.SubgridParams() + assert isinstance(sp, pineappl.SubgridParams) def test_issue_164(pdf): - luminosities = [pineappl.lumi.LumiEntry([(1, 2, 1.0)])] - orders = [pineappl.grid.Order(0, 0, 0, 0)] - params = pineappl.subgrid.SubgridParams() + luminosities = [pineappl.LumiEntry([(1, 2, 1.0)])] + orders = [pineappl.Order(0, 0, 0, 0)] + params = pineappl.SubgridParams() def convolve_grid(): - grid = pineappl.grid.Grid.create(luminosities, orders, [0.0, 1.0], params) + bin_limits = np.array([0.0, 1.0]) + grid = pineappl.Grid(luminosities, orders, bin_limits, params) grid.fill(0.2, 0.2, 10, 0, 0.5, 0, 0.5) return grid.convolve_with_one(2212, pdf.xfxQ, pdf.alphasQ) @@ -31,42 +30,44 @@ def convolve_grid(): res = convolve_grid() assert pytest.approx(res) != 0.0 + class TestSubgrid: def fake_grid(self): - luminosities = [pineappl.lumi.LumiEntry([(1, 2, 1.0)])] - orders = [pineappl.grid.Order(0, 0, 0, 0)] - params = pineappl.subgrid.SubgridParams() - grid = pineappl.grid.Grid.create(luminosities, orders, [0.0, 1.0], params) + luminosities = [pineappl.LumiEntry([(1, 2, 1.0)])] + orders = [pineappl.Order(0, 0, 0, 0)] + params = pineappl.SubgridParams() + bin_limits = np.array([0.0, 1.0]) + grid = pineappl.Grid(luminosities, orders, bin_limits, params) return grid - + def fake_importonlysubgrid(self): x1s = np.linspace(0.1, 1, 2) x2s = np.linspace(0.5, 1, 2) Q2s = np.linspace(10, 20, 2) mu2s = [tuple([q2, q2]) for q2 in Q2s] array = np.random.rand(len(Q2s), len(x1s), len(x2s)) - subgrid = pineappl.import_only_subgrid.ImportOnlySubgridV2(array, mu2s , x1s, x2s) + subgrid = pineappl.ImportOnlySubgridV2(array, mu2s, x1s, x2s) return subgrid, [x1s, x2s, mu2s, array] def test_subgrid_methods(self): grid = self.fake_grid() test_subgrid, infos = self.fake_importonlysubgrid() x1s, x2s, mu2s, _ = (obj for obj in infos) - grid.set_subgrid(0,0,0, test_subgrid) - extr_subgrid = grid.subgrid(0,0,0) + grid.set_subgrid(0, 0, 0, test_subgrid.into()) + extr_subgrid = grid.subgrid(0, 0, 0) facgrid = np.array([mu2.fac for mu2 in extr_subgrid.mu2_grid()]) rengrid = np.array([mu2.ren for mu2 in extr_subgrid.mu2_grid()]) np.testing.assert_allclose([mu2[0] for mu2 in mu2s], rengrid) np.testing.assert_allclose([mu2[1] for mu2 in mu2s], facgrid) np.testing.assert_allclose(extr_subgrid.x1_grid(), x1s) np.testing.assert_allclose(extr_subgrid.x2_grid(), x2s) - + def test_to_array3(self): grid = self.fake_grid() test_subgrid, infos = self.fake_importonlysubgrid() _, _, _, array = (obj for obj in infos) - grid.set_subgrid(0,0,0, test_subgrid) - extr_subgrid = grid.subgrid(0,0,0) + grid.set_subgrid(0, 0, 0, test_subgrid.into()) + extr_subgrid = grid.subgrid(0, 0, 0) test_array = extr_subgrid.to_array3() print(test_array) print(array) From 356f86f7e0eec0d98a9f4d96491017d91f3e55aa Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Wed, 7 Aug 2024 15:53:25 +0200 Subject: [PATCH 04/51] [working py interface] fixed missing Option --- pineappl_py/src/grid.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 50f56753..dfae4d79 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -456,10 +456,10 @@ impl PyGrid { pdg_id2: i32, xfx2: &Bound<'py, PyAny>, alphas: &Bound<'py, PyAny>, - order_mask: PyReadonlyArray1, - bin_indices: PyReadonlyArray1, - lumi_mask: PyReadonlyArray1, - xi: Vec<(f64, f64)>, + order_mask: Option>, + bin_indices: Option>, + lumi_mask: Option>, + xi: Option>, py: Python<'py>, ) -> Bound<'py, PyArray1> { let mut xfx1 = |id, x, q2| xfx1.call1((id, x, q2)).unwrap().extract().unwrap(); From 0a148089a0af0a9d5eeb306bab6116a2567f18a0 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Wed, 7 Aug 2024 16:59:39 +0200 Subject: [PATCH 05/51] actually decide to have nested modules --- pineappl_py/src/bin.rs | 6 ++++++ pineappl_py/src/evolution.rs | 6 ++++++ pineappl_py/src/fk_table.rs | 7 ++++++ pineappl_py/src/grid.rs | 10 +++++++++ pineappl_py/src/import_only_subgrid.rs | 7 ++++++ pineappl_py/src/lib.rs | 22 +++++++------------ pineappl_py/src/lumi.rs | 6 ++++++ pineappl_py/src/subgrid.rs | 8 +++++++ pineappl_py/tests/test_bin.py | 4 ++-- pineappl_py/tests/test_fk_table.py | 16 +++++++------- pineappl_py/tests/test_grid.py | 30 +++++++++++++------------- pineappl_py/tests/test_lumi.py | 5 ++--- pineappl_py/tests/test_sugrid.py | 24 ++++++++++----------- 13 files changed, 97 insertions(+), 54 deletions(-) diff --git a/pineappl_py/src/bin.rs b/pineappl_py/src/bin.rs index 82aa7d94..d12faea7 100644 --- a/pineappl_py/src/bin.rs +++ b/pineappl_py/src/bin.rs @@ -26,3 +26,9 @@ impl PyBinRemapper { Self::new(BinRemapper::new(normalizations.to_vec().unwrap(), limits).unwrap()) } } + +#[pymodule] +pub fn bin(_py: Python, m: &PyModule) -> PyResult<()> { + m.add_class::()?; + Ok(()) +} diff --git a/pineappl_py/src/evolution.rs b/pineappl_py/src/evolution.rs index eb97e08e..8698e9bb 100644 --- a/pineappl_py/src/evolution.rs +++ b/pineappl_py/src/evolution.rs @@ -44,3 +44,9 @@ impl PyEvolveInfo { pub struct PyOperatorSliceInfo { pub(crate) slice_info: OperatorSliceInfo, } + +#[pymodule] +pub fn evolution(_py: Python, m: &PyModule) -> PyResult<()> { + m.add_class::()?; + Ok(()) +} diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index e488f648..12efa3eb 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -302,3 +302,10 @@ impl PyFkTable { self.fk_table.optimize(assumptions.fk_assumptions) } } + +#[pymodule] +pub fn fk_table(_py: Python, m: &PyModule) -> PyResult<()> { + m.add_class::()?; + m.add_class::()?; + Ok(()) +} diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index dfae4d79..2825119c 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -869,3 +869,13 @@ impl PyGrid { self.grid.delete_bins(&bin_indices.to_vec().unwrap()) } } + +#[pymodule] +pub fn grid(_py: Python, m: &PyModule) -> PyResult<()> { + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + + Ok(()) +} diff --git a/pineappl_py/src/import_only_subgrid.rs b/pineappl_py/src/import_only_subgrid.rs index 5758fcf7..a3e74041 100644 --- a/pineappl_py/src/import_only_subgrid.rs +++ b/pineappl_py/src/import_only_subgrid.rs @@ -129,3 +129,10 @@ impl PyImportOnlySubgridV1 { } } } + +#[pymodule] +pub fn import_only_subgrid(_py: Python, m: &PyModule) -> PyResult<()> { + m.add_class::()?; + m.add_class::()?; + Ok(()) +} diff --git a/pineappl_py/src/lib.rs b/pineappl_py/src/lib.rs index 03b24288..5a20a07e 100644 --- a/pineappl_py/src/lib.rs +++ b/pineappl_py/src/lib.rs @@ -2,6 +2,7 @@ #![allow(unsafe_op_in_unsafe_fn)] use pyo3::prelude::*; +use pyo3::wrap_pymodule; pub mod bin; pub mod evolution; @@ -16,20 +17,13 @@ pub mod subgrid; /// NOTE: this name has to match the one in Cargo.toml 'lib.name' #[pymodule] fn pineappl(m: &Bound<'_, PyModule>) -> PyResult<()> { - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; + m.add_wrapped(wrap_pymodule!(bin::bin))?; + m.add_wrapped(wrap_pymodule!(grid::grid))?; + m.add_wrapped(wrap_pymodule!(import_only_subgrid::import_only_subgrid))?; + m.add_wrapped(wrap_pymodule!(evolution::evolution))?; + m.add_wrapped(wrap_pymodule!(lumi::lumi))?; + m.add_wrapped(wrap_pymodule!(fk_table::fk_table))?; + m.add_wrapped(wrap_pymodule!(subgrid::subgrid))?; m.add("version", env!("CARGO_PKG_VERSION"))?; Ok(()) diff --git a/pineappl_py/src/lumi.rs b/pineappl_py/src/lumi.rs index 7328fa8a..63c49bda 100644 --- a/pineappl_py/src/lumi.rs +++ b/pineappl_py/src/lumi.rs @@ -42,3 +42,9 @@ impl PyLumiEntry { self.lumi_entry.entry().to_vec() } } + +#[pymodule] +pub fn lumi(_py: Python, m: &PyModule) -> PyResult<()> { + m.add_class::()?; + Ok(()) +} diff --git a/pineappl_py/src/subgrid.rs b/pineappl_py/src/subgrid.rs index 076f4454..2717bf39 100644 --- a/pineappl_py/src/subgrid.rs +++ b/pineappl_py/src/subgrid.rs @@ -230,3 +230,11 @@ impl PySubgridEnum { PyArray1::from_slice_bound(py, &self.subgrid_enum.x2_grid()) } } + +#[pymodule] +pub fn subgrid(_py: Python, m: &PyModule) -> PyResult<()> { + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + Ok(()) +} diff --git a/pineappl_py/tests/test_bin.py b/pineappl_py/tests/test_bin.py index 3feecd48..66044c78 100644 --- a/pineappl_py/tests/test_bin.py +++ b/pineappl_py/tests/test_bin.py @@ -5,9 +5,9 @@ class TestBinRemapper: def test_init(self): - br = pineappl.BinRemapper(np.array([1.0]), [(2, 3)]) + br = pineappl.bin.BinRemapper(np.array([1.0]), [(2, 3)]) - assert isinstance(br, pineappl.BinRemapper) + assert isinstance(br, pineappl.bin.BinRemapper) with pytest.raises(AttributeError): br._bla() diff --git a/pineappl_py/tests/test_fk_table.py b/pineappl_py/tests/test_fk_table.py index dcef8c5e..b8ac400c 100644 --- a/pineappl_py/tests/test_fk_table.py +++ b/pineappl_py/tests/test_fk_table.py @@ -5,11 +5,11 @@ class TestFkTable: def fake_grid(self, bins=None): - lumis = [pineappl.LumiEntry([(1, 21, 1.0)])] - orders = [pineappl.Order(0, 0, 0, 0)] + lumis = [pineappl.lumi.LumiEntry([(1, 21, 1.0)])] + orders = [pineappl.grid.Order(0, 0, 0, 0)] bin_limits = np.array([1e-7, 1e-3, 1] if bins is None else bins, dtype=float) - subgrid_params = pineappl.SubgridParams() - g = pineappl.Grid(lumis, orders, bin_limits, subgrid_params) + subgrid_params = pineappl.subgrid.SubgridParams() + g = pineappl.grid.Grid(lumis, orders, bin_limits, subgrid_params) return g def test_convolve_with_one(self): @@ -18,14 +18,14 @@ def test_convolve_with_one(self): # DIS grid xs = np.linspace(0.5, 1.0, 5) vs = xs.copy() - subgrid = pineappl.ImportOnlySubgridV1( + 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.into()) - fk = pineappl.FkTable(g) + fk = pineappl.fk_table.FkTable(g) np.testing.assert_allclose( fk.convolve_with_one(2212, lambda pid, x, q2: 0.0), [0.0] * 2, @@ -35,8 +35,8 @@ def test_convolve_with_one(self): [5e7 / 9999, 0.0], ) - info = pineappl.OperatorSliceInfo( - 1.0, [], [], 1.0, [], [], pineappl.PidBasis.Pdg + info = pineappl.grid.OperatorSliceInfo( + 1.0, [], [], 1.0, [], [], pineappl.grid.PidBasis.Pdg ) # TODO: write a better test diff --git a/pineappl_py/tests/test_grid.py b/pineappl_py/tests/test_grid.py index 38d37f3d..6aeedebb 100644 --- a/pineappl_py/tests/test_grid.py +++ b/pineappl_py/tests/test_grid.py @@ -7,24 +7,24 @@ class TestOrder: def test_init(self): args = (2, 1, 0, 1) - o = pineappl.Order(*args) + o = pineappl.grid.Order(*args) - assert isinstance(o, pineappl.Order) + assert isinstance(o, pineappl.grid.Order) assert o.as_tuple() == args class TestGrid: def fake_grid(self, bins=None): - lumis = [pineappl.LumiEntry([(1, 21, 0.1)])] - orders = [pineappl.Order(3, 0, 0, 0)] + 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.SubgridParams() - g = pineappl.Grid(lumis, orders, bin_limits, subgrid_params) + subgrid_params = pineappl.subgrid.SubgridParams() + g = pineappl.grid.Grid(lumis, orders, bin_limits, subgrid_params) return g def test_init(self): g = self.fake_grid() - assert isinstance(g, pineappl.Grid) + assert isinstance(g, pineappl.grid.Grid) # orders assert len(g.orders()) == 1 assert g.orders()[0].as_tuple() == (3, 0, 0, 0) @@ -35,7 +35,7 @@ def test_set_subgrid(self): # DIS grid xs = np.linspace(0.1, 1.0, 5) vs = np.random.rand(len(xs)) - subgrid = pineappl.ImportOnlySubgridV1( + subgrid = pineappl.import_only_subgrid.ImportOnlySubgridV1( vs[np.newaxis, :, np.newaxis], np.array([90.0]), np.array(xs), @@ -47,7 +47,7 @@ def test_set_subgrid(self): x1s = np.linspace(0.1, 1, 2) x2s = np.linspace(0.5, 1, 2) Q2s = np.linspace(10, 20, 2) - subgrid = pineappl.ImportOnlySubgridV1( + subgrid = pineappl.import_only_subgrid.ImportOnlySubgridV1( np.random.rand(len(Q2s), len(x1s), len(x2s)), Q2s, x1s, x2s ) g.set_subgrid(0, 1, 0, subgrid.into()) @@ -64,14 +64,14 @@ def test_bins(self): # 1D normalizations = np.array([1.0, 1.0]) limits = [(1, 1), (2, 2)] - remapper = pineappl.BinRemapper(normalizations, limits) + remapper = pineappl.bin.BinRemapper(normalizations, limits) g.set_remapper(remapper) assert g.bin_dimensions() == 1 np.testing.assert_allclose(g.bin_left(0), [1, 2]) np.testing.assert_allclose(g.bin_right(0), [1, 2]) # 2D limits = [(1, 2), (2, 3), (2, 4), (3, 5)] - remapper = pineappl.BinRemapper(normalizations, limits) + remapper = pineappl.bin.BinRemapper(normalizations, limits) g.set_remapper(remapper) assert g.bin_dimensions() == 2 np.testing.assert_allclose(g.bin_left(0), [1, 2]) @@ -85,7 +85,7 @@ def test_convolve_with_one(self): # DIS grid xs = np.linspace(0.5, 1.0, 5) vs = xs.copy() - subgrid = pineappl.ImportOnlySubgridV1( + subgrid = pineappl.import_only_subgrid.ImportOnlySubgridV1( vs[np.newaxis, :, np.newaxis], np.array([90.0]), xs, @@ -110,9 +110,9 @@ def test_io(self, tmp_path): p = tmp_path / "test.pineappl" p.write_text("") g.write(str(p)) - gg = pineappl.Grid.read(p) - assert isinstance(gg, pineappl.Grid) - _ = pineappl.Grid.read(str(p)) + gg = pineappl.grid.Grid.read(p) + assert isinstance(gg, pineappl.grid.Grid) + _ = pineappl.grid.Grid.read(str(p)) def test_fill(self): g = self.fake_grid() diff --git a/pineappl_py/tests/test_lumi.py b/pineappl_py/tests/test_lumi.py index 763f8d0a..d5c8ad35 100644 --- a/pineappl_py/tests/test_lumi.py +++ b/pineappl_py/tests/test_lumi.py @@ -3,6 +3,5 @@ class TestLumiEntry: def test_init(self): - le = pineappl.LumiEntry([(2, 2, 0.5)]) - - assert isinstance(le, pineappl.LumiEntry) + le = pineappl.lumi.LumiEntry([(2, 2, 0.5)]) + assert isinstance(le, pineappl.lumi.LumiEntry) diff --git a/pineappl_py/tests/test_sugrid.py b/pineappl_py/tests/test_sugrid.py index 11469321..66c78b83 100644 --- a/pineappl_py/tests/test_sugrid.py +++ b/pineappl_py/tests/test_sugrid.py @@ -6,18 +6,18 @@ class TestSubgridParams: def test_init(self): - sp = pineappl.SubgridParams() - assert isinstance(sp, pineappl.SubgridParams) + sp = pineappl.subgrid.SubgridParams() + assert isinstance(sp, pineappl.subgrid.SubgridParams) def test_issue_164(pdf): - luminosities = [pineappl.LumiEntry([(1, 2, 1.0)])] - orders = [pineappl.Order(0, 0, 0, 0)] - params = pineappl.SubgridParams() + luminosities = [pineappl.lumi.LumiEntry([(1, 2, 1.0)])] + orders = [pineappl.grid.Order(0, 0, 0, 0)] + params = pineappl.subgrid.SubgridParams() def convolve_grid(): bin_limits = np.array([0.0, 1.0]) - grid = pineappl.Grid(luminosities, orders, bin_limits, params) + grid = pineappl.grid.Grid(luminosities, orders, bin_limits, params) grid.fill(0.2, 0.2, 10, 0, 0.5, 0, 0.5) return grid.convolve_with_one(2212, pdf.xfxQ, pdf.alphasQ) @@ -33,11 +33,11 @@ def convolve_grid(): class TestSubgrid: def fake_grid(self): - luminosities = [pineappl.LumiEntry([(1, 2, 1.0)])] - orders = [pineappl.Order(0, 0, 0, 0)] - params = pineappl.SubgridParams() + luminosities = [pineappl.lumi.LumiEntry([(1, 2, 1.0)])] + orders = [pineappl.grid.Order(0, 0, 0, 0)] + params = pineappl.subgrid.SubgridParams() bin_limits = np.array([0.0, 1.0]) - grid = pineappl.Grid(luminosities, orders, bin_limits, params) + grid = pineappl.grid.Grid(luminosities, orders, bin_limits, params) return grid def fake_importonlysubgrid(self): @@ -46,7 +46,7 @@ def fake_importonlysubgrid(self): Q2s = np.linspace(10, 20, 2) mu2s = [tuple([q2, q2]) for q2 in Q2s] array = np.random.rand(len(Q2s), len(x1s), len(x2s)) - subgrid = pineappl.ImportOnlySubgridV2(array, mu2s, x1s, x2s) + subgrid = pineappl.import_only_subgrid.ImportOnlySubgridV2(array, mu2s, x1s, x2s) return subgrid, [x1s, x2s, mu2s, array] def test_subgrid_methods(self): @@ -67,7 +67,7 @@ def test_to_array3(self): test_subgrid, infos = self.fake_importonlysubgrid() _, _, _, array = (obj for obj in infos) grid.set_subgrid(0, 0, 0, test_subgrid.into()) - extr_subgrid = grid.subgrid(0, 0, 0) + extr_subgrid = grid.subgrid(0,0,0) test_array = extr_subgrid.to_array3() print(test_array) print(array) From 3745f668ba4374b7044a1489b971d12a0b8bc7f8 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Thu, 8 Aug 2024 10:52:22 +0200 Subject: [PATCH 06/51] add spaces in signatures --- pineappl_py/src/grid.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 2825119c..145d83ba 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -383,7 +383,7 @@ impl PyGrid { /// numpy.ndarray(float) : /// cross sections for all bins, for each scale-variation tuple (first all bins, then /// the scale variation) - #[pyo3(signature = (pdg_id, xfx, alphas, order_mask = None, bin_indices = None, lumi_mask= None, xi = None))] + #[pyo3(signature = (pdg_id, xfx, alphas, order_mask = None, bin_indices = None, lumi_mask = None, xi = None))] pub fn convolve_with_one<'py>( &self, pdg_id: i32, @@ -448,7 +448,7 @@ impl PyGrid { /// numpy.ndarray(float) : /// cross sections for all bins, for each scale-variation tuple (first all bins, then /// the scale variation) - #[pyo3(signature = (pdg_id1, xfx1, pdg_id2, xfx2, alphas, order_mask = None, bin_indices = None, lumi_mask= None, xi = None))] + #[pyo3(signature = (pdg_id1, xfx1, pdg_id2, xfx2, alphas, order_mask = None, bin_indices = None, lumi_mask = None, xi = None))] pub fn convolve_with_two<'py>( &self, pdg_id1: i32, From aeddb822ea0fe125943d30f4bf3c9ee842ac860c Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Fri, 9 Aug 2024 09:54:16 +0200 Subject: [PATCH 07/51] various fixes in various places --- pineappl_py/src/channel.rs | 4 ++-- pineappl_py/src/grid.rs | 4 ++-- pineappl_py/tests/test_channel.py | 2 -- pineappl_py/tests/test_lumi.py | 4 ++-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/pineappl_py/src/channel.rs b/pineappl_py/src/channel.rs index 4e46ab38..5b2c4a42 100644 --- a/pineappl_py/src/channel.rs +++ b/pineappl_py/src/channel.rs @@ -9,7 +9,7 @@ use pyo3::prelude::*; /// 1. the PDG id of the first incoming parton /// 2. the PDG id of the second parton /// 3. a numerical factor that will multiply the result for this specific combination. -#[pyclass(name = "LumiEntry")] +#[pyclass(name = "Channel")] #[repr(transparent)] pub struct PyChannel { pub(crate) entry: Channel, @@ -47,6 +47,6 @@ impl PyChannel { #[pymodule] pub fn channel(_py: Python, m: &PyModule) -> PyResult<()> { - m.add_class::()?; + m.add_class::()?; Ok(()) } diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index ea9fdb8e..7783030e 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -425,7 +425,7 @@ impl PyGrid { /// numpy.ndarray(float) : /// cross sections for all bins, for each scale-variation tuple (first all bins, then /// the scale variation) - #[pyo3(signature = (pdg_id, xfx, alphas, order_mask = None, bin_indices = None, lumi_mask = None, xi = None))] + #[pyo3(signature = (pdg_id, xfx, alphas, order_mask = None, bin_indices = None, channel_mask = None, xi = None))] pub fn convolve_with_one<'py>( &self, pdg_id: i32, @@ -488,7 +488,7 @@ impl PyGrid { /// numpy.ndarray(float) : /// cross sections for all bins, for each scale-variation tuple (first all bins, then /// the scale variation) - #[pyo3(signature = (pdg_id1, xfx1, pdg_id2, xfx2, alphas, order_mask = None, bin_indices = None, lumi_mask = None, xi = None))] + #[pyo3(signature = (pdg_id1, xfx1, pdg_id2, xfx2, alphas, order_mask = None, bin_indices = None, channel_mask = None, xi = None))] pub fn convolve_with_two<'py>( &self, pdg_id1: i32, diff --git a/pineappl_py/tests/test_channel.py b/pineappl_py/tests/test_channel.py index 16dce2e3..fd07df6b 100644 --- a/pineappl_py/tests/test_channel.py +++ b/pineappl_py/tests/test_channel.py @@ -4,6 +4,4 @@ class TestChannel: def test_init(self): le = pineappl.channel.Channel([(2, 2, 0.5)]) - assert isinstance(le, pineappl.channel.Channel) - assert isinstance(le.raw, pineappl.pineappl.PyChannel) diff --git a/pineappl_py/tests/test_lumi.py b/pineappl_py/tests/test_lumi.py index d5c8ad35..7958fc36 100644 --- a/pineappl_py/tests/test_lumi.py +++ b/pineappl_py/tests/test_lumi.py @@ -3,5 +3,5 @@ class TestLumiEntry: def test_init(self): - le = pineappl.lumi.LumiEntry([(2, 2, 0.5)]) - assert isinstance(le, pineappl.lumi.LumiEntry) + le = pineappl.channel.Channel([(2, 2, 0.5)]) + assert isinstance(le, pineappl.channel.Channel) From 93d3c634d8df92d6e310bc79d7d75e9e711d7054 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Fri, 9 Aug 2024 13:40:33 +0200 Subject: [PATCH 08/51] remove lumi test and deprecated TODOs --- pineappl_py/src/grid.rs | 2 -- pineappl_py/tests/test_lumi.py | 7 ------- 2 files changed, 9 deletions(-) delete mode 100644 pineappl_py/tests/test_lumi.py diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 7783030e..5ca059ab 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -33,7 +33,6 @@ pub struct PyOrder { } // TODO: should probably be in a different module -// TODO: rename to `PidBasis` #[pyclass(name = "PidBasis")] #[derive(Clone)] pub enum PyPidBasis { @@ -51,7 +50,6 @@ impl From for PidBasis { } // TODO: should probably be in a different module -// TODO: rename to `OperatorSliceInfo` #[pyclass(name = "OperatorSliceInfo")] #[derive(Clone)] pub struct PyOperatorSliceInfo { diff --git a/pineappl_py/tests/test_lumi.py b/pineappl_py/tests/test_lumi.py deleted file mode 100644 index 7958fc36..00000000 --- a/pineappl_py/tests/test_lumi.py +++ /dev/null @@ -1,7 +0,0 @@ -import pineappl - - -class TestLumiEntry: - def test_init(self): - le = pineappl.channel.Channel([(2, 2, 0.5)]) - assert isinstance(le, pineappl.channel.Channel) From fc6d4667b36df601e850691b59b0569daa4d90b4 Mon Sep 17 00:00:00 2001 From: Radonirinaunimi Date: Fri, 9 Aug 2024 16:02:02 +0200 Subject: [PATCH 09/51] move OperatorSliceInfo and PidBasis into evolution module --- pineappl_py/src/evolution.rs | 79 +++++++++++++++++++++++++++--- pineappl_py/src/grid.rs | 76 +--------------------------- pineappl_py/tests/test_fk_table.py | 4 +- 3 files changed, 75 insertions(+), 84 deletions(-) diff --git a/pineappl_py/src/evolution.rs b/pineappl_py/src/evolution.rs index 70f38311..fd7f3b90 100644 --- a/pineappl_py/src/evolution.rs +++ b/pineappl_py/src/evolution.rs @@ -1,8 +1,77 @@ use numpy::{IntoPyArray, PyArray1}; use pineappl::evolution::{EvolveInfo, OperatorSliceInfo}; +use pineappl::pids::PidBasis; use pyo3::prelude::*; +/// PyO3 wrapper to :rustdoc:`pineappl::pids::PidBasis `. +#[pyclass(name = "PidBasis")] +#[derive(Clone)] +pub enum PyPidBasis { + Pdg, + Evol, +} + +impl From for PidBasis { + fn from(basis: PyPidBasis) -> Self { + match basis { + PyPidBasis::Pdg => Self::Pdg, + PyPidBasis::Evol => Self::Evol, + } + } +} + +/// PyO3 wrapper to :rustdoc:`pineappl::evolution::OperatorSliceInfo `. +#[pyclass(name = "OperatorSliceInfo")] +#[derive(Clone)] +pub struct PyOperatorSliceInfo { + pub(crate) info: OperatorSliceInfo, +} + +#[pymethods] +impl PyOperatorSliceInfo { + /// Constructor. + /// + /// Parameteters + /// ------------ + /// fac0 : float + /// initial factorization scale + /// pids0 : list(int) + /// flavors available at the initial scale + /// x0 : list(float) + /// x-grid at the initial scale + /// fac1 : float + /// evolved final scale + /// pids1 : list(int) + /// flavors available at the final scale + /// x1 : list(float) + /// x-grid at the final scale + /// pid_basis : PyPidBasis + /// flavor basis reprentation at the initial scale + #[new] + pub fn new( + fac0: f64, + pids0: Vec, + x0: Vec, + fac1: f64, + pids1: Vec, + x1: Vec, + pid_basis: PyPidBasis, + ) -> Self { + Self { + info: OperatorSliceInfo { + fac0, + pids0, + x0, + fac1, + pids1, + x1, + pid_basis: pid_basis.into(), + }, + } + } +} + /// PyO3 wrapper to :rustdoc:`pineappl::evolution::EvolveInfo `. #[pyclass] #[repr(transparent)] @@ -37,16 +106,10 @@ impl PyEvolveInfo { } } -/// PyO3 wrapper to :rustdoc:`pineappl::evolution::OperatorSliceInfo `. -#[pyclass] -#[repr(transparent)] -#[derive(Clone)] -pub struct PyOperatorSliceInfo { - pub(crate) slice_info: OperatorSliceInfo, -} - #[pymodule] pub fn evolution(_py: Python, m: &PyModule) -> PyResult<()> { m.add_class::()?; + m.add_class::()?; + m.add_class::()?; Ok(()) } diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 5ca059ab..e21dbbf3 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -1,13 +1,12 @@ use ndarray::CowArray; use pineappl::boc::Order; use pineappl::convolutions::LumiCache; -use pineappl::evolution::{AlphasTable, OperatorInfo, OperatorSliceInfo}; +use pineappl::evolution::{AlphasTable, OperatorInfo}; use pineappl::grid::{Grid, Ntuple}; -use pineappl::pids::PidBasis; use super::bin::PyBinRemapper; use super::channel::PyChannel; -use super::evolution::PyEvolveInfo; +use super::evolution::{PyEvolveInfo, PyOperatorSliceInfo, PyPidBasis}; use super::fk_table::PyFkTable; use super::subgrid::{PySubgridEnum, PySubgridParams}; @@ -32,74 +31,6 @@ pub struct PyOrder { pub(crate) order: Order, } -// TODO: should probably be in a different module -#[pyclass(name = "PidBasis")] -#[derive(Clone)] -pub enum PyPidBasis { - Pdg, - Evol, -} - -impl From for PidBasis { - fn from(basis: PyPidBasis) -> Self { - match basis { - PyPidBasis::Pdg => Self::Pdg, - PyPidBasis::Evol => Self::Evol, - } - } -} - -// TODO: should probably be in a different module -#[pyclass(name = "OperatorSliceInfo")] -#[derive(Clone)] -pub struct PyOperatorSliceInfo { - info: OperatorSliceInfo, -} - -#[pymethods] -impl PyOperatorSliceInfo { - /// Constructor. - /// - /// Parameteters - /// ------------ - /// fac0 : float - /// initial factorization scale - /// pids0 : list(int) - /// flavors available at the initial scale - /// x0 : list(float) - /// x-grid at the initial scale - /// fac1 : float - /// evolved final scale - /// pids1 : list(int) - /// flavors available at the final scale - /// x1 : list(float) - /// x-grid at the final scale - /// pid_basis : PyPidBasis - /// flavor basis reprentation at the initial scale - #[new] - pub fn new( - fac0: f64, - pids0: Vec, - x0: Vec, - fac1: f64, - pids1: Vec, - x1: Vec, - pid_basis: PyPidBasis, - ) -> Self { - Self { - info: OperatorSliceInfo { - fac0, - pids0, - x0, - fac1, - pids1, - x1, - pid_basis: pid_basis.into(), - }, - } - } -} - impl PyOrder { pub(crate) fn new(order: Order) -> Self { Self { order } @@ -918,9 +849,6 @@ impl PyGrid { #[pymodule] pub fn grid(_py: Python, m: &PyModule) -> PyResult<()> { m.add_class::()?; - m.add_class::()?; m.add_class::()?; - m.add_class::()?; - Ok(()) } diff --git a/pineappl_py/tests/test_fk_table.py b/pineappl_py/tests/test_fk_table.py index 3d16c1f2..97237c74 100644 --- a/pineappl_py/tests/test_fk_table.py +++ b/pineappl_py/tests/test_fk_table.py @@ -35,8 +35,8 @@ def test_convolve_with_one(self): [5e7 / 9999, 0.0], ) - info = pineappl.grid.OperatorSliceInfo( - 1.0, [], [], 1.0, [], [], pineappl.grid.PidBasis.Pdg + info = pineappl.evolution.OperatorSliceInfo( + 1.0, [], [], 1.0, [], [], pineappl.evolution.PidBasis.Pdg ) # TODO: write a better test From 37c877ea63c4567dd451439faf4aebd394abb475 Mon Sep 17 00:00:00 2001 From: Tanjona Rabemananjara Date: Tue, 13 Aug 2024 08:25:58 +0200 Subject: [PATCH 10/51] Update CHANGELOG.md --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d4dbef1..05fefa2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - added new method `Grid::delete_orders` and the corresponding switch `--delete-orders` in the subcommand `write` of the CLI +### Changed + +- renamed `pineappl.lumi.rs` to `pineappl.channel.rs` +- removed `.create()` and `.from_grid()` methods and directly instantiate objecs from the class +- `.into()` needs to be explicitly called on subgrids when using `set_subgrid()` +- replaced `pineappl.grid.PidBasis` with `pineappl.evolution.PidBasis` +- replaced `pineappl.grid.OperatorSliceInfo` with `pineappl.evolution.OperatorSliceInfo` + ## [0.8.2] - 22/07/2024 ### Changed From 2bd81c0e4b8298ed6671a6972f5236c8caebfe71 Mon Sep 17 00:00:00 2001 From: Tanjona Rabemananjara Date: Tue, 13 Aug 2024 10:18:09 +0200 Subject: [PATCH 11/51] fixed update to CHANGELOG.md according to review --- CHANGELOG.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05fefa2f..55c1ab6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,11 +14,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- renamed `pineappl.lumi.rs` to `pineappl.channel.rs` -- removed `.create()` and `.from_grid()` methods and directly instantiate objecs from the class -- `.into()` needs to be explicitly called on subgrids when using `set_subgrid()` -- replaced `pineappl.grid.PidBasis` with `pineappl.evolution.PidBasis` -- replaced `pineappl.grid.OperatorSliceInfo` with `pineappl.evolution.OperatorSliceInfo` +- dropped top-level Python interface layer +- renamed `lumi` to `channel` in PyO3 Python interface. This concerns 1) the argument names of `convolute_with_one` and similar functions; 2) the module `Python API:pineappl.lumi` was moved to `Python API:pineappl.channel`; 3) the class `LumiEntry` was renamed to `Channel` +- `.into()` needs to be explicitly called on subgrids when calling `Python API:pineappl.grid.set_subgrid()` +- replaced `Python API:pineappl.grid.PyPidBasis` with `Python API:pineappl.evolution.PidBasis` +- replaced `Python API:pineappl.grid.PyOperatorSliceInfo` with `Python API:pineappl.evolution.OperatorSliceInfo` + +### Removed + +- removed `Python API:pineappl.grid.Grid.create()` and `Python API:pineappl.fk_table.FkTable.from_grid()` methods; use the constructors of the respective class instead ## [0.8.2] - 22/07/2024 From 230b188c48df1d817e7dbf949f74d271356de50f Mon Sep 17 00:00:00 2001 From: Tanjona Rabemananjara Date: Tue, 13 Aug 2024 11:15:29 +0200 Subject: [PATCH 12/51] fixed 'Python API' --- CHANGELOG.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55c1ab6c..4d189eb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,15 +14,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- dropped top-level Python interface layer -- renamed `lumi` to `channel` in PyO3 Python interface. This concerns 1) the argument names of `convolute_with_one` and similar functions; 2) the module `Python API:pineappl.lumi` was moved to `Python API:pineappl.channel`; 3) the class `LumiEntry` was renamed to `Channel` -- `.into()` needs to be explicitly called on subgrids when calling `Python API:pineappl.grid.set_subgrid()` -- replaced `Python API:pineappl.grid.PyPidBasis` with `Python API:pineappl.evolution.PidBasis` -- replaced `Python API:pineappl.grid.PyOperatorSliceInfo` with `Python API:pineappl.evolution.OperatorSliceInfo` +- Python API: dropped top-level Python interface layer +- Python API: renamed `lumi` to `channel` in PyO3 Python interface. + This concerns 1) the argument names of `convolute_with_one` and + similar functions; 2) the module `pineappl.lumi` was moved to + `pineappl.channel`; 3) the class `LumiEntry` was renamed to `Channel` +- Python API: `.into()` needs to be explicitly called on subgrids when + calling `pineappl.grid.set_subgrid()` +- Python API: replaced `pineappl.grid.PyPidBasis` with + `pineappl.evolution.PidBasis` +- Python API: replaced `pineappl.grid.PyOperatorSliceInfo` with + `pineappl.evolution.OperatorSliceInfo` ### Removed -- removed `Python API:pineappl.grid.Grid.create()` and `Python API:pineappl.fk_table.FkTable.from_grid()` methods; use the constructors of the respective class instead +- Python API: removed `pineappl.grid.Grid.create()` and + `pineappl.fk_table.FkTable.from_grid()` methods; use the constructors + of the respective class instead ## [0.8.2] - 22/07/2024 From 07cfb02308756b8b8806963ff1e09a7d3a317b25 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 10:56:51 +0200 Subject: [PATCH 13/51] Start fixing the documentation --- pineappl_py/docs/.gitignore | 1 - pineappl_py/docs/source/conf.py | 179 +++---------------- pineappl_py/docs/source/index.rst | 2 +- pineappl_py/docs/source/modules/pineappl.rst | 7 + 4 files changed, 35 insertions(+), 154 deletions(-) create mode 100644 pineappl_py/docs/source/modules/pineappl.rst diff --git a/pineappl_py/docs/.gitignore b/pineappl_py/docs/.gitignore index 3025cff2..1e6524a5 100644 --- a/pineappl_py/docs/.gitignore +++ b/pineappl_py/docs/.gitignore @@ -1,7 +1,6 @@ # autogenerated file source/development/code_todos.rst # Ignore auto generated module references -source/modules source/development/ekomark # ignore temporary build files _build/ diff --git a/pineappl_py/docs/source/conf.py b/pineappl_py/docs/source/conf.py index 0026f926..671aa7af 100644 --- a/pineappl_py/docs/source/conf.py +++ b/pineappl_py/docs/source/conf.py @@ -1,84 +1,35 @@ # Configuration file for the Sphinx documentation builder. # -# This file only contains a selection of the most common options. For a full -# list see the documentation: +# For the full list of built-in configuration values, see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - -import pathlib -import os -import sys - -here = pathlib.Path(__file__).absolute().parent - # -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -project = "pineappl" -copyright = "2020-2021, the PineAPPL team" -author = "the PineAPPL team" +import pineappl +project = 'pineappl' +copyright = '2020–2024, the PineAPPL team' +author = 'the PineAPPL team' +release = pineappl.version +version = release -# -- General configuration --------------------------------------------------- -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.doctest", - "sphinx.ext.intersphinx", - "sphinx.ext.todo", - "sphinx.ext.coverage", - "sphinx.ext.mathjax", - "sphinx.ext.ifconfig", - "sphinx.ext.viewcode", - "sphinx.ext.autosectionlabel", - "sphinx.ext.napoleon", - "sphinxcontrib.bibtex", - "sphinx.ext.graphviz", - "sphinx.ext.extlinks", + 'sphinx.ext.autodoc', + 'sphinx.ext.autosectionlabel', + 'sphinx.ext.autosummary', + 'sphinx.ext.extlinks', + 'sphinx.ext.inheritance_diagram', + 'sphinx.ext.intersphinx', + 'sphinx.ext.napoleon', + 'sphinx.ext.todo', + 'sphinx_rtd_theme', + 'sphinxcontrib.bibtex', ] -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -source_suffix = { - ".rst": "restructuredtext", - ".txt": "restructuredtext", -} - -autosectionlabel_prefix_document = True -# autosectionlabel_maxdepth = 10 -# Allow to embed rst syntax in markdown files. -enable_eval_rst = True - -# The master toctree document. -master_doc = "index" -bibtex_bibfiles = ["refs.bib"] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ["shared/*"] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = None - -# A string to be included at the beginning of all files -shared = here / "shared" -rst_prolog = "\n".join([open(x).read() for x in os.scandir(shared)]) +autosummary_generate = True +autosummary_imported_members = True extlinks = { "yadism": ("https://nnpdf.github.io/yadism/%s", "yadism - %s"), @@ -86,89 +37,13 @@ "pineko": ("https://github.com/NNPDF/pineko/%s", "pineko - %s"), } -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = "sphinx_rtd_theme" - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] - -# -- Extension configuration ------------------------------------------------- - -# -- Options for intersphinx extension --------------------------------------- - -# Example configuration for intersphinx: refer to the Python standard library. -# Thanks https://github.com/bskinn/sphobjinv -intersphinx_mapping = { - "python": ("https://docs.python.org/3/", None), - "scipy": ("https://docs.scipy.org/doc/scipy/", None), - "numpy": ("https://numpy.org/doc/stable", None), -} -# -- Options for todo extension ---------------------------------------------- - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True - -mathjax3_config = { - "tex": { - "macros": { - # fncs - # "atan": [r"\text{atan}", 0], - # "span": [r"\text{span}", 0], - } - } -} - -# https://stackoverflow.com/questions/1871549/determine-if-python-is-running-inside-virtualenv -def get_base_prefix_compat(): - """Get base/real prefix, or sys.prefix if there is none.""" - return ( - getattr(sys, "base_prefix", None) - or getattr(sys, "real_prefix", None) - or sys.prefix - ) - - -def in_virtualenv(): - return get_base_prefix_compat() != sys.prefix - - -# https://github.com/readthedocs/readthedocs.org/issues/1139#issuecomment-312626491 -def run_apidoc(_): - import subprocess # pylint: disable=import-outside-toplevel - - from sphinx.ext.apidoc import main # pylint: disable=import-outside-toplevel - - sys.path.append(str(here.parent)) - # run maturin to have the latest stuff - pkg_root = here.parents[1] - # if in_virtualenv(): # in local repos we're always in a virtualenv - # subprocess.run(["maturin", "develop"], cwd=pkg_root) - # else: # on RTD we can't (for some reason we're not inside the virtualenv - or maybe only the subshell isn't) - # subprocess.run(["maturin", "build"], cwd=pkg_root) - # # On RTD we were already installing before, but of course this was fake - # # as it only had the raw Python stuff, so let's do it again - # subprocess.run(["pip", "uninstall", "pineappl", "-y"], cwd=pkg_root) - # wheels = list((pkg_root / "target" / "wheels").glob("pineappl*.whl")) - # # In case there are several wheels (as on RTD) find the one matching (and let the others happily fail) - # for wheel in wheels: - # subprocess.run(["pip", "install", str(wheel.absolute())], cwd=pkg_root) - - # analyse 'pineappl' - docs_dest = here / "modules" / "pineappl" - import pineappl +bibtex_bibfiles = ["refs.bib"] - # note that we can NOT point to the local directory (`here.parents[1] / "pineappl"`) - # but we need the package built by `maturin` and installed by `pip` - package = pathlib.Path(pineappl.__file__).parent - main(["--module-first", "-o", str(docs_dest), str(package)]) - (docs_dest / "modules.rst").unlink() +templates_path = ['_templates'] +exclude_patterns = [] +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output -def setup(app): - app.connect("builder-inited", run_apidoc) +html_theme = 'sphinx_rtd_theme' +html_static_path = ['_static'] diff --git a/pineappl_py/docs/source/index.rst b/pineappl_py/docs/source/index.rst index 632e0add..28160af7 100644 --- a/pineappl_py/docs/source/index.rst +++ b/pineappl_py/docs/source/index.rst @@ -18,7 +18,7 @@ The Python wrapper is also used in :yadism:`\ ` and :pineko:`\ `. We also list s installation recipes implementation - API + API indices .. important:: diff --git a/pineappl_py/docs/source/modules/pineappl.rst b/pineappl_py/docs/source/modules/pineappl.rst new file mode 100644 index 00000000..b66bc209 --- /dev/null +++ b/pineappl_py/docs/source/modules/pineappl.rst @@ -0,0 +1,7 @@ +pineappl package +================ + +.. automodule:: pineappl + :members: + :undoc-members: + :show-inheritance: From c05e008670103fd8fd53deccec932ef8edc56c7f Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 10:57:26 +0200 Subject: [PATCH 14/51] Remove obsolete container files --- pineappl_py/package/Containerfile | 27 ---------- pineappl_py/package/README.md | 89 ------------------------------- pineappl_py/package/maturin | 8 --- 3 files changed, 124 deletions(-) delete mode 100644 pineappl_py/package/Containerfile delete mode 100644 pineappl_py/package/README.md delete mode 100755 pineappl_py/package/maturin diff --git a/pineappl_py/package/Containerfile b/pineappl_py/package/Containerfile deleted file mode 100644 index 49e5821a..00000000 --- a/pineappl_py/package/Containerfile +++ /dev/null @@ -1,27 +0,0 @@ -FROM quay.io/pypa/manylinux2014_x86_64 - -ARG MATURIN_TAR='maturin-x86_64-unknown-linux-musl.tar.gz' -ARG MATURIN_TAG='v0.13.0-beta.9' - -# install c compiler -# and create a dedicated user -RUN /bin/bash -c "yum install gcc -y; \ - useradd -m pineappl;\ - su - pineappl" - -USER pineappl - -# install dependencies -# - rust -# - maturin -RUN /bin/bash -c "cd ${HOME}; \ - mkdir -p local/bin; \ - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y; \ - curl --remote-name -L https://github.com/PyO3/maturin/releases/download/${MATURIN_TAG}/${MATURIN_TAR}; \ - tar -xvzf ${MATURIN_TAR} --directory=local/bin/" - -COPY maturin /home/pineappl - -ENTRYPOINT ["/home/pineappl/maturin"] -# To minimize the size of the wheel use '--strip' -CMD ["build --release --interpreter 3.7 3.8 3.9 3.10 pypy3.7"] diff --git a/pineappl_py/package/README.md b/pineappl_py/package/README.md deleted file mode 100644 index 69defc67..00000000 --- a/pineappl_py/package/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# Packaging python interface - -In order to compile wheels to distribute some requirements have to be met: - -- `linux`: the compilation process has to be run in a - [`manylinux`](https://github.com/pypa/manylinux) compliant environment, for - this reason a suitable container image is provided (see - [published packages](https://github.com/orgs/NNPDF/packages?repo_name=pineappl) - and the respective [`Containerfile`](./Containerfile)) - - Notice that the default container provided by - [pypa](https://github.com/pypa/manylinux) is not sufficient, since it does not - ship a C compiler (required to compile the `syn` crate). -- `macOS`: it just needs to be run in a macOS environment, see - [publishing workflow](https://github.com/NNPDF/pineappl/tree/master/.github/workflows/wheels.yml) -- `windows`: it just needs to be run in a windows environment, see - [publishing workflow](https://github.com/NNPDF/pineappl/tree/master/.github/workflows/wheels.yml) - -## `maturin` container image - -`maturin` image has its own version (following [semver](https://semver.org/)), -and: - -- it is based on `manylinux2014_x86_64` -- build wheels for a range of CPython versions (the actual one depends on the - `maturin` version inside the container) - -### Using `maturin` to compile for `manylinux` - -This is the easy part: you just need to download the -[image](https://github.com/NNPDF/pineappl/pkgs/container/maturin) and run with -your favorite container tool. - -Here the explicit commands with `podman` [[1]](#docker) - -```sh -podman pull ghcr.io/n3pdf/maturin:latest -podman run ghcr.io/n3pdf/maturin -podman cp :root/pineappl/pineappl_py/target/wheels/ . -``` - -Now wheels are available outside the container and can be uploaded in your -favorite way. - -#### Interactive use - -If you want to use the container environment interactively, you need to provide -an alternative entry point: - -```sh -podman run --entrypoint bash -it -``` - -### Create a new `maturin` image - -_Use case_: if a new rust or maturin version is released, it might be needed to -upgrade also those inside the `maturin` image (since they are pre-installed in -the image itself) - -To upgrade the build instructions ([_Containerfile_](./Containerfile)): - -- change `FROM` to choose a different manylinux base image (see the - [official source](https://github.com/pypa/manylinux)) -- change `ARG` for `MATURIN_TAG` to choose a different `maturin` version -- to change architecture both `FROM` and `ARG MATURIN_TAR=` have to be updated - from `x86_64` -- `rust` version is always taken to be the latest one at each build (so - rerunning the build **without changing** anything might generate a **different - image**) - -Once `Containerfile` has been updated then rerun: - -```sh -# inside pineappl/pineappl_py/package -podman build -t ghcr.io/n3pdf/maturin . -podman tag ghcr.io/n3pdf/maturin: -# login to GitHub registry with user credentials (not organization), see [2] -echo ${PAT} | podman login ghcr.io -u --password-stdin -# finally publish -podman push ghcr.io/n3pdf/maturin: -# and publish the new latest (all layers already available, it's just an alias) -podman push ghcr.io/n3pdf/maturin:latest -``` - -[1]: In the following I will use `podman` as the container -runtime for the examples. To use `docker` instead, you can simply replace -`podman -> docker`, they have compatible subcommands -[2]: official -[GitHub registry docs](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry) diff --git a/pineappl_py/package/maturin b/pineappl_py/package/maturin deleted file mode 100755 index 2b33a924..00000000 --- a/pineappl_py/package/maturin +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -export PATH=${HOME}/local/bin:${HOME}/.cargo/bin:${PATH} -cd ${HOME} -# clone pineappl code -git clone https://github.com/NNPDF/pineappl.git -# compile pineappl python package -cd pineappl/pineappl_py -maturin $@ From 01a264f4a748b5b81f93df513b718cbc390a022b Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 10:58:20 +0200 Subject: [PATCH 15/51] Remove obsolete `.gitignore` --- pineappl_py/docs/.gitignore | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 pineappl_py/docs/.gitignore diff --git a/pineappl_py/docs/.gitignore b/pineappl_py/docs/.gitignore deleted file mode 100644 index 1e6524a5..00000000 --- a/pineappl_py/docs/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# autogenerated file -source/development/code_todos.rst -# Ignore auto generated module references -source/development/ekomark -# ignore temporary build files -_build/ -# Ignore generated sphinx-bibtex file -source/bibtex.json From ca2fb730cd04de8970df5ce5be36c6246f179ac6 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 11:09:40 +0200 Subject: [PATCH 16/51] Remove unused bibtex functionality --- pineappl_py/docs/source/conf.py | 3 --- pineappl_py/docs/source/refs.bib | 0 2 files changed, 3 deletions(-) delete mode 100644 pineappl_py/docs/source/refs.bib diff --git a/pineappl_py/docs/source/conf.py b/pineappl_py/docs/source/conf.py index 671aa7af..988ed46e 100644 --- a/pineappl_py/docs/source/conf.py +++ b/pineappl_py/docs/source/conf.py @@ -25,7 +25,6 @@ 'sphinx.ext.napoleon', 'sphinx.ext.todo', 'sphinx_rtd_theme', - 'sphinxcontrib.bibtex', ] autosummary_generate = True @@ -37,8 +36,6 @@ "pineko": ("https://github.com/NNPDF/pineko/%s", "pineko - %s"), } -bibtex_bibfiles = ["refs.bib"] - templates_path = ['_templates'] exclude_patterns = [] diff --git a/pineappl_py/docs/source/refs.bib b/pineappl_py/docs/source/refs.bib deleted file mode 100644 index e69de29b..00000000 From 66922b274c6d7d24e7b3caa4a234184350c708d4 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 11:12:25 +0200 Subject: [PATCH 17/51] Add build instructions --- pineappl_py/README.md | 20 ++++++++++++++++++++ pineappl_py/requirements.txt | 28 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 pineappl_py/requirements.txt diff --git a/pineappl_py/README.md b/pineappl_py/README.md index da57beb5..e75e7657 100644 --- a/pineappl_py/README.md +++ b/pineappl_py/README.md @@ -12,3 +12,23 @@ For installation instructions see the [documentation]. [PyO3]: https://pyo3.rs [Rust API]: https://docs.rs/pineappl [documentation]: https://pineappl.readthedocs.io/en/latest/installation.html + +## Development + +Run + +```shell +python -m venv env && . env/bin/activate +pip install -r requirements.txt +maturin develop +``` + +to build and setup a new environment. + +Run + +```shell +cd docs && make html +``` + +to generate the documentation. diff --git a/pineappl_py/requirements.txt b/pineappl_py/requirements.txt new file mode 100644 index 00000000..7bd3ed9b --- /dev/null +++ b/pineappl_py/requirements.txt @@ -0,0 +1,28 @@ +alabaster==0.7.16 +babel==2.16.0 +certifi==2024.7.4 +charset-normalizer==3.3.2 +docutils==0.20.1 +idna==3.7 +imagesize==1.4.1 +importlib-metadata==8.2.0 +jinja2==3.1.4 +MarkupSafe==2.1.5 +maturin==1.7.0 +numpy==1.26.4 +packaging==24.1 +pygments==2.18.0 +requests==2.32.3 +snowballstemmer==2.2.0 +sphinx==7.4.7 +sphinx-rtd-theme==2.0.0 +sphinxcontrib-applehelp==2.0.0 +sphinxcontrib-devhelp==2.0.0 +sphinxcontrib-htmlhelp==2.1.0 +sphinxcontrib-jquery==4.1 +sphinxcontrib-jsmath==1.0.1 +sphinxcontrib-qthelp==2.0.0 +sphinxcontrib-serializinghtml==2.0.0 +tomli==2.0.1 +urllib3==2.2.2 +zipp==3.20.0 From 0f04923c7e7f657bc5da3ac16d6576ae81556e68 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 14 Aug 2024 12:48:52 +0300 Subject: [PATCH 18/51] Add more doc fixes --- pineappl_py/docs/source/conf.py | 2 -- pineappl_py/docs/source/implementation.rst | 3 +-- pineappl_py/docs/source/index.rst | 14 ++------------ 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/pineappl_py/docs/source/conf.py b/pineappl_py/docs/source/conf.py index 988ed46e..5e785079 100644 --- a/pineappl_py/docs/source/conf.py +++ b/pineappl_py/docs/source/conf.py @@ -31,9 +31,7 @@ autosummary_imported_members = True extlinks = { - "yadism": ("https://nnpdf.github.io/yadism/%s", "yadism - %s"), "rustdoc": ("https://docs.rs/pineappl/latest/pineappl/%s", "PineAPPL - %s"), - "pineko": ("https://github.com/NNPDF/pineko/%s", "pineko - %s"), } templates_path = ['_templates'] diff --git a/pineappl_py/docs/source/implementation.rst b/pineappl_py/docs/source/implementation.rst index 32a5e90a..cf9dcece 100644 --- a/pineappl_py/docs/source/implementation.rst +++ b/pineappl_py/docs/source/implementation.rst @@ -1,9 +1,8 @@ Implementation ============== -The wrapper is built using PyO3 to interface Rust to Python. This requires (for the moment) unfortunately a bit of overhead code so there exist four layers of code: +The wrapper is built using PyO3 to interface Rust to Python. - The original Rust library that actually provides all the functionality. Any true code should be placed here as this is shared by all interfaces. - The PyO3 wrapper objects written in Rust that define which methods are exposed to Python and that takes care of the type conversion from Python-understandable types to Rust types. - The PyO3 wrapper objects in Python which are an exact mirror of their Rust equivalent. This translation is provided by PyO3 and note that it also preserves the associated documentation. -- The additional Python wrappers around the raw PyO3 objects which provide convenience wrappers to cast arbitrary Python objects to objects that can actually used by PyO3. diff --git a/pineappl_py/docs/source/index.rst b/pineappl_py/docs/source/index.rst index 28160af7..cf92cdcd 100644 --- a/pineappl_py/docs/source/index.rst +++ b/pineappl_py/docs/source/index.rst @@ -8,7 +8,8 @@ PineAPPL is a computer library that makes it possible to produce fast-interpolat The :doc:`installation` instructions are given :doc:`here `. A practical example can be found in the ``example/`` subfolder of the `repository `_. -The Python wrapper is also used in :yadism:`\ ` and :pineko:`\ `. We also list some common :doc:`recipes` here. +The Python wrapper is also used in `yadism `_ and `pineko `_. +We also list some common :doc:`recipes` here. .. toctree:: :maxdepth: 1 @@ -20,14 +21,3 @@ The Python wrapper is also used in :yadism:`\ ` and :pineko:`\ `. We also list s implementation API indices - -.. important:: - - If you are looking for the methods of a specific class, be aware that part of - them are just passed to the underlying Rust object, whose class is the same - of the user-facing one, but prefixed with a ``Py``, e.g.: - :class:`pineappl.grid.Grid` and :class:`pineappl.pineappl.grid.PyGrid`. - - You will find the documentation of the unwrapped method in the raw ``Py`` - class, while part of the methods are wrapped and thus even documented in the - user-facing class. From 7606fb976fae8fcbcb0af19046c13f506b425301 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 14 Aug 2024 13:18:22 +0300 Subject: [PATCH 19/51] Use preferred PyModule.add_subgrid. See https://docs.rs/pyo3/0.21.2/pyo3/types/struct.PyModule.html#method.add_submodule --- pineappl_py/src/bin.rs | 8 +++++--- pineappl_py/src/channel.rs | 8 +++++--- pineappl_py/src/evolution.rs | 8 +++++--- pineappl_py/src/fk_table.rs | 8 +++++--- pineappl_py/src/grid.rs | 8 +++++--- pineappl_py/src/import_only_subgrid.rs | 8 +++++--- pineappl_py/src/lib.rs | 17 ++++++++--------- pineappl_py/src/subgrid.rs | 8 +++++--- 8 files changed, 43 insertions(+), 30 deletions(-) diff --git a/pineappl_py/src/bin.rs b/pineappl_py/src/bin.rs index 41d3fe4c..da051801 100644 --- a/pineappl_py/src/bin.rs +++ b/pineappl_py/src/bin.rs @@ -1,3 +1,4 @@ +//! Binnning interface. use pineappl::bin::BinRemapper; use numpy::{PyArrayMethods, PyReadonlyArray1}; @@ -33,8 +34,9 @@ impl PyBinRemapper { } } -#[pymodule] -pub fn bin(_py: Python, m: &PyModule) -> PyResult<()> { +/// Register submodule in parent. +pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { + let m = PyModule::new_bound(parent_module.py(), "bin")?; m.add_class::()?; - Ok(()) + parent_module.add_submodule(&m) } diff --git a/pineappl_py/src/channel.rs b/pineappl_py/src/channel.rs index 5b2c4a42..115b07ad 100644 --- a/pineappl_py/src/channel.rs +++ b/pineappl_py/src/channel.rs @@ -1,3 +1,4 @@ +//! Channel interface. use pineappl::boc::Channel; use pyo3::prelude::*; @@ -45,8 +46,9 @@ impl PyChannel { } } -#[pymodule] -pub fn channel(_py: Python, m: &PyModule) -> PyResult<()> { +/// Register submodule in parent. +pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { + let m = PyModule::new_bound(parent_module.py(), "channel")?; m.add_class::()?; - Ok(()) + parent_module.add_submodule(&m) } diff --git a/pineappl_py/src/evolution.rs b/pineappl_py/src/evolution.rs index fd7f3b90..005702de 100644 --- a/pineappl_py/src/evolution.rs +++ b/pineappl_py/src/evolution.rs @@ -1,3 +1,4 @@ +//! Evolution interface. use numpy::{IntoPyArray, PyArray1}; use pineappl::evolution::{EvolveInfo, OperatorSliceInfo}; use pineappl::pids::PidBasis; @@ -106,10 +107,11 @@ impl PyEvolveInfo { } } -#[pymodule] -pub fn evolution(_py: Python, m: &PyModule) -> PyResult<()> { +/// Register submodule in parent. +pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { + let m = PyModule::new_bound(parent_module.py(), "evolution")?; m.add_class::()?; m.add_class::()?; m.add_class::()?; - Ok(()) + parent_module.add_submodule(&m) } diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index fd2e6eb8..0542109c 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -1,3 +1,4 @@ +//! FK table interface. use pineappl::convolutions::LumiCache; use pineappl::fk_table::{FkAssumptions, FkTable}; use pineappl::grid::Grid; @@ -296,9 +297,10 @@ impl PyFkTable { } } -#[pymodule] -pub fn fk_table(_py: Python, m: &PyModule) -> PyResult<()> { +/// Register submodule in parent. +pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { + let m = PyModule::new_bound(parent_module.py(), "fk_table")?; m.add_class::()?; m.add_class::()?; - Ok(()) + parent_module.add_submodule(&m) } diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index e21dbbf3..320ac24e 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -1,3 +1,4 @@ +//! Grid interface. use ndarray::CowArray; use pineappl::boc::Order; use pineappl::convolutions::LumiCache; @@ -846,9 +847,10 @@ impl PyGrid { } } -#[pymodule] -pub fn grid(_py: Python, m: &PyModule) -> PyResult<()> { +/// Register submodule in parent. +pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { + let m = PyModule::new_bound(parent_module.py(), "grid")?; m.add_class::()?; m.add_class::()?; - Ok(()) + parent_module.add_submodule(&m) } diff --git a/pineappl_py/src/import_only_subgrid.rs b/pineappl_py/src/import_only_subgrid.rs index ba1c6940..2eadbdbe 100644 --- a/pineappl_py/src/import_only_subgrid.rs +++ b/pineappl_py/src/import_only_subgrid.rs @@ -1,3 +1,4 @@ +//! PyImportOnlySubgrid* interface. use super::subgrid::PySubgridEnum; use numpy::{PyArrayMethods, PyReadonlyArray1, PyReadonlyArray3}; @@ -150,9 +151,10 @@ impl PyImportOnlySubgridV1 { } } -#[pymodule] -pub fn import_only_subgrid(_py: Python, m: &PyModule) -> PyResult<()> { +/// Register submodule in parent. +pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { + let m = PyModule::new_bound(parent_module.py(), "import_only_subgrid")?; m.add_class::()?; m.add_class::()?; - Ok(()) + parent_module.add_submodule(&m) } diff --git a/pineappl_py/src/lib.rs b/pineappl_py/src/lib.rs index dcd2e64d..458382aa 100644 --- a/pineappl_py/src/lib.rs +++ b/pineappl_py/src/lib.rs @@ -1,8 +1,7 @@ -// this is needed for PyO3 to work +//! Generate PyO3 interface. #![allow(unsafe_op_in_unsafe_fn)] use pyo3::prelude::*; -use pyo3::wrap_pymodule; pub mod bin; pub mod channel; @@ -17,13 +16,13 @@ pub mod subgrid; /// NOTE: this name has to match the one in Cargo.toml 'lib.name' #[pymodule] fn pineappl(m: &Bound<'_, PyModule>) -> PyResult<()> { - m.add_wrapped(wrap_pymodule!(bin::bin))?; - m.add_wrapped(wrap_pymodule!(grid::grid))?; - m.add_wrapped(wrap_pymodule!(import_only_subgrid::import_only_subgrid))?; - m.add_wrapped(wrap_pymodule!(evolution::evolution))?; - m.add_wrapped(wrap_pymodule!(channel::channel))?; - m.add_wrapped(wrap_pymodule!(fk_table::fk_table))?; - m.add_wrapped(wrap_pymodule!(subgrid::subgrid))?; + bin::register(m)?; + grid::register(m)?; + import_only_subgrid::register(m)?; + evolution::register(m)?; + channel::register(m)?; + fk_table::register(m)?; + subgrid::register(m)?; m.add("version", env!("CARGO_PKG_VERSION"))?; Ok(()) diff --git a/pineappl_py/src/subgrid.rs b/pineappl_py/src/subgrid.rs index 559a1d2e..0be5354c 100644 --- a/pineappl_py/src/subgrid.rs +++ b/pineappl_py/src/subgrid.rs @@ -1,3 +1,4 @@ +//! Subgrid interface. use ndarray::Array3; use numpy::{IntoPyArray, PyArray1, PyArray3}; use pineappl::subgrid::Mu2; @@ -232,10 +233,11 @@ impl PySubgridEnum { } } -#[pymodule] -pub fn subgrid(_py: Python, m: &PyModule) -> PyResult<()> { +/// Register submodule in parent. +pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { + let m = PyModule::new_bound(parent_module.py(), "subgrid")?; m.add_class::()?; m.add_class::()?; m.add_class::()?; - Ok(()) + parent_module.add_submodule(&m) } From 6f9005e468fbd3a2efdea7cf08ea6669094bb73c Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 14 Aug 2024 14:14:22 +0300 Subject: [PATCH 20/51] Bring back sphinx.ext.autodoc --- pineappl_py/docs/source/conf.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/pineappl_py/docs/source/conf.py b/pineappl_py/docs/source/conf.py index 5e785079..99ad8359 100644 --- a/pineappl_py/docs/source/conf.py +++ b/pineappl_py/docs/source/conf.py @@ -7,6 +7,8 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information import pineappl +import sys +import pathlib project = 'pineappl' copyright = '2020–2024, the PineAPPL team' @@ -18,7 +20,6 @@ extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.autosectionlabel', - 'sphinx.ext.autosummary', 'sphinx.ext.extlinks', 'sphinx.ext.inheritance_diagram', 'sphinx.ext.intersphinx', @@ -27,8 +28,6 @@ 'sphinx_rtd_theme', ] -autosummary_generate = True -autosummary_imported_members = True extlinks = { "rustdoc": ("https://docs.rs/pineappl/latest/pineappl/%s", "PineAPPL - %s"), @@ -42,3 +41,24 @@ html_theme = 'sphinx_rtd_theme' html_static_path = ['_static'] + + +here = pathlib.Path(__file__).absolute().parent + +# https://github.com/readthedocs/readthedocs.org/issues/1139#issuecomment-312626491 +def run_apidoc(_): + from sphinx.ext.apidoc import main # pylint: disable=import-outside-toplevel + + sys.path.append(str(here.parent)) + # analyse 'pineappl' + docs_dest = here / "modules" + import pineappl # pylint: disable=import-outside-toplevel + + # note that we can NOT point to the local directory (`here.parents[1] / "pineappl"`) + # but we need the package built by `maturin` and installed by `pip` + package = pathlib.Path(pineappl.__file__).parent / "pineappl" + main(["--module-first", "--no-toc", "-o", str(docs_dest), str(package)]) + + +def setup(app): + app.connect("builder-inited", run_apidoc) From 144e7917fb2673d89052d7996e1a99a3cad5f94d Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 14 Aug 2024 15:39:44 +0300 Subject: [PATCH 21/51] Deactivate apidoc and use manual list --- pineappl_py/docs/Makefile | 3 +- pineappl_py/docs/source/conf.py | 27 +++++++-------- pineappl_py/docs/source/modules/pineappl.rst | 35 ++++++++++++++++++++ 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/pineappl_py/docs/Makefile b/pineappl_py/docs/Makefile index ea76ec01..ee1f7c7e 100644 --- a/pineappl_py/docs/Makefile +++ b/pineappl_py/docs/Makefile @@ -24,8 +24,9 @@ clean: rm -rf build rm -rf _build +# while apidoc does not work, we need to preserve that folder cleanall: clean - rm -rf $(PINEAPPLOUT) + # rm -rf $(PINEAPPLOUT) .PHONY: help Makefile diff --git a/pineappl_py/docs/source/conf.py b/pineappl_py/docs/source/conf.py index 99ad8359..61e3ef2b 100644 --- a/pineappl_py/docs/source/conf.py +++ b/pineappl_py/docs/source/conf.py @@ -45,20 +45,21 @@ here = pathlib.Path(__file__).absolute().parent -# https://github.com/readthedocs/readthedocs.org/issues/1139#issuecomment-312626491 -def run_apidoc(_): - from sphinx.ext.apidoc import main # pylint: disable=import-outside-toplevel +# TODO: find a way to reactivate apidoc, which doesn't seem to work for the moment. +# # https://github.com/readthedocs/readthedocs.org/issues/1139#issuecomment-312626491 +# def run_apidoc(_): +# from sphinx.ext.apidoc import main # pylint: disable=import-outside-toplevel - sys.path.append(str(here.parent)) - # analyse 'pineappl' - docs_dest = here / "modules" - import pineappl # pylint: disable=import-outside-toplevel +# sys.path.append(str(here.parent)) +# # analyse 'pineappl' +# docs_dest = here / "modules" +# import pineappl # pylint: disable=import-outside-toplevel - # note that we can NOT point to the local directory (`here.parents[1] / "pineappl"`) - # but we need the package built by `maturin` and installed by `pip` - package = pathlib.Path(pineappl.__file__).parent / "pineappl" - main(["--module-first", "--no-toc", "-o", str(docs_dest), str(package)]) +# # note that we can NOT point to the local directory (`here.parents[1] / "pineappl"`) +# # but we need the package built by `maturin` and installed by `pip` +# package = pathlib.Path(pineappl.__file__).parent / "pineappl" +# main(["--module-first", "--no-toc", "-o", str(docs_dest), str(package)]) -def setup(app): - app.connect("builder-inited", run_apidoc) +# def setup(app): +# app.connect("builder-inited", run_apidoc) diff --git a/pineappl_py/docs/source/modules/pineappl.rst b/pineappl_py/docs/source/modules/pineappl.rst index b66bc209..ec475f74 100644 --- a/pineappl_py/docs/source/modules/pineappl.rst +++ b/pineappl_py/docs/source/modules/pineappl.rst @@ -5,3 +5,38 @@ pineappl package :members: :undoc-members: :show-inheritance: + +.. automodule:: pineappl.bin + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: pineappl.channel + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: pineappl.evolution + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: pineappl.fk_table + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: pineappl.grid + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: pineappl.subgrid + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: pineappl.import_only_subgrid + :members: + :undoc-members: + :show-inheritance: From a0e1ae40462d669cda0d3a498775c79a14f1d909 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 14 Aug 2024 15:43:54 +0300 Subject: [PATCH 22/51] Rename PyEvolveInfo --- CHANGELOG.md | 2 ++ pineappl_py/src/evolution.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d189eb4..aaf94acf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 `pineappl.evolution.PidBasis` - Python API: replaced `pineappl.grid.PyOperatorSliceInfo` with `pineappl.evolution.OperatorSliceInfo` +- Python API: drop all `Py` prefix, e.g. `PyEvolveInfo` was renamed to + `EvolveInfo` ### Removed diff --git a/pineappl_py/src/evolution.rs b/pineappl_py/src/evolution.rs index 005702de..f6eb6ec3 100644 --- a/pineappl_py/src/evolution.rs +++ b/pineappl_py/src/evolution.rs @@ -74,7 +74,7 @@ impl PyOperatorSliceInfo { } /// PyO3 wrapper to :rustdoc:`pineappl::evolution::EvolveInfo `. -#[pyclass] +#[pyclass(name = "EvolveInfo")] #[repr(transparent)] pub struct PyEvolveInfo { pub(crate) evolve_info: EvolveInfo, From 517747393733074ba25b6f989864a14011e74b9a Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 14 Aug 2024 15:46:49 +0300 Subject: [PATCH 23/51] Fix links to Rust docs --- pineappl_py/src/evolution.rs | 2 +- pineappl_py/src/fk_table.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pineappl_py/src/evolution.rs b/pineappl_py/src/evolution.rs index f6eb6ec3..3df985f9 100644 --- a/pineappl_py/src/evolution.rs +++ b/pineappl_py/src/evolution.rs @@ -5,7 +5,7 @@ use pineappl::pids::PidBasis; use pyo3::prelude::*; -/// PyO3 wrapper to :rustdoc:`pineappl::pids::PidBasis `. +/// PyO3 wrapper to :rustdoc:`pineappl::pids::PidBasis `. #[pyclass(name = "PidBasis")] #[derive(Clone)] pub enum PyPidBasis { diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index 0542109c..629c4ec6 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -21,7 +21,7 @@ pub struct PyFkTable { pub(crate) fk_table: FkTable, } -/// PyO3 wrapper to :rustdoc:`pineappl::fk_table::PyFkAssumptions `. +/// PyO3 wrapper to :rustdoc:`pineappl::fk_table::PyFkAssumptions `. #[pyclass(name = "FkAssumptions")] #[repr(transparent)] pub struct PyFkAssumptions { From 8bce28c19f510c85331f04e9bd88a8bedbeeb3aa Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 14 Aug 2024 15:51:47 +0300 Subject: [PATCH 24/51] Add python module import hacks and module docs --- pineappl_py/src/bin.rs | 2 ++ pineappl_py/src/channel.rs | 2 ++ pineappl_py/src/evolution.rs | 2 ++ pineappl_py/src/fk_table.rs | 2 ++ pineappl_py/src/grid.rs | 2 ++ pineappl_py/src/import_only_subgrid.rs | 2 ++ pineappl_py/src/subgrid.rs | 2 ++ 7 files changed, 14 insertions(+) diff --git a/pineappl_py/src/bin.rs b/pineappl_py/src/bin.rs index da051801..b2ccbd7f 100644 --- a/pineappl_py/src/bin.rs +++ b/pineappl_py/src/bin.rs @@ -37,6 +37,8 @@ impl PyBinRemapper { /// Register submodule in parent. pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "bin")?; + m.setattr(pyo3::intern!(m.py(), "__doc__"), "Binning interface.")?; + pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.bin'] = m"); m.add_class::()?; parent_module.add_submodule(&m) } diff --git a/pineappl_py/src/channel.rs b/pineappl_py/src/channel.rs index 115b07ad..f7a49413 100644 --- a/pineappl_py/src/channel.rs +++ b/pineappl_py/src/channel.rs @@ -49,6 +49,8 @@ impl PyChannel { /// Register submodule in parent. pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "channel")?; + m.setattr(pyo3::intern!(m.py(), "__doc__"), "Channel interface.")?; + pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.channel'] = m"); m.add_class::()?; parent_module.add_submodule(&m) } diff --git a/pineappl_py/src/evolution.rs b/pineappl_py/src/evolution.rs index 3df985f9..de9216b2 100644 --- a/pineappl_py/src/evolution.rs +++ b/pineappl_py/src/evolution.rs @@ -110,6 +110,8 @@ impl PyEvolveInfo { /// Register submodule in parent. pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "evolution")?; + m.setattr(pyo3::intern!(m.py(), "__doc__"), "Evolution interface.")?; + pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.evolution'] = m"); m.add_class::()?; m.add_class::()?; m.add_class::()?; diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index 629c4ec6..e2fb1d14 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -300,6 +300,8 @@ impl PyFkTable { /// Register submodule in parent. pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "fk_table")?; + m.setattr(pyo3::intern!(m.py(), "__doc__"), "FK table interface.")?; + pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.fk_table'] = m"); m.add_class::()?; m.add_class::()?; parent_module.add_submodule(&m) diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 320ac24e..5c0181d6 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -850,6 +850,8 @@ impl PyGrid { /// Register submodule in parent. pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "grid")?; + m.setattr(pyo3::intern!(m.py(), "__doc__"), "Grid interface.")?; + pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.grid'] = m"); m.add_class::()?; m.add_class::()?; parent_module.add_submodule(&m) diff --git a/pineappl_py/src/import_only_subgrid.rs b/pineappl_py/src/import_only_subgrid.rs index 2eadbdbe..63d4784f 100644 --- a/pineappl_py/src/import_only_subgrid.rs +++ b/pineappl_py/src/import_only_subgrid.rs @@ -154,6 +154,8 @@ impl PyImportOnlySubgridV1 { /// Register submodule in parent. pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "import_only_subgrid")?; + m.setattr(pyo3::intern!(m.py(), "__doc__"), "ImportOnlySubgrid* interface.")?; + pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.import_only_subgrid'] = m"); m.add_class::()?; m.add_class::()?; parent_module.add_submodule(&m) diff --git a/pineappl_py/src/subgrid.rs b/pineappl_py/src/subgrid.rs index 0be5354c..1cc16980 100644 --- a/pineappl_py/src/subgrid.rs +++ b/pineappl_py/src/subgrid.rs @@ -236,6 +236,8 @@ impl PySubgridEnum { /// Register submodule in parent. pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "subgrid")?; + m.setattr(pyo3::intern!(m.py(), "__doc__"), "Subgrid interface.")?; + pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.subgrid'] = m"); m.add_class::()?; m.add_class::()?; m.add_class::()?; From 872b01be23298bfdd586ca80461cc8c793785644 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 14 Aug 2024 16:02:57 +0300 Subject: [PATCH 25/51] Improve docs --- pineappl_py/docs/source/implementation.rst | 8 -------- pineappl_py/docs/source/index.rst | 3 +-- pineappl_py/docs/source/recipes.rst | 14 ++++---------- 3 files changed, 5 insertions(+), 20 deletions(-) delete mode 100644 pineappl_py/docs/source/implementation.rst diff --git a/pineappl_py/docs/source/implementation.rst b/pineappl_py/docs/source/implementation.rst deleted file mode 100644 index cf9dcece..00000000 --- a/pineappl_py/docs/source/implementation.rst +++ /dev/null @@ -1,8 +0,0 @@ -Implementation -============== - -The wrapper is built using PyO3 to interface Rust to Python. - -- The original Rust library that actually provides all the functionality. Any true code should be placed here as this is shared by all interfaces. -- The PyO3 wrapper objects written in Rust that define which methods are exposed to Python and that takes care of the type conversion from Python-understandable types to Rust types. -- The PyO3 wrapper objects in Python which are an exact mirror of their Rust equivalent. This translation is provided by PyO3 and note that it also preserves the associated documentation. diff --git a/pineappl_py/docs/source/index.rst b/pineappl_py/docs/source/index.rst index cf92cdcd..600c36b3 100644 --- a/pineappl_py/docs/source/index.rst +++ b/pineappl_py/docs/source/index.rst @@ -1,7 +1,7 @@ Welcome to PineAPPL =================== -This is the Python wrapper for the `Rust PineAPPL library `_. +This is the Python wrapper for the `Rust PineAPPL library `_ using `PyO3 `_. PineAPPL is a computer library that makes it possible to produce fast-interpolation grids for fitting parton distribution functions (PDFs) including corrections of strong and electroweak origin. @@ -18,6 +18,5 @@ We also list some common :doc:`recipes` here. installation recipes - implementation API indices diff --git a/pineappl_py/docs/source/recipes.rst b/pineappl_py/docs/source/recipes.rst index f026bf4e..a599a888 100644 --- a/pineappl_py/docs/source/recipes.rst +++ b/pineappl_py/docs/source/recipes.rst @@ -13,7 +13,7 @@ How can I convolve a given PineAPPL grid with my PDF? import lhapdf g = pineappl.grid.Grid.read("path/to/grid.pineappl.lz4") pdf = lhapdf.mkPDF("YourPDF", 0) - bins = g.convolve(pdf.xfxQ2, pdf.xfxQ2, pdf.alphasQ2) + bins = g.convolve_with_one(2212, pdf.xfxQ2, pdf.alphasQ2) If the grid is actually an FkTable just replace @@ -23,16 +23,11 @@ If the grid is actually an FkTable just replace .. note:: - For the :meth:`pineappl.pineappl.PyGrid.read` function, both ``.pineappl`` + For the :meth:`pineappl.grid.Grid.read` function, both ``.pineappl`` and ``.pineappl.lz4`` extensions are acceptable, as long as they are consistent (without ``.lz4`` the grid is assumed not to be compressed, with it is assumed compressed). - This is asymmetric with respect to the - :meth:`pineappl.pineappl.PyGrid.write` function, in which the function will - refuse to guess, so another version is provided to write a compressed grid, - :meth:`pineappl.pineappl.PyGrid.write_lz4` - How can I edit a grid? ---------------------- @@ -60,9 +55,8 @@ change even the bins themselves. remapper = pineappl.bin.BinRemapper(normalizations, limits) g.set_remapper(remapper) -For more details about :class:`pineappl.bin.BinRemapper` check also the `Rust -documentation -`_, e.g. +For more details about :class:`pineappl.bin.BinRemapper` check also +the Rust documentation of :rustdoc:`pineappl::bin::BinRemapper `, e.g. on how to treat multidimensional distributions. How can I get the bin configurations from a given PineAPPL grid? From 5279c235bbb0a5e41aca921542fe99d2fd5c221f Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 15:03:06 +0200 Subject: [PATCH 26/51] Fix more broken links --- pineappl_py/src/fk_table.rs | 2 +- pineappl_py/src/grid.rs | 2 +- pineappl_py/src/subgrid.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index e2fb1d14..072b7e65 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -21,7 +21,7 @@ pub struct PyFkTable { pub(crate) fk_table: FkTable, } -/// PyO3 wrapper to :rustdoc:`pineappl::fk_table::PyFkAssumptions `. +/// PyO3 wrapper to :rustdoc:`pineappl::fk_table::FkAssumptions `. #[pyclass(name = "FkAssumptions")] #[repr(transparent)] pub struct PyFkAssumptions { diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 5c0181d6..432762eb 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -25,7 +25,7 @@ use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use pyo3::types::PyIterator; -/// PyO3 wrapper to :rustdoc:`pineappl::grid::Order `. +/// PyO3 wrapper to :rustdoc:`pineappl::boc::Order `. #[pyclass(name = "Order")] #[repr(transparent)] pub struct PyOrder { diff --git a/pineappl_py/src/subgrid.rs b/pineappl_py/src/subgrid.rs index 1cc16980..cad083b3 100644 --- a/pineappl_py/src/subgrid.rs +++ b/pineappl_py/src/subgrid.rs @@ -5,7 +5,7 @@ use pineappl::subgrid::Mu2; use pineappl::subgrid::{Subgrid, SubgridEnum, SubgridParams}; use pyo3::prelude::*; -/// PyO3 wrapper to :rustdoc:`pineappl::subgrid::SubgridParams ` +/// PyO3 wrapper to :rustdoc:`pineappl::subgrid::SubgridParams ` #[pyclass(name = "SubgridParams")] #[repr(transparent)] pub struct PySubgridParams { From 759f7fa0057978a401747a13ca114752d4849776 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 15:09:29 +0200 Subject: [PATCH 27/51] Run `cargo fmt` --- pineappl_py/src/fk_table.rs | 6 +++++- pineappl_py/src/grid.rs | 6 +++++- pineappl_py/src/subgrid.rs | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index 072b7e65..0c734778 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -301,7 +301,11 @@ impl PyFkTable { pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "fk_table")?; m.setattr(pyo3::intern!(m.py(), "__doc__"), "FK table interface.")?; - pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.fk_table'] = m"); + pyo3::py_run!( + parent_module.py(), + m, + "import sys; sys.modules['pineappl.fk_table'] = m" + ); m.add_class::()?; m.add_class::()?; parent_module.add_submodule(&m) diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 432762eb..76c40e28 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -851,7 +851,11 @@ impl PyGrid { pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "grid")?; m.setattr(pyo3::intern!(m.py(), "__doc__"), "Grid interface.")?; - pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.grid'] = m"); + pyo3::py_run!( + parent_module.py(), + m, + "import sys; sys.modules['pineappl.grid'] = m" + ); m.add_class::()?; m.add_class::()?; parent_module.add_submodule(&m) diff --git a/pineappl_py/src/subgrid.rs b/pineappl_py/src/subgrid.rs index cad083b3..48f39770 100644 --- a/pineappl_py/src/subgrid.rs +++ b/pineappl_py/src/subgrid.rs @@ -237,7 +237,11 @@ impl PySubgridEnum { pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "subgrid")?; m.setattr(pyo3::intern!(m.py(), "__doc__"), "Subgrid interface.")?; - pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.subgrid'] = m"); + pyo3::py_run!( + parent_module.py(), + m, + "import sys; sys.modules['pineappl.subgrid'] = m" + ); m.add_class::()?; m.add_class::()?; m.add_class::()?; From 4c53c713b6244d767e4a86fc4f3cbfd602b7e3f8 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 15:11:42 +0200 Subject: [PATCH 28/51] Reformat `CHANGELOG.md` --- CHANGELOG.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aaf94acf..538f63d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,18 +15,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Python API: dropped top-level Python interface layer -- Python API: renamed `lumi` to `channel` in PyO3 Python interface. - This concerns 1) the argument names of `convolute_with_one` and - similar functions; 2) the module `pineappl.lumi` was moved to - `pineappl.channel`; 3) the class `LumiEntry` was renamed to `Channel` -- Python API: `.into()` needs to be explicitly called on subgrids when - calling `pineappl.grid.set_subgrid()` +- Python API: renamed `lumi` to `channel` in PyO3 Python interface. This + concerns 1) the argument names of `convolute_with_one` and similar functions; + 2) the module `pineappl.lumi` was moved to `pineappl.channel`; 3) the class + `LumiEntry` was renamed to `Channel` +- Python API: `.into()` needs to be explicitly called on subgrids when calling + `pineappl.grid.set_subgrid()` - Python API: replaced `pineappl.grid.PyPidBasis` with `pineappl.evolution.PidBasis` - Python API: replaced `pineappl.grid.PyOperatorSliceInfo` with `pineappl.evolution.OperatorSliceInfo` -- Python API: drop all `Py` prefix, e.g. `PyEvolveInfo` was renamed to - `EvolveInfo` +- Python API: drop all `Py` prefixes, for instance `PyEvolveInfo` was renamed + to `EvolveInfo` ### Removed From 09460b6ec1f7502e1c72e75e0ffc1f4cd34b9af4 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 14 Aug 2024 16:24:53 +0300 Subject: [PATCH 29/51] Readd docs/gitignore --- pineappl_py/docs/.gitignore | 7 +++++++ pineappl_py/docs/Makefile | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 pineappl_py/docs/.gitignore diff --git a/pineappl_py/docs/.gitignore b/pineappl_py/docs/.gitignore new file mode 100644 index 00000000..f6b158dd --- /dev/null +++ b/pineappl_py/docs/.gitignore @@ -0,0 +1,7 @@ +# Ignore auto generated module references +# TODO: while apidoc does not work, we need to preserve that folder +# source/modules +# ignore temporary build files +build/ +# Ignore generated sphinx-bibtex file +source/bibtex.json diff --git a/pineappl_py/docs/Makefile b/pineappl_py/docs/Makefile index ee1f7c7e..db4a541c 100644 --- a/pineappl_py/docs/Makefile +++ b/pineappl_py/docs/Makefile @@ -24,7 +24,7 @@ clean: rm -rf build rm -rf _build -# while apidoc does not work, we need to preserve that folder +# TODO: while apidoc does not work, we need to preserve that folder cleanall: clean # rm -rf $(PINEAPPLOUT) From 53fba7ba5354fe7179f6969f896329ea00efecc0 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 14 Aug 2024 16:30:02 +0300 Subject: [PATCH 30/51] Rename API header --- pineappl_py/docs/source/modules/pineappl.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pineappl_py/docs/source/modules/pineappl.rst b/pineappl_py/docs/source/modules/pineappl.rst index ec475f74..3bbe4b8e 100644 --- a/pineappl_py/docs/source/modules/pineappl.rst +++ b/pineappl_py/docs/source/modules/pineappl.rst @@ -1,5 +1,5 @@ -pineappl package -================ +PineAPPL's Python API +===================== .. automodule:: pineappl :members: From 2727c4cba2212cac50da93a2b2bd31f90da7c2a5 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 14 Aug 2024 16:38:24 +0300 Subject: [PATCH 31/51] Shuffle docs/gitignoe upwards --- pineappl_py/.gitignore | 9 +++++++-- pineappl_py/docs/.gitignore | 7 ------- 2 files changed, 7 insertions(+), 9 deletions(-) delete mode 100644 pineappl_py/docs/.gitignore diff --git a/pineappl_py/.gitignore b/pineappl_py/.gitignore index 21abbfe8..2452cb59 100644 --- a/pineappl_py/.gitignore +++ b/pineappl_py/.gitignore @@ -21,8 +21,13 @@ coverage.xml .coverage # Sphinx documentation -docs/_build/ -doc/_build/ +# Ignore auto generated module references +# TODO: while apidoc does not work, we need to preserve that folder +# docs/source/modules +# ignore temporary build files +docs/build/ +# Ignore generated sphinx-bibtex file +docs/source/bibtex.json # Environments .env diff --git a/pineappl_py/docs/.gitignore b/pineappl_py/docs/.gitignore deleted file mode 100644 index f6b158dd..00000000 --- a/pineappl_py/docs/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Ignore auto generated module references -# TODO: while apidoc does not work, we need to preserve that folder -# source/modules -# ignore temporary build files -build/ -# Ignore generated sphinx-bibtex file -source/bibtex.json From 19e15646962c97244f1e5d4b7446a60e1fcce113 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 14 Aug 2024 16:43:06 +0300 Subject: [PATCH 32/51] Drop requirements.txt --- pineappl_py/README.md | 12 ++++++++++-- pineappl_py/requirements.txt | 28 ---------------------------- 2 files changed, 10 insertions(+), 30 deletions(-) delete mode 100644 pineappl_py/requirements.txt diff --git a/pineappl_py/README.md b/pineappl_py/README.md index e75e7657..1bbf34d9 100644 --- a/pineappl_py/README.md +++ b/pineappl_py/README.md @@ -19,11 +19,19 @@ Run ```shell python -m venv env && . env/bin/activate -pip install -r requirements.txt +pip install .[docs] +``` + +to setup a new environment. + + +Run + +```shell maturin develop ``` -to build and setup a new environment. +to build the project. Run diff --git a/pineappl_py/requirements.txt b/pineappl_py/requirements.txt deleted file mode 100644 index 7bd3ed9b..00000000 --- a/pineappl_py/requirements.txt +++ /dev/null @@ -1,28 +0,0 @@ -alabaster==0.7.16 -babel==2.16.0 -certifi==2024.7.4 -charset-normalizer==3.3.2 -docutils==0.20.1 -idna==3.7 -imagesize==1.4.1 -importlib-metadata==8.2.0 -jinja2==3.1.4 -MarkupSafe==2.1.5 -maturin==1.7.0 -numpy==1.26.4 -packaging==24.1 -pygments==2.18.0 -requests==2.32.3 -snowballstemmer==2.2.0 -sphinx==7.4.7 -sphinx-rtd-theme==2.0.0 -sphinxcontrib-applehelp==2.0.0 -sphinxcontrib-devhelp==2.0.0 -sphinxcontrib-htmlhelp==2.1.0 -sphinxcontrib-jquery==4.1 -sphinxcontrib-jsmath==1.0.1 -sphinxcontrib-qthelp==2.0.0 -sphinxcontrib-serializinghtml==2.0.0 -tomli==2.0.1 -urllib3==2.2.2 -zipp==3.20.0 From 77995e07d76eb944780ae750e76404f2c6cc2bf0 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 14 Aug 2024 16:44:33 +0300 Subject: [PATCH 33/51] Apply suggestions from code review --- pineappl_py/.gitignore | 2 -- pineappl_py/docs/source/conf.py | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pineappl_py/.gitignore b/pineappl_py/.gitignore index 2452cb59..83eb351c 100644 --- a/pineappl_py/.gitignore +++ b/pineappl_py/.gitignore @@ -26,8 +26,6 @@ coverage.xml # docs/source/modules # ignore temporary build files docs/build/ -# Ignore generated sphinx-bibtex file -docs/source/bibtex.json # Environments .env diff --git a/pineappl_py/docs/source/conf.py b/pineappl_py/docs/source/conf.py index 61e3ef2b..8c3b56cf 100644 --- a/pineappl_py/docs/source/conf.py +++ b/pineappl_py/docs/source/conf.py @@ -43,9 +43,9 @@ html_static_path = ['_static'] -here = pathlib.Path(__file__).absolute().parent - # TODO: find a way to reactivate apidoc, which doesn't seem to work for the moment. + +# here = pathlib.Path(__file__).absolute().parent # # https://github.com/readthedocs/readthedocs.org/issues/1139#issuecomment-312626491 # def run_apidoc(_): # from sphinx.ext.apidoc import main # pylint: disable=import-outside-toplevel From 6895357718ef53ccda0fea63d0fa9b87ffcb0329 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 16:20:03 +0200 Subject: [PATCH 34/51] Fix installation instructions --- pineappl_py/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pineappl_py/README.md b/pineappl_py/README.md index 1bbf34d9..b4ff694d 100644 --- a/pineappl_py/README.md +++ b/pineappl_py/README.md @@ -19,7 +19,7 @@ Run ```shell python -m venv env && . env/bin/activate -pip install .[docs] +pip install maturin ``` to setup a new environment. @@ -36,6 +36,7 @@ to build the project. Run ```shell +maturin develop -E docs cd docs && make html ``` From 03e7d6ac363ea10e9afa2ab7377503782fd58da7 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 16:20:18 +0200 Subject: [PATCH 35/51] Remove unneeded dependency --- pineappl_py/pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pineappl_py/pyproject.toml b/pineappl_py/pyproject.toml index cb088610..7c861e62 100644 --- a/pineappl_py/pyproject.toml +++ b/pineappl_py/pyproject.toml @@ -28,7 +28,6 @@ cli = ["pineappl-cli"] docs = [ "sphinx>=6.2.1", "sphinx_rtd_theme>=1.2.2", - "sphinxcontrib-bibtex>=2.5.0", "nbsphinx>=0.9.2", ] test = ["pytest", "pytest-cov"] From 645388786430b15b22234d54142463d625e4cd2f Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 16:29:37 +0200 Subject: [PATCH 36/51] Remove yet another unneeded dependency Co-authored-by: Felix Hekhorn --- pineappl_py/pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pineappl_py/pyproject.toml b/pineappl_py/pyproject.toml index 7c861e62..2b0864f2 100644 --- a/pineappl_py/pyproject.toml +++ b/pineappl_py/pyproject.toml @@ -28,7 +28,6 @@ cli = ["pineappl-cli"] docs = [ "sphinx>=6.2.1", "sphinx_rtd_theme>=1.2.2", - "nbsphinx>=0.9.2", ] test = ["pytest", "pytest-cov"] From b0de152dfe81591158f25b3b1d6602c150dfc919 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 17:11:10 +0200 Subject: [PATCH 37/51] Write more detailed instructions for Python development --- pineappl_py/README.md | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/pineappl_py/README.md b/pineappl_py/README.md index b4ff694d..51d3668f 100644 --- a/pineappl_py/README.md +++ b/pineappl_py/README.md @@ -19,11 +19,20 @@ Run ```shell python -m venv env && . env/bin/activate -pip install maturin ``` -to setup a new environment. +to setup a new environment and check that `pip --version` returns at least `pip +22.0 from ...`. If not, upgrade `pip` via + +```shell +pip install -U pip +``` +Next, install the needed dependencies: + +```shell +pip install maturin +``` Run @@ -31,13 +40,21 @@ Run maturin develop ``` -to build the project. +to build the project, which also install it into the environment so that it can +be used in Python project using the same environment. -Run +### Documentation + +Run the following once to install the documentation's dependencies: + +```shell +pip install .[docs] +``` + +Then run ```shell -maturin develop -E docs -cd docs && make html +( cd docs && make clean html ) ``` to generate the documentation. From 43485a6ff58bc29bbee3806b9ced98e00287e3d9 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 17:13:37 +0200 Subject: [PATCH 38/51] Add some small fixes to Python's `README.md` file --- pineappl_py/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pineappl_py/README.md b/pineappl_py/README.md index 51d3668f..47583150 100644 --- a/pineappl_py/README.md +++ b/pineappl_py/README.md @@ -28,7 +28,7 @@ to setup a new environment and check that `pip --version` returns at least `pip pip install -U pip ``` -Next, install the needed dependencies: +Next, install `maturin`: ```shell pip install maturin @@ -40,8 +40,8 @@ Run maturin develop ``` -to build the project, which also install it into the environment so that it can -be used in Python project using the same environment. +to build the project, which also installs it into the environment so that it +can be used in Python projects that use the same environment. ### Documentation From ba7aa7a47d661bb54cc589ef5514e845deca3f9c Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Wed, 14 Aug 2024 17:25:39 +0200 Subject: [PATCH 39/51] Add single quotes in `pip install ...` Co-authored-by: Alessandro Candido --- pineappl_py/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pineappl_py/README.md b/pineappl_py/README.md index 47583150..a91bb744 100644 --- a/pineappl_py/README.md +++ b/pineappl_py/README.md @@ -48,7 +48,7 @@ can be used in Python projects that use the same environment. Run the following once to install the documentation's dependencies: ```shell -pip install .[docs] +pip install '.[docs]' ``` Then run From 3bf331d98ac0aa416ba37aa8d9796e745ddc66ef Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 15 Aug 2024 08:34:26 +0200 Subject: [PATCH 40/51] Run `black` --- pineappl_py/tests/test_sugrid.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pineappl_py/tests/test_sugrid.py b/pineappl_py/tests/test_sugrid.py index 32055ea2..f4fedff2 100644 --- a/pineappl_py/tests/test_sugrid.py +++ b/pineappl_py/tests/test_sugrid.py @@ -46,7 +46,9 @@ def fake_importonlysubgrid(self): Q2s = np.linspace(10, 20, 2) mu2s = [tuple([q2, q2]) for q2 in Q2s] array = np.random.rand(len(Q2s), len(x1s), len(x2s)) - subgrid = pineappl.import_only_subgrid.ImportOnlySubgridV2(array, mu2s, x1s, x2s) + subgrid = pineappl.import_only_subgrid.ImportOnlySubgridV2( + array, mu2s, x1s, x2s + ) return subgrid, [x1s, x2s, mu2s, array] def test_subgrid_methods(self): @@ -67,7 +69,7 @@ def test_to_array3(self): test_subgrid, infos = self.fake_importonlysubgrid() _, _, _, array = (obj for obj in infos) grid.set_subgrid(0, 0, 0, test_subgrid.into()) - extr_subgrid = grid.subgrid(0,0,0) + extr_subgrid = grid.subgrid(0, 0, 0) test_array = extr_subgrid.to_array3() print(test_array) print(array) From 3a8064b16a5ab652721038cc9c445951176f5e42 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 15 Aug 2024 09:18:34 +0200 Subject: [PATCH 41/51] Fix most compilation warnings --- pineappl_py/src/evolution.rs | 2 ++ pineappl_py/src/fk_table.rs | 8 ++++---- pineappl_py/src/grid.rs | 2 +- pineappl_py/src/subgrid.rs | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pineappl_py/src/evolution.rs b/pineappl_py/src/evolution.rs index de9216b2..d7ecf17e 100644 --- a/pineappl_py/src/evolution.rs +++ b/pineappl_py/src/evolution.rs @@ -9,7 +9,9 @@ use pyo3::prelude::*; #[pyclass(name = "PidBasis")] #[derive(Clone)] pub enum PyPidBasis { + /// PDG Monte Carlo IDs. Pdg, + /// NNPDF's evolution basis IDs. Evol, } diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index 0c734778..08328dcd 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -261,15 +261,15 @@ impl PyFkTable { pub fn convolve_with_two<'py>( &self, pdg_id1: i32, - xfx1: &PyAny, + xfx1: &Bound<'py, PyAny>, pdg_id2: i32, - xfx2: &PyAny, + xfx2: &Bound<'py, PyAny>, bin_indices: Option>, channel_mask: Option>, py: Python<'py>, ) -> Bound<'py, PyArray1> { - let mut xfx1 = |id, x, q2| f64::extract(xfx1.call1((id, x, q2)).unwrap()).unwrap(); - let mut xfx2 = |id, x, q2| f64::extract(xfx2.call1((id, x, q2)).unwrap()).unwrap(); + let mut xfx1 = |id, x, q2| xfx1.call1((id, x, q2)).unwrap().extract().unwrap(); + let mut xfx2 = |id, x, q2| xfx2.call1((id, x, q2)).unwrap().extract().unwrap(); let mut alphas = |_| 1.0; let mut lumi_cache = LumiCache::with_two(pdg_id1, &mut xfx1, pdg_id2, &mut xfx2, &mut alphas); diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 76c40e28..ec9bb2e1 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -7,7 +7,7 @@ use pineappl::grid::{Grid, Ntuple}; use super::bin::PyBinRemapper; use super::channel::PyChannel; -use super::evolution::{PyEvolveInfo, PyOperatorSliceInfo, PyPidBasis}; +use super::evolution::{PyEvolveInfo, PyOperatorSliceInfo}; use super::fk_table::PyFkTable; use super::subgrid::{PySubgridEnum, PySubgridParams}; diff --git a/pineappl_py/src/subgrid.rs b/pineappl_py/src/subgrid.rs index 48f39770..13dda42b 100644 --- a/pineappl_py/src/subgrid.rs +++ b/pineappl_py/src/subgrid.rs @@ -139,7 +139,7 @@ impl PySubgridParams { #[pyclass(name = "Mu2")] #[repr(transparent)] pub struct PyMu2 { - pub mu2: Mu2, + pub(crate) mu2: Mu2, } #[pymethods] From a7d461d22f36ab6b7a6a50f9b2221c01f3dcff4b Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 15 Aug 2024 09:21:42 +0200 Subject: [PATCH 42/51] Remove deprecated methods --- pineappl_py/src/grid.rs | 96 +---------------------------------------- 1 file changed, 2 insertions(+), 94 deletions(-) diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index ec9bb2e1..2c485a5b 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -2,7 +2,7 @@ use ndarray::CowArray; use pineappl::boc::Order; use pineappl::convolutions::LumiCache; -use pineappl::evolution::{AlphasTable, OperatorInfo}; +use pineappl::evolution::AlphasTable; use pineappl::grid::{Grid, Ntuple}; use super::bin::PyBinRemapper; @@ -12,9 +12,7 @@ use super::fk_table::PyFkTable; use super::subgrid::{PySubgridEnum, PySubgridParams}; use itertools::izip; -use numpy::{ - IntoPyArray, PyArray1, PyArrayMethods, PyReadonlyArray1, PyReadonlyArray4, PyReadonlyArray5, -}; +use numpy::{IntoPyArray, PyArray1, PyArrayMethods, PyReadonlyArray1, PyReadonlyArray4}; use std::collections::HashMap; use std::fs::File; @@ -449,82 +447,6 @@ impl PyGrid { .into_pyarray_bound(py) } - /// Convolve with an evolution operator. - /// - /// Parameters - /// ---------- - /// operator : numpy.ndarray(int, rank=5) - /// evolution tensor - /// fac0 : float - /// reference scale - /// pids0 : numpy.ndarray(int) - /// sorting of the particles in the tensor for final FkTable - /// x0 : numpy.ndarray(float) - /// final FKTable interpolation grid - /// fac1 : numpy.ndarray(float) - /// list of factorization scales - /// pids1 : numpy.ndarray(int) - /// sorting of the particles in the grid - /// x1 : numpy.ndarray(float) - /// interpolation grid at process level - /// ren1 : numpy.ndarray(float) - /// list of renormalization scales - /// alphas : numpy.ndarray(float) - /// list with :math:`\alpha_s(Q2)` for the process scales - /// xi : (float, float) - /// factorization and renormalization variation - /// pid_basis : str - /// type of channel identifier - /// order_mask : numpy.ndarray(bool) - /// boolean mask to activate orders - /// - /// Returns - /// ------- - /// PyFkTable : - /// produced FK table - #[deprecated(since = "0.7.4", note = "use evolve_with_slice_iter instead")] - pub fn evolve( - &self, - operator: PyReadonlyArray5, - fac0: f64, - pids0: PyReadonlyArray1, - x0: PyReadonlyArray1, - fac1: PyReadonlyArray1, - pids1: PyReadonlyArray1, - x1: PyReadonlyArray1, - ren1: PyReadonlyArray1, - alphas: PyReadonlyArray1, - xi: (f64, f64), - pid_basis: String, - order_mask: PyReadonlyArray1, - ) -> PyFkTable { - let op_info = OperatorInfo { - fac0: fac0, - pids0: pids0.to_vec().unwrap(), - x0: x0.to_vec().unwrap(), - fac1: fac1.to_vec().unwrap(), - pids1: pids1.to_vec().unwrap(), - x1: x1.to_vec().unwrap(), - ren1: ren1.to_vec().unwrap(), - alphas: alphas.to_vec().unwrap(), - xir: xi.0, - xif: xi.1, - pid_basis: pid_basis.parse().unwrap(), - }; - - let evolved_grid = self - .grid - .evolve( - operator.as_array(), - &op_info, - order_mask.as_slice().unwrap(), - ) - .expect("Nothing returned from evolution."); - PyFkTable { - fk_table: evolved_grid, - } - } - /// Collect information for convolution with an evolution operator. /// /// Parameters @@ -707,20 +629,6 @@ impl PyGrid { } } - /// Merge with another grid, loaded from file. - /// - /// Note - /// ---- - /// For a current limitation with the implementation of the bound object `Grid` is not possible - /// to operate with two `Grid`s in memory, since is not possible to pass a `Grid` by argument - #[deprecated = "Deprecated in favor of PyGrid::merge"] - pub fn merge_from_file(&mut self, path: PathBuf) -> PyResult<()> { - match self.grid.merge(Self::read(path).grid) { - Ok(()) => Ok(()), - Err(x) => Err(PyValueError::new_err(format!("{:?}", x))), - } - } - /// Extract the number of dimensions for bins. /// /// E.g.: two differential cross-sections will return 2. From 024bcd6defcbcf1920488a81e30ffaccdb9101cb Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 15 Aug 2024 09:21:56 +0200 Subject: [PATCH 43/51] Run `cargo fmt` --- pineappl_py/src/bin.rs | 6 +++++- pineappl_py/src/channel.rs | 6 +++++- pineappl_py/src/evolution.rs | 6 +++++- pineappl_py/src/import_only_subgrid.rs | 11 +++++++++-- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/pineappl_py/src/bin.rs b/pineappl_py/src/bin.rs index b2ccbd7f..445b9428 100644 --- a/pineappl_py/src/bin.rs +++ b/pineappl_py/src/bin.rs @@ -38,7 +38,11 @@ impl PyBinRemapper { pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "bin")?; m.setattr(pyo3::intern!(m.py(), "__doc__"), "Binning interface.")?; - pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.bin'] = m"); + pyo3::py_run!( + parent_module.py(), + m, + "import sys; sys.modules['pineappl.bin'] = m" + ); m.add_class::()?; parent_module.add_submodule(&m) } diff --git a/pineappl_py/src/channel.rs b/pineappl_py/src/channel.rs index f7a49413..3f257430 100644 --- a/pineappl_py/src/channel.rs +++ b/pineappl_py/src/channel.rs @@ -50,7 +50,11 @@ impl PyChannel { pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "channel")?; m.setattr(pyo3::intern!(m.py(), "__doc__"), "Channel interface.")?; - pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.channel'] = m"); + pyo3::py_run!( + parent_module.py(), + m, + "import sys; sys.modules['pineappl.channel'] = m" + ); m.add_class::()?; parent_module.add_submodule(&m) } diff --git a/pineappl_py/src/evolution.rs b/pineappl_py/src/evolution.rs index d7ecf17e..2835e8cf 100644 --- a/pineappl_py/src/evolution.rs +++ b/pineappl_py/src/evolution.rs @@ -113,7 +113,11 @@ impl PyEvolveInfo { pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "evolution")?; m.setattr(pyo3::intern!(m.py(), "__doc__"), "Evolution interface.")?; - pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.evolution'] = m"); + pyo3::py_run!( + parent_module.py(), + m, + "import sys; sys.modules['pineappl.evolution'] = m" + ); m.add_class::()?; m.add_class::()?; m.add_class::()?; diff --git a/pineappl_py/src/import_only_subgrid.rs b/pineappl_py/src/import_only_subgrid.rs index 63d4784f..fa52b132 100644 --- a/pineappl_py/src/import_only_subgrid.rs +++ b/pineappl_py/src/import_only_subgrid.rs @@ -154,8 +154,15 @@ impl PyImportOnlySubgridV1 { /// Register submodule in parent. pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let m = PyModule::new_bound(parent_module.py(), "import_only_subgrid")?; - m.setattr(pyo3::intern!(m.py(), "__doc__"), "ImportOnlySubgrid* interface.")?; - pyo3::py_run!(parent_module.py(), m, "import sys; sys.modules['pineappl.import_only_subgrid'] = m"); + m.setattr( + pyo3::intern!(m.py(), "__doc__"), + "ImportOnlySubgrid* interface.", + )?; + pyo3::py_run!( + parent_module.py(), + m, + "import sys; sys.modules['pineappl.import_only_subgrid'] = m" + ); m.add_class::()?; m.add_class::()?; parent_module.add_submodule(&m) From ea9d1577b44f8f3ad185e4f7c4cacb9bfe4db05f Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 15 Aug 2024 09:32:59 +0200 Subject: [PATCH 44/51] Move structs into modules corresponding to Rust modules --- pineappl_py/src/boc.rs | 149 +++++++++++++++++++++++++++++ pineappl_py/src/channel.rs | 60 ------------ pineappl_py/src/evolution.rs | 23 +---- pineappl_py/src/grid.rs | 87 +---------------- pineappl_py/src/lib.rs | 6 +- pineappl_py/tests/test_boc.py | 7 ++ pineappl_py/tests/test_channel.py | 7 -- pineappl_py/tests/test_fk_table.py | 4 +- pineappl_py/tests/test_grid.py | 2 +- pineappl_py/tests/test_sugrid.py | 4 +- 10 files changed, 168 insertions(+), 181 deletions(-) create mode 100644 pineappl_py/src/boc.rs delete mode 100644 pineappl_py/src/channel.rs create mode 100644 pineappl_py/tests/test_boc.py delete mode 100644 pineappl_py/tests/test_channel.py diff --git a/pineappl_py/src/boc.rs b/pineappl_py/src/boc.rs new file mode 100644 index 00000000..aadad461 --- /dev/null +++ b/pineappl_py/src/boc.rs @@ -0,0 +1,149 @@ +//! Interface for bins, orders and channels. + +use numpy::{IntoPyArray, PyArray1}; +use pineappl::boc::{Channel, Order}; + +use pyo3::prelude::*; + +/// PyO3 wrapper to :rustdoc:`pineappl::boc::Channel `. +/// +/// Each entry consists of a tuple, which contains, in the following order: +/// +/// 1. the PDG id of the first incoming parton +/// 2. the PDG id of the second parton +/// 3. a numerical factor that will multiply the result for this specific combination. +#[pyclass(name = "Channel")] +#[repr(transparent)] +pub struct PyChannel { + pub(crate) entry: Channel, +} + +impl PyChannel { + pub(crate) fn new(entry: Channel) -> Self { + Self { entry } + } +} + +#[pymethods] +impl PyChannel { + /// Constructor. + /// + /// Parameters + /// ---------- + /// entry: list(tuple(int, int, float)) + /// channel configuration + #[new] + pub fn new_entry(entry: Vec<(i32, i32, f64)>) -> Self { + Self::new(Channel::new(entry)) + } + + /// Get list representation. + /// + /// Returns + /// ------- + /// list(tuple(int,int,float)) : + /// list representation + pub fn into_array(&self) -> Vec<(i32, i32, f64)> { + self.entry.entry().to_vec() + } +} + +/// Register submodule in parent. +pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { + let m = PyModule::new_bound(parent_module.py(), "boc")?; + m.setattr( + pyo3::intern!(m.py(), "__doc__"), + "Interface for bins, orders and channels.", + )?; + pyo3::py_run!( + parent_module.py(), + m, + "import sys; sys.modules['pineappl.channel'] = m" + ); + m.add_class::()?; + parent_module.add_submodule(&m) +} + +/// PyO3 wrapper to :rustdoc:`pineappl::boc::Order `. +#[pyclass(name = "Order")] +#[repr(transparent)] +pub struct PyOrder { + pub(crate) order: Order, +} + +impl PyOrder { + pub(crate) fn new(order: Order) -> Self { + Self { order } + } +} + +#[pymethods] +impl PyOrder { + /// Constructor. + /// + /// Parameters + /// ---------- + /// alphas : int + /// power of :math:`\alpha_s` + /// alpha : int + /// power of :math:`\alpha` + /// logxir : int + /// power of :math:`\ln(\xi_r)` + /// logxif : int + /// power of :math:`\ln(\xi_f)` + #[new] + pub fn new_order(alphas: u32, alpha: u32, logxir: u32, logxif: u32) -> Self { + Self::new(Order::new(alphas, alpha, logxir, logxif)) + } + + /// Tuple representation. + /// + /// Returns + /// ------- + /// alphas : int + /// power of :math:`\alpha_s` + /// alpha : int + /// power of :math:`\alpha` + /// logxir : int + /// power of :math:`\ln(\xi_r)` + /// logxif : int + /// power of :math:`\ln(\xi_f)` + pub fn as_tuple(&self) -> (u32, u32, u32, u32) { + ( + self.order.alphas, + self.order.alpha, + self.order.logxir, + self.order.logxif, + ) + } + + /// Return a mask suitable to pass as the `order_mask` parameter of [`Grid::convolve`]. + /// + /// The selection of `orders` is controlled using the `max_as` and `max_al` parameters, for + /// instance setting `max_as = 1` and `max_al = 0` selects the LO QCD only, `max_as = 2` and + /// `max_al = 0` the NLO QCD; setting `max_as = 3` and `max_al = 2` would select all NLOs, and + /// the NNLO QCD. + /// + /// See `pineappl` crate docs for more examples. + /// + /// Returns + /// ------- + /// numpy.ndarray(bool) + /// boolean array, to be used as orders' mask + #[staticmethod] + pub fn create_mask<'py>( + orders: Vec>, + max_as: u32, + max_al: u32, + logs: bool, + py: Python<'py>, + ) -> Bound<'py, PyArray1> { + Order::create_mask( + &orders.iter().map(|o| o.order.clone()).collect::>(), + max_as, + max_al, + logs, + ) + .into_pyarray_bound(py) + } +} diff --git a/pineappl_py/src/channel.rs b/pineappl_py/src/channel.rs deleted file mode 100644 index 3f257430..00000000 --- a/pineappl_py/src/channel.rs +++ /dev/null @@ -1,60 +0,0 @@ -//! Channel interface. -use pineappl::boc::Channel; - -use pyo3::prelude::*; - -/// PyO3 wrapper to :rustdoc:`pineappl::boc::Channel `. -/// -/// Each entry consists of a tuple, which contains, in the following order: -/// -/// 1. the PDG id of the first incoming parton -/// 2. the PDG id of the second parton -/// 3. a numerical factor that will multiply the result for this specific combination. -#[pyclass(name = "Channel")] -#[repr(transparent)] -pub struct PyChannel { - pub(crate) entry: Channel, -} - -impl PyChannel { - pub(crate) fn new(entry: Channel) -> Self { - Self { entry } - } -} - -#[pymethods] -impl PyChannel { - /// Constructor. - /// - /// Parameters - /// ---------- - /// entry: list(tuple(int, int, float)) - /// channel configuration - #[new] - pub fn new_entry(entry: Vec<(i32, i32, f64)>) -> Self { - Self::new(Channel::new(entry)) - } - - /// Get list representation. - /// - /// Returns - /// ------- - /// list(tuple(int,int,float)) : - /// list representation - pub fn into_array(&self) -> Vec<(i32, i32, f64)> { - self.entry.entry().to_vec() - } -} - -/// Register submodule in parent. -pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { - let m = PyModule::new_bound(parent_module.py(), "channel")?; - m.setattr(pyo3::intern!(m.py(), "__doc__"), "Channel interface.")?; - pyo3::py_run!( - parent_module.py(), - m, - "import sys; sys.modules['pineappl.channel'] = m" - ); - m.add_class::()?; - parent_module.add_submodule(&m) -} diff --git a/pineappl_py/src/evolution.rs b/pineappl_py/src/evolution.rs index 2835e8cf..28d1b8bd 100644 --- a/pineappl_py/src/evolution.rs +++ b/pineappl_py/src/evolution.rs @@ -1,29 +1,11 @@ //! Evolution interface. + +use super::pids::PyPidBasis; use numpy::{IntoPyArray, PyArray1}; use pineappl::evolution::{EvolveInfo, OperatorSliceInfo}; -use pineappl::pids::PidBasis; use pyo3::prelude::*; -/// PyO3 wrapper to :rustdoc:`pineappl::pids::PidBasis `. -#[pyclass(name = "PidBasis")] -#[derive(Clone)] -pub enum PyPidBasis { - /// PDG Monte Carlo IDs. - Pdg, - /// NNPDF's evolution basis IDs. - Evol, -} - -impl From for PidBasis { - fn from(basis: PyPidBasis) -> Self { - match basis { - PyPidBasis::Pdg => Self::Pdg, - PyPidBasis::Evol => Self::Evol, - } - } -} - /// PyO3 wrapper to :rustdoc:`pineappl::evolution::OperatorSliceInfo `. #[pyclass(name = "OperatorSliceInfo")] #[derive(Clone)] @@ -120,6 +102,5 @@ pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { ); m.add_class::()?; m.add_class::()?; - m.add_class::()?; parent_module.add_submodule(&m) } diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 2c485a5b..998cd729 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -1,12 +1,11 @@ //! Grid interface. use ndarray::CowArray; -use pineappl::boc::Order; use pineappl::convolutions::LumiCache; use pineappl::evolution::AlphasTable; use pineappl::grid::{Grid, Ntuple}; use super::bin::PyBinRemapper; -use super::channel::PyChannel; +use super::boc::{PyChannel, PyOrder}; use super::evolution::{PyEvolveInfo, PyOperatorSliceInfo}; use super::fk_table::PyFkTable; use super::subgrid::{PySubgridEnum, PySubgridParams}; @@ -23,90 +22,6 @@ use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use pyo3::types::PyIterator; -/// PyO3 wrapper to :rustdoc:`pineappl::boc::Order `. -#[pyclass(name = "Order")] -#[repr(transparent)] -pub struct PyOrder { - pub(crate) order: Order, -} - -impl PyOrder { - pub(crate) fn new(order: Order) -> Self { - Self { order } - } -} - -#[pymethods] -impl PyOrder { - /// Constructor. - /// - /// Parameters - /// ---------- - /// alphas : int - /// power of :math:`\alpha_s` - /// alpha : int - /// power of :math:`\alpha` - /// logxir : int - /// power of :math:`\ln(\xi_r)` - /// logxif : int - /// power of :math:`\ln(\xi_f)` - #[new] - pub fn new_order(alphas: u32, alpha: u32, logxir: u32, logxif: u32) -> Self { - Self::new(Order::new(alphas, alpha, logxir, logxif)) - } - - /// Tuple representation. - /// - /// Returns - /// ------- - /// alphas : int - /// power of :math:`\alpha_s` - /// alpha : int - /// power of :math:`\alpha` - /// logxir : int - /// power of :math:`\ln(\xi_r)` - /// logxif : int - /// power of :math:`\ln(\xi_f)` - pub fn as_tuple(&self) -> (u32, u32, u32, u32) { - ( - self.order.alphas, - self.order.alpha, - self.order.logxir, - self.order.logxif, - ) - } - - /// Return a mask suitable to pass as the `order_mask` parameter of [`Grid::convolve`]. - /// - /// The selection of `orders` is controlled using the `max_as` and `max_al` parameters, for - /// instance setting `max_as = 1` and `max_al = 0` selects the LO QCD only, `max_as = 2` and - /// `max_al = 0` the NLO QCD; setting `max_as = 3` and `max_al = 2` would select all NLOs, and - /// the NNLO QCD. - /// - /// See `pineappl` crate docs for more examples. - /// - /// Returns - /// ------- - /// numpy.ndarray(bool) - /// boolean array, to be used as orders' mask - #[staticmethod] - pub fn create_mask<'py>( - orders: Vec>, - max_as: u32, - max_al: u32, - logs: bool, - py: Python<'py>, - ) -> Bound<'py, PyArray1> { - Order::create_mask( - &orders.iter().map(|o| o.order.clone()).collect::>(), - max_as, - max_al, - logs, - ) - .into_pyarray_bound(py) - } -} - /// PyO3 wrapper to :rustdoc:`pineappl::grid::Grid `. #[pyclass(name = "Grid")] #[repr(transparent)] diff --git a/pineappl_py/src/lib.rs b/pineappl_py/src/lib.rs index 458382aa..0f10ee9b 100644 --- a/pineappl_py/src/lib.rs +++ b/pineappl_py/src/lib.rs @@ -4,11 +4,12 @@ use pyo3::prelude::*; pub mod bin; -pub mod channel; +pub mod boc; pub mod evolution; pub mod fk_table; pub mod grid; pub mod import_only_subgrid; +pub mod pids; pub mod subgrid; /// PyO3 Python module that contains all exposed classes from Rust. @@ -17,11 +18,12 @@ pub mod subgrid; #[pymodule] fn pineappl(m: &Bound<'_, PyModule>) -> PyResult<()> { bin::register(m)?; + boc::register(m)?; grid::register(m)?; import_only_subgrid::register(m)?; evolution::register(m)?; - channel::register(m)?; fk_table::register(m)?; + pids::register(m)?; subgrid::register(m)?; m.add("version", env!("CARGO_PKG_VERSION"))?; diff --git a/pineappl_py/tests/test_boc.py b/pineappl_py/tests/test_boc.py new file mode 100644 index 00000000..9b00171d --- /dev/null +++ b/pineappl_py/tests/test_boc.py @@ -0,0 +1,7 @@ +import pineappl + + +class TestChannel: + def test_init(self): + le = pineappl.boc.Channel([(2, 2, 0.5)]) + assert isinstance(le, pineappl.boc.Channel) diff --git a/pineappl_py/tests/test_channel.py b/pineappl_py/tests/test_channel.py deleted file mode 100644 index fd07df6b..00000000 --- a/pineappl_py/tests/test_channel.py +++ /dev/null @@ -1,7 +0,0 @@ -import pineappl - - -class TestChannel: - def test_init(self): - le = pineappl.channel.Channel([(2, 2, 0.5)]) - assert isinstance(le, pineappl.channel.Channel) diff --git a/pineappl_py/tests/test_fk_table.py b/pineappl_py/tests/test_fk_table.py index 97237c74..af047ed8 100644 --- a/pineappl_py/tests/test_fk_table.py +++ b/pineappl_py/tests/test_fk_table.py @@ -5,7 +5,7 @@ class TestFkTable: def fake_grid(self, bins=None): - channels = [pineappl.channel.Channel([(1, 21, 1.0)])] + channels = [pineappl.boc.Channel([(1, 21, 1.0)])] orders = [pineappl.grid.Order(0, 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() @@ -36,7 +36,7 @@ def test_convolve_with_one(self): ) info = pineappl.evolution.OperatorSliceInfo( - 1.0, [], [], 1.0, [], [], pineappl.evolution.PidBasis.Pdg + 1.0, [], [], 1.0, [], [], pineappl.pids.PidBasis.Pdg ) # TODO: write a better test diff --git a/pineappl_py/tests/test_grid.py b/pineappl_py/tests/test_grid.py index 8a60a068..f0678db9 100644 --- a/pineappl_py/tests/test_grid.py +++ b/pineappl_py/tests/test_grid.py @@ -15,7 +15,7 @@ def test_init(self): class TestGrid: def fake_grid(self, bins=None): - channels = [pineappl.channel.Channel([(1, 21, 0.1)])] + channels = [pineappl.boc.Channel([(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() diff --git a/pineappl_py/tests/test_sugrid.py b/pineappl_py/tests/test_sugrid.py index f4fedff2..91a0d423 100644 --- a/pineappl_py/tests/test_sugrid.py +++ b/pineappl_py/tests/test_sugrid.py @@ -11,7 +11,7 @@ def test_init(self): def test_issue_164(pdf): - channels = [pineappl.channel.Channel([(1, 2, 1.0)])] + channels = [pineappl.boc.Channel([(1, 2, 1.0)])] orders = [pineappl.grid.Order(0, 0, 0, 0)] params = pineappl.subgrid.SubgridParams() @@ -33,7 +33,7 @@ def convolve_grid(): class TestSubgrid: def fake_grid(self): - channels = [pineappl.channel.Channel([(1, 2, 1.0)])] + channels = [pineappl.boc.Channel([(1, 2, 1.0)])] orders = [pineappl.grid.Order(0, 0, 0, 0)] params = pineappl.subgrid.SubgridParams() bin_limits = np.array([0.0, 1.0]) From e3174cbce50eebcebf764e2ebb6c548f8c6ada79 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 15 Aug 2024 09:33:51 +0200 Subject: [PATCH 45/51] Remove comment --- pineappl_py/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/pineappl_py/src/lib.rs b/pineappl_py/src/lib.rs index 0f10ee9b..e6bf3185 100644 --- a/pineappl_py/src/lib.rs +++ b/pineappl_py/src/lib.rs @@ -13,8 +13,6 @@ pub mod pids; pub mod subgrid; /// PyO3 Python module that contains all exposed classes from Rust. -/// -/// NOTE: this name has to match the one in Cargo.toml 'lib.name' #[pymodule] fn pineappl(m: &Bound<'_, PyModule>) -> PyResult<()> { bin::register(m)?; From 803c460fbc6c469e1095c8db5afbcfaf2fd27ddd Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 15 Aug 2024 09:38:35 +0200 Subject: [PATCH 46/51] Add missing file `pineappl_py/src/pids.rs` --- pineappl_py/src/pids.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 pineappl_py/src/pids.rs diff --git a/pineappl_py/src/pids.rs b/pineappl_py/src/pids.rs new file mode 100644 index 00000000..81b3b67e --- /dev/null +++ b/pineappl_py/src/pids.rs @@ -0,0 +1,36 @@ +//! PIDs interface. + +use pineappl::pids::PidBasis; +use pyo3::prelude::*; + +/// PyO3 wrapper to :rustdoc:`pineappl::pids::PidBasis `. +#[pyclass(name = "PidBasis")] +#[derive(Clone)] +pub enum PyPidBasis { + /// PDG Monte Carlo IDs. + Pdg, + /// NNPDF's evolution basis IDs. + Evol, +} + +impl From for PidBasis { + fn from(basis: PyPidBasis) -> Self { + match basis { + PyPidBasis::Pdg => Self::Pdg, + PyPidBasis::Evol => Self::Evol, + } + } +} + +/// Register submodule in parent. +pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { + let m = PyModule::new_bound(parent_module.py(), "pids")?; + m.setattr(pyo3::intern!(m.py(), "__doc__"), "PIDs interface.")?; + pyo3::py_run!( + parent_module.py(), + m, + "import sys; sys.modules['pineappl.pids'] = m" + ); + m.add_class::()?; + parent_module.add_submodule(&m) +} From 011125b8509c5a4d3f8d61bae7b64fe9f9f608b9 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 15 Aug 2024 09:58:41 +0200 Subject: [PATCH 47/51] Remove boilerplate code --- pineappl_py/src/bin.rs | 12 ++++-------- pineappl_py/src/boc.rs | 12 ++++-------- pineappl_py/src/grid.rs | 24 +++++++++++------------- pineappl_py/src/subgrid.rs | 12 +++--------- 4 files changed, 22 insertions(+), 38 deletions(-) diff --git a/pineappl_py/src/bin.rs b/pineappl_py/src/bin.rs index 445b9428..76cd5b47 100644 --- a/pineappl_py/src/bin.rs +++ b/pineappl_py/src/bin.rs @@ -12,12 +12,6 @@ pub struct PyBinRemapper { pub(crate) bin_remapper: BinRemapper, } -impl PyBinRemapper { - pub(crate) fn new(bin_remapper: BinRemapper) -> Self { - Self { bin_remapper } - } -} - #[pymethods] impl PyBinRemapper { /// Constructor. @@ -29,8 +23,10 @@ impl PyBinRemapper { /// limits : list(tuple(float, float)) /// bin limits #[new] - pub fn new_f64(normalizations: PyReadonlyArray1, limits: Vec<(f64, f64)>) -> Self { - Self::new(BinRemapper::new(normalizations.to_vec().unwrap(), limits).unwrap()) + pub fn new(normalizations: PyReadonlyArray1, limits: Vec<(f64, f64)>) -> Self { + Self { + bin_remapper: BinRemapper::new(normalizations.to_vec().unwrap(), limits).unwrap(), + } } } diff --git a/pineappl_py/src/boc.rs b/pineappl_py/src/boc.rs index aadad461..124bd0c0 100644 --- a/pineappl_py/src/boc.rs +++ b/pineappl_py/src/boc.rs @@ -18,12 +18,6 @@ pub struct PyChannel { pub(crate) entry: Channel, } -impl PyChannel { - pub(crate) fn new(entry: Channel) -> Self { - Self { entry } - } -} - #[pymethods] impl PyChannel { /// Constructor. @@ -33,8 +27,10 @@ impl PyChannel { /// entry: list(tuple(int, int, float)) /// channel configuration #[new] - pub fn new_entry(entry: Vec<(i32, i32, f64)>) -> Self { - Self::new(Channel::new(entry)) + pub fn new(entry: Vec<(i32, i32, f64)>) -> Self { + Self { + entry: Channel::new(entry), + } } /// Get list representation. diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 998cd729..98314b07 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -30,12 +30,6 @@ pub struct PyGrid { pub(crate) grid: Grid, } -impl PyGrid { - pub(crate) fn new(grid: Grid) -> Self { - Self { grid } - } -} - #[pymethods] impl PyGrid { /// Constructor. @@ -57,12 +51,14 @@ impl PyGrid { bin_limits: PyReadonlyArray1, subgrid_params: PySubgridParams, ) -> Self { - Self::new(Grid::new( - channels.iter().map(|pyc| pyc.entry.clone()).collect(), - orders.iter().map(|pyo| pyo.order.clone()).collect(), - bin_limits.to_vec().unwrap(), - subgrid_params.subgrid_params, - )) + Self { + grid: Grid::new( + channels.iter().map(|pyc| pyc.entry.clone()).collect(), + orders.iter().map(|pyo| pyo.order.clone()).collect(), + bin_limits.to_vec().unwrap(), + subgrid_params.subgrid_params, + ), + } } /// Add a point to the grid. @@ -508,7 +504,9 @@ impl PyGrid { /// grid #[staticmethod] pub fn read(path: PathBuf) -> Self { - Self::new(Grid::read(BufReader::new(File::open(path).unwrap())).unwrap()) + Self { + grid: Grid::read(BufReader::new(File::open(path).unwrap())).unwrap(), + } } /// Write to file. diff --git a/pineappl_py/src/subgrid.rs b/pineappl_py/src/subgrid.rs index 13dda42b..d0290961 100644 --- a/pineappl_py/src/subgrid.rs +++ b/pineappl_py/src/subgrid.rs @@ -12,12 +12,6 @@ pub struct PySubgridParams { pub(crate) subgrid_params: SubgridParams, } -impl PySubgridParams { - pub(crate) fn new(subgrid_params: SubgridParams) -> Self { - Self { subgrid_params } - } -} - impl Clone for PySubgridParams { fn clone(&self) -> Self { let mut subgrid_params = SubgridParams::default(); @@ -39,9 +33,9 @@ impl PySubgridParams { /// Constructor using the defaults. #[new] pub fn default() -> Self { - let subgrid_params = SubgridParams::default(); - - Self::new(subgrid_params) + Self { + subgrid_params: SubgridParams::default(), + } } /// Set number of :math:`Q^2` bins. From 5e730567d6a6677d3c82cd103262612cc7fc8d37 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 15 Aug 2024 09:59:43 +0200 Subject: [PATCH 48/51] Reorder use statements --- pineappl_py/src/bin.rs | 2 +- pineappl_py/src/boc.rs | 1 - pineappl_py/src/evolution.rs | 1 - pineappl_py/src/fk_table.rs | 8 +++----- pineappl_py/src/grid.rs | 17 +++++++---------- pineappl_py/src/import_only_subgrid.rs | 2 +- pineappl_py/src/lib.rs | 1 + pineappl_py/src/subgrid.rs | 1 + 8 files changed, 14 insertions(+), 19 deletions(-) diff --git a/pineappl_py/src/bin.rs b/pineappl_py/src/bin.rs index 76cd5b47..17398e17 100644 --- a/pineappl_py/src/bin.rs +++ b/pineappl_py/src/bin.rs @@ -1,7 +1,7 @@ //! Binnning interface. -use pineappl::bin::BinRemapper; use numpy::{PyArrayMethods, PyReadonlyArray1}; +use pineappl::bin::BinRemapper; use pyo3::prelude::*; /// PyO3 wrapper to :rustdoc:`pineappl::bin::BinRemapper `. diff --git a/pineappl_py/src/boc.rs b/pineappl_py/src/boc.rs index 124bd0c0..343aa71b 100644 --- a/pineappl_py/src/boc.rs +++ b/pineappl_py/src/boc.rs @@ -2,7 +2,6 @@ use numpy::{IntoPyArray, PyArray1}; use pineappl::boc::{Channel, Order}; - use pyo3::prelude::*; /// PyO3 wrapper to :rustdoc:`pineappl::boc::Channel `. diff --git a/pineappl_py/src/evolution.rs b/pineappl_py/src/evolution.rs index 28d1b8bd..762ee7e2 100644 --- a/pineappl_py/src/evolution.rs +++ b/pineappl_py/src/evolution.rs @@ -3,7 +3,6 @@ use super::pids::PyPidBasis; use numpy::{IntoPyArray, PyArray1}; use pineappl::evolution::{EvolveInfo, OperatorSliceInfo}; - use pyo3::prelude::*; /// PyO3 wrapper to :rustdoc:`pineappl::evolution::OperatorSliceInfo `. diff --git a/pineappl_py/src/fk_table.rs b/pineappl_py/src/fk_table.rs index 08328dcd..33af7ffe 100644 --- a/pineappl_py/src/fk_table.rs +++ b/pineappl_py/src/fk_table.rs @@ -1,19 +1,17 @@ //! FK table interface. + +use super::grid::PyGrid; +use numpy::{IntoPyArray, PyArray1, PyArray4, PyArrayMethods, PyReadonlyArray1}; use pineappl::convolutions::LumiCache; use pineappl::fk_table::{FkAssumptions, FkTable}; use pineappl::grid::Grid; - -use numpy::{IntoPyArray, PyArray1, PyArray4, PyArrayMethods, PyReadonlyArray1}; use pyo3::prelude::*; - use std::collections::HashMap; use std::fs::File; use std::io::BufReader; use std::path::PathBuf; use std::str::FromStr; -use crate::grid::PyGrid; - /// PyO3 wrapper to :rustdoc:`pineappl::fk_table::FkTable `. #[pyclass(name = "FkTable")] #[repr(transparent)] diff --git a/pineappl_py/src/grid.rs b/pineappl_py/src/grid.rs index 98314b07..dbca4db7 100644 --- a/pineappl_py/src/grid.rs +++ b/pineappl_py/src/grid.rs @@ -1,27 +1,24 @@ //! Grid interface. -use ndarray::CowArray; -use pineappl::convolutions::LumiCache; -use pineappl::evolution::AlphasTable; -use pineappl::grid::{Grid, Ntuple}; use super::bin::PyBinRemapper; use super::boc::{PyChannel, PyOrder}; use super::evolution::{PyEvolveInfo, PyOperatorSliceInfo}; use super::fk_table::PyFkTable; use super::subgrid::{PySubgridEnum, PySubgridParams}; - use itertools::izip; +use ndarray::CowArray; use numpy::{IntoPyArray, PyArray1, PyArrayMethods, PyReadonlyArray1, PyReadonlyArray4}; - +use pineappl::convolutions::LumiCache; +use pineappl::evolution::AlphasTable; +use pineappl::grid::{Grid, Ntuple}; +use pyo3::exceptions::PyValueError; +use pyo3::prelude::*; +use pyo3::types::PyIterator; use std::collections::HashMap; use std::fs::File; use std::io::BufReader; use std::path::PathBuf; -use pyo3::exceptions::PyValueError; -use pyo3::prelude::*; -use pyo3::types::PyIterator; - /// PyO3 wrapper to :rustdoc:`pineappl::grid::Grid `. #[pyclass(name = "Grid")] #[repr(transparent)] diff --git a/pineappl_py/src/import_only_subgrid.rs b/pineappl_py/src/import_only_subgrid.rs index fa52b132..b58a006c 100644 --- a/pineappl_py/src/import_only_subgrid.rs +++ b/pineappl_py/src/import_only_subgrid.rs @@ -1,6 +1,6 @@ //! PyImportOnlySubgrid* interface. -use super::subgrid::PySubgridEnum; +use super::subgrid::PySubgridEnum; use numpy::{PyArrayMethods, PyReadonlyArray1, PyReadonlyArray3}; use pineappl::import_only_subgrid::ImportOnlySubgridV1; use pineappl::import_only_subgrid::ImportOnlySubgridV2; diff --git a/pineappl_py/src/lib.rs b/pineappl_py/src/lib.rs index e6bf3185..5c0c5e1d 100644 --- a/pineappl_py/src/lib.rs +++ b/pineappl_py/src/lib.rs @@ -1,4 +1,5 @@ //! Generate PyO3 interface. + #![allow(unsafe_op_in_unsafe_fn)] use pyo3::prelude::*; diff --git a/pineappl_py/src/subgrid.rs b/pineappl_py/src/subgrid.rs index d0290961..06e82eb2 100644 --- a/pineappl_py/src/subgrid.rs +++ b/pineappl_py/src/subgrid.rs @@ -1,4 +1,5 @@ //! Subgrid interface. + use ndarray::Array3; use numpy::{IntoPyArray, PyArray1, PyArray3}; use pineappl::subgrid::Mu2; From ad4395159c17056e53ca51bbd0764d62ce40282c Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 15 Aug 2024 10:01:31 +0200 Subject: [PATCH 49/51] Add missing `repr(transparent)` --- pineappl_py/src/evolution.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/pineappl_py/src/evolution.rs b/pineappl_py/src/evolution.rs index 762ee7e2..4a28a3de 100644 --- a/pineappl_py/src/evolution.rs +++ b/pineappl_py/src/evolution.rs @@ -8,6 +8,7 @@ use pyo3::prelude::*; /// PyO3 wrapper to :rustdoc:`pineappl::evolution::OperatorSliceInfo `. #[pyclass(name = "OperatorSliceInfo")] #[derive(Clone)] +#[repr(transparent)] pub struct PyOperatorSliceInfo { pub(crate) info: OperatorSliceInfo, } From 8ef229741373a9a49fb67883f69e228de8d5a66d Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 15 Aug 2024 10:03:28 +0200 Subject: [PATCH 50/51] Fix bug in `PySubgridParams::clone` --- pineappl_py/src/subgrid.rs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/pineappl_py/src/subgrid.rs b/pineappl_py/src/subgrid.rs index 06e82eb2..5eb89a78 100644 --- a/pineappl_py/src/subgrid.rs +++ b/pineappl_py/src/subgrid.rs @@ -8,27 +8,12 @@ use pyo3::prelude::*; /// PyO3 wrapper to :rustdoc:`pineappl::subgrid::SubgridParams ` #[pyclass(name = "SubgridParams")] +#[derive(Clone)] #[repr(transparent)] pub struct PySubgridParams { pub(crate) subgrid_params: SubgridParams, } -impl Clone for PySubgridParams { - fn clone(&self) -> Self { - let mut subgrid_params = SubgridParams::default(); - subgrid_params.set_q2_bins(self.subgrid_params.q2_bins()); - subgrid_params.set_q2_max(self.subgrid_params.q2_max()); - subgrid_params.set_q2_min(self.subgrid_params.q2_min()); - subgrid_params.set_q2_order(self.subgrid_params.q2_order()); - subgrid_params.set_reweight(self.subgrid_params.reweight()); - subgrid_params.set_x_bins(self.subgrid_params.x_bins()); - subgrid_params.set_x_max(self.subgrid_params.x_max()); - subgrid_params.set_x_min(self.subgrid_params.x_min()); - subgrid_params.set_x_order(self.subgrid_params.x_order()); - Self { subgrid_params } - } -} - #[pymethods] impl PySubgridParams { /// Constructor using the defaults. From 73868e969f778e19357ee4be09325b6562ac7db0 Mon Sep 17 00:00:00 2001 From: Christopher Schwan Date: Thu, 15 Aug 2024 11:08:09 +0200 Subject: [PATCH 51/51] Fix `CHANGELOG.md` Co-authored-by: Felix Hekhorn --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 538f63d4..c244fc1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Python API: dropped top-level Python interface layer - Python API: renamed `lumi` to `channel` in PyO3 Python interface. This concerns 1) the argument names of `convolute_with_one` and similar functions; - 2) the module `pineappl.lumi` was moved to `pineappl.channel`; 3) the class + 2) the module `pineappl.lumi` was moved to `pineappl.boc`; 3) the class `LumiEntry` was renamed to `Channel` - Python API: `.into()` needs to be explicitly called on subgrids when calling `pineappl.grid.set_subgrid()`