Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend th covmat plots #1910

Merged
merged 43 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
0bf056a
init a new th covmat plot
giacomomagni Jan 15, 2024
dd7801a
make plots working
giacomomagni Jan 16, 2024
418ba12
some cleaning
giacomomagni Jan 16, 2024
04665ab
Add pull plots
andreab1997 Jan 16, 2024
a91d4ea
fix ordering in exp covmat
giacomomagni Jan 16, 2024
002703e
Merge branch 'other_thcovmat_plots' of https://github.com/NNPDF/nnpdf…
giacomomagni Jan 16, 2024
e53362b
add another diag plot by process
giacomomagni Jan 17, 2024
b3b1b65
add and additional n3lo 3pt prescription
giacomomagni Jan 17, 2024
0a9041e
Update validphys2/src/validphys/results.py
giacomomagni Jan 17, 2024
c5dd554
Update validphys2/src/validphys/results.py
giacomomagni Jan 17, 2024
d2de44d
Update validphys2/src/validphys/results.py
giacomomagni Jan 17, 2024
aee5d43
Merge branch 'master' into other_thcovmat_plots
giacomomagni Jan 17, 2024
300b9bd
Merge branch 'master' into other_thcovmat_plots
andreab1997 Jan 25, 2024
031692b
Add wrong test
andreab1997 Jan 25, 2024
b47ebcb
remove pdb
andreab1997 Jan 25, 2024
5265501
Fix regeression test
andreab1997 Jan 26, 2024
f072974
Fix bug in _covmat_t0_considered
andreab1997 Jan 29, 2024
3e8e230
Solve little bug
andreab1997 Jan 30, 2024
2b8645a
init a new th covmat plot
giacomomagni Jan 15, 2024
5633cce
make plots working
giacomomagni Jan 16, 2024
2e55128
some cleaning
giacomomagni Jan 16, 2024
29cb077
fix ordering in exp covmat
giacomomagni Jan 16, 2024
8170673
Add pull plots
andreab1997 Jan 16, 2024
d254579
add another diag plot by process
giacomomagni Jan 17, 2024
45516df
add and additional n3lo 3pt prescription
giacomomagni Jan 17, 2024
b03fed9
Update validphys2/src/validphys/results.py
giacomomagni Jan 17, 2024
9f355fb
Update validphys2/src/validphys/results.py
giacomomagni Jan 17, 2024
227c329
Update validphys2/src/validphys/results.py
giacomomagni Jan 17, 2024
fee17fd
Add wrong test
andreab1997 Jan 25, 2024
eeec162
remove pdb
andreab1997 Jan 25, 2024
4222527
Fix regeression test
andreab1997 Jan 26, 2024
569d5e3
Fix bug in _covmat_t0_considered
andreab1997 Jan 29, 2024
34dd64d
Solve little bug
andreab1997 Jan 30, 2024
d846bab
Merge branch 'other_thcovmat_plots' of github.com:NNPDF/nnpdf into ot…
andreab1997 Jan 31, 2024
638f2ed
Add regression test for entire thcovmat
andreab1997 Jan 31, 2024
b9cc5b3
Remove useless function to read regression table
andreab1997 Jan 31, 2024
9b1b5fc
Correct wrong import
andreab1997 Jan 31, 2024
dbd8516
Update validphys2/src/validphys/pdfplots.py
andreab1997 Feb 8, 2024
1a7754f
Update validphys2/src/validphys/pdfgrids.py
andreab1997 Feb 8, 2024
4a24968
Add docstring
andreab1997 Feb 8, 2024
811409d
Merge branch 'master' into other_thcovmat_plots
andreab1997 Feb 8, 2024
e503116
Add docstring for plot_diag_cov_comparison_by_process
andreab1997 Feb 8, 2024
cc29211
run black+isort+other
RoyStegeman Feb 8, 2024
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
36 changes: 11 additions & 25 deletions validphys2/src/validphys/covmats.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,7 @@ def dataset_inputs_t0_exp_covmat_separate(
return covmat


def dataset_inputs_total_covmat_separate(
dataset_inputs_exp_covmat_separate,
loaded_theory_covmat,
):
def dataset_inputs_total_covmat_separate(dataset_inputs_exp_covmat_separate, loaded_theory_covmat):
"""
Function to compute the covmat to be used for the sampling by make_replica.
In this case the t0 prescription is not used for the experimental covmat and the multiplicative
Expand Down Expand Up @@ -409,10 +406,7 @@ def dataset_inputs_exp_covmat_separate(
return covmat


def dataset_inputs_t0_total_covmat(
dataset_inputs_t0_exp_covmat,
loaded_theory_covmat,
):
def dataset_inputs_t0_total_covmat(dataset_inputs_t0_exp_covmat, loaded_theory_covmat):
"""
Function to compute the covmat to be used for the sampling by make_replica and for the chi2
by fitting_data_dict. In this case the t0 prescription is used for the experimental covmat
Expand Down Expand Up @@ -447,10 +441,7 @@ def dataset_inputs_t0_exp_covmat(
return covmat


def dataset_inputs_total_covmat(
dataset_inputs_exp_covmat,
loaded_theory_covmat,
):
def dataset_inputs_total_covmat(dataset_inputs_exp_covmat, loaded_theory_covmat):
"""
Function to compute the covmat to be used for the sampling by make_replica and for the chi2
by fitting_data_dict. In this case the t0 prescription is not used for the experimental covmat
Expand Down Expand Up @@ -529,7 +520,7 @@ def generate_exp_covmat(


def sqrt_covmat(covariance_matrix):
"""Function that computes the square root of the covariance matrix.
r"""Function that computes the square root of the covariance matrix.

Parameters
----------
Expand Down Expand Up @@ -588,7 +579,7 @@ def sqrt_covmat(covariance_matrix):
dimensions = covariance_matrix.shape

if covariance_matrix.size == 0:
return np.zeros((0,0))
return np.zeros((0, 0))
elif dimensions[0] != dimensions[1]:
raise ValueError(
"The input covariance matrix should be square but "
Expand Down Expand Up @@ -740,9 +731,9 @@ def pdferr_plus_covmat(dataset, pdf, covmat_t0_considered):
elif pdf.error_type == 'hessian':
rescale_fac = pdf._rescale_factor()
hessian_eigenvectors = th.error_members

# see core.HessianStats
X = (hessian_eigenvectors[:,0::2] - hessian_eigenvectors[:,1::2])*0.5
X = (hessian_eigenvectors[:, 0::2] - hessian_eigenvectors[:, 1::2]) * 0.5
# need to rescale the Hessian eigenvectors in case the eigenvector confidence interval is not 68%
X = X / rescale_fac
pdf_cov = X @ X.T
Expand Down Expand Up @@ -913,7 +904,7 @@ def dataspecs_datasets_covmat_differences_table(dataspecs_speclabel, dataspecs_c
return df


def _covmat_t0_considered(covmat_t0_considered, fitthcovmat, dataset):
def _covmat_t0_considered(covmat_t0_considered, fitthcovmat, dataset_input):
"""Helper function so we can dispatch the full
covariance matrix, having considered both ``use_t0``
and ``use_pdferr``
Expand All @@ -922,10 +913,11 @@ def _covmat_t0_considered(covmat_t0_considered, fitthcovmat, dataset):
# exploit `reorder_thcovmat_as_expcovmat` to take only the part of the covmat for the relevant dataset
return (
covmat_t0_considered
+ reorder_thcovmat_as_expcovmat(fitthcovmat, [dataset]).values
+ reorder_thcovmat_as_expcovmat(fitthcovmat, [dataset_input]).values
)
return covmat_t0_considered


def _dataset_inputs_covmat_t0_considered(dataset_inputs_covmat_t0_considered, fitthcovmat, data):
"""Helper function so we can dispatch the full
covariance matrix accross dataset_inputs, having considered both ``use_t0``
Expand Down Expand Up @@ -956,10 +948,4 @@ def _dataset_inputs_covmat_t0_considered(dataset_inputs_covmat_t0_considered, fi

datasets_covmat = collect('covariance_matrix', ('data',))

datasets_covariance_matrix = collect(
'covariance_matrix',
(
'experiments',
'experiment',
),
)
datasets_covariance_matrix = collect('covariance_matrix', ('experiments', 'experiment'))
39 changes: 39 additions & 0 deletions validphys2/src/validphys/pdfgrids.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,45 @@ def distance_grids(pdfs, xplotting_grids, normalize_to: (int, str, type(None)) =
return newgrids


@check_pdf_normalize_to
def pull_grids(pdfs, xplotting_grids, normalize_to: (int, str, type(None)) = None):
"""Return an object containing the value of the pull between the two PDFs at the specified values
of x and flavour.
The parameter ``normalize_to`` identifies the reference PDF set with respect to the
pull is computed.
This method returns pull grids where the relative pull between both PDF
sets, defined as the distance in terms of the standard deviations of the reference PDF, is computed. At least one grid will be identical to zero.
"""

gr2_stats = xplotting_grids[normalize_to].grid_values
cv2 = gr2_stats.central_value()
sg2 = gr2_stats.std_error()

newgrids = []
for grid, pdf in zip(xplotting_grids, pdfs):
if pdf == pdfs[normalize_to]:
# Zero the PDF we are normalizing against
pdf_zero = pdf.stats_class(np.zeros_like(gr2_stats.data[0:1]))
newgrid = grid.copy_grid(grid_values=pdf_zero)
newgrids.append(newgrid)
continue

g_stats = grid.grid_values
cv1 = g_stats.central_value()
sg1 = g_stats.std_error()

# Wrap the pull into a Stats (1, flavours, points)
pull = Stats([np.sqrt((cv1 - cv2) ** 2 / (sg1**2 + sg2**2))])

newgrid = grid.copy_grid(grid_values=pull)
newgrids.append(newgrid)

return newgrids


pull_grids_list = collect(pull_grids, ('pdfs_list',))


@check_pdf_normalize_to
def variance_distance_grids(pdfs, xplotting_grids, normalize_to: (int, str, type(None)) = None):
"""Return an object containing the value of the variance distance PDF at the specified values
Expand Down
112 changes: 107 additions & 5 deletions validphys2/src/validphys/pdfplots.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,112 @@ def plot_pdf_uncertainties(
yield from UncertaintyPDFPlotter(pdfs, xplotting_grids, xscale, normalize_to, ymin, ymax)


class PullPDFPlotter(metaclass=abc.ABCMeta):
"""Auxiliary class which groups multiple pulls in one plot.

pdfs_list is a list of dictionaries, each containing the two PDFs to be used
for the pull.
pull_grids_list is the list of the pull computed for the PDF pairs described
by pdfs_list.
"""

def __init__(self, pdfs_list, pull_grids_list, xscale, normalize_to, ymin, ymax):
self.pdfs_list = pdfs_list
self.pull_grids_list = pull_grids_list
self._xscale = xscale
self.normalize_to = normalize_to
self.ymin = ymin
self.ymax = ymax
self.firstgrid = pull_grids_list[0][0]

def legend(self, flstate):
return flstate.ax.legend()

def get_ylabel(self):
return "Pull"

@property
def Q(self):
return self.firstgrid.Q

@property
def xscale(self):
if self._xscale is None:
return scale_from_grid(self.firstgrid)
return self._xscale

def get_title(self, flstate):
return '$%s$' % flstate.parton_name + f', Q={self.Q : .1f} GeV'

def draw(self, pdfs, grid, flstate):
ax = flstate.ax
flindex = flstate.flindex
color = ax._get_lines.get_next_color()

# The grid for the pull is (1, flavours, points)
# take only the flavour we are interested in
gv = grid.select_flavour(flindex).grid_values.data.squeeze()

ax.plot(grid.xgrid, gv, color=color, label=f'{pdfs[0].label}-{pdfs[1].label}')

return gv

def plot_call(self):
basis = self.firstgrid.basis
for flindex, fl in enumerate(self.firstgrid.flavours):
fig, ax = plotutils.subplots()
parton_name = basis.elementlabel(fl)
flstate = FlavourState(flindex=flindex, fl=fl, fig=fig, ax=ax, parton_name=parton_name)
ax.set_title(self.get_title(flstate))

all_vals = []
for pdf, grids in zip(self.pdfs_list, self.pull_grids_list):
limits = self.draw([pdf['pdfs'][0], pdf['pdfs'][1]], grids[1], flstate)
if limits is not None:
all_vals.append(np.atleast_2d(limits))

# Note these two lines do not conmute!
ax.set_xscale(self.xscale)
plotutils.frame_center(ax, self.firstgrid.xgrid, np.concatenate(all_vals))
if self.ymin is not None:
ax.set_ylim(ymin=self.ymin)
if self.ymax is not None:
ax.set_ylim(ymax=self.ymax)

ax.set_xlabel('$x$')
ax.set_xlim(self.firstgrid.xgrid[0])

ax.set_ylabel(self.get_ylabel())

ax.set_axisbelow(True)

self.legend(flstate)
yield fig, parton_name

def __call__(self):
for fig, parton_name in self.plot_call():
ax = fig.get_axes()[0]
ymin, _ = ax.get_ylim()
ax.set_ylim(max(0, ymin), None)
yield fig, parton_name


@figuregen
@check_scale('xscale', allow_none=True)
def plot_pdf_pulls(
pdfs_list,
pull_grids_list,
xscale: (str, type(None)) = None,
normalize_to: (int, str, type(None)) = None,
ymin=None,
ymax=None,
):
"""Plot the PDF standard deviations as a function of x.
If normalize_to is set, the ratio to that
PDF's central value is plotted. Otherwise it is the absolute values."""
yield from PullPDFPlotter(pdfs_list, pull_grids_list, xscale, normalize_to, ymin, ymax)()


class AllFlavoursPlotter(PDFPlotter):
"""Auxiliary class which groups multiple PDF flavours in one plot."""

Expand Down Expand Up @@ -799,11 +905,7 @@ def plot_lumi1d(
handles.append(handle)
labels.append(f"{pdf.label} {label_add}")

ax.legend(
handles,
labels,
handler_map={plotutils.HandlerSpec: plotutils.ComposedHandler()},
)
ax.legend(handles, labels, handler_map={plotutils.HandlerSpec: plotutils.ComposedHandler()})

ax.set_ylabel(ylabel)
ax.set_xlabel("$m_{X}$ (GeV)")
Expand Down
32 changes: 28 additions & 4 deletions validphys2/src/validphys/results.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
results.py

Expand Down Expand Up @@ -103,12 +102,15 @@ def sqrtcovmat(self):
def name(self):
return self._dataset.name


class ThPredictionsResult(StatsResult):
"""Class holding theory prediction, inherits from StatsResult
When created with `from_convolution`, it keeps tracks of the PDF for which it was computed
"""

def __init__(self, dataobj, stats_class, datasetnames=None, label=None, pdf=None, theoryid=None):
def __init__(
self, dataobj, stats_class, datasetnames=None, label=None, pdf=None, theoryid=None
):
self.stats_class = stats_class
self.label = label
self._datasetnames = datasetnames
Expand All @@ -129,7 +131,7 @@ def make_label(pdf, dataset):
elif hasattr(th, "label"):
label = th.label
else:
label = "%s@<Theory %s>" % (pdf, th.id)
label = "{}@<Theory {}>".format(pdf, th.id)
return label

@classmethod
Expand Down Expand Up @@ -291,9 +293,19 @@ def procs_data_values(proc_result_table):
return data_central_values


def procs_data_values_experiment(proc_result_table_experiment):
"""Like groups_data_values but grouped by experiment."""
data_central_values = proc_result_table_experiment["data_central"]
return data_central_values


groups_results = collect("dataset_inputs_results", ("group_dataset_inputs_by_metadata",))

procs_results = collect("dataset_inputs_results", ("group_dataset_inputs_by_process",))
procs_results = collect("dataset_inputs_results_central", ("group_dataset_inputs_by_process",))

procs_results_experiment = collect(
"dataset_inputs_results_central", ("group_dataset_inputs_by_experiment",)
)


def group_result_table_no_table(groups_results, groups_index):
Expand Down Expand Up @@ -334,6 +346,11 @@ def proc_result_table(proc_result_table_no_table):
return proc_result_table_no_table


@table
def proc_result_table_experiment(procs_results_experiment, experiments_index):
return group_result_table_no_table(procs_results_experiment, experiments_index)


experiment_result_table = collect("group_result_table", ("group_dataset_inputs_by_experiment",))


Expand Down Expand Up @@ -567,6 +584,13 @@ def results_with_scale_variations(results, theory_covmat_dataset):
return (data_result, theory_error_result)


def dataset_inputs_results_central(
data, pdf: PDF, dataset_inputs_covariance_matrix, dataset_inputs_sqrt_covmat
):
"""Like `dataset_inputs_results` but for a group of datasets and replica0."""
return results_central(data, pdf, dataset_inputs_covariance_matrix, dataset_inputs_sqrt_covmat)


def dataset_inputs_results(
data, pdf: PDF, dataset_inputs_covariance_matrix, dataset_inputs_sqrt_covmat
):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@
'n3lo 3pt hadronic': ['(0, 0, 0, 0)','(1, 0, 0, 0)','(2, 0, 0, 0)','(3, 0, 0, 0)','(4, 0, 0, 0)','(5, 0, 0, 0)','(6, 0, 0, 0)','(7, 0, 0, 0)','(8, 0, 0, 0)','(9, 0, 0, 0)','(10, 0, 0, 0)','(11, 0, 0, 0)','(12, 0, 0, 0)','(13, 0, 0, 0)','(14, 0, 0, 0)','(15, 0, 0, 0)','(16, 0, 0, 0)','(17, 0, 0, 0)','(18, 0, 0, 0)','(19, 0, 0, 0)','(0, 1, 0, 0)','(0, 2, 0, 0)','(0, 3, 0, 0)','(0, 4, 0, 0)','(0, 5, 0, 0)','(0, 6, 0, 0)','(0, 7, 0, 0)','(0, 8, 0, 0)','(0, 9, 0, 0)','(0, 10, 0, 0)','(0, 11, 0, 0)','(0, 12, 0, 0)','(0, 13, 0, 0)','(0, 14, 0, 0)','(0, 15, 0, 0)','(0, 16, 0, 0)','(0, 17, 0, 0)','(0, 18, 0, 0)','(0, 19, 0, 0)','(0, 20, 0, 0)','(0, 21, 0, 0)','(0, 0, 1, 0)','(0, 0, 2, 0)','(0, 0, 3, 0)','(0, 0, 4, 0)','(0, 0, 5, 0)','(0, 0, 6, 0)','(0, 0, 7, 0)','(0, 0, 8, 0)','(0, 0, 9, 0)','(0, 0, 10, 0)','(0, 0, 11, 0)','(0, 0, 12, 0)','(0, 0, 13, 0)','(0, 0, 14, 0)','(0, 0, 15, 0)','(0, 0, 0, 1)','(0, 0, 0, 2)','(0, 0, 0, 3)','(0, 0, 0, 4)','(0, 0, 0, 5)','(0, 0, 0, 6)', '(1, 0.5 hadronic)', '(1, 2 hadronic)','(-1, -1)','(1, 1)']
# N3LO 7 point scale variations
'n3lo 7 point': ['(0, 0, 0, 0)', '(2, 1)', '(0.5, 1)', '(1, 2)', '(1, 0.5)', '(2, 2)', '(0.5, 0.5)']
# N3LO 3 point hadronic renormalization scale variations
'n3lo 3r point hadronic': ['(0, 0, 0, 0)', '(1, 0.5 hadronic)', '(1, 2 hadronic)']
# N3LO 3 point missing renormalization scale variations
'n3lo 3r point missing': ['(0, 0, 0, 0)', '(1, 0.5 missing)', '(1, 2 missing)']
Loading