diff --git a/doc/sphinx/source/vp/theorycov/examples.rst b/doc/sphinx/source/vp/theorycov/examples.rst index 387d23ed67..61471b8512 100644 --- a/doc/sphinx/source/vp/theorycov/examples.rst +++ b/doc/sphinx/source/vp/theorycov/examples.rst @@ -11,8 +11,7 @@ at NLO. You need to provide the central theory under the ``default_theory`` flag, corresponding to :math:`(\mu_F, \mu_R) = (0,0)`, -which for NLO is theory 163. Under ``theoryids`` you need to provide all the -relevant theories, as outlined above. +which for NLO is theory 163. ``dataspecs`` associates a chosen label (``speclabel``) with each of the theory choices. This details what scale variation the theory corresponds to. @@ -33,10 +32,11 @@ relevant c-factors. default_theory: - theoryid: 163 + theoryid: 163 + point_prescription: '3 point' + theoryids: - - 163 - - 180 - - 173 + from_: scale_variation_theories dataspecs: - theoryid: 163 @@ -203,9 +203,7 @@ matrix against the NNLO-NLO shift. In this case the 5 point prescription is chos and Drell-Yan experiments only are considered. Note that as we are dealing with 5 theories, we need to set the ``fivetheories`` -flag, which in this case is set to ``nobar``. This must be used in conjunction -with the correct ``theoryids`` and ordering of ``theoryids`` in order not to throw -an error. +flag, which in this case is set to ``nobar``. The flag ``orthonormalisation`` corresponds to the method used to orthonormalise the basis vectors of the theory covariance matrix. There are three choices: @@ -401,14 +399,11 @@ For each dataspec we can give the ``_experiments_list_nlo``. theoryconfig: - theoryids: - - 163 - - 177 - - 176 - - 179 - - 174 - theoryid: 163 + point_prescription: '5-point' + + theoryids: + from_: scale_variation_theories use_cuts: fromfit fit: 190315_ern_nlo_central_163_global @@ -433,7 +428,7 @@ For each dataspec we can give the ``_experiments_list_nlo``. speclabel: $(\xi_F,\xi_R)=(1,0.5)$ experiments: *experiments_list_nlo - template: ../../template_test.md + template: template_test.md dataset_report: meta: Null @@ -450,7 +445,7 @@ capturing the NNLO-NLO shift. .. code-block:: md :linenos: - % Theory shift validation test: 9 pts + % Theory shift validation test: 5 pt Non-zero eigenvalues -------------------- @@ -496,5 +491,3 @@ capturing the NNLO-NLO shift. -------------------- {@deltamiss_plot@} - -. diff --git a/doc/sphinx/source/vp/theorycov/point_prescrip.rst b/doc/sphinx/source/vp/theorycov/point_prescrip.rst index cb58e86248..bf994251e8 100644 --- a/doc/sphinx/source/vp/theorycov/point_prescrip.rst +++ b/doc/sphinx/source/vp/theorycov/point_prescrip.rst @@ -7,8 +7,6 @@ appear in ``validphys2``. 3 points -------- -theoryids: 163, 180, 173 - .. math:: s_{11} = \frac{1}{2}\bigg\{ \Delta_1(+,+)^2 + \Delta_1(-,-)^2 \bigg\} .. math:: s_{12} = \frac{1}{4}\bigg\{\bigg(\Delta_1(+,+) + \Delta_1(-,-) \bigg) \bigg(\Delta_2(+,+) + \Delta_2(-,-) \bigg) \bigg\} @@ -17,8 +15,6 @@ theoryids: 163, 180, 173 5 points --------- -theoryids: 163, 177, 176, 179, 174 - .. math:: s_{11} = \frac{1}{2}\bigg\{ \Delta_1(+,0)^2 + \Delta_1(-,0)^2 + \Delta_1(0,+)^2 + \Delta_1(0,-)^2 \bigg\} .. math:: @@ -31,8 +27,6 @@ theoryids: 163, 177, 176, 179, 174 :math:`\mathbf{\overline{5}}` points ------------------------------------ -theoryids: 163, 180, 173, 175, 178 - .. math:: s_{11} = \frac{1}{2}\bigg\{ \Delta_1(+,+)^2 + \Delta_1(-,-)^2 + \Delta_1(+,-)^2 + \Delta_1(-,+)^2 \bigg\} .. math:: @@ -46,7 +40,6 @@ theoryids: 163, 180, 173, 175, 178 ------------------- | Specify in the runcard ``seventheories: original`` -| theoryids: 163, 177, 176, 179, 174, 180, 173 .. math:: @@ -65,8 +58,6 @@ theoryids: 163, 180, 173, 175, 178 7 points - Gavin (default) -------------------------- -theoryids: 163, 177, 176, 179, 174, 180, 173 - .. math:: \begin{split} @@ -86,8 +77,6 @@ theoryids: 163, 177, 176, 179, 174, 180, 173 9 points -------- -theoryids: 163, 177, 176, 179, 174, 180, 173, 175, 178 - .. math:: \begin{split} diff --git a/doc/sphinx/source/vp/theorycov/runcard_layout.rst b/doc/sphinx/source/vp/theorycov/runcard_layout.rst index 8d760da303..35bcd7f8b9 100644 --- a/doc/sphinx/source/vp/theorycov/runcard_layout.rst +++ b/doc/sphinx/source/vp/theorycov/runcard_layout.rst @@ -1,25 +1,15 @@ Important information about runcard layout ========================================== -- **IMPORTANT:** In runcards, theories must be listed according to - points :math:`(\mu_0, \mu_i)` in the following order: :math:`(0,0)`, - :math:`(+,0)`, :math:`(-,0)`, :math:`(0,+)`, :math:`(0,-)`, - :math:`(+,+)`, :math:`(-,-)`, :math:`(+,-)`, :math:`(-,+)`. Here "+" - refers to doubled scale, "-" to halved scale and "0" to central - scale. - -- In terms of ``theoryids``, at NLO this corresponds to: 163, 177, 176, - 179, 174, 180, 173, 175, 178. This ensures that the prescriptions - will be implemented correctly. The ``theoryids`` to input for each - prescription are listed explicitly in the section on point - prescriptions below. If an incorrect configuration of ``theoryids`` - is given, you should receive an error message. - - The flag ``fivetheories`` specifies the choice of 5 or :math:`\bar{5}` prescription for the case of 5 input theories. You must assign a value ``nobar`` or ``bar`` correspondingly. If you do not do this, ``validphys`` will give an error. +- The default behaviour for the 7-point prescription is to use Gavin + Salam's modification to it. To use the original 7-point prescription + instead, the ``seventheories`` flag must be set to ``original``. + - As a fit you must provide the fit for central scales at the relevant order. diff --git a/doc/sphinx/source/vp/theorycov/summary.rst b/doc/sphinx/source/vp/theorycov/summary.rst index 00c23ebfa0..2df834ef25 100644 --- a/doc/sphinx/source/vp/theorycov/summary.rst +++ b/doc/sphinx/source/vp/theorycov/summary.rst @@ -31,19 +31,27 @@ See the `short - Theoretical covariance matrices are built according to the various prescriptions. -- As input you need theories at the relevant scale combinations which - correspond to the prescription. +- As input you need theories for the relevant scale combinations which + correspond to the prescription. This information is taken from the + ``scalevariations`` module, which consists of two files: -- These must be ordered in a specific way in the runcard. + #. ``pointprescriptions.yaml``: correspondence between each point prescription + and the scale combinations that are used to construct it -- The prescription is chosen based on the number of input theories, - which must be one of :math:`\{3,5,7,9\}`. + #. ``scalevariationtheoryids.yaml``: correspondence between each scale combination + and a theoryid for a given central theoryid + +- The prescription must be one of 3 point, 5 point, 7 point or 9 point. - In the case of 5 theories, you must further specify whether the 5 or :math:`\bar{5}` prescription is required. You can do this by allocating the flag ``fivetheories`` to ``nobar`` or ``bar`` in the runcard. +- In the case of 7 theories, there are two options. The default is the + modified prescription that Gavin Salam proposed. To use the original + prescription instead, specify ``seventheories: original`` in the runcard. + - Currently the renormalisation scales are correlated within each process type. These process types are categorised as {DIS CC, DIS NC, Drell-Yan, Jets, Top}. diff --git a/validphys2/setup.py b/validphys2/setup.py index e8435f099b..b2842289cd 100644 --- a/validphys2/setup.py +++ b/validphys2/setup.py @@ -40,6 +40,7 @@ 'comparefit': ['*'], 'tests/baseline': ['*'], 'cuts': ['*'], + 'scalevariations': ['*'], }, zip_safe = False, classifiers=[ diff --git a/validphys2/src/validphys/config.py b/validphys2/src/validphys/config.py index 0f0e140f8e..59c2c9b7e7 100644 --- a/validphys2/src/validphys/config.py +++ b/validphys2/src/validphys/config.py @@ -11,6 +11,7 @@ import numbers import copy import os +from importlib.resources import read_text from collections import ChainMap from collections.abc import Mapping, Sequence @@ -19,7 +20,9 @@ from reportengine.environment import Environment, EnvironmentError_ from reportengine.configparser import ConfigError, element_of, _parse_func from reportengine.helputils import get_parser_type +from reportengine.namespaces import NSList from reportengine import report +from reportengine.compat import yaml from validphys.core import (ExperimentSpec, DataSetInput, ExperimentInput, CutsPolicy, MatchedCuts, ThCovMatSpec) @@ -32,6 +35,8 @@ from validphys.theorycovariance.theorycovarianceutils import process_lookup from validphys.plotoptions import get_info +import validphys.scalevariations + log = logging.getLogger(__name__) class Environment(Environment): @@ -843,7 +848,6 @@ def produce_fit_data_groupby_experiment(self, fit): key in the plotting info file. """ #TODO: consider this an implimentation detail - from reportengine.namespaces import NSList with self.set_context(ns=self._curr_ns.new_child({'fit':fit})): _, experiments = self.parse_from_('fit', 'experiments', write=False) @@ -984,6 +988,76 @@ def produce_defaults(self, q2min=None, w2min=None, filter_defaults={}): return filter_defaults + def produce_scale_variation_theories(self, theoryid, point_prescription): + """Produces a list of theoryids given a theoryid at central scales and a point + prescription. The options for the latter are '3 point', '5 point', '5bar point', '7 point' + and '9 point'. Note that these are defined in arXiv:1906.10698. This hard codes the + theories needed for each prescription to avoid user error.""" + pp = point_prescription + th = theoryid.id + + lsv = yaml.safe_load( + read_text(validphys.scalevariations, "scalevariationtheoryids.yaml") + ) + + scalevarsfor_list = lsv["scale_variations_for"] + # Allowed central theoryids + cent_thids = [ + str(scalevarsfor_dict["theoryid"]) for scalevarsfor_dict in scalevarsfor_list + ] + + if th not in cent_thids: + valid_thids = ", ".join(cent_thids) + raise ConfigError( + "Scale variations are not currently defined for this central theoryid. It is " + + f"currently only possible to use one of the following as the central theory: {valid_thids}. " + + "Please use one of these instead if you wish to include theory uncertainties here." + ) + + # Find scales that correspond to this point prescription + pp_scales_dict = yaml.safe_load( + read_text(validphys.scalevariations, "pointprescriptions.yaml") + ) + + try: + scales = pp_scales_dict[pp] + except KeyError: + valid_pps = ", ".join(pp_scales_dict.keys()) + raise ConfigError( + "Scale variations are not currently defined for this point prescription. This " + + "configuration only works when 'point_prescription' is equal to one of the " + + f"following: {valid_pps}. Please use one of these instead if you wish to " + + "include theory uncertainties here." + ) + + # Get dictionary containing theoryid and variations for central theory from runcard + for scalevarsfor_dict in scalevarsfor_list: + if scalevarsfor_dict["theoryid"] == int(th): + theoryid_variations = scalevarsfor_dict + + # Find theoryids for given point prescription for given central theoryid + try: + thids = [theoryid_variations["variations"][scale] for scale in scales] + except KeyError: + available_scales = list(theoryid_variations["variations"]) + missing_scales = [] + for scale in scales: + if scale not in available_scales: + missing_scales.append(scale) + missing_scales_string = ", ".join(missing_scales) + raise ConfigError( + "For this central theoryid, the requested point prescription is not currently " + + "available. To use this point prescription for this central theoryid, theoryids " + + "that correspond to the following scale choices must be created and added to " + + "validphys2/src/validphys/scalevariations/scalevariationtheoryids.yaml: " + + f"(k_F, k_R) = {missing_scales_string}." + ) + + # Check each theory is loaded + theoryids = [self.loader.check_theoryID(thid) for thid in thids] + # NSList needs to be used for theoryids to be recognised as a namespace + return {"theoryids": NSList(theoryids, nskey="theoryid")} + class Config(report.Config, CoreConfig, ParamfitsConfig): """The effective configuration parser class.""" diff --git a/validphys2/src/validphys/scalevariations/__init__.py b/validphys2/src/validphys/scalevariations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/validphys2/src/validphys/scalevariations/pointprescriptions.yaml b/validphys2/src/validphys/scalevariations/pointprescriptions.yaml new file mode 100644 index 0000000000..5abac68042 --- /dev/null +++ b/validphys2/src/validphys/scalevariations/pointprescriptions.yaml @@ -0,0 +1,8 @@ +# Mapping between a point prescription and the scale combinations that form it +# IMPORTANT: scale combinations must be listed according to (k_F, k_R) in the following order: +# (1, 1), (2, 1), (0.5, 1), (1, 2), (1, 0.5), (2, 2), (0.5, 0.5), (2, 0.5), (0.5, 2) +'3 point': ['(1, 1)', '(2, 2)', '(0.5, 0.5)'] +'5 point': ['(1, 1)', '(2, 1)', '(0.5, 1)', '(1, 2)', '(1, 0.5)'] +'5bar point': ['(1, 1)', '(2, 2)', '(0.5, 0.5)', '(2, 0.5)', '(0.5, 2)'] +'7 point': ['(1, 1)', '(2, 1)', '(0.5, 1)', '(1, 2)', '(1, 0.5)', '(2, 2)', '(0.5, 0.5)'] +'9 point': ['(1, 1)', '(2, 1)', '(0.5, 1)', '(1, 2)', '(1, 0.5)', '(2, 2)', '(0.5, 0.5)', '(2, 0.5)', '(0.5, 2)'] diff --git a/validphys2/src/validphys/scalevariations/scalevariationtheoryids.yaml b/validphys2/src/validphys/scalevariations/scalevariationtheoryids.yaml new file mode 100644 index 0000000000..b535322e41 --- /dev/null +++ b/validphys2/src/validphys/scalevariations/scalevariationtheoryids.yaml @@ -0,0 +1,13 @@ +# The format of the scale combinations is (k_F, k_R) +scale_variations_for: + - theoryid: 163 + variations: + (0.5, 0.5): 173 + (0.5, 1): 176 + (0.5, 2): 178 + (1, 0.5): 174 + (1, 1): 163 + (1, 2): 179 + (2, 0.5): 175 + (2, 1): 177 + (2, 2): 180