BioDynaMo  v1.05.120-25dc9790
progress_bar.cc
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------
2 //
3 // Copyright (C) 2021 CERN & University of Surrey for the benefit of the
4 // BioDynaMo collaboration. All Rights Reserved.
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 //
9 // See the LICENSE file distributed with this work for details.
10 // See the NOTICE file distributed with this work for additional information
11 // regarding copyright ownership.
12 //
13 // -----------------------------------------------------------------------------
14 
15 #include "core/util/progress_bar.h"
16 #include <unistd.h>
17 #include <cassert>
18 #include <iomanip>
19 #include <string>
20 #include "core/util/timing.h"
21 
22 namespace bdm {
23 
24 inline real_t TimeConversionFactor(const std::string& unit) {
25  if (unit == "ms") {
26  return 1;
27  } else if (unit == "s") {
28  return 1000;
29  } else if (unit == "min") {
30  return 1000 * 60;
31  } else {
32  return 1000 * 60 * 60;
33  }
34 }
35 
37 
38 ProgressBar::ProgressBar(int total_steps)
39  : total_steps_(total_steps), start_time_(Timing::Timestamp()) {}
40 
41 void ProgressBar::Step(uint64_t steps) { executed_steps_ += steps; }
42 
43 void ProgressBar::PrintProgressBar(std::ostream& out) {
44  // Do not write to file because it does not handle "\r" well.
45  if (write_to_file_) {
46  return;
47  }
48 
49  // Print empty line at first iteration to compensate for "\r" below.
50  if (first_iter_) {
51  // Determine if we write to file or terminal.
52  if (!isatty(fileno(stdout))) {
53  std::cout << "<ProgressBar::PrintProgressBar> omits output because you "
54  "write to file."
55  << std::endl;
56  write_to_file_ = true;
57  return;
58  }
59  out << "ET = Elapsed Time; TR = Time Remaining" << std::endl;
60  first_iter_ = false;
61  }
62 
63  // If total_steps_ is not set, we fall back to simple step printing. This can
64  // be the case if someone uses SimulateUntil where we do not know the number
65  // of steps in advance.
66  if (total_steps_ == 0) {
67  out << "Time step: " << total_steps_ << std::endl;
68  }
69 
70  // 1. Get current and compute elapsed time
71  int64_t current_time = Timing::Timestamp();
72  auto elapsed_time = static_cast<real_t>(current_time - start_time_);
73 
74  // 2. Compute ETA
75  real_t fraction_computed =
76  static_cast<real_t>(executed_steps_) / static_cast<real_t>(total_steps_);
77  assert(fraction_computed <= 1);
78  real_t remaining_time = elapsed_time / fraction_computed - elapsed_time;
79  elapsed_time /= time_conversion_factor_;
80  remaining_time /= time_conversion_factor_;
81 
82  // 3. Print progress bar
83  size_t n_steps_computed = std::floor(fraction_computed / 0.02);
84 
85  // Write terminal output to string first to determine the number of digits
86  std::string terminal_output = "";
87  terminal_output.append("[")
88  .append(std::string(n_steps_computed, '#'))
89  .append(std::string(50 - n_steps_computed, ' '))
90  .append("] ");
91  terminal_output.append(std::to_string(executed_steps_))
92  .append(" / ")
93  .append(std::to_string(total_steps_))
94  .append(" ");
95  terminal_output.append("( ET: ")
96  .append(std::to_string(elapsed_time))
97  .append(", TR:")
98  .append(std::to_string(remaining_time))
99  .append(")[")
100  .append(time_unit_)
101  .append("]");
102  terminal_output.append("\r");
103 
104  // Update number of terminal characters
105  n_terminal_chars_ = std::max({terminal_output.length(), n_terminal_chars_});
106 
107  // If the string is shorter than n_terminal_chars_, we need to add spaces
108  // to override the previous output
109  if (terminal_output.length() < n_terminal_chars_) {
110  terminal_output.append(
111  std::string(n_terminal_chars_ - terminal_output.length(), ' '));
112  }
113 
114  // Print to terminal
115  out << terminal_output;
116 
117  // 3. Go to new line once we've reached the last step
118  if (executed_steps_ == total_steps_) {
119  out << "\n";
120  }
121 }
122 
123 void ProgressBar::SetTimeUnit(const std::string& time_unit) {
124  // Accept only the following time units: ms, s, min, h
125  if (time_unit == "ms" || time_unit == "s" || time_unit == "min" ||
126  time_unit == "h") {
127  time_unit_ = time_unit;
129  } else {
130  Log::Warning("ProgressBar::SetTimeUnit",
131  "Time unit not supported. Use ms, s, min, h instead. ",
132  "Falling back to [s].");
133  }
134 }
135 
136 } // namespace bdm
timing.h
bdm::ProgressBar::SetTimeUnit
void SetTimeUnit(const std::string &time_unit)
Definition: progress_bar.cc:123
bdm::ProgressBar::start_time_
int64_t start_time_
Timestamp when to when the progress bar was initialized.
Definition: progress_bar.h:49
bdm
Definition: agent.cc:39
bdm::ProgressBar::time_unit_
std::string time_unit_
Time unit string for elapsed and remaining time.
Definition: progress_bar.h:43
bdm::ProgressBar::total_steps_
uint64_t total_steps_
Total number of steps to be executed.
Definition: progress_bar.h:45
bdm::ProgressBar::time_conversion_factor_
real_t time_conversion_factor_
Variable for conversion of time units (e.g. 1000 for ms to s).
Definition: progress_bar.h:54
bdm::real_t
double real_t
Definition: real_t.h:21
bdm::ProgressBar::PrintProgressBar
void PrintProgressBar(std::ostream &out=std::cout)
Prints the progress bar.
Definition: progress_bar.cc:43
bdm::Timing
Definition: timing.h:29
bdm::Log::Warning
static void Warning(const std::string &location, const Args &... parts)
Prints warning message.
Definition: log.h:67
bdm::ProgressBar::first_iter_
bool first_iter_
Definition: progress_bar.h:57
bdm::TimeConversionFactor
real_t TimeConversionFactor(const std::string &unit)
Definition: progress_bar.cc:24
bdm::ProgressBar::write_to_file_
bool write_to_file_
Definition: progress_bar.h:60
bdm::ProgressBar::Step
void Step(uint64_t steps=1)
Inceases the counter executed_steps_ by steps.
Definition: progress_bar.cc:41
bdm::ProgressBar::ProgressBar
ProgressBar()
Definition: progress_bar.cc:36
bdm::ProgressBar::executed_steps_
uint64_t executed_steps_
Number of steps that have already been executed.
Definition: progress_bar.h:47
bdm::ProgressBar
This class implements a progress bar that can be used to track the progress of a simulation.
Definition: progress_bar.h:40
bdm::ProgressBar::n_terminal_chars_
size_t n_terminal_chars_
Definition: progress_bar.h:52
bdm::Timing::Timestamp
static int64_t Timestamp()
Definition: timing.h:33
progress_bar.h