From bec625590b18a7e7982e00cc5765e71c5aabf125 Mon Sep 17 00:00:00 2001 From: "Ryan (Marty) LaRocque" Date: Thu, 26 Mar 2020 23:14:48 -0600 Subject: [PATCH 1/3] Added relative tolerence functionality to assert_xydata() and assert_bin_values() --- matplotcheck/base.py | 56 ++++++++++++++--------- matplotcheck/tests/test_base_data.py | 68 ++++++++++++++++++++++++---- 2 files changed, 93 insertions(+), 31 deletions(-) diff --git a/matplotcheck/base.py b/matplotcheck/base.py index 6bdcc12c..94fec9c0 100644 --- a/matplotcheck/base.py +++ b/matplotcheck/base.py @@ -829,11 +829,13 @@ def assert_xydata( points_only=False, xtime=False, xlabels=False, - tolerence=0, + tol_rel=0, + tol_abs=0, message="Incorrect data values", ): """Asserts that the x and y data of Axes `ax` matches `xy_expected` - with error message `m`. If ``xy_expected = None``, assertion is passed. + with error message `message`. If ``xy_expected = None``, + assertion is passed. Parameters ---------- @@ -860,12 +862,15 @@ def assert_xydata( Set ``True`` if using x axis labels rather than x data. Instead of comparing numbers in the x-column to expected, compares numbers or text in x labels to expected. - tolerence : float - Measure of relative error allowed. - For example: Given a tolerance ``tolerence=0.1``, an expected value - ``e``, and an actual value ``a``, this asserts - ``abs(a - e) < (e * 0.1)``. (This uses `np.testing.assert_allclose` - with ``rtol=tolerence`` and ``atol=inf``.) + tol_rel : float + A non-zero value of tol_rel allows a relative tolerance when + checking the data. For example, a relative tolerance of 0.1 would + check that the actual data is within 10% of the actual data. + tol_abs : float + A non-zero value of tol_abs allows an absolute tolerance when + checking the data. For example, an absolute tolerance of 1 checks + that the actual data does not differ from the expected data by more + than 1. message : string The error message to be displayed if the xy-data does not match `xy_expected` @@ -874,7 +879,8 @@ def assert_xydata( Raises ------- AssertionError - with message `m` if legends overlap + with message `message`, if x and y data of Axes `ax` does not match + `xy_expected` """ if xy_expected is None: return @@ -909,19 +915,21 @@ def assert_xydata( xy_expected.sort_values(by=xcol), ) - if tolerence > 0: + if tol_rel > 0 or tol_abs > 0: if xtime: raise ValueError("tolerance must be 0 with datetime on x-axis") np.testing.assert_allclose( xy_data["x"], xy_expected[xcol], - rtol=tolerence, + rtol=tol_rel, + atol=tol_abs, err_msg=message, ) np.testing.assert_allclose( xy_data["y"], xy_expected[ycol], - rtol=tolerence, + rtol=tol_rel, + atol=tol_abs, err_msg=message, ) @@ -1225,7 +1233,8 @@ def get_bin_midpoints(self): def assert_bin_values( self, bin_values, - tolerance=0, + tol_rel=0, + tol_abs=0, message="Did not find expected bin values in plot", ): """Asserts that the values of histogram bins match `bin_values`. @@ -1235,12 +1244,16 @@ def assert_bin_values( bin_values : list A list of numbers representing the expected values of each consecutive bin (i.e. the heights of the bars in the histogram). - tolerence : float - Measure of relative error allowed. - For example: Given a tolerance ``tolerence=0.1``, an expected value - ``e``, and an actual value ``a``, this asserts - ``abs(a - e) < (e * 0.1)``. (This uses `np.testing.assert_allclose` - with ``rtol=tolerence`` and ``atol=inf``.) + tol_rel : float + A non-zero value of tol_rel allows a relative tolerance when + checking the bin values. For example, a relative tolerance of 0.1 + would check that the actual bin values are within 10% of the + expected bin values. + tol_abs : float + A non-zero value of tol_abs allows an absolute tolerance when + checking the bin values. For example, an absolute tolerance of 1 + checks that the actual bin values do not differ from the expected + bin values by more than 1. message : string The error message to be displayed if the bin values do not match `bin_values` @@ -1262,12 +1275,13 @@ def assert_bin_values( expected_bin_values = bin_values plot_bin_values = self.get_bin_values() - if tolerance > 0: + if tol_rel > 0 or tol_abs > 0: try: np.testing.assert_allclose( plot_bin_values, expected_bin_values, - rtol=tolerance, + rtol=tol_rel, + atol=tol_abs, err_msg=message, ) except AssertionError: diff --git a/matplotcheck/tests/test_base_data.py b/matplotcheck/tests/test_base_data.py index a9cea54d..e682d899 100644 --- a/matplotcheck/tests/test_base_data.py +++ b/matplotcheck/tests/test_base_data.py @@ -87,21 +87,42 @@ def test_assert_xydata_scatter(pt_scatter_plt, pd_df): plt.close() -def test_assert_xydata_tolerance(pt_scatter_plt, pd_df): +def test_assert_xydata_rel_tol(pt_scatter_plt, pd_df): """Checks that slightly altered data still passes with an appropriate - tolerance""" + relative tolerence""" for i in range(len(pd_df["A"])): pd_df["A"][i] = pd_df["A"][i] + (np.floor(pd_df["A"][i] * 0.25)) pd_df["B"][i] = pd_df["B"][i] + (np.floor(pd_df["B"][i] * 0.25)) - pt_scatter_plt.assert_xydata(pd_df, xcol="A", ycol="B", tolerence=0.5) + pt_scatter_plt.assert_xydata(pd_df, xcol="A", ycol="B", tol_rel=0.5) plt.close() -def test_assert_xydata_tolerance_fail(pt_scatter_plt, pd_df): - """Checks that data altered beyond the tolerance throws an assertion.""" +def test_assert_xydata_rel_tol_fail(pt_scatter_plt, pd_df): + """Checks that data altered beyond the relative tolerence throws an + AssertionError.""" pd_df["A"][1] = pd_df["A"][1] * 2 with pytest.raises(AssertionError, match="Incorrect data values"): - pt_scatter_plt.assert_xydata(pd_df, xcol="A", ycol="B", tolerence=0.1) + pt_scatter_plt.assert_xydata(pd_df, xcol="A", ycol="B", tol_rel=0.1) + plt.close() + + +def test_assert_xydata_abs_tol(pt_scatter_plt, pd_df): + """Checks that slightly altered data still passes with an appropriate + absolute tolerence""" + pd_df = pd_df.astype(np.float) + for i in range(len(pd_df["A"])): + pd_df["A"][i] = pd_df["A"][i] + np.random.choice([-0.1, 0.1]) + pd_df["B"][i] = pd_df["B"][i] + np.random.choice([-0.1, 0.1]) + pt_scatter_plt.assert_xydata(pd_df, xcol="A", ycol="B", tol_abs=0.2) + plt.close() + + +def test_assert_xydata_abs_tol_fail(pt_scatter_plt, pd_df): + """Checks that data altered beyond the absolute tolerence correctly + fails.""" + pd_df["A"][1] = pd_df["A"][1] + 1 + with pytest.raises(AssertionError, match="Incorrect data values"): + pt_scatter_plt.assert_xydata(pd_df, xcol="A", ycol="B", tol_abs=0.1) plt.close() @@ -350,19 +371,19 @@ def test_assert_bin_values_incorrect(pt_hist_overlapping): plt.close() -def test_assert_bin_values_tolerance(pt_hist_overlapping): +def test_assert_bin_values_tol_rel(pt_hist_overlapping): """Test that assert_bin_values correctly passes when using tolerance flag.""" bin_values = pt_hist_overlapping.get_bin_values() for i in range(len(bin_values)): bin_values[i] = bin_values[i] * 1.1 - pt_hist_overlapping.assert_bin_values(bin_values, tolerance=0.11) + pt_hist_overlapping.assert_bin_values(bin_values, tol_rel=0.11) plt.close() -def test_assert_bin_values_tolerance_fails(pt_hist_overlapping): +def test_assert_bin_values_tol_rel_fails(pt_hist_overlapping): """Test that assert_bin_values correctly fails when using tolerance flag.""" bin_values = pt_hist_overlapping.get_bin_values() @@ -372,7 +393,34 @@ def test_assert_bin_values_tolerance_fails(pt_hist_overlapping): with pytest.raises( AssertionError, match="Did not find expected bin values in plot" ): - pt_hist_overlapping.assert_bin_values(bin_values, tolerance=0.09) + pt_hist_overlapping.assert_bin_values(bin_values, tol_rel=0.09) + + plt.close() + + +def test_assert_bin_values_tol_abs(pt_hist_overlapping): + """Test that assert_bin_values correctly passes when using tolerance + flag.""" + bin_values = pt_hist_overlapping.get_bin_values() + for i in range(len(bin_values)): + bin_values[i] = bin_values[i] + 1 + + pt_hist_overlapping.assert_bin_values(bin_values, tol_abs=2) + + plt.close() + + +def test_assert_bin_values_tol_abs_fails(pt_hist_overlapping): + """Test that assert_bin_values correctly fails when using tolerance + flag.""" + bin_values = pt_hist_overlapping.get_bin_values() + for i in range(len(bin_values)): + bin_values[i] = bin_values[i] + 1 + + with pytest.raises( + AssertionError, match="Did not find expected bin values in plot" + ): + pt_hist_overlapping.assert_bin_values(bin_values, tol_abs=0.5) plt.close() From 047915f41da78c02f5e51373ebe5c12b73a8297b Mon Sep 17 00:00:00 2001 From: "Ryan (Marty) LaRocque" Date: Thu, 26 Mar 2020 23:18:11 -0600 Subject: [PATCH 2/3] Fixed docstrings --- matplotcheck/tests/test_base_data.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/matplotcheck/tests/test_base_data.py b/matplotcheck/tests/test_base_data.py index e682d899..aa1bc1fe 100644 --- a/matplotcheck/tests/test_base_data.py +++ b/matplotcheck/tests/test_base_data.py @@ -372,8 +372,8 @@ def test_assert_bin_values_incorrect(pt_hist_overlapping): def test_assert_bin_values_tol_rel(pt_hist_overlapping): - """Test that assert_bin_values correctly passes when using tolerance - flag.""" + """Test that assert_bin_values correctly passes when using relative + tolerence.""" bin_values = pt_hist_overlapping.get_bin_values() for i in range(len(bin_values)): bin_values[i] = bin_values[i] * 1.1 @@ -384,8 +384,8 @@ def test_assert_bin_values_tol_rel(pt_hist_overlapping): def test_assert_bin_values_tol_rel_fails(pt_hist_overlapping): - """Test that assert_bin_values correctly fails when using tolerance - flag.""" + """Test that assert_bin_values correctly fails when using relative + tolerence.""" bin_values = pt_hist_overlapping.get_bin_values() for i in range(len(bin_values)): bin_values[i] = bin_values[i] * 1.1 @@ -399,8 +399,8 @@ def test_assert_bin_values_tol_rel_fails(pt_hist_overlapping): def test_assert_bin_values_tol_abs(pt_hist_overlapping): - """Test that assert_bin_values correctly passes when using tolerance - flag.""" + """Test that assert_bin_values correctly passes when using absolute + tolerence.""" bin_values = pt_hist_overlapping.get_bin_values() for i in range(len(bin_values)): bin_values[i] = bin_values[i] + 1 @@ -411,8 +411,8 @@ def test_assert_bin_values_tol_abs(pt_hist_overlapping): def test_assert_bin_values_tol_abs_fails(pt_hist_overlapping): - """Test that assert_bin_values correctly fails when using tolerance - flag.""" + """Test that assert_bin_values correctly fails when using absolute + tolerence.""" bin_values = pt_hist_overlapping.get_bin_values() for i in range(len(bin_values)): bin_values[i] = bin_values[i] + 1 From 6edd030165f81897b454cbb73345970ceeddc885 Mon Sep 17 00:00:00 2001 From: "Ryan (Marty) LaRocque" Date: Mon, 4 May 2020 02:25:49 -0600 Subject: [PATCH 3/3] Remove relative tolerance --- CHANGELOG.rst | 2 + matplotcheck/base.py | 40 +++++---------- matplotcheck/tests/test_base_data.py | 73 +++++----------------------- 3 files changed, 27 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3c68e212..88057a6d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -25,6 +25,8 @@ Unreleased in them (@nkorinek, #182) - added contributors file and updated README to remove that information (@nkorinek, #121) +- Changed tolerance functionality from relative tolerance to absolute + tolerance. (@ryla5068, #234) 0.1.2 ----- diff --git a/matplotcheck/base.py b/matplotcheck/base.py index 6f52f146..3f896c47 100644 --- a/matplotcheck/base.py +++ b/matplotcheck/base.py @@ -833,8 +833,7 @@ def assert_xydata( points_only=False, xtime=False, xlabels=False, - tol_rel=0, - tol_abs=0, + tolerance=0, message="Incorrect data values", ): """Asserts that the x and y data of Axes `ax` matches `xy_expected` @@ -866,15 +865,11 @@ def assert_xydata( Set ``True`` if using x axis labels rather than x data. Instead of comparing numbers in the x-column to expected, compares numbers or text in x labels to expected. - tol_rel : float - A non-zero value of tol_rel allows a relative tolerance when - checking the data. For example, a relative tolerance of 0.1 would - check that the actual data is within 10% of the actual data. - tol_abs : float - A non-zero value of tol_abs allows an absolute tolerance when - checking the data. For example, an absolute tolerance of 1 checks - that the actual data does not differ from the expected data by more - than 1. + tolerance : float + A non-zero value of tol_rel allows an absolute tolerance when + checking the data. For example, a tolerance of 0.1 would + check that the actual data is within 0.1 units of the actual data. + Note that the units for datetime data is always days. message : string The error message to be displayed if the xy-data does not match `xy_expected` @@ -919,21 +914,19 @@ def assert_xydata( xy_expected.sort_values(by=xcol), ) - if tol_rel > 0 or tol_abs > 0: + if tolerance > 0: if xtime: raise ValueError("tolerance must be 0 with datetime on x-axis") np.testing.assert_allclose( xy_data["x"], xy_expected[xcol], - rtol=tol_rel, - atol=tol_abs, + atol=tolerance, err_msg=message, ) np.testing.assert_allclose( xy_data["y"], xy_expected[ycol], - rtol=tol_rel, - atol=tol_abs, + atol=tolerance, err_msg=message, ) @@ -1237,8 +1230,7 @@ def get_bin_midpoints(self): def assert_bin_values( self, bin_values, - tol_rel=0, - tol_abs=0, + tolerance=0, message="Did not find expected bin values in plot", ): """Asserts that the values of histogram bins match `bin_values`. @@ -1248,12 +1240,7 @@ def assert_bin_values( bin_values : list A list of numbers representing the expected values of each consecutive bin (i.e. the heights of the bars in the histogram). - tol_rel : float - A non-zero value of tol_rel allows a relative tolerance when - checking the bin values. For example, a relative tolerance of 0.1 - would check that the actual bin values are within 10% of the - expected bin values. - tol_abs : float + tolerance : float A non-zero value of tol_abs allows an absolute tolerance when checking the bin values. For example, an absolute tolerance of 1 checks that the actual bin values do not differ from the expected @@ -1279,13 +1266,12 @@ def assert_bin_values( expected_bin_values = bin_values plot_bin_values = self.get_bin_values() - if tol_rel > 0 or tol_abs > 0: + if tolerance > 0: try: np.testing.assert_allclose( plot_bin_values, expected_bin_values, - rtol=tol_rel, - atol=tol_abs, + atol=tolerance, err_msg=message, ) except AssertionError: diff --git a/matplotcheck/tests/test_base_data.py b/matplotcheck/tests/test_base_data.py index aa1bc1fe..2a09729c 100644 --- a/matplotcheck/tests/test_base_data.py +++ b/matplotcheck/tests/test_base_data.py @@ -87,42 +87,22 @@ def test_assert_xydata_scatter(pt_scatter_plt, pd_df): plt.close() -def test_assert_xydata_rel_tol(pt_scatter_plt, pd_df): +def test_assert_xydata_tolerance(pt_scatter_plt, pd_df): """Checks that slightly altered data still passes with an appropriate - relative tolerence""" - for i in range(len(pd_df["A"])): - pd_df["A"][i] = pd_df["A"][i] + (np.floor(pd_df["A"][i] * 0.25)) - pd_df["B"][i] = pd_df["B"][i] + (np.floor(pd_df["B"][i] * 0.25)) - pt_scatter_plt.assert_xydata(pd_df, xcol="A", ycol="B", tol_rel=0.5) - plt.close() - - -def test_assert_xydata_rel_tol_fail(pt_scatter_plt, pd_df): - """Checks that data altered beyond the relative tolerence throws an - AssertionError.""" - pd_df["A"][1] = pd_df["A"][1] * 2 - with pytest.raises(AssertionError, match="Incorrect data values"): - pt_scatter_plt.assert_xydata(pd_df, xcol="A", ycol="B", tol_rel=0.1) - plt.close() - - -def test_assert_xydata_abs_tol(pt_scatter_plt, pd_df): - """Checks that slightly altered data still passes with an appropriate - absolute tolerence""" + tolerence""" pd_df = pd_df.astype(np.float) for i in range(len(pd_df["A"])): pd_df["A"][i] = pd_df["A"][i] + np.random.choice([-0.1, 0.1]) pd_df["B"][i] = pd_df["B"][i] + np.random.choice([-0.1, 0.1]) - pt_scatter_plt.assert_xydata(pd_df, xcol="A", ycol="B", tol_abs=0.2) + pt_scatter_plt.assert_xydata(pd_df, xcol="A", ycol="B", tolerance=0.2) plt.close() -def test_assert_xydata_abs_tol_fail(pt_scatter_plt, pd_df): - """Checks that data altered beyond the absolute tolerence correctly - fails.""" +def test_assert_xydata_abs_tolerance_fails(pt_scatter_plt, pd_df): + """Checks that data altered beyond the tolerence correctly fails.""" pd_df["A"][1] = pd_df["A"][1] + 1 with pytest.raises(AssertionError, match="Incorrect data values"): - pt_scatter_plt.assert_xydata(pd_df, xcol="A", ycol="B", tol_abs=0.1) + pt_scatter_plt.assert_xydata(pd_df, xcol="A", ycol="B", tolerance=0.1) plt.close() @@ -371,48 +351,19 @@ def test_assert_bin_values_incorrect(pt_hist_overlapping): plt.close() -def test_assert_bin_values_tol_rel(pt_hist_overlapping): - """Test that assert_bin_values correctly passes when using relative - tolerence.""" - bin_values = pt_hist_overlapping.get_bin_values() - for i in range(len(bin_values)): - bin_values[i] = bin_values[i] * 1.1 - - pt_hist_overlapping.assert_bin_values(bin_values, tol_rel=0.11) - - plt.close() - - -def test_assert_bin_values_tol_rel_fails(pt_hist_overlapping): - """Test that assert_bin_values correctly fails when using relative - tolerence.""" - bin_values = pt_hist_overlapping.get_bin_values() - for i in range(len(bin_values)): - bin_values[i] = bin_values[i] * 1.1 - - with pytest.raises( - AssertionError, match="Did not find expected bin values in plot" - ): - pt_hist_overlapping.assert_bin_values(bin_values, tol_rel=0.09) - - plt.close() - - -def test_assert_bin_values_tol_abs(pt_hist_overlapping): - """Test that assert_bin_values correctly passes when using absolute - tolerence.""" +def test_assert_bin_values_tolerance(pt_hist_overlapping): + """Test that assert_bin_values correctly passes when using tolerence.""" bin_values = pt_hist_overlapping.get_bin_values() for i in range(len(bin_values)): bin_values[i] = bin_values[i] + 1 - pt_hist_overlapping.assert_bin_values(bin_values, tol_abs=2) + pt_hist_overlapping.assert_bin_values(bin_values, tolerance=2) plt.close() -def test_assert_bin_values_tol_abs_fails(pt_hist_overlapping): - """Test that assert_bin_values correctly fails when using absolute - tolerence.""" +def test_assert_bin_values_tolerance_fails(pt_hist_overlapping): + """Test that assert_bin_values correctly fails when using tolerence.""" bin_values = pt_hist_overlapping.get_bin_values() for i in range(len(bin_values)): bin_values[i] = bin_values[i] + 1 @@ -420,7 +371,7 @@ def test_assert_bin_values_tol_abs_fails(pt_hist_overlapping): with pytest.raises( AssertionError, match="Did not find expected bin values in plot" ): - pt_hist_overlapping.assert_bin_values(bin_values, tol_abs=0.5) + pt_hist_overlapping.assert_bin_values(bin_values, tolerance=0.5) plt.close()