Repository navigation
Expand file tree
/
Copy pathnotification_bridge.cpp
More file actions
125 lines (110 loc) · 4.87 KB
/
Copy pathnotification_bridge.cpp
File metadata and controls
125 lines (110 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* SPDX-FileCopyrightText: 2025 LichtFeld Studio Authors
*
* SPDX-License-Identifier: GPL-3.0-or-later */
#include "notification_bridge.hpp"
#include "core/event_bridge/localization_manager.hpp"
#include "core/events.hpp"
#include "gui/string_keys.hpp"
#include "py_ui.hpp"
#include <cmath>
#include <format>
#include <mutex>
#include <optional>
namespace lfs::python {
using namespace lfs::core::events;
namespace {
struct LatestEvaluationMetrics {
int iteration = 0;
float psnr = 0.0f;
float ssim = 0.0f;
std::optional<float> lpips;
};
std::mutex g_latest_eval_metrics_mutex;
std::optional<LatestEvaluationMetrics> g_latest_eval_metrics;
} // namespace
static std::string formatDuration(const float seconds) {
const float clamped = std::max(0.0f, seconds);
const int total = static_cast<int>(std::round(clamped));
const int hours = total / 3600;
const int minutes = (total % 3600) / 60;
const int secs = total % 60;
if (hours > 0) {
return std::format("{}h {}m {}s", hours, minutes, secs);
}
if (minutes > 0) {
return std::format("{}m {}s", minutes, secs);
}
if (clamped >= 1.0f) {
return std::format("{}s", secs);
}
return std::format("{:.1f}s", clamped);
}
void setup_notification_handlers() {
// Failure events (dataset/config/export/video/mesh/training/CUDA/disk) now
// surface through the native C++ ErrorBus (Phase 8, error_event_bridge),
// so they appear even when Python is absent. Re-adding failure modals here
// would double them. Only the success TrainingCompleted modal and the
// eval-metrics tracking it depends on remain Python-owned.
state::TrainingStarted::when([](const auto&) {
std::lock_guard lock(g_latest_eval_metrics_mutex);
g_latest_eval_metrics.reset();
});
state::EvaluationCompleted::when([](const auto& e) {
std::lock_guard lock(g_latest_eval_metrics_mutex);
g_latest_eval_metrics = LatestEvaluationMetrics{
.iteration = e.iteration,
.psnr = e.psnr,
.ssim = e.ssim,
.lpips = e.lpips};
});
state::TrainingCompleted::when([](const auto& e) {
if (!e.success)
return; // failures surface via the native ErrorBus bridge
if (e.suppress_notification)
return; // stop was part of New Project / app close / reset / trainer teardown on scene/dataset replacement — no modal (issue #1604, #1645)
namespace Str = lichtfeld::Strings::Training::Button;
auto message = e.user_stopped
? LOCF("messages.training_stopped_body", e.iteration)
: std::format("Training completed successfully.\n\n"
"{} iterations | loss {:.6f} | {}",
e.iteration, e.final_loss, formatDuration(e.elapsed_seconds));
std::optional<LatestEvaluationMetrics> eval_snapshot;
{
std::lock_guard lock(g_latest_eval_metrics_mutex);
eval_snapshot = g_latest_eval_metrics;
}
if (eval_snapshot.has_value()) {
if (eval_snapshot->iteration == e.iteration) {
message += std::format(
"\nFinal metrics: PSNR {:.2f} | SSIM {:.4f}",
eval_snapshot->psnr,
eval_snapshot->ssim);
} else {
message += std::format(
"\nLast eval @ {}: PSNR {:.2f} | SSIM {:.4f}",
eval_snapshot->iteration,
eval_snapshot->psnr,
eval_snapshot->ssim);
}
if (eval_snapshot->lpips)
message += std::format(" | LPIPS {:.4f}", *eval_snapshot->lpips);
}
if (e.user_stopped) {
// Stopped by user: OK only — Edit mode is nonsensical when scene may be clearing (issue #1604)
PyModalRegistry::instance().show_confirm(
"Training Stopped", message,
{"OK"},
[](const std::string&) {});
} else {
const std::string edit_label = LOC(Str::SWITCH_EDIT_MODE);
PyModalRegistry::instance().show_confirm(
"Training Complete", message,
{edit_label, "OK"},
[edit_label](const std::string& clicked) {
if (clicked == edit_label)
cmd::SwitchToEditMode{}.emit();
});
}
});
}
} // namespace lfs::python