diff --git a/Reconstruction/eflowRec/eflowRec/PFLCCalibTool.h b/Reconstruction/eflowRec/eflowRec/PFLCCalibTool.h new file mode 100644 index 0000000000000000000000000000000000000000..ae9a48321e85c1a3cac9efa9df7630aefda57fe7 --- /dev/null +++ b/Reconstruction/eflowRec/eflowRec/PFLCCalibTool.h @@ -0,0 +1,67 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef PFLCCALIBTOOL_H +#define PFLCCALIBTOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/ToolHandle.h" +#include "xAODCaloEvent/CaloCluster.h" +#include "xAODCaloEvent/CaloClusterContainer.h" +#include "CaloRec/CaloClusterCollectionProcessor.h" +#include "eflowRec/IPFBaseTool.h" +#include "eflowRec/IPFClusterCollectionTool.h" + +#include <cassert> + +class eflowCaloObjectContainer; +class eflowRecCluster; + +static const InterfaceID IID_PFLCCalibTool("PFLCCalibTool", 1, 0); + +class PFLCCalibTool : virtual public IPFBaseTool, public AthAlgTool { + + public: + + PFLCCalibTool(const std::string& type,const std::string& name,const IInterface* parent); + + ~PFLCCalibTool() {} + + static const InterfaceID& interfaceID(); + + StatusCode initialize(); + void execute(eflowCaloObjectContainer* theEflowCaloObjectContainer, xAOD::CaloClusterContainer& theCaloClusterContainer); + StatusCode finalize(); + + private: + + void apply(ToolHandle<CaloClusterCollectionProcessor>& calibTool, xAOD::CaloCluster* cluster); + void applyLocal(ToolHandle<CaloClusterCollectionProcessor>& calibTool, eflowRecCluster *cluster); + void applyLocalWeight(eflowRecCluster* theEFRecCluster); + + /** Tool to put all clusters into a temporary container - then we use this to calculate moments, some of which depend on configuration of nearby clusters */ + ToolHandle<IPFClusterCollectionTool> m_clusterCollectionTool; + + /* Tool for applying local hadronc calibration weights to cells */ + ToolHandle<CaloClusterCollectionProcessor> m_clusterLocalCalibTool; + + /* Tool to deal with out of cluster corrections */ + ToolHandle<CaloClusterCollectionProcessor> m_clusterLocalCalibOOCCTool; + + /* Tool to do Pi0 corrections */ + ToolHandle<CaloClusterCollectionProcessor> m_clusterLocalCalibOOCCPi0Tool; + + /* Tool for correcting clusters at cell level for dead materia */ + ToolHandle<CaloClusterCollectionProcessor> m_clusterLocalCalibDMTool; + + bool m_useLocalWeight; + +}; + +inline const InterfaceID& PFLCCalibTool::interfaceID() +{ + return IID_PFLCCalibTool; +} + +#endif diff --git a/Reconstruction/eflowRec/eflowRec/PFOChargedCreatorTool.h b/Reconstruction/eflowRec/eflowRec/PFOChargedCreatorTool.h new file mode 100644 index 0000000000000000000000000000000000000000..2ea32817837e319945ba2e0aae5d1e928effe6d0 --- /dev/null +++ b/Reconstruction/eflowRec/eflowRec/PFOChargedCreatorTool.h @@ -0,0 +1,63 @@ +#ifndef PFOCHARGEDCREATORTOOL_H +#define PFOCHARGEDCREATORTOOL_H + +#include "eflowRec/IPFBaseTool.h" + +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/ToolHandle.h" +#include "StoreGate/DataHandle.h" + +#include "TrackVertexAssociationTool/ITrackVertexAssociationTool.h" + +#include "xAODPFlow/PFOContainer.h" +#include "xAODTracking/VertexContainer.h" + +class eflowCaloObject; +class eflowCaloObjectContainer; +class eflowRecCluster; + +static const InterfaceID IID_PFOChargedCreatorTool("PFOChargedCreatorTool", 1, 0); + +class PFOChargedCreatorTool : virtual public IPFBaseTool, public AthAlgTool { + +public: + + PFOChargedCreatorTool(const std::string& type,const std::string& name,const IInterface* parent); + + ~PFOChargedCreatorTool() {} + + static const InterfaceID& interfaceID(); + + StatusCode initialize(); + StatusCode execute(eflowCaloObject* energyFlowCaloObject); + void execute(eflowCaloObjectContainer* theEflowCaloObjectContainer, xAOD::CaloClusterContainer& theCaloClusterContainer); + StatusCode finalize(); + +private: + StatusCode setupPFOContainers(); + /** Create the charged PFO */ + void createChargedPFO(eflowCaloObject* energyFlowCaloObject, bool addClusters = false); + /** Function to add links to the vertex to which a charged PFO is matched (using the tracking CP loose vertex association tool) */ + void addVertexLinksToChargedPFO(const xAOD::VertexContainer& theVertexContainer); + + /** Toggle e/p mode */ + bool m_eOverPMode; + + /** ToolHandle to tracking CP loose vertex selection tool */ + ToolHandle<CP::ITrackVertexAssociationTool> m_trackVertexAssociationTool; + + /** ReadHandle for vertex container */ + SG::ReadHandle<xAOD::VertexContainer> m_vertexContainerReadHandle; + + /** WriteHandle for charged PFO */ + SG::WriteHandle<xAOD::PFOContainer> m_chargedPFOContainerWriteHandle; + + +}; + +inline const InterfaceID& PFOChargedCreatorTool::interfaceID() +{ + return IID_PFOChargedCreatorTool; +} + +#endif diff --git a/Reconstruction/eflowRec/share/PFlowHiveExOpts.py b/Reconstruction/eflowRec/share/PFlowHiveExOpts.py index 9a8d491087b8fec572ce20ce32365ee04f53bbfb..59112ddeede41655615ab8a44fb2420eb2476e6d 100644 --- a/Reconstruction/eflowRec/share/PFlowHiveExOpts.py +++ b/Reconstruction/eflowRec/share/PFlowHiveExOpts.py @@ -179,7 +179,7 @@ topSequence += PFClusterSelector from eflowRec.eflowRecConf import PFAlgorithm PFAlgorithm = PFAlgorithm("PFAlgorithm") -PFAlgorithm.PrivateToolList = [] +PFAlgorithm.SubtractionToolList = [] from eflowRec.eflowRecConf import PFCellLevelSubtractionTool PFCellLevelSubtractionTool = PFCellLevelSubtractionTool("PFCellLevelSubtractionTool") @@ -219,10 +219,125 @@ if jobproperties.eflowRecFlags.eflowAlgType == "EOverP": MatchingTool.DistanceType = 'EtaPhiSquareDistance' MatchingTool.MatchCut = 0.2*0.2 # float +PFAlgorithm.SubtractionToolList += [PFCellLevelSubtractionTool] +from eflowRec.eflowRecConf import PFRecoverSplitShowersTool +PFRecoverSplitShowersTool = PFRecoverSplitShowersTool("PFRecoverSplitShowersTool") + +CellEOverPTool_Recover=eflowCellEOverPTool_mc12_JetETMiss("eflowCellEOverPTool_mc12_JetETMiss_Recover") + +PFRecoverSplitShowersTool.eflowCellEOverPTool=CellEOverPTool_Recover + +if jobproperties.eflowRecFlags.recoverIsolatedTracks == True: + PFRecoverSplitShowersTool.RecoverIsolatedTracks = True +if jobproperties.eflowRecFlags.useUpdated2015ChargedShowerSubtraction == False: + PFRecoverSplitShowersTool.useUpdated2015ChargedShowerSubtraction = False + +MatchingTool_Recover = PFTrackClusterMatchingTool() +MatchingTool_Recover.TrackPositionType = 'EM2EtaPhi' # str +MatchingTool_Recover.ClusterPositionType = 'PlainEtaPhi' # str +MatchingTool_Recover.DistanceType = 'EtaPhiSquareDistance' # str +MatchingTool_Recover.MatchCut = 0.2*0.2 # float +PFRecoverSplitShowersTool.PFTrackClusterMatchingTool = MatchingTool + +PFAlgorithm.SubtractionToolList += [PFRecoverSplitShowersTool] -PFAlgorithm.PrivateToolList += [PFCellLevelSubtractionTool] +from eflowRec.eflowRecConf import PFMomentCalculatorTool +PFMomentCalculatorTool = PFMomentCalculatorTool("PFMomentCalculatorTool") + +from CaloRec.CaloRecConf import CaloClusterMomentsMaker +PFClusterMomentsMaker = CaloClusterMomentsMaker("PFClusterMomentsMaker") + +from CaloRec.CaloTopoClusterFlags import jobproperties + +from CaloTools.CaloNoiseToolDefault import CaloNoiseToolDefault +theCaloNoiseTool = CaloNoiseToolDefault() +from AthenaCommon.AppMgr import ToolSvc +ToolSvc += theCaloNoiseTool + +PFClusterMomentsMaker.MaxAxisAngle = 20*deg +PFClusterMomentsMaker.WeightingOfNegClusters = jobproperties.CaloTopoClusterFlags.doTreatEnergyCutAsAbsolute() +PFClusterMomentsMaker.MinBadLArQuality = 4000 +PFClusterMomentsMaker.CaloNoiseTool = theCaloNoiseTool +PFClusterMomentsMaker.UsePileUpNoise = True +PFClusterMomentsMaker.TwoGaussianNoise = jobproperties.CaloTopoClusterFlags.doTwoGaussianNoise() +PFClusterMomentsMaker.OutputLevel = INFO +PFClusterMomentsMaker.MomentsNames = [ + "FIRST_PHI" + ,"FIRST_ETA" + ,"SECOND_R" + ,"SECOND_LAMBDA" + ,"DELTA_PHI" + ,"DELTA_THETA" + ,"DELTA_ALPHA" + ,"CENTER_X" + ,"CENTER_Y" + ,"CENTER_Z" + ,"CENTER_MAG" + ,"CENTER_LAMBDA" + ,"LATERAL" + ,"LONGITUDINAL" + ,"FIRST_ENG_DENS" + ,"ENG_FRAC_EM" + ,"ENG_FRAC_MAX" + ,"ENG_FRAC_CORE" + ,"FIRST_ENG_DENS" + ,"SECOND_ENG_DENS" + ,"ISOLATION" + ,"EM_PROBABILITY" + ,"ENG_POS" + ,"ENG_BAD_CELLS" + ,"N_BAD_CELLS" + ,"BADLARQ_FRAC" + ,"AVG_LAR_Q" + ,"AVG_TILE_Q" + ,"SIGNIFICANCE" +] + +PFMomentCalculatorTool.CaloClusterMomentsMaker = PFClusterMomentsMaker + +from eflowRec.eflowRecConf import PFClusterCollectionTool +PFClusterCollectionTool_default = PFClusterCollectionTool("PFClusterCollectionTool") + +PFMomentCalculatorTool.PFClusterCollectionTool = PFClusterCollectionTool_default + +PFAlgorithm.BaseToolList = [PFMomentCalculatorTool] + +from eflowRec.eflowRecConf import PFLCCalibTool +PFLCCalibTool = PFLCCalibTool("PFLCCalibTool") + +from eflowRec.eflowLocalHadCal import eflowLocalHadCal +LocalHadCal = eflowLocalHadCal() +Calib = LocalHadCal.eflowCaloClusterLocalCalib("PFLCCalibTool") +CalibOO = LocalHadCal.eflowCaloClusterLocalCalibOO("PFLCCalibTool") +CalibOOPi0 = LocalHadCal.eflowCaloClusterLocalCalibOOPi0("PFLCCalibTool") +CalibDM = LocalHadCal.eflowCaloClusterLocalCalibDM("PFLCCalibTool") + +from CaloRec.CaloTopoClusterFlags import jobproperties +if not (jobproperties.CaloTopoClusterFlags.doTopoClusterLocalCalib()): + #load local hadron calibration database, if not done so by CaloRec already + from CaloRec import CaloClusterTopoCoolFolder + +PFLCCalibTool.CaloClusterLocalCalib=Calib +PFLCCalibTool.CaloClusterLocalCalibOOCC=CalibOO +PFLCCalibTool.CaloClusterLocalCalibOOCCPi0=CalibOOPi0 +PFLCCalibTool.CaloClusterLocalCalibDM=CalibDM + +PFClusterCollectionTool_LCCalib = PFClusterCollectionTool("PFClusterCollectionTool_LCCalib") +PFLCCalibTool.eflowRecClusterCollectionTool=PFClusterCollectionTool_LCCalib +PFLCCalibTool.UseLocalWeight = False + +PFAlgorithm.BaseToolList += [PFLCCalibTool] + +from eflowRec.eflowRecConf import PFOChargedCreatorTool +PFOChargedCreatorTool = PFOChargedCreatorTool("PFOChargedCreatorTool") + +from TrackVertexAssociationTool.TrackVertexAssociationToolConf import CP__TightTrackVertexAssociationTool +PFlowTrackVertexAssociationTool = CP__TightTrackVertexAssociationTool(name="PFlowTightCPTool", dzSinTheta_cut=2.0, doPV=True) +PFOChargedCreatorTool.TrackVertexAssociationTool = PFlowTrackVertexAssociationTool + +PFAlgorithm.BaseToolList += [PFOChargedCreatorTool] topSequence += PFAlgorithm @@ -235,6 +350,9 @@ StreamESD=createOutputStream("StreamESD","myESD.pool.root",True) include ("CaloRecEx/CaloRecOutputItemList_jobOptions.py") StreamESD.ItemList+=CaloESDList +StreamESD.ItemList += [ "xAOD::PFOContainer#JetETMissChargedParticleFlowObjectsV2"] +StreamESD.ItemList += [ "xAOD::PFOAuxContainer#JetETMissChargedParticleFlowObjectsV2Aux."] + print StreamESD.ItemList #---------------------------------------------------------------------------------# diff --git a/Reconstruction/eflowRec/src/PFLCCalibTool.cxx b/Reconstruction/eflowRec/src/PFLCCalibTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..80d61f4637faece149e191c96e59f1e6efff7828 --- /dev/null +++ b/Reconstruction/eflowRec/src/PFLCCalibTool.cxx @@ -0,0 +1,130 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "eflowRec/PFLCCalibTool.h" +#include "eflowRec/eflowCaloObject.h" +#include "eflowRec/eflowRecCluster.h" + +#include "xAODCaloEvent/CaloCluster.h" +#include "xAODCaloEvent/CaloClusterContainer.h" +#include "xAODCaloEvent/CaloClusterKineHelper.h" +#include "CaloRec/CaloClusterProcessor.h" + +#include "CaloDetDescr/CaloDetDescrManager.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "CaloUtils/CaloClusterStoreHelper.h" + +PFLCCalibTool::PFLCCalibTool(const std::string& type, const std::string& name, const IInterface* parent) : + AthAlgTool(type, name, parent), + m_clusterCollectionTool("eflowRecClusterCollectionTool", this), + m_clusterLocalCalibTool("CaloClusterLocalCalib", this), + m_clusterLocalCalibOOCCTool("CaloClusterLocalCalib", this), + m_clusterLocalCalibOOCCPi0Tool("CaloClusterLocalCalib", this), + m_clusterLocalCalibDMTool("CaloClusterLocalCalib", this), + m_useLocalWeight(false) { + declareInterface<PFLCCalibTool>(this); + declareProperty("eflowRecClusterCollectionTool", m_clusterCollectionTool, "Tool to choose clusters to use"); + declareProperty("CaloClusterLocalCalib", m_clusterLocalCalibTool, "Cluster Calibration for EFlowRec"); + declareProperty("CaloClusterLocalCalibOOCC", m_clusterLocalCalibOOCCTool, "Cluster CalibrationOOCC for EFlowRec"); + declareProperty("CaloClusterLocalCalibOOCCPi0", m_clusterLocalCalibOOCCPi0Tool, "Cluster CalibrationOOCCPi0 for EFlowRec"); + declareProperty("CaloClusterLocalCalibDM", m_clusterLocalCalibDMTool, "Cluster CalibrationDM for EFlowRec"); + declareProperty("UseLocalWeight", m_useLocalWeight, "Use weight before subtraction"); +} + +StatusCode PFLCCalibTool::initialize() { + + /* Retrieve the cluster collection tool */ + ATH_CHECK(m_clusterCollectionTool.retrieve()); + + /* Retrieve basic local-hadron calibration tool */ + ATH_CHECK(m_clusterLocalCalibTool.retrieve()); + + /* Retrieve tools for out-of-cluster corrections */ + ATH_CHECK(m_clusterLocalCalibOOCCTool.retrieve()); + + ATH_CHECK(m_clusterLocalCalibOOCCPi0Tool.retrieve()); + + /* Retrieve tool for DM corrections */ + ATH_CHECK(m_clusterLocalCalibDMTool.retrieve()); + + return StatusCode::SUCCESS; + +} + +void PFLCCalibTool::execute(eflowCaloObjectContainer* theEflowCaloObjectContainer, xAOD::CaloClusterContainer& theCaloClusterContainer) { + + if (m_useLocalWeight) { + std::unique_ptr<eflowRecClusterContainer> theEFRecCluster = m_clusterCollectionTool->retrieve(theEflowCaloObjectContainer, true); + /* Calibrate each cluster */ + eflowRecClusterContainer::iterator itCluster = theEFRecCluster->begin(); + eflowRecClusterContainer::iterator endCluster = theEFRecCluster->end(); + for (; itCluster != endCluster; ++itCluster) { + eflowRecCluster* cluster = (*itCluster); + applyLocalWeight(cluster); + } + } else { + /* Collect all the clusters in a temporary container (with VIEW_ELEMENTS!) */ + std::unique_ptr<xAOD::CaloClusterContainer> tempClusterContainer = m_clusterCollectionTool->execute(theEflowCaloObjectContainer, true, theCaloClusterContainer); + + /* Calibrate each cluster */ + xAOD::CaloClusterContainer::iterator itCluster = tempClusterContainer->begin(); + xAOD::CaloClusterContainer::iterator endCluster = tempClusterContainer->end(); + for (; itCluster != endCluster; ++itCluster) { + xAOD::CaloCluster* cluster = (*itCluster); + /* Subsequently apply all ClusterLocalCalibTools, print debug output at each stage, if DEBUG it set */ + + apply(m_clusterLocalCalibTool, cluster); + + apply(m_clusterLocalCalibOOCCTool, cluster); + + apply(m_clusterLocalCalibOOCCPi0Tool, cluster); + + apply(m_clusterLocalCalibDMTool, cluster); + + } + + } +} + +StatusCode PFLCCalibTool::finalize() { + return StatusCode::SUCCESS; +} + + +void PFLCCalibTool::apply(ToolHandle<CaloClusterCollectionProcessor>& calibTool, xAOD::CaloCluster* cluster) { + + assert(!m_useLocalWeight); + CaloClusterCollectionProcessor* myCollectionProcessor = &(*calibTool); + CaloClusterProcessor* myCalibProcessor = dynamic_cast<CaloClusterProcessor*>(myCollectionProcessor); + if (myCalibProcessor) { + if (myCalibProcessor->execute(cluster).isFailure()) { + if (msgLvl(MSG::WARNING)) + msg(MSG::WARNING) << "Could not execute " << calibTool.name() << endmsg; + } + } else if (msgLvl(MSG::WARNING)) + msg(MSG::WARNING) << " dynamic_cast provided NULL pointer to CaloClusterProcessor " << endmsg; +} + +void PFLCCalibTool::applyLocalWeight(eflowRecCluster* theEFRecClusters) { + xAOD::CaloCluster* theCluster = theEFRecClusters->getClusterForModification( + eflowCaloObject::getClusterContainerPtr()); + + /* Iterate over cells of old cluster and replicate them with energy weighted by -1 if negative and add it to the new cluster */ + const std::map<IdentifierHash, double> weightMap = theEFRecClusters->getCellsWeight(); + const CaloCell_ID* calo_id = CaloDetDescrManager::instance()->getCaloCell_ID(); + xAOD::CaloCluster::cell_iterator cellIter = theCluster->cell_begin(); + + for (int cellIndex = 0; cellIter != theCluster->cell_end(); cellIter++) { + const CaloCell* pCell = *cellIter; + IdentifierHash myHashId = calo_id->calo_cell_hash(pCell->ID()); + double weight = weightMap.find(myHashId)->second; + theCluster->reweightCell(cellIter, weight); + cellIndex++; + } + + CaloClusterKineHelper::calculateKine(theCluster, true, false); + + theCluster->recoStatus().setStatus(CaloRecoStatus::CALIBRATEDLHC); + +} diff --git a/Reconstruction/eflowRec/src/PFOChargedCreatorTool.cxx b/Reconstruction/eflowRec/src/PFOChargedCreatorTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a29ec3aa36f560344eb66fd400ff30dd79005f23 --- /dev/null +++ b/Reconstruction/eflowRec/src/PFOChargedCreatorTool.cxx @@ -0,0 +1,155 @@ +#include "eflowRec/PFOChargedCreatorTool.h" + +#include "eflowRec/eflowCaloObject.h" +#include "eflowRec/eflowRecCluster.h" +#include "eflowRec/eflowRecTrack.h" + +#include "xAODPFlow/PFOAuxContainer.h" + +PFOChargedCreatorTool::PFOChargedCreatorTool(const std::string& type, const std::string& name, const IInterface* parent) : + AthAlgTool(type, name, parent), + m_eOverPMode(false), + m_trackVertexAssociationTool("",this), + m_vertexContainerReadHandle("PrimaryVertices"), + m_chargedPFOContainerWriteHandle("JetETMissChargedParticleFlowObjectsV2") +{ + declareInterface<PFOChargedCreatorTool>(this); + /* Name of eflow Container to be created */ + declareProperty("EOverPMode", m_eOverPMode); + declareProperty("TrackVertexAssociationTool", m_trackVertexAssociationTool); + declareProperty("VertexContainerName",m_vertexContainerReadHandle); + declareProperty("PFOOutputName", m_chargedPFOContainerWriteHandle); +} + +StatusCode PFOChargedCreatorTool::initialize(){ + + ATH_CHECK(m_trackVertexAssociationTool.retrieve()); + + ATH_CHECK(m_vertexContainerReadHandle.initialize()); + + ATH_CHECK(m_chargedPFOContainerWriteHandle.initialize()); + + return StatusCode::SUCCESS; +} + +StatusCode PFOChargedCreatorTool::execute(eflowCaloObject* energyFlowCaloObject){ + + ATH_MSG_DEBUG("Executing eflowObjectCreatorTool "); + + if (m_eOverPMode) createChargedPFO(energyFlowCaloObject, true); + else createChargedPFO(energyFlowCaloObject); + + const xAOD::VertexContainer* theVertexContainer = m_vertexContainerReadHandle.ptr(); + addVertexLinksToChargedPFO(*theVertexContainer); + + return StatusCode::SUCCESS; + +} + +void PFOChargedCreatorTool::execute(eflowCaloObjectContainer* theEflowCaloObjectContainer, xAOD::CaloClusterContainer& theCaloClusterContainer){ + + ATH_MSG_DEBUG("Processing eflowCaloObjectContainer"); + + m_chargedPFOContainerWriteHandle.record(std::make_unique<xAOD::PFOContainer>(),std::make_unique<xAOD::PFOAuxContainer>()); + + /* Create Charged PFOs from all eflowCaloObjects */ + unsigned int nEFCaloObs = theEflowCaloObjectContainer->size(); + for (unsigned int iEFCalOb = 0; iEFCalOb < nEFCaloObs; ++iEFCalOb){ + eflowCaloObject* thisEflowCaloObject = theEflowCaloObjectContainer->at(iEFCalOb); + if (execute(thisEflowCaloObject).isFailure()){ + ATH_MSG_WARNING("Execute failed for one eflowCaloObject. "); + continue; + } + } + + +} + +StatusCode PFOChargedCreatorTool::finalize(){ return StatusCode::SUCCESS; } + +void PFOChargedCreatorTool::createChargedPFO(eflowCaloObject* energyFlowCaloObject, bool addClusters){ + + /* Loop over all tracks in the eflowCaloObject */ + int nTracks = energyFlowCaloObject->nTracks(); + for (int iTrack = 0; iTrack < nTracks; ++iTrack) { + + eflowRecTrack* efRecTrack = energyFlowCaloObject->efRecTrack(iTrack); + + /* Skip tracks that haven't been subtracted */ + if (false == m_eOverPMode){ + if (!efRecTrack->isSubtracted()){ continue; } + } + + /* Create new xAOD::PFO */ + xAOD::PFO* thisPFO = new xAOD::PFO(); + m_chargedPFOContainerWriteHandle->push_back(thisPFO); + + /* Get the track elementLink and add it to the xAOD:PFO */ + ElementLink<xAOD::TrackParticleContainer> theTrackLink = efRecTrack->getTrackElemLink(); + bool isSet = thisPFO->setTrackLink(theTrackLink); + if (!isSet) { msg(MSG::WARNING) << "Could not set Track B in PFO " << endmsg; } + thisPFO->setCharge(efRecTrack->getTrack()->charge()); + + std::pair<double,double> etaPhi(0.0,0.0); + + if (m_eOverPMode){ + /* In EOverPMode want charged eflowObjects to have extrapolated eta,phi as coordinates + * (needed for analysis of EOverP Data) */ + etaPhi = efRecTrack->getTrackCaloPoints().getEM2etaPhi(); + + /*add information to xAOD*/ + xAOD::PFODetails::PFOAttributes myAttribute_layerHED = xAOD::PFODetails::PFOAttributes::eflowRec_layerHED; + thisPFO->setAttribute<int>(myAttribute_layerHED,efRecTrack->getLayerHED() ); + + xAOD::PFODetails::PFOAttributes myAttribute_layerVectorCellOrdering = xAOD::PFODetails::PFOAttributes::eflowRec_layerVectorCellOrdering; + thisPFO->setAttribute<std::vector<int> >(myAttribute_layerVectorCellOrdering,efRecTrack->getLayerCellOrderVector() ); + + xAOD::PFODetails::PFOAttributes myAttribute_radiusVectorCellOrdering = xAOD::PFODetails::PFOAttributes::eflowRec_radiusVectorCellOrdering; + thisPFO->setAttribute<std::vector<float> >(myAttribute_radiusVectorCellOrdering,efRecTrack->getRadiusCellOrderVector() ); + + xAOD::PFODetails::PFOAttributes myAttribute_avgEdensityVectorCellOrdering = xAOD::PFODetails::PFOAttributes::eflowRec_avgEdensityVectorCellOrdering; + thisPFO->setAttribute<std::vector<float> >(myAttribute_avgEdensityVectorCellOrdering,efRecTrack->getAvgEDensityCellOrderVector() ); + } else { + /* In normal mode we want te track eta,phi at the perigee */ + etaPhi.first = efRecTrack->getTrack()->eta(); + etaPhi.second = efRecTrack->getTrack()->phi(); + } + /* Set the 4-vector of the xAOD::PFO */ + thisPFO->setP4(efRecTrack->getTrack()->pt(), etaPhi.first, etaPhi.second, efRecTrack->getTrack()->m()); + + /* Add the amount of energy the track was expected to deposit in the calorimeter - this is needed to calculate the charged weight in the jet finding */ + xAOD::PFODetails::PFOAttributes myAttribute_tracksExpectedEnergyDeposit = xAOD::PFODetails::PFOAttributes::eflowRec_tracksExpectedEnergyDeposit; + thisPFO->setAttribute<float>(myAttribute_tracksExpectedEnergyDeposit,efRecTrack->getEExpect() ); + + /* Flag if this track was in a dense environment for later checking */ + xAOD::PFODetails::PFOAttributes myAttribute_isInDenseEnvironment = xAOD::PFODetails::PFOAttributes::eflowRec_isInDenseEnvironment; + //There is some issue using bools - when written to disk they convert to chars. So lets store the bool as an int. + thisPFO->setAttribute<int>(myAttribute_isInDenseEnvironment, (efRecTrack->isInDenseEnvironment())); + + /* Optionally we add the links to clusters to the xAOD::PFO */ + if (true == addClusters){ + unsigned int nClusters = energyFlowCaloObject->nClusters(); + for (unsigned int iCluster = 0; iCluster < nClusters; ++iCluster){ + eflowRecCluster* thisEfRecCluster = energyFlowCaloObject->efRecCluster(iCluster); + ElementLink<xAOD::CaloClusterContainer> theClusLink = thisEfRecCluster->getClusElementLink(); + bool isSet = thisPFO->addClusterLink(theClusLink); + if (!isSet) msg(MSG::WARNING) << "Could not set Cluster in PFO " << endmsg; + }//cluster loop + }//addClusters is set to true - so we added the clusters to the xAOD::PFO + + }//loop over the tracks on the eflowCaloObject +} + +void PFOChargedCreatorTool::addVertexLinksToChargedPFO(const xAOD::VertexContainer& theVertexContainer){ + + //This is a loop on all xAOD::PFO with non-zero charge + for (auto theChargedPFO : *m_chargedPFOContainerWriteHandle){ + const xAOD::TrackParticle* theTrack = theChargedPFO->track(0); + if (theTrack){ + ElementLink< xAOD::VertexContainer> theVertexLink = m_trackVertexAssociationTool->getUniqueMatchVertexLink(*theTrack,theVertexContainer); + bool haveSetLink = theChargedPFO->setVertexLink(theVertexLink); + if (!haveSetLink) msg(MSG::WARNING) << " Could not set vertex link on charged PFO " << endmsg; + }//if valid pointer to xAOD::TrackParticle + } + +} diff --git a/Reconstruction/eflowRec/src/components/eflowRec_entries.cxx b/Reconstruction/eflowRec/src/components/eflowRec_entries.cxx index a54861e592227334a27a4a7f418730cb38357384..b6f2d2b02eac082fc45aac844da33b109f63e272 100644 --- a/Reconstruction/eflowRec/src/components/eflowRec_entries.cxx +++ b/Reconstruction/eflowRec/src/components/eflowRec_entries.cxx @@ -23,6 +23,8 @@ #include "eflowRec/PFRecoverSplitShowersTool.h" #include "eflowRec/PFMomentCalculatorTool.h" #include "eflowRec/PFClusterCollectionTool.h" +#include "eflowRec/PFLCCalibTool.h" +#include "eflowRec/PFOChargedCreatorTool.h" #include "GaudiKernel/DeclareFactoryEntries.h" DECLARE_ALGORITHM_FACTORY( eflowBuilder ) @@ -39,6 +41,8 @@ DECLARE_TOOL_FACTORY( PFCellLevelSubtractionTool ) DECLARE_TOOL_FACTORY( PFRecoverSplitShowersTool ) DECLARE_TOOL_FACTORY( PFMomentCalculatorTool ) DECLARE_TOOL_FACTORY( PFClusterCollectionTool ) +DECLARE_TOOL_FACTORY( PFLCCalibTool ) +DECLARE_TOOL_FACTORY( PFOChargedCreatorTool ) DECLARE_TOOL_FACTORY( eflowRecoverSplitShowersTool ) DECLARE_TOOL_FACTORY( eflowCellLevelSubtractionTool ) DECLARE_TOOL_FACTORY( eflowLCCalibTool ) @@ -66,6 +70,8 @@ DECLARE_FACTORY_ENTRIES(eflowRec) { DECLARE_TOOL( PFRecoverSplitShowersTool ) DECLARE_TOOL( PFMomentCalculatorTool ) DECLARE_TOOL( PFClusterCollectionTool ) + DECLARE_TOOL( PFLCCalibTool ) + DECLARE_TOOL( PFOChargedCreatorTool ) DECLARE_TOOL ( eflowRecoverSplitShowersTool ) DECLARE_TOOL ( eflowCellLevelSubtractionTool ) DECLARE_TOOL ( eflowMomentCalculatorTool )