5 #include <boost/functional/hash.hpp>
6 #include <GaudiKernel/StatusCode.h>
7 #include "AthLinks/ElementLinkVector.h"
25 teIDs.push_back(te->getId());
87 auto add = [](
ConvProxy *toadd, std::set<ConvProxy *> &coll)
89 if (
std::find(coll.begin(), coll.end(), toadd) == coll.end())
97 auto place =
std::find(coll.begin(), coll.end(), torem);
98 if (place != coll.end())
105 for (
auto otherChild :
other->children)
108 add(
this, otherChild->parents);
111 for (
auto otherParent :
other->parents)
114 add(
this, otherParent->children);
118 for (
auto otherParent :
other->parents)
123 for (
auto otherChild :
other->children)
127 other->children.clear();
128 other->parents.clear();
136 std::ostringstream
os;
139 ret +=
" ptrs: " +
os.str();
161 ATH_MSG_INFO(
"Will use Trigger Navigation from TrigDecisionTool");
166 ATH_MSG_INFO(
"Will use Trigger Navigation decoded from TrigNavigation object");
183 std::string collName;
184 size_t delimeterIndex =
name.find(
'#');
185 if (delimeterIndex != std::string::npos)
188 collName =
name.substr(delimeterIndex + 1);
193 if ( collName.empty() )
207 if (keysSet.size() > 1 and keysSet.count(
"") != 0)
209 ATH_MSG_ERROR(
"Bad configuration for CLID " << clid <<
" requested saving of all (empty coll name configures) collections, yet there are also specific keys");
210 return StatusCode::FAILURE;
215 bool anyChainBad=
false;
217 if (
chain.find(
'*') != std::string::npos or
chain.find(
'|') != std::string::npos ) {
218 ATH_MSG_ERROR(
"Supplied chain name: " <<
chain <<
" contains wildcard characters, this is not supported by the conversion tool");
223 ATH_MSG_ERROR(
"Supplied chain names contain wildcard characters, this is not supported by the conversion tool");
224 return StatusCode::FAILURE;
227 ATH_MSG_INFO(
"No chains list supplied, the conversion will occur for all chains");
245 return StatusCode::SUCCESS;
250 return StatusCode::SUCCESS;
270 standaloneNav.
deserialize(navReadHandle->serialized());
271 run2NavigationPtr = &standaloneNav;
275 run2NavigationPtr =
m_tdt->ExperimentalAndExpertMethods().getNavigation();
299 ATH_MSG_DEBUG(
"Removed proxies to chains that are not converted, remaining number of elements " << convProxies.size());
314 auto decisionOutput = outputNavigation.
ptr();
337 ATH_MSG_DEBUG(
"Conversion done, from " << convProxies.size() <<
" elements to " << decisionOutput->size() <<
" elements");
343 for (
auto o: *decisionOutput) {
349 for (
auto proxy : convProxies)
354 return StatusCode::SUCCESS;
368 size_t stepToConsider = 0;
369 const size_t sigsSize = ptrChain->
signatures().size();
370 if ( sigsSize < 2 )
return 0;
373 stepToConsider =
step;
377 if ( stepToConsider == 0 )
return 0;
380 auto finalTE = (ptrChain->
signatures()[stepToConsider])->outputTEs()[0];
381 auto preFinalTEs = (ptrChain->
signatures()[stepToConsider-1])->outputTEs();
383 auto finalSeq =
m_configSvc->sequences().getSequence(finalTE->id());
384 std::set<HLT::te_id_type> tesInSeq;
385 std::set<HLT::te_id_type> tesInChain;
387 for (
auto te: finalSeq->inputTEs()) {
388 tesInSeq.insert(te->id());
391 for (
auto te: preFinalTEs) {
392 tesInChain.insert(te->id());
395 if (tesInSeq == tesInChain) {
396 return stepToConsider;
409 std::string
chainName = ptrChain->name();
428 std::map<HLT::te_id_type, HLT::te_id_type> etcutReplacementTEs;
429 auto etcutReplacement = [&etcutReplacementTEs](
HLT::te_id_type in) {
auto out = etcutReplacementTEs.find(in);
return (
out == etcutReplacementTEs.end() ? in :
out->second ); };
430 if (
chainName.find(
"etcut") != std::string::npos ) {
431 std::set<size_t> positionsOfEtCutLegs;
434 ATH_MSG_DEBUG(
"EtCut chains hack, chain with two etcut legs ");
435 positionsOfEtCutLegs.insert({0, 1});
437 ATH_MSG_DEBUG(
"EtCut chains hack, egamma chain with second etcut leg ");
438 positionsOfEtCutLegs.insert({1});
441 positionsOfEtCutLegs.insert({0});
445 std::map<size_t, HLT::te_id_type> positionToDesiredIDmap;
446 for (
auto ptrHLTSignature : ptrChain->signatures()) {
448 for (
auto ptrHLTTE : ptrHLTSignature->outputTEs()) {
449 if (positionsOfEtCutLegs.count(position) and positionToDesiredIDmap.find(position) != positionToDesiredIDmap.end() ) {
450 etcutReplacementTEs[ptrHLTTE->id()] = positionToDesiredIDmap[position];
453 if ( ptrHLTTE->name().find(
"calocalib") != std::string::npos and positionsOfEtCutLegs.count(position) ) {
454 positionToDesiredIDmap[position] = ptrHLTTE->id();
465 for (
auto ptrHLTSignature : ptrChain->signatures()) {
466 for (
auto ptrHLTTE : ptrHLTSignature->outputTEs()) {
467 unsigned int teId = etcutReplacement(ptrHLTTE->id());
468 allTEs[
teId].insert(chainId);
469 if (ptrHLTSignature == ptrChain->signatures().back()) {
470 finalTEs[
teId].insert(chainId);
471 ATH_MSG_DEBUG(
"TE will be used to mark final chain decision " << ptrHLTTE->name() <<
" chain " <<
chainName );
490 std::vector<size_t> mult_hack;
493 ptrChain->set_leg_multiplicities(mult_hack);
498 std::vector<size_t> mult_hack;
501 ptrChain->set_leg_multiplicities(mult_hack);
505 std::vector<unsigned int> teIdsLastHealthyStepIds;
507 for (
auto ptrHLTSignature : ptrChain->signatures())
509 std::vector<int> teCounts;
510 std::vector<unsigned int> teIds;
511 unsigned int lastSeenId = 0;
512 for (
auto ptrHLTTE : ptrHLTSignature->outputTEs())
514 if ( lastSeenId != ptrHLTTE->id()) {
515 teCounts.push_back(1);
516 teIds.push_back(ptrHLTTE->id());
520 lastSeenId = ptrHLTTE->id();
523 ATH_MSG_DEBUG(
"TE multiplicities seen in this step " << teCounts);
527 if ( multiplicityCounts ) {
528 teIdsLastHealthyStepIds = teIds;
529 ATH_MSG_DEBUG(
"There is a match, will assign chain leg IDs to TEs " << teCounts <<
" " << teIds);
530 for (
size_t legNumber = 0; legNumber < teIds.size(); ++ legNumber){
532 allTEs[etcutReplacement(teIds[legNumber])].insert(chainLegId);
536 for (
size_t legNumber = 0; legNumber < teIdsLastHealthyStepIds.size(); ++ legNumber ) {
539 ATH_MSG_DEBUG(
"created leg id " << chainLegId <<
" that will replace TE ID " << etcutReplacement(teIdsLastHealthyStepIds[legNumber]));
540 finalTEs[etcutReplacement(teIdsLastHealthyStepIds[legNumber])].insert(chainLegId);
544 ATH_MSG_DEBUG(
"Recognised " << allTEs.size() <<
" kinds of TEs and among them " << finalTEs.size() <<
" final types");
545 return StatusCode::SUCCESS;
551 std::vector<unsigned int> muons;
552 std::vector<unsigned int>
jets;
553 bool switchedTojets =
false;
554 for (
auto ptrHLTSignature : ptrChain->
signatures()) {
555 for (
auto ptrHLTTE : ptrHLTSignature->outputTEs()) {
556 if ( ptrHLTTE->name().find(
"_mu") == std::string::npos ) {
557 switchedTojets =
true;
561 jets.push_back(ptrHLTTE->id());
563 muons.push_back(ptrHLTTE->id());
571 finalTEs[muons[0]].insert(chainId);
573 finalTEs[
jets[0]].insert(chainId);
578 allTEs[muons[
index]].insert(chainId);
582 return StatusCode::SUCCESS;
591 std::map<const HLT::TriggerElement *, ConvProxy *> teToProxy;
599 convProxies.insert(
proxy);
600 teToProxy[te] =
proxy;
604 ConvProxy *predecessorProxy = teToProxy[predecessor];
605 if (predecessorProxy !=
nullptr)
607 proxy->parents.insert(predecessorProxy);
616 for (
auto proxy : convProxies)
620 for (
auto p :
proxy->children)
622 for (
auto p :
proxy->parents)
625 for (
auto p :
proxy->parents)
627 for (
auto pp :
p->parents)
635 for (
auto c :
proxy->children)
637 for (
auto cc :
c->children)
648 ATH_MSG_DEBUG(
"Created " << convProxies.size() <<
" proxy objects");
649 return StatusCode::SUCCESS;
655 const std::vector<std::function<
void(
const ConvProxy*)>>& printers)
const {
658 for (
auto p: proxies) {
661 for (
auto& printer: printers) {
672 for (
auto &ptrConvProxy : convProxies)
674 auto teId = ptrConvProxy->te->getId();
675 bool teActive = ptrConvProxy->te->getActiveState();
677 if (
iter != allTEs.end())
679 ptrConvProxy->runChains.insert(
iter->second.begin(),
iter->second.end());
682 ptrConvProxy->passChains.insert(
iter->second.begin(),
iter->second.end());
686 for (
auto &objTeIdToChain : allTEs)
688 if (
teId == objTeIdToChain.first)
690 for (
auto &chainId : objTeIdToChain.second)
692 (ptrConvProxy->runChains).insert(chainId);
698 return StatusCode::SUCCESS;
709 size_t numberOfUpdates = 0;
710 for (
auto p : convProxies)
712 for (
auto child :
p->children)
714 size_t startSize =
p->runChains.size();
717 if (startSize !=
p->runChains.size())
725 ATH_MSG_DEBUG(
"Needed to propagate chains from " << numberOfUpdates <<
" child(ren)");
726 if (numberOfUpdates == 0)
731 return StatusCode::SUCCESS;
739 if ((*i)->runChains.empty())
745 parent->children.erase(toDel);
749 child->parents.erase(toDel);
752 i = convProxies.erase(
i);
759 ATH_MSG_DEBUG(
"After eliminating proxies not associated to chainsof intereset left with " << convProxies.size());
760 return StatusCode::SUCCESS;
775 return StatusCode::SUCCESS;
778 template <
typename MAP>
782 std::vector<ConvProxy *> todelete;
783 for (
auto &[
key, proxies] : keyToProxyMap)
785 if (proxies.size() > 1)
787 ATH_MSG_DEBUG(
"Merging " << proxies.size() <<
" similar proxies");
788 for (
auto p : proxies)
790 if (
p->mergeAllowed(*proxies.begin()))
792 (*proxies.begin())->
merge(
p);
793 todelete.push_back(
p);
799 for (
auto proxy : todelete)
801 convProxies.erase(
proxy);
805 return StatusCode::SUCCESS;
811 const size_t beforeCount = convProxies.size();
812 std::map<uint64_t, ConvProxySet_t> feaToProxyMap;
813 for (
auto proxy : convProxies)
826 for (
auto [feaHash, proxies] : feaToProxyMap)
828 auto first = *proxies.begin();
829 for (
auto p : proxies)
832 filterFEAs(
p->te->getFeatureAccessHelpers(), run2Nav))
834 ATH_MSG_ERROR(
"Proxies grouped by FEA hash have actually distinct features (specific FEAs are different)");
835 for (
auto id:
p->passChains )
ATH_MSG_ERROR(
"... chain id for this proxy " <<
id);
837 for (
auto fea:
first->te->getFeatureAccessHelpers() ) {
840 for (
auto fea:
p->te->getFeatureAccessHelpers() ) {
844 return StatusCode::FAILURE;
851 ATH_MSG_DEBUG(
"Proxies with features collapsing reduces size from " << beforeCount <<
" to " << convProxies.size());
853 return StatusCode::SUCCESS;
859 struct ParentChildCharacteristics
863 size_t distanceFromParent = 0;
864 bool operator<(
const ParentChildCharacteristics &rhs)
const
867 return parent < rhs.parent;
868 if (child != rhs.child)
869 return child < rhs.child;
870 return distanceFromParent < rhs.distanceFromParent;
873 const size_t beforeCount = convProxies.size();
874 std::map<ParentChildCharacteristics, ConvProxySet_t> groupedProxies;
875 for (
auto proxy : convProxies)
888 if (
proxy->children.size() == 1 and
889 std::all_of(
proxy->children.begin(),
proxy->children.end(), hasSomeFeatures ) and
890 proxy->parents.size() == 1 and
891 std::all_of(
proxy->parents.begin(),
proxy->parents.end(), hasSomeFeatures )
895 groupedProxies[{*(
proxy->parents.begin()), *(
proxy->children.begin()), 0}].insert(
proxy);
902 for (
auto pp :
proxy->parents)
907 for (
auto cp :
proxy->children)
916 ATH_MSG_DEBUG(
"Proxies without features collapsing reduces size from " << beforeCount <<
" to " << convProxies.size());
917 return StatusCode::SUCCESS;
924 if ((*i)->parents.size() > 1)
930 parent->children.erase(toDel);
934 child->parents.erase(toDel);
937 i = convProxies.erase(
i);
944 return StatusCode::SUCCESS;
950 for (
auto &
proxy : convProxies)
952 if (
proxy->te !=
nullptr)
969 if (expectedCLID != 0 && sgCLID != expectedCLID)
971 ATH_MSG_VERBOSE(
"Skipping feature with CLID " << sgCLID <<
" (name: " << sgName
972 <<
") for TE " <<
teName <<
" because expected CLID is " << expectedCLID);
976 ATH_MSG_VERBOSE(
"Added feature with CLID " << sgCLID <<
" (name: " << sgName <<
") for TE " <<
teName);
983 return StatusCode::SUCCESS;
990 auto ordered_sorter = [&setRoiName = std::as_const(
m_setRoiName)](
const std::string &left,
const std::string &right) ->
bool
992 return std::find(cbegin(setRoiName), cend(setRoiName), left) <
std::find(cbegin(setRoiName), cend(setRoiName), right);
997 for (
auto &
proxy : convProxies)
1001 ATH_MSG_DEBUG(
"Several RoIs pointing to a proxy, taking latest one for now");
1017 [](
const std::map<std::string, HLT::TriggerElement::FeatureAccessHelper>::value_type &
p)
1018 { return p.second; });
1022 std::set<const ConvProxy*> visited;
1023 std::function<void(std::set<ConvProxy *> &,
const std::vector<HLT::TriggerElement::FeatureAccessHelper> &)>
1024 roiPropagator = [&](std::set<ConvProxy *> &convProxyChildren,
const std::vector<HLT::TriggerElement::FeatureAccessHelper> &roiParent)
1026 for (
auto &proxyChild : convProxyChildren)
1028 if ( visited.count(proxyChild) == 1 ) {
1031 visited.insert(proxyChild);
1032 if (proxyChild->rois.empty())
1034 proxyChild->rois = roiParent;
1035 if (proxyChild->children.empty() ==
false)
1037 roiPropagator(proxyChild->children, roiParent);
1043 for (
auto &
proxy : convProxies)
1048 return StatusCode::SUCCESS;
1053 for (
auto &
proxy : convProxies)
1064 return StatusCode::SUCCESS;
1069 for (
auto &
proxy : convProxies)
1072 for (
auto chainId :
proxy->runChains)
1077 for (
auto chainId :
proxy->passChains)
1085 for (
auto &
proxy : convProxies)
1087 for (
auto &parentProxy :
proxy->parents)
1093 return StatusCode::SUCCESS;
1103 sfNode->setName(
"SF");
1106 for (
auto chainId : chainIds)
1113 else if (chainId.numeric() == idStore)
1123 if (
proxy->hNode.empty())
1126 makeSingleSFNode(
proxy->imNode,
proxy->runChains, idToStore);
1131 for (
auto &hNode :
proxy->hNode)
1133 makeSingleSFNode(hNode,
proxy->passChains, idToStore);
1138 for (
auto proxy : convProxies)
1141 if (
proxy->children.empty())
1149 std::vector<TCU::DecisionID> toRetain;
1152 auto whereInMap = terminalIds.find(
teId);
1153 if (whereInMap != terminalIds.end())
1155 toRetain.insert(toRetain.end(), whereInMap->second.begin(), whereInMap->second.end());
1158 for (
auto chainIdstore : toRetain)
1160 makeSFNodes(
proxy, chainIdstore);
1167 return StatusCode::SUCCESS;
1190 return StatusCode::FAILURE;
1195 filteredIDs.insert(idToCheck);
1198 terminus->
setDecisions( std::vector<TCU::DecisionID>() );
1201 "the terminus node goes from " << currentIDs.size() <<
" to " << filteredIDs.size() <<
" chain IDs.");
1209 return StatusCode::SUCCESS;
1213 const EventContext &context)
const
1216 auto makeL1Node = [&
decisions, &context](
auto firstDecisionNode,
auto chainIds)
1220 for (
auto chainId : chainIds)
1229 for (
auto &
proxy : convProxies)
1232 if (
proxy->parents.empty())
1239 return StatusCode::SUCCESS;
1245 if (
proxy.features.empty())
1249 for (
const auto &fea :
proxy.features)
1251 if (fea.getIndex().objectsBegin() == fea.getIndex().objectsEnd())
1255 for (
auto n = fea.getIndex().objectsBegin();
n < fea.getIndex().objectsEnd(); ++
n)
1267 for (
const auto &
proxy : convProxies)
1277 for (
auto chainId :
proxy->passChains)
1284 for (
auto &childProxy :
proxy->children)
1291 if (
proxy->features.empty())
1297 auto hNodeIter =
proxy->hNode.begin();
1298 for (std::size_t feaIdx = 0; feaIdx <
proxy->features.size(); ++feaIdx)
1300 auto &fea =
proxy->features[feaIdx];
1301 auto [sgKey, sgCLID, sgName] =
getSgKey(run2Nav, fea);
1303 if (fea.getIndex().objectsBegin() == fea.getIndex().objectsEnd())
1309 for (
auto n = fea.getIndex().objectsBegin();
n < fea.getIndex().objectsEnd(); ++
n)
1312 const std::string& linkName = (feaIdx == bestFeaIdx &&
n == bestObjIdx) ?
1314 (*hNodeIter)->typelessSetObjectLink(linkName, sgKey, sgCLID,
n,
n + 1);
1320 return StatusCode::SUCCESS;
1326 for (
auto &
proxy : convProxies)
1328 for (
auto &roi :
proxy->rois)
1330 auto [sgKey, sgCLID, sgName] =
getSgKey(run2Nav, roi);
1335 if (
proxy->rois.empty() ==
false)
1342 return StatusCode::SUCCESS;
1347 for (
auto &
proxy : convProxies)
1349 for (
auto &trk :
proxy->tracks)
1359 auto [sgKey, sgCLID, sgName] =
getSgKey(run2Nav, trk);
1363 auto d = std::make_unique<TrigCompositeUtils::Decision>();
1364 d->makePrivateStore();
1365 d->typelessSetObjectLink(tName, sgKey, sgCLID, trk.getIndex().objectsBegin());
1370 if (
track.isValid())
1373 viewBookkeeper(*
t) = ROIElementLink;
1381 if (
track.isValid())
1384 viewBookkeeper(*
t) = ROIElementLink;
1391 ATH_MSG_WARNING(
"Unable to create an ElementLink into a container with no entries");
1397 return StatusCode::SUCCESS;
1406 return fea.
getCLID() == thePassBitsCLID or fea.
getCLID() == thePassBitsContCLID;
1410 std::vector<HLT::TriggerElement::FeatureAccessHelper>
out;
1411 for (
auto fea : feaVector)
1419 auto [sgKey, sgCLID, sgName] =
getSgKey(navigationDecoder, fea);
1423 ATH_MSG_VERBOSE(
"Skipping unrecorded (missing in SG) FEA hash calculation - name in SG: " << sgName <<
" FEA " << fea);
1440 for (
auto fea :
filterFEAs(feaVector, navigationDecoder))
1442 const auto & [sgKey, sgCLID, sgName] =
getSgKey(navigationDecoder, fea);
1445 if (expectedCLID != 0 && sgCLID != expectedCLID)
1448 <<
" (expected " << expectedCLID <<
")");
1452 ATH_MSG_VERBOSE(
"Including FEA in hash CLID: " << fea.getCLID() <<
" te Id: " << te_ptr->
getId());
1453 boost::hash_combine(
hash, fea.getCLID());
1454 boost::hash_combine(
hash, fea.getIndex().subTypeIndex());
1455 boost::hash_combine(
hash, fea.getIndex().objectsBegin());
1456 boost::hash_combine(
hash, fea.getIndex().objectsEnd());
1463 boost::hash_combine(
hash, te_ptr->
getId());
1464 boost::hash_combine(
hash,
reinterpret_cast<std::uintptr_t
>(te_ptr));
1474 if (
iter->second.empty() )
1476 ATH_MSG_DEBUG(
"fea to save CLID: " << fea.
getCLID() <<
", sgName: " << sgName <<
" " <<
iter->second.size() <<
" " <<
iter->second.empty() );
1477 return iter->second.contains(sgName);
1487 auto [sgKey, sgCLID, sgName] =
getSgKey(run2Nav, roi);
1498 for (
auto p : proxies)
1500 if (
p->runChains.empty())
1503 return StatusCode::FAILURE;
1507 return StatusCode::SUCCESS;
1512 for (
auto p : proxies)
1514 if (
p->children.empty() and
p->parents.empty() and not
p->runChains.empty())
1516 ATH_MSG_ERROR(
"Orphanted proxy N chains run:" <<
p->runChains.size());
1517 return StatusCode::FAILURE;
1521 return StatusCode::SUCCESS;
1526 ATH_MSG_DEBUG(
"CHECK OK, no excessive number of H nodes per proxy");
1527 return StatusCode::SUCCESS;
1533 std::set<const TrigCompositeUtils::Decision *> linkedHNodes;
1536 if (
d->name() ==
"IM" or
d->name() ==
"FS")
1540 linkedHNodes.insert(*
el);
1546 if (
d->name() ==
"H")
1548 if (linkedHNodes.count(
d) == 0)
1551 return StatusCode::FAILURE;
1557 return StatusCode::SUCCESS;
1562 const std::string hltLabel = navigationDecoder.
label(
helper.getCLID(),
helper.getIndex().subTypeIndex());
1564 const CLID saveCLID = [&](
const CLID &clid)
1575 std::string type_name;
1576 if (
m_clidSvc->getTypeNameOfID(saveCLID, type_name).isFailure())
1586 return {0, saveCLID,
""};
1589 return {
evtStore()->stringToKey(sgStringKey, saveCLID), saveCLID, hltLabel};
1596 std::size_t bestObj = 0;
1597 float bestPt = -1.0;
1599 for (std::size_t
i = 0;
i <
proxy.features.size(); ++
i) {
1600 const auto& fea =
proxy.features[
i];
1601 auto [sgKey, sgCLID, sgName] =
getSgKey(run2Nav, fea);
1605 if (sgKey == 0)
continue;
1606 const std::string* keyStr =
evtStore()->keyToString(sgKey, sgCLID);
1607 if (!keyStr)
continue;
1610 for (
auto n = fea.getIndex().objectsBegin();
n < fea.getIndex().objectsEnd(); ++
n) {
1611 if (
n >= cont->
size())
continue;
1614 if (
p->pt() > bestPt) {
1622 for (std::size_t
i = 0;
i <
proxy.features.size(); ++
i) {
1623 auto [sgKey, sgCLID, sgName] =
getSgKey(run2Nav,
proxy.features[
i]);
1626 bestObj =
proxy.features[
i].getIndex().objectsBegin();
1630 return {bestFea, bestObj};
1640 if (
teName.find(
"etcut") != std::string::npos &&
1641 teName.find(
"trkcut") == std::string::npos) {
1645 else if (
teName.rfind(
"EF_e", 0) == 0) {
1649 else if (
teName.rfind(
"EF_g", 0) == 0) {
1653 else if (
teName.rfind(
"EF_mu", 0) == 0 ||
teName.find(
"_mu") != std::string::npos) {
1657 else if (
teName.rfind(
"EF_tau", 0) == 0 ||
teName.find(
"_tau") != std::string::npos) {