129 {
130
131
132 if (passingLegs.empty()) {
133 return StatusCode::SUCCESS;
134 }
135
136 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.");
137 for(const auto& legpair : passingLegs) {
138 ATH_MSG_DEBUG(
" Leg " << legpair.first <<
" has " << legpair.second.size() <<
" features");
139 }
140
141
142 std::vector<Combination> legDecisions;
144
145
146 bool hasViableLegs{true};
147
148 std::vector<size_t> legMultiplicityForComputation(
legMultiplicity().size(),0);
150
151
152 legMultiplicityForComputation[0] = 2;
153 hasViableLegs = legDecisions[0].size() >= 2;
154 } else {
156 ATH_MSG_DEBUG(
"Var " << varInfo.varTag <<
" needs legs " << varInfo.legA <<
", " << varInfo.legB);
157
158
159 if (passingLegs.contains(varInfo.legA) && passingLegs.contains(varInfo.legB)) {
160 size_t goodLegA{false}, goodLegB{false};
163 if ((iLegA<0) or (iLegB<0)){
164 ATH_MSG_ERROR(
"TrigComboHypoTool::decide: Index into array is negative");
165 return StatusCode::FAILURE;
166 }
167 goodLegA = !passingLegs[varInfo.legA].empty();
168 legMultiplicityForComputation[iLegA] = std::max<size_t>(1,legMultiplicityForComputation[iLegA]);
169 ATH_MSG_DEBUG(
"Leg " << varInfo.legA <<
" has " << passingLegs[varInfo.legA].size() <<
" features --> " << (goodLegA ?
"pass" :
"fail"));
170 if(varInfo.legB != varInfo.legA) {
171 goodLegB = !passingLegs[varInfo.legB].empty();
172 ATH_MSG_DEBUG(
"Leg " << varInfo.legB <<
" has " << passingLegs[varInfo.legB].size() <<
" features --> " << (goodLegB ?
"pass" :
"fail"));
173 legMultiplicityForComputation[iLegB] = std::max<size_t>(1,legMultiplicityForComputation[iLegB]);
174 } else {
175 goodLegB = goodLegA = passingLegs[varInfo.legA].size() >= 2;
176 ATH_MSG_DEBUG(
"Leg " << varInfo.legA <<
" has " << passingLegs[varInfo.legA].size() <<
" features --> " << (goodLegB ?
"pass" :
"fail"));
177
178 legMultiplicityForComputation[iLegA] = std::max<size_t>(2,legMultiplicityForComputation[iLegA]);
179 }
180 hasViableLegs &= (goodLegA && goodLegB);
181 if (!hasViableLegs) {
182 ATH_MSG_DEBUG(
"Did not find at least 2 features on the target legs to compute " << varInfo.varTag);
183 }
184 } else {
186 "Insufficient passing legs to compute " << varInfo.varTag
187 << ", intended on (" << varInfo.legA << ", " << varInfo.legB << ")"
188 );
189 hasViableLegs = false;
190 }
191 }
192 }
193
194 if (!hasViableLegs) {
195 ATH_MSG_DEBUG(
"This ComboHypoTool cannot run in this event, this chain **REJECTS** this event.");
198 return StatusCode::SUCCESS;
199 }
200
201
202
204 HLT::NestedUniqueCombinationGenerator nucg;
205 for (size_t legindex = 0; size_t legmult : legMultiplicityForComputation){
206 size_t out_of = legDecisions[legindex].size();
207 if(legmult==0) {
208 extraLegs.insert(extraLegs.end(),legDecisions[legindex].cbegin(),legDecisions[legindex].cend());
209 } else {
210 nucg.
add({out_of, legmult});
211 ATH_MSG_DEBUG(
"For leg index " << legindex <<
" we will be choosing any " << legmult <<
" Decision Objects out of " << out_of);
212 }
213 ++legindex;
214 }
215
216
217 std::vector<Combination> passingCombinations;
218 std::vector<float>
values;
220 size_t warnings = 0, iterations = 0;
221
222 auto get_index_offset = [&legMultiplicityForComputation](size_t legindex) {
224 for (auto iLeg=legMultiplicityForComputation.cbegin(); iLeg!=legMultiplicityForComputation.cbegin()+legindex; ++iLeg) {
226 }
228 };
229 do {
230 bool lastDecision(true);
231 const std::vector<size_t> combination = nucg();
232 ++nucg;
233 ++iterations;
235
236
239
241
242 size_t legA_index = 0;
243 size_t legB_index = 0;
244
245
249 }
250
252 "Computing " << iVarInfo->varTag << " on legs "
253 << iVarInfo->legA << " (" << legA_index << "), "
254 << iVarInfo->legB << " (" << legB_index << ")"
255 );
256 if(iVarInfo->legA==iVarInfo->legB) {
257
258
259 Combination featurePair = {legDecisions[legA_index][combination.at(legA_index+get_index_offset(legA_index))],legDecisions[legA_index][combination.at(legA_index+get_index_offset(legA_index)+1)]};
260 combinationToCheck.insert(combinationToCheck.end(),featurePair.cbegin(),featurePair.cend());
261 combinationToRecord.insert(combinationToRecord.end(),featurePair.cbegin(),featurePair.cend());
262 } else {
263
264 Combination featurePair = {legDecisions[legA_index][combination.at(legA_index+get_index_offset(legA_index))],legDecisions[legB_index][combination.at(legB_index+get_index_offset(legB_index))]};
265 combinationToCheck.insert(combinationToCheck.end(),featurePair.cbegin(),featurePair.cend());
266 combinationToRecord.insert(combinationToRecord.end(),featurePair.cbegin(),featurePair.cend());
267 }
268
269 try {
270 lastDecision =
executeAlgStep(combinationToCheck, *iVarInfo, values);
271 ATH_MSG_DEBUG(
"Combination " << (iterations - 1) <<
" decided to be " << (lastDecision ?
"passing" :
"failing") <<
" " << iVarInfo->varTag);
272 } catch (std::exception& e) {
274 return StatusCode::FAILURE;
275 }
276
278 ATH_MSG_WARNING(
"Have so far processed " << iterations <<
" combinations for " <<
decisionId() <<
" in this event, " << passingCombinations.size() <<
" passing.");
279 ++warnings;
281 ATH_MSG_WARNING(
"Too many combinations! Breaking the loop at this point.");
282 break;
283 }
284 }
285 }
286
287
288 if (lastDecision) {
289 combinationToRecord.insert(combinationToRecord.end(),extraLegs.cbegin(),extraLegs.cend());
290 passingCombinations.push_back(std::move(combinationToRecord));
292 break;
293 }
294 } else {
296 break;
297 }
298 }
299
300
304 auto varOfAccepted = Monitored::Scalar(
m_varTag_vec[varInfo.index]+
"OfAccepted", value );
305 auto monitorIt = Monitored::Group (
m_monTool_vec[varInfo.index], varOfAccepted);
306 ATH_MSG_VERBOSE( varInfo.varTag <<
" = " << value <<
" is in range " << varInfo.rangeStr() <<
".");
308 }
309 }
310 } while (nucg);
311
313
314 ATH_MSG_DEBUG(
"Passing " << passingCombinations.size() <<
" combinations out of " << iterations <<
", "
315 <<
decisionId() << (passingCombinations.size() ?
" **ACCEPTS**" :
" **REJECTS**") <<
" this event based on OR logic.");
316
318 ATH_MSG_DEBUG(
"Note: stopped after the first successful combination due to the EnableOverride flag.");
319 }
320
321 } else {
322
323 const bool passAll = (passingCombinations.size() == iterations);
324
325 ATH_MSG_DEBUG(
"Passing " << passingCombinations.size() <<
" combinations out of " << iterations <<
", "
326 <<
decisionId() << (passAll ?
" **ACCEPTS**" :
" **REJECTS**") <<
" this event based on AND logic.");
327
329 ATH_MSG_DEBUG(
"Note: stopped after the first failed combination due to the EnableOverride flag.");
330 }
331
332 if (not passAll) {
333 passingCombinations.clear();
334 }
335
336 }
337
338 if (not passingCombinations.empty()) {
340 } else {
342 }
343
345 return StatusCode::SUCCESS;
346}
#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.