From 7622fe10c198f72690e2331837375b3c940dbd74 Mon Sep 17 00:00:00 2001
From: lukas leufen <l.leufen@fz-juelich.de>
Date: Thu, 14 Nov 2019 15:58:25 +0100
Subject: [PATCH] experiment setup class, improved time tracking

---
 run.py               | 85 +++++++++++++++++++++++++++++++++++++++-----
 src/helpers.py       | 13 +++++--
 test/test_helpers.py | 11 ++++--
 3 files changed, 96 insertions(+), 13 deletions(-)

diff --git a/run.py b/run.py
index 2781c14f..3cedc2d9 100644
--- a/run.py
+++ b/run.py
@@ -6,6 +6,78 @@ import logging
 from src.helpers import TimeTracking
 from src import helpers
 import argparse
+import time
+
+
+formatter = "%(asctime)s - %(levelname)s: %(message)s  [%(filename)s:%(funcName)s:%(lineno)s]"
+logging.basicConfig(level=logging.INFO, format=formatter)
+
+
+class run(object):
+    """
+    basic run class to measure execution time. Either call this class calling it by 'with' or delete the class instance
+    after finishing the measurement. The duration result is logged.
+    """
+
+    def __init__(self):
+        self.time = TimeTracking()
+        logging.info(f"{self.__class__.__name__} started")
+
+    def __del__(self):
+        self.time.stop()
+        logging.info(f"{self.__class__.__name__} finished after {self.time}")
+
+    def __enter__(self):
+        pass
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        pass
+
+    def do_stuff(self):
+        time.sleep(2)
+
+
+class ExperimentSetup:
+
+    def __init__(self):
+        self.data_path = None
+        self.experiment_path = None
+        self.experiment_name = None
+        self.trainable = False
+        self.setup_experiment()
+
+    def setup_experiment(self):
+
+        # set data path of this experiment
+        self.data_path = helpers.prepare_host()
+
+        # set experiment name
+        experiment_date = parser.parse_args(["experiment_date"])
+        self.experiment_name, self.experiment_path = helpers.set_experiment_name(experiment_date=experiment_date)
+
+        # set if model shall be trained or not
+        self.trainable = True
+
+
+class PreProcessing(run):
+
+    def __init__(self, setup):
+        super().__init__()
+        self.setup = setup
+
+
+class Training(run):
+
+    def __init__(self, setup):
+        super().__init__()
+        self.setup = setup
+
+
+class PostProcessing(run):
+
+    def __init__(self, setup):
+        super().__init__()
+        self.setup = setup
 
 
 if __name__ == "__main__":
@@ -14,14 +86,11 @@ if __name__ == "__main__":
     parser.add_argument('experiment date', metavar='exp_date', type=str, nargs=1,  help='set experiment date as string',
                         default=None)
 
-    logging.info("start run script")
-    total_time = TimeTracking()
+    with run():
+        exp_setup = ExperimentSetup()
 
-    # set data path of this experiment
-    data_path = helpers.prepare_host()
+        PreProcessing(exp_setup)
 
-    # set experiment name
-    experiment_date = parser.parse_args(["experiment_date"])
-    experiment_name, experiment_path = helpers.set_experiment_name(experiment_date=experiment_date)
+        Training(exp_setup)
 
-    # set if model shall be trained or not
\ No newline at end of file
+        PostProcessing(exp_setup)
diff --git a/src/helpers.py b/src/helpers.py
index e380caa6..6f8af63b 100644
--- a/src/helpers.py
+++ b/src/helpers.py
@@ -103,6 +103,7 @@ class TimeTracking(object):
 
     def _start(self):
         self.start = time.time()
+        self.end = None
 
     def _end(self):
         self.end = time.time()
@@ -119,9 +120,15 @@ class TimeTracking(object):
     def run(self):
         self._start()
 
-    def stop(self):
-        self.end = time.time()
-        return self._duration()
+    def stop(self, get_duration=False):
+        if self.end is None:
+            self._end()
+        else:
+            msg = f"Time was already stopped {time.time() - self.end}s ago."
+            logging.error(msg)
+            raise AssertionError(msg)
+        if get_duration:
+            return self.duration()
 
     def duration(self):
         return self._duration()
diff --git a/test/test_helpers.py b/test/test_helpers.py
index cf0bc6b4..742082e5 100644
--- a/test/test_helpers.py
+++ b/test/test_helpers.py
@@ -127,14 +127,21 @@ class TestTimeTracking:
     def test_stop(self):
         t = TimeTracking()
         assert t.end is None
-        duration = t.stop()
+        duration = t.stop(get_duration=True)
         assert duration == t._duration()
+        with pytest.raises(AssertionError) as e:
+            t.stop()
+        assert "Time was already stopped" in e.value.args[0]
+        t.run()
+        assert t.end is None
+        assert t.stop() is None
+        assert t.end is not None
 
     def test_duration(self):
         t = TimeTracking()
         duration = t
         assert duration is not None
-        duration = t.stop()
+        duration = t.stop(get_duration=True)
         assert duration == t.duration()
 
 
-- 
GitLab