From c3bc3e17e03fde7dfd075cef28f3b13fcf4bbfa9 Mon Sep 17 00:00:00 2001
From: Valentina Tudorache <valentina.tudorache@cern.ch>
Date: Thu, 18 Nov 2021 16:21:30 +0100
Subject: [PATCH] GeneratorFilters: Truth xAOD Generator Filter MultiElecMuTau

---
 .../xAODMultiElecMuTauFilter.h                |  34 +++++
 .../components/GeneratorFilters_entries.cxx   |   3 +
 .../src/xAODMultiElecMuTauFilter.cxx          | 121 ++++++++++++++++++
 3 files changed, 158 insertions(+)
 create mode 100644 Generators/GeneratorFilters/GeneratorFilters/xAODMultiElecMuTauFilter.h
 create mode 100644 Generators/GeneratorFilters/src/xAODMultiElecMuTauFilter.cxx

diff --git a/Generators/GeneratorFilters/GeneratorFilters/xAODMultiElecMuTauFilter.h b/Generators/GeneratorFilters/GeneratorFilters/xAODMultiElecMuTauFilter.h
new file mode 100644
index 00000000000..53c0916574b
--- /dev/null
+++ b/Generators/GeneratorFilters/GeneratorFilters/xAODMultiElecMuTauFilter.h
@@ -0,0 +1,34 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATORFILTERS_XAODMULTIELECMUTAUFILTER_H
+#define GENERATORFILTERS_XAODMULTIELECMUTAUFILTER_H
+
+#include "GeneratorModules/GenFilter.h"
+#include "xAODTruth/TruthEvent.h"
+#include "xAODTruth/TruthEventContainer.h"
+
+/// Select multiple charged leptons taking into account electrons, muons and taus (inc. hadronic decays).
+///
+///  The user can steer the maximum |eta| and minimum pt and there is a separate
+/// (visible) pt cut for hadronic taus.
+///
+/// @author Carl Gwilliam
+class xAODMultiElecMuTauFilter : public GenFilter {
+public:
+
+  xAODMultiElecMuTauFilter(const std::string& name, ISvcLocator* pSvcLocator);
+  virtual StatusCode filterEvent();
+
+private:
+
+  double m_minPt;
+  double m_maxEta;
+  double m_minVisPtHadTau;
+  int    m_NLeptons;
+  bool   m_incHadTau;
+  bool   m_TwoSameSignLightLeptonsOneHadTau;
+};
+
+#endif
diff --git a/Generators/GeneratorFilters/src/components/GeneratorFilters_entries.cxx b/Generators/GeneratorFilters/src/components/GeneratorFilters_entries.cxx
index 6cfc7578dea..8b618a6213a 100644
--- a/Generators/GeneratorFilters/src/components/GeneratorFilters_entries.cxx
+++ b/Generators/GeneratorFilters/src/components/GeneratorFilters_entries.cxx
@@ -20,6 +20,8 @@
 #include "GeneratorFilters/xAODDecayTimeFilter.h"
 #include "GeneratorFilters/xAODDecaysFinalStateFilter.h"
 #include "GeneratorFilters/xAODChargedTracksFilter.h"
+#include "GeneratorFilters/xAODMultiElecMuTauFilter.h"
+
 
 
 // slimmers for 22.6
@@ -138,6 +140,7 @@ DECLARE_COMPONENT( xAODDiLeptonMassFilter )
 DECLARE_COMPONENT( xAODDecayTimeFilter )
 DECLARE_COMPONENT( xAODDecaysFinalStateFilter )
 DECLARE_COMPONENT( xAODChargedTracksFilter )
+DECLARE_COMPONENT( xAODMultiElecMuTauFilter )
 
 
 //slimmers accepted for 22.6
