6 #include "GaudiKernel/SystemOfUnits.h"
10 #include <Math/Vector4D.h>
11 #include <Math/Vector4Dfwd.h>
12 #include <Math/Vector2D.h>
13 #include <Math/Vector2Dfwd.h>
27 const std::map<std::string, TrigComboHypoTool::ComboHypoVars>
VarMap = {
28 {
"dR", TrigComboHypoTool::ComboHypoVars::DR},
29 {
"invm", TrigComboHypoTool::ComboHypoVars::INVM},
30 {
"dphi", TrigComboHypoTool::ComboHypoVars::DPHI},
32 {
"deta", TrigComboHypoTool::ComboHypoVars::DETA}
36 const std::string&
name,
44 errmsg =
"legA ID not set!";
48 errmsg=
"legB ID not set!";
52 errmsg=
"Trying to configure the Tool without setting at least one of UseMin or UseMax!";
56 errmsg =
"Cannot specify the same MET leg for both sides!";
76 ATH_MSG_ERROR(
"Trying to configure the Tool with legA and legB vectors of different size!");
77 return StatusCode::FAILURE;
80 ATH_MSG_ERROR(
"Trying to configure the Tool with UseMin and UseMax vectors of different size!");
81 return StatusCode::FAILURE;
84 ATH_MSG_ERROR(
"Trying to configure the Tool with legA/B and UseMax/Min vectors of different size!");
85 return StatusCode::FAILURE;
88 ATH_MSG_ERROR(
"Trying to configure the Tool with varTag and UseMax/Min(LegA/B) vectors of different size!");
89 return StatusCode::FAILURE;
99 ATH_MSG_ERROR(
"The variable is not present in the ComboHypoVars list");
100 return StatusCode::FAILURE;
116 std::string validmsg{
""};
117 if(!
info.validate(validmsg)) {
119 return StatusCode::FAILURE;
126 return StatusCode::SUCCESS;
133 if (passingLegs.empty()) {
134 return StatusCode::SUCCESS;
137 ATH_MSG_DEBUG(
"Looking for legs from " <<
decisionId() <<
" in the map. Map contains features for " << passingLegs.size() <<
" legs, which may be data for many chains.");
138 for(
const auto& legpair : passingLegs) {
139 ATH_MSG_DEBUG(
" Leg " << legpair.first <<
" has " << legpair.second.size() <<
" features");
143 std::vector<Combination> legDecisions;
147 bool hasViableLegs{
true};
153 legMultiplicityForComputation[0] = 2;
154 hasViableLegs = legDecisions[0].size() >= 2;
157 ATH_MSG_DEBUG(
"Var " << varInfo.varTag <<
" needs legs " << varInfo.legA <<
", " << varInfo.legB);
160 if (passingLegs.contains(varInfo.legA) && passingLegs.contains(varInfo.legB)) {
161 size_t goodLegA{
false}, goodLegB{
false};
164 goodLegA = !passingLegs[varInfo.legA].empty();
165 legMultiplicityForComputation[iLegA] = std::max<size_t>(1,legMultiplicityForComputation[iLegA]);
166 ATH_MSG_DEBUG(
"Leg " << varInfo.legA <<
" has " << passingLegs[varInfo.legA].size() <<
" features --> " << (goodLegA ?
"pass" :
"fail"));
167 if(varInfo.legB != varInfo.legA) {
168 goodLegB = !passingLegs[varInfo.legB].empty();
169 ATH_MSG_DEBUG(
"Leg " << varInfo.legB <<
" has " << passingLegs[varInfo.legB].size() <<
" features --> " << (goodLegB ?
"pass" :
"fail"));
170 legMultiplicityForComputation[iLegB] = std::max<size_t>(1,legMultiplicityForComputation[iLegB]);
172 goodLegB = goodLegA = passingLegs[varInfo.legA].size() >= 2;
173 ATH_MSG_DEBUG(
"Leg " << varInfo.legA <<
" has " << passingLegs[varInfo.legA].size() <<
" features --> " << (goodLegB ?
"pass" :
"fail"));
175 legMultiplicityForComputation[iLegA] = std::max<size_t>(2,legMultiplicityForComputation[iLegA]);
177 hasViableLegs &= (goodLegA && goodLegB);
178 if (!hasViableLegs) {
179 ATH_MSG_DEBUG(
"Did not find at least 2 features on the target legs to compute " << varInfo.varTag);
183 "Insufficient passing legs to compute " << varInfo.varTag
184 <<
", intended on (" << varInfo.legA <<
", " << varInfo.legB <<
")"
186 hasViableLegs =
false;
191 if (!hasViableLegs) {
192 ATH_MSG_DEBUG(
"This ComboHypoTool cannot run in this event, this chain **REJECTS** this event.");
195 return StatusCode::SUCCESS;
202 for (
size_t legindex = 0;
size_t legmult : legMultiplicityForComputation){
203 size_t out_of = legDecisions[legindex].size();
205 extraLegs.insert(extraLegs.end(),legDecisions[legindex].cbegin(),legDecisions[legindex].cend());
207 nucg.
add({out_of, legmult});
208 ATH_MSG_DEBUG(
"For leg index " << legindex <<
" we will be choosing any " << legmult <<
" Decision Objects out of " << out_of);
214 std::vector<Combination> passingCombinations;
215 std::vector<float>
values;
217 size_t warnings = 0, iterations = 0;
219 auto get_index_offset = [legMultiplicityForComputation](
size_t legindex) {
221 for (
auto iLeg=legMultiplicityForComputation.cbegin(); iLeg!=legMultiplicityForComputation.cbegin()+legindex; ++iLeg) {
227 bool lastDecision(
true);
228 const std::vector<size_t> combination = nucg();
245 "Computing " << iVarInfo->varTag <<
" on legs "
246 << iVarInfo->legA <<
" (" << legA_index <<
"), "
247 << iVarInfo->legB <<
" (" << legB_index <<
")"
249 if(iVarInfo->legA==iVarInfo->legB) {
252 const auto& featurePair = {legDecisions[legA_index][combination.at(legA_index+get_index_offset(legA_index))],legDecisions[legA_index][combination.at(legA_index+get_index_offset(legA_index)+1)]};
253 combinationToCheck.insert(combinationToCheck.end(),featurePair);
254 combinationToRecord.insert(combinationToRecord.end(),featurePair);
257 const auto& featurePair = {legDecisions[legA_index][combination.at(legA_index+get_index_offset(legA_index))],legDecisions[legB_index][combination.at(legB_index+get_index_offset(legB_index))]};
258 combinationToCheck.insert(combinationToCheck.end(),featurePair);
259 combinationToRecord.insert(combinationToRecord.end(),featurePair);
264 ATH_MSG_DEBUG(
"Combination " << (iterations - 1) <<
" decided to be " << (lastDecision ?
"passing" :
"failing") <<
" " << iVarInfo->varTag);
267 return StatusCode::FAILURE;
271 ATH_MSG_WARNING(
"Have so far processed " << iterations <<
" combinations for " <<
decisionId() <<
" in this event, " << passingCombinations.size() <<
" passing.");
274 ATH_MSG_WARNING(
"Too many combinations! Breaking the loop at this point.");
282 combinationToRecord.insert(combinationToRecord.end(),extraLegs.cbegin(),extraLegs.cend());
283 passingCombinations.push_back(combinationToRecord);
299 ATH_MSG_VERBOSE( varInfo.varTag <<
" = " <<
value <<
" is in range " << varInfo.rangeStr() <<
".");
307 ATH_MSG_DEBUG(
"Passing " << passingCombinations.size() <<
" combinations out of " << iterations <<
", "
308 <<
decisionId() << (passingCombinations.size() ?
" **ACCEPTS**" :
" **REJECTS**") <<
" this event based on OR logic.");
311 ATH_MSG_DEBUG(
"Note: stopped after the first successful combination due to the EnableOverride flag.");
316 const bool passAll = (passingCombinations.size() == iterations);
318 ATH_MSG_DEBUG(
"Passing " << passingCombinations.size() <<
" combinations out of " << iterations <<
", "
319 <<
decisionId() << (passAll ?
" **ACCEPTS**" :
" **REJECTS**") <<
" this event based on AND logic.");
322 ATH_MSG_DEBUG(
"Note: stopped after the first failed combination due to the EnableOverride flag.");
326 passingCombinations.clear();
331 if (not passingCombinations.empty()) {
338 return StatusCode::SUCCESS;
345 std::pair<KineInfo,KineInfo> kinepair;
347 ATH_MSG_ERROR(
"Failed to extract kinematics of feature pair!");
352 float eta_check, phi_check, pt_check;
353 std::tie(eta_check,phi_check,pt_check) = kinepair.first;
354 msg() <<
MSG::VERBOSE <<
" Test filled legA kinematics: pt " << pt_check*
invGeV <<
", eta " << eta_check <<
", phi " << phi_check <<
endmsg;
356 std::tie(eta_check,phi_check,pt_check) = kinepair.second;
357 msg() <<
MSG::VERBOSE <<
" Test filled legB kinematics: pt " << pt_check*
invGeV <<
", eta " << eta_check <<
", phi " << phi_check <<
endmsg;
381 return combId.numeric() == targetleg;
389 std::copy(combination.begin(),combination.end(),std::back_inserter(leg_features));
394 std::copy_if(combination.begin(),combination.end(),std::back_inserter(leg_features),isMyLeg);
397 if (leg_features.size()==2) {
398 legpair.first = leg_features[0];
399 legpair.second = leg_features[1];
401 ATH_MSG_ERROR(leg_features.size() <<
" Decision Objects supplied on leg " <<
leg
402 <<
", must be 2 for same-leg topo selection!");
417 std::copy_if(combination.begin(),combination.end(),std::back_inserter(legA_features),isLegA);
418 if(legA_features.size()!=1) {
419 ATH_MSG_ERROR(legA_features.size() <<
" Decision Objects supplied on leg " << legA
420 <<
", must be 1 for different-leg topo selection!");
424 std::copy_if(combination.begin(),combination.end(),std::back_inserter(legB_features),isLegB);
425 if (legB_features.size()!=1) {
426 ATH_MSG_ERROR(legB_features.size() <<
" Decision Objects supplied on leg " << legB
427 <<
", must be 1 for different-leg topo selection!");
431 legpair.first = legA_features[0];
432 legpair.second = legB_features[0];
441 size_t nFeatures(combination.size());
443 ATH_MSG_ERROR(
"Number of Decision Objects passed is less than 2! Sum over decision objects on all legs = " << combination.size() );
446 std::pair<Combo::LegDecision,Combo::LegDecision> legpair;
451 ATH_MSG_ERROR(
"Failed to extract requisite kinematic info from leg " << varInfo.
legA <<
"!");
456 ATH_MSG_ERROR(
"Failed to extract requisite kinematic info from leg " << varInfo.
legB <<
"!");
466 auto pLink = TrigCompositeUtils::findLink<xAOD::TrigMissingETContainer>( *decision.second,
featureString() ).link;
467 if (!pLink.isValid()){
471 ROOT::Math::XYVectorF metv((*pLink)->ex(),(*pLink)->ey());
476 auto pLink = TrigCompositeUtils::findLink<xAOD::IParticleContainer>( *decision.second,
featureString() ).link;
477 if (!pLink.isValid()){
481 eta = (*pLink)->p4().Eta();
482 phi = (*pLink)->p4().Phi();
483 pt = (*pLink)->p4().Pt();
486 kinematics = std::make_tuple(
eta,
phi,
pt);
492 const auto& [legA_kine,legB_kine] = kinepair;
493 const auto& [
eta1,phi1,pt1] = legA_kine;
494 const auto& [
eta2,phi2,pt2] = legB_kine;
501 case ComboHypoVars::DR:
506 case ComboHypoVars::DPHI:
511 case ComboHypoVars::INVM:
513 ROOT::Math::PtEtaPhiMVector
p1(pt1,
eta1,phi1,0.),
p2(pt2,
eta2,phi2,0.);
523 case ComboHypoVars::DETA:
530 ATH_MSG_ERROR(
"Undefined variable requested -- should never happen!");