Source code for sarkas.utilities.timing

"""
Module for handling the timing in a MD run.
"""
import datetime
import sys
import time
from dataclasses import dataclass, field
from os.path import exists as os_path_exists
from typing import Optional

from .exceptions import TimerError


[docs]@dataclass class SarkasTimer: """ Timer class modified from https://realpython.com/python-timer/ """ _start_time: Optional[float] = field(default=None, init=False, repr=False)
[docs] def start(self): """Start a new timer""" if self._start_time is not None: raise TimerError("Timer is running. Use .stop() to stop it") self._start_time = time.perf_counter_ns()
[docs] def stop(self) -> int: """ Stop the timer, and report the elapsed time. Returns ------- elapsed_time: int Elapsed time in nanoseconds. """ if self._start_time is None: raise TimerError("Timer is not running. Use .start() to start it") # Calculate elapsed time elapsed_time = time.perf_counter_ns() - self._start_time self._start_time = None return elapsed_time
[docs] @staticmethod def current() -> int: """Grab the current time in nanoseconds.""" return time.perf_counter_ns()
[docs] @staticmethod def time_division(tme: int) -> list: """ Divide time into hours, min, sec, msec, microsec (usec), and nanosec. Parameters ---------- tme : int Time in nanoseconds. Returns ------- : list [hours, min, sec, msec, microsec (usec), nanosec] """ t_hrs, rem = divmod(tme, 3.6e12) t_min, rem_m = divmod(rem, 6e10) t_sec, rem_s = divmod(rem_m, 1e9) t_msec, rem_ms = divmod(rem_s, 1e6) t_usec, rem_us = divmod(rem_ms, 1e3) t_nsec, _ = divmod(rem_us, 1) return [t_hrs, t_min, t_sec, t_msec, t_usec, t_nsec]
[docs]def datetime_stamp(log_file): """Add a Date and Time stamp to log file. If the file exists it appends three paragraph so that it is easier to see the new line. Parameters ---------- log_file : str Path to file on which date time stamp should be appended to. """ if os_path_exists(log_file): with open(log_file, "a+") as f_log: # Add some space to better distinguish the new beginning print(f"\n\n\n", file=f_log) with open(log_file, "a+") as f_log: ct = datetime.datetime.now() print(f"{'':~^80}", file=f_log) print(f"Date: {ct.year} - {ct.month} - {ct.day}", file=f_log) print(f"Time: {ct.hour}:{ct.minute}:{ct.second}", file=f_log) print(f"{'':~^80}\n", file=f_log)
[docs]def time_stamp(log_file: str, message: str, timing: tuple, print_to_screen: bool = False): """ Print out to screen elapsed times. If verbose output, print to file first and then to screen. Parameters ---------- log_file : str Path to file on which date time stamp should be appended to. message : str Message to print. timing : tuple Time in hrs, min, sec, msec, usec, nsec. print_to_screen : bool Flag for printing the message to screen. Default is False. """ screen = sys.stdout f_log = open(log_file, "a+") repeat = 2 if print_to_screen else 1 t_hrs, t_min, t_sec, t_msec, t_usec, t_nsec = timing # redirect printing to file sys.stdout = f_log while repeat > 0: if t_hrs == 0 and t_min == 0 and t_sec <= 2: print(f"\n{message} Time: {int(t_sec)} sec {int(t_msec)} msec {int(t_usec)} usec {int(t_nsec)} nsec") else: print(f"\n{message} Time: {int(t_hrs)} hrs {int(t_min)} min {int(t_sec)} sec") repeat -= 1 sys.stdout = screen f_log.close()