From 7e700c8800ea878ab6e2216b743374d674d03a9d Mon Sep 17 00:00:00 2001
From: David Robert Verelst <dave@dtu.dk>
Date: Wed, 14 Jun 2017 14:30:23 +0200
Subject: [PATCH] tests for eq_load and fatigue_lifetime

---
 wetb/prepost/tests/test_Simulations.py | 113 ++++++++++++++++++++++++-
 1 file changed, 110 insertions(+), 3 deletions(-)

diff --git a/wetb/prepost/tests/test_Simulations.py b/wetb/prepost/tests/test_Simulations.py
index b6ea828..00a7c4d 100644
--- a/wetb/prepost/tests/test_Simulations.py
+++ b/wetb/prepost/tests/test_Simulations.py
@@ -14,16 +14,22 @@ import unittest
 import os
 import filecmp
 import shutil
-#import pickle
 
-from wetb.prepost import dlctemplate as tmpl
+import numpy as np
+import pandas as pd
 
+from wetb.prepost import dlctemplate as tmpl
+from wetb.prepost import Simulations as sim
+from wetb.fatigue_tools.fatigue import eq_load
 
-class TestGenerateInputs(unittest.TestCase):
 
+class Template(unittest.TestCase):
     def setUp(self):
         self.basepath = os.path.dirname(__file__)
 
+
+class TestGenerateInputs(Template):
+
     def test_launch_dlcs_excel(self):
         # manually configure paths, HAWC2 model root path is then constructed as
         # p_root_remote/PROJECT/sim_id, and p_root_local/PROJECT/sim_id
@@ -75,5 +81,106 @@ class TestGenerateInputs(unittest.TestCase):
 #        self.assertTrue(pkl_remote == pkl_ref)
 
 
+class TestFatigueLifetime(Template):
+
+    def test_leq_1hz(self):
+        """Simple test of wetb.fatigue_tools.fatigue.eq_load using a sine
+        signal.
+        """
+        amplitude = 1
+        m = 1
+        point_per_deg = 100
+
+        # sine signal with 10 periods (20 peaks)
+        nr_periods = 10
+        time = np.linspace(0, nr_periods*2*np.pi, point_per_deg*180)
+        neq = time[-1]
+        # mean value of the signal shouldn't matter
+        signal = amplitude * np.sin(time) + 5
+        r_eq_1hz = eq_load(signal, no_bins=1, m=m, neq=neq)[0]
+        r_eq_1hz_expected = ((2*nr_periods*amplitude**m)/neq)**(1/m)
+        np.testing.assert_allclose(r_eq_1hz, r_eq_1hz_expected)
+
+        # sine signal with 20 periods (40 peaks)
+        nr_periods = 20
+        time = np.linspace(0, nr_periods*2*np.pi, point_per_deg*180)
+        neq = time[-1]
+        # mean value of the signal shouldn't matter
+        signal = amplitude * np.sin(time) + 9
+        r_eq_1hz2 = eq_load(signal, no_bins=1, m=m, neq=neq)[0]
+        r_eq_1hz_expected2 = ((2*nr_periods*amplitude**m)/neq)**(1/m)
+        np.testing.assert_allclose(r_eq_1hz2, r_eq_1hz_expected2)
+
+        # 1hz equivalent load should be independent of the length of the signal
+        np.testing.assert_allclose(r_eq_1hz, r_eq_1hz2)
+
+    def test_leq_life(self):
+        """Verify if prepost.Simulation.Cases.fatigue_lifetime() returns
+        the expected life time equivalent load.
+        """
+        # ---------------------------------------------------------------------
+        # very simple case
+        cases = {'case1':{'[post_dir]':'no-path', '[sim_id]':'A0'},
+                 'case2':{'[post_dir]':'no-path', '[sim_id]':'A0'}}
+        cc = sim.Cases(cases)
+
+        fh_list = [('case1', 10/3600), ('case2', 20/3600)]
+        dfs = pd.DataFrame({'m=1.0' : [2, 3],
+                            'channel' : ['channel1', 'channel1'],
+                            '[case_id]' : ['case1', 'case2']})
+        neq_life = 1.0
+        df_Leq = cc.fatigue_lifetime(dfs, neq_life, fh_lst=fh_list,
+                                     save=False, update=False, csv=False,
+                                     xlsx=False, silent=False)
+        np.testing.assert_allclose(df_Leq['m=1.0'].values, 2*10 + 3*20)
+        self.assertTrue(df_Leq['channel'].values[0]=='channel1')
+
+        # ---------------------------------------------------------------------
+        # slightly more complicated
+        neq_life = 3.0
+        df_Leq = cc.fatigue_lifetime(dfs, neq_life, fh_lst=fh_list,
+                                     save=False, update=False, csv=False,
+                                     xlsx=False, silent=False)
+        np.testing.assert_allclose(df_Leq['m=1.0'].values,
+                                   (2*10 + 3*20)/neq_life)
+
+        # ---------------------------------------------------------------------
+        # a bit more complex and also test the sorting of fh_lst and dfs
+        cases = {'case1':{'[post_dir]':'no-path', '[sim_id]':'A0'},
+                 'case2':{'[post_dir]':'no-path', '[sim_id]':'A0'},
+                 'case3':{'[post_dir]':'no-path', '[sim_id]':'A0'},
+                 'case4':{'[post_dir]':'no-path', '[sim_id]':'A0'}}
+        cc = sim.Cases(cases)
+
+        fh_list = [('case3', 10/3600), ('case2', 20/3600),
+                   ('case1', 50/3600), ('case4', 40/3600)]
+        dfs = pd.DataFrame({'m=3.0' : [2, 3, 4, 5],
+                            'channel' : ['channel1']*4,
+                            '[case_id]' : ['case4', 'case2', 'case3', 'case1']})
+        neq_life = 5.0
+        df_Leq = cc.fatigue_lifetime(dfs, neq_life, fh_lst=fh_list,
+                                     save=False, update=False, csv=False,
+                                     xlsx=False, silent=False)
+        expected = ((2*2*2*40 + 3*3*3*20 + 4*4*4*10 + 5*5*5*50)/5)**(1/3)
+        np.testing.assert_allclose(df_Leq['m=3.0'].values, expected)
+
+        # ---------------------------------------------------------------------
+        # more cases and with sorting
+        base = {'[post_dir]':'no-path', '[sim_id]':'A0'}
+        cases = {'case%i' % k : base for k in range(50)}
+        cc = sim.Cases(cases)
+        # reverse the order of how they appear in dfs and fh_lst
+        fh_list = [('case%i' % k, k*10/3600) for k in range(49,-1,-1)]
+        dfs = pd.DataFrame({'m=5.2' : np.arange(1,51,1),
+                            'channel' : ['channel1']*50,
+                            '[case_id]' : ['case%i' % k for k in range(50)]})
+        df_Leq = cc.fatigue_lifetime(dfs, neq_life, fh_lst=fh_list,
+                                     save=False, update=False, csv=False,
+                                     xlsx=False, silent=False)
+        expected = np.sum(np.power(np.arange(1,51,1), 5.2)*np.arange(0,50,1)*10)
+        expected = np.power(expected/neq_life, 1/5.2)
+        np.testing.assert_allclose(df_Leq['m=5.2'].values, expected)
+
+
 if __name__ == "__main__":
     unittest.main()
-- 
GitLab