ATLAS Offline Software
Loading...
Searching...
No Matches
DiphotonVertexDecorator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6// DiphotonVertexDecorator.cxx
8// To add the diphoton vertex to the evtStore
9
11#include <vector>
12#include <string>
13#include "TString.h"
14
15
21// For DeltaR
24
26
27// Athena initialize
29{
31 ATH_CHECK( m_primaryVertexKey.initialize() );
32 ATH_CHECK( m_photonKey.initialize() );
33 ATH_CHECK( m_diphotonVertexKey.initialize() );
34 ATH_CHECK( m_FEContainerHandleKey.initialize() );
35 return StatusCode::SUCCESS;
36}
37
38
39StatusCode DerivationFramework::DiphotonVertexDecorator::addBranches(const EventContext& ctx) const
40{
41 ATH_MSG_DEBUG( "DiphotonVertexDecorator::AddingBranches" );
42
44
45 if (!PV->empty() && PV->at(0)) {
46 ATH_MSG_DEBUG( "Default PV " << PV->at(0) << ", type = " << PV->at(0)->vertexType() << " , z = " << PV->at(0)->z() );
47 }
48
49 // Select the two highest pt photons that pass a preselection
50
52 const xAOD::Photon *ph1 = nullptr, *ph2 = nullptr;
53
54 for (const xAOD::Photon* ph: *photons)
55 {
56 if (!PhotonPreselect(ph)) continue;
57 if (not ph1 or ph->pt() > ph1->pt()) // new leading photon
58 {
59 ph2 = ph1;
60 ph1 = ph;
61 }
62 else if (not ph2 or ph->pt() > ph2->pt()) ph2 = ph; // new subleading photon
63 }
64
65 const ConstDataVector< xAOD::PhotonContainer > vertexPhotons = {ph1, ph2};
66
69
70 ATH_CHECK( m_photonVertexSelectionTool->decorateInputs(*(vertexPhotons.asDataVector()), &vertexFailType) );
71
72 // Get the photon vertex if possible
73 std::vector<std::pair<const xAOD::Vertex*, float> > vxResult;
74 const xAOD::Vertex *newPV = nullptr;
75
77 SG::Decorator<char> passORDec("passOR");
78 for(const auto *const fe : *FEHandle) passORDec(*fe) = true;
79
80 if (ph1 and ph2)
81 {
82 vxResult = m_photonVertexSelectionTool->getVertex( *( vertexPhotons.asDataVector()) , m_ignoreConv, true, &yyvertexVtxType, &vertexFailType );
83 if(!vxResult.empty()) {
84 newPV = vxResult[0].first; //output of photon vertex selection tool must be sorted according to score
85 }
86 ATH_CHECK(matchFlowElement(ph1,&*FEHandle));
87 ATH_CHECK(matchFlowElement(ph2,&*FEHandle));
88 }
89
90 // Decorate the vertices with the NN score
91 ATH_MSG_DEBUG("PhotonVertexSelection returns vertex " << newPV << " " << (newPV? Form(" with z = %g", newPV->z()) : "") );
92 // Create shallow copy of the PrimaryVertices container
93 std::pair< xAOD::VertexContainer*, xAOD::ShallowAuxContainer* > HggPV = xAOD::shallowCopyContainer( *PV );
94 HggPV.second->setShallowIO(false);
95
97 ATH_CHECK(vertexContainer.recordNonConst(std::unique_ptr< xAOD::VertexContainer >(HggPV.first),
98 std::unique_ptr< xAOD::ShallowAuxContainer >(HggPV.second)));
99
100
101 static const SG::Accessor<float> vertexScoreAcc("vertexScore");
102 static const SG::Accessor<int> vertexFailTypeAcc("vertexFailType");
103 static const SG::Accessor<int> vertexCaseAcc("vertexCase");
104 static const SG::Accessor<phlink_t> leadingPhotonLinkAcc("leadingPhotonLink");
105 static const SG::Accessor<phlink_t> subleadingPhotonLinkAcc("subleadingPhotonLink");
106
107 if (newPV) {
108 //loop over vertex container; shallow copy has the same order
109 for (unsigned int iPV=0; iPV<PV->size(); iPV++) {
110 const auto *vx = PV->at(iPV);
111 auto yyvx = (HggPV.first)->at(iPV);
112 //reset vertex type
113 if (vx == newPV) {
114 //is this the diphoton primary vertex returned from the tool?
115 yyvx->setVertexType( xAOD::VxType::PriVtx );
116 } else if ( vx->vertexType()==xAOD::VxType::PriVtx || vx->vertexType()==xAOD::VxType::PileUp ) {
117 //not overriding the type of dummy vertices of type 0 (NoVtx)
118 yyvx->setVertexType( xAOD::VxType::PileUp );
119 }
120 //decorate score
121 for (const auto& vxR: vxResult) {
122 //find vertex in output from photonVertexSelectionTool
123 if ( vx == vxR.first ) {
124 vertexScoreAcc(*yyvx) = vxR.second;
125 vertexFailTypeAcc(*yyvx) = vertexFailType;
126 vertexCaseAcc(*yyvx) = yyvertexVtxType;
127 leadingPhotonLinkAcc(*yyvx) = phlink_t(*photons, ph1->index());
128 subleadingPhotonLinkAcc(*yyvx) = phlink_t(*photons, ph2->index());
129 break;
130 }
131 }
132 }
133 }
134 else {
135 //no vertex returned by photonVertexSelectionTool, decorate default PV with fit information
137 xAOD::VertexContainer::iterator yyvx_end = (HggPV.first)->end();
138 for(yyvx_itr = (HggPV.first)->begin(); yyvx_itr != yyvx_end; ++yyvx_itr ) {
139 if ( (*yyvx_itr)->vertexType()==xAOD::VxType::PriVtx ) {
140 vertexScoreAcc(**yyvx_itr) = -9999;
141 vertexFailTypeAcc(**yyvx_itr) = vertexFailType;
142 vertexCaseAcc(**yyvx_itr) = yyvertexVtxType;
143 leadingPhotonLinkAcc(**yyvx_itr) = (phlink_t()) ;
144 subleadingPhotonLinkAcc(**yyvx_itr) = (phlink_t());
145 }
146 }
147 }
148
149
150 if( !evtStore()->transientContains< xAOD::VertexContainer >( m_diphotonVertexKey.key() ) ){
151 ATH_MSG_WARNING("Unable to find transient xAOD::VertexContainer, \"" << m_diphotonVertexKey.key() << "\"");
152 }
153
154 return StatusCode::SUCCESS;
155}
156
158{
159
160 if (!ph) return false;
161
162 if (!ph->isGoodOQ(34214)) return false;
163
164 bool val(false);
165 bool defined(false);
166
167 static const SG::ConstAccessor<char> DFCommonPhotonsIsEMLooseAcc("DFCommonPhotonsIsEMLoose");
168 if(DFCommonPhotonsIsEMLooseAcc.isAvailable(*ph)){
169 defined = true;
170 val = static_cast<bool>(DFCommonPhotonsIsEMLooseAcc(*ph));
171 }
172 else{
173 defined = ph->passSelection(val, "Loose");
174 }
175
176 if(!defined || !val) return false;
177
178 // veto topo-seeded clusters
180
181 // Check which variable versions are best...
182 const xAOD::CaloCluster *caloCluster(ph->caloCluster());
183 double eta = std::abs(caloCluster->etaBE(2));
184
185 if (eta > m_maxEta) return false;
186 if (m_removeCrack && 1.37 <= eta && eta <= 1.52) return false;
187
188 if (ph->pt() < m_minPhotonPt) return false;
189
190 return true;
191
192}
193
195 const xAOD::IParticle* swclus = eg->caloCluster();
196
197 // Preselect FEs based on proximity: dR<0.4
198 std::vector<const xAOD::FlowElement*> nearbyFE;
199 nearbyFE.reserve(20);
200 for(const auto *const fe : *feCont) {
201 if(xAOD::P4Helpers::isInDeltaR(*fe, *swclus, 0.4, true)) {
202 if( ( !fe->isCharged() && fe->e() > FLT_MIN )) nearbyFE.push_back(fe);
203 } // DeltaR check
204 } // FE loop
205
206 SG::Decorator<char> passORDec("passOR");
207
208 double eg_cl_e = swclus->e();
209 bool doSum = true;
210 double sumE_fe = 0.;
211 const xAOD::IParticle* bestbadmatch = nullptr;
212 std::sort(nearbyFE.begin(),nearbyFE.end(),greaterPtFlowElement);
213 for(const auto& fe : nearbyFE) {
214 if(!xAOD::P4Helpers::isInDeltaR(*fe, *swclus, m_tcMatch_dR, true)) {continue;}
215 // Handle neutral FEs like topoclusters
216 double fe_e = fe->e();
217 // skip cluster if it's above our bad match threshold or outside the matching radius
218 if(fe_e>m_tcMatch_maxRat*eg_cl_e) {
219 ATH_MSG_VERBOSE("Reject topocluster in sum. Ratio vs eg cluster: " << (fe_e/eg_cl_e));
220 if( !bestbadmatch || (std::abs(fe_e/eg_cl_e-1.) < std::abs(bestbadmatch->e()/eg_cl_e-1.)) ) bestbadmatch = fe;
221 continue;
222 }
223
224 ATH_MSG_VERBOSE("E match with new nFE: " << std::abs(sumE_fe+fe_e - eg_cl_e) / eg_cl_e);
225 if( (doSum = std::abs(sumE_fe+fe_e-eg_cl_e) < std::abs(sumE_fe - eg_cl_e)) ) {
226 passORDec(*fe) = false;
227 sumE_fe += fe_e;
228 } // if we will retain the topocluster
229 else {break;}
230 } // loop over nearby clusters
231 if(sumE_fe<FLT_MIN && bestbadmatch) {
232 passORDec(*bestbadmatch) = false;
233 }
234
235 return StatusCode::SUCCESS;
236}
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
DataVector adapter that acts like it holds const pointers.
Helper class to provide type-safe access to aux data.
ElementLink< xAOD::PhotonContainer > phlink_t
FailType
Declare the interface that the class provides.
DataVector adapter that acts like it holds const pointers.
const DV * asDataVector() const
Return a pointer to this object, as a const DataVector.
DataModel_detail::iterator< DataVector > iterator
Definition DataVector.h:842
SG::ReadHandleKey< xAOD::PhotonContainer > m_photonKey
static bool greaterPtFlowElement(const xAOD::FlowElement *part1, const xAOD::FlowElement *part2)
SG::ReadHandleKey< xAOD::FlowElementContainer > m_FEContainerHandleKey
virtual StatusCode addBranches(const EventContext &ctx) const override final
SG::WriteHandleKey< xAOD::VertexContainer > m_diphotonVertexKey
SG::ReadHandleKey< xAOD::VertexContainer > m_primaryVertexKey
ToolHandle< CP::IPhotonVertexSelectionTool > m_photonVertexSelectionTool
StatusCode matchFlowElement(const xAOD::Photon *eg, const xAOD::FlowElementContainer *pfoCont) const
Helper class to provide type-safe access to aux data.
size_t index() const
Return the index of this element within its container.
Helper class to provide constant type-safe access to aux data.
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
Helper class to provide type-safe access to aux data.
Definition Decorator.h:59
StatusCode recordNonConst(std::unique_ptr< T > data)
Record a non-const object to the store.
float etaBE(const unsigned layer) const
Get the eta in one layer of the EM Calo.
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition Egamma_v1.cxx:66
bool isGoodOQ(uint32_t mask) const
Check object quality. Return True is it is Good Object Quality.
bool passSelection(bool &value, const std::string &menu) const
Check if the egamma object pass a selection menu (using the name) If the menu decision is stored in t...
uint16_t author(uint16_t bitmask=EgammaParameters::AuthorALL) const
Get author.
const xAOD::CaloCluster * caloCluster(size_t index=0) const
Pointer to the xAOD::CaloCluster/s that define the electron candidate.
Class providing the definition of the 4-vector interface.
virtual double e() const =0
The total energy of the particle.
float z() const
Returns the z position.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
const uint16_t AuthorCaloTopo35
Photon reconstructed by SW CaloTopo35 seeded clusters.
Definition EgammaDefs.h:38
bool isInDeltaR(const xAOD::IParticle &p1, const xAOD::IParticle &p2, double dR, bool useRapidity=true)
Check if 2 xAOD::IParticle are in a cone.
@ PileUp
Pile-up vertex.
@ PriVtx
Primary vertex.
FlowElementContainer_v1 FlowElementContainer
Definition of the current "pfo container version".
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
std::pair< std::unique_ptr< T >, std::unique_ptr< ShallowAuxContainer > > shallowCopyContainer(const T &cont, const EventContext &ctx)
Function making a shallow copy of a constant container.
Vertex_v1 Vertex
Define the latest version of the vertex class.
Photon_v1 Photon
Definition of the current "egamma version".