From 7932d81b4cac026a0168c6876da34ca8043ec6cf Mon Sep 17 00:00:00 2001 From: Sebastian Freund Date: Thu, 16 Nov 2023 08:47:42 +0100 Subject: [PATCH] #22 avoiding unsteady effects when checking a slice of a load data set as described in https://github.com/Gunnstein/fatpack/issues/22. - Including test case - bugfix in get_load_class_boundaries() unsing k+1 instead of k+2 --- fatpack/rainflow.py | 25 ++++++++++++++++++------- fatpack/test.py | 18 ++++++++++++++---- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/fatpack/rainflow.py b/fatpack/rainflow.py index 708d7e5..5f49e8e 100644 --- a/fatpack/rainflow.py +++ b/fatpack/rainflow.py @@ -38,15 +38,18 @@ def get_load_classes(y, k=64): return np.linspace(ymin, ymax, k+1) -def get_load_class_boundaries(y, k=64): - ymin, ymax = y.min(), y.max() +def get_load_class_boundaries(y, k=64, ymin=None, ymax=None): + if ymin is None: + ymin = y.min() + if ymax is None: + ymax = y.max() dy = (ymax-ymin) / (2.0*k) y0 = ymin - dy y1 = ymax + dy - return np.linspace(y0, y1, k+2) + return np.linspace(y0, y1, k+1) -def find_reversals_strict(y, k=64): +def find_reversals_strict(y, k=64, ymin=None, ymax=None): """Return reversals (peaks and valleys) and indices of reversals in `y`. The data points in the dataseries `y` are classified into `k` constant @@ -64,6 +67,10 @@ class boundary are rounded upwards if the reversal is a peak and downwards k : int The number of intervals to divide the min-max range of the dataseries into. + ymin : float + min value of data series + ymin : float + max value of data series Returns ------- @@ -81,7 +88,7 @@ class boundary are rounded upwards if the reversal is a peak and downwards y = y.copy() # Make sure we do not change the original sequence sgn = np.sign - Y = get_load_class_boundaries(y, k) + Y = get_load_class_boundaries(y, k, ymin, ymax) dY = Y[1] - Y[0] # Classifying points into levels @@ -128,7 +135,7 @@ class boundary are rounded upwards if the reversal is a peak and downwards return y[revix], np.array(revix) -def find_reversals(y, k=64): +def find_reversals(y, k=64, ymin=None, ymax=None): """Return reversals (peaks and valleys) and indices of reversals in `y`. The data points in the dataseries `y` are classified into `k` constant @@ -142,6 +149,10 @@ def find_reversals(y, k=64): k : int The number of intervals to divide the min-max range of the dataseries into. + ymin : float + min value of data series + ymin : float + max value of data series Returns ------- @@ -167,7 +178,7 @@ def find_reversals(y, k=64): """ - Y = get_load_class_boundaries(y, k) + Y = get_load_class_boundaries(y, k, ymin=ymin, ymax=ymax) dY = Y[1] - Y[0] # Classifying points into levels diff --git a/fatpack/test.py b/fatpack/test.py index 8e96145..2a37dc6 100644 --- a/fatpack/test.py +++ b/fatpack/test.py @@ -52,6 +52,8 @@ class_boundaries = np.array([ 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5]), + class_boundaries_minmax = np.array([-5.5, -3.5, -1.5, 0.5, 2.5, 4.5, 6.5, 8.5, 10.5, 12.5, + 14.5, 16.5, 18.5]), starting_destination_rainflow_matrix = np.array( [[ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.], [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], @@ -81,7 +83,7 @@ class TestFindReversalsStrict(BaseArrayTestCase, unittest.TestCase): def setUp(self): self.result_true = TESTDATA['reversals'] y = TESTDATA['dataseries'] - self.result, __ = find_reversals_strict(y, k=11) + self.result, __ = find_reversals_strict(y, k=12) class TestConcatenateResidue(BaseArrayTestCase, unittest.TestCase): @@ -123,14 +125,22 @@ class TestGetLoadClasses(BaseArrayTestCase, unittest.TestCase): def setUp(self): self.result_true = TESTDATA['classes'] y = TESTDATA['dataseries'] - self.result = get_load_classes(y, k=11) + self.result = get_load_classes(y, k=12) class TestGetLoadClassBoundaries(BaseArrayTestCase, unittest.TestCase): def setUp(self): self.result_true = TESTDATA['class_boundaries'] y = TESTDATA['dataseries'] - self.result = get_load_class_boundaries(y, k=11) + self.result = get_load_class_boundaries(y, k=12) + + +class TestGetLoadClassBoundariesMinMax(BaseArrayTestCase, unittest.TestCase): + def setUp(self): + self.result_true = TESTDATA['class_boundaries_minmax'] + y = TESTDATA['dataseries'] + yRange = np.max(y) - np.min(y) + self.result = get_load_class_boundaries(y, k=12, ymin=np.min(y) - yRange/2, ymax=np.max(y) + yRange/2) class TestFindRainflowMatrix(BaseArrayTestCase, unittest.TestCase): @@ -161,7 +171,7 @@ class TestFindRainflowRangesStrict(BaseArrayTestCase, unittest.TestCase): def setUp(self): self.result_true = TESTDATA['ranges_total_strict'] self.result = find_rainflow_ranges_strict( - TESTDATA['dataseries'], k=11) + TESTDATA['dataseries'], k=12) class TestFindRangeCount(unittest.TestCase):