ATLAS Offline Software
Loading...
Searching...
No Matches
AsgPhotonIsEMSelector.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Dear emacs, this is -*-c++-*-
6
14
15// Include this class's header
24#include "TEnv.h"
25#include "TPhotonIsEMSelector.h"
28#include "xAODEgamma/Electron.h"
29#include "xAODEgamma/Photon.h"
30
31//=============================================================================
32// Standard constructor
33//=============================================================================
34AsgPhotonIsEMSelector::AsgPhotonIsEMSelector(const std::string& myname)
35 : AsgTool(myname)
36 , m_configFile("")
37 , m_rootTool(nullptr)
38{
39
40 m_rootTool = new Root::TPhotonIsEMSelector(myname.c_str());
41
42 declareProperty("WorkingPoint", m_WorkingPoint = "", "The Working Point");
43 declareProperty("ConfigFile",
44 m_configFile = "",
45 "The config file to use (if not setting cuts one by one)");
46
47 // Name of the PID
48 declareProperty(
49 "isEMMask",
50 m_rootTool->m_isEMMask =
51 egammaPID::EgPidUndefined, // All pass by default, if not specified
52 "The mask to use");
53
54 // boolean to force to test converted photon hypothesis
55 declareProperty("ForceConvertedPhotonPID",
56 m_rootTool->m_forceConvertedPhotonPID = false,
57 "boolean to force to test converted photon hypothesis");
58
59 // boolean to force to test non converted photon hypothesis
60 declareProperty("ForceNonConvertedPhotonPID",
61 m_rootTool->m_forceNonConvertedPhotonPID = false,
62 "boolean to force to test non converted photon hypothesis");
63
64 // new cuts on f3
65 // Use f3core instead of f3
66 declareProperty("useF3core", m_useF3core = false, "Cut on f3 or f3core?");
67
68 // for the trigger needs:
69 declareProperty("caloOnly",
70 m_caloOnly = false,
71 "Flag to tell the tool if its a calo only cutbase");
72 declareProperty("trigEtTh", m_trigEtTh = -999., "Trigger threshold");
73
74 declareProperty("skipAmbiguityCut",m_skipAmbiguityCut = false,
75 "If true, it will skip the ambiguity cut. This is useful for HLT photon emulation");
76
77 declareProperty("removeTRTConversion", m_removeTRTConversion = true,
78 "boolean to treat barrel standalone TRT conversion as unconverted for Run3 ");
79}
80
81// =================================================================
86
87// =================================================================
88StatusCode
90{
91 if (!m_WorkingPoint.empty()) {
96 }
97
98 std::string filename = PathResolverFindCalibFile(m_configFile);
99 if (filename.empty()) {
100 ATH_MSG_ERROR("Could not locate " << m_configFile);
101 return StatusCode::FAILURE;
102 }
103 TEnv env;
104 env.ReadFile(filename.c_str(), kEnvLocal);
106 // Override the mask via the config only if it is not set
107 if (m_rootTool->m_isEMMask == egammaPID::EgPidUndefined) {
108 unsigned int mask(
109 env.GetValue("isEMMask", static_cast<int>(egammaPID::EgPidUndefined)));
110 m_rootTool->m_isEMMask = mask;
111 }
113 m_rootTool->m_cutBinEta_photonsNonConverted =
114 AsgConfigHelper::HelperFloat("CutBinEta_photonsNonConverted", env);
115 m_rootTool->m_cutBinEnergy_photonsNonConverted =
116 AsgConfigHelper::HelperFloat("CutBinEnergy_photonsNonConverted", env);
117 m_rootTool->m_cutBinMu_photonsNonConverted =
118 AsgConfigHelper::HelperFloat("CutBinMu_photonsNonConverted", env);
119 m_rootTool->m_e277_photonsNonConverted =
120 AsgConfigHelper::HelperFloat("e277_photonsNonConverted", env);
121 m_rootTool->m_cutHadLeakage_photonsNonConverted =
122 AsgConfigHelper::HelperFloat("CutHadLeakage_photonsNonConverted", env);
123 m_rootTool->m_Reta37_photonsNonConverted =
124 AsgConfigHelper::HelperFloat("Reta37_photonsNonConverted", env);
125 m_rootTool->m_Rphi33_photonsNonConverted =
126 AsgConfigHelper::HelperFloat("Rphi33_photonsNonConverted", env);
127 m_rootTool->m_weta2_photonsNonConverted =
128 AsgConfigHelper::HelperFloat("weta2_photonsNonConverted", env);
129 m_rootTool->m_cutBinEtaStrips_photonsNonConverted =
130 AsgConfigHelper::HelperFloat("CutBinEtaStrips_photonsNonConverted", env);
131 m_rootTool->m_cutBinEnergyStrips_photonsNonConverted =
132 AsgConfigHelper::HelperFloat("CutBinEnergyStrips_photonsNonConverted", env);
133 m_rootTool->m_cutBinMuStrips_photonsNonConverted =
134 AsgConfigHelper::HelperFloat("CutBinMuStrips_photonsNonConverted", env);
135 m_rootTool->m_f1_photonsNonConverted =
136 AsgConfigHelper::HelperFloat("f1_photonsNonConverted", env);
137 m_rootTool->m_deltae_photonsNonConverted =
138 AsgConfigHelper::HelperFloat("deltae_photonsNonConverted", env);
139 m_rootTool->m_DEmaxs1_photonsNonConverted =
140 AsgConfigHelper::HelperFloat("DEmaxs1_photonsNonConverted", env);
141 m_rootTool->m_wtot_photonsNonConverted =
142 AsgConfigHelper::HelperFloat("wtot_photonsNonConverted", env);
143 m_rootTool->m_fracm_photonsNonConverted =
144 AsgConfigHelper::HelperFloat("fracm_photonsNonConverted", env);
145 m_rootTool->m_w1_photonsNonConverted =
146 AsgConfigHelper::HelperFloat("w1_photonsNonConverted", env);
147 m_rootTool->m_cutF3_photonsNonConverted =
148 AsgConfigHelper::HelperFloat("CutF3_photonsNonConverted", env);
149 m_rootTool->m_cutBinEta_photonsConverted =
150 AsgConfigHelper::HelperFloat("CutBinEta_photonsConverted", env);
151 m_rootTool->m_cutBinEnergy_photonsConverted =
152 AsgConfigHelper::HelperFloat("CutBinEnergy_photonsConverted", env);
153 m_rootTool->m_cutBinMu_photonsConverted =
154 AsgConfigHelper::HelperFloat("CutBinMu_photonsConverted", env);
155 m_rootTool->m_e277_photonsConverted =
156 AsgConfigHelper::HelperFloat("e277_photonsConverted", env);
157 m_rootTool->m_cutHadLeakage_photonsConverted =
158 AsgConfigHelper::HelperFloat("CutHadLeakage_photonsConverted", env);
159 m_rootTool->m_Reta37_photonsConverted =
160 AsgConfigHelper::HelperFloat("Reta37_photonsConverted", env);
161 m_rootTool->m_Rphi33_photonsConverted =
162 AsgConfigHelper::HelperFloat("Rphi33_photonsConverted", env);
163 m_rootTool->m_weta2_photonsConverted =
164 AsgConfigHelper::HelperFloat("weta2_photonsConverted", env);
165 m_rootTool->m_cutBinEtaStrips_photonsConverted =
166 AsgConfigHelper::HelperFloat("CutBinEtaStrips_photonsConverted", env);
167 m_rootTool->m_cutBinEnergyStrips_photonsConverted =
168 AsgConfigHelper::HelperFloat("CutBinEnergyStrips_photonsConverted", env);
169 m_rootTool->m_cutBinMuStrips_photonsConverted =
170 AsgConfigHelper::HelperFloat("CutBinMuStrips_photonsConverted", env);
171 m_rootTool->m_f1_photonsConverted =
172 AsgConfigHelper::HelperFloat("f1_photonsConverted", env);
173 m_rootTool->m_deltae_photonsConverted =
174 AsgConfigHelper::HelperFloat("deltae_photonsConverted", env);
175 m_rootTool->m_DEmaxs1_photonsConverted =
176 AsgConfigHelper::HelperFloat("DEmaxs1_photonsConverted", env);
177 m_rootTool->m_wtot_photonsConverted =
178 AsgConfigHelper::HelperFloat("wtot_photonsConverted", env);
179 m_rootTool->m_fracm_photonsConverted =
180 AsgConfigHelper::HelperFloat("fracm_photonsConverted", env);
181 m_rootTool->m_w1_photonsConverted =
182 AsgConfigHelper::HelperFloat("w1_photonsConverted", env);
183 m_rootTool->m_cutminEp_photonsConverted =
184 AsgConfigHelper::HelperFloat("CutminEp_photonsConverted", env);
185 m_rootTool->m_cutmaxEp_photonsConverted =
186 AsgConfigHelper::HelperFloat("CutmaxEp_photonsConverted", env);
187 m_rootTool->m_cutF3_photonsConverted =
188 AsgConfigHelper::HelperFloat("CutF3_photonsConverted", env);
189
190 // Get the message level and set the underlying ROOT tool message level
191 // accordingly
192 m_rootTool->msg().setLevel(this->msg().level());
193
194 // We need to initialize the underlying ROOT TSelectorTool
195 if (m_rootTool->initialize().isFailure()) {
196 ATH_MSG_ERROR("Could not initialize the TPhotonIsEMSelector!");
197 return StatusCode::FAILURE;
198 }
199
200 // if we use mu-dependent menu
201 m_isMuDep =
202 !m_rootTool->m_cutBinMu_photonsNonConverted.empty() ||
203 !m_rootTool->m_cutBinMu_photonsConverted.empty() ||
204 !m_rootTool->m_cutBinMuStrips_photonsNonConverted.empty() ||
205 !m_rootTool->m_cutBinMuStrips_photonsConverted.empty();
206 ATH_CHECK(m_EvtInfoKey.initialize());
207 if (m_isMuDep)
208 ATH_MSG_INFO("Running a mu-dependent photon ID menu");
209
210 return StatusCode::SUCCESS;
211}
212
213//=============================================================================
214// return the accept info object
215//=============================================================================
216
217const asg::AcceptInfo&
219{
220 return m_rootTool->getAcceptInfo();
221}
222
223//=============================================================================
224// The main accept method: the actual cuts are applied here
225//=============================================================================
228{
229 return AsgPhotonIsEMSelector::accept(Gaudi::Hive::currentContext(), part);
230}
231
233AsgPhotonIsEMSelector::accept(const EventContext& ctx,
234 const xAOD::IParticle* part) const
235{
236
237 if (part->type() == xAOD::Type::Photon ||
238 part->type() == xAOD::Type::Electron) {
239 return accept(ctx, static_cast<const xAOD::Egamma*>(part));
240 }
241
243 "AsgElectronIsEMSelector::could not convert argument to Photon/Electron");
244 return m_rootTool->accept();
245}
247AsgPhotonIsEMSelector::accept(const EventContext& ctx,
248 const xAOD::Egamma* eg) const
249{
250
251 if (eg) {
252 unsigned int isEM = ~0;
253 StatusCode sc = execute(ctx, eg, isEM);
254 if (sc.isFailure()) {
255 ATH_MSG_ERROR("could not calculate isEM");
256 return m_rootTool->accept();
257 }
258 return m_rootTool->fillAccept(isEM);
259 }
260
261 ATH_MSG_ERROR("AsgElectronIsEMSelector::accept was given a bad argument");
262 return m_rootTool->accept();
263}
265AsgPhotonIsEMSelector::accept(const EventContext& ctx,
266 const xAOD::Photon* ph) const
267{
268 return accept(ctx, static_cast<const xAOD::Egamma*>(ph));
269}
271AsgPhotonIsEMSelector::accept(const EventContext& ctx,
272 const xAOD::Electron* el) const
273{
274 return accept(ctx, static_cast<const xAOD::Egamma*>(el));
275}
276
277//=============================================================================
279//=============================================================================
280std::string
282{
283 //
284 // For Loose, Medium and Tight ignore if the difference is in bit 23
285 if (m_rootTool->m_isEMMask == egammaPID::PhotonLoose ||
286 (egammaPID::PhotonLoose ^ m_rootTool->m_isEMMask) ==
288 return "Loose";
289 }
290 if (m_rootTool->m_isEMMask == egammaPID::PhotonMedium ||
291 (egammaPID::PhotonMedium ^ m_rootTool->m_isEMMask) ==
293 return "Medium";
294 }
295 if (m_rootTool->m_isEMMask == egammaPID::PhotonTight ||
296 (egammaPID::PhotonTight ^ m_rootTool->m_isEMMask) ==
298 return "Tight";
299 }
300 if (m_rootTool->m_isEMMask == egammaPID::PhotonLooseEF) {
301 return "LooseEF";
302 }
303 if (m_rootTool->m_isEMMask == egammaPID::PhotonMediumEF) {
304 return "MediumEF";
305 }
306 if (m_rootTool->m_isEMMask == 0) {
307 return "No cuts applied";
308 }
309
310 ATH_MSG_ERROR("Didn't recognize the given operating point with mask: "
311 << m_rootTool->m_isEMMask);
312 return "";
313}
314
315// A simple execute command wrapper
316// ==============================================================
317StatusCode
318AsgPhotonIsEMSelector::execute(const EventContext& ctx,
319 const xAOD::Egamma* eg,
320 unsigned int& isEM) const
321{
322 //
323 // Particle identification for photons based on cuts
324 // trigEtTh : threshold in ET as applied by trigger
325 //
326 (void)ctx;
327
328 // initialisation
329 isEM = 0;
330
331 // protection against null pointer
332 if (eg == nullptr) {
333 ATH_MSG_ERROR("eg == 0");
334 // if object is bad then use the bit for "bad eta"
335 isEM = (0x1 << egammaPID::ClusterEtaRange_Photon);
336 return StatusCode::SUCCESS;
337 }
338
339 // protection against bad clusters
340 const xAOD::CaloCluster* cluster = eg->caloCluster();
341 if (cluster == nullptr) {
342 ATH_MSG_ERROR("exiting because cluster is NULL " << cluster);
343 // if object is bad then use the bit for "bad eta"
344 isEM = (0x1 << egammaPID::ClusterEtaRange_Photon);
345 return StatusCode::SUCCESS;
346 }
347
348 // Fill variables
349 // eta position in second sampling
350 const float eta2 = fabsf(cluster->etaBE(2));
351 // transverse energy in calorimeter (using eta position in second sampling)
352 const double energy = cluster->e();
353 double et = 0.;
354 if (eta2 < 999.) {
355 const double cosheta = cosh(eta2);
356 et = (cosheta != 0.) ? energy / cosheta : 0.;
357 }
358
359 // variables based on HCAL
360 // transverse energy in 1st scintillator of hadronic calorimeter/ET
361 float Rhad1 = eg->showerShapeValue(xAOD::EgammaParameters::Rhad1);
362 // transverse energy in hadronic calorimeter/ET
363 float Rhad = eg->showerShapeValue(xAOD::EgammaParameters::Rhad);
364
365 // variables based on S2 of EM CAL
366 // E(7*7) in 2nd sampling
367 float e277 = eg->showerShapeValue(xAOD::EgammaParameters::e277);
368 // E(3*7)/E(7*7) in 2nd sampling
369 float Reta = eg->showerShapeValue(xAOD::EgammaParameters::Reta);
370 // E(3*3)/E(3*7) in 2nd sampling
371 float Rphi = eg->showerShapeValue(xAOD::EgammaParameters::Rphi);
372 // shower width in 2nd sampling
373 float weta2c = eg->showerShapeValue(xAOD::EgammaParameters::weta2);
374
375 // variables based on S1 of EM CAL
376 // fraction of energy reconstructed in the 1st sampling
377 float f1 = eg->showerShapeValue(xAOD::EgammaParameters::f1);
378 // shower width in 3 strips in 1st sampling
379 float weta1c = eg->showerShapeValue(xAOD::EgammaParameters::weta1);
380 // (E of 1st max in strips-E of 2nd max)/(E of 1st max+E of 2nd max)
381 float Eratio = eg->showerShapeValue(xAOD::EgammaParameters::Eratio);
382 // E(2nd max)-E(min) in strips
383 float DeltaE = eg->showerShapeValue(xAOD::EgammaParameters::DeltaE);
384 // total shower width in 1st sampling
385 float wtot = eg->showerShapeValue(xAOD::EgammaParameters::wtots1);
386 // E(+/-3)-E(+/-1)/E(+/-1)
387 float fracm = eg->showerShapeValue(xAOD::EgammaParameters::fracs1);
388
389 float f3(0);
390 if (m_useF3core) {
391 f3 = eg->showerShapeValue(xAOD::EgammaParameters::f3core);
392 } else {
393 f3 = eg->showerShapeValue(xAOD::EgammaParameters::f3);
394 }
395
396 // cut on E/p
397 double ep = 1.0; // default passes
398
399 if (m_caloOnly) {
400 ATH_MSG_DEBUG("Doing CaloCutsOnly");
401 } else {
403 eg)) // returns false if not photon or no conversion
404 {
405 const xAOD::Photon* ph = static_cast<const xAOD::Photon*>(eg);
406 float p = xAOD::EgammaHelpers::momentumAtVertex(ph).mag();
407 if (p != 0.) {
408 ep = energy / p;
409 } else {
410 ep = 9999999.;
411 }
412 }
413 }
414
415 // modifiy et when dealing with trigger
416 // to be sure that it will take the correct bin (VD)
417 if (m_trigEtTh > 0)
418 et = m_trigEtTh * 1.01;
419
420 // pileup
421 float mu = m_isMuDep ? this->getMu(ctx) : -999;
422
423 //runnumber
424 int runnumber = this->RunNumber(ctx);
425 bool excludeTRT = false;
426
427 if(runnumber >= 410000 && m_removeTRTConversion) excludeTRT = true; // exclude TRT converted photons only for Run-3
428
429
430 // apply calorimeter selection for photons
431 isEM = m_rootTool->calcIsEm(eta2,
432 et,
433 Rhad1,
434 Rhad,
435 e277,
436 Reta,
437 Rphi,
438 weta2c,
439 f1,
440 Eratio,
441 DeltaE,
442 weta1c,
443 wtot,
444 fracm,
445 f3,
446 ep,
448 mu);
449
450 // Add ambiguity resolution cut for photon (vs electron)
451 // to reproduce release 21.2 ambiguity tool configuration
452 if (!m_skipAmbiguityCut){
453 static const SG::AuxElement::Accessor<uint8_t> acc("ambiguityType");
454 int AmbiguityType = acc(*eg);
455 if (eg->author() == xAOD::EgammaParameters::AuthorAmbiguous &&
458 }
459 }
460
461 return StatusCode::SUCCESS;
462}
463
464float AsgPhotonIsEMSelector::getMu(const EventContext& ctx) const {
466 if (!evtI.isValid()) {
467 ATH_MSG_WARNING("Cannot find EventInfo, returning -999.");
468 return -999;
469 }
470 return evtI->actualInteractionsPerCrossing();
471}
472
473int AsgPhotonIsEMSelector::RunNumber(const EventContext& ctx) const {
475 if (!evtI.isValid()) {
476 ATH_MSG_WARNING("Cannot find EventInfo, returning -999.");
477 return -999;
478 }
479 return evtI->runNumber();
480}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading from StoreGate.
static Double_t sc
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
float getMu(const EventContext &ctx) const
std::string m_configFile
Config File.
virtual const asg::AcceptInfo & getAcceptInfo() const
Method to get the plain AcceptInfo.
virtual asg::AcceptData accept(const xAOD::IParticle *part) const
Accept with generic interface.
std::string m_WorkingPoint
Working Point.
bool m_caloOnly
Flag for calo only cut-base.
int RunNumber(const EventContext &ctx) const
Root::TPhotonIsEMSelector * m_rootTool
Pointer to the underlying ROOT based tool.
ASG_TOOL_CLASS3(AsgPhotonIsEMSelector, IAsgPhotonIsEMSelector, IAsgEGammaIsEMSelector, IAsgSelectionTool) public ~AsgPhotonIsEMSelector()
Default constructor.
SG::ReadHandleKey< xAOD::EventInfo > m_EvtInfoKey
virtual std::string getOperatingPointName() const
Method to get the operating point.
virtual StatusCode execute(const EventContext &ctx, const xAOD::Egamma *eg, unsigned int &isEM) const
The basic isem.
bool m_useF3core
use f3core or f3 (default: use f3)
virtual StatusCode initialize()
AlgTool initialize method.
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:572
virtual bool isValid() override final
Can the handle be successfully dereferenced?
virtual double e() const
The total energy of the particle.
float etaBE(const unsigned layer) const
Get the eta in one layer of the EM Calo.
Class providing the definition of the 4-vector interface.
static std::vector< uint32_t > runnumber
Definition iLumiCalc.h:37
unsigned int findMask(const std::string &input, const std::map< std::string, unsigned int > &maskmap)
std::string findConfigFile(const std::string &input, const std::map< std::string, std::string > &configmap)
std::vector< float > HelperFloat(const std::string &input, TEnv &env)
const std::map< std::string, std::string > PhotonCutPointToConfFile
const std::map< std::string, unsigned int > PhotonCutPointToMask
const unsigned int PhotonLooseEF
TrigEgamma Pid Definitions.
const unsigned int PhotonMediumEF
Medium photon selection for online EF.
const unsigned int PhotonMedium
Medium photon selection.
@ AmbiguityResolution_Photon
ambiguity resolution for photon (vs electron)
@ ClusterEtaRange_Photon
cluster eta range
const unsigned int PhotonLoose
Loose photon selection.
const unsigned int PhotonTight
Tight photon selection.
const unsigned int EgPidUndefined
@ Photon
The object is a photon.
Definition ObjectType.h:47
@ Electron
The object is an electron.
Definition ObjectType.h:46
bool isConvertedPhoton(const xAOD::Egamma *eg, bool excludeTRT=false)
is the object a converted photon
Amg::Vector3D momentumAtVertex(const xAOD::Photon *, bool debug=false)
return the momentum at the vertex (which can be 0)
const uint16_t AuthorAmbiguous
Object Reconstructed by standard cluster-based algorithm.
Definition EgammaDefs.h:32
@ wtots1
shower width is determined in a window detaxdphi = 0,0625 ×~0,2, corresponding typically to 20 strips...
@ f3core
E3(3x3)/E fraction of the energy reconstructed in the third compartment of the electromagnetic calori...
Definition EgammaEnums.h:66
@ e277
uncalibrated energy (sum of cells) of the middle sampling in a rectangle of size 7x7
Definition EgammaEnums.h:81
@ 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)
@ DeltaE
e2tsts1-emins1
@ fracs1
shower shape in the shower core : [E(+/-3)-E(+/-1)]/E(+/-1), where E(+/-n) is the energy in ± n strip...
@ weta2
the lateral width is calculated with a window of 3x5 cells using the energy weighted sum over all cel...
@ weta1
shower width using +/-3 strips around the one with the maximal energy deposit: w3 strips = sqrt{sum(E...
Definition EgammaEnums.h:98
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
Egamma_v1 Egamma
Definition of the current "egamma version".
Definition Egamma.h:17
Photon_v1 Photon
Definition of the current "egamma version".
Electron_v1 Electron
Definition of the current "egamma version".
Extra patterns decribing particle interation process.
MsgStream & msg
Definition testRead.cxx:32