Skip to content

Commit

Permalink
Merge pull request #2198 from NNPDF/update_th_covmat
Browse files Browse the repository at this point in the history
Sum covmats from various point prescriptions
  • Loading branch information
scarlehoff authored Nov 18, 2024
2 parents f403018 + 9baef9e commit 375b6e8
Show file tree
Hide file tree
Showing 20 changed files with 1,548 additions and 1,012 deletions.
5 changes: 1 addition & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ jobs:
matrix:
os: [ubuntu-latest, macos-14]
python-version: ["3.12"] # Test only the latest python in all system
include:
- os: ubuntu-latest # Test also the oldest python supported in ubuntu
python-version: "3.9"
fail-fast: false
runs-on: ${{ matrix.os }}
env:
Expand Down Expand Up @@ -54,7 +51,7 @@ jobs:
$CONDA_PREFIX/conda-bld/noarch/*.tar.bz2 \
[email protected]:~/packages/conda/noarch
- name: Build and upload sphinx documentation to NNPDF server
if: startsWith(matrix.os, 'ubuntu') && github.ref == 'refs/heads/master' && matrix.python-version == '3.9'
if: startsWith(matrix.os, 'ubuntu') && github.ref == 'refs/heads/master'
shell: bash -l {0}
run: |
KEY=$( mktemp )
Expand Down
12 changes: 2 additions & 10 deletions doc/sphinx/source/tutorials/general_th_covmat.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ Instructions
############################################################################
theorycovmatconfig:
use_scalevar_uncertainties: False
use_user_uncertainties: True
user_covmat_path: "IeGM9CY8RxGcb5r6bIEYlQ==/topthcovmat.csv"
use_thcovmat_in_sampling: True
use_thcovmat_in_fitting: True
Expand All @@ -57,16 +55,10 @@ generation). The default is ``True`` for both.
Changing either of these to ``False`` will affect the fit outcome and should
be avoided unless you know what you are doing.


4. The flag ``use_scalevar_uncertainties`` corresponds to whether or not a
theory covmat is to be constructed from a pointprescription with instructions
inside ``theorycovmatconfig``. Usually in cases where a custom covmat is
being loaded, this will be set to ``False``.

5. Make sure that datasets are grouped under one big experiment called "BIGEXP",
1. Make sure that datasets are grouped under one big experiment called "BIGEXP",
just like in :ref:`vptheorycov-index`.

6. For an example runcard, see `here <https://github.com/NNPDF/nnpdf/tree/master/validphys2/examples/fit_with_user_covmat.yaml.>`_
2. For an example runcard, see `here <https://github.com/NNPDF/nnpdf/tree/master/validphys2/examples/fit_with_user_covmat.yaml.>`_


Including both scale variation uncertainties and user uncertainties
Expand Down
4 changes: 1 addition & 3 deletions n3fit/runcards/examples/Fit_with_theory_covmat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ datacuts:
theory:
theoryid: 708 # database id
theorycovmatconfig:
point_prescription: "9 point"
theoryids:
from_: scale_variation_theories
point_prescriptions: ["9 point", "3 point"]
pdf: NNPDF31_nlo_as_0118
use_thcovmat_in_fitting: true
use_thcovmat_in_sampling: true
Expand Down
4 changes: 1 addition & 3 deletions n3fit/runcards/examples/nnpdfpol20_dis_nlo_mhou.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ theory:
theoryid: 41_100_010

theorycovmatconfig:
point_prescription: '7 point'
theoryids:
from_: scale_variation_theories
point_prescriptions: ['7 point']
pdf: NNPDFpol11_100
unpolarized_bc: NNPDF40_nlo_pch_as_01180
use_thcovmat_in_fitting: true
Expand Down
12 changes: 0 additions & 12 deletions n3fit/src/n3fit/scripts/n3fit_exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ def from_yaml(cls, o, *args, **kwargs):
N3FIT_FIXED_CONFIG['positivity_bound'] = None

# Theorycovmat flags and defaults
N3FIT_FIXED_CONFIG['theory_covmat_flag'] = False
N3FIT_FIXED_CONFIG['use_thcovmat_in_fitting'] = False
N3FIT_FIXED_CONFIG['use_thcovmat_in_sampling'] = False
if (thconfig := file_content.get('theorycovmatconfig')) is not None:
Expand All @@ -166,17 +165,6 @@ def from_yaml(cls, o, *args, **kwargs):
N3FIT_FIXED_CONFIG['use_thcovmat_in_sampling'] = thconfig.get(
'use_thcovmat_in_sampling', True
)
if (
N3FIT_FIXED_CONFIG['use_thcovmat_in_sampling']
or N3FIT_FIXED_CONFIG['use_thcovmat_in_fitting']
):
N3FIT_FIXED_CONFIG['theory_covmat_flag'] = True
N3FIT_FIXED_CONFIG['use_user_uncertainties'] = thconfig.get(
'use_user_uncertainties', False
)
N3FIT_FIXED_CONFIG['use_scalevar_uncertainties'] = thconfig.get(
'use_scalevar_uncertainties', True
)
# Fitting flag
file_content.update(N3FIT_FIXED_CONFIG)
return cls(file_content, *args, **kwargs)
Expand Down
9 changes: 8 additions & 1 deletion n3fit/src/n3fit/scripts/vp_setupfit.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,14 @@ def from_yaml(cls, o, *args, **kwargs):
filter_action = 'datacuts::theory::fitting filter'
check_n3fit_action = 'datacuts::theory::fitting n3fit_checks_action'
SETUPFIT_FIXED_CONFIG['actions_'] += [check_n3fit_action, filter_action]
if file_content.get('theorycovmatconfig') is not None:
if (thconfig := file_content.get('theorycovmatconfig')) is not None:
if thconfig.get('point_prescription') is not None:
raise ConfigError(
"`point_prescription` has been removed in favor of a list of "
"`point_prescriptions`. The options that can be included in the list are found "
"in pointprescriptions.yaml. E.g. \n"
"`point_prescriptions: ['9 point', '3 point']`"
)
SETUPFIT_FIXED_CONFIG['actions_'].append(
'datacuts::theory::theorycovmatconfig nnfit_theory_covmat'
)
Expand Down
2 changes: 0 additions & 2 deletions validphys2/examples/data_theory_comparison_w_sv.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ use_cuts: "internal"

theoryid: 717 # define the central theory
point_prescription: "3 point"
theoryids:
from_: scale_variation_theories
use_theorycovmat: true

use_pdferr: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ theoryid: 163
point_prescription: '3 point'


theoryids:
from_: scale_variation_theories

dataspecs:
- theoryid: 163
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ default_theory:
theoryid: 163
point_prescription: '9 point'

theoryids:
from_: scale_variation_theories


dataspecs:
- theoryid: 163
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ theoryconfig: # For generating theory covariance matrix

theoryid: 163

theoryids:
from_: scale_variation_theories

point_prescription: '3 point'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@ theoryconfig: # For generating theory covariance matrix

theoryid: 163

theoryids:
from_: scale_variation_theories

point_prescription: '9 point'

use_cuts: fromfit
Expand Down
79 changes: 32 additions & 47 deletions validphys2/src/validphys/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,8 @@ def produce_replicas(self, nreplica: int):
"""Produce a replicas array"""
return NSList(range(1, nreplica + 1), nskey="replica")

def produce_inclusive_use_scalevar_uncertainties(
self, use_scalevar_uncertainties: bool = False, point_prescription: (str, None) = None
):
"""Whether to use a scale variation uncertainty theory covmat.
Checks whether a point prescription is included in the runcard and if so
assumes scale uncertainties are to be used."""
if (not use_scalevar_uncertainties) and (point_prescription is not None):
use_scalevar_uncertainties = True
return use_scalevar_uncertainties
def parse_point_prescriptions(self, point_prescriptions):
return NSList(point_prescriptions, nskey="point_prescription")

# TODO: load fit config from here
@element_of("fits")
Expand Down Expand Up @@ -736,9 +729,7 @@ def produce_experiment_from_input(self, experiment_input, theoryid, use_cuts, fi
}

@configparser.explicit_node
def produce_dataset_inputs_fitting_covmat(
self, theory_covmat_flag=False, use_thcovmat_in_fitting=False
):
def produce_dataset_inputs_fitting_covmat(self, use_thcovmat_in_fitting=False):
"""
Produces the correct covmat to be used in fitting_data_dict according
to some options: whether to include the theory covmat, whether to
Expand All @@ -747,7 +738,7 @@ def produce_dataset_inputs_fitting_covmat(
"""
from validphys import covmats

if theory_covmat_flag and use_thcovmat_in_fitting:
if use_thcovmat_in_fitting:
return covmats.dataset_inputs_t0_total_covmat
return covmats.dataset_inputs_t0_exp_covmat

Expand All @@ -758,7 +749,7 @@ def produce_sep_mult(self, separate_multiplicative=False):

@configparser.explicit_node
def produce_dataset_inputs_sampling_covmat(
self, sep_mult=False, theory_covmat_flag=False, use_thcovmat_in_sampling=False
self, sep_mult=False, use_thcovmat_in_sampling=False
):
"""
Produces the correct covmat to be used in make_replica according
Expand All @@ -767,7 +758,7 @@ def produce_dataset_inputs_sampling_covmat(
"""
from validphys import covmats

if theory_covmat_flag and use_thcovmat_in_sampling:
if use_thcovmat_in_sampling:
if sep_mult:
return covmats.dataset_inputs_total_covmat_separate
else:
Expand All @@ -782,20 +773,21 @@ def produce_loaded_theory_covmat(
self,
output_path,
data_input,
theory_covmat_flag=False,
use_user_uncertainties=False,
use_scalevar_uncertainties=True,
user_covmat_path=None,
point_prescriptions=None,
use_thcovmat_in_sampling=False,
use_thcovmat_in_fitting=False,
):
"""
Loads the theory covmat from the correct file according to how it
was generated by vp-setupfit.
"""
if theory_covmat_flag is False:
if not use_thcovmat_in_sampling and not use_thcovmat_in_fitting:
return 0.0
# Load correct file according to how the thcovmat was generated by vp-setupfit
generic_path = "datacuts_theory_theorycovmatconfig_theory_covmat_custom.csv"
if use_user_uncertainties is True:
if use_scalevar_uncertainties is True:
if user_covmat_path is not None:
if point_prescriptions is not None:
generic_path = "datacuts_theory_theorycovmatconfig_total_theory_covmat.csv"
else:
generic_path = "datacuts_theory_theorycovmatconfig_user_covmat.csv"
Expand Down Expand Up @@ -1152,15 +1144,13 @@ def parse_lumi_channel(self, ch: str):
def produce_all_lumi_channels(self):
return {"lumi_channels": self.parse_lumi_channels(list(LUMI_CHANNELS))}

def produce_loaded_user_covmat_path(
self, user_covmat_path: str = "", use_user_uncertainties: bool = False
):
def produce_loaded_user_covmat_path(self, user_covmat_path: str = ""):
"""
Path to the user covmat provided by user_covmat_path in the runcard.
If no path is provided, returns None.
For use in theorycovariance.construction.user_covmat.
"""
if not use_user_uncertainties:
if user_covmat_path is None:
return None
else:
l = self.loader
Expand All @@ -1169,26 +1159,26 @@ def produce_loaded_user_covmat_path(

@configparser.explicit_node
def produce_nnfit_theory_covmat(
self, inclusive_use_scalevar_uncertainties, use_user_uncertainties: bool = False
self, point_prescriptions: list = None, user_covmat_path: str = None
):
"""
Return the theory covariance matrix used in the fit.
This function is only used in vp-setupfit to store the necessary covmats as .csv files in
the tables directory.
"""
if inclusive_use_scalevar_uncertainties:
if use_user_uncertainties:
if point_prescriptions is not None:
if user_covmat_path is not None:
# Both scalevar and user uncertainties
from validphys.theorycovariance.construction import total_theory_covmat_fitting

f = total_theory_covmat_fitting
else:
# Only scalevar uncertainties
from validphys.theorycovariance.construction import theory_covmat_custom_fitting
from validphys.theorycovariance.construction import theory_covmat_custom

f = theory_covmat_custom_fitting
elif use_user_uncertainties:
f = theory_covmat_custom
elif user_covmat_path is not None:
# Only user uncertainties
from validphys.theorycovariance.construction import user_covmat_fitting

Expand Down Expand Up @@ -1223,21 +1213,17 @@ def produce_fitthcovmat(
thcovmat_present = False

if use_thcovmat_if_present and thcovmat_present:
# Expected directory of theory covmat hardcoded
covmat_path = fit.path / "tables"
# Expected path of theory covmat hardcoded
covmat_path = (
fit.path / "tables" / "datacuts_theory_theorycovmatconfig_theory_covmat_custom.csv"
)
# All possible valid files
covfiles = sorted(covmat_path.glob("*theory_covmat*.csv"))
if not covfiles:
if not covmat_path.exists():
raise ConfigError(
"Fit appeared to use theory covmat in fit but the file was not at the "
f"usual location: {covmat_path}."
)
if len(covfiles) > 1:
raise ConfigError(
"More than one valid theory covmat file found at the "
f"usual location: {covmat_path}. These are {covfiles}."
)
fit_theory_covmat = ThCovMatSpec(covfiles[0])
fit_theory_covmat = ThCovMatSpec(covmat_path)
else:
fit_theory_covmat = None
return fit_theory_covmat
Expand Down Expand Up @@ -1671,11 +1657,10 @@ def produce_group_dataset_inputs_by_experiment(self, data_input):
def produce_group_dataset_inputs_by_process(self, data_input):
return self.produce_group_dataset_inputs_by_metadata(data_input, "nnpdf31_process")

def produce_scale_variation_theories(self, point_prescription, t0id):
def produce_theoryids(self, t0id, point_prescription):
"""Produces a list of theoryids given a theoryid at central scales and a point
prescription. The options for the latter are defined in pointprescriptions.yaml.
This hard codes the theories needed for each prescription to avoid user error."""
pp = point_prescription
th = t0id.id

lsv = yaml.safe_load(read_text(validphys.scalevariations, "scalevariationtheoryids.yaml"))
Expand All @@ -1697,7 +1682,7 @@ def produce_scale_variation_theories(self, point_prescription, t0id):
)

try:
scales = pp_scales_dict[pp]
scales = pp_scales_dict[point_prescription]
except KeyError:
valid_pps = ", ".join(pp_scales_dict.keys())
raise ConfigError(
Expand Down Expand Up @@ -1727,13 +1712,13 @@ def produce_scale_variation_theories(self, point_prescription, t0id):
+ "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}."
+ f"missing variations = {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")}

return NSList(theoryids, nskey="theoryid")

@configparser.explicit_node
def produce_filter_data(self, fakedata: bool = False, theorycovmatconfig=None):
Expand Down
Loading

0 comments on commit 375b6e8

Please sign in to comment.