Skip to content

Commit 85f806c

Browse files
committed
Enforce data-input ordering in nnfit_theory_covmat
1 parent 99a2339 commit 85f806c

4 files changed

Lines changed: 43 additions & 26 deletions

File tree

validphys2/src/validphys/config.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,19 @@ def produce_dataset_inputs_sampling_covmat(
897897
else:
898898
return covmats.dataset_inputs_exp_covmat
899899

900+
def produce_fitting_covmat_name(self, fit):
901+
"""Produce the name of the covmat to be used in fitting,
902+
according to how it was generated by vp-setupfit.
903+
"""
904+
runcard = fit.as_input()
905+
use_thcovmat = runcard.get("theorycovmatconfig", {}).get("use_thcovmat_in_fitting", False)
906+
if use_thcovmat:
907+
covmat_name = "datacuts_theory_theorycovmatconfig_fitting_covmat_table.csv"
908+
else:
909+
covmat_name = "datacuts_theory_fitting_covmat_table.csv"
910+
path = fit.path / "tables" / covmat_name
911+
return path
912+
900913
def produce_loaded_theory_covmat(
901914
self,
902915
output_path,
@@ -1363,9 +1376,9 @@ def produce_nnfit_theory_covmat(
13631376
f = total_theory_covmat_fitting
13641377
else:
13651378
# Only scalevar uncertainties
1366-
from validphys.theorycovariance.construction import theory_covmat_custom
1379+
from validphys.theorycovariance.construction import theory_covmat_custom_fitting
13671380

1368-
f = theory_covmat_custom
1381+
f = theory_covmat_custom_fitting
13691382
elif user_covmat_path is not None:
13701383
# Only user uncertainties
13711384
from validphys.theorycovariance.construction import user_covmat_fitting

validphys2/src/validphys/n3fit_data.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -416,13 +416,19 @@ def setupfit_fitting_covmat(dataset_inputs_fitting_covmat, diagonal_basis=True):
416416
log.info("working in diagonal basis.")
417417

418418
# convert covmat to correlation
419-
diag_inv_sqrt = 1 / np.sqrt(np.diag(covmat))
420-
cormat = np.einsum("i, ij, j -> ij", diag_inv_sqrt, covmat, diag_inv_sqrt)
419+
sigma = np.sqrt(np.diag(covmat))
420+
sigma_inv = 1 / sigma
421+
cormat = np.einsum("i, ij, j -> ij", sigma_inv, covmat, sigma_inv)
421422

422423
# diagonalise the correlation matrix
423-
eig_vals, uT = np.linalg.eigh(cormat)
424-
uT = np.einsum("i, ik -> ik", diag_inv_sqrt, uT)
425-
diagonal_rotation = uT.T
424+
eig_vals, v = np.linalg.eigh(cormat) # cormat = V @ diag(eig_vals) @ V.T
425+
u = np.einsum("i, ij -> ij", sigma, v)
426+
rec_covmat = u @ np.diag(eig_vals) @ u.T
427+
assert np.allclose(
428+
covmat, rec_covmat
429+
), "Diagonalisation failed to reproduce original covmat"
430+
431+
diagonal_rotation = np.einsum("ij, j -> ij", v.T, sigma_inv)
426432

427433
return covmat, diagonal_rotation, eig_vals
428434

@@ -435,9 +441,7 @@ def fitting_data_dict(
435441
_inv_covmat_prepared,
436442
kfold_masks,
437443
fittable_datasets_masked,
438-
output_path,
439444
threshold=0.0,
440-
diagonal_basis=True,
441445
):
442446
"""
443447
Provider which takes the information from validphys ``data``.

validphys2/src/validphys/pseudodata.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class ReplicaGenerationError(Exception):
3131
pass
3232

3333

34-
def fit_diagonal_basis_rotation(fit):
34+
def fit_diagonal_basis_rotation(fitting_covmat_name, fit):
3535
"""Rotation matrix taking pseudodata from the original to the diagonal basis,
3636
or ``None`` if ``fit`` was not run in diagonal basis.
3737
@@ -40,17 +40,14 @@ def fit_diagonal_basis_rotation(fit):
4040
applied here is bit-identical to the one used at generation time.
4141
"""
4242
runcard = fit.as_input()
43+
4344
if not runcard.get("diagonal_basis", True):
4445
return None
45-
use_thcovmat = runcard.get("theorycovmatconfig", {}).get("use_thcovmat_in_fitting", False)
46-
fname = (
47-
"datacuts_theory_theorycovmatconfig_fitting_covmat_table.csv"
48-
if use_thcovmat
49-
else "datacuts_theory_fitting_covmat_table.csv"
50-
)
46+
5147
eigensystem = pd.read_csv(
52-
fit.path / "tables" / fname, index_col=[0], header=[0], sep="\t|,", engine="python"
48+
fitting_covmat_name, index_col=[0], header=[0], sep="\t|,", engine="python"
5349
)
50+
5451
return eigensystem.iloc[:, 1:].values
5552

5653

validphys2/src/validphys/theorycovariance/construction.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -456,13 +456,10 @@ def total_theory_covmat(theory_covmat_custom, user_covmat):
456456
return theory_covmat_custom + user_covmat
457457

458458

459-
def theory_covmat_custom_fitting(theory_covmat_custom_per_prescription, procs_index_matched):
460-
"""theory_covmat_custom_per_prescription but reindexed so the order of the datasets matches
461-
those in the experiment covmat so they are aligned when fitting."""
462-
df = theory_covmat_custom_per_prescription.reindex(procs_index_matched).T.reindex(
463-
procs_index_matched
464-
)
465-
return df
459+
def _reindex_covmat_to_fitting_order(covmat, index):
460+
"""Reindex a covmat DataFrame so the dataset ordering matches the experiment
461+
covmat (the grouped/runcard order) used when fitting."""
462+
return covmat.reindex(index).T.reindex(index)
466463

467464

468465
theory_covmats_fitting = collect(theory_covmat_custom_per_prescription, ("point_prescriptions",))
@@ -474,16 +471,22 @@ def theory_covmat_custom(theory_covmats_fitting):
474471
return sum(theory_covmats_fitting)
475472

476473

474+
def theory_covmat_custom_fitting(theory_covmat_custom, procs_index_matched):
475+
"""theory_covmat_custom (summed over all point prescriptions) reindexed so the
476+
dataset ordering matches the experiment covmat for alignment when fitting."""
477+
return _reindex_covmat_to_fitting_order(theory_covmat_custom, procs_index_matched)
478+
479+
477480
def total_theory_covmat_fitting(total_theory_covmat, procs_index_matched):
478481
"""total_theory_covmat but reindexed so the order of the datasets matches
479482
those in the experiment covmat so they are aligned when fitting."""
480-
return theory_covmat_custom_fitting(total_theory_covmat, procs_index_matched)
483+
return _reindex_covmat_to_fitting_order(total_theory_covmat, procs_index_matched)
481484

482485

483486
def user_covmat_fitting(user_covmat, procs_index_matched):
484487
"""user_covmat but reindexed so the order of the datasets matches
485488
those in the experiment covmat so they are aligned when fitting."""
486-
return theory_covmat_custom_fitting(user_covmat, procs_index_matched)
489+
return _reindex_covmat_to_fitting_order(user_covmat, procs_index_matched)
487490

488491

489492
def procs_index_matched(groups_index, procs_index):

0 commit comments

Comments
 (0)