Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ repos:
- id: pydocstyle
files: ^src/
additional_dependencies:
- toml
- tomli
- repo: https://github.com/pre-commit/pre-commit
rev: v4.5.1
hooks:
Expand Down
34 changes: 17 additions & 17 deletions extras/theories/theory_nnlo.yaml
Original file line number Diff line number Diff line change
@@ -1,44 +1,44 @@
ID: NNLO
Comments: Example of NNLO theory
CKM: 0.97428 0.22530 0.003470 0.22520 0.97345 0.041000 0.00862 0.04030 0.999152
CKM: 0.97367 0.22431 3.82e-3 0.221 0.975 41.1e-3 8.6e-3 41.5e-3 1.010
DAMP: 0
EScaleVar: 1
FNS: FONLL-C
GF: 1.1663787e-05
GF: 1.1663788e-5
HQ: POLE
IC: 1
IB: 0
MP: 0.938
MW: 80.398
MZ: 91.1876
MZ: 91.1880
MW: 80.3692
MaxNfAs: 5
MaxNfPdf: 5
ModEv: TRN
ModEv: EXA
IterEv: 60
ModSV: expanded
NfFF: 4
PTO: 2
Q0: 1.65
QED: 0
Qedref: 1.777
Qmb: 4.92
Qmc: 1.51
Qmt: 172.5
Qref: 91.2
SIN2TW: 0.23126
Qedref: 91.1880
Qref: 91.1880
alphas: 0.118
alphaqed: 0.0075700
SIN2TW: 0.22348
SxOrd: LL
SxRes: 0
TMC: 1
XIF: 1.0
XIR: 1.0
alphaqed: 0.007496252
alphas: 0.118
global_nx: 0
kbThr: 1.0
mc: 1.502
Qmc: 1.502
kcThr: 1.0
ktThr: 1.0
mb: 4.92
mc: 1.51
mb: 4.936
Qmb: 4.936
kbThr: 1.0
mt: 172.5
Qmt: 172.5
nfref: null
nf0: null
fact_to_ren_scale_ratio: 1.0
Expand Down
4 changes: 3 additions & 1 deletion src/pinefarm/cli/autogen.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ def runcards(dataset, target, select_obs=None, name=None):

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

if target == "NNLOJET":
if target.upper() == "NNLOJET":
output_runcards = generate_pinecard_from_nnpdf(
dataset, output_path=output, observables=select_obs
)
else:
raise ValueError(f"Target {target} not recognized")

rich.print("Pinecards written to: ")
rich.print(" " + "\n".join(str(i) for i in output_runcards))
Expand Down
2 changes: 1 addition & 1 deletion src/pinefarm/external/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def decide_external_tool(dsname: str):
"""
# 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"):
if dsname.upper().startswith("NNLOJET"):
from .nnlojet import NNLOJET

return NNLOJET, "blue"
Expand Down
57 changes: 42 additions & 15 deletions src/pinefarm/external/nnlojet/nnpdf_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
yaml.default_flow_style = False
yaml.indent(sequence=4, offset=2, mapping=4)

HISTOGRAM_VARIABLES = {"y", "etay", "eta", "pT", "pT2", "M2"}
HISTOGRAM_VARIABLES = {"y", "etay", "eta", "pT", "pT2", "M2", "ET"}


def _legacy_nnpdf_translation(df, proc_type):
Expand Down Expand Up @@ -88,23 +88,28 @@ def _1d_histogram(kin_df, hist_var):
def _nnlojet_observable(observable, process):
"""Try to automatically understand the NNLOJET observables given the NNPDF process and obs."""
observable = observable.lower()
process = process.upper()
if observable in ("eta", "y", "etay"):
if process.upper().startswith("Z"):
if process.startswith("Z"):
return "yz"
if process.upper().startswith("WP") and not process.upper().endswith("J"):
if process.startswith("WP") and not process.endswith("J"):
return "ylp"
if process.upper().startswith("WM") and not process.upper().endswith("J"):
if process.startswith("WM") and not process.endswith("J"):
return "ylm"
if process.startswith("GJ"):
return "y_gam"
if observable == "pt":
if process.upper().startswith("Z"):
if process.startswith("Z"):
return "ptz"
if process.upper().startswith("W"):
if process.startswith("W"):
return "ptw"
if observable == "m" and process.upper().startswith("Z"):
if observable == "m" and process.startswith("Z"):
return "mll"
if observable == "m2":
print("\033[91m [WARNING] \033[0m Changed M2 to M in the selectors")
return "mll"
if observable == "et" and process.startswith("GJ"):
return "pt_gam"

raise ValueError(f"Observable {observable} not recognized for process {process}")

Expand Down Expand Up @@ -193,9 +198,17 @@ def _generate_nnlojet_pinecard(runname, process, energy, experiment, histograms)
"""Generate a pinecard for NNLOJET runs from an NNPDF dataset."""
selectors = select_selectors(experiment, process)
histograms = deepcopy(histograms)
photon = {}

# Digest the process variable
if process.startswith("Z0"):
process = process.replace("Z0", "Z")
if process.startswith("G"):
# Defaults for: 2302.00510
photon = {
"photon_isolation": "etsum[R=0.4, ETmax_const=4.8, ETmax_epsilon=0.0042, ET_threshold=0]",
"photon_fragmentation": "BFG2",
}

# Digest the histogram variable
for histo in histograms:
Expand All @@ -204,7 +217,7 @@ def _generate_nnlojet_pinecard(runname, process, energy, experiment, histograms)

ret = {
"runname": runname,
"process": {"proc": process, "sqrts": energy},
"process": {"proc": process, "sqrts": energy, **photon},
"pdf": "NNPDF40_nnlo_as_01180",
"techcut": 1e-7,
"histograms": histograms,
Expand All @@ -227,11 +240,21 @@ def _generate_nnlojet_pinecard(runname, process, energy, experiment, histograms)
},
"selectors": selectors,
}

# Add the scale
if process.startswith("Z"):
ret["scales"] = {"mur": "etz", "muf": "etz"}
elif process.startswith("W"):
ret["scales"] = {"mur": "etw", "muf": "etw"}
elif process.startswith("G"):
# Defaults for: 2302.00510 R=0.4
ret["scales"] = {"mur": "pt_gam", "muf": "[pt_gam, 0.871*sqrt_pt_gam]"}

return ret


def generate_pinecard_from_nnpdf(
nnpdf_dataset, scale="etz", output_path=".", observables=None
nnpdf_dataset, scale=None, output_path=".", observables=None
):
"""Generate a NNLOJET pinecard from an NNPDF dataset.

