Source code for atomate2.turbomole.utils
# Part of atomate2-turbomole package.
"""Module containing utilities for the atomate2-turbomole package."""
from __future__ import annotations
import re
from datetime import datetime
from monty.json import MSONable
from turbomoleio.input.utils import get_define_template
float_number_re = r"[+-]?[0-9]*[.]?[0-9]+"
timing_re = r"(\d+h|)(\d+m)(" + float_number_re + r"s)"
[docs]
class JobexTimings(MSONable):
"""Object containing timing information about a jobex run.
Note: this will be moved and adapted in turbomoleio.
"""
def __init__(self, steps_timings):
"""Construct JobexTimings.
Args:
steps_timings (list): List of the timings for each step.
"""
self.steps_timings = steps_timings
[docs]
@classmethod
def from_file(cls, filepath="time.stat"):
"""Create JobexTimings from file.
Args:
filepath: Path to the "time.stat" file containing timing information.
Returns
-------
JobexTimings instance with the timing information of the jobex calculation.
"""
with open(filepath) as f:
string = f.read().strip()
pattern = (
r"([\s\S]*?\s+)" # lazy matching
r"real\s+"
+ timing_re
+ r"\s+user\s+"
+ timing_re
+ r"\s+sys\s+"
+ timing_re
)
match = re.findall(pattern, string)
steps_timings = []
for step in match:
real_t = float(step[3][:-1]) + 60.0 * float(step[2][:-1])
if step[1]:
real_t += 3600.0 * float(step[1][:-1])
user_t = float(step[6][:-1]) + 60.0 * float(step[5][:-1])
if step[4]:
user_t += 3600.0 * float(step[4][:-1])
sys_t = float(step[9][:-1]) + 60.0 * float(step[8][:-1])
if step[7]:
sys_t += 3600.0 * float(step[7][:-1])
sp = [line.strip() for line in step[0].strip().splitlines()]
if len(sp) == 1:
details = None
elif len(sp) == 2:
details = sp[1]
else:
raise RuntimeError(
"More than two time.stat lines for a given jobex step"
)
step_type = sp[0]
steps_timings.append(
{
"step": step_type,
"details": details,
"real": real_t,
"user": user_t,
"sys": sys_t,
}
)
return cls(steps_timings=steps_timings)
[docs]
def total_time(self, time="real", step=None):
"""Get the total time.
Args:
time: Which type of time to use.
step: Which type of step to use.
Returns
-------
float: Time used in seconds.
"""
if step is not None:
return sum([s[time] for s in self.steps_timings if s["step"] == step])
return sum([s[time] for s in self.steps_timings])
[docs]
def get_define_parameters(define_template=None, define_parameters=None):
"""Get the define parameters based on a template and additional define parameters.
Args:
define_template: Name of template to use as basis for define parameters.
define_parameters: Parameters for turbomoleio's DefineRunner.
"""
if define_template is None and define_parameters is None:
raise RuntimeError(
'Should provide at least one of "define_template" or "define_parameters"'
)
dp = get_define_template(define_template) if define_template else {}
if define_parameters:
dp.update(define_parameters)
return dp
[docs]
def datetime_str() -> str:
"""
Get a string representation of the current time.
Returns
-------
str
The current time.
"""
return str(datetime.utcnow())