diff --git a/Event/FourMomUtils/FourMomUtils/xAODP4Helpers.h b/Event/FourMomUtils/FourMomUtils/xAODP4Helpers.h index 5364bc0a316312a47a77acbbf0b8bb85ffe465ce..199929b513dc8088fa2a2acd905209cfb20b81da 100644 --- a/Event/FourMomUtils/FourMomUtils/xAODP4Helpers.h +++ b/Event/FourMomUtils/FourMomUtils/xAODP4Helpers.h @@ -106,18 +106,24 @@ namespace xAOD + /// @f$ \Delta{R}^2 @f$ from bare rapidity,phi + inline + double deltaR2( double rapidity1, double phi1, double rapidity2, double phi2 ) + { + const double dPhi = xAOD::P4Helpers::deltaPhi( phi1, phi2 ); + const double dRapidity = rapidity1-rapidity2; + return dRapidity*dRapidity + dPhi*dPhi; + } + /// @f$ \Delta{R}^2 @f$ from 1 @c xAOD::IParticle inline double deltaR2( const xAOD::IParticle& p4, double rapidity, double phi, bool useRapidity=true ) { - const double dPhi = xAOD::P4Helpers::deltaPhi( p4, phi ); if (useRapidity) { - const double dRapidity = p4.rapidity() - rapidity; - return dRapidity*dRapidity + dPhi*dPhi; + return xAOD::P4Helpers::deltaR2(p4.rapidity(),p4.phi(),rapidity,phi); } else { - const double dEta = p4.eta() - rapidity; - return dEta*dEta + dPhi*dPhi; + return xAOD::P4Helpers::deltaR2(p4.eta(),p4.phi(),rapidity,phi); } } @@ -125,24 +131,24 @@ namespace xAOD inline double deltaR2( const xAOD::IParticle& pA, const xAOD::IParticle& pB, bool useRapidity=true ) { - const double dPhi = xAOD::P4Helpers::deltaPhi( pA, pB ); - const double dPhiSq = dPhi*dPhi; if (useRapidity) { - const double dRapidity = xAOD::P4Helpers::deltaRapidity( pA, pB ); - return dRapidity*dRapidity + dPhiSq; + return xAOD::P4Helpers::deltaR2(pA.rapidity(),pA.phi(),pB.rapidity(),pB.phi()); } else { - const double dEta = xAOD::P4Helpers::deltaEta( pA, pB ); - return dEta*dEta + dPhiSq; + return xAOD::P4Helpers::deltaR2(pA.eta(),pA.phi(),pB.eta(),pB.phi()); } } - /** delta R from two xAOD::IParticle pointers */ + /** delta R^2 from two xAOD::IParticle pointers */ inline double deltaR2( const xAOD::IParticle * const pA, const xAOD::IParticle * const pB, bool useRapidity=true ) { return xAOD::P4Helpers::deltaR2( *pA, *pB, useRapidity ); } + /// @f$ \Delta{R} @f$ from bare bare rapidity,phi + inline + double deltaR( double rapidity1, double phi1, double rapidity2, double phi2 ) + { return std::sqrt( xAOD::P4Helpers::deltaR2( rapidity1, phi1, rapidity2, phi2 ) ); } /// @f$ \Delta{R} @f$ from 1 @c xAOD::IParticle inline diff --git a/Trigger/TrigHypothesis/TrigHypoCommonTools/CMakeLists.txt b/Trigger/TrigHypothesis/TrigHypoCommonTools/CMakeLists.txt index c36e7f111374f22bbaaaef2012bad4000379db4b..4a6be0796776cd00fe1cfc4ca5c9e212bb3f88a7 100644 --- a/Trigger/TrigHypothesis/TrigHypoCommonTools/CMakeLists.txt +++ b/Trigger/TrigHypothesis/TrigHypoCommonTools/CMakeLists.txt @@ -3,11 +3,15 @@ # Declare the package name: atlas_subdir( TrigHypoCommonTools ) +# External reqs +find_package( ROOT COMPONENTS Core GenVector ) + # Component(s) in the package: atlas_add_component( TrigHypoCommonTools src/*.cxx src/components/*.cxx - LINK_LIBRARIES AsgTools AthLinks AthenaBaseComps AthenaMonitoringKernelLib DecisionHandlingLib GaudiKernel HLTSeedingLib TrigCompositeUtilsLib TrigT1Result xAODBase ) + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} AsgTools AthLinks AthenaBaseComps AthenaMonitoringKernelLib DecisionHandlingLib FourMomUtils GaudiKernel HLTSeedingLib TrigCompositeUtilsLib TrigT1Result xAODBase ) # Install files from the package: atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} --extend-extensions=ATL900,ATL901 ) diff --git a/Trigger/TrigHypothesis/TrigHypoCommonTools/src/TrigComboHypoTool.cxx b/Trigger/TrigHypothesis/TrigHypoCommonTools/src/TrigComboHypoTool.cxx index f456e6dd75e6bdda906e40e6d862ec0af52f46b1..761c0e828f7b821b5d9efd8659493abad21e3db6 100644 --- a/Trigger/TrigHypothesis/TrigHypoCommonTools/src/TrigComboHypoTool.cxx +++ b/Trigger/TrigHypothesis/TrigHypoCommonTools/src/TrigComboHypoTool.cxx @@ -3,26 +3,59 @@ */ #include "TrigComboHypoTool.h" +#include "GaudiKernel/SystemOfUnits.h" +#include <Math/Vector4D.h> // for LorentzVector +#include <Math/Vector4Dfwd.h> // PtEtaPhiM typedef +#include <Math/Vector2D.h> // for DisplacementVector +#include <Math/Vector2Dfwd.h> // Polar2DVectorF typedef + #include "xAODTrigMissingET/TrigMissingETContainer.h" +#include "FourMomUtils/xAODP4Helpers.h" #include <vector> +#include <algorithm> #include <cmath> +constexpr float invGeV = 1. / Gaudi::Units::GeV; + using namespace TrigCompositeUtils; +// Translate strings into enum values +const std::map<std::string, TrigComboHypoTool::ComboHypoVars> VarMap = { + {"dR", TrigComboHypoTool::ComboHypoVars::DR}, + {"invm", TrigComboHypoTool::ComboHypoVars::INVM}, + {"dphi", TrigComboHypoTool::ComboHypoVars::DPHI}, + {"mT", TrigComboHypoTool::ComboHypoVars::MT} +}; + TrigComboHypoTool::TrigComboHypoTool(const std::string& type, const std::string& name, const IInterface* parent) : ComboHypoToolBase(type, name, parent) {} -void TrigComboHypoTool::fillVarMap(){ - m_varMap["dR"] = comboHypoVars::DR; - m_varMap["invm"] = comboHypoVars::INVM; - m_varMap["dphi"] = comboHypoVars::DPHI; - m_varMap["mT"] = comboHypoVars::MT; + +bool TrigComboHypoTool::VarInfo::validate(std::string& errmsg) const { + if (legA==0){ + errmsg = "legA ID not set!"; + return false; + } + if (legB==0){ + errmsg="legB ID not set!"; + return false; + } + if ((!useMin) && (!useMax)){ + errmsg="Trying to configure the Tool without setting at least one of UseMin or UseMax!"; + return false; + } + if (legA==legB && (legA_is_MET || legB_is_MET)) { + errmsg = "Cannot specify the same MET leg for both sides!"; + return false; + } + return true; } + StatusCode TrigComboHypoTool::initialize() { ATH_MSG_DEBUG("Variable = " << m_varTag_vec ); @@ -36,235 +69,268 @@ StatusCode TrigComboHypoTool::initialize() ATH_CHECK( m_monTool_vec.retrieve() ); if (m_legA_vec.size() != m_legB_vec.size()) { - ATH_MSG_ERROR("Trying to configure the Tool with legA and legB with different size!"); + ATH_MSG_ERROR("Trying to configure the Tool with legA and legB vectors of different size!"); return StatusCode::FAILURE; } if (m_useMin_vec.size() != m_useMax_vec.size()) { - ATH_MSG_ERROR("Trying to configure the Tool with UseMin and UseMax with different size!"); + ATH_MSG_ERROR("Trying to configure the Tool with UseMin and UseMax vectors of different size!"); return StatusCode::FAILURE; } if (m_legA_vec.size() != m_useMax_vec.size()) { - ATH_MSG_ERROR("Trying to configure the Tool with legA/B and UseMax/Min with different size!"); + ATH_MSG_ERROR("Trying to configure the Tool with legA/B and UseMax/Min vectors of different size!"); return StatusCode::FAILURE; } if (m_varTag_vec.size() != m_useMax_vec.size()) { - ATH_MSG_ERROR("Trying to configure the Tool with varTag and UseMax/Min(LegA/B) with different size!"); + ATH_MSG_ERROR("Trying to configure the Tool with varTag and UseMax/Min(LegA/B) vectors of different size!"); return StatusCode::FAILURE; } - fillVarMap(); - for (size_t i=0; i<m_legA_vec.size(); ++i){ - if (m_legA_vec[i]==""){ - ATH_MSG_ERROR("Array of legA IDs not set!"); - return StatusCode::FAILURE; - } - if (m_legB_vec[i]==""){ - ATH_MSG_ERROR("Array of legB IDs not set!"); - return StatusCode::FAILURE; + for (size_t i=0; i<m_varTag_vec.size(); ++i){ + VarInfo info; + info.index = i; + if(!m_monTool_vec.empty()) { + info.monToolName = m_monTool_vec[i].name(); } - if ((!m_useMin_vec[i]) && (!m_useMax_vec[i])){ - ATH_MSG_ERROR("Trying to configure the Tool without setting UseMin and UseMax!"); + if (VarMap.find(m_varTag_vec[i]) == VarMap.end()){ + ATH_MSG_ERROR("The variable is not present in the ComboHypoVars list"); return StatusCode::FAILURE; } - if (m_varMap.find(m_varTag_vec[i]) == m_varMap.end()){ - ATH_MSG_ERROR("The variable is not present in the comboHypoVars list"); + info.varTag = (m_varTag_vec[i]); + info.var = VarMap.at(m_varTag_vec[i]); + // + info.useMin = m_useMin_vec[i]; + if(info.useMin) {info.varMin=m_varMin_vec[i];} + info.useMax = m_useMax_vec[i]; + if(info.useMax) {info.varMax=m_varMax_vec[i];} + // + info.legA = m_legA_vec[i]; + info.legA_is_MET = m_isLegA_MET_vec[i]; + info.legB = m_legB_vec[i]; + info.legB_is_MET = m_isLegB_MET_vec[i]; + info.legsAreEqual = info.legA==info.legB; + + std::string validmsg{""}; + if(!info.validate(validmsg)) { + ATH_MSG_ERROR(validmsg); return StatusCode::FAILURE; } - m_var_vec.push_back(m_varMap[m_varTag_vec[i]]); + + m_varInfo_vec.push_back(info); } ATH_MSG_DEBUG("Initialization completed successfully"); return StatusCode::SUCCESS; } -bool TrigComboHypoTool::executeAlg(const std::vector<Combo::LegDecision>& combination) const { + +bool TrigComboHypoTool::executeAlg(const Combination& combination) const { //loop over all the hypos - bool lastDecision(true); - std::vector<float> values; - values.reserve(m_varTag_vec.size()); + bool lastDecision(true); + std::vector<float> values; + values.reserve(m_varInfo_vec.size()); - for (size_t i=0; i<m_varTag_vec.size() && lastDecision; ++i){ - lastDecision = executeAlgStep(combination, i, values); + for (auto varInfo = m_varInfo_vec.cbegin(); varInfo!=m_varInfo_vec.cend() && lastDecision; ++varInfo){ + lastDecision = executeAlgStep(combination, *varInfo, values); } - - //now fill the monitoring histograms with the accepted values - for (size_t i=0; i<m_varTag_vec.size() && lastDecision; ++i){ - std::string monToolName=m_varTag_vec[i]; - if (m_varTag_vec.size()>1){ - monToolName = monToolName + m_legA_vec[i] + m_legB_vec[i]; + + // Monitoring of variables for only accepted events + if(lastDecision && !m_monTool_vec.empty()) { + for (auto varInfo = m_varInfo_vec.cbegin(); varInfo!=m_varInfo_vec.cend(); ++varInfo){ + float value = values[varInfo->index]; + auto varOfAccepted = Monitored::Scalar(varInfo->monToolName+"OfAccepted", value ); + auto monitorIt = Monitored::Group (m_monTool_vec[varInfo->index], varOfAccepted); + ATH_MSG_DEBUG( varInfo->varTag << " = " << value << " is in range " << varInfo->rangeStr() << "."); } - auto varOfAccepted = Monitored::Scalar(monToolName+"OfAccepted" , -1.0 ); - auto monitorIt = Monitored::Group (m_monTool_vec[i], varOfAccepted); - varOfAccepted = values[i]; - ATH_MSG_DEBUG( m_varTag_vec[i] <<"= "<< varOfAccepted << " is within [" <<m_varMin_vec[i]<< "," << m_varMax_vec[i] << "] This selection passed! "); } - return lastDecision; } -bool TrigComboHypoTool::executeAlgStep(const std::vector<Combo::LegDecision>& combination, size_t index, std::vector<float> &vals) const { - ATH_MSG_DEBUG("On combination executeAlg"); - std::string monToolName=m_varTag_vec[index]; - if (m_varTag_vec.size()>1){ - monToolName = monToolName + m_legA_vec[index] + m_legB_vec[index]; - } - auto varOfProcessed = Monitored::Scalar(monToolName+"OfProcessed" , -1.0 ); - auto monitorIt = Monitored::Group (m_monTool_vec[index], varOfProcessed); - //check that we found the two legs - int nCombs(combination.size()); - if (nCombs < 2){ - ATH_MSG_ERROR("Number of Decision Objects passed is less than 2! Sum over decision objects on all legs = " << combination.size() ); +bool TrigComboHypoTool::executeAlgStep(const Combination& combination, const VarInfo& varInfo, std::vector<float> &vals) const { + ATH_MSG_DEBUG("Executing selection " << varInfo.index << " of " << m_varInfo_vec.size() << ": " << varInfo.rangeStr()); + + std::pair<KineInfo,KineInfo> kinepair; + if(!fillPairKinematics(kinepair, combination, varInfo)) { + ATH_MSG_ERROR("Failed to extract kinematics of feature pair!"); return false; } - int legA_index(-1), legB_index(-1); - - ATH_MSG_DEBUG("Decision objects available = "<< combination); - for (int i=0; i<nCombs; ++i){ - auto combId = HLT::Identifier(combination[i].first); - if (!TrigCompositeUtils::isLegId(combId)) - continue; - std::string legName = combId.name().substr(0,6); - if (legName == m_legA_vec[index]){ - if (legA_index != -1) { - ATH_MSG_WARNING("More than one Decision Object supplied on " << legName - << "! E.g. from a 2muX leg or similar. Do not know which one to use, will take the last one!"); - } - legA_index = i; - }else if (legName == m_legB_vec[index]){ - if (legB_index != -1) { - ATH_MSG_WARNING("More than one Decision Object supplied on " << legName - << "! E.g. from a 2muX leg or similar. Do not know which one to use, will take the last one!"); - } - legB_index = i; - } - ATH_MSG_DEBUG("\t Leg: "<< legName <<", full name:"<<combId.name()); + + if(msgLvl(MSG::DEBUG)) { + float eta_check, phi_check, pt_check; + std::tie(eta_check,phi_check,pt_check) = kinepair.first; + msg() << MSG::DEBUG << "Test filled legA kinematics: pt " << pt_check*invGeV << ", eta " << eta_check << ", phi " << phi_check << endmsg; + + std::tie(eta_check,phi_check,pt_check) = kinepair.second; + msg() << MSG::DEBUG << "Test filled legB kinematics: pt " << pt_check*invGeV << ", eta " << eta_check << ", phi " << phi_check << endmsg; } - if ( legA_index<0){ - ATH_MSG_ERROR("legA = "<< m_legA_vec[index] << " NOT FOUND!"); - return false; + // apply the cut + float value = compute(kinepair,varInfo.var); + if(!m_monTool_vec.empty()) { + auto varOfProcessed = Monitored::Scalar(varInfo.monToolName+"OfProcessed" , value ); + auto monitorIt = Monitored::Group (m_monTool_vec[varInfo.index], varOfProcessed); } - if ( legB_index<0){ - ATH_MSG_ERROR("legB = "<< m_legB_vec[index] << " NOT FOUND!"); + vals.push_back(value); + bool pass = varInfo.test(value); + + ATH_MSG_DEBUG("Found a combination with " << value); + if(!pass) { + ATH_MSG_DEBUG("Combination failed var cut: " << varInfo.varTag << " = " << value << " not in range " << varInfo.rangeStr()); + } + return pass; +} + + +/// Test function to compare decision ID with the legs to be used in var computation +bool testLegId(const Combo::LegDecision& d, uint32_t targetleg) { + auto combId = HLT::Identifier(d.first); + if(!TrigCompositeUtils::isLegId(combId)) return false; + return combId.numeric() == targetleg; +} + + +bool TrigComboHypoTool::fillLegDecisions_sameLeg(std::pair<Combo::LegDecision,Combo::LegDecision>& legpair, const Combination& combination, uint32_t leg) const { + Combination leg_features; + if(m_skipLegCheck) { + // If there is only one leg, the decision IDs don't have a leg ID + std::copy(combination.begin(),combination.end(),std::back_inserter(leg_features)); + } else { + // Extract the features matching the legs + // We take all of them, so as to be able to check if there is any ambiguity + auto isMyLeg = [&leg](const Combo::LegDecision& d) { return testLegId(d,leg); }; + std::copy_if(combination.begin(),combination.end(),std::back_inserter(leg_features),isMyLeg); + } + + if (leg_features.size()==2) { + legpair.first = leg_features[0]; + legpair.second = leg_features[1]; + } else { + ATH_MSG_ERROR(leg_features.size() << " Decision Objects supplied on leg " << leg + << ", must be 2 for same-leg topo selection!"); return false; } - float eta1, phi1, pt1; - float eta2, phi2, pt2; - - auto EL= combination[legA_index].second; + return true; +} - if (m_isLegA_MET_vec[index]) { - auto legA_pLink = TrigCompositeUtils::findLink<xAOD::TrigMissingETContainer>( *EL, featureString() ).link; - if (!legA_pLink.isValid()){ - ATH_MSG_ERROR("link for "<<m_legA_vec[index]<<"is MET"); - ATH_MSG_ERROR("link for "<<m_legA_vec[index]<<" not valid"); - return false; - } - float ex = (*legA_pLink)[0].ex()/1000.;//converting to GeV - float ey = (*legA_pLink)[0].ey()/1000.;//converting to GeV - eta1 = -9999.; - phi1 = ex==0.0 && ey==0.0 ? 0.0: std::atan2(ey,ex); - pt1 = std::sqrt(ex*ex+ey*ey); - }else { - auto legA_pLink = TrigCompositeUtils::findLink<xAOD::IParticleContainer>( *EL, featureString() ).link; - if (!legA_pLink.isValid()){ - ATH_MSG_ERROR("link for "<<m_legA_vec[index]<<"is not MET"); - ATH_MSG_ERROR("link for "<<m_legA_vec[index]<<" not valid"); - return false; - } - eta1 = (*legA_pLink)->p4().Eta(); - phi1 = (*legA_pLink)->p4().Phi(); - pt1 = (*legA_pLink)->p4().Pt(); +bool TrigComboHypoTool::fillLegDecisions_diffLeg(std::pair<Combo::LegDecision,Combo::LegDecision>& legpair, const Combination& combination, uint32_t legA, uint32_t legB) const { + // Extract the features matching the legs + // We take all of them, so as to be able to check if there is any ambiguity + auto isLegA = [&legA](const Combo::LegDecision& d) { return testLegId(d,legA); }; + auto isLegB = [&legB](const Combo::LegDecision& d) { return testLegId(d,legB); }; + Combination legA_features, legB_features; + + std::copy_if(combination.begin(),combination.end(),std::back_inserter(legA_features),isLegA); + if(legA_features.size()!=1) { + ATH_MSG_ERROR(legA_features.size() << " Decision Objects supplied on leg " << legA + << ", must be 1 for different-leg topo selection!"); + return false; + } + + std::copy_if(combination.begin(),combination.end(),std::back_inserter(legB_features),isLegB); + if (legB_features.size()!=1) { + ATH_MSG_ERROR(legB_features.size() << " Decision Objects supplied on leg " << legB + << ", must be 1 for different-leg topo selection!"); + return false; } - ATH_MSG_DEBUG("link for legA: "<<m_legA_vec[index]<<" is valid"); - EL = combination[legB_index].second; + legpair.first = legA_features[0]; + legpair.second = legB_features[0]; - if (m_isLegB_MET_vec[index]) { - auto legB_pLink = TrigCompositeUtils::findLink<xAOD::TrigMissingETContainer>( *EL, featureString() ).link; - if (!legB_pLink.isValid()){ - ATH_MSG_ERROR("link for "<<m_legB_vec[index]<<" not valid"); + return true; +} + + +bool TrigComboHypoTool::fillPairKinematics(std::pair<KineInfo,KineInfo>& kinepair, const Combination& combination, const VarInfo& varInfo) const { + ATH_MSG_DEBUG("Decision objects available = "<< combination); + // Check that there are enough features + size_t nFeatures(combination.size()); + if (nFeatures < 2){ + ATH_MSG_ERROR("Number of Decision Objects passed is less than 2! Sum over decision objects on all legs = " << combination.size() ); return false; } - float ex = (*legB_pLink)[0].ex()/1000.;//converting to GeV - float ey = (*legB_pLink)[0].ey()/1000.;//converting to GeV - eta2 = -9999.; - phi2 = ex==0.0 && ey==0.0 ? 0.0: std::atan2(ey,ex); - pt2 = std::sqrt(ex*ex+ey*ey); - }else { - auto legB_pLink = TrigCompositeUtils::findLink<xAOD::IParticleContainer>( *EL, featureString() ).link; - if (!legB_pLink.isValid()){ - ATH_MSG_ERROR("link for "<<m_legB_vec[index]<<"is not MET"); - ATH_MSG_ERROR("link for "<<m_legB_vec[index]<<" not valid"); + std::pair<Combo::LegDecision,Combo::LegDecision> legpair; + if (varInfo.legsAreEqual) {fillLegDecisions_sameLeg(legpair,combination,varInfo.legA);} + else {fillLegDecisions_diffLeg(legpair,combination,varInfo.legA,varInfo.legB);} + ATH_MSG_DEBUG("Fill leg A kinematics"); + if(!fillKineInfo(kinepair.first,legpair.first,varInfo.legA_is_MET)) { + ATH_MSG_ERROR("Failed to extract requisite kinematic info from leg " << varInfo.legA << "!"); return false; } - eta2 = (*legB_pLink)->p4().Eta(); - phi2 = (*legB_pLink)->p4().Phi(); - pt2 = (*legB_pLink)->p4().Pt(); - } - ATH_MSG_DEBUG("link for legB: "<<m_legB_vec[index]<<" is valid"); - - // apply the cut - bool pass(true); - float value(-9999.); - - switch(m_var_vec[index]){ - case comboHypoVars::DR: - { - float dEta = eta2 - eta1; - float dPhi = -remainder( -phi1 + phi2, 2*M_PI ); - value = std::sqrt(dEta*dEta + dPhi*dPhi); - break; - } - case comboHypoVars::INVM: - { - value = std::sqrt(2.*pt1*pt2*(std::cosh(eta1 - eta2) - std::cos(phi1 - phi2) ) )*1e-3; // Convert to GeV - break; - } - case comboHypoVars::DPHI: - { - value = std::fabs(remainder( -phi1 + phi2, 2*M_PI )); - break; - } - case comboHypoVars::MT: - { - float ex = pt1*std::cos(phi1) + pt2*std::cos(phi2); - float ey = pt1*std::sin(phi1) + pt2*std::sin(phi2); - value = std::sqrt(ex*ex + ey*ey)/1000.;//converting to GeV - break; + ATH_MSG_DEBUG("Fill leg B kinematics"); + if(!fillKineInfo(kinepair.second,legpair.second,varInfo.legB_is_MET)) { + ATH_MSG_ERROR("Failed to extract requisite kinematic info from leg " << varInfo.legB << "!"); + return false; } - default: - ATH_MSG_ERROR("m_varTag = "<<m_varTag_vec[index]<<" not present in the list of comboHypoVars"); - return false; + return true; } - varOfProcessed = value; - vals.push_back(value); - ATH_MSG_DEBUG("Found a combination with " << varOfProcessed); - if (m_useMin_vec[index] && m_useMax_vec[index]){ - if (varOfProcessed < m_varMin_vec[index] || varOfProcessed > m_varMax_vec[index]){ - ATH_MSG_DEBUG("Combination failed var cut: "<< m_varTag_vec[index] <<"= "<< varOfProcessed << " not in [" << m_varMin_vec[index] << "," << m_varMax_vec[index] << "]"); - pass=false; - } - }else if (m_useMin_vec[index]){ - if (varOfProcessed < m_varMin_vec[index] ){ - ATH_MSG_DEBUG("Combination failed var cut: "<< m_varTag_vec[index] <<"= "<< varOfProcessed << " not > " << m_varMin_vec[index]); - pass=false; +bool TrigComboHypoTool::fillKineInfo(TrigComboHypoTool::KineInfo& kinematics, Combo::LegDecision decision, bool isMET) const { + float eta, phi, pt; + if (isMET) { + auto pLink = TrigCompositeUtils::findLink<xAOD::TrigMissingETContainer>( *decision.second, featureString() ).link; + if (!pLink.isValid()){ + ATH_MSG_ERROR("link for MET not valid"); + return false; } - }else if (m_useMax_vec[index]){ - if (varOfProcessed > m_varMax_vec[index]){ - ATH_MSG_DEBUG("Combination failed var cut: "<< m_varTag_vec[index] <<"= "<< varOfProcessed << " not < " << m_varMax_vec[index]); - pass=false; + ROOT::Math::XYVectorF metv((*pLink)->ex(),(*pLink)->ey()); + eta = FLOATDEFAULT; + phi = metv.phi(); + pt = metv.r(); + } else { + auto pLink = TrigCompositeUtils::findLink<xAOD::IParticleContainer>( *decision.second, featureString() ).link; + if (!pLink.isValid()){ + ATH_MSG_ERROR("link for IParticle not valid"); + return false; } + eta = (*pLink)->p4().Eta(); + phi = (*pLink)->p4().Phi(); + pt = (*pLink)->p4().Pt(); } - return pass; - + ATH_MSG_DEBUG("Filled kinematics with pt " << pt*invGeV << ", eta " << eta << ", phi " << phi); + kinematics = std::make_tuple(eta,phi,pt); + return true; } +float TrigComboHypoTool::compute(const std::pair<KineInfo,KineInfo>& kinepair, ComboHypoVars var) const { + const auto& [legA_kine,legB_kine] = kinepair; + const auto& [eta1,phi1,pt1] = legA_kine; + const auto& [eta2,phi2,pt2] = legB_kine; + ATH_MSG_DEBUG("Leg A has pt " << pt1*invGeV << ", eta " << eta1 << ", phi " << phi1); + ATH_MSG_DEBUG("Leg B has pt " << pt2*invGeV << ", eta " << eta2 << ", phi " << phi2); + float value(0); + switch(var) { + case ComboHypoVars::DR: + { + value = xAOD::P4Helpers::deltaR(eta1,phi1,eta2,phi2); + break; + } + case ComboHypoVars::DPHI: + { + value = xAOD::P4Helpers::deltaPhi(phi1,phi2); + break; + } + case ComboHypoVars::INVM: + { + ROOT::Math::PtEtaPhiMVector p1(pt1,eta1,phi1,0.), p2(pt2,eta2,phi2,0.); + value = (p1+p2).M()*invGeV; // Convert to GeV + break; + } + case ComboHypoVars::MT: + { + ROOT::Math::Polar2DVectorF p1(pt1,phi1), p2(pt2,phi2); + value = sqrt((p1+p2).Mag2())*invGeV; // Convert to GeV + break; + } + default: + { + ATH_MSG_ERROR("Undefined variable requested -- should never happen!"); + } + } + return value; +} \ No newline at end of file diff --git a/Trigger/TrigHypothesis/TrigHypoCommonTools/src/TrigComboHypoTool.h b/Trigger/TrigHypothesis/TrigHypoCommonTools/src/TrigComboHypoTool.h index 3b5bfca80d9c2b353455765a42a29abb20539876..c9100bb114fdccaf375dbf229ee22a514eb36c64 100644 --- a/Trigger/TrigHypothesis/TrigHypoCommonTools/src/TrigComboHypoTool.h +++ b/Trigger/TrigHypothesis/TrigHypoCommonTools/src/TrigComboHypoTool.h @@ -7,6 +7,8 @@ #include <string> #include <vector> +#include <tuple> +#include <limits> #include "DecisionHandling/ComboHypoToolBase.h" @@ -29,7 +31,9 @@ class TrigComboHypoTool: public ComboHypoToolBase { + public: + enum ComboHypoVars { UNDEF=-1, DR=0, DPHI, INVM, MT}; TrigComboHypoTool(const std::string& type, const std::string& name, @@ -38,35 +42,83 @@ class TrigComboHypoTool: public ComboHypoToolBase { virtual ~TrigComboHypoTool() {}; virtual StatusCode initialize() override; - enum comboHypoVars { DR=0, INVM, DPHI, MT}; - private: - - virtual bool executeAlg(const std::vector<Combo::LegDecision>& combination) const override; - bool executeAlgStep(const std::vector<Combo::LegDecision>& combination, size_t index, std::vector<float>& values) const; - + + static constexpr float FLOATDEFAULT = std::numeric_limits<float>::lowest(); + + /// Organise info per var selection in a struct + struct VarInfo { + std::string varTag{""}; + ComboHypoVars var{UNDEF}; + size_t index{0}; + std::string monToolName{""}; + + bool useMin{false}; + float varMin{FLOATDEFAULT}; + bool useMax{false}; + float varMax{FLOATDEFAULT}; + + bool legA_is_MET{false}; + uint32_t legA{0}; + bool legB_is_MET{false}; + uint32_t legB{0}; + bool legsAreEqual{false}; + + /// Check consistency of single var config + bool validate(std::string& errmsg) const; + /// Generate range string for printing + std::string rangeStr() const { + return (useMin ? std::to_string(varMin) + " < " : "") + varTag + (useMax ? " < " + std::to_string(varMax): ""); + } + bool test(float value) const { + return (useMin ? value > varMin : true) && (useMax ? value < varMax : true); + } + + }; + + /// Typedef for convenience, will contain eta/phi/pt info + typedef std::tuple<float,float,float> KineInfo; + typedef std::vector<Combo::LegDecision> Combination; + + /// Top-level function to make chain-level decision + /// This applies the AND of all configured var selections + virtual bool executeAlg(const Combination& combination) const override; + + /// Implementation of selection on individual variables + bool executeAlgStep(const Combination& combination, const VarInfo&, std::vector<float>& values) const; + /// Computation of the variables from the specified kinematics + float compute(const std::pair<KineInfo,KineInfo>& kinepair, ComboHypoVars var) const; + + /// Helpers to extract kinematics from the specified legs of the chain + /// Specialised for two cases -- exactly two objects from the same leg + /// or exactly one object each from two legs. + bool fillLegDecisions_sameLeg(std::pair<Combo::LegDecision,Combo::LegDecision>& legpair, const Combination& combination, uint32_t leg) const; + bool fillLegDecisions_diffLeg(std::pair<Combo::LegDecision,Combo::LegDecision>& legpair, const Combination& combination, uint32_t legA, uint32_t legB) const; + bool fillPairKinematics(std::pair<KineInfo,KineInfo>& kinepair, const Combination& combination, const VarInfo& varInfo) const; + bool fillKineInfo(KineInfo& kinematics, Combo::LegDecision decision, bool isMET) const; + + /// Gaudi configuration hooks // flags - Gaudi::Property<std::vector<std::string>> m_varTag_vec {this, "Variables" , { ""}, "Variables to cut on"}; - Gaudi::Property< std::vector<bool> > m_useMin_vec {this, "UseMinVec" , {false}, "Array with the apply_min_cut setting"}; - Gaudi::Property< std::vector<bool> > m_useMax_vec {this, "UseMaxVec" , {false}, "Array with the apply_max_cut setting"}; + Gaudi::Property<std::vector<std::string>> m_varTag_vec {this, "Variables" , {""}, "Variables to cut on"}; + Gaudi::Property<std::vector<bool> > m_useMin_vec {this, "UseMinVec" , {false}, "Array with the apply_min_cut setting"}; + Gaudi::Property<std::vector<bool> > m_useMax_vec {this, "UseMaxVec" , {false}, "Array with the apply_max_cut setting"}; //legs - Gaudi::Property<std::vector<std::string>> m_legA_vec {this, "LegAVec" , { ""}, "Array with the first Leg ID"}; - Gaudi::Property<std::vector<std::string>> m_legB_vec {this, "LegBVec" , { ""}, "Array with the second Leg ID"}; + Gaudi::Property<std::vector<uint32_t>> m_legA_vec {this, "LegAVec" , {0}, "Array with the first Leg ID"}; + Gaudi::Property<std::vector<uint32_t>> m_legB_vec {this, "LegBVec" , {0}, "Array with the second Leg ID"}; Gaudi::Property<std::vector< bool >> m_isLegA_MET_vec {this, "IsLegA_METVec", {false}, "Array with the first Leg MET identifier"}; Gaudi::Property<std::vector< bool >> m_isLegB_MET_vec {this, "IsLegB_METVec", {false}, "Array with the second Leg MET identifier"}; + Gaudi::Property<bool> m_skipLegCheck {this, "SkipLegCheck" , {false}, "Ignore leg IDs for chains with only one leg"}; // cuts - Gaudi::Property<std::vector<float>> m_varMin_vec {this, "LowerCutVec", {-9999.}, "Array with the lower cut for legs pair"}; - Gaudi::Property<std::vector<float>> m_varMax_vec {this, "UpperCutVec", {-9999.}, "Array with the upper cut for legs pair"}; + Gaudi::Property<std::vector<float>> m_varMin_vec {this, "LowerCutVec", {FLOATDEFAULT}, "Array with the lower cut for legs pair"}; + Gaudi::Property<std::vector<float>> m_varMax_vec {this, "UpperCutVec", {FLOATDEFAULT}, "Array with the upper cut for legs pair"}; // monitoring ToolHandleArray<GenericMonitoringTool> m_monTool_vec {this, "MonTools", {}, "Monitoring tools" }; - std::map<std::string, comboHypoVars> m_varMap; - std::vector<comboHypoVars> m_var_vec; - - void fillVarMap(); + /// Internal variables for more efficient config lookup + std::vector<VarInfo> m_varInfo_vec; }; // TRIGCOMBOHYPO_TRIGCOMBOHYPOTOOL_H #endif diff --git a/Trigger/TrigValidation/TrigAnalysisTest/share/ref_RDOtoRDOTrig_v1Dev_build.ref b/Trigger/TrigValidation/TrigAnalysisTest/share/ref_RDOtoRDOTrig_v1Dev_build.ref index 3ada39a58ca12be91fd905f9d9d899ae67d21be8..71163814dcda7822b3c1f004f2c65dde2d3cbcc3 100644 --- a/Trigger/TrigValidation/TrigAnalysisTest/share/ref_RDOtoRDOTrig_v1Dev_build.ref +++ b/Trigger/TrigValidation/TrigAnalysisTest/share/ref_RDOtoRDOTrig_v1Dev_build.ref @@ -74,8 +74,14 @@ HLT_2g10_loose_mu20_L1MU20: stepFeatures: 0: 14 1: 1 +HLT_2g15_loose_25dphiAA_invmAA80_L1DPHI-M70-2eEM12M: + eventCount: 0 HLT_2g15_loose_dPhi25_m80_L1DPHI-M70-2eEM12M: eventCount: 0 +HLT_2g15_tight_25dphiAA_L1DPHI-M70-2eEM12M: + eventCount: 0 +HLT_2g15_tight_25dphiAA_invmAA80_L1DPHI-M70-2eEM12M: + eventCount: 0 HLT_2g15_tight_L1DPHI-M70-2eEM12M: eventCount: 0 HLT_2g15_tight_dPhi25_L1DPHI-M70-2eEM12M: @@ -621,6 +627,18 @@ HLT_2mu6_10invm70_L1MU6: 1: 6 2: 8 3: 8 +HLT_2mu6_10invmAA70_L1MU6: + eventCount: 2 + stepCounts: + 0: 4 + 1: 3 + 2: 3 + 3: 2 + stepFeatures: + 0: 8 + 1: 6 + 2: 8 + 3: 8 HLT_2mu6_2j50_0eta490_j0_DJMASS900j50_L1MJJ-500-NFF: eventCount: 0 HLT_2mu6_L12MU6: @@ -1463,10 +1481,28 @@ HLT_e140_lhloose_L1eEM22M: eventCount: 0 HLT_e140_lhloose_noringer_L1EM22VHI: eventCount: 0 +HLT_e14_lhtight_e4_etcut_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 + stepFeatures: + 0: 14 HLT_e14_lhtight_e4_etcut_Jpsiee_L1JPSI-1M5-EM12: eventCount: 0 stepFeatures: 0: 14 +HLT_e14_lhtight_e4_etcut_probe_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 +HLT_e14_lhtight_noringer_e4_etcut_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 + stepCounts: + 0: 1 + 1: 1 + 2: 1 + 3: 1 + stepFeatures: + 0: 15 + 1: 18 + 2: 12 + 3: 7 HLT_e14_lhtight_noringer_e4_etcut_Jpsiee_L1JPSI-1M5-EM12: eventCount: 0 stepCounts: @@ -1479,6 +1515,18 @@ HLT_e14_lhtight_noringer_e4_etcut_Jpsiee_L1JPSI-1M5-EM12: 1: 18 2: 12 3: 7 +HLT_e14_lhtight_noringer_e4_etcut_probe_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 + stepCounts: + 0: 1 + 1: 1 + 2: 1 + 3: 1 + stepFeatures: + 0: 1 + 1: 2 + 2: 1 + 3: 1 HLT_e15_lhvloose_L1EM10VH: eventCount: 5 stepCounts: @@ -1674,15 +1722,15 @@ HLT_e20_lhvloose_L1EM15VH: 2: 4 3: 4 4: 4 -HLT_e24_lhmedium_2g12_loose_02dRAB_L1EM20VH_3EM10VH: +HLT_e24_lhmedium_g12_loose_g12_loose_02dRAB_02dRAC_L1EM20VH_3EM10VH: eventCount: 0 stepCounts: 0: 1 1: 1 stepFeatures: - 0: 7 - 1: 3 - 2: 3 + 0: 13 + 1: 5 + 2: 5 HLT_e24_lhmedium_g25_medium_02dRAB_L12EM20VH: eventCount: 0 stepCounts: @@ -1998,6 +2046,20 @@ HLT_e26_lhtight_L1EM22VHI: 2: 4 3: 4 4: 4 +HLT_e26_lhtight_e15_etcut_50invmAB130_L1EM22VHI: + eventCount: 3 + stepCounts: + 0: 3 + 1: 3 + 2: 3 + 3: 3 + 4: 3 + stepFeatures: + 0: 23 + 1: 65 + 2: 19 + 3: 16 + 4: 3 HLT_e26_lhtight_e15_etcut_L1EM22VHI: eventCount: 3 stepCounts: @@ -2040,6 +2102,28 @@ HLT_e26_lhtight_e15_etcut_idperf_Zee_L1EM22VHI: 2: 19 3: 16 4: 3 +HLT_e26_lhtight_e15_etcut_probe_50invmAB130_L1EM22VHI: + eventCount: 3 + stepCounts: + 0: 5 + 1: 4 + 2: 4 + 3: 4 + 4: 4 + 5: 3 + 6: 3 + 7: 3 + 8: 3 + stepFeatures: + 0: 5 + 1: 6 + 2: 4 + 3: 4 + 4: 4 + 5: 14 + 6: 61 + 7: 16 + 8: 13 HLT_e26_lhtight_ivarloose_2j20_0eta290_020jvt_pf_ftf_boffperf_L1EM22VHI: eventCount: 3 stepCounts: @@ -3058,6 +3142,18 @@ HLT_e5_idperf_tight_L1EM3: 2: 24 3: 24 4: 24 +HLT_e5_lhtight_e14_etcut_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 + stepCounts: + 0: 2 + 1: 2 + 2: 2 + 3: 2 + stepFeatures: + 0: 8 + 1: 23 + 2: 4 + 3: 4 HLT_e5_lhtight_e14_etcut_Jpsiee_L1JPSI-1M5-EM12: eventCount: 0 stepCounts: @@ -3070,6 +3166,30 @@ HLT_e5_lhtight_e14_etcut_Jpsiee_L1JPSI-1M5-EM12: 1: 23 2: 4 3: 4 +HLT_e5_lhtight_e14_etcut_probe_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 + stepCounts: + 0: 2 + 1: 2 + 2: 2 + 3: 2 + stepFeatures: + 0: 4 + 1: 5 + 2: 2 + 3: 2 +HLT_e5_lhtight_e9_etcut_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepCounts: + 0: 3 + 1: 3 + 2: 3 + 3: 2 + stepFeatures: + 0: 17 + 1: 48 + 2: 10 + 3: 9 HLT_e5_lhtight_e9_etcut_Jpsiee_L1JPSI-1M5-EM7: eventCount: 0 stepCounts: @@ -3082,6 +3202,27 @@ HLT_e5_lhtight_e9_etcut_Jpsiee_L1JPSI-1M5-EM7: 1: 48 2: 10 3: 9 +HLT_e5_lhtight_e9_etcut_probe_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepCounts: + 0: 3 + 1: 3 + 2: 3 + 3: 3 + stepFeatures: + 0: 10 + 1: 22 + 2: 3 + 3: 3 +HLT_e5_lhtight_noringer_e14_etcut_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 + stepCounts: + 0: 1 + 1: 1 + stepFeatures: + 0: 5 + 1: 10 + 2: 2 HLT_e5_lhtight_noringer_e14_etcut_Jpsiee_L1JPSI-1M5-EM12: eventCount: 0 stepCounts: @@ -3091,6 +3232,30 @@ HLT_e5_lhtight_noringer_e14_etcut_Jpsiee_L1JPSI-1M5-EM12: 0: 5 1: 10 2: 2 +HLT_e5_lhtight_noringer_e14_etcut_probe_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 + stepCounts: + 0: 1 + 1: 1 + 2: 1 + 3: 1 + stepFeatures: + 0: 1 + 1: 2 + 2: 1 + 3: 1 +HLT_e5_lhtight_noringer_e9_etcut_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepCounts: + 0: 2 + 1: 2 + 2: 2 + 3: 1 + stepFeatures: + 0: 10 + 1: 21 + 2: 6 + 3: 5 HLT_e5_lhtight_noringer_e9_etcut_Jpsiee_L1JPSI-1M5-EM7: eventCount: 0 stepCounts: @@ -3103,6 +3268,18 @@ HLT_e5_lhtight_noringer_e9_etcut_Jpsiee_L1JPSI-1M5-EM7: 1: 21 2: 6 3: 5 +HLT_e5_lhtight_noringer_e9_etcut_probe_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepCounts: + 0: 2 + 1: 2 + 2: 2 + 3: 2 + stepFeatures: + 0: 3 + 1: 9 + 2: 2 + 3: 2 HLT_e5_lhvloose_j70_0eta320_j50_0eta490_j0_DJMASS1000j50_xe50_tcpufit_L1MJJ-500-NFF: eventCount: 0 stepCounts: @@ -3272,6 +3449,15 @@ HLT_e7_lhmedium_mu24_L1MU20: 8: 1 HLT_e80_lhvloose_L1EM22VHI: eventCount: 0 +HLT_e9_lhtight_e4_etcut_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepCounts: + 0: 2 + 1: 2 + stepFeatures: + 0: 32 + 1: 88 + 2: 22 HLT_e9_lhtight_e4_etcut_Jpsiee_L1JPSI-1M5-EM7: eventCount: 0 stepCounts: @@ -3290,6 +3476,26 @@ HLT_e9_lhtight_e4_etcut_L1JPSI-1M5-EM7: 0: 32 1: 88 2: 22 +HLT_e9_lhtight_e4_etcut_probe_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepCounts: + 0: 2 + 1: 2 + stepFeatures: + 0: 2 + 1: 6 +HLT_e9_lhtight_noringer_e4_etcut_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepCounts: + 0: 2 + 1: 2 + 2: 1 + 3: 1 + stepFeatures: + 0: 32 + 1: 86 + 2: 29 + 3: 7 HLT_e9_lhtight_noringer_e4_etcut_Jpsiee_L1JPSI-1M5-EM7: eventCount: 0 stepCounts: @@ -3302,6 +3508,18 @@ HLT_e9_lhtight_noringer_e4_etcut_Jpsiee_L1JPSI-1M5-EM7: 1: 86 2: 29 3: 7 +HLT_e9_lhtight_noringer_e4_etcut_probe_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepCounts: + 0: 2 + 1: 2 + 2: 1 + 3: 1 + stepFeatures: + 0: 2 + 1: 6 + 2: 1 + 3: 1 HLT_e9_lhvloose_mu20_mu8noL1_L1MU20: eventCount: 0 stepCounts: diff --git a/Trigger/TrigValidation/TriggerTest/share/ref_data_v1Dev_build.ref b/Trigger/TrigValidation/TriggerTest/share/ref_data_v1Dev_build.ref index e270fc1fa64a42bfadba5c3d506fea29258b9576..608d39b9b2a7d512f770ff90ec434ab5116f06e3 100644 --- a/Trigger/TrigValidation/TriggerTest/share/ref_data_v1Dev_build.ref +++ b/Trigger/TrigValidation/TriggerTest/share/ref_data_v1Dev_build.ref @@ -36,8 +36,14 @@ HLT_2e5_lhvloose_bBeeM6000_L12EM3: 3: 2 HLT_2g10_loose_mu20_L1MU20: eventCount: 0 +HLT_2g15_loose_25dphiAA_invmAA80_L1DPHI-M70-2eEM12M: + eventCount: 0 HLT_2g15_loose_dPhi25_m80_L1DPHI-M70-2eEM12M: eventCount: 0 +HLT_2g15_tight_25dphiAA_L1DPHI-M70-2eEM12M: + eventCount: 0 +HLT_2g15_tight_25dphiAA_invmAA80_L1DPHI-M70-2eEM12M: + eventCount: 0 HLT_2g15_tight_L1DPHI-M70-2eEM12M: eventCount: 0 HLT_2g15_tight_dPhi25_L1DPHI-M70-2eEM12M: @@ -255,6 +261,12 @@ HLT_2mu6_10invm70_L1MU6: 0: 1 stepFeatures: 0: 2 +HLT_2mu6_10invmAA70_L1MU6: + eventCount: 0 + stepCounts: + 0: 1 + stepFeatures: + 0: 2 HLT_2mu6_2j50_0eta490_j0_DJMASS900j50_L1MJJ-500-NFF: eventCount: 0 HLT_2mu6_L12MU6: @@ -586,10 +598,18 @@ HLT_e140_lhloose_L1eEM22M: eventCount: 0 HLT_e140_lhloose_noringer_L1EM22VHI: eventCount: 0 +HLT_e14_lhtight_e4_etcut_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 HLT_e14_lhtight_e4_etcut_Jpsiee_L1JPSI-1M5-EM12: eventCount: 0 +HLT_e14_lhtight_e4_etcut_probe_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 +HLT_e14_lhtight_noringer_e4_etcut_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 HLT_e14_lhtight_noringer_e4_etcut_Jpsiee_L1JPSI-1M5-EM12: eventCount: 0 +HLT_e14_lhtight_noringer_e4_etcut_probe_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 HLT_e15_lhvloose_L1EM10VH: eventCount: 0 stepCounts: @@ -620,7 +640,7 @@ HLT_e20_lhtight_ivarloose_L1ZAFB-25DPHI-eEM18M: eventCount: 0 HLT_e20_lhvloose_L1EM15VH: eventCount: 0 -HLT_e24_lhmedium_2g12_loose_02dRAB_L1EM20VH_3EM10VH: +HLT_e24_lhmedium_g12_loose_g12_loose_02dRAB_02dRAC_L1EM20VH_3EM10VH: eventCount: 0 HLT_e24_lhmedium_g25_medium_02dRAB_L12EM20VH: eventCount: 0 @@ -668,6 +688,10 @@ HLT_e26_lhmedium_nopix_lrttight_L1EM22VHI: eventCount: 0 HLT_e26_lhtight_L1EM22VHI: eventCount: 0 +HLT_e26_lhtight_e15_etcut_50invmAB130_L1EM22VHI: + eventCount: 0 + stepFeatures: + 0: 1 HLT_e26_lhtight_e15_etcut_L1EM22VHI: eventCount: 0 stepFeatures: @@ -680,6 +704,8 @@ HLT_e26_lhtight_e15_etcut_idperf_Zee_L1EM22VHI: eventCount: 0 stepFeatures: 0: 1 +HLT_e26_lhtight_e15_etcut_probe_50invmAB130_L1EM22VHI: + eventCount: 0 HLT_e26_lhtight_ivarloose_2j20_0eta290_020jvt_pf_ftf_boffperf_L1EM22VHI: eventCount: 0 HLT_e26_lhtight_ivarloose_L1EM22VHI: @@ -900,18 +926,58 @@ HLT_e5_idperf_tight_L1EM3: 2: 5 3: 5 4: 5 +HLT_e5_lhtight_e14_etcut_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 HLT_e5_lhtight_e14_etcut_Jpsiee_L1JPSI-1M5-EM12: eventCount: 0 +HLT_e5_lhtight_e14_etcut_probe_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 +HLT_e5_lhtight_e9_etcut_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepFeatures: + 0: 3 HLT_e5_lhtight_e9_etcut_Jpsiee_L1JPSI-1M5-EM7: eventCount: 0 stepFeatures: 0: 3 +HLT_e5_lhtight_e9_etcut_probe_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepCounts: + 0: 1 + 1: 1 + 2: 1 + 3: 1 + stepFeatures: + 0: 3 + 1: 6 + 2: 1 + 3: 1 +HLT_e5_lhtight_noringer_e14_etcut_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 HLT_e5_lhtight_noringer_e14_etcut_Jpsiee_L1JPSI-1M5-EM12: eventCount: 0 +HLT_e5_lhtight_noringer_e14_etcut_probe_1invmAB3_L1JPSI-1M5-EM12: + eventCount: 0 +HLT_e5_lhtight_noringer_e9_etcut_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepFeatures: + 0: 2 HLT_e5_lhtight_noringer_e9_etcut_Jpsiee_L1JPSI-1M5-EM7: eventCount: 0 stepFeatures: 0: 2 +HLT_e5_lhtight_noringer_e9_etcut_probe_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepCounts: + 0: 1 + 1: 1 + 2: 1 + 3: 1 + stepFeatures: + 0: 2 + 1: 4 + 2: 1 + 3: 1 HLT_e5_lhvloose_j70_0eta320_j50_0eta490_j0_DJMASS1000j50_xe50_tcpufit_L1MJJ-500-NFF: eventCount: 0 HLT_e5_lhvloose_nopix_lrtloose_idperf_probe_g25_medium_L1EM20VH: @@ -940,6 +1006,10 @@ HLT_e7_lhmedium_mu24_L1MU20: eventCount: 0 HLT_e80_lhvloose_L1EM22VHI: eventCount: 0 +HLT_e9_lhtight_e4_etcut_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepFeatures: + 0: 5 HLT_e9_lhtight_e4_etcut_Jpsiee_L1JPSI-1M5-EM7: eventCount: 0 stepFeatures: @@ -948,10 +1018,18 @@ HLT_e9_lhtight_e4_etcut_L1JPSI-1M5-EM7: eventCount: 0 stepFeatures: 0: 5 +HLT_e9_lhtight_e4_etcut_probe_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 +HLT_e9_lhtight_noringer_e4_etcut_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 + stepFeatures: + 0: 5 HLT_e9_lhtight_noringer_e4_etcut_Jpsiee_L1JPSI-1M5-EM7: eventCount: 0 stepFeatures: 0: 5 +HLT_e9_lhtight_noringer_e4_etcut_probe_1invmAB3_L1JPSI-1M5-EM7: + eventCount: 0 HLT_e9_lhvloose_mu20_mu8noL1_L1MU20: eventCount: 0 HLT_eb_low_L1RD2_FILLED: diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/ComboHypoHandling.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/ComboHypoHandling.py index 551146debfe71adf0345c20f2134c100399ceb9a..c2b5c175212474e05e3de40e083e2c925139ac82 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/ComboHypoHandling.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/ComboHypoHandling.py @@ -8,6 +8,8 @@ from AthenaCommon.Logging import logging log = logging.getLogger(__name__) logging.getLogger().info("Importing %s",__name__) import math +import re +from TrigConfHLTData.HLTUtils import string2hash topoLegIndices = "ABCDEF" @@ -47,161 +49,145 @@ def TrigComboHypoToolFromDict(chainDict): from TrigHypoCommonTools.TrigHypoCommonToolsConf import TrigComboHypoTool from AthenaMonitoringKernel.GenericMonitoringTool import GenericMonitoringTool, defineHistogram - name = chainDict['chainName'] - log.debug("[TrigComboHypoToolFromDict] chain %s, combo hypos to be processed: %s, t", name, chainDict['extraComboHypos']) + chainName = chainDict['chainName'] + log.debug("[TrigComboHypoToolFromDict] chain %s, combo hypos to be processed: %s, t", chainName, chainDict['extraComboHypos']) #define the list for housing all the info needed to initialize the TrigComboHypoTool module in the form of a dict topoDefs = [] - for topoID in range(len(chainDict['extraComboHypos'])): - topoInfo = chainDict['extraComboHypos'][topoID] - #here we need to decompress the name to get: variable_name, min, max - log.debug("[TrigComboHypoToolFromDict] new combo hypo name: %s, topoInfo = %s", name, topoInfo) - singleTopoDef = {} - - isLegMET = [] - for chId in range(len(chainDict['chainParts'])): - if chainDict['chainParts'][chId]['signature'] == 'MET': - isLegMET.append(True) - else: - isLegMET.append(False) - log.debug("[TrigComboHypoToolFromDict] chainParts[%i]: %s", chId, chainDict['chainParts'][chId]) - - import re - # get the variable - obs_to_use = [] - for obs in allowed_obs.keys(): - if obs in topoInfo: - obs_to_use.append(obs) - if len(obs_to_use)!=1: - log.error("[TrigComboHypoToolFromDict] N of vars found in he hypo name = %d in chain name %s", len(obs_to_use), name) - raise Exception("[TrigComboHypoToolFromDict] N of vars found in the hypo name is different from 1") - singleTopoDef['var'] = obs_to_use[0] - - #get the limits - l_min = re.findall(r"\d+"+obs_to_use[0], topoInfo) - if len(l_min)==1: - l_min[0] = l_min[0].replace(obs_to_use[0],"") - if obs_to_use[0] in ['dR','dPhi']: - cut_min = float(l_min[0])/10. - else: - cut_min = float(l_min[0]) - if len(l_min)>1: - log.error("[TrigComboHypoToolFromDict] unable to get min value: N min = %d, l_min = %d", len(l_min), l_min) - raise Exception("[TrigComboHypoToolFromDict] cannot set min value") - - if len(l_min)==1:#remove the min value from the string name - l_max = re.findall(r"\d+", topoInfo.replace(l_min[0],"")) - else:#no min value was found - l_max = re.findall(r"\d+", topoInfo) - if len(l_max)>1: - log.error("[TrigComboHypoToolFromDict] unable to get max value: N max = %d, l_max = %d", len(l_max), l_max) - raise Exception("[TrigComboHypoToolFromDict] cannot set max value") - if len(l_max)==1: - if obs_to_use[0] in ['dR','dPhi']: - cut_max = float(l_max[0])/10. - else: - cut_max = float(l_min[0]) - - #get the legs - l_names = topoInfo.replace(obs_to_use[0], "") - if len(l_min)>0: - l_names = l_names.replace(l_min[0], "") - if len(l_max)>0: - l_names = l_names.replace(l_max[0], "") - - if len(l_names)!=2: - log.error("[TrigComboHypoToolFromDict] N_legs = %d, legs_name = %s", len(l_names), l_names) - raise Exception("[TrigComboHypoToolFromDict] Number of legs is different from 2") - - legA = -1 - legB = -1 - for i in range(len(topoLegIndices)): - if topoLegIndices[i] == l_names[0]: - legA = i - elif topoLegIndices[i] == l_names[1]: - legB = i - if legA<0 or legB<0: - log.error("[TrigComboHypoToolFromDict] Didn't find leg indexes in %s", l_names) - raise Exception("[TrigComboHypoToolFromDict] Didn't find leg indexes") - singleTopoDef['legA'] = "leg{:03d}".format(legA) - singleTopoDef['legB'] = "leg{:03d}".format(legB) - - #count the number of MET legs used in the hypo - n_MET_legs=0 - if isLegMET[legA]: - n_MET_legs += 1 - if isLegMET[legB]: - n_MET_legs += 1 + # Define regex for parsing the topoInfo + # Pattern is: min cut, var, legA, legB, max cut + # Min and max are both optional, check afterwards that at least one is filled + # Only the allowed vars and legs will be recognised, anything else fails to match + theregex = fr"(\d*)({'|'.join(allowed_obs.keys())})([{topoLegIndices}])([{topoLegIndices}])(\d*)" + matcher = re.compile(theregex) + + for iTopo, topoInfo in enumerate(chainDict['extraComboHypos']): + log.debug("[TrigComboHypoToolFromDict] new combo hypo for chain: %s, topoInfo = %s", chainName, topoInfo) + # Attempt to regex-match the topo specification + result = matcher.match(topoInfo) + if not result: + log.error("[TrigComboHypoToolFromDict] Topo expression %s does not conform to format (min?)(var)(legA)(legB)(max?).",topoInfo) + log.error("[TrigComboHypoToolFromDict] Must use leg IDs in %s, vars in {allowed_obs.keys()}",topoLegIndices) + raise ValueError(f"[TrigComboHypoToolFromDict] Invalid topo expression {topoInfo} received in 'extraComboHypos'!") + + # Extract the matched info and validate + str_min, var, char_legA, char_legB, str_max = result.groups() + # Manipulation of the cuts + # At least one must be filled + use_min = bool(str_min) + use_max = bool(str_max) + if not (use_min or use_max): + log.error("[TrigComboHypoToolFromDict] Topo expression %s does not specify a min or max cut value.",topoInfo) + raise ValueError(f"[TrigComboHypoToolFromDict] Invalid topo expression {topoInfo} received in 'extraComboHypos'!") + # Convert into float values, dividing for 0.1 precision as needed + if var in ['dR','dphi']: + cut_min = float(str_min)/10. if use_min else float('nan') + cut_max = float(str_max)/10. if use_max else float('nan') + else: + cut_min = float(str_min) if use_min else float('nan') + cut_max = float(str_max) if use_max else float('nan') + + # Convert char leg representation to int + i_legA = topoLegIndices.find(char_legA) + i_legB = topoLegIndices.find(char_legB) + + # Fill info for each leg, looking up in chainParts + # Convert leg name into HLT identifier for matching in the tool + legInfo = [] + for ileg in [i_legA,i_legB]: + cpart = chainDict['chainParts'][ileg] + legname = f"leg{ileg:03d}_{chainName}" + legInfo.append({ + 'index' : ileg, + 'legname' : legname, + 'HLTId' : string2hash(legname), + 'isMET' : cpart['signature']=='MET', + 'multiplicity': int(cpart['multiplicity']) + }) + + # Count how many input legs are MET, for consistency checks + n_MET_legs = legInfo[0]['isMET'] + legInfo[1]['isMET'] + + # Check multiplicity of the configured legs + # For chains like "HLT_2muX_10invm70AA", no leg ID will be attached + # in which case set a flag to use all objects in the combination list + skipLegCheck = False + if i_legA==i_legB: + if legInfo[0]['multiplicity'] != 2: + log.error("[TrigComboHypoToolFromDict] Error configuring topo for chain %s!",chainName) + log.error("[TrigComboHypoToolFromDict] Topo selection %s requires multiplicity 2 on leg %d, found %d!",topoInfo,i_legA,legInfo[0]['multiplicity']) + raise Exception("[TrigComboHypoToolFromDict] Invalid multiplicity") + if n_MET_legs==2: + log.error("[TrigComboHypoToolFromDict] Configured with the same MET leg on both sides -- impossible to satisfy!") + raise Exception("[TrigComboHypoToolFromDict] Identical MET legs for topo selection") + if len(chainDict['chainParts'])==1: + skipLegCheck=True + else: + for li in legInfo: + if li['multiplicity'] != 1: + log.error("[TrigComboHypoToolFromDict] Error configuring topo for chain %s!",chainName) + log.error("[TrigComboHypoToolFromDict] Topo selection %s requires multiplicity 1 on leg %d, found %d!",topoInfo,li['index'],li['multiplicity']) + raise Exception("[TrigComboHypoToolFromDict] Invalid multiplicity") + #now check that the variable we plan to use allows the use of the MET - if n_MET_legs not in allowed_obs[obs_to_use[0]]['n_MET_legs']: - log.error("[TrigComboHypoToolFromDict] Attempting to use the MET leg in var %s. N_MET_legs = %d", obs_to_use[0], isLegMET.count(True)) + if n_MET_legs not in allowed_obs[var]['n_MET_legs']: + log.error("[TrigComboHypoToolFromDict] Attempting var %s with %d MET legs, %s allowed", var, n_MET_legs, allowed_obs[var]['n_MET_legs']) raise Exception("[TrigComboHypoToolFromDict] Attempting to use the MET leg in var") - singleTopoDef['isLegA_MET'] = isLegMET[legA] - singleTopoDef['isLegB_MET'] = isLegMET[legB] - + if len(chainDict['extraComboHypos'])==1:#to avoid breaking changes in the ref files - monToolName = "MonTool_"+name - histNameTag = obs_to_use[0] + monToolName = "MonTool_"+chainName + histNameTag = var else: - monToolName = "MonTool_"+name+"_"+chainDict['extraComboHypos'][topoID] - histNameTag = obs_to_use[0] + "leg{:03d}".format(legA) + "leg{:03d}".format(legB) + monToolName = f"MonTool_{chainName}_{chainDict['extraComboHypos'][iTopo]}" + histNameTag = f"{var}leg{i_legA:03d}leg{i_legB:03d}" monTool = GenericMonitoringTool(monToolName) - monTool.Histograms = [defineHistogram(histNameTag+'OfAccepted', type='TH1F', path='EXPERT', - title=obs_to_use[0]+" in accepted combinations; {}".format(obs_to_use[0]), - xbins=allowed_obs[obs_to_use[0]]['hist_nbins'], - xmin=allowed_obs[obs_to_use[0]]['hist_min'], - xmax=allowed_obs[obs_to_use[0]]['hist_max']), - defineHistogram(histNameTag+'OfProcessed', type='TH1F', path='EXPERT', - title=obs_to_use[0]+" in processed combinations; {}".format(obs_to_use[0]), - xbins=allowed_obs[obs_to_use[0]]['hist_nbins'], - xmin=allowed_obs[obs_to_use[0]]['hist_min'], - xmax=allowed_obs[obs_to_use[0]]['hist_max'])] - log.debug("[TrigComboHypoToolFromDict] tool configured for hypo name: %s, topoInfo = %s", name, topoInfo) - #now fill the holders needed to initialize the TrigComboHypoTool - if len(l_min)==1: - singleTopoDef['useMin'] = True - singleTopoDef['lowerCut'] = cut_min - else: - singleTopoDef['useMin'] = False - singleTopoDef['lowerCut'] = 0. - - if len(l_max)==1: - singleTopoDef['useMax'] = True - singleTopoDef['upperCut'] = cut_max - else: - singleTopoDef['useMax'] = False - singleTopoDef['upperCut'] = 0. + monTool.Histograms = [defineHistogram(histNameTag+'OfAccepted', type='TH1F', path='EXPERT', + title=var+" in accepted combinations; {}".format(var), + xbins=allowed_obs[var]['hist_nbins'], + xmin=allowed_obs[var]['hist_min'], + xmax=allowed_obs[var]['hist_max']), + defineHistogram(histNameTag+'OfProcessed', type='TH1F', path='EXPERT', + title=var+" in processed combinations; {}".format(var), + xbins=allowed_obs[var]['hist_nbins'], + xmin=allowed_obs[var]['hist_min'], + xmax=allowed_obs[var]['hist_max'])] + log.debug("[TrigComboHypoToolFromDict] tool configured for hypo name: %s, topoInfo = %s", chainName, topoInfo) if len(chainDict['extraComboHypos'])==1:#to avoid breaking changes in the ref files - monTool.HistPath = 'ComboHypo/'+name + monTool.HistPath = f'ComboHypo/{chainName}' else: - monTool.HistPath = 'ComboHypo/'+name+"_detail_"+singleTopoDef['var'] + singleTopoDef['legA'] + singleTopoDef['legB'] - singleTopoDef['monTool'] = monTool - + monTool.HistPath = f'ComboHypo/{chainName}_detail_{histNameTag}' + + # Set keys of dict to match tool config properties + singleTopoDef = { + "Variables" : var, + "UseMinVec" : use_min, + "UseMaxVec" : use_max, + "LowerCutVec" : cut_min, + "UpperCutVec" : cut_max, + "LegAVec" : legInfo[0]["HLTId"], + "LegBVec" : legInfo[1]["HLTId"], + "IsLegA_METVec": legInfo[0]["isMET"], + "IsLegB_METVec": legInfo[1]["isMET"], + "MonTools" : monTool, + } topoDefs.append(singleTopoDef) #some debug info - log.debug("[TrigComboHypoToolFromDict] tool configured for hypo name: %s, topoInfo = %s", name, topoInfo) - log.debug("[TrigComboHypoToolFromDict] var = %s", singleTopoDef['var']) - log.debug("[TrigComboHypoToolFromDict] legA = %d", singleTopoDef['legA']) - log.debug("[TrigComboHypoToolFromDict] legB = %d", singleTopoDef['legB']) - if len(l_min)==1: - log.debug("[TrigComboHypoToolFromDict] min = %10.3f", singleTopoDef['lowerCut']) - if len(l_max)==1: - log.debug("[TrigComboHypoToolFromDict] max = %10.3f", singleTopoDef['upperCut']) + log.debug("[TrigComboHypoToolFromDict] tool configured for hypo name: %s, topoInfo = %s", chainName, topoInfo) + log.debug("[TrigComboHypoToolFromDict] var = %s", singleTopoDef['Variables']) + log.debug("[TrigComboHypoToolFromDict] legA = %s", singleTopoDef['LegAVec']) + log.debug("[TrigComboHypoToolFromDict] legB = %s", singleTopoDef['LegBVec']) + if use_min: + log.debug("[TrigComboHypoToolFromDict] min = %10.3f", singleTopoDef['LowerCutVec']) + if use_max: + log.debug("[TrigComboHypoToolFromDict] max = %10.3f", singleTopoDef['UpperCutVec']) #end of the loop over the hypos - tool= TrigComboHypoTool(name) - tool.Variables = [x['var'] for x in topoDefs] - tool.LegAVec = [x['legA'] for x in topoDefs] - tool.IsLegA_METVec = [x['isLegA_MET'] for x in topoDefs] - tool.LegBVec = [x['legB'] for x in topoDefs] - tool.IsLegB_METVec = [x['isLegB_MET'] for x in topoDefs] - tool.UseMinVec = [x['useMin'] for x in topoDefs] - tool.LowerCutVec = [x['lowerCut'] for x in topoDefs] - tool.UseMaxVec = [x['useMax'] for x in topoDefs] - tool.UpperCutVec = [x['upperCut'] for x in topoDefs] - tool.MonTools = [x['monTool'] for x in topoDefs] + + # convert list of dicts into dict of lists + toolProps = {k:[thedef[k] for thedef in topoDefs] for k in topoDefs[0]} + tool = TrigComboHypoTool(chainName, SkipLegCheck=skipLegCheck, **toolProps) return tool @@ -214,6 +200,7 @@ comboConfigurator = { } def addTopoInfo(theChainConfig, mainChainDict, listOfChainDefs, lengthOfChainConfigs): + log.debug("[addTopoInfo] Adding topo info to chain %s", theChainConfig) def findStepIndexInChain(chain, step): for istep,chainstep in enumerate(chain.steps): @@ -222,7 +209,8 @@ def addTopoInfo(theChainConfig, mainChainDict, listOfChainDefs, lengthOfChainCon return None for step,(topoCfg,topoExpr) in theChainConfig.topoMap.items(): - thestep = -1 if step=="last" else findStepIndexInChain(theChainConfig,step) + thestep = theChainConfig.steps[-1] if step=="last" else theChainConfig.steps[findStepIndexInChain(theChainConfig,step)] + log.debug("[addTopoInfo] Adding %s to step %s",topoExpr,thestep) if thestep is None: log.error("Failed to find step %s in Chain! ChainDict follows:", step) log.error(mainChainDict) @@ -237,16 +225,16 @@ def addTopoInfo(theChainConfig, mainChainDict, listOfChainDefs, lengthOfChainCon # No need to add if it has been added previously # Handle better and avoid doing this repeatedly on the same steps? - if topoCfg not in theChainConfig.steps[thestep].comboToolConfs: - if len(theChainConfig.steps[thestep].comboToolConfs) > 0: - log.warning("[addTopoInfo] step %s already has ComboHypo tools %s",theChainConfig.steps[thestep],theChainConfig.steps[thestep].comboToolConfs) + if topoCfg not in thestep.comboToolConfs: + if len(thestep.comboToolConfs) > 0: + log.warning("[addTopoInfo] step %s already has ComboHypo tools %s",thestep,thestep.comboToolConfs) log.warning("[addTopoInfo] these will be added to, make sure this is the behaviour you want.") - theChainConfig.steps[thestep].addComboHypoTools(topoCfg) - theChainConfig.steps[thestep].name = theChainConfig.steps[thestep].name+'_combo_'+topoExpr + thestep.name = thestep.name+'_combo_'+topoExpr + thestep.addComboHypoTools(topoCfg) - theChainConfig.steps[thestep].makeCombo() - log.debug("[addTopoInfo] new combo hypo name: %s",theChainConfig.steps[thestep].combo.name) + thestep.makeCombo() + log.debug("[addTopoInfo] new combo hypo name: %s",thestep.combo.name) if bonus_debug: log.debug("[addTopoInfo] new theChainConfig %s", theChainConfig) diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py index 2272c8d226ac76e7b4cc8038349b92c627ce4c3d..bb8051ace40e9e1ecd530e160555359359bb769b 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py @@ -86,6 +86,8 @@ def setupMenu(): ChainProp(name='HLT_mu6_msonly_L1MU6', groups=SingleMuonGroup, monGroups=['muonMon:shifter','muonMon:val','idMon:t0']), ChainProp(name='HLT_2mu6_10invm70_L1MU6', groups=SingleMuonGroup), + # Using generic hypo + ChainProp(name='HLT_2mu6_10invmAA70_L1MU6', groups=SingleMuonGroup), ChainProp(name='HLT_mu10_lateMu_L1LATE-MU10_XE50', l1SeedThresholds=['FSNOSEED'], groups=SingleMuonGroup), # ATR-20049 @@ -200,6 +202,10 @@ def setupMenu(): #Support photon chains ATR-23425 ChainProp(name='HLT_2g15_loose_dPhi25_m80_L1DPHI-M70-2eEM12M', l1SeedThresholds=['eEM10L'], groups=SupportPhIGroup+MultiPhotonGroup), # TODO: mismatch between L1topo threshold and L1 seed to be fixed ChainProp(name='HLT_2g20_loose_L12EM15VH', groups=SupportLegGroup+MultiPhotonGroup), + # Copy with generic TrigComboHypoTool + ChainProp(name='HLT_2g15_tight_25dphiAA_invmAA80_L1DPHI-M70-2eEM12M', l1SeedThresholds=['eEM10L'], groups=PrimaryPhIGroup+MultiPhotonGroup), + ChainProp(name='HLT_2g15_loose_25dphiAA_invmAA80_L1DPHI-M70-2eEM12M', l1SeedThresholds=['eEM10L'], groups=SupportPhIGroup+MultiPhotonGroup), + ChainProp(name='HLT_2g15_tight_25dphiAA_L1DPHI-M70-2eEM12M', l1SeedThresholds=['eEM10L'], groups=PrimaryPhIGroup+MultiPhotonGroup), #------------ 1e_1g HEG ATR-23158 ChainProp(name='HLT_e25_mergedtight_g35_medium_Heg_02dRAB_L12EM20VH',l1SeedThresholds=['EM20VH','EM20VH'], groups=PrimaryLegGroup+MultiElectronGroup), @@ -287,6 +293,30 @@ def setupMenu(): ChainProp(name='HLT_2g22_tight_L1EM7_UNPAIRED_ISO', l1SeedThresholds=['EM7'], stream=['Late'], groups=PrimaryLegGroup+MultiPhotonGroup), ChainProp(name='HLT_2g50_tight_L1EM7_EMPTY', l1SeedThresholds=['EM7'], stream=['Late'], groups=PrimaryLegGroup+MultiPhotonGroup), ChainProp(name='HLT_2g50_tight_L1EM7_UNPAIRED_ISO', l1SeedThresholds=['EM7'], stream=['Late'], groups=PrimaryLegGroup+MultiPhotonGroup), + + # Alternative formulation of T&P chains with generic mass cut combohypotool + # With & without 'probe' expression to check count consistency + # Zee + ChainProp(name='HLT_e26_lhtight_e15_etcut_probe_50invmAB130_L1EM22VHI', l1SeedThresholds=['EM22VHI','EM7'], groups=TagAndProbeLegGroup+MultiElectronGroup), + ChainProp(name='HLT_e26_lhtight_e15_etcut_50invmAB130_L1EM22VHI', l1SeedThresholds=['EM22VHI','EM7'], groups=MultiElectronGroup), + # Jpsiee + ChainProp(name='HLT_e9_lhtight_e4_etcut_probe_1invmAB3_L1JPSI-1M5-EM7', l1SeedThresholds=['EM7','EM3'], groups=SupportLegGroup+MultiElectronGroup), + ChainProp(name='HLT_e5_lhtight_e9_etcut_probe_1invmAB3_L1JPSI-1M5-EM7', l1SeedThresholds=['EM3','EM7'], groups=SupportLegGroup+MultiElectronGroup), + ChainProp(name='HLT_e14_lhtight_e4_etcut_probe_1invmAB3_L1JPSI-1M5-EM12', l1SeedThresholds=['EM12','EM3'], groups=SupportLegGroup+MultiElectronGroup), + ChainProp(name='HLT_e5_lhtight_e14_etcut_probe_1invmAB3_L1JPSI-1M5-EM12', l1SeedThresholds=['EM3','EM12'], groups=SupportLegGroup+MultiElectronGroup), + ChainProp(name='HLT_e9_lhtight_noringer_e4_etcut_probe_1invmAB3_L1JPSI-1M5-EM7', l1SeedThresholds=['EM7','EM3'], groups=SupportLegGroup+MultiElectronGroup), + ChainProp(name='HLT_e5_lhtight_noringer_e9_etcut_probe_1invmAB3_L1JPSI-1M5-EM7', l1SeedThresholds=['EM3','EM7'], groups=SupportLegGroup+MultiElectronGroup), + ChainProp(name='HLT_e14_lhtight_noringer_e4_etcut_probe_1invmAB3_L1JPSI-1M5-EM12', l1SeedThresholds=['EM12','EM3'], groups=SupportLegGroup+MultiElectronGroup), + ChainProp(name='HLT_e5_lhtight_noringer_e14_etcut_probe_1invmAB3_L1JPSI-1M5-EM12', l1SeedThresholds=['EM3','EM12'], groups=SupportLegGroup+MultiElectronGroup), + # + ChainProp(name='HLT_e9_lhtight_e4_etcut_1invmAB3_L1JPSI-1M5-EM7', l1SeedThresholds=['EM7','EM3'], groups=MultiElectronGroup), + ChainProp(name='HLT_e5_lhtight_e9_etcut_1invmAB3_L1JPSI-1M5-EM7', l1SeedThresholds=['EM3','EM7'], groups=MultiElectronGroup), + ChainProp(name='HLT_e14_lhtight_e4_etcut_1invmAB3_L1JPSI-1M5-EM12', l1SeedThresholds=['EM12','EM3'], groups=MultiElectronGroup), + ChainProp(name='HLT_e5_lhtight_e14_etcut_1invmAB3_L1JPSI-1M5-EM12', l1SeedThresholds=['EM3','EM12'], groups=MultiElectronGroup), + ChainProp(name='HLT_e9_lhtight_noringer_e4_etcut_1invmAB3_L1JPSI-1M5-EM7', l1SeedThresholds=['EM7','EM3'], groups=MultiElectronGroup), + ChainProp(name='HLT_e5_lhtight_noringer_e9_etcut_1invmAB3_L1JPSI-1M5-EM7', l1SeedThresholds=['EM3','EM7'], groups=MultiElectronGroup), + ChainProp(name='HLT_e14_lhtight_noringer_e4_etcut_1invmAB3_L1JPSI-1M5-EM12', l1SeedThresholds=['EM12','EM3'], groups=MultiElectronGroup), + ChainProp(name='HLT_e5_lhtight_noringer_e14_etcut_1invmAB3_L1JPSI-1M5-EM12', l1SeedThresholds=['EM3','EM12'], groups=MultiElectronGroup), ] TriggerFlags.METSlice.signatures = TriggerFlags.METSlice.signatures() + [ diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py index ea35e965b2360d19fb2a2764e77aad7d9ac798f4..aaac56749f9abf18f90284c8155c6c2c8b5e20a1 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py @@ -928,7 +928,7 @@ class ChainStep(object): log.debug("[ChainStep] onlyJets, sig_set: %s, %s",self.onlyJets, sig_set) self.multiplicity = multiplicity self.comboHypoCfg=comboHypoCfg - self.comboToolConfs=comboToolConfs + self.comboToolConfs = list(comboToolConfs) self.stepDicts = chainDicts # one dict per leg self.isEmpty=(sum(multiplicity)==0 or isEmpty) if not self.isEmpty: diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/Physics_pp_run3_v1.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/Physics_pp_run3_v1.py index 6d11e5fdb824ee4939a0536a89c60c0c08b430e3..3151e490f701b638600e95484e94de9e635f67df 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/Physics_pp_run3_v1.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/Physics_pp_run3_v1.py @@ -231,7 +231,7 @@ def setupMenu(): #------- Electron+Photon Chains # primary e-g chains: electron + photon stay in the same step - these need to be parallel merged! ChainProp(name='HLT_e24_lhmedium_g25_medium_02dRAB_L12EM20VH', l1SeedThresholds=['EM20VH','EM20VH'], stream=[PhysicsStream], groups=PrimaryLegGroup+MultiElectronGroup), - ChainProp(name='HLT_e24_lhmedium_2g12_loose_02dRAB_L1EM20VH_3EM10VH', l1SeedThresholds=['EM20VH','EM10VH'], stream=[PhysicsStream], groups=PrimaryLegGroup+MultiElectronGroup), # unsure about l1SeedThresholds + ChainProp(name='HLT_e24_lhmedium_g12_loose_g12_loose_02dRAB_02dRAC_L1EM20VH_3EM10VH', l1SeedThresholds=['EM20VH','EM10VH','EM10VH'], stream=[PhysicsStream], groups=PrimaryLegGroup+MultiElectronGroup), # unsure about l1SeedThresholds # Electron LRT chains ChainProp(name='HLT_e26_lhloose_nopix_lrttight_L1EM22VHI', groups=PrimaryLegGroup+SingleElectronGroup), diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py index 6103c8965b4ac28d18445d1d344bd1307468ac45..51611e330760ae9c86dc6baf44a5141d5af43c81 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py @@ -1028,7 +1028,12 @@ UnconventionalTrackingChainParts_Default = { #========================================================== # Combined Chains #========================================================== -AllowedTopos_comb = ['03dRAB','03dRAB30','02dRAB','50invmAB','60invmAB','afpdijet','18dphiAB','18dphiAC','80mTAC'] +AllowedTopos_comb = [ + '03dRAB','03dRAB30','02dRAB','02dRAC','50invmAB','60invmAB','afpdijet','18dphiAB','18dphiAC','80mTAC', + '1invmAB3','50invmAB130', # Jpsiee, Zee/Zeg + '25dphiAA','invmAA80', # Low-mass diphoton + '10invmAA70', # Low-mass dimuon + ] # ---- Combined Dictionary of all allowed Values ---- CombinedChainParts = deepcopy(PhotonChainParts)