 |
Darwin
1.0
Event loop based prototype framework
|
|
| typedef std::pair< unsigned, unsigned > | Slice |
| |
|
| optional< bool > | getBool (string s) |
| |
| template<typename ... Args> |
| void | FromPT2MetaInfo (const pt::ptree &elements, const MetaInfo &metainfo, ostream &cout, Args... args) |
| |
| void | forceMetaInfo (const fs::path &input, const fs::path &output, const int steering) |
| |
| int | getMetaInfo (vector< fs::path > inputs, const fs::path &output) |
| |
| int | initMetaInfo (const pt::ptree &config) |
| |
| template<int thousand = 1024> |
| const char * | GetHumanReadableSize (long double size) |
| |
| Long64_t | GetSize (TBranch *br) |
| |
| Long64_t | loopBranches (TObjArray *branches, size_t factor, int nIndent=0) |
| |
| void | printBranches (vector< fs::path > inputs) |
| |
| void | printDarwinSoftwareVersion () |
| |
| void | printEntries (vector< fs::path > inputs) |
| |
| void | PrintCloseFriend (TList *friends, const int steering, string offset="") |
| |
| void | printFriends (vector< fs::path > inputs, const int steering) |
| |
| void | printHist (vector< fs::path > inputs, const pt::ptree &config) |
| |
| int | printMetaInfo (vector< fs::path > inputs, const pt::ptree &config) |
| |
| std::unique_ptr< TFile > | GetOutput (std::filesystem::path output, const char *name) |
| |
| void | StandardInit () |
| |
| std::vector< std::filesystem::path > | GetROOTfiles (std::vector< std::filesystem::path > inputs) |
| |
| std::unique_ptr< TChain > | GetChain (std::vector< std::filesystem::path > inputs, const char *name="events") |
| |
| template<typename THX = TH1> |
| std::unique_ptr< THX > | GetHist (std::vector< std::filesystem::path > inputs, const char *name="h") |
| |
| std::string | GetFirstTreeLocation (const std::filesystem::path &input) |
| |
| std::unique_ptr< TTree > | NewTree (const std::unique_ptr< TChain > &chain, const bool makeFriend, const char *thisFunc) |
| |
| std::ostream & | operator<< (std::ostream &Stream, const Darwin::Tools::Slice &slice) |
| |
| static std::ostream | dev_null (nullptr) |
| |
| std::vector< const char * > | tokenize (const char *str) |
| |
Classes and functions related to the framework.
◆ Slice
| typedef std::pair<unsigned, unsigned> Slice |
current slice (>=0) / total number of slices (>0)
◆ anonymous enum
| Enumerator |
|---|
| none | default (for simple executables)
|
| config | activate -c option to provide config file
|
| split | activate -k and -j to define slice
|
| fill | activate -f to fill the tree
|
| Friend | activate -F to only fill the new branches
|
| syst | activate -s to systematic uncertainties
|
| verbose | bit for debug mode (-v is always available)
|
◆ dev_null()
| static std::ostream Darwin::Tools::dev_null |
( |
nullptr |
| ) |
|
|
static |
to redirect output stream to nowhere
◆ forceMetaInfo()
| void Darwin::Tools::forceMetaInfo |
( |
const fs::path & |
input, |
|
|
const fs::path & |
output, |
|
|
const int |
steering |
|
) |
| |
Force content of all TTree::UserInfo() and TList found in the topmost directory of the root file. This method is to be used as a last resort, and certainly not in the context of reproducible results.
- Parameters
-
| input | input config file (INFO, JSON, XML) |
| output | ROOT file |
| steering | parameters obtained from explicit options |
98 if (input.extension() ==
".json")
99 pt::read_json(input,
config);
100 else if (input.extension() ==
".xml")
101 pt::read_xml(input,
config);
103 pt::read_info(input,
config);
106 unique_ptr<TFile> fOut(TFile::Open(output.c_str(),
"UPDATE"));
107 auto t = unique_ptr<TTree>(fOut->Get<TTree>(location.c_str()));
109 BOOST_THROW_EXCEPTION(
DE::BadInput(
"The tree can't be found in this file.", fOut));
111 t->GetUserInfo()->Clear();
114 MetaInfo metainfo(t,
false);
116 metainfo.Set<
bool>(
"git",
"reproducible",
false);
117 if (metainfo.Find(
"history")) {
118 TList * history = metainfo.List(
"history");
119 metainfo.List()->Remove(history);
◆ FromPT2MetaInfo()
| void Darwin::Tools::FromPT2MetaInfo |
( |
const pt::ptree & |
elements, |
|
|
const MetaInfo & |
metainfo, |
|
|
ostream & |
cout, |
|
|
Args... |
args |
|
) |
| |
Sets whatever is in the input config file into the metainfo of a TTree.
- Parameters
-
| elements | from config file |
| metainfo | target metainfo (will be modified) |
| cout | overrides standard output |
| args | key chain |
56 if constexpr (
sizeof...(Args) < 10)
57 for (const auto& element: elements) {
58 const char * key = element.first.c_str();
59 const auto& value = element.second.get_value<
string>();
62 if constexpr (
sizeof...(Args) > 0)
63 (cout << ... << args) <<
' ';
64 cout <<
def << key <<
" \"" << value <<
'"' << endl;
68 auto match = [&value](
const string& reg) {
69 return regex_match( value, regex(reg) );
71 if (
auto isBool =
getBool(value); isBool)
72 metainfo.Set<
bool>(args..., key, *isBool);
73 else if (match(
"-?[0-9]+"))
74 metainfo.Set<
int>(args..., key, stoi(value));
75 else if (match(
"-?[0-9]+([\\.][0-9]+)?"))
76 metainfo.Set<
float>(args..., key, stof(value));
77 else if (element.second.size() == 0) {
79 if constexpr (
sizeof...(Args) > 0)
80 metainfo.Set<
string>(args...,
string(key));
83 metainfo.Set<
string>(args..., key, value);
◆ getBool()
| optional<bool> Darwin::Tools::getBool |
( |
string |
s | ) |
|
Translates a string into a boolean if possible.
36 static const array<string,4> trueStr {
"true",
"on",
"ktrue",
"yes"},
37 falseStr {
"false",
"off",
"kfalse",
"no"};
38 if (
auto it = find(trueStr.begin(), trueStr.end(), s);
40 return make_optional<bool>(
true);
41 if (
auto it = find(falseStr.begin(), falseStr.end(), s);
43 return make_optional<bool>(
false);
◆ GetChain()
| std::unique_ptr< TChain > GetChain |
( |
std::vector< std::filesystem::path > |
inputs, |
|
|
const char * |
name = "events" |
|
) |
| |
Load chain from a list of files.
internal path to TTree
- Parameters
-
| inputs | ROOT files or directories |
| name | internal path to `TTree` |
71 namespace fs = filesystem;
73 unique_ptr<TChain> chain = make_unique<TChain>(name);
75 for (
auto const& input: inputs) {
76 int code = chain->Add(input.c_str(), 0);
79 if (code == 1)
continue;
80 auto fIn = make_unique<TFile>(input.c_str(),
"READ");
83 "found in (one of) the input file(s).", fIn));
85 if (chain->GetEntries() == 0)
86 BOOST_THROW_EXCEPTION(std::invalid_argument(
"Empty trees in input!"));
◆ GetFirstTreeLocation()
| std::string GetFirstTreeLocation |
( |
const std::filesystem::path & |
input | ) |
|
one input ROOT file
Look for a tree in the input file (stop at the first found one).
NOTE: in principle, we take the risk of not looking at the same TTree as all other executables, but this is unlikely in practice
- Parameters
-
94 namespace fs = filesystem;
97 unique_ptr<TFile> fIn(TFile::Open(input.c_str(),
"READ"));
98 if (!fIn || !fIn->IsOpen() || fIn->IsZombie() || !fs::exists(input))
99 BOOST_THROW_EXCEPTION( fs::filesystem_error(
"Failed to open input file",
100 input, make_error_code(std::errc::io_error)) );
102 function<string(TDirectory *)> loop;
103 loop = [&loop](TDirectory * d) ->
string {
106 for (
const auto&& obj: *(d->GetListOfKeys())) {
107 auto const key =
dynamic_cast<TKey*
>(obj);
108 if (
dynamic_cast<TTree *
>(key->ReadObj()) ==
nullptr)
continue;
109 return obj->GetName();
113 for (
const auto&& obj: *(d->GetListOfKeys())) {
114 auto const key =
dynamic_cast<TKey*
>(obj);
115 auto dd =
dynamic_cast<TDirectory *
>(key->ReadObj());
116 if (dd ==
nullptr)
continue;
117 if (
auto location = loop(dd); !location.empty())
118 return Form(
"%s/%s", dd->GetName(), location.c_str());
124 string location = loop(fIn.get());
125 if (location.empty())
126 BOOST_THROW_EXCEPTION(
DE::BadInput(
"No `TTree` could be found in the input file.", fIn) );
◆ GetHist()
| std::unique_ptr<THX> Darwin::Tools::GetHist |
( |
std::vector< std::filesystem::path > |
inputs, |
|
|
const char * |
name = "h" |
|
) |
| |
|
inline |
Load a histogram from a list of files.
- Parameters
-
| inputs | ROOT files or directories |
| name | internal path to ROOT histogram |
50 namespace fs = filesystem;
54 for (
auto const& input: inputs) {
55 auto fIn = make_unique<TFile>(input.c_str(),
"READ");
57 unique_ptr<THX> h(fIn->Get<THX>(name));
60 BOOST_THROW_EXCEPTION(
DE::BadInput(Form(
"`%s` cannot be found in (one of) the "
61 " file(s).", name), fIn));
67 sum->SetDirectory(
nullptr);
◆ GetHumanReadableSize()
| const char* Darwin::Tools::GetHumanReadableSize |
( |
long double |
size | ) |
|
From an absolute number of bytes to human readable size in KB, MB, GB, etc.
< https://en.wikipedia.org/wiki/Byte
- Parameters
-
31 static const array levels = {
'\0',
'K',
'M',
'G',
'T',
'P',
'E',
'Z',
'Y'};
32 auto level = levels.begin();
33 while (level != prev(levels.end())
34 && size >
static_cast<long double>(thousand)) {
38 return Form(
"%.0Lf%c", size, *level);
◆ getMetaInfo()
| int Darwin::Tools::getMetaInfo |
( |
vector< fs::path > |
inputs, |
|
|
const fs::path & |
output |
|
) |
| |
Print content of the first TTree::UserInfo() found in the root file.
- Parameters
-
| inputs | input ROOT files |
| output | output config file (INFO, JSON, XML) |
29 const size_t N = inputs.size();
31 vector<size_t> hashes(N,0);
37 for (
size_t i = 0; i < N; ++i) {
40 unique_ptr<TFile> fIn(TFile::Open(inputs[i].c_str(),
"READ"));
42 BOOST_THROW_EXCEPTION(
DE::BadInput(
"Can't open the file.", fIn));
45 auto t = unique_ptr<TTree>(
dynamic_cast<TTree*
>(fIn->Get<TTree>(location.c_str())));
47 BOOST_THROW_EXCEPTION(
DE::BadInput(
"The tree can't be found in this file.", fIn));
50 MetaInfo mi(t,
false);
61 bool identical =
true;
63 for (
size_t i = 0; i < N; ++i) {
64 ss << inputs[i] <<
'\t' << hex << hashes[i] <<
'\n';
66 identical &= hashes[i-1] == hashes[i];
69 if (identical)
return EXIT_SUCCESS;
70 cerr <<
red << ss.str() <<
def;
◆ GetOutput()
| std::unique_ptr< TFile > GetOutput |
( |
std::filesystem::path |
output, |
|
|
const char * |
name |
|
) |
| |
Shortcut to create a reproducible output file (see ROOT Doxygen for details)
16 const auto fname = output;
17 output +=
"?reproducible="; output += name;
18 std::unique_ptr<TFile> f(TFile::Open(output.c_str(),
"RECREATE"));
19 if (!f || !f->IsOpen() || f->IsZombie() || !fs::exists(fname))
20 BOOST_THROW_EXCEPTION( fs::filesystem_error(
"Failed to open output file",
21 output, make_error_code(std::errc::io_error)) );
◆ GetROOTfiles()
| std::vector< std::filesystem::path > GetROOTfiles |
( |
std::vector< std::filesystem::path > |
inputs | ) |
|
ROOT files or directories.
In case directories are given as inputs, instead of files, this function looks for all ROOT files in those directories (and subdirectories, iteratively).
- Parameters
-
| inputs | ROOT files or directories |
36 namespace fs = filesystem;
38 if (inputs.size() == 0)
39 BOOST_THROW_EXCEPTION(fs::filesystem_error(
"No input was found!",
40 make_error_code(errc::no_such_file_or_directory)));
42 vector<fs::path> root_inputs;
43 root_inputs.reserve(inputs.size());
45 for (
auto input: inputs) {
46 input = fs::absolute(input);
47 if (fs::is_directory(input)) {
48 for (
const auto &entry : fs::recursive_directory_iterator(
49 input, fs::directory_options::follow_directory_symlink)) {
50 if (fs::is_regular_file(entry) && entry.path().extension() ==
".root") {
51 root_inputs.push_back(entry);
55 else if (input.extension() ==
".root")
56 root_inputs.push_back(input);
59 sort(root_inputs.begin(), root_inputs.end(),
60 [](
const fs::path& a,
const fs::path& b) {
61 return strnatcmp(a.c_str(), b.c_str()) < 0;
◆ GetSize()
| Long64_t Darwin::Tools::GetSize |
( |
TBranch * |
br | ) |
|
Adapted from ROOT example
45 TMemFile f(
"buffer",
"CREATE");
46 auto fcurrent = br->GetTree()->GetCurrentFile();
48 auto settings = fcurrent->GetCompressionSettings();
49 f.SetCompressionSettings(settings);
51 f.WriteObject(br,
"thisbranch");
52 TKey * key = f.GetKey(
"thisbranch");
53 Long64_t size = key->GetNbytes();
55 Long64_t basket = br->GetZipBytes();
56 if (basket == 0) basket = br->GetTotBytes();
◆ initMetaInfo()
| int Darwin::Tools::initMetaInfo |
( |
const pt::ptree & |
config | ) |
|
Writes a minimal MetaInfo to standard output.
- Parameters
-
| config | config, with `flags` and `corrections` at least |
24 auto formatStr =
config.get<
string>(
"format");
25 MetaInfo::Format format;
26 if (formatStr ==
"info")
27 format = MetaInfo::INFO;
28 else if (formatStr ==
"json")
29 format = MetaInfo::JSON;
30 else if (formatStr ==
"xml")
31 format = MetaInfo::XML;
33 BOOST_THROW_EXCEPTION( std::invalid_argument(
34 "Unknown MetaInfo format \"" + formatStr +
"\"") );
36 MetaInfo(MetaInfo::IKnowWhatIAmDoing{}).Write(cout, format);
◆ loopBranches()
| Long64_t Darwin::Tools::loopBranches |
( |
TObjArray * |
branches, |
|
|
size_t |
factor, |
|
|
int |
nIndent = 0 |
|
) |
| |
Adapted from ROOT example
- Parameters
-
| branches | list of (sub)branches |
| factor | correction factor for #files in `TChain` |
68 size_t n = branches->GetEntries();
70 for (
size_t i = 0; i < n; ++i) {
71 auto br =
dynamic_cast<TBranch*
>(branches->At(i));
74 string branchname(nIndent,
' ');
75 branchname += br->GetName();
76 cout << left << setw(40) << branchname
79 TObjArray * subbranches = br->GetListOfBranches();
◆ NewTree()
| std::unique_ptr< TTree > NewTree |
( |
const std::unique_ptr< TChain > & |
chain, |
|
|
const bool |
makeFriend, |
|
|
const char * |
thisFunc |
|
) |
| |
name of present exec
Either clone the input TChain or define the input TChain as a friend of the new TTree.
The title of the TTree is used to store (retrieve) the name of the present (previous) command. Different names are indeed necessary to distinguish the same branch in a TTree and its friend(s).
TODO: TTree::BuildIndex() to preserve the association despite skipped events?
- Parameters
-
| chain | input |
| makeFriend | steering containing the option |
| thisFunc | name of present exec |
137 unique_ptr<TTree> tOut;
139 tOut = make_unique<TTree>(
"events", thisFunc);
143 TString lastFunc = chain->GetTree()->GetTitle();
144 if (lastFunc ==
"" || lastFunc == chain->GetTree()->GetName()) {
145 cerr <<
orange <<
"Unable to identify the command used to obtain the input from the title.\n" <<
def;
146 lastFunc =
"previous";
150 tOut->AddFriend(chain.get(), lastFunc);
153 TList * userinfo = chain->GetTree()->GetUserInfo();
154 tOut->GetUserInfo()->AddAll(userinfo);
159 tOut = unique_ptr<TTree>(chain->CloneTree(0));
160 tOut->SetTitle(thisFunc);
◆ operator<<()
| std::ostream& Darwin::Tools::operator<< |
( |
std::ostream & |
Stream, |
|
|
const Darwin::Tools::Slice & |
slice |
|
) |
| |
Prints the current slice and the total number of slices.
27 Stream << slice.second <<
'/' << slice.first;
◆ printBranches()
| void Darwin::Tools::printBranches |
( |
vector< fs::path > |
inputs | ) |
|
Adapted from ROOT example
- Parameters
-
92 size_t factor = inputs.size();
94 unique_ptr<TChain> tIn =
GetChain(inputs, location.c_str());
95 TObjArray * branches = tIn->GetListOfBranches();
◆ PrintCloseFriend()
| void Darwin::Tools::PrintCloseFriend |
( |
TList * |
friends, |
|
|
const int |
steering, |
|
|
string |
offset = "" |
|
) |
| |
Retrieve and prints the name and the friends.
- Parameters
-
| friends | obtained from `TTree::GetListOfFriends()` |
| steering | bitflied from `Options::steering()` |
| offset | spaces to show the distance from the original tree |
29 if (friends ==
nullptr)
return;
31 if (steering &
verbose) friends->Print();
34 for (TObject * obj: *friends) {
35 auto buddy =
dynamic_cast<TFriendElement*
>(obj);
36 cout << offset << buddy->GetName()
37 <<
' ' << buddy->GetFile()->GetName()
38 <<
':' << buddy->GetTreeName() << endl;
40 TList * comrades = buddy->GetTree()->GetListOfFriends();
◆ printDarwinSoftwareVersion()
| void Darwin::Tools::printDarwinSoftwareVersion |
( |
| ) |
|
Print the versions of the various pieces of software. Each software appears on a new line. Tought for exception handling in Python code and for Doxygen.
18 for (
auto const& v: MetaInfo::versions)
19 cout << v.first <<
' ' << v.second <<
'\n';
◆ printEntries()
| void Darwin::Tools::printEntries |
( |
vector< fs::path > |
inputs | ) |
|
Get total number of entries in input ROOT file(s) or directory, and prints it directly to the terminal.
- Parameters
-
28 unique_ptr<TChain> tIn =
GetChain(inputs, location.c_str());
29 cout << tIn->GetEntries() << endl;
31 catch (boost::wrapexcept<std::invalid_argument>& e) {
◆ printFriends()
| void Darwin::Tools::printFriends |
( |
vector< fs::path > |
inputs, |
|
|
const int |
steering |
|
) |
| |
Prints the recursive list of friends to the input n-tuple.
- Parameters
-
| inputs | input ROOT files |
| steering | bitfield from `Options::steering()` |
54 unique_ptr<TChain> chain =
GetChain(inputs, location.c_str());
56 TList * friends = chain->GetTree()->GetListOfFriends();
◆ printHist()
| void Darwin::Tools::printHist |
( |
vector< fs::path > |
inputs, |
|
|
const pt::ptree & |
config |
|
) |
| |
Print the content of a 1D histogram in columns.
Convention: index lowEdge upEdge content error
- Parameters
-
| inputs | input ROOT files |
| config | config handled with `Darwin::Tools::options` |
30 auto histname =
config.get<
string>(
"hist").c_str();
31 auto h = GetHist<TH1>({inputs}, histname);
32 if (h->GetDimension() > 1)
33 BOOST_THROW_EXCEPTION(
DE::BadInput(
"The desired histogram is not 1D",
34 TFile(inputs.front().c_str()) ));
35 int N = h->GetNbinsX();
36 for (
int i = 0; i <= N+1; ++i) {
37 double low = h->GetBinLowEdge(i),
38 up = h->GetBinLowEdge(i+1),
39 content = h->GetBinContent(i),
40 error = h->GetBinError(i);
41 if (error == 0 && content == 0)
continue;
45 if (i == 0) cout <<
"underflow";
46 else if (i == N+1) cout <<
"overflow";
51 if (i == 0) cout <<
"-inf";
56 if (i > N) cout <<
"+inf";
60 cout << setw(15) << content
◆ printMetaInfo()
| int Darwin::Tools::printMetaInfo |
( |
vector< fs::path > |
inputs, |
|
|
const pt::ptree & |
config |
|
) |
| |
Print the value(s) corresponding to a given key in the first given input ROOT file.
If no value / subtree is found, the command fails and exits. If multiple entries are found, they are all printed. Only the first subtree is displayed.
The INFO format allows a key to have a value and a child. Since the JSON format does not allow that, we assume here that this case does not happen.
- Parameters
-
| inputs | input ROOT files |
| config | config, with `flags` and `corrections` at least |
41 unique_ptr<TFile> fIn(TFile::Open(inputs.front().c_str(),
"READ"));
43 BOOST_THROW_EXCEPTION(
DE::BadInput(
"Can't open the file.", fIn));
46 auto t = unique_ptr<TTree>(
dynamic_cast<TTree*
>(fIn->Get<TTree>(location.c_str())));
48 BOOST_THROW_EXCEPTION(
DE::BadInput(
"The tree can't be found in this file.", fIn));
51 MetaInfo metainfo(t,
false);
52 auto ptree = metainfo.MkPtree();
53 auto key =
config.get<
string>(
"path");
55 auto value = ptree.get<
string>(key);
57 cout << value << endl;
61 auto child = ptree.get_child_optional(key);
63 for (
auto& el: *child) {
64 string key = el.first,
65 val = el.second.get_value<
string>();
66 if (!key.empty()) cout << key <<
' ';
67 if (!val.empty()) cout << val;
◆ StandardInit()
Standard initialisation for ROOT.
"Now you own all histogram objects and you will need to delete them, for in- stance through the use of std::unique_ptr. You can still set the directory of a histogram by calling SetDirectory() once it has been created."
28 TH1::SetDefaultSumw2();
29 TH1::AddDirectory(kFALSE);
◆ tokenize()
| std::vector<const char *> Darwin::Tools::tokenize |
( |
const char * |
str | ) |
|
|
inline |
Tokenize a C-style string into a vector of C-style string with space as delimiter. It is especially useful in tests where the command is hard-coded.
17 std::cout <<
"\e[1m" << str <<
"\e[0m" << std::endl;
20 char * cmd =
new char[strlen(str)+1];
24 std::vector<const char *> args;
25 for (
char * arg = strtok(cmd,
" ");
27 arg = strtok(NULL,
" "))
28 args.push_back(std::move(arg));
static const char * def
Definition: colours.h:11
static const char * red
Definition: colours.h:5
Handling of exceptions.
Definition: darwin.h:34
static const char * orange
Definition: colours.h:6
static const char * bold
Definition: colours.h:7