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

Clarify behaviour if zero uncertainties #251

Merged
merged 2 commits into from
Feb 14, 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
10 changes: 9 additions & 1 deletion docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -337,4 +337,12 @@ After creating the Uncertainty objects, the only additional step is to attach th
variable.add_uncertainty(unc1)
variable.add_uncertainty(unc2)


See `Uncertainties`_ for more guidance. In particular, note that ``hepdata_lib`` will omit the ``errors`` key from the
YAML output if all uncertainties are zero for a particular bin, printing a warning message "Note that bins with zero
content should preferably be omitted completely from the HEPData table". A legitimate use case is where there are
multiple dependent variables and a (different) subset of the bins has missing content for some dependent variables.
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.

.. _`Uncertainties`: https://hepdata-submission.readthedocs.io/en/latest/data_yaml.html#uncertainties
6 changes: 4 additions & 2 deletions hepdata_lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,15 @@ class Variable:
# pylint: disable=too-many-instance-attributes
# Eight is reasonable in this case.

def __init__(self, name, is_independent=True, is_binned=True, units="", values=None):
def __init__(self, name, is_independent=True, is_binned=True, units="", values=None,
zero_uncertainties_warning=True):
# pylint: disable=too-many-arguments
self.name = name
self.is_independent = is_independent
self.is_binned = is_binned
self.qualifiers = []
self.units = units
self.zero_uncertainties_warning = zero_uncertainties_warning
# needed to make pylint happy, see https://github.com/PyCQA/pylint/issues/409
self._values = None
self.values = values if values else []
Expand Down Expand Up @@ -273,7 +275,7 @@ def make_dict(self):
},
"label": unc.label
})
elif self.uncertainties:
elif self.uncertainties and self.zero_uncertainties_warning:
print(
"Warning: omitting 'errors' since all uncertainties " \
"are zero for bin {} of variable '{}'.".format(i+1, self.name)
Expand Down
26 changes: 25 additions & 1 deletion tests/test_uncertainty.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def test_scale_values(self):
def test_set_values_from_intervals(self):
'''Test behavior of Uncertainy.test_set_values_from_intervals function'''

# Dummy central values and variatons relative to central value
# Dummy central values and variations relative to central value
npoints = 100
values = list(range(0, npoints, 1))
uncertainty = [(-random.uniform(0, 1), random.uniform(0, 1))
Expand Down Expand Up @@ -91,3 +91,27 @@ def test_mixed_uncertainties(self):
pattern = ['symerror', 'asymerror', 'asymerror', 'symerror']
self.assertTrue((list(dictionary['values'][i]['errors'][0].keys())[
0], value) for i, value in enumerate(pattern))

def test_zero_uncertainties(self):
'''Test cases where a data point has zero uncertainties'''

# Asymmetric uncertainties
var = Variable("testvar", is_binned=False, values=[1, 2, 3, 4])
unc = Uncertainty("fake_unc", is_symmetric=False)
unc.values = [(-1, 1), (-1.5, 2), (0, 0), (-2.5, 2.5)]
var.add_uncertainty(unc)
dictionary = var.make_dict()
# 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])

# Symmetric uncertainties (and use "zero_uncertainties_warning=False" option)
var = Variable("testvar", is_binned=False, values=[1, 2, 3, 4],
zero_uncertainties_warning=False)
unc = Uncertainty("fake_unc", is_symmetric=True)
unc.values = [1, 1.5, 0, 2.5]
var.add_uncertainty(unc)
dictionary = var.make_dict()
# 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])
Loading