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;
166 const std::vector<int>& multiplicityPerLeg =
m.second;
170 allDecisionIds.insert(requiredDecisionID);
172 bool overallDecision =
true;
174 std::vector< SG::SGKeySet > legFeatureHashes;
175 legFeatureHashes.resize( multiplicityPerLeg.size() );
191 for (
size_t legIndex = 0; legIndex < multiplicityPerLeg.size(); ++legIndex ) {
192 const size_t requiredMultiplicity = multiplicityPerLeg.at( legIndex );
196 if (multiplicityPerLeg.size() > 1) {
197 ATH_MSG_DEBUG(chainId <<
" has multiplicityPerLeg.size() > 1, so we use legXXX_HLT_YYY, instead of HLT_YYY");
202 ATH_MSG_DEBUG(
"Container " << legIndex <<
", looking at leg : " << legId );
204 Combo::LegDecisionsMap::const_iterator
it = dmap.find(requiredDecisionIDLeg);
205 if (
it == dmap.end() ) {
210 const size_t nLegDecisionObjects =
it->second.size();
212 ATH_MSG_DEBUG(
"Will attempt to meet the required multiplicity of " << requiredMultiplicity <<
" for leg " << legId
213 <<
" with " << nLegDecisionObjects <<
" Decision Objects in leg " << legIndex <<
" of " << legId);
231 bool roiIsFullscan =
false;
232 bool objectRequestsNoMultiplicityCheck =
false;
233 ATH_CHECK(
extractFeatureAndRoI(
it->first, dEL, featureKey, featureIndex, roiKey, roiIndex, roiIsFullscan, objectRequestsNoMultiplicityCheck, priorFeaturesMap) );
234 const bool theFeatureIsTheROI = (
SG::sgkeyEqual (featureKey, roiKey) and featureIndex == roiIndex);
235 const bool thereIsNoFeatureYet = (featureKey == 0 and roiKey != 0);
236 if (objectRequestsNoMultiplicityCheck or (roiIsFullscan and (theFeatureIsTheROI or thereIsNoFeatureYet))) {
238 for (
size_t i = 0;
i < requiredMultiplicity; ++
i) {
239 legFeatureHashes.at( legIndex ).insert( ++passthroughCounter );
240 ATH_MSG_DEBUG(
" -- Add feature hash '" << passthroughCounter <<
"' to leg " << legIndex
241 <<
". (Note: unique passing hash generated from " << (objectRequestsNoMultiplicityCheck ?
"an object requesting NO multiplicity checks" :
"an FullScan ROI") <<
")");
244 const SG::sgkey_t uniquenessHash = (featureKey != 0 ? (featureKey + featureIndex) : (roiKey + roiIndex));
245 legFeatureHashes.at( legIndex ).insert( uniquenessHash );
246 ATH_MSG_DEBUG(
" -- Add feature hash '" << uniquenessHash <<
"' to leg " << legIndex <<
".");
251 thisChainCombMap.insert (*
it);
252 allDecisionIds.insert(requiredDecisionIDLeg);
260 size_t emergencyBreak = 0;
262 bool somethingChanged =
false;
264 for (
auto const& [
key, payloadSet] : priorFeaturesMap) {
265 if (payloadSet.count(legHash) == 1) {
266 ATH_MSG_DEBUG(
"Feature hash=" << legHash <<
" identified as a prior feature of hash=" <<
key
267 <<
", we will up-cast this hash to the later version for ComboHypo uniqueness comparison purposes.");
268 legHashes.erase(legHash);
269 legHashes.insert(
key);
272 somethingChanged =
true;
276 if (somethingChanged) {
280 if (!somethingChanged or ++emergencyBreak == 500) {
281 if (emergencyBreak == 500) {
295 std::set<SG::sgkey_t> allFeatureHashes;
296 for (
const SG::SGKeySet& legHashes : legFeatureHashes) {
297 allFeatureHashes.insert(legHashes.begin(), legHashes.end());
299 for (
const SG::sgkey_t featureHash : allFeatureHashes) {
300 size_t legsWithHash = 0;
301 size_t keepLegIndex = 0;
303 for (
size_t legIndex = 0; legIndex < multiplicityPerLeg.size(); ++legIndex) {
304 if (legFeatureHashes.at(legIndex).count(featureHash) == 0) {
308 const int32_t requiredMultiplicity = multiplicityPerLeg.at(legIndex);
309 const int32_t currentMultiplicity = legFeatureHashes.at(legIndex).size();
310 const int32_t safetyMargin = currentMultiplicity - requiredMultiplicity;
311 if (safetyMargin < keepLegMargin) {
312 keepLegMargin = safetyMargin;
313 keepLegIndex = legIndex;
316 if (legsWithHash == 1) {
320 for (
size_t legIndex = 0; legIndex < multiplicityPerLeg.size(); ++legIndex) {
321 if (legIndex == keepLegIndex) {
322 ATH_MSG_DEBUG(
"Keeping feature hash '" << featureHash <<
"', on leg " << legIndex <<
". This leg can least afford to lose it. "
323 <<
"Leg has " << legFeatureHashes.at(legIndex).size()
324 <<
" features, and a multiplicity requirement of " << multiplicityPerLeg.at(legIndex));
327 if (legFeatureHashes.at(legIndex).erase(featureHash)) {
328 ATH_MSG_DEBUG(
"Removed duplicate feature hash '" << featureHash <<
"', from leg " << legIndex <<
". Leg now has " << legFeatureHashes.at(legIndex).size()
329 <<
" remaining features, and a multiplicity requirement of " << multiplicityPerLeg.at(legIndex));
335 for (
size_t legIndex = 0; legIndex < multiplicityPerLeg.size(); ++legIndex) {
336 const size_t requiredMultiplicity = multiplicityPerLeg.at(legIndex);
337 const size_t currentMultiplicity = legFeatureHashes.at(legIndex).size();
338 if (currentMultiplicity < requiredMultiplicity) {
339 ATH_MSG_DEBUG(
"Leg " << legIndex <<
" fails multiplicity check. Required unique features:" << requiredMultiplicity <<
", found unique features: " << currentMultiplicity);
340 overallDecision =
false;
346 ATH_MSG_DEBUG(
"Chain " << chainId << ( overallDecision ?
" is accepted" :
" is rejected") <<
" after multiplicity requirements" );
347 if ( overallDecision ==
true ) {
348 for (
auto decID: allDecisionIds) {
350 passingLegs.insert (thisChainCombMap.begin(), thisChainCombMap.end());
356 if (passingLegs.size()!=0){
367 for (
auto const& [
id,
decisions] : passingLegs) {
375 return StatusCode::SUCCESS;
386 bool& objectRequestsNoMultiplicityCheck,
387 SG::SGKeyMap<std::set<uint32_t>>& priorFeaturesMap)
const
398 ATH_MSG_ERROR(
"We are only expecting to search from a single navigation node in extractFeatureAndRoI");
399 return StatusCode::FAILURE;
403 std::vector<SG::sgkey_t>
keys;
404 std::vector<uint32_t> clids;
405 std::vector<Decision::index_type> indicies;
406 std::vector<const Decision*> sources;
408 std::set<const Decision*> fullyExploredFrom;
413 const Decision* featureSource =
nullptr;
416 featureKey =
keys.at(0);
417 featureIndex = indicies.at(0);
418 featureSource = sources.at(0);
421 objectRequestsNoMultiplicityCheck = (featureSource and featureSource->
hasDetail<int32_t>(
"noCombo") and featureSource->
getDetail<int32_t>(
"noCombo") == 1);
423 if (foundFeature and priorFeaturesMap.count(featureKey + featureIndex) == 0) {
424 const std::string* key_str =
evtStore()->keyToString(featureKey);
425 ATH_MSG_DEBUG(
"Note: Will use feature hash " << featureKey + featureIndex <<
", for " << (key_str ? *key_str :
"UNKNOWN") <<
" index=" << featureIndex);
428 if (
keys.size() > 1) {
429 for (
size_t i = 1;
i <
keys.size(); ++
i) {
431 if (featureKey + featureIndex ==
keys.at(
i) + indicies.at(
i)) {
434 priorFeaturesMap[featureKey + featureIndex].insert(
keys.at(
i) + indicies.at(
i));
437 priorFeaturesMap.insert( std::pair<
uint32_t, std::set<uint32_t>>(featureKey + featureIndex, std::set<uint32_t>()) );
448 roiIsFullscan = (*(roiEL))->isFullscan();
450 const std::string* roi_str =
evtStore()->keyToString(roiKey);
451 ATH_MSG_DEBUG(
"Note: Located fallback-ROI, if used this will have feature hash =" << roiKey + roiIndex <<
", for " << (roi_str ? *roi_str :
"UNKNOWN") <<
" index=" << roiIndex);
455 if (!foundFeature && !foundROI) {
459 return StatusCode::SUCCESS;
464 for (
size_t inputContainerIndex = 0; inputContainerIndex <
m_inputs.size(); ++inputContainerIndex ) {
466 if ( !inputHandle.isValid() ) {
467 ATH_MSG_ERROR(
"No input ReadHandle from " << inputHandle.key() );
468 return StatusCode::FAILURE;
470 ATH_MSG_DEBUG(
"-- Found ReadHandle from " << inputHandle.key() <<
" with "<< inputHandle->size() <<
" elements:" );
471 for (
const Decision* decision : *inputHandle ) {
472 ATH_MSG_DEBUG(
"-- -- Input Decision #"<< decision->index() <<
" with "<<
decisionIDs( decision ).
size() <<
" active IDs. Populating the multiplicity map:" );
475 int32_t chainLeg = 0;
484 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.");
489 const std::vector<int>& legToInputCollectionIndex =
it->second;
490 const size_t requiredInputContainerIndex =
static_cast<size_t>(legToInputCollectionIndex.at(chainLeg));
491 if (requiredInputContainerIndex != inputContainerIndex) {
492 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()
493 <<
" which come from input collection index " << requiredInputContainerIndex <<
" (which is " <<
m_inputs.at(requiredInputContainerIndex).key() <<
")"
494 <<
". Not the current index " << inputContainerIndex <<
" (which is " <<
m_inputs.at(inputContainerIndex).key() <<
")");
507 for (
const auto&
entry: dmap){
509 const std::vector<ElementLink<DecisionContainer>>&
decisions =
entry.second;
512 ATH_MSG_DEBUG(
" Decision: (ContainerKey:"<<
d.dataID()<<
", DecisionElementIndex:"<<
d.index()<<
")");
519 return StatusCode::SUCCESS;