diff --git a/benchmarks/ekobox/benchmark_evol_pdf.py b/benchmarks/ekobox/benchmark_evol_pdf.py index 90f3e776b..141e2e9cb 100644 --- a/benchmarks/ekobox/benchmark_evol_pdf.py +++ b/benchmarks/ekobox/benchmark_evol_pdf.py @@ -1,18 +1,17 @@ # -*- coding: utf-8 -*- import pathlib -import lhapdf import numpy as np import pytest -import eko.output.legacy from eko import basis_rotation as br from ekobox import evol_pdf as ev_p -from ekobox import gen_op as g_o -from ekobox import gen_theory as g_t +from ekobox import operators_card as oc +from ekobox import theory_card as tc from ekobox.genpdf import load test_pdf = pathlib.Path(__file__).parent / "fakepdf" +lhapdf = pytest.importorskip("lhapdf") @pytest.mark.isolated @@ -22,8 +21,8 @@ def benchmark_evolve_single_member(tmp_path, cd, lhapdf_path): 100.0, 10000.0, ] - op = g_o.gen_op_card(q2grid) - theory = g_t.gen_theory_card( + op = oc.generate(q2grid) + theory = tc.generate( 0, 5.0, update={ @@ -78,8 +77,8 @@ def benchmark_evolve_single_member(tmp_path, cd, lhapdf_path): @pytest.mark.isolated def benchmark_evolve_more_members(tmp_path, cd, lhapdf_path): - op = g_o.gen_op_card([10, 100], update={"xgrid": [1e-7, 0.01, 0.1, 0.2, 0.3]}) - theory = g_t.gen_theory_card(0, 1.0) + op = oc.generate([10, 100], update={"xgrid": [1e-7, 0.01, 0.1, 0.2, 0.3]}) + theory = tc.generate(0, 1.0) with lhapdf_path(test_pdf): pdfs = lhapdf.mkPDFs("myMSTW2008nlo90cl") d = tmp_path / "sub" @@ -91,21 +90,3 @@ def benchmark_evolve_more_members(tmp_path, cd, lhapdf_path): _ = lhapdf.mkPDFs("Debug") info = load.load_info_from_file("Debug") assert info["XMin"] == op["xgrid"][0] - - -@pytest.mark.isolated -def benchmark_gen_and_dump_out(tmp_path): - op = g_o.gen_op_card([100.0], update={"xgrid": [1e-7, 0.01, 0.1, 0.2, 0.3]}) - theory = g_t.gen_theory_card(0, 1.0) - - out = ev_p.gen_out(theory, op, path=tmp_path) - - ops_id = f"o{op['hash'][:6]}_t{theory['hash'][:6]}" - outpath = f"{tmp_path}/{ops_id}.tar" - loaded_out = eko.output.legacy.load_tar(outpath) - assert list(out.xgrid) == list(loaded_out.xgrid) - for el, load_el in zip(out[100.0].operator, loaded_out[100.0].operator): - np.testing.assert_allclose( - out[100.0].operator, - loaded_out[100.0].operator, - ) diff --git a/benchmarks/ekobox/benchmark_gen_theory.py b/benchmarks/ekobox/benchmark_gen_theory.py deleted file mode 100644 index 07320fa5e..000000000 --- a/benchmarks/ekobox/benchmark_gen_theory.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -import pytest - -from ekobox import gen_theory as g_t - - -@pytest.mark.isolated -def benchmark_gen_theory_card(): - theory = g_t.gen_theory_card(0, 1.0) - assert theory["PTO"] == 0 - assert theory["Q0"] == 1.0 - assert theory["mt"] == 173.07 - up_err = {"Prova": "Prova"} - with pytest.raises(ValueError): - theory = g_t.gen_theory_card(0, 1.0, update=up_err) - up = {"mb": 132.3, "PTO": 2} - theory = g_t.gen_theory_card(0, 1.0, update=up) - assert theory["PTO"] == 2 - assert theory["mb"] == 132.3 - - -@pytest.mark.isolated -def benchmark_export_load_theory_card(tmp_path, cd): - with cd(tmp_path): - theory = g_t.gen_theory_card(2, 12.3, name="debug_theory") - g_t.export_theory_card("debug_theory_two", theory) - theory_loaded = g_t.import_theory_card("debug_theory.yaml") - theory_two_loaded = g_t.import_theory_card("debug_theory_two.yaml") - for key in theory.keys(): - assert theory[key] == theory_loaded[key] == theory_two_loaded[key] diff --git a/benchmarks/ekobox/genpdf/benchmark_flavors.py b/benchmarks/ekobox/genpdf/benchmark_flavors.py index 010dc7408..9dc6913f5 100644 --- a/benchmarks/ekobox/genpdf/benchmark_flavors.py +++ b/benchmarks/ekobox/genpdf/benchmark_flavors.py @@ -13,38 +13,6 @@ lhapdf = pytest.importorskip("lhapdf") -@pytest.mark.isolated -def benchmark_is_evolution(): - assert genpdf.flavors.is_evolution_labels(["V", "T3"]) - assert not genpdf.flavors.is_evolution_labels(["21", "2"]) - - -@pytest.mark.isolated -def benchmark_is_pids(): - assert not genpdf.flavors.is_pid_labels(["V", "T3"]) - assert not genpdf.flavors.is_pid_labels(["35", "9"]) - assert not genpdf.flavors.is_pid_labels({}) - assert genpdf.flavors.is_pid_labels([21, 2]) - - -@pytest.mark.isolated -def benchmark_flavors_pid_to_flavor(): - flavs = genpdf.flavors.pid_to_flavor([1, 2, 21, -3]) - for f in flavs: - for g in flavs: - if not np.allclose(f, g): - assert f @ g == 0 - - -@pytest.mark.isolated -def benchmark_flavors_evol_to_flavor(): - flavs = genpdf.flavors.evol_to_flavor(["S", "g", "T3", "V8"]) - for f in flavs: - for g in flavs: - if not np.allclose(f, g): - assert f @ g == 0 - - @pytest.mark.isolated def benchmark_flavors_pids_ct14(tmp_path, cd): with cd(tmp_path): @@ -101,59 +69,3 @@ def benchmark_flavors_evol_ct14(tmp_path, cd): np.testing.assert_allclose( pdf.xfxQ2(21, x, Q2), gonly.xfxQ2(21, x, Q2) ) - - -@pytest.mark.isolated -def benchmark_flavors_evol_raw(): - blocks = [ - { - "Q2grid": np.array([1, 2]), - "xgrid": np.array([0.1, 1.0]), - "pids": np.array([-1, 21, 1]), - "data": np.array([[0.1, 0.2, 0.1]] * 4), - } - ] - gonly = genpdf.flavors.project(blocks, genpdf.flavors.evol_to_flavor(["g"])) - assert len(gonly) == 1 - np.testing.assert_allclose( - gonly[0]["data"], - np.array( - [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]] * 4 - ), - ) - Sonly = genpdf.flavors.project(blocks, genpdf.flavors.evol_to_flavor(["S"])) - assert len(Sonly) == 1 - for i in [0, 1, 2, 3]: - # g and gamma are zero - np.testing.assert_allclose(Sonly[0]["data"][i][7], 0) - np.testing.assert_allclose(Sonly[0]["data"][i][0], 0) - # quark are all equal and equal to anti-quarks - for pid in [2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13]: - np.testing.assert_allclose(Sonly[0]["data"][i][pid], Sonly[0]["data"][i][1]) - - -@pytest.mark.isolated -def benchmark_flavors_evol_nodata(): - # try with a block without data - blocks = [ - { - "Q2grid": np.array([1, 2]), - "xgrid": np.array([0.1, 1.0]), - "pids": np.array([-1, 21, 1]), - "data": np.array([]), - }, - { - "Q2grid": np.array([1, 2]), - "xgrid": np.array([0.1, 1.0]), - "pids": np.array([-1, 21, 1]), - "data": np.array([[0.1, 0.2, 0.1]] * 4), - }, - ] - gonly = genpdf.flavors.project(blocks, genpdf.flavors.evol_to_flavor(["g"])) - assert len(gonly) == 2 - np.testing.assert_allclose( - gonly[1]["data"], - np.array( - [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]] * 4 - ), - ) diff --git a/benchmarks/ekobox/genpdf/benchmark_init.py b/benchmarks/ekobox/genpdf/benchmark_init.py index 3e23e8006..29a9b0b05 100644 --- a/benchmarks/ekobox/genpdf/benchmark_init.py +++ b/benchmarks/ekobox/genpdf/benchmark_init.py @@ -14,32 +14,6 @@ lhapdf = pytest.importorskip("lhapdf") -@pytest.mark.isolated -def benchmark_genpdf_exceptions(tmp_path, cd): - # using a wrong label and then a wrong parent pdf - with cd(tmp_path): - with pytest.raises(TypeError): - genpdf.generate_pdf( - "test_genpdf_exceptions1", - ["f"], - { - 21: lambda x, Q2: 3.0 * x * (1.0 - x), - 2: lambda x, Q2: 4.0 * x * (1.0 - x), - }, - ) - with pytest.raises(ValueError): - genpdf.generate_pdf( - "test_genpdf_exceptions2", - ["g"], - 10, - ) - with pytest.raises(FileExistsError): - genpdf.install_pdf("foo") - - with pytest.raises(TypeError): - genpdf.generate_pdf("debug", [21], info_update=(10, 15, 20)) - - @pytest.mark.isolated def benchmark_genpdf_no_parent_and_install(tmp_path, cd): with cd(tmp_path): diff --git a/pyproject.toml b/pyproject.toml index 626925191..0e5386e24 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -101,7 +101,7 @@ python_classes = ['Test*', 'Benchmark*'] python_functions = ['test_*', 'benchmark_*'] addopts = [ '--cov=eko', - # '--cov=ekobox', + '--cov=ekobox', '--cov-report=html', '--cov-report=xml', '--strict-markers', @@ -113,7 +113,8 @@ markers = ["isolated: marks benchmarks as isolated"] # extensions not to check extension-pkg-whitelist = ["numpy", "numba", "lhapdf", "pegasus"] ignore-paths = ["benchmarks/", "doc/", "tests/"] -jobs = 1 # has to be 1 as pylint is NOT threadsafe +# jobs has to be 1 as pylint is NOT threadsafe +jobs = 1 [tool.pylint.messages_control] disable = ["invalid-name", "fixme"] [tool.pylint.reports] diff --git a/src/eko/member.py b/src/eko/member.py index e9f3b4576..f97c8cca1 100644 --- a/src/eko/member.py +++ b/src/eko/member.py @@ -243,7 +243,7 @@ def operator_multiply(left, right, operation): Returns ------- - dict : + dict new operator members dictionary """ # prepare paths diff --git a/src/ekobox/__init__.py b/src/ekobox/__init__.py index 3ce63bd8f..3a140e99a 100644 --- a/src/ekobox/__init__.py +++ b/src/ekobox/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- from ekomark import apply -from . import evol_pdf, gen_info, gen_op, gen_theory +from . import evol_pdf, info_file, operators_card, theory_card diff --git a/src/ekobox/evol_pdf.py b/src/ekobox/evol_pdf.py index f6c745c83..9427f8676 100644 --- a/src/ekobox/evol_pdf.py +++ b/src/ekobox/evol_pdf.py @@ -6,7 +6,7 @@ from eko import basis_rotation as br from ekomark import apply -from . import gen_info, genpdf +from . import genpdf, info_file def evolve_pdfs( @@ -27,36 +27,26 @@ def evolve_pdfs( ---------- initial_PDF_list : list(lhapdf object) list of PDF members to be evolved - theory_card : dict theory card - operators_card : dict operators card - path : str path to cached eko output (if "None" it will be recomputed) - targetgrid : list(float) target x-grid (if different from input x-grid) - install : bool set whether to install evolved PDF to lhapdf directory - name : str set name of evolved PDF - info_update : dict dict of info to add or update to default info file - """ eko_output = None if path is not None: my_path = pathlib.Path(path) if my_path.is_dir(): - ops_id = f"o{operators_card['hash'][:6]}_t{theory_card['hash'][:6]}.tar" - ops_id_path = pathlib.Path(ops_id) - outpath = my_path / ops_id_path.relative_to(ops_id_path.anchor) + outpath = my_path / ekofileid(theory_card, operators_card) eko_output = eko.output.legacy.load_tar(outpath) else: eko_output = eko.output.legacy.load_tar(my_path) @@ -73,7 +63,7 @@ def evolve_pdfs( info_update = {} info_update["XMin"] = targetgrid[0] info_update["XMax"] = targetgrid[-1] - info = gen_info.create_info_file( + info = info_file.build( theory_card, operators_card, len(evolved_PDF_list), @@ -100,28 +90,20 @@ def evolve_pdfs( genpdf.install_pdf(name) -def gen_out(theory_card, op_card, path=None): +def ekofileid(theory_card, operators_card): """ - Generates EKO output from theory and operators cards and, if requested, - dumps it in tar format + Return a common filename composed by the hashes. Parameters ---------- - theory_card : dict - theory card - op_card : dict - operators card - path : str - path of dumped output (if "None" output is not dumped) + theory_card : dict + theory card + operators_card : dict + operators card Returns ------- - : eko.output.Output - eko output + str + file name """ - eko_output = eko.run_dglap(theory_card, op_card) - if path is not None: - ops_id = f"o{op_card['hash'][:6]}_t{theory_card['hash'][:6]}" - path = f"{path}/{ops_id}.tar" - eko.output.legacy.dump_tar(eko_output, path) - return eko_output + return f"o{operators_card['hash'][:6]}_t{theory_card['hash'][:6]}.tar" diff --git a/src/ekobox/genpdf/__init__.py b/src/ekobox/genpdf/__init__.py index 496ef9d0b..4df6caf96 100644 --- a/src/ekobox/genpdf/__init__.py +++ b/src/ekobox/genpdf/__init__.py @@ -11,20 +11,37 @@ from . import export, flavors, load -def take_data(parent_pdf_set=None, members=False): +def take_data(parent_pdf_set=None, members=False, xgrid=None, Q2grid=None): """ - Auxiliary function for generate_pdf. It provides the info, the heads - of the member files and the blocks to be generated to generate_pdf. + Auxiliary function for `generate_pdf`. + + It provides the info, the heads of the member files and the blocks + to be generated to `generate_pdf`. Parameters ---------- - parent_pdf_set : - the PDF set to be used as parent + parent_pdf_set : None or str or dict + the PDF set to be used as parent set members : bool - if true every member of the parent are loaded + if true every member of the parent is loaded + xgrid : list(float) + produced x grid if given + Q2grid : list(float) + produced Q2 grid if given + + Returns + ------- + info : dict + info dictionary + heads : list(str) + heads of member files if necessary + blocks : list(dict) + data blocks """ - xgrid = np.geomspace(1e-9, 1, 240) - Q2grid = np.geomspace(1.3, 1e5, 35) + if xgrid is None: + xgrid = np.geomspace(1e-9, 1, 240) + if Q2grid is None: + Q2grid = np.geomspace(1.3, 1e5, 35) # collect blocks all_blocks = [] info = None @@ -44,9 +61,9 @@ def take_data(parent_pdf_set=None, members=False): info = load.load_info_from_file(parent_pdf_set) # iterate on members for m in range(int(info["NumMembers"])): - dat = load.load_blocks_from_file(parent_pdf_set, m) - heads.append(dat[0]) - all_blocks.append(dat[1]) + head, blocks = load.load_blocks_from_file(parent_pdf_set, m) + heads.append(head) + all_blocks.append(blocks) if not members: break elif isinstance(parent_pdf_set, dict): @@ -65,37 +82,44 @@ def take_data(parent_pdf_set=None, members=False): ) else: raise ValueError("Unknown parent pdf type") - return heads, info, all_blocks + return info, heads, all_blocks def generate_pdf( - name, labels, parent_pdf_set=None, members=False, info_update=None, install=False + name, + labels, + parent_pdf_set=None, + members=False, + info_update=None, + install=False, + xgrid=None, + Q2grid=None, ): """ Generate a new PDF from a parent PDF with a set of flavors. - If parent_pdf_set is the name of an available PDF set, + If `parent_pdf_set` is the name of an available PDF set, it will be used as parent. In order to use the toy PDF - as parent, it is enough to set parent_pdf_set = "toy" or "toylh". - If parent_pdf_set is not specified, a debug PDF constructed as - x * (1-x) for every flavor will be usedas parent. + as parent, it is enough to set `parent_pdf_set` to "toy" or "toylh". + If `parent_pdf_set` is not specified, a debug PDF constructed as + x * (1-x) for every flavor will be used as parent. It is also possible to provide custom functions for each flavor - in the form of a dictionary: {pid: f(x,Q2)}. + in the form of a dictionary: `{pid: f(x,Q2)}`. - In labels it is possible to pass a list of PIDs or evolution basis + With `labels` it is possible to pass a list of PIDs or evolution basis combinations to keep in the generated PDF. In order to project on custom combinations of PIDs, it is also possible to pass a list containing the desired factors for each flavor. The default behaviour is to generate only one member for a PDF set - (the zero member) but it can be changed setting to True the member flag. + (the zero member) but it can be changed setting to True the `members` flag. - The info_update argument is a dictionary and provide to the user a way - to change the info file of the generated PDF set. If a key of info_update + The `info_update` argument is a dictionary and provide to the user as a way + to change the info file of the generated PDF set. If a key of `info_update` matches with one key of the standard info file, the information are updated, otherwise they are simply added. - Turning True the value of the install flag, it is possible to autmatically + Turning True the value of the `install` flag, it is possible to automatically install the generated PDF to the lhapdf directory. By default install is False. Parameters @@ -110,6 +134,10 @@ def generate_pdf( iterate on members install : bool install on LHAPDF path + xgrid : list(float) + produced x grid if given + Q2grid : list(float) + produced Q2 grid if given Examples -------- @@ -126,7 +154,7 @@ def generate_pdf( through the pure-singlet contributions (starting at |NNLO|) >>> from eko import basis_rotation as br - >>> from ekobox.tools import genpdf + >>> from ekobox import genpdf >>> import numpy as np >>> anti_qed_singlet = np.zeros_like(br.flavor_basis_pids, dtype=np.float_) >>> anti_qed_singlet[br.flavor_basis_pids.index(1)] = -4 @@ -147,7 +175,9 @@ def generate_pdf( flavor_combinations = flavors.pid_to_flavor(labels) # labels = verify_labels(args.labels) - heads, info, all_blocks = take_data(parent_pdf_set=parent_pdf_set, members=members) + info, heads, all_blocks = take_data( + parent_pdf_set, members, xgrid=xgrid, Q2grid=Q2grid + ) # filter the PDF new_all_blocks = [] @@ -156,10 +186,7 @@ def generate_pdf( # changing info file according to user choice if info_update is not None: - if isinstance(info_update, dict): - info.update(info_update) - else: - raise TypeError("Info to update are not in a dictionary format") + info.update(info_update) # write info["Flavors"] = [int(pid) for pid in br.flavor_basis_pids] info["NumFlavors"] = len(br.flavor_basis_pids) @@ -190,8 +217,8 @@ def install_pdf(name): print(f"install_pdf {name}") target = pathlib.Path(lhapdf.paths()[0]) src = pathlib.Path(name) - if not src.exists(): - raise FileExistsError(src) + # shutil.move only accepts paths since 3.9 so we need to cast + # https://docs.python.org/3/library/shutil.html?highlight=shutil#shutil.move shutil.move(str(src), str(target)) @@ -212,7 +239,7 @@ def generate_block(xfxQ2, xgrid, Q2grid, pids): Returns ------- - dict : + dict PDF block """ block = dict(Q2grid=Q2grid, pids=pids, xgrid=xgrid) diff --git a/src/ekobox/genpdf/export.py b/src/ekobox/genpdf/export.py index 3a7a02de3..8f906513f 100644 --- a/src/ekobox/genpdf/export.py +++ b/src/ekobox/genpdf/export.py @@ -126,9 +126,7 @@ def dump_set(name, info, member_blocks, pdf_type_list=None): """ dump_info(name, info) for mem, blocks in enumerate(member_blocks): - if not isinstance(pdf_type_list, list): - dump_blocks(name, mem, blocks) - elif len(pdf_type_list) == 0: + if not isinstance(pdf_type_list, list) or len(pdf_type_list) == 0: dump_blocks(name, mem, blocks) else: dump_blocks(name, mem, blocks, pdf_type=pdf_type_list[mem]) diff --git a/src/ekobox/genpdf/flavors.py b/src/ekobox/genpdf/flavors.py index 116443419..121d28c15 100644 --- a/src/ekobox/genpdf/flavors.py +++ b/src/ekobox/genpdf/flavors.py @@ -129,6 +129,7 @@ def is_pid_labels(labels): except (ValueError, TypeError): return False for label in labels: + # label might still be a list (for general projection) if not isinstance(label, np.int_): return False if label not in br.flavor_basis_pids: diff --git a/src/ekobox/genpdf/load.py b/src/ekobox/genpdf/load.py index 4c1112b2d..de5322288 100644 --- a/src/ekobox/genpdf/load.py +++ b/src/ekobox/genpdf/load.py @@ -23,7 +23,7 @@ def load_info_from_file(pdfset_name): Returns ------- - dict : + dict info dictionary """ import lhapdf # pylint: disable=import-error, import-outside-toplevel @@ -55,13 +55,10 @@ def load_blocks_from_file(pdfset_name, member): """ import lhapdf # pylint: disable=import-error, import-outside-toplevel - pdf = lhapdf.mkPDF(pdfset_name, member) src = pathlib.Path(lhapdf.paths()[0]) / pdfset_name # read actual file cnt = [] - with open( - src / f"{pdfset_name}_{pdf.memberID:04d}.dat", "r", encoding="utf-8" - ) as o: + with open(src / f"{pdfset_name}_{member:04d}.dat", "r", encoding="utf-8") as o: cnt = o.readlines() # file head head = cnt[0] diff --git a/src/ekobox/gen_info.py b/src/ekobox/info_file.py similarity index 92% rename from src/ekobox/gen_info.py rename to src/ekobox/info_file.py index 757ae4c7c..668ffdd5c 100644 --- a/src/ekobox/gen_info.py +++ b/src/ekobox/info_file.py @@ -5,7 +5,7 @@ from .genpdf import load -def create_info_file(theory_card, operators_card, num_members, info_update): +def build(theory_card, operators_card, num_members, info_update): """ Generate a lhapdf info file from theory and operators card @@ -22,8 +22,8 @@ def create_info_file(theory_card, operators_card, num_members, info_update): Returns ------- - : dict - info file in lhapdf format + dict + info file in lhapdf format """ template_info = copy.deepcopy(load.template_info) template_info["SetDesc"] = "Evolved PDF from " + str(theory_card["Q0"]) + " GeV" diff --git a/src/ekobox/gen_op.py b/src/ekobox/operators_card.py similarity index 65% rename from src/ekobox/gen_op.py rename to src/ekobox/operators_card.py index 6ce7d9034..49de99240 100644 --- a/src/ekobox/gen_op.py +++ b/src/ekobox/operators_card.py @@ -7,27 +7,27 @@ from ekomark.data import operators -def gen_op_card(Q2grid, update=None, name=None): - """Generate operators card. +def generate(Q2grid, update=None, name=None): + """ + Generate operators card. - Generates an operator card with some mandatory user choice + Generates an operators card with some mandatory user choice (in this case only the Q2 grid) and some default values which can be changed by the update input dict. Parameters ---------- - Q2grid : list(float) - grid for Q2 - update : dict - dictionary of info to update in op. card - name : str - name of exported op.card (if name not None) + Q2grid : list(float) + grid for Q2 + update : dict + dictionary of info to update in op. card + name : str + name of exported op.card (if name not None) Returns ------- - dict - operator card - + dict + operators card """ # Constructing the dictionary with some default value def_op = copy.deepcopy(operators.default_card) @@ -46,40 +46,39 @@ def gen_op_card(Q2grid, update=None, name=None): serialized = sql.serialize(def_op) def_op["hash"] = (sql.add_hash(serialized))[-1] if name is not None: - export_op_card(name, def_op) + dump(name, def_op) return def_op -def export_op_card(name, op): - """Export the operators card in the current directory +def dump(name, op): + """ + Export the operators card in the current directory Parameters ---------- - name : str - name of the op. card to export - - op : dict - op card - + name : str + name of the operators card to export + op : dict + operators card """ target = f"{name}.yaml" with open(target, "w", encoding="utf-8") as out: yaml.safe_dump(op, out) -def import_op_card(path): +def load(path): """ Import the operators card specified by path Parameters ---------- path : str - path to op. card in yaml format + path to operators card in yaml format Returns ------- - : dict - op card + dict + operators card """ with open(path, "r", encoding="utf-8") as o: op = yaml.safe_load(o) diff --git a/src/ekobox/gen_theory.py b/src/ekobox/theory_card.py similarity index 79% rename from src/ekobox/gen_theory.py rename to src/ekobox/theory_card.py index 69fba7cdd..76118a3c9 100644 --- a/src/ekobox/gen_theory.py +++ b/src/ekobox/theory_card.py @@ -5,33 +5,29 @@ from banana.data import sql, theories -def gen_theory_card(pto, initial_scale, update=None, name=None): +def generate(pto, initial_scale, update=None, name=None): """ Generates a theory card with some mandatory user choice and some default values which can be changed by the update input dict Parameters ---------- - pto : int perturbation theory order initial_scale: float - initial scale of evolution + initial scale of evolution [GeV] update : dict info to update to default theory card name : str - name of exported theory card (if name not None ) + name of exported theory card (if name is not None ) Returns ------- - - : dict - theory card + dict + theory card """ # Constructing the dictionary with some default values theory = copy.deepcopy(theories.default_card) - # delete unuseful member - del theory["FNS"] # Adding the mandatory inputs theory["PTO"] = pto theory["Q0"] = initial_scale @@ -42,13 +38,13 @@ def gen_theory_card(pto, initial_scale, update=None, name=None): raise ValueError("Provided key not in theory card") theory.update(update) serialized = sql.serialize(theory) - theory["hash"] = (sql.add_hash(serialized))[-1] + theory["hash"] = sql.add_hash(serialized)[-1] if name is not None: - export_theory_card(name, theory) + dump(name, theory) return theory -def export_theory_card(name, theory): +def dump(name, theory): """ Export the theory card in the current directory @@ -65,7 +61,7 @@ def export_theory_card(name, theory): yaml.safe_dump(theory, out) -def import_theory_card(path): +def load(path): """ Import the theory card specified by path @@ -76,7 +72,7 @@ def import_theory_card(path): Returns ------- - : dict + dict theory card """ with open(path, "r", encoding="utf-8") as o: diff --git a/tests/conftest.py b/tests/conftest.py index 35a8a9213..4969506dd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,8 +1,29 @@ # -*- coding: utf-8 -*- +import os +import pathlib +import shutil +import sys +from contextlib import contextmanager + import numpy as np import pytest +@pytest.fixture +def cd(): + # thanks https://stackoverflow.com/questions/431684/how-do-i-change-the-working-directory-in-python/24176022#24176022 + @contextmanager + def wrapped(newdir): + prevdir = os.getcwd() + os.chdir(os.path.expanduser(newdir)) + try: + yield + finally: + os.chdir(prevdir) + + return wrapped + + class FakePDF: def hasFlavor(self, pid): return pid == 1 @@ -72,3 +93,42 @@ def fake_factory(): @pytest.fixture def fake_output(): return FakeOutput().fake_output() + + +@pytest.fixture +def fake_lhapdf(tmp_path): + def lhapdf_paths(): + return [tmp_path] + + # Thanks https://stackoverflow.com/questions/43162722/mocking-a-module-import-in-pytest + module = type(sys)("lhapdf") + module.paths = lhapdf_paths + sys.modules["lhapdf"] = module + + yield tmp_path + + +fakepdf = pathlib.Path(__file__).parents[1] / "benchmarks" / "ekobox" / "fakepdf" + + +def copy_lhapdf(fake_lhapdf, n): + src = fakepdf / n + dst = fake_lhapdf / n + shutil.copytree(src, dst) + yield n + shutil.rmtree(dst) + + +@pytest.fixture +def fake_ct14(fake_lhapdf): + yield from copy_lhapdf(fake_lhapdf, "myCT14llo_NF3") + + +@pytest.fixture +def fake_nn31(fake_lhapdf): + yield from copy_lhapdf(fake_lhapdf, "myNNPDF31_nlo_as_0118") + + +@pytest.fixture +def fake_mstw(fake_lhapdf): + yield from copy_lhapdf(fake_lhapdf, "myMSTW2008nlo90cl") diff --git a/tests/ekobox/test_evol_pdf.py b/tests/ekobox/test_evol_pdf.py index e69de29bb..fc833cd90 100644 --- a/tests/ekobox/test_evol_pdf.py +++ b/tests/ekobox/test_evol_pdf.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +from banana import toy + +import eko +import eko.output.legacy as out +from ekobox import evol_pdf as ev_p +from ekobox import operators_card as oc +from ekobox import theory_card as tc + +op = oc.generate( + [100.0], + update={ + "xgrid": [0.1, 0.5, 1.0], + "configs": {"interpolation_polynomial_degree": 1}, + }, +) +theory = tc.generate(0, 1.65) + + +def test_evolve_pdfs_run(fake_lhapdf, cd): + n = "test_evolve_pdfs_run" + mytmp = fake_lhapdf / "install" + mytmp.mkdir() + with cd(mytmp): + ev_p.evolve_pdfs([toy.mkPDF("", 0)], theory, op, install=True, name=n) + p = fake_lhapdf / n + assert p.exists() + + +def test_evolve_pdfs_dump_path(fake_lhapdf, cd): + n = "test_evolve_pdfs_dump_path" + peko = fake_lhapdf / ev_p.ekofileid(theory, op) + out.dump_tar(eko.run_dglap(theory, op), peko) + assert peko.exists() + with cd(fake_lhapdf): + ev_p.evolve_pdfs([toy.mkPDF("", 0)], theory, op, name=n, path=fake_lhapdf) + p = fake_lhapdf / n + assert p.exists() + + +def test_evolve_pdfs_dump_file(fake_lhapdf, cd): + n = "test_evolve_pdfs_dump_file" + peko = fake_lhapdf / ev_p.ekofileid(theory, op) + out.dump_tar(eko.run_dglap(theory, op), peko) + assert peko.exists() + with cd(fake_lhapdf): + ev_p.evolve_pdfs([toy.mkPDF("", 0)], theory, op, name=n, path=peko) + p = fake_lhapdf / n + assert p.exists() diff --git a/tests/ekobox/test_genpdf.py b/tests/ekobox/test_genpdf.py new file mode 100644 index 000000000..3f68ae9b4 --- /dev/null +++ b/tests/ekobox/test_genpdf.py @@ -0,0 +1,202 @@ +# -*- coding: utf-8 -*- +import numpy as np +import pytest + +from eko import basis_rotation as br +from ekobox import genpdf + + +def test_genpdf_exceptions(tmp_path, cd): + with cd(tmp_path): + # wrong label + with pytest.raises(TypeError): + genpdf.generate_pdf( + "test_genpdf_exceptions1", + ["f"], + { + 21: lambda x, Q2: 3.0 * x * (1.0 - x), + 2: lambda x, Q2: 4.0 * x * (1.0 - x), + }, + ) + # wrong parent pdf + with pytest.raises(ValueError): + genpdf.generate_pdf( + "test_genpdf_exceptions2", + ["g"], + 10, + ) + # non-existant PDF set + with pytest.raises(FileNotFoundError): + genpdf.install_pdf("foo") + with pytest.raises(TypeError): + genpdf.generate_pdf("debug", [21], info_update=(10, 15, 20)) + + +def test_generate_block(): + xg = np.linspace(0.0, 1.0, 5) + q2s = np.geomspace(1.0, 1e3, 5) + pids = np.arange(3) + b = genpdf.generate_block(lambda pid, x, q2: pid * x * q2, xg, q2s, pids) + assert isinstance(b, dict) + assert sorted(b.keys()) == sorted(["data", "Q2grid", "xgrid", "pids"]) + assert isinstance(b["data"], np.ndarray) + assert b["data"].shape == (len(xg) * len(q2s), len(pids)) + + +def test_install_pdf(fake_lhapdf, cd): + # move into subdir to be able to move + mytmp = fake_lhapdf / "install" + mytmp.mkdir() + n = "test_install_pdf" + p = mytmp / n + i = "test.info" + with cd(mytmp): + with pytest.raises(FileNotFoundError): + genpdf.install_pdf(p) + p.mkdir() + (p / i).write_text("Bla") + genpdf.install_pdf(p) + pp = fake_lhapdf / n + assert not p.exists() + assert pp.exists() + ppi = pp / i + assert ppi.exists() + assert "Bla" == ppi.read_text() + + +def test_generate_pdf_debug_pid(fake_lhapdf, cd): + mytmp = fake_lhapdf / "install" + mytmp.mkdir() + n = "test_generate_pdf_debug_pid" + xg = np.linspace(0.0, 1.0, 5) + q2s = np.geomspace(1.0, 1e3, 7) + p = mytmp / n + i = f"{n}.info" + with cd(mytmp): + genpdf.generate_pdf( + n, + [21], + None, + info_update={"Debug": "debug"}, + install=True, + xgrid=xg, + Q2grid=q2s, + ) + pp = fake_lhapdf / n + assert not p.exists() + assert pp.exists() + # check info file + ppi = pp / i + assert ppi.exists() + assert "Debug: debug" in ppi.read_text() + ii = genpdf.load.load_info_from_file(n) + assert "Debug" in ii + assert ii["Debug"] == "debug" + # check member file + ppm = pp / f"{n}_0000.dat" + assert ppm.exists() + assert "PdfType: central" in ppm.read_text() + head, blocks = genpdf.load.load_blocks_from_file(n, 0) + assert "PdfType: central" in head + assert len(blocks) == 1 + b = blocks[0] + assert 21 in b["pids"] + for k, line in enumerate(b["data"]): + for pid, f in zip(b["pids"], line): + # the gluon is non-zero in the bulk - x=0 is included here + if ( + pid == 21 + and k > len(b["Q2grid"]) - 1 + and k < len(b["data"]) - len(b["Q2grid"]) + ): + assert not f == 0.0 + else: + assert f == 0.0 + + +def test_generate_pdf_pdf_evol(fake_lhapdf, fake_nn31, fake_mstw, fake_ct14, cd): + # iterate pdfs with their error type and number of blocks + for fake_pdf, err_type, nmem, nb in ( + (fake_nn31, "replica", 1, 2), + (fake_mstw, "error", 1, 3), + (fake_ct14, "", 0, 1), + ): + n = f"test_generate_pdf_{err_type}_evol" + p = fake_lhapdf / n + i = f"{n}.info" + pi = p / i + with cd(fake_lhapdf): + genpdf.generate_pdf( + n, + ["S"], + fake_pdf, + members=nmem > 0, + ) + assert p.exists() + # check info file + assert pi.exists() + # check member files + for m in range(nmem + 1): + pm = p / f"{n}_{m:04d}.dat" + assert pm.exists() + head, blocks = genpdf.load.load_blocks_from_file(n, m) + assert ("PdfType: central" if m == 0 else f"PdfType: {err_type}") in head + assert len(blocks) == nb + for b in blocks: + for k, line in enumerate(b["data"]): + for pid, f in zip(b["pids"], line): + # the singlet is non-zero in the bulk - x >= 0 + if abs(pid) in range(1, 6 + 1) and k < len(b["data"]) - len( + b["Q2grid"] + ): + assert not f == 0.0 + assert not np.isclose(f, 0.0, atol=1e-15) + else: + # MSTW is not 0 at the end, but only almost + if err_type == "error" and k >= len(b["data"]) - len( + b["Q2grid"] + ): + np.testing.assert_allclose(f, 0.0, atol=1e-15) + else: + assert f == 0.0 + + +def test_generate_pdf_toy_antiqed(fake_lhapdf, cd): + # iterate pdfs with their error type and number of blocks + n = "test_generate_pdf_toy_antiqed" + xg = np.linspace(1e-5, 1.0, 5) + q2s = np.geomspace(1.0, 1e3, 7) + anti_qed_singlet = np.zeros_like(br.flavor_basis_pids, dtype=np.float_) + anti_qed_singlet[br.flavor_basis_pids.index(1)] = -4 + anti_qed_singlet[br.flavor_basis_pids.index(-1)] = -4 + anti_qed_singlet[br.flavor_basis_pids.index(2)] = 1 + anti_qed_singlet[br.flavor_basis_pids.index(-2)] = 1 + p = fake_lhapdf / n + i = f"{n}.info" + pi = p / i + with cd(fake_lhapdf): + genpdf.generate_pdf( + n, + [anti_qed_singlet], + "toy", + xgrid=xg, + Q2grid=q2s, + ) + assert p.exists() + # check info file + assert pi.exists() + # check member files + pm = p / f"{n}_0000.dat" + assert pm.exists() + assert "PdfType: central" in pm.read_text() + head, blocks = genpdf.load.load_blocks_from_file(n, 0) + assert "PdfType: central" in head + assert len(blocks) == 1 + b = blocks[0] + for k, line in enumerate(b["data"]): + for pid, f in zip(b["pids"], line): + # the u and d are non-zero in the bulk - x=0 is not included here + if abs(pid) in [1, 2] and k < len(b["data"]) - len(b["Q2grid"]): + assert not f == 0.0 + else: + assert f == 0.0 diff --git a/tests/ekobox/test_genpdf_cli.py b/tests/ekobox/test_genpdf_cli.py new file mode 100644 index 000000000..ec973140e --- /dev/null +++ b/tests/ekobox/test_genpdf_cli.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +from click.testing import CliRunner + +from ekobox.genpdf.cli import cli + + +def test_genpdf_CLI_messages(): + runner = CliRunner() + result = runner.invoke(cli, ["generate"]) + assert "Error: Missing argument 'NAME'." in result.output + result = runner.invoke(cli, ["install"]) + assert "Error: Missing argument 'NAME'." in result.output + result = runner.invoke(cli, ["generate", "TestEmptyLabels"]) + assert result.exception and "Labels must contain at least one element" in str( + result.exception + ) + result = runner.invoke(cli, ["generate", "--help"]) + assert "-p, --parent-pdf-set TEXT" in result.output + assert "-m, --members" in result.output + assert "-i, --install" in result.output + + +def test_genpdf_CLI(fake_lhapdf, cd): + mytmp = fake_lhapdf / "install" + mytmp.mkdir() + n = "test_genpdf_CLI" + runner = CliRunner() + with cd(mytmp): + result_gen = runner.invoke(cli, ["generate", n, "21"]) + assert result_gen.exception is None + result_inst = runner.invoke(cli, ["install", n]) + assert result_inst.exception is None + p = fake_lhapdf / n + assert p.exists() + pi = p / f"{n}.info" + assert pi.exists() + pm = p / f"{n}_0000.dat" + assert pm.exists() diff --git a/tests/ekobox/test_genpdf_export.py b/tests/ekobox/test_genpdf_export.py new file mode 100644 index 000000000..578308136 --- /dev/null +++ b/tests/ekobox/test_genpdf_export.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +import numpy as np +import yaml + +from ekobox import genpdf + + +def test_list_to_str(): + a = genpdf.export.list_to_str([1, 2]) + assert isinstance(a, str) + assert "1." in a + b = genpdf.export.list_to_str([1.0, 2.0]) + assert isinstance(b, str) + assert "1." in a + + +def test_array_to_str(): + s = (2, 2) + a = genpdf.export.array_to_str(np.arange(4).reshape(s)) + assert isinstance(a, str) + assert "1." in a + b = np.array([e.split() for e in a.splitlines()]) + assert b.shape == s + + +def test_dump_info(tmp_path): + n = "test" + p = tmp_path / n + f = p / f"{n}.info" + i = {"a": "b", "c": 2} + genpdf.export.dump_info(p, i) + assert p.exists() + assert f.exists() + # the files might not be perfect yaml, but should be yaml compatible + with open(f, "r", encoding="utf-8") as o: + ii = yaml.safe_load(o) + for k, v in i.items(): + assert k in ii + assert ii[k] == v + + +def fake_blocks(n_blocks, n_x, n_q2, n_pids): + bs = [] + for _ in range(n_blocks): + bs.append( + { + "xgrid": np.linspace(0.0, 1.0, n_x), + "Q2grid": np.geomspace(1.0, 1e3, n_q2), + "pids": np.arange(n_pids), + "data": np.random.rand(n_x * n_q2, n_pids), + } + ) + return bs + + +def test_dump_blocks(tmp_path): + n = "test" + p = tmp_path / n + nb = 2 + for m in range(3): + f = p / f"{n}_{m:04d}.dat" + is_my_type = m > 1 + pdf_type = "Bla: blub" if is_my_type else None + genpdf.export.dump_blocks(p, m, fake_blocks(nb, 2, 2, 2), pdf_type=pdf_type) + assert p.exists() + assert f.exists() + cnt = f.read_text() + if is_my_type: + assert "Bla: blub" in cnt + else: + assert ("central" in cnt) == (m == 0) + assert "Format" in cnt + assert cnt.count("---") == nb + 1 + + +def test_dump_set(tmp_path): + n = "test" + p = tmp_path / n + i = {"a": "b", "c": 2} + nmem = 2 + for pdf_type_list in (None, ["Bla: Blub"] * nmem): + genpdf.export.dump_set( + p, i, [fake_blocks(2, 2, 2, 2) for _ in range(nmem)], pdf_type_list + ) + assert p.exists() + f = p / f"{n}.info" + assert f.exists() + for m in range(nmem): + f = p / f"{n}_{m:04d}.dat" + assert f.exists() + if pdf_type_list is not None: + assert "Bla: Blub" in f.read_text() diff --git a/tests/ekobox/test_genpdf_flavors.py b/tests/ekobox/test_genpdf_flavors.py new file mode 100644 index 000000000..19013e2ce --- /dev/null +++ b/tests/ekobox/test_genpdf_flavors.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- + +import numpy as np + +from ekobox import genpdf + + +def test_is_evolution(): + assert genpdf.flavors.is_evolution_labels(["V", "T3"]) + assert not genpdf.flavors.is_evolution_labels([[1, 2]]) + assert not genpdf.flavors.is_evolution_labels(["21", "2"]) + + +def test_is_pids(): + assert not genpdf.flavors.is_pid_labels(["V", "T3"]) + assert not genpdf.flavors.is_pid_labels(["35", "9"]) + assert not genpdf.flavors.is_pid_labels({}) + assert not genpdf.flavors.is_pid_labels([[1, 2]]) + assert genpdf.flavors.is_pid_labels([21, 2]) + + +def test_flavors_pid_to_flavor(): + flavs = genpdf.flavors.pid_to_flavor([1, 2, 21, -3]) + for f in flavs: + for g in flavs: + if not np.allclose(f, g): + assert f @ g == 0 + + +def test_flavors_evol_to_flavor(): + flavs = genpdf.flavors.evol_to_flavor(["S", "g", "T3", "V8"]) + for f in flavs: + for g in flavs: + if not np.allclose(f, g): + assert f @ g == 0 + + +def test_flavors_evol_raw(): + blocks = [ + { + "Q2grid": np.array([1, 2]), + "xgrid": np.array([0.1, 1.0]), + "pids": np.array([-1, 21, 1]), + "data": np.array([[0.1, 0.2, 0.1]] * 4), + } + ] + gonly = genpdf.flavors.project(blocks, genpdf.flavors.evol_to_flavor(["g"])) + assert len(gonly) == 1 + np.testing.assert_allclose( + gonly[0]["data"], + np.array( + [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]] * 4 + ), + ) + Sonly = genpdf.flavors.project(blocks, genpdf.flavors.evol_to_flavor(["S"])) + assert len(Sonly) == 1 + for i in [0, 1, 2, 3]: + # g and gamma are zero + np.testing.assert_allclose(Sonly[0]["data"][i][7], 0) + np.testing.assert_allclose(Sonly[0]["data"][i][0], 0) + # quark are all equal and equal to anti-quarks + for pid in [2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13]: + np.testing.assert_allclose(Sonly[0]["data"][i][pid], Sonly[0]["data"][i][1]) + + +def test_flavors_evol_nodata(): + # try with a block without data + blocks = [ + { + "Q2grid": np.array([1, 2]), + "xgrid": np.array([0.1, 1.0]), + "pids": np.array([-1, 21, 1]), + "data": np.array([]), + }, + { + "Q2grid": np.array([1, 2]), + "xgrid": np.array([0.1, 1.0]), + "pids": np.array([-1, 21, 1]), + "data": np.array([[0.1, 0.2, 0.1]] * 4), + }, + ] + gonly = genpdf.flavors.project(blocks, genpdf.flavors.evol_to_flavor(["g"])) + assert len(gonly) == 2 + np.testing.assert_allclose( + gonly[1]["data"], + np.array( + [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]] * 4 + ), + ) diff --git a/tests/ekobox/test_genpdf_load.py b/tests/ekobox/test_genpdf_load.py new file mode 100644 index 000000000..00e823001 --- /dev/null +++ b/tests/ekobox/test_genpdf_load.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +import numpy as np + +from ekobox import genpdf + + +def test_load_info(fake_ct14): + info = genpdf.load.load_info_from_file(fake_ct14) + assert "SetDesc" in info + assert "fake" in info["SetDesc"] + assert sorted(info["Flavors"]) == sorted([-3, -2, -1, 21, 1, 2, 3]) + + +def test_load_data_ct14(fake_ct14): + blocks = genpdf.load.load_blocks_from_file(fake_ct14, 0)[1] + assert len(blocks) == 1 + b0 = blocks[0] + assert isinstance(b0, dict) + assert sorted(b0.keys()) == sorted(["pids", "xgrid", "Q2grid", "data"]) + assert sorted(b0["pids"]) == sorted([-3, -2, -1, 21, 1, 2, 3]) + assert len(b0["data"].T) == 7 + np.testing.assert_allclose(b0["xgrid"][0], 1e-9) diff --git a/benchmarks/ekobox/benchmark_gen_info.py b/tests/ekobox/test_info_file.py similarity index 62% rename from benchmarks/ekobox/benchmark_gen_info.py rename to tests/ekobox/test_info_file.py index 7eb10d3d3..643d02745 100644 --- a/benchmarks/ekobox/benchmark_gen_info.py +++ b/tests/ekobox/test_info_file.py @@ -2,18 +2,16 @@ import math import numpy as np -import pytest -from ekobox import gen_info as g_i -from ekobox import gen_op as g_o -from ekobox import gen_theory as g_t +from ekobox import info_file +from ekobox import operators_card as oc +from ekobox import theory_card as tc -@pytest.mark.isolated -def benchmark_create_info_file(): - op = g_o.gen_op_card([10, 100]) - theory = g_t.gen_theory_card(1, 10.0, update={"alphas": 0.2}) - info = g_i.create_info_file( +def test_build(): + op = oc.generate([10, 100]) + theory = tc.generate(1, 10.0, update={"alphas": 0.2}) + info = info_file.build( theory, op, 4, info_update={"SetDesc": "Prova", "NewArg": 15.3, "MTop": 1.0} ) assert info["AlphaS_MZ"] == 0.2 diff --git a/tests/ekobox/test_mock.py b/tests/ekobox/test_mock.py new file mode 100644 index 000000000..0d9311086 --- /dev/null +++ b/tests/ekobox/test_mock.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +import numpy as np + +from ekobox import mock + + +def test_eko_identity(): + for s in ((1, 2, 2, 2, 2), (1, 3, 3, 3, 3)): + i = mock.eko_identity(s) + assert s == i.shape + # is identity? + f = np.random.rand(*s[-2:]) + g = np.einsum("qkbja,ja->qkb", i, f) + np.testing.assert_allclose(g[0], f) diff --git a/benchmarks/ekobox/benchmark_gen_op.py b/tests/ekobox/test_operators_card.py similarity index 54% rename from benchmarks/ekobox/benchmark_gen_op.py rename to tests/ekobox/test_operators_card.py index bd3b613ed..de196191c 100644 --- a/benchmarks/ekobox/benchmark_gen_op.py +++ b/tests/ekobox/test_operators_card.py @@ -1,32 +1,30 @@ # -*- coding: utf-8 -*- import pytest -from ekobox import gen_op as g_o +from ekobox import operators_card as oc -@pytest.mark.isolated -def benchmark_gen_op_card(): - op = g_o.gen_op_card([10, 100]) +def test_generate_ocard(): + op = oc.generate([10, 100]) assert op["Q2grid"] == [10, 100] assert op["configs"]["interpolation_polynomial_degree"] == 4 up_err = {"Prova": "Prova"} with pytest.raises(ValueError): - op = g_o.gen_op_card([10], update=up_err) + op = oc.generate([10], update=up_err) up = { "configs": {"interpolation_polynomial_degree": 2, "interpolation_is_log": False} } - op = g_o.gen_op_card([100], update=up) + op = oc.generate([100], update=up) assert op["Q2grid"] == [100] assert op["configs"]["interpolation_polynomial_degree"] == 2 assert op["configs"]["interpolation_is_log"] is False -@pytest.mark.isolated -def benchmark_export_load_op_card(tmp_path, cd): +def test_dump_load_op_card(tmp_path, cd): with cd(tmp_path): - op = g_o.gen_op_card([100], name="debug_op") - g_o.export_op_card("debug_op_two", op) - op_loaded = g_o.import_op_card("debug_op.yaml") - op_two_loaded = g_o.import_op_card("debug_op_two.yaml") + op = oc.generate([100], name="debug_op") + oc.dump("debug_op_two", op) + op_loaded = oc.load("debug_op.yaml") + op_two_loaded = oc.load("debug_op_two.yaml") for key in op.keys(): assert op[key] == op_loaded[key] == op_two_loaded[key] diff --git a/tests/ekobox/test_theory_card.py b/tests/ekobox/test_theory_card.py new file mode 100644 index 000000000..7b1f55ead --- /dev/null +++ b/tests/ekobox/test_theory_card.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +import pytest + +from ekobox import theory_card as tc + + +def test_generate_theory_card(): + theory = tc.generate(0, 1.0) + assert theory["PTO"] == 0 + assert theory["Q0"] == 1.0 + assert theory["mt"] == 173.07 + up_err = {"Prova": "Prova"} + with pytest.raises(ValueError): + theory = tc.generate(0, 1.0, update=up_err) + up = {"mb": 132.3, "PTO": 2} + theory = tc.generate(0, 1.0, update=up) + assert theory["PTO"] == 2 + assert theory["mb"] == 132.3 + + +def test_dump_load_theory_card(tmp_path, cd): + with cd(tmp_path): + theory = tc.generate(2, 12.3, name="debug_theory") + tc.dump("debug_theory_two", theory) + theory_loaded = tc.load("debug_theory.yaml") + theory_two_loaded = tc.load("debug_theory_two.yaml") + for key in theory.keys(): + assert theory[key] == theory_loaded[key] == theory_two_loaded[key] diff --git a/benchmarks/ekobox/benchmark_utils.py b/tests/ekobox/test_utils.py similarity index 54% rename from benchmarks/ekobox/benchmark_utils.py rename to tests/ekobox/test_utils.py index 37a5661f0..ccf6198be 100644 --- a/benchmarks/ekobox/benchmark_utils.py +++ b/tests/ekobox/test_utils.py @@ -2,31 +2,37 @@ import numpy as np import pytest -from ekobox import evol_pdf as ev_p -from ekobox import gen_op as g_o -from ekobox import gen_theory as g_t +import eko +from ekobox import operators_card as oc +from ekobox import theory_card as tc from ekobox import utils -@pytest.mark.isolated -def benchmark_ekos_product(): +def test_ekos_product(): # Generating two ekos - op1 = g_o.gen_op_card( - [60.0, 80.0, 100.0], update={"xgrid": [1e-7, 0.01, 0.1, 0.2, 0.3]} + op1 = oc.generate( + [60.0, 80.0, 100.0], + update={ + "xgrid": [0.1, 0.5, 1.0], + "configs": {"interpolation_polynomial_degree": 1}, + }, ) - theory1 = g_t.gen_theory_card(0, 5.0) + theory1 = tc.generate(0, 5.0) - op2 = g_o.gen_op_card( + op2 = oc.generate( [80.0, 100.0, 120.0], - update={"xgrid": [1e-7, 0.01, 0.1, 0.2, 0.3]}, + update={ + "xgrid": [0.1, 0.5, 1.0], + "configs": {"interpolation_polynomial_degree": 1}, + }, ) - theory2 = g_t.gen_theory_card(0, 10.0) - theory_err = g_t.gen_theory_card(0, 5.0) + theory2 = tc.generate(0, 10.0) + theory_err = tc.generate(0, 5.0) - eko_ini = ev_p.gen_out(theory1, op1) - eko_fin = ev_p.gen_out(theory2, op2) + eko_ini = eko.run_dglap(theory1, op1) + eko_fin = eko.run_dglap(theory2, op2) # Test_error - eko_fin_err = ev_p.gen_out(theory_err, op2) + eko_fin_err = eko.run_dglap(theory_err, op2) with pytest.raises(ValueError): _ = utils.ekos_product(eko_ini, eko_fin_err) # product is copied