DAS  3.0
Das Analysis System
MetaInfo

Description

Generic meta-information for n-tuple (including speficities to Darwin).

Wrapper for TList information typically stored in TTree::GetUserInfo(). The list includes information such as:

  • a list of generic flags, e.g. the R parameter and jet algo (flags)
  • some minimal software version information (git),
  • the list of corrections applied so far (corrections),
  • the successive commands run so far (history)
  • and anything else that is possibly relevant (the format is flexible). The information stored in the list can be converted into a config file to reproduce identical results.

To initialise the meta information in a new TTree, a config with flags is required:

MetaInfo metainfo(tree, config);

To modify the meta information of an existing TTree, only the tree is necessary, but the config may be compared to the existing meta information:

MetaInfo metainfo(tree);
metainfo.Check(config);

This is typically useful for reproducibility purposes, in the case where the config was extracted from another TTree at a more advanced stage.

A typical use case is to determine generic flags for the data processing:

bool isMC = metainfo.Get<bool>("flags", "isMC");
int year = metainfo.Get<bool>("flags", "year");

The metainfo can then be used like any other UserInfo instance. Although one is entirely free to store any sort of information, it is important to keep in mind the minimal structure of the file (see above) and respect it as much as possible. For instance, to indicate an additional correction, the preferred way is the following:

metainfo.Set<string>("corrections", "nameOfMyCorrection", "value");

#include <MetaInfo.h>

+ Inheritance diagram for MetaInfo:
+ Collaboration diagram for MetaInfo:

Classes

struct  IKnowWhatIAmDoing
 

Public Member Functions

 MetaInfo (const IKnowWhatIAmDoing &, bool git_init=true)
 
 MetaInfo (TTree *t, const boost::property_tree::ptree &config, bool git_init=true)
 
 MetaInfo (TTree *t, bool git_init=true)
 
 MetaInfo (TList *l, bool git_init=true)
 
template<typename Ptr , typename ... Args>
 MetaInfo (const Ptr &t, Args... args)
 
 ~MetaInfo ()
 
void Check (const boost::property_tree::ptree &) const
 
template<unsigned h>
unsigned Seed (std::pair< unsigned short, unsigned short > slice={1, 0}) const
 
std::set< Darwin::Physics::VariationAddVars (const std::string &, const std::vector< std::string > &, const int=Darwin::Physics::symmetric, const int=1)
 
std::set< Darwin::Physics::VariationGetVars (const std::string &, const std::string &="") const
 
std::set< Darwin::Physics::VariationGetVars () const
 
 MetaInfo (const IKnowWhatIAmDoing &, bool git_init=true)
 
 MetaInfo (TTree *t, const boost::property_tree::ptree &config, bool git_init=true)
 
 MetaInfo (TTree *t, bool git_init=true)
 
 MetaInfo (TList *l, bool git_init=true)
 
template<typename Ptr , typename ... Args>
 MetaInfo (const Ptr &t, Args... args)
 
 ~MetaInfo ()
 
void Check (const boost::property_tree::ptree &) const
 
template<unsigned h>
unsigned Seed (std::pair< unsigned short, unsigned short > slice={1, 0}) const
 
std::set< Darwin::Physics::VariationAddVars (const std::string &, const std::vector< std::string > &, const int=Darwin::Physics::symmetric, const int=1)
 
std::set< Darwin::Physics::VariationGetVars (const std::string &, const std::string &="") const
 
std::set< Darwin::Physics::VariationGetVars () const
 
- Public Member Functions inherited from UserInfo
template<typename... Args>
TList * List (const char *key, Args... args) const
 
TList * List () const
 
template<class T , typename... Args>
Get (const char *key, Args... args) const
 
template<typename... Args>
bool Find (const char *key, Args... args) const
 
template<class T , typename... Args>
void Set (const char *key, Args... args) const
 
 UserInfo (const char *="UserInfo")
 
 UserInfo (const boost::property_tree::ptree &)
 
 UserInfo (TList *)
 
 UserInfo (TTree *)
 
 UserInfo (TTree *, const boost::property_tree::ptree &)
 
 ~UserInfo ()
 
void Write () const
 
bool Empty () const
 
boost::property_tree::ptree Write (std::ostream &, Format=INFO) const
 
boost::property_tree::ptree Write (const std::filesystem::path &) const
 
boost::property_tree::ptree MkPtree (Format format=INFO) const
 
void ls () const
 
template<typename... Args>
TList * List (const char *key, Args... args) const
 
TList * List () const
 
template<class T , typename... Args>
Get (const char *key, Args... args) const
 
template<typename... Args>
bool Find (const char *key, Args... args) const
 
template<class T , typename... Args>
void Set (const char *key, Args... args) const
 
 UserInfo (const char *="UserInfo")
 
 UserInfo (const boost::property_tree::ptree &)
 
 UserInfo (TList *)
 
 UserInfo (TTree *)
 
 UserInfo (TTree *, const boost::property_tree::ptree &)
 
 ~UserInfo ()
 
void Write () const
 
bool Empty () const
 
boost::property_tree::ptree Write (std::ostream &, Format=INFO) const
 
boost::property_tree::ptree Write (const std::filesystem::path &) const
 
boost::property_tree::ptree MkPtree (Format format=INFO) const
 
void ls () const
 

Static Public Member Functions

static std::string libgit2_version ()
 
static std::string libgit2_version ()
 

Static Public Attributes

static std::map< std::string, std::string > versions
 

Private Member Functions

void GitInit ()
 
void PrintStatus () const
 
bool AllChangesCommitted () const
 
void SetupGit (bool)
 
void SetupVersions ()
 
