Crombie Tools
Selection.h
Go to the documentation of this file.
1 #ifndef CROMBIE_CUTCONFIG_H
2 #define CROMBIE_CUTCONFIG_H
3 
4 #include <fstream>
5 #include <map>
6 #include <string>
7 #include <regex>
8 #include <iterator>
9 
10 #include "crombie/Debug.h"
11 #include "crombie/Misc.h"
12 #include "crombie/Parse.h"
13 
14 namespace crombie {
15  namespace Selection {
16 
17  class Selection {
18  public:
19  Selection(const std::string& cut, const std::string& mc, const std::string& data, const bool blinded)
20  : cut{cut}, data{data}, mc{mc}, blinded{blinded} {
21  Debug::Debug(__PRETTY_FUNCTION__, "Selection:", cut, "---", mc, "---", data);
22  }
23 
24  const std::string cut; ///< The cut that plots must pass
25  const std::string data; ///< The data weight for plots
26  const std::string mc; ///< The mc weight for plots
27  const bool blinded; ///< Whether data should be blinded or not
28  };
29 
30 
32 
33 
35  public:
36  SelectionConfig(const std::string& mchistname)
37  : mchistname{mchistname} {}
38 
39  const std::string mchistname; ///< The mchist to normalize the weight to
40 
42 
43  friend std::istream& operator>>(std::istream& is, SelectionConfig& config);
44  };
45 
46  std::istream& operator>>(std::istream& is, SelectionConfig& config);
47 
48  /**
49  Returns the a cut with a variable taken out.
50  The function only removes expressions where the variable name is to the left of an operator.
51  */
52  std::string nminus1(const std::string& var, const std::string& cut);
53 
54  /// Reads a configuration file that maps regions to selections
55  /// Reads a configuration file for file info
56  SelectionConfig read(const std::string& mchistname, const std::string& config) {
57  SelectionConfig output {mchistname};
58  std::ifstream input {config};
59  input >> output;
60  return output;
61  }
62 
63 
64  // IMPLEMENTATIONS BELOW HERE //
65 
66 
67  std::string nminus1(const std::string& var, const std::string& cut) {
68  std::regex expr{std::string("\\b") + var + "\\b\\s*[=<>]*\\s*-?[\\d\\.]+"};
69  return std::regex_replace(cut, expr, "(1)");
70  }
71 
72  std::istream& operator>>(std::istream& is, SelectionConfig& config) {
73  using symbols = Types::map<std::string>;
74  symbols sym;
75 
76  auto parse_cut = [&sym] (const std::string& cut) {
77  if (cut[0] == '\'')
78  return cut.substr(1, cut.size() - 2);
79  try {
80  return sym.at(cut);
81  }
82  catch(const std::out_of_range& e) {
83  std::cerr << "Exception locating " << cut << std::endl;
84  throw;
85  }
86  };
87 
88  auto current_symbol = symbols::key_type{};
89  auto joiner = symbols::mapped_type{};
90 
91  std::regex expr{"^([^\\s]*)\\s*([^\\s\\']*)\\s+(.+)$"};
92  std::smatch matches;
93 
94  for (auto& line : Parse::parse(is)) {
95  if (line[0] == ':') {
96  auto tokens = Misc::tokenize(line);
97  if (tokens.size() == 3)
98  tokens.push_back("'1.0'");
99 
100  if (tokens.size() != 4)
101  throw std::runtime_error{"Problem with selection line " + line};
102  // First token is ':'
103  config.selections.emplace(std::make_pair(tokens[1],
104  Selection(parse_cut(tokens[1]), // Cut
105  parse_cut(tokens[2]), // MC weight
106  parse_cut(tokens[3]), // Data weight
107  line[1] == 'b') // Should this be blind
108  ));
109  }
110  else if (std::regex_search(line, matches, expr)) {
111  if (matches[1].length()) {
112  current_symbol = matches[1];
113  joiner = matches[2];
114  if (joiner.size())
115  joiner = decltype(joiner)(" ") + joiner + " ";
116  }
117  sym[current_symbol] += (matches[2].length() ? "" : joiner) + parse_cut(matches[3]);
118  }
119  }
120  return is;
121  }
122 
123  }
124 }
125 
126 #endif