Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
e519636
Implementing check for repeated added rules.
achiefa Jul 1, 2025
d7bb1af
Implementing uniqueness parsing logic for filter rules.
achiefa Jul 1, 2025
61f6cb4
Update error message
achiefa Jul 2, 2025
7d9e969
Copied fro branch 'HT_thcovmat'
achiefa Jul 15, 2024
356cddc
Removed version
achiefa Jul 15, 2024
4bab1da
Saving progress - not ready
achiefa Jul 15, 2024
56d60cf
Implemented d/p ratio
achiefa Jul 16, 2024
c58758a
Parsing 'separate_multiplicative' in vp_setupfit
achiefa Jul 16, 2024
e4d9e60
Minor adjustments
achiefa Jul 16, 2024
f11b466
Corrected bug
achiefa Jul 16, 2024
ad050da
Correcting bug
achiefa Jul 17, 2024
be18a4b
Implemented knots in runcard
achiefa Aug 5, 2024
c6a1f4e
Added valiphys card for chi2 report
achiefa Aug 20, 2024
e0c21cc
First implementation of HT at the level of theory predictions
achiefa Aug 23, 2024
6fe1974
Implemented table for kinematics
achiefa Sep 20, 2024
bc58ac6
Allowed theory HT in runcard - added HERACOMB in HT calculations
achiefa Sep 21, 2024
754a916
Excluded HERACOMB
achiefa Sep 21, 2024
525d239
Hacking NMC dataset
achiefa Sep 21, 2024
ab292f4
Grouping kinematics
achiefa Sep 26, 2024
576bad1
Reimplementing thcovmat
achiefa Sep 26, 2024
8b9de4b
Added comment in HT for DIS
achiefa Sep 27, 2024
e403c61
Corrected normalisation for SIGMARED DIS NC data sets
achiefa Sep 27, 2024
5040fb0
Removing unused code
achiefa Sep 29, 2024
6c04f5f
Added HT for F2C data (EMC) - removed deprecated function
achiefa Oct 2, 2024
054a492
Corrected EMC data iron target
achiefa Oct 2, 2024
4a6986b
Removed deprecated code
achiefa Oct 3, 2024
94e2fe1
Refactoring + DIS CC
achiefa Oct 3, 2024
5382633
Corrected bug - ready for cc test
achiefa Oct 11, 2024
43225ad
Corrected bug - ready
achiefa Oct 11, 2024
6ca745c
Removing unnecessary code
achiefa Oct 11, 2024
610d765
Corrected bug after rebase
achiefa Oct 12, 2024
2dc457c
Add normalisation in CC x-secs
achiefa Oct 17, 2024
1400eb4
Correct normalisation
achiefa Oct 17, 2024
2530ae6
Restore n3fit files from master
achiefa Oct 17, 2024
4404032
remove _PB suffix from process type
RoyStegeman Nov 14, 2024
037d5b3
format a bit
RoyStegeman Nov 14, 2024
2570a1a
Update for new thcovmat construction + refactor + docstrings
achiefa Jan 14, 2025
ba65cc6
Correct typo + example runcard
achiefa Jan 14, 2025
91af93c
Correct bug
achiefa Jan 14, 2025
8d43f0d
Correct nuclear factors for nuclear targets
achiefa Jan 15, 2025
a622417
First implementation of jet data
achiefa Jan 20, 2025
8665ec7
Change pc jet dependence from pT to eta
achiefa Jan 23, 2025
39e68e4
Allowing step-function for the prior
achiefa Jan 28, 2025
4729dce
Vectorize step_function + docstring
achiefa Jan 29, 2025
a230495
Correct bug in step function
achiefa Jan 29, 2025
c61d3f5
Correct bug in step function
achiefa Jan 29, 2025
2e6a29e
Produce covs_pt_prescrip
achiefa Jan 30, 2025
7f32963
Allow different funcs for posterior
achiefa Feb 10, 2025
0edb275
Adjusting linear triangular function
achiefa Feb 12, 2025
34fd363
Correct bug in linear function
achiefa Feb 17, 2025
049baa3
Implement multiplicative PC for jet
achiefa Feb 21, 2025
24204a5
Correct docstring
achiefa Feb 28, 2025
26e1e41
Remove unused vp runcard
achiefa Mar 10, 2025
85188cb
Dijet + clean-up + checks for pc dict
achiefa Mar 10, 2025
f28807b
Remove translation layer for pc parameters
achiefa Mar 10, 2025
43c1666
Remove copy of the same collection procs_data -> groups_data_by_proce…
achiefa Mar 10, 2025
b805509
Remove unused collect
achiefa Mar 10, 2025
fbf60e3
Update basic runcard
achiefa Mar 10, 2025
b061166
Allow generation of L1 data
achiefa Mar 10, 2025
65d8588
Jets with single parameters
achiefa Apr 14, 2025
8490ccb
Adjust format
achiefa Apr 14, 2025
77b8cce
Restoring nodes for jets and dijets
achiefa Apr 23, 2025
caa8125
Implementation of multiplicative shifts
achiefa Jun 10, 2025
aef98bc
Less functions for PCs
achiefa Jun 17, 2025
cf277ef
Combined di-jet
achiefa Jul 1, 2025
b8d380c
Correct combined di-jet
achiefa Jul 3, 2025
8d7aaf5
Remove func_type dependence - default is linear interpolation
achiefa Aug 13, 2025
7e6a97c
Allow multiplicative factor for user covmat
achiefa Sep 25, 2025
52997f3
Remove debug trace
achiefa Sep 25, 2025
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
151 changes: 151 additions & 0 deletions n3fit/runcards/examples/Basic_runcard_pc_covmat.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#
# Configuration file for n3fit
#
######################################################################################
description: NNPDF4.0 ht with TCM - DIS (NC & CC) only

