ATLAS Offline Software
JetPFlowSelectionAlg.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
9 
12 
13 #include "xAODEgamma/Electron.h"
15 #include "xAODMuon/Muon.h"
16 #include "xAODPFlow/FlowElement.h"
18 #include "xAODPFlow/FEHelpers.h"
19 
21  ATH_MSG_DEBUG("Initializing " );
22 
27  }
36 
37 
38  return StatusCode::SUCCESS;
39 }
40 
41 StatusCode JetPFlowSelectionAlg::execute(const EventContext& ctx) const {
42  ATH_MSG_DEBUG(" execute() ... ");
43 
45  if (! ChargedPFlowObjects.isValid()){
46  ATH_MSG_ERROR("Can't retrieve input container "<< m_ChargedPFlowContainerKey);
47  return StatusCode::FAILURE;
48  }
49 
51  if (! NeutralPFlowObjects.isValid()){
52  ATH_MSG_ERROR("Can't retrieve input container "<< m_NeutralPFlowContainerKey);
53  return StatusCode::FAILURE;
54  }
55 
57  if (!chargedFE_ElectronLinks.isValid()){
58  ATH_MSG_ERROR("Can't retrieve input decoration " << chargedFE_ElectronLinks.key());
59  return StatusCode::FAILURE;
60  }
61 
63  if (!chargedFE_MuonLinks.isValid()){
64  ATH_MSG_ERROR("Can't retrieve input decoration "<< chargedFE_MuonLinks.key());
65  return StatusCode::FAILURE;
66  }
67 
69  if (!neutralFE_ElectronLinks.isValid()){
70  ATH_MSG_ERROR("Can't retrieve input decoration "<< neutralFE_ElectronLinks.key());
71  return StatusCode::FAILURE;
72  }
73 
75  if (!neutralFE_MuonLinks.isValid()){
76  ATH_MSG_ERROR("Can't retrieve input decoration "<< neutralFE_MuonLinks.key());
77  return StatusCode::FAILURE;
78  }
79 
80  auto selectedChargedPFlowObjects = std::make_unique<xAOD::FlowElementContainer>(); // SG::VIEW_ELEMENTS
81  auto selectedChargedPFlowObjectsAux = std::make_unique<xAOD::FlowElementAuxContainer>();
82  selectedChargedPFlowObjects->setStore(selectedChargedPFlowObjectsAux.get());
83 
84  auto selectedNeutralPFlowObjects = std::make_unique<xAOD::FlowElementContainer>();
85  auto selectedNeutralPFlowObjectsAux = std::make_unique<xAOD::FlowElementAuxContainer>();
86  selectedNeutralPFlowObjects->setStore(selectedNeutralPFlowObjectsAux.get());
87 
88  // To store the charged FE objects matched to an electron/muon
89  std::vector< const xAOD::FlowElement* > ChargedPFlowObjects_matched;
90 
91  FEMuonHelper muonHelper;
92  FEElectronHelper electronHelper;
93 
94  // Loop over Charged FE objects
95  for ( const xAOD::FlowElement* fe : *ChargedPFlowObjects ) {
96 
97  // Select FE object if not matched to an electron or muon via links
98  if ( !electronHelper.checkElectronLinks(chargedFE_ElectronLinks(*fe),m_electronID) && !muonHelper.checkMuonLinks(chargedFE_MuonLinks(*fe),m_muonID) ){
99  xAOD::FlowElement* selectedFE = new xAOD::FlowElement();
100  selectedChargedPFlowObjects->push_back(selectedFE);
101  *selectedFE = *fe; // copies auxdata
102  }
103  else { // Use the matched object to put back its energy later
104  ChargedPFlowObjects_matched.push_back(fe);
105  }
106 
107  } // End loop over Charged FE Objects
108 
109 
110  // Loop over Neutral FE objects
111  for ( const xAOD::FlowElement* fe : *NeutralPFlowObjects ) {
112 
113  //if links to an electron, then we veto entire neutral FE
115  if (electronHelper.checkElectronLinks(neutralFE_ElectronLinks(*fe),m_electronID)) continue;
116  }
117 
118  xAOD::FlowElement* selectedFE = new xAOD::FlowElement();
119  selectedNeutralPFlowObjects->push_back(selectedFE);
120  *selectedFE = *fe;
121 
122  //if links to a muon, then we need to subtract off the muon energy in
123  //this calorimeter cluster
124 
125  if (m_removeNeutralMuonFE && muonHelper.checkMuonLinks(neutralFE_MuonLinks(*fe),m_muonID)){
127  selectedFE->setP4(muonHelper.adjustNeutralCaloEnergy(clusterMuonEnergyFracs(*fe),*fe));
128  }
129 
130 
131  } // End loop over Neutral FE Objects
132 
133  // Add the energy from removed charged FE clusters to neutral FE object
134  // if shared clusters exist, create the new neutral FE object otherwise
135  for ( const xAOD::FlowElement* chargedFE : ChargedPFlowObjects_matched ){
136 
137  // Get charged FE topoclusters and weights
138  std::vector<std::pair<const xAOD::IParticle*,float> > theOtherPairs_charged = chargedFE->otherObjectsAndWeights();
139  std::vector<ElementLink<xAOD::IParticleContainer>> theOtherLinks_charged = chargedFE->otherObjectLinks();
140 
141  // Loop over charged FE topoclusters
142  for (unsigned int iCluster = 0; iCluster < chargedFE->nOtherObjects(); ++iCluster){
143 
144  bool thisCluster_matched = false;
145 
146  std::pair<const xAOD::IParticle*,float> theOtherPair_charged = theOtherPairs_charged[iCluster];
147  const xAOD::IParticle* theCluster_charged = theOtherPair_charged.first;
148  float theClusterWeight_charged = theOtherPair_charged.second;
149 
150  // Loop over neutral FE objects
151  for ( xAOD::FlowElement* neutralFE : *selectedNeutralPFlowObjects ) {
152  if (thisCluster_matched) continue;
153 
154  // Loop over neutral FE topoclusters
155  std::vector<std::pair<const xAOD::IParticle*,float> > theOtherPairs_neutral = neutralFE->otherObjectsAndWeights();
156  for (auto& [theCluster_neutral, theClusterWeight_neutral] : theOtherPairs_neutral){
157 
158  // If topoclusters are matched, add the energy to the neutral FE object
159  if (theCluster_charged == theCluster_neutral){
160 
161  // Add the energy to the neutral FE object
162  float newEnergy = neutralFE->e() + theClusterWeight_charged;
163  neutralFE->setP4(newEnergy/cosh(neutralFE->eta()),
164  neutralFE->eta(),
165  neutralFE->phi(),
166  neutralFE->m());
167 
168  ATH_MSG_DEBUG("Updated neutral FlowElement with E, pt, eta and phi: "
169  << neutralFE->e() << ", " << neutralFE->pt() << ", "
170  << neutralFE->eta() << " and " << neutralFE->phi());
171 
172  thisCluster_matched = true;
173  }
174 
175  } // End loop over neutral FE clusters
176  } // End loop over neutral FE objects
177 
178  // If a topocluster is left unmatched, create a neutral FE object.
179  // Ignore topoclusters with nullptr
180  if ( !thisCluster_matched && theCluster_charged ){
181 
182  //check if charged cluster belongs to an electron, before we put it back as neutral
183  bool belongsToElectron = false;
185 
186  //get container index of charged cluster and compare to indices of electron topoclusters
187  unsigned int chargedClusterIndex = theCluster_charged->index();
188 
190  if (!electronReadHandle.isValid()){
191  ATH_MSG_ERROR("Can't retrieve electron container "<< m_electronContainerKey.key());
192  return StatusCode::FAILURE;
193  }
194 
195  for (auto thisElectron : *electronReadHandle){
196  const std::vector<const xAOD::CaloCluster*> electronTopoClusters = xAOD::EgammaHelpers::getAssociatedTopoClusters(thisElectron->caloCluster());
197  for (auto thisElectronTopoCluster : electronTopoClusters){
198  if (thisElectronTopoCluster->index() == chargedClusterIndex){
199  belongsToElectron = true;
200  break;
201  }
202  }
203  }
204  }
205 
206  if (belongsToElectron) continue;
207 
208  bool belongsToMuon = false;
209  double muonCaloEnergy = 0.0;
210  if (m_removeNeutralMuonFE){
212  std::vector<double> muonCaloEnergies = chargedFE_energy_match_muonReadHandle(*chargedFE);
213  muonCaloEnergy = muonCaloEnergies[iCluster];
214  }
215 
216  if (belongsToMuon) continue;
217 
218  xAOD::FlowElement* newFE = new xAOD::FlowElement();
219  selectedNeutralPFlowObjects->push_back(newFE);
220 
221  newFE->setP4((theClusterWeight_charged - muonCaloEnergy) / cosh(theCluster_charged->eta()), // using energy from charged FE weight, not cluster->e()
222  theCluster_charged->eta(),
223  theCluster_charged->phi(),
224  theCluster_charged->m());
225  newFE->setCharge(0);
226  newFE->setSignalType(xAOD::FlowElement::SignalType::NeutralPFlow);
227 
228  ATH_MSG_DEBUG("Created neutral FlowElement with E, pt, eta and phi: "
229  << newFE->e() << ", " << newFE->pt() << ", "
230  << newFE->eta() << " and " << newFE->phi());
231 
232  std::vector<ElementLink<xAOD::IParticleContainer>> theClusters;
234  theIParticleLink.resetWithKeyAndIndex(theOtherLinks_charged[iCluster].persKey(), theOtherLinks_charged[iCluster].persIndex());
235 
236  theClusters.push_back(theIParticleLink);
237  newFE->setOtherObjectLinks(theClusters);
238 
239  //Add Standard data to these new FlowElements
241  const xAOD::CaloCluster* castCluster_charged = dynamic_cast<const xAOD::CaloCluster*>(theCluster_charged);
242  FEFiller.addStandardMoments(*newFE,*castCluster_charged);
243  FEFiller.addStandardSamplingEnergies(*newFE,*castCluster_charged);
244 
245  float layerEnergy_TileBar0 = castCluster_charged->eSample(xAOD::CaloCluster::CaloSample::TileBar0);
246  float layerEnergy_TileExt0 = castCluster_charged->eSample(xAOD::CaloCluster::CaloSample::TileExt0);
247  const static SG::AuxElement::Accessor<float> accFloatTIle0E("LAYERENERGY_TILE0");
248  accFloatTIle0E(*newFE) = layerEnergy_TileBar0 + layerEnergy_TileExt0;
249 
250  const static SG::AuxElement::Accessor<float> accFloatTiming("TIMING");
251  accFloatTiming(*newFE) = castCluster_charged->time();
252  }
253 
254  } // End loop over topoclusters of removed charged FE objects
255  } // End loop over removed charged FE objects
256 
257 
258  auto handle_ChargedPFlow_out = SG::makeHandle(m_outputChargedPFlowHandleKey, ctx);
259  if (!handle_ChargedPFlow_out.record(std::move(selectedChargedPFlowObjects), std::move(selectedChargedPFlowObjectsAux)) ){
260  ATH_MSG_ERROR("Can't record output PFlow container "<< m_outputChargedPFlowHandleKey);
261  return StatusCode::FAILURE;
262  }
263 
264  auto handle_NeutralPFlow_out = SG::makeHandle(m_outputNeutralPFlowHandleKey, ctx);
265  if (!handle_NeutralPFlow_out.record(std::move(selectedNeutralPFlowObjects), std::move(selectedNeutralPFlowObjectsAux)) ){
266  ATH_MSG_ERROR("Can't record output PFlow container "<< m_outputNeutralPFlowHandleKey);
267  return StatusCode::FAILURE;
268  }
269 
270  return StatusCode::SUCCESS;
271 }
FEMuonHelper::adjustNeutralCaloEnergy
TLorentzVector adjustNeutralCaloEnergy(const std::vector< double > &clusterMuonEnergyFracs, const xAOD::FlowElement &theFE) const
Definition: FEMuonHelper.cxx:30
WriteHandle.h
Handle class for recording to StoreGate.
xAOD::CaloCluster_v1::time
flt_t time() const
Access cluster time.
FEHelpers::FillNeutralFlowElements::addStandardSamplingEnergies
void addStandardSamplingEnergies(xAOD::FlowElement &theFE, const xAOD::CaloCluster &theCluster)
Definition: FEHelpers.cxx:246
JetPFlowSelectionAlg::m_chargedFE_energy_match_muonReadHandleKey
SG::ReadDecorHandleKey< xAOD::FlowElementContainer > m_chargedFE_energy_match_muonReadHandleKey
Definition: JetPFlowSelectionAlg.h:61
xAOD::EgammaHelpers::getAssociatedTopoClusters
std::vector< const xAOD::CaloCluster * > getAssociatedTopoClusters(const xAOD::CaloCluster *cluster)
Return a vector of all the topo clusters associated with the egamma cluster.
Definition: EgammaxAODHelpers.cxx:65
FEMuonHelper.h
FEHelpers::FillNeutralFlowElements::addStandardMoments
void addStandardMoments(xAOD::FlowElement &theFE, const xAOD::CaloCluster &theCluster)
Definition: FEHelpers.cxx:213
JetPFlowSelectionAlg::m_chargedFEElectronsReadDecorKey
SG::ReadDecorHandleKey< xAOD::FlowElementContainer > m_chargedFEElectronsReadDecorKey
Definition: JetPFlowSelectionAlg.h:51
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:68
Muon.h
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
CaloCell_ID_FCS::TileExt0
@ TileExt0
Definition: FastCaloSim_CaloCell_ID.h:37
xAOD::FlowElement_v1::setSignalType
void setSignalType(signal_t t)
JetPFlowSelectionAlg::m_electronContainerKey
SG::ReadHandleKey< xAOD::ElectronContainer > m_electronContainerKey
Definition: JetPFlowSelectionAlg.h:45
JetPFlowSelectionAlg::m_outputNeutralPFlowHandleKey
SG::WriteHandleKey< xAOD::FlowElementContainer > m_outputNeutralPFlowHandleKey
Definition: JetPFlowSelectionAlg.h:49
JetPFlowSelectionAlg::m_removeNeutralMuonFE
Gaudi::Property< bool > m_removeNeutralMuonFE
Definition: JetPFlowSelectionAlg.h:41
JetPFlowSelectionAlg::m_ChargedPFlowContainerKey
SG::ReadHandleKey< xAOD::FlowElementContainer > m_ChargedPFlowContainerKey
Definition: JetPFlowSelectionAlg.h:43
xAOD::FlowElement_v1::phi
virtual double phi() const override
The azimuthal angle ( ) of the particle.
xAOD::FlowElement_v1::pt
virtual double pt() const override
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
xAOD::FlowElement_v1::setOtherObjectLinks
void setOtherObjectLinks(const std::vector< ElementLink< IParticleContainer >> &elV)
SG::VarHandleKey::empty
bool empty() const
Test if the key is blank.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:150
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:41
JetPFlowSelectionAlg::m_chargedFEMuonsReadDecorKey
SG::ReadDecorHandleKey< xAOD::FlowElementContainer > m_chargedFEMuonsReadDecorKey
Definition: JetPFlowSelectionAlg.h:52
JetPFlowSelectionAlg::m_outputChargedPFlowHandleKey
SG::WriteHandleKey< xAOD::FlowElementContainer > m_outputChargedPFlowHandleKey
Definition: JetPFlowSelectionAlg.h:48
xAOD::FlowElement_v1::setCharge
void setCharge(float c)
JetPFlowSelectionAlg::m_NeutralPFlowContainerKey
SG::ReadHandleKey< xAOD::FlowElementContainer > m_NeutralPFlowContainerKey
Definition: JetPFlowSelectionAlg.h:44
FEHelpers::FillNeutralFlowElements
Definition: Event/xAOD/xAODPFlow/xAODPFlow/FEHelpers.h:27
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:270
xAOD::CaloCluster_v1
Description of a calorimeter cluster.
Definition: CaloCluster_v1.h:59
EgammaxAODHelpers.h
JetPFlowSelectionAlg::m_removeNeutralElectronFE
Gaudi::Property< bool > m_removeNeutralElectronFE
Definition: JetPFlowSelectionAlg.h:38
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
FlowElementAuxContainer.h
SG::ReadDecorHandle
Handle class for reading a decoration on an object.
Definition: StoreGate/StoreGate/ReadDecorHandle.h:94
FlowElement.h
CaloCell_ID_FCS::TileBar0
@ TileBar0
Definition: FastCaloSim_CaloCell_ID.h:31
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
xAOD::FlowElement
FlowElement_v1 FlowElement
Definition of the current "pfo version".
Definition: FlowElement.h:16
JetPFlowSelectionAlg::m_muonID
Gaudi::Property< std::string > m_muonID
Definition: JetPFlowSelectionAlg.h:40
JetPFlowSelectionAlg::execute
StatusCode execute(const EventContext &ctx) const override
Definition: JetPFlowSelectionAlg.cxx:41
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
SG::AuxElement::index
size_t index() const
Return the index of this element within its container.
FEMuonHelper
Definition: Reconstruction/PFlow/PFlowUtils/PFlowUtils/FEMuonHelper.h:8
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
JetPFlowSelectionAlg::m_neutralFEMuonsReadDecorKey
SG::ReadDecorHandleKey< xAOD::FlowElementContainer > m_neutralFEMuonsReadDecorKey
Definition: JetPFlowSelectionAlg.h:56
FEElectronHelper::checkElectronLinks
bool checkElectronLinks(const std::vector< ElementLink< xAOD::ElectronContainer > > &FE_ElectronLinks, const std::string &qualityString) const
Definition: FEElectronHelper.cxx:5
JetPFlowSelectionAlg::m_neutralFEMuons_efrac_match_DecorKey
SG::ReadDecorHandleKey< xAOD::FlowElementContainer > m_neutralFEMuons_efrac_match_DecorKey
Definition: JetPFlowSelectionAlg.h:59
FEHelpers.h
ReadHandle.h
Handle class for reading from StoreGate.
xAOD::FlowElement_v1::e
virtual double e() const override
The total energy of the particle.
Definition: FlowElement_v1.cxx:25
JetPFlowSelectionAlg::m_neutralFEElectronsReadDecorKey
SG::ReadDecorHandleKey< xAOD::FlowElementContainer > m_neutralFEElectronsReadDecorKey
Definition: JetPFlowSelectionAlg.h:54
xAOD::FlowElement_v1::eta
virtual double eta() const override
The pseudorapidity ( ) of the particle.
xAOD::CaloCluster_v1::eSample
float eSample(const CaloSample sampling) const
Definition: CaloCluster_v1.cxx:521
FEElectronHelper
Definition: FEElectronHelper.h:7
FEMuonHelper::checkMuonLinks
bool checkMuonLinks(const std::vector< ElementLink< xAOD::MuonContainer > > &FE_MuonLinks, const std::string &qualityString) const
Verify if at least one combined muon in a list passes the relevant quality criteria Details of muon w...
Definition: FEMuonHelper.cxx:5
xAOD::IParticle::eta
virtual double eta() const =0
The pseudorapidity ( ) of the particle.
ReadDecorHandle.h
Handle class for reading a decoration on an object.
xAOD::FlowElement_v1::setP4
void setP4(float pt, float eta, float phi, float m)
Definition: FlowElement_v1.cxx:39
Electron.h
xAOD::IParticle::phi
virtual double phi() const =0
The azimuthal angle ( ) of the particle.
FEElectronHelper.h
JetPFlowSelectionAlg.h
JetPFlowSelectionAlg::m_electronID
Gaudi::Property< std::string > m_electronID
Definition: JetPFlowSelectionAlg.h:37
JetPFlowSelectionAlg::initialize
StatusCode initialize() override
Athena algorithm's Hooks.
Definition: JetPFlowSelectionAlg.cxx:20
xAOD::IParticle::e
virtual double e() const =0
The total energy of the particle.
xAOD::IParticle::m
virtual double m() const =0
The invariant mass of the particle.
xAOD::FlowElement_v1
A detector object made of other lower level object(s)
Definition: FlowElement_v1.h:25