ATLAS Offline Software
DiphotonVertexDecorator.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 // DiphotonVertexDecorator.cxx, (c) ATLAS Detector software
8 // To add the diphoton vertex to the evtStore
9 
11 #include <vector>
12 #include <string>
13 #include "TString.h"
14 
15 #include "CLHEP/Units/SystemOfUnits.h"
16 
17 #include "xAODCore/ShallowCopy.h"
22 // For DeltaR
25 
27 
28 // Constructor
30  const std::string& n,
31  const IInterface* p) :
32  AthAlgTool(t, n, p)
33 {
34 
35  declareInterface<DerivationFramework::IAugmentationTool>(this);
36 
37  declareProperty("RemoveCrack", m_removeCrack = true);
38  declareProperty("MaxEta", m_maxEta = 2.37);
39  declareProperty("MinimumPhotonPt", m_minPhotonPt = 20*CLHEP::GeV);
40  declareProperty("IgnoreConvPointing", m_ignoreConv = false);
41  declareProperty("TCMatchMaxRat", m_tcMatch_maxRat = 1.5 );
42  declareProperty("TCMatchDeltaR", m_tcMatch_dR = 0.1 );
43 
44 }
45 
46 // Destructor
48 }
49 
50 // Athena initialize and finalize
52 {
53  ATH_CHECK( m_photonVertexSelectionTool.retrieve() );
54  ATH_CHECK( m_primaryVertexKey.initialize() );
55  ATH_CHECK( m_photonKey.initialize() );
56  ATH_CHECK( m_diphotonVertexKey.initialize() );
57  ATH_CHECK( m_FEContainerHandleKey.initialize() );
58  return StatusCode::SUCCESS;
59 }
60 
62 {
63  return StatusCode::SUCCESS;
64 }
65 
67 {
68 
69  ATH_MSG_DEBUG( "DiphotonVertexDecorator::AddingBranches" );
70 
71  SG::ReadHandle<xAOD::VertexContainer> PV (m_primaryVertexKey);
72 
73  if (!PV->empty() && PV->at(0)) {
74  ATH_MSG_DEBUG( "Default PV " << PV->at(0) << ", type = " << PV->at(0)->vertexType() << " , z = " << PV->at(0)->z() );
75  }
76 
77  // Select the two highest pt photons that pass a preselection
78 
79  SG::ReadHandle<xAOD::PhotonContainer> photons (m_photonKey);
80  const xAOD::Photon *ph1 = nullptr, *ph2 = nullptr;
81 
82  for (const xAOD::Photon* ph: *photons)
83  {
84  if (!PhotonPreselect(ph)) continue;
85  if (not ph1 or ph->pt() > ph1->pt()) // new leading photon
86  {
87  ph2 = ph1;
88  ph1 = ph;
89  }
90  else if (not ph2 or ph->pt() > ph2->pt()) ph2 = ph; // new subleading photon
91  }
92 
93  const ConstDataVector< xAOD::PhotonContainer > vertexPhotons = {ph1, ph2};
94 
97 
98  ATH_CHECK( m_photonVertexSelectionTool->decorateInputs(*(vertexPhotons.asDataVector()), &vertexFailType) );
99 
100  // Get the photon vertex if possible
101  std::vector<std::pair<const xAOD::Vertex*, float> > vxResult;
102  const xAOD::Vertex *newPV = nullptr;
103 
104  SG::ReadHandle<xAOD::FlowElementContainer> FEHandle(m_FEContainerHandleKey);
105  SG::Decorator<char> passORDec("passOR");
106  for(const auto *const fe : *FEHandle) passORDec(*fe) = true;
107 
108  if (ph1 and ph2)
109  {
110  vxResult = m_photonVertexSelectionTool->getVertex( *( vertexPhotons.asDataVector()) , m_ignoreConv, true, &yyvertexVtxType, &vertexFailType );
111  if(!vxResult.empty()) {
112  newPV = vxResult[0].first; //output of photon vertex selection tool must be sorted according to score
113  }
114  ATH_CHECK(matchFlowElement(ph1,&*FEHandle));
115  ATH_CHECK(matchFlowElement(ph2,&*FEHandle));
116  }
117 
118  // Decorate the vertices with the NN score
119  ATH_MSG_DEBUG("PhotonVertexSelection returns vertex " << newPV << " " << (newPV? Form(" with z = %g", newPV->z()) : "") );
120  // Create shallow copy of the PrimaryVertices container
121  std::pair< xAOD::VertexContainer*, xAOD::ShallowAuxContainer* > HggPV = xAOD::shallowCopyContainer( *PV );
122  HggPV.second->setShallowIO(false);
123 
124  SG::WriteHandle<xAOD::VertexContainer> vertexContainer(m_diphotonVertexKey);
125  ATH_CHECK(vertexContainer.recordNonConst(std::unique_ptr< xAOD::VertexContainer >(HggPV.first),
126  std::unique_ptr< xAOD::ShallowAuxContainer >(HggPV.second)));
127 
128 
129  static const SG::Accessor<float> vertexScoreAcc("vertexScore");
130  static const SG::Accessor<int> vertexFailTypeAcc("vertexFailType");
131  static const SG::Accessor<int> vertexCaseAcc("vertexCase");
132  static const SG::Accessor<phlink_t> leadingPhotonLinkAcc("leadingPhotonLink");
133  static const SG::Accessor<phlink_t> subleadingPhotonLinkAcc("subleadingPhotonLink");
134 
135  if (newPV) {
136  //loop over vertex container; shallow copy has the same order
137  for (unsigned int iPV=0; iPV<PV->size(); iPV++) {
138  const auto *vx = PV->at(iPV);
139  auto yyvx = (HggPV.first)->at(iPV);
140  //reset vertex type
141  if (vx == newPV) {
142  //is this the diphoton primary vertex returned from the tool?
143  yyvx->setVertexType( xAOD::VxType::PriVtx );
144  } else if ( vx->vertexType()==xAOD::VxType::PriVtx || vx->vertexType()==xAOD::VxType::PileUp ) {
145  //not overriding the type of dummy vertices of type 0 (NoVtx)
146  yyvx->setVertexType( xAOD::VxType::PileUp );
147  }
148  //decorate score
149  for (const auto& vxR: vxResult) {
150  //find vertex in output from photonVertexSelectionTool
151  if ( vx == vxR.first ) {
152  vertexScoreAcc(*yyvx) = vxR.second;
153  vertexFailTypeAcc(*yyvx) = vertexFailType;
154  vertexCaseAcc(*yyvx) = yyvertexVtxType;
155  leadingPhotonLinkAcc(*yyvx) = phlink_t(*photons, ph1->index());
156  subleadingPhotonLinkAcc(*yyvx) = phlink_t(*photons, ph2->index());
157  break;
158  }
159  }
160  }
161  }
162  else {
163  //no vertex returned by photonVertexSelectionTool, decorate default PV with fit information
165  xAOD::VertexContainer::iterator yyvx_end = (HggPV.first)->end();
166  for(yyvx_itr = (HggPV.first)->begin(); yyvx_itr != yyvx_end; ++yyvx_itr ) {
167  if ( (*yyvx_itr)->vertexType()==xAOD::VxType::PriVtx ) {
168  vertexScoreAcc(**yyvx_itr) = -9999;
169  vertexFailTypeAcc(**yyvx_itr) = vertexFailType;
170  vertexCaseAcc(**yyvx_itr) = yyvertexVtxType;
171  leadingPhotonLinkAcc(**yyvx_itr) = (phlink_t()) ;
172  subleadingPhotonLinkAcc(**yyvx_itr) = (phlink_t());
173  }
174  }
175  }
176 
177 
178  if( !evtStore()->transientContains< xAOD::VertexContainer >( m_diphotonVertexKey.key() ) ){
179  ATH_MSG_WARNING("Unable to find transient xAOD::VertexContainer, \"" << m_diphotonVertexKey.key() << "\"");
180  }
181 
182  return StatusCode::SUCCESS;
183 }
184 
186 {
187 
188  if (!ph) return false;
189 
190  if (!ph->isGoodOQ(34214)) return false;
191 
192  bool val(false);
193  bool defined(false);
194 
195  static const SG::ConstAccessor<char> DFCommonPhotonsIsEMLooseAcc("DFCommonPhotonsIsEMLoose");
196  if(DFCommonPhotonsIsEMLooseAcc.isAvailable(*ph)){
197  defined = true;
198  val = static_cast<bool>(DFCommonPhotonsIsEMLooseAcc(*ph));
199  }
200  else{
201  defined = ph->passSelection(val, "Loose");
202  }
203 
204  if(!defined || !val) return false;
205 
206  // veto topo-seeded clusters
207  if (ph->author(xAOD::EgammaParameters::AuthorCaloTopo35)) return false;
208 
209  // Check which variable versions are best...
210  const xAOD::CaloCluster *caloCluster(ph->caloCluster());
211  double eta = std::abs(caloCluster->etaBE(2));
212 
213  if (eta > m_maxEta) return false;
214  if (m_removeCrack && 1.37 <= eta && eta <= 1.52) return false;
215 
216  if (ph->pt() < m_minPhotonPt) return false;
217 
218  return true;
219 
220 }
221 
223  const xAOD::IParticle* swclus = eg->caloCluster();
224 
225  // Preselect FEs based on proximity: dR<0.4
226  std::vector<const xAOD::FlowElement*> nearbyFE;
227  nearbyFE.reserve(20);
228  for(const auto *const fe : *feCont) {
229  if(xAOD::P4Helpers::isInDeltaR(*fe, *swclus, 0.4, true)) {
230  if( ( !fe->isCharged() && fe->e() > FLT_MIN )) nearbyFE.push_back(fe);
231  } // DeltaR check
232  } // FE loop
233 
234  SG::Decorator<char> passORDec("passOR");
235 
236  double eg_cl_e = swclus->e();
237  bool doSum = true;
238  double sumE_fe = 0.;
239  const xAOD::IParticle* bestbadmatch = nullptr;
240  std::sort(nearbyFE.begin(),nearbyFE.end(),greaterPtFlowElement);
241  for(const auto& fe : nearbyFE) {
242  if(!xAOD::P4Helpers::isInDeltaR(*fe, *swclus, m_tcMatch_dR, true)) {continue;}
243  // Handle neutral FEs like topoclusters
244  double fe_e = fe->e();
245  // skip cluster if it's above our bad match threshold or outside the matching radius
246  if(fe_e>m_tcMatch_maxRat*eg_cl_e) {
247  ATH_MSG_VERBOSE("Reject topocluster in sum. Ratio vs eg cluster: " << (fe_e/eg_cl_e));
248  if( !bestbadmatch || (std::abs(fe_e/eg_cl_e-1.) < std::abs(bestbadmatch->e()/eg_cl_e-1.)) ) bestbadmatch = fe;
249  continue;
250  }
251 
252  ATH_MSG_VERBOSE("E match with new nFE: " << std::abs(sumE_fe+fe_e - eg_cl_e) / eg_cl_e);
253  if( (doSum = std::abs(sumE_fe+fe_e-eg_cl_e) < std::abs(sumE_fe - eg_cl_e)) ) {
254  passORDec(*fe) = false;
255  sumE_fe += fe_e;
256  } // if we will retain the topocluster
257  else {break;}
258  } // loop over nearby clusters
259  if(sumE_fe<FLT_MIN && bestbadmatch) {
260  passORDec(*bestbadmatch) = false;
261  }
262 
263  return StatusCode::SUCCESS;
264 }
ShallowCopy.h
GeV
#define GeV
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/Root/HelperFunctions.cxx:17
ParticleTest.eg
eg
Definition: ParticleTest.py:29
SG::Accessor< float >
ConstDataVector.h
DataVector adapter that acts like it holds const pointers.
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
xAODP4Helpers.h
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
CP::IPhotonVertexSelectionTool::Unknown
@ Unknown
Definition: IPhotonVertexSelectionTool.h:45
DerivationFramework::DiphotonVertexDecorator::m_minPhotonPt
double m_minPhotonPt
Definition: DiphotonVertexDecorator.h:65
DerivationFramework::DiphotonVertexDecorator::m_removeCrack
bool m_removeCrack
Definition: DiphotonVertexDecorator.h:66
xAOD::Egamma_v1::author
uint16_t author(uint16_t bitmask=EgammaParameters::AuthorALL) const
Get author.
Definition: Egamma_v1.cxx:166
DerivationFramework::DiphotonVertexDecorator::m_maxEta
double m_maxEta
Definition: DiphotonVertexDecorator.h:67
SG::ConstAccessor< char >
DerivationFramework::DiphotonVertexDecorator::PhotonPreselect
bool PhotonPreselect(const xAOD::Photon *ph) const
Definition: DiphotonVertexDecorator.cxx:185
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
DerivationFramework::DiphotonVertexDecorator::m_tcMatch_maxRat
double m_tcMatch_maxRat
Definition: DiphotonVertexDecorator.h:71
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:41
ConstDataVector::asDataVector
const DV * asDataVector() const
Return a pointer to this object, as a const DataVector.
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
DerivationFramework::DiphotonVertexDecorator::~DiphotonVertexDecorator
~DiphotonVertexDecorator()
Destructor.
Definition: DiphotonVertexDecorator.cxx:47
xAOD::CaloCluster_v1::etaBE
float etaBE(const unsigned layer) const
Get the eta in one layer of the EM Calo.
Definition: CaloCluster_v1.cxx:644
xAOD::CaloCluster_v1
Description of a calorimeter cluster.
Definition: CaloCluster_v1.h:59
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
DerivationFramework::DiphotonVertexDecorator::initialize
StatusCode initialize()
Definition: DiphotonVertexDecorator.cxx:51
SG::Decorator< char >
SG::WriteHandle::recordNonConst
StatusCode recordNonConst(std::unique_ptr< T > data)
Record a non-const object to the store.
DataModel_detail::iterator
(Non-const) Iterator class for DataVector/DataList.
Definition: DVLIterator.h:184
CP::IPhotonVertexSelectionTool::yyVtxType
yyVtxType
Definition: IPhotonVertexSelectionTool.h:44
xAOD::EgammaParameters::AuthorCaloTopo35
const uint16_t AuthorCaloTopo35
Photon reconstructed by SW CaloTopo35 seeded clusters.
Definition: EgammaDefs.h:38
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
DerivationFramework::DiphotonVertexDecorator::matchFlowElement
StatusCode matchFlowElement(const xAOD::Photon *eg, const xAOD::FlowElementContainer *pfoCont) const
Definition: DiphotonVertexDecorator.cxx:222
DerivationFramework::DiphotonVertexDecorator::addBranches
virtual StatusCode addBranches() const
Pass the thinning service
Definition: DiphotonVertexDecorator.cxx:66
xAOD::Egamma_v1::caloCluster
const xAOD::CaloCluster * caloCluster(size_t index=0) const
Pointer to the xAOD::CaloCluster/s that define the electron candidate.
Definition: Egamma_v1.cxx:388
CP::IPhotonVertexSelectionTool::FailType
FailType
Declare the interface that the class provides.
Definition: IPhotonVertexSelectionTool.h:33
xAOD::VxType::PriVtx
@ PriVtx
Primary vertex.
Definition: TrackingPrimitives.h:571
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
xAOD::Vertex_v1::z
float z() const
Returns the z position.
SG::AuxElement::index
size_t index() const
Return the index of this element within its container.
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
DerivationFramework::DiphotonVertexDecorator::DiphotonVertexDecorator
DiphotonVertexDecorator(const std::string &t, const std::string &n, const IInterface *p)
Constructor with parameters.
Definition: DiphotonVertexDecorator.cxx:29
xAOD::VxType::PileUp
@ PileUp
Pile-up vertex.
Definition: TrackingPrimitives.h:573
phlink_t
ElementLink< xAOD::PhotonContainer > phlink_t
Definition: DiphotonVertexDecorator.cxx:26
DerivationFramework::DiphotonVertexDecorator::finalize
StatusCode finalize()
Definition: DiphotonVertexDecorator.cxx:61
xAOD::shallowCopyContainer
std::pair< std::unique_ptr< T >, std::unique_ptr< ShallowAuxContainer > > shallowCopyContainer(const T &cont, [[maybe_unused]] const EventContext &ctx)
Function making a shallow copy of a constant container.
Definition: ShallowCopy.h:110
EventInfo.h
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:76
VertexContainer.h
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
xAOD::Photon_v1
Definition: Photon_v1.h:37
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
ConstDataVector
DataVector adapter that acts like it holds const pointers.
Definition: ConstDataVector.h:76
Pythia8_RapidityOrderMPI.val
val
Definition: Pythia8_RapidityOrderMPI.py:14
DiphotonVertexDecorator.h
xAOD::Egamma_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: Egamma_v1.cxx:65
DerivationFramework::DiphotonVertexDecorator::m_ignoreConv
bool m_ignoreConv
Definition: DiphotonVertexDecorator.h:68
SG::ConstAccessor::isAvailable
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
DerivationFramework::DiphotonVertexDecorator::m_tcMatch_dR
double m_tcMatch_dR
Definition: DiphotonVertexDecorator.h:70
DataVector::at
const T * at(size_type n) const
Access an element, as an rvalue.
xAOD::P4Helpers::isInDeltaR
bool isInDeltaR(const xAOD::IParticle &p1, const xAOD::IParticle &p2, double dR, bool useRapidity=true)
Check if 2 xAOD::IParticle are in a cone.
Definition: xAODP4Helpers.h:174
AthAlgTool
Definition: AthAlgTool.h:26
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
Decorator.h
Helper class to provide type-safe access to aux data.
TrackingPrimitives.h
DataVector::empty
bool empty() const noexcept
Returns true if the collection is empty.
xAOD::IParticle::e
virtual double e() const =0
The total energy of the particle.
xAOD::Egamma_v1::passSelection
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...
xAOD::Egamma_v1::isGoodOQ
bool isGoodOQ(uint32_t mask) const
Check object quality. Return True is it is Good Object Quality.
Definition: Egamma_v1.cxx:236