From 81f5916bfbb40d0ad762ce73702e0396ead4e0c5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2026 17:59:32 +0000 Subject: [PATCH 1/2] chore(pre-commit): pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.15.13 → v0.15.16](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.13...v0.15.16) - [github.com/oxc-project/mirrors-oxfmt: v0.50.0 → v0.45.0](https://github.com/oxc-project/mirrors-oxfmt/compare/v0.50.0...v0.45.0) - [github.com/oxc-project/mirrors-oxlint: v1.65.0 → v1.60.0](https://github.com/oxc-project/mirrors-oxlint/compare/v1.65.0...v1.60.0) - [github.com/rvben/rumdl-pre-commit: v0.1.93 → v0.2.9](https://github.com/rvben/rumdl-pre-commit/compare/v0.1.93...v0.2.9) --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f4737e0cc..2c0e3b3a2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,18 +18,18 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.13 + rev: v0.15.16 hooks: - id: ruff-check args: - --fix - id: ruff-format - repo: https://github.com/oxc-project/mirrors-oxfmt - rev: v0.50.0 + rev: v0.45.0 hooks: - id: oxfmt - repo: https://github.com/oxc-project/mirrors-oxlint - rev: v1.65.0 + rev: v1.60.0 hooks: - id: oxlint - repo: https://github.com/pre-commit/pre-commit-hooks @@ -52,7 +52,7 @@ repos: hooks: - id: actionlint - repo: https://github.com/rvben/rumdl-pre-commit - rev: v0.1.93 + rev: v0.2.9 hooks: - id: rumdl-fmt - repo: https://github.com/shellcheck-py/shellcheck-py From 2163e86f39d6e00dd3afe0d702d2911abb28e2fe Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2026 17:59:48 +0000 Subject: [PATCH 2/2] chore(pre-commit): auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ...ation-stable-neo-hookean-easy-metrics.json | 2 +- ...46-activation-stable-neo-hookean-easy.json | 2 +- ...ation-stable-neo-hookean-zero-metrics.json | 2 +- ...46-activation-stable-neo-hookean-zero.json | 2 +- ...uscle46-activation-stable-neo-hookean.json | 2 +- .../data/20-inverse-face-3152k-summary.json | 2 +- ...smas1-noclamp-super-loose-reg-summary.json | 2 +- .../data/20-inverse-face-summary.json | 2 +- .../30-transfer-activation-3152k-summary.json | 2 +- ...ansfer-activation-3152k-smas1-summary.json | 2 +- ...nsfer-activation-515k-smas100-summary.json | 2 +- ...ransfer-activation-515k-smas1-summary.json | 2 +- ...sfer-activation-3152k-smas100-summary.json | 2 +- ...ansfer-activation-3152k-smas1-summary.json | 2 +- .../src/10-prepare-inverse-face.py | 12 ++++++-- .../20-forward-face-3152k-a087-summary.json | 2 +- .../data/20-forward-face-3152k-summary.json | 2 +- .../20-forward-face-515k-nosmas-summary.json | 2 +- .../30-inverse-face-515k-nosmas-summary.json | 2 +- .../src/10-prepare-forward-face.py | 8 +++-- .../05/27/forward-face/src/20-forward-face.py | 12 ++++++-- .../forward-face/src/30-inverse-face-515k.py | 30 +++++++++++++------ 22 files changed, 63 insertions(+), 35 deletions(-) diff --git a/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-easy-metrics.json b/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-easy-metrics.json index 18b901c7e..39971bce3 100644 --- a/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-easy-metrics.json +++ b/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-easy-metrics.json @@ -26,4 +26,4 @@ "forward_best_objective": 1481.1424852869957, "finite_outputs": true } -] \ No newline at end of file +] diff --git a/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-easy.json b/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-easy.json index c061b297c..94d53e89e 100644 --- a/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-easy.json +++ b/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-easy.json @@ -38,4 +38,4 @@ "adjoint-relative-residual": "/home/liblaf/github/liblaf/apple/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-easy-metrics-adjoint-relative-residual.png", "inverse-grad-absolute": "/home/liblaf/github/liblaf/apple/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-easy-metrics-inverse-grad-absolute.png" } -} \ No newline at end of file +} diff --git a/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-zero-metrics.json b/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-zero-metrics.json index e3eae723a..ed4812d40 100644 --- a/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-zero-metrics.json +++ b/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-zero-metrics.json @@ -404,4 +404,4 @@ "forward_best_objective": 1485.5675728610533, "finite_outputs": true } -] \ No newline at end of file +] diff --git a/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-zero.json b/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-zero.json index dc9f6ea0e..2f7ccd935 100644 --- a/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-zero.json +++ b/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-zero.json @@ -43,4 +43,4 @@ "adjoint-relative-residual": "/home/liblaf/github/liblaf/apple/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-zero-metrics-adjoint-relative-residual.png", "inverse-grad-absolute": "/home/liblaf/github/liblaf/apple/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean-zero-metrics-inverse-grad-absolute.png" } -} \ No newline at end of file +} diff --git a/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean.json b/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean.json index d95032cbc..541e835f1 100644 --- a/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean.json +++ b/exp/2026/01/28/smas/data/31-inverse-smas46-muscle46-activation-stable-neo-hookean.json @@ -88,4 +88,4 @@ } } ] -} \ No newline at end of file +} diff --git a/exp/2026/05/20/inverse-face/data/20-inverse-face-3152k-summary.json b/exp/2026/05/20/inverse-face/data/20-inverse-face-3152k-summary.json index c72671419..48ca2367c 100644 --- a/exp/2026/05/20/inverse-face/data/20-inverse-face-3152k-summary.json +++ b/exp/2026/05/20/inverse-face/data/20-inverse-face-3152k-summary.json @@ -136,4 +136,4 @@ "repeated/forward_failure": false, "repeated/adjoint_failure": false, "passed": true -} \ No newline at end of file +} diff --git a/exp/2026/05/20/inverse-face/data/20-inverse-face-fresh-nu049-smas1-noclamp-super-loose-reg-summary.json b/exp/2026/05/20/inverse-face/data/20-inverse-face-fresh-nu049-smas1-noclamp-super-loose-reg-summary.json index 7f2af9301..5e39a8d43 100644 --- a/exp/2026/05/20/inverse-face/data/20-inverse-face-fresh-nu049-smas1-noclamp-super-loose-reg-summary.json +++ b/exp/2026/05/20/inverse-face/data/20-inverse-face-fresh-nu049-smas1-noclamp-super-loose-reg-summary.json @@ -16721,4 +16721,4 @@ "repeated/forward_failure": false, "repeated/adjoint_failure": false, "passed": true -} \ No newline at end of file +} diff --git a/exp/2026/05/20/inverse-face/data/20-inverse-face-summary.json b/exp/2026/05/20/inverse-face/data/20-inverse-face-summary.json index 31070dead..ebdafb629 100644 --- a/exp/2026/05/20/inverse-face/data/20-inverse-face-summary.json +++ b/exp/2026/05/20/inverse-face/data/20-inverse-face-summary.json @@ -125,4 +125,4 @@ "repeated/forward_failure": false, "repeated/adjoint_failure": false, "passed": true -} \ No newline at end of file +} diff --git a/exp/2026/05/20/inverse-face/data/30-transfer-activation-3152k-summary.json b/exp/2026/05/20/inverse-face/data/30-transfer-activation-3152k-summary.json index 112c021e3..d07d13a71 100644 --- a/exp/2026/05/20/inverse-face/data/30-transfer-activation-3152k-summary.json +++ b/exp/2026/05/20/inverse-face/data/30-transfer-activation-3152k-summary.json @@ -57,4 +57,4 @@ "forward/line_search_steps": 0, "forward/stagnation_count": 0, "time/forward_s": 16.038381466001738 -} \ No newline at end of file +} diff --git a/exp/2026/05/20/inverse-face/data/31-transfer-activation-3152k-smas1-summary.json b/exp/2026/05/20/inverse-face/data/31-transfer-activation-3152k-smas1-summary.json index 88e5908c8..26b87edcf 100644 --- a/exp/2026/05/20/inverse-face/data/31-transfer-activation-3152k-smas1-summary.json +++ b/exp/2026/05/20/inverse-face/data/31-transfer-activation-3152k-smas1-summary.json @@ -57,4 +57,4 @@ "forward/line_search_steps": 0, "forward/stagnation_count": 0, "time/forward_s": 6.737611743999878 -} \ No newline at end of file +} diff --git a/exp/2026/05/20/inverse-face/data/40-transfer-activation-515k-smas100-summary.json b/exp/2026/05/20/inverse-face/data/40-transfer-activation-515k-smas100-summary.json index 8a94d6b97..ce007c5f4 100644 --- a/exp/2026/05/20/inverse-face/data/40-transfer-activation-515k-smas100-summary.json +++ b/exp/2026/05/20/inverse-face/data/40-transfer-activation-515k-smas100-summary.json @@ -57,4 +57,4 @@ "forward/line_search_steps": 0, "forward/stagnation_count": 0, "time/forward_s": 3.82475233200239 -} \ No newline at end of file +} diff --git a/exp/2026/05/20/inverse-face/data/41-transfer-activation-515k-smas1-summary.json b/exp/2026/05/20/inverse-face/data/41-transfer-activation-515k-smas1-summary.json index ca81a08ec..b24ce90cc 100644 --- a/exp/2026/05/20/inverse-face/data/41-transfer-activation-515k-smas1-summary.json +++ b/exp/2026/05/20/inverse-face/data/41-transfer-activation-515k-smas1-summary.json @@ -57,4 +57,4 @@ "forward/line_search_steps": 0, "forward/stagnation_count": 0, "time/forward_s": 3.6330396700068377 -} \ No newline at end of file +} diff --git a/exp/2026/05/20/inverse-face/data/42-transfer-activation-3152k-smas100-summary.json b/exp/2026/05/20/inverse-face/data/42-transfer-activation-3152k-smas100-summary.json index 5bc1f9207..a83e3f59c 100644 --- a/exp/2026/05/20/inverse-face/data/42-transfer-activation-3152k-smas100-summary.json +++ b/exp/2026/05/20/inverse-face/data/42-transfer-activation-3152k-smas100-summary.json @@ -57,4 +57,4 @@ "forward/line_search_steps": 0, "forward/stagnation_count": 0, "time/forward_s": 4.520490328024607 -} \ No newline at end of file +} diff --git a/exp/2026/05/20/inverse-face/data/43-transfer-activation-3152k-smas1-summary.json b/exp/2026/05/20/inverse-face/data/43-transfer-activation-3152k-smas1-summary.json index 40b9e0d5e..0da3a73a5 100644 --- a/exp/2026/05/20/inverse-face/data/43-transfer-activation-3152k-smas1-summary.json +++ b/exp/2026/05/20/inverse-face/data/43-transfer-activation-3152k-smas1-summary.json @@ -57,4 +57,4 @@ "forward/line_search_steps": 0, "forward/stagnation_count": 0, "time/forward_s": 6.646797652996611 -} \ No newline at end of file +} diff --git a/exp/2026/05/20/inverse-face/src/10-prepare-inverse-face.py b/exp/2026/05/20/inverse-face/src/10-prepare-inverse-face.py index 9ae98d0fb..e5b0e0917 100644 --- a/exp/2026/05/20/inverse-face/src/10-prepare-inverse-face.py +++ b/exp/2026/05/20/inverse-face/src/10-prepare-inverse-face.py @@ -123,7 +123,9 @@ def add_material_fields(mesh: pv.UnstructuredGrid, cfg: Config) -> None: zero_activation_fields(mesh) -def fixed_point_mask(mesh: pv.UnstructuredGrid, cfg: Config) -> tuple[np.ndarray, dict[str, int]]: +def fixed_point_mask( + mesh: pv.UnstructuredGrid, cfg: Config +) -> tuple[np.ndarray, dict[str, int]]: fixed = np.zeros(mesh.n_points, dtype=bool) counts: dict[str, int] = {} for name in cfg.fixed_point_masks: @@ -222,8 +224,12 @@ def metric_summary( "n_active_tets": int(np.asarray(mesh.cell_data["ActivationMask"]).sum()), "n_target_points": int(target_mask.sum()), "n_fixed_points": int(np.asarray(mesh.point_data["FixedBoundary"]).sum()), - "n_fixed_cranium_points": int(np.asarray(mesh.point_data["FixedCranium"]).sum()), - "n_fixed_mandible_points": int(np.asarray(mesh.point_data["FixedMandible"]).sum()), + "n_fixed_cranium_points": int( + np.asarray(mesh.point_data["FixedCranium"]).sum() + ), + "n_fixed_mandible_points": int( + np.asarray(mesh.point_data["FixedMandible"]).sum() + ), "muscle_fraction_volume": float(np.sum(muscle * volume)), "smas_fraction_volume": float(np.sum(smas * volume)), "target_displacement_mean": float(target_norm.mean()), diff --git a/exp/2026/05/27/forward-face/data/20-forward-face-3152k-a087-summary.json b/exp/2026/05/27/forward-face/data/20-forward-face-3152k-a087-summary.json index 70a9d80fb..4d107a992 100644 --- a/exp/2026/05/27/forward-face/data/20-forward-face-3152k-a087-summary.json +++ b/exp/2026/05/27/forward-face/data/20-forward-face-3152k-a087-summary.json @@ -56,4 +56,4 @@ "IsLipBottom/target_rms": 0.3993310920970844, "IsLipBottom/target_max": 1.0284059764202034, "IsLipBottom/rms_ratio_to_target": 0.30975080437456287 -} \ No newline at end of file +} diff --git a/exp/2026/05/27/forward-face/data/20-forward-face-3152k-summary.json b/exp/2026/05/27/forward-face/data/20-forward-face-3152k-summary.json index 15b3211b9..947ada679 100644 --- a/exp/2026/05/27/forward-face/data/20-forward-face-3152k-summary.json +++ b/exp/2026/05/27/forward-face/data/20-forward-face-3152k-summary.json @@ -56,4 +56,4 @@ "IsLipBottom/target_rms": 0.3993310920970844, "IsLipBottom/target_max": 1.0284059764202034, "IsLipBottom/rms_ratio_to_target": 0.3094006908630162 -} \ No newline at end of file +} diff --git a/exp/2026/05/27/forward-face/data/20-forward-face-515k-nosmas-summary.json b/exp/2026/05/27/forward-face/data/20-forward-face-515k-nosmas-summary.json index d74e2fae6..3b99316af 100644 --- a/exp/2026/05/27/forward-face/data/20-forward-face-515k-nosmas-summary.json +++ b/exp/2026/05/27/forward-face/data/20-forward-face-515k-nosmas-summary.json @@ -57,4 +57,4 @@ "IsLipBottom/target_rms": 0.42244197929946425, "IsLipBottom/target_max": 1.016519397545366, "IsLipBottom/rms_ratio_to_target": 0.12364134545496203 -} \ No newline at end of file +} diff --git a/exp/2026/05/27/forward-face/data/30-inverse-face-515k-nosmas-summary.json b/exp/2026/05/27/forward-face/data/30-inverse-face-515k-nosmas-summary.json index 5efd622ac..a450b5688 100644 --- a/exp/2026/05/27/forward-face/data/30-inverse-face-515k-nosmas-summary.json +++ b/exp/2026/05/27/forward-face/data/30-inverse-face-515k-nosmas-summary.json @@ -4974,4 +4974,4 @@ "activation_inv/error_rms": 0.2491769718442089, "activation_inv/error_max_norm": 0.6141888156955176, "passed": true -} \ No newline at end of file +} diff --git a/exp/2026/05/27/forward-face/src/10-prepare-forward-face.py b/exp/2026/05/27/forward-face/src/10-prepare-forward-face.py index 2c1d3004e..e988b5319 100644 --- a/exp/2026/05/27/forward-face/src/10-prepare-forward-face.py +++ b/exp/2026/05/27/forward-face/src/10-prepare-forward-face.py @@ -236,8 +236,12 @@ def metric_summary( "activation/n_tets": int(active.sum()), "target/n_points": int(target_mask.sum()), "fixed/n_points": int(fixed.sum()), - "fixed/n_cranium_points": int(np.asarray(mesh.point_data["FixedCranium"]).sum()), - "fixed/n_mandible_points": int(np.asarray(mesh.point_data["FixedMandible"]).sum()), + "fixed/n_cranium_points": int( + np.asarray(mesh.point_data["FixedCranium"]).sum() + ), + "fixed/n_mandible_points": int( + np.asarray(mesh.point_data["FixedMandible"]).sum() + ), "volume/muscle_fraction": float(np.sum(muscle * volume)), "volume/smas_fraction": float(np.sum(smas * volume)), "volume/smas_stiffness_fraction": float(np.sum(smas_stiffness * volume)), diff --git a/exp/2026/05/27/forward-face/src/20-forward-face.py b/exp/2026/05/27/forward-face/src/20-forward-face.py index f0939001d..15a5f2295 100644 --- a/exp/2026/05/27/forward-face/src/20-forward-face.py +++ b/exp/2026/05/27/forward-face/src/20-forward-face.py @@ -153,7 +153,9 @@ def set_material( mesh.cell_data[FRACTION.vtk] = np.asarray(fraction, dtype=np.float64) -def unpack_symmetric(values: tuple[float, float, float, float, float, float]) -> np.ndarray: +def unpack_symmetric( + values: tuple[float, float, float, float, float, float], +) -> np.ndarray: xx, yy, zz, xy, xz, yz = values return np.asarray( [[xx, xy, xz], [xy, yy, yz], [xz, yz, zz]], @@ -304,7 +306,9 @@ def summarize( elapsed_s: float, cfg: Config, ) -> dict[str, Any]: - target_displacement = np.asarray(target.point_data["Displacement"], dtype=np.float64) + target_displacement = np.asarray( + target.point_data["Displacement"], dtype=np.float64 + ) active = np.asarray(mesh.cell_data["ActivationMask"], dtype=bool) volume = np.asarray(mesh.cell_data["Volume"], dtype=np.float64) muscle = np.asarray(mesh.cell_data["MuscleFraction"], dtype=np.float64) @@ -356,7 +360,9 @@ def make_result_mesh( metrics: dict[str, float | int | bool | str], ) -> pv.UnstructuredGrid: result = mesh.copy(deep=True) - target_displacement = np.asarray(target.point_data["Displacement"], dtype=np.float64) + target_displacement = np.asarray( + target.point_data["Displacement"], dtype=np.float64 + ) error = displacement - target_displacement result.point_data["Displacement"] = displacement result.point_data["DisplacementNorm"] = np.linalg.norm(displacement, axis=1) diff --git a/exp/2026/05/27/forward-face/src/30-inverse-face-515k.py b/exp/2026/05/27/forward-face/src/30-inverse-face-515k.py index 929585296..188156d79 100644 --- a/exp/2026/05/27/forward-face/src/30-inverse-face-515k.py +++ b/exp/2026/05/27/forward-face/src/30-inverse-face-515k.py @@ -297,7 +297,9 @@ def local_deltas_from_activation_inv( local_activation_inv = eye + matrix_from_symmetric(local_activation_inv_delta) local_activation = np.linalg.inv(local_activation_inv) local_activation_delta = pack_symmetric_np(local_activation[None, ...] - eye)[0] - return local_activation_delta, np.asarray(local_activation_inv_delta, dtype=np.float64) + return local_activation_delta, np.asarray( + local_activation_inv_delta, dtype=np.float64 + ) def activation_inv_from_local_delta( @@ -553,7 +555,9 @@ def make_result_mesh( result = mesh.copy(deep=True) add_masks(result, target_ids, active_ids) - target_displacement = np.asarray(target.point_data["Displacement"], dtype=np.float64) + target_displacement = np.asarray( + target.point_data["Displacement"], dtype=np.float64 + ) error = displacement - target_displacement result.point_data["Displacement"] = displacement result.point_data["DisplacementNorm"] = np.linalg.norm(displacement, axis=1) @@ -698,7 +702,9 @@ def adjoint_solve(self, u_grad: torch.Tensor) -> Any: device=torch.get_default_device(), ) local_activation_inv_delta = torch.nn.Parameter( - torch.zeros(6, dtype=torch.get_default_dtype(), device=torch.get_default_device()) + torch.zeros( + 6, dtype=torch.get_default_dtype(), device=torch.get_default_device() + ) ) optimizer = torch.optim.Adam( [local_activation_inv_delta], @@ -936,7 +942,9 @@ def summarize( ) -> dict[str, Any]: from liblaf.apple.common import ACTIVATION_INV - target_displacement = np.asarray(target.point_data["Displacement"], dtype=np.float64) + target_displacement = np.asarray( + target.point_data["Displacement"], dtype=np.float64 + ) error = displacement - target_displacement target_error = error[target_ids] target_error_norm = np.linalg.norm(target_error, axis=1) @@ -1039,10 +1047,12 @@ def main(cfg: Config) -> None: _, local_activation_inv_delta = local_deltas_from_activation_inv( recovered_local_activation_inv_delta ) - activation, activation_inv, local_activation_delta = full_activation_fields_from_local( - mesh, - active_ids, - local_activation_inv_delta, + activation, activation_inv, local_activation_delta = ( + full_activation_fields_from_local( + mesh, + active_ids, + local_activation_inv_delta, + ) ) total_elapsed_s = time.perf_counter() - total_start summary = summarize( @@ -1075,7 +1085,9 @@ def main(cfg: Config) -> None: try: save_snapshot(cfg.output_snapshot, result) except (OSError, RuntimeError, ValueError): - logger.warning("failed to save snapshot: %s", cfg.output_snapshot, exc_info=True) + logger.warning( + "failed to save snapshot: %s", cfg.output_snapshot, exc_info=True + ) save_json(cfg.output_summary, summary) cherries.log_metrics(numeric_metrics(summary, exclude=frozenset({"trace"}))) print(