Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
StatisticProgress.cpp
Go to the documentation of this file.
1#include "StatisticProgress.h"
2
3#include <algorithm>
4
5namespace {
6
7std::string format_seconds(double seconds) {
8 std::ostringstream oss;
9 if (seconds < 60.0) {
10 oss << std::fixed << std::setprecision(1) << seconds << "s";
11 } else if (seconds < 3600.0) {
12 const int minutes = static_cast<int>(seconds / 60.0);
13 const int sec = static_cast<int>(seconds) % 60;
14 oss << minutes << "m" << std::setw(2) << std::setfill('0')
15 << sec << std::setfill(' ') << "s";
16 } else {
17 const int hours = static_cast<int>(seconds / 3600.0);
18 const int minutes = (static_cast<int>(seconds) / 60) % 60;
19 const int sec = static_cast<int>(seconds) % 60;
20 oss << hours << "h"
21 << std::setw(2) << std::setfill('0') << minutes << "m"
22 << std::setw(2) << std::setfill('0') << sec
23 << std::setfill(' ') << "s";
24 }
25 return oss.str();
26}
27
28} // namespace
29
30void StatisticProgressMonitor::reset(const std::string& phase, const std::string& message) {
31 std::lock_guard<std::mutex> lock(mutex_);
32 latest_ = {};
33 latest_.phase = phase;
34 latest_.message = message;
35 latest_.sequence = next_sequence_++;
36}
37
39 std::lock_guard<std::mutex> lock(mutex_);
40 event.fraction = std::clamp(event.fraction, 0.0, 1.0);
41 event.sequence = next_sequence_++;
42 latest_ = std::move(event);
43}
44
46 std::lock_guard<std::mutex> lock(mutex_);
47 return latest_;
48}
49
51 std::size_t total,
52 std::size_t probe_draws,
53 std::size_t update_every,
54 std::ostream& os,
55 std::string label,
56 std::string item_label,
57 std::shared_ptr<StatisticProgressMonitor> monitor,
58 std::string phase)
59 : enabled_(enabled), total_(total), probe_draws_(probe_draws == 0 ? 1 : probe_draws),
60 update_every_(update_every == 0 ? 1 : update_every), os_(&os),
61 start_(std::chrono::steady_clock::now()), label_(std::move(label)),
62 item_label_(std::move(item_label)), monitor_(std::move(monitor)), phase_(std::move(phase))
63{
64 publish(0, 0, 0, false, "Starting Monte-Carlo sampling");
65}
66
67double StatisticProgressReporter::elapsed_seconds() const {
68 return std::chrono::duration<double>(std::chrono::steady_clock::now() - start_).count();
69}
70
71double StatisticProgressReporter::eta_seconds(std::size_t accepted_count) const {
72 if (accepted_count == 0 || accepted_count < probe_draws_ || accepted_count >= total_) return -1.0;
73 return (elapsed_seconds() / static_cast<double>(accepted_count)) * static_cast<double>(total_ - accepted_count);
74}
75
76std::string StatisticProgressReporter::bar(std::size_t accepted_count) const {
77 constexpr std::size_t width = 28;
78 const double raw_frac = total_ == 0 ? 1.0 : static_cast<double>(accepted_count) / static_cast<double>(total_);
79 const double frac = std::clamp(raw_frac, 0.0, 1.0);
80 const std::size_t filled = static_cast<std::size_t>(frac * width);
81 std::string out("[");
82 for (std::size_t i = 0; i < width; ++i) out.push_back(i < filled ? '#' : '.');
83 out.push_back(']');
84 return out;
85}
86
87std::string StatisticProgressReporter::eta_string(std::size_t accepted_count) const {
88 const double eta = eta_seconds(accepted_count);
89 return eta < 0.0 ? "estimating" : format_seconds(eta);
90}
91
92void StatisticProgressReporter::publish(std::size_t accepted_count,
93 std::size_t attempts,
94 std::size_t failures,
95 bool finished,
96 const std::string& message) {
97 if (!monitor_) return;
99 ev.phase = phase_;
100 ev.message = message;
101 ev.completed = accepted_count;
102 ev.total = total_;
103 ev.attempts = attempts;
104 ev.failures = failures;
105 ev.fraction = total_ == 0 ? 1.0 : static_cast<double>(accepted_count) / static_cast<double>(total_);
106 ev.elapsed_seconds = elapsed_seconds();
107 ev.eta_seconds = finished ? 0.0 : eta_seconds(accepted_count);
108 ev.finished = finished;
109 monitor_->update(std::move(ev));
110}
111
112void StatisticProgressReporter::accepted(std::size_t accepted_count, std::size_t attempts, std::size_t failures) {
113 if (!enabled_ && !monitor_) return;
114 if (total_ == 0) return;
115 if (accepted_count != total_ && accepted_count % update_every_ != 0 && accepted_count != probe_draws_) return;
116
117 if (attempts == 0) attempts = accepted_count;
118 publish(accepted_count, attempts, failures, false,
119 label_ + ": " + std::to_string(accepted_count) + "/" + std::to_string(total_) + " " + item_label_);
120 if (!enabled_) return;
121 const double pct = 100.0 * static_cast<double>(accepted_count) / static_cast<double>(total_);
122 (*os_) << "\r\033[K[" << label_ << "] " << bar(accepted_count)
123 << " " << accepted_count << "/" << total_ << " " << item_label_
124 << " (" << std::fixed << std::setprecision(1) << pct << "%)"
125 << " | ETA " << eta_string(accepted_count) << std::flush;
126}
127
128void StatisticProgressReporter::finish(std::size_t accepted_count, std::size_t attempts, std::size_t failures) {
129 publish(accepted_count, attempts, failures, true,
130 label_ + " completed: " + std::to_string(accepted_count) + "/" + std::to_string(total_) + " " + item_label_);
131 if (!enabled_) return;
132 (*os_) << "\r\033[K[" << label_ << "] " << bar(accepted_count)
133 << " " << accepted_count << "/" << total_ << " " << item_label_
134 << " completed in " << format_seconds(elapsed_seconds())
135 << " (attempts=" << attempts << ", rejected=" << failures << ")\n";
136}
137
139 std::string label,
140 std::size_t total_steps,
141 std::ostream& os,
142 std::shared_ptr<StatisticProgressMonitor> monitor,
143 std::string phase)
144 : enabled_(enabled), label_(std::move(label)), total_steps_(total_steps == 0 ? 1 : total_steps),
145 os_(&os), start_(std::chrono::steady_clock::now()), monitor_(std::move(monitor)), phase_(std::move(phase)) {}
146
147std::string StatisticStageProgressReporter::bar(std::size_t completed_steps) const {
148 constexpr std::size_t width = 28;
149 const double frac = std::clamp(static_cast<double>(completed_steps) / static_cast<double>(total_steps_), 0.0, 1.0);
150 const std::size_t filled = static_cast<std::size_t>(frac * width);
151 std::string out("[");
152 for (std::size_t i = 0; i < width; ++i) out.push_back(i < filled ? '#' : '.');
153 out.push_back(']');
154 return out;
155}
156
157double StatisticStageProgressReporter::elapsed_seconds() const {
158 return std::chrono::duration<double>(std::chrono::steady_clock::now() - start_).count();
159}
160
161std::string StatisticStageProgressReporter::elapsed_string() const { return format_seconds(elapsed_seconds()); }
162
163void StatisticStageProgressReporter::publish(std::size_t completed_steps, const std::string& message, bool finished) {
164 if (!monitor_) return;
166 ev.phase = phase_;
167 ev.message = message;
168 ev.completed = std::min(completed_steps, total_steps_);
169 ev.total = total_steps_;
170 ev.fraction = static_cast<double>(ev.completed) / static_cast<double>(total_steps_);
171 ev.elapsed_seconds = elapsed_seconds();
172 // Stage durations (covariance assembly, inversion, minimization, contours)
173 // are not homogeneous, so extrapolating from completed stage count would be
174 // misleading. Keep the measured ETA exclusively for Monte-Carlo sampling.
175 ev.eta_seconds = finished ? 0.0 : -1.0;
176 ev.finished = finished;
177 monitor_->update(std::move(ev));
178}
179
180void StatisticStageProgressReporter::start(const std::string& message) {
181 publish(0, message, false);
182 if (enabled_) (*os_) << "[" << label_ << "] " << message << '\n';
183}
184
185void StatisticStageProgressReporter::step(std::size_t completed_steps, const std::string& message) {
186 publish(completed_steps, message, false);
187 if (!enabled_) return;
188 const std::size_t shown = std::min(completed_steps, total_steps_);
189 (*os_) << "[" << label_ << "] " << bar(shown) << " " << shown << "/" << total_steps_
190 << " | " << message << " | elapsed " << elapsed_string() << '\n';
191}
192
193void StatisticStageProgressReporter::finish(const std::string& message) {
194 publish(total_steps_, message, true);
195 if (enabled_) (*os_) << "[" << label_ << "] " << bar(total_steps_) << " " << total_steps_ << "/" << total_steps_
196 << " | " << message << " | total " << elapsed_string() << '\n';
197}
198
void update(StatisticProgressEvent event)
StatisticProgressEvent snapshot() const
void reset(const std::string &phase="preparing", const std::string &message="Preparing statistic workflow")
void accepted(std::size_t accepted_count, std::size_t attempts=0, std::size_t failures=0)
StatisticProgressReporter(bool enabled, std::size_t total, std::size_t probe_draws=5, std::size_t update_every=1, std::ostream &os=std::cout, std::string label="Monte-Carlo", std::string item_label="accepted", std::shared_ptr< StatisticProgressMonitor > monitor=nullptr, std::string phase="monte_carlo")
void finish(std::size_t accepted_count, std::size_t attempts, std::size_t failures)
void finish(const std::string &message)
StatisticStageProgressReporter(bool enabled, std::string label, std::size_t total_steps, std::ostream &os=std::cout, std::shared_ptr< StatisticProgressMonitor > monitor=nullptr, std::string phase="chi2_pipeline")
void start(const std::string &message)
void step(std::size_t completed_steps, const std::string &message)
Hash specialization for SymbolId<Tag>.
Definition BlockName.h:353