Progress Bar¶
When running long computations, it is useful to have a visual way of identifying the progress of the code, without relying heavily on vast streams of data. The ProgressBar provides a simple, intuitive way of tracking the status of code, with support for tracking multiple process simultaneously.
Class Definition¶
-
template<int
Dimension= 1, boolDeleteMode= true, charSymbol= '#', unsigned intMaxHashes= 20>
classJSL::ProgressBar¶ A neat display widget for tracking the progress of a process by printing a progress bar on the screen, which updates to visually indicate the process is running. Supports arbitrary “levels” of progress bars which can be independently modified through a variadic argument interface.
- Template Parameters:
Dimension – The number of concurrent bars to print (fixes the number of arguments which must be provided to subsequent functions). Defaults to 1 if 0 template arguments provided
DeleteMode – If true, utilises JSL::deleteLine() to remove the previous line before reprinting, such that the bar appears animated. If false, provides a more limited form of animation (false only available in Dimension==1 mode). Defaults to true.
Symbol – The symbol which is printed within the bar to fill up space. Defaults to “#”.
MaxHashes – The number of symbols in a full bar (dictates the width of the progress bar)
Public Functions
-
template<typename ...
Ts>
inlineProgressBar(Ts... targetCounts)¶ Constructor function. Accepts a number of integer arguments equal to Dimension, throws an error if this is not true.
- Parameters:
targetCounts – The number of processes (i.e. max loop index) that must complete before each bar is considered full.
-
template<typename ...
Ts>
inline voidUpdate(Ts... positions)¶ Provide a progress update (i.e. loop index) for each of the active bars. Accepts a number of integer arguments equal to Dimension.
- Parameters:
positons – The current process count (to be compared against the targets) of the open progress bars
-
inline void
SetName(const std::vector<std::string> &names)¶ Sets all names for the bars simultaneously.
- Parameters:
names – A vector of strings (equal to Dimension), each of which is printed before their respective bar.
-
inline void
SetName(unsigned int idx, const std::string &name)¶ Changes the name of the idx-th bar.
- Parameters:
idx – The bar name to be changes
name – The string which is printed in the front of the bar
-
inline void
SetName(const std::string &name)¶ An override for SetName(unsigned int idx, const std::string & name) available only when Dimension == 1.
- Parameters:
name – The message to go in front of the bar as it prints
-
inline void
Clear()¶ Deletes all levels of the bar from the screen, useful once the bar has finished and is no longer needed.
Private Functions
-
template<typename ...
Ts>
inline voidUnpackTargets(int target, Ts... targets)¶ The variadic internal function called by the compiler, looping over the arbitrary number of inputs and storing them in internal vectors.
-
template<typename ...
Ts>
inline voidUnrollPositions(const int idx, int pos, Ts... remainder)¶ The variadic internal function which is called by Update(), loops over the arguments and computes the number of Symbols required by each bar.
-
inline void
ClearScreen()¶ Loops over the existing bars and erases them using ANSI codes.
-
inline void
PrintPositions_DeleteMode()¶ The version of Printing which happens if DeleteMode is true — clears the previous bars using ANSI codes, then overwrites them with the new values.
-
inline void
PrintPositions_RetainMode()¶ The version of Printing which happens if DeleteMode is false - gradually prints the progress bar one Symbol at a time, then adds the close brace “]” whn the final one is printed.
Private Members
-
bool
firstPrint= true¶ Toggle to ensure open-brace “[” is printed only once.
-
std::vector<int>
BarTargets¶ Storage for the target number of processes.
-
std::vector<double>
BarProgress¶ Current progress value (between 0 and 1)
-
std::vector<int>
Hashes¶ Current printed number of symbols for each bar.
-
std::vector<std::string>
Names¶ The names printed in front of each bar.
-
bool
reprintNeeded¶ Toggle which ensures reprinting only occurs when something changes, prevents unnecessary overhead.
-
int
bufferWidth= 10¶ Default size allocated for names, increases if a value of anmes would overfill it.
-
int
prevHashes= 0¶ Used in DeleteMode=false to compute new hashe number.
Example Usage¶
Simple Case¶
In the simplest case, we can omit the template arguments, and run the progress bar in the following way:
#include <iostream>
#include "JSL.h"
void timeWastingFunction(int i)
{
// code that takes some time to complete.....
}
int main(int argc, char * argv[])
{
int N = 100;
JSL::ProgressBar pb(N);
for (int i = 0; i < N; ++i)
{
timeWastingFunction(i);
pb.Update(i);
}
return 0;
}
This would output the following bar, which overwrites itself as i advances:
[ ] //at i = 0
[############## ] //at i = 50
[###########################] // at code end
Multi-Tiered Case¶
In the case of multiple (potentially nested) processes which must be completed, we can add additional bars:
#include <iostream>
#include "JSL.h"
void tieredTimeWastingFunction(int i, int j)
{
// code that takes some time to complete.....
}
int main(int argc, char * argv[])
{
int N = 10;
int N2 = 1000;
JSL::ProgressBar<2,False,'@'> pb(N,N2);
pb.SetNames({"First Loop", "Second Loop"});
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < N2; ++j)
{
tieredTimeWastingFunction(i,j);
pb.Update(i,j);
}
}
return 0;
}
At i=j=0 this produces:
First Loop [ ]
Second Loop [ ]
As the inner loop progresses:
First Loop [ ]
Second Loop [@@@@@@@@@ ]
When the inner loop completes, the bar resets itself, and the outer loop updates:
As the inner loop progresses:
First Loop [@@@@ ]
Second Loop [ ]
No Delete Case¶
In the case that, for example, the output of the code is being piped to file, printing ANSI escape codes leads to nonsensical output. In this case, the No-Delete mode is a much safer (if more limited) way to run.
#include <iostream>
#include "JSL.h"
void timeWastingFunction(int i)
{
// code that takes some time to complete.....
}
int main(int argc, char * argv[])
{
int N = 100;
JSL::ProgressBar<1,False> pb(N);
for (int i = 0; i < N; ++i)
{
timeWastingFunction(i);
pb.Update(i);
}
return 0;
}
In this case the output appears very similar to the Simple Case above, but note that the output is printed sequentially, rather than being deleted and then rewritten:
[ //at i = 0
[############## //at i = 50
[###########################] // at code end