Skip to content

Commit

Permalink
Complete most tests
Browse files Browse the repository at this point in the history
  • Loading branch information
felixhekhorn committed Jul 29, 2022
1 parent bc89ac6 commit f8eb456
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 36 deletions.
7 changes: 4 additions & 3 deletions src/eko/compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def update(theory: dict, operators: Optional[dict]):
if "alphaqed" in new_theory:
new_theory["alphaem"] = new_theory.pop("alphaqed")
if "QED" in new_theory:
new_theory["order"] = (new_theory.pop("PTO") + 1, new_theory.pop("QED"))
new_theory["order"] = [new_theory.pop("PTO") + 1, new_theory.pop("QED")]

if operators is not None and "configs" not in operators:
new_operators["configs"] = {}
Expand All @@ -51,14 +51,15 @@ def update(theory: dict, operators: Optional[dict]):

max_order = operators["ev_op_max_order"]
if isinstance(max_order, int):
new_operators["configs"]["ev_op_max_order"] = (
new_operators["configs"]["ev_op_max_order"] = [
max_order,
new_theory["order"][1],
)
]

new_operators["rotations"]["xgrid"] = operators["interpolation_xgrid"]
for basis in ("inputgrid", "targetgrid", "inputpids", "targetpids"):
new_operators["rotations"][f"{basis}"] = operators[basis]
new_operators["Q0"] = new_theory["Q0"]

return new_theory, new_operators

Expand Down
33 changes: 10 additions & 23 deletions src/eko/output/struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,13 +363,11 @@ def __post_init__(self):
"""Validate class members."""
if self.path.suffix != ".tar":
raise ValueError("Not a valid path for an EKO")
if not tarfile.is_tarfile(self.path):
raise ValueError("EKO: the corresponding file is not a valid tar archive")

@staticmethod
def opname(q2: float) -> str:
"""Operator file name from :math:`Q^2` value."""
return f"operators/{q2:8.2f}"
return f"{OPERATORSDIR}/{q2:8.2f}"

def __getitem__(self, q2: float) -> Operator:
"""Retrieve operator for given :math:`Q^2`.
Expand All @@ -379,7 +377,7 @@ def __getitem__(self, q2: float) -> Operator:
Parameters
----------
q2: float
q2 : float
:math:`Q^2` value labeling the operator to be retrieved
Returns
Expand All @@ -388,9 +386,10 @@ def __getitem__(self, q2: float) -> Operator:
the retrieved operator
"""
op = self._operators[q2]
if op is not None:
return op
if q2 in self._operators:
op = self._operators[q2]
if op is not None:
return op

