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 if ((iLegA<0) or (iLegB<0)){
165 ATH_MSG_ERROR(
"TrigComboHypoTool::decide: Index into array is negative");
166 return StatusCode::FAILURE;
168 goodLegA = !passingLegs[varInfo.legA].empty();
169 legMultiplicityForComputation[iLegA] = std::max<size_t>(1,legMultiplicityForComputation[iLegA]);
170 ATH_MSG_DEBUG(
"Leg " << varInfo.legA <<
" has " << passingLegs[varInfo.legA].size() <<
" features --> " << (goodLegA ?
"pass" :
"fail"));
171 if(varInfo.legB != varInfo.legA) {
172 goodLegB = !passingLegs[varInfo.legB].empty();
173 ATH_MSG_DEBUG(
"Leg " << varInfo.legB <<
" has " << passingLegs[varInfo.legB].size() <<
" features --> " << (goodLegB ?
"pass" :
"fail"));
174 legMultiplicityForComputation[iLegB] = std::max<size_t>(1,legMultiplicityForComputation[iLegB]);
176 goodLegB = goodLegA = passingLegs[varInfo.legA].size() >= 2;
177 ATH_MSG_DEBUG(
"Leg " << varInfo.legA <<
" has " << passingLegs[varInfo.legA].size() <<
" features --> " << (goodLegB ?
"pass" :
"fail"));
179 legMultiplicityForComputation[iLegA] = std::max<size_t>(2,legMultiplicityForComputation[iLegA]);
181 hasViableLegs &= (goodLegA && goodLegB);
182 if (!hasViableLegs) {
183 ATH_MSG_DEBUG(
"Did not find at least 2 features on the target legs to compute " << varInfo.varTag);
187 "Insufficient passing legs to compute " << varInfo.varTag
188 <<
", intended on (" << varInfo.legA <<
", " << varInfo.legB <<
")"
190 hasViableLegs =
false;
195 if (!hasViableLegs) {
196 ATH_MSG_DEBUG(
"This ComboHypoTool cannot run in this event, this chain **REJECTS** this event.");
199 return StatusCode::SUCCESS;
206 for (
size_t legindex = 0;
size_t legmult : legMultiplicityForComputation){
207 size_t out_of = legDecisions[legindex].size();
209 extraLegs.insert(extraLegs.end(),legDecisions[legindex].cbegin(),legDecisions[legindex].cend());
211 nucg.
add({out_of, legmult});
212 ATH_MSG_DEBUG(
"For leg index " << legindex <<
" we will be choosing any " << legmult <<
" Decision Objects out of " << out_of);
218 std::vector<Combination> passingCombinations;
219 std::vector<float>
values;
221 size_t warnings = 0, iterations = 0;
223 auto get_index_offset = [&legMultiplicityForComputation](
size_t legindex) {
225 for (
auto iLeg=legMultiplicityForComputation.cbegin(); iLeg!=legMultiplicityForComputation.cbegin()+legindex; ++iLeg) {
231 bool lastDecision(
true);
232 const std::vector<size_t> combination = nucg();
249 "Computing " << iVarInfo->varTag <<
" on legs "
250 << iVarInfo->legA <<
" (" << legA_index <<
"), "
251 << iVarInfo->legB <<
" (" << legB_index <<
")"
253 if(iVarInfo->legA==iVarInfo->legB) {
256 Combination 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)]};
257 combinationToCheck.insert(combinationToCheck.end(),featurePair.cbegin(),featurePair.cend());
258 combinationToRecord.insert(combinationToRecord.end(),featurePair.cbegin(),featurePair.cend());
261 Combination 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))]};
262 combinationToCheck.insert(combinationToCheck.end(),featurePair.cbegin(),featurePair.cend());
263 combinationToRecord.insert(combinationToRecord.end(),featurePair.cbegin(),featurePair.cend());
268 ATH_MSG_DEBUG(
"Combination " << (iterations - 1) <<
" decided to be " << (lastDecision ?
"passing" :
"failing") <<
" " << iVarInfo->varTag);
271 return StatusCode::FAILURE;
275 ATH_MSG_WARNING(
"Have so far processed " << iterations <<
" combinations for " <<
decisionId() <<
" in this event, " << passingCombinations.size() <<
" passing.");
278 ATH_MSG_WARNING(
"Too many combinations! Breaking the loop at this point.");
286 combinationToRecord.insert(combinationToRecord.end(),extraLegs.cbegin(),extraLegs.cend());
287 passingCombinations.push_back(combinationToRecord);
303 ATH_MSG_VERBOSE( varInfo.varTag <<
" = " <<
value <<
" is in range " << varInfo.rangeStr() <<
".");
311 ATH_MSG_DEBUG(
"Passing " << passingCombinations.size() <<
" combinations out of " << iterations <<
", "
312 <<
decisionId() << (passingCombinations.size() ?
" **ACCEPTS**" :
" **REJECTS**") <<
" this event based on OR logic.");
315 ATH_MSG_DEBUG(
"Note: stopped after the first successful combination due to the EnableOverride flag.");
320 const bool passAll = (passingCombinations.size() == iterations);
322 ATH_MSG_DEBUG(
"Passing " << passingCombinations.size() <<
" combinations out of " << iterations <<
", "
323 <<
decisionId() << (passAll ?
" **ACCEPTS**" :
" **REJECTS**") <<
" this event based on AND logic.");
326 ATH_MSG_DEBUG(
"Note: stopped after the first failed combination due to the EnableOverride flag.");
330 passingCombinations.clear();
335 if (not passingCombinations.empty()) {
342 return StatusCode::SUCCESS;
349 std::pair<KineInfo,KineInfo> kinepair;
351 ATH_MSG_ERROR(
"Failed to extract kinematics of feature pair!");
356 float eta_check, phi_check, pt_check;
357 std::tie(eta_check,phi_check,pt_check) = kinepair.first;
358 msg() <<
MSG::VERBOSE <<
" Test filled legA kinematics: pt " << pt_check*
invGeV <<
", eta " << eta_check <<
", phi " << phi_check <<
endmsg;
360 std::tie(eta_check,phi_check,pt_check) = kinepair.second;
361 msg() <<
MSG::VERBOSE <<
" Test filled legB kinematics: pt " << pt_check*
invGeV <<
", eta " << eta_check <<
", phi " << phi_check <<
endmsg;
385 return combId.numeric() == targetleg;
393 std::copy(combination.begin(),combination.end(),std::back_inserter(leg_features));
398 std::copy_if(combination.begin(),combination.end(),std::back_inserter(leg_features),isMyLeg);
401 if (leg_features.size()==2) {
402 legpair.first = leg_features[0];
403 legpair.second = leg_features[1];
405 ATH_MSG_ERROR(leg_features.size() <<
" Decision Objects supplied on leg " <<
leg
406 <<
", must be 2 for same-leg topo selection!");
421 std::copy_if(combination.begin(),combination.end(),std::back_inserter(legA_features),isLegA);
422 if(legA_features.size()!=1) {
423 ATH_MSG_ERROR(legA_features.size() <<
" Decision Objects supplied on leg " << legA
424 <<
", must be 1 for different-leg topo selection!");
428 std::copy_if(combination.begin(),combination.end(),std::back_inserter(legB_features),isLegB);
429 if (legB_features.size()!=1) {
430 ATH_MSG_ERROR(legB_features.size() <<
" Decision Objects supplied on leg " << legB
431 <<
", must be 1 for different-leg topo selection!");
435 legpair.first = legA_features[0];
436 legpair.second = legB_features[0];
445 size_t nFeatures(combination.size());
447 ATH_MSG_ERROR(
"Number of Decision Objects passed is less than 2! Sum over decision objects on all legs = " << combination.size() );
450 std::pair<Combo::LegDecision,Combo::LegDecision> legpair;
455 ATH_MSG_ERROR(
"Failed to extract requisite kinematic info from leg " << varInfo.
legA <<
"!");
460 ATH_MSG_ERROR(
"Failed to extract requisite kinematic info from leg " << varInfo.
legB <<
"!");
470 auto pLink = TrigCompositeUtils::findLink<xAOD::TrigMissingETContainer>( *decision.second,
featureString() ).link;
471 if (!pLink.isValid()){
475 ROOT::Math::XYVectorF metv((*pLink)->ex(),(*pLink)->ey());
480 auto pLink = TrigCompositeUtils::findLink<xAOD::IParticleContainer>( *decision.second,
featureString() ).link;
481 if (!pLink.isValid()){
485 eta = (*pLink)->p4().Eta();
486 phi = (*pLink)->p4().Phi();
487 pt = (*pLink)->p4().Pt();
490 kinematics = std::make_tuple(
eta,
phi,
pt);
496 const auto& [legA_kine,legB_kine] = kinepair;
497 const auto& [
eta1,phi1,pt1] = legA_kine;
498 const auto& [
eta2,phi2,pt2] = legB_kine;
505 case ComboHypoVars::DR:
510 case ComboHypoVars::DPHI:
515 case ComboHypoVars::INVM:
517 ROOT::Math::PtEtaPhiMVector
p1(pt1,
eta1,phi1,0.),
p2(pt2,
eta2,phi2,0.);
527 case ComboHypoVars::DETA:
534 ATH_MSG_ERROR(
"Undefined variable requested -- should never happen!");