From 218ae794fedad5af06c74b24f76743fcf4919b24 Mon Sep 17 00:00:00 2001
From: Bill Balunas <bill.balunas@cern.ch>
Date: Mon, 29 Mar 2021 18:21:50 +0200
Subject: [PATCH] Handle FlowElements correctly in MET overlaps

---
 Event/xAOD/xAODMissingET/CMakeLists.txt       |  2 +-
 .../Root/MissingETAssociationMap_v1.cxx       | 21 +++++++++++--------
 .../Root/MissingETAssociation_v1.cxx          | 20 +++++++++++-------
 .../versions/MissingETAssociation_v1.h        |  5 ++++-
 .../PFlow/PFlowUtils/PFlowUtils/FEHelpers.h   |  2 ++
 .../PFlow/PFlowUtils/Root/FEHelpers.cxx       | 10 +++++++++
 6 files changed, 41 insertions(+), 19 deletions(-)

diff --git a/Event/xAOD/xAODMissingET/CMakeLists.txt b/Event/xAOD/xAODMissingET/CMakeLists.txt
index ad1cfc648186..5565d62160e3 100644
--- a/Event/xAOD/xAODMissingET/CMakeLists.txt
+++ b/Event/xAOD/xAODMissingET/CMakeLists.txt
@@ -13,7 +13,7 @@ atlas_add_library( xAODMissingET
    Root/*.cxx
    PUBLIC_HEADERS xAODMissingET
    INCLUDE_DIRS ${Boost_INCLUDE_DIRS}
-   LINK_LIBRARIES AthContainers AthLinks xAODBase xAODCore xAODJet
+   LINK_LIBRARIES AthContainers AthLinks xAODBase xAODCore xAODJet PFlowUtilsLib
    PRIVATE_LINK_LIBRARIES xAODCaloEvent xAODTracking xAODTruth )
 
 atlas_add_xaod_smart_pointer_dicts(
diff --git a/Event/xAOD/xAODMissingET/Root/MissingETAssociationMap_v1.cxx b/Event/xAOD/xAODMissingET/Root/MissingETAssociationMap_v1.cxx
index dbdfe7254a2b..ec44742151cb 100644
--- a/Event/xAOD/xAODMissingET/Root/MissingETAssociationMap_v1.cxx
+++ b/Event/xAOD/xAODMissingET/Root/MissingETAssociationMap_v1.cxx
@@ -11,6 +11,8 @@
 #include "xAODBase/IParticleContainer.h"
 #include "xAODBase/ObjectType.h"
 
+#include "PFlowUtils/FEHelpers.h"
+
 #include <cstdio>
 #include <iterator>
 #include <utility>
@@ -212,26 +214,27 @@ const xAOD::IParticleContainer* MissingETAssociationMap_v1::getUniqueSignals(con
   MissingETBase::Types::const_signal_vector_t* uniques = new MissingETBase::Types::const_signal_vector_t(SG::VIEW_ELEMENTS);
   for(IParticleContainer::const_iterator iSig=signals->begin();
       iSig!=signals->end(); ++iSig) {
+    xAOD::Type::ObjectType objType = (*iSig)->type();
+    if(objType == xAOD::Type::FlowElement) objType = FEHelpers::signalToXAODType(static_cast<const xAOD::FlowElement&>(**iSig));
     switch(p) {
     case MissingETBase::UsageHandler::TrackCluster:      
-      if((*iSig)->type()==xAOD::Type::CaloCluster
-	 || (*iSig)->type()==xAOD::Type::TrackParticle) {break;}
+      if(objType==xAOD::Type::CaloCluster
+      || objType==xAOD::Type::TrackParticle) {break;}
       else {continue;}
     case MissingETBase::UsageHandler::OnlyCluster:
-      if((*iSig)->type()==xAOD::Type::CaloCluster) {break;}
+      if(objType==xAOD::Type::CaloCluster) {break;}
       else {continue;}
     case MissingETBase::UsageHandler::OnlyTrack:
-      if((*iSig)->type()==xAOD::Type::TrackParticle) {break;}
+      if(objType==xAOD::Type::TrackParticle) {break;}
       else {continue;}
     case MissingETBase::UsageHandler::ParticleFlow:
-      if((*iSig)->type()==xAOD::Type::ParticleFlow) {break;}
-      else if((*iSig)->type()==xAOD::Type::FlowElement && ((static_cast<const xAOD::FlowElement*>(*iSig))->signalType() & xAOD::FlowElement::PFlow)) {break;}
+      if(objType==xAOD::Type::ParticleFlow) {break;}
       else {continue;}
     case MissingETBase::UsageHandler::TruthParticle:
-      if((*iSig)->type()==xAOD::Type::TruthParticle) {break;}
+      if(objType==xAOD::Type::TruthParticle) {break;}
       else {continue;}
     case MissingETBase::UsageHandler::AllCalo:
-      if((*iSig)->type()!=xAOD::Type::TrackParticle) {break;}
+      if(objType!=xAOD::Type::TrackParticle) {break;}
       else {continue;}
     default: {continue;}
     }
@@ -261,7 +264,7 @@ const xAOD::IParticleContainer* MissingETAssociationMap_v1::getOverlapRemovedSig
 {
   MissingETBase::Types::const_signal_vector_t* uniques = new MissingETBase::Types::const_signal_vector_t(SG::VIEW_ELEMENTS);
   for(const auto *const sig : *signals) {
-    if(!MissingETAssociation_v1::testPolicy(sig->type(),p)) continue;
+    if(!MissingETAssociation_v1::testPolicy(*sig,p)) continue;
     
     size_t assocIndex = findIndexByJetConst(sig);
     if(assocIndex==MissingETBase::Numerical::invalidIndex()) {
diff --git a/Event/xAOD/xAODMissingET/Root/MissingETAssociation_v1.cxx b/Event/xAOD/xAODMissingET/Root/MissingETAssociation_v1.cxx
index b49bf85a97bf..9209496fd38a 100644
--- a/Event/xAOD/xAODMissingET/Root/MissingETAssociation_v1.cxx
+++ b/Event/xAOD/xAODMissingET/Root/MissingETAssociation_v1.cxx
@@ -8,6 +8,7 @@
 #include "xAODTruth/TruthParticle.h"
 #include "xAODPFlow/PFO.h"
 #include "xAODPFlow/FlowElement.h"
+#include "PFlowUtils/FEHelpers.h"
 
 #include <iterator>
 #include <cstdio>
@@ -698,6 +699,7 @@ namespace xAOD {
           if(mine == target) {
             if((*mine)->type()==xAOD::Type::TruthParticle) overlapTypes |= 1;
             else if((*mine)->type()==xAOD::Type::Other) overlapTypes |= 1 << xAOD::Type::NeutralParticle;
+            else if((*mine)->type()==xAOD::Type::FlowElement) overlapTypes |= 1 << FEHelpers::signalToXAODType(static_cast<const xAOD::FlowElement&>(**mine));
             else overlapTypes |= 1 << (*mine)->type();
           }
         }
@@ -731,8 +733,6 @@ namespace xAOD {
           else {continue;}
         case MissingETBase::UsageHandler::ParticleFlow:
           if(types[iOL] & 1<<xAOD::Type::ParticleFlow) {break;}
-          //TODO: Check with TJ that this is OK
-          if(types[iOL] & 1<<xAOD::Type::FlowElement) {break;}
           else {continue;}
         case MissingETBase::UsageHandler::TruthParticle:
           if(types[iOL] & 1) {break;}
@@ -814,7 +814,7 @@ namespace xAOD {
 
   bool MissingETAssociation_v1::checkUsage(const MissingETAssociationHelper& helper, const IParticle* pSig, MissingETBase::UsageHandler::Policy p) const
   {
-    if(MissingETAssociation_v1::testPolicy(pSig->type(),p)) {
+    if(MissingETAssociation_v1::testPolicy(*pSig,p)) {
       const IParticleContainer* pCont = static_cast<const IParticleContainer*>(pSig->container());
       MissingETBase::Types::objlink_t el(*pCont,pSig->index());
       for(size_t iObj=0; iObj<this->objectLinks().size(); ++iObj) {
@@ -869,19 +869,23 @@ namespace xAOD {
     m_objConstLinks.reserve(50);
   }
 
-  bool MissingETAssociation_v1::testPolicy(unsigned int type,MissingETBase::UsageHandler::Policy p) {
+  bool MissingETAssociation_v1::testPolicy(const xAOD::IParticle& part, MissingETBase::UsageHandler::Policy p) {
+    xAOD::Type::ObjectType objType = part.type();
+    if(objType == xAOD::Type::FlowElement) objType = FEHelpers::signalToXAODType(static_cast<const xAOD::FlowElement&>(part));
+    return testPolicy(objType, p);
+  }
+
+  bool MissingETAssociation_v1::testPolicy(xAOD::Type::ObjectType type, MissingETBase::UsageHandler::Policy p) {
     switch(p) {
     case MissingETBase::UsageHandler::TrackCluster:      
       return type==xAOD::Type::CaloCluster
-
-         || type==xAOD::Type::TrackParticle;
+          || type==xAOD::Type::TrackParticle;
     case MissingETBase::UsageHandler::OnlyCluster:
       return type==xAOD::Type::CaloCluster;
     case MissingETBase::UsageHandler::OnlyTrack:
       return type==xAOD::Type::TrackParticle;
     case MissingETBase::UsageHandler::ParticleFlow:
-      if(type==xAOD::Type::ParticleFlow) {return true;}
-      return type==xAOD::Type::FlowElement;
+      return type==xAOD::Type::ParticleFlow;
     case MissingETBase::UsageHandler::AllCalo:
       return type!=xAOD::Type::TrackParticle;
     default: break;
diff --git a/Event/xAOD/xAODMissingET/xAODMissingET/versions/MissingETAssociation_v1.h b/Event/xAOD/xAODMissingET/xAODMissingET/versions/MissingETAssociation_v1.h
index 858fc85a11ee..b7b0a2afc322 100644
--- a/Event/xAOD/xAODMissingET/xAODMissingET/versions/MissingETAssociation_v1.h
+++ b/Event/xAOD/xAODMissingET/xAODMissingET/versions/MissingETAssociation_v1.h
@@ -29,7 +29,7 @@ namespace xAOD
   {
   public:
 
-    static bool testPolicy(unsigned int type, MissingETBase::UsageHandler::Policy p);
+    static bool testPolicy(const xAOD::IParticle& part, MissingETBase::UsageHandler::Policy p);
 
     /*! @brief Vector sum of constituents for subtractive overlap removal */                                                                                                            
     class ConstVec
@@ -354,6 +354,9 @@ namespace xAOD
     /*!@}*/
 
   protected:
+
+    static bool testPolicy(xAOD::Type::ObjectType type, MissingETBase::UsageHandler::Policy p);
+
     /// Function initialising the object to work in standalone mode
     void createPrivateStore();
 
diff --git a/Reconstruction/PFlow/PFlowUtils/PFlowUtils/FEHelpers.h b/Reconstruction/PFlow/PFlowUtils/PFlowUtils/FEHelpers.h
index e9fff1b1f06e..72cd1d446382 100644
--- a/Reconstruction/PFlow/PFlowUtils/PFlowUtils/FEHelpers.h
+++ b/Reconstruction/PFlow/PFlowUtils/PFlowUtils/FEHelpers.h
@@ -22,6 +22,8 @@ namespace FEHelpers {
 
   std::string getClusterMomentName(xAOD::CaloCluster::MomentType momentType);
 
+  xAOD::Type::ObjectType signalToXAODType(const xAOD::FlowElement& fe);
+
 }
 
 #endif
\ No newline at end of file
diff --git a/Reconstruction/PFlow/PFlowUtils/Root/FEHelpers.cxx b/Reconstruction/PFlow/PFlowUtils/Root/FEHelpers.cxx
index 14c3286782b4..d7dbbb89ee76 100644
--- a/Reconstruction/PFlow/PFlowUtils/Root/FEHelpers.cxx
+++ b/Reconstruction/PFlow/PFlowUtils/Root/FEHelpers.cxx
@@ -171,4 +171,14 @@ namespace FEHelpers {
     }
   }
 
+  xAOD::Type::ObjectType signalToXAODType(const xAOD::FlowElement& fe){
+    xAOD::FlowElement::signal_t st = fe.signalType();
+    if(st & xAOD::FlowElement::PFlow)       return xAOD::Type::ParticleFlow;
+    if(st & xAOD::FlowElement::CaloCluster) return xAOD::Type::CaloCluster;
+    if(st & xAOD::FlowElement::Track)       return xAOD::Type::TrackParticle;
+    if(st & xAOD::FlowElement::Muon)        return xAOD::Type::Muon;
+    if(st & xAOD::FlowElement::TCC)         return xAOD::Type::TrackCaloCluster;
+    if(st & xAOD::FlowElement::UFO)         return xAOD::Type::TrackCaloCluster; // UFO doesn't have its own xAOD type
+    return xAOD::Type::Other;
+  }
 }
\ No newline at end of file
-- 
GitLab