From c1fe1839071287928cc41fa63c39a60974aa19bb Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 23 Jul 2024 18:05:25 +0200 Subject: [PATCH] update compare and convolve to accept multiple pdfs --- docs/source/overview/running.rst | 4 +- pyproject.toml | 2 +- src/pineko/cli/compare.py | 10 +++-- src/pineko/cli/convolve.py | 73 ++++++++++++++++++++++++-------- src/pineko/comparator.py | 62 +++++++++++++++++++++------ src/pineko/evolve.py | 14 +++--- 6 files changed, 123 insertions(+), 42 deletions(-) diff --git a/docs/source/overview/running.rst b/docs/source/overview/running.rst index e2920989..fe2bb123 100644 --- a/docs/source/overview/running.rst +++ b/docs/source/overview/running.rst @@ -50,7 +50,7 @@ Then you can convolve the |EKO| with the grids by running:: Note that you can also convolve a single grid with a single eko (obtaining a single FK table) by running:: - pineko convolve GRID OPCARD FKTABLE MAX_AS MAX_AL + pineko convolve GRID FKTABLE MAX_AS MAX_AL OP_PATH_1 OP_PATH_2 If necessary it is possible to specify the values of the *renormalization* and *factorization* scale variations with the options ``--xir`` and ``--xif``. @@ -91,7 +91,7 @@ Comparing grids and FK tables With the command ``pineko compare`` it is possible to compare the predictions as provided by the grid (convolved with a |PDF|) with the predictions as provided by the |FK| table. This is done like - pineko compare GRID FKTABLE MAX_AS MAX_AL PDF + pineko compare GRID FKTABLE MAX_AS MAX_AL PDF_1 PDF_2 again eventually specifying the values of *renormalization* and *factorization* scales with the appropriate options. diff --git a/pyproject.toml b/pyproject.toml index 4f21eeba..1db36a65 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ packages = [{ include = "pineko", from = "src" }] [tool.poetry.dependencies] python = ">=3.9,<3.13" eko = "^0.14.2" -pineappl = "^0.8.1" +pineappl = "^0.8.2" PyYAML = "^6.0" numpy = "^1.21.0" pandas = "^2.1" diff --git a/src/pineko/cli/compare.py b/src/pineko/cli/compare.py index 6a85e2c9..f018dc1a 100644 --- a/src/pineko/cli/compare.py +++ b/src/pineko/cli/compare.py @@ -13,10 +13,10 @@ @click.argument("fktable_path", type=click.Path()) @click.argument("max_as", type=int) @click.argument("max_al", type=int) -@click.argument("pdf", type=str) +@click.argument("pdfs", type=click.STRING, nargs=-1) @click.option("--xir", default=1.0, help="renormalization scale variation") @click.option("--xif", default=1.0, help="factorization scale variation") -def subcommand(pineappl_path, fktable_path, max_as, max_al, pdf, xir, xif): +def subcommand(pineappl_path, fktable_path, max_as, max_al, pdfs, xir, xif): """Compare process level PineAPPL grid and derived FK Table. The comparison between the grid stored at PINEAPPL_PATH, and the FK table @@ -31,5 +31,9 @@ def subcommand(pineappl_path, fktable_path, max_as, max_al, pdf, xir, xif): """ pine = pineappl.grid.Grid.read(pineappl_path) fk = pineappl.fk_table.FkTable.read(fktable_path) + pdf1 = pdfs[0] + pdf2 = pdfs[1] if len(pdfs) == 2 else None # Note that we need to cast to string before printing to avoid ellipsis ... - rich.print(comparator.compare(pine, fk, max_as, max_al, pdf, xir, xif).to_string()) + rich.print( + comparator.compare(pine, fk, max_as, max_al, pdf1, xir, xif, pdf2).to_string() + ) diff --git a/src/pineko/cli/convolve.py b/src/pineko/cli/convolve.py index abb35c16..e197b95d 100644 --- a/src/pineko/cli/convolve.py +++ b/src/pineko/cli/convolve.py @@ -11,15 +11,21 @@ @command.command("convolve") @click.argument("grid_path", type=click.Path(exists=True)) -@click.argument("op_path", type=click.Path(exists=True)) @click.argument("fktable", type=click.Path()) @click.argument("max_as", type=int) @click.argument("max_al", type=int) +@click.argument("op_paths", type=click.Path(exists=True), nargs=-1) @click.option("--xir", default=1.0, help="renormalization scale variation") @click.option("--xif", default=1.0, help="factorization scale variation") @click.option("--min_as", type=int, help="Minimum exponent of as") @click.option( - "--pdf", default=None, help="if given, print comparison table", show_default=True + "--pdf1", + default=None, + help="PDF for the first convolution. If given, print comparison table", + show_default=True, +) +@click.option( + "--pdf2", default=None, help="PDF for the second convolution.", show_default=True ) @click.option( "--assumptions", @@ -28,11 +34,22 @@ show_default=True, ) def subcommand( - grid_path, op_path, fktable, max_as, max_al, xir, xif, pdf, assumptions, min_as + grid_path, + fktable, + max_as, + max_al, + op_paths, + xir, + xif, + pdf1, + pdf2, + assumptions, + min_as, ): """Convolute PineAPPL grid and EKO into an FK table. - GRID_PATH and OP_PATH are the path to the respective elements to convolve, and + GRID_PATH and OP_PATH are the path to the respective elements to convolve. + Note that multiple operators are allowed. FKTABLE is the path where to dump the output. MAX_AS and MAX_AL are used to specify the order in QCD and QED @@ -50,26 +67,46 @@ def subcommand( PDF is an optional PDF set compatible with the EKO to compare grid and FK table. """ grid = pineappl.grid.Grid.read(grid_path) - with eko.EKO.edit(op_path) as operators: + n_ekos = len(op_paths) + with eko.EKO.edit(op_paths[0]) as operators_a: rich.print( rich.panel.Panel.fit("Computing ...", style="magenta", box=rich.box.SQUARE), f" {grid_path}\n", - f"+ {op_path}\n", + f"+ {op_paths}\n", f"= {fktable}\n", f"with max_as={max_as}, max_al={max_al}, xir={xir}, xif={xif}", f"min_as: {min_as}" if min_as is not None else "", ) - _grid, _fk, comp = evolve.evolve_grid( - grid, - operators, - fktable, - max_as, - max_al, - xir, - xif, - assumptions=assumptions, - comparison_pdf=pdf, - min_as=min_as, - ) + if n_ekos == 1: + _grid, _fk, comp = evolve.evolve_grid( + grid, + operators_a, + fktable, + max_as, + max_al, + xir, + xif, + assumptions=assumptions, + comparison_pdf1=pdf1, + comparison_pdf2=pdf2, + min_as=min_as, + ) + else: + with eko.EKO.edit(op_paths[1]) as operators_b: + _grid, _fk, comp = evolve.evolve_grid( + grid, + operators_a, + fktable, + max_as, + max_al, + xir, + xif, + operators_b=operators_b, + assumptions=assumptions, + comparison_pdf1=pdf1, + comparison_pdf2=pdf2, + min_as=min_as, + ) + if comp is not None: print(comp.to_string()) diff --git a/src/pineko/comparator.py b/src/pineko/comparator.py index 090b9026..2c445785 100644 --- a/src/pineko/comparator.py +++ b/src/pineko/comparator.py @@ -5,7 +5,7 @@ import pineappl -def compare(pine, fktable, max_as, max_al, pdf, xir, xif): +def compare(pine, fktable, max_as, max_al, pdf1, xir, xif, pdf2=None): """Build comparison table. Parameters @@ -18,12 +18,14 @@ def compare(pine, fktable, max_as, max_al, pdf, xir, xif): maximum power of strong coupling max_al : int maximum power of electro-weak coupling - pdf : str + pdf1 : str PDF set name xir : float renormalization scale variation xif : float factorization scale variation + pdf2: str or None + PDF set for the second convolution, if different from the first Returns ------- @@ -32,19 +34,53 @@ def compare(pine, fktable, max_as, max_al, pdf, xir, xif): """ import lhapdf # pylint: disable=import-error,import-outside-toplevel - pdfset = lhapdf.mkPDF(pdf, 0) - pdgid = int(pdfset.set().get_entry("Particle")) + pdfset1 = lhapdf.mkPDF(pdf1, 0) + pdgid1 = int(pdfset1.set().get_entry("Particle")) + + if pdf2 is not None: + pdfset2 = lhapdf.mkPDF(pdf1, 0) + pdgid2 = int(pdfset2.set().get_entry("Particle")) + else: + pdfset2 = pdfset1 + pdgid2 = pdgid1 + + try: + parton1 = pine.key_values()["convolution_particle_1"] + parton2 = pine.key_values()["convolution_particle_2"] + except KeyError: + parton1 = pine.key_values()["initial_state_1"] + parton2 = pine.key_values()["initial_state_2"] + hadronic = parton1 == parton2 + order_mask = pineappl.grid.Order.create_mask(pine.orders(), max_as, max_al, True) - before = np.array( - pine.convolve_with_one( - pdgid, - pdfset.xfxQ2, - pdfset.alphasQ2, - order_mask=order_mask, - xi=((xir, xif),), + if hadronic: + before = np.array( + pine.convolve_with_two( + pdgid1, + pdfset1.xfxQ2, + pdfset1.alphasQ2, + pdgid2, + pdfset2.xfxQ2, + pdfset2.alphasQ2, + order_mask=order_mask, + xi=((xir, xif),), + ) ) - ) - after = np.array(fktable.convolve_with_one(pdgid, pdfset.xfxQ2)) + after = np.array( + fktable.convolve_with_one(pdgid1, pdfset1.xfxQ2, pdgid2, pdfset2.xfxQ2) + ) + else: + before = np.array( + pine.convolve_with_one( + pdgid1, + pdfset1.xfxQ2, + pdfset1.alphasQ2, + order_mask=order_mask, + xi=((xir, xif),), + ) + ) + after = np.array(fktable.convolve_with_one(pdgid1, pdfset1.xfxQ2)) + df = pd.DataFrame() # add bin info for d in range(pine.bin_dimensions()): diff --git a/src/pineko/evolve.py b/src/pineko/evolve.py index f6d79a9e..a8c741b5 100644 --- a/src/pineko/evolve.py +++ b/src/pineko/evolve.py @@ -279,7 +279,8 @@ def evolve_grid( xif, operators_b=None, assumptions="Nf6Ind", - comparison_pdf=None, + comparison_pdf1=None, + comparison_pdf2=None, meta_data=None, min_as=None, ): @@ -305,8 +306,10 @@ def evolve_grid( additonal evolution operator if different from operators_a assumptions : str assumptions on the flavor dimension - comparison_pdf : None or str + comparison_pdf1 : None or str if given, a comparison table (with / without evolution) will be printed + comparison_pdf2 : None or str + PDF set for the second convolution if different from the first one meta_data : None or dict if given, additional meta data written to the FK table min_as: None or int @@ -421,12 +424,13 @@ def prepare(operator, items): fktable.set_key_value(k, v) # compare before/after comparison = None - if comparison_pdf is not None: + if comparison_pdf1 is not None: comparison = comparator.compare( - grid, fktable, max_as, max_al, comparison_pdf, xir, xif + grid, fktable, max_as, max_al, comparison_pdf1, xir, xif, comparison_pdf2 ) fktable.set_key_value("results_fk", comparison.to_string()) - fktable.set_key_value("results_fk_pdfset", comparison_pdf) + fktable.set_key_value("results_fk_pdfset1", comparison_pdf1) + fktable.set_key_value("results_fk_pdfset2", comparison_pdf2) # write fktable.write_lz4(str(fktable_path)) return grid, fktable, comparison