From 131758ec549878f4e8d1d76220077c6645d35580 Mon Sep 17 00:00:00 2001 From: Frank Winklmeier <fwinkl@cern> Date: Sun, 27 Dec 2020 10:54:28 +0100 Subject: [PATCH] Revert "EventUtils: Delete unused ParticleSortingAlg/Tool" This reverts commit 2904e609e744365d044903dc80438b0d46dea245. --- .../EventUtils/src/ParticleSortingAlg.cxx | 158 +++++++++ .../EventUtils/src/ParticleSortingAlg.h | 149 ++++++++ .../EventUtils/src/ParticleSortingTool.cxx | 318 ++++++++++++++++++ .../EventUtils/src/ParticleSortingTool.h | 183 ++++++++++ .../src/components/EventUtils_entries.cxx | 4 + 5 files changed, 812 insertions(+) create mode 100644 PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingAlg.cxx create mode 100644 PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingAlg.h create mode 100644 PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.cxx create mode 100644 PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.h diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingAlg.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingAlg.cxx new file mode 100644 index 00000000000..f5ad85275d7 --- /dev/null +++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingAlg.cxx @@ -0,0 +1,158 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +// ParticleSortingAlg.cxx +// Implementation file for class ParticleSortingAlg +// Author: Karsten Koeneke <karsten.koeneke@cern.ch> +/////////////////////////////////////////////////////////////////// + +// EventUtils includes +#include "ParticleSortingAlg.h" + +// FrameWork includes +#include "Gaudi/Property.h" +#include "GaudiKernel/IJobOptionsSvc.h" +#include "DerivationFrameworkInterfaces/IAugmentationTool.h" + +/////////////////////////////////////////////////////////////////// +// Public methods: +/////////////////////////////////////////////////////////////////// + +// Constructors +//////////////// +ParticleSortingAlg::ParticleSortingAlg( const std::string& name, + ISvcLocator* pSvcLocator ) : + ::AthAlgorithm( name, pSvcLocator ), + m_jos("JobOptionsSvc", name), + m_tool("ParticleSortingTool/ParticleSortingTool", this), + m_inCollKey(""), + m_setInCollKey(false), + m_outCollKey(""), + m_setOutCollKey(false), + m_sortVar("pt"), + m_setSortVar(false), + m_sortDescending(true), + m_setSortDescending(false), + m_nEventsProcessed(0) +{ + declareProperty("JobOptionsSvc", m_jos, "The JobOptionService instance."); + + declareProperty("SortingTool", m_tool, "The private ParticleSortingTool" ); + + declareProperty("InputContainer", m_inCollKey="", "Input container name" ); + m_inCollKey.declareUpdateHandler( &ParticleSortingAlg::setupInputContainer, this ); + + declareProperty("OutputContainer", m_outCollKey="", + "The name of the output container (with SG::VIEW_ELEMENTS) with the sorted copy of input objects" ); + m_outCollKey.declareUpdateHandler( &ParticleSortingAlg::setupOutputContainer, this ); + + declareProperty("SortVariable", m_sortVar="pt", + "Define by what parameter to sort (default: 'pt'; allowed: 'pt', 'eta', 'phi', 'm', 'e', 'rapidity')" ); + m_sortVar.declareUpdateHandler( &ParticleSortingAlg::setupSortVar, this ); + + declareProperty("SortDescending", m_sortDescending=true, + "Define if the container should be sorted in a descending order (default=true)" ); + m_sortDescending.declareUpdateHandler( &ParticleSortingAlg::setupSortDescending, this ); +} + + + +// Destructor +/////////////// +ParticleSortingAlg::~ParticleSortingAlg() +{} + + + +// Athena Algorithm's Hooks +//////////////////////////// +StatusCode ParticleSortingAlg::initialize() +{ + ATH_MSG_DEBUG ("Initializing " << name() << "..."); + + // Print out the used configuration + ATH_MSG_DEBUG ( " using = " << m_jos ); + ATH_MSG_DEBUG ( " using = " << m_tool ); + ATH_MSG_DEBUG ( " using = " << m_inCollKey ); + ATH_MSG_DEBUG ( " using = " << m_outCollKey ); + ATH_MSG_DEBUG ( " using = " << m_sortVar ); + ATH_MSG_DEBUG ( " using = " << m_sortDescending ); + + + // Initialize the counters to zero + m_nEventsProcessed = 0 ; + + + // Get the JobOptionService + // We will use this to set the properties of our private skimming tool + // from the properties of this algorithm. + ATH_MSG_VERBOSE( "Getting the JobOptionService"); + ATH_CHECK( m_jos.retrieve() ); + + // Get the full name of the private skimTool + ATH_MSG_VERBOSE( "Getting the full name of the tool"); + const std::string& fullToolName = this->name() + "." + m_tool.name(); + ATH_MSG_DEBUG( "Got the full name of the tool: " << fullToolName ); + + // Now, set all properties of the private skimTool that were acutally configured + if (m_setInCollKey) { + ATH_MSG_DEBUG( "Setting property" << m_inCollKey + << " of private tool with name: '" << fullToolName << "'" ); + ATH_CHECK( m_jos->addPropertyToCatalogue (fullToolName,m_inCollKey) ); + } + if (m_setOutCollKey) { + ATH_MSG_DEBUG( "Setting property" << m_outCollKey + << " of private tool with name: '" << fullToolName << "'" ); + ATH_CHECK( m_jos->addPropertyToCatalogue (fullToolName,m_outCollKey) ); + } + if (m_setSortVar) { + ATH_MSG_DEBUG( "Setting property" << m_sortVar + << " of private tool with name: '" << fullToolName << "'" ); + ATH_CHECK( m_jos->addPropertyToCatalogue (fullToolName,m_sortVar) ); + } + if (m_setSortDescending) { + ATH_MSG_DEBUG( "Setting property" << m_sortDescending + << " of private tool with name: '" << fullToolName << "'" ); + ATH_CHECK( m_jos->addPropertyToCatalogue (fullToolName,m_sortDescending) ); + } + ATH_MSG_DEBUG( "Done setting properties of the tool"); + + // Get the skimming tool + ATH_CHECK( m_tool.retrieve() ); + + ATH_MSG_DEBUG ( "==> done with initialize " << name() << "..." ); + + return StatusCode::SUCCESS; +} + + + +StatusCode ParticleSortingAlg::finalize() +{ + ATH_MSG_DEBUG ("Finalizing " << name() << "..."); + + // Release all tools and services + ATH_CHECK( m_jos.release() ); + ATH_CHECK( m_tool.release() ); + + return StatusCode::SUCCESS; +} + + + +StatusCode ParticleSortingAlg::execute() +{ + // Increase the event counter + ++m_nEventsProcessed; + + // Simple status message at the beginning of each event execute, + ATH_MSG_DEBUG ( "==> execute " << name() << " on " << m_nEventsProcessed << ". event..." ); + + // Call the tool + ATH_CHECK( m_tool->addBranches() ); + + return StatusCode::SUCCESS; +} diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingAlg.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingAlg.h new file mode 100644 index 00000000000..763f04c952c --- /dev/null +++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingAlg.h @@ -0,0 +1,149 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +// ParticleSortingAlg.h +// Header file for class ParticleSortingAlg +// Author: Karsten Koeneke <karsten.koeneke@cern.ch> +/////////////////////////////////////////////////////////////////// +#ifndef EVENTUTILS_PARTICLESORTINGALG_H +#define EVENTUTILS_PARTICLESORTINGALG_H 1 + +// FrameWork includes +#include "GaudiKernel/ToolHandle.h" +#include "GaudiKernel/ServiceHandle.h" +#include "AthenaBaseComps/AthAlgorithm.h" + +// STL includes +#include <string> + +// Forward declarations +class IJobOptionsSvc; +namespace DerivationFramework { + class IAugmentationTool; +} + +class ParticleSortingAlg + : public ::AthAlgorithm +{ + + /////////////////////////////////////////////////////////////////// + // Public methods: + /////////////////////////////////////////////////////////////////// + public: + + // Copy constructor: + + /// Constructor with parameters: + ParticleSortingAlg( const std::string& name, ISvcLocator* pSvcLocator ); + + /// Destructor: + virtual ~ParticleSortingAlg(); + + /// Athena algorithm's initalize hook + virtual StatusCode initialize(); + + /// Athena algorithm's execute hook + virtual StatusCode execute(); + + /// Athena algorithm's finalize hook + virtual StatusCode finalize(); + + +private: + // The update handlers + + /// This internal method will realize if a user sets the 'InputContainer' property + void setupInputContainer( Gaudi::Details::PropertyBase& /*prop*/ ); + + /// This internal method will realize if a user sets the 'OutputContainer' property + void setupOutputContainer( Gaudi::Details::PropertyBase& /*prop*/ ); + + /// This internal method will realize if a user sets the 'SortVariable' property + void setupSortVar( Gaudi::Details::PropertyBase& /*prop*/ ); + + /// This internal method will realize if a user sets the 'SortDeceding' property + void setupSortDescending( Gaudi::Details::PropertyBase& /*prop*/ ); + + + + /////////////////////////////////////////////////////////////////// + // Private data: + /////////////////////////////////////////////////////////////////// + private: + /// The job options service (will be used to forward this algs properties to + /// the private tool) + ServiceHandle<IJobOptionsSvc> m_jos; + + /// The ToolHandle to the private ParticleSortingTool + ToolHandle<DerivationFramework::IAugmentationTool> m_tool; + + /// Input container name + StringProperty m_inCollKey; + + /// This boolean is true if the user sets the 'InputContainer' property + bool m_setInCollKey; + + + /// The name of the output container (with SG::VIEW_ELEMENTS) with the sorted copy of input objects + StringProperty m_outCollKey; + + /// This boolean is true if the user sets the 'OutputContainer' property + bool m_setOutCollKey; + + + /// Define by what parameter to sort (default: 'pt') + StringProperty m_sortVar; + + /// This boolean is true if the user sets the 'SortVariable' property + bool m_setSortVar; + + + /// Define if the container should be sorted in a descending order (default=true) + BooleanProperty m_sortDescending; + + /// This boolean is true if the user sets the 'SortDescending' property + bool m_setSortDescending; + + + /// Internal event counter + unsigned long m_nEventsProcessed; + +}; + + + +/////////////////////////////////////////////////////////////////// +// Inline methods: +/////////////////////////////////////////////////////////////////// + +/// This internal method will realize if a user sets the 'InputContainer' property +inline void ParticleSortingAlg::setupInputContainer( Gaudi::Details::PropertyBase& /*prop*/ ) { + m_setInCollKey = true; + return; +} + +/// This internal method will realize if a user sets the 'OutputContainer' property +inline void ParticleSortingAlg::setupOutputContainer( Gaudi::Details::PropertyBase& /*prop*/ ) { + m_setOutCollKey = true; + return; +} + +/// This internal method will realize if a user sets the 'SortVariable' property +inline void ParticleSortingAlg::setupSortVar( Gaudi::Details::PropertyBase& /*prop*/ ) +{ + m_setSortVar = true; + return; +} + +/// This internal method will realize if a user sets the 'SortDeceding' property +inline void ParticleSortingAlg::setupSortDescending( Gaudi::Details::PropertyBase& /*prop*/ ) +{ + m_setSortDescending = true; + return; +} + + +#endif //> !EVENTUTILS_PARTICLESORTINGALG_H diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.cxx new file mode 100644 index 00000000000..876c7e005d2 --- /dev/null +++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.cxx @@ -0,0 +1,318 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +// ParticleSortingTool.cxx +// Implementation file for class ParticleSortingTool +// Author: Karsten Koeneke <karsten.koeneke@cern.ch> +/////////////////////////////////////////////////////////////////// + +// EventUtils includes +#include "ParticleSortingTool.h" + +// EDM includes +#include "xAODBase/IParticle.h" +#include "xAODBase/IParticleContainer.h" +#include "xAODMuon/MuonContainer.h" +#include "xAODJet/JetContainer.h" +#include "xAODEgamma/ElectronContainer.h" +#include "xAODEgamma/PhotonContainer.h" +#include "xAODTau/TauJetContainer.h" +#include "xAODPFlow/PFOContainer.h" +#include "xAODTracking/NeutralParticleContainer.h" +#include "xAODTracking/TrackParticleContainer.h" +#include "xAODTruth/TruthParticleContainer.h" +#include "xAODParticleEvent/CompositeParticleContainer.h" +#include "xAODParticleEvent/ParticleContainer.h" +#include "xAODCaloEvent/CaloClusterContainer.h" +#include "AthContainers/ConstDataVector.h" + +// Constructors +//////////////// +ParticleSortingTool::ParticleSortingTool( const std::string& type, + const std::string& name, + const IInterface* parent ) : + ::AthAlgTool ( type, name, parent ), + m_inCollKey(""), + m_outCollKey(""), + m_sortVar("pt"), + m_sortDescending(true), + m_contID(0), + m_sortID(0), + m_nEventsProcessed(0) +{ + declareInterface< DerivationFramework::IAugmentationTool >(this); + + declareProperty("InputContainer", m_inCollKey="", "Input container name" ); + + declareProperty("OutputContainer", m_outCollKey="", + "The name of the output container (with SG::VIEW_ELEMENTS) with the sorted copy of input objects" ); + + declareProperty("SortVariable", m_sortVar="pt", + "Define by what parameter to sort (default: 'pt'; allowed: 'pt', 'eta', 'phi', 'm', 'e', 'rapidity')" ); + + declareProperty("SortDescending", m_sortDescending=true, + "Define if the container should be sorted in a descending order (default=true)" ); +} + + +// Destructor +/////////////// +ParticleSortingTool::~ParticleSortingTool() +{} + + + +// Athena algtool's Hooks +//////////////////////////// +StatusCode ParticleSortingTool::initialize() +{ + ATH_MSG_DEBUG ("Initializing " << name() << "..."); + + // Print out the used configuration + ATH_MSG_DEBUG ( " using = " << m_inCollKey ); + ATH_MSG_DEBUG ( " using = " << m_outCollKey ); + + // initialize the counters + m_contID = 0; + m_sortID = 0; + m_nEventsProcessed = 0; + + // Figure out how to sort + if ( m_sortVar.value() == "pt" ) { m_sortID = 1; } + else if ( m_sortVar.value() == "eta" ) { m_sortID = 2; } + else if ( m_sortVar.value() == "phi" ) { m_sortID = 3; } + else if ( m_sortVar.value() == "m" ) { m_sortID = 4; } + else if ( m_sortVar.value() == "e" ) { m_sortID = 5; } + else if ( m_sortVar.value() == "rapidity" ) { m_sortID = 6; } + else { + ATH_MSG_INFO("Didn't find a valid value for SortVariable=" << m_sortVar.value() << "." + << " Assuming it's an auxdata member"); + m_sortID = 7; + } + if ( m_sortDescending.value() ) { m_sortID *= -1; } + + return StatusCode::SUCCESS; +} + + + + +StatusCode ParticleSortingTool::finalize() +{ + ATH_MSG_DEBUG ("Finalizing " << name() << "..."); + + return StatusCode::SUCCESS; +} + + + +// Declare a short pre-processor macro to deal with the different container types +#define COPY_AND_SORT_CONTAINER( CONTAINERTYPE ) \ +else if ( evtStore()->contains<CONTAINERTYPE>( m_inCollKey.value() ) ) { \ + ATH_MSG_DEBUG("Trying to copy, sort, and record container of type "#CONTAINERTYPE ); \ + const CONTAINERTYPE* inCont; \ + ATH_CHECK( evtStore()->retrieve( inCont, m_inCollKey.value() ) ); \ + CONTAINERTYPE* outCont = new CONTAINERTYPE( SG::VIEW_ELEMENTS ); \ + *outCont = *inCont; \ + ATH_CHECK( evtStore()->record ( outCont, m_outCollKey.value() ) ); \ + ATH_CHECK( this->doSort(outCont) ); \ +} + + +// Declare a short pre-processor macro to deal with the different container types +#define OVERWRITE_AND_SORT_CONTAINER( CONTAINERTYPE ) \ +else if ( evtStore()->contains<CONTAINERTYPE>( m_inCollKey.value() ) ) { \ + ATH_MSG_DEBUG("Trying to copy, sort, and overwrite container of type "#CONTAINERTYPE ); \ + const CONTAINERTYPE* inCont; \ + ATH_CHECK( evtStore()->retrieve( inCont, m_inCollKey.value() ) ); \ + ConstDataVector<CONTAINERTYPE>* outCont = new ConstDataVector<CONTAINERTYPE>( SG::VIEW_ELEMENTS ); \ + for ( const CONTAINERTYPE::base_value_type* inPart : *inCont ){ \ + outCont->push_back(inPart); \ + } \ + ATH_CHECK( evtStore()->overwrite( outCont, m_inCollKey.value() ) ); \ + ATH_CHECK( this->doSortConst<CONTAINERTYPE>(outCont) ); \ +} + + + +StatusCode ParticleSortingTool::addBranches() const +{ + // Increase the event counter + ++m_nEventsProcessed; + + // Simple status message at the beginning of each event execute, + ATH_MSG_DEBUG ( "==> addBranches " << name() << " on " << m_nEventsProcessed << ". event..." ); + + if ( m_outCollKey.value().empty() ) { + // Try to get the input container as non-const + ATH_MSG_DEBUG("Got an empty 'OutputCollection' property. " + << "Trying to retrieve a non-const version of the 'InputContainer'..."); + xAOD::IParticleContainer* inCont = evtStore()->tryRetrieve<xAOD::IParticleContainer>( m_inCollKey.value() ); + if (inCont){ ATH_CHECK( this->doSort(inCont) ); } + else { + ATH_MSG_DEBUG("We couldn't retrieve a non-const version of the input container... try const."); + const xAOD::IParticleContainer* inCont2 = nullptr; + ATH_CHECK( evtStore()->retrieve( inCont2, m_inCollKey.value()) ); + // Now, do the copy and sorting and overwriting of all known container types + if (false) { + } + OVERWRITE_AND_SORT_CONTAINER(xAOD::MuonContainer) + OVERWRITE_AND_SORT_CONTAINER(xAOD::ElectronContainer) + OVERWRITE_AND_SORT_CONTAINER(xAOD::PhotonContainer) + OVERWRITE_AND_SORT_CONTAINER(xAOD::TauJetContainer) + OVERWRITE_AND_SORT_CONTAINER(xAOD::JetContainer) + OVERWRITE_AND_SORT_CONTAINER(xAOD::PFOContainer) + OVERWRITE_AND_SORT_CONTAINER(xAOD::NeutralParticleContainer) + OVERWRITE_AND_SORT_CONTAINER(xAOD::TrackParticleContainer) + OVERWRITE_AND_SORT_CONTAINER(xAOD::TruthParticleContainer) + OVERWRITE_AND_SORT_CONTAINER(xAOD::CompositeParticleContainer) + OVERWRITE_AND_SORT_CONTAINER(xAOD::ParticleContainer) + OVERWRITE_AND_SORT_CONTAINER(xAOD::CaloClusterContainer) + else { + ATH_MSG_ERROR("Couln't find the provided intput container in store gate for later overwriting"); + return StatusCode::FAILURE; + } + } + } + else { + ATH_MSG_DEBUG("Got a non-empty 'OutputCollection' property. " + << "Trying to retrieve a const version of the 'InputContainer'..."); + + // Now, do the copy and sorting of all known container types + if (false) { + } + COPY_AND_SORT_CONTAINER(xAOD::MuonContainer) + COPY_AND_SORT_CONTAINER(xAOD::ElectronContainer) + COPY_AND_SORT_CONTAINER(xAOD::PhotonContainer) + COPY_AND_SORT_CONTAINER(xAOD::TauJetContainer) + COPY_AND_SORT_CONTAINER(xAOD::JetContainer) + COPY_AND_SORT_CONTAINER(xAOD::PFOContainer) + COPY_AND_SORT_CONTAINER(xAOD::NeutralParticleContainer) + COPY_AND_SORT_CONTAINER(xAOD::TrackParticleContainer) + COPY_AND_SORT_CONTAINER(xAOD::TruthParticleContainer) + COPY_AND_SORT_CONTAINER(xAOD::CompositeParticleContainer) + COPY_AND_SORT_CONTAINER(xAOD::ParticleContainer) + COPY_AND_SORT_CONTAINER(xAOD::CaloClusterContainer) + else { + ATH_MSG_ERROR("Couln't find the provided intput container in store gate"); + return StatusCode::FAILURE; + } + + } + + return StatusCode::SUCCESS; +} + + + +StatusCode ParticleSortingTool::doSort( xAOD::IParticleContainer* cont ) const +{ + if ( !cont ) { + ATH_MSG_ERROR("No container to be sorted"); + return StatusCode::FAILURE; + } + // Actually do the sorting, using a C++11 lambda function construct + // to be able to use the member function here + if ( std::abs(m_sortID) == 1 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->comparePt(a,b); + } ); + } + else if ( std::abs(m_sortID) == 2 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->compareEta(a,b); + } ); + } + else if ( std::abs(m_sortID) == 3 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->comparePhi(a,b); + } ); + } + else if ( std::abs(m_sortID) == 4 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->compareMass(a,b); + } ); + } + else if ( std::abs(m_sortID) == 5 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->compareEnergy(a,b); + } ); + } + else if ( std::abs(m_sortID) == 6 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->compareRapidity(a,b); + } ); + } + else if ( std::abs(m_sortID) == 7 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->compareAuxData(a,b); + } ); + } + + return StatusCode::SUCCESS; +} + + +bool ParticleSortingTool::comparePt( const xAOD::IParticle* partA, + const xAOD::IParticle* partB ) const +{ + const double a = partA->pt(); + const double b = partB->pt(); + return this->compareDouble(a,b); +} + + +bool ParticleSortingTool::compareEta( const xAOD::IParticle* partA, + const xAOD::IParticle* partB ) const +{ + const double a = partA->eta(); + const double b = partB->eta(); + return this->compareDouble(a,b); +} + + +bool ParticleSortingTool::comparePhi( const xAOD::IParticle* partA, + const xAOD::IParticle* partB ) const +{ + const double a = partA->phi(); + const double b = partB->phi(); + return this->compareDouble(a,b); +} + + +bool ParticleSortingTool::compareMass( const xAOD::IParticle* partA, + const xAOD::IParticle* partB ) const +{ + const double a = partA->m(); + const double b = partB->m(); + return this->compareDouble(a,b); +} + + +bool ParticleSortingTool::compareEnergy( const xAOD::IParticle* partA, + const xAOD::IParticle* partB ) const +{ + const double a = partA->e(); + const double b = partB->e(); + return this->compareDouble(a,b); +} + + +bool ParticleSortingTool::compareRapidity( const xAOD::IParticle* partA, + const xAOD::IParticle* partB ) const +{ + const double a = partA->rapidity(); + const double b = partB->rapidity(); + return this->compareDouble(a,b); +} + +bool ParticleSortingTool::compareAuxData( const xAOD::IParticle* partA, + const xAOD::IParticle* partB ) const +{ + const double a = partA->auxdata<float>( this->m_sortVar.value() ); + const double b = partB->auxdata<float>( this->m_sortVar.value() ); + return this->compareDouble(a,b); +} diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.h new file mode 100644 index 00000000000..dc097711cfb --- /dev/null +++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.h @@ -0,0 +1,183 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +// ParticleSortingTool.h +// Header file for class ParticleSortingTool +// Author: Karsten Koeneke <karsten.koeneke@cern.ch> +/////////////////////////////////////////////////////////////////// +#ifndef EVENTUTILS_PARTICLESORTINGTOOL_H +#define EVENTUTILS_PARTICLESORTINGTOOL_H 1 + +// FrameWork includes +#include "AthenaBaseComps/AthAlgTool.h" +#include "DerivationFrameworkInterfaces/IAugmentationTool.h" +#include "CxxUtils/fpcompare.h" + +// EDM inlcudes +#include "xAODBase/IParticle.h" +#include "xAODBase/IParticleContainer.h" +#include "AthContainers/ConstDataVector.h" + +// STL includes +#include <vector> +#include <string> +#include <cmath> + +class ParticleSortingTool + : virtual public ::DerivationFramework::IAugmentationTool, + public ::AthAlgTool +{ + + /////////////////////////////////////////////////////////////////// + // Public methods: + /////////////////////////////////////////////////////////////////// +public: + + // Copy constructor: + + /// Constructor with parameters: + ParticleSortingTool( const std::string& type, + const std::string& name, + const IInterface* parent ); + + /// Destructor: + virtual ~ParticleSortingTool(); + + /// Athena algtool's initialize + virtual StatusCode initialize() override; + + /// Athena algtool's finalize + virtual StatusCode finalize() override; + + + /// Implement the method from the ISkimmingTool interface + virtual StatusCode addBranches() const final override; + + + +// Private methods +private: + + /// Helper method that implements the call to the right sort function + StatusCode doSort( xAOD::IParticleContainer* cont ) const; + + /// Helper method to sort a ConstDataVector + template<class CONTAINERTYPE> + StatusCode doSortConst( ConstDataVector<CONTAINERTYPE>* cont ) const; + + /// The method to compare the particle's pt + bool comparePt( const xAOD::IParticle* partA, const xAOD::IParticle* partB ) const; + + /// The method to compare the particle's eta + bool compareEta( const xAOD::IParticle* partA, const xAOD::IParticle* partB ) const; + + /// The method to compare the particle's phi + bool comparePhi( const xAOD::IParticle* partA, const xAOD::IParticle* partB ) const; + + /// The method to compare the particle's mass + bool compareMass( const xAOD::IParticle* partA, const xAOD::IParticle* partB ) const; + + /// The method to compare the particle's energy + bool compareEnergy( const xAOD::IParticle* partA, const xAOD::IParticle* partB ) const; + + /// The method to compare the particle's rapidity + bool compareRapidity( const xAOD::IParticle* partA, const xAOD::IParticle* partB ) const; + + /// The method to compare an auxdata member of the particle + bool compareAuxData( const xAOD::IParticle* partA, const xAOD::IParticle* partB ) const; + + /// Method to compare two doubles + inline bool compareDouble( double a, double b ) const; + + + /////////////////////////////////////////////////////////////////// + // Private data: + /////////////////////////////////////////////////////////////////// +private: + + /// Input container name + StringProperty m_inCollKey; + + /// The name of the output container (with SG::VIEW_ELEMENTS) with the sorted copy of input objects + StringProperty m_outCollKey; + + /// Define by what parameter to sort (default: 'pt') + StringProperty m_sortVar; + + /// Define if the container should be sorted in a descending order (default=true) + BooleanProperty m_sortDescending; + + + /// Internal container type identifier + mutable unsigned int m_contID; + + /// Internal identifier for the type of sorting + mutable int m_sortID; + + /// Internal event counter + mutable unsigned long m_nEventsProcessed; + +}; + + +inline bool ParticleSortingTool::compareDouble( double a, double b ) const +{ + if ( m_sortID < 0 ) { return CxxUtils::fpcompare::greater(a,b); } + else { return CxxUtils::fpcompare::less(a,b); } +} + + +template<class CONTAINERTYPE> +StatusCode ParticleSortingTool::doSortConst( ConstDataVector<CONTAINERTYPE>* cont ) const +{ + if ( !cont ) { + ATH_MSG_ERROR("No ConstDataVector to be sorted"); + return StatusCode::FAILURE; + } + // Actually do the sorting, using a C++11 lambda function construct + // to be able to use the member function here + if ( std::abs(m_sortID) == 1 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->comparePt(a,b); + } ); + } + else if ( std::abs(m_sortID) == 2 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->compareEta(a,b); + } ); + } + else if ( std::abs(m_sortID) == 3 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->comparePhi(a,b); + } ); + } + else if ( std::abs(m_sortID) == 4 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->compareMass(a,b); + } ); + } + else if ( std::abs(m_sortID) == 5 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->compareEnergy(a,b); + } ); + } + else if ( std::abs(m_sortID) == 6 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->compareRapidity(a,b); + } ); + } + else if ( std::abs(m_sortID) == 7 ) { + cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) { + return this->compareAuxData(a,b); + } ); + } + + return StatusCode::SUCCESS; +} + + + +#endif //> !EVENTUTILS_PARTICLESORTINGTOOL_H diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/components/EventUtils_entries.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/components/EventUtils_entries.cxx index 557082712e4..1f217ab44bc 100644 --- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/components/EventUtils_entries.cxx +++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/components/EventUtils_entries.cxx @@ -1,3 +1,5 @@ +#include "../ParticleSortingTool.h" +#include "../ParticleSortingAlg.h" #include "../CutTool.h" #include "../CutAlg.h" #include "../ParticleSelectionTool.h" @@ -7,6 +9,8 @@ #include "../TriggerSelectionAlg.h" #include "../EventDecisionAlg.h" +DECLARE_COMPONENT( ParticleSortingTool ) +DECLARE_COMPONENT( ParticleSortingAlg ) DECLARE_COMPONENT( CutTool ) DECLARE_COMPONENT( CutAlg ) DECLARE_COMPONENT( ParticleSelectionTool ) -- GitLab