From 7bb164120be5078642c180f4bd20d7629ce38313 Mon Sep 17 00:00:00 2001 From: Fabian Joswig Date: Fri, 20 Jan 2023 11:44:31 +0000 Subject: [PATCH 1/8] tests: fuzzy test for Obs added, test dependencies and documentation updated. --- .github/workflows/pytest.yml | 1 + CONTRIBUTING.md | 4 +++- pyerrors/obs.py | 1 + setup.py | 2 +- tests/obs_test.py | 6 ++++++ 5 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 536f7d53..5321d1ae 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -40,6 +40,7 @@ jobs: pip install pytest pip install pytest-cov pip install pytest-benchmark + pip install hypothesis pip install py pip freeze diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 98ab0c75..8d803e4a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,7 +25,9 @@ For all pull requests tests are executed for the most recent python releases via pytest -vv --cov=pyerrors pytest -vv --nbmake examples/*.ipynb ``` -requiring `pytest`, `pytest-cov`, `pytest-benchmark` and `nbmake`. To get a coverage report in html run +requiring `pytest`, `pytest-cov`, `pytest-benchmark`, `hypothesis' and `nbmake`. To install the test dependencies one can run `pip install pyerrors[test]` + +To get a coverage report in html run ``` pytest --cov=pyerrors --cov-report html ``` diff --git a/pyerrors/obs.py b/pyerrors/obs.py index 9df6b5c2..d56e34ea 100644 --- a/pyerrors/obs.py +++ b/pyerrors/obs.py @@ -10,6 +10,7 @@ import matplotlib.pyplot as plt from scipy.stats import skew, skewtest, kurtosis, kurtosistest import numdifftools as nd from itertools import groupby +from hypothesis import given, strategies as st from .covobs import Covobs # Improve print output of numpy.ndarrays containing Obs objects. diff --git a/setup.py b/setup.py index 3aa4d889..6ad29512 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ setup(name='pyerrors', packages=find_packages(), python_requires='>=3.7.0', install_requires=['numpy>=1.19', 'autograd>=1.5', 'numdifftools>=0.9.41', 'matplotlib>=3.5', 'scipy>=1.7', 'iminuit>=2.17', 'h5py>=3.7', 'lxml>=4.9', 'python-rapidjson>=1.9', 'pandas>=1.1'], - extras_require={'test': ['pytest', 'pytest-cov', 'pytest-benchmark']}, + extras_require={'test': ['pytest', 'pytest-cov', 'pytest-benchmark', 'hypothesis']}, classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Science/Research', diff --git a/tests/obs_test.py b/tests/obs_test.py index 5fbedf98..aa6372d8 100644 --- a/tests/obs_test.py +++ b/tests/obs_test.py @@ -4,9 +4,15 @@ import copy import matplotlib.pyplot as plt import pyerrors as pe import pytest +from hypothesis import given, strategies as st np.random.seed(0) +@given(st.lists(st.floats(allow_nan=False, allow_infinity=False, width=32), min_size=5), st.text()) +def test_fuzzy_obs(data, string): + my_obs = pe.Obs([data], [string]) + my_obs * my_obs + def test_Obs_exceptions(): with pytest.raises(Exception): From f33db8280e1e8510d3fa92556c8b5c0021a0ea27 Mon Sep 17 00:00:00 2001 From: Fabian Joswig Date: Fri, 20 Jan 2023 11:46:16 +0000 Subject: [PATCH 2/8] fix: unnecessary import removed. --- pyerrors/obs.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyerrors/obs.py b/pyerrors/obs.py index d56e34ea..9df6b5c2 100644 --- a/pyerrors/obs.py +++ b/pyerrors/obs.py @@ -10,7 +10,6 @@ import matplotlib.pyplot as plt from scipy.stats import skew, skewtest, kurtosis, kurtosistest import numdifftools as nd from itertools import groupby -from hypothesis import given, strategies as st from .covobs import Covobs # Improve print output of numpy.ndarrays containing Obs objects. From 9ba09e6b8f49e0096d16a8035d8a0619a8554012 Mon Sep 17 00:00:00 2001 From: Fabian Joswig Date: Fri, 20 Jan 2023 11:49:44 +0000 Subject: [PATCH 3/8] tests: gamma_method added to fuzzy test. --- tests/obs_test.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/obs_test.py b/tests/obs_test.py index aa6372d8..6c4817b7 100644 --- a/tests/obs_test.py +++ b/tests/obs_test.py @@ -8,10 +8,11 @@ from hypothesis import given, strategies as st np.random.seed(0) -@given(st.lists(st.floats(allow_nan=False, allow_infinity=False, width=32), min_size=5), st.text()) -def test_fuzzy_obs(data, string): +@given(st.lists(st.floats(allow_nan=False, allow_infinity=False, width=32), min_size=5), st.text(), st.floats(allow_nan=False, allow_infinity=False, width=32, min_value=0)) +def test_fuzzy_obs(data, string, S): my_obs = pe.Obs([data], [string]) my_obs * my_obs + my_obs.gamma_method(S=S) def test_Obs_exceptions(): From 7682e2914605007e9c0253337278630ae13ef3c1 Mon Sep 17 00:00:00 2001 From: Fabian Joswig Date: Fri, 20 Jan 2023 11:54:43 +0000 Subject: [PATCH 4/8] test: tests refactored. --- tests/obs_test.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/obs_test.py b/tests/obs_test.py index 6c4817b7..cc0203c1 100644 --- a/tests/obs_test.py +++ b/tests/obs_test.py @@ -8,7 +8,9 @@ from hypothesis import given, strategies as st np.random.seed(0) -@given(st.lists(st.floats(allow_nan=False, allow_infinity=False, width=32), min_size=5), st.text(), st.floats(allow_nan=False, allow_infinity=False, width=32, min_value=0)) +@given(st.lists(st.floats(allow_nan=False, allow_infinity=False, width=32), min_size=5), + st.text(), + st.floats(allow_nan=False, allow_infinity=False, width=32, min_value=0)) def test_fuzzy_obs(data, string, S): my_obs = pe.Obs([data], [string]) my_obs * my_obs @@ -66,7 +68,7 @@ def test_Obs_exceptions(): one.plot_piechart() plt.close('all') -def test_dump(): +def test_dump_pickle(): value = np.random.normal(5, 10) dvalue = np.abs(np.random.normal(0, 1)) test_obs = pe.pseudo_Obs(value, dvalue, 't') @@ -75,6 +77,12 @@ def test_dump(): new_obs = pe.load_object('test_dump.p') os.remove('test_dump.p') assert test_obs == new_obs + + +def test_dump_json(): + value = np.random.normal(5, 10) + dvalue = np.abs(np.random.normal(0, 1)) + test_obs = pe.pseudo_Obs(value, dvalue, 't') test_obs.dump('test_dump', dataype="json.gz", path=".") test_obs.dump('test_dump', dataype="json.gz") new_obs = pe.input.json.load_json("test_dump") From 033d8e9ac4fbb71825d380b5fed966256ba8c431 Mon Sep 17 00:00:00 2001 From: Fabian Joswig Date: Mon, 23 Jan 2023 10:42:26 +0000 Subject: [PATCH 5/8] ci: python 3.11 added to pytest workflow, minimal version of h5py bumped to 3.8 --- .github/workflows/pytest.yml | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 5321d1ae..50316b09 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -16,7 +16,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - python-version: ["3.7", "3.8", "3.9", "3.10"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] include: - os: macos-latest python-version: 3.9 diff --git a/setup.py b/setup.py index 6ad29512..9391a53e 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ setup(name='pyerrors', license="MIT", packages=find_packages(), python_requires='>=3.7.0', - install_requires=['numpy>=1.19', 'autograd>=1.5', 'numdifftools>=0.9.41', 'matplotlib>=3.5', 'scipy>=1.7', 'iminuit>=2.17', 'h5py>=3.7', 'lxml>=4.9', 'python-rapidjson>=1.9', 'pandas>=1.1'], + install_requires=['numpy>=1.19', 'autograd>=1.5', 'numdifftools>=0.9.41', 'matplotlib>=3.5', 'scipy>=1.7', 'iminuit>=2.17', 'h5py>=3.8', 'lxml>=4.9', 'python-rapidjson>=1.9', 'pandas>=1.1'], extras_require={'test': ['pytest', 'pytest-cov', 'pytest-benchmark', 'hypothesis']}, classifiers=[ 'Development Status :: 5 - Production/Stable', From 9d602e4e519bc28ccab6b6053718679b92daf587 Mon Sep 17 00:00:00 2001 From: Fabian Joswig Date: Mon, 23 Jan 2023 16:23:09 +0000 Subject: [PATCH 6/8] build: minimal numpy version bumped to 1.21 as 1.20 runs out of support next week. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9391a53e..37a56f51 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ setup(name='pyerrors', license="MIT", packages=find_packages(), python_requires='>=3.7.0', - install_requires=['numpy>=1.19', 'autograd>=1.5', 'numdifftools>=0.9.41', 'matplotlib>=3.5', 'scipy>=1.7', 'iminuit>=2.17', 'h5py>=3.8', 'lxml>=4.9', 'python-rapidjson>=1.9', 'pandas>=1.1'], + install_requires=['numpy>=1.21', 'autograd>=1.5', 'numdifftools>=0.9.41', 'matplotlib>=3.5', 'scipy>=1.7', 'iminuit>=2.17', 'h5py>=3.8', 'lxml>=4.9', 'python-rapidjson>=1.9', 'pandas>=1.1'], extras_require={'test': ['pytest', 'pytest-cov', 'pytest-benchmark', 'hypothesis']}, classifiers=[ 'Development Status :: 5 - Production/Stable', From 5adc3e0c76679772e6f5623dc4488fe332f34dfc Mon Sep 17 00:00:00 2001 From: Fabian Joswig Date: Tue, 24 Jan 2023 10:10:52 +0000 Subject: [PATCH 7/8] test: sin2 cos2 test for error propagation added. --- tests/obs_test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/obs_test.py b/tests/obs_test.py index cc0203c1..b01ed034 100644 --- a/tests/obs_test.py +++ b/tests/obs_test.py @@ -17,6 +17,13 @@ def test_fuzzy_obs(data, string, S): my_obs.gamma_method(S=S) +@given(st.floats(allow_nan=False, allow_infinity=False, width=16)) +def test_sin2_cos2(value): + Obs = pe.pseudo_Obs(value, value * 0.123, "C0") + iamzero = np.sin(Obs) ** 2 + np.cos(Obs) ** 2 - 1 + assert iamzero.is_zero(atol=1e-6) + + def test_Obs_exceptions(): with pytest.raises(Exception): pe.Obs([np.random.rand(10)], ['1', '2']) From 07de2e767fa5eaab33258de6085bf07a498ca4a8 Mon Sep 17 00:00:00 2001 From: Fabian Joswig Date: Tue, 24 Jan 2023 12:59:15 +0000 Subject: [PATCH 8/8] docs: Explanation about ensemble names made more explicit in documentation. --- pyerrors/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyerrors/__init__.py b/pyerrors/__init__.py index a6fefe8d..981e0fd7 100644 --- a/pyerrors/__init__.py +++ b/pyerrors/__init__.py @@ -41,7 +41,7 @@ print(my_new_obs) # Print the result to stdout `pyerrors` introduces a new datatype, `Obs`, which simplifies error propagation and estimation for auto- and cross-correlated data. An `Obs` object can be initialized with two arguments, the first is a list containing the samples for an observable from a Monte Carlo chain. The samples can either be provided as python list or as numpy array. -The second argument is a list containing the names of the respective Monte Carlo chains as strings. These strings uniquely identify a Monte Carlo chain/ensemble. +The second argument is a list containing the names of the respective Monte Carlo chains as strings. These strings uniquely identify a Monte Carlo chain/ensemble. **It is crucial for the correct error propagation that observations from the same Monte Carlo history are labeled with the same name. See [Multiple ensembles/replica](#Multiple-ensembles/replica) for details.** ```python import pyerrors as pe @@ -142,6 +142,8 @@ my_sum.details() > · Ensemble 'ensemble1' : 1000 configurations (from 1 to 1000) > · Ensemble 'ensemble2' : 500 configurations (from 1 to 500) ``` +Observables from the **same Monte Carlo chain** have to be initialized with the **same name** for correct error propagation. If different names were used in this case the data would be treated as statistically independent resulting in loss of relevant information and a potential over or under estimate of the statistical error. + `pyerrors` identifies multiple replica (independent Markov chains with identical simulation parameters) by the vertical bar `|` in the name of the data set.