######################################################################################
dataset_inputs:
- {dataset: NMC_NC_NOTFIXED_EM-F2, frac: 0.75, variant: legacy_dw}
- {dataset: NMC_NC_NOTFIXED_P_EM-SIGMARED, frac: 0.75, variant: legacy}
- {dataset: SLAC_NC_NOTFIXED_D_EM-F2, frac: 0.75, variant: legacy_dw}
- {dataset: BCDMS_NC_NOTFIXED_P_EM-F2, frac: 0.75, variant: legacy_dw}
- {dataset: CHORUS_CC_NOTFIXED_PB_NU-SIGMARED, frac: 0.75, variant: legacy_dw}
- {dataset: NUTEV_CC_NOTFIXED_FE_NB-SIGMARED, cfac: [MAS], frac: 0.75, variant: legacy_dw}
- {dataset: HERA_CC_318GEV_EP-SIGMARED, frac: 0.75, variant: legacy}
- {dataset: HERA_NC_318GEV_EAVG_CHARM-SIGMARED, frac: 0.75, variant: legacy}
- {dataset: HERA_NC_318GEV_EAVG_BOTTOM-SIGMARED, frac: 0.75, variant: legacy}
- {dataset: DYE866_Z0_800GEV_DW_RATIO_PDXSECRATIO, frac: 0.75, variant: legacy}
- {dataset: CDF_Z0_1P96TEV_ZRAP, frac: 0.75, variant: legacy}
- {dataset: ATLAS_Z0J_8TEV_PT-Y, frac: 0.75, variant: legacy_10}
- {dataset: ATLAS_1JET_8TEV_R06_PTY, frac: 0.75, variant: legacy_decorrelated}
- {dataset: ATLAS_2JET_7TEV_R06_M12Y, frac: 0.75, variant: legacy}
- {dataset: CMS_2JET_7TEV_M12Y, frac: 0.75}
- {dataset: CMS_1JET_8TEV_PTY, frac: 0.75, variant: legacy}
- {dataset: LHCB_Z0_13TEV_DIELECTRON-Y, frac: 0.75}

