128 {
129
130
131 if (passingLegs.empty()) {
132 return StatusCode::SUCCESS;
133 }
134
135 ATH_MSG_DEBUG(
"Looking for legs from " <<
decisionId() <<
" in the map. Map contains features for " << passingLegs.size() <<
" legs, which may be data for many chains.");
136 for(const auto& legpair : passingLegs) {
137 ATH_MSG_DEBUG(
" Leg " << legpair.first <<
" has " << legpair.second.size() <<
" features");
138 }
139
140
141 std::vector<Combination> legDecisions;
143
144
145 bool hasViableLegs{true};
146
147 std::vector<size_t> legMultiplicityForComputation(
legMultiplicity().size(),0);
149 ATH_MSG_DEBUG(
"Var " << varInfo.varTag <<
" needs legs " << varInfo.legA <<
", " << varInfo.legB <<
", " << varInfo.legC);
150
151
152 if (passingLegs.contains(varInfo.legA) && passingLegs.contains(varInfo.legB) && passingLegs.contains(varInfo.legC)) {
153 bool goodLegA{false}, goodLegB{false}, goodLegC{false};
157 if ((iLegA<0) or (iLegB<0) or (iLegC<0)){
158 ATH_MSG_ERROR(
"Trig3VarComboHypoTool::decide: Index into array is negative");
159 return StatusCode::FAILURE;
160 }
161 goodLegA = !passingLegs[varInfo.legA].empty();
162 legMultiplicityForComputation[iLegA] = std::max<size_t>(1,legMultiplicityForComputation[iLegA]);
163 ATH_MSG_DEBUG(
"Leg " << varInfo.legA <<
" has " << passingLegs[varInfo.legA].size() <<
" features --> " << (goodLegA ?
"pass" :
"fail"));
164
165 if(varInfo.legB == varInfo.legA) {
166 ATH_MSG_ERROR(
"Trig3VarComboHypoTool::decide: legB has to be different from legA");
167 return StatusCode::FAILURE;
168 }
169 goodLegB = !passingLegs[varInfo.legB].empty();
170 ATH_MSG_DEBUG(
"Leg " << varInfo.legB <<
" has " << passingLegs[varInfo.legB].size() <<
" features --> " << (goodLegB ?
"pass" :
"fail"));
171 legMultiplicityForComputation[iLegB] = std::max<size_t>(1,legMultiplicityForComputation[iLegB]);
172
173 if(varInfo.legC == varInfo.legA) {
174 ATH_MSG_ERROR(
"Trig3VarComboHypoTool::decide: legC has to be different from legA");
175 return StatusCode::FAILURE;
176 }
177 if(varInfo.legC == varInfo.legB) {
178 ATH_MSG_ERROR(
"Trig3VarComboHypoTool::decide: legC has to be different from legB");
179 return StatusCode::FAILURE;
180 }
181 goodLegC = !passingLegs[varInfo.legC].empty();
182 ATH_MSG_DEBUG(
"Leg " << varInfo.legC <<
" has " << passingLegs[varInfo.legC].size() <<
" features --> " << (goodLegC ?
"pass" :
"fail"));
183 legMultiplicityForComputation[iLegC] = std::max<size_t>(1,legMultiplicityForComputation[iLegC]);
184
185 hasViableLegs &= (goodLegA && goodLegB && goodLegC);
186 if (!hasViableLegs) {
187 ATH_MSG_DEBUG(
"Did not find at least 3 features on the target legs to compute " << varInfo.varTag);
188 }
189 } else {
191 "Insufficient passing legs to compute " << varInfo.varTag
192 << ", intended on (" << varInfo.legA << ", " << varInfo.legB << ", " << varInfo.legC << ")"
193 );
194 hasViableLegs = false;
195 }
196
197 }
198
199 if (!hasViableLegs) {
200 ATH_MSG_DEBUG(
"This Trig3VarComboHypoTool cannot run in this event, this chain **REJECTS** this event.");
203 return StatusCode::SUCCESS;
204 }
205
206
207
209 HLT::NestedUniqueCombinationGenerator nucg;
210 for (size_t legindex = 0; size_t legmult : legMultiplicityForComputation){
211 size_t out_of = legDecisions[legindex].size();
212 if(legmult==0) {
213 extraLegs.insert(extraLegs.end(),legDecisions[legindex].cbegin(),legDecisions[legindex].cend());
214 } else {
215 nucg.
add({out_of, legmult});
216 ATH_MSG_DEBUG(
"For leg index " << legindex <<
" we will be choosing any " << legmult <<
" Decision Objects out of " << out_of);
217 }
218 ++legindex;
219 }
220
221
222 std::vector<Combination> passingCombinations;
223 std::vector<float>
values;
225 size_t warnings = 0, iterations = 0;
226
227 auto get_index_offset = [&legMultiplicityForComputation](size_t legindex) {
229 for (auto iLeg=legMultiplicityForComputation.cbegin(); iLeg!=legMultiplicityForComputation.cbegin()+legindex; ++iLeg) {
231 }
233 };
234 do {
235 bool lastDecision(true);
236 const std::vector<size_t> combination = nucg();
237 ++nucg;
238 ++iterations;
240
241
244
246
247 size_t legA_index{0};
248 size_t legB_index{0};
249 size_t legC_index{0};
250
254
256 "Computing " << iVarInfo->varTag << " on legs "
257 << iVarInfo->legA << " (" << legA_index << "), "
258 << iVarInfo->legB << " (" << legB_index << "), "
259 << iVarInfo->legC << " (" << legC_index << ")"
260 );
261 if(iVarInfo->legA==iVarInfo->legB) {
263 break;
264 }
265 if(iVarInfo->legA==iVarInfo->legC) {
267 break;
268 }
269 if(iVarInfo->legB==iVarInfo->legC) {
271 break;
272 }
273
274
275 Combination featureTrio = {legDecisions[legA_index][combination.at(legA_index+get_index_offset(legA_index))],
276 legDecisions[legB_index][combination.at(legB_index+get_index_offset(legB_index))],
277 legDecisions[legC_index][combination.at(legC_index+get_index_offset(legC_index))]};
278 combinationToCheck.insert(combinationToCheck.end(),featureTrio.cbegin(),featureTrio.cend());
279 combinationToRecord.insert(combinationToRecord.end(),featureTrio.cbegin(),featureTrio.cend());
280
281 try {
282 lastDecision =
executeAlgStep(combinationToCheck, *iVarInfo, values);
283 ATH_MSG_DEBUG(
"Combination " << (iterations - 1) <<
" decided to be " << (lastDecision ?
"passing" :
"failing") <<
" " << iVarInfo->varTag);
284 } catch (std::exception& e) {
286 return StatusCode::FAILURE;
287 }
288
290 ATH_MSG_WARNING(
"Have so far processed " << iterations <<
" combinations for " <<
decisionId() <<
" in this event, " << passingCombinations.size() <<
" passing.");
291 ++warnings;
293 ATH_MSG_WARNING(
"Too many combinations! Breaking the loop at this point.");
294 break;
295 }
296 }
297 }
298
299
300 if (lastDecision) {
301 combinationToRecord.insert(combinationToRecord.end(),extraLegs.cbegin(),extraLegs.cend());
302 passingCombinations.push_back(std::move(combinationToRecord));
304 break;
305 }
306 } else {
308 break;
309 }
310 }
311
312
316 auto varOfAccepted = Monitored::Scalar(
m_varTag_vec[varInfo.index]+
"OfAccepted", value );
317 auto monitorIt = Monitored::Group (
m_monTool_vec[varInfo.index], varOfAccepted);
318 ATH_MSG_VERBOSE( varInfo.varTag <<
" = " << value <<
" is in range " << varInfo.rangeStr() <<
".");
320 }
321 }
322
323 } while (nucg);
324
326
327 ATH_MSG_DEBUG(
"Passing " << passingCombinations.size() <<
" combinations out of " << iterations <<
", "
328 <<
decisionId() << (passingCombinations.size() ?
" **ACCEPTS**" :
" **REJECTS**") <<
" this event based on OR logic.");
329
331 ATH_MSG_DEBUG(
"Note: stopped after the first successful combination due to the EnableOverride flag.");
332 }
333
334 } else {
335
336 const bool passAll = (passingCombinations.size() == iterations);
337
338 ATH_MSG_DEBUG(
"Passing " << passingCombinations.size() <<
" combinations out of " << iterations <<
", "
339 <<
decisionId() << (passAll ?
" **ACCEPTS**" :
" **REJECTS**") <<
" this event based on AND logic.");
340
342 ATH_MSG_DEBUG(
"Note: stopped after the first failed combination due to the EnableOverride flag.");
343 }
344
345 if (not passAll) {
346 passingCombinations.clear();
347 }
348
349 }
350
351 if (not passingCombinations.empty()) {
353 } else {
355 }
356
358 return StatusCode::SUCCESS;
359}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
void add(const UniqueCombinationGenerator &gen)
int32_t getIndexFromLeg(const HLT::Identifier &legIdentifier)
Extract the numeric index of a leg identifier.