From 3e2d12a4ff0a1013ce33cd07b193a2c52c9e4939 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Tue, 1 Aug 2023 17:06:34 +0200 Subject: [PATCH] Drop Bases --- src/eko/io/bases.py | 117 ---------------------------------- src/eko/io/metadata.py | 8 +-- src/eko/io/struct.py | 12 +--- src/ekobox/apply.py | 12 ++-- tests/eko/io/test_bases.py | 83 ------------------------ tests/eko/io/test_metadata.py | 6 +- tests/eko/io/test_runcards.py | 1 - tests/eko/runner/__init__.py | 10 +-- tests/eko/runner/conftest.py | 3 +- tests/ekobox/test_apply.py | 11 ++-- 10 files changed, 27 insertions(+), 236 deletions(-) delete mode 100644 src/eko/io/bases.py delete mode 100644 tests/eko/io/test_bases.py diff --git a/src/eko/io/bases.py b/src/eko/io/bases.py deleted file mode 100644 index 97a28dc36..000000000 --- a/src/eko/io/bases.py +++ /dev/null @@ -1,117 +0,0 @@ -"""Operators bases.""" -from dataclasses import dataclass, fields -from typing import Optional - -import numpy as np -import numpy.typing as npt - -from .. import basis_rotation as br -from .. import interpolation -from .dictlike import DictLike - - -@dataclass -class Bases(DictLike): - """Rotations related configurations. - - Here "Rotation" is intended in a broad sense: it includes both rotations in - flavor space (labeled with suffix `pids`) and in :math:`x`-space (labeled - with suffix `grid`). - Rotations in :math:`x`-space correspond to reinterpolate the result on a - different basis of polynomials. - - """ - - xgrid: interpolation.XGrid - """Internal momentum fraction grid.""" - _targetgrid: Optional[interpolation.XGrid] = None - _inputgrid: Optional[interpolation.XGrid] = None - _targetpids: Optional[npt.NDArray] = None - _inputpids: Optional[npt.NDArray] = None - - def __post_init__(self): - """Adjust types when loaded from serialized object.""" - for attr in ("xgrid", "_inputgrid", "_targetgrid"): - value = getattr(self, attr) - if value is None: - continue - if isinstance(value, (np.ndarray, list)): - setattr(self, attr, interpolation.XGrid(value)) - elif not isinstance(value, interpolation.XGrid): - setattr(self, attr, interpolation.XGrid.load(value)) - - @property - def pids(self): - """Internal flavor basis, used for computation.""" - return np.array(br.flavor_basis_pids) - - @property - def inputpids(self) -> npt.NDArray: - """Provide pids expected on the input PDF.""" - if self._inputpids is None: - return self.pids - return self._inputpids - - @inputpids.setter - def inputpids(self, value): - self._inputpids = value - - @property - def targetpids(self) -> npt.NDArray: - """Provide pids corresponding to the output PDF.""" - if self._targetpids is None: - return self.pids - return self._targetpids - - @targetpids.setter - def targetpids(self, value): - self._targetpids = value - - @property - def inputgrid(self) -> interpolation.XGrid: - """Provide :math:`x`-grid expected on the input PDF.""" - if self._inputgrid is None: - return self.xgrid - return self._inputgrid - - @inputgrid.setter - def inputgrid(self, value: interpolation.XGrid): - self._inputgrid = value - - @property - def targetgrid(self) -> interpolation.XGrid: - """Provide :math:`x`-grid corresponding to the output PDF.""" - if self._targetgrid is None: - return self.xgrid - return self._targetgrid - - @targetgrid.setter - def targetgrid(self, value: interpolation.XGrid): - self._targetgrid = value - - @classmethod - def from_dict(cls, dictionary: dict): - """Deserialize rotation. - - Load from full state, but with public names. - - """ - d = dictionary.copy() - for f in fields(cls): - if f.name.startswith("_"): - d[f.name] = d.pop(f.name[1:]) - return cls._from_dict(d) - - @property - def raw(self): - """Serialize rotation. - - Pass through interfaces, access internal values but with a public name. - - """ - d = self._raw() - for key in d.copy(): - if key.startswith("_"): - d[key[1:]] = d.pop(key) - - return d diff --git a/src/eko/io/metadata.py b/src/eko/io/metadata.py index 415b2dfa5..00f189ab4 100644 --- a/src/eko/io/metadata.py +++ b/src/eko/io/metadata.py @@ -8,7 +8,7 @@ import yaml from .. import version as vmod -from .bases import Bases +from ..interpolation import XGrid from .dictlike import DictLike from .paths import InternalPaths from .types import EvolutionPoint as EPoint @@ -34,10 +34,8 @@ class Metadata(DictLike): origin: EPoint """Inital scale.""" - bases: Bases - """Manipulation information, describing the current status of the EKO (e.g. - `inputgrid` and `targetgrid`). - """ + xgrid: XGrid + """Interpolation grid""" # tagging information _path: Optional[pathlib.Path] = None """Path to temporary dir.""" diff --git a/src/eko/io/struct.py b/src/eko/io/struct.py index fecba3c57..dbbb231f9 100644 --- a/src/eko/io/struct.py +++ b/src/eko/io/struct.py @@ -16,7 +16,6 @@ from .. import interpolation from . import exceptions, raw from .access import AccessConfigs -from .bases import Bases from .inventory import Inventory from .items import Evolution, Matching, Operator, Recipe, Target from .metadata import Metadata @@ -105,20 +104,15 @@ def paths(self) -> InternalPaths: """Accessor for internal paths.""" return InternalPaths(self.metadata.path) - @property - def bases(self) -> Bases: - """Bases information.""" - return self.metadata.bases - @property def xgrid(self) -> interpolation.XGrid: """Momentum fraction internal grid.""" - return self.bases.xgrid + return self.metadata.xgrid @xgrid.setter def xgrid(self, value: interpolation.XGrid): """Set `xgrid` value.""" - self.bases.xgrid = value + self.metadata.xgrid = value self.update() @property @@ -551,7 +545,7 @@ def build(self) -> EKO: metadata = Metadata( _path=self.path, origin=(self.operator.mu20, self.theory.heavy.num_flavs_init), - bases=Bases(xgrid=self.operator.xgrid), + xgrid=self.operator.xgrid, ) InternalPaths(self.path).bootstrap( theory=self.theory.raw, diff --git a/src/ekobox/apply.py b/src/ekobox/apply.py index c392ffe78..5722a6ad6 100644 --- a/src/ekobox/apply.py +++ b/src/ekobox/apply.py @@ -74,12 +74,12 @@ def apply_pdf_flavor( output PDFs and their associated errors for the computed mu2grid """ # create pdfs - pdfs = np.zeros((len(eko.bases.inputpids), len(eko.bases.inputgrid))) - for j, pid in enumerate(eko.bases.inputpids): + pdfs = np.zeros((len(br.flavor_basis_pids), len(eko.xgrid))) + for j, pid in enumerate(br.flavor_basis_pids): if not lhapdf_like.hasFlavor(pid): continue pdfs[j] = np.array( - [lhapdf_like.xfxQ2(pid, x, eko.mu20) / x for x in eko.bases.inputgrid.raw] + [lhapdf_like.xfxQ2(pid, x, eko.mu20) / x for x in eko.xgrid.raw] ) # build output @@ -91,11 +91,11 @@ def apply_pdf_flavor( else: error_final = None out_grid[ep] = { - "pdfs": dict(zip(eko.bases.targetpids, pdf_final)), + "pdfs": dict(zip(br.flavor_basis_pids, pdf_final)), "errors": None, } if error_final is not None: - out_grid[ep]["errors"] = dict(zip(eko.bases.targetpids, error_final)) + out_grid[ep]["errors"] = dict(zip(br.flavor_basis_pids, error_final)) # rotate to evolution basis if flavor_rotation is not None: @@ -117,7 +117,7 @@ def apply_pdf_flavor( # rotate/interpolate to target grid if targetgrid is not None: b = interpolation.InterpolatorDispatcher( - xgrid=eko.bases.targetgrid, + xgrid=eko.xgrid, polynomial_degree=eko.operator_card.configs.interpolation_polynomial_degree, mode_N=False, ) diff --git a/tests/eko/io/test_bases.py b/tests/eko/io/test_bases.py deleted file mode 100644 index a0165243f..000000000 --- a/tests/eko/io/test_bases.py +++ /dev/null @@ -1,83 +0,0 @@ -from dataclasses import fields - -import numpy as np - -from eko import basis_rotation as br -from eko import interpolation -from eko.io.bases import Bases - - -class TestBases: - XGRID_TEST = [1e-3, 1e-2, 1e-1, 1.0] - - def test_serialization(self): - rot = Bases(interpolation.XGrid(self.XGRID_TEST)) - - d = rot.raw - rot1 = rot.from_dict(d) - - for f in fields(Bases): - assert getattr(rot, f.name) == getattr(rot1, f.name) - - assert d["targetgrid"] is None - assert "_targetgrid" not in d - - def test_pids(self): - rot = Bases(interpolation.XGrid(self.XGRID_TEST)) - - # no check on correctness of value set - rot.inputpids = [0, 1] - # but the internal grid is unmodified - assert len(rot.pids) == 14 - # and fallback implemented for unset external bases - assert np.all(rot.targetpids == rot.pids) - - def test_grids(self): - rot = Bases(interpolation.XGrid(self.XGRID_TEST)) - - # no check on correctness of value set - rot.inputgrid = interpolation.XGrid([0.1, 1]) - # but the internal grid is unmodified - assert len(rot.xgrid) == len(self.XGRID_TEST) - # and fallback implemented for unset external grids - assert np.all(rot.targetgrid == rot.xgrid) - - def test_fallback(self): - xg = interpolation.XGrid([0.1, 1.0]) - r = Bases(xgrid=xg) - np.testing.assert_allclose(r.targetpids, r.pids) - np.testing.assert_allclose(r.inputpids, r.pids) - assert r.xgrid == xg - assert r.targetgrid == xg - assert r.inputgrid == xg - - def test_overwrite(self): - tpids = np.array([3, 4] + list(br.flavor_basis_pids[2:])) - ipids = np.array([5, 6] + list(br.flavor_basis_pids[2:])) - xg = interpolation.XGrid([0.1, 1.0]) - txg = interpolation.XGrid([0.2, 1.0]) - ixg = interpolation.XGrid([0.3, 1.0]) - r = Bases( - xgrid=xg, - _targetgrid=txg, - _inputgrid=ixg, - _targetpids=tpids, - _inputpids=ipids, - ) - np.testing.assert_allclose(r.targetpids, tpids) - np.testing.assert_allclose(r.inputpids, ipids) - assert r.xgrid == xg - assert r.targetgrid == txg - assert r.inputgrid == ixg - - def test_init(self): - xg = interpolation.XGrid([0.1, 1.0]) - txg = np.array([0.2, 1.0]) - ixg = {"grid": [0.3, 1.0], "log": True} - r = Bases(xgrid=xg, _targetgrid=txg, _inputgrid=ixg) - assert isinstance(r.xgrid, interpolation.XGrid) - assert isinstance(r.targetgrid, interpolation.XGrid) - assert isinstance(r.inputgrid, interpolation.XGrid) - assert r.xgrid == xg - assert r.targetgrid == interpolation.XGrid(txg) - assert r.inputgrid == interpolation.XGrid.load(ixg) diff --git a/tests/eko/io/test_metadata.py b/tests/eko/io/test_metadata.py index a5651e0c8..fcfa8dd09 100644 --- a/tests/eko/io/test_metadata.py +++ b/tests/eko/io/test_metadata.py @@ -3,11 +3,11 @@ import pytest import yaml -from eko.io import bases, metadata, paths +from eko.io import metadata, paths def test_metadata(tmp_path, caplog): - m = metadata.Metadata((1.0, 3), bases.Bases([0.1, 1.0])) + m = metadata.Metadata(origin=(1.0, 3), xgrid=[0.1, 1.0]) # errors with caplog.at_level(logging.INFO): m.update() @@ -26,7 +26,7 @@ def test_metadata(tmp_path, caplog): m.version = "0.0.0-a1~really1.0.0" m.update() # if I read back the thing should be what I set - mn = metadata.Metadata((1.0, 3), bases.Bases([0.1, 1.0])) + mn = metadata.Metadata(origin=(1.0, 3), xgrid=[0.1, 1.0]) mm = metadata.Metadata.load(tmp_path) assert m.path == tmp_path assert mm.version != mn.version diff --git a/tests/eko/io/test_runcards.py b/tests/eko/io/test_runcards.py index 6af37edcb..4b4996336 100644 --- a/tests/eko/io/test_runcards.py +++ b/tests/eko/io/test_runcards.py @@ -7,7 +7,6 @@ from banana.data.theories import default_card as theory_card from eko.io import runcards as rc -from eko.io.bases import Bases from ekomark.data.operators import default_card as operator_card diff --git a/tests/eko/runner/__init__.py b/tests/eko/runner/__init__.py index c8ec5b854..0e3ea68c0 100644 --- a/tests/eko/runner/__init__.py +++ b/tests/eko/runner/__init__.py @@ -1,19 +1,21 @@ import numpy as np +from eko import basis_rotation as br + def check_shapes(o, txs, ixs, theory_card, operators_card): - tpids = len(o.bases.targetpids) - ipids = len(o.bases.inputpids) + tpids = len(br.flavor_basis_pids) + ipids = len(br.flavor_basis_pids) op_shape = (tpids, len(txs), ipids, len(ixs)) # check output = input np.testing.assert_allclose(o.xgrid.raw, operators_card.xgrid.raw) # targetgrid and inputgrid in the opcard are now ignored, we are testing this np.testing.assert_allclose( - o.bases.targetgrid.raw, + o.xgrid.raw, txs.raw, ) - np.testing.assert_allclose(o.bases.inputgrid.raw, ixs.raw) + np.testing.assert_allclose(o.xgrid.raw, ixs.raw) np.testing.assert_allclose(o.mu20, operators_card.mu20) # check available operators ~o.operators diff --git a/tests/eko/runner/conftest.py b/tests/eko/runner/conftest.py index a1516b2a7..a2966c5e9 100644 --- a/tests/eko/runner/conftest.py +++ b/tests/eko/runner/conftest.py @@ -4,6 +4,7 @@ import pytest from eko import EKO +from eko import basis_rotation as br from eko.io.items import Operator from eko.io.runcards import OperatorCard, TheoryCard from eko.runner import commons, recipes @@ -21,7 +22,7 @@ def neweko(theory_card: TheoryCard, operator_card: OperatorCard, tmp_path: Path) @pytest.fixture def identity(neweko: EKO): xs = len(neweko.xgrid.raw) - flavs = len(neweko.bases.pids) + flavs = len(br.flavor_basis_pids) return Operator(operator=np.eye(xs * flavs).reshape((xs, flavs, xs, flavs))) diff --git a/tests/ekobox/test_apply.py b/tests/ekobox/test_apply.py index 8fa23548f..70eb74adc 100644 --- a/tests/ekobox/test_apply.py +++ b/tests/ekobox/test_apply.py @@ -1,5 +1,6 @@ import numpy as np +from eko import basis_rotation as br from ekobox import apply from tests.conftest import EKOFactory @@ -12,13 +13,13 @@ def test_apply(self, eko_factory: EKOFactory, fake_pdf): pdf_grid = apply.apply_pdf(eko, fake_pdf) assert len(pdf_grid) == len(eko.evolgrid) pdfs = pdf_grid[ep_out]["pdfs"] - assert list(pdfs.keys()) == list(eko.bases.targetpids) + assert list(pdfs.keys()) == list(br.flavor_basis_pids) # rotate to target_grid target_grid = [0.75] pdf_grid = apply.apply_pdf(eko, fake_pdf, target_grid) assert len(pdf_grid) == 1 pdfs = pdf_grid[ep_out]["pdfs"] - assert list(pdfs.keys()) == list(eko.bases.targetpids) + assert list(pdfs.keys()) == list(br.flavor_basis_pids) def test_apply_flavor(self, eko_factory: EKOFactory, fake_pdf, monkeypatch): eko = eko_factory.get() @@ -27,12 +28,8 @@ def test_apply_flavor(self, eko_factory: EKOFactory, fake_pdf, monkeypatch): monkeypatch.setattr( "eko.basis_rotation.rotate_flavor_to_evolution", np.ones((14, 14)) ) - monkeypatch.setattr( - "eko.basis_rotation.flavor_basis_pids", - eko.bases.targetpids, - ) fake_evol_basis = tuple( - ["a", "b"] + [str(x) for x in range(len(eko.bases.pids) - 2)] + ["a", "b"] + [str(x) for x in range(len(br.flavor_basis_pids) - 2)] ) monkeypatch.setattr("eko.basis_rotation.evol_basis", fake_evol_basis) pdf_grid = apply.apply_pdf(eko, fake_pdf, rotate_to_evolution_basis=True)