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  base_class(t, n, p)
33 {
34 
35 
36  declareProperty("RemoveCrack", m_removeCrack = true);
37  declareProperty("MaxEta", m_maxEta = 2.37);
38  declareProperty("MinimumPhotonPt", m_minPhotonPt = 20*CLHEP::GeV);
39  declareProperty("IgnoreConvPointing", m_ignoreConv = false);
40  declareProperty("TCMatchMaxRat", m_tcMatch_maxRat = 1.5 );
41  declareProperty("TCMatchDeltaR", m_tcMatch_dR = 0.1 );
42 
43 }
44 
45 // Destructor
47 }
48 
49 // Athena initialize and finalize
51 {
52  ATH_CHECK( m_photonVertexSelectionTool.retrieve() );
53  ATH_CHECK( m_primaryVertexKey.initialize() );
54  ATH_CHECK( m_photonKey.initialize() );
55  ATH_CHECK( m_diphotonVertexKey.initialize() );
56  ATH_CHECK( m_FEContainerHandleKey.initialize() );
57  return StatusCode::SUCCESS;
58 }
59 
61 {
62  return StatusCode::SUCCESS;
63 }
64 
66 {
67 
68  ATH_MSG_DEBUG( "DiphotonVertexDecorator::AddingBranches" );
69 
70  SG::ReadHandle<xAOD::VertexContainer> PV (m_primaryVertexKey);
71 
72  if (!PV->empty() && PV->at(0)) {
73  ATH_MSG_DEBUG( "Default PV " << PV->at(0) << ", type = " << PV->at(0)->vertexType() << " , z = " << PV->at(0)->z() );
74  }
75 
76  // Select the two highest pt photons that pass a preselection
77 
78  SG::ReadHandle<xAOD::PhotonContainer> photons (m_photonKey);
79  const xAOD::Photon *ph1 = nullptr, *ph2 = nullptr;
80 
81  for (const xAOD::Photon* ph: *photons)
82  {
83  if (!PhotonPreselect(ph)) continue;
84  if (not ph1 or ph->pt() > ph1->pt()) // new leading photon
85  {
86  ph2 = ph1;
87  ph1 = ph;
88  }
89  else if (not ph2 or ph->pt() > ph2->pt()) ph2 = ph; // new subleading photon
90  }
91 
92  const ConstDataVector< xAOD::PhotonContainer > vertexPhotons = {ph1, ph2};
93 
96 
97  ATH_CHECK( m_photonVertexSelectionTool->decorateInputs(*(vertexPhotons.asDataVector()), &vertexFailType) );
98 
99  // Get the photon vertex if possible
100  std::vector<std::pair<const xAOD::Vertex*, float> > vxResult;
101  const xAOD::Vertex *newPV = nullptr;
102 
103  SG::ReadHandle<xAOD::FlowElementContainer> FEHandle(m_FEContainerHandleKey);
104  SG::Decorator<char> passORDec("passOR");
105  for(const auto *const fe : *FEHandle) passORDec(*fe) = true;
106 
107  if (ph1 and ph2)
108  {
109  vxResult = m_photonVertexSelectionTool->getVertex( *( vertexPhotons.asDataVector()) , m_ignoreConv, true, &yyvertexVtxType, &vertexFailType );
110  if(!vxResult.empty()) {
111  newPV = vxResult[0].first; //output of photon vertex selection tool must be sorted according to score
112  }
113  ATH_CHECK(matchFlowElement(ph1,&*FEHandle));
114  ATH_CHECK(matchFlowElement(ph2,&*FEHandle));
115  }
116 
117  // Decorate the vertices with the NN score
118  ATH_MSG_DEBUG("PhotonVertexSelection returns vertex " << newPV << " " << (newPV? Form(" with z = %g", newPV->z()) : "") );
119  // Create shallow copy of the PrimaryVertices container
120  std::pair< xAOD::VertexContainer*, xAOD::ShallowAuxContainer* > HggPV = xAOD::shallowCopyContainer( *PV );
121  HggPV.second->setShallowIO(false);
122 
123  SG::WriteHandle<xAOD::VertexContainer> vertexContainer(m_diphotonVertexKey);
124  ATH_CHECK(vertexContainer.recordNonConst(std::unique_ptr< xAOD::VertexContainer >(HggPV.first),
125  std::unique_ptr< xAOD::ShallowAuxContainer >(HggPV.second)));
126 
127 
128  static const SG::Accessor<float> vertexScoreAcc("vertexScore");
129  static const SG::Accessor<int> vertexFailTypeAcc("vertexFailType");
130  static const SG::Accessor<int> vertexCaseAcc("vertexCase");
131  static const SG::Accessor<phlink_t> leadingPhotonLinkAcc("leadingPhotonLink");
132  static const SG::Accessor<phlink_t> subleadingPhotonLinkAcc("subleadingPhotonLink");
133 
134  if (newPV) {
135  //loop over vertex container; shallow copy has the same order
136  for (unsigned int iPV=0; iPV<PV->size(); iPV++) {
137  const auto *vx = PV->at(iPV);
138  auto yyvx = (HggPV.first)->at(iPV);
139  //reset vertex type
140  if (vx == newPV) {
141  //is this the diphoton primary vertex returned from the tool?
142  yyvx->setVertexType( xAOD::VxType::PriVtx );
143  } else if ( vx->vertexType()==xAOD::VxType::PriVtx || vx->vertexType()==xAOD::VxType::PileUp ) {
144  //not overriding the type of dummy vertices of type 0 (NoVtx)
145  yyvx->setVertexType( xAOD::VxType::PileUp );
146  }
147  //decorate score
148  for (const auto& vxR: vxResult) {
149  //find vertex in output from photonVertexSelectionTool
150  if ( vx == vxR.first ) {
151  vertexScoreAcc(*yyvx) = vxR.second;
152  vertexFailTypeAcc(*yyvx) = vertexFailType;
153  vertexCaseAcc(*yyvx) = yyvertexVtxType;
154  leadingPhotonLinkAcc(*yyvx) = phlink_t(*photons, ph1->index());
155  subleadingPhotonLinkAcc(*yyvx) = phlink_t(*photons, ph2->index());
156  break;
157  }
158  }
159  }
160  }
161  else {
162  //no vertex returned by photonVertexSelectionTool, decorate default PV with fit information
164  xAOD::VertexContainer::iterator yyvx_end = (HggPV.first)->end();
165  for(yyvx_itr = (HggPV.first)->begin(); yyvx_itr != yyvx_end; ++yyvx_itr ) {
166  if ( (*yyvx_itr)->vertexType()==xAOD::VxType::PriVtx ) {
167  vertexScoreAcc(**yyvx_itr) = -9999;
168  vertexFailTypeAcc(**yyvx_itr) = vertexFailType;
169  vertexCaseAcc(**yyvx_itr) = yyvertexVtxType;
170  leadingPhotonLinkAcc(**yyvx_itr) = (phlink_t()) ;
171  subleadingPhotonLinkAcc(**yyvx_itr) = (phlink_t());
172  }
173  }
174  }
175 
176 
177  if( !evtStore()->transientContains< xAOD::VertexContainer >( m_diphotonVertexKey.key() ) ){
178  ATH_MSG_WARNING("Unable to find transient xAOD::VertexContainer, \"" << m_diphotonVertexKey.key() << "\"");
179  }
180 
181  return StatusCode::SUCCESS;
182 }
183 
185 {
186 
187  if (!ph) return false;
188 
189  if (!ph->isGoodOQ(34214)) return false;
190 
191  bool val(false);
192  bool defined(false);
193 
194  static const SG::ConstAccessor<char> DFCommonPhotonsIsEMLooseAcc("DFCommonPhotonsIsEMLoose");
195  if(DFCommonPhotonsIsEMLooseAcc.isAvailable(*ph)){
196  defined = true;
197  val = static_cast<bool>(DFCommonPhotonsIsEMLooseAcc(*ph));
198  }
199  else{
200  defined = ph->passSelection(val, "Loose");
201  }
202 
203  if(!defined || !val) return false;
204 
205  // veto topo-seeded clusters
206  if (ph->author(xAOD::EgammaParameters::AuthorCaloTopo35)) return false;
207 
208  // Check which variable versions are best...
209  const xAOD::CaloCluster *caloCluster(ph->caloCluster());
210  double eta = std::abs(caloCluster->etaBE(2));
211 
212  if (eta > m_maxEta) return false;
213  if (m_removeCrack && 1.37 <= eta && eta <= 1.52) return false;
214 
215  if (ph->pt() < m_minPhotonPt) return false;
216 
217  return true;
218 
219 }
220 
222  const xAOD::IParticle* swclus = eg->caloCluster();
223 
224  // Preselect FEs based on proximity: dR<0.4
225  std::vector<const xAOD::FlowElement*> nearbyFE;
226  nearbyFE.reserve(20);
227  for(const auto *const fe : *feCont) {
228  if(xAOD::P4Helpers::isInDeltaR(*fe, *swclus, 0.4, true)) {
229  if( ( !fe->isCharged() && fe->e() > FLT_MIN )) nearbyFE.push_back(fe);
230  } // DeltaR check
231  } // FE loop
232 
233  SG::Decorator<char> passORDec("passOR");
234 
235  double eg_cl_e = swclus->e();
236  bool doSum = true;
237  double sumE_fe = 0.;
238  const xAOD::IParticle* bestbadmatch = nullptr;
239  std::sort(nearbyFE.begin(),nearbyFE.end(),greaterPtFlowElement);
240  for(const auto& fe : nearbyFE) {
241  if(!xAOD::P4Helpers::isInDeltaR(*fe, *swclus, m_tcMatch_dR, true)) {continue;}
242  // Handle neutral FEs like topoclusters
243  double fe_e = fe->e();
244  // skip cluster if it's above our bad match threshold or outside the matching radius
245  if(fe_e>m_tcMatch_maxRat*eg_cl_e) {
246  ATH_MSG_VERBOSE("Reject topocluster in sum. Ratio vs eg cluster: " << (fe_e/eg_cl_e));
247  if( !bestbadmatch || (std::abs(fe_e/eg_cl_e-1.) < std::abs(bestbadmatch->e()/eg_cl_e-1.)) ) bestbadmatch = fe;
248  continue;
249  }
250 
251  ATH_MSG_VERBOSE("E match with new nFE: " << std::abs(sumE_fe+fe_e - eg_cl_e) / eg_cl_e);
252  if( (doSum = std::abs(sumE_fe+fe_e-eg_cl_e) < std::abs(sumE_fe - eg_cl_e)) ) {
253  passORDec(*fe) = false;
254  sumE_fe += fe_e;
255  } // if we will retain the topocluster
256  else {break;}
257  } // loop over nearby clusters
258  if(sumE_fe<FLT_MIN && bestbadmatch) {
259  passORDec(*bestbadmatch) = false;
260  }
261 
262  return StatusCode::SUCCESS;
263 }
ShallowCopy.h
GeV
#define GeV
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/Root/HelperFunctions.cxx:18
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:67
xAODP4Helpers.h
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:184
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:92
DerivationFramework::DiphotonVertexDecorator::~DiphotonVertexDecorator
~DiphotonVertexDecorator()
Destructor.
Definition: DiphotonVertexDecorator.cxx:46
xAOD::CaloCluster_v1::etaBE
float etaBE(const unsigned layer) const
Get the eta in one layer of the EM Calo.
Definition: CaloCluster_v1.cxx:628
xAOD::CaloCluster_v1
Description of a calorimeter cluster.
Definition: CaloCluster_v1.h:62
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
DerivationFramework::DiphotonVertexDecorator::initialize
StatusCode initialize()
Definition: DiphotonVertexDecorator.cxx:50
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:729
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:221
DerivationFramework::DiphotonVertexDecorator::addBranches
virtual StatusCode addBranches() const
Definition: DiphotonVertexDecorator.cxx:65
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:572
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:794
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:574
phlink_t
ElementLink< xAOD::PhotonContainer > phlink_t
Definition: DiphotonVertexDecorator.cxx:26
DerivationFramework::DiphotonVertexDecorator::finalize
StatusCode finalize()
Definition: DiphotonVertexDecorator.cxx:60
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:73
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
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