Skip to content

Commit 801b8b1

Browse files
committed
Apply comments
1 parent 1b73b3b commit 801b8b1

4 files changed

Lines changed: 76 additions & 101 deletions

File tree

doc/sphinx/source/vp/theorycov/power_corrections.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ The following keys are used:
155155
length of ``nodes``.
156156
- ``pc_included_procs``: list of process types to which power corrections
157157
are applied (e.g. ``["DIS NC", "DIS CC", "JETS", "DIJET"]``).
158-
- ``pc_excluded_exps``: list of dataset names to exclude from power corrections
158+
- ``pc_excluded_datasets``: list of dataset names to exclude from power corrections
159159
even if their process type is included.
160160
- ``pdf``: the PDF used for computing the theory predictions that enter the
161161
multiplicative shifts.
@@ -187,7 +187,7 @@ Example
187187
yshift: [2.0, 2.0, 2.0, 2.0, 2.0]
188188
nodes: [0.25, 0.75, 1.25, 1.75, 2.25]
189189
pc_included_procs: ["JETS", "DIJET", "DIS NC", "DIS CC"]
190-
pc_excluded_exps:
190+
pc_excluded_datasets:
191191
- HERA_NC_318GEV_EAVG_CHARM-SIGMARED
192192
- HERA_NC_318GEV_EAVG_BOTTOM-SIGMARED
193193
pdf: NNPDF40_nnlo_as_01180
@@ -234,5 +234,5 @@ Module reference
234234
- ``covmat_power_corrections(deltas1, deltas2)``:
235235
computes the theory covariance sub-matrix between two datasets from their
236236
shift dictionaries.
237-
- ``covs_pt_prescrip_pc(combine_by_type, point_prescription, pdf, pc_parameters, pc_included_procs, pc_excluded_exps)``:
237+
- ``covs_pt_prescrip_pc(combine_by_type, point_prescription, pdf, pc_parameters, pc_included_procs, pc_excluded_datasets)``:
238238
assembles the full power correction covariance matrix across all datasets.

n3fit/runcards/examples/Basic_runcard_pc_covmat.yml

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@ dataset_inputs:
1717
- {dataset: NUTEV_CC_NOTFIXED_FE_NU-SIGMARED, cfac: [MAS], variant: legacy_dw}
1818
- {dataset: NUTEV_CC_NOTFIXED_FE_NB-SIGMARED, cfac: [MAS], variant: legacy_dw}
1919
- {dataset: HERA_NC_318GEV_EM-SIGMARED}
20-
- {dataset: ATLAS_1JET_8TEV_R06_PTY, frac: 0.75, variant: decorrelated}
21-
- {dataset: ATLAS_2JET_7TEV_R06_M12Y, frac: 0.75}
22-
- {dataset: CMS_1JET_8TEV_PTY, frac: 0.75}
23-
- {dataset: CMS_2JET_7TEV_M12-Y, frac: 0.75}
24-
- {dataset: CMS_2JET_13TEV_M12-YSTAR-YB-R08, frac: 0.75}
25-
- {dataset: ATLAS_2JET_7TEV_R06_M12Y, frac: 0.75}
20+
- {dataset: ATLAS_1JET_8TEV_R06_PTY, variant: decorrelated}
21+
- {dataset: ATLAS_2JET_7TEV_R06_M12Y}
22+
- {dataset: CMS_1JET_8TEV_PTY}
23+
- {dataset: CMS_2JET_7TEV_M12-Y}
24+
- {dataset: CMS_2JET_13TEV_M12-YSTAR-YB-R08}
2625