################################################################################
datacuts:
t0pdfset: 240701-02-rs-nnpdf40-baseline
q2min: 2.5
w2min: 3.24

################################################################################
# NNLO QCD TRN evolution
theory:
theoryid: 708

theorycovmatconfig:
point_prescriptions: ["9 point", "power corrections"]
pc_parameters:
H2p: {yshift: [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0], nodes: [0.0, 0.001, 0.01, 0.1, 0.3, 0.5, 0.7, 0.9, 1]}
H2d: {yshift: [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0], nodes: [0.0, 0.001, 0.01, 0.1, 0.3, 0.5, 0.7, 0.9, 1]}
HLp: {yshift: [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0], nodes: [0.0, 0.001, 0.01, 0.1, 0.3, 0.5, 0.7, 0.9, 1]}
HLd: {yshift: [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0], nodes: [0.0, 0.001, 0.01, 0.1, 0.3, 0.5, 0.7, 0.9, 1]}
H3p: {yshift: [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0], nodes: [0.0, 0.001, 0.01, 0.1, 0.3, 0.5, 0.7, 0.9, 1]}
H3d: {yshift: [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0], nodes: [0.0, 0.001, 0.01, 0.1, 0.3, 0.5, 0.7, 0.9, 1]}
Hj: {yshift: [2.0, 2.0, 2.0, 2.0, 2.0, 2.0], nodes: [0.25, 0.75, 1.25, 1.75, 2.25, 2.75]}
H2j_ATLAS: {yshift: [2.0, 2.0, 2.0, 2.0, 2.0, 2.0], nodes: [0.25, 0.75, 1.25, 1.75, 2.25, 2.75]}
H2j_CMS: {yshift: [2.0, 2.0, 2.0, 2.0, 2.0], nodes: [0.25, 0.75, 1.25, 1.75, 2.25]}
pc_included_procs: ["JETS", "DIJET", "DIS NC", "DIS CC"]
pc_excluded_exps: [HERA_NC_318GEV_EAVG_CHARM-SIGMARED,
HERA_NC_318GEV_EAVG_BOTTOM-SIGMARED,]
pdf: 210619-n3fit-001
use_thcovmat_in_fitting: true
use_thcovmat_in_sampling: true
resample_negative_pseudodata: false

# For fits <= 4.0 multiplicative and additive uncertainties were sampled separately
# and thus the flag `separate_multiplicative` needs to be set to True
# sampling:
# separate_multiplicative: True

################################################################################
trvlseed: 591866982
nnseed: 945709987
mcseed: 519562661
genrep: true

################################################################################
parameters: # This defines the parameter dictionary that is passed to the Model Trainer
nodes_per_layer: [25, 20, 8]
activation_per_layer: [tanh, tanh, linear]
initializer: glorot_normal
optimizer:
clipnorm: 6.073e-6
learning_rate: 2.621e-3
optimizer_name: Nadam
epochs: 3000
positivity:
initial: 184.8
multiplier:
integrability:
initial: 10
multiplier:
stopping_patience: 0.1
layer_type: dense
dropout: 0.0
threshold_chi2: 3.5

fitting:
fitbasis: EVOL
savepseudodata: True
basis:
- {fl: sng, trainable: false, smallx: [1.089, 1.119], largex: [1.475, 3.119]}
- {fl: g, trainable: false, smallx: [0.7504, 1.098], largex: [2.814, 5.669]}
- {fl: v, trainable: false, smallx: [0.479, 0.7384], largex: [1.549, 3.532]}
- {fl: v3, trainable: false, smallx: [0.1073, 0.4397], largex: [1.733, 3.458]}
- {fl: v8, trainable: false, smallx: [0.5507, 0.7837], largex: [1.516, 3.356]}
- {fl: t3, trainable: false, smallx: [-0.4506, 0.9305], largex: [1.745, 3.424]}
- {fl: t8, trainable: false, smallx: [0.5877, 0.8687], largex: [1.522, 3.515]}
- {fl: t15, trainable: false, smallx: [1.089, 1.141], largex: [1.492, 3.222]}