with tarfile.open(self.path) as tar:
names = list(
Expand All @@ -399,18 +398,11 @@ def __getitem__(self, q2: float) -> Operator:

if len(names) == 0:
raise ValueError(f"Q2 value '{q2}' not available in '{self.path}'")
if len(names) > 1:
raise ValueError(
f"Q2 value '{q2}' occurs multiple times in '{self.path}'"
)

name = names[0]
compressed = name.endswith(".lz4")
stream = tar.extractfile(name)

if stream is None:
raise ValueError

op = Operator.load(stream, compressed=compressed)

self._operators[q2] = op
Expand Down Expand Up @@ -686,10 +678,6 @@ def extract(path: os.PathLike, filename: str) -> str:

with tarfile.open(path, "r") as tar:
fd = tar.extractfile(filename)
if fd is None:
raise ValueError(
f"The member '{filename}' is not a readable file inside EKO tar"
)
content = fd.read().decode()

return content
Expand Down Expand Up @@ -763,6 +751,9 @@ def detached(cls, theory: dict, operator: dict, path: pathlib.Path):
"""
bases = operator["rotations"]
for basis in ("inputgrid", "targetgrid", "inputpids", "targetpids"):
bases[f"_{basis}"] = bases[basis]
del bases[basis]
bases["pids"] = np.array(br.flavor_basis_pids)
for k in ("xgrid", "_inputgrid", "_targetgrid"):
if operator["rotations"][k] is None:
Expand Down Expand Up @@ -834,10 +825,6 @@ def new(cls, theory: dict, operator: dict, path: Optional[os.PathLike] = None):

shutil.rmtree(td)

for basis in ("inputgrid", "targetgrid", "inputpids", "targetpids"):
operator["rotations"][f"_{basis}"] = operator["rotations"][basis]
del operator["rotations"][basis]

eko = cls.detached(theory, operator, path=path)
logger.info(f"New operator created at path '{path}'")
return eko
Expand Down Expand Up @@ -882,7 +869,7 @@ def raw(self) -> dict:
return dict(
path=str(self.path),
Q0=float(np.sqrt(self.Q02)),
Q2grid=self.Q2grid,
Q2grid=self.Q2grid.tolist(),
configs=self.configs.raw,
rotations=self.rotations.raw,
debug=self.debug.raw,
Expand Down
4 changes: 1 addition & 3 deletions src/eko/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,7 @@ def __init__(self, theory_card: dict, operators_card: dict):
self.post_process[key] = rot.get(key, None)
new_operators["rotations"][key] = None

self.out = EKO.new(
theory=theory_card, operator=dict(Q0=np.sqrt(tc.q2_ref), **new_operators)
)
self.out = EKO.new(theory=theory_card, operator=new_operators)

def get_output(self) -> EKO:
"""Run evolution and generate output operator.
Expand Down
7 changes: 1 addition & 6 deletions tests/eko/test_compatibility.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
# -*- coding: utf-8 -*-
from eko import compatibility

theory1 = {
"alphas": 0.1180,
"alphaqed": 0.007496,
"PTO": 2,
"QED": 0,
}
theory1 = {"alphas": 0.1180, "alphaqed": 0.007496, "PTO": 2, "QED": 0, "Q0": 1.0}


def test_compatibility():
Expand Down
124 changes: 123 additions & 1 deletion tests/eko/test_output_struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import pytest
import yaml

from eko import interpolation, output
from eko import compatibility, interpolation, output
from eko.output import struct
from ekobox import operators_card as oc
from ekobox import theory_card as tc


@dataclass
Expand Down Expand Up @@ -125,6 +127,126 @@ def test_init(self):
assert r.inputgrid == interpolation.XGrid.load(ixg)


class TestEKO:
def _default_cards(self):
t = tc.generate(0, 1.0)
o = oc.generate([10.0])
return compatibility.update(t, o)

def test_new_error(self, tmp_path):
nt, no = self._default_cards()
# try to write to a file different from bla
no_tar_path = tmp_path / "Blub.bla"
with pytest.raises(ValueError):
struct.EKO.new(nt, no, no_tar_path)
# try to overwrite an existing file
exists_path = tmp_path / "Blub.tar"
exists_path.write_text("Blub", encoding="utf-8")
with pytest.raises(FileExistsError):
struct.EKO.new(nt, no, exists_path)

def test_load_error(self, tmp_path):
# try to read from a non-tar path
no_tar_path = tmp_path / "Blub.tar"
no_tar_path.write_text("Blub", encoding="utf-8")
with pytest.raises(ValueError):
struct.EKO.load(no_tar_path)

def test_properties(self):
eko = struct.EKO.new(*self._default_cards())
assert "mc" in eko.theory_card
assert "debug" in eko.operator_card
np.testing.assert_allclose(eko.Q2grid, np.array([10.0]))
assert 10.0 in eko
default_grid = interpolation.XGrid(eko.operator_card["rotations"]["xgrid"])
assert eko.xgrid == default_grid
for use_target in (True, False):
assert eko.interpolator(False, use_target).xgrid == default_grid
xg = interpolation.XGrid([0.1, 1.0])
eko.xgrid = xg
assert eko.xgrid == xg
assert "debug" in eko.raw
# check we can dump and reload
stream = io.StringIO()
yaml.safe_dump(eko.raw, stream)
stream.seek(0)
raw_eko = yaml.safe_load(stream)
assert "debug" in raw_eko

def test_ops(self):
v = np.random.rand(2, 2)
opv = struct.Operator(operator=v)
eko = struct.EKO.new(*self._default_cards())
# try setting not an operator
with pytest.raises(ValueError):
eko[10.0] = "bla"
# approx
eko[10.0] = opv
assert eko.approx(20.0) is None
assert eko.approx(11.0, atol=2) == 10.0
eko[11.0] = opv
with pytest.raises(ValueError):
eko.approx(10.5, atol=2)
# iterate
for q2, q2eko in zip((10.0, 11.0), eko):
assert q2 == q2eko
np.testing.assert_allclose(v, eko[q2].operator)
for q2, (q2eko, op) in zip((10.0, 11.0), eko.items()):
assert q2 == q2eko
np.testing.assert_allclose(v, op.operator)
# getter
with pytest.raises(ValueError):
eko[12.0]
with eko.operator(10.0) as op:
np.testing.assert_allclose(v, op.operator)
# overwrite
vv = np.random.rand(2, 2)
opvv = struct.Operator(operator=vv)
eko[11.0] = opvv
np.testing.assert_allclose(vv, eko[11.0].operator)

def test_interpolator(self):
nt, no = self._default_cards()
txg = np.geomspace(0.1, 1.0, 5)
ixg = np.geomspace(0.01, 1.0, 5)
no["rotations"]["targetgrid"] = txg
no["rotations"]["inputgrid"] = ixg
eko = struct.EKO.new(nt, no)
assert eko.interpolator(False, True).xgrid == interpolation.XGrid(txg)
assert eko.interpolator(False, False).xgrid == interpolation.XGrid(ixg)

def test_copy(self, tmp_path):
v = np.random.rand(2, 2)
opv = struct.Operator(operator=v)
eko1 = struct.EKO.new(*self._default_cards())
eko1[10.0] = opv
np.testing.assert_allclose(eko1[10.0].operator, v)
p = tmp_path / "eko2.tar"
eko2 = eko1.deepcopy(p)
np.testing.assert_allclose(eko1[10.0].operator, v)
np.testing.assert_allclose(eko2[10.0].operator, v)
vv = np.random.rand(2, 2)
opvv = struct.Operator(operator=vv)
eko2[10.0] = opvv
np.testing.assert_allclose(eko1[10.0].operator, v)
np.testing.assert_allclose(eko2[10.0].operator, vv)
# try loading again
eko2_ = struct.EKO.load(p)
assert eko2.raw == eko2_.raw

def test_extract(self, tmp_path):
p = tmp_path / "test.tar"
eko = struct.EKO.new(*self._default_cards(), p)
# check theory file
t = struct.EKO.extract(p, struct.THEORYFILE)
assert isinstance(t, str)
tt = yaml.safe_load(io.StringIO(t))
assert tt == eko.theory_card
# try a wrong file
with pytest.raises(KeyError):
t = struct.EKO.extract(p, "Blub.bla")


class TestLegacy:
def test_items(self, fake_output):
"""Test autodump, autoload, and manual unload."""
Expand Down
1 change: 1 addition & 0 deletions tests/eko/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
}
operators_card = {
"Q2grid": [10, 100],
"Q0": np.sqrt(2),
"configs": {
"interpolation_polynomial_degree": 1,
"interpolation_is_log": True,
Expand Down

0 comments on commit f8eb456

Please sign in to comment.