35 return StatusCode::SUCCESS;
42 if (! ChargedPFlowObjects.
isValid()){
44 return StatusCode::FAILURE;
48 if (! NeutralPFlowObjects.
isValid()){
50 return StatusCode::FAILURE;
54 if (!chargedFE_ElectronLinks.isValid()){
55 ATH_MSG_ERROR(
"Can't retrieve input decoration " << chargedFE_ElectronLinks.key());
56 return StatusCode::FAILURE;
60 if (!chargedFE_MuonLinks.isValid()){
61 ATH_MSG_ERROR(
"Can't retrieve input decoration "<< chargedFE_MuonLinks.key());
62 return StatusCode::FAILURE;
66 if (!neutralFE_ElectronLinks.isValid()){
67 ATH_MSG_ERROR(
"Can't retrieve input decoration "<< neutralFE_ElectronLinks.key());
68 return StatusCode::FAILURE;
72 if (!neutralFE_MuonLinks.isValid()){
73 ATH_MSG_ERROR(
"Can't retrieve input decoration "<< neutralFE_MuonLinks.key());
74 return StatusCode::FAILURE;
77 auto selectedChargedPFlowObjects = std::make_unique<xAOD::FlowElementContainer>();
78 auto selectedChargedPFlowObjectsAux = std::make_unique<xAOD::FlowElementAuxContainer>();
79 selectedChargedPFlowObjects->setStore(selectedChargedPFlowObjectsAux.get());
81 auto selectedNeutralPFlowObjects = std::make_unique<xAOD::FlowElementContainer>();
82 auto selectedNeutralPFlowObjectsAux = std::make_unique<xAOD::FlowElementAuxContainer>();
83 selectedNeutralPFlowObjects->setStore(selectedNeutralPFlowObjectsAux.get());
86 std::vector< const xAOD::FlowElement* > ChargedPFlowObjects_matched;
94 selectedChargedPFlowObjects->push_back(selectedFE);
98 ChargedPFlowObjects_matched.push_back(fe);
113 selectedNeutralPFlowObjects->push_back(selectedFE);
120 double totalMuonCaloEnergy = 0.0;
121 for (
auto energy : clusterMuonEnergyFracs(*fe) ) totalMuonCaloEnergy +=
energy;
122 TLorentzVector newP4;
123 newP4.SetPxPyPzE(fe->p4().Px(),fe->p4().Py(),fe->p4().Pz(),fe->e() - totalMuonCaloEnergy);
124 selectedFE->
setP4(newP4);
135 std::vector<std::pair<const xAOD::IParticle*,float> > theOtherPairs_charged = chargedFE->otherObjectsAndWeights();
136 std::vector<ElementLink<xAOD::IParticleContainer>> theOtherLinks_charged = chargedFE->otherObjectLinks();
139 for (
unsigned int iCluster = 0; iCluster < chargedFE->nOtherObjects(); ++iCluster){
141 bool thisCluster_matched =
false;
143 std::pair<const xAOD::IParticle*,float> theOtherPair_charged = theOtherPairs_charged[iCluster];
144 const xAOD::IParticle* theCluster_charged = theOtherPair_charged.first;
145 float theClusterWeight_charged = theOtherPair_charged.second;
149 if (thisCluster_matched)
continue;
152 std::vector<std::pair<const xAOD::IParticle*,float> > theOtherPairs_neutral = neutralFE->otherObjectsAndWeights();
153 for (
auto& [theCluster_neutral, theClusterWeight_neutral] : theOtherPairs_neutral){
156 if (theCluster_charged == theCluster_neutral){
159 float newEnergy = neutralFE->
e() + theClusterWeight_charged;
160 neutralFE->setP4(newEnergy/cosh(neutralFE->eta()),
165 ATH_MSG_DEBUG(
"Updated neutral FlowElement with E, pt, eta and phi: "
166 << neutralFE->e() <<
", " << neutralFE->pt() <<
", "
167 << neutralFE->eta() <<
" and " << neutralFE->phi());
169 thisCluster_matched =
true;
177 if ( !thisCluster_matched && theCluster_charged ){
180 bool belongsToElectron =
false;
184 unsigned int chargedClusterIndex = theCluster_charged->
index();
187 if (!electronReadHandle.
isValid()){
189 return StatusCode::FAILURE;
192 for (
auto thisElectron : *electronReadHandle){
194 for (
auto thisElectronTopoCluster : electronTopoClusters){
195 if (thisElectronTopoCluster->index() == chargedClusterIndex){
196 belongsToElectron =
true;
203 if (belongsToElectron)
continue;
205 bool belongsToMuon =
false;
206 double muonCaloEnergy = 0.0;
209 std::vector<double> muonCaloEnergies = chargedFE_energy_match_muonReadHandle(*chargedFE);
210 muonCaloEnergy = muonCaloEnergies[iCluster];
213 if (belongsToMuon)
continue;
216 selectedNeutralPFlowObjects->push_back(newFE);
218 newFE->
setP4((theClusterWeight_charged - muonCaloEnergy) / cosh(theCluster_charged->
eta()),
219 theCluster_charged->
eta(),
220 theCluster_charged->
phi(),
221 theCluster_charged->
m());
223 newFE->
setSignalType(xAOD::FlowElement::SignalType::NeutralPFlow);
225 ATH_MSG_DEBUG(
"Created neutral FlowElement with E, pt, eta and phi: "
226 << newFE->
e() <<
", " << newFE->
pt() <<
", "
227 << newFE->
eta() <<
" and " << newFE->
phi());
229 std::vector<ElementLink<xAOD::IParticleContainer>> theClusters;
231 theIParticleLink.
resetWithKeyAndIndex(theOtherLinks_charged[iCluster].persKey(), theOtherLinks_charged[iCluster].persIndex());
233 theClusters.push_back(theIParticleLink);
245 accFloatTIle0E(*newFE) = layerEnergy_TileBar0 + layerEnergy_TileExt0;
248 accFloatTiming(*newFE) = castCluster_charged->
time();
256 if (!handle_ChargedPFlow_out.record(std::move(selectedChargedPFlowObjects), std::move(selectedChargedPFlowObjectsAux)) ){
258 return StatusCode::FAILURE;
262 if (!handle_NeutralPFlow_out.record(std::move(selectedNeutralPFlowObjects), std::move(selectedNeutralPFlowObjectsAux)) ){
264 return StatusCode::FAILURE;
267 return StatusCode::SUCCESS;
275 ATH_MSG_WARNING(
"JetPFlowSelectionAlg encountered an invalid electron element link. Skipping. ");
280 bool passElectronID =
false;
287 if(
electron->pt() > 10000 && passElectronID){
300 ATH_MSG_WARNING(
"JetPFlowSelectionAlg encountered an invalid muon element link. Skipping. ");