6#include "GaudiKernel/SystemOfUnits.h"
10#include <Math/Vector4Dfwd.h>
11#include <Math/Vector2D.h>
22constexpr float invGeV = 1. / Gaudi::Units::GeV;
27const std::map<std::string, Trig3VarComboHypoTool::ComboHypoVars>
VarMap = {
32 const std::string& name,
33 const IInterface* parent)
39 errmsg =
"legA ID not set!";
51 errmsg=
"Trying to configure the Tool without setting at least one of UseMin or UseMax!";
55 errmsg =
"Currently all legs must be different";
74 ATH_MSG_ERROR(
"Trying to configure the Tool with legA/legB/legC vectors of different size!");
75 return StatusCode::FAILURE;
78 ATH_MSG_ERROR(
"Trying to configure the Tool with UseMin and UseMax vectors of different size!");
79 return StatusCode::FAILURE;
82 ATH_MSG_ERROR(
"Trying to configure the Tool with legA/B and UseMax/Min vectors of different size!");
83 return StatusCode::FAILURE;
86 ATH_MSG_ERROR(
"Trying to configure the Tool with varTag and UseMax/Min(LegA/B/C) vectors of different size!");
87 return StatusCode::FAILURE;
97 ATH_MSG_ERROR(
"The variable is not present in the ComboHypoVars list");
98 return StatusCode::FAILURE;
115 std::string validmsg{
""};
116 if(!info.validate(validmsg)) {
118 return StatusCode::FAILURE;
125 return StatusCode::SUCCESS;
131 if (passingLegs.empty()) {
132 return StatusCode::SUCCESS;
135 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.");
136 for(
const auto& legpair : passingLegs) {
137 ATH_MSG_DEBUG(
" Leg " << legpair.first <<
" has " << legpair.second.size() <<
" features");
141 std::vector<Combination> legDecisions;
145 bool hasViableLegs{
true};
147 std::vector<size_t> legMultiplicityForComputation(
legMultiplicity().size(),0);
149 ATH_MSG_DEBUG(
"Var " << varInfo.varTag <<
" needs legs " << varInfo.legA <<
", " << varInfo.legB <<
", " << varInfo.legC);
152 if (passingLegs.contains(varInfo.legA) && passingLegs.contains(varInfo.legB) && passingLegs.contains(varInfo.legC)) {
153 bool goodLegA{
false}, goodLegB{
false}, goodLegC{
false};
157 if ((iLegA<0) or (iLegB<0) or (iLegC<0)){
158 ATH_MSG_ERROR(
"Trig3VarComboHypoTool::decide: Index into array is negative");
159 return StatusCode::FAILURE;
161 goodLegA = !passingLegs[varInfo.legA].empty();
162 legMultiplicityForComputation[iLegA] = std::max<size_t>(1,legMultiplicityForComputation[iLegA]);
163 ATH_MSG_DEBUG(
"Leg " << varInfo.legA <<
" has " << passingLegs[varInfo.legA].size() <<
" features --> " << (goodLegA ?
"pass" :
"fail"));
165 if(varInfo.legB == varInfo.legA) {
166 ATH_MSG_ERROR(
"Trig3VarComboHypoTool::decide: legB has to be different from legA");
167 return StatusCode::FAILURE;
169 goodLegB = !passingLegs[varInfo.legB].empty();
170 ATH_MSG_DEBUG(
"Leg " << varInfo.legB <<
" has " << passingLegs[varInfo.legB].size() <<
" features --> " << (goodLegB ?
"pass" :
"fail"));
171 legMultiplicityForComputation[iLegB] = std::max<size_t>(1,legMultiplicityForComputation[iLegB]);
173 if(varInfo.legC == varInfo.legA) {
174 ATH_MSG_ERROR(
"Trig3VarComboHypoTool::decide: legC has to be different from legA");
175 return StatusCode::FAILURE;
177 if(varInfo.legC == varInfo.legB) {
178 ATH_MSG_ERROR(
"Trig3VarComboHypoTool::decide: legC has to be different from legB");
179 return StatusCode::FAILURE;
181 goodLegC = !passingLegs[varInfo.legC].empty();
182 ATH_MSG_DEBUG(
"Leg " << varInfo.legC <<
" has " << passingLegs[varInfo.legC].size() <<
" features --> " << (goodLegC ?
"pass" :
"fail"));
183 legMultiplicityForComputation[iLegC] = std::max<size_t>(1,legMultiplicityForComputation[iLegC]);
185 hasViableLegs &= (goodLegA && goodLegB && goodLegC);
186 if (!hasViableLegs) {
187 ATH_MSG_DEBUG(
"Did not find at least 3 features on the target legs to compute " << varInfo.varTag);
191 "Insufficient passing legs to compute " << varInfo.varTag
192 <<
", intended on (" << varInfo.legA <<
", " << varInfo.legB <<
", " << varInfo.legC <<
")"
194 hasViableLegs =
false;
199 if (!hasViableLegs) {
200 ATH_MSG_DEBUG(
"This Trig3VarComboHypoTool cannot run in this event, this chain **REJECTS** this event.");
203 return StatusCode::SUCCESS;
210 for (
size_t legindex = 0;
size_t legmult : legMultiplicityForComputation){
211 size_t out_of = legDecisions[legindex].size();
213 extraLegs.insert(extraLegs.end(),legDecisions[legindex].cbegin(),legDecisions[legindex].cend());
215 nucg.
add({out_of, legmult});
216 ATH_MSG_DEBUG(
"For leg index " << legindex <<
" we will be choosing any " << legmult <<
" Decision Objects out of " << out_of);
222 std::vector<Combination> passingCombinations;
223 std::vector<float> values;
225 size_t warnings = 0, iterations = 0;
227 auto get_index_offset = [&legMultiplicityForComputation](
size_t legindex) {
229 for (
auto iLeg=legMultiplicityForComputation.cbegin(); iLeg!=legMultiplicityForComputation.cbegin()+legindex; ++iLeg) {
235 bool lastDecision(
true);
236 const std::vector<size_t> combination = nucg();
247 size_t legA_index{0};
248 size_t legB_index{0};
249 size_t legC_index{0};
256 "Computing " << iVarInfo->varTag <<
" on legs "
257 << iVarInfo->legA <<
" (" << legA_index <<
"), "
258 << iVarInfo->legB <<
" (" << legB_index <<
"), "
259 << iVarInfo->legC <<
" (" << legC_index <<
")"
261 if(iVarInfo->legA==iVarInfo->legB) {
265 if(iVarInfo->legA==iVarInfo->legC) {
269 if(iVarInfo->legB==iVarInfo->legC) {
275 Combination featureTrio = {legDecisions[legA_index][combination.at(legA_index+get_index_offset(legA_index))],
276 legDecisions[legB_index][combination.at(legB_index+get_index_offset(legB_index))],
277 legDecisions[legC_index][combination.at(legC_index+get_index_offset(legC_index))]};
278 combinationToCheck.insert(combinationToCheck.end(),featureTrio.cbegin(),featureTrio.cend());
279 combinationToRecord.insert(combinationToRecord.end(),featureTrio.cbegin(),featureTrio.cend());
282 lastDecision =
executeAlgStep(combinationToCheck, *iVarInfo, values);
283 ATH_MSG_DEBUG(
"Combination " << (iterations - 1) <<
" decided to be " << (lastDecision ?
"passing" :
"failing") <<
" " << iVarInfo->varTag);
284 }
catch (std::exception& e) {
286 return StatusCode::FAILURE;
290 ATH_MSG_WARNING(
"Have so far processed " << iterations <<
" combinations for " <<
decisionId() <<
" in this event, " << passingCombinations.size() <<
" passing.");
293 ATH_MSG_WARNING(
"Too many combinations! Breaking the loop at this point.");
301 combinationToRecord.insert(combinationToRecord.end(),extraLegs.cbegin(),extraLegs.cend());
302 passingCombinations.push_back(std::move(combinationToRecord));
315 float value = values[varInfo.index];
318 ATH_MSG_VERBOSE( varInfo.varTag <<
" = " << value <<
" is in range " << varInfo.rangeStr() <<
".");
327 ATH_MSG_DEBUG(
"Passing " << passingCombinations.size() <<
" combinations out of " << iterations <<
", "
328 <<
decisionId() << (passingCombinations.size() ?
" **ACCEPTS**" :
" **REJECTS**") <<
" this event based on OR logic.");
331 ATH_MSG_DEBUG(
"Note: stopped after the first successful combination due to the EnableOverride flag.");
336 const bool passAll = (passingCombinations.size() == iterations);
338 ATH_MSG_DEBUG(
"Passing " << passingCombinations.size() <<
" combinations out of " << iterations <<
", "
339 <<
decisionId() << (passAll ?
" **ACCEPTS**" :
" **REJECTS**") <<
" this event based on AND logic.");
342 ATH_MSG_DEBUG(
"Note: stopped after the first failed combination due to the EnableOverride flag.");
346 passingCombinations.clear();
351 if (not passingCombinations.empty()) {
358 return StatusCode::SUCCESS;
364 std::tuple<KineInfo,KineInfo,KineInfo> kinetrio;
366 ATH_MSG_ERROR(
"Failed to extract kinematics of feature trio!");
370 if(msgLvl(MSG::VERBOSE)) {
371 float etaCheck, phiCheck, ptCheck;
372 std::tie(etaCheck,phiCheck,ptCheck) = std::get<0>(kinetrio);
373 msg() << MSG::VERBOSE <<
" Test filled legA kinematics: pt " << ptCheck*
invGeV <<
", eta " << etaCheck <<
", phi " << phiCheck <<
endmsg;
375 std::tie(etaCheck,phiCheck,ptCheck) = std::get<1>(kinetrio);
376 msg() << MSG::VERBOSE <<
" Test filled legB kinematics: pt " << ptCheck*
invGeV <<
", eta " << etaCheck <<
", phi " << phiCheck <<
endmsg;
378 std::tie(etaCheck,phiCheck,ptCheck) = std::get<2>(kinetrio);
379 msg() << MSG::VERBOSE <<
" Test filled legC kinematics: pt " << ptCheck*
invGeV <<
", eta " << etaCheck <<
", phi " << phiCheck <<
endmsg;
388 vals.push_back(value);
389 bool pass = varInfo.
test(value);
402 return combId.numeric() == targetleg;
408 auto isLegA = [&legA](
const Combo::LegDecision& d) {
return testLegId3varcombo(d,legA); };
409 auto isLegB = [&legB](
const Combo::LegDecision& d) {
return testLegId3varcombo(d,legB); };
410 auto isLegC = [&legC](
const Combo::LegDecision& d) {
return testLegId3varcombo(d,legC); };
411 Combination legA_features, legB_features, legC_features;
413 std::copy_if(combination.begin(),combination.end(),std::back_inserter(legA_features),isLegA);
414 if(legA_features.size()!=1) {
415 ATH_MSG_ERROR(legA_features.size() <<
" Decision Objects supplied on leg " << legA
416 <<
", must be 1 for different-leg topo selection!");
420 std::copy_if(combination.begin(),combination.end(),std::back_inserter(legB_features),isLegB);
421 if (legB_features.size()!=1) {
422 ATH_MSG_ERROR(legB_features.size() <<
" Decision Objects supplied on leg " << legB
423 <<
", must be 1 for different-leg topo selection!");
427 std::copy_if(combination.begin(),combination.end(),std::back_inserter(legC_features),isLegC);
428 if (legC_features.size()!=1) {
429 ATH_MSG_ERROR(legB_features.size() <<
" Decision Objects supplied on leg " << legC
430 <<
", must be 1 for different-leg topo selection!");
434 std::get<0>(legtrio) = legA_features[0];
435 std::get<1>(legtrio) = legB_features[0];
436 std::get<2>(legtrio) = legC_features[0];
444 size_t nFeatures(combination.size());
446 ATH_MSG_ERROR(
"Number of Decision Objects passed is less than 3! Sum over decision objects on all legs = " << combination.size() );
449 std::tuple<Combo::LegDecision,Combo::LegDecision,Combo::LegDecision> legtrio;
453 ATH_MSG_ERROR(
"Failed to extract requisite kinematic info from leg " << varInfo.
legA <<
"!");
458 ATH_MSG_ERROR(
"Failed to extract requisite kinematic info from leg " << varInfo.
legB <<
"!");
463 ATH_MSG_ERROR(
"Failed to extract requisite kinematic info from leg " << varInfo.
legC <<
"!");
473 if (!pLink.isValid()){
477 ROOT::Math::XYVectorF metv((*pLink)->ex(),(*pLink)->ey());
483 if (!pLink.isValid()){
487 eta = (*pLink)->p4().Eta();
488 phi = (*pLink)->p4().Phi();
489 pt = (*pLink)->p4().Pt();
492 kinematics = std::make_tuple(
eta,
phi,pt);
497 const auto& [legA_kine,legB_kine,legC_kine] = kinetrio;
498 const auto& [eta1,phi1,pt1] = legA_kine;
499 const auto& [eta2,phi2,pt2] = legB_kine;
500 const auto& [eta3,phi3,pt3] = legC_kine;
510 ROOT::Math::PtEtaPhiMVector p1(pt1,eta1,phi1,0.), p2(pt2,eta2,phi2,0.);
511 value = (p1+p2).M()*
invGeV;
517 ATH_MSG_DEBUG(
" invmAB = " << value <<
", dRAC = " << dRAC <<
", dRBC = " << dRBC);
519 if(dRAC < 0.2 || dRBC < 0.2)
526 ATH_MSG_ERROR(
"Undefined variable requested -- should never happen!");
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
Header file to be included by clients of the Monitored infrastructure.
static thread_local std::ostringstream errmsg
An ensemble of UniqueCombinationGenerator API description.
void add(const UniqueCombinationGenerator &gen)
Group of local monitoring quantities and retain correlation when filling histograms
Declare a monitored scalar variable.
const std::string & featureString()
int32_t getIndexFromLeg(const HLT::Identifier &legIdentifier)
Extract the numeric index of a leg identifier.
LinkInfo< T > findLink(const Decision *start, const std::string &linkName, const bool suppressMultipleLinksWarning=false)
Perform a recursive search for ElementLinks of type T and name 'linkName', starting from Decision obj...
bool isLegId(const HLT::Identifier &legIdentifier)
Recognise whether the chain ID is a leg ID.
double deltaR(double rapidity1, double phi1, double rapidity2, double phi2)
from bare bare rapidity,phi