ATLAS Offline Software
Loading...
Searching...
No Matches
AsgElectronSelectorTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
14
15// Include this class's header
21
22
23//EDM includes
24#include "xAODEgamma/Electron.h"
26#include "TEnv.h"
27
30// STL includes
31#include <string>
32#include <cstdint>
33#include <cmath>
34#include <unordered_map>
35
37{
62
63 const std::unordered_map<std::string, int> variableMap = {
64 {"eta", eta},
65 {"et", et},
66 {"f3", f3},
67 {"Rhad", Rhad},
68 {"Rhad1", Rhad1},
69 {"Reta", Reta},
70 {"weta2", weta2},
71 {"f1", f1},
72 {"Eratio", Eratio},
73 {"deltaEta1", deltaEta1},
74 {"d0", d0},
75 {"qd0", qd0},
76 {"d0significance", d0significance},
77 {"Rphi", Rphi},
78 {"dPOverP", dPOverP},
79 {"deltaPhiRescaled2", deltaPhiRescaled2},
80 {"trans_TRTPID", trans_TRTPID},
81 {"wtots1", wtots1},
82 {"EoverP", EoverP},
83 {"nPixHitsPlusDeadSensors", nPixHitsPlusDeadSensors},
84 {"nSCTHitsPlusDeadSensors", nSCTHitsPlusDeadSensors},
85 {"SCTWeightedCharge", SCTWeightedCharge},
86 };
87};
88
90 TEnv& env,
91 const std::string& prefixName,
92 const std::string& layerName,
93 const std::string& userModelFileName,
94 const std::string& userQuantileFileName,
95 asg::AsgTool* parentTool
96) {
97 prefix = prefixName;
98 name = layerName;
99 unsigned int numberOfExpectedBinCombinedMVA = AsgElectronSelectorTool::s_fnDiscEtBins * AsgElectronSelectorTool::s_fnDiscEtaBins;
100 unsigned int numberOfExpectedEtaBins = AsgElectronSelectorTool::s_fnDiscEtBins;
101 // 1. Getting quantiles and model files
102 std::string modelFile = !userModelFileName.empty()
103 ? userModelFileName
104 : env.GetValue((prefix + "inputModelFileName").c_str(), "");
105
106 std::string quantileFile = !userQuantileFileName.empty()
107 ? userQuantileFileName
108 : env.GetValue((prefix + "inputQuantileFileName").c_str(), "");
109
110 std::string modelPath = PathResolverFindCalibFile(modelFile);
111 std::string quantilePath = PathResolverFindCalibFile(quantileFile);
112
113 if (modelPath.empty() || quantilePath.empty()) {
114 return false;
115 }
116
117 // 2.
118 m_multiClass = env.GetValue((prefix + "multiClass").c_str(), false);
119 m_nOutputs = env.GetValue((prefix + "n_outputs").c_str(), m_multiClass ? 6 : 1);
120 // Include cf node in numerator or denominator when combining different outputs
121 m_cfSignal = env.GetValue((prefix + "cfSignal").c_str(), false);
122
123 // 3.
124 std::string varStr = env.GetValue((prefix + "Variables").c_str(), "");
125 std::stringstream varsStream(varStr);
126 std::string substr;
127
128 std::vector<std::string> tempVariables;
129 m_enum_variables.clear();
130
131 while (std::getline(varsStream, substr, ',')) {
132 if (substr.empty()) continue;
133 if (!prefix.empty() && substr.rfind(prefix, 0) == 0) {
134 substr = substr.substr(prefix.length());
135 }
137 return false;
138 }
139 tempVariables.push_back(substr);
141 }
142
143 if (tempVariables.empty()) return false;
144
145 m_cutAmbiguity = AsgConfigHelper::HelperInt((prefix + "CutAmbiguity").c_str(), env);
146 m_cutBL = AsgConfigHelper::HelperInt((prefix + "CutBL").c_str(), env);
147 m_cutPi = AsgConfigHelper::HelperInt((prefix + "CutPi").c_str(), env);
148 m_cutSCT = AsgConfigHelper::HelperInt((prefix + "CutSCT").c_str(), env);
149 m_fractions = AsgConfigHelper::HelperDouble((prefix + "Fractions").c_str(), env);
150 m_cutSelector = AsgConfigHelper::HelperDouble((prefix + "CutSelector").c_str(), env);
151 m_cutSelectorCF = AsgConfigHelper::HelperDouble((prefix + "CutSelectorCF").c_str(), env);
152
153
154
155 if (m_cutSelector.size() != numberOfExpectedBinCombinedMVA){
156 parentTool->msg(MSG::ERROR) <<"Configuration issue : cutSelector expected size " << numberOfExpectedBinCombinedMVA <<
157 " input size " << m_cutSelector.size();
158 return false;
159 }
160 if (!m_cutSelectorCF.empty()){
161 m_CFReject = true;
162 if (m_cutSelectorCF.size() != numberOfExpectedBinCombinedMVA){
163 parentTool->msg(MSG::ERROR) <<"Configuration issue : cutSelectorCF expected size " << numberOfExpectedBinCombinedMVA <<
164 " input size " << m_cutSelectorCF.size();
165 return false;
166 }
167 if(!m_multiClass){
168 parentTool->msg(MSG::ERROR) <<"Configuration issue : CF rejection is only defined "
169 "for multiClass: TRUE";
170 return false;
171 }
172 } else {
173 m_CFReject = false;
174 }
175
176 if (m_multiClass){
177 unsigned int nFractionsPerBin = m_nOutputs - 1;
178 unsigned int expectedFractionsSize = numberOfExpectedEtaBins * nFractionsPerBin;
179
180 if (m_fractions.size() != expectedFractionsSize) {
181 parentTool->msg(MSG::ERROR) <<"Configuration issue: multiclass is TRUE, but the number of fractions ("
182 << m_fractions.size() << ") does not match " << m_nOutputs << " classes ("
183 << expectedFractionsSize << " fractions expected).";
184 return false;
185 }
186 }
187
188 m_mvaTool = std::make_unique<ElectronDNNCalculator>(
189 dynamic_cast<AsgElectronSelectorTool*>(parentTool),
190 modelPath.c_str(),
191 quantilePath.c_str(),
192 tempVariables
193 );
194
195 m_defaultOutputs = std::vector<float>(m_nOutputs, -999.0f);
196 return true;
197}
198
199std::vector<float> AsgElectronSelectorTool::SelectionLayer::evaluate(const std::vector<double>& inputs) const {
200 if (!m_mvaTool) return m_defaultOutputs;
201 auto scores = m_mvaTool->calculate(inputs);
202 std::vector<float> res(scores.rows());
203 for (int i = 0; i < scores.rows(); ++i) {
204 res[i] = scores(i, 0);
205 }
206 return res;
207}
208
209
210//=============================================================================
211// Standard constructor
212//=============================================================================
214 AsgTool(myname),
215 m_configFile{""}
216{
217
218 // Declare the needed properties
219 declareProperty("WorkingPoint", m_workingPoint="", "The Working Point");
220 declareProperty("ConfigFile", m_configFile="", "The config file to use");
221
222 // model file name. Managed in the ElectronDNNCalculator.
223 declareProperty("inputModelFileName", m_modelFileName="", "The input file name that holds the model" );
224 // QuantileTransformer file name ( required for preprocessing ). Managed in the ElectronDNNCalculator.
225 declareProperty("quantileFileName", m_quantileFileName="", "The input file name that holds the QuantileTransformer");
226 // especially for trigger electron
227 declareProperty("skipDeltaPoverP",m_skipDeltaPoverP = false,"If true, it will skip the check of deltaPoverP");
228
229 declareProperty("skipAmbiguityCut",m_skipAmbiguityCut = false,"If true, it will skip the ambiguity cut");
230}
231
232
233//=============================================================================
234// Standard destructor
235//=============================================================================
237= default;
238
239
240//=============================================================================
241// Asgena initialize method
242//=============================================================================
244{
245
246if (m_configFile.empty()) {
247 if (!m_workingPoint.empty()){
249 ATH_MSG_INFO("operating point : " << this->getOperatingPointName());
250 }
251}
252else {
253 ATH_MSG_INFO("Using USER provided config file: " << m_configFile);
254}
255 if (m_configFile.empty()){
256 ATH_MSG_ERROR("Could not find configuration file " << m_configFile);
257 return StatusCode::FAILURE;
258 }
259
261 ATH_MSG_INFO("CONFIG FILE (logical): " << m_configFile);
262 ATH_MSG_INFO("CONFIG FILE (resolved full path): " << configFile);
263
264 if (configFile.empty()){
265 ATH_MSG_ERROR("Could not locate " << m_configFile);
266 return StatusCode::FAILURE;
267 }
268
269 ATH_MSG_DEBUG("Configfile to use: " << m_configFile);
270 TEnv env;
271 env.ReadFile(configFile.c_str(), kEnvLocal);
272
273 int nLayers = env.GetValue("nSelectionLayers", 1);
274
275 const std::vector<std::string> defaultPrefixes = {
276 "", // Layer 0: No prefix
277 "SecondSelection.", // Layer 1
278 "ThirdSelection.", // Layer 2
279 "FourthSelection." // Layer 3
280 };
281
282 m_layers.clear();
283 for (int i = 0; i < nLayers; ++i) {
284 std::string prefix = (i < static_cast<int>(defaultPrefixes.size()))
285 ? defaultPrefixes[i]
286 : ("Layer" + std::to_string(i + 1) + ".");
287
288 std::string layerName = (i == 0) ? "FirstSelection"
289 : (i == 1) ? "SecondSelection"
290 : ("Layer" + std::to_string(i + 1));
291
292 SelectionLayer layer;
293 std::string userModel = (i == 0) ? m_modelFileName : "";
294 std::string userQuantile = (i == 0) ? m_quantileFileName : "";
295
296 if (!layer.initialize(env, prefix, layerName, userModel, userQuantile, this)) {
297 ATH_MSG_ERROR("Error initializing layer " << i << " with prefix: " << prefix);
298 return StatusCode::FAILURE;
299 }
300 m_layers.push_back(std::move(layer));
301 }
302
303 // do smooth interpolation between bins
304 m_doSmoothBinInterpolation = env.GetValue("doSmoothBinInterpolation", false);
305
306 // --------------------------------------------------------------------------
307 // Register the cuts and check that the registration worked:
308 // NOTE: THE ORDER IS IMPORTANT!!! Cut0 corresponds to bit 0, Cut1 to bit 1,...
309 // use an int as a StatusCode
310 int sc(1);
311
312 // Cut position for the kineatic pre-selection
313 m_cutPosition_kinematic = m_acceptMVA.addCut("kinematic", "pass kinematic");
314 if (m_cutPosition_kinematic < 0) sc = 0;
315
316 // NSilicon
317 m_cutPosition_NSilicon = m_acceptMVA.addCut("NSCT", "pass NSCT");
318 if (m_cutPosition_NSilicon < 0) sc = 0;
319
320 // NPixel
321 m_cutPosition_NPixel = m_acceptMVA.addCut("NPixel", "pass NPixel");
322 if (m_cutPosition_NPixel < 0) sc = 0;
323
324 // NBlayer
325 m_cutPosition_NBlayer = m_acceptMVA.addCut("NBlayer", "pass NBlayer");
326 if (m_cutPosition_NBlayer < 0) sc = 0;
327
328 // Ambiguity
329 m_cutPosition_ambiguity = m_acceptMVA.addCut("ambiguity", "pass ambiguity");
330 if (m_cutPosition_ambiguity < 0) sc = 0;
331
332
333 // Cut position for the likelihood selection - DO NOT CHANGE ORDER!
334 m_cutPosition_MVA = m_acceptMVA.addCut("passMVA", "pass MVA");
335 if (m_cutPosition_MVA < 0) sc = 0;
336
337 // Check that we got everything OK
338 if (sc == 0){
339 ATH_MSG_ERROR("ERROR: Something went wrong with the setup of the decision objects...");
340 return StatusCode::FAILURE;
341 }
342
343 ATH_MSG_INFO("Initialization SUCCESS");
344 return StatusCode::SUCCESS;
345}
346
347
348//=============================================================================
349// return the accept info object
350//=============================================================================
351
356
357//=============================================================================
358// The main accept method: the actual cuts are applied here
359//=============================================================================
360asg::AcceptData AsgElectronSelectorTool::accept( const EventContext& ctx, const xAOD::Electron* eg, double mu ) const
361{
362 ATH_MSG_VERBOSE("\t AsgElectronSelectorTool::accept( &ctx, *eg, mu= "<<(&ctx)<<", "<<eg<<", "<<mu<<" )");
363
364 // Setup return accept with AcceptInfo
365 asg::AcceptData acceptData(&m_acceptMVA);
366
367 if (!eg){
368 throw std::runtime_error("AsgElectronSelectorTool: Failed, no electron object was passed");
369 }
370
371 const xAOD::CaloCluster* cluster = eg->caloCluster();
372 if (!cluster){
373 ATH_MSG_DEBUG("exiting because cluster is NULL " << cluster);
374 return acceptData;
375 }
376
377 if(!cluster->hasSampling(CaloSampling::CaloSample::EMB2) && !cluster->hasSampling(CaloSampling::CaloSample::EME2)){
378 ATH_MSG_DEBUG("Failed, cluster is missing samplings EMB2 and EME2");
379 return acceptData;
380 }
381
382 const double energy = cluster->e();
383 const float eta = cluster->etaBE(2);
384
385 if(isForwardElectron(eg, eta)){
386 ATH_MSG_DEBUG("Failed, this is a forward electron! The AsgElectronSelectorTool is only suitable for central electrons!");
387 return acceptData;
388 }
389
390 const xAOD::TrackParticle* track = eg->trackParticle();
391 if (!track){
392 ATH_MSG_DEBUG("exiting because track is NULL " << track);
393 return acceptData;
394 }
395
396 // transverse energy of the electron (using the track eta)
397 double et = (std::cosh(track->eta()) != 0.) ? energy / std::cosh(track->eta()) : 0.;
398
399 // number of track hits
400 uint8_t nSiHitsPlusDeadSensors(0);
401 uint8_t nPixHitsPlusDeadSensors(0);
402 bool passBLayerRequirement(false);
403 uint8_t ambiguityBit(0);
404
405 bool allFound = true;
406 std::string notFoundList = "";
407
408 // get the ambiguity type from the decoration
409 if (!m_skipAmbiguityCut){
410 static const SG::Accessor<uint8_t> ambiguityTypeAcc("ambiguityType");
411 if (ambiguityTypeAcc.isAvailable(*eg)) {
412 ambiguityBit = ambiguityTypeAcc(*eg);
413 }
414 else {
415 allFound = false;
416 notFoundList += "ambiguityType ";
417 }
418 }
419
420 nSiHitsPlusDeadSensors = ElectronSelectorHelpers::numberOfSiliconHitsAndDeadSensors(*track);
421 nPixHitsPlusDeadSensors = ElectronSelectorHelpers::numberOfPixelHitsAndDeadSensors(*track);
422 passBLayerRequirement = ElectronSelectorHelpers::passBLayerRequirement(*track);
423
424 // calculate the output of the selector tool
425 SelectorOutputs mvaOutputs = runSelections(ctx, eg, mu);
426
427 if (!allFound){
428 throw std::runtime_error("AsgElectronSelectorTool: Not all variables needed for the decision are found. The following variables are missing: " + notFoundList );
429 }
430
431 // Set up the individual cuts
432 bool passKine(true);
433 bool passNSilicon(true);
434 bool passNPixel(true);
435 bool passNBlayer(true);
436 bool passAmbiguity(true);
437 bool passMVA(true);
438
439
440 if (std::abs(eta) > 2.47){
441 ATH_MSG_DEBUG("This electron is fabs(eta)>2.47 Returning False.");
442 passKine = false;
443 }
444
445 unsigned int etBin = getDiscEtBin(et);
446 unsigned int etaBin = getDiscEtaBin(eta);
447
448 // sanity
449 if (etBin >= s_fnDiscEtBins){
450 ATH_MSG_DEBUG("Cannot evaluate model for Et " << et << ". Returning false..");
451 passKine = false;
452 }
453
454 // Return if the kinematic requirements are not fulfilled
455 acceptData.setCutResult(m_cutPosition_kinematic, passKine);
456 if (!passKine){return acceptData;}
457
458for (size_t idx = 0; idx < m_layers.size(); ++idx) {
459 const auto& layer = m_layers[idx];
460 const auto& scores = mvaOutputs.layerOutputs[idx];
461
462 // ambiguity bit
463 if (!layer.m_cutAmbiguity.empty()){
464 if (!ElectronSelectorHelpers::passAmbiguity((xAOD::AmbiguityTool::AmbiguityType)ambiguityBit, layer.m_cutAmbiguity[etaBin])){
465 ATH_MSG_DEBUG("MVA macro: ambiguity Bit cut failed.");
466 passAmbiguity = false;
467 }
468 }
469
470 // blayer cut
471 if (!layer.m_cutBL.empty()) {
472 if(layer.m_cutBL[etaBin] == 1 && !passBLayerRequirement){
473 ATH_MSG_DEBUG("MVA macro: Blayer cut failed.");
474 passNBlayer = false;
475 }
476 }
477 // pixel cut
478 if (!layer.m_cutPi.empty()){
479 if (nPixHitsPlusDeadSensors < layer.m_cutPi[etaBin]){
480 ATH_MSG_DEBUG("MVA macro: Pixels Failed.");
481 passNPixel = false;
482 }
483 }
484 // SCT cut
485 if (!layer.m_cutSCT.empty()){
486 if (nSiHitsPlusDeadSensors < layer.m_cutSCT[etaBin]){
487 ATH_MSG_DEBUG( "MVA macro: Silicon Failed.");
488 passNSilicon = false;
489 }
490 }
491 unsigned int ibin_combinedMVA = etBin*s_fnDiscEtaBins+etaBin; // Must change if number of eta bins changes!.
492
493 // First cut on the CF discriminant
494 // If empty, continue only with prompt ID
495 if (!layer.m_cutSelectorCF.empty()){
496 double cutDiscriminantCF;
497 // To protect against a binning mismatch, which should never happen
498 if (ibin_combinedMVA >= layer.m_cutSelectorCF.size()){
499 throw std::runtime_error("AsgElectronSelectorTool: The desired eta/pt bin is outside of the range specified by the input. This should never happen! This indicates a mismatch between the binning in the configuration file and the tool implementation." );
500 }
502 cutDiscriminantCF = interpolateCuts(layer.m_cutSelectorCF, et, eta);
503 }
504 else{
505 cutDiscriminantCF = layer.m_cutSelectorCF.at(ibin_combinedMVA);
506 }
507 // Determine if the calculated mva score value passes the combined cut
508 ATH_MSG_DEBUG("MVA macro: CF Discriminant: ");
509 double mvaScoreCF = combineOutputsCF(scores);
510 if (mvaScoreCF < cutDiscriminantCF){
511 ATH_MSG_DEBUG("MVA macro: CF cut failed.");
512 passMVA = false;
513 }
514 }
515 // (Second) cut on prompt discriminant
516 // Cut on Score MVA First Selection
517 if (!layer.m_cutSelector.empty()) {
518 double cutDiscriminant;
519 // To protect against a binning mismatch, which should never happen
520 if (ibin_combinedMVA >= layer.m_cutSelector.size()){
521 throw std::runtime_error("AsgElectronSelectorTool: The desired eta/pt bin is outside of the range specified by the input. This should never happen! This indicates a mismatch between the binning in the configuration file and the tool implementation." );
522 }
524 cutDiscriminant = interpolateCuts(layer.m_cutSelector, et, eta);
525 }
526 else{
527 cutDiscriminant = layer.m_cutSelector.at(ibin_combinedMVA);
528 }
529
530 // Determine if the calculated mva score value passes the combined cut
531 ATH_MSG_DEBUG("MVA macro: Prompt Discriminant: ");
532 double disc = layer.m_multiClass
533 ? combineOutputs(scores, eta, layer.m_fractions, layer.m_cfSignal)
534 : transformMLOutput(scores.at(0));
535
536 if (disc < cutDiscriminant) {
537 ATH_MSG_DEBUG("MVA macro: Prompt cut failed in layer " << layer.name);
538 passMVA = false;
539 }
540 }
541 if (!passMVA || !passNSilicon || !passNPixel || !passNBlayer || !passAmbiguity) {
542 break;
543 }
544}
545 // Set the individual cut bits in the return object
546 acceptData.setCutResult(m_cutPosition_NSilicon, passNSilicon);
547 acceptData.setCutResult(m_cutPosition_NPixel, passNPixel);
548 acceptData.setCutResult(m_cutPosition_NBlayer, passNBlayer);
549 acceptData.setCutResult(m_cutPosition_ambiguity, passAmbiguity);
550 acceptData.setCutResult(m_cutPosition_MVA, passMVA);
551
552 return acceptData;
553
554}
555
556//=============================================================================
557// The main result method: the actual mvaScore is calculated here
558//=============================================================================
559double AsgElectronSelectorTool::calculate( const EventContext& ctx, const xAOD::Electron* eg, double mu ) const
560{
561 // Get all outputs of the mva tool
562 SelectorOutputs mvaOutputs = runSelections(ctx, eg, mu);
563 if (mvaOutputs.layerOutputs.empty()) return -999.0;
564
565 auto discScores = getDiscriminant(mvaOutputs, eg);
566 return discScores.empty() ? -999.0 : discScores.back(); //Returns final layer score
567}
568
569std::vector<double> AsgElectronSelectorTool::getDiscriminant(const SelectorOutputs& mvaOutputs, const xAOD::Electron* eg ) const
570{
571 std::vector<double> discriminants;
572 const xAOD::CaloCluster* cluster = eg->caloCluster();
573 const float eta = cluster->etaBE(2);
574 // If a binary model is used, vector will have one entry
575
576 for (size_t i = 0; i < mvaOutputs.layerOutputs.size(); ++i) {
577 const auto& scores = mvaOutputs.layerOutputs[i];
578 if (scores.empty()) continue;
579
580 const auto& layer = m_layers[i];
581 double disc = layer.m_multiClass
582 ? combineOutputs(scores, eta, layer.m_fractions, layer.m_cfSignal)
583 : transformMLOutput(scores.at(0));
584
585 discriminants.push_back(disc);
586 }
587
588 return discriminants;
589}
590
591std::vector<float> AsgElectronSelectorTool::calculateMultipleOutputs(const EventContext &ctx, const xAOD::Electron *eg, double mu) const
592{
593 SelectorOutputs mvaOutputs = runSelections(ctx, eg, mu);
594
595 if (!mvaOutputs.layerOutputs.empty()) {
596 return mvaOutputs.layerOutputs.back();
597 }
598 return {};
599}
601{
602
603 SelectorOutputs mvaOutputs;
604 ATH_MSG_VERBOSE("\t AsgElectronSelectorTool::calculateMultipleOutputs( &ctx, *eg, mu= "<<(&ctx)<<", "<<eg<<", "<<mu<<" )");
605 if (!eg){
606 throw std::runtime_error("AsgElectronSelectorTool: Failed, no electron object was passed" );
607 }
608
609 const xAOD::CaloCluster* cluster = eg->caloCluster();
610 if (!cluster){
611 ATH_MSG_DEBUG("Failed, no cluster.");
612 // Return a default value
613 for (const auto& l : m_layers) mvaOutputs.layerOutputs.push_back(l.m_defaultOutputs);
614 return mvaOutputs;
615 }
616
617 if (!cluster->hasSampling(CaloSampling::CaloSample::EMB2) && !cluster->hasSampling(CaloSampling::CaloSample::EME2)){
618 ATH_MSG_DEBUG("Failed, cluster is missing samplings EMB2 and EME2.");
619 // Return a default value
620 for (const auto& l : m_layers) mvaOutputs.layerOutputs.push_back(l.m_defaultOutputs);
621 return mvaOutputs;
622 }
623
624 const double energy = cluster->e();
625 const float eta = cluster->etaBE(2);
626
627 if (isForwardElectron(eg, eta)){
628 ATH_MSG_DEBUG("Failed, this is a forward electron! The AsgElectronSelectorTool is only suitable for central electrons!");
629 // Return a default value
630 for (const auto& l : m_layers) mvaOutputs.layerOutputs.push_back(l.m_defaultOutputs);
631 return mvaOutputs;
632 }
633
634 const xAOD::TrackParticle* track = eg->trackParticle();
635 if (!track){
636 ATH_MSG_DEBUG("Failed, no track.");
637 // Return a default value
638 for (const auto& l : m_layers) mvaOutputs.layerOutputs.push_back(l.m_defaultOutputs);
639 return mvaOutputs;
640 }
641
642 // transverse energy of the electron (using the track eta)
643 const double et = energy / std::cosh(track->eta());
644
645 // Variables used in the ML model
646 // track quantities
647 double SCTWeightedCharge(0.0);
648 uint8_t nSCTHitsPlusDeadSensors(0);
649 uint8_t nPixHitsPlusDeadSensors(0);
650 float d0(0.0), d0sigma(0.0), d0significance(0.0), qd0(0.0);
651 float trackqoverp(0.0);
652 double dPOverP(0.0);
653 float TRT_PID(0.0);
654 double trans_TRTPID(0.0);
655
656 // Track Cluster matching
657 float deltaEta1(0), deltaPhiRescaled2(0), EoverP(0);
658
659 // Calorimeter
660 float Reta(0), Rphi(0), Rhad1(0), Rhad(0), w2(0), f1(0), Eratio(0), f3(0), wtots1(0);
661
662 bool allFound = true;
663 std::string notFoundList = "";
664
665 // retrieve track variables
666 trackqoverp = track->qOverP();
667 d0 = track->d0();
668 qd0 = (eg->charge())*track->d0();
669 float vard0 = track->definingParametersCovMatrix()(0, 0);
670 if (vard0 > 0){
671 d0sigma = std::sqrt(vard0);
672 }
673 d0significance = (d0sigma == 0.) ? -99999. : std::abs(d0 / d0sigma);
674
675 const static SG::Accessor<float> trans_TRT_PID_acc("transformed_e_probability_ht");
676 if (!trans_TRT_PID_acc.isAvailable(*eg)) {
677 // most probable case, need to compute the variable
678
679 if (!track->summaryValue(TRT_PID, xAOD::eProbabilityHT)) {
680 allFound = false;
681 notFoundList += "eProbabilityHT ";
682 }
683
684 // Transform the TRT PID output for use in the LH tool.
685 const double tau = 15.0;
686 const double fEpsilon = 1.0e-30; // to avoid zero division
687 double pid_tmp = TRT_PID;
688 if (pid_tmp >= 1.0)
689 pid_tmp = 1.0 - 1.0e-15; // this number comes from TMVA
690 else if (pid_tmp <= fEpsilon)
691 pid_tmp = fEpsilon;
692 trans_TRTPID = -std::log(1.0 / pid_tmp - 1.0) * (1. / tau);
693 }
694 else
695 {
696 // it means the variable have been already computed by another tool
697 // usually this is the EGammaVariableCorrection, which means that
698 // it is also fudged (only MC)
699 trans_TRTPID = trans_TRT_PID_acc(*eg);
700 }
701
702 //Change default value of TRT PID to 0.15 instead of 0 when there is no information from the TRT
703 if ((std::abs(trans_TRTPID) < 1.0e-6) && (std::abs(eta) > 2.01)){
704 trans_TRTPID = 0.15;
705 }
706
707 unsigned int index;
708 if (track->indexOfParameterAtPosition(index, xAOD::LastMeasurement)){
709 double refittedTrack_LMqoverp = track->charge() / std::sqrt(std::pow(track->parameterPX(index), 2) +
710 std::pow(track->parameterPY(index), 2) +
711 std::pow(track->parameterPZ(index), 2));
712
713 dPOverP = 1 - trackqoverp / (refittedTrack_LMqoverp);
714 }
715 else if (!m_skipDeltaPoverP) {
716 allFound = false;
717 notFoundList += "deltaPoverP ";
718 }
719
720 EoverP = energy * std::abs(trackqoverp);
721
722 nPixHitsPlusDeadSensors = ElectronSelectorHelpers::numberOfPixelHitsAndDeadSensors(*track);
723 nSCTHitsPlusDeadSensors = ElectronSelectorHelpers::numberOfSCTHitsAndDeadSensors(*track);
724
725 float charge = 0;
726 uint8_t SCT = 0;
727 for (unsigned TPit = 0; TPit < eg->nTrackParticles(); TPit++) {
728 uint8_t temp_NSCTHits = 0;
729 if (eg->trackParticle(TPit)) {
730 eg->trackParticle(TPit)->summaryValue(temp_NSCTHits, xAOD::numberOfSCTHits);
731 SCT += temp_NSCTHits;
732 charge += temp_NSCTHits*(eg->trackParticle(TPit)->charge());
733 }
734 }
735 if (SCT)
736 SCTWeightedCharge = (eg->charge()*charge/SCT);
737 else {
738 ATH_MSG_WARNING("No SCT hit for any track associated to electron ! nTP = " << eg->nTrackParticles());
739 }
740
741 // retrieve Calorimeter variables
742 // reta = e237/e277
744 allFound = false;
745 notFoundList += "Reta ";
746 }
747 // rphi e233/e237
749 allFound = false;
750 notFoundList += "Rphi ";
751 }
752 // rhad1 = ethad1/et
754 allFound = false;
755 notFoundList += "Rhad1 ";
756 }
757 // rhad = ethad/et
759 allFound = false;
760 notFoundList += "Rhad ";
761 }
762 // shower width in 2nd sampling
764 allFound = false;
765 notFoundList += "weta2 ";
766 }
767 // fraction of energy reconstructed in the 1st sampling
769 allFound = false;
770 notFoundList += "f1 ";
771 }
772 // E of 2nd max between max and min in strips
774 allFound = false;
775 notFoundList += "Eratio ";
776 }
777 // fraction of energy reconstructed in the 3rd sampling
779 allFound = false;
780 notFoundList += "f3 ";
781 }
782
783 // Set f3 to default value in eta region where it is poorly modelled
784 if (std::abs(eta) > 2.01) {
785 f3 = 0.05;
786 }
787
788 // Shower width in first sampling of the calorimeter
790 allFound = false;
791 notFoundList += "wtots1 ";
792 }
793
794 // retrieve Track Cluster matching variables
795 // difference between cluster eta (sampling 1) and the eta of the track
797 allFound = false;
798 notFoundList += "deltaEta1 ";
799 }
800 // difference between the cluster phi (sampling 2) and the phi of the track extrapolated from the last measurement point.
802 allFound = false;
803 notFoundList += "deltaPhiRescaled2 ";
804 }
805
806
807 ATH_MSG_VERBOSE(Form("Vars: eta=%8.5f, et=%8.5f, f3=%8.5f, rHad==%8.5f, rHad1=%8.5f, Reta=%8.5f, w2=%8.5f, f1=%8.5f, Emaxs1=%8.5f, deltaEta1=%8.5f, d0=%8.5f, qd0=%8.5f, d0significance=%8.5f, Rphi=%8.5f, dPOverP=%8.5f, deltaPhiRescaled2=%8.5f, TRT_PID=%8.5f, trans_TRTPID=%8.5f, mu=%8.5f, wtots1=%8.5f, EoverP=%8.5f, nPixHitsPlusDeadSensors=%2df, nSCTHitsPlusDeadSensors=%2df, SCTWeightedCharge=%8.5f",
808 eta, et, f3, Rhad, Rhad1, Reta,
809 w2, f1, Eratio,
810 deltaEta1, d0, qd0,
811 d0significance,
812 Rphi, dPOverP, deltaPhiRescaled2,
813 TRT_PID, trans_TRTPID,
814 mu,
815 wtots1, EoverP, int(nPixHitsPlusDeadSensors), int(nSCTHitsPlusDeadSensors), SCTWeightedCharge));
816
817 if (!allFound){
818 throw std::runtime_error("AsgElectronSelectorTool: Not all variables needed for MVA calculation are found. The following variables are missing: " + notFoundList );
819 }
820
821
822 mvaOutputs.layerOutputs.reserve(m_layers.size());
823 for (const auto& layer : m_layers) {
824 std::vector<double> variableValues;
825 variableValues.reserve(layer.m_enum_variables.size());
826 for (const auto varID : layer.m_enum_variables) {
827
828 switch(varID)
829 {
831 variableValues.push_back(std::abs(eta)); break; // TODO - rename to abseta?
833 variableValues.push_back(et); break;
835 variableValues.push_back(f3); break;
837 variableValues.push_back(Rhad); break;
839 variableValues.push_back(Rhad1); break;
841 variableValues.push_back(Reta); break;
843 variableValues.push_back(w2); break;
845 variableValues.push_back(f1); break;
847 variableValues.push_back(Eratio); break;
849 variableValues.push_back(deltaEta1); break;
851 variableValues.push_back(d0); break;
853 variableValues.push_back(qd0); break;
855 variableValues.push_back(d0significance); break;
857 variableValues.push_back(Rphi); break;
859 variableValues.push_back(dPOverP); break;
861 variableValues.push_back(deltaPhiRescaled2); break;
863 variableValues.push_back(trans_TRTPID); break;
865 variableValues.push_back(wtots1); break;
867 variableValues.push_back(EoverP); break;
869 variableValues.push_back(nPixHitsPlusDeadSensors); break;
871 variableValues.push_back(nSCTHitsPlusDeadSensors); break;
873 variableValues.push_back(SCTWeightedCharge); break;
874 default:
875 // Handle unknown varID or error case
876 throw std::runtime_error("AsgElectronSelectorTool: unknown variable "
877 "index, something went wrong in initialization!" );
878 break;
879
880 }
881 }
882
883 mvaOutputs.layerOutputs.push_back(layer.evaluate(variableValues));
884 }
885
886return mvaOutputs;
887}
888
889//=============================================================================
891//=============================================================================
893{
894 return m_workingPoint;
895}
896
897//=============================================================================
899{
900 return accept(Gaudi::Hive::currentContext(), part);
901}
902asg::AcceptData AsgElectronSelectorTool::accept( const EventContext& ctx, const xAOD::IParticle* part ) const
903{
904 ATH_MSG_VERBOSE("\t AsgElectronSelectorTool::accept( &ctx, *part= "<<(&ctx)<<", "<<part<<" )");
905 const xAOD::Electron* eg = dynamic_cast<const xAOD::Electron*>(part);
906 if (eg){
907 return accept(ctx, eg);
908 }
909 else {
910 ATH_MSG_DEBUG("AsgElectronSelectorTool::could not cast to const Electron");
911 // Setup return accept with AcceptInfo
912 asg::AcceptData acceptData(&m_acceptMVA);
913 return acceptData;
914 }
915}
916
917double AsgElectronSelectorTool::calculate( const EventContext& ctx, const xAOD::IParticle* part ) const
918{
919 ATH_MSG_VERBOSE("\t AsgElectronSelectorTool::calculate( &ctx, *part"<<(&ctx)<<", "<<part<<" )");
920 const xAOD::Electron* eg = dynamic_cast<const xAOD::Electron*>(part);
921 if (eg){
922 return calculate(ctx, eg);
923 }
924 else {
925 ATH_MSG_DEBUG("AsgElectronSelectorTool::could not cast to const Electron");
926 // Return a default value
927 return -999.;
928 }
929}
930
931asg::AcceptData AsgElectronSelectorTool::accept( const EventContext& ctx, const xAOD::Egamma* eg, double mu ) const
932{
933 ATH_MSG_VERBOSE("\t AsgElectronSelectorTool::accept( &ctx, *eg, mu= "<<(&ctx)<<", "<<eg<<", "<<mu<<" )");
934 const xAOD::Electron* ele = dynamic_cast<const xAOD::Electron*>(eg);
935 if (ele){
936 return accept(ctx, ele, mu);
937 }
938 else {
939 ATH_MSG_DEBUG("AsgElectronSelectorTool::could not cast to const Electron");
940 // Setup return accept with AcceptInfo
941 asg::AcceptData acceptData(&m_acceptMVA);
942 return acceptData;
943 }
944}
945
946double AsgElectronSelectorTool::calculate( const EventContext& ctx, const xAOD::Egamma* eg, double mu ) const
947{
948 ATH_MSG_VERBOSE("\t AsgElectronSelectorTool::calculate( &ctx, *eg, mu= "<<(&ctx)<<", "<<eg<<", "<<mu<<" )");
949 const xAOD::Electron* ele = dynamic_cast<const xAOD::Electron*>(eg);
950 if (ele){
951 return calculate(ctx, ele, mu);
952 }
953 else {
954 ATH_MSG_DEBUG("AsgElectronSelectorTool::could not cast to const Electron");
955 return -999.;
956 }
957}
958
960{
961 static const SG::ConstAccessor< uint16_t > accAuthor( "author" );
962
963 if (accAuthor.isAvailable(*eg)){
964 // cannot just do eg->author() because it isn't always filled
965 // at trigger level
966 if (accAuthor(*eg) == xAOD::EgammaParameters::AuthorFwdElectron){
967 ATH_MSG_DEBUG("Failed, this is a forward electron! The AsgElectronSelectorTool is only suitable for central electrons!");
968 return true;
969 }
970 }
971 else{
972 //Check for fwd via eta range the old logic
973 if (std::abs(eta) > 2.5){
974 ATH_MSG_DEBUG("Failed, cluster->etaBE(2) range due to " << eta << " seems like a fwd electron" );
975 return true;
976 }
977 }
978
979 return false;
980}
981
982
984{
985 // returns transformed or non-transformed output
986 constexpr double oneOverTau = 1 ;
987 constexpr double fEpsilon = 1.0e-30; // to avoid zero division
988 if (score >= 1.0) score = 1.0 - 1.0e-15; // this number comes from TMVA
989 else if (score <= fEpsilon) score = fEpsilon;
990 //cppcheck-suppress invalidFunctionArg
991 score = -std::log(1.0 / score - 1.0) * oneOverTau;
992 ATH_MSG_DEBUG("score is " << score);
993 return score;
994}
995
996
997double AsgElectronSelectorTool::combineOutputs( const std::vector<float>& mvaScores, double eta, const std::vector<double>& fractions, bool cfSignal ) const
998{
999 unsigned int etaBin = getDiscEtaBin(eta);
1000 double disc = 0;
1001 size_t nClasses = mvaScores.size();
1002 size_t nFractionsPerBin = nClasses - 1;
1003
1004 if (cfSignal && nClasses >= 3) {
1005
1006 double numerator = mvaScores.at(0) * (1.0 - fractions.at(nFractionsPerBin * etaBin + 0)) +
1007 mvaScores.at(1) * fractions.at(nFractionsPerBin * etaBin + 0);
1008
1009 double denominator = 0.0;
1010 for (size_t i = 2; i < nClasses; ++i) {
1011 denominator += mvaScores.at(i) * fractions.at(nFractionsPerBin * etaBin + i - 1);
1012 }
1013 if (denominator != 0.0) {
1014 disc = numerator / denominator;
1015 }
1016 }
1017 else {
1018
1019 double numerator = mvaScores.at(0);
1020 double denominator = 0.0;
1021
1022 for (size_t i = 1; i < nClasses; ++i) {
1023 denominator += mvaScores.at(i) * fractions.at(nFractionsPerBin * etaBin + i - 1);
1024 }
1025 if (denominator != 0.0) {
1026 disc = numerator / denominator;
1027 }
1028 }
1029 // Log transform to have values in reasonable range
1030 return std::log(disc);
1031}
1032
1033double AsgElectronSelectorTool::combineOutputsCF( const std::vector<float>& mvaScores)
1034{
1035 double disc = 0;
1036 disc = mvaScores.at(0) / mvaScores.at(1);
1037
1038 return std::log(disc);
1039}
1040
1041
1042// Gets the Discriminant Eta bin [0,s_fnDiscEtaBins-1] given the eta
1044{
1045 const unsigned int nEtaBins = s_fnDiscEtaBins;
1046 const double etaBins[nEtaBins] = {0.1, 0.6, 0.8, 1.15, 1.37, 1.52, 1.81, 2.01, 2.37, 2.47};
1047 for (unsigned int etaBin = 0; etaBin < nEtaBins; ++etaBin){
1048 if (std::abs(eta) < etaBins[etaBin]) return etaBin;
1049 }
1050 return (nEtaBins-1);
1051}
1052
1053// Gets the Discriminant Et bin (MeV) [0,s_fnDiscEtBins-1]
1055{
1056 static const double GeV = 1000;
1057 const unsigned int nEtBins = s_fnDiscEtBins;
1058 const double etBins[nEtBins] = {7*GeV,10*GeV,15*GeV,20*GeV,25*GeV,30*GeV,35*GeV,40*GeV,45*GeV,6000*GeV};
1059 for (unsigned int etBin = 0; etBin < nEtBins; ++etBin){
1060 if (et < etBins[etBin]) return etBin;
1061 }
1062 return (nEtBins-1);
1063}
1064
1065
1066// Note that this will only perform the cut interpolation up to ~45 GeV, so
1067// no smoothing is done above this for the high ET LH binning yet
1068double AsgElectronSelectorTool::interpolateCuts( const std::vector<double>& cuts,double et,double eta )
1069{
1070 const int etbin = getDiscEtBin(et);
1071 const int etabin = getDiscEtaBin(eta);
1072 unsigned int ibin_combinedML = etbin*s_fnDiscEtaBins+etabin;
1073 double cut = cuts.at(ibin_combinedML);
1074 const double GeV = 1000;
1075 const double eTBins[10] = {5.5*GeV,8.5*GeV,12.5*GeV,17.5*GeV,22.5*GeV,27.5*GeV,32.5*GeV,37.5*GeV,42.5*GeV,47.5*GeV};
1076
1077 if (et >= eTBins[9]) return cut; // no interpolation for electrons above 47.5 GeV
1078 if (et <= eTBins[0]) return cut; // no interpolation for electrons below 5.5 GeV
1079
1080 // find the bin where the value is smaller than the next bin
1081 // Start with bin = 1, since it always has to be at least in
1082 // bin 1 because of previous cut
1083 int bin = 1;
1084 while ( et > eTBins[bin] ) bin++;
1085
1086 double etLow = eTBins[bin-1];
1087 double etUp = eTBins[bin];
1088 double discLow = cuts.at((bin-1) * s_fnDiscEtaBins+etabin);
1089 double discUp = cuts.at((bin) * s_fnDiscEtaBins+etabin);
1090
1091 double gradient = ( discUp - discLow ) / ( etUp - etLow );
1092
1093 return discLow + (et - etLow) * gradient;
1094}
Scalar eta() const
pseudorapidity method
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
double charge(const T &p)
Definition AtlasPID.h:999
std::vector< std::vector< float > > scores
std::pair< std::vector< unsigned int >, bool > res
static Double_t sc
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
virtual std::string getOperatingPointName() const override
Get the name of the current operating point.
static const unsigned int s_fnDiscEtBins
virtual const asg::AcceptInfo & getAcceptInfo() const override
Method to get the plain AcceptInfo.
std::string m_workingPoint
Working Point.
static unsigned int getDiscEtaBin(double eta)
Gets the Discriminant Eta bin [0,s_fnDiscEtaBins-1] given the eta.
int m_cutPosition_kinematic
The position of the kinematic cut bit in the AcceptInfo return object.
static unsigned int getDiscEtBin(double et)
Gets the Descriminant Et bin the et (MeV) [0,s_fnDiscEtBins-1].
virtual StatusCode initialize() override
Gaudi Service Interface method implementations.
std::string m_modelFileName
The input file name that holds the model.
bool m_skipDeltaPoverP
Flag for skip the use of deltaPoverP in dnn calculation (like at HLT).
SelectorOutputs runSelections(const EventContext &ctx, const xAOD::Electron *eg, double mu) const
The result method for multiple outputs: can return multiple outputs of the MVA.
virtual ~AsgElectronSelectorTool()
Standard destructor.
static double interpolateCuts(const std::vector< double > &cuts, double et, double eta)
Interpolates cut values along pt.
static const unsigned int s_fnDiscEtaBins
asg::AcceptInfo m_acceptMVA
Accept info.
virtual std::vector< float > calculateMultipleOutputs(const EventContext &ctx, const xAOD::Electron *eg, double mu=-99) const override
calculate all outputs of the underlying method (MVA) if it produces multiple outputs
int m_cutPosition_NPixel
The position of the NPixel cut bit in the AcceptInfo return object.
int m_cutPosition_NSilicon
The position of the NSilicon cut bit in the AcceptInfo return object.
std::string m_quantileFileName
The input file name that holds the QuantileTransformer.
bool isForwardElectron(const xAOD::Egamma *eg, const float eta) const
check for FwdElectron
AsgElectronSelectorTool(const std::string &myname)
Standard constructor.
int m_cutPosition_NBlayer
The position of the NBlayer cut bit in the AcceptInfo return object.
int m_cutPosition_MVA
The position of the MVA cut bit in the AcceptInfo return object.
double transformMLOutput(float score) const
Applies a logit transformation to the score returned by the underlying MVA tool.
double combineOutputs(const std::vector< float > &mvaScores, double eta, const std::vector< double > &fractions, bool cfSignal=false) const
Combines the six output nodes of a multiclass model into one discriminant.
double calculate(const xAOD::IParticle *part) const
The main result method: the actual mva score is calculated here.
asg::AcceptData accept(const xAOD::IParticle *part) const override
The main accept method: using the generic interface.
std::vector< double > getDiscriminant(const SelectorOutputs &mvaOutputs, const xAOD::Electron *egu) const
Computes discrimiant value from mva output based on whether multiclass is true or false.
static double combineOutputsCF(const std::vector< float > &mvaScores)
int m_cutPosition_ambiguity
The position of the ambiguity cut bit in the AcceptInfo return object.
std::string m_configFile
The input config file.
std::vector< SelectionLayer > m_layers
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
MsgStream & msg() const
Helper class to provide type-safe access to aux data.
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
void setCutResult(const std::string &cutName, bool cutResult)
Set the result of a cut, based on the cut name (safer).
Definition AcceptData.h:135
Base class for the dual-use tool implementation classes.
Definition AsgTool.h:47
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
virtual double e() const
The total energy of the particle.
bool hasSampling(const CaloSample s) const
Checks if certain smapling contributes to cluster.
float etaBE(const unsigned layer) const
Get the eta in one layer of the EM Calo.
bool showerShapeValue(float &value, const EgammaParameters::ShowerShapeType information) const
Accessor for ShowerShape values.
const xAOD::CaloCluster * caloCluster(size_t index=0) const
Pointer to the xAOD::CaloCluster/s that define the electron candidate.
bool trackCaloMatchValue(float &value, const EgammaParameters::TrackCaloMatchType information) const
Accessor for Track to Calo Match Values.
float charge() const
Obtain the charge of the object.
const xAOD::TrackParticle * trackParticle(size_t index=0) const
Pointer to the xAOD::TrackParticle/s that match the electron candidate.
size_t nTrackParticles() const
Return the number xAOD::TrackParticles that match the electron candidate.
Class providing the definition of the 4-vector interface.
bool summaryValue(uint8_t &value, const SummaryType &information) const
Accessor for TrackSummary values.
bool contains(const std::string &s, const std::string &regx)
does a string contain the substring
Definition hcg.cxx:116
const std::unordered_map< std::string, int > variableMap
std::vector< int > HelperInt(const std::string &input, TEnv &env)
std::vector< double > HelperDouble(const std::string &input, TEnv &env)
std::string findConfigFile(const std::string &input, const std::map< std::string, std::string > &configmap)
const std::map< std::string, std::string > ElectronDNNPointToConfFile
bool passAmbiguity(xAOD::AmbiguityTool::AmbiguityType type, const uint16_t criterion)
return true if the ambiguity type is one of several that are stored in a bitmask
std::size_t numberOfPixelHitsAndDeadSensors(const xAOD::TrackParticle &tp)
return the number of Pixel hits plus dead sensors in the track particle
std::size_t numberOfSCTHitsAndDeadSensors(const xAOD::TrackParticle &tp)
return the number of SCT hits plus dead sensors in the track particle
bool passBLayerRequirement(const xAOD::TrackParticle &tp)
return true if effective number of BL hits + outliers is at least one
std::size_t numberOfSiliconHitsAndDeadSensors(const xAOD::TrackParticle &tp)
return the number of Silicon hits plus dead sensors in the track particle
Definition index.py:1
@ deltaPhiRescaled2
difference between the cluster phi (second sampling) and the phi of the track extrapolated to the sec...
@ deltaEta1
difference between the cluster eta (first sampling) and the eta of the track extrapolated to the firs...
const uint16_t AuthorFwdElectron
Electron reconstructed by the Forward cluster-based algorithm.
Definition EgammaDefs.h:30
@ wtots1
shower width is determined in a window detaxdphi = 0,0625 ×~0,2, corresponding typically to 20 strips...
@ f3
fraction of energy reconstructed in 3rd sampling
Definition EgammaEnums.h:55
@ f1
E1/E = fraction of energy reconstructed in the first sampling, where E1 is energy in all strips belon...
Definition EgammaEnums.h:53
@ Eratio
(emaxs1-e2tsts1)/(emaxs1+e2tsts1)
@ weta2
the lateral width is calculated with a window of 3x5 cells using the energy weighted sum over all cel...
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Egamma_v1 Egamma
Definition of the current "egamma version".
Definition Egamma.h:17
@ eProbabilityHT
Electron probability from High Threshold (HT) information [float].
@ numberOfSCTHits
number of hits in SCT [unit8_t].
Electron_v1 Electron
Definition of the current "egamma version".
Definition Electron.h:17
@ LastMeasurement
Parameter defined at the position of the last measurement.
std::vector< int > m_cutSCT
cut min on precision hits
std::vector< int > m_enum_variables
Enum version of used variables.
std::vector< double > m_cutSelector
cut on mva output
std::vector< int > m_cutPi
cut min on pixel hits
bool initialize(TEnv &env, const std::string &prefixName, const std::string &layerName, const std::string &m_modelFileName, const std::string &m_quantileFileName, asg::AsgTool *parentTool)
bool m_cfSignal
Use the CF output node in the numerator or the denominator.
std::vector< float > evaluate(const std::vector< double > &inputs) const
std::unique_ptr< const ElectronDNNCalculator > m_mvaTool
Pointer to the class that calculates the MVA score.
std::vector< float > m_defaultOutputs
Default vector to return if calculation fails.
std::vector< double > m_fractions
Fractions to combine the output nodes of a multiclass model into one discriminant.
std::vector< int > m_cutAmbiguity
do cut on ambiguity bit
std::vector< int > m_cutBL
cut min on b-layer hits
std::vector< std::vector< float > > layerOutputs
Extra patterns decribing particle interation process.