diff --git a/Generators/GeneratorFilters/src/xAODMultiElecMuTauFilter.cxx b/Generators/GeneratorFilters/src/xAODMultiElecMuTauFilter.cxx
new file mode 100644
index 00000000000..023bd7d3684
--- /dev/null
+++ b/Generators/GeneratorFilters/src/xAODMultiElecMuTauFilter.cxx
@@ -0,0 +1,121 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeneratorFilters/xAODMultiElecMuTauFilter.h"
+#include "CLHEP/Vector/LorentzVector.h"
+
+
+xAODMultiElecMuTauFilter::xAODMultiElecMuTauFilter(const std::string& name, ISvcLocator* pSvcLocator)
+  : GenFilter(name,pSvcLocator)
+{
+declareProperty("MinPt",                             m_minPt                            = 5000. );
+declareProperty("MaxEta",                            m_maxEta                           = 10.0  );
+declareProperty("MinVisPtHadTau",                    m_minVisPtHadTau                   = 10000.);
+declareProperty("NLeptons",                          m_NLeptons                         = 4     );
+declareProperty("IncludeHadTaus",                    m_incHadTau                        = true  );
+declareProperty("TwoSameSignLightLeptonsOneHadTau",  m_TwoSameSignLightLeptonsOneHadTau = false );
+}
+
+
+StatusCode xAODMultiElecMuTauFilter::filterEvent() {
+  int numLeptons = 0;
+  int numLightLeptons = 0;
+  int numHadTaus = 0;
+  if (m_TwoSameSignLightLeptonsOneHadTau) {
+    if (m_NLeptons!=3) ATH_MSG_ERROR("TwoSameSignLightLeptonsOneHadTau request possible only for NLeptons = 3. Check your jobOptions.");
+  }
+  int charge1 = 0; 
+  int charge2 = 0; 
+
+  // Retrieve full TruthEvent container
+  const xAOD::TruthEventContainer *xTruthEventContainer;
+  if (evtStore()->retrieve(xTruthEventContainer, "TruthEvents").isFailure())
+  {
+    ATH_MSG_ERROR("No TruthEvents collection with name " << "TruthEvents" << " found in StoreGate!");
+    return StatusCode::FAILURE;
+  }
+
+  xAOD::TruthEventContainer::const_iterator itr;
+  for (itr = xTruthEventContainer->begin(); itr!=xTruthEventContainer->end(); ++itr) {
+    const xAOD::TruthEvent *genEvt = (*itr);
+    unsigned int nPart = genEvt->nTruthParticles();
+    for (unsigned int iPart = 0; iPart < nPart; ++iPart) {
+       const xAOD::TruthParticle* pitr =  genEvt->truthParticle(iPart);
+       if (pitr->status() == 1 && (std::abs(pitr->pdgId()) == 11 || std::abs(pitr->pdgId()) == 13)) {
+         if (pitr->pt() >= m_minPt && std::abs(pitr->eta()) <= m_maxEta) {
+           ATH_MSG_DEBUG("Found lepton with PDG ID = " << pitr->pdgId()
+                         << ", status = " <<  pitr->status()
+                         << ", pt = "     <<  pitr->pt()
+                         << ", eta = "    <<  pitr->eta());
+            numLeptons++;
+            numLightLeptons++;
+            if (numLightLeptons==1) { if (pitr->pdgId() < 0) { charge1 = -1; } else { charge1 = 1; } } 
+           if (numLightLeptons==2) { if (pitr->pdgId() < 0) { charge2 = -1; } else { charge2 = 1; } } 
+         }
+         continue;
+       }
+       //Look for Hadronic taus (leptonic ones will be saved by above) that have status!=3 and don't decay to another tau (FSR)
+       if (!m_incHadTau) continue;
+       const xAOD::TruthParticle *tau= nullptr;
+       const xAOD::TruthParticle *taunu= nullptr;
+       if (std::abs(pitr->pdgId()) != 15 || pitr->status() == 3) continue;
+         tau = pitr;
+         if(!tau->decayVtx()) continue;
+         // Loop over children and:
+         // 1. Find if it is hadronic (i.e. no decay lepton).
+         // 2. Veto tau -> tau (FSR)
+         // 3. Store the tau neutino to calculate the visible momentum
+         for (unsigned int iChild = 0; iChild < tau->decayVtx()->nOutgoingParticles(); ++iChild) {
+             const xAOD::TruthParticle* citr =  tau->decayVtx()->outgoingParticle(iChild);
+             //Ignore tau -> tau (FSR)
+             if (pitr->pdgId() == citr->pdgId()) {
+               ATH_MSG_DEBUG("FSR tau decay.  Ignoring!");
+               tau = nullptr;
+               break;
+           }
+             // Ignore leptonic decays
+             if (std::abs(citr->pdgId()) == 13 || std::abs(citr->pdgId()) == 11) {
+               tau = nullptr;
+               break;
+          }
+            // Find tau decay nu
+            if (std::abs(citr->pdgId()) == 16) {
+               taunu = citr;
+           }
+         }
+         if (tau) {
+           // Good hadronic decay
+           CLHEP::HepLorentzVector tauVisMom = CLHEP::HepLorentzVector(tau->px() - taunu->px(),
+                                                         tau->py() - taunu->py(),
+                                                         tau->pz() - taunu->pz(),
+                                                         tau->e()  - taunu->e());
+           if (tauVisMom.perp() >= m_minVisPtHadTau && std::abs(tauVisMom.eta()) <= m_maxEta) {
+             ATH_MSG_DEBUG("Found hadronic tau decay with PDG ID = " << tau->pdgId()
+                           << ", status = " << tau->status()
+                           << ", vis pt = " << tauVisMom.perp()
+                           << ", eta = " <<  tauVisMom.eta());
+             numLeptons++;
+             numHadTaus++;
+        
+           }
+       }
+    }
+  }
+
+ bool passed_event = false;
+  if (m_TwoSameSignLightLeptonsOneHadTau) {
+    if ( ((numLightLeptons+numHadTaus)==numLeptons) && numLightLeptons == 2 && numHadTaus == 1 && charge1==charge2 ) {
+      ATH_MSG_INFO("Found " << numLeptons << " Leptons: two same sign ligh leptons + one hadronic tau! Event passed.");
+      passed_event = true;
+    }
+  } else {
+    if ( numLeptons >= m_NLeptons ) {
+      ATH_MSG_INFO("Found " << numLeptons << "Leptons. Event passed.");
+      passed_event = true;
+    }
+  }
+  setFilterPassed(passed_event);
+
+  return StatusCode::SUCCESS;
+}
-- 
GitLab