Expand Down Expand Up @@ -277,6 +300,8 @@ def generate_pinecard_from_nnpdf(
if "M2" in hist_vars:
if len(kin_df["M2"]["mid"].unique()) == 1:
hist_vars.remove("M2")
elif process.startswith("PH"):
process = process.replace("PH", "GJ")

# Create the histogram depending on whether this is a 1D or 2D distribution (or total)
histograms = None
Expand All @@ -286,10 +311,10 @@ def generate_pinecard_from_nnpdf(
elif len(hist_vars) == 2:

# Let's see whether we know how to do this 2D distribution
if "M2" in hist_vars:
svar = "M2"
elif "y" in hist_vars:
svar = "y"
for var_i_know in ["M2", "y", "eta"]:
if var_i_know in hist_vars:
svar = var_i_know
break
else:
raise NotImplementedError(f"Don't know how to do this 2D: {hist_vars}")
hist_vars.remove(svar)
Expand Down Expand Up @@ -349,7 +374,7 @@ def generate_pinecard_from_nnpdf(
processes = [process]
if process.startswith("WPWM"):
processes = [process.replace("WP", ""), process.replace("WM", "")]
if process == "DY":
elif process == "DY":
processes = ["Z0", "WP", "WM"]

parent_folder = output_path.parent
Expand All @@ -360,7 +385,9 @@ def generate_pinecard_from_nnpdf(
runname = nnpdf_dataset.replace(process, proc)

ret = _generate_nnlojet_pinecard(runname, proc, energy, experiment, histograms)
ret["scales"] = {"mur": scale, "muf": scale}
if scale is not None:
# Default to etz
ret["scales"] = {"mur": scale, "muf": scale}

# Beautify before dumping
data = CommentedMap(ret)
Expand Down
13 changes: 10 additions & 3 deletions src/pinefarm/external/nnlojet/runcardgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,14 +222,19 @@ def parse_input_yaml(yaml_path):


def _fill_process(process):
"""Fill process options."""
"""Fill process block given the metadata for the process"""
process_name = process["proc"]
sqrts = process["sqrts"]
"""Fill process block given the metadata for the process"""
jet = process.get("jet", "none[0]") # Can be None
fill_photon = ""
if process_name.startswith("G"):
fill_photon = f"""
photon_isolation = {process['photon_isolation']}
photon_fragmentation = {process['photon_fragmentation']}"""
return f"""
PROCESS {process_name}
collider = pp sqrts = {sqrts}
jet = none[0]
jet = {jet}{fill_photon}
decay_type = 1
END_PROCESS
"""
Expand All @@ -239,6 +244,7 @@ def _fill_run(runname, pdf, mode_line, techcut=1e-7, multi_channel=3):
"""Fil run options."""
if multi_channel == 0:
multi_channel = ".false."
# Note, scale coefficients need to be set to true to fill the grid
return f"""
RUN {runname.upper()}
PDF = {pdf}[0]
Expand Down Expand Up @@ -268,6 +274,7 @@ def _fill_parameters(theory_parameters):
return f"""
PARAMETERS
{ptext}
hard_photon_alpha0 = .true. ! only useful for GJ runs
END_PARAMETERS
"""

Expand Down
5 changes: 5 additions & 0 deletions src/pinefarm/external/nnlojet/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ def __init__(self, pinecard, theorycard, *args, **kwargs):
# Save the yaml dictionary from the NNLOJET pinecard
self._yaml_dict = safe_load(yaml_card.open("r"))

@staticmethod
def install():
"""NNLOJET should be installed manually."""
pass

def preparation(self):
"""Run the preparation step for NNLOJET."""
# Update the yaml card according to the theory
Expand Down
1 change: 0 additions & 1 deletion src/pinefarm/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,6 @@ def lhapdf():

This is currently needed by every tool due to postprocessing requirements.
"""

def installed():
"""Define availability condition."""
try:
Expand Down
Loading