38 [](
const Combo::MultiplicityReqMap::value_type&
a,
const Combo::MultiplicityReqMap::value_type&
b ){
39 return a.second.size() < b.second.size();
42 const size_t maxMult = maxMultEl->second.size();
52 <<
" multiplicities: " <<
m.second
59 bool errorOccured =
false;
67 }
else if (
value.size() != it_input->second.size()) {
68 ATH_MSG_ERROR(
"Inconsistent configuration vector sizes for " <<
key <<
" Multiplicities Required size:" <<
value.size()
69 <<
", Input Collections Index size:" << it_input->second.size());
73 if (
value.size() > maxMult ) {
76 <<
" configured with input multiplicity " <<
value.size() <<
" like this: " <<
value
77 <<
" which is lower than for this chain " << maxMultEl->first <<
" " << maxMult);
82 return ( errorOccured ? StatusCode::FAILURE : StatusCode::SUCCESS );
88 for (
auto const& element : passingLegs) {
89 passing.insert(element.first);
92 ATH_MSG_DEBUG(
"Copying "<<passing.size()<<
" positive decision IDs to outputs");
94 for (
size_t input_counter = 0; input_counter <
m_inputs.size(); ++input_counter ) {
97 auto outDecisions = outputHandle.
ptr();
99 if ( inputHandle.isValid() ) {
101 for (
const Decision* inputDecision : *inputHandle) {
108 ATH_MSG_DEBUG(
"Searching this element in the map: ("<<thisEL.dataID() <<
" , " << thisEL.index()<<
")");
113 const std::vector<ElementLink<DecisionContainer>>& Comb=passingLegs.at(
c);
114 if(
std::find(Comb.begin(), Comb.end(), thisEL) == Comb.end()) {
117 ATH_MSG_DEBUG(
" Adding "<< cID <<
" because EL is found in the passingLegs map");
118 finalIds.insert( cID.
numeric() );
121 finalIds.insert( mainChain.
numeric() );
127 ATH_MSG_DEBUG(
"New decision (Container Index:" << input_counter <<
", Element Index:"<< newDec->
index() <<
") has "
136 ATH_MSG_DEBUG(
"Output Handle " <<
m_outputs.at(input_counter).key() <<
" with " << outputHandle->
size() <<
" Decision objects");
140 ATH_MSG_DEBUG(
" Decision object #" <<
d->index() <<
" with " << objDecisions.size()<<
" positive decision IDs");
148 return StatusCode::SUCCESS;
169 allDecisionIds.insert(requiredDecisionID);
171 bool overallDecision =
true;
173 std::vector< SG::SGKeySet > legFeatureHashes;
174 legFeatureHashes.resize( multiplicityPerLeg.size() );
190 for (
size_t legIndex = 0; legIndex < multiplicityPerLeg.size(); ++legIndex ) {
191 const size_t requiredMultiplicity = multiplicityPerLeg.at( legIndex );
195 if (multiplicityPerLeg.size() > 1) {
196 ATH_MSG_DEBUG(chainId <<
" has multiplicityPerLeg.size() > 1, so we use legXXX_HLT_YYY, instead of HLT_YYY");
201 ATH_MSG_DEBUG(
"Container " << legIndex <<
", looking at leg : " << legId );
203 Combo::LegDecisionsMap::const_iterator
it = dmap.find(requiredDecisionIDLeg);
204 if (
it == dmap.end() ) {
209 const size_t nLegDecisionObjects =
it->second.size();
211 ATH_MSG_DEBUG(
"Will attempt to meet the required multiplicity of " << requiredMultiplicity <<
" for leg " << legId
212 <<
" with " << nLegDecisionObjects <<
" Decision Objects in leg " << legIndex <<
" of " << legId);
230 bool roiIsFullscan =
false;
231 bool objectRequestsNoMultiplicityCheck =
false;
232 ATH_CHECK(
extractFeatureAndRoI(
it->first, dEL, featureKey, featureIndex, roiKey, roiIndex, roiIsFullscan, objectRequestsNoMultiplicityCheck, priorFeaturesMap) );
233 const bool theFeatureIsTheROI = (
SG::sgkeyEqual (featureKey, roiKey) and featureIndex == roiIndex);
234 const bool thereIsNoFeatureYet = (featureKey == 0 and roiKey != 0);
235 if (objectRequestsNoMultiplicityCheck or (roiIsFullscan and (theFeatureIsTheROI or thereIsNoFeatureYet))) {
237 for (
size_t i = 0;
i < requiredMultiplicity; ++
i) {
238 legFeatureHashes.at( legIndex ).insert( ++passthroughCounter );
239 ATH_MSG_DEBUG(
" -- Add feature hash '" << passthroughCounter <<
"' to leg " << legIndex
240 <<
". (Note: unique passing hash generated from " << (objectRequestsNoMultiplicityCheck ?
"an object requesting NO multiplicity checks" :
"an FullScan ROI") <<
")");
243 const SG::sgkey_t uniquenessHash = (featureKey != 0 ? (featureKey + featureIndex) : (roiKey + roiIndex));
244 legFeatureHashes.at( legIndex ).insert( uniquenessHash );
245 ATH_MSG_DEBUG(
" -- Add feature hash '" << uniquenessHash <<
"' to leg " << legIndex <<
".");
250 thisChainCombMap.insert (*
it);
251 allDecisionIds.insert(requiredDecisionIDLeg);
259 size_t emergencyBreak = 0;
261 bool somethingChanged =
false;
263 for (
auto const& [
key, payloadSet] : priorFeaturesMap) {
264 if (payloadSet.count(legHash) == 1) {
265 ATH_MSG_DEBUG(
"Feature hash=" << legHash <<
" identified as a prior feature of hash=" <<
key
266 <<
", we will up-cast this hash to the later version for ComboHypo uniqueness comparison purposes.");
267 legHashes.erase(legHash);
268 legHashes.insert(
key);
271 somethingChanged =
true;
275 if (somethingChanged) {
279 if (!somethingChanged or ++emergencyBreak == 500) {
280 if (emergencyBreak == 500) {
294 std::set<SG::sgkey_t> allFeatureHashes;
295 for (
const SG::SGKeySet& legHashes : legFeatureHashes) {
296 allFeatureHashes.insert(legHashes.begin(), legHashes.end());
298 for (
const SG::sgkey_t featureHash : allFeatureHashes) {
299 size_t legsWithHash = 0;
300 size_t keepLegIndex = 0;
302 for (
size_t legIndex = 0; legIndex < multiplicityPerLeg.size(); ++legIndex) {
303 if (legFeatureHashes.at(legIndex).count(featureHash) == 0) {
307 const int32_t requiredMultiplicity = multiplicityPerLeg.at(legIndex);
308 const int32_t currentMultiplicity = legFeatureHashes.at(legIndex).size();
309 const int32_t safetyMargin = currentMultiplicity - requiredMultiplicity;
310 if (safetyMargin < keepLegMargin) {
311 keepLegMargin = safetyMargin;
312 keepLegIndex = legIndex;
315 if (legsWithHash == 1) {
319 for (
size_t legIndex = 0; legIndex < multiplicityPerLeg.size(); ++legIndex) {
320 if (legIndex == keepLegIndex) {
321 ATH_MSG_DEBUG(
"Keeping feature hash '" << featureHash <<
"', on leg " << legIndex <<
". This leg can least afford to lose it. "
322 <<
"Leg has " << legFeatureHashes.at(legIndex).size()
323 <<
" features, and a multiplicity requirement of " << multiplicityPerLeg.at(legIndex));
326 if (legFeatureHashes.at(legIndex).erase(featureHash)) {
327 ATH_MSG_DEBUG(
"Removed duplicate feature hash '" << featureHash <<
"', from leg " << legIndex <<
". Leg now has " << legFeatureHashes.at(legIndex).size()
328 <<
" remaining features, and a multiplicity requirement of " << multiplicityPerLeg.at(legIndex));
334 for (
size_t legIndex = 0; legIndex < multiplicityPerLeg.size(); ++legIndex) {
335 const size_t requiredMultiplicity = multiplicityPerLeg.at(legIndex);
336 const size_t currentMultiplicity = legFeatureHashes.at(legIndex).size();
337 if (currentMultiplicity < requiredMultiplicity) {
338 ATH_MSG_DEBUG(
"Leg " << legIndex <<
" fails multiplicity check. Required unique features:" << requiredMultiplicity <<
", found unique features: " << currentMultiplicity);
339 overallDecision =
false;
345 ATH_MSG_DEBUG(
"Chain " << chainId << ( overallDecision ?
" is accepted" :
" is rejected") <<
" after multiplicity requirements" );
346 if ( overallDecision ==
true ) {
347 for (
auto decID: allDecisionIds) {
349 passingLegs.insert (thisChainCombMap.begin(), thisChainCombMap.end());
355 if (passingLegs.size()!=0){
366 for (
auto const& [
id,
decisions] : passingLegs) {
374 return StatusCode::SUCCESS;
385 bool& objectRequestsNoMultiplicityCheck,
386 SG::SGKeyMap<std::set<uint32_t>>& priorFeaturesMap)
const
397 ATH_MSG_ERROR(
"We are only expecting to search from a single navigation node in extractFeatureAndRoI");
398 return StatusCode::FAILURE;
402 std::vector<SG::sgkey_t>
keys;
403 std::vector<uint32_t> clids;
404 std::vector<Decision::index_type> indicies;
405 std::vector<const Decision*> sources;
407 std::set<const Decision*> fullyExploredFrom;
412 const Decision* featureSource =
nullptr;
415 featureKey =
keys.at(0);
416 featureIndex = indicies.at(0);
417 featureSource = sources.at(0);
420 objectRequestsNoMultiplicityCheck = (featureSource and featureSource->
hasDetail<int32_t>(
"noCombo") and featureSource->
getDetail<int32_t>(
"noCombo") == 1);
422 if (foundFeature and priorFeaturesMap.count(featureKey + featureIndex) == 0) {
423 const std::string* key_str =
evtStore()->keyToString(featureKey);
424 ATH_MSG_DEBUG(
"Note: Will use feature hash " << featureKey + featureIndex <<
", for " << (key_str ? *key_str :
"UNKNOWN") <<
" index=" << featureIndex);
427 if (
keys.size() > 1) {
428 for (
size_t i = 1;
i <
keys.size(); ++
i) {
430 if (featureKey + featureIndex ==
keys.at(
i) + indicies.at(
i)) {
433 priorFeaturesMap[featureKey + featureIndex].insert(
keys.at(
i) + indicies.at(
i));
436 priorFeaturesMap.insert( std::pair<
uint32_t, std::set<uint32_t>>(featureKey + featureIndex, std::set<uint32_t>()) );
447 roiIsFullscan = (*(roiEL))->isFullscan();
449 const std::string* roi_str =
evtStore()->keyToString(roiKey);
450 ATH_MSG_DEBUG(
"Note: Located fallback-ROI, if used this will have feature hash =" << roiKey + roiIndex <<
", for " << (roi_str ? *roi_str :
"UNKNOWN") <<
" index=" << roiIndex);
454 if (!foundFeature && !foundROI) {
458 return StatusCode::SUCCESS;
463 for (
size_t inputContainerIndex = 0; inputContainerIndex <
m_inputs.size(); ++inputContainerIndex ) {
465 if ( !inputHandle.isValid() ) {
466 ATH_MSG_ERROR(
"No input ReadHandle from " << inputHandle.key() );
467 return StatusCode::FAILURE;
469 ATH_MSG_DEBUG(
"-- Found ReadHandle from " << inputHandle.key() <<
" with "<< inputHandle->size() <<
" elements:" );
470 for (
const Decision* decision : *inputHandle ) {
471 ATH_MSG_DEBUG(
"-- -- Input Decision #"<< decision->index() <<
" with "<<
decisionIDs( decision ).
size() <<
" active IDs. Populating the multiplicity map:" );
480 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.");
485 const std::vector<int>& legToInputCollectionIndex =
it->second;
486 const size_t requiredInputContainerIndex =
static_cast<size_t>(legToInputCollectionIndex.at(chainLeg));
487 if (requiredInputContainerIndex != inputContainerIndex) {
488 ATH_MSG_VERBOSE(
"-- -- -- Ignoring the DecisionID " <<
id <<
" on leg " << chainLeg <<
" as we are only permitted to accept passing objects on leg #" << chainLeg <<
" of " <<
chainName
489 <<
" which come from input collection index " << requiredInputContainerIndex <<
" (which is " <<
m_inputs.at(requiredInputContainerIndex).key() <<
")"
490 <<
". Not the current index " << inputContainerIndex <<
" (which is " <<
m_inputs.at(inputContainerIndex).key() <<
")");
503 for (
const auto&
entry: dmap){
505 const std::vector<ElementLink<DecisionContainer>>&
decisions =
entry.second;
508 ATH_MSG_DEBUG(
" Decision: (ContainerKey:"<<
d.dataID()<<
", DecisionElementIndex:"<<
d.index()<<
")");
515 return StatusCode::SUCCESS;