From c0226c04b9b9e6192d6f36abc7bb017cb2c5d086 Mon Sep 17 00:00:00 2001 From: enocera Date: Sun, 14 Jun 2026 18:48:35 +0200 Subject: [PATCH 1/7] Apply shift to all theoretical predictions when multiple theoretical predictions are compared to data --- validphys2/src/validphys/dataplots.py | 65 +++++++++++++++------------ 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/validphys2/src/validphys/dataplots.py b/validphys2/src/validphys/dataplots.py index 1297e2eb2f..f1de23b186 100644 --- a/validphys2/src/validphys/dataplots.py +++ b/validphys2/src/validphys/dataplots.py @@ -263,10 +263,6 @@ def _plot_fancy_impl( nkinlabels = len(table.columns) ndata = len(table) - # Compute shifts due to the correlated part of the exp cov matrix - lcd_wc = loaded_commondata_with_cuts(commondata, cutlist[0]) - theory_predictions = results[1].central_value - # This is easier than cheking every time if labellist is None: labellist = [None] * len(results) @@ -281,36 +277,49 @@ def _plot_fancy_impl( # We modify the table, so we pass only the label columns norm_cv, _ = transform_result(cv, err, table.iloc[:, :nkinlabels], info) - cvcols = [] - - # Compute systematic shifts - # For unknown reasons, `shifts_from_systematics` may - # randomly fails. If a LinAlgError is raised, shifts are not included in - # the final plot. - if with_shift: - try: - shifts, alpha = shifts_from_systematics(lcd_wc, theory_predictions) - except np.linalg.LinAlgError: - log.warning( - "Error occurred in computing systematic shifts for " - f"{info.ds_metadata.name}. These will be disregarded in the plots." - ) - with_shift = False - + cvcols = [] + for i, (result, cuts) in enumerate(zip(results, cutlist)): - # We modify the table, so we pass only the label columns + mask = cut_mask(cuts) cv = np.full(ndata, np.nan) err = np.full(ndata, np.nan) - # Shift the theory when with_shift option is True - if i == 1 and with_shift: - cv[mask] = result.central_value - shifts + + shifts = None + alpha = None + do_shift = with_shift + + # Compute shifts due to the correlated part on the experiemntal ucnertainty + if with_shift: + lcd_wc = loaded_commondata_with_cuts(commondata, cuts) + theory_predictions = result.central_value + + # For unknown reasons, `shifts_from_systematics` may randomly fail. + # If a LinAlgError is raised, shifts are not included in the final plot. + try: + shifts, alpha = shifts_from_systematics(lcd_wc, theory_predictions) + except np.linalg.LinAlgError: + log.warning( + "Error occurred in computing systematic shifts for " + f"{info.ds_metadata.name}. These will be disregarded in the plots." + ) + do_shift = False + + # Shift theory predictions, but not data + if i >= 1 and do_shift: + cv[mask] = result.central_value - shifts + else: + cv[mask] = result.central_value + + # Retain only the uncorrelated part of the data error if shifting the data + if i == 0 and do_shift: + err[mask] = alpha + else: + err[mask] = result.std_error + + # No shifts else: cv[mask] = result.central_value - # Retain only the uncorrelated part of the error if shifting the data - if i == 0 and with_shift: - err[mask] = alpha - else: err[mask] = result.std_error cv, err = transform_result(cv, err, table.iloc[:, :nkinlabels], info) From 058979722746ecd42e225699d14464736e9dcf0e Mon Sep 17 00:00:00 2001 From: enocera Date: Thu, 25 Jun 2026 12:02:10 +0200 Subject: [PATCH 2/7] Separate computation of shifts from extraction of the uncorrelated part of the uncertainty --- validphys2/src/validphys/covmats.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/validphys2/src/validphys/covmats.py b/validphys2/src/validphys/covmats.py index 7de450dcc0..79722f5102 100644 --- a/validphys2/src/validphys/covmats.py +++ b/validphys2/src/validphys/covmats.py @@ -292,9 +292,35 @@ def shifts_from_systematics(lcd_wc, theory_predictions): # Compute the shifts shifts = -np.matmul(beta * alpha[:, np.newaxis], r) - return shifts, alpha + return shifts +def extract_uncorr_unc(lcd_wc): + """Extract the uncorrelated part of the experimental uncertainty + from a :py:class:`validphys.coredata.CommonData` object + Parameters + ---------- + loaded_commondata_with_cuts : validphys.coredata.CommonData + CommonData which stores information about systematic errors, + their treatment and description. + Returns + ------- + alpha: np.array + Numpy array of dimension N_dat (where N_dat is the number of data + points) containing the numericla value of the uncorrelated part of + the experimental uncertainty + """ + # Separate statistical and systematic errors + stat_errors = lcd_wc.stat_errors.to_numpy() + syst_errors = lcd_wc.systematic_errors(None) + + # Determine the uncorrelated part of the error + alpha2 = stat_errors**2 + is_uncorr = syst_errors.columns.isin(("UNCORR", "THEORYUNCORR")) + alpha2 += (syst_errors.loc[:, is_uncorr].to_numpy() ** 2).sum(axis=1) + alpha = np.sqrt(alpha2) + return alpha + @check_cuts_considered @functools.lru_cache def dataset_t0_predictions(t0dataset, t0set): From 8d9e405ee02270fe22e4e78c9184f460dec4d890 Mon Sep 17 00:00:00 2001 From: enocera Date: Thu, 25 Jun 2026 16:26:48 +0200 Subject: [PATCH 3/7] Separated computation of the shifts from the extraction of corr and uncorr parts of the exp uncertainty --- validphys2/src/validphys/covmats.py | 43 ++++++++++++++++++--------- validphys2/src/validphys/dataplots.py | 5 ++-- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/validphys2/src/validphys/covmats.py b/validphys2/src/validphys/covmats.py index 79722f5102..297a948c34 100644 --- a/validphys2/src/validphys/covmats.py +++ b/validphys2/src/validphys/covmats.py @@ -252,23 +252,16 @@ def shifts_from_systematics(lcd_wc, theory_predictions): points) containing the numerical value of the systematic shifts due to correlated uncertainties """ - - # Separate statistical and systematic errors - stat_errors = lcd_wc.stat_errors.to_numpy() - syst_errors = lcd_wc.systematic_errors(None) - - # Determine the uncorrelated part of the error - alpha2 = stat_errors**2 - is_uncorr = syst_errors.columns.isin(("UNCORR", "THEORYUNCORR")) - alpha2 += (syst_errors.loc[:, is_uncorr].to_numpy() ** 2).sum(axis=1) - alpha = np.sqrt(alpha2) + + # Separate the uncorrelated and correlated parts of the exp uncertainty + alpha = unco_unc(lcd_wc) + beta = corr_unc(lcd_wc) if alpha.all() == 0: shifts = np.zeros(len(alpha)) else: # Determine the correlated part of the error - beta = syst_errors.loc[:, ~is_uncorr].to_numpy() beta = beta / alpha[:, np.newaxis] # The number of data points and the number of correlated systematics @@ -294,7 +287,7 @@ def shifts_from_systematics(lcd_wc, theory_predictions): return shifts -def extract_uncorr_unc(lcd_wc): +def unco_unc(lcd_wc): """Extract the uncorrelated part of the experimental uncertainty from a :py:class:`validphys.coredata.CommonData` object Parameters @@ -306,8 +299,8 @@ def extract_uncorr_unc(lcd_wc): ------- alpha: np.array Numpy array of dimension N_dat (where N_dat is the number of data - points) containing the numericla value of the uncorrelated part of - the experimental uncertainty + points) containing the numerical value of the uncorrelated + part of the experimental uncertainty """ # Separate statistical and systematic errors stat_errors = lcd_wc.stat_errors.to_numpy() @@ -320,6 +313,28 @@ def extract_uncorr_unc(lcd_wc): alpha = np.sqrt(alpha2) return alpha + +def corr_unc(lcd_wc): + """Extract the correlated part of the experimental uncertainty + from a :py:class:`validphys.coredata.CommonData` object + Parameters + ---------- + loaded_commondata_with_cuts : validphys.coredata.CommonData + CommonData which stores information about systematic errors, + their treatment and description. + Returns + ------- + beta: np.array + Numpy array of dimension N_dat (where N_dat is the number of data + points) containing the numerical value of the correlated + part of the experimental uncertainty + """ + # Separate statistical and systematic errors + syst_errors = lcd_wc.systematic_errors(None) + is_uncorr = syst_errors.columns.isin(("UNCORR", "THEORYUNCORR")) + beta = syst_errors.loc[:, ~is_uncorr].to_numpy() + + return beta @check_cuts_considered @functools.lru_cache diff --git a/validphys2/src/validphys/dataplots.py b/validphys2/src/validphys/dataplots.py index f1de23b186..6bedf044c0 100644 --- a/validphys2/src/validphys/dataplots.py +++ b/validphys2/src/validphys/dataplots.py @@ -25,7 +25,7 @@ from validphys.checks import check_not_using_pdferr from validphys.commondata import loaded_commondata_with_cuts from validphys.core import CutsPolicy, MCStats, cut_mask, load_commondata -from validphys.covmats import shifts_from_systematics +from validphys.covmats import shifts_from_systematics, unco_unc 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 @@ -297,7 +297,8 @@ def _plot_fancy_impl( # For unknown reasons, `shifts_from_systematics` may randomly fail. # If a LinAlgError is raised, shifts are not included in the final plot. try: - shifts, alpha = shifts_from_systematics(lcd_wc, theory_predictions) + shifts = shifts_from_systematics(lcd_wc, theory_predictions) + alpha = unco_unc(lcd_wc) except np.linalg.LinAlgError: log.warning( "Error occurred in computing systematic shifts for " From ccd20fe71616f31e343ec8da1b0d66b8959184b8 Mon Sep 17 00:00:00 2001 From: enocera Date: Thu, 25 Jun 2026 17:58:22 +0200 Subject: [PATCH 4/7] Implemented review comments --- validphys2/src/validphys/dataplots.py | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/validphys2/src/validphys/dataplots.py b/validphys2/src/validphys/dataplots.py index 6bedf044c0..dadf7e9ca1 100644 --- a/validphys2/src/validphys/dataplots.py +++ b/validphys2/src/validphys/dataplots.py @@ -27,7 +27,7 @@ from validphys.core import CutsPolicy, MCStats, cut_mask, load_commondata from validphys.covmats import shifts_from_systematics, unco_unc from validphys.plotoptions.core import get_info, kitable, transform_result -from validphys.results import chi2_stat_labels, chi2_stats +from validphys.results import chi2_stat_labels, chi2_stats, DataResult from validphys.sumrules import POL_LIMS from validphys.utils import sane_groupby_iter, scale_from_grid, split_ranges @@ -288,9 +288,9 @@ def _plot_fancy_impl( shifts = None alpha = None do_shift = with_shift - + # Compute shifts due to the correlated part on the experiemntal ucnertainty - if with_shift: + if do_shift: lcd_wc = loaded_commondata_with_cuts(commondata, cuts) theory_predictions = result.central_value @@ -298,25 +298,15 @@ def _plot_fancy_impl( # If a LinAlgError is raised, shifts are not included in the final plot. try: shifts = shifts_from_systematics(lcd_wc, theory_predictions) - alpha = unco_unc(lcd_wc) except np.linalg.LinAlgError: log.warning( "Error occurred in computing systematic shifts for " f"{info.ds_metadata.name}. These will be disregarded in the plots." ) - do_shift = False + shifts = 0. - # Shift theory predictions, but not data - if i >= 1 and do_shift: - cv[mask] = result.central_value - shifts - else: - cv[mask] = result.central_value - - # Retain only the uncorrelated part of the data error if shifting the data - if i == 0 and do_shift: - err[mask] = alpha - else: - err[mask] = result.std_error + cv[mask] = result.central_value - shifts + err[mask] = unco_unc(lcd_wc) # No shifts else: From b72dfcaa86508ff6677155ce752867e3e8fd964d Mon Sep 17 00:00:00 2001 From: enocera Date: Fri, 26 Jun 2026 11:46:28 +0200 Subject: [PATCH 5/7] dataplot cleanup --- validphys2/src/validphys/dataplots.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/validphys2/src/validphys/dataplots.py b/validphys2/src/validphys/dataplots.py index dadf7e9ca1..3be896c831 100644 --- a/validphys2/src/validphys/dataplots.py +++ b/validphys2/src/validphys/dataplots.py @@ -285,12 +285,12 @@ def _plot_fancy_impl( cv = np.full(ndata, np.nan) err = np.full(ndata, np.nan) - shifts = None - alpha = None - do_shift = with_shift + #shifts = None + #alpha = None + #do_shift = with_shift # Compute shifts due to the correlated part on the experiemntal ucnertainty - if do_shift: + if with_shift: lcd_wc = loaded_commondata_with_cuts(commondata, cuts) theory_predictions = result.central_value From 007e926be31e961ff0ec92f004d5c1b120d04eb3 Mon Sep 17 00:00:00 2001 From: enocera Date: Fri, 26 Jun 2026 15:41:45 +0200 Subject: [PATCH 6/7] Shift in dataplot.py: separate data uncertainty and theory shift in four cases: no shift, no shift because no unc unc, no shift because shift fails, with shift --- validphys2/src/validphys/dataplots.py | 76 +++++++++++++++++++++------ 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/validphys2/src/validphys/dataplots.py b/validphys2/src/validphys/dataplots.py index 3be896c831..e44665213b 100644 --- a/validphys2/src/validphys/dataplots.py +++ b/validphys2/src/validphys/dataplots.py @@ -285,35 +285,79 @@ def _plot_fancy_impl( cv = np.full(ndata, np.nan) err = np.full(ndata, np.nan) - #shifts = None - #alpha = None - #do_shift = with_shift - - # Compute shifts due to the correlated part on the experiemntal ucnertainty + # With shifts if with_shift: + shifts = 0. + lcd_wc = loaded_commondata_with_cuts(commondata, cuts) + + # Determine data uncertainty + if isinstance(result, DataResult): + alpha = unco_unc(lcd_wc) + if alpha.all() == 0.: + err[mask] = result.std_error + with_shift = False + else: + err[mask] = alpha + # Determine theory shift + else: + err[mask] = result.std_error + theory_predictions = result.central_value + try: + shifts = shifts_from_systematics(lcd_wc, theory_predictions) + except np.linalg.LinAlgError: + log.warning( + "Error occurred in computing systematic shifts for " + f"{info.ds_metadata.name}. These will be disregarded in the plots." + ) + with_shift = False + + cv[mask] = result.central_value - shifts + + # No shifts + else: + cv[mask] = result.central_value + err[mask] = result.std_error + + cv, err = transform_result(cv, err, table.iloc[:, :nkinlabels], info) + + """ + # Compute shifts due to the correlated part on the experimental ucnertainty + if with_shift and not isinstance(result, DataResult): lcd_wc = loaded_commondata_with_cuts(commondata, cuts) theory_predictions = result.central_value - # For unknown reasons, `shifts_from_systematics` may randomly fail. - # If a LinAlgError is raised, shifts are not included in the final plot. - try: - shifts = shifts_from_systematics(lcd_wc, theory_predictions) - except np.linalg.LinAlgError: - log.warning( - "Error occurred in computing systematic shifts for " - f"{info.ds_metadata.name}. These will be disregarded in the plots." - ) + # Check if the uncorrelated part of the uncertainty is zero or non-zero + #alpha = unco_unc(lcd_wc) + if alpha.all() == 0.: shifts = 0. + err[mask] = result.std_error + with_shift = False + else: + + # For unknown reasons, `shifts_from_systematics` may randomly fail. + # If a LinAlgError is raised, shifts are not included in the final plot. + try: + shifts = shifts_from_systematics(lcd_wc, theory_predictions) + err[mask] = alpha + except np.linalg.LinAlgError: + log.warning( + "Error occurred in computing systematic shifts for " + f"{info.ds_metadata.name}. These will be disregarded in the plots." + ) + shifts = 0. + err[mask] = result.std_error + with_shift = False cv[mask] = result.central_value - shifts - err[mask] = unco_unc(lcd_wc) - + # No shifts else: cv[mask] = result.central_value err[mask] = result.std_error cv, err = transform_result(cv, err, table.iloc[:, :nkinlabels], info) + """ + # By doing tuple keys we avoid all possible name collisions cvcol = ('cv', i) From 34de111b43827efa0fd01f2ad63baf8c5e321175 Mon Sep 17 00:00:00 2001 From: enocera Date: Sat, 27 Jun 2026 09:16:54 +0200 Subject: [PATCH 7/7] Fixed uncertainty in case in which shift fails --- validphys2/src/validphys/dataplots.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/validphys2/src/validphys/dataplots.py b/validphys2/src/validphys/dataplots.py index e44665213b..34cd25b69e 100644 --- a/validphys2/src/validphys/dataplots.py +++ b/validphys2/src/validphys/dataplots.py @@ -289,17 +289,10 @@ def _plot_fancy_impl( if with_shift: shifts = 0. lcd_wc = loaded_commondata_with_cuts(commondata, cuts) - - # Determine data uncertainty - if isinstance(result, DataResult): - alpha = unco_unc(lcd_wc) - if alpha.all() == 0.: - err[mask] = result.std_error - with_shift = False - else: - err[mask] = alpha + fail = False + # Determine theory shift - else: + if not isinstance(result, DataResult): err[mask] = result.std_error theory_predictions = result.central_value try: @@ -309,7 +302,16 @@ def _plot_fancy_impl( "Error occurred in computing systematic shifts for " f"{info.ds_metadata.name}. These will be disregarded in the plots." ) + fail = True + + # Determine data uncertainty + else: + alpha = unco_unc(lcd_wc) + if alpha.all() == 0. or fail: + err[mask] = result.std_error with_shift = False + else: + err[mask] = alpha cv[mask] = result.central_value - shifts