RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
ProgressBar.h
Go to the documentation of this file.
1//
2// Copyright (C) David Cosgrove 2025.
3//
4// @@ All Rights Reserved @@
5// This file is part of the RDKit.
6// The contents are covered by the terms of the BSD license
7// which is included in the file license.txt, found at the root
8// of the RDKit source tree.
9//
10// This implements a very basic thread-safe progress bar, based on code
11// here
12// https://www.cppstories.com/2020/02/inidicators.html/
13// which is written by the author of https://github.com/p-ranav/indicators
14// which is released under an MIT license.
15
16#ifndef PROGRESSBAR_H
17#define PROGRESSBAR_H
18
19#include <atomic>
20#include <chrono>
21#include <ctime>
22#include <mutex>
23#include <iostream>
24
25namespace RDKit {
27 public:
28 ProgressBar() : d_startTime(std::chrono::system_clock::now()) {}
29 ProgressBar(unsigned int width, std::uint64_t numToDo)
30 : d_bar_width(width),
31 d_numToDo(numToDo),
32 d_startTime(std::chrono::system_clock::now()) {}
33 ProgressBar(const ProgressBar &) = delete;
34 ProgressBar &operator=(const ProgressBar &) = delete;
37 ~ProgressBar() = default;
38
39 void update(float value, std::ostream &os = std::cout) {
40 set_progress(value);
42 }
43 void increment(std::uint64_t incr = 1, std::ostream &os = std::cout) {
44 d_done += incr;
45 float newProgress =
46 100.0 * static_cast<float>(d_done) / static_cast<float>(d_numToDo);
47 update(newProgress, os);
48 }
49
50 void set_progress(float value) {
51 std::unique_lock lock{d_mutex};
52 d_progress = value;
53 }
54
55 void write_progress(std::ostream &os = std::cout) {
56 std::unique_lock lock{d_mutex};
57 if (d_progress > 100.0f) {
58 return;
59 }
60 os << "\r" << std::flush;
61 os << "[";
62 const auto completed = static_cast<size_t>(
63 d_progress * static_cast<float>(d_bar_width) / 100.0);
64 for (size_t i = 0; i < d_bar_width; ++i) {
65 if (i <= completed)
66 os << "*";
67 else
68 os << " ";
69 }
70
71 // End bar
72 os << "]";
73
74 auto currTime = std::chrono::system_clock::now();
75 std::chrono::duration<double> elapsed = currTime - d_startTime;
76 std::chrono::duration<double> totToDo = elapsed / (d_progress / 100.0);
77 auto projFinish =
78 d_startTime +
79 std::chrono::duration_cast<std::chrono::system_clock::duration>(
80 totToDo);
81
82 // Convert to time_t for localtime
83 std::time_t finish_time_t =
84 std::chrono::system_clock::to_time_t(projFinish);
85
86 // Convert to local time structure using threadsafe version
87 std::tm local_tm{};
88#if defined(_WIN32)
89 localtime_s(&local_tm, &finish_time_t);
90#else
91 localtime_r(&finish_time_t, &local_tm);
92#endif
93 std::string fmt = "%H:%M %a";
94 static constexpr std::int64_t weekSecs = 7 * 24 * 3600;
95 if (std::chrono::duration_cast<std::chrono::seconds>(totToDo).count() >
96 weekSecs) {
97 fmt = "%d %m %y";
98 }
99 // Write progress percentage and actual values
100 os << " " << std::min(static_cast<size_t>(d_progress), size_t(100)) << "%"
101 << " " << d_done << "/" << d_numToDo << " "
102 << std::put_time(&local_tm, fmt.c_str()) << std::flush;
103 }
104
105 private:
106 std::mutex d_mutex;
107 float d_progress{0.0};
108 unsigned int d_bar_width{60};
109 std::uint64_t d_numToDo{0};
110 std::atomic<std::uint64_t> d_done{0};
111 std::chrono::time_point<std::chrono::system_clock> d_startTime;
112};
113} // namespace RDKit
114
115#endif // PROGRESSBAR_H
ProgressBar(unsigned int width, std::uint64_t numToDo)
Definition ProgressBar.h:29
void increment(std::uint64_t incr=1, std::ostream &os=std::cout)
Definition ProgressBar.h:43
ProgressBar(const ProgressBar &)=delete
void set_progress(float value)
Definition ProgressBar.h:50
ProgressBar & operator=(ProgressBar &&)=delete
void write_progress(std::ostream &os=std::cout)
Definition ProgressBar.h:55
ProgressBar & operator=(const ProgressBar &)=delete
void update(float value, std::ostream &os=std::cout)
Definition ProgressBar.h:39
ProgressBar(ProgressBar &&)=delete
~ProgressBar()=default
Std stuff.