From 4bd1fa2591556fc3f46d89c751a9d2492015114b Mon Sep 17 00:00:00 2001
From: leufen1 <l.leufen@fz-juelich.de>
Date: Mon, 16 May 2022 09:24:38 +0200
Subject: [PATCH] new helper relative round

---
 mlair/helpers/helpers.py          | 15 +++++++++++++
 test/test_helpers/test_helpers.py | 35 ++++++++++++++++++++++++++++++-
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/mlair/helpers/helpers.py b/mlair/helpers/helpers.py
index 8104c7c5..b583cf7d 100644
--- a/mlair/helpers/helpers.py
+++ b/mlair/helpers/helpers.py
@@ -122,6 +122,21 @@ def float_round(number: float, decimals: int = 0, round_type: Callable = math.ce
     return round_type(number * multiplier) / multiplier
 
 
+def relative_round(x: float, sig: int) -> float:
+    """
+    Round small numbers according to given "significance".
+
+    Example: relative_round(0.03112, 2) -> 0.031, relative_round(0.03112, 1) -> 0.03
+
+    :params x: number to round
+    :params sig: "significance" to determine number of decimals
+
+    :return: rounded number
+    """
+    assert sig >= 1
+    return round(x, sig-int(np.floor(np.log10(abs(x))))-1)
+
+
 def remove_items(obj: Union[List, Dict, Tuple], items: Any):
     """
     Remove item(s) from either list, tuple or dictionary.
diff --git a/test/test_helpers/test_helpers.py b/test/test_helpers/test_helpers.py
index b850b361..70640be9 100644
--- a/test/test_helpers/test_helpers.py
+++ b/test/test_helpers/test_helpers.py
@@ -15,7 +15,7 @@ import string
 from mlair.helpers import to_list, dict_to_xarray, float_round, remove_items, extract_value, select_from_dict, sort_like
 from mlair.helpers import PyTestRegex
 from mlair.helpers import Logger, TimeTracking
-from mlair.helpers.helpers import is_xarray, convert2xrda
+from mlair.helpers.helpers import is_xarray, convert2xrda, relative_round
 
 
 class TestToList:
@@ -171,6 +171,39 @@ class TestFloatRound:
         assert float_round(-34.9221, 0) == -34.
 
 
+class TestRelativeRound:
+
+    def test_relative_round_big_numbers(self):
+        assert relative_round(101, 1) == 100
+        assert relative_round(99, 1) == 100
+        assert relative_round(105, 2) == 100
+        assert relative_round(106, 2) == 110
+        assert relative_round(106, 3) == 106
+
+    def test_relative_round_float_numbers(self):
+        assert relative_round(101.2033, 4) == 101.2
+        assert relative_round(101.2033, 5) == 101.2
+        assert relative_round(101.2033, 6) == 101.203
+
+    def test_relative_round_small_numbers(self):
+        assert relative_round(0.03112, 2) == 0.031
+        assert relative_round(0.03112, 1) == 0.03
+        assert relative_round(0.031126, 4) == 0.03113
+
+    def test_relative_round_negative_numbers(self):
+        assert relative_round(-101.2033, 5) == -101.2
+        assert relative_round(-106, 2) == -110
+        assert relative_round(-0.03112, 2) == -0.031
+        assert relative_round(-0.03112, 1) == -0.03
+        assert relative_round(-0.031126, 4) == -0.03113
+
+    def test_relative_round_wrong_significance(self):
+        with pytest.raises(AssertionError):
+            relative_round(300, -1)
+        with pytest.raises(TypeError):
+            relative_round(300, 1.1)
+
+
 class TestSelectFromDict:
 
     @pytest.fixture
-- 
GitLab