Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 23 additions & 12 deletions simpeg/directives/_save_geoh5.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,8 @@ def get_values(self, values: list[np.ndarray] | None):

class SaveSensitivityGeoH5(SaveArrayGeoH5):
"""
Save the model at the current iteration to a geoh5 file.
Save the approximate sensitivities (JtJdiag) at the current
iteration to a geoh5 file.
"""

_attribute_type = "sensitivities"
Expand All @@ -337,7 +338,7 @@ def get_values(self, values: list[np.ndarray] | None):

class SaveDataGeoH5(SaveArrayGeoH5):
"""
Save the model at the current iteration to a geoh5 file.
Save the predicted data at the current iteration to a geoh5 file.
"""

_attribute_type = "predicted"
Expand Down Expand Up @@ -384,22 +385,28 @@ def joint_index(self, value: list[int] | None):


class SaveLogFilesGeoH5(BaseSaveGeoH5):
"""
Save iteration metrics to log files and attach them to the geoh5 file as bytes.

:param h5_object: The geoh5 object to which the log files will be attached.
:param base_name: The base name of the log files.
"""

def __init__(
self,
h5_object,
base_name,
**kwargs,
):
self.base_name = base_name
super().__init__(h5_object, **kwargs)
Comment on lines 395 to 402
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SaveLogFilesGeoH5 is exported as part of simpeg.directives, but base_name is now a required positional arg. This is a breaking API change for downstream code that instantiates the directive without it. Consider providing a default (e.g., "SimPEG") and/or making it a keyword-only optional parameter to preserve backwards compatibility.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Na, an update to simpeg comes with it


def write(self, iteration: int, **_):
dirpath = Path(self._workspace.h5file).parent
filepath = dirpath / "SimPEG.out"
filepath = dirpath / f"{self.base_name}.out"

if iteration == 0:
with open(filepath, "w", encoding="utf-8") as f:
f.write("iteration beta phi_d phi_m time\n")
log = []
with open(dirpath / "SimPEG.log", "r", encoding="utf-8") as file:
with open(dirpath / f"{self.base_name}.log", "r", encoding="utf-8") as file:
iteration = 0
for line in file:
val = re.findall(r"[+-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+-]?\d+)", line)
Expand All @@ -408,6 +415,10 @@ def write(self, iteration: int, **_):
iteration += 1

if len(log) > 0:
if not filepath.exists():
with open(filepath, "w", encoding="utf-8") as f:
f.write("iteration beta phi_d phi_m time\n")

with open(filepath, "a", encoding="utf-8") as file:
date_time = datetime.now().strftime("%b-%d-%Y:%H:%M:%S")

Expand All @@ -427,19 +438,19 @@ def save_log(self):
h5_object = w_s.get_entity(self.h5_object)[0]

for file in [
"SimPEG.out",
"SimPEG.log",
"ChiFactors.log",
".out",
".log",
".chi",
Comment on lines 439 to +443
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

save_log() now looks for a chi-factors file at f"{base_name}.chi", but ScaleMisfitMultipliers writes ChiFactors.log by default (see simpeg/directives/_directives.py:2704). As written, chi-factor logs likely won’t be found/saved. Consider keeping ChiFactors.log, or making the chi-factor filename configurable and aligning both producers/consumers.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also updated

]:
filepath = dirpath / file
filepath = dirpath / f"{self.base_name}{file}"

if not filepath.is_file():
continue

with open(filepath, "rb") as f:
raw_file = f.read()

file_entity = h5_object.get_entity(file)[0]
file_entity = h5_object.get_entity(f"{self.base_name}{file}")[0]
if file_entity is None:
Comment on lines 444 to 454
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

file_entity = h5_object.get_entity(file)[0] is now using strings like ".out"/".log" as the lookup key, but add_file(filepath) will typically create an entity named after the actual file (e.g., f"{base_name}.out"). This mismatch can prevent updates to existing entities and may repeatedly add new file entities. Use filepath.name (or another consistent identifier) for both get_entity(...) and add_file(...) so the same entity is updated each time.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On purpose

file_entity = h5_object.add_file(filepath)

Expand Down
Loading