void UpdateList (const bool) const
 
 MetaInfo (bool, const char *)
 
 MetaInfo (TTree *, const boost::property_tree::ptree &, bool, const char *)
 
 MetaInfo (TTree *, bool, const char *)
 
 MetaInfo (TList *, bool, const char *)
 
void GitInit ()
 
void PrintStatus () const
 
bool AllChangesCommitted () const
 
void SetupGit (bool)
 
void SetupVersions ()
 
void UpdateList (const bool) const
 
 MetaInfo (bool, const char *)
 
 MetaInfo (TTree *, const boost::property_tree::ptree &, bool, const char *)
 
 MetaInfo (TTree *, bool, const char *)
 
 MetaInfo (TList *, bool, const char *)
 

Static Private Member Functions

static int get_one_status (const char *, unsigned int, void *)
 
static int get_one_status (const char *, unsigned int, void *)
 

Private Attributes

git_repository * repo
 
int git_error
 
char sha [16]
 
const std::filesystem::path origin
 

Additional Inherited Members

- Public Types inherited from UserInfo
enum  Format {
  INFO, JSON, XML, INFO,
  JSON, XML
}
 
enum  Format {
  INFO, JSON, XML, INFO,
  JSON, XML
}
 
- Protected Member Functions inherited from UserInfo
boost::property_tree::ptree MkPtree (TList *, Format=INFO) const
 
boost::property_tree::ptree MkPtree (TList *, Format=INFO) const
 

Constructor & Destructor Documentation

◆ MetaInfo() [1/18]

MetaInfo ( bool  git_init,
const char *  origin 
)
private

Used internally to set the git repo location (last parameter).

283  : UserInfo(new TList), repo(nullptr), origin(origin)
284 {
285  int preseed = time(nullptr) % numeric_limits<int>::max();
286  Set<int>("preseed", preseed);
287 
288  SetupGit(git_init);
289  SetupVersions();
290 }

◆ MetaInfo() [2/18]

MetaInfo ( TTree *  t,
const boost::property_tree::ptree &  config,
bool  git_init,
const char *  origin 
)
private

Used internally to set the git repo location (last parameter).

296  : UserInfo(t), repo(nullptr), origin(origin)
297 {
298  if (!Empty())
299  BOOST_THROW_EXCEPTION(invalid_argument("Only a new tree's metainfo may be initialised."));
300 
301  try {
302  // flags
303  const auto& flags = config.get_child("flags");
304  Set<bool>("flags", "isMC", flags.get<bool>("isMC"));
305  Set<int >("flags", "year", flags.get<int >("year"));
306  Set<int >("flags", "R" , flags.get<int >("R" ));
307  const auto& labels = flags.get_child_optional("labels");
308  if (labels) // note: here, we use `boost::optional`,
309  // not `std::optional`, hence we have to test explicitly
310  for (const auto& label: *labels) {
311  // there are subtle differences between INFO, JSON, and XML
312  // - in INFO: the label is stored in the key and the value is empty
313  // - in JSON: the label is stored in the value and the key is empty
314  // - in XML: the label is stored in the value and the key is "item"
315  string key = label.first,
316  value = label.second.get_value<string>();
317 
318  if (key.empty() || key == "item")
319  Set<string>("flags", "labels", value);
320  else if (value.empty())
321  Set<string>("flags", "labels", key);
322  else
323  BOOST_THROW_EXCEPTION(invalid_argument("Empty labels are not allowed"));
324  }
325 
326  if (config.count("history"))
327  Set<string>("history", config.get<string>("history"));
328 
329  if (config.count("preseed"))
330  Set<int>("preseed", config.get<int>("preseed"));
331  else {
332  int preseed = time(nullptr) % numeric_limits<int>::max();
333  Set<int>("preseed", preseed);
334  }
335 
336  SetupGit(git_init);
337  // Set git information coming from the config
338  if (!git_init) {
339  Set<string>("git", "commit", config.get<string>("git.commit"));
340  Set<bool>("git", "reproducible", config.get<bool>("git.reproducible"));
341  }
342 
343  SetupVersions();
344  }
345  catch (const pt::ptree_error& e) {
346  BOOST_THROW_EXCEPTION(e);
347  }
348 }

◆ MetaInfo() [3/18]

MetaInfo ( TTree *  t,
bool  git_init,
const char *  origin 
)
private

Used internally to set the git repo location (last parameter).

352  : UserInfo(t), repo(nullptr), origin(origin)
353 {
354  if (!git_init) return;
355  GitInit();
356  UpdateList(false);
357 }

◆ MetaInfo() [4/18]

MetaInfo ( TList *  l,
bool  git_init,
const char *  origin 
)
private

Used internally to set the git repo location (last parameter).

361  : UserInfo(l), repo(nullptr), origin(origin)
362 {
363  if (!git_init) return;
364  GitInit();
365  UpdateList(true);
366 }

◆ MetaInfo() [5/18]

MetaInfo ( const IKnowWhatIAmDoing ,
bool  git_init = true 
)
inline

Constsructor for first call ever. This creates a minimal MetaInfo.

This is a low-level constructor and the produced MetaInfo lacks some information:

  • The preseed is chosen randomly.
  • The caller is responsible for populating "flags".
  • No command history is recorded.
  • git.complete is set to false. Do not use this constructor.
154  : MetaInfo(git_init, DARWIN_GIT_REPO)
155  {}

◆ MetaInfo() [6/18]

MetaInfo ( TTree *  t,
const boost::property_tree::ptree &  config,
bool  git_init = true 
)
inline

Constsructor for first call ever, where the second parameter should be extracted from the config file or from the command line.