################################################################################
positivity:
posdatasets:
# Positivity Lagrange Multiplier
- {dataset: NNPDF_POS_2P24GEV_F2U, maxlambda: 1e6}
- {dataset: NNPDF_POS_2P24GEV_F2D, maxlambda: 1e6}
- {dataset: NNPDF_POS_2P24GEV_F2S, maxlambda: 1e6}
- {dataset: NNPDF_POS_2P24GEV_FLL, maxlambda: 1e6}
- {dataset: NNPDF_POS_2P24GEV_DYU, maxlambda: 1e10}
- {dataset: NNPDF_POS_2P24GEV_DYD, maxlambda: 1e10}
- {dataset: NNPDF_POS_2P24GEV_DYS, maxlambda: 1e10}
- {dataset: NNPDF_POS_2P24GEV_F2C, maxlambda: 1e6}
# Positivity of MSbar PDFs
- {dataset: NNPDF_POS_2P24GEV_XUQ, maxlambda: 1e6}
- {dataset: NNPDF_POS_2P24GEV_XUB, maxlambda: 1e6}
- {dataset: NNPDF_POS_2P24GEV_XDQ, maxlambda: 1e6}
- {dataset: NNPDF_POS_2P24GEV_XDB, maxlambda: 1e6}
- {dataset: NNPDF_POS_2P24GEV_XSQ, maxlambda: 1e6}
- {dataset: NNPDF_POS_2P24GEV_XSB, maxlambda: 1e6}
- {dataset: NNPDF_POS_2P24GEV_XGL, maxlambda: 1e6}

added_filter_rules:
- dataset: NNPDF_POS_2P24GEV_FLL
rule: "x > 5.0e-7"
- dataset: NNPDF_POS_2P24GEV_F2C
rule: "x < 0.74"
- dataset: NNPDF_POS_2P24GEV_XGL
rule: "x > 0.1"
- dataset: NNPDF_POS_2P24GEV_XUQ
rule: "x > 0.1"
- dataset: NNPDF_POS_2P24GEV_XUB
rule: "x > 0.1"
- dataset: NNPDF_POS_2P24GEV_XDQ
rule: "x > 0.1"
- dataset: NNPDF_POS_2P24GEV_XDB
rule: "x > 0.1"
- dataset: NNPDF_POS_2P24GEV_XSQ
rule: "x > 0.1"
- dataset: NNPDF_POS_2P24GEV_XSB
rule: "x > 0.1"

integrability:
integdatasets:
- {dataset: NNPDF_INTEG_3GEV_XT8, maxlambda: 1e2}
- {dataset: NNPDF_INTEG_3GEV_XT3, maxlambda: 1e2}

################################################################################
debug: false
maxcores: 8
2 changes: 1 addition & 1 deletion n3fit/src/n3fit/performfit.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def performfit(
debug=False,
maxcores=None,
double_precision=False,
parallel_models=True,
parallel_models=False,
):
"""
This action will (upon having read a validcard) process a full PDF fit
Expand Down
6 changes: 3 additions & 3 deletions n3fit/src/n3fit/scripts/vp_setupfit.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env python
"""
setup-fit - prepare and apply data cuts before fit
setup-fit constructs the fit [results] folder where data used by nnfit
will be stored.
setup-fit - prepare and apply data cuts before fit
setup-fit constructs the fit [results] folder where data used by nnfit
will be stored.
"""

# Implementation notes
Expand Down
12 changes: 12 additions & 0 deletions validphys2/src/validphys/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,3 +361,15 @@ def check_darwin_single_process(NPROC):
"""
if platform.system() == "Darwin" and NPROC != 1:
raise CheckError("NPROC must be set to 1 on OSX, because multithreading is not supported.")


