diff --git a/Calorimeter/CaloCalibHitRec/CMakeLists.txt b/Calorimeter/CaloCalibHitRec/CMakeLists.txt index cc0504e37e5d31b373ebc3bec829c6dbda77bded..b55c8b11c7eb3ad7454cc770e057f35081bb73ac 100644 --- a/Calorimeter/CaloCalibHitRec/CMakeLists.txt +++ b/Calorimeter/CaloCalibHitRec/CMakeLists.txt @@ -16,6 +16,7 @@ atlas_depends_on_subdirs( PUBLIC Control/StoreGate DetectorDescription/Identifier Event/xAOD/xAODCaloEvent + Event/xAOD/xAODTruth Control/CxxUtils GaudiKernel PRIVATE @@ -36,7 +37,7 @@ atlas_add_component( CaloCalibHitRec src/*.cxx src/components/*.cxx INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} - LINK_LIBRARIES ${CLHEP_LIBRARIES} CaloDmDetDescr CaloGeoHelpers CaloIdentifier CaloRecLib CaloSimEvent AthenaBaseComps StoreGateLib SGtests Identifier xAODCaloEvent GaudiKernel CaloDetDescrLib CaloEvent AthenaKernel AtlasDetDescr LArRecEvent McParticleEvent TileEvent PathResolver CxxUtils ) + LINK_LIBRARIES ${CLHEP_LIBRARIES} CaloDmDetDescr CaloGeoHelpers CaloIdentifier CaloRecLib CaloSimEvent AthenaBaseComps StoreGateLib SGtests Identifier xAODCaloEvent xAODTruth GaudiKernel CaloDetDescrLib CaloEvent AthenaKernel AtlasDetDescr LArRecEvent McParticleEvent TileEvent PathResolver CxxUtils ) # Install files from the package: atlas_install_headers( CaloCalibHitRec ) diff --git a/Calorimeter/CaloCalibHitRec/CaloCalibHitRec/CaloCalibClusterTruthAttributerTool.h b/Calorimeter/CaloCalibHitRec/CaloCalibHitRec/CaloCalibClusterTruthAttributerTool.h new file mode 100644 index 0000000000000000000000000000000000000000..d0ac0d485794f09f22c3f0d7e2227d2fd1427072 --- /dev/null +++ b/Calorimeter/CaloCalibHitRec/CaloCalibHitRec/CaloCalibClusterTruthAttributerTool.h @@ -0,0 +1,24 @@ +#ifndef CALOCALIBCLUSTERTRUTHATTRIBUTERTOOL_H +#define CALOCALIBCLUSTERTRUTHATTRIBUTERTOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "CaloCalibHitRec/ICaloCalibClusterTruthAttributerTool.h" + +/** Concrete tool that calculates calibration hit truth energies in xAOD::CaloCluster */ + +class CaloCalibClusterTruthAttributerTool : public extends<AthAlgTool, ICaloCalibClusterTruthAttributerTool> { + +public: + + CaloCalibClusterTruthAttributerTool(const std::string& type,const std::string& name,const IInterface* parent); + virtual ~CaloCalibClusterTruthAttributerTool(); + + /** This calculates the truth energies of N leading truth particles in a topocluster */ + virtual StatusCode calculateTruthEnergies(const xAOD::CaloCluster& theCaloCluster, unsigned int numTruthParticles, const std::map<Identifier,std::vector<const CaloCalibrationHit*> >& identifierToCaloHitMap, const std::map<unsigned int,const xAOD::TruthParticle*>& truthBarcodeToTruthParticleMap, std::vector<std::pair<unsigned int, double > >& barcodeTrueCalHitEnergy) const override; + +private: + /** Toggle storage of invisible and escaped energy - by default this is false, and hence we do not store the invisible or escaped calibration hit truth (ctt) energy. Hence only the EM and nonEM truth ctt energy is stored by default */ + Gaudi::Property<bool> m_fullTruthEnergy{this,"storeFullTruthEnergy",false,"Toggle storage of invisible and escaped energy"}; + +}; +#endif diff --git a/Calorimeter/CaloCalibHitRec/CaloCalibHitRec/CaloCalibDefineTypes.h b/Calorimeter/CaloCalibHitRec/CaloCalibHitRec/CaloCalibDefineTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..1cb37fd1a0ccc0ea91955767dd456ced5768204d --- /dev/null +++ b/Calorimeter/CaloCalibHitRec/CaloCalibHitRec/CaloCalibDefineTypes.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef CALOCALIBDEFINETYPES_H +#define CALOCALIBDEFINETYPES_H + +/** A header file to define the CLID for a few types put into Storegate by CaloCalibHitRec/CaloCalibClusterTruthMapMakerAlgorithm */ + +#include "AthenaKernel/CLASS_DEF.h" + +#include "Identifier/Identifier.h" + +//EDM Classes +#include "CaloSimEvent/CaloCalibrationHit.h" +#include "xAODTruth/TruthParticle.h" + +//C++ classes +#include <map> +#include <vector> + +/* Here are the definitions. We use CLASS_DEF2 for these types, which have a comma in the name */ +CLASS_DEF2(std::map<Identifier,std::vector<const CaloCalibrationHit*> >,11518007,1) +CLASS_DEF2(std::map<unsigned int,const xAOD::TruthParticle* >,256282227,1) +#endif diff --git a/Calorimeter/CaloCalibHitRec/CaloCalibHitRec/ICaloCalibClusterTruthAttributerTool.h b/Calorimeter/CaloCalibHitRec/CaloCalibHitRec/ICaloCalibClusterTruthAttributerTool.h new file mode 100644 index 0000000000000000000000000000000000000000..34a5c29d37766ddf9eee1e0a5d13af2fdd5535c0 --- /dev/null +++ b/Calorimeter/CaloCalibHitRec/CaloCalibHitRec/ICaloCalibClusterTruthAttributerTool.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ICALOCALIBCLUSTERTRUTHATTRIBUTERTOOL_H +#define ICALOCALIBCLUSTERTRUTHATTRIBUTERTOOL_H + +#include "GaudiKernel/IAlgTool.h" +#include "Identifier/Identifier.h" + +//EDM Classes +#include "CaloSimEvent/CaloCalibrationHit.h" +#include "xAODCaloEvent/CaloCluster.h" +#include "xAODTruth/TruthParticle.h" + +//c++ includes +#include <vector> +#include <map> +#include <utility> + +/** Interface class tools calculating calibration hit truth information */ + +class ICaloCalibClusterTruthAttributerTool : virtual public IAlgTool { + +public: + /** This calculates the truth energies of N leading truth particles in a topocluster */ + virtual StatusCode calculateTruthEnergies(const xAOD::CaloCluster& theCaloCluster, unsigned int numTruthParticles, const std::map<Identifier,std::vector<const CaloCalibrationHit*> >& identifierToCaloHitMap, const std::map<unsigned int,const xAOD::TruthParticle*>& truthBarcodeToTruthParticleMap, std::vector<std::pair<unsigned int, double > >& barcodeTrueCalHitEnergy) const = 0; + + DeclareInterfaceID(ICaloCalibClusterTruthAttributerTool,1,0); + +}; +#endif diff --git a/Calorimeter/CaloCalibHitRec/share/CaloCalibHitDecorator_algorithms.py b/Calorimeter/CaloCalibHitRec/share/CaloCalibHitDecorator_algorithms.py new file mode 100644 index 0000000000000000000000000000000000000000..d727c1ec71b7d9e89aadcabf86b2e0099fa8e777 --- /dev/null +++ b/Calorimeter/CaloCalibHitRec/share/CaloCalibHitDecorator_algorithms.py @@ -0,0 +1,11 @@ +from CaloCalibHitRec.CaloCalibHitRecConf import CaloCalibClusterTruthMapMakerAlgorithm +CaloCalibClusterTruthMapMakerAlgorithm = CaloCalibClusterTruthMapMakerAlgorithm() +topSequence += CaloCalibClusterTruthMapMakerAlgorithm + +from CaloCalibHitRec.CaloCalibHitRecConf import CaloCalibClusterDecoratorAlgorithm +CaloCalibClusterDecoratorAlgorithm = CaloCalibClusterDecoratorAlgorithm() + +from CaloCalibHitRec.CaloCalibHitRecConf import CaloCalibClusterTruthAttributerTool +CaloCalibClusterTruthAttributerTool = CaloCalibClusterTruthAttributerTool() +CaloCalibClusterDecoratorAlgorithm.TruthAttributerTool = CaloCalibClusterTruthAttributerTool +topSequence += CaloCalibClusterDecoratorAlgorithm diff --git a/Calorimeter/CaloCalibHitRec/share/CaloCalibHitDecorator_jobOptions.py b/Calorimeter/CaloCalibHitRec/share/CaloCalibHitDecorator_jobOptions.py new file mode 100644 index 0000000000000000000000000000000000000000..b47a479eed5180a92c56e808f127ed58d086691f --- /dev/null +++ b/Calorimeter/CaloCalibHitRec/share/CaloCalibHitDecorator_jobOptions.py @@ -0,0 +1,34 @@ +from AthenaCommon.AthenaCommonFlags import athenaCommonFlags +athenaCommonFlags.FilesInput=["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/RecExRecoTest/mc16_13TeV.361022.Pythia8EvtGen_A14NNPDF23LO_jetjet_JZ2W.recon.ESD.e3668_s3170_r10572_homeMade.pool.root"] + +from RecExConfig.RecFlags import rec +rec.doEgamma.set_Value_and_Lock(False) +#Set to true temporarily due to muon geometry bug, see ATLASRECTS-5160 +rec.doMuon.set_Value_and_Lock(True) + +from CaloRec.CaloRecFlags import jobproperties +jobproperties.CaloRecFlags.Enabled.set_Value_and_Lock(False) +jobproperties.CaloRecFlags.doCaloCluster.set_Value_and_Lock(False) +jobproperties.CaloRecFlags.doCaloTopoCluster.set_Value_and_Lock(False) + +#this turns off CaloCluster2xAOD +rec.doWritexAOD.set_Value_and_Lock(False) +#nothing to say on these +rec.doWriteTAG.set_Value_and_Lock(False) +rec.doTruth.set_Value_and_Lock(False) +rec.doAODCaloCells.set_Value_and_Lock(False) +rec.doTrigger.set_Value_and_Lock(False) +#Turns off xAODRingSetConfWriter +rec.doCaloRinger.set_Value_and_Lock(False) + +#disables VertexCnvAlg +from InDetRecExample.InDetJobProperties import jobproperties +jobproperties.InDetJobProperties.doxAOD.set_Value_and_Lock(False) +#Disables AllExecutedEvents +rec.doFileMetaData.set_Value_and_Lock(False) + +athenaCommonFlags.EvtMax=10 +UserAlgs = ["CaloCalibHitRec/CaloCalibHitDecorator_algorithms.py"] +include ("RecExCommon/RecExCommon_topOptions.py") +#Add decoration to output item list +StreamAOD.ItemList+=['xAOD::CaloClusterAuxContainer#CaloCalTopoClustersAux.SECOND_R.SECOND_LAMBDA.CENTER_MAG.CENTER_LAMBDA.ISOLATION.ENG_BAD_CELLS.N_BAD_CELLS.BADLARQ_FRAC.ENG_POS.AVG_LAR_Q.AVG_TILE_Q.EM_PROBABILITY.BadChannelList.calclus_NLeadingTruthParticleBarcodeEnergyPairs'] diff --git a/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterDecoratorAlgorithm.cxx b/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterDecoratorAlgorithm.cxx new file mode 100644 index 0000000000000000000000000000000000000000..88bceeb0b0fa615cb5bd5acc4517d48691870654 --- /dev/null +++ b/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterDecoratorAlgorithm.cxx @@ -0,0 +1,54 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CaloCalibClusterDecoratorAlgorithm.h" + +//Core classes +#include "StoreGate/WriteDecorHandle.h" + +StatusCode CaloCalibClusterDecoratorAlgorithm::initialize(){ + + ATH_CHECK(m_mapIdentifierToCalibHitsReadHandleKey.initialize()); + ATH_CHECK(m_mapTruthBarcodeToTruthParticleReadHandleKey.initialize()); + + ATH_CHECK(m_caloClusterWriteDecorHandleKeyNLeadingTruthParticles.initialize()); + + ATH_CHECK(m_truthAttributerTool.retrieve()); + + return StatusCode::SUCCESS; +} + +StatusCode CaloCalibClusterDecoratorAlgorithm::execute(const EventContext& ctx) const{ + + SG::ReadHandle<std::map<Identifier,std::vector<const CaloCalibrationHit*> > > mapIdentifierToCalibHitsReadHandle(m_mapIdentifierToCalibHitsReadHandleKey, ctx); + if(!mapIdentifierToCalibHitsReadHandle.isValid()){ + ATH_MSG_WARNING("Could not retrieve map between Identifier and calibraiton hits from Storegae"); + return StatusCode::FAILURE; + } + + SG::ReadHandle<std::map<unsigned int,const xAOD::TruthParticle* > > mapTruthBarcodeToTruthParticleReadHandle(m_mapTruthBarcodeToTruthParticleReadHandleKey, ctx); + if(!mapTruthBarcodeToTruthParticleReadHandle.isValid()){ + ATH_MSG_WARNING("Could not retrieve map between truth barcode and truth particle from Storegate"); + return StatusCode::FAILURE; + } + + SG::WriteDecorHandle<xAOD::CaloClusterContainer, std::vector< std::pair<unsigned int, double> > > caloClusterWriteDecorHandleNLeadingTruthParticles(m_caloClusterWriteDecorHandleKeyNLeadingTruthParticles, ctx); + StatusCode sc; + + for (auto thisCaloCluster : *caloClusterWriteDecorHandleNLeadingTruthParticles){ + + std::vector<std::pair<unsigned int, double > > newBarCodeTruthPairs; + sc = m_truthAttributerTool->calculateTruthEnergies(*thisCaloCluster, m_numTruthParticles, *mapIdentifierToCalibHitsReadHandle, *mapTruthBarcodeToTruthParticleReadHandle, newBarCodeTruthPairs); + if (sc == StatusCode::FAILURE) return sc; + + for (const auto& thisPair : newBarCodeTruthPairs) ATH_MSG_DEBUG("Cluster Final loop: Particle with barcode " << thisPair.first << " has truth energy of " << thisPair.second << " for cluster with e, eta " << thisCaloCluster->e() << " and " << thisCaloCluster->eta()); + caloClusterWriteDecorHandleNLeadingTruthParticles(*thisCaloCluster) = newBarCodeTruthPairs; + } + + return StatusCode::SUCCESS; +} + +StatusCode CaloCalibClusterDecoratorAlgorithm::finalize(){ + return StatusCode::SUCCESS; +} diff --git a/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterDecoratorAlgorithm.h b/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterDecoratorAlgorithm.h new file mode 100644 index 0000000000000000000000000000000000000000..7989f875d54ba0687024fa9241a757af960506f1 --- /dev/null +++ b/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterDecoratorAlgorithm.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef CALOCALIBCLUSTERDECORATORALGORITHM_H +#define CALOCALIBCLUSTERDECORATORALGORITHM_H + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "CaloCalibHitRec/CaloCalibDefineTypes.h" +#include "CaloCalibHitRec/ICaloCalibClusterTruthAttributerTool.h" + +//EDM Classes +#include "CaloSimEvent/CaloCalibrationHit.h" +#include "xAODTruth/TruthParticle.h" + +//EDM Container Classes +#include "xAODCaloEvent/CaloClusterContainer.h" + +//C++ classes +#include <map> +#include <vector> + +/** This algorithm decorates xAOD::CaloCluster with calibration hit truth information + +It relies on upstream creation of several maps in CaloCalibClusterTruthMapMakerAlgorithm, stored in Storegate, to provide fast access to required information. +The actual calculations are taken care of my an ICaloCalibClusterTruthAttributerTool. +The user may toggle how many truth particles to consider per xAOD::CaloCluster, ordered in leading calibration hit truth pt, via a Gaudi Property "NumTruthParticles". */ + +class CaloCalibClusterDecoratorAlgorithm : public AthReentrantAlgorithm { + +public: + /** Constructor from base class */ + using AthReentrantAlgorithm::AthReentrantAlgorithm; + + /** Destructor */ + virtual ~CaloCalibClusterDecoratorAlgorithm() {}; + + /* Gaudi algorithm hooks */ + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& ctx) const override; + virtual StatusCode finalize() override; + +private: + /** ReadHandleKey for the map between Identifiers and sets of calibration hits */ + SG::ReadHandleKey<std::map<Identifier,std::vector<const CaloCalibrationHit*> > > m_mapIdentifierToCalibHitsReadHandleKey{this,"IdentifierToCalibHitsMapName","IdentifierToCalibHitsMap","ReadHandleKey for the map between Identifiers and sets of calibration hits"}; + + /** ReadHandleKey for the map between truth particle barcode and the pdg Id */ + SG::ReadHandleKey<std::map<unsigned int,const xAOD::TruthParticle* > > m_mapTruthBarcodeToTruthParticleReadHandleKey{this,"TruthBarcodeToTruthParticleMapName","TruthBarcodeTruthParticleMap","ReadHandleKey for the map between truth particle barcode and the pdg Id"}; + + /** Write handle key to decorate CaloCluster with threeN leading truth particle barcode and energy */ + SG::WriteDecorHandleKey<xAOD::CaloClusterContainer> m_caloClusterWriteDecorHandleKeyNLeadingTruthParticles{this,"CaloClusterWriteDecorHandleKey_NLeadingTruthParticles","CaloCalTopoClusters.calclus_NLeadingTruthParticleBarcodeEnergyPairs"}; + + /** ToolHandle to a tool to create the calibration hit truth information that we need for the decoration */ + ToolHandle<ICaloCalibClusterTruthAttributerTool> m_truthAttributerTool{this,"TruthAttributerTool",""," ToolHandle to a tool to create the calibration hit truth information that we need for the decoration"}; + + /** Allow user to set the number of truth particles per clusterCaloCluster or PFO, in descending pt order, for which to store calibration hit enery */ + Gaudi::Property<unsigned int> m_numTruthParticles{this,"NumTruthParticles",3,"Set number of truth particles per CaloCluster/PFO for which we store calibration hit energy"}; + +}; +#endif diff --git a/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterTruthAttributerTool.cxx b/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterTruthAttributerTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b57b8fab217cf86842820cb7ce58fc2784c3d0fd --- /dev/null +++ b/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterTruthAttributerTool.cxx @@ -0,0 +1,104 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CaloCalibHitRec/CaloCalibClusterTruthAttributerTool.h" + +CaloCalibClusterTruthAttributerTool::CaloCalibClusterTruthAttributerTool(const std::string& type, const std::string& name, const IInterface* parent) : base_class(type,name,parent) { +} + +CaloCalibClusterTruthAttributerTool::~CaloCalibClusterTruthAttributerTool(){} + +StatusCode CaloCalibClusterTruthAttributerTool::calculateTruthEnergies(const xAOD::CaloCluster& theCaloCluster, unsigned int numTruthParticles, const std::map<Identifier,std::vector<const CaloCalibrationHit*> >& identifierToCaloHitMap, const std::map<unsigned int,const xAOD::TruthParticle*>& truthBarcodeToTruthParticleMap, std::vector<std::pair<unsigned int, double > >& barcodeTrueCalHitEnergy) const{ + + const CaloClusterCellLink* theCellLinks = theCaloCluster.getCellLinks(); + + if (!theCellLinks) { + ATH_MSG_ERROR("A CaloCluster has no CaloClusterCellLinks"); + return StatusCode::FAILURE; + } + + //loop once over the cells to find the barcodes and pt of truth particles in this cluster + std::map<unsigned int, double> barcodeTruePtMap; + + for (auto thisCaloCell : *theCellLinks){ + + if (!thisCaloCell){ + ATH_MSG_WARNING("Have invalid pointer to CaloCell"); + continue; + } + + //get the unique calorimeter cell identifier + Identifier cellID = thisCaloCell->ID(); + + //look up the calibration hit that corresponds to this calorimeter cell - we use find because not all calorimeter cells will have calibration hits + std::map<Identifier,std::vector<const CaloCalibrationHit*> >::const_iterator identifierToCaloHitMapIterator = identifierToCaloHitMap.find(cellID); + if (identifierToCaloHitMap.end() == identifierToCaloHitMapIterator) continue; + const std::vector<const CaloCalibrationHit*>& theseCalibrationHits = (*identifierToCaloHitMapIterator).second; + + for (auto thisCalibrationHit : theseCalibrationHits){ + unsigned int barcode = thisCalibrationHit->particleID(); + const xAOD::TruthParticle* theTruthParticle = truthBarcodeToTruthParticleMap.at(barcode); + double theTruthParticlePt = theTruthParticle->pt(); + + barcodeTruePtMap[barcode] = theTruthParticlePt; + + }//calibration hit loop + + }//first loop on calorimeter cells to find leading three truth particles with calibration hits + + std::vector<std::pair<unsigned int, double > > barcodeTruePtPairs; + + for (const auto& thisEntry : barcodeTruePtMap) barcodeTruePtPairs.push_back(thisEntry); + + std::sort(barcodeTruePtPairs.begin(),barcodeTruePtPairs.end(),[]( std::pair<unsigned int, double> a, std::pair<unsigned int, double> b) -> bool {return a.second > b.second;} ); + + std::vector<std::pair<unsigned int, double > > barcodeTruePtPairs_truncated; + if (barcodeTruePtPairs.size() < numTruthParticles) numTruthParticles = barcodeTruePtPairs.size(); + barcodeTruePtPairs_truncated.reserve(numTruthParticles); + for ( unsigned int counter = 0; counter < numTruthParticles; counter++) barcodeTruePtPairs_truncated.push_back(barcodeTruePtPairs[counter]); + + for (const auto& thisPair : barcodeTruePtPairs_truncated) ATH_MSG_DEBUG("Truncated loop: barcode and pt are " << thisPair.first << " and " << thisPair.second); + + //make secod vector to store calibraiton hit energies, which should be same size as previous vector + barcodeTrueCalHitEnergy = barcodeTruePtPairs_truncated; + for (auto& thisPair : barcodeTrueCalHitEnergy) thisPair.second = 0.0; + + //now loop on calorimeter cells again to sum up the truth energies of the leading three particles. + for (auto thisCaloCell : *theCellLinks){ + + if (!thisCaloCell){ + ATH_MSG_WARNING("Have invalid pointer to CaloCell"); + continue; + } + + //get the unique calorimeter cell identifier + Identifier cellID = thisCaloCell->ID(); + + //look up the calibration hit that corresponds to this calorimeter cell - we use find because not all calorimeter cells will have calibration hits + std::map<Identifier,std::vector<const CaloCalibrationHit*> >::const_iterator identifierToCaloHitMapIterator = identifierToCaloHitMap.find(cellID); + if (identifierToCaloHitMap.end() == identifierToCaloHitMapIterator) continue; + std::vector<const CaloCalibrationHit*> theseCalibrationHits = (*identifierToCaloHitMapIterator).second; + + for (auto thisCalibrationHit : theseCalibrationHits){ + unsigned int barcode = thisCalibrationHit->particleID(); + double thisCalHitTruthEnergy = thisCalibrationHit->energyEM() + thisCalibrationHit->energyNonEM(); + if (true == m_fullTruthEnergy) thisCalHitTruthEnergy += (thisCalibrationHit->energyEscaped() + thisCalibrationHit->energyInvisible()); + + for (unsigned int counter = 0; counter < barcodeTruePtPairs_truncated.size(); counter++){ + auto thisPair = barcodeTruePtPairs_truncated[counter]; + if (barcode == thisPair.first) { + barcodeTrueCalHitEnergy[counter].second += thisCalHitTruthEnergy; + ATH_MSG_DEBUG("For barcode pair of " << barcode << " and " << thisPair.first << " add truth energy of " << thisCalHitTruthEnergy << " and running total is " << barcodeTrueCalHitEnergy[counter].second); + } + } + + }//calibration hit loop + + }//second loop on calorimeter cells to sum up truth energies of the leading three particles + + for (const auto& thisPair : barcodeTrueCalHitEnergy) ATH_MSG_DEBUG("Truncated loop 2: barcode and true energy are " << thisPair.first << " and " << thisPair.second << " for cluster with e, eta of " << theCaloCluster.e() << " and " << theCaloCluster.eta() ); + + return StatusCode::SUCCESS; + +} diff --git a/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterTruthMapMakerAlgorithm.cxx b/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterTruthMapMakerAlgorithm.cxx new file mode 100644 index 0000000000000000000000000000000000000000..9fd46f82c68ee6048c8f4ba010146b0613d05468 --- /dev/null +++ b/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterTruthMapMakerAlgorithm.cxx @@ -0,0 +1,111 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CaloCalibClusterTruthMapMakerAlgorithm.h" + +StatusCode CaloCalibClusterTruthMapMakerAlgorithm::initialize(){ + + ATH_CHECK(m_tileActiveCaloCalibrationHitReadHandleKey.initialize()); + ATH_CHECK(m_tileInactiveCaloCalibrationHitReadHandleKey.initialize()); + ATH_CHECK(m_tileDMCaloCalibrationHitReadHandleKey.initialize()); + + ATH_CHECK(m_lArActiveCaloCalibrationHitReadHandleKey.initialize()); + ATH_CHECK(m_lArInactiveCaloCalibrationHitReadHandleKey.initialize()); + ATH_CHECK(m_lArDMCaloCalibrationHitReadHandleKey.initialize()); + + ATH_CHECK(m_truthParticleReadHandleKey.initialize()); + + ATH_CHECK(m_mapIdentifierToCalibHitsWriteHandleKey.initialize()); + ATH_CHECK(m_mapTruthBarcodeToTruthParticleWriteHandleKey.initialize()); + + return StatusCode::SUCCESS; + +} + +StatusCode CaloCalibClusterTruthMapMakerAlgorithm::execute(const EventContext& ctx) const{ + + SG::WriteHandle<std::map<Identifier,std::vector<const CaloCalibrationHit*> > > mapIdentifierToCalibHitsWriteHandle(m_mapIdentifierToCalibHitsWriteHandleKey,ctx); + ATH_CHECK(mapIdentifierToCalibHitsWriteHandle.record(std::make_unique<std::map<Identifier,std::vector<const CaloCalibrationHit*> > >())); + fillIdentifierToCaloHitMap(*mapIdentifierToCalibHitsWriteHandle, ctx); + + SG::WriteHandle<std::map<unsigned int,const xAOD::TruthParticle* >> mapTruthBarcodeToTruthParticleWriteHandle(m_mapTruthBarcodeToTruthParticleWriteHandleKey,ctx); + ATH_CHECK(mapTruthBarcodeToTruthParticleWriteHandle.record(std::make_unique<std::map<unsigned int,const xAOD::TruthParticle* > >())); + fillTruthBarcodeToTruthParticleMap(*mapTruthBarcodeToTruthParticleWriteHandle, ctx); + + return StatusCode::SUCCESS; +} + + +StatusCode CaloCalibClusterTruthMapMakerAlgorithm::finalize(){return StatusCode::SUCCESS;} + +void CaloCalibClusterTruthMapMakerAlgorithm::fillIdentifierToCaloHitMap(std::map<Identifier,std::vector<const CaloCalibrationHit*> >& identifierToCaloHitMap, const EventContext& ctx) const{ + + //get calibration hit containers and add them to a vector + + std::vector<SG::ReadHandle<CaloCalibrationHitContainer> > calibrationHitReadHandles; + + SG::ReadHandle<CaloCalibrationHitContainer> tileActiveCaloCalibrationHitReadHandle(m_tileActiveCaloCalibrationHitReadHandleKey,ctx); + if (!tileActiveCaloCalibrationHitReadHandle.isValid()) ATH_MSG_WARNING("Could not retrieve CaloCalibrationHitContainer with key " << tileActiveCaloCalibrationHitReadHandle.key()); + else calibrationHitReadHandles.push_back(tileActiveCaloCalibrationHitReadHandle); + + SG::ReadHandle<CaloCalibrationHitContainer> tileInactiveCaloCalibrationHitReadHandle(m_tileInactiveCaloCalibrationHitReadHandleKey,ctx); + if (!tileInactiveCaloCalibrationHitReadHandle.isValid()) ATH_MSG_WARNING("Could not retrieve CaloCalibrationHitContainer with key " << tileInactiveCaloCalibrationHitReadHandle.key()); + else calibrationHitReadHandles.push_back(tileInactiveCaloCalibrationHitReadHandle); + + SG::ReadHandle<CaloCalibrationHitContainer> tileDMCaloCalibrationHitReadHandle(m_tileDMCaloCalibrationHitReadHandleKey,ctx); + if (!tileDMCaloCalibrationHitReadHandle.isValid()) ATH_MSG_WARNING("Could not retrieve CaloCalibrationHitContainer with key " << tileDMCaloCalibrationHitReadHandle.key()); + else calibrationHitReadHandles.push_back(tileDMCaloCalibrationHitReadHandle); + + SG::ReadHandle<CaloCalibrationHitContainer> lArActiveCaloCalibrationHitReadHandle(m_lArActiveCaloCalibrationHitReadHandleKey,ctx); + if (!lArActiveCaloCalibrationHitReadHandle.isValid()) ATH_MSG_WARNING("Could not retrieve CaloCalibrationHitContainer with key " << lArActiveCaloCalibrationHitReadHandle.key()); + else calibrationHitReadHandles.push_back(lArActiveCaloCalibrationHitReadHandle); + + SG::ReadHandle<CaloCalibrationHitContainer> lArInactiveCaloCalibrationHitReadHandle(m_lArInactiveCaloCalibrationHitReadHandleKey,ctx); + if (!lArInactiveCaloCalibrationHitReadHandle.isValid()) ATH_MSG_WARNING("Could not retrieve CaloCalibrationHitContainer with key " << lArInactiveCaloCalibrationHitReadHandle.key()); + else calibrationHitReadHandles.push_back(lArInactiveCaloCalibrationHitReadHandle); + + SG::ReadHandle<CaloCalibrationHitContainer> lArDMCaloCalibrationHitReadHandle(m_lArDMCaloCalibrationHitReadHandleKey,ctx); + if (!lArDMCaloCalibrationHitReadHandle.isValid()) ATH_MSG_WARNING("Could not retrieve CaloCalibrationHitContainer with key " << lArDMCaloCalibrationHitReadHandle.key()); + else calibrationHitReadHandles.push_back(lArDMCaloCalibrationHitReadHandle); + + for (auto& thisCalibrationHitReadHandle : calibrationHitReadHandles){ + for (auto thisCalibrationHit : *thisCalibrationHitReadHandle){ + + if (!thisCalibrationHit) { + ATH_MSG_WARNING("Got invalid pointer to CaloCalibrationHit in container with key :" << thisCalibrationHitReadHandle.key()); + continue; + } + + //fill the map + Identifier thisIdentifier = thisCalibrationHit->cellID(); + //count returns 1 if the key exists, otherwise it returns 0 + int count = identifierToCaloHitMap.count(thisIdentifier); + if (0 == count) identifierToCaloHitMap[thisIdentifier] = std::vector<const CaloCalibrationHit*>{thisCalibrationHit}; + else identifierToCaloHitMap[thisIdentifier].push_back(thisCalibrationHit); + + }//loop on calibration hits in a container + }//loop over calibration hit containers + +} + +void CaloCalibClusterTruthMapMakerAlgorithm::fillTruthBarcodeToTruthParticleMap(std::map<unsigned int,const xAOD::TruthParticle*>& truthBarcodeToTruthParticleMap, const EventContext& ctx) const{ + + SG::ReadHandle<xAOD::TruthParticleContainer> truthParticleReadHandle(m_truthParticleReadHandleKey, ctx); + + if (!truthParticleReadHandle.isValid()){ + ATH_MSG_WARNING("Invalid ReadHandle to TruthParticles with key " << truthParticleReadHandle.key()); + return; + } + + for ( auto thisTruthParticle : *truthParticleReadHandle){ + + if (!thisTruthParticle){ + ATH_MSG_WARNING("Got invalid pointer to TruthParticle"); + continue; + } + + truthBarcodeToTruthParticleMap[thisTruthParticle->barcode()] = thisTruthParticle; + }//truth particle loop + +} diff --git a/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterTruthMapMakerAlgorithm.h b/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterTruthMapMakerAlgorithm.h new file mode 100644 index 0000000000000000000000000000000000000000..74b7807a49356916a13d1e2f3428f10604669a54 --- /dev/null +++ b/Calorimeter/CaloCalibHitRec/src/CaloCalibClusterTruthMapMakerAlgorithm.h @@ -0,0 +1,74 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef CALOCALIBCLUSTERTRUTHMAPMAKERALGORITHM_H +#define CALOCALIBCLUSTERTRUTHMAPMAKERALGORITHM_H + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "CaloCalibHitRec/CaloCalibDefineTypes.h" + +//EDM Container Classes +#include "CaloSimEvent/CaloCalibrationHitContainer.h" +#include "xAODTruth/TruthParticleContainer.h" + +//EDM Classes +#include "CaloSimEvent/CaloCalibrationHit.h" +#include "xAODTruth/TruthParticle.h" + +//C++ classes +#include <map> +#include <vector> + +/** This algorithm creates several maps used for fast access to information in the calculations related to calibration hit truth energy */ + +class CaloCalibClusterTruthMapMakerAlgorithm : public AthReentrantAlgorithm { + +public: + /** Use base class constructor */ + using AthReentrantAlgorithm::AthReentrantAlgorithm; + + /** Destructor */ + virtual ~CaloCalibClusterTruthMapMakerAlgorithm() {}; + + /* Gaudi algorithm hooks */ + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& ctx) const override; + virtual StatusCode finalize() override; + +private: + /** This fills a map between calorimeter cell identifiers and calibration hits for a fast lookup */ + void fillIdentifierToCaloHitMap(std::map<Identifier,std::vector<const CaloCalibrationHit*> >& identifierToCaloHitMap, const EventContext& ctx) const; + + /** This fills a map between the truth barcode and the pdg Id for a fast lookup */ + void fillTruthBarcodeToTruthParticleMap(std::map<unsigned int,const xAOD::TruthParticle*>& truthBarcodeToTruthParticleMap, const EventContext& ctx) const; + + /** ReadHandleKey for Active Tile Calibration Hits */ + SG::ReadHandleKey<CaloCalibrationHitContainer> m_tileActiveCaloCalibrationHitReadHandleKey{this,"tileActiveCaloCalibrationHitsName","TileCalibHitActiveCell","ReadHandleKey for Active Tile Calibration Hits"}; + + /** ReadHandleKey for Inactive Tile Calibration Hits */ + SG::ReadHandleKey<CaloCalibrationHitContainer> m_tileInactiveCaloCalibrationHitReadHandleKey{this,"tileInactiveCaloCalibrationHitsName","TileCalibHitInactiveCell","ReadHandleKey for Inactive Tile Calibration Hits"}; + + /** ReadHandleKey for Dead Material Tile Calibration Hits */ + SG::ReadHandleKey<CaloCalibrationHitContainer> m_tileDMCaloCalibrationHitReadHandleKey{this,"tileDMCaloCalibrationHitsName","TileCalibHitDeadMaterial","ReadHandleKey for Dead Material Tile Calibration Hits"}; + + /** ReadHandleKey for Active LAr Calibration Hits */ + SG::ReadHandleKey<CaloCalibrationHitContainer> m_lArActiveCaloCalibrationHitReadHandleKey{this,"lArActiveCaloCalibrationHitsName","LArCalibrationHitActive","ReadHandleKey for Active LAr Calibration Hits"}; + + /** ReadHandleKey for Inactive LAr Calibration Hits */ + SG::ReadHandleKey<CaloCalibrationHitContainer> m_lArInactiveCaloCalibrationHitReadHandleKey{this,"lArInactiveCaloCalibrationHitsName","LArCalibrationHitInactive","ReadHandleKey for Inactive LAr Calibration Hits"}; + + /** ReadHandleKey for Dead Material LAr Calibration Hits */ + SG::ReadHandleKey<CaloCalibrationHitContainer> m_lArDMCaloCalibrationHitReadHandleKey{this,"lArDMCaloCalibrationHitsName","LArCalibrationHitDeadMaterial","ReadHandleKey for Dead Material LAr Calibration Hits"}; + + /** ReadHandle for the TruthParticles */ + SG::ReadHandleKey<xAOD::TruthParticleContainer> m_truthParticleReadHandleKey{this,"truthParticlesName","TruthParticles","ReadHandle for the TruthParticles"}; + + /** WriteHandleKey for the map between Identifiers and sets of calibration hits */ + SG::WriteHandleKey<std::map<Identifier,std::vector<const CaloCalibrationHit*> > > m_mapIdentifierToCalibHitsWriteHandleKey{this,"IdentifierToCalibHitsMapName","IdentifierToCalibHitsMap","WriteHandleKey for the map between Identifiers and sets of calibration hits"}; + + /** WriteHandleKey for the map between truth particle barcode and the pdg Id */ + SG::WriteHandleKey<std::map<unsigned int,const xAOD::TruthParticle* > > m_mapTruthBarcodeToTruthParticleWriteHandleKey{this,"TruthBarcodeToTruthParticleMapName","TruthBarcodeTruthParticleMap","WriteHandleKey for the map between truth particle barcode and the pdg Id"}; + +}; +#endif diff --git a/Calorimeter/CaloCalibHitRec/src/components/CaloCalibHitRec_entries.cxx b/Calorimeter/CaloCalibHitRec/src/components/CaloCalibHitRec_entries.cxx index 415a926300c9c1e1f1b7c7d958cda31d1d973b46..8393dee680f7bde0aeb22a9561e99f99c0e031dc 100644 --- a/Calorimeter/CaloCalibHitRec/src/components/CaloCalibHitRec_entries.cxx +++ b/Calorimeter/CaloCalibHitRec/src/components/CaloCalibHitRec_entries.cxx @@ -2,11 +2,15 @@ #include "CaloCalibHitRec/CalibHitIDCheck.h" #include "CaloCalibHitRec/CaloCalibClusterMomentsMaker.h" #include "CaloCalibHitRec/CaloCalibClusterMomentsMaker2.h" - +#include "CaloCalibHitRec/CaloCalibClusterTruthAttributerTool.h" +#include "../CaloCalibClusterTruthMapMakerAlgorithm.h" +#include "../CaloCalibClusterDecoratorAlgorithm.h" DECLARE_COMPONENT( CalibHitToCaloCell ) DECLARE_COMPONENT( CalibHitIDCheck ) DECLARE_COMPONENT( CaloCalibClusterMomentsMaker ) DECLARE_COMPONENT( CaloCalibClusterMomentsMaker2 ) - +DECLARE_COMPONENT( CaloCalibClusterTruthAttributerTool ) +DECLARE_COMPONENT( CaloCalibClusterTruthMapMakerAlgorithm ) +DECLARE_COMPONENT( CaloCalibClusterDecoratorAlgorithm ) diff --git a/Event/xAOD/xAODCaloEvent/xAODCaloEvent/selection.xml b/Event/xAOD/xAODCaloEvent/xAODCaloEvent/selection.xml index 2a191b3424598abe861634bf1b8e64f745fa071b..f6adc21807d412c088badc51cd4c9bcb747974bd 100644 --- a/Event/xAOD/xAODCaloEvent/xAODCaloEvent/selection.xml +++ b/Event/xAOD/xAODCaloEvent/xAODCaloEvent/selection.xml @@ -72,6 +72,7 @@ <class name="std::bitset<3>" /> <class name="xAOD::CaloVertexedClusterBase"/> <class name="xAOD::CaloVertexedTopoCluster"/> + <class name="std::vector<std::vector<std::pair<unsigned int, double > > >"/> <!-- Suppress the unwanted classes found by ROOT 6. --> <!-- Hopefully we can remove these extra lines at one point... --> diff --git a/Event/xAOD/xAODCaloEvent/xAODCaloEvent/xAODCaloEventDict.h b/Event/xAOD/xAODCaloEvent/xAODCaloEvent/xAODCaloEventDict.h index 5e01bdd4c10157d93d5e6ef7b0166a3609961f35..67cdc44988140159bfa666e7f773fbe2042da68b 100644 --- a/Event/xAOD/xAODCaloEvent/xAODCaloEvent/xAODCaloEventDict.h +++ b/Event/xAOD/xAODCaloEvent/xAODCaloEvent/xAODCaloEventDict.h @@ -55,6 +55,7 @@ namespace { std::vector< std::vector< ElementLink< xAOD::CaloClusterContainer_v1 > > > el3; // Additional type(s) needed: std::bitset< 3 > type1; // Using 3 instead of CaloCluster::NSTATES... + std::vector<std::vector<std::pair<unsigned int, double > > > calHitDecoratorType; //BadChannel lists xAOD::CaloClusterBadChannelData_v1 bcd; diff --git a/Reconstruction/PFlow/PFlowUtils/CMakeLists.txt b/Reconstruction/PFlow/PFlowUtils/CMakeLists.txt index ee5a65eff160d5017f601c43e5762d5232599fd7..d57f06fe8af2fdc90f34510df0b0ef524795a84b 100644 --- a/Reconstruction/PFlow/PFlowUtils/CMakeLists.txt +++ b/Reconstruction/PFlow/PFlowUtils/CMakeLists.txt @@ -15,6 +15,7 @@ endif() # Declare the package's dependencies: atlas_depends_on_subdirs( PUBLIC + Calorimeter/CaloCalibHitRec Control/AthToolSupport/AsgTools Event/xAOD/xAODPFlow PRIVATE @@ -37,3 +38,4 @@ endif() # Install files from the package: atlas_install_python_modules( python/*.py ) +atlas_install_joboptions( share/*.py ) diff --git a/Reconstruction/PFlow/PFlowUtils/share/PFlowCalibHitDecorator_algorithms.py b/Reconstruction/PFlow/PFlowUtils/share/PFlowCalibHitDecorator_algorithms.py new file mode 100644 index 0000000000000000000000000000000000000000..c816b24d85495a105fd65de617735c89233f2a3a --- /dev/null +++ b/Reconstruction/PFlow/PFlowUtils/share/PFlowCalibHitDecorator_algorithms.py @@ -0,0 +1,17 @@ +from CaloCalibHitRec.CaloCalibHitRecConf import CaloCalibClusterTruthMapMakerAlgorithm +CaloCalibClusterTruthMapMakerAlgorithm = CaloCalibClusterTruthMapMakerAlgorithm() +topSequence += CaloCalibClusterTruthMapMakerAlgorithm + +from CaloCalibHitRec.CaloCalibHitRecConf import CaloCalibClusterDecoratorAlgorithm +CaloCalibClusterDecoratorAlgorithm = CaloCalibClusterDecoratorAlgorithm() + +from CaloCalibHitRec.CaloCalibHitRecConf import CaloCalibClusterTruthAttributerTool as CalibClusterTruthAttributerTool +CaloCalibClusterTruthAttributerTool = CalibClusterTruthAttributerTool() +CaloCalibClusterDecoratorAlgorithm.TruthAttributerTool = CaloCalibClusterTruthAttributerTool +topSequence += CaloCalibClusterDecoratorAlgorithm + +from PFlowUtils.PFlowUtilsConf import PFlowCalibPFODecoratorAlgorithm +PFlowCalibPFODecoratorAlgorithm = PFlowCalibPFODecoratorAlgorithm() +PFlowCalibPFOTruthAttributerTool = CalibClusterTruthAttributerTool("PFlowCalibPFOTruthAttributerTool") +PFlowCalibPFODecoratorAlgorithm.TruthAttributerTool = PFlowCalibPFOTruthAttributerTool +topSequence+=PFlowCalibPFODecoratorAlgorithm diff --git a/Reconstruction/PFlow/PFlowUtils/share/PFlowCalibHitDecorator_jobOptions.py b/Reconstruction/PFlow/PFlowUtils/share/PFlowCalibHitDecorator_jobOptions.py new file mode 100644 index 0000000000000000000000000000000000000000..cd9dce64c3bd6ee54276f4cfc0dc22f635bf87d5 --- /dev/null +++ b/Reconstruction/PFlow/PFlowUtils/share/PFlowCalibHitDecorator_jobOptions.py @@ -0,0 +1,38 @@ +from AthenaCommon.AthenaCommonFlags import athenaCommonFlags +athenaCommonFlags.FilesInput=["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/RecExRecoTest/mc16_13TeV.361022.Pythia8EvtGen_A14NNPDF23LO_jetjet_JZ2W.recon.ESD.e3668_s3170_r10572_homeMade.pool.root"] + +from RecExConfig.RecFlags import rec +rec.doEgamma.set_Value_and_Lock(False) +#Set to true temporarily due to muon geometry bug, see ATLASRECTS-5160 +rec.doMuon.set_Value_and_Lock(True) + +from RecExConfig.RecAlgsFlags import recAlgs +recAlgs.doEFlow.set_Value_and_Lock(True) + +from CaloRec.CaloRecFlags import jobproperties +jobproperties.CaloRecFlags.Enabled.set_Value_and_Lock(True) +jobproperties.CaloRecFlags.doCaloCluster.set_Value_and_Lock(True) +jobproperties.CaloRecFlags.doCaloTopoCluster.set_Value_and_Lock(True) + +#this turns off CaloCluster2xAOD +rec.doWritexAOD.set_Value_and_Lock(False) +#nothing to say on these +rec.doWriteTAG.set_Value_and_Lock(False) +rec.doTruth.set_Value_and_Lock(False) +rec.doAODCaloCells.set_Value_and_Lock(False) +rec.doTrigger.set_Value_and_Lock(False) +#Turns off xAODRingSetConfWriter +rec.doCaloRinger.set_Value_and_Lock(False) + +#disables VertexCnvAlg +from InDetRecExample.InDetJobProperties import jobproperties +jobproperties.InDetJobProperties.doxAOD.set_Value_and_Lock(False) +#Disables AllExecutedEvents +rec.doFileMetaData.set_Value_and_Lock(False) + +athenaCommonFlags.EvtMax=10 +UserAlgs = ["PFlowUtils/PFlowCalibHitDecorator_algorithms.py"] +include ("RecExCommon/RecExCommon_topOptions.py") +#Add decoration to output item list +StreamAOD.ItemList+=['xAOD::PFOAuxContainer#JetETMissNeutralParticleFlowObjectsAux.+calpfo_NLeadingTruthParticleBarcodeEnergyPairs'] +StreamAOD.ItemList+=['xAOD::CaloClusterAuxContainer#CaloCalTopoClustersAux.SECOND_R.SECOND_LAMBDA.CENTER_MAG.CENTER_LAMBDA.ISOLATION.ENG_BAD_CELLS.N_BAD_CELLS.BADLARQ_FRAC.ENG_POS.AVG_LAR_Q.AVG_TILE_Q.EM_PROBABILITY.BadChannelList.calclus_NLeadingTruthParticleBarcodeEnergyPairs'] diff --git a/Reconstruction/PFlow/PFlowUtils/src/PFlowCalibPFODecoratorAlgorithm.cxx b/Reconstruction/PFlow/PFlowUtils/src/PFlowCalibPFODecoratorAlgorithm.cxx new file mode 100644 index 0000000000000000000000000000000000000000..851aa7bc421dc60757e429d056d9ac82df31ee83 --- /dev/null +++ b/Reconstruction/PFlow/PFlowUtils/src/PFlowCalibPFODecoratorAlgorithm.cxx @@ -0,0 +1,60 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "PFlowCalibPFODecoratorAlgorithm.h" + +//Core classes +#include "StoreGate/WriteDecorHandle.h" + +StatusCode PFlowCalibPFODecoratorAlgorithm::initialize(){ + + ATH_CHECK(m_mapIdentifierToCalibHitsReadHandleKey.initialize()); + ATH_CHECK(m_mapTruthBarcodeToTruthParticleReadHandleKey.initialize()); + + ATH_CHECK(m_pfoWriteDecorHandleKeyNLeadingTruthParticles.initialize()); + + ATH_CHECK(m_truthAttributerTool.retrieve()); + + return StatusCode::SUCCESS; +} + +StatusCode PFlowCalibPFODecoratorAlgorithm::execute(const EventContext& ctx) const{ + + SG::ReadHandle<std::map<Identifier,std::vector<const CaloCalibrationHit*> > > mapIdentifierToCalibHitsReadHandle(m_mapIdentifierToCalibHitsReadHandleKey, ctx); + if(!mapIdentifierToCalibHitsReadHandle.isValid()){ + ATH_MSG_WARNING("Could not retrieve map between Identifier and calibraiton hits from Storegae"); + return StatusCode::FAILURE; + } + + SG::ReadHandle<std::map<unsigned int,const xAOD::TruthParticle* > > mapTruthBarcodeToTruthParticleReadHandle(m_mapTruthBarcodeToTruthParticleReadHandleKey, ctx); + if(!mapTruthBarcodeToTruthParticleReadHandle.isValid()){ + ATH_MSG_WARNING("Could not retrieve map between truth barcode and truth particle from Storegate"); + return StatusCode::FAILURE; + } + + SG::WriteDecorHandle<xAOD::PFOContainer, std::vector< std::pair<unsigned int, double> > > pfoWriteDecorHandleNLeadingTruthParticles(m_pfoWriteDecorHandleKeyNLeadingTruthParticles, ctx); + + StatusCode sc; + + for (auto thisPFO : *pfoWriteDecorHandleNLeadingTruthParticles){ + + const xAOD::CaloCluster* thisCaloCluster = thisPFO->cluster(0); + + std::vector<std::pair<unsigned int, double > > newBarCodeTruthPairs; + sc = m_truthAttributerTool->calculateTruthEnergies(*thisCaloCluster, m_numTruthParticles, *mapIdentifierToCalibHitsReadHandle, *mapTruthBarcodeToTruthParticleReadHandle, newBarCodeTruthPairs); + if (sc == StatusCode::FAILURE) return sc; + + for (const auto& thisPair : newBarCodeTruthPairs) ATH_MSG_DEBUG("Cluster Final loop: Particle with barcode " << thisPair.first << " has truth energy of " << thisPair.second << " for cluster with e, eta " << thisCaloCluster->e() << " and " << thisCaloCluster->eta()); + + pfoWriteDecorHandleNLeadingTruthParticles(*thisPFO) = newBarCodeTruthPairs; + } + + return StatusCode::SUCCESS; +} + +StatusCode PFlowCalibPFODecoratorAlgorithm::finalize(){ + return StatusCode::SUCCESS; +} + + diff --git a/Reconstruction/PFlow/PFlowUtils/src/PFlowCalibPFODecoratorAlgorithm.h b/Reconstruction/PFlow/PFlowUtils/src/PFlowCalibPFODecoratorAlgorithm.h new file mode 100644 index 0000000000000000000000000000000000000000..0ab272466cb2fba706663d0dd87d6f1aae0a5984 --- /dev/null +++ b/Reconstruction/PFlow/PFlowUtils/src/PFlowCalibPFODecoratorAlgorithm.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef PFLOWCALIBPFODECORATORALGORITHM_H +#define PFLOWCALIBPFODECORATORALGORITHM_H + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "CaloCalibHitRec/CaloCalibDefineTypes.h" +#include "CaloCalibHitRec/ICaloCalibClusterTruthAttributerTool.h" + +//EDM Classes +#include "CaloSimEvent/CaloCalibrationHit.h" +#include "xAODTruth/TruthParticle.h" + +//EDM Container Classes +#include "xAODPFlow/PFOContainer.h" + +//C++ classes +#include <map> +#include <vector> + +/** This algorithm decorates xAOD::PFO with calibration hit truth information + +It relies on upstream creation of several maps in CaloCalibClusterTruthMapMakerAlgorithm, stored in Storegate, to provide fast access to required information. +The actual calculations are taken care of my an ICaloCalibClusterTruthAttributerTool. +The user may toggle how many truth particles to consider per xAOD::CaloCluster (represented by a xAOD::PFO, with zero electrical charge, in the particle flow representation of the event), ordered in leading calibration hit truth pt, via a Gaudi Property "NumTruthParticles". */ + +class PFlowCalibPFODecoratorAlgorithm : public AthReentrantAlgorithm { + +public: + /** Constructor from base class */ + using AthReentrantAlgorithm::AthReentrantAlgorithm; + + /** Destructor */ + virtual ~PFlowCalibPFODecoratorAlgorithm() {}; + + /* Gaudi algorithm hooks */ + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& ctx) const override; + virtual StatusCode finalize() override; + +private: + /** ReadHandleKey for the map between Identifiers and sets of calibration hits */ + SG::ReadHandleKey<std::map<Identifier,std::vector<const CaloCalibrationHit*> > > m_mapIdentifierToCalibHitsReadHandleKey{this,"IdentifierToCalibHitsMapName","IdentifierToCalibHitsMap","ReadHandleKey for the map between Identifieirs and sets of calibration hits"}; + + /** ReadHandleKey for the map between truth particle barcode and the pdg Id */ + SG::ReadHandleKey<std::map<unsigned int,const xAOD::TruthParticle* > > m_mapTruthBarcodeToTruthParticleReadHandleKey{this,"TruthBarcodeToTruthParticleMapName","TruthBarcodeTruthParticleMap","ReadHandleKey for the map between truth particle barcode and the pdg Id"}; + + /** Write handle key to decorate PFO with threeN leading truth particle barcode and energy */ + SG::WriteDecorHandleKey<xAOD::PFOContainer> m_pfoWriteDecorHandleKeyNLeadingTruthParticles{this,"PFOWriteDecorHandleKey_NLeadingTruthParticles","JetETMissNeutralParticleFlowObjects.calpfo_NLeadingTruthParticleBarcodeEnergyPairs"}; + + /** ToolHandle to a tool to create the calibration hit truth information that we need for the decoration */ + ToolHandle<ICaloCalibClusterTruthAttributerTool> m_truthAttributerTool{this,"TruthAttributerTool",""," ToolHandle to a tool to create the calibration hit truth information that we need for the decoration"}; + + /** Allow user to set the number of truth particles per clusterCaloCluster or PFO, in descending pt order, for which to store calibration hit enery */ + Gaudi::Property<unsigned int> m_numTruthParticles{this,"NumTruthParticles",3,"Set number of truth particles per CaloCluster/PFO for which we store calibration hit energy"}; + +}; +#endif diff --git a/Reconstruction/PFlow/PFlowUtils/src/components/PFlowUtils_entries.cxx b/Reconstruction/PFlow/PFlowUtils/src/components/PFlowUtils_entries.cxx index 54efb890a95a914bd46adac41762fe73e74dba30..bacff888094dd73f1deec60ccbc899acd9acbb9f 100644 --- a/Reconstruction/PFlow/PFlowUtils/src/components/PFlowUtils_entries.cxx +++ b/Reconstruction/PFlow/PFlowUtils/src/components/PFlowUtils_entries.cxx @@ -2,8 +2,10 @@ #include "PFlowUtils/WeightPFOTool.h" #include "../ParticleFlowEventFilter_r207.h" #include "../CombinePFO.h" +#include "../PFlowCalibPFODecoratorAlgorithm.h" DECLARE_COMPONENT( CP::RetrievePFOTool ) DECLARE_COMPONENT( CP::WeightPFOTool ) DECLARE_COMPONENT( ParticleFlowEventFilter_r207 ) DECLARE_COMPONENT( CombinePFO ) +DECLARE_COMPONENT( PFlowCalibPFODecoratorAlgorithm )