diff --git a/benchmarks/bench_evolve.py b/benchmarks/bench_evolve.py index 7da92ed8..59124dd5 100644 --- a/benchmarks/bench_evolve.py +++ b/benchmarks/bench_evolve.py @@ -34,7 +34,7 @@ def benchmark_write_operator_card_from_file_num_fonll( with open(tcard_path, encoding="utf-8") as f: tcard = yaml.safe_load(f) _x_grid, _q2_grid = pineko.evolve.write_operator_card_from_file( - pine_path, default_path, target_path, tcard + pine_path, target_path, tcard ) # Check if the opcards are ok for opcard_path, cfg in zip( @@ -49,11 +49,10 @@ def benchmark_write_operator_card_from_file_num_fonll( def benchmark_write_operator_card_from_file(tmp_path, test_files, test_configs): pine_path = test_files / "data/grids/400/HERA_NC_225GEV_EP_SIGMARED.pineappl.lz4" - default_path = test_files / "data/operator_cards/400/_template.yaml" target_path = pathlib.Path(tmp_path / "test_operator.yaml") tcard = pineko.theory_card.load(400) x_grid, _q2_grid = pineko.evolve.write_operator_card_from_file( - pine_path, default_path, target_path, tcard + pine_path, target_path, tcard ) # Load the operator card @@ -64,13 +63,12 @@ def benchmark_write_operator_card_from_file(tmp_path, test_files, test_configs): wrong_pine_path = test_files / "data/grids/208/HERA_CC_318GEV_EM_wrong.pineappl.lz4" with pytest.raises(FileNotFoundError): _ = pineko.evolve.write_operator_card_from_file( - wrong_pine_path, default_path, target_path, 1.0 + wrong_pine_path, target_path, 1.0 ) def benchmark_dglap(tmp_path, test_files, test_configs): pine_path = test_files / "data/grids/400/HERA_NC_225GEV_EP_SIGMARED.pineappl.lz4" - default_path = test_files / "data/operator_cards/400/_template.yaml" target_path = pathlib.Path(tmp_path / "test_operator.yaml") theory_id = 400 @@ -78,7 +76,7 @@ def benchmark_dglap(tmp_path, test_files, test_configs): # In order to check if the operator card is enough for eko, let's compute the eko pineko.evolve.write_operator_card_from_file( - pine_path, default_path, target_path, tcard + pine_path, target_path, tcard ) # Load the opcard diff --git a/src/pineko/cli/opcard.py b/src/pineko/cli/opcard.py index 0f175a01..60e3017a 100644 --- a/src/pineko/cli/opcard.py +++ b/src/pineko/cli/opcard.py @@ -29,5 +29,5 @@ def subcommand(pineappl_path, default_card_path, thcard_path, opcard_path): tcard = yaml.safe_load(pathlib.Path(thcard_path).read_text(encoding="utf-8")) opcard_path = pathlib.Path(opcard_path) _x_grid, q2_grid = evolve.write_operator_card_from_file( - pineappl_path, default_card_path, opcard_path, tcard + pineappl_path, opcard_path, tcard ) diff --git a/src/pineko/evolve.py b/src/pineko/evolve.py index 9ae02ba2..e145b109 100644 --- a/src/pineko/evolve.py +++ b/src/pineko/evolve.py @@ -22,7 +22,7 @@ from eko.matchings import Atlas, nf_default from eko.quantities import heavy_quarks -from . import check, comparator, version +from . import check, comparator, template, version logger = logging.getLogger(__name__) @@ -94,7 +94,6 @@ def get_convolution_suffix(convolution: pineappl.convolutions.Conv) -> str: def write_operator_card_from_file( pineappl_path: os.PathLike, - default_card_path: os.PathLike, card_path: os.PathLike, tcard: dict, ): @@ -104,8 +103,6 @@ def write_operator_card_from_file( ---------- pineappl_path : str or os.PathLike path to grid to evolve - default_card : str or os.PathLike - base operator card card_path : str or os.PathLike target path tcard: dict @@ -124,11 +121,7 @@ def write_operator_card_from_file( raise FileNotFoundError(pineappl_path) pineappl_grid = pineappl.grid.Grid.read(pineappl_path) pineappl_grid.optimize() - default_card = yaml.safe_load( - pathlib.Path(default_card_path).read_text(encoding="utf-8") - ) - - return write_operator_card(pineappl_grid, default_card, card_path, tcard) + return write_operator_card(pineappl_grid, card_path, tcard) def dump_card( @@ -166,7 +159,6 @@ def dump_card( def write_operator_card( pineappl_grid: pineappl.grid.Grid, - default_card: dict, card_path: Union[str, os.PathLike], tcard: dict, ): @@ -176,8 +168,6 @@ def write_operator_card( ---------- pineappl_grid : pineappl.grid.Grid grid to evolve - default_card : dict - base operator card card_path : str or os.PathLike target path tcard: dict @@ -204,18 +194,19 @@ def write_operator_card( # ... to get the x and muF grids for the eko evol_info = pineappl_grid.evolve_info(order_mask) muf2_grid = evol_info.fac1 - operators_card = copy.deepcopy(default_card) + operators_card = {} + operators_card["configs"] = {} sv_method = sv_scheme(tcard) xif = 1.0 if sv_method is not None else tcard["XIF"] # update scale variation method - operators_card["configs"]["scvar_method"] = sv_method + operators_card["configs"]["scvar_method"] = sv_scheme(tcard) operators_card["init"] = (tcard["Q0"], tcard["nf0"]) - if default_card.get("init") is not None and default_card["init"] != [ + if template.CONSTANTS["init"] is not None and template.CONSTANTS["init"] != ( tcard["Q0"], tcard["nf0"], - ]: - raise ValueError("Template declares a value of Q0, nf0 different from theory") + ): + raise ValueError("Q0, nf0 from theory different than default") q2_grid = (xif * xif * muf2_grid).tolist() # If we are producing nFONLL FKs we need to look to NfFF... @@ -232,6 +223,8 @@ def write_operator_card( x_grid = np.append(x_grid, 1.0) operators_card["configs"]["interpolation_polynomial_degree"] = 1 operators_card["xgrid"] = x_grid.tolist() + else: + operators_card["xgrid"] = template.xgrid # Add the version of eko and pineko to the operator card # using importlib.metadata.version to get the correct tag in editable mode @@ -247,28 +240,30 @@ def write_operator_card( opconf["evolution_method"] = "iterate-exact" if "IterEv" in tcard: opconf["ev_op_iterations"] = tcard["IterEv"] - elif "ev_op_iterations" not in default_card["configs"]: + elif template.CONSTANTS["configs"]["ev_op_iterations"] is None: raise ValueError( "EXA used but IterEv not found in the theory card and not ev_op_iterations set in the template" ) # If the evolution method is defined in the template and it is different, fail - template_method = default_card["configs"].get("evolution_method") + template_method = template.CONSTANTS["configs"]["evolution_method"] if ( template_method is not None and template_method != opconf["evolution_method"] ): - raise ValueError( - f"The template and the theory have different evolution method ({template_method} vs {opconf['key']})" + logger.warning( + f"Your theory has a different evolution method than the default({template_method} vs {opconf['evolution_method']})." + f"The evolution method will be set to the default value {template_method}, check if this is what you want" ) # If the change is on the number of iterations, take the template value but warn the user - template_iter = default_card["configs"].get("ev_op_iterations") + template_iter = template.CONSTANTS["configs"]["ev_op_iterations"] if template_iter is not None and int(template_iter) != int( opconf["ev_op_iterations"] ): - raise ValueError( - f"The number of iteration in the theory and template is different, ({template_iter} vs {opconf['ev_op_iterations']})" + logger.warning( + f"Warning! The number of iteration in the theory and template is different, ({template_iter} vs {opconf['ev_op_iterations']})." + f"The evolution method will be set to the default value {template_iter}, check if this is what you want" ) # Some safety checks diff --git a/src/pineko/template.py b/src/pineko/template.py new file mode 100644 index 00000000..41379509 --- /dev/null +++ b/src/pineko/template.py @@ -0,0 +1,69 @@ +"""Default settings and interpolation xgrid (previously in _template.yaml).""" +import yaml + +# Define the interpolation x-grid as previously defined as 'xgrid' in _template.yaml +xgrid = ( + [1.9999999999999954e-07, + 3.034304765867952e-07, + 4.6035014748963906e-07, + 6.984208530700364e-07, + 1.0596094959101024e-06, + 1.607585498470808e-06, + 2.438943292891682e-06, + 3.7002272069854957e-06, + 5.613757716930151e-06, + 8.516806677573355e-06, + 1.292101569074731e-05, + 1.9602505002391748e-05, + 2.97384953722449e-05, + 4.511438394964044e-05, + 6.843744918967896e-05, + 0.00010381172986576898, + 0.00015745605600841445, + 0.00023878782918561914, + 0.00036205449638139736, + 0.0005487795323670796, + 0.0008314068836488144, + 0.0012586797144272762, + 0.0019034634022867384, + 0.0028738675812817515, + 0.004328500638820811, + 0.006496206194633799, + 0.009699159574043398, + 0.014375068581090129, + 0.02108918668378717, + 0.030521584007828916, + 0.04341491741702269, + 0.060480028754447364, + 0.08228122126204893, + 0.10914375746330703, + 0.14112080644440345, + 0.17802566042569432, + 0.2195041265003886, + 0.2651137041582823, + 0.31438740076927585, + 0.3668753186482242, + 0.4221667753589648, + 0.4798989029610255, + 0.5397572337880445, + 0.601472197967335, + 0.6648139482473823, + 0.7295868442414312, + 0.7956242522922756, + 0.8627839323906108, + 0.9309440808717544, + 1] + ) + +CONSTANTS = { + "configs": { + "ev_op_iterations": 60, + "evolution_method": "iterate-exact", + "inversion_method": "expanded", + "polarized": False, + "scvar_method": "null", + "time_like": False + }, + "init": (1.65, 4), +} + diff --git a/src/pineko/theory.py b/src/pineko/theory.py index 4a8e3e36..9b6e2a2c 100644 --- a/src/pineko/theory.py +++ b/src/pineko/theory.py @@ -309,8 +309,6 @@ def opcard(self, name, grid, tcard): return _x_grid, q2_grid = evolve.write_operator_card_from_file( grid, - self.operator_cards_path - / configs.configs["paths"]["operator_card_template_name"], opcard_path, tcard, ) diff --git a/tests/test_evolve.py b/tests/test_evolve.py index 477e7731..91fb56a9 100644 --- a/tests/test_evolve.py +++ b/tests/test_evolve.py @@ -52,26 +52,3 @@ def metadata(self): return {"convolution_particle_1": 2212, "convolution_particle_2": 11} -def test_write_operator_card_q0(tmp_path): - """Checks https://github.com/NNPDF/pineko/issues/146""" - p = tmp_path / "q0.yaml" - g = FakePine() - t = copy.deepcopy(default_card) - o = copy.deepcopy(example.raw_operator()) - # 1. Same Q0 and init, all ok - t["Q0"] = 5.0 - o["init"] = [5.0, 4] - _xs, _mu2s = pineko.evolve.write_operator_card(g, o, p, t) - with open(p, encoding="utf8") as f: - oo = yaml.safe_load(f) - np.testing.assert_allclose(oo["init"][0], t["Q0"]) - # 2. Q0 only in theory, all ok - o.pop("init") - _xs, _mu2s = pineko.evolve.write_operator_card(g, o, p, t) - with open(p, encoding="utf8") as f: - oo = yaml.safe_load(f) - np.testing.assert_allclose(oo["init"][0], t["Q0"]) - # 3. op is different, raises error - o["init"] = [11.0, 3] - with pytest.raises(ValueError): - _xs, _mu2s = pineko.evolve.write_operator_card(g, o, p, t)