import os
import pkgutil
import re
import shutil
import warnings
from string import Template
from uncertainties import ufloat_fromstr
from hepi.input import Order
from .. import Input, Result, get_output_dir
[docs]
class ResumminoResult(Result):
"""
Resummino Result Data.
Attributes:
VNLO (double): virtual NLO result.
RNLO (double): real NLO result.
P_PLUS_K (double): collineare remainders P+K NLO result.
RNLOG (double): real NLO gluon result.
RNLOQ (double): real NLO quark result.
VNLO_PLUS_P_PLUS_K (double): VNLO+P+K result.
RNLO_PLUS_VNLO_PLUS_P_PLUS_K (double): RNLO+VNLO+P+K result.
"""
def __init__(
self, lo, nlo, nlo_plus_nll, annlo_plus_nnll, vnlo, p_plus_k, rnlog, rnloq
):
"""
Sets given and computes dependent ``Attributes``.
Args:
lo (:obj:`double`): corresponds to :attr:`LO`.
nlo (:obj:`double`): corresponds to :attr:`NLO`.
nlo_plus_nll (:obj:`double`): corresponds to :attr:`NLO_PLUS_NLL`.
vnlo (:obj:`double`): corresponds to :attr:`VNLO`.
p_plus_k (:obj:`double`): corresponds to :attr:`P_PLUS_K`.
rnlog (:obj:`double`): corresponds to :attr:`RNLOG`.
rnloq (:obj:`double`): corresponds to :attr:`RNLOQ`.
"""
Result.__init__(self, lo, nlo, nlo_plus_nll, annlo_plus_nnll)
[docs]
self.P_PLUS_K = p_plus_k
if not (vnlo is None or p_plus_k is None):
self.VNLO_PLUS_P_PLUS_K = self.VNLO + self.P_PLUS_K
else:
self.VNLO_PLUS_P_PLUS_K = None
if not (rnlog is None or rnloq is None):
self.RNLO = rnlog + rnloq
else:
self.RNLO = None
if not (self.RNLO is None or self.VNLO_PLUS_P_PLUS_K is None):
self.RNLO_PLUS_VNLO_PLUS_P_PLUS_K = self.RNLO + self.VNLO_PLUS_P_PLUS_K
else:
self.RNLO_PLUS_VNLO_PLUS_P_PLUS_K = None
[docs]
def is_valid(file: str, p: Input, d, **kwargs) -> bool:
"""
Verifies that an file is a complete output.
Args:
file (str): File path to be parsed.
p (:class:`hepi.Input`): Onput parameters.
d (:obj:`dict`): Param dictionary.
Returns:
bool : True if `file` could be parsed.
"""
order = p.order
data = pkgutil.get_data(__name__, "plot_template.in").decode("utf-8")
src = Template(data)
result = src.substitute(d)
sname = d["slha"]
with open(file, mode="r") as f:
with open(get_output_dir() + sname, "r") as sf:
if not kwargs["ignore_error"] and not f.read().startswith(
result + "\n\n" + sf.read()
):
warnings.warn(
"Possible hash collision in "
+ file
+ " -> moved to "
+ file
+ ".old",
RuntimeWarning,
)
shutil.move(file, file + ".old")
return False
res = parse_single(file)
if res.LO is not None and order is Order.LO:
return True
if res.LO is not None and res.NLO is not None and order is Order.NLO:
return True
if (
res.LO is not None
and res.NLO is not None
and res.NLO_PLUS_NLL is not None
and order is Order.NLO_PLUS_NLL
):
return True
if (
res.LO is not None
and res.NLO is not None
and res.aNNLO_PLUS_NNLL is not None
and order is Order.aNNLO_PLUS_NNLL
):
return True
print("RESTART", res.LO, res.NLO, res.NLO_PLUS_NLL, file)
return False
[docs]
def parse_single(file: str) -> ResumminoResult:
"""
Extracts LO, NLO and NLO+NLL from Resummino output file.
Args:
file (str): File path to be parsed.
Returns:
:class:`ResumminoResult` : If a value is not found in the file None is used.
"""
# TODO generalize units like RS
lo_pattern = re.compile(r"^LO = \((.*)\) pb")
nlo_pattern = re.compile(r"^NLO = \((.*)\) pb")
nll_pattern = re.compile(r"^NLO\+NLL = \((.*)\) pb")
nnll_pattern = re.compile(r"^aNNLO\+NNLL = \((.*)\) pb")
vnlo_pattern = re.compile(r"^vNLO = \((.*)\) pb")
ppk_pattern = re.compile(r"^P\+K = \((.*)\) pb")
rnlog_pattern = re.compile(r"^rNLOg = \((.*)\) pb")
rnloq_pattern = re.compile(r"^rNLOq = \((.*)\) pb")
lo_result = None
nlo_result = None
nll_result = None
nnll_result = None
vnlo_result = None
ppk_result = None
rnlog_result = None
rnloq_result = None
with open(file) as output:
for line in output:
tmp = lo_pattern.search(line)
if tmp is not None:
lo_result = ufloat_fromstr(tmp.group(1).replace("+-", "+/-"))
tmp = nlo_pattern.search(line)
if tmp is not None:
nlo_result = ufloat_fromstr(tmp.group(1).replace("+-", "+/-"))
tmp = nll_pattern.search(line)
if tmp is not None:
nll_result = ufloat_fromstr(tmp.group(1).replace("+-", "+/-"))
tmp = nnll_pattern.search(line)
if tmp is not None:
nnll_result = ufloat_fromstr(tmp.group(1).replace("+-", "+/-"))
tmp = vnlo_pattern.search(line)
if tmp is not None:
vnlo_result = ufloat_fromstr(tmp.group(1).replace("+-", "+/-"))
tmp = ppk_pattern.search(line)
if tmp is not None:
ppk_result = ufloat_fromstr(tmp.group(1).replace("+-", "+/-"))
tmp = rnlog_pattern.search(line)
if tmp is not None:
rnlog_result = ufloat_fromstr(tmp.group(1).replace("+-", "+/-"))
tmp = rnloq_pattern.search(line)
if tmp is not None:
rnloq_result = ufloat_fromstr(tmp.group(1).replace("+-", "+/-"))
if lo_result is not None and lo_result < 0:
warnings.warn("LO < 0")
if nlo_result is not None and nlo_result < 0:
warnings.warn("NLO < 0")
if nll_result is not None and nll_result < 0:
warnings.warn("NLL < 0")
if nnll_result is not None and nnll_result < 0:
warnings.warn("NNLL < 0")
return ResumminoResult(
lo_result,
nlo_result,
nll_result,
nnll_result,
vnlo_result,
ppk_result,
rnlog_result,
rnloq_result,
)