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>
26 const std::map<std::string, TrigComboHypoTool::ComboHypoVars>
VarMap = {
27 {
"dR", TrigComboHypoTool::ComboHypoVars::DR},
28 {
"invm", TrigComboHypoTool::ComboHypoVars::INVM},
29 {
"dphi", TrigComboHypoTool::ComboHypoVars::DPHI},
31 {
"deta", TrigComboHypoTool::ComboHypoVars::DETA}
35 const std::string&
name,
43 errmsg =
"legA ID not set!";
47 errmsg=
"legB ID not set!";
51 errmsg=
"Trying to configure the Tool without setting at least one of UseMin or UseMax!";
55 errmsg =
"Cannot specify the same MET leg for both sides!";
75 ATH_MSG_ERROR(
"Trying to configure the Tool with legA and legB vectors of different size!");
76 return StatusCode::FAILURE;
79 ATH_MSG_ERROR(
"Trying to configure the Tool with UseMin and UseMax vectors of different size!");
80 return StatusCode::FAILURE;
83 ATH_MSG_ERROR(
"Trying to configure the Tool with legA/B and UseMax/Min vectors of different size!");
84 return StatusCode::FAILURE;
87 ATH_MSG_ERROR(
"Trying to configure the Tool with varTag and UseMax/Min(LegA/B) vectors of different size!");
88 return StatusCode::FAILURE;
98 ATH_MSG_ERROR(
"The variable is not present in the ComboHypoVars list");
99 return StatusCode::FAILURE;
115 std::string validmsg{
""};
116 if(!
info.validate(validmsg)) {
118 return StatusCode::FAILURE;
125 return StatusCode::SUCCESS;
132 if (passingLegs.empty()) {
133 return StatusCode::SUCCESS;
136 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.");
137 for(
const auto& legpair : passingLegs) {
138 ATH_MSG_DEBUG(
" Leg " << legpair.first <<
" has " << legpair.second.size() <<
" features");
142 std::vector<Combination> legDecisions;
146 bool hasViableLegs{
true};
152 legMultiplicityForComputation[0] = 2;
153 hasViableLegs = legDecisions[0].size() >= 2;
156 ATH_MSG_DEBUG(
"Var " << varInfo.varTag <<
" needs legs " << varInfo.legA <<
", " << varInfo.legB);
159 if (passingLegs.contains(varInfo.legA) && passingLegs.contains(varInfo.legB)) {
160 size_t goodLegA{
false}, goodLegB{
false};
163 if ((iLegA<0) or (iLegB<0)){
164 ATH_MSG_ERROR(
"TrigComboHypoTool::decide: Index into array is negative");
165 return StatusCode::FAILURE;
167 goodLegA = !passingLegs[varInfo.legA].empty();
168 legMultiplicityForComputation[iLegA] = std::max<size_t>(1,legMultiplicityForComputation[iLegA]);
169 ATH_MSG_DEBUG(
"Leg " << varInfo.legA <<
" has " << passingLegs[varInfo.legA].size() <<
" features --> " << (goodLegA ?
"pass" :
"fail"));
170 if(varInfo.legB != varInfo.legA) {
171 goodLegB = !passingLegs[varInfo.legB].empty();
172 ATH_MSG_DEBUG(
"Leg " << varInfo.legB <<
" has " << passingLegs[varInfo.legB].size() <<
" features --> " << (goodLegB ?
"pass" :
"fail"));
173 legMultiplicityForComputation[iLegB] = std::max<size_t>(1,legMultiplicityForComputation[iLegB]);
175 goodLegB = goodLegA = passingLegs[varInfo.legA].size() >= 2;
176 ATH_MSG_DEBUG(
"Leg " << varInfo.legA <<
" has " << passingLegs[varInfo.legA].size() <<
" features --> " << (goodLegB ?
"pass" :
"fail"));
178 legMultiplicityForComputation[iLegA] = std::max<size_t>(2,legMultiplicityForComputation[iLegA]);
180 hasViableLegs &= (goodLegA && goodLegB);
181 if (!hasViableLegs) {
182 ATH_MSG_DEBUG(
"Did not find at least 2 features on the target legs to compute " << varInfo.varTag);
186 "Insufficient passing legs to compute " << varInfo.varTag
187 <<
", intended on (" << varInfo.legA <<
", " << varInfo.legB <<
")"
189 hasViableLegs =
false;
194 if (!hasViableLegs) {
195 ATH_MSG_DEBUG(
"This ComboHypoTool cannot run in this event, this chain **REJECTS** this event.");
198 return StatusCode::SUCCESS;
205 for (
size_t legindex = 0;
size_t legmult : legMultiplicityForComputation){
206 size_t out_of = legDecisions[legindex].size();
208 extraLegs.insert(extraLegs.end(),legDecisions[legindex].cbegin(),legDecisions[legindex].cend());
210 nucg.
add({out_of, legmult});
211 ATH_MSG_DEBUG(
"For leg index " << legindex <<
" we will be choosing any " << legmult <<
" Decision Objects out of " << out_of);
217 std::vector<Combination> passingCombinations;
218 std::vector<float>
values;
220 size_t warnings = 0, iterations = 0;
222 auto get_index_offset = [&legMultiplicityForComputation](
size_t legindex) {
224 for (
auto iLeg=legMultiplicityForComputation.cbegin(); iLeg!=legMultiplicityForComputation.cbegin()+legindex; ++iLeg) {
230 bool lastDecision(
true);
231 const std::vector<size_t> combination = nucg();
242 size_t legA_index = 0;
243 size_t legB_index = 0;
252 "Computing " << iVarInfo->varTag <<
" on legs "
253 << iVarInfo->legA <<
" (" << legA_index <<
"), "
254 << iVarInfo->legB <<
" (" << legB_index <<
")"
256 if(iVarInfo->legA==iVarInfo->legB) {
259 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)]};
260 combinationToCheck.insert(combinationToCheck.end(),featurePair.cbegin(),featurePair.cend());
261 combinationToRecord.insert(combinationToRecord.end(),featurePair.cbegin(),featurePair.cend());
264 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))]};
265 combinationToCheck.insert(combinationToCheck.end(),featurePair.cbegin(),featurePair.cend());
266 combinationToRecord.insert(combinationToRecord.end(),featurePair.cbegin(),featurePair.cend());
271 ATH_MSG_DEBUG(
"Combination " << (iterations - 1) <<
" decided to be " << (lastDecision ?
"passing" :
"failing") <<
" " << iVarInfo->varTag);
274 return StatusCode::FAILURE;
278 ATH_MSG_WARNING(
"Have so far processed " << iterations <<
" combinations for " <<
decisionId() <<
" in this event, " << passingCombinations.size() <<
" passing.");
281 ATH_MSG_WARNING(
"Too many combinations! Breaking the loop at this point.");
289 combinationToRecord.insert(combinationToRecord.end(),extraLegs.cbegin(),extraLegs.cend());
290 passingCombinations.push_back(std::move(combinationToRecord));
306 ATH_MSG_VERBOSE( varInfo.varTag <<
" = " <<
value <<
" is in range " << varInfo.rangeStr() <<
".");
314 ATH_MSG_DEBUG(
"Passing " << passingCombinations.size() <<
" combinations out of " << iterations <<
", "
315 <<
decisionId() << (passingCombinations.size() ?
" **ACCEPTS**" :
" **REJECTS**") <<
" this event based on OR logic.");
318 ATH_MSG_DEBUG(
"Note: stopped after the first successful combination due to the EnableOverride flag.");
323 const bool passAll = (passingCombinations.size() == iterations);
325 ATH_MSG_DEBUG(
"Passing " << passingCombinations.size() <<
" combinations out of " << iterations <<
", "
326 <<
decisionId() << (passAll ?
" **ACCEPTS**" :
" **REJECTS**") <<
" this event based on AND logic.");
329 ATH_MSG_DEBUG(
"Note: stopped after the first failed combination due to the EnableOverride flag.");
333 passingCombinations.clear();
338 if (not passingCombinations.empty()) {
345 return StatusCode::SUCCESS;
352 std::pair<KineInfo,KineInfo> kinepair;
354 ATH_MSG_ERROR(
"Failed to extract kinematics of feature pair!");
359 float eta_check, phi_check, pt_check;
360 std::tie(eta_check,phi_check,pt_check) = kinepair.first;
361 msg() <<
MSG::VERBOSE <<
" Test filled legA kinematics: pt " << pt_check*
invGeV <<
", eta " << eta_check <<
", phi " << phi_check <<
endmsg;
363 std::tie(eta_check,phi_check,pt_check) = kinepair.second;
364 msg() <<
MSG::VERBOSE <<
" Test filled legB kinematics: pt " << pt_check*
invGeV <<
", eta " << eta_check <<
", phi " << phi_check <<
endmsg;
388 return combId.numeric() == targetleg;
396 std::copy(combination.begin(),combination.end(),std::back_inserter(leg_features));
401 std::copy_if(combination.begin(),combination.end(),std::back_inserter(leg_features),isMyLeg);
404 if (leg_features.size()==2) {
405 legpair.first = leg_features[0];
406 legpair.second = leg_features[1];
408 ATH_MSG_ERROR(leg_features.size() <<
" Decision Objects supplied on leg " <<
leg
409 <<
", must be 2 for same-leg topo selection!");
424 std::copy_if(combination.begin(),combination.end(),std::back_inserter(legA_features),isLegA);
425 if(legA_features.size()!=1) {
426 ATH_MSG_ERROR(legA_features.size() <<
" Decision Objects supplied on leg " << legA
427 <<
", must be 1 for different-leg topo selection!");
431 std::copy_if(combination.begin(),combination.end(),std::back_inserter(legB_features),isLegB);
432 if (legB_features.size()!=1) {
433 ATH_MSG_ERROR(legB_features.size() <<
" Decision Objects supplied on leg " << legB
434 <<
", must be 1 for different-leg topo selection!");
438 legpair.first = legA_features[0];
439 legpair.second = legB_features[0];
448 size_t nFeatures(combination.size());
450 ATH_MSG_ERROR(
"Number of Decision Objects passed is less than 2! Sum over decision objects on all legs = " << combination.size() );
453 std::pair<Combo::LegDecision,Combo::LegDecision> legpair;
458 ATH_MSG_ERROR(
"Failed to extract requisite kinematic info from leg " << varInfo.
legA <<
"!");
463 ATH_MSG_ERROR(
"Failed to extract requisite kinematic info from leg " << varInfo.
legB <<
"!");
473 auto pLink = TrigCompositeUtils::findLink<xAOD::TrigMissingETContainer>( *decision.second,
featureString() ).link;
474 if (!pLink.isValid()){
478 ROOT::Math::XYVectorF metv((*pLink)->ex(),(*pLink)->ey());
483 auto pLink = TrigCompositeUtils::findLink<xAOD::IParticleContainer>( *decision.second,
featureString() ).link;
484 if (!pLink.isValid()){
488 eta = (*pLink)->p4().Eta();
489 phi = (*pLink)->p4().Phi();
490 pt = (*pLink)->p4().Pt();
493 kinematics = std::make_tuple(
eta,
phi,
pt);
499 const auto& [legA_kine,legB_kine] = kinepair;
500 const auto& [
eta1,phi1,pt1] = legA_kine;
501 const auto& [
eta2,phi2,pt2] = legB_kine;
508 case ComboHypoVars::DR:
513 case ComboHypoVars::DPHI:
518 case ComboHypoVars::INVM:
520 ROOT::Math::PtEtaPhiMVector
p1(pt1,
eta1,phi1,0.),
p2(pt2,
eta2,phi2,0.);
530 case ComboHypoVars::DETA:
537 ATH_MSG_ERROR(
"Undefined variable requested -- should never happen!");