2726
################################################################################
2827
diagonal_frac: 0.75
@@ -44,8 +43,8 @@ theorycovmatconfig:
4443
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]}
4544
H2j_ystar: {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]}
4645
H2j_yb: {yshift: [2.0, 2.0, 2.0, 2.0, 2.0], nodes: [0.25, 0.75, 1.25, 1.75, 2.25]}
47-
pc_included_procs: ["DIJET"]
48-
pc_excluded_exps: []
46+
pc_included_procs: ["DIS NC", "DIS CC", "JETS", "DIJET"]
47+
pc_excluded_datasets: []
4948
pdf: 260202-jk-nnpdf41-mhou
5049
use_thcovmat_in_fitting: true
5150
use_thcovmat_in_sampling: true
@@ -56,8 +55,8 @@ nnseed: 953262798
5655
mcseed: 1437981271
5756
genrep: true
5857
parameters: # This defines the parameter dictionary that is passed to the Model Trainer
59-
nodes_per_layer: [70, 50, 25, 20, 9]
60-
activation_per_layer: [tanh, tanh, tanh, tanh, linear]
58+
nodes_per_layer: [25, 20, 9]
59+
activation_per_layer: [tanh, tanh, linear]
6160
initializer: glorot_normal
6261
optimizer:
6362
clipnorm: 6.073e-6

validphys2/src/validphys/theorycovariance/construction.py

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212

