Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
CinematicExtractor.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cctype>
5#include <iterator>
6#include <sstream>
7#include <stdexcept>
8
9namespace {
10
11std::string read_file_to_string(const std::string& filename)
12{
13 std::ifstream file(filename);
14 if (!file) {
15 return {};
16 }
17
18 std::ostringstream buffer;
19 buffer << file.rdbuf();
20 return buffer.str();
21}
22
23std::optional<std::string> first_braced_argument_list_after_compute(const std::string& content)
24{
25 const std::string needle = "computeWilsonCoefficients";
26 const std::size_t call_pos = content.find(needle);
27 if (call_pos == std::string::npos) {
28 return std::nullopt;
29 }
30
31 const std::size_t first_brace = content.find('{', call_pos);
32 if (first_brace == std::string::npos) {
33 return std::nullopt;
34 }
35
36 int depth = 0;
37 bool in_string = false;
38 bool escaped = false;
39
40 for (std::size_t i = first_brace; i < content.size(); ++i) {
41 const char c = content[i];
42
43 if (in_string) {
44 if (escaped) {
45 escaped = false;
46 } else if (c == '\\') {
47 escaped = true;
48 } else if (c == '"') {
49 in_string = false;
50 }
51 continue;
52 }
53
54 if (c == '"') {
55 in_string = true;
56 continue;
57 }
58
59 if (c == '{') {
60 ++depth;
61 } else if (c == '}') {
62 --depth;
63 if (depth == 0) {
64 return content.substr(first_brace, i - first_brace + 1);
65 }
66 }
67 }
68
69 return std::nullopt;
70}
71
72} // namespace
73
74int countMatchInRegex(std::string s, std::string re) {
75 std::regex words_regex(re);
76 auto words_begin = std::sregex_iterator(s.begin(), s.end(), words_regex);
77 auto words_end = std::sregex_iterator();
78
79 return std::distance(words_begin, words_end);
80}
81
82std::pair<int, int> CinematicExtractor::extract(const std::string& filename) {
83 const auto process = extract_process(filename);
84 return {static_cast<int>(process.incoming_count()), static_cast<int>(process.outgoing_count())};
85}
86
87CinematicProcess CinematicExtractor::extract_process(const std::string& filename) const {
88 CinematicProcess process;
89 const std::string content = read_file_to_string(filename);
90 if (content.empty()) {
91 return {};
92 }
93
94 const std::regex particle_regex("(Incoming|Outgoing)\\s*\\(\\s*\"([^\"]+)\"");
95
96 auto parse_particle_list = [&](const std::string& particle_list) {
97 CinematicProcess process;
98 auto begin = std::sregex_iterator(particle_list.begin(), particle_list.end(), particle_regex);
99 auto end = std::sregex_iterator();
100
101 for (auto it = begin; it != end; ++it) {
102 const std::string direction = (*it)[1].str();
103 const std::string particle = normalize_particle_name((*it)[2].str());
104
105 if (direction == "Incoming") {
106 process.incoming.push_back(particle);
107 } else {
108 process.outgoing.push_back(particle);
109 }
110 }
111 return process;
112 };
113
114 // Preferred path: the process is written literally in the
115 // computeWilsonCoefficients(...) call.
116 if (const auto particle_list = first_braced_argument_list_after_compute(content);
117 particle_list.has_value()) {
118 auto process = parse_particle_list(*particle_list);
119 if (!process.empty()) {
120 return process;
121 }
122 }
123
124 // Newer templates factor the insertions in a helper such as
125 // hyperiso_bsll_insertions() and pass a variable to computeWilsonCoefficients.
126 // The old parser then saw the first unrelated block after the call and fell
127 // back to legacy KIN values. As a fallback, scan balanced braced blocks and
128 // return the first one that really contains Incoming/Outgoing insertions.
129 for (std::size_t brace = content.find('{'); brace != std::string::npos;
130 brace = content.find('{', brace + 1)) {
131 int depth = 0;
132 bool in_string = false;
133 bool escaped = false;
134
135 for (std::size_t i = brace; i < content.size(); ++i) {
136 const char c = content[i];
137
138 if (in_string) {
139 if (escaped) {
140 escaped = false;
141 } else if (c == '\\') {
142 escaped = true;
143 } else if (c == '"') {
144 in_string = false;
145 }
146 continue;
147 }
148
149 if (c == '"') {
150 in_string = true;
151 continue;
152 }
153
154 if (c == '{') {
155 ++depth;
156 } else if (c == '}') {
157 --depth;
158 if (depth == 0) {
159 auto process = parse_particle_list(content.substr(brace, i - brace + 1));
160 if (!process.empty()) {
161 return process;
162 }
163 break;
164 }
165 }
166 }
167 }
168
169 return {};
170}
171
172std::string CinematicExtractor::normalize_particle_name(std::string particle_name) {
173 particle_name.erase(std::remove_if(particle_name.begin(), particle_name.end(),
174 [](unsigned char c) { return std::isspace(c); }), particle_name.end());
175
176 if (!particle_name.empty() && particle_name.front() == '~') {
177 particle_name.erase(particle_name.begin());
178 }
179
180 std::transform(particle_name.begin(), particle_name.end(), particle_name.begin(),
181 [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
182
183 if (particle_name == "gamma" || particle_name == "photon") {
184 return "a";
185 }
186
187 return particle_name;
188}
189
190std::optional<std::string> CinematicExtractor::mass_symbol_for_particle(const std::string& particle_name) {
191 const auto normalized = normalize_particle_name(particle_name);
192 const auto& symbols = default_mass_symbols();
193
194 const auto it = symbols.find(normalized);
195 if (it == symbols.end()) {
196 return std::nullopt;
197 }
198 return it->second;
199}
200
201const std::unordered_map<std::string, std::string>& CinematicExtractor::default_mass_symbols() {
202 static const std::unordered_map<std::string, std::string> symbols {
203 {"u", "m_u"}, {"d", "m_d"}, {"s", "m_s"},
204 {"c", "m_c"}, {"b", "m_b"}, {"t", "m_t"},
205
206 {"e", "m_e"}, {"mu", "m_mu"}, {"tau", "m_tau"},
207 {"ve", "0"}, {"vmu", "0"}, {"vtau", "0"},
208
209 {"a", "0"}, {"g", "0"},
210 {"w", "m_W"}, {"w+", "m_W"}, {"w-", "m_W"},
211 {"z", "m_Z"}, {"h", "m_h"}
212 };
213
214 return symbols;
215}
int countMatchInRegex(std::string s, std::string re)
Counts the number of occurrences of a regex pattern in a given string.
static std::optional< std::string > mass_symbol_for_particle(const std::string &particle_name)
Returns the MARTY mass symbol associated with a particle name.
std::pair< int, int > extract(const std::string &filename)
Legacy API: returns {number_of_incoming, number_of_outgoing}.
static std::string normalize_particle_name(std::string particle_name)
Normalizes common MARTY particle names for dictionary lookup.
static const std::unordered_map< std::string, std::string > & default_mass_symbols()
Default particle -> MARTY mass-symbol dictionary.
CinematicProcess extract_process(const std::string &filename) const
Extracts the first MARTY process from a template file.
Incoming/outgoing particles extracted from a MARTY computeWilsonCoefficients call.
std::vector< std::string > outgoing
std::vector< std::string > incoming