@make_argcheck
def check_pc_parameters(pc_parameters):
"""Check that the parameters for the PC method are set correctly"""
for par in pc_parameters.values():
# Check that the length of shifts is the same as the length of nodes
if (len(par['yshift']) != len(par['nodes'])):
raise ValueError(
f"The length of nodes does not match that of the list in {par['ht']}."
f"Check the runcard. Got {len(par['yshift'])} != {len(par['nodes'])}"
)
43 changes: 42 additions & 1 deletion validphys2/src/validphys/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,21 @@ def produce_nnfit_theory_covmat(
f = user_covmat_fitting

return f

def produce_mult_factor_user_covmat(self, mult_factor: float = None, user_covmat_path: str = None):
"""
Multiplicative factors for the user covmat provided by mult_factors_user_covmat in the runcard.
If no factors are provided, returns None.
For use in theorycovariance.construction.user_covmat.
"""
# Check that if mult_factors is provided, user_covmat_paths is also provided
if mult_factor is not None and user_covmat_path is None:
raise ConfigError("If mult_factors is provided, user_covmat_paths must also be provided.")

if mult_factor is None:
return 1.0 if user_covmat_path is not None else None
else:
return mult_factor

def produce_fitthcovmat(
self, use_thcovmat_if_present: bool = False, fit: (str, type(None)) = None
Expand Down Expand Up @@ -1799,6 +1814,8 @@ def produce_theoryids(self, t0id, point_prescription):
prescription. The options for the latter are defined in pointprescriptions.yaml.
This hard codes the theories needed for each prescription to avoid user error."""
th = t0id.id
if point_prescription == 'power corrections':
return NSList([t0id], nskey="theoryid")

lsv = yaml_safe.load(read_text(validphys.scalevariations, "scalevariationtheoryids.yaml"))

Expand Down Expand Up @@ -1881,7 +1898,18 @@ def produce_filter_data(
if not fakedata:
return validphys.filters.filter_real_data
else:
if inconsistent_fakedata:
# TODO we don't want to sample from the theory covmat for L1 data,
# but we do want to use the theory covmat for L2 data
if theorycovmatconfig is not None and theorycovmatconfig.get(
"use_thcovmat_in_fakedata_sampling"
):
# NOTE: By the time we run theory covmat closure tests,
# hopefully the generation of pseudodata will be done in python.
raise ConfigError(
"Generating L1 closure test data which samples from the theory "
"covariance matrix has not been implemented yet."
)
elif inconsistent_fakedata:
log.info("Using filter for inconsistent closure data")
return validphys.filters.filter_inconsistent_closure_data_by_experiment

Expand Down Expand Up @@ -1909,6 +1937,19 @@ def produce_total_phi_data(self, fitthcovmat):
return validphys.results.total_phi_data_from_experiments
return validphys.results.dataset_inputs_phi_data

@configparser.explicit_node
def produce_covs_pt_prescrip(self, point_prescription):
if point_prescription != 'power corrections':
from validphys.theorycovariance.construction import covs_pt_prescrip_mhou

f = covs_pt_prescrip_mhou
else:
from validphys.theorycovariance.construction import covs_pt_prescrip_pc

f = covs_pt_prescrip_pc

return f


class Config(report.Config, CoreConfig):
"""The effective configuration parser class."""
24 changes: 16 additions & 8 deletions validphys2/src/validphys/dataplots.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
Plots of relations between data PDFs and fits.
"""

from __future__ import generator_stop

from collections import defaultdict
from collections.abc import Sequence
import itertools
Expand All @@ -28,7 +26,7 @@
from validphys.core import CutsPolicy, MCStats, cut_mask
from validphys.plotoptions.core import get_info, kitable, transform_result
from validphys.results import chi2_stat_labels, chi2_stats
from validphys.sumrules import POL_LIMS, partial_polarized_sum_rules
from validphys.sumrules import POL_LIMS
from validphys.utils import sane_groupby_iter, scale_from_grid, split_ranges

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -301,9 +299,7 @@ def _plot_fancy_impl(
min_vals = []
max_vals = []
fig, ax = plotutils.subplots()
ax.set_title(
"{} {}".format(info.dataset_label, info.group_label(samefig_vals, info.figure_by))
)
ax.set_title(f"{info.dataset_label} {info.group_label(samefig_vals, info.figure_by)}")

lineby = sane_groupby_iter(fig_data, info.line_by)

Expand Down Expand Up @@ -1287,7 +1283,7 @@ def _check_display_cuts_requires_use_cuts(display_cuts, use_cuts):

@make_argcheck
def _check_marker_by(marker_by):
markers = ('process type', 'experiment', 'dataset', 'group')
markers = ('process type', 'experiment', 'dataset', 'group', 'kinematics')
if marker_by not in markers:
raise CheckError("Unknown marker_by value", marker_by, markers)

Expand Down Expand Up @@ -1346,7 +1342,8 @@ def plot_xq2(
will be displaed and marked.

The points are grouped according to the `marker_by` option. The possible
values are: "process type", "experiment", "group" or "dataset".
values are: "process type", "experiment", "group" or "dataset" for discrete
colors, or "kinematics" for coloring by 1/(Q2(1-x))

Some datasets can be made to appear highlighted in the figure: Define a key
called ``highlight_datasets`` containing the names of the datasets to be
Expand Down Expand Up @@ -1477,6 +1474,7 @@ def plot_xq2(

xh = defaultdict(list)
q2h = defaultdict(list)
cvdict = defaultdict(list)

if not highlight_datasets:
highlight_datasets = set()
Expand Down Expand Up @@ -1507,6 +1505,8 @@ def next_options():
elif marker_by == "group":
# if group is None then make sure that shows on legend.
key = str(group)
elif marker_by == "kinematics":
key = None
else:
raise ValueError('Unknown marker_by value')

Expand All @@ -1522,6 +1522,7 @@ def next_options():
xdict = x
q2dict = q2

cvdict[key].append(commondata.load().get_cv())
xdict[key].append(fitted[0])
q2dict[key].append(fitted[1])
if display_cuts:
Expand All @@ -1536,6 +1537,13 @@ def next_options():
else:
# This is to get the label key
coords = [], []
if marker_by == "kinematics":
ht_magnitude = np.concatenate(cvdict[key]) / (coords[1] * (1 - coords[0]))
out = ax.scatter(
*coords, marker='.', c=ht_magnitude, cmap="viridis", norm=mcolors.LogNorm()
)
clb = fig.colorbar(out)
clb.ax.set_title(r'$F_\mathrm{exp}\frac{1}{Q^2(1-x)}$')
ax.plot(*coords, label=key, markeredgewidth=1, markeredgecolor=None, **key_options[key])

# Iterate again so highlights are printed on top.
Expand Down
4 changes: 3 additions & 1 deletion validphys2/src/validphys/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ def to_dict(self):
class FilterRule:
"""
Dataclass which carries the filter rule information.

"""

dataset: str = None
Expand Down Expand Up @@ -172,6 +171,9 @@ def default_filter_rules_input():
are unique, i.d. if there are no multiple rules for the same dataset of
process with the same rule (`reason` and `local_variables` are not hashed).
"""
# TODO: This should be done using a more sophisticated comparison
# that checks if two rules are actually the same, regardless of the
# order in which the cuts are defined.
list_rules = yaml_safe.load(read_text(validphys.cuts, "filters.yaml"))
unique_rules = set(FilterRule(**rule) for rule in list_rules)
if len(unique_rules) != len(list_rules):
Expand Down
Loading
Loading