The preseed is taken from the config file or generated on the fly in a non-reproducible way. Use getMetaInfo for see how to force the seed to a value from the config file.

Parameters
t`TTree` whose `UserInfo` will be populated
configinput config (must include flags)
168  : MetaInfo(t, config, git_init, DARWIN_GIT_REPO)
169  {}

◆ MetaInfo() [7/18]

MetaInfo ( TTree *  t,
bool  git_init = true 
)
inline

Constsructor for call of existing n-tuple. By default, the git.complete flag will be reset to false. It should be set to true after the event loop in the executable.

Parameters
t`TTree` whose `UserInfo` will be modified
git_initflag to init git repo
178  : MetaInfo(t, git_init, DARWIN_GIT_REPO)
179  {}

◆ MetaInfo() [8/18]

MetaInfo ( TList *  l,
bool  git_init = true 
)
inline

Constsructor for direct call to a list (typically from a projection). By default, the git.complete will be kept as it is.

Parameters
l`TList` that will be modified
git_initflag to init git repo
187  : MetaInfo(l, git_init, DARWIN_GIT_REPO)
188  {}

◆ MetaInfo() [9/18]

MetaInfo ( const Ptr &  t,
Args...  args 
)
inline

Generic constsructor for smart pointers.

194  : MetaInfo(&*t, args...) { }

◆ ~MetaInfo() [1/2]

~MetaInfo ( )

Destructor (releases memory & shuts down Git).

369 {
370  if (repo == nullptr) return;
371  git_repository_free(repo);
372  git_libgit2_shutdown();
373 }

◆ MetaInfo() [10/18]

MetaInfo ( bool  ,
const char *   
)
private

Used internally to set the git repo location (last parameter).

◆ MetaInfo() [11/18]

MetaInfo ( TTree *  ,
const boost::property_tree::ptree &  ,
bool  ,
const char *   
)
private

Used internally to set the git repo location (last parameter).

◆ MetaInfo() [12/18]

MetaInfo ( TTree *  ,
bool  ,
const char *   
)
private

Used internally to set the git repo location (last parameter).

◆ MetaInfo() [13/18]

MetaInfo ( TList *  ,
bool  ,
const char *   
)
private

Used internally to set the git repo location (last parameter).

◆ MetaInfo() [14/18]

MetaInfo ( const IKnowWhatIAmDoing ,
bool  git_init = true 
)
inline

Constsructor for first call ever. This creates a minimal MetaInfo.

This is a low-level constructor and the produced MetaInfo lacks some information:

  • The preseed is chosen randomly.
  • The caller is responsible for populating "flags".
  • No command history is recorded.
  • git.complete is set to false. Do not use this constructor.
154  : MetaInfo(git_init, DARWIN_GIT_REPO)
155  {}

◆ MetaInfo() [15/18]

MetaInfo ( TTree *  t,
const boost::property_tree::ptree &  config,
bool  git_init = true 
)
inline

Constsructor for first call ever, where the second parameter should be extracted from the config file or from the command line.

The preseed is taken from the config file or generated on the fly in a non-reproducible way. Use getMetaInfo for see how to force the seed to a value from the config file.

Parameters
t`TTree` whose `UserInfo` will be populated
configinput config (must include flags)
168  : MetaInfo(t, config, git_init, DARWIN_GIT_REPO)
169  {}

◆ MetaInfo() [16/18]

MetaInfo ( TTree *  t,
bool  git_init = true 
)
inline

Constsructor for call of existing n-tuple. By default, the git.complete flag will be reset to false. It should be set to true after the event loop in the executable.

Parameters
t`TTree` whose `UserInfo` will be modified
git_initflag to init git repo
178  : MetaInfo(t, git_init, DARWIN_GIT_REPO)
179  {}

◆ MetaInfo() [17/18]

MetaInfo ( TList *  l,
bool  git_init = true 
)
inline

Constsructor for direct call to a list (typically from a projection). By default, the git.complete will be kept as it is.

Parameters
l`TList` that will be modified
git_initflag to init git repo
187  : MetaInfo(l, git_init, DARWIN_GIT_REPO)
188  {}

◆ MetaInfo() [18/18]

MetaInfo ( const Ptr &  t,
Args...  args 
)
inline

Generic constsructor for smart pointers.

194  : MetaInfo(&*t, args...) { }

◆ ~MetaInfo() [2/2]

~MetaInfo ( )

Destructor (releases memory & shuts down Git).

Member Function Documentation

◆ AddVars() [1/2]

std::set< Darwin::Physics::Variation > AddVars ( const std::string &  group,
const std::vector< std::string > &  names,
const int  vartype = Darwin::Physics::symmetric,
const int  n = 1 
)

Define a family of uncertainties.

This function offers a unique proxy to define a large number of similar uncertainties, including various sources, correlation bits, up and down variations, and replicas. For instance, for various JES uncertainties:

auto variations = metainfo.AddVars(RecJet::ScaleVar, {"FlavourQCD", /* ... *&zwj;/});

or for a hundred replicas (e.g. when the seed of a generator is changed):

auto variations = metainfo.AddVars(GenEvent::WeightVar, {"Replica"}, 100, replicas);

or for the impact of a binned correction caused by physics objects on the whole event (where 20 is the number of bins):

auto variations = metainfo.AddVars(RecEvent::WeightVar, {"Prefiring"}, 20, symmetric | replicas);

or for to express partial correlations:

auto variations = metainfo.AddVars(RecJet::WeightVar, {"bSFstat"}, 3, symmetric | bits);
Parameters
groupgroup
namesnames
vartypevariation type
nnumber of members (replicas or correlation bit)
453 {
454  using enum Darwin::Physics::VarType;
455  set<DP::Variation> variations;
456 
457  size_t index = Find("variations", group.c_str()) ?
458  List("variations", group.c_str())->GetSize() : 0;
459 
460  if (n < 1)
461  BOOST_THROW_EXCEPTION(
462  invalid_argument("The number of members must be larger than 0."));
463 
464  if (vartype == single && n != 1)
465  BOOST_THROW_EXCEPTION(
466  invalid_argument("Single variations must have exactly one member."));
467 
468  const vector suffixes = (vartype & symmetric) ? vector{"Up"s, "Down"s}
469  : vector{""s};
470 
471  for (auto name: names) {
472 
473  // add to metainfo
474  for (const auto& suffix: suffixes) {
475  string fullname = name + suffix;
476  Set<int>("variations", group.c_str(), fullname.c_str(), n);
477  }
478 
479  // add members (up and down variations should follow each other)
480  for (int i = 1; i <= n; ++i)
481  for (const auto& suffix: suffixes)
482  variations.emplace(group, name + suffix, ++index, i);
483  }
484 
485  return variations;
486 }

◆ AddVars() [2/2]

std::set<Darwin::Physics::Variation> AddVars ( const std::string &  ,
const std::vector< std::string > &  ,
const int  = Darwin::Physics::symmetric,
const int  = 1 
)

Define a family of uncertainties.

This function offers a unique proxy to define a large number of similar uncertainties, including various sources, correlation bits, up and down variations, and replicas. For instance, for various JES uncertainties:

auto variations = metainfo.AddVars(RecJet::ScaleVar, {"FlavourQCD", /* ... *&zwj;/});

or for a hundred replicas (e.g. when the seed of a generator is changed):

auto variations = metainfo.AddVars(GenEvent::WeightVar, {"Replica"}, 100, replicas);

or for the impact of a binned correction caused by physics objects on the whole event (where 20 is the number of bins):

auto variations = metainfo.AddVars(RecEvent::WeightVar, {"Prefiring"}, 20, symmetric | replicas);

or for to express partial correlations:

auto variations = metainfo.AddVars(RecJet::WeightVar, {"bSFstat"}, 3, symmetric | bits);

◆ AllChangesCommitted() [1/2]

bool AllChangesCommitted ( ) const
private

Function to check possibly uncommitted changes per file. It calls internally MetaInfo::get_one_status with a foreach loop.

Returns
true if all changes have been committed
174 {
175  // https://libgit2.org/libgit2/#HEAD/group/status/git_status_foreach
176  return git_status_foreach(repo, get_one_status, repo) == 0;
177 }

◆ AllChangesCommitted() [2/2]

bool AllChangesCommitted ( ) const
private

Function to check possibly uncommitted changes per file. It calls internally MetaInfo::get_one_status with a foreach loop.

Returns
true if all changes have been committed

◆ Check() [1/2]

void Check ( const boost::property_tree::ptree &  config) const

Compare the meta information with the config given in argument. Either warnings or errors are thrown according to the severity of the inconsistencies. It also completes the records of successive commands.

376 {
377  try {
378  const auto& flags = config.get_child_optional("flags");
379  if (flags) {
380  if (Get<bool>("flags", "isMC") != flags->get<bool>("isMC") ||
381  Get<int >("flags", "year") != flags->get<int >("year") ||
382  Get<int >("flags", "R" ) != flags->get<int >("R" ))
383  BOOST_THROW_EXCEPTION(invalid_argument("Inconsistent flags between metainfo and config"));
384 
385  const auto& labels_in_config = flags->get_child_optional("labels");
386  if (labels_in_config) // TODO?
387  for (const auto& label: *labels_in_config) {
388  string key = label.first,
389  value = label.second.get_value<string>();
390 
391  if (key.empty() || key == "item") {
392  if (Find("flags", "labels", value)) continue;
393  cerr << orange << "Warning: Adding label '" + value + "' in config, which was not found in input metainfo.\n" << def;
394  Set<string>("flags", "labels", value);
395  }
396  else if (value.empty()) {
397  if (Find("flags", "labels", key)) continue;
398  cerr << orange << "Warning: Adding label '" + key + "' in config, which was not found in input metainfo.\n" << def;
399  Set<string>("flags", "labels", key);
400  }
401  }
402  if (Find("flags", "labels")) {
403  const auto& labels_in_metainfo = MkPtree(List("flags", "labels"));
404  for (const auto& label: labels_in_metainfo) {
405  string value = label.second.get_value<string>();
406  if (labels_in_config->count(value)) continue;
407  bool found = false;
408  if (labels_in_config)
409  for (const auto& label2: *labels_in_config) {
410  string value2 = label2.second.get_value<string>();
411  found = found || (value2 == value);
412  }
413  if (!found)
414  cerr << orange << "Warning: Label '" + value + "' in metainfo was not found in config.\n" << def;
415  }
416  }
417  }
418 
419  // in case the config comes from `getMetaInfo`, this checks if anything has changed meanwhile
420  const auto& git = config.get_child_optional("git");
421  if (git) {
422  auto commit = git->get<string>("commit");
423  if (origin != Get<string>("git", "repo"))
424  cerr << orange << "Warning: inconsistent repositories between metainfo and config.\n" << def;
425  else if (origin == Get<string>("git", "repo") && sha != Get<string>("git", "commit"))
426  cerr << orange << "Warning: inconsistent commits between metainfo and config.\n" << def;
427  else if (!git->get<bool>("reproducible") || !git->get<bool>("complete"))
428  cerr << orange << "Warning: the input config was generated from an irreproducible or incomplete file.\n" << def;
429  else if (AllChangesCommitted() && Get<bool>("git", "reproducible") && Get<bool>("git", "complete"))
430  cerr << green << "Expecting to reproduce the same result as the one used to generate the input config!\n" << def;
431  }
432 
433  if (config.count("history"))
434  Set<string>("history", config.get<string>("history"));
435 
436  if (config.count("preseed")) {
437  auto c = config.get<int>("preseed"),
438  s = Get<int>("preseed");
439  if (c != s)
440  cerr << orange << "The preseed in the sample (" << s << ") differs from the preseed in the config (" << c << "). The value from the config will be " << bold << "ignored" << normal << ".\n" << def;
441  }
442  }
443  catch (const pt::ptree_error& e) {
444  BOOST_THROW_EXCEPTION(e);
445  }
446 }

◆ Check() [2/2]

void Check ( const boost::property_tree::ptree &  ) const

Compare the meta information with the config given in argument. Either warnings or errors are thrown according to the severity of the inconsistencies. It also completes the records of successive commands.

◆ get_one_status() [1/2]

int get_one_status ( const char *  p,
unsigned int  ,
void *  data 
)
staticprivate

Function to check if a file is ignored.

Returns
EXIT_SUCCESS or EXIT_FAILURE
Parameters
ppath to file
datapointer to `git_repository`
40 {
41  auto repo = static_cast<git_repository *>(data);
42  int ignore = 0;
43  // https://libgit2.org/libgit2/#HEAD/group/ignore/git_ignore_path_is_ignored
44  int git_error = git_ignore_path_is_ignored(&ignore, repo, p);
45  if (git_error != 0)
46  BOOST_THROW_EXCEPTION(fs::filesystem_error("File status could not be determined", p, error_code{git_error, git_error_category}));
47  return (ignore == 1) ? EXIT_SUCCESS : EXIT_FAILURE;
48 }

◆ get_one_status() [2/2]

static int get_one_status ( const char *  ,
unsigned int  ,
void *   
)
staticprivate

Function to check if a file is ignored.

Returns
EXIT_SUCCESS or EXIT_FAILURE

◆ GetVars() [1/4]

std::set<Darwin::Physics::Variation> GetVars ( ) const

Retrieve all variations, including the nominal one.

◆ GetVars() [2/4]

std::set< Darwin::Physics::Variation > GetVars ( ) const

Retrieve all variations, including the nominal one.

521 {
522  set<DP::Variation> variations{DP::nominal};
523 
524  const TList * groupList = List("variations");
525  for (const TObject * groupObj: *groupList) {
526  const string group = groupObj->GetName();
527  variations.merge(GetVars(group));
528  }
529 
530  return variations;
531 }

◆ GetVars() [3/4]

std::set<Darwin::Physics::Variation> GetVars ( const std::string &  ,
const std::string &  = "" 
) const

Retrieve a series of uncertainties.

◆ GetVars() [4/4]

std::set< Darwin::Physics::Variation > GetVars ( const std::string &  group,
const std::string &  expression = "" 
) const

Retrieve a series of uncertainties.

Parameters
groupgroup
expressionregex search
490 {
491  set<DP::Variation> variations;
492 
493  if (!Find("variations", group.c_str()))
494  BOOST_THROW_EXCEPTION( invalid_argument("No variation found for "s + group) );
495 
496  size_t index = 0;
497  for (const TObject * obj: *List("variations", group.c_str())) {
498  const char * name = obj->GetName();
499  auto n = Get<int>("variations", group.c_str(), name);
500  if (n < 1)
501  BOOST_THROW_EXCEPTION(
502  invalid_argument("The number of members must be larger than 0."));
503 
504  try {
505  regex re(expression);
506  if (regex_search(name, re))
507  for (int i = 1; i <= n; ++i)
508  variations.emplace(group, name, ++index, i);
509  else
510  index += n;
511  }
512  catch (const regex_error& e) {
513  BOOST_THROW_EXCEPTION(e);
514  }
515  }
516 
517  return variations;
518 }

◆ GitInit() [1/2]

void GitInit ( )
private

Inits and opens git repo, sets sha to the value at running time.

51 {
52  // https://libgit2.org/libgit2/#HEAD/group/libgit2/git_libgit2_init
53  git_libgit2_init();
54 
55  if (origin.empty())
56  BOOST_THROW_EXCEPTION(fs::filesystem_error("Empty path to Git repository", origin, make_error_code(errc::invalid_argument)));
57 
58  // open repo
59  if (!(fs::exists(origin) && fs::is_directory(origin)))
60  BOOST_THROW_EXCEPTION(fs::filesystem_error("Git repository cannot be found", origin, make_error_code(errc::not_a_directory)));
61 
62  // https://libgit2.org/libgit2/#HEAD/group/repository/git_repository_open
63  git_error = git_repository_open(&repo, origin.c_str());
64  if (git_error != 0)
65  BOOST_THROW_EXCEPTION(fs::filesystem_error("Invalid git repository", origin, error_code{git_error, git_error_category}));
66 
67  // get HEAD
68  git_object * head_commit = nullptr;
69  // https://libgit2.org/libgit2/#HEAD/group/revparse/git_revparse_single
70  git_error = git_revparse_single(&head_commit, repo, "HEAD^{commit}");
71  if (git_error != 0)
72  BOOST_THROW_EXCEPTION(system_error(git_error, git_error_category, "Head commit could not be determined "
73  "(check if $DARWIN_GIT_REPO has been defined and points to the root of the git repository)"));
74  auto commit = reinterpret_cast<git_commit *>(head_commit);
75 
76  // get SHA-1
77  const git_oid * id = git_commit_id(commit);
78  // https://libgit2.org/libgit2/#HEAD/group/oid/git_oid_tostr
79  git_oid_tostr(sha, 16, id);
80 
81  // display a few properties
82  // https://libgit2.org/libgit2/#HEAD/group/commit/git_commit_author
83  const git_signature * author = git_commit_author(commit);
84  // https://libgit2.org/libgit2/#HEAD/group/commit/git_commit_message
85  cerr << underline << "latest commit" << def << ": " << git_commit_message(commit)
86  << " by " << author->name << " (" << sha << ")\n";
87 
88  // https://libgit2.org/libgit2/#HEAD/group/commit/git_commit_free
89  git_commit_free(commit);
90 }

◆ GitInit() [2/2]

void GitInit ( )
private

Inits and opens git repo, sets sha to the value at running time.

◆ libgit2_version() [1/2]

std::string libgit2_version ( )
static
Returns
string with libgit2 version.
264 {
265  int major, minor, rev;
266  // https://libgit2.org/libgit2/#HEAD/group/libgit2/git_libgit2_version
267  int git_error = git_libgit2_version(&major, &minor, &rev);
268  if (git_error != 0)
269  BOOST_THROW_EXCEPTION(runtime_error("Unable to get libgit2 version"));
270  return Form("%d.%d.%d", major, minor, rev);
271 }

◆ libgit2_version() [2/2]

static std::string libgit2_version ( )
static
Returns
string with libgit2 version.

◆ PrintStatus() [1/2]

void PrintStatus ( ) const
private

Mimicks git status.

Adapted from this example. See also the documentation.

◆ PrintStatus() [2/2]

void PrintStatus ( ) const
private

Mimicks git status.

Adapted from this example. See also the documentation.

93 {
94  git_status_list * status = nullptr;
95  // https://libgit2.org/libgit2/#HEAD/group/status/git_status_list_new
96  git_error = git_status_list_new(&status, repo, nullptr);
97  if (git_error != 0)
98  BOOST_THROW_EXCEPTION(system_error(git_error, git_error_category, "File status could not be determined"));
99  // https://libgit2.org/libgit2/#HEAD/group/status/git_status_list_entrycount
100  const size_t maxi = git_status_list_entrycount(status);
101 
102  for (size_t i = 0; i < maxi; ++i) {
103  const git_status_entry * s = git_status_byindex(status, i);
104 
105  if (s->status == GIT_STATUS_CURRENT) continue;
106  if (s->status & GIT_STATUS_IGNORED) continue;
107 
108  char istatus = ' ', // index status
109  wstatus = ' '; // worktree status
110  const char * extra = "", // for submodule info
111  * a = nullptr,
112  * b = nullptr,
113  * c = nullptr;
114 
115  if (s->status & GIT_STATUS_INDEX_NEW ) istatus = 'A';
116  else if (s->status & GIT_STATUS_INDEX_MODIFIED ) istatus = 'M';
117  else if (s->status & GIT_STATUS_INDEX_DELETED ) istatus = 'D';
118  else if (s->status & GIT_STATUS_INDEX_RENAMED ) istatus = 'R';
119  else if (s->status & GIT_STATUS_INDEX_TYPECHANGE) istatus = 'T';
120 
121  if (s->status & GIT_STATUS_WT_NEW) {
122  if (istatus == ' ') { istatus = '?'; }
123  wstatus = '?';
124  }
125  else if (s->status & GIT_STATUS_WT_MODIFIED ) wstatus = 'M';
126  else if (s->status & GIT_STATUS_WT_DELETED ) wstatus = 'D';
127  else if (s->status & GIT_STATUS_WT_RENAMED ) wstatus = 'R';
128  else if (s->status & GIT_STATUS_WT_TYPECHANGE) wstatus = 'T';
129  if (istatus == '?' && wstatus == '?') continue; // TODO?
130 
131  // A commit in a tree is how submodules are stored, so let's go take a look at its status.
132  if (s->index_to_workdir &&
133  s->index_to_workdir->new_file.mode == GIT_FILEMODE_COMMIT) {
134  unsigned int smstatus = 0;
135 
136  // https://libgit2.org/libgit2/#HEAD/group/submodule/git_submodule_status
137  if (!git_submodule_status(&smstatus, repo, s->index_to_workdir->new_file.path,
138  GIT_SUBMODULE_IGNORE_UNSPECIFIED)) {
139  if (smstatus & GIT_SUBMODULE_STATUS_WD_MODIFIED ) extra = " (new commits)";
140  else if (smstatus & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) extra = " (modified content)";
141  else if (smstatus & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED ) extra = " (modified content)";
142  else if (smstatus & GIT_SUBMODULE_STATUS_WD_UNTRACKED ) extra = " (untracked content)";
143  }
144  }
145 
146  // Now that we have all the information, format the output.
147  if (s->head_to_index) {
148  a = s->head_to_index->old_file.path;
149  b = s->head_to_index->new_file.path;
150  }
151  if (s->index_to_workdir) {
152  if (!a) a = s->index_to_workdir->old_file.path;
153  if (!b) b = s->index_to_workdir->old_file.path;
154  c = s->index_to_workdir->new_file.path;
155  }
156 
157  cerr << istatus << wstatus << ' ' << a;
158  if (istatus == 'R') cerr << ' ' << b;
159  if (wstatus == 'R') cerr << ' ' << c;
160  cerr << extra << '\n';
161  }
162 
163  for (size_t i = 0; i < maxi; ++i) {
164  // https://libgit2.org/libgit2/#HEAD/group/status/git_status_byindex
165  const git_status_entry * s = git_status_byindex(status, i);
166  if (s->status != GIT_STATUS_WT_NEW) continue;
167  cerr << "?? " << s->index_to_workdir->old_file.path << '\n';
168  }
169  // https://libgit2.org/libgit2/#HEAD/group/status/git_status_list_free
170  git_status_list_free(status);
171 }

◆ Seed() [1/2]

unsigned Seed ( std::pair< unsigned short, unsigned short >  slice = {1,0}) const
inline

Generate the seed in a reproducible way:

\[ s = h + (k+1) \times b \]

where

  • $h$ is hard-coded in the program and should be different for every call of the functor,
  • $k$ corresponds to the (incremented) slice index,
  • and $b$ should be different for every sample (a.k.a. preseed).
Parameters
slicevariable part
223  {1,0}
224  ) const
225  {
226  unsigned b = Get<int>("preseed");
227  unsigned k = slice.second;
228  return h + (k+1) * b;
229  }

◆ Seed() [2/2]

unsigned Seed ( std::pair< unsigned short, unsigned short >  slice = {1,0}) const
inline

Generate the seed in a reproducible way:

\[ s = h + (k+1) \times b \]

where

  • $h$ is hard-coded in the program and should be different for every call of the functor,
  • $k$ corresponds to the (incremented) slice index,
  • and $b$ should be different for every sample (a.k.a. preseed).
Parameters
slicevariable part
223  {1,0}
224  ) const
225  {
226  unsigned b = Get<int>("preseed");
227  unsigned k = slice.second;
228  return h + (k+1) * b;
229  }

◆ SetupGit() [1/2]

void SetupGit ( bool  git_init)
private

Fills in git information in the MetaInfo.

180 {
181  bool all_changes_committed = false;
182  if (git_init) {
183  GitInit();
184  all_changes_committed = AllChangesCommitted();
185  if (!all_changes_committed) {
186  cerr << orange << "Warning: uncommited changes.\n";
187  PrintStatus();
188  cerr << def;
189  }
190  // NOTE Only set if git_init is true
191  Set<string>("git", "commit", string(sha));
192  }
193  Set<fs::path>("git", "repo" , origin );
194  Set<bool> ("git", "reproducible", all_changes_committed);
195  Set<bool> ("git", "complete" , false );
196 }

◆ SetupGit() [2/2]

void SetupGit ( bool  )
private

Fills in git information in the MetaInfo.

◆ SetupVersions() [1/2]

void SetupVersions ( )
private

Fills in software version information in the MetaInfo.

◆ SetupVersions() [2/2]

void SetupVersions ( )
private

Fills in software version information in the MetaInfo.

199 {
200  for (auto const& version: versions) {
201  string const& soft = version.first,
202  vers = version.second;
203  Set<string>("software", soft.c_str(), vers);
204  }
205 }

◆ UpdateList() [1/2]

void UpdateList ( const bool  assumeComplete) const
private

Update list with present git information. The flags and git blocks are expected to be found, otherwise it crashes smoothly. Then it updates the Git information.

Parameters
assumeCompleteshould assume completeness (typically `false` for event loops)
208 {
209  if (Empty())
210  BOOST_THROW_EXCEPTION(invalid_argument("No metainfo in input to update."));
211 
212  if (!Find("flags"))
213  BOOST_THROW_EXCEPTION(invalid_argument("Missing flags in input."));
214  if (!Find("git"))
215  BOOST_THROW_EXCEPTION(invalid_argument("Missing git information in input."));
216 
217  /****** git business ******/
218 
219  if (origin != Get<fs::path>("git", "repo")) {
220  cerr << orange << "Warning: inconsistent repositories between input and output.\n" << def;
221  Set<fs::path>("git", "repo", origin);
222  }
223  else if (sha != Get<string>("git", "commit")) {
224  cerr << orange << "Warning: inconsistent commits between input and output.\n" << def;
225  Set<string>("git", "commit", string(sha));
226  }
227 
228  bool all_changes_committed = AllChangesCommitted();
229  if (!all_changes_committed) {
230  cerr << orange << "Warning: uncommited changes.\n";
231  PrintStatus();
232  cerr << def;
233  }
234  auto reproducible = Get<bool>("git", "reproducible");
235  if (!reproducible)
236  cerr << orange << "Warning: input tree not reproducible.\n" << def;
237  Set<bool>("git", "reproducible", all_changes_committed && reproducible);
238 
239  auto complete = Get<bool>("git", "complete");
240  if (!complete)
241  cerr << orange << "Warning: input tree not complete.\n" << def;
242  Set<bool>("git", "complete", assumeComplete && complete);
243 
244  /****** software business ******/
245 
246  for (auto const& version: versions) {
247  string const& soft = version.first,
248  vers1 = version.second;
249  if (!Find("software", soft.c_str())) continue;
250  auto vers2 = Get<string>("software", soft.c_str());
251 
252  if (vers1 == vers2) continue;
253  cerr << orange << "Warning: inconsistent " << soft << " versions ("
254  << vers1 << " vs " << vers2 << ")\n" << def;
255  }
256 
257  /****** seeding business ******/
258 
259  if (!Find("preseed"))
260  BOOST_THROW_EXCEPTION(invalid_argument("No preseed could be found."));
261 }

◆ UpdateList() [2/2]

void UpdateList ( const bool  ) const
private

Update list with present git information. The flags and git blocks are expected to be found, otherwise it crashes smoothly. Then it updates the Git information.

Member Data Documentation

◆ git_error

int git_error
mutableprivate

C-style error code from Git operations (see source code)

◆ origin

const std::filesystem::path origin
private

path to local repo determined at compilation time

◆ repo

git_repository * repo
private

pointer to local Git repo

◆ sha

char sha
private

commit SHA at running time

◆ versions

static std::map< std::string, std::string > versions
static
Initial value:
= {
{"Darwin" , DARWIN_VERSION},
{"gpp" , Form("%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)},
{"Cpp" , Form("C++%ld", __cplusplus/100-2000)},
{"ROOT" , gROOT->GetVersion()},
{"Boost" , BOOST_LIB_VERSION},
{"libgit2", libgit2_version()}
}

software version


The documentation for this class was generated from the following files:
DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.name
name
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:48
Darwin::Physics::replicas
@ replicas
Definition: Variation.h:16
Ntupliser_cfg.cerr
cerr
Definition: Ntupliser_cfg.py:93
Darwin::Tools::UserInfo::List
TList * List() const
Access directly to main list.
Definition: UserInfo.h:201
Darwin::Tools::UserInfo::l
TList * l
main list (typically from TTree::GetUserInfo())
Definition: UserInfo.h:64
Darwin::Tools::MetaInfo::SetupVersions
void SetupVersions()
Fills in software version information in the MetaInfo.
Definition: MetaInfo.cc:198
Ntupliser_cfg.labels
dictionary labels
Definition: Ntupliser_cfg.py:31
Darwin::Tools::MetaInfo::git_error
int git_error
Definition: MetaInfo.h:71
Step::def
static const char * def
Definition: Step.h:36
Ntupliser_cfg.args
args
Definition: Ntupliser_cfg.py:11
Darwin::Exceptions::git_error_category
git_error_category
Error category for libgit2.
underline
static const char * underline
Definition: colours.h:10
Ntupliser_cfg.year
int year
Definition: Ntupliser_cfg.py:63
Darwin::Physics::bits
@ bits
Definition: Variation.h:17
Ntupliser_cfg.p
p
Definition: Ntupliser_cfg.py:362
Darwin::Tools::MetaInfo::GetVars
std::set< Darwin::Physics::Variation > GetVars() const
Retrieve all variations, including the nominal one.
Definition: MetaInfo.cc:520
jercExample.key
string key
Definition: jercExample.py:109
Darwin::Tools::MetaInfo::GitInit
void GitInit()
Inits and opens git repo, sets sha to the value at running time.
Definition: MetaInfo.cc:50
btvExample_106X.data
data
Definition: btvExample_106X.py:10
Darwin::Physics::VarType
VarType
Definition: Variation.h:13
DARWIN_GIT_REPO
#define DARWIN_GIT_REPO
Definition: main.cc:21
Darwin::Tools::MetaInfo::AllChangesCommitted
bool AllChangesCommitted() const
Definition: MetaInfo.cc:173
DAS::Uncertainties::nominal
const Variation nominal
Definition: Variation.h:55
orange
static const char * orange
Definition: colours.h:6
Darwin::Tools::UserInfo::Find
bool Find(TList *mother, const char *key) const
Recursive finder.
Definition: UserInfo.h:107
DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.version
version
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:49
normal
static const char * normal
Definition: colours.h:8
Darwin::Physics::single
@ single
Definition: Variation.h:14
Darwin::Tools::MetaInfo::PrintStatus
void PrintStatus() const
Definition: MetaInfo.cc:92
Step::green
static const char * green
Definition: Step.h:33
DARWIN_VERSION
#define DARWIN_VERSION
Definition: version.h:1
Darwin::Tools::UserInfo::MkPtree
boost::property_tree::ptree MkPtree(TList *, Format=INFO) const
Definition: UserInfo.cc:52
Darwin::Tools::MetaInfo::MetaInfo
MetaInfo(bool, const char *)
Used internally to set the git repo location (last parameter).
Definition: MetaInfo.cc:282
Darwin::Tools::MetaInfo::repo
git_repository * repo
pointer to local Git repo
Definition: MetaInfo.h:70
Ntupliser_cfg.isMC
string isMC
Definition: Ntupliser_cfg.py:59
Darwin::Tools::MetaInfo::UpdateList
void UpdateList(const bool) const
Definition: MetaInfo.cc:207
Darwin::Tools::MetaInfo::origin
const std::filesystem::path origin
path to local repo determined at compilation time
Definition: MetaInfo.h:74
Darwin::Tools::UserInfo::Empty
bool Empty() const
Check if list is empty.
Definition: UserInfo.cc:156
Darwin::Tools::MetaInfo::get_one_status
static int get_one_status(const char *, unsigned int, void *)
Definition: MetaInfo.cc:39
Darwin::Tools::MetaInfo::sha
char sha[16]
commit SHA at running time
Definition: MetaInfo.h:73
Darwin::Tools::MetaInfo::SetupGit
void SetupGit(bool)
Fills in git information in the MetaInfo.
Definition: MetaInfo.cc:179
Darwin::Tools::MetaInfo::libgit2_version
static std::string libgit2_version()
Definition: MetaInfo.cc:263
Darwin::Tools::MetaInfo::versions
static std::map< std::string, std::string > versions
software version
Definition: MetaInfo.h:210
Darwin::Tools::UserInfo::UserInfo
UserInfo(const char *="UserInfo")
Constructor (starting from scratch)
Definition: UserInfo.cc:161
Ntupliser_cfg.flags
dictionary flags
Definition: Ntupliser_cfg.py:27
Darwin::Physics::symmetric
@ symmetric
Definition: Variation.h:15
Darwin::Tools::config
@ config
activate -c option to provide config file
Definition: Options.h:25
Step::bold
static const char * bold
Definition: Step.h:35