From cc49a86d9da4067b94763cddafaa96a74935e207 Mon Sep 17 00:00:00 2001 From: Kauser Zulfiqar Date: Sun, 6 Oct 2024 15:24:49 +0200 Subject: [PATCH 01/11] update_info_json method is added to update and add the additional information in the info.json file --- micromagneticmodel/driver.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/micromagneticmodel/driver.py b/micromagneticmodel/driver.py index 25250d0..c479ec7 100644 --- a/micromagneticmodel/driver.py +++ b/micromagneticmodel/driver.py @@ -1,6 +1,7 @@ import abc import datetime import json +import os import pathlib import subprocess as sp import sys @@ -126,6 +127,7 @@ def drive( """ # This method is implemented in the derived driver class. It raises # exception if any of the arguments are not valid. + self.start_time = datetime.datetime.now() self.drive_kwargs_setup(kwargs) self._check_system(system) workingdir = self._setup_working_directory( @@ -140,7 +142,9 @@ def drive( ) self._call(system=system, runner=runner, verbose=verbose, **kwargs) self._read_data(system) - + self.end_time = datetime.datetime.now() + info_file_path = os.path.join(workingdir, "info.json") + self.update_info_json(info_file_path) system.drive_number += 1 def schedule( @@ -325,3 +329,14 @@ def _setup_working_directory(system, dirname, mode, append=True): workingdir = system_dir / f"{mode}-{next_number}" workingdir.mkdir(parents=True) return workingdir + + def update_info_json(self, info_file_path): + os.path.exists(info_file_path) + with open(info_file_path, encoding="utf-8") as jsonfile: + info = json.load(jsonfile) + + info["end_time"] = self.end_time.strftime("%H:%M:%S") + info["elapsed_time"] = str(self.end_time - self.start_time) + info["success"] = True + with open(info_file_path, "w", encoding="utf-8") as jsonfile: + json.dump(info, jsonfile) From d0eb24fdc8a280c1535c325e9210699b7ee668ee Mon Sep 17 00:00:00 2001 From: Kauser Zulfiqar Date: Fri, 11 Oct 2024 16:46:19 +0200 Subject: [PATCH 02/11] removed _write_info_json --- micromagneticmodel/tests/test_driver.py | 1 - 1 file changed, 1 deletion(-) diff --git a/micromagneticmodel/tests/test_driver.py b/micromagneticmodel/tests/test_driver.py index e1c6a92..c800ec0 100644 --- a/micromagneticmodel/tests/test_driver.py +++ b/micromagneticmodel/tests/test_driver.py @@ -37,7 +37,6 @@ def _check_system(self, system): def _write_input_files(self, system, **kwargs): with open(f"{system.name}.input", "w", encoding="utf-8") as f: f.write(str(-1)) # factor -1 used to invert magnetisation direction in call - self._write_info_json(system, **kwargs) def _call(self, system, runner, **kwargs): with open(f"{system.name}.input", encoding="utf-8") as f: From d02f8658f40405886855c8cd4ded6b822bac00f1 Mon Sep 17 00:00:00 2001 From: Kauser Zulfiqar Date: Fri, 11 Oct 2024 17:13:02 +0200 Subject: [PATCH 03/11] comments are resolved --- micromagneticmodel/driver.py | 37 +++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/micromagneticmodel/driver.py b/micromagneticmodel/driver.py index c479ec7..a85f7bd 100644 --- a/micromagneticmodel/driver.py +++ b/micromagneticmodel/driver.py @@ -1,7 +1,6 @@ import abc import datetime import json -import os import pathlib import subprocess as sp import sys @@ -127,7 +126,7 @@ def drive( """ # This method is implemented in the derived driver class. It raises # exception if any of the arguments are not valid. - self.start_time = datetime.datetime.now() + drive_kwargs = kwargs.copy() self.drive_kwargs_setup(kwargs) self._check_system(system) workingdir = self._setup_working_directory( @@ -140,11 +139,12 @@ def drive( ovf_format=ovf_format, **kwargs, ) + self._start_time = datetime.datetime.now() + self._write_info_json(system, **drive_kwargs) self._call(system=system, runner=runner, verbose=verbose, **kwargs) self._read_data(system) - self.end_time = datetime.datetime.now() - info_file_path = os.path.join(workingdir, "info.json") - self.update_info_json(info_file_path) + self._end_time = datetime.datetime.now() + self._update_info_json() system.drive_number += 1 def schedule( @@ -301,10 +301,11 @@ def _write_info_json(self, system, **kwargs): info["drive_number"] = system.drive_number info["date"] = datetime.datetime.now().strftime("%Y-%m-%d") info["time"] = datetime.datetime.now().strftime("%H:%M:%S") - info["driver"] = self.__class__.__name__ # "adapter" is the ubermag package (e.g. oommfc) that communicates with the # calculator (e.g. OOMMF) info["adapter"] = self.__module__.split(".")[0] + info["driver"] = self.__class__.__name__ + info["start_time"] = self._start_time.isoformat(timespec="seconds") for k, v in kwargs.items(): info[k] = v with open("info.json", "w", encoding="utf-8") as jsonfile: @@ -330,13 +331,23 @@ def _setup_working_directory(system, dirname, mode, append=True): workingdir.mkdir(parents=True) return workingdir - def update_info_json(self, info_file_path): - os.path.exists(info_file_path) - with open(info_file_path, encoding="utf-8") as jsonfile: + @staticmethod + def _conversion_to_hms(time_dfference): + total_seconds = int(time_dfference.total_seconds()) + hours, remainder = divmod(total_seconds, 3600) + minutes, seconds = divmod(remainder, 60) + if time_dfference.total_seconds() < 1: + microseconds = time_dfference.microseconds + return f"{hours:02}:{minutes:02}:{seconds:02}.{microseconds:06}" + return f"{hours:02}:{minutes:02}:{seconds:02}" + + def _update_info_json(self): + with open("info.json", encoding="utf-8") as jsonfile: info = json.load(jsonfile) - - info["end_time"] = self.end_time.strftime("%H:%M:%S") - info["elapsed_time"] = str(self.end_time - self.start_time) + info["end_time"] = self._end_time.isoformat(timespec="seconds") + info["elapsed_time"] = self._conversion_to_hms( + self._end_time - self._start_time + ) info["success"] = True - with open(info_file_path, "w", encoding="utf-8") as jsonfile: + with open("info.json", "w", encoding="utf-8") as jsonfile: json.dump(info, jsonfile) From f44c6dfae96d61f0558700810a90ecd083eb0be6 Mon Sep 17 00:00:00 2001 From: Kauser Zulfiqar Date: Mon, 28 Oct 2024 10:47:52 +0100 Subject: [PATCH 04/11] resolved all comments except info --- micromagneticmodel/driver.py | 46 ++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/micromagneticmodel/driver.py b/micromagneticmodel/driver.py index a85f7bd..e536b77 100644 --- a/micromagneticmodel/driver.py +++ b/micromagneticmodel/driver.py @@ -1,6 +1,7 @@ import abc import datetime import json +import math import pathlib import subprocess as sp import sys @@ -124,14 +125,15 @@ def drive( If system directory already exists and append=False. """ + drive_kwargs = kwargs.copy() # This method is implemented in the derived driver class. It raises # exception if any of the arguments are not valid. - drive_kwargs = kwargs.copy() self.drive_kwargs_setup(kwargs) self._check_system(system) workingdir = self._setup_working_directory( system=system, dirname=dirname, mode="drive", append=append ) + start_time = datetime.datetime.now() with uu.changedir(workingdir): self._write_input_files( @@ -139,12 +141,19 @@ def drive( ovf_format=ovf_format, **kwargs, ) - self._start_time = datetime.datetime.now() - self._write_info_json(system, **drive_kwargs) - self._call(system=system, runner=runner, verbose=verbose, **kwargs) + + self._write_info_json(system, start_time, **drive_kwargs) + try: + self._call(system=system, runner=runner, verbose=verbose, **kwargs) + except Exception: + success = False + raise + else: + success = True + finally: + end_time = datetime.datetime.now() + self._update_info_json(start_time, end_time, success) self._read_data(system) - self._end_time = datetime.datetime.now() - self._update_info_json() system.drive_number += 1 def schedule( @@ -296,16 +305,16 @@ def _write_schedule_script(self, system, header, script_name, runner): f.write("\n") f.write("\n".join(run_commands)) - def _write_info_json(self, system, **kwargs): + def _write_info_json(self, system, start_time, **kwargs): info = {} info["drive_number"] = system.drive_number - info["date"] = datetime.datetime.now().strftime("%Y-%m-%d") - info["time"] = datetime.datetime.now().strftime("%H:%M:%S") + info["date"] = start_time.strftime("%Y-%m-%d") + info["time"] = start_time.strftime("%H:%M:%S") + info["start_time"] = start_time.isoformat(timespec="seconds") # "adapter" is the ubermag package (e.g. oommfc) that communicates with the # calculator (e.g. OOMMF) info["adapter"] = self.__module__.split(".")[0] info["driver"] = self.__class__.__name__ - info["start_time"] = self._start_time.isoformat(timespec="seconds") for k, v in kwargs.items(): info[k] = v with open("info.json", "w", encoding="utf-8") as jsonfile: @@ -332,22 +341,17 @@ def _setup_working_directory(system, dirname, mode, append=True): return workingdir @staticmethod - def _conversion_to_hms(time_dfference): - total_seconds = int(time_dfference.total_seconds()) + def _conversion_to_hms(time_difference): + total_seconds = math.ceil(time_difference.total_seconds()) hours, remainder = divmod(total_seconds, 3600) minutes, seconds = divmod(remainder, 60) - if time_dfference.total_seconds() < 1: - microseconds = time_dfference.microseconds - return f"{hours:02}:{minutes:02}:{seconds:02}.{microseconds:06}" return f"{hours:02}:{minutes:02}:{seconds:02}" - def _update_info_json(self): + def _update_info_json(self, start_time, end_time, success): with open("info.json", encoding="utf-8") as jsonfile: info = json.load(jsonfile) - info["end_time"] = self._end_time.isoformat(timespec="seconds") - info["elapsed_time"] = self._conversion_to_hms( - self._end_time - self._start_time - ) - info["success"] = True + info["end_time"] = end_time.isoformat(timespec="seconds") + info["elapsed_time"] = self._conversion_to_hms(end_time - start_time) + info["success"] = success with open("info.json", "w", encoding="utf-8") as jsonfile: json.dump(info, jsonfile) From 16556dcc742b2a0399ffa972de1a2220d329b67e Mon Sep 17 00:00:00 2001 From: Kauser Zulfiqar Date: Tue, 5 Nov 2024 15:06:42 +0100 Subject: [PATCH 05/11] info json for schedule --- micromagneticmodel/driver.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/micromagneticmodel/driver.py b/micromagneticmodel/driver.py index e536b77..cab33b4 100644 --- a/micromagneticmodel/driver.py +++ b/micromagneticmodel/driver.py @@ -249,6 +249,7 @@ def schedule( """ # This method is implemented in the derived driver class. It raises # exception if any of the arguments are not valid. + drive_kwargs = kwargs.copy() self.schedule_kwargs_setup(kwargs) self._check_system(system) workingdir = self._setup_working_directory( @@ -260,6 +261,8 @@ def schedule( if pathlib.Path(header).exists(): header = pathlib.Path(header).absolute() + start_time = datetime.datetime.now() + with uu.changedir(workingdir): self._write_input_files( system=system, @@ -269,6 +272,7 @@ def schedule( self._write_schedule_script( system=system, header=header, script_name=script_name, runner=runner ) + self._write_info_json(system, start_time, **drive_kwargs) stdout = stderr = sp.PIPE if sys.platform == "win32": From 3b7e4304cb39f334eda872d100cead1eeb82ccde Mon Sep 17 00:00:00 2001 From: Martin Lang <67915889+lang-m@users.noreply.github.com> Date: Wed, 6 Nov 2024 12:49:33 +0100 Subject: [PATCH 06/11] schedule: rename internal variable --- micromagneticmodel/driver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/micromagneticmodel/driver.py b/micromagneticmodel/driver.py index cab33b4..73a7eb4 100644 --- a/micromagneticmodel/driver.py +++ b/micromagneticmodel/driver.py @@ -247,9 +247,9 @@ def schedule( If system directory already exists and append=False. """ + schedule_kwargs = kwargs.copy() # This method is implemented in the derived driver class. It raises # exception if any of the arguments are not valid. - drive_kwargs = kwargs.copy() self.schedule_kwargs_setup(kwargs) self._check_system(system) workingdir = self._setup_working_directory( @@ -272,7 +272,7 @@ def schedule( self._write_schedule_script( system=system, header=header, script_name=script_name, runner=runner ) - self._write_info_json(system, start_time, **drive_kwargs) + self._write_info_json(system, start_time, **schedule_kwargs) stdout = stderr = sp.PIPE if sys.platform == "win32": From 33cc5e84072c940af3ae002d745de0676ec170c9 Mon Sep 17 00:00:00 2001 From: Kauser Zulfiqar Date: Mon, 18 Nov 2024 13:55:50 +0100 Subject: [PATCH 07/11] added ubermag_version in info list --- micromagneticmodel/driver.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/micromagneticmodel/driver.py b/micromagneticmodel/driver.py index cab33b4..9f931ee 100644 --- a/micromagneticmodel/driver.py +++ b/micromagneticmodel/driver.py @@ -1,5 +1,6 @@ import abc import datetime +import importlib.metadata import json import math import pathlib @@ -357,5 +358,6 @@ def _update_info_json(self, start_time, end_time, success): info["end_time"] = end_time.isoformat(timespec="seconds") info["elapsed_time"] = self._conversion_to_hms(end_time - start_time) info["success"] = success + info["ubermag_version"] = importlib.metadata.version("ubermag") with open("info.json", "w", encoding="utf-8") as jsonfile: json.dump(info, jsonfile) From 440c63af64ca84258593dacdc4af475bc0b12052 Mon Sep 17 00:00:00 2001 From: Kauser Zulfiqar Date: Tue, 19 Nov 2024 09:27:54 +0100 Subject: [PATCH 08/11] added adapter version and removed ubermag version --- micromagneticmodel/driver.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/micromagneticmodel/driver.py b/micromagneticmodel/driver.py index 047c5cb..324e56e 100644 --- a/micromagneticmodel/driver.py +++ b/micromagneticmodel/driver.py @@ -319,6 +319,9 @@ def _write_info_json(self, system, start_time, **kwargs): # "adapter" is the ubermag package (e.g. oommfc) that communicates with the # calculator (e.g. OOMMF) info["adapter"] = self.__module__.split(".")[0] + info["adapter_version"] = importlib.metadata.version( + self.__module__.split(".")[0] + ) info["driver"] = self.__class__.__name__ for k, v in kwargs.items(): info[k] = v @@ -358,6 +361,5 @@ def _update_info_json(self, start_time, end_time, success): info["end_time"] = end_time.isoformat(timespec="seconds") info["elapsed_time"] = self._conversion_to_hms(end_time - start_time) info["success"] = success - info["ubermag_version"] = importlib.metadata.version("ubermag") with open("info.json", "w", encoding="utf-8") as jsonfile: json.dump(info, jsonfile) From a1db50e534418ab4f1f1bb275c32035a27646b48 Mon Sep 17 00:00:00 2001 From: Kauser Zulfiqar Date: Tue, 19 Nov 2024 09:29:07 +0100 Subject: [PATCH 09/11] added test for the updated file --- micromagneticmodel/tests/test_driver.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/micromagneticmodel/tests/test_driver.py b/micromagneticmodel/tests/test_driver.py index c800ec0..807dc89 100644 --- a/micromagneticmodel/tests/test_driver.py +++ b/micromagneticmodel/tests/test_driver.py @@ -1,4 +1,3 @@ -import datetime import json import discretisedfield as df @@ -78,10 +77,24 @@ def test_external_driver(tmp_path): assert info["driver"] == "MyExternalDriver" assert info["drive_number"] == 0 - info_time = datetime.datetime.fromisoformat(f"{info['date']}T{info['time']}") - now = datetime.datetime.now() - # assumption: this test runs in under one minute - assert (now - info_time).total_seconds() < 60 + assert "start_time" in info + assert "end_time" in info + assert "elapsed_time" in info + assert "success" in info + assert info["success"] is True + + def _parse_time_str_to_seconds(time_str): + h, m, s = map(int, time_str.split(":")) + return h * 3600 + m * 60 + s + + elapsed_time = info["elapsed_time"] + + if isinstance(elapsed_time, str): # HH:MM:SS format + elapsed_seconds = _parse_time_str_to_seconds(elapsed_time) + # assumption: this test runs in under one minute + assert elapsed_seconds < 60 + else: + raise TypeError("Unexpected format for elapsed_time") with pytest.raises(FileExistsError): driver.drive(system, dirname=str(tmp_path), append=False) From b93eca7e6b6e05a069c48c63aa789c5e4b6afaf0 Mon Sep 17 00:00:00 2001 From: Kauser Zulfiqar Date: Fri, 22 Nov 2024 11:14:24 +0100 Subject: [PATCH 10/11] removed str condition in the test --- micromagneticmodel/tests/test_driver.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/micromagneticmodel/tests/test_driver.py b/micromagneticmodel/tests/test_driver.py index 807dc89..1f55d67 100644 --- a/micromagneticmodel/tests/test_driver.py +++ b/micromagneticmodel/tests/test_driver.py @@ -88,13 +88,9 @@ def _parse_time_str_to_seconds(time_str): return h * 3600 + m * 60 + s elapsed_time = info["elapsed_time"] - - if isinstance(elapsed_time, str): # HH:MM:SS format - elapsed_seconds = _parse_time_str_to_seconds(elapsed_time) - # assumption: this test runs in under one minute - assert elapsed_seconds < 60 - else: - raise TypeError("Unexpected format for elapsed_time") + elapsed_seconds = _parse_time_str_to_seconds(elapsed_time) + # assumption: this test runs in under one minute + assert elapsed_seconds < 60 with pytest.raises(FileExistsError): driver.drive(system, dirname=str(tmp_path), append=False) From 3cd9c6b030f5853f72186c69adb0b0686d1060ac Mon Sep 17 00:00:00 2001 From: Martin Lang <67915889+lang-m@users.noreply.github.com> Date: Sun, 2 Feb 2025 13:30:23 +0100 Subject: [PATCH 11/11] Apply suggestions from code review --- micromagneticmodel/tests/test_driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/micromagneticmodel/tests/test_driver.py b/micromagneticmodel/tests/test_driver.py index 1f55d67..f4e7e0a 100644 --- a/micromagneticmodel/tests/test_driver.py +++ b/micromagneticmodel/tests/test_driver.py @@ -81,7 +81,7 @@ def test_external_driver(tmp_path): assert "end_time" in info assert "elapsed_time" in info assert "success" in info - assert info["success"] is True + assert info["success"] def _parse_time_str_to_seconds(time_str): h, m, s = map(int, time_str.split(":"))