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

Add support for inhomogenous error breakdowns #265

Merged
merged 7 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -370,5 +370,7 @@ multiple dependent variables and a (different) subset of the bins has missing co
In this case the uncertainties should be set to zero for the missing bins with a non-numeric central value like ``'-'``.
The warning message can be suppressed by passing an optional argument ``zero_uncertainties_warning=False`` when
defining an instance of the ``Variable`` class.
Furthermore, note that `None` can be used to suppress the uncertainty for individual bins in cases where
the uncertainty components may only apply to a subset of the values.

.. _`Uncertainties`: https://hepdata-submission.readthedocs.io/en/latest/data_yaml.html#uncertainties
.. _`Uncertainties`: https://hepdata-submission.readthedocs.io/en/latest/data_yaml.html#uncertainties
3 changes: 3 additions & 0 deletions hepdata_lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ def add_uncertainty(self, uncertainty):
self.uncertainties.append(uncertainty)

def make_dict(self):
# pylint: disable=too-many-branches
"""
Return all data in this Variable as a dictionary.

Expand Down Expand Up @@ -277,6 +278,8 @@ def make_dict(self):
# if at least one of the uncertainties is not zero.
if nonzero_uncs[i]:
for unc in self.uncertainties:
if unc.values[i] is None:
continue
if unc.is_symmetric:
valuedict['errors'].append({
"symerror":
Expand Down
9 changes: 6 additions & 3 deletions hepdata_lib/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,8 @@ def any_uncertainties_nonzero(uncertainties, size):
for unc in uncertainties:

# Treat one-sided uncertainties as
values = np.array(unc.values)
tmp = 0 if unc.is_symmetric else (0,0)
values = np.array([tmp if v is None else v for v in unc.values])
values[values.astype(str)==''] = 0
values = values.astype(float)

Expand All @@ -273,15 +274,17 @@ def sanitize_value(value):
Handle conversion of input types for internal storage.

:param value: User-side input value to sanitize.
:type value: string, int, or castable to float
:type value: string, int, NoneType, or castable to float

Strings and integers are left alone,
Strings, integers and None are left alone,
everything else is converted to float.
"""
if isinstance(value,str):
return value
if isinstance(value,int):
return value
if value is None:
return value
20DM marked this conversation as resolved.
Show resolved Hide resolved
return float(value)


Expand Down
15 changes: 15 additions & 0 deletions tests/test_uncertainty.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,18 @@ def test_zero_uncertainties(self):
# Check that 'errors' key is missing only if zero uncertainties
self.assertTrue(all('errors' in dictionary['values'][i] for i in [0, 1, 3]))
self.assertTrue('errors' not in dictionary['values'][2])

def test_inhomogenous_uncertainties(self):
'''Test cases where an uncertainty only applies to a subset of the bins'''
var = Variable("testvar", is_independent=False, is_binned=False, values=[1,2,3],
zero_uncertainties_warning=False)
unc_a = Uncertainty('errorA', is_symmetric=True)
unc_a.values = [ 0.1, 0.2, None ]
var.add_uncertainty(unc_a)
unc_b = Uncertainty('errorB', is_symmetric=True)
unc_b.values = [ 0.1, 0.2, 0.3 ]
var.add_uncertainty(unc_b)
dictionary = var.make_dict()
self.assertTrue(len([ errs['label'] for i in [0,1,2] \
for errs in dictionary['values'][i]['errors'] \
if errs['label'] == 'errorA'])==2)