39 [](
const Combo::MultiplicityReqMap::value_type&
a,
const Combo::MultiplicityReqMap::value_type&
b ){
40 return a.second.size() < b.second.size();
43 const size_t maxMult = maxMultEl->second.size();
53 <<
" multiplicities: " <<
m.second
60 bool errorOccured =
false;
68 }
else if (
value.size() != it_input->second.size()) {
69 ATH_MSG_ERROR(
"Inconsistent configuration vector sizes for " <<
key <<
" Multiplicities Required size:" <<
value.size()
70 <<
", Input Collections Index size:" << it_input->second.size());
74 if (
value.size() > maxMult ) {
77 <<
" configured with input multiplicity " <<
value.size() <<
" like this: " <<
value
78 <<
" which is lower than for this chain " << maxMultEl->first <<
" " << maxMult);
83 return ( errorOccured ? StatusCode::FAILURE : StatusCode::SUCCESS );
89 for (
auto const& element : passingLegs) {
90 passing.insert(element.first);
93 ATH_MSG_DEBUG(
"Copying "<<passing.size()<<
" positive decision IDs to outputs");
95 for (
size_t input_counter = 0; input_counter <
m_inputs.size(); ++input_counter ) {
98 auto outDecisions = outputHandle.
ptr();
100 if ( inputHandle.isValid() ) {
102 for (
const Decision* inputDecision : *inputHandle) {
109 ATH_MSG_DEBUG(
"Searching this element in the map: ("<<thisEL.dataID() <<
" , " << thisEL.index()<<
")");
114 const std::vector<ElementLink<DecisionContainer>>& Comb=passingLegs.at(
c);
115 if(
std::find(Comb.begin(), Comb.end(), thisEL) == Comb.end()) {
118 ATH_MSG_DEBUG(
" Adding "<< cID <<
" because EL is found in the passingLegs map");
119 finalIds.insert( cID.
numeric() );
122 finalIds.insert( mainChain.
numeric() );
128 ATH_MSG_DEBUG(
"New decision (Container Index:" << input_counter <<
", Element Index:"<< newDec->
index() <<
") has "
137 ATH_MSG_DEBUG(
"Output Handle " <<
m_outputs.at(input_counter).key() <<
" with " << outputHandle->
size() <<
" Decision objects");
141 ATH_MSG_DEBUG(
" Decision object #" <<
d->index() <<
" with " << objDecisions.size()<<
" positive decision IDs");
149 return StatusCode::SUCCESS;
167 const std::vector<int>& multiplicityPerLeg =
m.second;
171 allDecisionIds.insert(requiredDecisionID);
173 bool overallDecision =
true;
175 std::vector< SG::SGKeySet > legFeatureHashes;
176 legFeatureHashes.resize( multiplicityPerLeg.size() );
192 for (
size_t legIndex = 0; legIndex < multiplicityPerLeg.size(); ++legIndex ) {
193 const size_t requiredMultiplicity = multiplicityPerLeg.at( legIndex );
197 if (multiplicityPerLeg.size() > 1) {
198 ATH_MSG_DEBUG(chainId <<
" has multiplicityPerLeg.size() > 1, so we use legXXX_HLT_YYY, instead of HLT_YYY");
203 ATH_MSG_DEBUG(
"Container " << legIndex <<
", looking at leg : " << legId );
205 Combo::LegDecisionsMap::const_iterator
it = dmap.find(requiredDecisionIDLeg);
206 if (
it == dmap.end() ) {
207 overallDecision =
false;
212 const size_t nLegDecisionObjects =
it->second.size();
214 ATH_MSG_DEBUG(
"Will attempt to meet the required multiplicity of " << requiredMultiplicity <<
" for leg " << legId
215 <<
" with " << nLegDecisionObjects <<
" Decision Objects in leg " << legIndex <<
" of " << legId);
232 uint16_t featureIndex = 0, roiIndex = 0;
233 bool roiIsFullscan =
false;
234 bool objectRequestsNoMultiplicityCheck =
false;
235 ATH_CHECK(
extractFeatureAndRoI(
it->first, dEL, featureKey, featureIndex, roiKey, roiIndex, roiIsFullscan, objectRequestsNoMultiplicityCheck, priorFeaturesMap, context) );
236 const bool theFeatureIsTheROI = (
SG::sgkeyEqual (featureKey, roiKey) and featureIndex == roiIndex);
237 const bool thereIsNoFeatureYet = (featureKey == 0 and roiKey != 0);
238 if (objectRequestsNoMultiplicityCheck or (roiIsFullscan and (theFeatureIsTheROI or thereIsNoFeatureYet))) {
240 for (
size_t i = 0;
i < requiredMultiplicity; ++
i) {
241 legFeatureHashes.at( legIndex ).insert( ++passthroughCounter );
242 ATH_MSG_DEBUG(
" -- Add feature hash '" << passthroughCounter <<
"' to leg " << legIndex
243 <<
". (Note: unique passing hash generated from " << (objectRequestsNoMultiplicityCheck ?
"an object requesting NO multiplicity checks" :
"an FullScan ROI") <<
")");
246 const SG::sgkey_t uniquenessHash = (featureKey != 0 ? (featureKey + featureIndex) : (roiKey + roiIndex));
247 legFeatureHashes.at( legIndex ).insert( uniquenessHash );
248 ATH_MSG_DEBUG(
" -- Add feature hash '" << uniquenessHash <<
"' to leg " << legIndex <<
".");
253 thisChainCombMap.insert (*
it);
254 allDecisionIds.insert(requiredDecisionIDLeg);
262 size_t emergencyBreak = 0;
264 bool somethingChanged =
false;
266 for (
auto const& [
key, payloadSet] : priorFeaturesMap) {
267 if (payloadSet.count(legHash) == 1) {
268 ATH_MSG_DEBUG(
"Feature hash=" << legHash <<
" identified as a prior feature of hash=" <<
key
269 <<
", we will up-cast this hash to the later version for ComboHypo uniqueness comparison purposes.");
270 legHashes.erase(legHash);
271 legHashes.insert(
key);
274 somethingChanged =
true;
278 if (somethingChanged) {
282 if (!somethingChanged or ++emergencyBreak == 500) {
283 if (emergencyBreak == 500) {
297 std::set<SG::sgkey_t> allFeatureHashes;
298 for (
const SG::SGKeySet& legHashes : legFeatureHashes) {
299 allFeatureHashes.insert(legHashes.begin(), legHashes.end());
301 for (
const SG::sgkey_t featureHash : allFeatureHashes) {
302 size_t legsWithHash = 0;
303 size_t keepLegIndex = 0;
305 for (
size_t legIndex = 0; legIndex < multiplicityPerLeg.size(); ++legIndex) {
306 if (legFeatureHashes.at(legIndex).count(featureHash) == 0) {
310 const int32_t requiredMultiplicity = multiplicityPerLeg.at(legIndex);
311 const int32_t currentMultiplicity = legFeatureHashes.at(legIndex).size();
312 const int32_t safetyMargin = currentMultiplicity - requiredMultiplicity;
313 if (safetyMargin < keepLegMargin) {
314 keepLegMargin = safetyMargin;
315 keepLegIndex = legIndex;
318 if (legsWithHash == 1) {
322 for (
size_t legIndex = 0; legIndex < multiplicityPerLeg.size(); ++legIndex) {
323 if (legIndex == keepLegIndex) {
324 ATH_MSG_DEBUG(
"Keeping feature hash '" << featureHash <<
"', on leg " << legIndex <<
". This leg can least afford to lose it. "
325 <<
"Leg has " << legFeatureHashes.at(legIndex).size()
326 <<
" features, and a multiplicity requirement of " << multiplicityPerLeg.at(legIndex));
329 if (legFeatureHashes.at(legIndex).erase(featureHash)) {
330 ATH_MSG_DEBUG(
"Removed duplicate feature hash '" << featureHash <<
"', from leg " << legIndex <<
". Leg now has " << legFeatureHashes.at(legIndex).size()
331 <<
" remaining features, and a multiplicity requirement of " << multiplicityPerLeg.at(legIndex));
337 for (
size_t legIndex = 0; legIndex < multiplicityPerLeg.size(); ++legIndex) {
338 const size_t requiredMultiplicity = multiplicityPerLeg.at(legIndex);
339 const size_t currentMultiplicity = legFeatureHashes.at(legIndex).size();
340 if (currentMultiplicity < requiredMultiplicity) {
341 ATH_MSG_DEBUG(
"Leg " << legIndex <<
" fails multiplicity check. Required unique features:" << requiredMultiplicity <<
", found unique features: " << currentMultiplicity);
342 overallDecision =
false;
348 ATH_MSG_DEBUG(
"Chain " << chainId << ( overallDecision ?
" is accepted" :
" is rejected") <<
" after multiplicity requirements" );
349 if ( overallDecision ==
true ) {
350 for (
auto decID: allDecisionIds) {
352 passingLegs.insert (thisChainCombMap.begin(), thisChainCombMap.end());
358 if (passingLegs.size()!=0){
369 for (
auto const& [
id,
decisions] : passingLegs) {
377 return StatusCode::SUCCESS;
388 bool& objectRequestsNoMultiplicityCheck,
390 const EventContext& ctx)
const
401 ATH_MSG_ERROR(
"We are only expecting to search from a single navigation node in extractFeatureAndRoI");
402 return StatusCode::FAILURE;
406 std::vector<SG::sgkey_t>
keys;
407 std::vector<uint32_t> clids;
408 std::vector<uint16_t> indicies;
409 std::vector<const Decision*> sources;
411 std::set<const xAOD::TrigComposite*> fullyExploredFrom;
416 const Decision* featureSource =
nullptr;
419 featureKey =
keys.at(0);
420 featureIndex = indicies.at(0);
421 featureSource = sources.at(0);
424 objectRequestsNoMultiplicityCheck = (featureSource and featureSource->
hasDetail<int32_t>(
"noCombo") and featureSource->
getDetail<int32_t>(
"noCombo") == 1);
426 if (foundFeature and priorFeaturesMap.count(featureKey + featureIndex) == 0) {
427 const std::string* key_str =
evtStore()->keyToString(featureKey);
428 ATH_MSG_DEBUG(
"Note: Will use feature hash " << featureKey + featureIndex <<
", for " << (key_str ? *key_str :
"UNKNOWN") <<
" index=" << featureIndex);
431 if (
keys.size() > 1) {
432 for (
size_t i = 1;
i <
keys.size(); ++
i) {
434 if (featureKey + featureIndex ==
keys.at(
i) + indicies.at(
i)) {
437 priorFeaturesMap[featureKey + featureIndex].insert(
keys.at(
i) + indicies.at(
i));
440 priorFeaturesMap.insert( std::pair<
uint32_t, std::set<uint32_t>>(featureKey + featureIndex, std::set<uint32_t>()) );
451 roiIsFullscan = (*(roiEL))->isFullscan();
453 const std::string* roi_str =
evtStore()->keyToString(roiKey);
454 ATH_MSG_DEBUG(
"Note: Located fallback-ROI, if used this will have feature hash =" << roiKey + roiIndex <<
", for " << (roi_str ? *roi_str :
"UNKNOWN") <<
" index=" << roiIndex);
458 if (!foundFeature && !foundROI) {
462 return StatusCode::SUCCESS;
467 for (
size_t inputContainerIndex = 0; inputContainerIndex <
m_inputs.size(); ++inputContainerIndex ) {
469 if ( !inputHandle.isValid() ) {
470 ATH_MSG_ERROR(
"No input ReadHandle from " << inputHandle.key() );
471 return StatusCode::FAILURE;
473 ATH_MSG_DEBUG(
"-- Found ReadHandle from " << inputHandle.key() <<
" with "<< inputHandle->size() <<
" elements:" );
474 for (
const Decision* decision : *inputHandle ) {
475 ATH_MSG_DEBUG(
"-- -- Input Decision #"<< decision->index() <<
" with "<<
decisionIDs( decision ).
size() <<
" active IDs. Populating the multiplicity map:" );
478 int32_t chainLeg = 0;
487 ATH_MSG_VERBOSE(
"-- -- -- Ignoring the DecsionID " <<
id <<
" on leg " << chainLeg <<
" as it does not correspond to any of the " <<
m_legToInputCollectionMap.size() <<
" chains this Alg is processing.");
492 const std::vector<int>& legToInputCollectionIndex =
it->second;
493 const size_t requiredInputContainerIndex =
static_cast<size_t>(legToInputCollectionIndex.at(chainLeg));
494 if (requiredInputContainerIndex != inputContainerIndex) {
495 ATH_MSG_VERBOSE(
"-- -- -- Ignoring the DecisionID " <<
id <<
" on leg " << chainLeg <<
" as we are only permitted to accept passing objects on leg #" << chainLeg <<
" of " << chainID.
name()
496 <<
" which come from input collection index " << requiredInputContainerIndex <<
" (which is " <<
m_inputs.at(requiredInputContainerIndex).key() <<
")"
497 <<
". Not the current index " << inputContainerIndex <<
" (which is " <<
m_inputs.at(inputContainerIndex).key() <<
")");
510 for (
const auto&
entry: dmap){
512 const std::vector<ElementLink<DecisionContainer>>&
decisions =
entry.second;
515 ATH_MSG_DEBUG(
" Decision: (ContainerKey:"<<
d.dataID()<<
", DecisionElementIndex:"<<
d.index()<<
")");
522 return StatusCode::SUCCESS;