Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NNLOJET runner #65

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
1 change: 0 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ repos:
hooks:
- id: pydocstyle
files: ^src/
args: ["--add-ignore=D107,D105"]
additional_dependencies:
- toml
- repo: https://github.com/pre-commit/pre-commit
Expand Down
550 changes: 335 additions & 215 deletions poetry.lock

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@ appdirs = "^1.4.4"
tomli = "^2.0.1"
yadism = { extras = ["box"], version = "^0.13.5", optional=true, markers = "python_version < '3.13'" }
eko = { extras = ["box"], version = "^0.14.2", optional=true, markers = "python_version < '3.13'" }
nnpdf-data = { version = "*", optional = true}

[tool.poetry.extras]
dis = ["yadism"]
vrap = ["eko"]
constraints = ["dis", "vrap"] # integrability + positivity
complete = ["yadism", "eko"]
complete = ["yadism", "eko", "nnpdf-data"]

[tool.poetry.group.docs]
optional = true
Expand Down Expand Up @@ -118,4 +119,4 @@ max-line-length = 100
max-args = 10

[tool.pydocstyle]
add_ignore = ['D105', 'D107']
add_ignore = ['D401','D105', 'D107']
2 changes: 1 addition & 1 deletion src/pinefarm/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Provide CLI."""

from . import configs, info, install, list, merge, run, update
from . import autogen, configs, info, install, list, merge, run, update
from ._base import command
41 changes: 41 additions & 0 deletions src/pinefarm/cli/autogen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Autogenerate pinecards from NNPDF metadata."""

import click
import rich

from .. import configs
from ..external.nnlojet import generate_pinecard_from_nnpdf
from ._base import command


@command.command("autogen")
@click.argument("dataset", nargs=1)
@click.option(
"--target",
help="Target program. Currently only NNLOJET supported",
default="NNLOJET",
)
@click.option(
"--name", help="Name of the pinecard (NNLOJET_<name>), defaults to name=dataset"
)
@click.option(
"--select-obs",
help="Observables to select from the NNPDF available kinematics (max. 2D distributions)",
type=str,
nargs=2,
)
def runcards(dataset, target, select_obs=None, name=None):
"""Generate a runcard from an NNPDF dataset."""
if name is None:
name = dataset.upper()

output = configs.configs["paths"]["runcards"] / f"{target}_{name}"

if target == "NNLOJET":
output_runcards = generate_pinecard_from_nnpdf(
dataset, output_path=output, observables=select_obs
)

rich.print("Pinecards written to: ")
rich.print(" " + "\n".join(str(i) for i in output_runcards))
rich.print("metadata.txt might be empty or incomplete, please modifiy it manually")
7 changes: 7 additions & 0 deletions src/pinefarm/cli/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,10 @@ def lhapdf():
"""Install LHAPDF."""
install.update_environ()
install.lhapdf()


@subcommand.command()
def nnlojet():
"""Install NNLOJET."""
install.update_environ()
install.nnlojet()
60 changes: 37 additions & 23 deletions src/pinefarm/cli/run.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Compute a dataset and compare using a given PDF."""

import pathlib
import sys
import time

import click
Expand All @@ -16,7 +17,8 @@
@click.argument("dataset")
@click.argument("theory-path", type=click.Path(exists=True))
@click.option("--pdf", default="NNPDF31_nlo_as_0118_luxqed")
def subcommand(dataset, theory_path, pdf):
@click.option("--dry", is_flag=True, help="Don't execute the underlying code")
def subcommand(dataset, theory_path, pdf, dry):
"""Compute a dataset and compare using a given PDF.

Given a DATASET name and a THEORY-PATH, a runcard is executed with the
Expand All @@ -25,46 +27,58 @@ def subcommand(dataset, theory_path, pdf):
The given PDF (default: `NNPDF31_nlo_as_0118_luxqed`) will be used to
compare original results with PineAPPL interpolation.

Parameters
----------
dataset: str
dataset name
theory: dict
theory dictionary
pdf: str
pdf name
"""
# read theory card from file
with open(theory_path) as f:
theory_card = yaml.safe_load(f)
main(dataset, theory_card, pdf)


def main(dataset, theory, pdf):
"""Compute a dataset and compare using a given PDF.

Parameters
----------
dataset : str
dataset name
theory : dict
theory dictionary
pdf : str
pdf name
# Fix (possible) problems with CKM matrix loading
if isinstance(theory_card.get("CKM"), str):
theory_card["CKM"] = [float(i) for i in theory_card["CKM"].split()]

"""
dataset = pathlib.Path(dataset).name
timestamp = None

if "-" in dataset:
dataset_raw, timestamp = dataset.rsplit("-", 1)
try:
dataset, timestamp = dataset.split("-")
# Check whether the timestamp is really an integer
_ = int(timestamp)
dataset = dataset_raw
except ValueError:
raise ValueError(
f"'{dataset}' not valid. '-' is only allowed once,"
" to separate dataset name from timestamp."
)
timestamp = None

rich.print(dataset)

datainfo = info.label(dataset)
try:
datainfo = info.label(dataset)
except UnboundLocalError as e:
raise UnboundLocalError(f"Runcard {dataset} could not be found") from e

rich.print(f"Computing [{datainfo.color}]{dataset}[/]...")
runner = datainfo.external(dataset, theory, pdf, timestamp=timestamp)
runner = datainfo.external(dataset, theory_card, pdf, timestamp=timestamp)

install_reqs(runner, pdf)

# Run the preparation step of the runner (if any)
runner_stop = runner.preparation()
if dry or runner_stop:
rich.print(
f"""Running in dry mode, exiting now.
The preparation step can be found in:
{runner.dest}"""
)
sys.exit(0)

###### <this part will eventually go to -prepare->

run_dataset(runner)


Expand Down
9 changes: 9 additions & 0 deletions src/pinefarm/external/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ def decide_external_tool(dsname: str):
color:
color code of the interface
"""
# The decisions are usually based on the existence of a `.yaml` file with a specific name
# or a prefix in the pinecard

if dsname.startswith("NNLOJET"):
from .nnlojet import NNLOJET

return NNLOJET, "blue"

# DIS with yadism
if (configs["paths"]["runcards"] / dsname / "observable.yaml").exists():
from . import yad # pylint: disable=import-outside-toplevel

Expand Down
4 changes: 4 additions & 0 deletions src/pinefarm/external/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ def install():
# Everybody needs LHAPDF unless explicitly skipped
_ = install.lhapdf()

def preparation(self):
"""Run the preparation method of the runner."""
return False

@abc.abstractmethod
def run(self):
"""Execute the program."""
Expand Down
4 changes: 4 additions & 0 deletions src/pinefarm/external/nnlojet/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"""NNLOJET interface."""

from .nnpdf_interface import generate_pinecard_from_nnpdf
from .runner import NNLOJET
Loading
Loading