1313
from reportengine import collect
1414
from reportengine.table import table
15-
16-
pass
1715
from validphys.checks import check_pc_parameters
1816
from validphys.results import results, results_central
1917
from validphys.theorycovariance.higher_twist_functions import compute_deltas_pc
@@ -78,7 +76,7 @@ def combine_by_type(each_dataset_results_central_bytheory, groups_data_by_proces
7876
dataset_size = defaultdict(list)
7977
theories_by_process = defaultdict(list)
8078
ordered_names = defaultdict(list)
81-
data_spec = defaultdict(list)
79+
data_spec = {}
8280
for dataset in each_dataset_results_central_bytheory:
8381
name = dataset[0][0].name
8482
theory_centrals = [x[1].central_value for x in dataset]
@@ -91,8 +89,8 @@ def combine_by_type(each_dataset_results_central_bytheory, groups_data_by_proces
9189

9290
# Store DataGroupSpecs instances
9391
for group_proc in groups_data_by_process:
94-
for exp_set in group_proc.datasets:
95-
data_spec[exp_set.name] = exp_set
92+
for ds in group_proc.datasets:
93+
data_spec[ds.name] = ds
9694

9795
process_info = ProcessInfo(
9896
preds=theories_by_process, namelist=ordered_names, sizes=dataset_size, data_spec=data_spec
@@ -362,7 +360,7 @@ def covs_pt_prescrip_mhou(combine_by_type, point_prescription):
362360

363361
@check_pc_parameters
364362
def covs_pt_prescrip_pc(
365-
combine_by_type, point_prescription, pdf, pc_parameters, pc_included_procs, pc_excluded_exps
363+
combine_by_type, point_prescription, pdf, pc_parameters, pc_included_procs, pc_excluded_datasets
366364
):
367365
"""Produces the sub-matrices of the theory covariance matrix for power
368366
corrections. Sub-matrices correspond to applying power corrected shifts
@@ -372,33 +370,34 @@ def covs_pt_prescrip_pc(
372370
running_index = 0
373371

374372
covmats = defaultdict(list)
375-
start_proc_by_exp = defaultdict(list)
376-
for exp_name, data_spec in datagroup_spec.items():
377-
start_proc_by_exp[exp_name] = running_index
378-
running_index += data_spec.load_commondata().ndata # takes cuts into account
379-
380-
for exp_name1, data_spec1 in datagroup_spec.items():
381-
for exp_name2, data_spec2 in datagroup_spec.items():
382-
process_type1 = process_lookup(exp_name1)
383-
process_type2 = process_lookup(exp_name2)
384-
385-
is_excluded_exp = any(name in pc_excluded_exps for name in [exp_name1, exp_name2])
386-
is_included_proc = any(
373+
start_proc_by_dsname = {}
374+
for ds_name, ds_spec in datagroup_spec.items():
375+
start_proc_by_dsname[ds_name] = running_index
376+
running_index += ds_spec.load_commondata().ndata # takes cuts into account
377+
378+
for ds_name1, ds_spec1 in datagroup_spec.items():
379+
for ds_name2, ds_spec2 in datagroup_spec.items():
380+
process_type1 = process_lookup(ds_name1)
381+
process_type2 = process_lookup(ds_name2)
382+
383+
is_excluded_ds = any(name in pc_excluded_datasets for name in [ds_name1, ds_name2])
384+
is_excluded_proc = any(
387385
proc not in pc_included_procs for proc in [process_type1, process_type2]
388386
)
389-
if not (is_excluded_exp or is_included_proc):
390-
deltas1 = compute_deltas_pc(data_spec1, pdf, pc_parameters)
391-
deltas2 = compute_deltas_pc(data_spec2, pdf, pc_parameters)
387+
if is_excluded_ds or is_excluded_proc:
388+
continue
392389

393-
# Convert deltas1 and deltas2 to the format expected by compute_covs_pt_prescrip
394-
deltas1 = [np.array(deltas1[shift]) for shift in sorted(deltas1.keys())]
395-
deltas2 = [np.array(deltas2[shift]) for shift in sorted(deltas2.keys())]
390+
deltas1_dict = compute_deltas_pc(ds_spec1, pdf, pc_parameters)
391+
deltas2_dict = compute_deltas_pc(ds_spec2, pdf, pc_parameters)
392+
393+
# Convert deltas1 and deltas2 to the format expected by compute_covs_pt_prescrip
394+
deltas1 = [np.array(deltas1_dict[shift]) for shift in sorted(deltas1_dict.keys())]
395+
deltas2 = [np.array(deltas2_dict[shift]) for shift in sorted(deltas2_dict.keys())]
396+
397+
s = compute_covs_pt_prescrip(point_prescription, ds_name1, deltas1, ds_name2, deltas2)
398+
start_locs = (start_proc_by_dsname[ds_name1], start_proc_by_dsname[ds_name2])
399+
covmats[start_locs] = s
396400

397-
s = compute_covs_pt_prescrip(
398-
point_prescription, exp_name1, deltas1, exp_name2, deltas2
399-
)
400-
start_locs = (start_proc_by_exp[exp_name1], start_proc_by_exp[exp_name2])
401-
covmats[start_locs] = s
402401
return covmats
403402

404403

validphys2/src/validphys/theorycovariance/higher_twist_functions.py

Lines changed: 36 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ def get_pc_type(
118118
)
119119
return ("H2j_ystar", "H2j_yb")
120120

121-
else:
122-
raise RuntimeError(f"{process_type} has not been implemented.")
121+
raise RuntimeError(f"{exp_name}: {process_type} has not been implemented.")
123122

124123

125124
def _get_dis_pc_type(exp_name: str) -> PCTypeResult:
@@ -139,23 +138,23 @@ def _get_dis_pc_type(exp_name: str) -> PCTypeResult:
139138
raise ValueError(f"The DIS observable for {exp_name} has not been implemented.")
140139

141140

142-
def _get_dijet_pc_type(experiment: str, pc_dict: Optional[dict] = None) -> str:
141+
def _get_dijet_pc_type(experiment: str, pc_dict: Optional[dict] = {}) -> str:
143142
"""Resolve DIJET experiment to PC type key with optional fallback."""
144143
if pc_dict.get("H2j_ystar") and pc_dict.get("H2j_yb"):
145144
return ("H2j_ystar", "H2j_yb")
145+
146+
if experiment == 'ATLAS':
147+
specific_key = "H2j_ystar"
148+
elif experiment == 'CMS':
149+
specific_key = "H2j_ymax"
146150
else:
147-
if experiment == 'ATLAS':
148-
specific_key = "H2j_ystar"
149-
elif experiment == 'CMS':
150-
specific_key = "H2j_ymax"
151-
else:
152-
raise ValueError(f"{experiment} is not implemented for DIJET.")
151+
raise ValueError(f"{experiment} is not implemented for DIJET.")
153152

154153
return specific_key
155154

156155

157156
def linear_bin_function(
158-
a: npt.ArrayLike, y_shift: npt.ArrayLike, bin_edges: npt.ArrayLike
157+
a: npt.ArrayLike, y_shift: npt.ArrayLike, nodes: npt.ArrayLike
159158
) -> np.ndarray:
160159
"""
161160
This function defines the linear bin function used to construct the prior. Specifically,
@@ -168,7 +167,7 @@ def linear_bin_function(
168167
A one-dimensional array of points at which the function is evaluated.
169168
y_shift: ArrayLike of float
170169
A one-dimensional array whose elements represent the y-value of each bin
171-
bin_nodes: ArrayLike of float
170+
nodes: ArrayLike of float
172171
A one-dimensional array containing the edges of the bins. The bins are
173172
constructed using pairs of consecutive points.
174173
@@ -177,36 +176,9 @@ def linear_bin_function(
177176
A one-dimensional array containing the function values evaluated at the points
178177
specified in `a`.
179178
"""
180-
res = np.zeros_like(a)
181-
for shift_pos, shift in enumerate(y_shift):
182-
if shift_pos > 0 and shift_pos < len(y_shift) - 1:
183-
bin_low = bin_edges[shift_pos - 1]
184-
bin_high = bin_edges[shift_pos + 1]
185-
bin_mid = bin_edges[shift_pos]
186-
m1 = shift / (bin_mid - bin_low)
187-
m2 = shift / (bin_high - bin_mid)
188-
elif shift_pos == 0: # Left-most bin
189-
bin_high = bin_edges[shift_pos + 1]
190-
bin_mid = bin_edges[shift_pos]
191-
bin_low = bin_mid
192-
m1 = 0.0
193-
m2 = shift / (bin_high - bin_mid)
194-
else: # Right-most bin
195-
bin_low = bin_edges[shift_pos - 1]
196-
bin_mid = bin_edges[shift_pos]
197-
bin_high = bin_mid
198-
m1 = shift / (bin_mid - bin_low)
199-
m2 = 0.0
200-
cond_low = np.multiply(
201-
a >= bin_low, a < bin_mid if shift_pos != len(y_shift) - 1 else a <= bin_mid
202-
)
203-
cond_high = np.multiply(
204-
a >= bin_mid, a < bin_high if shift_pos != len(y_shift) - 1 else a <= bin_high
205-
)
206-
res = np.add(res, [m1 * (val - bin_low) if cond else 0.0 for val, cond in zip(a, cond_low)])
207-
res = np.add(
208-
res, [-m2 * (val - bin_high) if cond else 0.0 for val, cond in zip(a, cond_high)]
209-
)
179+
a = np.asarray(a, dtype=float)
180+
res = np.interp(a, nodes, y_shift)
181+
res[(a < nodes[0]) | (a > nodes[-1])] = 0.0
210182
return res
211183

212184

@@ -256,10 +228,10 @@ def jets_pc_func(
256228
One-dimensional array containing the shifts for each bin.
257229
nodes: ArrayLike
258230
One-dimensional array containing the edges of the bins in rapidity.
259-
rap: ArrayLike
260-
List of rapidity points at which the power correction is evaluated.
261231
pT: ArrayLike
262232
List of pT points at which the power correction is evaluated.
233+
rap: ArrayLike
234+
List of rapidity points at which the power correction is evaluated.
263235
264236
Returns
265237
-------
@@ -442,6 +414,8 @@ def _F(tx, ty):
442414

443415
# ---------------------------------------------------------------------------
444416
# Power correction callable factories
417+
# If these functions are used to compute c-factors,
418+
# no need to multiply by the observable.
445419
# ---------------------------------------------------------------------------
446420
def mult_dis_pc(nodes, x, q2, dataset_sp, pdf, cfactors: bool = False) -> callable:
447421
"""
@@ -526,8 +500,6 @@ def func(y_values_p, y_values_d):
526500
h2d = dis_pc_func(y_values_d, d_nodes, x, q2)
527501
h2p = dis_pc_func(y_values_p, p_nodes, x, q2)
528502
if cfactors:
529-
# If this function is used to compute c-factors,
530-
# no need to multiply by the observable
531503
num = np.sum([np.ones_like(h2d), h2d], axis=0)
532504
denom = np.sum([np.ones_like(h2p), h2p], axis=0)
533505
return (num, denom)
@@ -583,10 +555,20 @@ def mult_dijet_pc(
583555
fk = fkspec.load_with_cuts(cuts)
584556
th_preds = central_fk_predictions(fk, pdf)
585557

558+
if distrb == '3D':
559+
if len(ystar) == 0 or len(yb) == 0:
560+
raise ValueError("For 3D distributions, ystar and yb must be provided.")
561+
elif distrb == "ystar":
562+
if len(ystar) == 0:
563+
raise ValueError("For ystar distributions, ystar must be provided.")
564+
elif distrb == "ymax":
565+
if len(ymax) == 0:
566+
raise ValueError("For ymax distributions, ymax must be provided.")
567+
else:
568+
raise ValueError(f"Unknown distrb value: {distrb!r}. Expected '3D', 'ystar', or 'ymax'.")
569+
586570
def func(ystar_shifts, y_b_shifts):
587571
if distrb == '3D':
588-
if len(ystar) == 0 or len(yb) == 0:
589-
raise ValueError("For 3D distributions, ystar and yb must be provided.")
590572
result = dijet3D_pc_func(
591573
ystar_shifts=ystar_shifts,
592574
yb_shifts=y_b_shifts,
@@ -597,8 +579,6 @@ def func(ystar_shifts, y_b_shifts):
597579
m_jj=m_jj,
598580
)
599581
elif distrb == "ystar":
600-
if len(ystar) == 0:
601-
raise ValueError("For ystar distributions, ystar must be provided.")
602582
result = dijet_ystar_pc_func(
603583
ystar_shifts=ystar_shifts,
604584
yb_shifts=y_b_shifts,
@@ -608,8 +588,6 @@ def func(ystar_shifts, y_b_shifts):
608588
ystar=ystar,
609589
)
610590
elif distrb == "ymax":
611-
if len(ymax) == 0:
612-
raise ValueError("For ymax distributions, ymax must be provided.")
613591
result = dijet_ymax_pc_func(
614592
ystar_shifts=ystar_shifts,
615593
yb_shifts=y_b_shifts,
@@ -618,10 +596,6 @@ def func(ystar_shifts, y_b_shifts):
618596
m_jj=m_jj,
619597
ymax=ymax,
620598
)
621-
else:
622-
raise ValueError(
623-
f"Unknown distrb value: {distrb!r}. Expected '3D', 'ystar', or 'ymax'."
624-
)
625599

626600
if cfactors:
627601
return np.sum([np.ones_like(result), result], axis=0)
@@ -756,9 +730,11 @@ def compute_deltas_pc(
756730
pc_type = get_pc_type(exp_name, process_type, experiment=experiment, pc_dict=pc_dict)
757731

758732
if process_type.startswith('DIS'):
759-
760-
x = dataset_sp.commondata.metadata.load_kinematics()['x'].to_numpy().reshape(-1)[cuts]
761-
q2 = dataset_sp.commondata.metadata.load_kinematics()['Q2'].to_numpy().reshape(-1)[cuts]
733+
try:
734+
x = dataset_sp.commondata.metadata.load_kinematics()['x'].to_numpy().reshape(-1)[cuts]
735+
q2 = dataset_sp.commondata.metadata.load_kinematics()['Q2'].to_numpy().reshape(-1)[cuts]
736+
except KeyError as e:
737+
raise ValueError(f"Required kinematic variable not found: {e}")
762738

763739
# NMC ratio: special case with two PC types (proton and deuteron)
764740
if isinstance(pc_type, tuple):
@@ -791,7 +767,6 @@ def compute_deltas_pc(
791767
raise ValueError(f"{experiment} is not implemented for DIJET.")
792768

793769
kinematics = dataset_sp.commondata.metadata.load_kinematics()
794-
# TODO Excpetion rule for CMS_2JET_7TEV_M12-Y should be removed
795770
rap = kinematics[rap_var].to_numpy().reshape(-1)[cuts]
796771
m_jj = kinematics['m_jj'].to_numpy().reshape(-1)[cuts]
797772

@@ -814,6 +789,8 @@ def compute_deltas_pc(
814789
# Both ystar and yb parameters contribute for all 2D distributions
815790
deltas.update(_apply_pars_combs(pars_combs, ["H2j_ystar", "H2j_yb"], pc_func))
816791

792+
# Fallback to the case where power corrections have same structure
793+
# as single-inclusice jets, with pT replaced by m_jj.
817794
else:
818795
nodes = pc_dict[pc_type]['nodes']
819796
pc_func = mult_jet_pc(nodes, m_jj, rap, dataset_sp, pdf, cfactors=cfactors)

0 commit comments

Comments
 (0)