diff --git a/Reconstruction/tauRecTools/Root/LinkDef.h b/Reconstruction/tauRecTools/Root/LinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..f9fa452558b6689ef1035f603096f64ab7ab8510 --- /dev/null +++ b/Reconstruction/tauRecTools/Root/LinkDef.h @@ -0,0 +1,12 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; +#pragma link C++ nestedclass; + +#endif diff --git a/Reconstruction/tauRecTools/Root/TauBuilderTool.cxx b/Reconstruction/tauRecTools/Root/TauBuilderTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..239735e88a813f92568e64df768723f5ccd466e3 --- /dev/null +++ b/Reconstruction/tauRecTools/Root/TauBuilderTool.cxx @@ -0,0 +1,308 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "tauRecTools/TauBuilderTool.h" + +#include "xAODJet/Jet.h" +#include "xAODJet/JetContainer.h" + +#include "xAODTau/TauJetContainer.h" +#include "xAODTau/TauJetAuxContainer.h" +#include "xAODTau/TauDefs.h" + +#include "tauRecTools/TauEventData.h" + + +//________________________________________ +TauBuilderTool::TauBuilderTool(const std::string& type) : + asg::AsgTool(type), + m_tauContainerName("TauJets"), + m_tauAuxContainerName("TauJetsAux."), + m_seedContainerName(""), + m_maxEta(2.5), + m_minPt(10000), + m_doCreateTauContainers(false) +{ + declareProperty("TauContainer", m_tauContainerName); + declareProperty("TauAuxContainer", m_tauAuxContainerName); + declareProperty("SeedContainer", m_seedContainerName); + declareProperty("MaxEta", m_maxEta); + declareProperty("MinPt", m_minPt); + declareProperty("doCreateTauContainers", m_doCreateTauContainers); + declareProperty("Tools", m_tools, "List of ITauToolBase tools"); +} + +//________________________________________ +TauBuilderTool::~TauBuilderTool(){} + +//________________________________________ +StatusCode TauBuilderTool::initialize(){ + StatusCode sc; + + //ATH_MSG_INFO("FF::TauBuilder :: initialize()"); + + //------------------------------------------------------------------------- + // No tools allocated! + //------------------------------------------------------------------------- + if (m_tools.size() == 0) { + ATH_MSG_ERROR("no tools given!"); + return StatusCode::FAILURE; + } + + //------------------------------------------------------------------------- + // Allocate tools + //------------------------------------------------------------------------- + ToolHandleArray<ITauToolBase> ::iterator itT = m_tools.begin(); + ToolHandleArray<ITauToolBase> ::iterator itTE = m_tools.end(); + ATH_MSG_INFO("List of tools in execution sequence:"); + ATH_MSG_INFO("------------------------------------"); + + unsigned int tool_count = 0; + + for (; itT != itTE; ++itT) { + sc = itT->retrieve(); + if (sc.isFailure()) { + ATH_MSG_WARNING("Cannot find tool named <" << *itT << ">"); + } else { + ++tool_count; + //ATH_MSG_INFO((*itT)->type() << " - " << (*itT)->name()); + ATH_MSG_INFO((*itT)->name()); + //If you want to utlize TauCandidate In Tools, + //decalre TauCandidate in your class, and pass its address + //to function below + (*itT)->setTauEventData(&m_data); + } + } + ATH_MSG_INFO(" "); + ATH_MSG_INFO("------------------------------------"); + + if (tool_count == 0) { + ATH_MSG_ERROR("could not allocate any tool!"); + return StatusCode::FAILURE; + } + + /////////////////////////////////////////////////////////////////////////// + + return StatusCode::SUCCESS; +} + +//________________________________________ +StatusCode TauBuilderTool::execute(){ + + StatusCode sc; + m_data.clear(); + + xAOD::TauJetContainer * pContainer = 0; + xAOD::TauJetAuxContainer* pAuxContainer = 0; + + + + if (m_doCreateTauContainers) { + //------------------------------------------------------------------------- + // Create and Record containers + //------------------------------------------------------------------------- + + pContainer = new xAOD::TauJetContainer(); + sc = evtStore()->record( pContainer, m_tauContainerName ) ; + if (sc.isFailure()) { + ATH_MSG_ERROR("Unable to record TauContainer in TDS"); + delete pContainer; + return StatusCode::FAILURE; + } + + pAuxContainer = new xAOD::TauJetAuxContainer(); + sc = evtStore()->record( pAuxContainer, m_tauAuxContainerName ) ; + if (sc.isFailure()) { + ATH_MSG_ERROR("Unable to record TauContainer in TDS"); + delete pContainer; + return StatusCode::FAILURE; + } + + pContainer->setStore( pAuxContainer ); + ATH_MSG_DEBUG( "Recorded xAOD tau jets with key: " + << m_tauAuxContainerName ); + + } else { + //------------------------------------------------------------------------- + // retrieve Tau Containers from StoreGate + //------------------------------------------------------------------------- + sc = evtStore()->retrieve(pContainer, m_tauContainerName); + if (sc.isFailure()) { + ATH_MSG_FATAL("Failed to retrieve " << m_tauContainerName); + return StatusCode::FAILURE; + } + + sc = evtStore()->retrieve(pAuxContainer, m_tauAuxContainerName); + if (sc.isFailure()) { + ATH_MSG_FATAL("Failed to retrieve " << m_tauAuxContainerName); + return StatusCode::FAILURE; + } + + } + + //not strictly necessary to set the containers + //but probably safer for tools to access + //the tau container via TauEventData than + //IParticle::container() (griffith) + m_data.xAODTauContainer = pContainer; + m_data.tauAuxContainer = pAuxContainer; + + //------------------------------------------------------------------------- + // Initialize tools for this event + //------------------------------------------------------------------------- + ToolHandleArray<ITauToolBase> ::iterator itT = m_tools.begin(); + ToolHandleArray<ITauToolBase> ::iterator itTE = m_tools.end(); + for (; itT != itTE; ++itT) { + sc = (*itT)->eventInitialize(); + if (sc != StatusCode::SUCCESS) + return StatusCode::FAILURE; + } + + //////////////////////////////////////////////////////// + + + //--------------------------------------------------------------------- + // Retrieve seed Container from TDS, return `failure' if not + // existing + //--------------------------------------------------------------------- + const xAOD::JetContainer * pSeedContainer; + sc = evtStore()->retrieve(pSeedContainer, m_seedContainerName); + // XXX still need to fix this. Currently only handle jets + // const DataHandle<INavigable4MomentumCollection> pSeedContainer; + // sc = evtStore()->retrieve(pSeedContainer, m_seedContainerName); + if (sc.isFailure() || !pSeedContainer) { + ATH_MSG_FATAL("No seed container with key:" << m_seedContainerName); + return StatusCode::FAILURE; + } + + //probably not necessary, but in case a tool wants this in the future + //probably safer to retrieve via TauEventData than + //*(pTau.jetLink())->container() + m_data.seedContainer = pSeedContainer; + + //--------------------------------------------------------------------- + // Loop over seeds + //--------------------------------------------------------------------- + xAOD::JetContainer::const_iterator itS = pSeedContainer->begin(); + xAOD::JetContainer::const_iterator itSE = pSeedContainer->end(); + // XXX still need to fix this. Currently only handle jets + // INavigable4MomentumCollection::const_iterator itS = pSeedContainer->begin(); + // INavigable4MomentumCollection::const_iterator itSE = pSeedContainer->end(); + + ATH_MSG_VERBOSE("Number of seeds in the container: " << pSeedContainer->size()); + + for (; itS != itSE; ++itS) { + const xAOD::Jet *pSeed = (*itS); + ATH_MSG_VERBOSE("Seeds eta:" << pSeed->eta() << ", pt:" << pSeed->pt()); + + if (fabs(pSeed->eta()) > m_maxEta) { + ATH_MSG_VERBOSE("--> Seed rejected, eta out of range!"); + continue; + } + + if (fabs(pSeed->pt()) < m_minPt) { + ATH_MSG_VERBOSE("--> Seed rejected, pt out of range!"); + continue; + } + + //----------------------------------------------------------------- + // Seed passed cuts --> create tau candidate + //----------------------------------------------------------------- + xAOD::TauJet* pTau = new xAOD::TauJet(); + pContainer->push_back( pTau ); + pTau->setJet(pSeedContainer, pSeed); + + //----------------------------------------------------------------- + // Process the candidate + //----------------------------------------------------------------- + ToolHandleArray<ITauToolBase>::iterator itT = m_tools.begin(); + ToolHandleArray<ITauToolBase>::iterator itTE = m_tools.end(); + + //----------------------------------------------------------------- + // Loop stops when Failure indicated by one of the tools + //----------------------------------------------------------------- + for (; itT != itTE; ++itT) { + ATH_MSG_VERBOSE("Invoking tool " << (*itT)->name()); + + sc = (*itT)->execute(*pTau); + + if (sc.isFailure()) + break; + } + + if (sc.isSuccess()) { + + + ATH_MSG_VERBOSE("The tau candidate has been registered"); + + //----------------------------------------------------------------- + // Process the candidate using endTools + //----------------------------------------------------------------- + //keep this here for future use (in case more than one seeding algo exist) + /* + ToolHandleArray<ITauToolBase> ::iterator p_itET = m_endTools.begin(); + ToolHandleArray<ITauToolBase> ::iterator p_itETE = m_endTools.end(); + for (; p_itET != p_itETE; ++p_itET) { + ATH_MSG_VERBOSE("Invoking endTool " << (*p_itET)->name()); + p_sc = (*p_itET)->execute(&m_data); + if (p_sc.isFailure()) + break; + } + */ + ////////////////////////////////////////////////////// + + } else if (!sc.isSuccess()) { + //TODO:cleanup of EndTools not necessary?? + //keep this here for future use (in case more than one seeding algo exist) + /* + ToolHandleArray<ITauToolBase> ::iterator p_itT1 = m_tools.begin(); + for (; p_itT1 != p_itT; ++p_itT1) + (*p_itT1)->cleanup(&m_data); + (*p_itT1)->cleanup(&m_data); + */ + //m_data.xAODTauContainer->pop_back(); + pContainer->pop_back(); + } else + //m_data.xAODTauContainer->pop_back(); + pContainer->pop_back(); + } + + + + //------------------------------------------------------------------------- + // Finalize tools for this event + //------------------------------------------------------------------------- + + itT = m_tools.begin(); + itTE = m_tools.end(); + for (; itT != itTE; ++itT) { + sc = (*itT)->eventFinalize(); + if (sc != StatusCode::SUCCESS) + return StatusCode::FAILURE; + } + + //keep this here for future use (in case more than one seeding algo exist) + /* + p_itET = m_endTools.begin(); + p_itETE = m_endTools.end(); + for (; p_itET != p_itETE; ++p_itET) { + p_sc = (*p_itET)->eventFinalize(&m_data); + if (p_sc != StatusCode::SUCCESS) + return StatusCode::FAILURE; + } + */ + + /////////////////////////////////////////////////////// + + // locking of containers is moved to separate tau tool + + return StatusCode::SUCCESS; +} + +//________________________________________ +StatusCode TauBuilderTool::finalize(){ + + return StatusCode::SUCCESS; +} + diff --git a/Reconstruction/tauRecTools/Root/TauCalibrateLC.cxx b/Reconstruction/tauRecTools/Root/TauCalibrateLC.cxx new file mode 100644 index 0000000000000000000000000000000000000000..0ad9767fb2d1dcc7e3e649c586b87b612d37649f --- /dev/null +++ b/Reconstruction/tauRecTools/Root/TauCalibrateLC.cxx @@ -0,0 +1,292 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//tau +#include "tauRecTools/TauCalibrateLC.h" +#include "xAODTau/TauJet.h" +#include "tauRecTools/TauEventData.h" + +//compilation error if attempting to include CLHEP first +//ASGTOOL_ATHENA defined here: +//https://svnweb.cern.ch/trac/atlasoff/browser/Control/AthToolSupport/AsgTools/trunk/AsgTools/AsgToolsConf.h +//included eventually from ITauToolBase +#ifdef ASGTOOL_ATHENA +#include "CLHEP/Vector/LorentzVector.h" +#include "CLHEP/Units/SystemOfUnits.h" +using CLHEP::GeV; +#else +#define GeV 1000 +#endif + +// root +#include "TFile.h" +#include "TF1.h" +#include "TH1D.h" + +/********************************************************************/ +TauCalibrateLC::TauCalibrateLC(const std::string& name) : +TauRecToolBase(name), +m_doEnergyCorr(false), +m_doAxisCorr(false), +m_printMissingContainerINFO(true), +m_clusterCone(0.2) //not used +{ + declareProperty("tauContainerKey", tauContainerKey = "TauJets"); + declareProperty("calibrationFile", calibrationFile = "EnergyCalibrationLC2012.root"); + declareProperty("vertexContainerKey", vertexContainerKey = "PrimaryVertices"); + declareProperty("doEnergyCorrection", m_doEnergyCorr); + declareProperty("doAxisCorrection", m_doAxisCorr); + declareProperty("ClusterCone", m_clusterCone); //not used +} + +/********************************************************************/ +TauCalibrateLC::~TauCalibrateLC() { +} + +/********************************************************************/ +StatusCode TauCalibrateLC::initialize() { + + std::string fullPath = find_file(calibrationFile); + + TFile * file = TFile::Open(fullPath.c_str(), "READ"); + + if (!file) { + ATH_MSG_FATAL("Failed to open " << fullPath); + return StatusCode::FAILURE; + } + + // get the histogram defining eta binning + std::string key = "etaBinning"; + TObject * obj = file->Get(key.c_str()); + etaBinHist = NULL; + if (obj) { + etaBinHist = dynamic_cast<TH1 *> (obj); + } + if (etaBinHist) { + TH1 * tmp = const_cast<TH1*> (etaBinHist); + tmp->SetDirectory(0); + } else { + ATH_MSG_FATAL("Failed to get an object with key " << key); + return StatusCode::FAILURE; + } + + //retrieve number of eta bins from file + m_nEtaBins = etaBinHist->GetNbinsX(); //member var + if (m_nEtaBins==6) + ATH_MSG_INFO("using 2011 tau energy calibration"); + else if (m_nEtaBins==5) + ATH_MSG_INFO("using 2012 tau energy calibration"); + else { + ATH_MSG_FATAL("Wrong or broken tau energy calibration file"); + return StatusCode::FAILURE; + } + + // get the histogram with eta corrections + key = "etaCorrection"; + obj = file->Get(key.c_str()); + etaCorrectionHist = NULL; + if (obj) { + etaCorrectionHist = dynamic_cast<TH1 *> (obj); + } + if (etaCorrectionHist) { + TH1 * tmp = const_cast<TH1*> (etaCorrectionHist); + tmp->SetDirectory(0); + } else { + ATH_MSG_FATAL("Failed to get an object with key " << key); + return StatusCode::FAILURE; + } + + TString tmpSlopKey[nProngBins] = {"slopeNPV1P", "slopeNPV3P"}; + TString tmpFuncBase[nProngBins] = {"OneP_Eta_", "MultiP_Eta_"}; + + for (int i = 0; i < nProngBins; i++) { + obj = file->Get(tmpSlopKey[i]); // get pile-up slope histograms + slopeNPVHist[i] = NULL; + if (obj) { + slopeNPVHist[i] = dynamic_cast<TH1 *> (obj); + } + if (slopeNPVHist[i]) { + TH1 * tmp = const_cast<TH1*> (slopeNPVHist[i]); + tmp->SetDirectory(0); + } else { + ATH_MSG_FATAL("Failed to get an object with key " << tmpSlopKey[i]); + return StatusCode::FAILURE; + } + + for (int j = 0; j < m_nEtaBins; j++) { + TString key = tmpFuncBase[i]; + key += j; + TObject * obj = file->Get(key); + calibFunc[i][j] = NULL; + if (obj) { + calibFunc[i][j] = dynamic_cast<TF1*> (obj); + } + if (calibFunc[i][j]) { + // The cast succeeded. + } else { + ATH_MSG_FATAL("Failed to get an object with key " << key); + return StatusCode::FAILURE; + } + } + } + m_averageNPV = slopeNPVHist[0]->GetBinContent(0); // underflow is the average number of reconstructed primary vertices + m_minNTrackAtVertex = static_cast<unsigned int> (slopeNPVHist[0]->GetBinContent(slopeNPVHist[0]->GetNbinsX() + 1)); //overflow is the minimum number of tracks at vertex + + ATH_MSG_DEBUG("averageNPV = " << m_averageNPV); + ATH_MSG_DEBUG("minimum number of tracks at primary vertex = " << m_minNTrackAtVertex); + + file->Close(); + + return StatusCode::SUCCESS; +} + +/********************************************************************/ +StatusCode TauCalibrateLC::execute(xAOD::TauJet& pTau) +{ + + // energy calibration depends on number of tracks - 1p or Mp + int prongBin = 1; //Mp + if (pTau.nTracks() <= 1) prongBin = 0; //1p + + // set tau energy scale + if (m_doEnergyCorr) { + + // get detector axis values + double eta = pTau.etaDetectorAxis(); + double absEta = std::abs(eta); + int etaBin = etaBinHist->GetXaxis()->FindBin(absEta) - 1; + + if (etaBin>=m_nEtaBins) etaBin = m_nEtaBins-1; // correction from last bin should be applied on all taus outside stored eta range + + // get primary vertex container + StatusCode sc; + const xAOD::VertexContainer * vxContainer = 0; + + // for tau trigger + bool inTrigger = tauEventData()->inTrigger(); + + int nVertex = 0; + + // Only retrieve the container if we are not in trigger + if (sc.isFailure() || !inTrigger ) { + // try standard + if (evtStore()->retrieve(vxContainer, vertexContainerKey).isFailure() || !vxContainer) { + if (m_printMissingContainerINFO) { + ATH_MSG_WARNING(vertexContainerKey << " container not found --> skip TauEnergyCalibrationLC (no further info) "); + m_printMissingContainerINFO=false; + } + return StatusCode::SUCCESS; + } + + // Calculate nVertex + xAOD::VertexContainer::const_iterator vx_iter = vxContainer->begin(); + xAOD::VertexContainer::const_iterator vx_end = vxContainer->end(); + + for (; vx_iter != vx_end; ++vx_iter) { + if ((*vx_iter)->nTrackParticles() >= m_minNTrackAtVertex) + ++nVertex; + } + + ATH_MSG_DEBUG("calculated nVertex " << nVertex ); + + } else { + + StatusCode scMu = StatusCode::FAILURE; + double muTemp = 0.0; + + if (tauEventData()->hasObject("AvgInteractions")) scMu = tauEventData()->getObject("AvgInteractions", muTemp); + + if(scMu.isSuccess()){ + ATH_MSG_DEBUG("AvgInteractions object in tau candidate = " << muTemp); + nVertex = muTemp; + } else { + ATH_MSG_DEBUG("No AvgInteractions object in tau candidate - using default value"); + nVertex = m_averageNPV; + } + + } + + // get detector axis energy + // was saved by TauAxisSetter + double energyLC = pTau.p4(xAOD::TauJetParameters::DetectorAxis).E() / GeV; //was sumClusterVector.e() / GeV; + + if (energyLC <= 0) { + ATH_MSG_DEBUG("tau energy at LC scale is " << energyLC << "--> set energy=0.001"); + //TODO: we can not set tau energy to 0 due to bug in P4Helpers during deltaR calculation + //will set it to 0.001 MeV + pTau.setP4(0.001, pTau.eta(), pTau.phi(), pTau.m()); + return StatusCode::SUCCESS; + } + + double slopeNPV = slopeNPVHist[prongBin]->GetBinContent(etaBin + 1); + double offset = slopeNPV * (nVertex - m_averageNPV); + + // FF: March,2014 + // no offset correction for trigger + //if (inTrigger) offset = 0.; + + if (energyLC - offset <= 0) { + ATH_MSG_DEBUG("after pile-up correction energy would be = " << energyLC - offset << " --> setting offset=0 now!"); + offset = 0; + } + + // apply offset correction + double energyPileupCorr = energyLC - offset; + + double calibConst = 1.0; + if (energyPileupCorr > 0 and energyPileupCorr < 10000) // from 0 to 10 TeV + { + calibConst = calibFunc[prongBin][etaBin]->Eval(energyPileupCorr); + + if (calibConst <= 0) { + ATH_MSG_DEBUG("calibration constant = " << calibConst); + ATH_MSG_DEBUG("prongBin = " << prongBin); + ATH_MSG_DEBUG("etaBin = " << etaBin); + ATH_MSG_DEBUG("energyPileupCorr = " << energyPileupCorr); + ATH_MSG_DEBUG("energyLC = " << energyLC); + calibConst = 1.0; + } + } + + double energyFinal = energyPileupCorr / calibConst; + + pTau.setP4(energyFinal * GeV / cosh( pTau.eta() ), pTau.eta(), pTau.phi(), pTau.m()); + + pTau.setP4(xAOD::TauJetParameters::TauEnergyScale, pTau.pt(), pTau.eta(), pTau.phi(), pTau.m()); + + pTau.setDetail(xAOD::TauJetParameters::TESCalibConstant, static_cast<float>( calibConst ) ); + pTau.setDetail(xAOD::TauJetParameters::TESOffset, static_cast<float>( offset * GeV ) ); + + ATH_MSG_DEBUG("Energy at LC scale = " << energyLC << " pile-up offset " << offset << " calib. const. = " << calibConst << " final energy = " << energyFinal); + } + + // final tau axis + if (m_doAxisCorr) { + + // get tau intermediate axis values + double eta = pTau.eta(); + double absEta = std::abs(eta); + double etaCorr = eta; + + if (absEta) + etaCorr = (eta / absEta)*(absEta - etaCorrectionHist->GetBinContent(etaCorrectionHist->GetXaxis()->FindBin(absEta))); + + ATH_MSG_DEBUG("eta " << eta << "; corrected eta = " << etaCorr); + + pTau.setP4( pTau.e() / cosh( etaCorr ), etaCorr, pTau.phi(), pTau.m()); + + pTau.setP4(xAOD::TauJetParameters::TauEtaCalib, pTau.pt(), pTau.eta(), pTau.phi(), pTau.m()); + + } + + return StatusCode::SUCCESS; +} + +//----------------------------------------------------------------------------- +// Finalize +//----------------------------------------------------------------------------- + +StatusCode TauCalibrateLC::finalize() { + return StatusCode::SUCCESS; +} diff --git a/Reconstruction/tauRecTools/Root/TauCommonCalcVars.cxx b/Reconstruction/tauRecTools/Root/TauCommonCalcVars.cxx new file mode 100644 index 0000000000000000000000000000000000000000..506e136fb346af6df83ec2d633e604eccfc6a13a --- /dev/null +++ b/Reconstruction/tauRecTools/Root/TauCommonCalcVars.cxx @@ -0,0 +1,253 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauCommonCalcVars.cxx +// package: Reconstruction/tauRec +// authors: Stan Lai +// date: 2008-05-18 +// +// This class calculates tau variables after core seed reconstruction +// +// 17/03/2010: (AK) change to P4Helpers +// 16/05/2011: (FF) fix if primaryVertexContainer==NULL (coverity 21734) +// Dez 2011: (FF) switch to full LC calibrated tau 4-vector for some variables +//----------------------------------------------------------------------------- +//TODO: rename + +//#include <GaudiKernel/IToolSvc.h> +//#include <GaudiKernel/ListItem.h> + +#include "tauRecTools/TauEventData.h" + +#include "tauRecTools/TauCommonCalcVars.h" +#include "tauRecTools/KineUtils.h" + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- + +TauCommonCalcVars::TauCommonCalcVars(const std::string &name) : +TauRecToolBase(name) { +} + +//----------------------------------------------------------------------------- +// Destructor +//----------------------------------------------------------------------------- + +TauCommonCalcVars::~TauCommonCalcVars() { +} + + +//----------------------------------------------------------------------------- +// Initializer +//----------------------------------------------------------------------------- + +StatusCode TauCommonCalcVars::initialize() { + return StatusCode::SUCCESS; +} + + +//----------------------------------------------------------------------------- +// Finalizer +//----------------------------------------------------------------------------- + +StatusCode TauCommonCalcVars::finalize() { + return StatusCode::SUCCESS; +} + + +//----------------------------------------------------------------------------- +// Execution +//----------------------------------------------------------------------------- +StatusCode TauCommonCalcVars::execute(xAOD::TauJet& pTau) { + + ///////////////////////////////////////////////// + // Calculate variables that are always valid + //////////////////////////////////////////////// + + // Leading track pT and et/pt(lead track) + if (pTau.nTracks() > 0) { + pTau.setDetail( xAOD::TauJetParameters::leadTrkPt, static_cast<float>( pTau.track(0)->pt() ) ); + + float emscale_ptEM = 0; + float emscale_ptHad = 0; + + if ( !pTau.detail( xAOD::TauJetParameters::etEMAtEMScale, emscale_ptEM ) ) + { + ATH_MSG_DEBUG("retrieval of tau detail failed. stopping calculation of further variables"); + return StatusCode::SUCCESS; + } + + if ( !pTau.detail( xAOD::TauJetParameters::etHadAtEMScale, emscale_ptHad ) ) + { + ATH_MSG_DEBUG("retrieval of tau detail failed. stopping calculation of further variables"); + return StatusCode::SUCCESS; + } + + //EM scale + + pTau.setDetail( xAOD::TauJetParameters::etOverPtLeadTrk, static_cast<float>( (emscale_ptEM + emscale_ptHad) / pTau.track(0)->pt() ) ); + + //switch to LC energy scale + //pDetails->setEtOverPtLeadTrk(pDetails->LC_TES_precalib() / fabs(pTau.track(0)->pt())); + } + + // XXX still need to decide whether we want to fill loose track variables anymore + // // Leading loose track pT and et/pt(lead loose track) + // if (pDetails->nLooseTrk() > 0) { + // pDetails->setLeadLooseTrkPt(pDetails->looseTrk(0)->pt()); + // //EM scale + // pDetails->setEtOverPtLeadLooseTrk((pDetails->seedCalo_etHadCalib() + pDetails->seedCalo_etEMCalib()) / fabs(pDetails->looseTrk(0)->pt())); + // //LC scale + // //pDetails->setEtOverPtLeadLooseTrk(pDetails->LC_TES_precalib() / fabs(pDetails->looseTrk(0)->pt())); + // } + + // invariant mass of track system + if ((pTau.nTracks() + pTau.nWideTracks()) > 0) { + + TLorentzVector sumOfTrackVector; + TLorentzVector tempTrackVector; + + for (unsigned int i = 0; i != pTau.nTracks(); ++i) + { + tempTrackVector.SetPtEtaPhiM( pTau.track(i)->pt(), pTau.track(i)->eta(), pTau.track(i)->phi(), pTau.track(i)->m()); + sumOfTrackVector += tempTrackVector; + } + for (unsigned int i = 0; i != pTau.nWideTracks(); ++i) + { + tempTrackVector.SetPtEtaPhiM( pTau.wideTrack(i)->pt(), pTau.wideTrack(i)->eta(), pTau.wideTrack(i)->phi(), pTau.wideTrack(i)->m()); + sumOfTrackVector += tempTrackVector; + } + + pTau.setDetail( xAOD::TauJetParameters::massTrkSys, static_cast<float>( sumOfTrackVector.M() ) ); + float tempfloat = 0; + if ( pTau.detail( xAOD::TauJetParameters::massTrkSys, tempfloat ) ) + ATH_MSG_VERBOSE("set massTrkSys " << tempfloat); + } + + // width of track system squared (trkWidth2) + if (pTau.nTracks() > 1) { + + double leadTrkPhi = pTau.track(0)->phi(); + double leadTrkEta = pTau.track(0)->eta(); + + double ptSum = 0; + double sumWeightedDR = 0; + double sumWeightedDR2 = 0; + + for (unsigned int i = 0; i != pTau.nTracks(); ++i) { + + double deltaR = Tau1P3PKineUtils::deltaR(leadTrkEta, leadTrkPhi, pTau.track(i)->eta(), pTau.track(i)->phi() ); + + ptSum += pTau.track(i)->pt(); + sumWeightedDR += deltaR * (pTau.track(i)->pt()); + sumWeightedDR2 += deltaR * deltaR * (pTau.track(i)->pt()); + } + + for (unsigned int i = 0; i != pTau.nWideTracks(); ++i) { + + double deltaR = Tau1P3PKineUtils::deltaR(leadTrkEta, leadTrkPhi, pTau.wideTrack(i)->eta(), pTau.wideTrack(i)->phi() ); + + ptSum += pTau.wideTrack(i)->pt(); + sumWeightedDR += deltaR * (pTau.wideTrack(i)->pt()); + sumWeightedDR2 += deltaR * deltaR * (pTau.wideTrack(i)->pt()); + } + + double trkWidth2 = sumWeightedDR2 / ptSum - sumWeightedDR * sumWeightedDR / ptSum / ptSum; + + if (trkWidth2 > 0.) pTau.setDetail( xAOD::TauJetParameters::trkWidth2, static_cast<float>( trkWidth2 ) ); + else pTau.setDetail( xAOD::TauJetParameters::trkWidth2, static_cast<float>( 0. ) ); + } + + // Calculation for seedCalo_trkAvgDist and seedCalo_trkRmsDist + + //FF: use now the 4-vector of the tau intermediate axis + //P4EEtaPhiM P4CaloSeed(1., pDetails->seedCalo_eta(), pDetails->seedCalo_phi(), 0.); + + if ((pTau.nWideTracks() + pTau.nTracks()) > 0) { + + double ptSum = 0; + double innerPtSum = 0; + double sumWeightedDR = 0; + double innerSumWeightedDR = 0; + double sumWeightedDR2 = 0; + + for (unsigned int i = 0; i != pTau.nTracks(); ++i) { + + double deltaR = Tau1P3PKineUtils::deltaR(pTau.eta(), pTau.phi(), pTau.track(i)->eta(), pTau.track(i)->phi() ); + + ptSum += pTau.track(i)->pt(); + sumWeightedDR += deltaR * (pTau.track(i)->pt()); + sumWeightedDR2 += deltaR * deltaR * (pTau.track(i)->pt()); + + //add calculation of innerTrkAvgDist + innerPtSum += pTau.track(i)->pt(); + innerSumWeightedDR += deltaR * (pTau.track(i)->pt()); + } + + for (unsigned int i = 0; i != pTau.nWideTracks(); ++i) { + + double deltaR = Tau1P3PKineUtils::deltaR(pTau.eta(), pTau.phi(), pTau.wideTrack(i)->eta(), pTau.wideTrack(i)->phi() ); + + ptSum += pTau.wideTrack(i)->pt(); + sumWeightedDR += deltaR * (pTau.wideTrack(i)->pt()); + sumWeightedDR2 += deltaR * deltaR * (pTau.wideTrack(i)->pt()); + } + + if (ptSum > 0.0001) { + // seedCalo_trkAvgDist + pTau.setDetail( xAOD::TauJetParameters::trkAvgDist, static_cast<float>( sumWeightedDR / ptSum ) ); + + float tempfloat; + if ( pTau.detail( xAOD::TauJetParameters::trkAvgDist, tempfloat ) ) + ATH_MSG_VERBOSE("set seedCalo_trkAvgDist " << tempfloat ); + + // seedCalo_trkRmsDist + double trkRmsDist2 = sumWeightedDR2 / ptSum - sumWeightedDR * sumWeightedDR / ptSum / ptSum; + if (trkRmsDist2 > 0) { + pTau.setDetail( xAOD::TauJetParameters::trkRmsDist, static_cast<float>( sqrt(trkRmsDist2) ) ); + } else { + pTau.setDetail( xAOD::TauJetParameters::trkRmsDist, static_cast<float>( 0. ) ); + } + if ( pTau.detail( xAOD::TauJetParameters::trkRmsDist, tempfloat ) ) + ATH_MSG_VERBOSE("set seedCalo_trkRmsDist " << tempfloat ); + } + + if (ptSum > 0.0) { + + // SumPtTrkFrac + pTau.setDetail( xAOD::TauJetParameters::SumPtTrkFrac, static_cast<float>( 1. - innerPtSum/ptSum ) ); + // FIXME!!! put pileup correction here once availabe + // FIXME!!! for now set corrected version same as uncorrected + pTau.setDetail( xAOD::TauJetParameters::SumPtTrkFracCorrected, static_cast<float>( 1. - innerPtSum/ptSum ) ); + + } else { + + pTau.setDetail( xAOD::TauJetParameters::SumPtTrkFrac, static_cast<float>( 0.0 ) ); + pTau.setDetail( xAOD::TauJetParameters::SumPtTrkFracCorrected, static_cast<float>( 0.0 ) ); + + } + + if (ptSum > 0.00 && innerPtSum > 0.0) { + + ATH_MSG_DEBUG("innerSumWeightedDR = " << innerSumWeightedDR << " innerPtSum = " << innerPtSum << " ptSum = " << ptSum ); + + // InnerTrkAvgDist + pTau.setDetail( xAOD::TauJetParameters::innerTrkAvgDist, static_cast<float>( innerSumWeightedDR / innerPtSum ) ); + // FIXME!!! put pileup correction here once availabe + // FIXME!!! for now set corrected version same as uncorrected + pTau.setDetail( xAOD::TauJetParameters::innerTrkAvgDistCorrected, static_cast<float>( innerSumWeightedDR / innerPtSum ) ); + + } else { + pTau.setDetail( xAOD::TauJetParameters::innerTrkAvgDist, static_cast<float>( 0.0 )); + pTau.setDetail( xAOD::TauJetParameters::innerTrkAvgDistCorrected, static_cast<float>( 0.0 )); + } + + } + + return StatusCode::SUCCESS; +} + + diff --git a/Reconstruction/tauRecTools/Root/TauGenericPi0Cone.cxx b/Reconstruction/tauRecTools/Root/TauGenericPi0Cone.cxx new file mode 100644 index 0000000000000000000000000000000000000000..77f9cb398c823d5958956ff5b4564ac08356db17 --- /dev/null +++ b/Reconstruction/tauRecTools/Root/TauGenericPi0Cone.cxx @@ -0,0 +1,102 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauGenericPi0Cone.cxx +// package: Reconstruction/tauRec +// authors: Robert Clarke, Blake Burghgrave +// date: 2014-01-04 +// +// +//----------------------------------------------------------------------------- + +//#include <GaudiKernel/IToolSvc.h> +//#include <GaudiKernel/ListItem.h> + +#include "FourMomUtils/P4Helpers.h" +//#include "FourMom/P4EEtaPhiM.h" +//#include "Particle/TrackParticle.h" + +#include "tauRecTools/TauEventData.h" +//#include "tauEvent/TauCommonDetails.h" +//#include "tauEvent/TauJetParameters.h" + +#include "tauRecTools/TauGenericPi0Cone.h" +#include "tauRecTools/TauTrackFilterUtils.h" + +#include "TLorentzVector.h" + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- + +TauGenericPi0Cone::TauGenericPi0Cone(const std::string &name) : +TauRecToolBase(name) { +} + + +//----------------------------------------------------------------------------- +// Destructor +//----------------------------------------------------------------------------- + +TauGenericPi0Cone::~TauGenericPi0Cone() { +} + + +//----------------------------------------------------------------------------- +// Initializer +//----------------------------------------------------------------------------- + +StatusCode TauGenericPi0Cone::initialize() { + ATH_MSG_VERBOSE("TauGenericPi0Cone Initialising"); + + return StatusCode::SUCCESS; +} + + +//----------------------------------------------------------------------------- +// Finalizer +//----------------------------------------------------------------------------- + +StatusCode TauGenericPi0Cone::finalize() { + ATH_MSG_VERBOSE("TauGenericPi0Cone Finalizing"); + + return StatusCode::SUCCESS; +} + + +//----------------------------------------------------------------------------- +// Execution +//----------------------------------------------------------------------------- +StatusCode TauGenericPi0Cone::execute(xAOD::TauJet& pTau) { + ATH_MSG_VERBOSE("TauGenericPi0Cone Executing"); + + TLorentzVector tau; + tau.SetPtEtaPhiE(pTau.pt()/1000, //GeV + pTau.eta(), + pTau.phi(), + pTau.e()/1000); //GeV + + int nProng = pTau.trackFilterProngs(); + int flag = pTau.trackFilterQuality(); + float pi0angle = 0.; //TODO sane default value + + // Get pi0 cone + if(flag != 0){ + int recProng = 0; + if((nProng == 3)||(nProng == 2)) recProng = 3; + if(nProng == 1) recProng = 1; + pi0angle = TauTrackFilterUtils::ComputePi0Cone(recProng,tau); + } + + // Convert to dR. + m_pi0conedr = std::min(pi0angle*cosh(tau.Eta()), 0.2); + + // Store result + pTau.setPi0ConeDR(m_pi0conedr); + + return StatusCode::SUCCESS; +} + diff --git a/Reconstruction/tauRecTools/Root/TauIDPileupCorrection.cxx b/Reconstruction/tauRecTools/Root/TauIDPileupCorrection.cxx new file mode 100644 index 0000000000000000000000000000000000000000..5e4251b4b8cc141aed872e13639eb0b8a2ea68eb --- /dev/null +++ b/Reconstruction/tauRecTools/Root/TauIDPileupCorrection.cxx @@ -0,0 +1,252 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//#include "CLHEP/Vector/LorentzVector.h" +//#include "CLHEP/Units/SystemOfUnits.h" + +// root +#include "TFile.h" +#include "TObject.h" +#include "TCollection.h" +#include "TF1.h" +#include "TH1D.h" +#include "TKey.h" + +//tau +#include "xAODTau/TauJet.h" +#include "tauRecTools/TauEventData.h" +#include "tauRecTools/TauIDPileupCorrection.h" + +#include "xAODEventInfo/EventInfo.h" + +//using CLHEP::GeV; + +/********************************************************************/ +TauIDPileupCorrection::TauIDPileupCorrection(const std::string& name) : +TauRecToolBase(name) +{ + declareProperty("averageEstimator", m_averageEstimator=20.); + declareProperty("minNTrack", m_minNTrackAtVertex=2); + + declareProperty("tauContainerKey", m_tauContainerKey = "TauJets"); + declareProperty("calibrationFile1Prong", m_file1P = "fitted.pileup_1prong_hlt.root"); + declareProperty("calibrationFile3Prong", m_file3P = "fitted.pileup_multiprongs_hlt.root"); + declareProperty("vertexContainerKey", m_vertexContainerKey = "PrimaryVertices"); + declareProperty("useMu", m_useMu = false); +} + +/********************************************************************/ +TauIDPileupCorrection::~TauIDPileupCorrection() { +} + +/********************************************************************/ +StatusCode TauIDPileupCorrection::initialize() { + + + // Open the 1P and 3P files + std::string fullPath = find_file(m_file1P); + TFile * file1P = TFile::Open(fullPath.c_str(), "READ"); + + if (!file1P) { + ATH_MSG_FATAL("Failed to open " << fullPath); + return StatusCode::FAILURE; + } + + // Loop over file contents + TIter keyIterator1P(file1P->GetListOfKeys()); + + while ( TObject *myObject = keyIterator1P() ) + { + TKey* myKey = (TKey*)myObject; + + ATH_MSG_DEBUG("Found a key of type: " << myKey->GetClassName()); + + if(std::string(myKey->GetClassName()) == "TF1") + { + ATH_MSG_DEBUG("Key is a TF1: " << myKey->GetName()); + // Copy the function to local map + m_calibFunctions1P[myKey->GetName()] = *((TF1*)file1P->Get(myKey->GetName())); + } + } + + file1P->Close(); + + fullPath = find_file(m_file3P); + TFile * file3P = TFile::Open(fullPath.c_str(), "READ"); + + TIter keyIterator3P(file3P->GetListOfKeys()); + + while ( TObject *myObject = keyIterator3P() ) + { + TKey* myKey = (TKey*)myObject; + + ATH_MSG_DEBUG("Found a key of type: " << myKey->GetClassName()); + + if(std::string(myKey->GetClassName()) == "TF1") + { + ATH_MSG_DEBUG("Key is a TF1: " << myKey->GetName()); + // Copy the function to local map + m_calibFunctions3P[myKey->GetName()] = *((TF1*)file3P->Get(myKey->GetName())); + } + } + + file3P->Close(); + + ATH_MSG_DEBUG("Found " << m_calibFunctions1P.size() << " variables to correct in 1P"); + ATH_MSG_DEBUG("Found " << m_calibFunctions3P.size() << " variables to correct in 3P"); + + // Here comes the ugly part: define the equivalency of details and strings + m_conversion.push_back(TauConversion("tau_centFrac_fit", xAOD::TauJetParameters::centFrac, xAOD::TauJetParameters::centFracCorrected)); + m_conversion.push_back(TauConversion("tau_massTrkSys_fit", xAOD::TauJetParameters::massTrkSys, xAOD::TauJetParameters::massTrkSysCorrected)); + m_conversion.push_back(TauConversion("tau_EMPOverTrkSysP_fit", xAOD::TauJetParameters::EMPOverTrkSysP, xAOD::TauJetParameters::EMPOverTrkSysPCorrected)); + m_conversion.push_back(TauConversion("tau_InnerTrkAvgDist_fit", xAOD::TauJetParameters::innerTrkAvgDist, xAOD::TauJetParameters::innerTrkAvgDistCorrected)); + m_conversion.push_back(TauConversion("tau_SumPtTrkFrac_fit", xAOD::TauJetParameters::SumPtTrkFrac, xAOD::TauJetParameters::SumPtTrkFracCorrected)); + m_conversion.push_back(TauConversion("tau_etOverPtLeadTrk_fit", xAOD::TauJetParameters::etOverPtLeadTrk, xAOD::TauJetParameters::etOverPtLeadTrkCorrected)); + m_conversion.push_back(TauConversion("tau_approx_ptRatio_fit", xAOD::TauJetParameters::ptRatioEflowApprox, xAOD::TauJetParameters::ptRatioEflowApproxCorrected)); + m_conversion.push_back(TauConversion("tau_approx_vistau_m_fit", xAOD::TauJetParameters::mEflowApprox, xAOD::TauJetParameters::mEflowApproxCorrected)); + m_conversion.push_back(TauConversion("tau_ChPiEMEOverCaloEME_fit", xAOD::TauJetParameters::ChPiEMEOverCaloEME, xAOD::TauJetParameters::ChPiEMEOverCaloEMECorrected)); + m_conversion.push_back(TauConversion("tau_trFlightPathSig_fit", xAOD::TauJetParameters::trFlightPathSig, xAOD::TauJetParameters::trFlightPathSigCorrected)); + m_conversion.push_back(TauConversion("tau_dRmax_fit", xAOD::TauJetParameters::dRmax, xAOD::TauJetParameters::dRmaxCorrected)); + m_conversion.push_back(TauConversion("tau_AbsipSigLeadTrk_BS_fit", xAOD::TauJetParameters::ipSigLeadTrk, xAOD::TauJetParameters::ipSigLeadTrkCorrected)); + m_conversion.push_back(TauConversion("tau_ipSigLeadTrk_fit", xAOD::TauJetParameters::ipSigLeadTrk, xAOD::TauJetParameters::ipSigLeadTrkCorrected)); + + return StatusCode::SUCCESS; +} + +/********************************************************************/ +StatusCode TauIDPileupCorrection::execute(xAOD::TauJet& pTau) +{ + // get detector axis values + //double eta = pTau.etaDetectorAxis(); + //double absEta = std::abs(eta); + + // get primary vertex container + StatusCode sc; + const xAOD::VertexContainer * vxContainer = 0; + + // for tau trigger + bool inTrigger = tauEventData()->inTrigger(); + + // check if we were asked to use mu instead of nVertex from the container + //TODO read the input root file to decide if we should use mu + bool useMu = m_useMu; + + double nVertex = 0; + + // Only retrieve the container if we are not in trigger + if ((sc.isFailure() || !inTrigger) && !useMu) { + // try standard + if (evtStore()->retrieve(vxContainer, m_vertexContainerKey).isFailure() || !vxContainer) { + if (m_printMissingContainerINFO) { + ATH_MSG_WARNING(m_vertexContainerKey << " container not found --> skip TauEnergyCalibrationLC (no further info) "); + m_printMissingContainerINFO=false; + } + return StatusCode::SUCCESS; + } + + // Calculate nVertex + xAOD::VertexContainer::const_iterator vx_iter = vxContainer->begin(); + xAOD::VertexContainer::const_iterator vx_end = vxContainer->end(); + + for (; vx_iter != vx_end; ++vx_iter) { + if ((*vx_iter)->nTrackParticles() >= m_minNTrackAtVertex) + ++nVertex; + } + + ATH_MSG_DEBUG("calculated nVertex " << nVertex ); + + } else { + + StatusCode scMu = StatusCode::FAILURE; + double muTemp = 0.0; + + if (tauEventData()->hasObject("AvgInteractions")) scMu = tauEventData()->getObject("AvgInteractions", muTemp); + else if (!inTrigger) { + // Get mu from EventInfo + const xAOD::EventInfo *eventInfo; + StatusCode scEI = StatusCode::FAILURE; + scEI = evtStore()->retrieve(eventInfo, "EventInfo"); + if (scEI.isFailure() || !eventInfo) { + ATH_MSG_ERROR("Could not retrieve EventInfo"); + return StatusCode::FAILURE; + } + muTemp = eventInfo->averageInteractionsPerCrossing(); + } + + if(scMu.isSuccess()){ + ATH_MSG_DEBUG("AvgInteractions object in tau candidate = " << muTemp); + } else { + ATH_MSG_DEBUG("No AvgInteractions object in tau candidate or averageInteractionsPerCrossing in EventInfo"); + } + + nVertex = muTemp; + } + + + // Possibly get a new averageEstimator + // TODO read averageEstimator from the root file + double averageEstimator = m_averageEstimator; + + // Start corrections + for(unsigned int i=0; i<m_conversion.size(); i++) + { + + ATH_MSG_DEBUG("Attempting to correct variable " << m_conversion[i].detailName); + float correction = 0; + + if(pTau.nTracks() <= 1) + { + // No calibration function available + if(m_calibFunctions1P.count(m_conversion[i].detailName) < 1) + continue; + + ATH_MSG_DEBUG("Variable correction function found"); + + // Calculate correction + correction = m_calibFunctions1P[m_conversion[i].detailName].Eval(nVertex) - m_calibFunctions1P[m_conversion[i].detailName].Eval(averageEstimator); + } + + if(pTau.nTracks() > 1) + { + // No calibration function available + if(m_calibFunctions3P.count(m_conversion[i].detailName) < 1) + continue; + + ATH_MSG_DEBUG("Variable correction function found"); + + // Calculate correction + correction = m_calibFunctions3P[m_conversion[i].detailName].Eval(nVertex) - m_calibFunctions3P[m_conversion[i].detailName].Eval(averageEstimator); + } + + + ATH_MSG_DEBUG("Correction is: " << correction); + ATH_MSG_DEBUG("For Pile-up Estimator: " << nVertex); + + // Retrieve current value and set corrected value + float uncorrectedValue; + pTau.detail(m_conversion[i].detailUncorr, uncorrectedValue); + + float correctedValue; + if (m_conversion[i].detailName == "tau_AbsipSigLeadTrk_BS_fit" + || m_conversion[i].detailName == "tau_ipSigLeadTrk_fit") + correctedValue = fabs(uncorrectedValue) - correction; + else + correctedValue = uncorrectedValue - correction; + + pTau.setDetail(m_conversion[i].detailCorr, correctedValue); + + ATH_MSG_DEBUG("Old value is: " << uncorrectedValue); + ATH_MSG_DEBUG("New value is: " << correctedValue); + } + + return StatusCode::SUCCESS; +} + +//----------------------------------------------------------------------------- +// Finalize +//----------------------------------------------------------------------------- + +StatusCode TauIDPileupCorrection::finalize() { + return StatusCode::SUCCESS; +} diff --git a/Reconstruction/tauRecTools/Root/TauProcessorTool.cxx b/Reconstruction/tauRecTools/Root/TauProcessorTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..969dd75d70ae47ce047362ddbcef0fee2687649a --- /dev/null +++ b/Reconstruction/tauRecTools/Root/TauProcessorTool.cxx @@ -0,0 +1,268 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "tauRecTools/TauProcessorTool.h" + +#include "xAODTau/TauJetContainer.h" +#include "xAODTracking/VertexContainer.h" +#include "xAODTracking/VertexAuxContainer.h" +#include "xAODPFlow/PFOContainer.h" +#include "xAODPFlow/PFOAuxContainer.h" + + +//________________________________________ +TauProcessorTool::TauProcessorTool(const std::string& type) : + asg::AsgTool(type), + m_tauContainerName("TauJets"), + m_tauAuxContainerName("TauJetsAux."), + m_AODmode(false) +{ + declareProperty("TauContainer", m_tauContainerName); + declareProperty("TauAuxContainer", m_tauAuxContainerName); + declareProperty("Tools", m_tools, "List of ITauToolBase tools"); + declareProperty("runOnAOD", m_AODmode); //AODS are input file + declareProperty("deepCopyChargedPFOContainer", m_deep_copy_chargedPFOContainer=true); + declareProperty("deepCopyHadronicPFOContainer", m_deep_copy_hadronicPFOContainer=true); + declareProperty("deepCopyNeutralPFOContainer", m_deep_copy_neutralPFOContainer=true); + declareProperty("deepCopySecVtxContainer", m_deep_copy_SecVtxContainer=true); +} + +//________________________________________ +TauProcessorTool::~TauProcessorTool(){} + +//________________________________________ +StatusCode TauProcessorTool::initialize(){ + + + //ATH_MSG_INFO("FF::TauProcessor :: initialize()"); + + //------------------------------------------------------------------------- + // No tools allocated! + //------------------------------------------------------------------------- + if (m_tools.size() == 0) { + ATH_MSG_ERROR("no tools given!"); + return StatusCode::FAILURE; + } + + StatusCode sc; + + //------------------------------------------------------------------------- + // Allocate tools + //------------------------------------------------------------------------- + ToolHandleArray<ITauToolBase> ::iterator itT = m_tools.begin(); + ToolHandleArray<ITauToolBase> ::iterator itTE = m_tools.end(); + ATH_MSG_INFO("List of tools in execution sequence:"); + ATH_MSG_INFO("------------------------------------"); + + unsigned int tool_count = 0; + + for (; itT != itTE; ++itT) { + sc = itT->retrieve(); + if (sc.isFailure()) { + ATH_MSG_WARNING("Cannot find tool named <" << *itT << ">"); + } else { + ++tool_count; + ATH_MSG_INFO((*itT)->name()); + //If you want to utlize TauCandidate In Tools, + //decalre TauCandidate in your class, and pass its address + //to function below + (*itT)->setTauEventData(&m_data); + } + } + ATH_MSG_INFO(" "); + ATH_MSG_INFO("------------------------------------"); + + if (tool_count == 0) { + ATH_MSG_ERROR("could not allocate any tool!"); + return StatusCode::FAILURE; + } + + /////////////////////////////////////////////////////////////////////////// + + return StatusCode::SUCCESS; +} + +//________________________________________ +StatusCode TauProcessorTool::execute(){ + + StatusCode sc; + m_data.clear(); + + if(m_AODmode){ + //------------------------------------------------------------------------- + // In AODMode, deep copy all PFOs BEFORE reading in tau + //------------------------------------------------------------------------- + if(m_deep_copy_SecVtxContainer){ + xAOD::VertexContainer* pSecVtxContainer(0); + xAOD::VertexAuxContainer* pSecVtxAuxContainer(0); + xAOD::Vertex* v(0); + ATH_CHECK(deepCopy(pSecVtxContainer, pSecVtxAuxContainer, v, "TauSecondaryVertices")); + } + + if(m_deep_copy_neutralPFOContainer){ + xAOD::PFOContainer* neutralPFOContainer(0); + xAOD::PFOAuxContainer* neutralPFOAuxStore(0); + xAOD::PFO* p(0); + //container name hard-coded, but configurable in tool where objects are created in core reco + ATH_CHECK(deepCopy(neutralPFOContainer, neutralPFOAuxStore, p, "TauNeutralParticleFlowObjects")); + } + + if(m_deep_copy_hadronicPFOContainer){ + xAOD::PFOContainer* hadronicPFOContainer(0); + xAOD::PFOAuxContainer* hadronicPFOAuxStore(0); + xAOD::PFO* p(0); + //container name hard-coded, but configurable in tool where objects are created in core reco + ATH_CHECK(deepCopy(hadronicPFOContainer, hadronicPFOAuxStore, p, "TauHadronicParticleFlowObjects")); + } + + if(m_deep_copy_chargedPFOContainer){ + xAOD::PFOContainer* chargedPFOContainer(0); + xAOD::PFOAuxContainer* chargedPFOAuxStore(0); + xAOD::PFO* p(0); + //container name hard-coded, but configurable in tool where objects are created in core reco + ATH_CHECK(deepCopy(chargedPFOContainer, chargedPFOAuxStore, p, "TauChargedParticleFlowObjects")); + } + //------------------------------------------------------------------------- + // End pre-tau reading operations + //------------------------------------------------------------------------- + } + + + const xAOD::TauJetContainer* pContainerOriginal(0); + const xAOD::TauJetAuxContainer* pAuxContainerOriginal(0); + + //------------------------------------------------------------------------- + // retrieve Tau Containers from StoreGate + //------------------------------------------------------------------------- + sc = evtStore()->retrieve(pContainerOriginal, m_tauContainerName); + if (sc.isFailure()) { + if (m_AODmode) { + // don't exit Athena if there is no Tau Container in (D)AODs when running in AOD mode + // just exit TauProcessor + // reason: somebody might use slimmed (D)AODs, where not needed containers are not present + ATH_MSG_WARNING("Failed to retrieve " << m_tauContainerName << "! Will exit TauProcessor now!!"); + return StatusCode::SUCCESS; + } + else { + ATH_MSG_FATAL("Failed to retrieve " << m_tauContainerName); + return StatusCode::FAILURE; + } + } + + sc = evtStore()->retrieve(pAuxContainerOriginal, m_tauAuxContainerName); + if (sc.isFailure()) { + if (m_AODmode) { + // don't exit Athena if there is no Tau AuxContainer in (D)AODs when running in AOD mode + // just exit TauProcessor + // reason: somebody might use slimmed (D)AODs, where not needed containers are not present + ATH_MSG_WARNING("Failed to retrieve " << m_tauAuxContainerName << "! Will exit TauProcessor now!!"); + return StatusCode::SUCCESS; + } + else { + ATH_MSG_FATAL("Failed to retrieve " << m_tauAuxContainerName); + return StatusCode::FAILURE; + } + } + + xAOD::TauJetContainer* pContainer = const_cast<xAOD::TauJetContainer*> (pContainerOriginal); + xAOD::TauJetAuxContainer* pAuxContainer = const_cast<xAOD::TauJetAuxContainer*> (pAuxContainerOriginal); + + if(m_AODmode){ + pContainer=0; + pAuxContainer=0; + xAOD::TauJet* tau(0); + ATH_CHECK(deepCopy(pContainer, pAuxContainer, tau, m_tauContainerName, m_tauAuxContainerName)); + } + + m_data.xAODTauContainer = pContainer; + m_data.tauAuxContainer = pAuxContainer; + + //------------------------------------------------------------------------- + // Initialize tools for this event + //------------------------------------------------------------------------- + ToolHandleArray<ITauToolBase> ::iterator itT = m_tools.begin(); + ToolHandleArray<ITauToolBase> ::iterator itTE = m_tools.end(); + for (; itT != itTE; ++itT) { + sc = (*itT)->eventInitialize(); + if (sc != StatusCode::SUCCESS) + return StatusCode::FAILURE; + } + + //////////////////////////////////////////////////////// + + //loop over taus + xAOD::TauJetContainer::iterator tau_it = pContainer->begin(); + xAOD::TauJetContainer::iterator tau_end = pContainer->end(); + + for(; tau_it != tau_end; ++tau_it) { + + //----------------------------------------------------------------- + // set tau candidate data for easy handling + //----------------------------------------------------------------- + + //----------------------------------------------------------------- + // Process the candidate + //----------------------------------------------------------------- + ToolHandleArray<ITauToolBase>::iterator itT = m_tools.begin(); + ToolHandleArray<ITauToolBase>::iterator itTE = m_tools.end(); + + //----------------------------------------------------------------- + // Loop stops when Failure indicated by one of the tools + //----------------------------------------------------------------- + for (; itT != itTE; ++itT) { + ATH_MSG_VERBOSE("Invoking tool " << (*itT)->name()); + + sc = (*itT)->execute(**tau_it); + + if (sc.isFailure()) + break; + } + + if (sc.isSuccess()) { + + ATH_MSG_VERBOSE("The tau candidate has been modified"); + + } else if (!sc.isSuccess()) { + //TODO:cleanup of EndTools not necessary?? + //keep this here for future use (in case more than one seeding algo exist) + /* + ToolHandleArray<ITauToolBase> ::iterator p_itT1 = m_tools.begin(); + for (; p_itT1 != p_itT; ++p_itT1) + (*p_itT1)->cleanup(&m_data); + (*p_itT1)->cleanup(&m_data); + */ + //delete m_data.tau; + } else { + //delete m_data.tau; + } + } + + + + //------------------------------------------------------------------------- + // Finalize tools for this event + //------------------------------------------------------------------------- + + itT = m_tools.begin(); + itTE = m_tools.end(); + for (; itT != itTE; ++itT) { + sc = (*itT)->eventFinalize(); + if (sc != StatusCode::SUCCESS) + return StatusCode::FAILURE; + } + + + /////////////////////////////////////////////////////// + // locking of containers is moved to separate tau tool + + + return StatusCode::SUCCESS; +} + +//________________________________________ +StatusCode TauProcessorTool::finalize(){ + + return StatusCode::SUCCESS; +} + diff --git a/Reconstruction/tauRecTools/Root/TauRecToolBase.cxx b/Reconstruction/tauRecTools/Root/TauRecToolBase.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a7f834cb1f237e18bf1112cd879c2a7cda98dca6 --- /dev/null +++ b/Reconstruction/tauRecTools/Root/TauRecToolBase.cxx @@ -0,0 +1,58 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "tauRecTools/TauRecToolBase.h" +#include "PathResolver/PathResolver.h" + + + +TauEventData defaultTauEventData; + +//________________________________________ +std::string TauRecToolBase::find_file(const std::string& fname) const { + static const std::string m_tauRecToolsTag="tauRecTools/00-00-00/"; + std::string full_path = PathResolverFindCalibFile(m_tauRecToolsTag+fname); + if(full_path=="") full_path = PathResolverFindCalibFile(fname); + return full_path; +} + +//________________________________________ +void TauRecToolBase::setTauEventData(TauEventData* data){ + m_data=data; + if(m_data==0) { + m_data=&defaultTauEventData; + m_data->clear(); + } +} + +//________________________________________ +TauRecToolBase::TauRecToolBase(const std::string& name) : + asg::AsgTool(name) { + +} + +//________________________________________ +StatusCode TauRecToolBase::initialize(){ + return StatusCode::SUCCESS; +} + +//________________________________________ +StatusCode TauRecToolBase::eventInitialize(){ + return StatusCode::SUCCESS; +} + +//________________________________________ +StatusCode TauRecToolBase::execute(xAOD::TauJet&){ + return StatusCode::SUCCESS; +} + +//________________________________________ +StatusCode TauRecToolBase::eventFinalize(){ + return StatusCode::SUCCESS; +} + +//________________________________________ +StatusCode TauRecToolBase::finalize(){ + return StatusCode::SUCCESS; +} diff --git a/Reconstruction/tauRecTools/Root/TauTrackFilter.cxx b/Reconstruction/tauRecTools/Root/TauTrackFilter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..938f9566e7f013408450db4d56236c5acb56b176 --- /dev/null +++ b/Reconstruction/tauRecTools/Root/TauTrackFilter.cxx @@ -0,0 +1,352 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauTrackFilter.cxx +// package: Reconstruction/tauRec +// authors: Robert Clarke, Blake Burghgrave +// date: 2014-01-04 +// +// +//----------------------------------------------------------------------------- + +//#include <GaudiKernel/IToolSvc.h> +//#include <GaudiKernel/ListItem.h> + +#include "FourMomUtils/P4Helpers.h" +//#include "FourMom/P4EEtaPhiM.h" + +#include "tauRecTools/TauEventData.h" + +#include "tauRecTools/TauTrackFilter.h" +#include "tauRecTools/TauTrackFilterUtils.h" + +#include "xAODTracking/TrackParticleContainer.h" + +#include "TLorentzVector.h" + +void TrackFilterAlg(TLorentzVector tau, + std::vector<TLorentzVector>* inputtracks20, + std::vector<int>* inputtracks20charge, + std::vector<TLorentzVector>* inputtracks40, + std::vector<int>* inputtracks40charge, + std::vector<TLorentzVector>* outputtracksgood, + std::vector<int>* outputtracksgoodcharge, + std::vector<TLorentzVector>* outputtracksbad, + std::vector<int>* outputtracksbadcharge, + int& nProng, + int& flag); + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- + +TauTrackFilter::TauTrackFilter(const std::string &name ) : +TauRecToolBase(name) { + declareProperty("TrackContainerName", m_trackContainerName = "InDetTrackParticles"); +} + +//----------------------------------------------------------------------------- +// Destructor +//----------------------------------------------------------------------------- + +TauTrackFilter::~TauTrackFilter() { +} + + +//----------------------------------------------------------------------------- +// Initializer +//----------------------------------------------------------------------------- + +StatusCode TauTrackFilter::initialize() { + ATH_MSG_VERBOSE("TauTrackFilter Initialising"); + + return StatusCode::SUCCESS; +} + + +//----------------------------------------------------------------------------- +// Finalizer +//----------------------------------------------------------------------------- + +StatusCode TauTrackFilter::finalize() { + ATH_MSG_VERBOSE("TauTrackFilter Finalizing"); + + return StatusCode::SUCCESS; +} + + +//----------------------------------------------------------------------------- +// Execution +//----------------------------------------------------------------------------- +StatusCode TauTrackFilter::execute(xAOD::TauJet& pTau) { + ATH_MSG_VERBOSE("TauTrackFilter Executing"); + + StatusCode sc; + + const xAOD::TrackParticleContainer *trackContainer; + + //TODO: trigger uses getObject + sc = evtStore()->retrieve(trackContainer, m_trackContainerName); + if (sc.isFailure() || !trackContainer) { + ATH_MSG_DEBUG(" No track container found in TDS !!"); + return StatusCode::SUCCESS; + } + + TLorentzVector tau; + tau.SetPtEtaPhiE(pTau.pt()/1000, //GeV + pTau.eta(), + pTau.phi(), + pTau.e()/1000); //GeV + + std::vector<TLorentzVector>* inputtracks20 = new std::vector<TLorentzVector>; + std::vector<TLorentzVector>* inputtracks40 = new std::vector<TLorentzVector>; + std::vector<int>* inputtracks20charge = new std::vector<int>; + std::vector<int>* inputtracks40charge = new std::vector<int>; + std::vector<TLorentzVector>* outputtracksgood = new std::vector<TLorentzVector>; + std::vector<TLorentzVector>* outputtracksbad = new std::vector<TLorentzVector>; + std::vector<int>* outputtracksgoodcharge = new std::vector<int>; + std::vector<int>* outputtracksbadcharge = new std::vector<int>; + int nProng = 0; + int flag = 0; + + std::vector<unsigned int> inputtracks20index; + std::vector<unsigned int> inputtracks40index; + + m_TrkPass.clear(); + + for(unsigned int j=0; j<pTau.nTracks(); j++ ) { + const xAOD::TrackParticle *TauJetTrack = pTau.track(j); + TLorentzVector inputTrack; + inputTrack.SetPtEtaPhiE(TauJetTrack->pt()/1000, //GeV + TauJetTrack->eta(), + TauJetTrack->phi(), + TauJetTrack->e()/1000); //GeV + float dR = tau.DeltaR(inputTrack); + if (dR < 0.2) { + inputtracks20->push_back(inputTrack); + inputtracks20charge->push_back(TauJetTrack->charge()); + inputtracks20index.push_back(j); + } + else if (dR < 0.4) { + inputtracks40->push_back(inputTrack); + inputtracks40charge->push_back(TauJetTrack->charge()); + inputtracks40index.push_back(j); + } + + // Add default status to track pass/fail member. + m_TrkPass.push_back(false); + } + + // Run the main algorithm + TrackFilterAlg(tau, + inputtracks20, + inputtracks20charge, + inputtracks40, + inputtracks40charge, + outputtracksgood, + outputtracksgoodcharge, + outputtracksbad, + outputtracksbadcharge, + nProng, + flag); + + // Store results + for (unsigned int j=0; j<outputtracksgood->size(); j++ ) { + for (unsigned int k=0; k<inputtracks20->size(); k++ ) { + if (outputtracksgood->at(j) == inputtracks20->at(k)) { + m_TrkPass.at(inputtracks20index.at(k)) = true; + } + } + for (unsigned int k=0; k<inputtracks40->size(); k++ ) { + if (outputtracksgood->at(j) == inputtracks40->at(k)) { + m_TrkPass.at(inputtracks40index.at(k)) = true; + } + } + } + m_nProng = nProng; + m_flag = flag; + + // Cleanup + delete inputtracks20; + delete inputtracks20charge; + delete inputtracks40; + delete inputtracks40charge; + delete outputtracksgood; + delete outputtracksbad; + delete outputtracksgoodcharge; + delete outputtracksbadcharge; + + // Set values in EDM + for (unsigned int numTrack=0; numTrack<m_TrkPass.size(); numTrack++) { + pTau.setTrackFlag(pTau.track(numTrack), xAOD::TauJetParameters::failTrackFilter, !m_TrkPass.at(numTrack)); + } + pTau.setTrackFilterProngs(m_nProng); + pTau.setTrackFilterQuality(m_flag); + + return StatusCode::SUCCESS; +} + + +//----------------------------------------------------------------------------- +// Main algorithm +//----------------------------------------------------------------------------- +void TrackFilterAlg(TLorentzVector tau, + std::vector<TLorentzVector>* inputtracks20, + std::vector<int>* inputtracks20charge, + std::vector<TLorentzVector>* inputtracks40, + std::vector<int>* inputtracks40charge, + std::vector<TLorentzVector>* outputtracksgood, + std::vector<int>* outputtracksgoodcharge, + std::vector<TLorentzVector>* outputtracksbad, + std::vector<int>* outputtracksbadcharge, + int& nProng, + int& flag) { + + std::vector<TauTrackFilterUtils::TrackInfo> unsorted,tracks,SScombination; + TauTrackFilterUtils::TrackInfo track; + unsigned int tracknum = inputtracks20->size(); + unsigned int widetracknum = inputtracks40->size(); + for(unsigned int i=0;i<tracknum;i++){ + track.p4 = (*inputtracks20)[i]; + track.charge = (*inputtracks20charge)[i]; + unsorted.push_back(track); + } + while (unsorted.size() > 0){ + float trackP = unsorted[0].p4.P(); + int index = 0; + for(unsigned int i=1;i<unsorted.size();i++){ + if(unsorted[i].p4.P() > trackP){ + index = i; + trackP = unsorted[i].p4.P(); + } + } + tracks.push_back(unsorted[index]); + tracks[tracks.size()-1].index = tracks.size()-1; + unsorted.erase(unsorted.begin()+index); + } +//Step 2: Test 3 Prong Hypothesis +//Step 2a: Arrange combinations of tracks for testing + + bool test3prong = true, test2prong = true, test1prong = true; + for(unsigned int i=0;i<widetracknum;i++){ + outputtracksbad->push_back((*inputtracks40)[i]); + outputtracksbadcharge->push_back((*inputtracks40charge)[i]); + } + if(tracknum > 4){ //Anything with more than 4 tracks is a fake. + flag = 0; + test3prong = false; + test2prong = false; + test1prong = false; + } + if(tracknum < 3) test3prong = false; //Don't test 3 prong if fewer than 3 tracks + if(tracknum < 2) test2prong = false; //Don't test 2 prong if fewer than 2 tracks + if(tracknum < 1){ + flag = 0; + test1prong = false; //Don't test 1 prong if no tracks within dR < 0.2 of tau + } + if(test3prong){ + //Test 3 Highest pT Tracks + bool isSS = false; + std::vector<TauTrackFilterUtils::TrackInfo> combination; + int charge = 0; TLorentzVector threetrack; + for(unsigned int i=0;i<3;i++){ + combination.push_back(tracks[i]); //Only Care about 3 Highest pT Tracks + charge+=tracks[i].charge; + threetrack+=tracks[i].p4; + } + if((tracknum == 3) && (abs(charge)!=1)) isSS = true; //Reject all same-sign combinations +//Step 2b: Check kinematics of track combinations against shrinking cones and mass boundaries +// for(unsigned int i=0;i<combinations.size();i++){ + bool goodcombo = false; + if(tracknum == 4){ + char eqn[] = "pol2"; + float a[] = {1.51673, -0.000150534, 2.64226e-06}; + float mass99 = TauTrackFilterUtils::Compute1dim(tau.P(),a,3,eqn); + if((threetrack.M() < mass99)&&(TauTrackFilterUtils::pass3prong(combination,tau))){ + goodcombo=true; + flag = 2; + } + else flag = 0; + test1prong=false; + test2prong=false; + } + else if(TauTrackFilterUtils::pass3prong(combination, tau)){ + goodcombo=true; + flag = 1; + } + if(goodcombo){ //A Combination is found which passes 3prong hypothesis + for(unsigned int i=0;i<combination.size();i++){ + if (isSS) SScombination.push_back(combination[i]); + outputtracksgood->push_back(combination[i].p4); + outputtracksgoodcharge->push_back(combination[i].charge); + } + if(isSS) flag = 0; + else flag = 1; + nProng = 3; + test1prong = false; + test2prong = false; + if(!test1prong){ //Fill Bad Track in the Case of 4 trk taus + if(tracknum == 4){ + outputtracksbad->push_back(tracks[3].p4); + outputtracksbadcharge->push_back(tracks[3].charge); + } + } + } + }//End 3 Prong Test Conditional + if (test2prong){ + std::vector<TauTrackFilterUtils::TrackInfo> pair; + for(unsigned int i=0;i<2;i++) pair.push_back(tracks[i]); + if(TauTrackFilterUtils::pass2prong(pair,tau)){ + nProng = 2; + for(unsigned int i=0;i<pair.size();i++){ //Fill Good Tracks + outputtracksgood->push_back(pair[i].p4); + outputtracksgoodcharge->push_back(pair[i].charge); + } + test1prong = false; + if(tracknum == 3){ + flag = 2; + outputtracksbad->push_back(tracks[2].p4); //Fill Bad Track in Case of 3 trk Taus + outputtracksbadcharge->push_back(tracks[2].charge); + } + else flag = 1; //Good 2 Prong if only 2 trks + } + }//End 2 Prong Test Conditional +//Step 4: Check tracks that don't pass 2 prong hypothesis against 1 prong hypothesis + if (test1prong){ + char eqn[] = "([0]*exp([1]*x))*pol6(2)+[9]"; + float a[10]; + a[0] = 0.079586; + a[1] = -0.0289929; + a[2] = 7.06684; + a[3] = -0.158835; + a[4] = 0.000607181; + a[5] = 6.8445e-05; + a[6] = -6.79205e-07; + a[7] = 2.13158e-09; + a[8] = -5.11643e-13; + a[9] = 0.030376; + float ratio10 = TauTrackFilterUtils::Compute1dim(tau.P(),a,10,eqn); + bool goodcase = false; + if(tracknum == 1) goodcase = true; + if(tracknum == 2){ + if(tracks[1].p4.Pt()/tracks[0].p4.Pt() < ratio10) goodcase = true; //Test 2trk taus most likely to actually be 1pngs + } + if((TauTrackFilterUtils::pass1prong(tracks[0].p4,tau))&&(goodcase)){ //A track is found which passes 1prong hypothesis + outputtracksgood->push_back(tracks[0].p4); + outputtracksgoodcharge->push_back(tracks[0].charge); + nProng = 1; + if (tracknum == 2){ + flag = 2; + outputtracksbad->push_back(tracks[1].p4); //Fill Bad Track in Case of 3 trk Taus + outputtracksbadcharge->push_back(tracks[1].charge); + } + else flag = 1; + } + else flag = 0; //Fake Tau + }//End 1 Prong Test Conditional + + return; +} + diff --git a/Reconstruction/tauRecTools/Root/TauTrackFilterUtils.cxx b/Reconstruction/tauRecTools/Root/TauTrackFilterUtils.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4c05a1ada32c13a1a3f508f743a7bfe860b19db0 --- /dev/null +++ b/Reconstruction/tauRecTools/Root/TauTrackFilterUtils.cxx @@ -0,0 +1,264 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauTrackFilterUtils.cxx +// package: Reconstruction/tauRec +// authors: Robert Clarke, Blake Burghgrave +// date: 2014-01-13 +// +// +//----------------------------------------------------------------------------- + +#include "TF1.h" +#include "TLorentzVector.h" +#include "tauRecTools/TauTrackFilterUtils.h" +#include <vector> +#include <iostream> +#include <string> + +using namespace TauTrackFilterUtils; + +bool TauTrackFilterUtils::pass3prong(std::vector<TauTrackFilterUtils::TrackInfo> combination,TLorentzVector tau){ + + //Step 1: calculate angles + TauTrackFilterUtils::TrackPair lp, lm, sp, ls, ms, mp; + + lm.angle = fabs(combination[0].p4.Angle(combination[1].p4.Vect())); + lm.mass = (combination[0].p4+combination[1].p4).M(); + lm.charge = combination[0].charge*combination[1].charge; + ls.angle = fabs(combination[0].p4.Angle(combination[2].p4.Vect())); + ls.mass = (combination[0].p4+combination[2].p4).M(); + ls.charge = combination[0].charge*combination[2].charge; + ms.angle = fabs(combination[1].p4.Angle(combination[2].p4.Vect())); + ms.mass = (combination[1].p4+combination[2].p4).M(); + ms.charge = combination[1].charge*combination[2].charge; + + lp = lm; + if(ls.angle > lp.angle){ + mp = lp; + lp = ls; + } + else mp = ls; + if(ms.angle > lp.angle){ + sp = mp; + mp = lp; + lp = ms; + } + else if(ms.angle > mp.angle){ + sp = mp; + mp = ms; + } + else sp = ms; + + //if (lp.angle < mp.angle) ATH_MSG_WARNING("Largest angle is smaller than medium angle!"); + //if (lp.angle < sp.angle) ATH_MSG_WARNING("Largest angle is smaller than smallest angle!"); + //if (mp.angle < sp.angle) ATH_MSG_WARNING("Medium angle is smaller than smallest angle!"); + + //Step 3: calculate 99% angles + float lp99 = 0, sp99 = 0, lm99 = 0, ls99 = 0; + float p = tau.P(), eta = fabs(tau.Eta()); + + float a[9][4]; + int npar = 4, npol = 3; + +a[0][0] = 0.179041; a[1][0] = -0.0531058; a[2][0] = 0; +a[0][1] = -0.0146875; a[1][1] = 0.00414247; a[2][1] = -0.000612045; +a[0][2] = 0.0188939; a[1][2] = -0.00452375; a[2][2] = 0.00120015; +a[0][3] = 58.3066; a[1][3] = -48.2594; a[2][3] = 26.8864; + lp99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.0741985; a[1][0] = -0.0181941; a[2][0] = 0; +a[0][1] = -0.0149252; a[1][1] = 0.00512965; a[2][1] = -0.00125462; +a[0][2] = 0.00802004; a[1][2] = -0.00252272; a[2][2] = 0.000761022; +a[0][3] = 25.0145; a[1][3] = 0; a[2][3] = 0; + sp99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.102084; a[1][0] = -0.0256446; a[2][0] = 0; +a[0][1] = -0.014259; a[1][1] = 0.00465467; a[2][1] = -0.00122856; +a[0][2] = 0.010552; a[1][2] = -0.00176856; a[2][2] = 0.000446776; +a[0][3] = 36.0848; a[1][3] = -16.1489; a[2][3] = 10.2994; + lm99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.152783; a[1][0] = -0.0390978; a[2][0] = 0; +a[0][1] = -0.0139914; a[1][1] = 0.00352551; a[2][1] = -0.000624039; +a[0][2] = 0.0159925; a[1][2] = -0.00332104; a[2][2] = 0.00100568; +a[0][3] = 43.5804; a[1][3] = -18.681; a[2][3] = 6.29988; + ls99 = ComputeAngle(p,eta,a,npar,npol); + + //Step 4: compare angles and track masses, pass if all pass, fail otherwise + if((lp.angle > lp99)||(sp.angle > sp99)||(lm.angle > lm99)||(ls.angle > ls99)) return false; //One or more of the angles has failed - not a three prong tau + return true; //Track combination is a 3prong candidate! +} //End pass3prong (efficiency studies) + +bool TauTrackFilterUtils::pass2prong(std::vector<TauTrackFilterUtils::TrackInfo> pair,TLorentzVector tau){ + float angle = fabs(pair[0].p4.Angle(pair[1].p4.Vect())); + int charge = pair[0].charge*pair[1].charge; + + // Used to have more vars, but some were unused. + //float lt99 = 0, mt99 = 0, st99 = 0, ct99 = 0, lp99 = 0, mp99 = 0, sp99 = 0, los99 = 0, sos99 = 0, ss99 = 0, lm99 = 0, ls99 = 0, ms99 = 0; + float lp99 = 0, mp99 = 0, sp99 = 0, los99 = 0, sos99 = 0, ss99 = 0, lm99 = 0; + float p = tau.P(), eta = fabs(tau.Eta()); + + float a[9][4]; + int npar = 4, npol = 9; + + a[0][0] = 0.0584232; a[1][0] = -0.0177642; a[2][0] = 0; a[3][0] = 0; a[4][0] = 0; a[5][0] = 0; a[6][0] = 0; a[7][0] = 0; a[8][0] = 0; + a[0][1] = 0.0447435; a[1][1] = -0.659295; a[2][1] = 2.99202; a[3][1] = -6.10742; a[4][1] = 6.34017; a[5][1] = -3.49095; a[6][1] = 0.972228; a[7][1] = -0.107807; a[8][1] = 0; + a[0][2] = -0.249078; a[1][2] = 3.75779; a[2][2] = -18.9563; a[3][2] = 45.4474; a[4][2] = -59.333; a[5][2] = 44.722; a[6][2] = -19.4586; a[7][2] = 4.54039; a[8][2] = -0.4399; + a[0][3] = 124.481; a[1][3] = -1129.76; a[2][3] = 5198.92; a[3][3] = -10538.1; a[4][3] = 10741.4; a[5][3] = -5757; a[6][3] = 1548.86; a[7][3] = -164.644; a[8][3] = 0; + //lt99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.057286; a[1][0] = -0.0168061; a[2][0] = 0; a[3][0] = 0; a[4][0] = 0; a[5][0] = 0; a[6][0] = 0; a[7][0] = 0; a[8][0] = 0; +a[0][1] = 0.0640448; a[1][1] = -0.922493; a[2][1] = 4.10239; a[3][1] = -8.19704; a[4][1] = 8.35619; a[5][1] = -4.52961; a[6][1] = 1.24415; a[7][1] = -0.136244; a[8][1] = 0; +a[0][2] = -0.222389; a[1][2] = 3.34829; a[2][2] = -16.8256; a[3][2] = 40.1156; a[4][2] = -52.0129; a[5][2] = 38.9152; a[6][2] = -16.8076; a[7][2] = 3.89426; a[8][2] = -0.374831; +a[0][3] = 97.8443; a[1][3] = -804.025; a[2][3] = 3412.76; a[3][3] = -6058.05; a[4][3] = 5028.88; a[5][3] = -1940.87; a[6][3] = 281.19; a[7][3] = 0; a[8][3] = 0; + //ct99 = ComputeAngle(p,eta,a,npar,npol); + npol = 3; +a[0][0] = 0.0665222; a[1][0] = 0; a[2][0] = 0; +a[0][1] = -0.018755; a[1][1] = 0.00258183; a[2][1] = 0; +a[0][2] = 0.045607; a[1][2] = -0.0234824; a[2][2] = 0.00375319; +a[0][3] = 43.8011; a[1][3] = -10.0462; a[2][3] = 0; + //mt99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.156972; a[1][0] = -0.0333305; a[2][0] = 0; +a[0][1] = -0.0231364; a[1][1] = 0.0120482; a[2][1] = -0.00289192; +a[0][2] = 0.0490898; a[1][2] = -0.0273084; a[2][2] = 0.00547379; +a[0][3] = 33.1651; a[1][3] = 0; a[2][3] = 0; + //st99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.179041; a[1][0] = -0.0531058; a[2][0] = 0; +a[0][1] = -0.0146875; a[1][1] = 0.00414247; a[2][1] = -0.000612045; +a[0][2] = 0.0188939; a[1][2] = -0.00452375; a[2][2] = 0.00120015; +a[0][3] = 58.3066; a[1][3] = -48.2594; a[2][3] = 26.8864; + lp99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.142962; a[1][0] = -0.0397119; a[2][0] = 0; +a[0][1] = -0.014084; a[1][1] = 0.00437622; a[2][1] = -0.000992845; +a[0][2] = 0.0145659; a[1][2] = -0.00270987; a[2][2] = 0.00079432; +a[0][3] = 42.4831; a[1][3] = -25.893; a[2][3] = 13.6075; + mp99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.0741985; a[1][0] = -0.0181941; a[2][0] = 0; +a[0][1] = -0.0149252; a[1][1] = 0.00512965; a[2][1] = -0.00125462; +a[0][2] = 0.00802004; a[1][2] = -0.00252272; a[2][2] = 0.000761022; +a[0][3] = 25.0145; a[1][3] = 0; a[2][3] = 0; + sp99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.177021; a[1][0] = -0.0800858; a[2][0] = 0.017266; +a[0][1] = -0.0145132; a[1][1] = 0.00508756; a[2][1] = -0.00133994; +a[0][2] = 0.0174059; a[1][2] = -0.00407948; a[2][2] = 0.00130897; +a[0][3] = 59.5959; a[1][3] = -51.819; a[2][3] = 28.742; + los99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.126153; a[1][0] = -0.0504026; a[2][0] = 0.0100601; +a[0][1] = -0.01373; a[1][1] = 0.0040825; a[2][1] = -0.00103933; +a[0][2] = 0.0121626; a[1][2] = -0.00239224; a[2][2] = 0.000832398; +a[0][3] = 43.6455; a[1][3] = -34.4061; a[2][3] = 17.558; + sos99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.159394; a[1][0] = -0.0461081; a[2][0] = 0; +a[0][1] = -0.0148102; a[1][1] = 0.00429109; a[2][1] = -0.000670516; +a[0][2] = 0.0167114; a[1][2] = -0.00539364; a[2][2] = 0.00175181; +a[0][3] = 48.371; a[1][3] = -35.9336; a[2][3] = 19.3991; + ss99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.102084; a[1][0] = -0.0256446; a[2][0] = 0; +a[0][1] = -0.014259; a[1][1] = 0.00465467; a[2][1] = -0.00122856; +a[0][2] = 0.010552; a[1][2] = -0.00176856; a[2][2] = 0.000446776; +a[0][3] = 36.0848; a[1][3] = -16.1489; a[2][3] = 10.2994; + lm99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.152783; a[1][0] = -0.0390978; a[2][0] = 0; +a[0][1] = -0.0139914; a[1][1] = 0.00352551; a[2][1] = -0.000624039; +a[0][2] = 0.0159925; a[1][2] = -0.00332104; a[2][2] = 0.00100568; +a[0][3] = 43.5804; a[1][3] = -18.681; a[2][3] = 6.29988; + //ls99 = ComputeAngle(p,eta,a,npar,npol); +a[0][0] = 0.160615; a[1][0] = -0.0284831; a[2][0] = -0.00879631; +a[0][1] = -0.0140811; a[1][1] = 0.00344844; a[2][1] = -0.000421752; +a[0][2] = 0.0173056; a[1][2] = -0.00371573; a[2][2] = 0.00112158; +a[0][3] = 59.28; a[1][3] = -48.2821; a[2][3] = 26.3103; + //ms99 = ComputeAngle(p,eta,a,npar,npol); + + if ((angle < lm99)&&((angle < lp99)||(angle < mp99)||(angle < sp99))){ + if((charge == -1)&&((angle < los99)||(angle < sos99))) return true; + else if((charge == 1)&&(angle < ss99)) return true; + else return false; + } + else return false; +} //End pass2prong + +bool TauTrackFilterUtils::pass1prong(TLorentzVector track,TLorentzVector tau){ + //Step 1: Compute Angle Between Track and Tau + float angle = fabs(track.Angle(tau.Vect())); + //Step 2: Compute 99% angle + float p = tau.P(), eta = fabs(tau.Eta()); + + int npar = 4, npol = 3; + float a[3][4]; + + a[0][0] = 0.120777; a[1][0] = -0.0261681; a[2][0] = 0; + a[0][1] = -0.0307174; a[1][1] = 0.0170112; a[2][1] = -0.00381298; + a[0][2] = 0.0662689; a[1][2] = -0.0402811; a[2][2] = 0.00760013; + a[0][3] = 24.512; a[1][3] = 0; a[2][3] = 0; + float angle99 = ComputeAngle(p,eta,a,npar,npol); + + //Step 3: compare angles and return decision + if(angle > angle99) return false; //Track angle exceeds kinematic boundary + else return true; +} //End pass1prong + +float TauTrackFilterUtils::ComputePi0Cone(int recProngs,TLorentzVector tau){ + float angle = -1; + float atrue = 0, arec = 0; + float p = tau.P(), eta = fabs(tau.Eta()); + int npar = 4, npol = 9; + float a[9][4]; + switch(recProngs){ + case 3: //3 Prong Case + a[0][0] = 0.0419208; a[1][0] = 0.0481497; a[2][0] = -0.0225545; a[3][0] = 0; a[4][0] = 0; a[5][0] = 0; a[6][0] = 0; a[7][0] = 0; a[8][0] = 0; + a[0][1] = -0.00568661; a[1][1] = -0.00336825; a[2][1] = 0.00172832; a[3][1] = 0; a[4][1] = 0; a[5][1] = 0; a[6][1] = 0; a[7][1] = 0; a[8][1] = 0; + a[0][2] = 0.00177496; a[1][2] = 0.00296773; a[2][2] = -0.00123081; a[3][2] = 0; a[4][2] = 0; a[5][2] = 0; a[6][2] = 0; a[7][2] = 0; a[8][2] = 0; + a[0][3] = 90.9262; a[1][3] = -89.7105; a[2][3] = 49.0447; a[3][3] = 0; a[4][3] = 0; a[5][3] = 0; a[6][3] = 0; a[7][3] = 0; a[8][3] = 0; + atrue = ComputeAngle(p,eta,a,npar,npol); + a[0][0] = 0.187427; a[1][0] = -0.0816934; a[2][0] = 0.0116366; a[3][0] = 0; a[4][0] = 0; a[5][0] = 0; a[6][0] = 0; a[7][0] = 0; a[8][0] = 0; + a[0][1] = -0.00961135; a[1][1] = 0.0188071; a[2][1] = -0.0279819; a[3][1] = 0.0175981; a[4][1] = -0.00374356; a[5][1] = 0; a[6][1] = 0; a[7][1] = 0; a[8][1] = 0; + a[0][2] = 0.0139015; a[1][2] = -0.0572689; a[2][2] = 0.0897538; a[3][2] = -0.0543513; a[4][2] = 0.0110609; a[5][2] = 0; a[6][2] = 0; a[7][2] = 0; a[8][2] = 0; + a[0][3] = -57.066; a[1][3] = 731.569; a[2][3] = -2351.02; a[3][3] = 3576.75; a[4][3] = -2802.87; a[5][3] = 1081.43; a[6][3] = -161.098; a[7][3] = 0; a[8][3] = 0; + arec = ComputeAngle(p,eta,a,npar,npol); + break; + case 1: //1 Prong Case + a[0][0] = 0.077467; a[1][0] = -0.0648352; a[2][0] = 0.15807; a[3][0] = -0.111211; a[4][0] = 0.0223358; a[5][0] = 0; a[6][0] = 0; a[7][0] = 0; a[8][0] = 0; + a[0][1] = -0.0212485; a[1][1] = 0.213133; a[2][1] = -1.10606; a[3][1] = 2.81065; a[4][1] = -3.95237; a[5][1] = 3.21507; a[6][1] = -1.50167; a[7][1] = 0.373201; a[8][1] = -0.0381986; + a[0][2] = 0.0180949; a[1][2] = -0.215859; a[2][2] = 1.06949; a[3][2] = -2.61577; a[4][2] = 3.56621; a[5][2] = -2.82425; a[6][2] = 1.28799; a[7][2] = -0.313272; a[8][2] = 0.0314451; + a[0][3] = 55.3658; a[1][3] = 83.3644; a[2][3] = -243.958; a[3][3] = 303.823; a[4][3] = -257.709; a[5][3] = 125.826; a[6][3] = -23.0882; a[7][3] = 0; a[8][3] = 0; + atrue = ComputeAngle(p,eta,a,npar,npol); + a[0][0] = 0.0887773; a[1][0] = 0.183147; a[2][0] = -0.53342; a[3][0] = 0.511497; a[4][0] = -0.207361; a[5][0] = 0.0299467; a[6][0] = 0; a[7][0] = 0; a[8][0] = 0; + a[0][1] = 0.00529589; a[1][1] = -0.0931825; a[2][1] = 0.331541; a[3][1] = -0.501175; a[4][1] = 0.356803; a[5][1] = -0.118988; a[6][1] = 0.0150108; a[7][1] = 0; a[8][1] = 0; + a[0][2] = -0.0152482; a[1][2] = 0.203442; a[2][2] = -0.799957; a[3][2] = 1.29237; a[4][2] = -0.943621; a[5][2] = 0.315001; a[6][2] = -0.0392101; a[7][2] = 0; a[8][2] = 0; + a[0][3] = 46.0655; a[1][3] = -61.8671; a[2][3] = 278.08; a[3][3] = -385.329; a[4][3] = 199.816; a[5][3] = -34.0016; a[6][3] = 0; a[7][3] = 0; a[8][3] = 0; + arec = ComputeAngle(p,eta,a,npar,npol); + break; + default: + //ATH_MSG_WARNING("Incorrect number of prongs!"); + return angle; + } + if (atrue > arec) angle = atrue; + else angle = arec; + return angle; +} //End ComputePi0Cone + +float TauTrackFilterUtils::ComputeAngle(float p, float eta, float a[9][4], int npar, int npol, char eqn[]){ + char name[10]; + char poleqn[10]; + + //TF1* etacoeff[npar]; //FIXME variable length array, use something like: = new TF1[npar]; + std::vector<TF1> etacoeff; + TF1* pcone = new TF1("pcone",eqn); + for(int i=0;i<npar;i++){ + sprintf(name,"p%i",i); + sprintf(poleqn,"pol%i",npol); + etacoeff.push_back(TF1(name,poleqn)); + for(int j=0;j<npol;j++) etacoeff.at(i).SetParameter(j,a[j][i]); + pcone->SetParameter(i,etacoeff.at(i).Eval(eta)); + } + float angle = pcone->Eval(p); + delete pcone; + return angle; +} + +float TauTrackFilterUtils::Compute1dim(float p, float a[10], int npar, char eqn[]){ + TF1* pcone = new TF1("pcone",eqn); + for(int i=0;i<npar;i++) pcone->SetParameter(i,a[i]); + float angle = pcone->Eval(p); + delete pcone; + return angle; +} diff --git a/Reconstruction/tauRecTools/cmt/Makefile.RootCore b/Reconstruction/tauRecTools/cmt/Makefile.RootCore new file mode 100644 index 0000000000000000000000000000000000000000..2d489eb6af629b7314a27b85e262bb16c63f2e76 --- /dev/null +++ b/Reconstruction/tauRecTools/cmt/Makefile.RootCore @@ -0,0 +1,60 @@ +# this makefile also gets parsed by shell scripts +# therefore it does not support full make syntax and features +# edit with care + +# for full documentation check: +# https://twiki.cern.ch/twiki/bin/viewauth/Atlas/RootCore#Package_Makefile + + +# the name of the package: +PACKAGE = tauRecTools + +# the libraries to link with this one: +PACKAGE_PRELOAD = + +# additional compilation flags to pass (not propagated to dependent packages): +PACKAGE_CXXFLAGS = + +# additional compilation flags to pass (propagated to dependent packages): +PACKAGE_OBJFLAGS = + +# additional linker flags to pass (for compiling the library): +PACKAGE_LDFLAGS = + +# additional linker flags to pass (for compiling binaries): +PACKAGE_BINFLAGS = + +# additional linker flags to pass (propagated to client libraries): +PACKAGE_LIBFLAGS = + +# the list of packages we depend on: +PACKAGE_DEP = AsgTools xAODTau PathResolver xAODEventInfo FourMomUtils xAODTracking + +# the list of packages we use if present, but that we can work without : +PACKAGE_TRYDEP = + +# list pattern of scripts to link directly into binary path: +PACKAGE_SCRIPTS = + +# whether to use pedantic compilation: +PACKAGE_PEDANTIC = 1 + +# whether to turn *off* optimization (set to dict to do it only for +# dictionaries): +PACKAGE_NOOPT = 0 + +# whether to build no library (needs to be set if no source files are +# present): +PACKAGE_NOCC = 0 + +# whether we build a reflex dictionary: +PACKAGE_REFLEX = 0 + +# the list of all unit tests that should be called in recursive testing, +# i.e. in unit tests that call other unit tests +# for that unit tests need to pass on all machines, and run very fast +PACKAGE_RECURSIVE_UT = + + + +include $(ROOTCOREDIR)/Makefile-common diff --git a/Reconstruction/tauRecTools/cmt/requirements b/Reconstruction/tauRecTools/cmt/requirements new file mode 100644 index 0000000000000000000000000000000000000000..f3d298d3f7e631fb1db6af99cd1d1aa3f0ed7ba9 --- /dev/null +++ b/Reconstruction/tauRecTools/cmt/requirements @@ -0,0 +1,76 @@ +package tauRecTools + +author S. Rajagopalan <srinir@bnl.gov> +author J. Griffiths <griffith@cern.ch> + +public +use AtlasPolicy AtlasPolicy-* +use AsgTools AsgTools-* Control/AthToolSupport +use xAODTau xAODTau-* Event/xAOD +use AtlasBoost AtlasBoost-* External +use AtlasROOT AtlasROOT-* External +use xAODTracking xAODTracking-* Event/xAOD +use AthLinks AthLinks-* Control + +private +use xAODJet xAODJet-* Event/xAOD +use AthContainers AthContainers-* Control +use PathResolver PathResolver-* Tools +use GaudiInterface GaudiInterface-* External +use FourMomUtils FourMomUtils-* Event +use FourMom FourMom-* Event +use AnalysisUtils AnalysisUtils-* PhysicsAnalysis/AnalysisCommon +use AtlasAIDA AtlasAIDA-* External +use AtlasCLHEP AtlasCLHEP-* External +use AtlasDetDescr AtlasDetDescr-* DetectorDescription +use CaloEvent CaloEvent-* Calorimeter +use CaloGeoHelpers CaloGeoHelpers-* Calorimeter +use CaloIdentifier CaloIdentifier-* Calorimeter +use CaloUtils CaloUtils-* Calorimeter +use CxxUtils CxxUtils-* Control +use EventKernel EventKernel-* Event +use ITrackToVertex ITrackToVertex-* Reconstruction/RecoTools +use CaloInterface CaloInterface-* Calorimeter +use InDetRecToolInterfaces InDetRecToolInterfaces-* InnerDetector/InDetRecTools +use JetEDM JetEDM-* Reconstruction/Jet +use JetEvent JetEvent-* Reconstruction/Jet +use NavFourMom NavFourMom-* Event +use Particle Particle-* Reconstruction +use RecoToolInterfaces RecoToolInterfaces-* Reconstruction/RecoTools +use TrkLinks TrkLinks-* Tracking/TrkEvent +use TrkParameters TrkParameters-* Tracking/TrkEvent +use TrkParticleBase TrkParticleBase-* Tracking/TrkEvent +use TrkParametersIdentificationHelpers TrkParametersIdentificationHelpers-* Tracking/TrkEvent +use TrkToolInterfaces TrkToolInterfaces-* Tracking/TrkTools +use TrkTrackSummary TrkTrackSummary-* Tracking/TrkEvent +use TrkVertexFitterInterfaces TrkVertexFitterInterfaces-* Tracking/TrkVertexFitter +use TrkVertexFitters TrkVertexFitters-* Tracking/TrkVertexFitter +use TrkVxEdmCnv TrkVxEdmCnv-* Tracking/TrkVertexFitter +use VxVertex VxVertex-* Tracking/TrkEvent +use tauEvent tauEvent-* Reconstruction +use xAODCaloEvent xAODCaloEvent-* Event/xAOD +use xAODPFlow xAODPFlow-* Event/xAOD +use xAODEventInfo xAODEventInfo-* Event/xAOD + + + + +# Specify the required ROOT components for cmake (transparent to CMT) +apply_pattern cmake_add_command command="find_package(ROOT COMPONENTS TMVA)" + + +public + +#macro_append tauRec_shlibflags "-L$(ROOTSYS)/lib -lCore -lCint -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lm -ldl -lpthread -rdynamic" +#macro_append ROOT_linkopts " -lTMVA" + +apply_pattern dual_use_library files="*.cxx *.c ../Root/*.cxx" + +apply_pattern declare_joboptions files="*.txt *.py" + +apply_pattern declare_runtime files="*.root *.dat *.xml" + +apply_pattern declare_python_modules files="*.py" + +apply_tag ROOTTMVALibs + diff --git a/Reconstruction/tauRecTools/src/CaloClusterVariables.cxx b/Reconstruction/tauRecTools/src/CaloClusterVariables.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ce6db2f5739825be0506c17c167f15e947c4f425 --- /dev/null +++ b/Reconstruction/tauRecTools/src/CaloClusterVariables.cxx @@ -0,0 +1,202 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CaloClusterVariables.h" +#include "tauEvent/TauJet.h" +#include "boost/foreach.hpp" +#include "math.h" + +const double CaloClusterVariables::DEFAULT = -1111.; + +//**************************************** +// constructor +//**************************************** + +CaloClusterVariables::CaloClusterVariables() : +m_numConstit((int) DEFAULT), +m_effNumConstit_int((int) DEFAULT), +m_effNumConstit(DEFAULT), +m_aveRadius(DEFAULT), +m_aveEffRadius(DEFAULT), +m_totMass(DEFAULT), +m_effMass(DEFAULT), +m_totEnergy(DEFAULT), +m_effEnergy(DEFAULT), +m_numCells(0), +m_doVertexCorrection(false) { +} + +//******************************************* +// update/fill the cluster based variables +//******************************************* + +bool CaloClusterVariables::update(const xAOD::TauJet& pTau, bool inAODmode) { + + const xAOD::Jet* pSeed = *pTau.jetLink(); + if(!pSeed) return false; + + xAOD::JetConstituentVector::const_iterator nav_it = pSeed->getConstituents().begin(); + xAOD::JetConstituentVector::const_iterator nav_itE = pSeed->getConstituents().end(); + const xAOD::CaloCluster* pCluster; + + unsigned int sumCells = 0; + + std::vector<xAOD::CaloVertexedCluster> constituents; + for (; nav_it != nav_itE; ++nav_it) { + pCluster = dynamic_cast<const xAOD::CaloCluster*> ( (*nav_it)->rawConstituent() ); + if (!pCluster) continue; + + // XXX moved the calculation of num cells up because later on we don't have access to the actual clusters anymore + if(!inAODmode) sumCells += pCluster->size(); + + // correct cluster + if (pTau.vertexLink() && m_doVertexCorrection) + constituents.emplace_back (*pCluster, (*pTau.vertexLink())->position()); + else + constituents.emplace_back (*pCluster); + } + + this->m_numConstit = (int) constituents.size(); + + // Order constituents by energy + sort(constituents.begin(), constituents.end(), CaloClusterCompare()); + + //**************************************** + // Looping over all constituents + //**************************************** + + double sum_px = 0; + double sum_py = 0; + double sum_pz = 0; + double sum_e = 0; + double sum_of_E2 = 0; + double sum_radii = 0; + CLHEP::HepLorentzVector centroid = calculateTauCentroid(this->m_numConstit, constituents); + + for (const xAOD::CaloVertexedCluster& c : constituents) { + double energy = c.e(); + sum_of_E2 += energy*energy; + + double px = c.p4().Px(); + double py = c.p4().Py(); + double pz = c.p4().Pz(); + // FF: phi is wrong in case px,py AND pz is negative when using HepLorentzVector(px,py,pz,1) + // because phi = atan(py/px) + // in trigger many clusters have negative energies/momentum + // negative values of px and py are only treated correctly if pz is positive. + // Otherwise px and py must be taken as positive values + // so using cluster eta/phi directly instead of creating a HLV. + //CLHEP::HepLorentzVector constituentHLV(px, py, pz, 1); + //sum_radii += centroid.deltaR(constituentHLV); + double dr = std::sqrt( std::pow(c.eta() - centroid.eta(),2) + std::pow(c.phi() - centroid.phi(),2)); + sum_radii += dr; + sum_e += energy; + sum_px += px; + sum_py += py; + sum_pz += pz; + } + + // Sum up the energy for constituents + this->m_totEnergy = sum_e; + + // Calculate the mass of the constituents + if (this->m_numConstit < 2) this->m_totMass = DEFAULT; + else { + double mass2 = sum_e * sum_e - (sum_px * sum_px + sum_py * sum_py + sum_pz * sum_pz); + this->m_totMass = mass2 > 0 ? sqrt(mass2) : -sqrt(-mass2); + } + + // Calculate the average radius of the constituents wrt the tau centroid + this->m_aveRadius = this->m_numConstit > 0 ? sum_radii / this->m_numConstit : DEFAULT; + + // sum of cells for the tau candidate + this->m_numCells = sumCells; + + // Effective number of constituents + this->m_effNumConstit = sum_of_E2 > 0 ? (sum_e * sum_e) / (sum_of_E2) : DEFAULT; + + this->m_effNumConstit_int = int(ceil(this->m_effNumConstit)); + + // A problem! + if (this->m_effNumConstit_int > this->m_numConstit) return false; + + // Avoid segfault, happens when we try to iterate below if sum_of_E2 was 0 or negative + if (this->m_effNumConstit_int < 0) return false; + + //**************************************** + // Now: Looping over effective constituents + //**************************************** + + sum_px = 0; + sum_py = 0; + sum_pz = 0; + sum_e = 0; + sum_of_E2 = 0; + sum_radii = 0; + centroid = calculateTauCentroid(this->m_effNumConstit_int, constituents); + + int icount = this->m_effNumConstit_int; + for (const xAOD::CaloVertexedCluster& c : constituents) { + if (icount <= 0) break; + --icount; + + double energy = c.e(); + //XXXchange to use tlorentzvector + double px = c.p4().Px(); + double py = c.p4().Py(); + double pz = c.p4().Pz(); + // FF: see comment above + //CLHEP::HepLorentzVector constituentHLV(px, py, pz, 1); + //sum_radii += centroid.deltaR(constituentHLV); + double dr = std::sqrt( std::pow(c.eta() - centroid.eta(),2) + std::pow(c.phi() - centroid.phi(),2)); + sum_radii += dr; + + sum_e += energy; + sum_px += px; + sum_py += py; + sum_pz += pz; + } + + // Sum up the energy for effective constituents + this->m_effEnergy = sum_e; + + // Calculate the mass of the constituents + if (this->m_effNumConstit_int < 2) this->m_effMass = DEFAULT; + else { + double mass2 = sum_e * sum_e - (sum_px * sum_px + sum_py * sum_py + sum_pz * sum_pz); + this->m_effMass = mass2 > 0 ? sqrt(mass2) : -sqrt(-mass2); + } + + // Calculate the average radius of the constituents wrt the tau centroid + this->m_aveEffRadius = this->m_effNumConstit_int > 0 ? sum_radii / this->m_effNumConstit_int : DEFAULT; + + return true; +} + + +//***************************************** +// Calculate the geometrical center of the +// tau constituents +//***************************************** +CLHEP::HepLorentzVector CaloClusterVariables::calculateTauCentroid(int nConst, const std::vector<xAOD::CaloVertexedCluster>& constituents) { + + double px = 0; + double py = 0; + double pz = 0; + double current_px, current_py, current_pz, modulus; + + for (const xAOD::CaloVertexedCluster& c : constituents) { + if (nConst <= 0) break; + --nConst; + current_px = c.p4().Px(); + current_py = c.p4().Py(); + current_pz = c.p4().Pz(); + modulus = sqrt(current_px * current_px + current_py * current_py + current_pz * current_pz); + px += current_px / modulus; + py += current_py / modulus; + pz += current_pz / modulus; + } + CLHEP::HepLorentzVector centroid(px, py, pz, 1); + return centroid; +} diff --git a/Reconstruction/tauRecTools/src/CaloClusterVariables.h b/Reconstruction/tauRecTools/src/CaloClusterVariables.h new file mode 100644 index 0000000000000000000000000000000000000000..88bf7c428509ccb116d423df356c7c7ef92f8b18 --- /dev/null +++ b/Reconstruction/tauRecTools/src/CaloClusterVariables.h @@ -0,0 +1,81 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef CALOCLUSTERVARIABLES_H +#define CALOCLUSTERVARIABLES_H + +#include <vector> +#include "CaloUtils/CaloVertexedCluster.h" +//#include "CaloEvent/CaloVertexedCluster.h" +#include "CxxUtils/fpcompare.h" +#include "xAODTau/TauJet.h" + +/** Provide calculations of cluster based variables using the clusters associated to the jet seed of the tau candidate. */ +class CaloClusterVariables { +public: + + static const double DEFAULT; + + CaloClusterVariables(); + + ~CaloClusterVariables() { + } + + bool update(const xAOD::TauJet& pTau, bool inAODmode=false); //!< update the internal variables for the given tau + + void setVertexCorrection(bool flag) {m_doVertexCorrection=flag;} + + // ID Variables + unsigned int numConstituents() { return (unsigned int) m_numConstit; } + + double totalMass() { return m_totMass; } + double effectiveMass() { return m_effMass; } + + double effectiveNumConstituents() { return m_effNumConstit; } + int effectiveNumConstituents_int() { return m_effNumConstit_int; } + + double averageEffectiveRadius() { return m_aveEffRadius; } + double averageRadius() { return m_aveRadius; } + + // Energy Variables + double totalEnergy() { return m_totEnergy; } + double effectiveEnergy() { return m_effEnergy; } + + //cells + unsigned int numCells() { return m_numCells; } + +private: + int m_numConstit; + int m_effNumConstit_int; + double m_effNumConstit; + double m_aveRadius; + double m_aveEffRadius; + double m_totMass; + double m_effMass; + double m_totEnergy; + double m_effEnergy; + unsigned int m_numCells; + + /** Calculate the geometrical center of the tau constituents */ + CLHEP::HepLorentzVector calculateTauCentroid(int nConst, const std::vector<xAOD::CaloVertexedCluster>& constituents); + + /** + * Enable cell origin correction. + * Eta and phi of the cells are corrected wrt to the origin of the tau vertex + */ + bool m_doVertexCorrection; +}; + +//------------------------------------------------------------------------- +//! Descending order by energy +//------------------------------------------------------------------------- +struct CaloClusterCompare { + bool operator()(const xAOD::CaloVertexedCluster& left, const xAOD::CaloVertexedCluster& right) { + //volatile double leftE = left.e(); + //volatile double rightE = right.e(); + return CxxUtils::fpcompare::greater (left.e(),right.e()); + } +}; + +#endif diff --git a/Reconstruction/tauRecTools/src/JetSeedBuilder.cxx b/Reconstruction/tauRecTools/src/JetSeedBuilder.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b7a829e895e3c889871583aad23ed1749c09e2d8 --- /dev/null +++ b/Reconstruction/tauRecTools/src/JetSeedBuilder.cxx @@ -0,0 +1,221 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/******************************************************************** +NAME: JetSeedBuilder.cxx +PACKAGE: offline/Reconstruction/tauRec +AUTHORS: N. Meyer +CREATED: Nov 27 2007 + +17/03/2010: AK: change to P4Helpers +16/05/2011: FF: fix rare case if no jet_seed found at all (coverity 21744) + Dec 2011: FF: changes for tauRec4 + ********************************************************************/ + +#include "EventKernel/SignalStateHelper.h" +#include "FourMomUtils/P4Helpers.h" + +#include "xAODJet/Jet.h" +#include "xAODJet/JetContainer.h" + +#include "xAODTau/TauJetContainer.h" +#include "xAODTau/TauJetAuxContainer.h" +#include "xAODTau/TauJet.h" + +#include "JetSeedBuilder.h" + +//------------------------------------------------------------------------- +// Constructor +//------------------------------------------------------------------------- + +JetSeedBuilder::JetSeedBuilder(const std::string& name) : + TauRecToolBase(name), + m_jetCollectionName("AntiKt4LCTopoJets"), + m_maxJetdist(0.1), + m_minJetPt(10000.0), + m_switch_jets_em_scale(false) { + declareProperty("JetCollection", m_jetCollectionName); + declareProperty("maxDist", m_maxJetdist); + declareProperty("minPt", m_minJetPt); + declareProperty("SwitchJetsEmScale", m_switch_jets_em_scale); +} + +//------------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------------- + +JetSeedBuilder::~JetSeedBuilder() { +} + + +void JetSeedBuilder::print() const { + +} + +//------------------------------------------------------------------------- +// initialize +//------------------------------------------------------------------------- + +StatusCode JetSeedBuilder::initialize() { + return StatusCode::SUCCESS; +} + +//------------------------------------------------------------------------- +// initialize +//------------------------------------------------------------------------- + +StatusCode JetSeedBuilder::finalize() { + return StatusCode::SUCCESS; +} + +//------------------------------------------------------------------------- +// Event Finalize +//------------------------------------------------------------------------- + +StatusCode JetSeedBuilder::eventFinalize() { + return StatusCode::SUCCESS; +} + +//------------------------------------------------------------------------- +// execute +//------------------------------------------------------------------------- + +StatusCode JetSeedBuilder::execute(xAOD::TauJet& pTau) { + + StatusCode sc; + + ATH_MSG_DEBUG("Starting execute"); + + bool inTrigger = tauEventData()->inTrigger(); + + if(inTrigger) + ATH_MSG_DEBUG("inTrigger read properly"); + + const xAOD::JetContainer *pJetColl; + + if (sc.isSuccess() && inTrigger) { + // called by Trigger + // retrieve JetCollection for trigger + ATH_MSG_DEBUG("Try to retrieve object from DataContainer"); + //sc = tauEventData()->getObject("JetCollection", pJetColl); + // Try a different approach: grab it directly + sc = true; + pJetColl = tauEventData()->seedContainer; + if (sc.isFailure() || !pJetColl) { + ATH_MSG_DEBUG("no JetCollection for trigger available"); + ATH_MSG_DEBUG("retrieve standard JetCollection <" << m_jetCollectionName << ">"); + // retrieve standard jet collection + sc = evtStore()->retrieve(pJetColl, m_jetCollectionName); + if (sc.isFailure()) { + ATH_MSG_WARNING("no JetCollection retrieved"); + return StatusCode::FAILURE; + } + } + } else { + // called by offline tauRec + // retrieve standard jet collection + sc = evtStore()->retrieve(pJetColl, m_jetCollectionName); + if (sc.isFailure()) { + ATH_MSG_WARNING("no JetCollection retrieved"); + return StatusCode::FAILURE; + } + } + + ATH_MSG_DEBUG("Pulling out the seed"); + + const xAOD::Jet* pJetSeed = 0; + if (pTau.jetLink().isValid()) pJetSeed = * pTau.jetLink(); + if (!pJetSeed) { + ATH_MSG_DEBUG("seed is not a jet -> tau will not be reconstructed"); + return StatusCode::FAILURE; + } + + ATH_MSG_DEBUG("Seed extracted"); + ATH_MSG_DEBUG("seed is Jet with" + << " pt=" << pJetSeed->pt() + << " eta=" << pJetSeed->eta() + << " phi=" << pJetSeed->phi() + ); + + xAOD::TauJetContainer* pContainer = tauEventData()->xAODTauContainer; + if(pContainer==0){ + pContainer = static_cast<xAOD::TauJetContainer*> (pTau.container()); + } + if(pContainer==0) { + ATH_MSG_FATAL("Can't find tau Container"); + return StatusCode::FAILURE; + } + + xAOD::TauJetContainer::iterator itTau = pContainer->begin(); + xAOD::TauJetContainer::iterator itTauE = pContainer->end(); + + for (; itTau != itTauE; ++itTau) { + if( (*itTau) == &pTau ) continue; + if ( (*itTau)->jetLink().isValid() ) { + if ( pJetSeed == ( * (*itTau)->jetLink() ) ) { + ATH_MSG_DEBUG("seed already used"); + return StatusCode::FAILURE; + } + } + } + + ///XXX need to decide whether to remove this, because there's no author flag in xAOD::TauJet + + //*********************************************************************** + // set author to both-seeded because we don't want to break any analysis + // most of the analyses are using author==3 or author==1 + // so setting author=3 should be safe for everybody + // calo seeded tau + // pTau.setAuthor(TauJetParameters::tauRec); + // // track seeded tau + // pTau.setAuthor(TauJetParameters::tau1P3P); + //*********************************************************************** + + // + // ATTENTION: direction will be overwritten later by TauAxis and TauEnergyCalibration + // + if (inTrigger && pJetSeed->e() < 0) { + // SL/SX trigger mode with negative jet_seed - do not set TauJet eta and phi in JetSeedBuilder + ATH_MSG_DEBUG("TauJet eta/phi will be set in Level2 Trigger for negative energy jet"); + + pTau.setDetail(xAOD::TauJetParameters::seedCalo_eta , static_cast<float>( pTau.eta() ) ); + pTau.setDetail(xAOD::TauJetParameters::seedCalo_phi , static_cast<float>( pTau.phi() ) ); + + pTau.setP4(pJetSeed->pt(),pTau.eta(),pTau.phi(),0.0); + + } else { + if (m_switch_jets_em_scale) { + ATH_MSG_INFO("trying to set seed jet signal state to EMSCALE, but this code has not been migrated to xAOD::Jet yet"); + //XXX still need to look up how signal states are handled for the xAOD jets + // SignalStateHelper sigstateH(P4SignalState::JETEMSCALE); + // sigstateH.controlObject(pJetSeed); + } + + pTau.setDetail(xAOD::TauJetParameters::seedCalo_eta , static_cast<float>( pJetSeed->eta() ) ); + pTau.setDetail(xAOD::TauJetParameters::seedCalo_phi , static_cast<float>( pJetSeed->phi() ) ); + if ( pJetSeed->pt() > 1e-7) + pTau.setP4(static_cast<float>( pJetSeed->pt() ) ,static_cast<float>( pJetSeed->eta() ) ,static_cast<float>( pJetSeed->phi() ) ,0.0 ); + else + pTau.setP4(static_cast<float>( pJetSeed->pt() ) ,static_cast<float>( pJetSeed->eta() ) ,static_cast<float>( pJetSeed->phi() ) , 0.0 ); + + //store 4-vector of seed + pTau.setP4( xAOD::TauJetParameters::JetSeed, pJetSeed->pt(), pJetSeed->eta(), pJetSeed->phi(), pJetSeed->m() ); + } + + // set now the link to the jet seed + // if not already set + if(!pTau.jetLink().isValid() || (*pTau.jetLink())!=pJetSeed ) pTau.setJet(pJetColl, pJetSeed); + + if ( pTau.jetLink().isValid() ) { + ATH_MSG_DEBUG("seed associated with tau is Jet with" + << " pt=" << (*pTau.jetLink())->pt() + << " eta=" << (*pTau.jetLink())->eta() + << " phi=" << (*pTau.jetLink())->phi() + ); + } + + return StatusCode::SUCCESS; +} + + diff --git a/Reconstruction/tauRecTools/src/JetSeedBuilder.h b/Reconstruction/tauRecTools/src/JetSeedBuilder.h new file mode 100644 index 0000000000000000000000000000000000000000..3ee4fb3916a82284f2a9488431c0586c969767ec --- /dev/null +++ b/Reconstruction/tauRecTools/src/JetSeedBuilder.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_JETSEEDBUILDER_H +#define TAUREC_JETSEEDBUILDER_H + +#include "tauRecTools/TauRecToolBase.h" + + +/** + * @brief Class to build tauRec seeds from topojets. + * + * Sets the jet ElementLink and basic kinematic variables in TauJet by searching a matching jet to the tau direction. + * Also the mass of the tau is set to 0. + * With tauRec4 the JetSeedBuilder method is the only one to search for a tau candidates. + * The author of the tau candidate is set 1 (former calo-only seeded) and 3 (former calo+track-seeded) to keep backwards compatibility. + * + * @author N.Meyer <nicom@cern.ch> + * @author Felix Friedrich +*/ + +class JetSeedBuilder : virtual public TauRecToolBase { +public: + + //------------------------------------------------------------- + //! Constructor + //------------------------------------------------------------- + ASG_TOOL_CLASS2( JetSeedBuilder, TauRecToolBase, ITauToolBase ) + JetSeedBuilder(const std::string& name); + + //------------------------------------------------------------- + //! Destructor + //------------------------------------------------------------- + virtual ~JetSeedBuilder(); + + virtual StatusCode initialize(); + + virtual StatusCode finalize(); + + virtual void print() const ; + + virtual StatusCode execute(xAOD::TauJet& pTau); + + virtual StatusCode eventFinalize(); + + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + +private: + std::string m_jetCollectionName; + float m_maxJetdist; + float m_minJetPt; + bool m_switch_jets_em_scale; +}; + +#endif /* JETSEEDBUILDER_H */ + diff --git a/Reconstruction/tauRecTools/src/LockTauContainers.cxx b/Reconstruction/tauRecTools/src/LockTauContainers.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b843044b7d40c56209d57bfdc47bde39436c5898 --- /dev/null +++ b/Reconstruction/tauRecTools/src/LockTauContainers.cxx @@ -0,0 +1,68 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "xAODTau/TauJetContainer.h" +#include "xAODTau/TauJetAuxContainer.h" + +#include "LockTauContainers.h" + +//********************************** +// Constructor +//********************************** + +LockTauContainers::LockTauContainers( + const std::string& name) : + TauRecToolBase(name) { +} + + +//************************************ +// initialize method +//************************************ + +StatusCode LockTauContainers::initialize() { + return StatusCode::SUCCESS; +} + +//************************************ +// finalize method +//************************************ + +StatusCode LockTauContainers::finalize() { + return StatusCode::SUCCESS; +} + +//************************************ +// event finalize method +//************************************ + +StatusCode LockTauContainers::eventFinalize() { + ATH_MSG_VERBOSE("LockTauContainers::eventFinialize"); + + //------------------------------------------------------------------------- + // Lock Containers + //------------------------------------------------------------------------- + + xAOD::TauJetContainer* pContainer = tauEventData()->xAODTauContainer; + xAOD::TauJetAuxContainer *pAuxContainer = tauEventData()->tauAuxContainer; + + StatusCode sc; + + if (pContainer) + sc = evtStore()->setConst(pContainer); + if (sc.isFailure()) { + ATH_MSG_ERROR("Cannot set tau container to const"); + return StatusCode::FAILURE; + } + + if (pAuxContainer) + sc = evtStore()->setConst(pAuxContainer); + if (sc.isFailure()) { + ATH_MSG_ERROR("Cannot set tau aux container to const"); + return StatusCode::FAILURE; + } + + ATH_MSG_VERBOSE("all tau containers are now locked"); + return StatusCode::SUCCESS; +} diff --git a/Reconstruction/tauRecTools/src/LockTauContainers.h b/Reconstruction/tauRecTools/src/LockTauContainers.h new file mode 100644 index 0000000000000000000000000000000000000000..4dc291c80d3fb819a65469972a4bea2e4f999af5 --- /dev/null +++ b/Reconstruction/tauRecTools/src/LockTauContainers.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_LOCKTAUCONTAINERS_H +#define TAUREC_LOCKTAUCONTAINERS_H + +#include "tauRecTools/TauRecToolBase.h" + +/** + * @brief Set tau containers to const to prevent downstream modification. + * + * @author Felix Friedrich + */ + +class LockTauContainers : virtual public TauRecToolBase +{ + public: + LockTauContainers(const std::string& name); + + ASG_TOOL_CLASS2(LockTauContainers, TauRecToolBase, ITauToolBase); + + ~LockTauContainers() { } + + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode execute(xAOD::TauJet&) { return StatusCode::SUCCESS; } + virtual StatusCode eventFinalize(); + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + + virtual void print() const {} +}; + +#endif /* TAUREC_LOCKTAUCONTAINERS_H */ + diff --git a/Reconstruction/tauRecTools/src/PhotonConversionPID.cxx b/Reconstruction/tauRecTools/src/PhotonConversionPID.cxx new file mode 100644 index 0000000000000000000000000000000000000000..1d570ff11435ded73635d1851cc3b0d03e1b8cfc --- /dev/null +++ b/Reconstruction/tauRecTools/src/PhotonConversionPID.cxx @@ -0,0 +1,149 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/******************************************************************** +NAME: PhotonConversionPID.cxx +PACKAGE: offline/Reconstruction/tauRec +AUTHORS: Michael Boehler <michael.boehler@desy.de> +CREATED: November 2008 + ********************************************************************/ + +#include "PhotonConversionPID.h" + +#include "xAODTracking/VertexContainer.h" +#include "TrkParticleBase/LinkToTrackParticleBase.h" +#include "TrkTrackSummary/TrackSummary.h" +#include "AthContainers/ConstDataVector.h" + +PhotonConversionPID::PhotonConversionPID(const std::string& name) + : +TauRecToolBase(name), +m_ownPolicy(static_cast<int> (SG::VIEW_ELEMENTS)) { + + declareProperty("OwnPolicy", m_ownPolicy); + declareProperty("ConversionCandidatesName", m_ConversionCandidatesName = "ConversionCandidate"); + declareProperty("ConversionOutputName", m_ConversionOutputName = "ConversionsPID_Container"); + declareProperty("ElectronProbability", m_eProb_cut = 0.9); +} + +/********************************************************************/ +PhotonConversionPID::~PhotonConversionPID() { +} + +/********************************************************************/ +StatusCode PhotonConversionPID::initialize() { + return StatusCode::SUCCESS; +} + +/********************************************************************/ +StatusCode PhotonConversionPID::finalize() { + return StatusCode::SUCCESS; +} + +/********************************************************************/ +StatusCode PhotonConversionPID::eventFinalize() { + + // ------------------------------------------------------------------ + // Retrieving VxCandidates (conversions) + // ------------------------------------------------------------------ + const xAOD::VertexContainer* ConvContainer; + StatusCode sc = evtStore()->retrieve(ConvContainer, m_ConversionCandidatesName); + + if (sc.isFailure() || !ConvContainer) { + ATH_MSG_DEBUG(" No VxCandidates container found in TDS !!"); + return StatusCode::SUCCESS; + } else { + ATH_MSG_VERBOSE("Processing Conversion Container Name = " << m_ConversionCandidatesName); + } + + ATH_MSG_DEBUG("VxContainer " << m_ConversionCandidatesName << " contains " << ConvContainer->size() << " vertices. "); + + + // ------------------------------------------------------------------------------------------------- + // Create and record the empty container VxCandidates (conversions after PID) + // ------------------------------------------------------------------------------------------------- + ATH_MSG_DEBUG(" Recording identified conversion collection with key: " << m_ConversionOutputName); + + ConstDataVector<xAOD::VertexContainer>* ConversionContainerPID = new ConstDataVector<xAOD::VertexContainer>(static_cast<SG::OwnershipPolicy> (m_ownPolicy)); + + sc = evtStore()->record(ConversionContainerPID, m_ConversionOutputName); + if (sc.isFailure()) { + ATH_MSG_ERROR("execute() : cannot record CaloCellContainer " << m_ConversionOutputName); + return sc; + } + + // Loop over ConversionVertex Container: + xAOD::VertexContainer::const_iterator itr = ConvContainer->begin(); + xAOD::VertexContainer::const_iterator itrE = ConvContainer->end(); + + for (; itr != itrE; ++itr) { + + const xAOD::Vertex* vxcand = (*itr); + + ATH_MSG_VERBOSE("Tracks at vertex: " << vxcand->nTrackParticles()); + + bool isTrk1_Conv = false; + bool isTrk2_Conv = false; + + // loop over all tracks of the vertex + for (unsigned int i = 0; i < vxcand->nTrackParticles(); i++) { + /* + // these lines navigate from a VxCandidate to the track summary of each track at vertex + Trk::VxTrackAtVertex* tmpVxAtVtx = (*trklist)[i]; + Trk::ITrackLink* trkLink = tmpVxAtVtx->trackOrParticleLink(); + Trk::LinkToTrackParticleBase * linkToTrack_part = dynamic_cast<Trk::LinkToTrackParticleBase *> (trkLink); + if (!linkToTrack_part) { + ATH_MSG_WARNING("dynamic_cast of LinkToTrackParticleBase failed"); + continue; + } + + const Trk::TrackParticleBase* TP_Base = linkToTrack_part->cachedElement(); + if (!TP_Base) { + ATH_MSG_WARNING("could not get TrackParticleBase from linkToTrack_part"); + continue; + } + + const Trk::TrackSummary* summary = TP_Base->trackSummary(); + */ + const xAOD::TrackParticle *track = vxcand->trackParticle(i); + float eProbabilityHT; + if (track && track->summaryValue(eProbabilityHT, xAOD::SummaryType::eProbabilityHT)) { + //--------------------------------------------------------------- + // Checks ID of Conversion Candidates (eProb based on TRT PID) + ATH_MSG_VERBOSE("Track " << i + 1 << " PID: " << eProbabilityHT); + + if (eProbabilityHT > m_eProb_cut) { + + // both conv tracks pass PID cut (in case of double track conv) + if (i == 0) { + isTrk1_Conv = true; + } + if (i == 1 || vxcand->nTrackParticles() == 1) { + isTrk2_Conv = true; + } + } + + //------------------------------------------------------------------ + // after both tracks have been tested and passed the PID cut the + // Conversions are stored in the new Conversion Container + if (isTrk1_Conv == true && isTrk2_Conv == true) { + ATH_MSG_VERBOSE(" Conversion accepted"); + ConversionContainerPID->push_back(vxcand); + } + + + } else { + // here a new track summary can be provided (not yet implemented) + ATH_MSG_WARNING("No Track Summary has been found! NO Photon Conversion Identification has been made!!!! "); + } + + } // end track loop + } // end vertex loop + + ATH_MSG_DEBUG("After ID " << ConversionContainerPID->size() << " Conversion are stored in " << m_ConversionOutputName); + + return StatusCode::SUCCESS; +} + +/********************************************************************/ diff --git a/Reconstruction/tauRecTools/src/PhotonConversionPID.h b/Reconstruction/tauRecTools/src/PhotonConversionPID.h new file mode 100644 index 0000000000000000000000000000000000000000..bc85bdaf2a3bcb6b107517d338b802d366b3604b --- /dev/null +++ b/Reconstruction/tauRecTools/src/PhotonConversionPID.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_PHOTONCONVERSIONPID_H +#define TAUREC_PHOTONCONVERSIONPID_H + +#include "tauRecTools/TauRecToolBase.h" + +/** + * @brief This tool identifies Conversion Candidates via a cut on the electron probability provided by the TRT PID Tool. + * + * Such Photon Conversions are needed e.g. to find Photon Conversions within the tau decay cone. + * + * @author M. Boehler + */ + +class PhotonConversionPID : virtual public TauRecToolBase { +public: + //------------------------------------------------------------- + //! Constructor + //------------------------------------------------------------- + + PhotonConversionPID(const std::string& name); + ASG_TOOL_CLASS2(PhotonConversionPID, TauRecToolBase, ITauToolBase); + + //------------------------------------------------------------- + //! Destructor + //------------------------------------------------------------- + ~PhotonConversionPID(); + + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode eventFinalize(); + virtual StatusCode execute(xAOD::TauJet&) { return StatusCode::SUCCESS; } + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + +private: + int m_ownPolicy; + + std::string m_ConversionCandidatesName; + std::string m_ConversionOutputName; + + double m_eProb_cut; +}; + +#endif diff --git a/Reconstruction/tauRecTools/src/PhotonConversionVertex.cxx b/Reconstruction/tauRecTools/src/PhotonConversionVertex.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6bab0395ceb0651620c5f24af7b07791e719dd7e --- /dev/null +++ b/Reconstruction/tauRecTools/src/PhotonConversionVertex.cxx @@ -0,0 +1,152 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/******************************************************************** +NAME: PhotonConversionVertex.cxx +PACKAGE: offline/Reconstruction/tauRec +AUTHORS: KG Tan <Kong.Guan.Tan@cern.ch> +CREATED: May 2011 + +This tool identifies conversion candidates in/near (definable) a +tau decay cone by reconstructing the conversion vertices and +applying a set of cuts optimized for tau conversions on the vertex +parameters. + ********************************************************************/ + +#include "PhotonConversionVertex.h" + +#include "tauEvent/TauJetContainer.h" +#include "xAODTracking/TrackParticleContainer.h" +#include "xAODTracking/VertexContainer.h" +#include "InDetRecToolInterfaces/IVertexFinder.h" +#include "AthContainers/ConstDataVector.h" + +PhotonConversionVertex::PhotonConversionVertex(const std::string& name) : +TauRecToolBase(name), +m_vertexFinderTool("InDet::InDetConversionFinderTools") { + declareProperty("TauRecContainer", m_inputTauJetContainerName = "TauJets"); + declareProperty("TrackParticleContainer", m_inputTrackParticleContainerName = "InDetTrackParticles"); + declareProperty("OutputConversionVertexContainerName", m_outputConversionVertexContainerName = "ConversionsVertex_Container"); + declareProperty("MaxTauJetDr", m_maxTauJetDr = 0.5); + declareProperty("ConversionFinderTool", m_vertexFinderTool); +} + +PhotonConversionVertex::~PhotonConversionVertex() { +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +StatusCode PhotonConversionVertex::initialize() { + // Get the VertexFinderTool + if (!retrieveTool(m_vertexFinderTool)) return StatusCode::FAILURE; + + return StatusCode::SUCCESS; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +StatusCode PhotonConversionVertex::finalize() { + return StatusCode::SUCCESS; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +StatusCode PhotonConversionVertex::eventFinalize() { + // get the jet container from TauEventData, or the StoreGate if it can't find it + xAOD::TauJetContainer* tauJetCont = tauEventData()->xAODTauContainer; + if (!tauJetCont) { + if (!openContainer(tauJetCont, m_inputTauJetContainerName)) + return StatusCode::FAILURE; + } + + // get the track particle container from StoreGate + const xAOD::TrackParticleContainer* trackParticleCont = 0; + if (!openContainer(trackParticleCont, m_inputTrackParticleContainerName)) return StatusCode::FAILURE; + + // Define container to store + xAOD::VertexContainer* conversionCandidatesVxCont = 0; + xAOD::VertexAuxContainer* conversionCandidatesVxContAux = 0; + conversionCandidatesVxCont = new xAOD::VertexContainer(); // No need to run conversion finding if no tracks are found! + conversionCandidatesVxContAux = new xAOD::VertexAuxContainer(); // No need to run conversion finding if no tracks are found! + std::pair<xAOD::VertexContainer*, xAOD::VertexAuxContainer*> convContPair; + + // Redo conversion over the tau seed cones, or over entire region + if (m_maxTauJetDr > 0.) { + + if (tauJetCont->size() > 0) { + + // Create a temporary TrackParticle container that contains tracks within the tau seed cones + ConstDataVector<xAOD::TrackParticleContainer> tempCont (SG::VIEW_ELEMENTS); + for (xAOD::TrackParticleContainer::const_iterator tpcItr = trackParticleCont->begin(); tpcItr != trackParticleCont->end(); ++tpcItr) { + double minTauDr = getMinDrTauDecay(tauJetCont, *tpcItr); + if (minTauDr < m_maxTauJetDr) { + tempCont.push_back(*tpcItr); + } + } + ATH_MSG_VERBOSE("Number of tracks within tau seed cones for conversion finding: " << tempCont.size()); + + // Run the conversion finding algorithm over the tau seed cones + convContPair = m_vertexFinderTool->findVertex(tempCont.asDataVector()); + conversionCandidatesVxCont = convContPair.first; + conversionCandidatesVxContAux = convContPair.second; + } +/** + else { + conversionCandidatesVxCont = new xAOD::VertexContainer(); // No need to run conversion finding if no tracks are found! + conversionCandidatesVxContAux = new xAOD::VertexAuxContainer(); // No need to run conversion finding if no tracks are found! + } +**/ + } else { + ATH_MSG_VERBOSE("Running over entire region! Number of tracks: " << trackParticleCont->size()); + + // Run the conversion finding algorithm over the entire region! + convContPair = m_vertexFinderTool->findVertex(trackParticleCont); + conversionCandidatesVxCont = convContPair.first; + conversionCandidatesVxContAux = convContPair.second; + } + + // Perform the storing + ATH_MSG_VERBOSE("Number of conversion vertices found: " << conversionCandidatesVxCont->size()); + conversionCandidatesVxCont->setStore( conversionCandidatesVxContAux ); + + if (!saveContainer(conversionCandidatesVxCont, m_outputConversionVertexContainerName)) return StatusCode::FAILURE; + if (!saveContainer(conversionCandidatesVxContAux, m_outputConversionVertexContainerName+"Aux")) return StatusCode::FAILURE; + + return StatusCode::SUCCESS; +} + +template <class T> +bool PhotonConversionVertex::openContainer(T* &container, std::string containerName) { + StatusCode sc = evtStore()->retrieve(container, containerName); + if (!container || sc.isFailure()) + ATH_MSG_FATAL("Container (" << containerName << ") not found in StoreGate"); + return container; +} + +template <class T> +bool PhotonConversionVertex::saveContainer(T* &container, std::string containerName) { + StatusCode sc = evtStore()->record(container, containerName); + if (!container || sc.isFailure()) + ATH_MSG_FATAL("Container (" << containerName << ") cannot be saved in StoreGate"); + return container; +} + +template <class T> +bool PhotonConversionVertex::retrieveTool(T &tool) { + if (tool.retrieve().isFailure()) { + ATH_MSG_FATAL("Failed to retrieve tool " << tool); + return false; + } else { + ATH_MSG_VERBOSE("Retrieved tool " << tool); + } + return true; +} + +double PhotonConversionVertex::getMinDrTauDecay(const xAOD::TauJetContainer* tauJetCont, const xAOD::TrackParticle *trackParticle) { + double minDR = 99999.; + for (xAOD::TauJetContainer::const_iterator tjcItr = tauJetCont->begin(); tjcItr != tauJetCont->end(); ++tjcItr) { + const xAOD::TauJet *tauJet = *tjcItr; + double dR = trackParticle->p4().DeltaR(tauJet->p4()); + if (dR < minDR) minDR = dR; + } + return minDR; +} diff --git a/Reconstruction/tauRecTools/src/PhotonConversionVertex.h b/Reconstruction/tauRecTools/src/PhotonConversionVertex.h new file mode 100644 index 0000000000000000000000000000000000000000..0f6d2dc2d17296ff91f9b89e5ee7a4f63eada48f --- /dev/null +++ b/Reconstruction/tauRecTools/src/PhotonConversionVertex.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_PHOTONCONVERSIONVERTEX_H +#define TAUREC_PHOTONCONVERSIONVERTEX_H + +#include "tauRecTools/TauRecToolBase.h" +#include "GaudiKernel/ToolHandle.h" + +namespace Analysis { + class TauJetContainer; +} + +namespace Rec { + class TrackParticle; +} + +namespace InDet { + class IVertexFinder; +} + +/** + * @brief Class that runs the tau conversion finding algorithm + * + * This tool identifies conversion candidates + * in/near (definable) a tau decay cone by reconstructing the conversion vertices + * and applying a set of cuts optimized for tau conversions on the vertex parameters. + * + * @author KG Tan <Kong.Guan.Tan@cern.ch> + * + */ + +class PhotonConversionVertex : virtual public TauRecToolBase { +public: + //------------------------------------------------------------- + //! Constructor and Destructor + //------------------------------------------------------------- + PhotonConversionVertex(const std::string& name); + ASG_TOOL_CLASS2(PhotonConversionVertex, TauRecToolBase, ITauToolBase); + ~PhotonConversionVertex(); + + //------------------------------------------------------------- + //! Algorithm functions + //------------------------------------------------------------- + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode eventFinalize(); + virtual StatusCode execute(xAOD::TauJet&) { return StatusCode::SUCCESS; } + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + +private: + //------------------------------------------------------------- + //! Convenience functions to handle storegate objects + //------------------------------------------------------------- + template <class T> + bool openContainer(T* &container, std::string containerName); + + template <class T> + bool saveContainer(T* &container, std::string containerName); + + template <class T> + bool retrieveTool(T &tool); + + //------------------------------------------------------------- + //! Gets the minimum dR between a particle and a set of taus + //------------------------------------------------------------- + double getMinDrTauDecay(const xAOD::TauJetContainer* tauJetCont, const xAOD::TrackParticle *trackParticle); + +private: + //------------------------------------------------------------- + //! Storegate names of input containers and output containers + //------------------------------------------------------------- + std::string m_inputTauJetContainerName; + std::string m_inputTrackParticleContainerName; + std::string m_outputConversionVertexContainerName; + + //------------------------------------------------------------- + //! Input parameters for conversion finding + //------------------------------------------------------------- + double m_maxTauJetDr; + + //------------------------------------------------------------- + //! Tool used by conversion finding, initialised in job options + //------------------------------------------------------------- + ToolHandle<InDet::IVertexFinder> m_vertexFinderTool; +}; + +#endif diff --git a/Reconstruction/tauRecTools/src/TauAxisSetter.cxx b/Reconstruction/tauRecTools/src/TauAxisSetter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..fd298e988e025d51abaffe5edebe9b13d6025110 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauAxisSetter.cxx @@ -0,0 +1,168 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CLHEP/Vector/LorentzVector.h" +#include "CLHEP/Units/SystemOfUnits.h" +#include "FourMomUtils/P4Helpers.h" +#include "FourMom/P4EEtaPhiM.h" +#include "JetEvent/Jet.h" +#include "CaloEvent/CaloCluster.h" + +//tau +#include "tauRecTools/TauEventData.h" + +#include "xAODTau/TauJetContainer.h" +#include "xAODTau/TauJetAuxContainer.h" +#include "xAODTau/TauJet.h" + +#include "CaloUtils/CaloVertexedCluster.h" + +#include "TauAxisSetter.h" + +/********************************************************************/ +TauAxisSetter::TauAxisSetter(const std::string& name) : +TauRecToolBase(name), +m_clusterCone(0.2), +m_doCellCorrection(false), +m_doAxisCorrection(true) +{ + declareProperty("ClusterCone", m_clusterCone); + declareProperty("tauContainerKey", tauContainerKey = "TauJets"); + declareProperty("CellCorrection", m_doCellCorrection); + declareProperty("AxisCorrection", m_doAxisCorrection = true); +} + +/********************************************************************/ +TauAxisSetter::~TauAxisSetter() { } + +/********************************************************************/ +StatusCode TauAxisSetter::initialize() +{ + return StatusCode::SUCCESS; +} + +StatusCode TauAxisSetter::eventInitialize() +{ + return StatusCode::SUCCESS; + +} + +/********************************************************************/ +StatusCode TauAxisSetter::execute(xAOD::TauJet& pTau) +{ + + const xAOD::Jet* pJetSeed = (*pTau.jetLink()); + if (!pJetSeed) { + ATH_MSG_WARNING("tau does not have jet seed for LC calibration"); + return StatusCode::SUCCESS; + } + + xAOD::JetConstituentVector::const_iterator cItr = pJetSeed->getConstituents().begin(); + xAOD::JetConstituentVector::const_iterator cItrE = pJetSeed->getConstituents().end(); + + /////////////////////////////////////////////////////////////////////////// + //calculate barycenter + TLorentzVector sumAllClusterVector; + TLorentzVector tempClusterVector; + for (; cItr != cItrE; ++cItr) { + tempClusterVector.SetPtEtaPhiE( (*cItr)->pt(), (*cItr)->eta(), (*cItr)->phi(), (*cItr)->e() ); + + sumAllClusterVector += tempClusterVector; + } + TLorentzVector BaryCenter; + BaryCenter.SetPtEtaPhiM(1., sumAllClusterVector.Eta(), sumAllClusterVector.Phi(), 0.); + + + /////////////////////////////////////////////////////////////////////////// + // calculate detector axis + TLorentzVector tauDetectorAxis; + // count number of constituents in core cone. could be zero! + int nConstituents = 0; + for (cItr = pJetSeed->getConstituents().begin(); cItr != cItrE; ++cItr) { + tempClusterVector.SetPtEtaPhiE( (*cItr)->pt(), (*cItr)->eta(), (*cItr)->phi(), (*cItr)->e() ); + + ATH_MSG_VERBOSE("cluster in detector axis loop:" << (*cItr)->pt()<< " " << (*cItr)->eta() << " " << (*cItr)->phi() << " " << (*cItr)->e() ); + ATH_MSG_VERBOSE("delta R is " << BaryCenter.DeltaR(tempClusterVector) ); + + if (BaryCenter.DeltaR(tempClusterVector) > m_clusterCone) + continue; + + nConstituents++; + tauDetectorAxis += tempClusterVector; + } + + if (nConstituents == 0) + { + StatusCode sc; + bool isCosmics = false; + if (tauEventData()->hasObject("IsCosmics?")) { + sc = tauEventData()->getObject("IsCosmics?", isCosmics); + } + + // If running cosmic triggers, don't worry about not having clusters in tau + if(tauEventData()->inTrigger() && isCosmics){ + ATH_MSG_WARNING("this tau candidate does not have any constituent clusters! breaking off tau tool chain and not recording this candidate!"); + } else { + ATH_MSG_DEBUG("this tau candidate does not have any constituent clusters! breaking off tau tool chain and not recording this candidate!"); + } + return StatusCode::FAILURE; + } + + ATH_MSG_VERBOSE("jet axis:" << (*pTau.jetLink())->pt()<< " " << (*pTau.jetLink())->eta() << " " << (*pTau.jetLink())->phi() << " " << (*pTau.jetLink())->e() ); + // save values for detector axis. + // FixMe: consider dropping these details variables as they are duplicated in the detector axis 4 vector + pTau.setDetail(xAOD::TauJetParameters::LC_TES_precalib , static_cast<float>( tauDetectorAxis.Pt() ) ); + pTau.setDetail(xAOD::TauJetParameters::seedCalo_eta, static_cast<float>( tauDetectorAxis.Eta() ) ); + pTau.setDetail(xAOD::TauJetParameters::seedCalo_phi, static_cast<float>( tauDetectorAxis.Phi() ) ); + ATH_MSG_VERBOSE("detector axis:" << tauDetectorAxis.Pt()<< " " << tauDetectorAxis.Eta() << " " << tauDetectorAxis.Phi() << " " << tauDetectorAxis.E() ); + + // detectorAxis (set default) + pTau.setP4(tauDetectorAxis.Pt(), tauDetectorAxis.Eta(), tauDetectorAxis.Phi(), pTau.m()); + // save detectorAxis + pTau.setP4(xAOD::TauJetParameters::DetectorAxis, tauDetectorAxis.Pt(), tauDetectorAxis.Eta(), tauDetectorAxis.Phi(), tauDetectorAxis.M()); + + /////////////////////////////////////////////////////////////////////////// + // calculate tau intermediate axis (corrected for tau vertex) + // not needed at trigger level + if(m_doAxisCorrection) + { + TLorentzVector tauInterAxis; + + for (cItr = pJetSeed->getConstituents().begin(); cItr != cItrE; ++cItr) { + tempClusterVector.SetPtEtaPhiE( (*cItr)->pt(), (*cItr)->eta(), (*cItr)->phi(), (*cItr)->e() ); + if (BaryCenter.DeltaR(tempClusterVector) > m_clusterCone) + continue; + + const xAOD::CaloCluster* cluster = dynamic_cast<const xAOD::CaloCluster*>( (*cItr)->rawConstituent() ); + if (!cluster) continue; + + if (pTau.vertexLink()) + tauInterAxis += xAOD::CaloVertexedCluster(*cluster, (*pTau.vertexLink())->position()).p4(); + else + tauInterAxis += xAOD::CaloVertexedCluster(*cluster).p4(); + } + + // save values for tau intermediate axis + // energy will be overwritten by EnergyCalibrationLC (if correctEnergy is enabled) + // direction will be overwritten by EnergyCalibrationLC (if correctAxis is enabled) + + // intermediate axis( set default) + pTau.setP4(tauInterAxis.Pt(), tauInterAxis.Eta(), tauInterAxis.Phi(), pTau.m()); + + ATH_MSG_VERBOSE("tau axis:" << tauInterAxis.Pt()<< " " << tauInterAxis.Eta() << " " << tauInterAxis.Phi() << " " << tauInterAxis.E() ); + + // save intermediateAxis + pTau.setP4(xAOD::TauJetParameters::IntermediateAxis, tauInterAxis.Pt(), tauInterAxis.Eta(), tauInterAxis.Phi(), tauInterAxis.M()); + } + + return StatusCode::SUCCESS; +} + +//----------------------------------------------------------------------------- +// Finalize +//----------------------------------------------------------------------------- +StatusCode TauAxisSetter::finalize() +{ + return StatusCode::SUCCESS; +} diff --git a/Reconstruction/tauRecTools/src/TauAxisSetter.h b/Reconstruction/tauRecTools/src/TauAxisSetter.h new file mode 100644 index 0000000000000000000000000000000000000000..a95997784976474acf95fe6f6dae57e890500a9d --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauAxisSetter.h @@ -0,0 +1,52 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUAXISSETTER_H +#define TAUREC_TAUAXISSETTER_H + +#include "tauRecTools/TauRecToolBase.h" + + +/** + * @brief Set Tau "Detector Axis" and "Intermediate Axis". + * + * Note that both axes starts from the barycenter of the cluster associated to the jet seed. + * Then only the 4-vectors of clusters in a cone of dR around these barycenter are summed up, forming the new axis. + * For the "Intermediate Axis" the clusters are correct wrt tau vertex in this step (barycenter remains the same). + * Using this procedure, the axes are different from the original jet seed axis. + * + * @author Margar Simonyan + * @author Felix Friedrich + * + */ + +class TauAxisSetter : virtual public TauRecToolBase { +public: + + TauAxisSetter(const std::string& name); + ASG_TOOL_CLASS2(TauAxisSetter, TauRecToolBase, ITauToolBase); + ~TauAxisSetter(); + + virtual StatusCode initialize(); + virtual StatusCode eventInitialize(); + virtual StatusCode finalize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + + virtual void print() const { } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + +private: + std::string tauContainerKey; + + double m_clusterCone; + /** + * enable cell origin correction + * eta and phi of the cells are corrected wrt to the origin of the tau vertex + */ + bool m_doCellCorrection; + bool m_doAxisCorrection; +}; + +#endif diff --git a/Reconstruction/tauRecTools/src/TauCalibrateEM.cxx b/Reconstruction/tauRecTools/src/TauCalibrateEM.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6f4533d973cbc1a6f1cdc2afaddb819f509aad6f --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauCalibrateEM.cxx @@ -0,0 +1,187 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TFile.h" +#include "TF1.h" +#include "GaudiKernel/Property.h" +#include "CLHEP/Units/SystemOfUnits.h" +#include "EventKernel/SignalStateHelper.h" +#include "JetEvent/Jet.h" + +#include "xAODTau/TauJet.h" +#include "tauRecTools/TauEventData.h" +#include "tauRecTools/ITauToolBase.h" +#include "TauCalibrateEM.h" + +using CLHEP::GeV; + +//------------------------------------------------------------------------- +// Constructor +//------------------------------------------------------------------------ + +TauCalibrateEM::TauCalibrateEM(const std::string& name) : +TauRecToolBase(name) { + declareProperty("response_functions_file", m_response_functions_file = "EMTES_Fits_Oct2010.root"); +} + +//------------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------------- + +TauCalibrateEM::~TauCalibrateEM() { +} + +//------------------------------------------------------------------------- +// initialize +//------------------------------------------------------------------------- + +StatusCode TauCalibrateEM::initialize() { + + std::string response_functions_path = find_file(m_response_functions_file); + TFile* f = TFile::Open(response_functions_path.c_str(), "READ"); + + m_f1_1p_lem = new TF1(*((TF1*) f->Get("OneP_LowEMF_Eta_All"))); + m_f1_1p_hem_barrel = new TF1(*((TF1*) f->Get("OneP_HighEMF_Eta_0"))); + m_f1_1p_hem_crack = new TF1(*((TF1*) f->Get("OneP_HighEMF_Eta_1"))); + m_f1_1p_hem_endcap = new TF1(*((TF1*) f->Get("OneP_HighEMF_Eta_2"))); + m_f1_mp_barrel = new TF1(*((TF1*) f->Get("MultiP_Eta_0"))); + m_f1_mp_crack = new TF1(*((TF1*) f->Get("MultiP_Eta_1"))); + m_f1_mp_endcap = new TF1(*((TF1*) f->Get("MultiP_Eta_2"))); + + m_min_1p_lem.first = m_f1_1p_lem->GetMinimumX(1.5, 3.0); + m_min_1p_lem.second = m_f1_1p_lem->Eval(m_min_1p_lem.first); + m_min_1p_hem_barrel.first = m_f1_1p_hem_barrel->GetMinimumX(1.5, 3.0); + m_min_1p_hem_barrel.second = m_f1_1p_hem_barrel->Eval(m_min_1p_hem_barrel.first); + m_min_1p_hem_crack.first = m_f1_1p_hem_crack->GetMinimumX(1.5, 3.0); + m_min_1p_hem_crack.second = m_f1_1p_hem_crack->Eval(m_min_1p_hem_crack.first); + m_min_1p_hem_endcap.first = m_f1_1p_hem_endcap->GetMinimumX(1.5, 3.0); + m_min_1p_hem_endcap.second = m_f1_1p_hem_endcap->Eval(m_min_1p_hem_endcap.first); + m_min_mp_barrel.first = m_f1_mp_barrel->GetMinimumX(2.0, 3.0); + m_min_mp_barrel.second = m_f1_mp_barrel->Eval(m_min_mp_barrel.first); + m_min_mp_crack.first = m_f1_mp_crack->GetMinimumX(2.0, 3.0); + m_min_mp_crack.second = m_f1_mp_crack->Eval(m_min_mp_crack.first); + m_min_mp_endcap.first = m_f1_mp_endcap->GetMinimumX(2.5, 3.5); + m_min_mp_endcap.second = m_f1_mp_endcap->Eval(m_min_mp_endcap.first); + + f->Close(); + return StatusCode::SUCCESS; +} + +//------------------------------------------------------------------------- +// execute +//------------------------------------------------------------------------- + +StatusCode TauCalibrateEM::execute(xAOD::TauJet& pTau) { + + const xAOD::Jet* pJetSeed = (*pTau.jetLink()); + + // XXX still need to migrate to signalstate handling of xAOD::Jet + // SignalStateHelper sigstateH(P4SignalState::JETEMSCALE); + // sigstateH.controlObject(pJetSeed); + + float emscale_ptEM = 0; + float emscale_ptHad = 0; + + if ( !pTau.detail( xAOD::TauJetParameters::etEMAtEMScale, emscale_ptEM ) ) + { + ATH_MSG_DEBUG("retrieval of tau detail failed. not calculating new em scale pt"); + return StatusCode::SUCCESS; + } + + if ( !pTau.detail( xAOD::TauJetParameters::etHadAtEMScale, emscale_ptHad ) ) + { + ATH_MSG_DEBUG("retrieval of tau detail failed. not calculating new em scale pt"); + return StatusCode::SUCCESS; + } + + double emscale_pt = emscale_ptEM + emscale_ptHad; + double emscale_eta = pJetSeed->eta(); + double emfrac = (emscale_pt != 0) ? emscale_ptEM / emscale_pt : 0.; + + + ATH_MSG_DEBUG("input variables: em_pt " << emscale_pt << " eta " << emscale_eta << " ntrack " << pTau.nTracks() << " emfrac " << emfrac); + + double new_pt = evaluate_new_pt(emscale_pt / GeV, fabs(emscale_eta), pTau.nTracks(), emfrac); + + + // do NOT set TauJet energy, as this will be done in tauCalibrateLC + //pTau.setE( new_pt * GeV * cosh( pTau.eta() ) ); + + // instead fill place holder in TauCommonDetails + //pDetails->setSeedCalo_etEMCalib(new_pt * GeV); + + pTau.setDetail( xAOD::TauJetParameters::EM_TES_scale, static_cast<float>( new_pt * GeV ) ); + + return StatusCode::SUCCESS; +} + +//----------------------------------------------------------------------------- +// Finalize +//----------------------------------------------------------------------------- + +StatusCode TauCalibrateEM::finalize() { + delete m_f1_1p_lem; + delete m_f1_1p_hem_barrel; + delete m_f1_1p_hem_crack; + delete m_f1_1p_hem_endcap; + delete m_f1_mp_barrel; + delete m_f1_mp_crack; + delete m_f1_mp_endcap; + + return StatusCode::SUCCESS; +} + +//----------------------------------------------------------------------------- +// calculate new tau pt at EM scale +//----------------------------------------------------------------------------- + +double TauCalibrateEM::evaluate_new_pt(double pt, double eta, int ntrack, double emfrac) { + + if (pt <= 0)return 0; + double ln_pt = log(pt); + if (ln_pt > 8.5) return pt; + + if (ntrack <= 1) { + // corrections for single prong taus + + if (emfrac < 0.15) { + // corrections for low EMF + if (ln_pt < m_min_1p_lem.first) return pt / m_min_1p_lem.second; + else return pt / m_f1_1p_lem->Eval(ln_pt); + } else { + // corrections for high EMF + + if (eta < 1.3) { + if (ln_pt < m_min_1p_hem_barrel.first) return pt / m_min_1p_hem_barrel.second; + else return pt / m_f1_1p_hem_barrel->Eval(ln_pt); + } else if (eta < 1.6) { + if (ln_pt < m_min_1p_hem_crack.first) return pt / m_min_1p_hem_crack.second; + else return pt / m_f1_1p_hem_crack->Eval(ln_pt); + } else { + if (ln_pt < m_min_1p_hem_endcap.first) return pt / m_min_1p_hem_endcap.second; + else return pt / m_f1_1p_hem_endcap->Eval(ln_pt); + } + } + + } else { + // corrections for multi-prong taus + + if (eta < 1.3) { + if (ln_pt < m_min_mp_barrel.first) return pt / m_min_mp_barrel.second; + else return pt / m_f1_mp_barrel->Eval(ln_pt); + } else if (eta < 1.6) { + if (ln_pt < m_min_mp_crack.first) return pt / m_min_mp_crack.second; + else return pt / m_f1_mp_crack->Eval(ln_pt); + } else { + if (ln_pt < m_min_mp_endcap.first) return pt / m_min_mp_endcap.second; + else return pt / m_f1_mp_endcap->Eval(ln_pt); + } + } + + return pt; +} + +// EOF + + diff --git a/Reconstruction/tauRecTools/src/TauCalibrateEM.h b/Reconstruction/tauRecTools/src/TauCalibrateEM.h new file mode 100644 index 0000000000000000000000000000000000000000..6c3d228b1e91ef5be11152cd7f417286363c44cc --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauCalibrateEM.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUCALIBRATEEM_H +#define TAUREC_TAUCALIBRATEEM_H + +#include <string> +#include <tauRecTools/TauRecToolBase.h> + +class TF1; + +/** implementation of tau EM energy scale (depreciated) */ +class TauCalibrateEM : virtual public TauRecToolBase { +public: + TauCalibrateEM(const std::string& name); + ASG_TOOL_CLASS2(TauCalibrateEM, TauRecToolBase, ITauToolBase); + ~TauCalibrateEM(); + + virtual StatusCode initialize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode finalize(); + + virtual void print() const { } + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + +private: + // private methods + double evaluate_new_pt(double pt, double eta, int ntrack, double emfrac); + + // configurables + std::string m_response_functions_file; + + // private data + TF1* m_f1_1p_lem; + TF1* m_f1_1p_hem_barrel; + TF1* m_f1_1p_hem_crack; + TF1* m_f1_1p_hem_endcap; + TF1* m_f1_mp_barrel; + TF1* m_f1_mp_crack; + TF1* m_f1_mp_endcap; + + std::pair<double, double> m_min_1p_lem; + std::pair<double, double> m_min_1p_hem_barrel; + std::pair<double, double> m_min_1p_hem_crack; + std::pair<double, double> m_min_1p_hem_endcap; + std::pair<double, double> m_min_mp_barrel; + std::pair<double, double> m_min_mp_crack; + std::pair<double, double> m_min_mp_endcap; + +}; + +#endif /* TAUCALIBRATEEM_H */ + diff --git a/Reconstruction/tauRecTools/src/TauCellVariables.cxx b/Reconstruction/tauRecTools/src/TauCellVariables.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b62c6c17c4af6d569b0818f370efbad486ba6ac3 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauCellVariables.cxx @@ -0,0 +1,392 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/******************************************************************** +NAME: TauCellVariables.cxx +PACKAGE: offline/Reconstruction/tauRec +AUTHORS: S. Rajagopalan +CREATED: March 15, 2001 + +Aug 2001: Add (e,px,py,pz) for sum of EM cells (FEP) +Veto cell if track is within 0.8*size. Hence 1 cell if track +is in center, more otherwise. + +Sep 2001: Take account of larger cells in third layer + +Nov 2001: Omit third layer of EM calorimeter from EM sums. This layer +can become quite thick in the barrel, so it is more likely to +be hadronic, while photons are mainly contained in the first +two layers. (D. Lissauer suggested this.) + +Dec 2002: Add tau likelihood calculation. +Feb 2003: Fix phi wrapping for et-weighted phi calculation. +Jan 2004: Use CLHEP units. Use phi = (-pi,pi]. +Feb 2004: Fix identifiers, add taucmsdrdR +March 2004: Fix CaloCluster -> CaloEnergyCluster +Jul 2004: force -PI < phi < PI +Jul 2004: move to I4Momentum +Aug 2004: admit arbitrary seeds +23/10/2006 - (AK) fixing some compilation warnings (unused parameter) +18/04/2007 - (AK) fixing some compilation warnings (unused parameter) +18/01/2008 - (NM) use etaCalo/phiCalo for merged algo, set tauJet eta/phi if not set by tau1p3p +16/03/2010 - (AK) use the cell id instead of the pointer +17/03/2010 - (AK) change to P4Helpers +16/05/2011 - (FF) introduce possibility to correct cell origin wrt to primary vertex and beamspot +Jan 2012 - (FF) add cellEnergyRing variables + ********************************************************************/ + +#include <algorithm> +#include <math.h> +#include <vector> +#include <sstream> + +#include "GaudiKernel/Property.h" +#include "CLHEP/Units/SystemOfUnits.h" + +#include "AtlasDetDescr/AtlasDetectorID.h" +#include "CaloUtils/CaloCellList.h" +#include "CaloEvent/CaloCluster.h" +#include "CaloEvent/CaloCell.h" +#include "CaloEvent/CaloSamplingHelper.h" +#include "CaloUtils/CaloVertexedCell.h" +#include "CaloIdentifier/CaloID.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "CaloGeoHelpers/CaloSampling.h" +#include "Particle/TrackParticle.h" +#include "FourMom/P4EEtaPhiM.h" + +#include "xAODTau/TauJet.h" +#include "xAODJet/Jet.h" +#include "tauRecTools/KineUtils.h" +#include "TauCellVariables.h" + +using CLHEP::GeV; + +TauCellVariables::TauCellVariables(const std::string& name) : + TauRecToolBase(name), +m_cellEthr(0.2 * GeV), +m_stripEthr(0.2 * GeV), +m_EMSumThr(0.5 * GeV), +m_EMSumR(0.2), +m_cellCone(0.2), +m_doCellCorrection(false) //FF: don't do cell correction by default +{ + + declareProperty("CellEthreshold", m_cellEthr); + declareProperty("StripEthreshold", m_stripEthr); + declareProperty("EMSumThreshold", m_EMSumThr); + declareProperty("EMSumRadius", m_EMSumR); + declareProperty("CellCone", m_cellCone); + declareProperty("CellCorrection", m_doCellCorrection); +} + +TauCellVariables::~TauCellVariables() { +} + +StatusCode TauCellVariables::finalize() { + return StatusCode::SUCCESS; +} + +StatusCode TauCellVariables::initialize() { + + ATH_MSG_VERBOSE("TauCellVariables::initialize"); // DEBUG + + StatusCode sc; + + // retrieve all helpers from det store + sc = detStore()->retrieve(m_emid); + if (sc.isFailure()) { + ATH_MSG_ERROR("Unable to retrieve LArEM_ID helper from DetectorStore"); + return sc; + } + ATH_MSG_VERBOSE("Storegate retrieved"); // DEBUG + + sc = detStore()->retrieve(m_tileid); + if (sc.isFailure()) { + ATH_MSG_ERROR("Unable to retrieve TileID helper from DetectorStore"); + return sc; + } + ATH_MSG_VERBOSE("TileID from DetectorStore"); // DEBUG + + return StatusCode::SUCCESS; +} + +StatusCode TauCellVariables::eventInitialize() { + return StatusCode::SUCCESS; +} + +StatusCode TauCellVariables::execute(xAOD::TauJet& pTau) { + + ATH_MSG_VERBOSE("execute"); // DEBUG + + AtlasDetectorID AtlasID; + + int numStripCell = 0; + int numEMCell = 0; + + double sumCellE = 0.; + double sumEMCellE = 0.; + + double eta = 0.; + double phi = 0.; + double stripEta = 0.; + double stripEta2 = 0.; + + double EMRadius = 0.; + + double sumStripET = 0.; + double sumCellET = 0.; + double sumEMCellET = 0.; + double sumCellET12 = 0.; + + double ET1Sum = 0; + + double EMET1Sum = 0; + double EMET4Sum = 0; + + double HadRadius = 0.; + double sumHadCellET = 0.; + + double cellEta, cellPhi, cellET, cellEnergy; + + std::vector<double> vCellRingEnergy(8,0.); //size=8, init with 0. + + ATH_MSG_VERBOSE("get cluster position, use for cell loop"); + + ATH_MSG_VERBOSE("position is eta=" << pTau.eta() << " phi=" << pTau.phi() ); + + //use tau vertex to correct cell position + bool applyCellCorrection = false; + if (m_doCellCorrection && pTau.vertexLink()) { + applyCellCorrection = true; + } + + /////////////////////////////////////////////////////////////////////// + // loop over all cells of the tau (placed there by the TauSeedBuilder) + + const xAOD::Jet* pJetSeed = (*pTau.jetLink()); + if (!pJetSeed) { + ATH_MSG_WARNING("tau does not have jet seed for cell variable calculation"); + return StatusCode::SUCCESS; + } + + xAOD::JetConstituentVector::const_iterator cItr = pJetSeed->getConstituents().begin(); + xAOD::JetConstituentVector::const_iterator cItrE = pJetSeed->getConstituents().end(); + + unsigned int num_cells = 0; + + std::bitset<200000> cellSeen; + + for (; cItr != cItrE; ++cItr) { + + const xAOD::CaloCluster* cluster = dynamic_cast<const xAOD::CaloCluster*>( (*cItr)->rawConstituent() ); + + CaloClusterCellLink::const_iterator firstcell = cluster->getCellLinks()->begin(); + CaloClusterCellLink::const_iterator lastcell = cluster->getCellLinks()->end(); + + + // ATH_MSG_VERBOSE( "in loop over clusters and cells : cluster phi= " << cluster->phi() << ", eta= " << cluster->eta()<< ", energy= " << cluster->e() << ", et= " <<cluster->pt() ); + + const CaloCell *cell; + double dR; + + //loop over cells and calculate the variables + for (; firstcell != lastcell; ++firstcell) { + cell = *firstcell; + + + if (cellSeen.test(cell->caloDDE()->calo_hash())) { + //already encountered this cell + continue; + } + else { + //New cell + cellSeen.set(cell->caloDDE()->calo_hash()); + } + ++num_cells; + + // ATH_MSG_VERBOSE( "in loop over clusters and cells : phi= " << cell->phi() << ", eta= " << cell->eta()<< ", energy= " << cell->energy() << ", et= " <<cell->et() ); + + // correct cell for tau vertex + if (applyCellCorrection) { + //ATH_MSG_INFO( "before cell correction: phi= " << cell->phi() << ", eta= " << cell->eta()<< ", energy= " << cell->energy() << ", et= " <<cell->et() ); + CaloVertexedCell vxCell (*cell, (*pTau.vertexLink())->position()); + cellPhi = vxCell.phi(); + cellEta = vxCell.eta(); + cellET = vxCell.et(); + cellEnergy = vxCell.energy(); + } + else { + cellPhi = cell->phi(); + cellEta = cell->eta(); + cellET = cell->et(); + cellEnergy = cell->energy(); + } + + CaloSampling::CaloSample calo = cell->caloDDE()->getSampling(); + + // Use cells those are in DR < m_cellCone of eta,phi of tau intermediate axis: + dR = Tau1P3PKineUtils::deltaR(pTau.eta(),pTau.phi(),cellEta,cellPhi); + + if (dR < m_cellCone) { + // Global sums + sumCellE += cellEnergy; + + eta += cellEnergy * cellEta; + + // Must handle phi wrapping! Compute relative to cluster phi: + double dphicc = cellPhi - pTau.phi(); + if (dphicc > M_PI) dphicc = dphicc - 2 * M_PI; + if (dphicc < -M_PI) dphicc = dphicc + 2 * M_PI; + + phi += cellEnergy*dphicc; + + // If cell is an EM cell, include in sum for EM radius and for + // total EM (e,px,py,pz) + // Nov 2000: Only include first 2 layers in EM + + if (dR < 0.1) ET1Sum += cellET; + + if ((calo == CaloSampling::PreSamplerB) || + (calo == CaloSampling::PreSamplerE) || + + (calo == CaloSampling::EMB1) || + (calo == CaloSampling::EME1) || + + (calo == CaloSampling::EMB2) || + (calo == CaloSampling::EME2) || + + (calo == CaloSampling::EMB3) || + (calo == CaloSampling::EME3)) { + if (dR < 0.1) EMET1Sum += cellET; + if (dR < m_cellCone) EMET4Sum += cellET; + } + + if ((calo == CaloSampling::PreSamplerB) || + (calo == CaloSampling::PreSamplerE) || + + (calo == CaloSampling::EMB1) || + (calo == CaloSampling::EME1) || + + (calo == CaloSampling::EMB2) || + (calo == CaloSampling::EME2)) { + + sumEMCellE += cellEnergy; + + // If cell is a strip cell, sum for stripET calculation: + if (((calo == CaloSampling::EMB1) || + (calo == CaloSampling::EME1)) // to be investigated + && (fabs(cellEta) < 2.5)) { + sumStripET += cellET; + stripEta += cellEta * cellET; + stripEta2 += pow(cellEta, 2) * cellET; + if (cellEnergy > m_stripEthr) numStripCell += 1; + } // end of strip cells + + EMRadius += dR*cellET; + sumEMCellET += cellET; + if (cellEnergy > m_cellEthr) numEMCell += 1; + + }// end of EM cells + else { // HAD cells + HadRadius += dR*cellET; + sumHadCellET += cellET; + } + + // Sum cells in 0.1 < DR < 0.2 for Econe calculation + sumCellET += cellET; + if (dR > 0.1 && dR < 0.2) sumCellET12 += cellET; + + }// end of dR < m_cellCone + else { + // nothing + } + + // vCellRingEnergy[0] is a dummy value + if (dR < 0.05) vCellRingEnergy[1] += cellET; + if (dR >= 0.05 && dR < 0.075) vCellRingEnergy[2] += cellET; + if (dR >= 0.075 && dR < 0.1) vCellRingEnergy[3] += cellET; + if (dR >= 0.1 && dR < 0.125) vCellRingEnergy[4] += cellET; + if (dR >= 0.125 && dR < 0.15) vCellRingEnergy[5] += cellET; + if (dR >= 0.15 && dR < 0.2) vCellRingEnergy[6] += cellET; + if (dR >= 0.2 && dR < 0.4) vCellRingEnergy[7] += cellET; + + } // end of loop over CaloCells + + }// end of loop over seed jet constituents + + ATH_MSG_DEBUG(num_cells << " cells in seed"); + + ////////////////////////////////////////////////////////////////////////// + // save variables + // keep this here until we know nobody complains that these were removed together with all extra details variables + // pExtraDetails->setSeedCalo_sumCellEnergy(sumCellE); + // pExtraDetails->setSeedCalo_sumEMCellEnergy(sumEMCellE); + // pExtraDetails->setSeedCalo_nEMCell(numEMCell); + // pExtraDetails->setSeedCalo_stripEt(sumStripET); + // + + pTau.setDetail(xAOD::TauJetParameters::nStrip , numStripCell ); + + // if (fabs(EMET4Sum) > 0.000001) + // pExtraDetails->setSeedCalo_EMCentFrac(EMET1Sum / EMET4Sum); + // else + // pExtraDetails->setSeedCalo_EMCentFrac(0); + + if (fabs(sumStripET) > 0.000001) { + stripEta = stripEta / sumStripET; + stripEta2 = stripEta2 / sumStripET; + } else { + stripEta = 0; + stripEta2 = -1.0; + } + + pTau.setDetail(xAOD::TauJetParameters::stripWidth2 , static_cast<float>(stripEta2 - stripEta * stripEta) ); + + if (fabs(sumEMCellET) > 0.000001) { + EMRadius = EMRadius / sumEMCellET; + } else { + EMRadius = -1.0; + } + if (fabs(sumHadCellET) > 0.000001) { + HadRadius = HadRadius / sumHadCellET; + } else { + HadRadius = -1.0; + } + + pTau.setDetail(xAOD::TauJetParameters::EMRadius , static_cast<float>( EMRadius ) ); + pTau.setDetail(xAOD::TauJetParameters::etEMAtEMScale , static_cast<float>( sumEMCellET ) ); + pTau.setDetail(xAOD::TauJetParameters::hadRadius , static_cast<float>( HadRadius ) ); + pTau.setDetail(xAOD::TauJetParameters::etHadAtEMScale , static_cast<float>( sumHadCellET ) ); + + if (fabs(sumCellET) > 0.000001) { + pTau.setDetail(xAOD::TauJetParameters::centFrac , static_cast<float>( ET1Sum / sumCellET ) ); + pTau.setDetail(xAOD::TauJetParameters::isolFrac , static_cast<float>( sumCellET12 / sumCellET ) ); + } else { + pTau.setDetail(xAOD::TauJetParameters::centFrac , static_cast<float>( 0.0 ) ); + pTau.setDetail(xAOD::TauJetParameters::isolFrac , static_cast<float>( -1.0 ) ); + } + + //save cell ring energies + + pTau.setDetail(xAOD::TauJetParameters::cellBasedEnergyRing1 , static_cast<float>( vCellRingEnergy[1] ) ); + + pTau.setDetail(xAOD::TauJetParameters::cellBasedEnergyRing2 , static_cast<float>( vCellRingEnergy[2] ) ); + + pTau.setDetail(xAOD::TauJetParameters::cellBasedEnergyRing3 , static_cast<float>( vCellRingEnergy[3] ) ); + + pTau.setDetail(xAOD::TauJetParameters::cellBasedEnergyRing4 , static_cast<float>( vCellRingEnergy[4] ) ); + + pTau.setDetail(xAOD::TauJetParameters::cellBasedEnergyRing5 , static_cast<float>( vCellRingEnergy[5] ) ); + + pTau.setDetail(xAOD::TauJetParameters::cellBasedEnergyRing6 , static_cast<float>( vCellRingEnergy[6] ) ); + + pTau.setDetail(xAOD::TauJetParameters::cellBasedEnergyRing7 , static_cast<float>( vCellRingEnergy[7] ) ); + + return StatusCode::SUCCESS; +} + + + + diff --git a/Reconstruction/tauRecTools/src/TauCellVariables.h b/Reconstruction/tauRecTools/src/TauCellVariables.h new file mode 100644 index 0000000000000000000000000000000000000000..d3977c1a5df618626b9b4d5ae771048bb46d30d6 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauCellVariables.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUCELLVARIABLES_H +#define TAUREC_TAUCELLVARIABLES_H + +#include "tauRecTools/TauRecToolBase.h" + +class LArEM_ID; +class TileID; + +/** + * @brief Calculate tau calorimeter variables from cell information. + * + * @authors Srini Rajagopalan, Anna Kaczmarska, Felix Friedrich + */ + +class TauCellVariables : virtual public TauRecToolBase { + +public: + TauCellVariables(const std::string& name); + ASG_TOOL_CLASS2(TauCellVariables, TauRecToolBase, ITauToolBase); + ~TauCellVariables(); + + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode eventInitialize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + + + virtual void print() const { } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + +private: + double m_cellEthr; //!< EM cell E threshold + double m_stripEthr; //!< cell E threshold for strips + double m_EMSumThr; //!< threshold for 4-vector EM sum + double m_EMSumR; //!< radius for 4-vector EM sum + double m_cellCone; //!< outer cone for cells used in calculations + + const LArEM_ID* m_emid; + const TileID* m_tileid; + + /** + * enable cell origin correction + * eta and phi of the cells are corrected wrt to the origin of the tau vertex + */ + bool m_doCellCorrection; +}; + +#endif /* TAUREC_TAUCELLVARIABLES_H */ + diff --git a/Reconstruction/tauRecTools/src/TauConversionFinder.cxx b/Reconstruction/tauRecTools/src/TauConversionFinder.cxx new file mode 100644 index 0000000000000000000000000000000000000000..41e2b4f77cca1e6772f8af4c2f5e74c9cbdfca07 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauConversionFinder.cxx @@ -0,0 +1,154 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/******************************************************************** +NAME: TauConversionFinder.cxx +PACKAGE: offline/Reconstruction/tauRec +AUTHORS: Michael Boehler <michael.boehler@desy.de> +CREATED: November 2008 + +This tool identifies if a tau track is reconstructed as photon +conversion track too. + ********************************************************************/ + +#include "TauConversionFinder.h" + +#include "xAODTracking/VertexContainer.h" +#include "GaudiKernel/IToolSvc.h" +#include "TrkParticleBase/LinkToTrackParticleBase.h" +#include "TrkTrackSummary/TrackSummary.h" + +/********************************************************************/ +TauConversionFinder::TauConversionFinder(const std::string& name) : + TauRecToolBase(name) { + + declareProperty("ConversionCandidatesName", m_ConversionCandidatesName = "ConversionsPID_Container"); //ConversionCandidate + declareProperty("TrackContainerName", m_trackContainerName = "InDetTrackParticles"); + declareProperty("DoNormalTracks", m_do_normal = true); + declareProperty("MinElectronProbability", m_eProb_cut = 0.9); + declareProperty("AdjustTauCharge", m_adjust_tau_charge = false); + +} + +/********************************************************************/ +TauConversionFinder::~TauConversionFinder() { +} + +/********************************************************************/ +StatusCode TauConversionFinder::initialize() { + ATH_MSG_VERBOSE("TauConversionFinder Initialising"); + + return StatusCode::SUCCESS; +} + +/********************************************************************/ +StatusCode TauConversionFinder::finalize() { + ATH_MSG_VERBOSE("TauConversionFinder Finalizing"); + + return StatusCode::SUCCESS; +} + +/********************************************************************/ +StatusCode TauConversionFinder::eventFinalize() { + + StatusCode sc; + +// const Rec::TrackParticleContainer *trackContainer; + const xAOD::TrackParticleContainer* trackContainer = 0; + + //TODO: trigger uses getObject + sc = evtStore()->retrieve(trackContainer, m_trackContainerName); + if (sc.isFailure() || !trackContainer) { + ATH_MSG_DEBUG(" No track container found in TDS !!"); + return StatusCode::SUCCESS; + } + + // ------------------------------------------------------------------ + // Retrieving VxCandidates (conversions) + // ------------------------------------------------------------------ + const xAOD::VertexContainer* ConvContainer; + + sc = evtStore()->retrieve(ConvContainer, m_ConversionCandidatesName); + if (sc.isFailure() || !ConvContainer) { + ATH_MSG_DEBUG(" No VxCandidates container found in TDS !!"); + return StatusCode::SUCCESS; + } else { + ATH_MSG_VERBOSE("Processing Conversion Container Name = " << m_ConversionCandidatesName); + } + ATH_MSG_VERBOSE("VxContainer " << m_ConversionCandidatesName << " contains " << ConvContainer->size() << " vertices. "); + + // ------------------------------------------------------------------ + // Check number of Tau Tracks + // ------------------------------------------------------------------ + if (!m_do_normal) { + return StatusCode::SUCCESS; + } + + // running in eventFinalize + // therefore need to loop over all tau candidates + xAOD::TauJetContainer *pTauJetCont = tauEventData()->xAODTauContainer; + + for (xAOD::TauJetContainer::iterator tjcItr = pTauJetCont->begin(); tjcItr != pTauJetCont->end(); ++tjcItr) { + + xAOD::TauJet& pTau = **tjcItr; + + unsigned int numTracks = pTau.nTracks(); + + m_numProng = numTracks; + + if (m_do_normal) + ATH_MSG_VERBOSE("Number of tau tracks before ConversionFinder (TauJet): " << m_numProng); + + // Loop over Conversion Container placed by TauPhotonConversionFinder + xAOD::VertexContainer::const_iterator itr = ConvContainer->begin(); + xAOD::VertexContainer::const_iterator itrE = ConvContainer->end(); + + for (; itr != itrE; ++itr) { + + const xAOD::Vertex* vxcand = (*itr); + + for (unsigned int i = 0; i < vxcand->nTrackParticles(); ++i) { + + const Trk::Track* conv_trk = vxcand->trackParticle(i)->track(); + + // just check if the track is reconstructed only by TRT + //-------------------------------------------- + // Find conversion in normal tau tracks + if (m_do_normal) { + for (unsigned int j = 0; j < numTracks; ++j) { + const xAOD::TrackParticle *pTauTrack = pTau.track(j); + const Trk::Track* tau_trk_def = pTauTrack->track(); + + if (conv_trk == tau_trk_def) { + + if (conv_trk->trackSummary()->getPID(Trk::eProbabilityHT) > m_eProb_cut) { + if (!pTau.trackFlag(pTauTrack, xAOD::TauJetParameters::isConversion)) { + ElementLink<xAOD::TrackParticleContainer> phoConvLink ; + phoConvLink.setElement(pTauTrack) ; + phoConvLink.setStorableObject( *trackContainer ) ; + phoConvLink.index(); + pTau.addTrackLink( phoConvLink ) ; + pTau.setTrackFlag(pTauTrack, xAOD::TauJetParameters::isConversion, true); + if (m_adjust_tau_charge) + pTau.setCharge(pTau.charge() - pTau.track(j)->charge()); + + m_numProng--; + } + } + } + } + } + + }//end of loop over Tracks at vertex + }// end of loop over VxContainer + + + if (m_do_normal) + ATH_MSG_VERBOSE("Number of tau tracks after ConversionFinder (TauJet): " << m_numProng); + }// end of loop over TauJetContainer + + return StatusCode::SUCCESS; +} + +/********************************************************************/ diff --git a/Reconstruction/tauRecTools/src/TauConversionFinder.h b/Reconstruction/tauRecTools/src/TauConversionFinder.h new file mode 100644 index 0000000000000000000000000000000000000000..3b9d3b78be9bcd7ccb2d2a81c703346579465b04 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauConversionFinder.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUCONVERSIONFINDER_H +#define TAUREC_TAUCONVERSIONFINDER_H + +#include "tauRecTools/TauRecToolBase.h" + +/** + * @brief This tool identifies if a tau track is reconstructed as photon conversion track too. + * + * @author M. Boehler + */ + +class TauConversionFinder : virtual public TauRecToolBase { +public: + //------------------------------------------------------------- + //! Constructor + //------------------------------------------------------------- + TauConversionFinder(const std::string& name); + ASG_TOOL_CLASS2(TauConversionFinder, TauRecToolBase, ITauToolBase); + + //------------------------------------------------------------- + //! Destructor + //------------------------------------------------------------- + ~TauConversionFinder(); + + virtual StatusCode initialize(); + virtual StatusCode eventFinalize(); + virtual StatusCode finalize(); + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + virtual StatusCode execute(xAOD::TauJet&) { return StatusCode::SUCCESS; } + + virtual void print() const { } + +private: + std::string m_vxCandidatesName; + std::string m_trackContainerName; + std::string m_ConversionCandidatesName; + + bool m_do_normal; + double m_eProb_cut; + bool m_adjust_tau_charge; + + int m_numProng; + +}; + +#endif diff --git a/Reconstruction/tauRecTools/src/TauConversionTagger.cxx b/Reconstruction/tauRecTools/src/TauConversionTagger.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a11b1151d499cafd38c69498b5bc9a731e2d4f90 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauConversionTagger.cxx @@ -0,0 +1,176 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauConversionTagger.cxx +// package: Reconstruction/tauRec +// authors: Dimitris Varouchas +// date: 2013-11-08 +// +// +//----------------------------------------------------------------------------- +//TODO: + +#include <GaudiKernel/IToolSvc.h> +#include <GaudiKernel/ListItem.h> + +#include "FourMomUtils/P4Helpers.h" +#include "FourMom/P4EEtaPhiM.h" +#include "CLHEP/Vector/LorentzVector.h" +#include "Particle/TrackParticle.h" + +#include "TrkParameters/TrackParameters.h" + +#include "tauRecTools/TauEventData.h" +#include "tauEvent/TauCommonDetails.h" +#include "tauEvent/TauJetParameters.h" + +#include "TauConversionTagger.h" + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- + +TauConversionTagger::TauConversionTagger(const std::string &name) : + TauRecToolBase(name), + m_trackToVertexTool("Reco::TrackToVertex") +{ + declareProperty("ConversionTaggerVersion", m_ConvTaggerVer = 1); + declareProperty("TrackContainerName", m_trackContainerName = "InDetTrackParticles"); + declareProperty("TrackToVertexTool", m_trackToVertexTool); + declareProperty ("TRTRatio", m_doTRTRatio = true); + declareProperty ("FullInfo", m_storeFullSummary = false); +} + +//----------------------------------------------------------------------------- +// Destructor +//----------------------------------------------------------------------------- + +TauConversionTagger::~TauConversionTagger() { +} + + +//----------------------------------------------------------------------------- +// Initializer +//----------------------------------------------------------------------------- + +StatusCode TauConversionTagger::initialize() { + return StatusCode::SUCCESS; +} + + +//----------------------------------------------------------------------------- +// Finalizer +//----------------------------------------------------------------------------- + +StatusCode TauConversionTagger::finalize() { + return StatusCode::SUCCESS; +} + + +//----------------------------------------------------------------------------- +// Execution +//----------------------------------------------------------------------------- +StatusCode TauConversionTagger::execute(xAOD::TauJet& pTau) { + + StatusCode sc; + + sc = m_trackToVertexTool.retrieve(); + if(sc.isFailure()) { + ATH_MSG_ERROR("Could not retrieve TrackToVertexTool"); + return StatusCode::FAILURE; + } + + //2012 data reporocessing bug + //events with no vertices had taus w/ associated tracks + if(pTau.vertexLink().isValid()==0) return StatusCode::SUCCESS; + + for(unsigned int j=0; j<pTau.nTracks(); j++ ) { + + const xAOD::TrackParticle *TauJetTrack = pTau.track(j); + const Trk::Perigee* perigee = m_trackToVertexTool->perigeeAtVertex(*TauJetTrack, (*pTau.vertexLink())->position()); + + // Declare TrackSummary info + // Note: all must be of type uint8_t for summaryValue filling to work in xAOD + // TODO: check if these default values are sane + uint8_t nBLHits = 0; + uint8_t expectBLayerHit = 0; + uint8_t nTRTHighTHits = 0; + uint8_t nTRTHighTOutliers = 0; + float nTRTHighT_outl = 0.; + uint8_t nTRTXenon = 0; + uint8_t nTRTHits = 0; + uint8_t nTRTOutliers = 0; + + // Fill TrackSummary info + TauJetTrack->summaryValue(nBLHits,xAOD::numberOfBLayerHits); + TauJetTrack->summaryValue(expectBLayerHit,xAOD::expectBLayerHit); + TauJetTrack->summaryValue(nTRTHighTHits,xAOD::numberOfTRTHighThresholdHits); + TauJetTrack->summaryValue(nTRTHighTOutliers,xAOD::numberOfTRTHighThresholdOutliers); + nTRTHighT_outl = nTRTHighTHits + nTRTHighTOutliers; + TauJetTrack->summaryValue(nTRTXenon,xAOD::numberOfTRTXenonHits); + TauJetTrack->summaryValue(nTRTHits,xAOD::numberOfTRTHits); + TauJetTrack->summaryValue(nTRTOutliers,xAOD::numberOfTRTOutliers); + + // TODO: check if default value is sane + m_TRTHighTOutliersRatio = 0.; + if (m_doTRTRatio || m_storeFullSummary) { + if (nTRTXenon > 0) + m_TRTHighTOutliersRatio = nTRTHighT_outl / nTRTXenon; + else if (nTRTHits + nTRTOutliers > 0) + m_TRTHighTOutliersRatio = nTRTHighT_outl / (nTRTHits+nTRTOutliers); + } + + double pt = TauJetTrack->pt(); + double d0 = perigee->parameters()[Trk::d0]; + + + m_TrkIsConv = false; + + double Rconv = sqrt(fabs(d0)*pt/(0.15*2.)); + double auxprod= d0 * perigee->parameters()[Trk::qOverP]; + double rconvii= auxprod > 0 ? Rconv : -Rconv; + delete perigee; //cleanup necessary to prevent mem leak + + if ( m_ConvTaggerVer==0 ) { + + m_a_cut[0][0]=0.0003; m_b_cut[0][0]=0.1725; + m_a_cut[0][1]=0.0003; m_b_cut[0][1]=0.2025; + + if ( nBLHits==0 && expectBLayerHit ){ + if( m_TRTHighTOutliersRatio > -m_a_cut[0][0]*Rconv + m_b_cut[0][0] && (-rconvii) > 40 && pt < 20000 ) m_TrkIsConv=true; + } + else { + if( m_TRTHighTOutliersRatio > -m_a_cut[0][1]*Rconv + m_b_cut[0][1] && (-rconvii) > 40 && pt < 20000 ) m_TrkIsConv=true; + } + } + + else if ( m_ConvTaggerVer==1 ) { + + m_a_cut[1][0]=0.0003; m_b_cut[1][0]=0.1725; + m_a_cut[1][1]=0.0003; m_b_cut[1][1]=0.2025; + + + if(nBLHits==0 ){ + if( m_TRTHighTOutliersRatio > -m_a_cut[1][0]*Rconv + m_b_cut[1][0] && (-rconvii) > 40 && pt < 20000 ) m_TrkIsConv=true; + } + else { + if( m_TRTHighTOutliersRatio > -m_a_cut[1][1]*Rconv + m_b_cut[1][1] && (-rconvii) > 40 && pt < 20000 ) m_TrkIsConv=true; + } + } + + else { + + ATH_MSG_WARNING("No tau conversion tagger compatible with version "<<m_ConvTaggerVer); + return false; + } + + ATH_MSG_VERBOSE("Is tau track a conversion? : " << m_TrkIsConv); + if (m_TrkIsConv && !pTau.trackFlag(TauJetTrack, xAOD::TauJetParameters::isConversion)) + pTau.setTrackFlag(TauJetTrack, xAOD::TauJetParameters::isConversion, true); + } + + return StatusCode::SUCCESS; +} + diff --git a/Reconstruction/tauRecTools/src/TauConversionTagger.h b/Reconstruction/tauRecTools/src/TauConversionTagger.h new file mode 100644 index 0000000000000000000000000000000000000000..af124dd8c75a4aa261ad2de95fd7d43e9f71a328 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauConversionTagger.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUCONVERSIONTAGGER_H +#define TAUREC_TAUCONVERSIONTAGGER_H + +#include "tauRecTools/TauRecToolBase.h" +#include "GaudiKernel/ToolHandle.h" +#include "ITrackToVertex/ITrackToVertex.h" + +/** + * @brief This tool identifies if a tau track originates from a photon conversion track. + * + * @author D. Varouchas + */ + + +class TauConversionTagger : virtual public TauRecToolBase { +public: + //------------------------------------------------------------- + //! Constructor + //------------------------------------------------------------- + TauConversionTagger( const std::string& name ); + ASG_TOOL_CLASS2(TauConversionTagger, TauRecToolBase, ITauToolBase); + + //------------------------------------------------------------- + //! Destructor + //------------------------------------------------------------- + ~TauConversionTagger(); + + virtual StatusCode initialize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode finalize(); + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + +private: + + std::string m_trackContainerName; + + int m_ConvTaggerVer; + bool m_TrkIsConv; + bool m_storeFullSummary; + bool m_doTRTRatio; + float m_a_cut[2][2], m_b_cut[2][2]; + float m_TRTHighTOutliersRatio; + ToolHandle<Reco::ITrackToVertex> m_trackToVertexTool; + +}; + +#endif diff --git a/Reconstruction/tauRecTools/src/TauElectronVetoVariables.cxx b/Reconstruction/tauRecTools/src/TauElectronVetoVariables.cxx new file mode 100644 index 0000000000000000000000000000000000000000..8c4e9c740a80ed064d3deb0b7ed9d1350b779fc8 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauElectronVetoVariables.cxx @@ -0,0 +1,384 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: tau1p3pEleVeto.cxx +// package: Reconstruction/tauRec +// authors: Zofia Czyczula +// date: 2006-09-27 +// +// +// This tool veto electrons. +// +// MODIFIED: +// 02-04-2007 - (AK) protection against missing egamma Collection +// 25-03-2008 - (AK for ZC) upgade of the code +// 28-03-1008 - (AK) fix for protection against missing egamma Collection +// ERROR->WARNING +// 15/04/2008 - (AK) fixing compilation warning bug #35463 +// 03-10-2008 - (ZC) upgarade of the code +// 16/03/2010 - (AK) use the cell id instead of the pointer +//----------------------------------------------------------------------------- + +//// +//TODO: this is cell based and use tracking variables -> can not run on AOD +//TODO: rename +// + +#include <algorithm> +#include <math.h> +#include <sstream> + +#include "GaudiKernel/ListItem.h" +#include "GaudiKernel/IToolSvc.h" +#include "GaudiKernel/Property.h" + +#include "CaloUtils/CaloCellList.h" +#include "CaloEvent/CaloCluster.h" +#include "CaloEvent/CaloCell.h" +#include "CaloUtils/CaloVertexedCell.h" +#include "AtlasDetDescr/AtlasDetectorID.h" +#include "CaloIdentifier/CaloID.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "CaloGeoHelpers/CaloSampling.h" + +#include "xAODTau/TauJet.h" +#include "xAODJet/Jet.h" +#include "tauRecTools/KineUtils.h" + +#include "TrkParametersIdentificationHelpers/TrackParametersIdHelper.h" +#include "RecoToolInterfaces/IParticleCaloExtensionTool.h" +#include "TauElectronVetoVariables.h" + +using CLHEP::GeV; + +//------------------------------------------------------------------------- +// Constructor +//------------------------------------------------------------------------- +TauElectronVetoVariables::TauElectronVetoVariables(const std::string &name) : +TauRecToolBase(name), +m_doCellCorrection(false), //FF: don't do cell correction by default +m_caloExtensionTool("Trk::ParticleCaloExtensionTool/ParticleCaloExtensionTool") +{ + declareProperty("CellCorrection", m_doCellCorrection); + declareProperty("ParticleCaloExtensionTool", m_caloExtensionTool ); +} + +//------------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------------- +TauElectronVetoVariables::~TauElectronVetoVariables() { } + +//------------------------------------------------------------------------- +// Finalizer +//------------------------------------------------------------------------- +StatusCode TauElectronVetoVariables::finalize() +{ + return StatusCode::SUCCESS; +} + +//------------------------------------------------------------------------- +// Initializer +//------------------------------------------------------------------------- +StatusCode TauElectronVetoVariables::initialize() +{ + if (m_caloExtensionTool.retrieve().isFailure()) { + ATH_MSG_ERROR("Cannot find tool named <" << m_caloExtensionTool << ">"); + return StatusCode::FAILURE; + } + return StatusCode::SUCCESS; +} +StatusCode TauElectronVetoVariables::eventInitialize() +{ + return StatusCode::SUCCESS; +} + +//------------------------------------------------------------------------- +// Execution +//------------------------------------------------------------------------- +StatusCode TauElectronVetoVariables::execute(xAOD::TauJet& pTau) +{ + + if (pTau.nTracks() < 1) { + return StatusCode::SUCCESS; + } + + ATH_MSG_VERBOSE(name() << " in execute() ..."); + + float detPhiTrk = 0.; + float detEtaTrk = 0.; + float clEtaTrk = 0.; + float distEtaTrk = 0.; + + float energy_3phi[101] = {0.0}; + float eta[101] = {0.0}; + int max1 = 0; + int max2 = 0; + int max = 0; + int n = 0; + float Emax1 = 0.; + float Emax2 = 0.; + float etamaxcut = 0.158; + float phimaxcut = 0.1; + float signum_eta = 0.; + + signum_eta = pTau.track(0)->eta() / fabs(pTau.track(0)->eta()); + + float sumETCellsLAr = 0.; + float eta0cut = 0.075; + float eta1cut = 0.0475; + float eta2cut = 0.075; + float eta3cut = 1.5; + float phi0cut = 0.3; + float phi1cut = 0.3; + float phi2cut = 0.075; + float phi3cut = 0.075; + float etareg = 0.; + float etacase1 = 1.8; + float etagran1 = 0.00315; + float etagran2 = 0.00415; + float sumETCellsHad1 = 0.; + float etahadcut = 0.2; + float phihadcut = 0.2; + + const CaloCell *pCell; + + //use tau vertex to correct cell position + bool applyCellCorrection = false; + if (m_doCellCorrection && pTau.vertexLink()) { + applyCellCorrection = true; + } + + //--------------------------------------------------------------------- + // Calculate eta, phi impact point of leading track at calorimeter layers EM 0,1,2,3 + //--------------------------------------------------------------------- + Trk::TrackParametersIdHelper parsIdHelper; + + const int numOfsampEM = 4; + double eta_extrapol[4]; + double phi_extrapol[4]; + + for (int i = 0; i < numOfsampEM; ++i) { + eta_extrapol[i] = -11111.; + phi_extrapol[i] = -11111.; + } + + // get the extrapolation into the calo + const Trk::CaloExtension* caloExtension = 0; + if( !m_caloExtensionTool->caloExtension(*pTau.track(0),caloExtension) || caloExtension->caloLayerIntersections().empty() ){ + ATH_MSG_WARNING("extrapolation of leading track to calo surfaces failed " ); + return StatusCode::SUCCESS; + } + + // loop over calo layers + for( auto cur = caloExtension->caloLayerIntersections().begin(); cur != caloExtension->caloLayerIntersections().end() ; ++cur ){ + + // only use entry layer + if( !parsIdHelper.isEntryToVolume((*cur)->cIdentifier()) ) continue; + + CaloSampling::CaloSample sample = parsIdHelper.caloSample((*cur)->cIdentifier()); + int index = -1; + if( sample == CaloSampling::PreSamplerE || sample == CaloSampling::PreSamplerB ) index = 0; + else if( sample == CaloSampling::EME1 || sample == CaloSampling::EMB1 ) index = 1; + else if( sample == CaloSampling::EME2 || sample == CaloSampling::EMB2 ) index = 2; + else if( sample == CaloSampling::EME3 || sample == CaloSampling::EMB3 ) index = 3; + if( index < 0 ) continue; + eta_extrapol[index] = (*cur)->position().eta(); + phi_extrapol[index] = (*cur)->position().phi(); + } + + for (int i = 0; i < numOfsampEM; ++i) { + if ( eta_extrapol[i] < -11110. || phi_extrapol[i] < -11110. ) + { + ATH_MSG_DEBUG("extrapolation of leading track to calo surfaces failed for sampling : " << i ); + return StatusCode::SUCCESS; + } + } + + const xAOD::Jet* pJetSeed = (*pTau.jetLink()); + if (!pJetSeed) { + ATH_MSG_WARNING("tau does not have jet seed for electron veto cell variable calculation"); + return StatusCode::SUCCESS; + } + + xAOD::JetConstituentVector::const_iterator cItr = pJetSeed->getConstituents().begin(); + xAOD::JetConstituentVector::const_iterator cItrE = pJetSeed->getConstituents().end(); + + std::bitset<200000> cellSeen; + + for (; cItr != cItrE; ++cItr) { + + const xAOD::CaloCluster* cluster = dynamic_cast<const xAOD::CaloCluster*>( (*cItr)->rawConstituent() ); + + CaloClusterCellLink::const_iterator pCellIter = cluster->getCellLinks()->begin(); + CaloClusterCellLink::const_iterator pCellIterE = cluster->getCellLinks()->end(); + + + double cellPhi; + double cellEta; + double cellET; + for (; pCellIter != pCellIterE; pCellIter++) { + + pCell = *pCellIter; + + if (cellSeen.test(pCell->caloDDE()->calo_hash())) { + //already encountered this cell + continue; + } + else { + //New cell + cellSeen.set(pCell->caloDDE()->calo_hash()); + } + + + if (applyCellCorrection) { + //ATH_MSG_INFO( "before cell correction: phi= " << cell->phi() << ", eta= " << cell->eta()<< ", energy= " << cell->energy() << ", et= " <<cell->et() ); + CaloVertexedCell vxCell (*pCell, (*pTau.vertexLink())->position()); + cellPhi = vxCell.phi(); + cellEta = vxCell.eta(); + cellET = vxCell.et(); + } + else { + cellPhi = pCell->phi(); + cellEta = pCell->eta(); + cellET = pCell->et(); + } + + int sampling = pCell->caloDDE()->getSampling(); + if (sampling == 4) sampling = 0; + if (sampling == 5) sampling = 1; + if (sampling == 6) sampling = 2; + if (sampling == 7) sampling = 3; + if (sampling == 18) sampling = 12; + if (sampling == 8) sampling = 12; + if (sampling == 15) sampling = 12; + if (sampling == 19) sampling = 13; + if (sampling == 16) sampling = 13; + if (sampling == 20) sampling = 14; + if (sampling == 17) sampling = 14; + + int i = 2; + if (sampling < 4) i = sampling; + if (sampling == 12 || sampling == 13 || sampling == 14) i = 3; + + detPhiTrk = Tau1P3PKineUtils::deltaPhi( cellPhi, phi_extrapol[i] ); + detEtaTrk = std::fabs( cellEta - eta_extrapol[i] ); + clEtaTrk = eta_extrapol[i]; + distEtaTrk = cellEta - eta_extrapol[i]; + + if ((sampling == 0 && detEtaTrk < eta0cut && detPhiTrk < phi0cut) || + (sampling == 1 && detEtaTrk < eta1cut && detPhiTrk < phi1cut) || + (sampling == 2 && detEtaTrk < eta2cut && detPhiTrk < phi2cut) || + (sampling == 3 && detEtaTrk < eta3cut && detPhiTrk < phi3cut)) { + + sumETCellsLAr += cellET; + } + + if (sampling == 12 && detEtaTrk < etahadcut && detPhiTrk < phihadcut) sumETCellsHad1 += cellET; + + if (fabs(cellEta) > 0.8 && fabs(cellEta) <= 1.2 && (sampling == 13 || sampling == 14) && detEtaTrk < etahadcut && detPhiTrk < phihadcut) { + sumETCellsHad1 += cellET; + } + + if (fabs(pTau.track(0)->eta()) <= 1.7) { + if (sampling == 1 && detEtaTrk < etamaxcut && detPhiTrk <= phimaxcut) { + if ((fabs(cellEta) < 1.37 || fabs(cellEta) > 1.52) && fabs(cellEta) < 1.85) { + if (fabs(clEtaTrk) <= etacase1 && fabs(cellEta) <= etacase1) { + n = 50 + int(distEtaTrk / etagran1); + } + if (fabs(clEtaTrk) <= etacase1 && fabs(cellEta) > etacase1) { + n = 50 + int(signum_eta * ((etacase1 - fabs(clEtaTrk)) / etagran1 + (-etacase1 + fabs(cellEta)) / etagran2)); + } + energy_3phi[n] = energy_3phi[n] + cellET / GeV; + eta[n] = signum_eta * (clEtaTrk - cellEta); + } else { + energy_3phi[n] = 0; + eta[n] = 0; + } + } + } else { + energy_3phi[n] = 0; + eta[n] = 0; + } + + if (fabs(cellEta) <= etacase1) { + etareg = 0.00315; + } else { + etareg = 0.00415; + } + + } //end cell loop + + }// end jet constituent loop + + for (int m1 = 0; m1 < 101; m1++) { + if ((energy_3phi[m1] > Emax1)) { + Emax1 = energy_3phi[m1]; + max1 = m1; + } + } + + for (int m2 = 1; m2 < 100; m2++) { + if (m2 == max1) continue; + + if ((energy_3phi[m2] > Emax2) && (energy_3phi[m2] > energy_3phi[m2 - 1]) && (energy_3phi[m2] > energy_3phi[m2 + 1])) { + Emax2 = energy_3phi[m2]; + max2 = m2; + } + } + + if (fabs(eta[max1]) >= etareg) { + max = max1; + } else { + max = max2; + } + + + float TRTratio = -9999.0; + uint8_t TRTHTHits; + uint8_t TRTHTOutliers; + uint8_t TRTHits; + uint8_t TRTOutliers; + + if ( !pTau.track(0)->summaryValue( TRTHits, xAOD::SummaryType::numberOfTRTHits ) ) + { + ATH_MSG_DEBUG("retrieval of track summary value failed. Not filling electron veto variables for this one prong candidate"); + return StatusCode::SUCCESS; + } + if ( !pTau.track(0)->summaryValue( TRTHTHits, xAOD::SummaryType::numberOfTRTHighThresholdHits ) ) + { + ATH_MSG_DEBUG("retrieval of track summary value failed. Not filling electron veto variables for this one prong candidate"); + return StatusCode::SUCCESS; + } + if ( !pTau.track(0)->summaryValue( TRTOutliers, xAOD::SummaryType::numberOfTRTOutliers ) ) + { + ATH_MSG_DEBUG("retrieval of track summary value failed. Not filling electron veto variables for this one prong candidate"); + return StatusCode::SUCCESS; + } + if ( !pTau.track(0)->summaryValue( TRTHTOutliers, xAOD::SummaryType::numberOfTRTHighThresholdOutliers ) ) + { + ATH_MSG_DEBUG("retrieval of track summary value failed. Not filling electron veto variables for this one prong candidate"); + return StatusCode::SUCCESS; + } + + + if (TRTHits + TRTOutliers != 0) { + TRTratio = float( TRTHTHits + TRTHTOutliers) / float( TRTHits + TRTOutliers ); + } else { + TRTratio = 0.0; + } + // } + + pTau.setDetail(xAOD::TauJetParameters::TRT_NHT_OVER_NLT , TRTratio ); + pTau.setDetail(xAOD::TauJetParameters::secMaxStripEt , energy_3phi[max] ); + pTau.setDetail(xAOD::TauJetParameters::hadLeakEt , static_cast<float>( sumETCellsHad1 / ( pTau.track(0)->pt() ) ) ); + pTau.setDetail(xAOD::TauJetParameters::sumEMCellEtOverLeadTrkPt , static_cast<float>( ( sumETCellsLAr / ( pTau.track(0)->pt() ) ) ) ); + + + return StatusCode::SUCCESS; +} + + + + diff --git a/Reconstruction/tauRecTools/src/TauElectronVetoVariables.h b/Reconstruction/tauRecTools/src/TauElectronVetoVariables.h new file mode 100644 index 0000000000000000000000000000000000000000..e1c4cf9fbeef87c9cc0e4fa431cff5a35468e7ea --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauElectronVetoVariables.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAU1P3PELEVETO_H +#define TAUREC_TAU1P3PELEVETO_H + +#include "tauRecTools/TauRecToolBase.h" +#include "GaudiKernel/ToolHandle.h" + +namespace Trk { + class IParticleCaloExtensionTool; +} + +/** + * @brief Calculate variables sensitive on electrons. + * + * The variables are mainly used by the electron veto in the TauDiscriminant package. + * + * @author Zofia Czyczula + */ + +class TauElectronVetoVariables : virtual public TauRecToolBase { +public: + + TauElectronVetoVariables(const std::string& name); + ASG_TOOL_CLASS2(TauElectronVetoVariables, TauRecToolBase, ITauToolBase); + + virtual ~TauElectronVetoVariables(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode eventInitialize(); + + virtual void print() const { } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + bool m_doCellCorrection; //!< enable cell origin correction + ToolHandle< Trk::IParticleCaloExtensionTool > m_caloExtensionTool; +}; + +#endif diff --git a/Reconstruction/tauRecTools/src/TauPi0ClusterCreator.cxx b/Reconstruction/tauRecTools/src/TauPi0ClusterCreator.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ffb8834c2f884f986185394eb78d2e486585e7d2 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauPi0ClusterCreator.cxx @@ -0,0 +1,571 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauPi0ClusterCreator.cxx +// package: Reconstruction/tauEvent +// authors: Benedict Winter, Will Davey, Stephanie Yuen +// date: 2012-10-09 +// +//----------------------------------------------------------------------------- + +#include "CaloUtils/CaloClusterStoreHelper.h" +#include "CaloGeoHelpers/CaloSampling.h" +#include "FourMomUtils/P4Helpers.h" +#include "xAODJet/Jet.h" + +#include "TauPi0ClusterCreator.h" + + +using std::vector; +using std::string; + +//------------------------------------------------------------------------- +// Constructor +//------------------------------------------------------------------------- + +TauPi0ClusterCreator::TauPi0ClusterCreator( const string& name) : + + TauRecToolBase(name) + , m_inputPi0ClusterContainerName("TauPi0SubtractedClusters") + , m_outputPi0ClusterContainerName("TauPi0Clusters") + , m_neutralPFOContainerName("TauNeutralParticleFlowObjects") + , m_hadronicClusterPFOContainerName("TauHadronicParticleFlowObjects") + , m_clusterEtCut(500.) +{ + + declareProperty("InputPi0ClusterContainerName", m_inputPi0ClusterContainerName); + declareProperty("OutputPi0ClusterContainerName", m_outputPi0ClusterContainerName); + declareProperty("NeutralPFOContainerName", m_neutralPFOContainerName); + declareProperty("HadronicClusterPFOContainerName", m_hadronicClusterPFOContainerName); + declareProperty("ClusterEtCut", m_clusterEtCut); + declareProperty("AODMode", m_AODmode=false); +} + +//------------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------------- + +TauPi0ClusterCreator::~TauPi0ClusterCreator() +{ +} + + +StatusCode TauPi0ClusterCreator::initialize() +{ + return StatusCode::SUCCESS; +} + +StatusCode TauPi0ClusterCreator::finalize() +{ + return StatusCode::SUCCESS; +} + +StatusCode TauPi0ClusterCreator::eventInitialize() +{ + // create new CaloClusterContainer + // this container will later persistified + // so it will get ownership of the objects + ATH_MSG_VERBOSE("record container " << m_outputPi0ClusterContainerName); + //--------------------------------------------------------------------- + // Create container for Pi0 + //--------------------------------------------------------------------- + m_pOutputPi0CaloClusterContainer = CaloClusterStoreHelper::makeContainer(&*evtStore(), + m_outputPi0ClusterContainerName, + msg() + ); + + //--------------------------------------------------------------------- + // Create neutral PFO container + //--------------------------------------------------------------------- + if(!m_AODmode){ + m_neutralPFOContainer = new xAOD::PFOContainer(); + m_neutralPFOAuxStore = new xAOD::PFOAuxContainer(); + m_neutralPFOContainer->setStore(m_neutralPFOAuxStore); + CHECK( evtStore()->record(m_neutralPFOContainer, m_neutralPFOContainerName ) ); + CHECK( evtStore()->record( m_neutralPFOAuxStore, m_neutralPFOContainerName + "Aux." ) ); + } + else { + CHECK( evtStore()->retrieve(m_neutralPFOContainer, m_neutralPFOContainerName) ); + CHECK( evtStore()->retrieve(m_neutralPFOAuxStore, m_neutralPFOContainerName+"Aux.") ); + } + + //--------------------------------------------------------------------- + // Create hadronic cluster PFO container + //--------------------------------------------------------------------- + if(!m_AODmode){ + m_hadronicClusterPFOContainer = new xAOD::PFOContainer(); + m_hadronicClusterPFOAuxStore = new xAOD::PFOAuxContainer(); + m_hadronicClusterPFOContainer->setStore(m_hadronicClusterPFOAuxStore); + CHECK( evtStore()->record(m_hadronicClusterPFOContainer, m_hadronicClusterPFOContainerName ) ); + CHECK( evtStore()->record( m_hadronicClusterPFOAuxStore, m_hadronicClusterPFOContainerName + "Aux." ) ); + } + else{ + CHECK( evtStore()->record(m_hadronicClusterPFOContainer, m_hadronicClusterPFOContainerName) ); + CHECK( evtStore()->record(m_hadronicClusterPFOAuxStore, m_hadronicClusterPFOContainerName + "Aux.") ); + } + + return StatusCode::SUCCESS; +} + +StatusCode TauPi0ClusterCreator::execute(xAOD::TauJet& pTau) +{ + + // Any tau needs to have PFO vectors. Set empty vectors before nTrack cut + vector<ElementLink<xAOD::PFOContainer> > empty; + pTau.setProtoChargedPFOLinks(empty); + pTau.setProtoNeutralPFOLinks(empty); + pTau.setProtoPi0PFOLinks(empty); + pTau.setHadronicPFOLinks(empty); + + // Any tau needs to have PanTauCellBasedProto 4mom. Set it to 0 before nTrack cut + pTau.setP4(xAOD::TauJetParameters::PanTauCellBasedProto, 0.0, 0.0, 0.0, 0.0); + + //--------------------------------------------------------------------- + // only run shower subtraction on 1-5 prong taus + //--------------------------------------------------------------------- + if (pTau.nTracks() == 0 || pTau.nTracks() >5 ) { + return StatusCode::SUCCESS; + } + ATH_MSG_DEBUG("ClusterCreator: new tau. \tpt = " << pTau.pt() << "\teta = " << pTau.eta() << "\tphi = " << pTau.phi() << "\tnprongs = " << pTau.nTracks()); + + //--------------------------------------------------------------------- + // retrieve the CaloClusterContainer created by the CaloClusterMaker + //--------------------------------------------------------------------- + const xAOD::CaloClusterContainer *pPi0ClusterContainer; + CHECK( evtStore()->retrieve(pPi0ClusterContainer, m_inputPi0ClusterContainerName) ); + + //--------------------------------------------------------------------- + // TODO: May want to use tau vertex in the future to calculate some cluster moments (DELTA_THETA, etc.). + // Doesn't help now, since all moments are calculated wrt 0.0.0 atm. + //--------------------------------------------------------------------- + + + // Retrieve Ecal1 shots and match them to clusters + //--------------------------------------------------------------------- + std::vector<const xAOD::PFO*> shotVector; + unsigned nShots = pTau.nShotPFOs(); + for(unsigned iShot=0;iShot<nShots;++iShot){ + const xAOD::PFO* thisShot = pTau.shotPFO(iShot); + shotVector.push_back( thisShot ); + } + std::map<unsigned, xAOD::CaloCluster*> clusterToShotMap = getClusterToShotMap(shotVector, *pPi0ClusterContainer, pTau); + + xAOD::CaloClusterContainer::const_iterator clusterItr (pPi0ClusterContainer->begin()), + clusterItrEnd(pPi0ClusterContainer->end()); + for (; clusterItr != clusterItrEnd; ++clusterItr){ + + // selection + if ((*clusterItr)->pt() < m_clusterEtCut) continue; + // Cluster container has clusters for all taus. + // Only run on clusters that belong to this tau + if ((*clusterItr)->p4().DeltaR(pTau.p4()) > .4) continue; + + // Get shots in this cluster. Need to use (CaloCluster*) (*clusterItr) + // (not a copy!) since the pointer will otherwise be different than in clusterToShotMap + std::vector<unsigned> shotsInCluster = getShotsMatchedToCluster( shotVector, clusterToShotMap, (xAOD::CaloCluster*) (*clusterItr)); + + // Make a copy of the cluster to store in output container. + xAOD::CaloCluster* pPi0Cluster = new xAOD::CaloCluster( *(*clusterItr) ); + + // store pi0 calo cluster in the output container + m_pOutputPi0CaloClusterContainer->push_back(pPi0Cluster); + + // Calculate input variables for fake supression. + // Do this before applying the vertex correction, + // since the position of the cluster in the + // calorimeter is required. + float EM1CoreFrac = getEM1CoreFrac(pPi0Cluster); + int NHitsInEM1 = getNPhotons(shotVector, shotsInCluster); + vector<int> NPosECellsInLayer = getNPosECells(pPi0Cluster); + vector<float> firstEtaWRTClusterPositionInLayer = get1stEtaMomWRTCluster(pPi0Cluster); + vector<float> secondEtaWRTClusterPositionInLayer = get2ndEtaMomWRTCluster(pPi0Cluster); + + // Retrieve cluster moments that are used for fake supression and that are not stored in AOD + // for every cluster. Do this after applying the vertex correction, since the moments + // (especcially DELTA_PHI and DELTA_THETA) must be calculated WRT the tau vertex + double CENTER_MAG = 0.0; + double FIRST_ETA = 0.0; + double SECOND_R = 0.0; + double SECOND_LAMBDA = 0.0; + double DELTA_PHI = 0.0; + double DELTA_THETA = 0.0; + double CENTER_LAMBDA = 0.0; + double LATERAL = 0.0; + double LONGITUDINAL = 0.0; + double ENG_FRAC_EM = 0.0; + double ENG_FRAC_MAX = 0.0; + double ENG_FRAC_CORE = 0.0; + double SECOND_ENG_DENS = 0.0; + + // TODO: Replace numbers by human readable enums + if( !pPi0Cluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 404, CENTER_MAG) ) ATH_MSG_WARNING("Couldn't retrieve CENTER_MAG moment. Set it to 0."); + + if( !pPi0Cluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 102, FIRST_ETA) ) ATH_MSG_WARNING("Couldn't retrieve FIRST_ETA moment. Set it to 0."); + if( !pPi0Cluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 201, SECOND_R) ) ATH_MSG_WARNING("Couldn't retrieve SECOND_R moment. Set it to 0."); + if( !pPi0Cluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 202, SECOND_LAMBDA) ) ATH_MSG_WARNING("Couldn't retrieve SECOND_LAMBDA moment. Set it to 0."); + if( !pPi0Cluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 301, DELTA_PHI) ) ATH_MSG_WARNING("Couldn't retrieve DELTA_PHI moment. Set it to 0."); + if( !pPi0Cluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 302, DELTA_THETA) ) ATH_MSG_WARNING("Couldn't retrieve DELTA_THETA moment. Set it to 0."); + if( !pPi0Cluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 501, CENTER_LAMBDA) ) ATH_MSG_WARNING("Couldn't retrieve CENTER_LAMBDA moment. Set it to 0."); + if( !pPi0Cluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 601, LATERAL) ) ATH_MSG_WARNING("Couldn't retrieve LATERAL moment. Set it to 0."); + if( !pPi0Cluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 602, LONGITUDINAL) ) ATH_MSG_WARNING("Couldn't retrieve LONGITUDINAL moment. Set it to 0."); + if( !pPi0Cluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 701, ENG_FRAC_EM) ) ATH_MSG_WARNING("Couldn't retrieve ENG_FRAC_EM moment. Set it to 0."); + if( !pPi0Cluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 702, ENG_FRAC_MAX) ) ATH_MSG_WARNING("Couldn't retrieve ENG_FRAC_MAX moment. Set it to 0."); + if( !pPi0Cluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 703, ENG_FRAC_CORE) ) ATH_MSG_WARNING("Couldn't retrieve ENG_FRAC_CORE moment. Set it to 0."); + if( !pPi0Cluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 805, SECOND_ENG_DENS) ) ATH_MSG_WARNING("Couldn't retrieve SECOND_ENG_DENS moment. Set it to 0."); + + float E_EM1 = pPi0Cluster->eSample(CaloSampling::EMB1) + pPi0Cluster->eSample(CaloSampling::EME1); + float E_EM2 = pPi0Cluster->eSample(CaloSampling::EMB2) + pPi0Cluster->eSample(CaloSampling::EME2); + + // create neutral PFO. Set BDTScore to dummy value <-1. The BDT score is calculated within TauPi0Selector.cxx. + xAOD::PFO* neutralPFO = new xAOD::PFO(); + m_neutralPFOContainer->push_back( neutralPFO ); + + // Create element link from tau to neutral PFO + ElementLink<xAOD::PFOContainer> PFOElementLink; + PFOElementLink.toContainedElement( *m_neutralPFOContainer, neutralPFO ); + pTau.addProtoNeutralPFOLink( PFOElementLink ); + + // Set PFO variables + ElementLink<xAOD::CaloClusterContainer> clusElementLink; + clusElementLink.toContainedElement( *m_pOutputPi0CaloClusterContainer, pPi0Cluster ); + neutralPFO->setClusterLink( clusElementLink ); + + neutralPFO->setP4( (float) pPi0Cluster->pt(), (float) pPi0Cluster->eta(), (float) pPi0Cluster->phi(), (float) pPi0Cluster->m()); + neutralPFO->setBDTPi0Score( (float) -9999. ); + neutralPFO->setCharge( 0. ); + neutralPFO->setCenterMag( (float) CENTER_MAG); + neutralPFO->setAttribute<int>(xAOD::PFODetails::PFOAttributes::nPi0Proto, -1); + + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_FIRST_ETA, (float) FIRST_ETA); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_SECOND_R, (float) SECOND_R); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_SECOND_LAMBDA, (float) SECOND_LAMBDA); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_DELTA_PHI, (float) DELTA_PHI); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_DELTA_THETA, (float) DELTA_THETA); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_CENTER_LAMBDA, (float) CENTER_LAMBDA); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_LATERAL, (float) LATERAL); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_LONGITUDINAL, (float) LONGITUDINAL); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_ENG_FRAC_EM, (float) ENG_FRAC_EM); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_ENG_FRAC_MAX, (float) ENG_FRAC_MAX); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_ENG_FRAC_CORE, (float) ENG_FRAC_CORE); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_SECOND_ENG_DENS, (float) SECOND_ENG_DENS); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_energy_EM1, (float) E_EM1); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_energy_EM2, (float) E_EM2); + + + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_EM1CoreFrac, EM1CoreFrac); + neutralPFO->setAttribute<int>(xAOD::PFODetails::PFOAttributes::cellBased_NHitsInEM1, NHitsInEM1); + neutralPFO->setAttribute<int>(xAOD::PFODetails::PFOAttributes::cellBased_NPosECells_PS, NPosECellsInLayer.at(0)); + neutralPFO->setAttribute<int>(xAOD::PFODetails::PFOAttributes::cellBased_NPosECells_EM1, NPosECellsInLayer.at(1)); + neutralPFO->setAttribute<int>(xAOD::PFODetails::PFOAttributes::cellBased_NPosECells_EM2, NPosECellsInLayer.at(2)); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_firstEtaWRTClusterPosition_EM1, firstEtaWRTClusterPositionInLayer.at(1)); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_firstEtaWRTClusterPosition_EM2, firstEtaWRTClusterPositionInLayer.at(2)); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_secondEtaWRTClusterPosition_EM1, secondEtaWRTClusterPositionInLayer.at(1)); + neutralPFO->setAttribute<float>(xAOD::PFODetails::PFOAttributes::cellBased_secondEtaWRTClusterPosition_EM2, secondEtaWRTClusterPositionInLayer.at(2)); + + // Store shot element links in neutral PFO + std::vector<ElementLink<xAOD::IParticleContainer> > shotlinks; + for(unsigned iShot = 0;iShot<shotsInCluster.size();++iShot){ + ElementLink<xAOD::PFOContainer> shotPFOElementLink = pTau.shotPFOLinks().at(shotsInCluster.at(iShot)); + ElementLink<xAOD::IParticleContainer> shotElementLink; + shotPFOElementLink.toPersistent(); + shotElementLink.resetWithKeyAndIndex( shotPFOElementLink.persKey(), shotPFOElementLink.persIndex() ); + if (!shotElementLink.isValid()) ATH_MSG_WARNING("Created an invalid element link to xAOD::PFO"); + shotlinks.push_back(shotElementLink); + } + if(!neutralPFO->setAssociatedParticleLinks( xAOD::PFODetails::TauShot,shotlinks)) + ATH_MSG_WARNING("Couldn't add shot links to neutral PFO!"); + } + + // Create hadronic PFOs, put them in output container and store links to tau + if(!setHadronicClusterPFOs(pTau)){ + ATH_MSG_ERROR("Could not set hadronic PFOs"); + return StatusCode::FAILURE; + } + + return StatusCode::SUCCESS; +} + + +StatusCode TauPi0ClusterCreator::eventFinalize() +{ + // pt sort container at the end of the event + // if(m_pOutputPi0CaloClusterContainer->size()) AnalysisUtils::Sort::pT(m_pOutputPi0CaloClusterContainer); + + //---------------------------------------------------------------------- + // Register cluster container in StoreGate + //---------------------------------------------------------------------- + CHECK( CaloClusterStoreHelper::finalizeClusters(&(*evtStore()), + m_pOutputPi0CaloClusterContainer, + m_outputPi0ClusterContainerName, + msg())); + + return StatusCode::SUCCESS; +} + +// Functions used to calculate BDT variables other than those provided by the CaloClusterMomentsMaker +float TauPi0ClusterCreator::getEM1CoreFrac( + const xAOD::CaloCluster* pi0Candidate) +{ + float coreEnergy=0.; + float sumEPosCellsEM1=0.; + + const CaloClusterCellLink* theCellLink = pi0Candidate->getCellLinks(); + CaloClusterCellLink::const_iterator cellInClusterItr = theCellLink->begin(); + CaloClusterCellLink::const_iterator cellInClusterItrE = theCellLink->end(); + for(;cellInClusterItr!=cellInClusterItrE;++cellInClusterItr){ + CaloCell* cellInCluster = (CaloCell*) *cellInClusterItr; + int sampling = cellInCluster->caloDDE()->getSampling(); + if(sampling!=1 && sampling!=5) continue; + float cellE = cellInCluster->e() * cellInClusterItr.weight(); + if(cellE<=0) continue; + sumEPosCellsEM1 += cellE; + float cellEtaWRTCluster = cellInCluster->eta()-pi0Candidate->eta(); + float cellPhiWRTCluster = P4Helpers::deltaPhi(cellInCluster->phi(), pi0Candidate->phi()); + if(fabs(cellPhiWRTCluster) > 0.05 || fabs(cellEtaWRTCluster) > 2 * 0.025/8.) continue; + coreEnergy+=cellE; + } + if(sumEPosCellsEM1<=0.) return 0.; + return coreEnergy/sumEPosCellsEM1; +} + +// Do cluster to shot matching. +// A cluster is matched to a shot if the seed cell of the shot is in the cluster +std::map<unsigned, xAOD::CaloCluster*> TauPi0ClusterCreator::getClusterToShotMap( + const std::vector<const xAOD::PFO*> shotVector, + const xAOD::CaloClusterContainer& pPi0ClusterContainer, + const xAOD::TauJet &pTau) +{ + std::map<unsigned, xAOD::CaloCluster*> clusterToShotMap; + for(unsigned iShot = 0;iShot<shotVector.size();++iShot){ + int seedHash_int = -1; + if( shotVector.at(iShot)->attribute(xAOD::PFODetails::PFOAttributes::tauShots_seedHash, seedHash_int) == false) { + std::cout << "WARNING: Couldn't find seed hash. Set it to -1, no cluster will be associated to shot." << std::endl; + } + const IdentifierHash seedHash = (const IdentifierHash) seedHash_int; + xAOD::CaloClusterContainer::const_iterator clusterItr (pPi0ClusterContainer.begin()), + clusterItrEnd(pPi0ClusterContainer.end()); + float weightInCluster=-1.; + float weightInPreviousCluster=-1; + for (; clusterItr != clusterItrEnd; ++clusterItr){ + xAOD::CaloCluster* cluster = (xAOD::CaloCluster*) (*clusterItr); + weightInCluster=-1.; + if (cluster->p4().Et() < m_clusterEtCut) continue; // Not interested in clusters that fail the Et cut + // Cluster container has clusters for all taus. + // Only run on clusters that belong to this tau + if (cluster->p4().DeltaR(pTau.p4()) > .4) continue; + const CaloClusterCellLink* theCellLink = cluster->getCellLinks(); + CaloClusterCellLink::const_iterator cellItr = theCellLink->begin(); + CaloClusterCellLink::const_iterator cellItrE = theCellLink->end(); + for(;cellItr!=cellItrE; ++cellItr){ + CaloCell* cellInCluster = (CaloCell*) *cellItr; + // Check if seed cell is in cluster. + if(cellInCluster->caloDDE()->calo_hash()!=seedHash) continue; + weightInCluster = cellItr.weight(); + // found cell, no need to loop over other cells + break; + } + if(weightInCluster<0) continue; + // Check if cell was already found in a previous cluster + if(weightInPreviousCluster<0){ + // Cell not found in a previous cluster. + // Have to check whether cell is shared with other cluster + clusterToShotMap[iShot] = cluster; + weightInPreviousCluster = weightInCluster; + } + else{ + // Cell has been found in a previous cluster + // assign shot to this cluster if it has larger weight for the cell + // otherwise the shots keeps assigned to the previous cluster + if(weightInCluster>weightInPreviousCluster){ + clusterToShotMap[iShot] = cluster; + } + // No need to loop over other clusters as cells can not be shared by more than two clusters + break; + } + } + } + return clusterToShotMap; +} + +std::vector<unsigned> TauPi0ClusterCreator::getShotsMatchedToCluster( + const std::vector<const xAOD::PFO*> shotVector, + std::map<unsigned, xAOD::CaloCluster*> clusterToShotMap, + xAOD::CaloCluster* pPi0Cluster) +{ + std::vector<unsigned> shotsMatchedToCluster; + for(unsigned iShot = 0;iShot<shotVector.size();++iShot){ + std::map<unsigned, xAOD::CaloCluster*>::iterator itr = clusterToShotMap.find(iShot); + if(itr==clusterToShotMap.end()) continue; + if(itr->second!=pPi0Cluster) continue; + shotsMatchedToCluster.push_back(iShot); + } + return shotsMatchedToCluster; +} + +int TauPi0ClusterCreator::getNPhotons( + const std::vector<const xAOD::PFO*> shotVector, + std::vector<unsigned> shotsInCluster + ) +{ + int nPhotons = 0; + for(unsigned iShot = 0;iShot<shotsInCluster.size();++iShot){ + int curNPhotons=0; + if(shotVector.at(shotsInCluster.at(iShot))->attribute(xAOD::PFODetails::PFOAttributes::tauShots_nPhotons,curNPhotons) == false) + ATH_MSG_WARNING("Can't find NHitsInEM1. Set it to 0."); + nPhotons+=curNPhotons; + } + return nPhotons; +} + +vector<int> TauPi0ClusterCreator::getNPosECells( + const xAOD::CaloCluster* pi0Candidate) +{ + vector<int> nPosECellsInLayer(3,0); // 3 layers initialised with 0 +ve cells + + const CaloClusterCellLink* theCellLink = pi0Candidate->getCellLinks(); + CaloClusterCellLink::const_iterator cellInClusterItr = theCellLink->begin(); + CaloClusterCellLink::const_iterator cellInClusterItrE = theCellLink->end(); + + for(;cellInClusterItr!=cellInClusterItrE; ++cellInClusterItr){ + CaloCell* cellInCluster = (CaloCell*) *cellInClusterItr; + int sampling = cellInCluster->caloDDE()->getSampling(); + // Get cell layer: PSB and PSE belong to layer 0, + // EMB1 and EME1 to layer 1, EMB2 and EME2 to layer 2. + int cellLayer = sampling%4; + if(cellLayer < 3 && cellInCluster->e() > 0) nPosECellsInLayer[cellLayer]++; + } + return nPosECellsInLayer; +} + + +vector<float> TauPi0ClusterCreator::get1stEtaMomWRTCluster( + const xAOD::CaloCluster* pi0Candidate) +{ + vector<float> firstEtaWRTClusterPositionInLayer (4, 0.); //init with 0. for 0-3 layers + vector<float> sumEInLayer (4, 0.); //init with 0. for 0-3 layers + + const CaloClusterCellLink* theCellLink = pi0Candidate->getCellLinks(); + CaloClusterCellLink::const_iterator cellInClusterItr = theCellLink->begin(); + CaloClusterCellLink::const_iterator cellInClusterItrE = theCellLink->end(); + + for(;cellInClusterItr!=cellInClusterItrE;++cellInClusterItr){ + CaloCell* cellInCluster = (CaloCell*) *cellInClusterItr; + int sampling = cellInCluster->caloDDE()->getSampling(); + // Get cell layer: PSB and PSE belong to layer 0, + // EMB1 and EME1 to layer 1, EMB2 and EME2 to layer 2. + int cellLayer = sampling%4; + + float cellEtaWRTClusterPos=cellInCluster->eta()-pi0Candidate->eta(); + float cellE=cellInCluster->e(); + if(cellE<=0 || cellLayer>=3) continue; + firstEtaWRTClusterPositionInLayer[cellLayer]+=cellEtaWRTClusterPos*cellE; + sumEInLayer[cellLayer]+=cellE; + } + + for(int iLayer=0;iLayer<4;++iLayer){ + if(sumEInLayer[iLayer]!=0) + firstEtaWRTClusterPositionInLayer[iLayer]/=fabs(sumEInLayer[iLayer]); + else firstEtaWRTClusterPositionInLayer[iLayer]=0.; + } + return firstEtaWRTClusterPositionInLayer; +} + +vector<float> TauPi0ClusterCreator::get2ndEtaMomWRTCluster( + const xAOD::CaloCluster* pi0Candidate) +{ + vector<float> secondEtaWRTClusterPositionInLayer (4, 0.); //init with 0. for 0-3 layers + vector<float> sumEInLayer (4, 0.); //init with 0. for 0-3 layers + + const CaloClusterCellLink* theCellLink = pi0Candidate->getCellLinks(); + CaloClusterCellLink::const_iterator cellInClusterItr = theCellLink->begin(); + CaloClusterCellLink::const_iterator cellInClusterItrE = theCellLink->end(); + + for(;cellInClusterItr!=cellInClusterItrE;++cellInClusterItr){ + CaloCell* cellInCluster = (CaloCell*) *cellInClusterItr; + int sampling = cellInCluster->caloDDE()->getSampling(); + // Get cell layer: PSB and PSE belong to layer 0, + // EMB1 and EME1 to layer 1, EMB2 and EME2 to layer 2. + int cellLayer = sampling%4; + + float cellEtaWRTClusterPos=cellInCluster->eta()-pi0Candidate->eta(); + float cellE=cellInCluster->e(); + if(cellE<=0 || cellLayer>=3) continue; + secondEtaWRTClusterPositionInLayer[cellLayer]+=cellEtaWRTClusterPos*cellEtaWRTClusterPos*cellE; + sumEInLayer[cellLayer]+=cellE; + } + + for(int iLayer=0;iLayer<4;++iLayer){ + if(sumEInLayer[iLayer]!=0) + secondEtaWRTClusterPositionInLayer[iLayer]/=fabs(sumEInLayer[iLayer]); + else secondEtaWRTClusterPositionInLayer[iLayer]=0.; + } + return secondEtaWRTClusterPositionInLayer; +} + +bool TauPi0ClusterCreator::setHadronicClusterPFOs( + xAOD::TauJet& pTau) +{ + const xAOD::Jet* tauJetSeed = (*pTau.jetLink()); + if (!tauJetSeed) { + ATH_MSG_ERROR("Could not retrieve tau jet seed"); + return false; + } + xAOD::JetConstituentVector::const_iterator clusterItr = tauJetSeed->getConstituents().begin(); + xAOD::JetConstituentVector::const_iterator clusterItrE = tauJetSeed->getConstituents().end(); + for (; clusterItr != clusterItrE; ++clusterItr){ + // Procedure: + // - Calculate cluster energy in Hcal. This is to treat -ve energy cells correctly + // - Then set 4momentum via setP4(E/cosh(eta), eta, phi, m). This forces the PFO to have the correct energy and mass + // - Ignore clusters outside 0.2 cone and those with overall negative energy or negative energy in Hcal + + // Get xAOD::CaloClusters from jet constituent + const xAOD::CaloCluster* cluster = dynamic_cast<const xAOD::CaloCluster*>( (*clusterItr)->rawConstituent() ); + if (!cluster) continue; + + // Don't create PFOs for clusters with overall (Ecal+Hcal) negative energy (noise) + if(cluster->e()<=0.) continue; + + // Only need clusters in core cone. Others are not needed for subtraction + if(pTau.p4().DeltaR(cluster->p4()) > 0.2) continue; + + // Loop over cells to calculate cluster energy in Hcal + double clusterE_Hcal=0.; + const CaloClusterCellLink* theCellLink = cluster->getCellLinks(); + CaloClusterCellLink::const_iterator cellInClusterItr = theCellLink->begin(); + CaloClusterCellLink::const_iterator cellInClusterItrE = theCellLink->end(); + for(;cellInClusterItr!=cellInClusterItrE;++cellInClusterItr){ + CaloCell* cellInCluster = (CaloCell*) *cellInClusterItr; + + //Get only HCAL cells + int sampling = cellInCluster->caloDDE()->getSampling(); + if (sampling < 8) continue; + + double cellE = cellInCluster->e()*cellInClusterItr.weight(); + clusterE_Hcal+=cellE; + } + // Don't save PFOs for clusters with negative energy in Hcal + if(clusterE_Hcal<=0.) continue; + + // Create hadronic PFO + xAOD::PFO* hadronicPFO = new xAOD::PFO(); + m_hadronicClusterPFOContainer->push_back( hadronicPFO ); + + // Set 4mom. Eta and phi are taken from cluster + double cluster_Pt_Hcal = clusterE_Hcal/std::cosh(cluster->eta()); + hadronicPFO->setP4( (float) cluster_Pt_Hcal, (float) cluster->eta(), (float) cluster->phi(), (float) 0.); + + // TODO: May want to set element link to the cluster the PFO is originating from + // ElementLink<xAOD::CaloClusterContainer> clusElementLink; + // clusElementLink.toContainedElement( CLUSTERCONTAINER, cluster ); + // hadronicPFO->setClusterLink( clusElementLink ); + + // Create element link from tau to hadronic PFO + ElementLink<xAOD::PFOContainer> PFOElementLink; + PFOElementLink.toContainedElement( *m_hadronicClusterPFOContainer, hadronicPFO ); + pTau.addHadronicPFOLink( PFOElementLink ); + } + return true; +} + diff --git a/Reconstruction/tauRecTools/src/TauPi0ClusterCreator.h b/Reconstruction/tauRecTools/src/TauPi0ClusterCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..ecf128c0d7f33307227f8cb45dfbe21cf9b202d5 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauPi0ClusterCreator.h @@ -0,0 +1,100 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUPI0CLUSTERCREATOR_H +#define TAUREC_TAUPI0CLUSTERCREATOR_H + +#include <string> +#include <vector> +#include "tauRecTools/TauRecToolBase.h" +#include "xAODPFlow/PFOAuxContainer.h" + +using std::vector; + +/** + * @brief Creates Pi0 clusters (Pi0 Finder). + * + * @author Will Davey <will.davey@cern.ch> + * @author Benedict Winter <benedict.tobias.winter@cern.ch> + * @author Stephanie Yuen <stephanie.yuen@cern.ch> + */ + +class TauPi0ClusterCreator : virtual public TauRecToolBase { +public: + TauPi0ClusterCreator(const std::string& name) ; + ASG_TOOL_CLASS2(TauPi0ClusterCreator, TauRecToolBase, ITauToolBase); + virtual ~TauPi0ClusterCreator(); + + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode eventInitialize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode eventFinalize(); + + virtual void print() const { } + + +private: + + + /** @brief fraction of cluster enegry in central EM1 cells */ + float getEM1CoreFrac( const xAOD::CaloCluster* /*pi0Candidate*/); + + /** @brief number of cells from cluster with positive energy in PS, EM1 and EM2 */ + vector<int> getNPosECells( const xAOD::CaloCluster* /*pi0Candidate*/); + + std::map<unsigned, xAOD::CaloCluster*> getClusterToShotMap( + const std::vector<const xAOD::PFO*> shotVector, + const xAOD::CaloClusterContainer& pPi0ClusterContainer, + const xAOD::TauJet &pTau); + + std::vector<unsigned> getShotsMatchedToCluster( + const std::vector<const xAOD::PFO*> shotVector, + std::map<unsigned, xAOD::CaloCluster*> clusterToShotMap, + xAOD::CaloCluster* pPi0Cluster); + + int getNPhotons( const std::vector<const xAOD::PFO*> /*shotVector*/, + std::vector<unsigned> /*shotsInCluster*/); + + /** @brief first eta moment in PS, EM1 and EM2 w.r.t cluster eta: (eta_i - eta_cluster) */ + vector<float> get1stEtaMomWRTCluster( const xAOD::CaloCluster* /*pi0Candidate*/); + + /** @brief second eta moment in PS, EM1 and EM2 w.r.t cluster eta: (eta_i - eta_cluster)^2 */ + vector<float> get2ndEtaMomWRTCluster(const xAOD::CaloCluster* /*pi0Candidate*/); + + /** @brief get hadronic cluster PFOs*/ + bool setHadronicClusterPFOs(xAOD::TauJet& pTau); + + /** @brief input cluster container of pi0 candidates */ + // TODO: input cluster container name + std::string m_inputPi0ClusterContainerName; + + /** @brief output cluster container of pi0 candidates */ + // TODO: output cluster container name + std::string m_outputPi0ClusterContainerName; + + /** @brief new neutral PFO container and name */ + xAOD::PFOContainer* m_neutralPFOContainer; + std::string m_neutralPFOContainerName; + xAOD::PFOAuxContainer* m_neutralPFOAuxStore; + + /** @brief new hadronic cluster PFO container and name */ + xAOD::PFOContainer* m_hadronicClusterPFOContainer; + std::string m_hadronicClusterPFOContainerName; + xAOD::PFOAuxContainer* m_hadronicClusterPFOAuxStore; + + + /** @brief pt threshold for pi0 candidate clusters */ + double m_clusterEtCut; + + /** @brief in AODMode (probaby never true) */ + bool m_AODmode; + + /** @brief output cluster container */ + xAOD::CaloClusterContainer* m_pOutputPi0CaloClusterContainer; + +}; + +#endif /* TAUPI0CLUSTERCREATOR_H */ + diff --git a/Reconstruction/tauRecTools/src/TauPi0ClusterScaler.cxx b/Reconstruction/tauRecTools/src/TauPi0ClusterScaler.cxx new file mode 100644 index 0000000000000000000000000000000000000000..25c6287eab37d33a1dff62b832149d88f1e79d79 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauPi0ClusterScaler.cxx @@ -0,0 +1,369 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauPi0ClusterScaler.cxx +// package: Reconstruction/tauRec +// authors: Stephanie Yuen, Benedict Winter, Will Davey +// date: 2014-08-04 +// +//----------------------------------------------------------------------------- + +#include <vector> + +#include "TauPi0ClusterScaler.h" +#include "xAODPFlow/PFO.h" + +#include "TrkParametersIdentificationHelpers/TrackParametersIdHelper.h" +#include "RecoToolInterfaces/IParticleCaloExtensionTool.h" +#include "xAODTau/TauJet.h" +#include "tauRecTools/ITauToolBase.h" + +using std::vector; +using std::string; + +//------------------------------------------------------------------------- +// Constructor +//------------------------------------------------------------------------- + +TauPi0ClusterScaler::TauPi0ClusterScaler( const string& name ) : + TauRecToolBase(name) + , m_caloExtensionTool("Trk::ParticleCaloExtensionTool/ParticleCaloExtensionTool") + , m_chargedPFOContainerName("TauChargedParticleFlowObjects") +{ + declareProperty("ParticleCaloExtensionTool", m_caloExtensionTool); + declareProperty("ChargedPFOContainerName", m_chargedPFOContainerName); + declareProperty("runOnAOD", m_AODmode=false); +} + +//------------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------------- + +TauPi0ClusterScaler::~TauPi0ClusterScaler() +{ +} + + +StatusCode TauPi0ClusterScaler::initialize() +{ + // retrieve tools + ATH_MSG_DEBUG( "Retrieving tools" ); + CHECK( m_caloExtensionTool.retrieve() ); + // Create vector with default values + for (int layer = 0 ; layer != CaloCell_ID::FCAL0; ++layer) { + m_defaultValues.push_back(-10.); + } + + return StatusCode::SUCCESS; +} + +StatusCode TauPi0ClusterScaler::eventInitialize() { + + //--------------------------------------------------------------------- + // Create charged PFO container + //--------------------------------------------------------------------- + if(!m_AODmode){ + m_chargedPFOContainer = new xAOD::PFOContainer(); + m_chargedPFOAuxStore = new xAOD::PFOAuxContainer(); + m_chargedPFOContainer->setStore(m_chargedPFOAuxStore); + CHECK( evtStore()->record(m_chargedPFOContainer, m_chargedPFOContainerName ) ); + CHECK( evtStore()->record( m_chargedPFOAuxStore, m_chargedPFOContainerName + "Aux." ) ); + } + else{ + CHECK( evtStore()->retrieve(m_chargedPFOContainer, m_chargedPFOContainerName) ); + CHECK( evtStore()->retrieve( m_chargedPFOAuxStore, m_chargedPFOContainerName + "Aux." ) ); + } + return StatusCode::SUCCESS; + +} + +StatusCode TauPi0ClusterScaler::finalize() +{ + StatusCode sc = AlgTool::finalize(); + return sc; +} + + +StatusCode TauPi0ClusterScaler::execute(xAOD::TauJet& pTau) +{ + // Clear vector of cell-based charged PFO Links. Required when rerunning on xAOD level. + pTau.clearProtoChargedPFOLinks(); + + //--------------------------------------------------------------------- + // only run on 1-5 prong taus + //--------------------------------------------------------------------- + if (pTau.nTracks() == 0 || pTau.nTracks() >5 ) { + return StatusCode::SUCCESS; + } + ATH_MSG_DEBUG("ClusterScaler: new tau. \tpt = " << pTau.pt() << "\teta = " << pTau.eta() << "\tphi = " << pTau.phi() << "\tnprongs = " << pTau.nTracks()); + + //--------------------------------------------------------------------- + // get tau tracks + //--------------------------------------------------------------------- + vector<const xAOD::TrackParticle*> tracks; + for(unsigned iTrack = 0; iTrack<pTau.nTracks();++iTrack){ + const xAOD::TrackParticle* track = pTau.track(iTrack); + tracks.push_back(track); + } + + //--------------------------------------------------------------------- + // prepare extrapolation of tracks to calo layers + //--------------------------------------------------------------------- + // clear vectors related to track extrapolation + // have to do that for each tau so it cannot be done in eventInitialize, + // which is called once per event (and not once per tau) + m_tracksEtaAtSampling.clear(); + m_tracksPhiAtSampling.clear(); + m_extrapolatedSamplings.clear(); + // Fill with default values + for(int layer = 0 ; layer != CaloCell_ID::FCAL0; ++layer) { + m_extrapolatedSamplings.push_back(false); + } + for(unsigned iTrack = 0; iTrack<tracks.size();++iTrack){ + m_tracksEtaAtSampling.push_back( m_defaultValues ); + m_tracksPhiAtSampling.push_back( m_defaultValues ); + } + + //--------------------------------------------------------------------- + // get energy in HCal associated to the different tracks + //--------------------------------------------------------------------- + vector<vector<ElementLink<xAOD::IParticleContainer> > > hadPFOLinks; + vector<double> EestInEcal = this->getEstEcalEnergy(tracks,pTau, hadPFOLinks); + + //--------------------------------------------------------------------- + // Create charged PFOs + //--------------------------------------------------------------------- + for(unsigned iTrack = 0; iTrack<tracks.size();++iTrack){ + const xAOD::TrackParticle* track = tracks.at(iTrack); + xAOD::PFO* chargedPFO = new xAOD::PFO(); + m_chargedPFOContainer->push_back(chargedPFO); + ElementLink<xAOD::TrackParticleContainer> myTrackLink = pTau.trackLinks().at(iTrack); + if(!chargedPFO->setTrackLink(myTrackLink)) ATH_MSG_WARNING("Could not add Track to PFO"); + chargedPFO->setCharge(track->charge()); + chargedPFO->setP4(track->pt(),track->eta(),track->phi(),track->m()); + // Create element link from tau to charged PFO + ElementLink<xAOD::PFOContainer> PFOElementLink; + PFOElementLink.toContainedElement( *m_chargedPFOContainer, chargedPFO ); + // Create element links to hadronic PFOs associated to tracks + if(!chargedPFO->setAssociatedParticleLinks(xAOD::PFODetails::TauShot,hadPFOLinks.at(iTrack))) + ATH_MSG_WARNING("Couldn't add hadronic PFO links to charged PFO!"); + pTau.addProtoChargedPFOLink( PFOElementLink ); + } + + //--------------------------------------------------------------------- + // get closest EM cluster to track for subtraction + //--------------------------------------------------------------------- + vector<float> smallestDRSquared; + vector<int> closestCluster; + for(unsigned iTrack = 0; iTrack<tracks.size();++iTrack){ + // The following vectors will store information on the clusters closest to the tracks + smallestDRSquared.push_back( 0.0016 ); // TODO: retune, for now match clusters that are closer than DR=0.04 to the track + closestCluster.push_back(-1); + } + + int thisCluster = 0; + unsigned nNeutPFO = pTau.nProtoNeutralPFOs(); + for(unsigned int iNeutPFO=0; iNeutPFO<nNeutPFO; iNeutPFO++, thisCluster++) { + const xAOD::PFO* curNeutPFO_const = pTau.protoNeutralPFO( iNeutPFO ); + int maxESample = 2; + if (fabs(curNeutPFO_const->eta()) > 1.45) maxESample = 6; + // check if tracks have been extrapolated to this sampling. Do so if this is not the case + if(m_extrapolatedSamplings.at(maxESample)==false){ + this->getExtrapolatedPositions(tracks,maxESample); + m_extrapolatedSamplings.at(maxESample)=true; + } + + for(unsigned iTrack = 0; iTrack<tracks.size();++iTrack){ + if(EestInEcal.at(iTrack)<0.001) continue; // No need to subtract + + TLorentzVector extTrack; + extTrack.SetPtEtaPhiE(tracks.at(iTrack)->pt(), m_tracksEtaAtSampling.at(iTrack).at(maxESample), m_tracksPhiAtSampling.at(iTrack).at(maxESample), tracks.at(iTrack)->e()); + // get eta/phi distance of cell to track + double deltaEta = extTrack.Eta()-curNeutPFO_const->eta(); + double deltaPhi = TVector2::Phi_mpi_pi( extTrack.Phi() - curNeutPFO_const->phi());; + + double deltaRToTrack_squared = deltaEta*deltaEta+deltaPhi*deltaPhi; + ATH_MSG_DEBUG("Track number " << iTrack << ", extTrack.Eta() = " << extTrack.Eta() << ", extTrack.Phi() = " << extTrack.Phi()); + + if(deltaRToTrack_squared>=smallestDRSquared.at(iTrack)) continue; + smallestDRSquared.at(iTrack) = deltaRToTrack_squared; + closestCluster.at(iTrack) = thisCluster; + } + } + + //--------------------------------------------------------------------- + // Set cluster energies to what they originally were before subtraction, in case subtraction is rerun on xAOD level + //--------------------------------------------------------------------- + for(unsigned int iNeutPFO=0; iNeutPFO<nNeutPFO; iNeutPFO++) { + const xAOD::PFO* curNeutPFO_const = pTau.protoNeutralPFO( iNeutPFO ); + xAOD::PFO* curNeutPFO = const_cast<xAOD::PFO*>(curNeutPFO_const); + //float originalE = 0; + //curNeutPFO->attribute(xAOD::PFODetails::PFOAttributes::protoasymmetryInEM1WRTTrk,originalE); + //curNeutPFO->setP4(originalE/TMath::CosH(curNeutPFO->eta()), curNeutPFO->eta(), curNeutPFO->phi(), curNeutPFO->m()); + + // Retrieve original 4momentum from the cluster linked to the PFO + double originalPt = curNeutPFO->cluster(0)->pt(); + double originalEta = curNeutPFO->cluster(0)->eta(); + double originalPhi = curNeutPFO->cluster(0)->phi(); + double originalM = curNeutPFO->cluster(0)->m(); + //ATH_MSG_INFO("PFO 4mom: pt << "<<curNeutPFO->pt()<<"\teta"<<curNeutPFO->eta()<<"\tphi"<<curNeutPFO->phi()<<"\tm"<<curNeutPFO->m()<<"\te"<<curNeutPFO->e() ); + //ATH_MSG_INFO("Cl 4mom: pt << "<<originalPt <<"\teta"<<originalEta <<"\tphi"<<originalPhi <<"\tm"<<originalM <<"\te"<<curNeutPFO->cluster(0)->e()<<"\n"); + curNeutPFO->setP4(originalPt, originalEta, originalPhi, originalM); + } + + //--------------------------------------------------------------------- + // scale charged pion energy out of closest EMNeutPFO to track + //--------------------------------------------------------------------- + thisCluster = 0; + for(unsigned int iNeutPFO=0; iNeutPFO<nNeutPFO; iNeutPFO++, thisCluster++) { + const xAOD::PFO* curNeutPFO_const = pTau.protoNeutralPFO( iNeutPFO ); + xAOD::PFO* curNeutPFO = const_cast<xAOD::PFO*>(curNeutPFO_const); + + float originalE = curNeutPFO->e(); + //ATH_MSG_INFO("iNeutPFO " << iNeutPFO << "\t before sub " << originalE/1000); + //Scale out charged pion energy for each track + for(unsigned iTrack = 0; iTrack<tracks.size();++iTrack){ + if(thisCluster!=closestCluster.at(iTrack)) continue; // No EMNeutPFO found + if(EestInEcal.at(iTrack)<0.001) continue; // No need to subtract + if(originalE - EestInEcal.at(iTrack) >0. ){ + float newE = originalE - EestInEcal.at(iTrack); + curNeutPFO->setP4(newE/TMath::CosH(curNeutPFO->eta()) , curNeutPFO->eta(), curNeutPFO->phi(), curNeutPFO->m()); + //ATH_MSG_INFO("should subtract " << EestInEcal.at(iTrack)/1000 << " GeV from EMNeutPFO " << iNeutPFO); + //float orgE = curNeutPFO->cluster(0)->e(); + //ATH_MSG_INFO("orgE = " << orgE << "\tPFO->e() = " << curNeutPFO->e()); + } + // Set it to something that will make the EMNeutPFO fail the pt cut + else { + curNeutPFO->setP4(100 , curNeutPFO->eta(), curNeutPFO->phi(), curNeutPFO->m()); + //ATH_MSG_INFO("should remove EMNeutPFO " << iNeutPFO); + } + } + //ATH_MSG_INFO("iNeutPFO " << iNeutPFO << "\t after sub " << curNeutPFO->e()/1000); + //ATH_MSG_INFO(""); + } + + ATH_MSG_DEBUG("End of TauPi0ClusterScaler::execute"); + + return StatusCode::SUCCESS; +} + +void TauPi0ClusterScaler::getExtrapolatedPositions( + vector<const xAOD::TrackParticle*> tracks, + int sampling) +{ + for (unsigned iTrack = 0 ; iTrack < tracks.size(); ++iTrack ) { + // get the extrapolation into the calo + ATH_MSG_DEBUG( "Try extrapolation of track with pt = " << tracks.at(iTrack)->pt() << ", eta " << tracks.at(iTrack)->eta() << ", phi" << tracks.at(iTrack)->phi() + << " to layer " << sampling); + const Trk::CaloExtension* caloExtension = 0; + if (!m_caloExtensionTool->caloExtension(*tracks.at(iTrack),caloExtension) + || caloExtension->caloLayerIntersections().size() < (unsigned int)(sampling+1)) return; + + // store if track extrapolation successful, only use entry layer + const Trk::TrackParameters* param_at_calo = caloExtension->caloLayerIntersections().at(sampling); + if (param_at_calo) { + ATH_MSG_DEBUG( "Extrapolated track with eta=" << tracks.at(iTrack)->eta() + << " phi="<<tracks.at(iTrack)->phi() + << " to eta=" << param_at_calo->position().eta() + << " phi="<<param_at_calo->position().phi() + ); + m_tracksEtaAtSampling.at(iTrack).at(sampling)=param_at_calo->position().eta(); + m_tracksPhiAtSampling.at(iTrack).at(sampling)=param_at_calo->position().phi(); + } + else ATH_MSG_DEBUG("Could not extrapolate track with pt = " << tracks.at(iTrack)->pt() << ", eta " << tracks.at(iTrack)->eta() << ", phi" << tracks.at(iTrack)->phi() + << " to layer " << sampling); + } +} + +vector<double> TauPi0ClusterScaler::getEstEcalEnergy( + vector<const xAOD::TrackParticle*> tracks, + const xAOD::TauJet& pTau, + vector<vector<ElementLink<xAOD::IParticleContainer> > >& hadPFOLinks) +{ + // Vector that stores hadronic energy and PFO links associated to tracks + vector<ElementLink<xAOD::IParticleContainer> > emptyLinkVector; + vector<double> EHcal; + for(unsigned iTrack = 0; iTrack<tracks.size();++iTrack){ + EHcal.push_back(0.); + hadPFOLinks.push_back(emptyLinkVector); + } + + ATH_MSG_DEBUG("new tau. eta = " << pTau.eta() << "\t phi = " << pTau.phi() ); + + //int PFONumber = -1; + unsigned nHadPFO = pTau.nHadronicPFOs(); + for(unsigned int iHadPFO=0; iHadPFO<nHadPFO; iHadPFO++){ + const xAOD::PFO* curHadPFO = pTau.hadronicPFO( iHadPFO ); + + /* + // For debugging... + PFONumber++; + double deltaEtaToTau = pTau.eta()-curHadPFO->eta(); + double deltaPhiToTau = TVector2::Phi_mpi_pi( pTau.phi() - curHadPFO->phi()); + + double deltaRToTau_squared = deltaEtaToTau*deltaEtaToTau+deltaPhiToTau*deltaPhiToTau; + ATH_MSG_INFO("PFO number << " << PFONumber << "\t energy = " << curHadPFO->e() << "\t eta = " << curHadPFO->eta() << "\t phi = " << curHadPFO->phi() << + "\t deltaEtaToTau = " << deltaEtaToTau << "\t deltaPhiToTau = " << deltaPhiToTau << "\t deltaRToTau_squared = " << deltaRToTau_squared ); + */ + + // Decide which sampling to extrapolate to. Choose Hcal samplings that usually contain most energy (|eta| dependent) + int sample = 13; // |eta| <= 1.0 + if ( fabs(curHadPFO->eta())>1.5 ) sample = 9; // 1.5 < |eta| + else if( fabs(curHadPFO->eta())>1.0 ) sample = 19; // 1.0 < |eta| <= 1.5 + + // check if tracks have been extrapolated to this sampling. Do so if this is not the case + if(m_extrapolatedSamplings.at(sample)==false){ + this->getExtrapolatedPositions(tracks,sample); + ATH_MSG_DEBUG("Extrapolate to layer " << sample << "\teta = " + << m_tracksEtaAtSampling.at(0).at(sample) << "\t phi = " << m_tracksPhiAtSampling.at(0).at(sample) ); + m_extrapolatedSamplings.at(sample)=true; + } + + // Assign PFO to track + int closestTrack = -1; + double dRToClosestTrack_squared = 0.16; // XXX can be tuned later + for(unsigned iTrack = 0; iTrack<tracks.size();++iTrack){ + const xAOD::TrackParticle* track = tracks.at(iTrack); + + // set extrapolated track direction + TLorentzVector extTrack; + extTrack.SetPtEtaPhiE(track->pt(), m_tracksEtaAtSampling.at(iTrack).at(sample), m_tracksPhiAtSampling.at(iTrack).at(sample), track->e()); + + // get eta/phi distance of cell to track + double deltaEta = extTrack.Eta()-curHadPFO->eta(); + double deltaPhi = TVector2::Phi_mpi_pi( extTrack.Phi() - curHadPFO->phi());; + double deltaRToTrack_squared = deltaEta*deltaEta+deltaPhi*deltaPhi; + + if(deltaRToTrack_squared>=dRToClosestTrack_squared) continue; + closestTrack = iTrack; + dRToClosestTrack_squared = deltaRToTrack_squared; + } + if(closestTrack == -1){ + //ATH_MSG_INFO("dRToClosestTrack_squared = " << dRToClosestTrack_squared << ". Skip PFO for Hcal estimate. \tPFO_energy = " << curHadPFO->e()/1000.); + continue; // Didn't find a track + } + EHcal.at(closestTrack) += curHadPFO->e(); + + ElementLink<xAOD::PFOContainer> hadPFOElementLink = pTau.hadronicPFOLinks().at(iHadPFO); + ElementLink<xAOD::IParticleContainer> hadElementLink; + hadPFOElementLink.toPersistent(); + hadElementLink.resetWithKeyAndIndex( hadPFOElementLink.persKey(), hadPFOElementLink.persIndex() ); + if (!hadElementLink.isValid()) ATH_MSG_WARNING("Created an invalid element link to xAOD::PFO"); + hadPFOLinks.at(closestTrack).push_back(hadElementLink); + //ATH_MSG_INFO("PFO associated to track " << closestTrack << "\tPFO_energy = " << curHadPFO->e()/1000. << "\tEHcal.at(closestTrack) = " << EHcal.at(closestTrack) ); + } + // Get energy estimate in ECAL + vector<double> E_ests; + for(unsigned iTrack = 0; iTrack<tracks.size();++iTrack){ + double E_est = tracks.at(iTrack)->e()-EHcal.at(iTrack); + // energy cant be less than 0 + if(E_est < 0) E_est = 0.; + // energy cant be more than track momentum + if(E_est > tracks.at(iTrack)->e()) E_est = tracks.at(iTrack)->e(); + E_ests.push_back(E_est); + } + return E_ests; +} + diff --git a/Reconstruction/tauRecTools/src/TauPi0ClusterScaler.h b/Reconstruction/tauRecTools/src/TauPi0ClusterScaler.h new file mode 100644 index 0000000000000000000000000000000000000000..2cc3ed5960158c2e0bb9ccaa761258c2896b466a --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauPi0ClusterScaler.h @@ -0,0 +1,71 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUPI0CLUSTERSCALER_H +#define TAUREC_TAUPI0CLUSTERSCALER_H + +#include <string> +#include "tauRecTools/TauRecToolBase.h" +#include "GaudiKernel/ToolHandle.h" +#include "xAODPFlow/PFO.h" +#include "xAODPFlow/PFOAuxContainer.h" + +/** + * @brief scale cluster energy to take care of charged pion energy + * + * @author Stephanie Yuen <stephanie.yuen@cern.ch> + * @author Benedict Winter <benedict.tobias.winter@cern.ch> + * @author Will Davey <will.davey@cern.ch> + */ + +namespace Trk { + class IParticleCaloExtensionTool; +} +class TauPi0ClusterScaler : virtual public TauRecToolBase { +public: + TauPi0ClusterScaler(const std::string& name); + ASG_TOOL_CLASS2(TauPi0ClusterScaler, TauRecToolBase, ITauToolBase); + virtual ~TauPi0ClusterScaler(); + + virtual StatusCode initialize(); + virtual StatusCode eventInitialize(); + virtual StatusCode finalize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + +private: + + /** @brief tool handles */ + ToolHandle<Trk::IParticleCaloExtensionTool> m_caloExtensionTool; + + /** @brief extrapolated position of tracks and vector of bools to keep track for which samplings this has already been done */ + std::vector<std::vector<double> > m_tracksEtaAtSampling; + std::vector<std::vector<double> > m_tracksPhiAtSampling; + std::vector<bool> m_extrapolatedSamplings; + std::vector<double> m_defaultValues; + + /** @brief get extrapolated track position at each layer */ + void getExtrapolatedPositions( std::vector<const xAOD::TrackParticle*>, + int sampling); + + /** @brief new charged PFO container and name */ + xAOD::PFOContainer* m_chargedPFOContainer; + std::string m_chargedPFOContainerName; + xAOD::PFOAuxContainer* m_chargedPFOAuxStore; + + /** @brief run on AOD */ + bool m_AODmode; + + /** @brief estimate energy deposited in Ecal by each charged pion */ + std::vector<double> getEstEcalEnergy( + std::vector<const xAOD::TrackParticle*> tracks, + const xAOD::TauJet& pTau, + std::vector<std::vector<ElementLink<xAOD::IParticleContainer> > >& hadPFOLinks); + +}; + +#endif /* TAUPI0CLUSTERSCALER_H */ + diff --git a/Reconstruction/tauRecTools/src/TauPi0CreateROI.cxx b/Reconstruction/tauRecTools/src/TauPi0CreateROI.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6ad60e747784283857d040154cda62a9167904bd --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauPi0CreateROI.cxx @@ -0,0 +1,173 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauPi0CreateROI.cxx +// package: Reconstruction/tauEvent +// authors: Will Davey, Benedict Winter, Stephanie Yuen +// date: 2012-10-09 +//----------------------------------------------------------------------------- + +#include <TString.h> + +#include "GaudiKernel/IToolSvc.h" + +#include "CaloEvent/CaloCellContainer.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "CaloUtils/CaloCellList.h" +#include "CaloInterface/ICaloCellMakerTool.h" + +#include "AthContainers/OwnershipPolicy.h" +#include "NavFourMom/INavigable4MomentumCollection.h" + +#include "TauPi0CreateROI.h" + +#include <boost/scoped_ptr.hpp> + +using std::vector; +using std::string; + +//------------------------------------------------------------------------- +// Constructor +//------------------------------------------------------------------------- + +TauPi0CreateROI::TauPi0CreateROI( const string& name ) : + TauRecToolBase(name) + , m_cellMakerTool("") + , m_calo_dd_man(NULL) + , m_calo_id(NULL) + , m_caloCellContainerName("AllCalo") + , m_pPi0CellContainer(NULL) + , m_pi0CellContainerName("TauCommonPi0Cells") +{ + declareProperty("CellMakerTool", m_cellMakerTool); + declareProperty("CaloCellContainerName", m_caloCellContainerName); + declareProperty("Pi0CellContainerName", m_pi0CellContainerName); +} + +//------------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------------- + +TauPi0CreateROI::~TauPi0CreateROI() { +} + +StatusCode TauPi0CreateROI::initialize() { + + // retrieve tools + ATH_MSG_DEBUG( "Retrieving tools" ); + CHECK( m_cellMakerTool.retrieve() ); + + // initialize calo cell geo + m_calo_dd_man = CaloDetDescrManager::instance(); + m_calo_id = m_calo_dd_man->getCaloCell_ID(); + + return StatusCode::SUCCESS; +} + +StatusCode TauPi0CreateROI::eventInitialize() { + + const CaloCell_ID* cellID; + if((detStore()->retrieve(cellID)).isFailure()){ + ATH_MSG_ERROR("Unable to retrieve caloCell_ID helper from DetectorStore"); + return StatusCode::FAILURE; + } + + // Get hash range + IdentifierHash hashMax; + hashMax = cellID->calo_cell_hash_max(); + ATH_MSG_VERBOSE("CaloCell Hash Max: " << hashMax); + + // Reset addedCellsMap + m_addedCellsMap.clear(); + for (unsigned i = 0; i < hashMax; i++) { + m_addedCellsMap.push_back(NULL); + } + + //--------------------------------------------------------------------- + // Create CustomCellContainer and register in StoreGate + //--------------------------------------------------------------------- + m_pPi0CellContainer = new CaloCellContainer(SG::OWN_ELEMENTS); + CHECK( evtStore()->record(m_pPi0CellContainer, m_pi0CellContainerName) ); + + // symlink as INavigable4MomentumCollection (as in CaloRec/CaloCellMaker) + CHECK(evtStore()->symLink(m_pPi0CellContainer, static_cast<INavigable4MomentumCollection*> (0))); + + return StatusCode::SUCCESS; +} + +StatusCode TauPi0CreateROI::execute(xAOD::TauJet& pTau) { + + //--------------------------------------------------------------------- + // only run on 1-5 prong taus + //--------------------------------------------------------------------- + if (pTau.nTracks() == 0 || pTau.nTracks() >5 ) { + return StatusCode::SUCCESS; + } + ATH_MSG_DEBUG("new tau. \tpt = " << pTau.pt() << "\teta = " << pTau.eta() << "\tphi = " << pTau.phi() << "\tnprongs = " << pTau.nTracks()); + + //--------------------------------------------------------------------- + // retrieve cells around tau + //--------------------------------------------------------------------- + // get all calo cell container + const CaloCellContainer *pCellContainer = NULL; + CHECK( evtStore()->retrieve(pCellContainer, m_caloCellContainerName) ); + + // get only EM cells within dR<0.4 + vector<CaloCell_ID::SUBCALO> emSubCaloBlocks; + emSubCaloBlocks.push_back(CaloCell_ID::LAREM); + boost::scoped_ptr<CaloCellList> pCells(new CaloCellList(pCellContainer,emSubCaloBlocks)); + pCells->select(pTau.eta(), pTau.phi(), 0.4); // TODO: change hardcoded 0.4 to tau cone variable, (or func. from TauJet)? + + //--------------------------------------------------------------------- + // Put Ecal cells in output container + //--------------------------------------------------------------------- + + CaloCellList::list_iterator cellItr(pCells->begin()), cellItrE(pCells->end()); + for(; cellItr != cellItrE; ++cellItr) { + const CaloCell* cell = (*cellItr); + + // only keep cells that are in Ecal (PS, EM1, EM2 and EM3, both barrel and endcap). + int samp = cell->caloDDE()->getSampling(); + if(samp>7) continue; + + // Store cell in output container + storeCell(cell); + } + + return StatusCode::SUCCESS; +} + +StatusCode TauPi0CreateROI::eventFinalize() { + + //--------------------------------------------------------------------- + // use the m_cellMakerTool to finalize the custom CaloCellContainer + //--------------------------------------------------------------------- + CHECK( m_cellMakerTool->process(static_cast<CaloCellContainer*> (m_pPi0CellContainer)) ); + + return StatusCode::SUCCESS; +} + +StatusCode TauPi0CreateROI::finalize() { + return StatusCode::SUCCESS; +} + +void TauPi0CreateROI::storeCell(const CaloCell* cell){ + // Store cell in output container if it is a new cell + // Produce a copy of the cell, in order to prevent + // the energy of the original cell to be changed. + // Store unweighted cells, since the cell weights are applied during reclustering + + //Ask cell for it's hash + const IdentifierHash cellHash = cell->caloDDE()->calo_hash(); + //Check if this cell is already part of reducedCellContainer + bool isNewCell = (m_addedCellsMap.at(cellHash)==NULL); + + if(isNewCell){ + CaloCell* copyCell = cell->clone(); + m_pPi0CellContainer->push_back(const_cast<CaloCell*> (copyCell)); + m_addedCellsMap[cellHash] = copyCell; + } +} + diff --git a/Reconstruction/tauRecTools/src/TauPi0CreateROI.h b/Reconstruction/tauRecTools/src/TauPi0CreateROI.h new file mode 100644 index 0000000000000000000000000000000000000000..75a6bacfed58b3d4455c57df3f4eefa8864e6b2c --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauPi0CreateROI.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUPI0CREATEROI_H +#define TAUREC_TAUPI0CREATEROI_H + +#include <string> +#include <vector> + +#include "GaudiKernel/ToolHandle.h" +#include "tauRecTools/TauRecToolBase.h" + +#include "xAODTau/TauJet.h" + +class ICaloCellMakerTool; + +/** + * @brief Create ROIs for the Pi0 finder. + * + * @author Will Davey <will.davey@cern.ch> + * @author Benedict Winter <benedict.tobias.winter@cern.ch> + * @author Stephanie Yuen <stephanie.yuen@cern.ch> + */ + +class TauPi0CreateROI : virtual public TauRecToolBase { +public: + TauPi0CreateROI(const std::string& name); + ASG_TOOL_CLASS2(TauPi0CreateROI, TauRecToolBase, ITauToolBase); + virtual ~TauPi0CreateROI(); + + virtual StatusCode initialize(); + virtual StatusCode eventInitialize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode eventFinalize(); + virtual StatusCode finalize(); + + virtual void cleanup(xAOD::TauJet* ) { } + virtual void print() const { } + +private: + + /** @brief store cell in output container */ + void storeCell(const CaloCell* /* cell*/); + + /** @brief tool handles */ + ToolHandle<ICaloCellMakerTool> m_cellMakerTool; + + /** @brief calo cell navigation */ + const CaloDetDescrManager* m_calo_dd_man; + const CaloCell_ID* m_calo_id; + + /** @brief all calo cell container name */ + std::string m_caloCellContainerName; + + /** @brief output cell container and name*/ + CaloCellContainer *m_pPi0CellContainer; + std::string m_pi0CellContainerName; + + /** @brief hash map in order to keep track, which cells have been added to output cell container*/ + std::vector<CaloCell*> m_addedCellsMap; +}; + +#endif /* TAUPI0CREATEROI_H */ + diff --git a/Reconstruction/tauRecTools/src/TauPi0ScoreCalculator.cxx b/Reconstruction/tauRecTools/src/TauPi0ScoreCalculator.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e9ca28113d9120bf5be740ef7ef36b4678202601 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauPi0ScoreCalculator.cxx @@ -0,0 +1,234 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauPi0ScoreCalculator.cxx +// package: Reconstruction/tauRec +// authors: Benedict Winter, Will Davey +// date: 2012-10-09 +// +//----------------------------------------------------------------------------- + +#include <vector> + +#include "TauPi0ScoreCalculator.h" +#include "xAODPFlow/PFO.h" + +#include "TMVA/Reader.h" + +using std::vector; +using std::string; + +//------------------------------------------------------------------------- +// Constructor +//------------------------------------------------------------------------- + +TauPi0ScoreCalculator::TauPi0ScoreCalculator( const string& name ) : + TauRecToolBase(name) + , m_readerOption("Silent:!Color") +{ + declareProperty("ReaderOption", m_readerOption); + declareProperty("BDTWeightFile", m_weightfile); +} + +//------------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------------- + +TauPi0ScoreCalculator::~TauPi0ScoreCalculator() +{ +} + + +StatusCode TauPi0ScoreCalculator::initialize() +{ + //--------------------------------------------------------------------- + // Create TMVA reader + //--------------------------------------------------------------------- + m_tmvaReader = new TMVA::Reader(TString(m_readerOption)); + + if (msgLvl(MSG::DEBUG)) m_tmvaReader->SetVerbose(true); + + int spectator = 1.; + m_tmvaReader->AddSpectator( "nTau" ,&spectator); + m_tmvaReader->AddSpectator( "nTau_test : = nTau%5" ,&spectator); + m_tmvaReader->AddSpectator( "Sample" ,&spectator); + m_tmvaReader->AddSpectator( "Pi0Cluster_type" ,&spectator); + m_tmvaReader->AddSpectator( "Pi0Cluster_BDTScore_old" ,&spectator); + m_tmvaReader->AddVariable( "Pi0Cluster_Abs_FIRST_ETA" ,&m_Abs_FIRST_ETA); + m_tmvaReader->AddVariable( "Pi0Cluster_SECOND_R" ,&m_SECOND_R); +// m_tmvaReader->AddVariable( "Pi0Cluster_SECOND_LAMBDA" ,&m_SECOND_LAMBDA); +// m_tmvaReader->AddVariable( "Pi0Cluster_Abs_DELTA_PHI" ,&m_Abs_DELTA_PHI); + m_tmvaReader->AddVariable( "Pi0Cluster_Abs_DELTA_THETA" ,&m_Abs_DELTA_THETA); + m_tmvaReader->AddVariable( "Pi0Cluster_CENTER_LAMBDA_helped" ,&m_CENTER_LAMBDA_helped); +// m_tmvaReader->AddVariable( "Pi0Cluster_LATERAL" ,&m_LATERAL); + m_tmvaReader->AddVariable( "Pi0Cluster_LONGITUDINAL" ,&m_LONGITUDINAL); + m_tmvaReader->AddVariable( "Pi0Cluster_ENG_FRAC_EM" ,&m_ENG_FRAC_EM); +// m_tmvaReader->AddVariable( "Pi0Cluster_ENG_FRAC_MAX" ,&m_ENG_FRAC_MAX); + m_tmvaReader->AddVariable( "Pi0Cluster_ENG_FRAC_CORE" ,&m_ENG_FRAC_CORE); + m_tmvaReader->AddVariable( "Pi0Cluster_log_SECOND_ENG_DENS" ,&m_log_SECOND_ENG_DENS); + m_tmvaReader->AddVariable( "Pi0Cluster_EcoreOverEEM1" ,&m_EcoreOverEEM1); +// m_tmvaReader->AddVariable( "Pi0Cluster_NHitsInEM1" ,&m_NHitsInEM1); +// m_tmvaReader->AddVariable( "Pi0Cluster_NPosECells_PS" ,&m_NPosCells_PS); + m_tmvaReader->AddVariable( "Pi0Cluster_NPosECells_EM1" ,&m_NPosCells_EM1); + m_tmvaReader->AddVariable( "Pi0Cluster_NPosECells_EM2" ,&m_NPosCells_EM2); + m_tmvaReader->AddVariable( "Pi0Cluster_AbsFirstEtaWRTClusterPosition_EM1" ,&m_firstEtaWRTCluster_EM1); +// m_tmvaReader->AddVariable( "Pi0Cluster_AbsFirstEtaWRTClusterPosition_EM2" ,&m_firstEtaWRTCluster_EM2); +// m_tmvaReader->AddVariable( "Pi0Cluster_secondEtaWRTClusterPosition_EM1" ,&m_secondEtaWRTCluster_EM1); + m_tmvaReader->AddVariable( "Pi0Cluster_secondEtaWRTClusterPosition_EM2" ,&m_secondEtaWRTCluster_EM2); +// m_tmvaReader->AddVariable( "Pi0Cluster_energy_EM1" ,&m_energy_EM1); +// m_tmvaReader->AddVariable( "Pi0Cluster_energy_EM2" ,&m_energy_EM2); + + if (bookMethod(m_tmvaReader, "BDT method").isFailure()) return StatusCode::FAILURE; + + return StatusCode::SUCCESS; +} + +StatusCode TauPi0ScoreCalculator::finalize() +{ + StatusCode sc = AlgTool::finalize(); + delete m_tmvaReader; + return sc; +} + + +StatusCode TauPi0ScoreCalculator::execute(xAOD::TauJet& pTau) +{ + //--------------------------------------------------------------------- + // only run on 1-5 prong taus + //--------------------------------------------------------------------- + if (pTau.nTracks() == 0 || pTau.nTracks() >5 ) { + return StatusCode::SUCCESS; + } + ATH_MSG_DEBUG("ScoreCalculator: new tau. \tpt = " << pTau.pt() << "\teta = " << pTau.eta() << "\tphi = " << pTau.phi() << "\tnprongs = " << pTau.nTracks()); + + //--------------------------------------------------------------------- + // retrieve neutral PFOs from tau, calculate BDT scores and store them in PFO + //--------------------------------------------------------------------- + unsigned nNeutPFO = pTau.nProtoNeutralPFOs(); + for(unsigned int iNeutPFO=0; iNeutPFO<nNeutPFO; iNeutPFO++) { + const xAOD::PFO* curNeutPFO_const = pTau.protoNeutralPFO( iNeutPFO ); + float BDTScore = calculateScore(curNeutPFO_const); + xAOD::PFO* curNeutPFO = const_cast<xAOD::PFO*>(curNeutPFO_const); + curNeutPFO->setBDTPi0Score((float) BDTScore); + } + + ATH_MSG_DEBUG("End of TauPi0ScoreCalculator::execute"); + + return StatusCode::SUCCESS; +} + + +float TauPi0ScoreCalculator::calculateScore(const xAOD::PFO* neutralPFO) +{ + m_Abs_FIRST_ETA=0.; + m_SECOND_R=0.; + m_SECOND_LAMBDA=0.; + m_Abs_DELTA_PHI=0.; + m_Abs_DELTA_THETA=0.; + m_CENTER_LAMBDA_helped=0.; + m_LATERAL=0.; + m_LONGITUDINAL=0.; + m_ENG_FRAC_EM=0.; + m_ENG_FRAC_MAX=0.; + m_ENG_FRAC_CORE=0.; + m_log_SECOND_ENG_DENS=0.; + m_EcoreOverEEM1=0.; + // Need to convert int variables to floats after retrieving them + int NHitsInEM1=0; + int NPosCells_PS=0; + int NPosCells_EM1=0; + int NPosCells_EM2=0; + m_firstEtaWRTCluster_EM1=0.; + m_firstEtaWRTCluster_EM2=0.; + m_secondEtaWRTCluster_EM1=0.; + m_secondEtaWRTCluster_EM2=0.; + m_energy_EM1=0.; + m_energy_EM2=0.; + + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_FIRST_ETA,m_Abs_FIRST_ETA) == false) + ATH_MSG_WARNING("Can't find FIRST_ETA. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_SECOND_R,m_SECOND_R) == false) + ATH_MSG_WARNING("Can't find SECOND_R. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_SECOND_LAMBDA,m_SECOND_LAMBDA) == false) + ATH_MSG_WARNING("Can't find SECOND_LAMBDA. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_DELTA_PHI,m_Abs_DELTA_PHI) == false) + ATH_MSG_WARNING("Can't find DELTA_PHI. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_DELTA_THETA,m_Abs_DELTA_THETA) == false) + ATH_MSG_WARNING("Can't find DELTA_THETA. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_CENTER_LAMBDA,m_CENTER_LAMBDA_helped) == false) + ATH_MSG_WARNING("Can't find CENTER_LAMBDA. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_LATERAL,m_LATERAL) == false) + ATH_MSG_WARNING("Can't find LATERAL. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_LONGITUDINAL,m_LONGITUDINAL) == false) + ATH_MSG_WARNING("Can't find LONGITUDINAL. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_ENG_FRAC_EM,m_ENG_FRAC_EM) == false) + ATH_MSG_WARNING("Can't find ENG_FRAC_EM. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_ENG_FRAC_MAX,m_ENG_FRAC_MAX) == false) + ATH_MSG_WARNING("Can't find ENG_FRAC_MAX. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_ENG_FRAC_CORE,m_ENG_FRAC_CORE) == false) + ATH_MSG_WARNING("Can't find ENG_FRAC_CORE. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_SECOND_ENG_DENS,m_log_SECOND_ENG_DENS) == false) + ATH_MSG_WARNING("Can't find SECOND_ENG_DENS. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_EM1CoreFrac,m_EcoreOverEEM1) == false) + ATH_MSG_WARNING("Can't find EM1CoreFrac. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_NHitsInEM1,NHitsInEM1) == false) + ATH_MSG_WARNING("Can't find NHitsInEM1. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_NPosECells_PS,NPosCells_PS) == false) + ATH_MSG_WARNING("Can't find NPosECells_PS. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_NPosECells_EM1,NPosCells_EM1) == false) + ATH_MSG_WARNING("Can't find NPosECells_EM1. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_NPosECells_EM2,NPosCells_EM2) == false) + ATH_MSG_WARNING("Can't find NPosECells_EM2. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_firstEtaWRTClusterPosition_EM1,m_firstEtaWRTCluster_EM1) == false) + ATH_MSG_WARNING("Can't find firstEtaWRTClusterPosition_EM1. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_firstEtaWRTClusterPosition_EM2,m_firstEtaWRTCluster_EM2) == false) + ATH_MSG_WARNING("Can't find firstEtaWRTClusterPosition_EM2. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_secondEtaWRTClusterPosition_EM1,m_secondEtaWRTCluster_EM1) == false) + ATH_MSG_WARNING("Can't find secondEtaWRTClusterPosition_EM1. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_secondEtaWRTClusterPosition_EM2,m_secondEtaWRTCluster_EM2) == false) + ATH_MSG_WARNING("Can't find secondEtaWRTClusterPosition_EM2. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_energy_EM1,m_energy_EM1) == false) + ATH_MSG_WARNING("Can't find energy_EM1. Set it to 0."); + if(neutralPFO->attribute(xAOD::PFODetails::PFOAttributes::cellBased_energy_EM2,m_energy_EM2) == false) + ATH_MSG_WARNING("Can't find energy_EM2. Set it to 0."); + // Apply variable transformations + m_Abs_FIRST_ETA = fabs(m_Abs_FIRST_ETA); + m_Abs_DELTA_PHI = fabs(m_Abs_DELTA_PHI); + m_Abs_DELTA_THETA = fabs(m_Abs_DELTA_THETA); + m_CENTER_LAMBDA_helped = fmin(m_CENTER_LAMBDA_helped, 1000.); + if(m_log_SECOND_ENG_DENS==0.) m_log_SECOND_ENG_DENS=-50.; + else m_log_SECOND_ENG_DENS = log(m_log_SECOND_ENG_DENS); + // Convert ints to floats so they can be read by the TMVA reader + m_NHitsInEM1 = (float) NHitsInEM1; + m_NPosCells_PS = (float) NPosCells_PS; + m_NPosCells_EM1 = (float) NPosCells_EM1; + m_NPosCells_EM2 = (float) NPosCells_EM2; + m_firstEtaWRTCluster_EM1 = fabs(m_firstEtaWRTCluster_EM1); + m_firstEtaWRTCluster_EM2 = fabs(m_firstEtaWRTCluster_EM2); + + // Calculate BDT score + float BDTScore = m_tmvaReader->EvaluateMVA( "BDT method" ); + + return BDTScore; +} + +StatusCode TauPi0ScoreCalculator::bookMethod(TMVA::Reader *reader, const std::string &methodName) const +{ + if (m_weightfile == ""){ + ATH_MSG_ERROR("No weight file given"); + return StatusCode::FAILURE; + } + std::string resolvedFileName = find_file(m_weightfile); + if (resolvedFileName != "") { + ATH_MSG_DEBUG( "Parameterisation file found: " << resolvedFileName ); + } + else { + ATH_MSG_ERROR( "Parameterisation file " << m_weightfile << " not found" ); + return StatusCode::FAILURE; + } + reader->BookMVA( methodName, resolvedFileName); + return StatusCode::SUCCESS; +} + diff --git a/Reconstruction/tauRecTools/src/TauPi0ScoreCalculator.h b/Reconstruction/tauRecTools/src/TauPi0ScoreCalculator.h new file mode 100644 index 0000000000000000000000000000000000000000..9ac6c3148439d5092bd3938739b4c9bc418ed025 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauPi0ScoreCalculator.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUPI0SCORECALCULATOR_H +#define TAUREC_TAUPI0SCORECALCULATOR_H + +#include <string> +#include "tauRecTools/TauRecToolBase.h" +#include "xAODPFlow/PFO.h" + +namespace TMVA{ + class Reader; +} + +/** + * @brief Selectes pi0Candidates (Pi0 Finder). + * + * @author Veit Scharf + * @author Will Davey <will.davey@cern.ch> + * @author Benedict Winter <benedict.tobias.winter@cern.ch> + * @author Stephanie Yuen <stephanie.yuen@cern.ch> + */ + +class TauPi0ScoreCalculator : virtual public TauRecToolBase { +public: + TauPi0ScoreCalculator(const std::string& name); + ASG_TOOL_CLASS2(TauPi0ScoreCalculator, TauRecToolBase, ITauToolBase); + virtual ~TauPi0ScoreCalculator(); + + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + +private: + + std::string m_readerOption; + TMVA::Reader *m_tmvaReader; + + std::string m_weightfile; + + float m_Abs_FIRST_ETA; + float m_SECOND_R; + float m_SECOND_LAMBDA; + float m_Abs_DELTA_PHI; + float m_Abs_DELTA_THETA; + float m_CENTER_LAMBDA_helped; + float m_LATERAL; + float m_LONGITUDINAL; + float m_ENG_FRAC_EM; + float m_ENG_FRAC_MAX; + float m_ENG_FRAC_CORE; + float m_log_SECOND_ENG_DENS; + float m_EcoreOverEEM1; + float m_NHitsInEM1; + float m_NPosCells_PS; + float m_NPosCells_EM1; + float m_NPosCells_EM2; + float m_firstEtaWRTCluster_EM1; + float m_firstEtaWRTCluster_EM2; + float m_secondEtaWRTCluster_EM1; + float m_secondEtaWRTCluster_EM2; + float m_energy_EM1; + float m_energy_EM2; + + /** @brief function used to calculate BDT score */ + float calculateScore(const xAOD::PFO* neutralPFO); + + /** @brief Book TMVA methods. */ + StatusCode bookMethod(TMVA::Reader *reader, const std::string &methodName) const; + +}; + +#endif /* TAUPI0SCORECALCULATOR_H */ + diff --git a/Reconstruction/tauRecTools/src/TauPi0Selector.cxx b/Reconstruction/tauRecTools/src/TauPi0Selector.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4d6c9a91bd9933e2c5c186f36e21c536c42b00fc --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauPi0Selector.cxx @@ -0,0 +1,170 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauPi0Selector.cxx +// package: Reconstruction/tauRec +// authors: Benedict Winter, Will Davey +// date: 2012-10-09 +// +//----------------------------------------------------------------------------- + +#include "TauPi0Selector.h" +#include "FourMomUtils/P4Helpers.h" +#include "CaloUtils/CaloVertexedCluster.h" + +using std::string; + +//------------------------------------------------------------------------- +// Constructor +//------------------------------------------------------------------------- + +TauPi0Selector::TauPi0Selector( const string& name ) : + TauRecToolBase(name) +{ + declareProperty("ClusterEtCut", m_clusterEtCut); + declareProperty("ClusterBDTCut_1prong", m_clusterBDTCut_1prong); + declareProperty("ClusterBDTCut_mprong", m_clusterBDTCut_mprong); +} + +//------------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------------- + +TauPi0Selector::~TauPi0Selector() +{ +} + +StatusCode TauPi0Selector::initialize() +{ + return StatusCode::SUCCESS; +} + +StatusCode TauPi0Selector::finalize() +{ + return StatusCode::SUCCESS; +} + +StatusCode TauPi0Selector::execute(xAOD::TauJet& pTau) +{ + // Clear vector of cell-based pi0 PFO Links. Required when rerunning on xAOD level. + pTau.clearProtoPi0PFOLinks(); + // Set proto decay mode to "not set". Will be overwritten for taus with 1-5 tracks + pTau.setPanTauDetail(xAOD::TauJetParameters::pantau_CellBasedInput_DecayModeProto, xAOD::TauJetParameters::DecayMode::Mode_NotSet); + + //--------------------------------------------------------------------- + // only run on 1-5 prong taus + //--------------------------------------------------------------------- + if (pTau.nTracks() == 0 || pTau.nTracks() >5 ) { + return StatusCode::SUCCESS; + } + + // Set proto decay mode to "other". Will be overwritten for taus with 1 or 3 tracks + pTau.setPanTauDetail(xAOD::TauJetParameters::pantau_CellBasedInput_DecayModeProto, xAOD::TauJetParameters::DecayMode::Mode_Other); + + //--------------------------------------------------------------------- + // retrieve neutral PFOs from tau. Apply selection and create links to + // Pi0NeutralPFOs + //--------------------------------------------------------------------- + int nRecoPi0s=0; + unsigned nNeutPFO = pTau.nProtoNeutralPFOs(); + for(unsigned int iNeutPFO=0; iNeutPFO<nNeutPFO; iNeutPFO++) { + const xAOD::PFO* curNeutPFO_const = pTau.protoNeutralPFO( iNeutPFO ); + + // Set number of pi0s to 0 for all neutral PFOs. Required when rerunning on xAOD level + xAOD::PFO* curNeutPFO = const_cast<xAOD::PFO*>(curNeutPFO_const); + curNeutPFO->setAttribute<int>(xAOD::PFODetails::PFOAttributes::nPi0Proto, 0); + + // Get eta bin + int etaBin = getPi0Cluster_etaBin( curNeutPFO->p4().Eta() ); + + // Preselection + if(curNeutPFO->p4().Et() < m_clusterEtCut.at(etaBin)) continue; + if(pTau.p4().DeltaR(curNeutPFO->p4()) > 0.2) continue; // TODO: Replace by shrinking cone? + + // BDT Selection + float BDTScore = curNeutPFO->bdtPi0Score(); + ATH_MSG_DEBUG("etaBin = " << etaBin << ", m_clusterEtCut.at(etaBin) = " <<m_clusterEtCut.at(etaBin) << ", m_clusterBDTCut_1prong.at(etaBin) = " + << m_clusterBDTCut_1prong.at(etaBin) << ", m_clusterBDTCut_mprong.at(etaBin) = " << m_clusterBDTCut_mprong.at(etaBin)); + if( (pTau.nTracks()==1 && BDTScore < m_clusterBDTCut_1prong.at(etaBin)) || (pTau.nTracks()>1 && BDTScore < m_clusterBDTCut_mprong.at(etaBin)) ) continue; + + // Set number of pi0s + int nHitsInEM1 = 0; + if(!curNeutPFO->attribute(xAOD::PFODetails::cellBased_NHitsInEM1, nHitsInEM1)) ATH_MSG_WARNING("Couldn't retrieve nHitsInEM1. Will set it to 0."); + if(nHitsInEM1<3){ + curNeutPFO->setAttribute<int>(xAOD::PFODetails::PFOAttributes::nPi0Proto, 1); + nRecoPi0s++; + } + else{ + curNeutPFO->setAttribute<int>(xAOD::PFODetails::PFOAttributes::nPi0Proto, 2); + nRecoPi0s+=2; + } + + // Set element link to Pi0tagged PFO + ElementLink<xAOD::PFOContainer> pfoLink = pTau.protoNeutralPFOLinks().at(iNeutPFO); + pTau.addProtoPi0PFOLink(pfoLink); + } + // Calculate visTau hlv and store it in pPi0Details. + TLorentzVector p4 = getP4(pTau); + pTau.setP4(xAOD::TauJetParameters::PanTauCellBasedProto, p4.Pt(),p4.Eta(),p4.Phi(),p4.M()); + // pTau.setPtPanTauCellBasedProto( p4.Pt()); + // pTau.setEtaPanTauCellBasedProto(p4.Eta()); + // pTau.setPhiPanTauCellBasedProto(p4.Phi()); + // pTau.setEPanTauCellBasedProto( p4.E()); + // pTau.setMPanTauCellBasedProto( p4.M()); + + if(pTau.nTracks()==1){ + if(nRecoPi0s==0) pTau.setPanTauDetail(xAOD::TauJetParameters::pantau_CellBasedInput_DecayModeProto, xAOD::TauJetParameters::DecayMode::Mode_1p0n); + else if(nRecoPi0s==1) pTau.setPanTauDetail(xAOD::TauJetParameters::pantau_CellBasedInput_DecayModeProto, xAOD::TauJetParameters::DecayMode::Mode_1p1n); + else pTau.setPanTauDetail(xAOD::TauJetParameters::pantau_CellBasedInput_DecayModeProto, xAOD::TauJetParameters::DecayMode::Mode_1pXn); + } + if(pTau.nTracks()==3){ + if(nRecoPi0s==0) pTau.setPanTauDetail(xAOD::TauJetParameters::pantau_CellBasedInput_DecayModeProto, xAOD::TauJetParameters::DecayMode::Mode_3p0n); + else pTau.setPanTauDetail(xAOD::TauJetParameters::pantau_CellBasedInput_DecayModeProto, xAOD::TauJetParameters::DecayMode::Mode_3pXn); + } + + + return StatusCode::SUCCESS; +} + +int TauPi0Selector::getPi0Cluster_etaBin(double Pi0Cluster_eta){ + int Pi0Cluster_etaBin = -1; + double Pi0Cluster_noCorr_ABSeta = fabs(Pi0Cluster_eta); + + if( Pi0Cluster_noCorr_ABSeta < 0.80 ) Pi0Cluster_etaBin = 0; + else if( Pi0Cluster_noCorr_ABSeta < 1.40 ) Pi0Cluster_etaBin = 1; + else if( Pi0Cluster_noCorr_ABSeta < 1.50 ) Pi0Cluster_etaBin = 2; + else if( Pi0Cluster_noCorr_ABSeta < 1.90 ) Pi0Cluster_etaBin = 3; + else Pi0Cluster_etaBin = 4; + return Pi0Cluster_etaBin; +} + +TLorentzVector TauPi0Selector::getP4(const xAOD::TauJet& pTau) +{ + // Get 4mom of first charged PFO, which is available for all taus that are treated in this algorithm + const xAOD::PFO* firstChargedPFO = pTau.protoChargedPFO( 0 ); + TLorentzVector p4 = firstChargedPFO->p4(); + // Add other PFO momenta + unsigned nChargedPFO = pTau.nProtoChargedPFOs(); + for(unsigned int iChargedPFO=1; iChargedPFO<nChargedPFO; iChargedPFO++){ + const xAOD::PFO* curChargedPFO = pTau.protoChargedPFO( iChargedPFO ); + p4+=curChargedPFO->p4(); + } + unsigned nPi0NeutPFO = pTau.nProtoPi0PFOs(); + for(unsigned int iPi0NeutPFO=0; iPi0NeutPFO<nPi0NeutPFO; iPi0NeutPFO++){ + const xAOD::PFO* curPi0NeutPFO = pTau.protoPi0PFO( iPi0NeutPFO ); + TLorentzVector cluster_corrP4; + if(pTau.vertexLink()) + cluster_corrP4 = xAOD::CaloVertexedCluster(*curPi0NeutPFO->cluster(0) , (*pTau.vertexLink())->position()).p4(); + else + cluster_corrP4 = xAOD::CaloVertexedCluster(*curPi0NeutPFO->cluster(0)).p4(); + TLorentzVector pi0_corrP4; + double pi0_corrP = std::sqrt(curPi0NeutPFO->e()*curPi0NeutPFO->e()-134.9766*CLHEP::MeV*134.9766*CLHEP::MeV); + double pi0_corrPt = pi0_corrP/TMath::CosH(cluster_corrP4.Eta()); + pi0_corrP4.SetPtEtaPhiM(pi0_corrPt,cluster_corrP4.Eta(),cluster_corrP4.Phi(),134.9766*CLHEP::MeV); + p4+=pi0_corrP4; + } + return p4; +} + diff --git a/Reconstruction/tauRecTools/src/TauPi0Selector.h b/Reconstruction/tauRecTools/src/TauPi0Selector.h new file mode 100644 index 0000000000000000000000000000000000000000..096d0922c083f6d23cd2548f04b7dd8eaf37a098 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauPi0Selector.h @@ -0,0 +1,44 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUPI0SELECTOR_H +#define TAUREC_TAUPI0SELECTOR_H + +#include <string> +#include "tauRecTools/TauRecToolBase.h" + +/** + * @brief Selects pi0s + * + * @author Will Davey <will.davey@cern.ch> + * @author Benedict Winter <benedict.tobias.winter@cern.ch> + * @author Stephanie Yuen <stephanie.yuen@cern.ch> + */ + +class TauPi0Selector : virtual public TauRecToolBase { +public: + TauPi0Selector(const std::string& name); + ASG_TOOL_CLASS2(TauPi0Selector, TauRecToolBase, ITauToolBase); + virtual ~TauPi0Selector(); + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + +private: + + std::vector<float> m_clusterEtCut; + std::vector<float> m_clusterBDTCut_1prong; + std::vector<float> m_clusterBDTCut_mprong; + /** @brief function used to get eta bin of Pi0Cluster */ + int getPi0Cluster_etaBin(double Pi0Cluster_eta); + /** @brief function used to calculate the visible tau 4 momentum */ + TLorentzVector getP4(const xAOD::TauJet& tauJet); +}; + +#endif /* TAUPI0SELECTOR_H */ diff --git a/Reconstruction/tauRecTools/src/TauShotFinder.cxx b/Reconstruction/tauRecTools/src/TauShotFinder.cxx new file mode 100644 index 0000000000000000000000000000000000000000..befd3bda457174a1afd2cca0e6c14d67db87af3b --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauShotFinder.cxx @@ -0,0 +1,564 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauShotFinder.cxx +// package: Reconstruction/tauRec +// authors: Will Davey, Benedict Winter, Stephanie Yuen +// date: 2013-05-22 +// +//----------------------------------------------------------------------------- + +#include <boost/scoped_ptr.hpp> + +#include "GaudiKernel/IToolSvc.h" + +#include "CaloEvent/CaloCellContainer.h" +#include "xAODCaloEvent/CaloClusterContainer.h" +#include "xAODCaloEvent/CaloClusterKineHelper.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "CaloIdentifier/LArNeighbours.h" +#include "CaloUtils/CaloClusterStoreHelper.h" +#include "CaloUtils/CaloCellList.h" +#include "CaloUtils/CaloCellESort.h" +#include "CaloInterface/IHadronicCalibrationTool.h" +#include "FourMomUtils/P4Helpers.h" +#include "TauShotFinder.h" +#include "TauShotVariableHelpers.h" +//#include "TMVA/Reader.h" +#include "xAODPFlow/PFOContainer.h" +#include "xAODPFlow/PFOAuxContainer.h" +#include "xAODPFlow/PFO.h" + +using std::vector; +using std::string; + +//------------------------------------------------------------------------- +// Constructor +//------------------------------------------------------------------------- + +TauShotFinder::TauShotFinder( const string& name ) : + TauRecToolBase(name) + , m_caloWeightTool("H1WeightToolCSC12Generic") + , m_caloCellContainerName("AllCalo") + , m_shotClusterContainer(NULL) + , m_shotClusterContainerName("TauShotClusters") + , m_shotPFOContainerName("TauShotParticleFlowObjects") + , m_calo_dd_man(NULL) + , m_calo_id(NULL) +{ + declareProperty("CaloWeightTool", m_caloWeightTool); + declareProperty("CaloCellContainerName", m_caloCellContainerName); + declareProperty("ShotClusterContainerName", m_shotClusterContainerName); + declareProperty("ShotPFOContainerName", m_shotPFOContainerName); +// declareProperty("ReaderOption", m_readerOption); +// declareProperty("BDTWeightFile_barrel", m_weightfile_barrel); +// declareProperty("BDTWeightFile_endcap1", m_weightfile_endcap1); +// declareProperty("BDTWeightFile_endcap2", m_weightfile_endcap2); + declareProperty("NCellsInEta", m_nCellsInEta); + declareProperty("MinPtCut", m_minPtCut); + declareProperty("AutoDoubleShotCut", m_autoDoubleShotCut); + declareProperty("MergedBDTScoreCut", m_mergedBDTScoreCut); +} + +//------------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------------- + +TauShotFinder::~TauShotFinder() { +} + +StatusCode TauShotFinder::initialize() { + + // retrieve tools + ATH_MSG_DEBUG( "Retrieving tools" ); + CHECK( m_caloWeightTool.retrieve() ); + + // initialize calo cell geo + m_calo_dd_man = CaloDetDescrManager::instance(); + m_calo_id = m_calo_dd_man->getCaloCell_ID(); + + /* + //--------------------------------------------------------------------- + // Create TMVA readers + //--------------------------------------------------------------------- + m_tmvaReader_barrel = new TMVA::Reader(TString(m_readerOption)); + if (msgLvl(MSG::DEBUG)) m_tmvaReader_barrel->SetVerbose(true); + m_tmvaReader_barrel->AddVariable("(shot_pt_3-shot_pt)/shot_pt_3",&G_PTFRAC); + m_tmvaReader_barrel->AddVariable("shot_stdpt_5" ,&G_STDPT_5 ); + m_tmvaReader_barrel->AddVariable("shot_stdeta_5" ,&G_STDETA_5 ); + m_tmvaReader_barrel->AddVariable("shot_deltapt_min" ,&G_DELTAPT_MIN ); + + m_tmvaReader_endcap1 = new TMVA::Reader(TString(m_readerOption)); + if (msgLvl(MSG::DEBUG)) m_tmvaReader_endcap1->SetVerbose(true); + m_tmvaReader_endcap1->AddVariable("(shot_pt_3-shot_pt)/shot_pt_3",&G_PTFRAC); + m_tmvaReader_endcap1->AddVariable("shot_stdpt_5" ,&G_STDPT_5 ); + m_tmvaReader_endcap1->AddVariable("shot_stdeta_5" ,&G_STDETA_5 ); + m_tmvaReader_endcap1->AddVariable("shot_deltapt_min" ,&G_DELTAPT_MIN ); + + m_tmvaReader_endcap2 = new TMVA::Reader(TString(m_readerOption)); + if (msgLvl(MSG::DEBUG)) m_tmvaReader_endcap2->SetVerbose(true); + m_tmvaReader_endcap2->AddVariable("(shot_pt_3-shot_pt)/shot_pt_3",&G_PTFRAC); + m_tmvaReader_endcap2->AddVariable("shot_stdpt_5" ,&G_STDPT_5 ); + m_tmvaReader_endcap2->AddVariable("shot_stdeta_5" ,&G_STDETA_5 ); + m_tmvaReader_endcap2->AddVariable("shot_deltapt_min" ,&G_DELTAPT_MIN ); + + if (bookMethod(m_tmvaReader_barrel, m_tmvaReader_endcap1, m_tmvaReader_endcap2, "BDT method").isFailure()) return StatusCode::FAILURE; + */ + + // setupCuts(); + + return StatusCode::SUCCESS; +} + +StatusCode TauShotFinder::finalize() +{ + StatusCode sc = AlgTool::finalize(); + /* + delete m_tmvaReader_barrel; + delete m_tmvaReader_endcap1; + delete m_tmvaReader_endcap2; + */ + return sc; +} + +StatusCode TauShotFinder::eventInitialize() { + + //--------------------------------------------------------------------- + // Create Shot ClusterContainer and register in StoreGate + //--------------------------------------------------------------------- + m_shotClusterContainer = CaloClusterStoreHelper::makeContainer(&*evtStore(), + m_shotClusterContainerName, + msg() + ); + + //--------------------------------------------------------------------- + // Create Shot PFO container + //--------------------------------------------------------------------- + m_PFOShotContainer = new xAOD::PFOContainer(); + CHECK( evtStore()->record(m_PFOShotContainer, m_shotPFOContainerName ) ); + m_PFOShotAuxStore = new xAOD::PFOAuxContainer(); + CHECK( evtStore()->record( m_PFOShotAuxStore, m_shotPFOContainerName + "Aux." ) ); + m_PFOShotContainer->setStore(m_PFOShotAuxStore); + + return StatusCode::SUCCESS; +} + +StatusCode TauShotFinder::execute(xAOD::TauJet& pTau) { + + // Any tau needs to have shot PFO vectors. Set empty vectors before nTrack cut + vector<ElementLink<xAOD::PFOContainer> > empty; + pTau.setShotPFOLinks(empty); + + //--------------------------------------------------------------------- + // only run shower subtraction on 1-5 prong taus + //--------------------------------------------------------------------- + if (pTau.nTracks() == 0 || pTau.nTracks() >5 ) { + return StatusCode::SUCCESS; + } + ATH_MSG_DEBUG(""); + ATH_MSG_DEBUG("New tau"); + + //--------------------------------------------------------------------- + // retrieve cells around tau + //--------------------------------------------------------------------- + // get all calo cell container + const CaloCellContainer *pCellContainer = NULL; + CHECK( evtStore()->retrieve(pCellContainer, m_caloCellContainerName) ); + + // get only EM cells within dR<0.2 + // TODO: might be possible to select only EM1 cells, but probbaly wont + // speed things up much anyway + vector<CaloCell_ID::SUBCALO> emSubCaloBlocks; + emSubCaloBlocks.push_back(CaloCell_ID::LAREM); + boost::scoped_ptr<CaloCellList> pCells(new CaloCellList(pCellContainer,emSubCaloBlocks)); + + // TODO: change hardcoded 0.2 to tau cone variable, (or func. from TauJet?) + pCells->select(pTau.eta(), pTau.phi(), 0.4); + + // Dump cells into a std::vector since CaloCellList wont allow sorting + // (maybe this can be done faster at some point). + // Also apply very basic preselection + std::vector<const CaloCell*> cells; + CaloCellList::list_iterator cellItr = pCells->begin(); + for(; cellItr!=pCells->end();++cellItr){ + // require cells above 100 MeV + if( (*cellItr)->pt()*m_caloWeightTool->wtCell(*cellItr) < 100. ) continue; + // require cells in EM1 + int samp = (*cellItr)->caloDDE()->getSampling(); + if( !( samp == CaloCell_ID::EMB1 || samp == CaloCell_ID::EME1 ) ) continue; + cells.push_back(*cellItr); + } + // sort cells in descending pt + std::sort(cells.begin(),cells.end(),ptSort(*this)); + + //--------------------------------------------------------------------- + // shot seeding + //--------------------------------------------------------------------- + // get seed cells + std::vector<const CaloCell*> seedCells; + std::set<IdentifierHash> seedCellHashes; + cellItr = cells.begin(); + for(; cellItr != cells.end(); ++cellItr) { + const CaloCell* cell = (*cellItr); + const IdentifierHash cellHash = cell->caloDDE()->calo_hash(); + + // apply seed selection on nearest neighbours + std::vector<IdentifierHash> nextEta, prevEta; + m_calo_id->get_neighbours(cellHash,LArNeighbours::nextInEta,nextEta); + m_calo_id->get_neighbours(cellHash,LArNeighbours::prevInEta,prevEta); + std::vector<IdentifierHash> neighbours = nextEta; + neighbours.insert(neighbours.end(),prevEta.begin(),prevEta.end()); + bool status = true; + std::vector<IdentifierHash>::iterator hashItr = neighbours.begin(); + for(;hashItr!=neighbours.end();++hashItr){ + // must not be next to seed cell (TODO: maybe this requirement can be removed) + if( seedCellHashes.find(*hashItr) != seedCellHashes.end() ){ + status = false; + break; + } + // must be maximum + const CaloCell* neigCell = pCellContainer->findCell(*hashItr); + if( !neigCell ) continue; + if( neigCell->pt()*m_caloWeightTool->wtCell(neigCell) >= cell->pt()*m_caloWeightTool->wtCell(cell) ){ + status = false; + break; + } + } + if( !status ) continue; + seedCells.push_back(cell); + seedCellHashes.insert(cellHash); + } // preselected cells + ATH_MSG_DEBUG("seedCells.size() = " << seedCells.size()); + + // merge across phi and construct shots + while( seedCells.size() ){ + + const CaloCell* cell = seedCells.front(); + const IdentifierHash seedHash = cell->caloDDE()->calo_hash(); + + // look for match across phi in current seeds + const CaloCell* nextPhi = NULL; + const CaloCell* prevPhi = NULL; + for( cellItr = seedCells.begin(); cellItr!=seedCells.end(); ++cellItr){ + if( (*cellItr) == cell ) continue; + IdentifierHash shotCellHash = (*cellItr)->caloDDE()->calo_hash(); + if( this->isPhiNeighbour(seedHash,shotCellHash,true) ) nextPhi = (*cellItr); + else if( this->isPhiNeighbour(seedHash,shotCellHash,false) ) prevPhi = (*cellItr); + } + + const CaloCell* mergePhi = NULL; + if( nextPhi && prevPhi ){ + // take higest-pt if merged up and down + if( nextPhi->pt()*m_caloWeightTool->wtCell(nextPhi) > prevPhi->pt()*m_caloWeightTool->wtCell(prevPhi) ) mergePhi = nextPhi; + else mergePhi = prevPhi; + } + else if (nextPhi) mergePhi = nextPhi; + else if (prevPhi) mergePhi = prevPhi; + + // get neighbours in 5x1 window + std::vector<const CaloCell*> windowNeighbours = this->getNeighbours(pCellContainer,cell,2); + if( mergePhi ){ + std::vector<const CaloCell*> mergeCells = this->getNeighbours(pCellContainer,mergePhi,2); + windowNeighbours.push_back(mergePhi); + windowNeighbours.insert(windowNeighbours.end(),mergeCells.begin(),mergeCells.end()); + } + + + // create seed cluster + xAOD::CaloCluster* shotCluster = CaloClusterStoreHelper::makeCluster(pCellContainer); + shotCluster->getCellLinks()->reserve(windowNeighbours.size()+1); + shotCluster->addCell(pCellContainer->findIndex(seedHash), 1.); + cellItr = windowNeighbours.begin(); + for( ; cellItr!=windowNeighbours.end(); ++cellItr) + shotCluster->addCell(pCellContainer->findIndex((*cellItr)->caloDDE()->calo_hash()),1.0); + CaloClusterKineHelper::calculateKine(shotCluster,true,true); + m_shotClusterContainer->push_back(shotCluster); + + // create shot PFO and store it in output container + xAOD::PFO* shot = new xAOD::PFO(); + m_PFOShotContainer->push_back( shot ); + + // Create element link from tau to shot + ElementLink<xAOD::PFOContainer> PFOElementLink; + PFOElementLink.toContainedElement( *m_PFOShotContainer, shot ); + pTau.addShotPFOLink( PFOElementLink ); + + if( mergePhi ){ + // interpolate position + double dPhi = TVector2::Phi_mpi_pi( mergePhi->phi() - cell->phi()); + double ratio = mergePhi->pt()*m_caloWeightTool->wtCell(mergePhi)/(cell->pt()*m_caloWeightTool->wtCell(cell) + mergePhi->pt()*m_caloWeightTool->wtCell(mergePhi)); + float phi = cell->phi()+dPhi*ratio; + float pt = cell->pt()*m_caloWeightTool->wtCell(cell)+mergePhi->pt()*m_caloWeightTool->wtCell(mergePhi); + + shot->setP4( (float) pt, (float) cell->eta(), (float) phi, (float) cell->m()); + } + else shot->setP4( (float) cell->pt()*m_caloWeightTool->wtCell(cell), (float) cell->eta(), (float) cell->phi(), (float) cell->m()); + + shot->setBDTPi0Score( (float) -9999. ); + shot->setCharge( 0. ); + double center_mag = 0.0; + // No need to calculate cluster moments atm. + //if( !shotCluster->retrieveMoment((xAOD::CaloCluster_v1::MomentType) 404, center_mag) ) ATH_MSG_WARNING("Couldn't retrieve CENTER_MAG moment. Set it to 0."); + shot->setCenterMag( (float) center_mag); + + ElementLink<xAOD::CaloClusterContainer> clusElementLink; + clusElementLink.toContainedElement( *m_shotClusterContainer, shotCluster ); + shot->setClusterLink( clusElementLink ); + shot->setAttribute<int>(xAOD::PFODetails::PFOAttributes::tauShots_nCellsInEta, m_nCellsInEta); + shot->setAttribute<int>(xAOD::PFODetails::PFOAttributes::tauShots_seedHash, seedHash); + + // Get cell block for variable calculations + std::vector<std::vector<const CaloCell*> > cellBlock = TauShotVariableHelpers::getCellBlock(shot, m_calo_id); + + // Some DEBUG statements + if (msgLvl(MSG::DEBUG)) { + if(cell->pt()*m_caloWeightTool->wtCell(cell)>300){ + ATH_MSG_DEBUG(""); + ATH_MSG_DEBUG("New shot. \t block size phi = " << cellBlock.size() << " \t block size eta = " << cellBlock.at(0).size() << "\t shot->pt() = " << shot->pt()); + for(unsigned iCellPhi = 0; iCellPhi<cellBlock.size();++iCellPhi){ + for(unsigned iCellEta = 0; iCellEta<cellBlock.at(iCellPhi).size();++iCellEta){ + const CaloCell* cell = cellBlock.at(iCellPhi).at(iCellEta); + if( cell==NULL ) ATH_MSG_DEBUG("Cell" << iCellPhi << iCellEta << ": \t NULL" ); + else ATH_MSG_DEBUG("Cell"<<iCellPhi<<iCellEta<<":\tPt = "<< cell->pt()*m_caloWeightTool->wtCell(cell)<<"\teta = "<<cell->eta()<<"\tphi = "<<cell->phi()); + } + } + } + } + // Get eta bin + int etaBin = getEtaBin(cell->eta()); + + // set variables used for photon counting + m_pt1=TauShotVariableHelpers::ptWindow(cellBlock,1,m_caloWeightTool); + m_pt3=TauShotVariableHelpers::ptWindow(cellBlock,3,m_caloWeightTool); + m_pt5=TauShotVariableHelpers::ptWindow(cellBlock,5,m_caloWeightTool); + // The folliwing variables are not needed atm + /* + m_ws5=TauShotVariableHelpers::ws5(cellBlock,m_caloWeightTool); + m_sdevEta5_WRTmean=TauShotVariableHelpers::sdevEta_WRTmean(cellBlock,m_caloWeightTool); + m_sdevEta5_WRTmode=TauShotVariableHelpers::sdevEta_WRTmode(cellBlock,m_caloWeightTool); + m_sdevPt5=TauShotVariableHelpers::sdevPt(cellBlock,m_caloWeightTool); + m_deltaPt12_min=TauShotVariableHelpers::deltaPt12_min(cellBlock,m_caloWeightTool); + m_Fside_3not1=TauShotVariableHelpers::Fside(cellBlock,3,1,m_caloWeightTool); + m_Fside_5not1=TauShotVariableHelpers::Fside(cellBlock,5,1,m_caloWeightTool); + m_Fside_5not3=TauShotVariableHelpers::Fside(cellBlock,5,3,m_caloWeightTool); + m_fracSide_3not1=TauShotVariableHelpers::fracSide(cellBlock,3,1,m_caloWeightTool); + m_fracSide_5not1=TauShotVariableHelpers::fracSide(cellBlock,5,1,m_caloWeightTool); + m_fracSide_5not3=TauShotVariableHelpers::fracSide(cellBlock,5,3,m_caloWeightTool); + m_pt1OverPt3=TauShotVariableHelpers::ptWindowFrac(cellBlock,3,1,m_caloWeightTool); + m_pt3OverPt5=TauShotVariableHelpers::ptWindowFrac(cellBlock,5,3,m_caloWeightTool); + + + // Same variable names as in Stephanie's private code + G_PTFRAC=m_fracSide_3not1; + G_STDPT_5=m_sdevPt5; + G_STDETA_5=fmin(m_sdevEta5_WRTmean,0.0036); + G_DELTAPT_MIN=fmax(-1000.,fmin(m_deltaPt12_min,2000)); + + // Calculate BDT scores + float mergedBDTScore=getMergedBDTScore(etaBin); + */ + + //////////////////////////////////////////////////////////////////////////////////////////// + // Calculate number of photons in shot + //////////////////////////////////////////////////////////////////////////////////////////// + //int nPhotons = getNPhotons(etaBin, mergedBDTScore, m_pt1); + int nPhotons = getNPhotons(etaBin, 1, m_pt1); + + //////////////////////////////////////////////////////////////////////////////////////////// + // Set variables in shot PFO + //////////////////////////////////////////////////////////////////////////////////////////// + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_pt1, m_pt1); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_pt3, m_pt3); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_pt5, m_pt5); + // The folliwing variables are not needed atm + /* + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_ws5, m_ws5); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_sdevEta5_WRTmean, m_sdevEta5_WRTmean); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_sdevEta5_WRTmode, m_sdevEta5_WRTmode); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_sdevPt5, m_sdevPt5); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_deltaPt12_min, m_deltaPt12_min); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_Fside_3not1, m_Fside_3not1); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_Fside_5not1, m_Fside_5not1); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_Fside_5not3, m_Fside_5not3); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_fracSide_3not1, m_fracSide_3not1); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_fracSide_5not1, m_fracSide_5not1); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_fracSide_5not3, m_fracSide_5not3); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_pt1OverPt3, m_pt1OverPt3); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_pt3OverPt5, m_pt3OverPt5); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_mergedScore, mergedBDTScore); + shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_signalScore, -1.); + */ + shot->setAttribute<int>(xAOD::PFODetails::PFOAttributes::tauShots_nPhotons, nPhotons); + + // remove shot(s) from list + vector<const CaloCell*>::iterator cellItrNonConst; + cellItrNonConst = std::find(seedCells.begin(),seedCells.end(),cell); + seedCells.erase(cellItrNonConst); + if( mergePhi ){ + cellItrNonConst = std::find(seedCells.begin(),seedCells.end(),mergePhi); + seedCells.erase(cellItrNonConst); + } + + /* + ATH_MSG_DEBUG("Storing shot. pt: " << shot->pt() + << ", eta: " << shot->eta() + << ", phi: " << shot->phi() + ); + */ + + } // seed cells + + + return StatusCode::SUCCESS; +} + +StatusCode TauShotFinder::eventFinalize() { + CHECK( CaloClusterStoreHelper::finalizeClusters(&*evtStore(), + m_shotClusterContainer, + m_shotClusterContainerName, + msg()) ); + + return StatusCode::SUCCESS; +} + +std::vector<const CaloCell*> TauShotFinder::getNeighbours(const CaloCellContainer* pCellContainer, + const CaloCell* cell, + int maxDepth) +{ + std::vector<const CaloCell*> cells; + this->addNeighbours(pCellContainer,cell,cells,0,maxDepth,true); //next + this->addNeighbours(pCellContainer,cell,cells,0,maxDepth,false); //prev + return cells; +} + +void TauShotFinder::addNeighbours(const CaloCellContainer* pCellContainer, + const CaloCell* cell, + std::vector<const CaloCell*>& cells, + int depth, + int maxDepth, + bool next) +{ + depth++; + if( depth > maxDepth ) return; + + const IdentifierHash cellHash = cell->caloDDE()->calo_hash(); + std::vector<IdentifierHash> neigHashes; + if( next ) + m_calo_id->get_neighbours(cellHash,LArNeighbours::nextInEta,neigHashes); + else + m_calo_id->get_neighbours(cellHash,LArNeighbours::prevInEta,neigHashes); + + std::vector<IdentifierHash>::iterator hashItr = neigHashes.begin(); + for( ; hashItr!=neigHashes.end(); ++hashItr ){ + const CaloCell* newCell = pCellContainer->findCell(*hashItr); + if(!newCell)continue; + cells.push_back(newCell); + this->addNeighbours(pCellContainer,newCell,cells,depth,maxDepth,next); + // no EM1 cell should have more than one neighbor. Just add this neigbor for now + // FIXME: Check whether it happens that a cell has > 1 neighbors + break; + } +} + +bool TauShotFinder::isPhiNeighbour(IdentifierHash cell1Hash, IdentifierHash cell2Hash, bool next){ + std::vector<IdentifierHash> neigHashes; + if( next ) m_calo_id->get_neighbours(cell1Hash,LArNeighbours::nextInPhi,neigHashes); + else m_calo_id->get_neighbours(cell1Hash,LArNeighbours::prevInPhi,neigHashes); + std::vector<IdentifierHash>::iterator itr = neigHashes.begin(); + for( ; itr!=neigHashes.end(); ++itr ){ + if(cell2Hash == (*itr)) return true; + } + return false; +} + +float TauShotFinder::getEtaBin(float seedEta){ + float absSeedEta=fabs(seedEta); + if(fabs(absSeedEta)<0.80) return 0; // Central Barrel + else if(fabs(absSeedEta)<1.39) return 1; // Outer Barrel + else if(fabs(absSeedEta)<1.51) return 2; // crack + else if(fabs(absSeedEta)<1.80) return 3; // endcap, fine granularity + else return 4; // endcap, coarse granularity +} + +/* +float TauShotFinder::getMergedBDTScore(int etaBin){ + float BDTScore = -1; + if(etaBin==0) BDTScore = m_tmvaReader_barrel->EvaluateMVA( "BDT method" ); // barrel1 + else if(etaBin==1) BDTScore = m_tmvaReader_barrel->EvaluateMVA( "BDT method" ); // barrel2 + else if(etaBin==2) BDTScore = m_tmvaReader_barrel->EvaluateMVA( "BDT method" ); // just use barrel BDT for now to check how it looks in data + else if(etaBin==3) BDTScore = m_tmvaReader_endcap1->EvaluateMVA( "BDT method" ); // endcap1 + else if(etaBin==4) BDTScore = m_tmvaReader_endcap2->EvaluateMVA( "BDT method" ); // endcap2 + return BDTScore; +} +*/ + +float TauShotFinder::getNPhotons(int etaBin, float mergedBDTScore, float seedEnergy){ + if(etaBin==2) return 0; // no photon counting in crack atm + ATH_MSG_DEBUG("etaBin = " << etaBin << ", seedEnergy = " << seedEnergy << ", m_minPtCut.at(etaBin) = " << m_minPtCut.at(etaBin) << ", m_autoDoubleShotCut.at(etaBin) = " + << m_autoDoubleShotCut.at(etaBin) << ", mergedBDTScore = " << mergedBDTScore << ", m_mergedBDTScoreCut.at(etaBin) = " << m_mergedBDTScoreCut.at(etaBin) ); + if( seedEnergy < m_minPtCut.at(etaBin) ) return 0; + if( seedEnergy > m_autoDoubleShotCut.at(etaBin) ) return 2; + if( mergedBDTScore < m_mergedBDTScoreCut.at(etaBin) ) return 2; + return 1; +} + +// some really slick c++ way of doing sort (since we need to use the member m_caloWeightTool) +// how about learing a thing or two from python... +TauShotFinder::ptSort::ptSort( const TauShotFinder& info ) : m_info(info) { } +bool TauShotFinder::ptSort::operator()( const CaloCell* c1, const CaloCell* c2 ){ + return c1->pt()*m_info.m_caloWeightTool->wtCell(c1) > c2->pt()*m_info.m_caloWeightTool->wtCell(c2); +} + +/* +StatusCode TauShotFinder::bookMethod(TMVA::Reader *reader_barrel, + TMVA::Reader *reader_endcap1, + TMVA::Reader *reader_endcap2, + const std::string &methodName) const +{ + if (m_weightfile_barrel == ""){ + ATH_MSG_ERROR("No weight m_weightfile_barrel given"); + return StatusCode::FAILURE; + } + if (m_weightfile_endcap1 == ""){ + ATH_MSG_ERROR("No weight m_weightfile_endcap1 given"); + return StatusCode::FAILURE; + } + if (m_weightfile_endcap2 == ""){ + ATH_MSG_ERROR("No weight m_weightfile_endcap2 given"); + return StatusCode::FAILURE; + } + std::string resolvedFileName = find_file(m_weightfile_barrel); + if (resolvedFileName != ""){ + ATH_MSG_DEBUG( "Parameterisation file found: " << resolvedFileName ); + } + else { + ATH_MSG_ERROR( "Parameterisation file " << m_weightfile_barrel << " not found" ); + return StatusCode::FAILURE; + } + reader_barrel->BookMVA( methodName, resolvedFileName); + + resolvedFileName = find_file(m_weightfile_endcap1); + if (resolvedFileName != ""){ + ATH_MSG_DEBUG( "Parameterisation file found: " << resolvedFileName ); + } + else { + ATH_MSG_ERROR( "Parameterisation file " << m_weightfile_endcap1 << " not found" ); + return StatusCode::FAILURE; + } + reader_endcap1->BookMVA( methodName, resolvedFileName); + + resolvedFileName = find_file(m_weightfile_endcap2); + if (resolvedFileName != ""){ + ATH_MSG_DEBUG( "Parameterisation file found: " << resolvedFileName ); + } + else { + ATH_MSG_ERROR( "Parameterisation file " << m_weightfile_endcap2 << " not found" ); + return StatusCode::FAILURE; + } + reader_endcap2->BookMVA( methodName, resolvedFileName); + return StatusCode::SUCCESS; +} +*/ +// EOF diff --git a/Reconstruction/tauRecTools/src/TauShotFinder.h b/Reconstruction/tauRecTools/src/TauShotFinder.h new file mode 100755 index 0000000000000000000000000000000000000000..2800791be0030a2d28e7c92b524275d990e96bf3 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauShotFinder.h @@ -0,0 +1,166 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUSHOTFINDER_H +#define TAUREC_TAUSHOTFINDER_H + +//#include <string> +//#include <vector> +//#include <map> + +#include "GaudiKernel/ToolHandle.h" +#include "tauRecTools/TauRecToolBase.h" +#include "xAODPFlow/PFOAuxContainer.h" +#include "xAODCaloEvent/CaloClusterAuxContainer.h" + +//#include "CaloIdentifier/CaloCell_ID.h" + +class CaloDetDescrManager; +class CaloCell_ID; +class IHadronicCalibrationTool; + +/* +namespace TMVA{ + class Reader; +} +*/ + +/** + * @brief Find photon shots in the EM1 strip layer. + * + * @author Will Davey <will.davey@cern.ch> + * @author Benedict Winter <benedict.tobias.winter@cern.ch> + * @author Stephanie Yuen <stephanie.yuen@cern.ch> + */ + +class TauShotFinder : virtual public TauRecToolBase { +public: + TauShotFinder(const std::string& name); + ASG_TOOL_CLASS2(TauShotFinder, TauRecToolBase, ITauToolBase); + virtual ~TauShotFinder(); + + virtual StatusCode initialize(); + virtual StatusCode eventInitialize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode eventFinalize(); + virtual StatusCode finalize(); + + virtual void print() const { } + + +private: + + /** @brief tool handles */ + ToolHandle<IHadronicCalibrationTool> m_caloWeightTool; + + /** @brief all calo cell container name */ + std::string m_caloCellContainerName; + /** @brief new shot cluster container and name */ + xAOD::CaloClusterContainer* m_shotClusterContainer; + std::string m_shotClusterContainerName; + + /** @brief new shot PFO container and name */ + xAOD::PFOContainer* m_PFOShotContainer; + std::string m_shotPFOContainerName; + xAOD::PFOAuxContainer* m_PFOShotAuxStore; + + + /** @brief calo cell navigation */ + const CaloDetDescrManager* m_calo_dd_man; + const CaloCell_ID* m_calo_id; + + /** @brief readers */ + /* + std::string m_readerOption; + + TMVA::Reader *m_tmvaReader_barrel; + std::string m_weightfile_barrel; + + TMVA::Reader *m_tmvaReader_endcap1; + std::string m_weightfile_endcap1; + + TMVA::Reader *m_tmvaReader_endcap2; + std::string m_weightfile_endcap2; + */ + + /** @brief Thanks C++ for ruining my day */ + struct ptSort + { + ptSort( const TauShotFinder& info ); + const TauShotFinder& m_info; + bool operator()( const CaloCell* c1, const CaloCell* c2 ); + }; + + /** @brief get neighbour cells */ + std::vector<const CaloCell*> getNeighbours(const CaloCellContainer*,const CaloCell*,int /*maxDepth*/); + + void addNeighbours(const CaloCellContainer*, + const CaloCell* cell, + std::vector<const CaloCell*>& cells, + int depth, + int maxDepth, + bool next); + + bool isPhiNeighbour(IdentifierHash cell1Hash, IdentifierHash cell2Hash, bool next); + + /** @brief get eta bin */ + float getEtaBin(float /*seedEta*/); + + /** @brief get merged BDTscore */ + // float getMergedBDTScore(int /*etaBin*/); + + /** @brief get NPhotons in shot */ + float getNPhotons(int /*etaBin*/, + float /*mergedBDTScore*/, + float /*seedEnergy*/); + + + /** @brief Book TMVA methods. */ + /* + StatusCode bookMethod(TMVA::Reader *reader_barrel, + TMVA::Reader *reader_endcap1, + TMVA::Reader *reader_endcap2, + const std::string &methodName) const; + */ + + // number of cells in eta + int m_nCellsInEta; + + // cut values + std::vector<float> m_minPtCut; + std::vector<float> m_autoDoubleShotCut; + std::vector<float> m_mergedBDTScoreCut; + + // BDT input variables + float m_pt1; + float m_pt3; + float m_pt5; + /* + float m_ws5; + float m_sdevEta5_WRTmean; + float m_sdevEta5_WRTmode; + float m_sdevPt5; + float m_deltaPt12_min; + float m_Fside_3not1; + float m_Fside_5not1; + float m_Fside_5not3; + float m_fracSide_3not1; + float m_fracSide_5not1; + float m_fracSide_5not3; + float m_pt1OverPt3; + float m_pt3OverPt5; + */ + + /* + // FIXME: same variable names as in Stephanie's private code atm + float G_PTFRAC; + float G_STDPT_5; + float G_STDETA_5; + float G_DELTAPT_MIN; + */ + +}; + +#endif /* TAUSHOTFINDER_H */ + diff --git a/Reconstruction/tauRecTools/src/TauShotVariableHelpers.cxx b/Reconstruction/tauRecTools/src/TauShotVariableHelpers.cxx new file mode 100644 index 0000000000000000000000000000000000000000..3645dd3b5db95f8884e4c39f18458878b2e9db5b --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauShotVariableHelpers.cxx @@ -0,0 +1,358 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @brief implementation of photon shot variable calculation + * + * @author Will Davey <will.davey@cern.ch> + * @author Benedict Winter <benedict.tobias.winter@cern.ch> + * @author Stephanie Yuen <stephanie.yuen@cern.ch> + */ + +#include "TauShotVariableHelpers.h" + +using xAOD::PFO; +using std::vector; + +namespace TauShotVariableHelpers { + std::vector<std::vector<const CaloCell*> > getCellBlock(xAOD::PFO* shot, const CaloCell_ID* calo_id){ + std::vector<std::vector<const CaloCell*> > cellVector; + std::vector<const CaloCell*> oneEtaLayer; + int nCellsInEta = 0; + if( shot->attribute(xAOD::PFODetails::PFOAttributes::tauShots_nCellsInEta, nCellsInEta) == false) { + std::cout << "WARNING: Couldn't find nCellsInEta. Return empty cell block." << std::endl; + return cellVector; + } + int seedHash = 0; + if( shot->attribute(xAOD::PFODetails::PFOAttributes::tauShots_seedHash, seedHash) == false) { + std::cout << "WARNING: Couldn't find seed hash. Return empty cell block." << std::endl; + return cellVector; + } + for(int iCell=0;iCell<nCellsInEta;++iCell) oneEtaLayer.push_back(NULL); + // have two layers in phi + cellVector.push_back(oneEtaLayer); + cellVector.push_back(oneEtaLayer); + // get cluster from shot + const xAOD::CaloCluster* cluster = shot->cluster(0); + const CaloClusterCellLink* theCellLink = cluster->getCellLinks(); + CaloClusterCellLink::const_iterator cellItr = theCellLink->begin(); + CaloClusterCellLink::const_iterator cellItrE = theCellLink->end(); + + // get seed cell from shot cluster + const CaloCell* seedCell=NULL; + for(;cellItr!=cellItrE;++cellItr){ + if((*cellItr)->caloDDE()->calo_hash()!=(unsigned) seedHash) continue; + seedCell = *cellItr; + break; + } + if(seedCell==NULL){ + std::cout << "WARNING: Couldn't find seed cell in shot cluster. Return empty cell block." << std::endl; + return cellVector; + } + + // get merged cell in phi. Keep NULL if shot is not merged across phi + const CaloCell* mergedCell = NULL; + std::vector<IdentifierHash> nextInPhi; + std::vector<IdentifierHash> prevInPhi; + calo_id->get_neighbours(seedCell->caloDDE()->calo_hash(),LArNeighbours::nextInPhi,nextInPhi); + calo_id->get_neighbours(seedCell->caloDDE()->calo_hash(),LArNeighbours::prevInPhi,prevInPhi); + for(cellItr=theCellLink->begin();cellItr!=cellItrE;++cellItr){ + std::vector<IdentifierHash>::iterator itr = nextInPhi.begin(); + for( ; itr!=nextInPhi.end(); ++itr ){ + if((*cellItr)->caloDDE()->calo_hash() != (*itr)) continue; + mergedCell = (*cellItr); + break; + } + if(mergedCell!=NULL) break; + itr = prevInPhi.begin(); + for( ; itr!=prevInPhi.end(); ++itr ){ + if((*cellItr)->caloDDE()->calo_hash() != (*itr)) continue; + mergedCell = (*cellItr); + break; + } + if(mergedCell!=NULL) break; + } + // store cells in the eta layer, which contains the seed cell + int nCellsFromSeed = 1; + const CaloCell* lastCell = seedCell; + cellVector.at(0).at(nCellsInEta/2) = seedCell; // store seed cell + std::vector<IdentifierHash> next; + while(lastCell!=NULL && nCellsFromSeed<nCellsInEta/2+1){ + calo_id->get_neighbours(lastCell->caloDDE()->calo_hash(),LArNeighbours::nextInEta,next); + lastCell = NULL; + for(cellItr=theCellLink->begin();cellItr!=cellItrE;++cellItr){ + std::vector<IdentifierHash>::iterator itr = next.begin(); + for( ; itr!=next.end(); ++itr ){ + if((*cellItr)->caloDDE()->calo_hash() != (*itr)) continue; + cellVector.at(0).at(nCellsInEta/2+nCellsFromSeed) = (*cellItr); + lastCell = (*cellItr); + } + } + nCellsFromSeed++; + } + nCellsFromSeed = 1; + lastCell = seedCell; + while(lastCell!=NULL && nCellsFromSeed<nCellsInEta/2+1){ + calo_id->get_neighbours(lastCell->caloDDE()->calo_hash(),LArNeighbours::prevInEta,next); + lastCell = NULL; + for(cellItr=theCellLink->begin();cellItr!=cellItrE;++cellItr){ + std::vector<IdentifierHash>::iterator itr = next.begin(); + for( ; itr!=next.end(); ++itr ){ + if((*cellItr)->caloDDE()->calo_hash() != (*itr)) continue; + cellVector.at(0).at(nCellsInEta/2-nCellsFromSeed) = (*cellItr); + lastCell = (*cellItr); + } + } + nCellsFromSeed++; + } + // store cells in the eta layer, which contains the merged cell + int nCellsFromMerged = 1; + lastCell = mergedCell; // is NULL if shot is not merged + cellVector.at(1).at(nCellsInEta/2) = mergedCell; // store merged cell + while(lastCell!=NULL && nCellsFromMerged<nCellsInEta/2+1){ + calo_id->get_neighbours(lastCell->caloDDE()->calo_hash(),LArNeighbours::nextInEta,next); + lastCell = NULL; + for(cellItr=theCellLink->begin();cellItr!=cellItrE;++cellItr){ + std::vector<IdentifierHash>::iterator itr = next.begin(); + for( ; itr!=next.end(); ++itr ){ + if((*cellItr)->caloDDE()->calo_hash() != (*itr)) continue; + cellVector.at(1).at(nCellsInEta/2+nCellsFromMerged) = (*cellItr); + lastCell = (*cellItr); + } + } + nCellsFromMerged++; + } + nCellsFromMerged = 1; + lastCell = mergedCell; + while(lastCell!=NULL && nCellsFromMerged<nCellsInEta/2+1){ + calo_id->get_neighbours(lastCell->caloDDE()->calo_hash(),LArNeighbours::prevInEta,next); + lastCell = NULL; + for(cellItr=theCellLink->begin();cellItr!=cellItrE;++cellItr){ + std::vector<IdentifierHash>::iterator itr = next.begin(); + for( ; itr!=next.end(); ++itr ){ + if((*cellItr)->caloDDE()->calo_hash() != (*itr)) continue; + cellVector.at(1).at(nCellsInEta/2-nCellsFromMerged) = (*cellItr); + lastCell = (*cellItr); + } + } + nCellsFromMerged++; + } + return cellVector; + + } + + + float mean_eta(vector<vector<const CaloCell*> > shotCells, ToolHandle<IHadronicCalibrationTool>& m_caloWeightTool){ + float sumEta=0.; + float sumWeight=0.; + vector<vector<const CaloCell*> >::iterator itrPhi = shotCells.begin(); + for( ; itrPhi!=shotCells.end(); ++itrPhi ){ + vector<const CaloCell*>::iterator itrEta = itrPhi->begin(); + for( ; itrEta!=itrPhi->end(); ++itrEta ){ + if((*itrEta) == NULL) continue; + sumWeight += (*itrEta)->pt()*m_caloWeightTool->wtCell(*itrEta); + sumEta += (*itrEta)->pt()*m_caloWeightTool->wtCell(*itrEta) * (*itrEta)->eta(); + } + } + if(sumWeight<=0.) return -99999.; + return sumEta/sumWeight; + } + + float mean_pt(vector<vector<const CaloCell*> > shotCells, ToolHandle<IHadronicCalibrationTool>& m_caloWeightTool){ + float sumPt=0.; + int nCells = 0; + vector<vector<const CaloCell*> >::iterator itrPhi = shotCells.begin(); + for( ; itrPhi!=shotCells.end(); ++itrPhi ){ + vector<const CaloCell*>::iterator itrEta = itrPhi->begin(); + for( ; itrEta!=itrPhi->end(); ++itrEta ){ + if((*itrEta) == NULL) continue; + sumPt += (*itrEta)->pt()*m_caloWeightTool->wtCell(*itrEta); + nCells ++; + } + } + if(nCells==0) return -99999.; + return sumPt/nCells; + } + + float ptWindow(vector<vector<const CaloCell*> > shotCells, int windowSize, ToolHandle<IHadronicCalibrationTool>& m_caloWeightTool){ + // window size should be odd and noti be larger than eta window of shotCells + int nCells_eta = shotCells.at(0).size(); + int seedIndex = nCells_eta/2; + if( windowSize%2!=1 ) return 0.; + if( windowSize > nCells_eta) return 0.; + float ptWindow = 0.; + for(int iCell = 0; iCell != nCells_eta; ++iCell ){ + if(fabs(iCell-seedIndex)>windowSize/2) continue; + if(shotCells.at(0).at(iCell) != NULL) ptWindow+=shotCells.at(0).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(0).at(iCell)); + if(shotCells.at(1).at(iCell) != NULL) ptWindow+=shotCells.at(1).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(1).at(iCell)); + } + return ptWindow; + } + + float ws5(vector<vector<const CaloCell*> > shotCells, ToolHandle<IHadronicCalibrationTool>& m_caloWeightTool){ + int nCells_eta = shotCells.at(0).size(); + int seedIndex = nCells_eta/2; + float sumWeight=0.; + float sumDev2=0.; + vector<vector<const CaloCell*> >::iterator itrPhi = shotCells.begin(); + for( ; itrPhi!=shotCells.end(); ++itrPhi ){ + for(unsigned iCell = 0; iCell != itrPhi->size(); ++iCell ){ + if(itrPhi->at(iCell) == NULL) continue; + sumWeight += itrPhi->at(iCell)->pt()*m_caloWeightTool->wtCell(itrPhi->at(iCell)); + sumDev2 += itrPhi->at(iCell)->pt()*m_caloWeightTool->wtCell(itrPhi->at(iCell)) * pow(iCell-seedIndex,2); + } + } + if(sumWeight<=0. || sumDev2 <0.) return -99999.; + return sqrt( sumDev2 / sumWeight ); + } + + float sdevEta_WRTmean(vector<vector<const CaloCell*> > shotCells, ToolHandle<IHadronicCalibrationTool>& m_caloWeightTool){ + float mean = mean_eta(shotCells, m_caloWeightTool); + float sumWeight=0.; + float sumDev2=0.; + vector<vector<const CaloCell*> >::iterator itrPhi = shotCells.begin(); + for( ; itrPhi!=shotCells.end(); ++itrPhi ){ + vector<const CaloCell*>::iterator itrEta = itrPhi->begin(); + for( ; itrEta!=itrPhi->end(); ++itrEta ){ + if((*itrEta) == NULL) continue; + sumWeight += (*itrEta)->pt()*m_caloWeightTool->wtCell(*itrEta); + sumDev2 += (*itrEta)->pt()*m_caloWeightTool->wtCell(*itrEta) * pow((*itrEta)->eta() - mean,2); + } + } + if(sumWeight<=0. || sumDev2 <0.) return -99999.; + return sqrt( sumDev2 / sumWeight ); + } + + float sdevEta_WRTmode(vector<vector<const CaloCell*> > shotCells, ToolHandle<IHadronicCalibrationTool>& m_caloWeightTool){ + int nCells_eta = shotCells.at(0).size(); + int seedIndex = nCells_eta/2; + float mode = shotCells.at(0).at(seedIndex)->eta(); + float sumWeight=0.; + float sumDev2=0.; + vector<vector<const CaloCell*> >::iterator itrPhi = shotCells.begin(); + for( ; itrPhi!=shotCells.end(); ++itrPhi ){ + vector<const CaloCell*>::iterator itrEta = itrPhi->begin(); + for( ; itrEta!=itrPhi->end(); ++itrEta ){ + if((*itrEta) == NULL) continue; + sumWeight += (*itrEta)->pt()*m_caloWeightTool->wtCell(*itrEta); + sumDev2 += (*itrEta)->pt()*m_caloWeightTool->wtCell(*itrEta) * pow((*itrEta)->eta() - mode,2); + } + } + if(sumWeight<=0. || sumDev2 <0.) return -99999.; + return sqrt( sumDev2 / sumWeight ); + } + + float sdevPt(vector<vector<const CaloCell*> > shotCells, ToolHandle<IHadronicCalibrationTool>& m_caloWeightTool){ + float mean = mean_pt(shotCells, m_caloWeightTool); + float sumWeight=0.; + float sumDev2=0.; + vector<vector<const CaloCell*> >::iterator itrPhi = shotCells.begin(); + for( ; itrPhi!=shotCells.end(); ++itrPhi ){ + vector<const CaloCell*>::iterator itrEta = itrPhi->begin(); + for( ; itrEta!=itrPhi->end(); ++itrEta ){ + if((*itrEta) == NULL) continue; + sumWeight += (*itrEta)->pt()*m_caloWeightTool->wtCell(*itrEta); + sumDev2 += pow((*itrEta)->pt()*m_caloWeightTool->wtCell(*itrEta) - mean,2); + } + } + if(sumWeight<=0. || sumDev2 <0.) return -99999.; + return sqrt(sumDev2)/sumWeight; + } + + float deltaPt12_min(vector<vector<const CaloCell*> > shotCells, ToolHandle<IHadronicCalibrationTool>& m_caloWeightTool){ + int nCells_eta = shotCells.at(0).size(); + int seedIndex = nCells_eta/2; + bool haveLeft = false; + bool haveRight = false; + float deltaPt_left = 0.; + float deltaPt_right = 0.; + if(shotCells.at(0).at(seedIndex-1)!=NULL && shotCells.at(0).at(seedIndex-2)!=NULL){ + haveLeft = true; + deltaPt_left = shotCells.at(0).at(seedIndex-1)->pt()*m_caloWeightTool->wtCell(shotCells.at(0).at(seedIndex-1)) + -shotCells.at(0).at(seedIndex-2)->pt()*m_caloWeightTool->wtCell(shotCells.at(0).at(seedIndex-2)); + if(shotCells.at(1).at(seedIndex-1)!=NULL && shotCells.at(1).at(seedIndex-2)!=NULL){ + deltaPt_left += shotCells.at(1).at(seedIndex-1)->pt()*m_caloWeightTool->wtCell(shotCells.at(1).at(seedIndex-1)) + -shotCells.at(1).at(seedIndex-2)->pt()*m_caloWeightTool->wtCell(shotCells.at(1).at(seedIndex-2)); + } + } + if(shotCells.at(0).at(seedIndex+1)!=NULL && shotCells.at(0).at(seedIndex+2)!=NULL){ + haveRight = true; + deltaPt_right = shotCells.at(0).at(seedIndex+1)->pt()*m_caloWeightTool->wtCell(shotCells.at(0).at(seedIndex+1)) + -shotCells.at(0).at(seedIndex+2)->pt()*m_caloWeightTool->wtCell(shotCells.at(0).at(seedIndex+2)); + if(shotCells.at(1).at(seedIndex+1)!=NULL && shotCells.at(1).at(seedIndex+2)!=NULL){ + deltaPt_right += shotCells.at(1).at(seedIndex+1)->pt()*m_caloWeightTool->wtCell(shotCells.at(1).at(seedIndex+1)) + -shotCells.at(1).at(seedIndex+2)->pt()*m_caloWeightTool->wtCell(shotCells.at(1).at(seedIndex+1)); + } + } + if(haveLeft && haveRight) return fmin(deltaPt_left,deltaPt_right); + if(haveLeft) return deltaPt_left; + if(haveRight) return deltaPt_right; + else return -1.; + } + + + float Fside(vector<vector<const CaloCell*> > shotCells, int largerWindow, int smallerWindow, ToolHandle<IHadronicCalibrationTool>& m_caloWeightTool){ + // window sizes should be odd and windows should be not larger than eta window of shotCells + int nCells_eta = shotCells.at(0).size(); + int seedIndex = nCells_eta/2; + if( largerWindow%2!=1 || smallerWindow%2!=1) return 0.; + if( largerWindow <= smallerWindow) return 0.; + if( largerWindow > nCells_eta) return 0.; + float pt_largerWindow = 0.; + float pt_smallerWindow = 0.; + for(int iCell = 0; iCell != nCells_eta; ++iCell ){ + if(fabs(iCell-seedIndex)>largerWindow/2) continue; + if(shotCells.at(0).at(iCell)!=NULL) pt_largerWindow+=shotCells.at(0).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(0).at(iCell)); + if(shotCells.at(1).at(iCell)!=NULL) pt_largerWindow+=shotCells.at(1).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(1).at(iCell)); + if(fabs(iCell-seedIndex)>smallerWindow/2) continue; + if(shotCells.at(0).at(iCell)!=NULL) pt_smallerWindow+=shotCells.at(0).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(0).at(iCell)); + if(shotCells.at(1).at(iCell)!=NULL) pt_smallerWindow+=shotCells.at(1).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(1).at(iCell)); + } + if(pt_smallerWindow==0.) return -99999.; + return (pt_largerWindow-pt_smallerWindow)/pt_smallerWindow; + } + + float fracSide(vector<vector<const CaloCell*> > shotCells, int largerWindow, int smallerWindow, ToolHandle<IHadronicCalibrationTool>& m_caloWeightTool){ + // window sizes should be odd and windows should be not larger than eta window of shotCells + int nCells_eta = shotCells.at(0).size(); + int seedIndex = nCells_eta/2; + if( largerWindow%2!=1 || smallerWindow%2!=1) return 0.; + if( largerWindow <= smallerWindow) return 0.; + if( largerWindow > nCells_eta) return 0.; + float pt_largerWindow = 0.; + float pt_smallerWindow = 0.; + for(int iCell = 0; iCell != nCells_eta; ++iCell ){ + if(fabs(iCell-seedIndex)>largerWindow/2) continue; + if(shotCells.at(0).at(iCell)!=NULL) pt_largerWindow+=shotCells.at(0).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(0).at(iCell)); + if(shotCells.at(1).at(iCell)!=NULL) pt_largerWindow+=shotCells.at(1).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(1).at(iCell)); + if(fabs(iCell-seedIndex)>smallerWindow/2) continue; + if(shotCells.at(0).at(iCell)!=NULL) pt_smallerWindow+=shotCells.at(0).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(0).at(iCell)); + if(shotCells.at(1).at(iCell)!=NULL) pt_smallerWindow+=shotCells.at(1).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(1).at(iCell)); + } + if(pt_largerWindow==0.) return -99999.; + return (pt_largerWindow-pt_smallerWindow)/pt_largerWindow; + } + + float ptWindowFrac(vector<vector<const CaloCell*> > shotCells, int largerWindow, int smallerWindow, ToolHandle<IHadronicCalibrationTool>& m_caloWeightTool){ + // window sizes should be odd and windows should be not larger than eta window of shotCells + int nCells_eta = shotCells.at(0).size(); + int seedIndex = nCells_eta/2; + if( largerWindow%2!=1 || smallerWindow%2!=1) return 0.; + if( largerWindow <= smallerWindow) return 0.; + if( largerWindow > nCells_eta) return 0.; + float pt_largerWindow = 0.; + float pt_smallerWindow = 0.; + for(int iCell = 0; iCell != nCells_eta; ++iCell ){ + if(fabs(iCell-seedIndex)>largerWindow/2) continue; + if(shotCells.at(0).at(iCell)!=NULL) pt_largerWindow+=shotCells.at(0).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(0).at(iCell)); + if(shotCells.at(1).at(iCell)!=NULL) pt_largerWindow+=shotCells.at(1).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(1).at(iCell)); + if(fabs(iCell-seedIndex)>smallerWindow/2) continue; + if(shotCells.at(0).at(iCell)!=NULL) pt_smallerWindow+=shotCells.at(0).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(0).at(iCell)); + if(shotCells.at(1).at(iCell)!=NULL) pt_smallerWindow+=shotCells.at(1).at(iCell)->pt()*m_caloWeightTool->wtCell(shotCells.at(1).at(iCell)); + } + if(pt_largerWindow==0.) return -99999.; + return pt_smallerWindow/pt_largerWindow; + } +} + diff --git a/Reconstruction/tauRecTools/src/TauShotVariableHelpers.h b/Reconstruction/tauRecTools/src/TauShotVariableHelpers.h new file mode 100644 index 0000000000000000000000000000000000000000..e2e9b76f8d4ad315c4b9bb865265230825274f4c --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauShotVariableHelpers.h @@ -0,0 +1,79 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @brief implementation of photon shot variable calculation + * + * @author Will Davey <will.davey@cern.ch> + * @author Benedict Winter <benedict.tobias.winter@cern.ch> + * @author Stephanie Yuen <stephanie.yuen@cern.ch> + */ + +#ifndef TAUSHOTVARIABLEHELPERS_H +#define TAUSHOTVARIABLEHELPERS_H + +#include "xAODPFlow/PFO.h" +#include "GaudiKernel/ToolHandle.h" +#include "CaloInterface/IHadronicCalibrationTool.h" + +namespace TauShotVariableHelpers { + + /** @brief get cell block with (currently) 5x2 cells in correct order for variable calculations */ + std::vector<std::vector<const CaloCell*> > getCellBlock(xAOD::PFO* shot, + const CaloCell_ID* calo_id); + + /** @brief mean eta, used by other functions */ + float mean_eta(std::vector<std::vector<const CaloCell*> > /*shotCells*/, + ToolHandle<IHadronicCalibrationTool>& /*m_caloWeightTool*/); + + /** @brief mean pt, used by other functions */ + float mean_pt(std::vector<std::vector<const CaloCell*> > /*shotCells*/, + ToolHandle<IHadronicCalibrationTool>& /*m_caloWeightTool*/); + + /** @brief pt in windows */ + float ptWindow(std::vector<std::vector<const CaloCell*> > /*shotCells*/, + int /*windowSize*/, + ToolHandle<IHadronicCalibrationTool>& /*m_caloWeightTool*/); + + /** @brief ws5 variable (egamma) */ + float ws5(std::vector<std::vector<const CaloCell*> > /*shotCells*/, + ToolHandle<IHadronicCalibrationTool>& /*m_caloWeightTool*/); + + /** @brief standard deviation in eta WRT mean */ + float sdevEta_WRTmean(std::vector<std::vector<const CaloCell*> > /*shotCells*/, + ToolHandle<IHadronicCalibrationTool>& /*m_caloWeightTool*/); + + /** @brief standard deviation in eta WRT mode */ + float sdevEta_WRTmode(std::vector<std::vector<const CaloCell*> > /*shotCells*/, + ToolHandle<IHadronicCalibrationTool>& /*m_caloWeightTool*/); + + /** @brief normalized standard deviation in pt */ + float sdevPt(std::vector<std::vector<const CaloCell*> > /*shotCells*/, + ToolHandle<IHadronicCalibrationTool>& /*m_caloWeightTool*/); + + /** @brief pT diff b/w lead and sub-lead cell */ + float deltaPt12_min(std::vector<std::vector<const CaloCell*> > /*shotCells*/, + ToolHandle<IHadronicCalibrationTool>& /*m_caloWeightTool*/); + + /** @brief Fside variable (egamma) */ + float Fside(std::vector<std::vector<const CaloCell*> > /*shotCells*/, + int /*largerWindow*/, + int /*smallerWindow*/, + ToolHandle<IHadronicCalibrationTool>& /*m_caloWeightTool*/); + + /** @brief similar than Fside but in unit of eta instead of number of cells */ + float fracSide(std::vector<std::vector<const CaloCell*> > /*shotCells*/, + int /*largerWindow*/, + int /*smallerWindow*/, + ToolHandle<IHadronicCalibrationTool>& /*m_caloWeightTool*/); + + /** @brief pt window fraction */ + float ptWindowFrac(std::vector<std::vector<const CaloCell*> > /*shotCells*/, + int /*largerWindow*/, + int /*smallerWindow*/, + ToolHandle<IHadronicCalibrationTool>& /*m_caloWeightTool*/); +} + +#endif // TAUSHOTVARIABLEHELPERS_H + diff --git a/Reconstruction/tauRecTools/src/TauSubstructureVariables.cxx b/Reconstruction/tauRecTools/src/TauSubstructureVariables.cxx new file mode 100644 index 0000000000000000000000000000000000000000..971f24203a16dbc376881540211eab3891f24326 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauSubstructureVariables.cxx @@ -0,0 +1,398 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//********************************************************************// +// NAME: TauSubstructureVariables.cxx // +// PACKAGE: offline/Reconstruction/tauRec // +// AUTHORS: M. Trottier-McDonald // +// CREATED: January 11 2010 // +//********************************************************************// + +#include <algorithm> +#include <math.h> +#include <sstream> + +#include "GaudiKernel/Property.h" +#include "FourMomUtils/P4Helpers.h" + +#include "AnalysisUtils/AnalysisMisc.h" + +#include "xAODJet/Jet.h" +#include "xAODTau/TauJet.h" + +#include "CaloClusterVariables.h" +#include "TauSubstructureVariables.h" + +#include "tauRecTools/KineUtils.h" +#include "CaloUtils/CaloVertexedCluster.h" +//#include "CaloEvent/CaloVertexedCluster.h" + +using CLHEP::GeV; + +const double TauSubstructureVariables::DEFAULT = -1111.; + +//********************************** +// Constructor +//********************************** + +TauSubstructureVariables::TauSubstructureVariables( const std::string& name ) : + TauRecToolBase(name), + m_maxPileUpCorrection(4 * GeV), + m_pileUpAlpha(1.0), + m_doVertexCorrection(false), //FF: don't do cell correction by default + m_inAODmode(false) { + declareProperty("maxPileUpCorrection", m_maxPileUpCorrection); + declareProperty("pileUpAlpha", m_pileUpAlpha); + declareProperty("VertexCorrection", m_doVertexCorrection); + declareProperty("inAODmode", m_inAODmode); +} + + +//********************************** +// Destructor +//********************************** + +TauSubstructureVariables::~TauSubstructureVariables() { +} + + +//*********************************** +// Initialize method +//*********************************** + +StatusCode TauSubstructureVariables::initialize() { + return StatusCode::SUCCESS; +} + +//*********************************** +// Finalize method +//*********************************** + +StatusCode TauSubstructureVariables::finalize() { + return StatusCode::SUCCESS; +} + +StatusCode TauSubstructureVariables::eventInitialize() { + return StatusCode::SUCCESS; +} + + +//************************************ +// Execute method +//************************************ + +StatusCode TauSubstructureVariables::execute(xAOD::TauJet& pTau) { + // Getting our hands on the TauJet object + //---------------------------------------- + + // Getting the jet seed + // By asking taujet instead of TauEventData->seed, we take advantage of the machinery already + // in place to retrieve a jet seed for track only candidates. + //------------------------------------------------------------------------------------------------ + const xAOD::Jet* taujetseed = (*pTau.jetLink()); + + //***************************************************** + // calculate some tau substructure variables + //***************************************************** + + CaloClusterVariables CaloClusterVariablesTool; + CaloClusterVariablesTool.setVertexCorrection(m_doVertexCorrection); + + bool isFilled = CaloClusterVariablesTool.update(pTau, m_inAODmode); + + if (!isFilled) { + if (!taujetseed) ATH_MSG_DEBUG("Taujet->jet() pointer is NULL: calo cluster variables will be set to -1111"); + else ATH_MSG_DEBUG("problem in calculating calo cluster variables -> will be set to -1111"); + + pTau.setDetail(xAOD::TauJetParameters::numCells , static_cast<int>(0) ); + pTau.setDetail(xAOD::TauJetParameters::numTopoClusters , static_cast<int>(DEFAULT) ); + pTau.setDetail(xAOD::TauJetParameters::numEffTopoClusters , static_cast<float>(DEFAULT) ); + pTau.setDetail(xAOD::TauJetParameters::topoInvMass, static_cast<float>(DEFAULT) ); + pTau.setDetail(xAOD::TauJetParameters::effTopoInvMass, static_cast<float>(DEFAULT) ); + pTau.setDetail(xAOD::TauJetParameters::topoMeanDeltaR, static_cast<float>(DEFAULT) ); + pTau.setDetail(xAOD::TauJetParameters::effTopoMeanDeltaR, static_cast<float>(DEFAULT) ); + + } else { + // Getting the variables + //----------------------- + double TopoInvMass = CaloClusterVariablesTool.totalMass(); + double EffTopoInvMass = CaloClusterVariablesTool.effectiveMass(); + unsigned int NumTopoClusters = CaloClusterVariablesTool.numConstituents(); + double NumEffTopoClusters = CaloClusterVariablesTool.effectiveNumConstituents(); + double TopoMeanDeltaR = CaloClusterVariablesTool.averageRadius(); + double EffTopoMeanDeltaR = CaloClusterVariablesTool.averageEffectiveRadius(); + unsigned int Ncells = CaloClusterVariablesTool.numCells(); + + ATH_MSG_VERBOSE(" Substructure variables: "); + ATH_MSG_VERBOSE("-------------------------"); + ATH_MSG_VERBOSE(" TopoInvMass: " << TopoInvMass); + ATH_MSG_VERBOSE(" EffTopoInvMass: " << EffTopoInvMass); + ATH_MSG_VERBOSE(" NumTopoClusters: " << NumTopoClusters); + ATH_MSG_VERBOSE("NumEffTopoClusters: " << NumEffTopoClusters); + ATH_MSG_VERBOSE(" TopoMeanDeltaR: " << TopoMeanDeltaR); + ATH_MSG_VERBOSE(" EffTopoMeanDeltaR: " << EffTopoMeanDeltaR); + ATH_MSG_VERBOSE(" NumCells: " << Ncells); + + //Record the variables + //--------------------- + + if (!m_inAODmode) pTau.setDetail(xAOD::TauJetParameters::numCells , static_cast<int> (Ncells) ); + pTau.setDetail(xAOD::TauJetParameters::numTopoClusters , static_cast<int> (NumTopoClusters) ); + pTau.setDetail(xAOD::TauJetParameters::numEffTopoClusters , static_cast<float>(NumEffTopoClusters) ); + pTau.setDetail(xAOD::TauJetParameters::topoInvMass , static_cast<float>(TopoInvMass) ); + pTau.setDetail(xAOD::TauJetParameters::effTopoInvMass , static_cast<float>(EffTopoInvMass) ); + pTau.setDetail(xAOD::TauJetParameters::topoMeanDeltaR , static_cast<float>(TopoMeanDeltaR) ); + pTau.setDetail(xAOD::TauJetParameters::effTopoMeanDeltaR , static_cast<float>(EffTopoMeanDeltaR) ); + + } + + //***************************************************** + // calculate some new cluster based ID variables + //***************************************************** + + if (taujetseed == NULL) { + + // No jet seed? Warning! Fill variables with dummy values + //-------------------------------------------------------- + + ATH_MSG_DEBUG("Taujet->jet() pointer is NULL: substructure variables will be set to -1111"); + + pTau.setDetail(xAOD::TauJetParameters::lead2ClusterEOverAllClusterE, static_cast<float>(DEFAULT) ); + pTau.setDetail(xAOD::TauJetParameters::lead3ClusterEOverAllClusterE, static_cast<float>(DEFAULT) ); + pTau.setDetail(xAOD::TauJetParameters::caloIso , static_cast<float>(DEFAULT) ); + pTau.setDetail(xAOD::TauJetParameters::caloIsoCorrected , static_cast<float>(DEFAULT) ); + pTau.setDetail(xAOD::TauJetParameters::dRmax , static_cast<float>(DEFAULT) ); + + return StatusCode::SUCCESS; + } + + // New cluster-based variables + float totalEnergy(0.); + float calo_iso(0.); + float dr(0.); + + unsigned int num_clusters(0); + const xAOD::CaloCluster* incluster; + std::vector<const xAOD::CaloCluster*> vClusters; + + TLorentzVector leadClusVec; + TLorentzVector subLeadClusVec; + TLorentzVector approxSubstructure4Vec; + double clusELead = -1111.0; + double clusESubLead = -1111.0; + + // loop over all clusters of the jet seed + xAOD::JetConstituentVector jcv = taujetseed->getConstituents(); + xAOD::JetConstituentVector::const_iterator nav_it = jcv.begin(); + xAOD::JetConstituentVector::const_iterator nav_itE = jcv.end(); + for (; nav_it != nav_itE; ++nav_it) { + ++num_clusters; + + incluster = dynamic_cast<const xAOD::CaloCluster*>( (*nav_it)->rawConstituent() ); + if (!incluster) continue; + + // save all clusters of jet seed + vClusters.push_back(incluster); + + // calc total energy + totalEnergy += incluster->e(); + + //apply Vertex correction on a temporary + TLorentzVector tempclusvec; + if (m_doVertexCorrection && pTau.vertexLink()) + tempclusvec = xAOD::CaloVertexedCluster(*incluster, (*pTau.vertexLink())->position()).p4(); + else + tempclusvec = xAOD::CaloVertexedCluster(*incluster).p4(); + + dr = Tau1P3PKineUtils::deltaR(pTau.eta(),pTau.phi(), tempclusvec.Eta(), tempclusvec.Phi()); + if (0.2 <= dr && dr < 0.4) + { + calo_iso += tempclusvec.Et(); + } + else if (dr < 0.2) + { + double clusEnergyBE = ( incluster->energyBE(0) + incluster->energyBE(1) + incluster->energyBE(2) ); + + if (clusEnergyBE > clusELead) + { + //change current leading cluster to subleading + clusESubLead = clusELead; + subLeadClusVec = leadClusVec; + + //set energy and 4-vector of leading cluster + clusELead = clusEnergyBE; + leadClusVec.SetPtEtaPhiM(clusELead/cosh(tempclusvec.Eta()), tempclusvec.Eta(), tempclusvec.Phi(), 0); + } + else if (clusEnergyBE > clusESubLead) + { + //set energy and 4-vector of subleading cluster only + clusESubLead = clusEnergyBE; + subLeadClusVec.SetPtEtaPhiM(clusESubLead/cosh(tempclusvec.Eta()), tempclusvec.Eta(), tempclusvec.Phi(), 0); + } + + } + + } + + if (clusELead > 0.) { + approxSubstructure4Vec += leadClusVec; + } + if (clusESubLead > 0.) { + approxSubstructure4Vec += subLeadClusVec; + } + + // now sort cluster by energy + AnalysisUtils::Sort::e(&vClusters); + + // determine energy sum of leading 2 and leading 3 clusters + float sum2LeadClusterE(0.); + float sum3LeadClusterE(0.); + std::vector<const xAOD::CaloCluster*>::const_iterator icluster(vClusters.begin()); + std::vector<const xAOD::CaloCluster*>::const_iterator icluster_end(vClusters.end()); + + for (; icluster != icluster_end && icluster != vClusters.begin() + 3; ++icluster) { + if (icluster < vClusters.begin() + 2) { + sum2LeadClusterE += (*icluster)->e(); + } + sum3LeadClusterE += (*icluster)->e(); + } + + //record variables + if (totalEnergy != 0) { + ATH_MSG_VERBOSE(" lead2ClusterEOverAllClusterE: " << sum2LeadClusterE / totalEnergy); + ATH_MSG_VERBOSE(" lead3ClusterEOverAllClusterE: " << sum3LeadClusterE / totalEnergy); + + pTau.setDetail(xAOD::TauJetParameters::lead2ClusterEOverAllClusterE, static_cast<float>(sum2LeadClusterE / totalEnergy) ); + pTau.setDetail(xAOD::TauJetParameters::lead3ClusterEOverAllClusterE, static_cast<float>(sum3LeadClusterE / totalEnergy) ); + } + + ATH_MSG_VERBOSE(" caloIso: " << calo_iso); + pTau.setDetail(xAOD::TauJetParameters::caloIso, static_cast<float>(calo_iso) ); + + + // calculate calorimeter energies in different layers + float PSSEnergy(0.); + float EMEnergy(0.); + float HADEnergy(0.); + icluster = vClusters.begin(); + for (; icluster != icluster_end; ++icluster) { + float clEnergy = (*icluster)->e(); + + //Calculate the fractions of energy in different calorimeter layers + const xAOD::CaloCluster *cl = *icluster; + float PreSampler = cl->eSample(CaloSampling::PreSamplerB) + cl->eSample(CaloSampling::PreSamplerE); + float EMLayer1 = cl->eSample(CaloSampling::EMB1) + cl->eSample(CaloSampling::EME1); + float EMLayer2 = cl->eSample(CaloSampling::EMB2) + cl->eSample(CaloSampling::EME2); + + float Energy = cl->rawE(); + float PSSF = Energy != 0 ? (PreSampler + EMLayer1) / Energy : 0; + float EM2F = Energy != 0 ? EMLayer2 / Energy : 0; + float EMF = PSSF + EM2F; + + PSSEnergy += PSSF * clEnergy; + EMEnergy += EMF * clEnergy; + HADEnergy += (Energy != 0) ? (1 - EMF) * clEnergy : 0; + } + + // calculate trk momentum + float trkSysMomentum(0.); + for (unsigned int i(0); i < pTau.nTracks(); ++i) { + trkSysMomentum += pTau.track(i)->pt() * cosh(pTau.track(i)->eta()); + + //adding the core tracks to the approximate substructure 4 vector + approxSubstructure4Vec += pTau.track(i)->p4(); + } + + // set new approximate energy flow variables for tau ID + pTau.setDetail(xAOD::TauJetParameters::ptRatioEflowApprox, static_cast<float>(approxSubstructure4Vec.Pt()/ pTau.detail<float>(xAOD::TauJetParameters::LC_TES_precalib)) ); + pTau.setDetail(xAOD::TauJetParameters::mEflowApprox, static_cast<float>(approxSubstructure4Vec.M()) ); + + + float fPSSFraction = (totalEnergy != 0) ? PSSEnergy / totalEnergy : DEFAULT; + float fChPIEMEOverCaloEME = (EMEnergy != 0) ? (trkSysMomentum - HADEnergy) / EMEnergy : DEFAULT; + float fEMPOverTrkSysP = DEFAULT; + if (pTau.nTracks() > 0) fEMPOverTrkSysP = (trkSysMomentum != 0) ? EMEnergy / trkSysMomentum : DEFAULT; + + pTau.setDetail(xAOD::TauJetParameters::PSSFraction, static_cast<float>(fPSSFraction)); + pTau.setDetail(xAOD::TauJetParameters::ChPiEMEOverCaloEME, static_cast<float>(fChPIEMEOverCaloEME)); + pTau.setDetail(xAOD::TauJetParameters::EMPOverTrkSysP, static_cast<float>(fEMPOverTrkSysP)); + + + // get primary vertex container + // CALO_ISO_CORRECTED + // JVF and PT_PILEUP + // jvf and sumPtTrk are now a vector and the old run1-type jvf value is stored in the 0-th element + // sumPtTrk is calculated wrt Vertices + + float jvf(0.0); + float sumPtTrk(0.0); + + // for tau trigger: JVF and sumPtTrack are not available + bool inTrigger = tauEventData()->inTrigger(); + + if (!inTrigger) + { + std::vector<float> sumPtTrkvec; + std::vector<float> jvfvec; + + // ToDo still need to check if the 500MeV threshold is correct + taujetseed->getAttribute(xAOD::JetAttribute::SumPtTrkPt500, sumPtTrkvec); + taujetseed->getAttribute(xAOD::JetAttribute::JVF, jvfvec); + + if (!jvfvec.empty() && !sumPtTrkvec.empty()) { + // ToDo need to check if first vertex is the vertex we want to use here! + jvf = jvfvec[0]; + sumPtTrk = sumPtTrkvec[0]; + } + else { + ATH_MSG_WARNING("jvf value vector and/or sumPtTrk vector returned from seed jet is empty!"); + } + } + + float pt_pileup = (1.0 - jvf) * sumPtTrk; + + const float max_pileup_correction = m_maxPileUpCorrection; + const float alpha = m_pileUpAlpha; + float pileup_correction = alpha * pt_pileup; + + ATH_MSG_VERBOSE(" --------------------------------------"); + ATH_MSG_VERBOSE(" Pile-up correction parameter"); + ATH_MSG_VERBOSE(" -> sumPtTrk: " << sumPtTrk); + ATH_MSG_VERBOSE(" -> jvf: " << jvf); + ATH_MSG_VERBOSE(" -> pt_pileup: " << pt_pileup); + ATH_MSG_VERBOSE(" -> alpha: " << alpha); + ATH_MSG_VERBOSE(" -> max pileup corr: " << max_pileup_correction); + + if (pileup_correction > max_pileup_correction) { + pileup_correction = max_pileup_correction; + } + const float calo_iso_corrected = calo_iso - pileup_correction; + + ATH_MSG_VERBOSE(" -> pileup corr: " << pileup_correction); + ATH_MSG_VERBOSE(" --------------------------------------"); + + //record variable + ATH_MSG_VERBOSE(" caloIsoCorrected: " << calo_iso_corrected); + pTau.setDetail(xAOD::TauJetParameters::caloIsoCorrected, static_cast<float>(calo_iso_corrected) ); + + // calculate dRMax + unsigned int numTrack(pTau.nTracks()); + if (numTrack > 0) { + float dRmin = -1 * -1111; + float dRmax = -1111; + float dR; + + for (unsigned int i(0); i < numTrack; ++i) { + if (pTau.track(i) == 0) continue; + dR = Tau1P3PKineUtils::deltaR( pTau.track(i)->eta(), pTau.track(i)->phi(), pTau.eta(), pTau.phi() ); + if (dRmin > dR) dRmin = dR; + if (dRmax < dR) dRmax = dR; + } + //record variable + ATH_MSG_VERBOSE(" dRmax: " << dRmax); + pTau.setDetail(xAOD::TauJetParameters::dRmax, static_cast<float>(dRmax) ); + } + + return StatusCode::SUCCESS; +} diff --git a/Reconstruction/tauRecTools/src/TauSubstructureVariables.h b/Reconstruction/tauRecTools/src/TauSubstructureVariables.h new file mode 100644 index 0000000000000000000000000000000000000000..f5038d6125017265f94ce28a9996e65ce9ee8cf9 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauSubstructureVariables.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUSUBSTRUCTUREBUILDER_H +#define TAUREC_TAUSUBSTRUCTUREBUILDER_H + +#include "tauRecTools/TauRecToolBase.h" + +/** + * @brief Calculate variables from the tau substructure. + * + * @author M. Trottier-McDonald + * @author Felix Friedrich + * + */ + +class TauSubstructureVariables : virtual public TauRecToolBase +{ + public: + + static const double DEFAULT; + + TauSubstructureVariables(const std::string& name); + ASG_TOOL_CLASS2(TauSubstructureVariables, TauRecToolBase, ITauToolBase); + + ~TauSubstructureVariables(); + + virtual StatusCode execute(xAOD::TauJet& pTau); + + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode eventInitialize(); + + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + + private: + /** Maximal pile up correction in GeV for a tau candidate. + * Used for the caloIso corrected variable. + */ + double m_maxPileUpCorrection; + double m_pileUpAlpha; //!< slope of the pileup correction + + /** + * enable cell origin correction + * eta and phi of the cells are corrected wrt to the origin of the tau vertex + */ + bool m_doVertexCorrection; + bool m_inAODmode; //!< don't update everything if running on AODs +}; + +#endif diff --git a/Reconstruction/tauRecTools/src/TauTestDump.cxx b/Reconstruction/tauRecTools/src/TauTestDump.cxx new file mode 100644 index 0000000000000000000000000000000000000000..1289173e2ccbfbf2a148439fbcb2c5374e615d80 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauTestDump.cxx @@ -0,0 +1,112 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauTestDump.cxx +// package: Reconstruction/tauRec +// authors: Felix Friedrich +// date: 2012-11-05 +// +//----------------------------------------------------------------------------- + +#include <GaudiKernel/IToolSvc.h> +#include <GaudiKernel/ListItem.h> + +#include "FourMomUtils/P4Helpers.h" +#include "FourMom/P4EEtaPhiM.h" +#include "CLHEP/Vector/LorentzVector.h" +#include "Particle/TrackParticle.h" + + +#include "tauRecTools/TauEventData.h" +//#include "tauEvent/TauCommonDetails.h" +//#include "tauEvent/TauPi0Details.h" +//#include "tauEvent/TauPi0Cluster.h" +#include "xAODTau/TauJet.h" + +//#include "tauEvent/TauJetParameters.h" + +#include "TauTestDump.h" + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- + +TauTestDump::TauTestDump(const std::string &name ) : +TauRecToolBase(name) { +} + +//----------------------------------------------------------------------------- +// Destructor +//----------------------------------------------------------------------------- + +TauTestDump::~TauTestDump() { +} + + +//----------------------------------------------------------------------------- +// Initializer +//----------------------------------------------------------------------------- + +StatusCode TauTestDump::initialize() { + return StatusCode::SUCCESS; +} + + +//----------------------------------------------------------------------------- +// Finalizer +//----------------------------------------------------------------------------- + +StatusCode TauTestDump::finalize() { + return StatusCode::SUCCESS; +} + + +//----------------------------------------------------------------------------- +// Execution +//----------------------------------------------------------------------------- +StatusCode TauTestDump::execute(xAOD::TauJet& pTau) { + + ATH_MSG_INFO("=== TAU TEST DUMP BEGIN ==================== "); + + ATH_MSG_INFO("Tau recorded with: pt="<< pTau.pt() <<", eta=" <<pTau.eta()<<", phi="<<pTau.phi()); + float tfFlightPathSig; + float ipSigLeadTrk; + pTau.detail(xAOD::TauJetParameters::ipSigLeadTrk, ipSigLeadTrk); + pTau.detail(xAOD::TauJetParameters::trFlightPathSig,tfFlightPathSig ); + ATH_MSG_INFO(" numTrack="<<pTau.nTracks() << ", tfFlightPathSig=" << tfFlightPathSig <<", ipSigLeadTrk=" << ipSigLeadTrk ); + + //stop here + return StatusCode::SUCCESS; + + /* Unreachable due to the above return statement. Disabled to shut coverity up. + if (pTau.nTracks() != 1) { + // Pi0 calculated only for 1p taus --> leave test case + ATH_MSG_INFO("Pi0 calculated only for 1p taus --> leave test case"); + return StatusCode::SUCCESS; + } + + // Default PFO pi0 + ATH_MSG_INFO("dumping pi0 standard"); + if (pTau.nPi0PFOs()>0) { + for (unsigned int i=0; i<pTau.nPi0PFOs();++i) ATH_MSG_INFO(pTau.pi0PFO(i)->e()<< " "); + } + else ATH_MSG_INFO("no pi0 cand"); + + // Cell-based PFO pi0 + ATH_MSG_INFO("dumping pi0 cell-based"); + if (pTau.nProtoPi0PFOs()>0) { + for (unsigned int i=0; i<pTau.nProtoPi0PFOs();++i) ATH_MSG_INFO(pTau.protoPi0PFO(i)->e()<< " "); + } + else ATH_MSG_INFO("no pi0 cand"); + + ATH_MSG_INFO("end dumping pi0"); + + ATH_MSG_INFO("=== TAU TEST DUMP END ==================== "); + + return StatusCode::SUCCESS; + */ +} + + diff --git a/Reconstruction/tauRecTools/src/TauTestDump.h b/Reconstruction/tauRecTools/src/TauTestDump.h new file mode 100644 index 0000000000000000000000000000000000000000..1256c97b7ce71469fc72153af8fef7e9921e4fa4 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauTestDump.h @@ -0,0 +1,38 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUTESTDUMP_H +#define TAUREC_TAUTESTDUMP_H + +#include "tauRecTools/TauRecToolBase.h" + + +/** + * @brief Tau Tool for developing, testing and debugging + * + * + * + * @author Felix Friedrich + */ + +class TauTestDump : virtual public TauRecToolBase { +public: + //----------------------------------------------------------------- + // Constructor and destructor + //----------------------------------------------------------------- + TauTestDump(const std::string& name); + ASG_TOOL_CLASS2(TauTestDump, TauRecToolBase, ITauToolBase); + ~TauTestDump(); + + virtual StatusCode initialize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode finalize(); + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + +}; + +#endif // TAUREC_TAUTESTDUMP_H diff --git a/Reconstruction/tauRecTools/src/TauTrackFinder.cxx b/Reconstruction/tauRecTools/src/TauTrackFinder.cxx new file mode 100644 index 0000000000000000000000000000000000000000..9ab9fa9621f3d231ff9238c7081e533d0ffe7750 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauTrackFinder.cxx @@ -0,0 +1,640 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TrkToolInterfaces/ITrackSelectorTool.h" +#include "TrkParametersIdentificationHelpers/TrackParametersIdHelper.h" +#include "RecoToolInterfaces/IParticleCaloExtensionTool.h" + +#include "xAODTau/TauJet.h" +#include "xAODTau/TauJetContainer.h" + +#include "TauTrackFinder.h" +#include "tauRecTools/KineUtils.h" +#include "tauRecTools/TrackSort.h" + + +TauTrackFinder::TauTrackFinder(const std::string& name ) : + TauRecToolBase(name), + m_caloExtensionTool("Trk::ParticleCaloExtensionTool/ParticleCaloExtensionTool"), + m_trackSelectorTool_tau(""), + m_trackToVertexTool("Reco::TrackToVertex"), + m_z0maxDelta(1000), + m_applyZ0cut(false), + m_storeInOtherTrks(true), + m_bypassSelector(false), + m_bypassExtrapolator(false) +{ + declareProperty("MaxJetDrTau", m_maxJetDr_tau = 0.2); + declareProperty("MaxJetDrWide", m_maxJetDr_wide = 0.4); + declareProperty("TrackSelectorToolTau", m_trackSelectorTool_tau); + declareProperty("TrackParticleContainer", m_inputTrackParticleContainerName = "InDetTrackParticles"); + declareProperty("ParticleCaloExtensionTool", m_caloExtensionTool ); + declareProperty("TrackToVertexTool",m_trackToVertexTool); + declareProperty("maxDeltaZ0wrtLeadTrk", m_z0maxDelta); + declareProperty("removeTracksOutsideZ0wrtLeadTrk", m_applyZ0cut); + declareProperty("StoreRemovedCoreWideTracksInOtherTracks", m_storeInOtherTrks = true); + declareProperty("BypassSelector", m_bypassSelector = false); + declareProperty("BypassExtrapolator", m_bypassExtrapolator = false); +} + +TauTrackFinder::~TauTrackFinder() { +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +StatusCode TauTrackFinder::initialize() { + + // Get the TrackSelectorTool + if (!retrieveTool(m_trackSelectorTool_tau)) return StatusCode::FAILURE; + + // Get the TJVA + if (!retrieveTool(m_trackToVertexTool)) return StatusCode::FAILURE; + if (!retrieveTool(m_caloExtensionTool)) return StatusCode::FAILURE; + + return StatusCode::SUCCESS; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +StatusCode TauTrackFinder::finalize() { + return StatusCode::SUCCESS; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +StatusCode TauTrackFinder::eventInitialize() { + return StatusCode::SUCCESS; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +StatusCode TauTrackFinder::eventFinalize() { + return StatusCode::SUCCESS; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +StatusCode TauTrackFinder::execute(xAOD::TauJet& pTau) { + + ATH_MSG_VERBOSE("TauTrackFinder Executing"); + + StatusCode sc; + // get the track particle container from StoreGate + const xAOD::TrackParticleContainer* trackParticleCont = 0; + + //for tau trigger + bool inTrigger = tauEventData()->inTrigger(); + if (inTrigger) sc = tauEventData()->getObject( "TrackContainer", trackParticleCont ); + + if( !inTrigger || !trackParticleCont || sc.isFailure() ) { + // try standard + if (!openContainer(trackParticleCont, m_inputTrackParticleContainerName)) { + if (!inTrigger) return StatusCode::FAILURE; // in offline we don't reconstruct tau candidates without having a track container + else return StatusCode::SUCCESS; // we don't want stop trigger if there is no track container + } + } + + std::vector<const xAOD::TrackParticle*> tauTracks; + std::vector<const xAOD::TrackParticle*> wideTracks; + std::vector<const xAOD::TrackParticle*> otherTracks; + + const xAOD::Vertex* pVertex = pTau.vertexLink()!=0 ? (*pTau.vertexLink()) : NULL; + // retrieve tracks wrt a vertex + // as a vertex is used: tau origin / PV / beamspot / 0,0,0 (in this order, depending on availability) + getTauTracksFromPV(pTau, *trackParticleCont, pVertex, tauTracks, wideTracks, otherTracks); + + + this->resetDeltaZ0Cache(); + // remove core and wide tracks outside a maximal delta z0 wrt lead core track + if (m_applyZ0cut) { + this->removeOffsideTracksWrtLeadTrk(tauTracks, wideTracks, otherTracks, pVertex, m_z0maxDelta); + } + + //clear tracks first (needed for "rerun mode" if called on AODs again) + pTau.clearTrackLinks(); + pTau.clearWideTrackLinks(); + pTau.clearOtherTrackLinks(); + + bool alreadyUsed = false; + //check for tracks used in multiple taus + xAOD::TauJetContainer* pContainer = tauEventData()->xAODTauContainer; + if(pContainer==0){ + pContainer = static_cast<xAOD::TauJetContainer*> (pTau.container()); + } + if(pContainer==0) { + ATH_MSG_FATAL("Can't find tau Container"); + return StatusCode::FAILURE; + } + + + for (std::vector<const xAOD::TrackParticle*>::iterator track_it = tauTracks.begin(); track_it != tauTracks.end() ;) + { + alreadyUsed = false; + + //loop over all up-to-now reconstructed tau candidates + xAOD::TauJetContainer::const_iterator tau_it = pContainer->begin(); + xAOD::TauJetContainer::const_iterator tau_end = pContainer->end(); + for( ; tau_it != tau_end; tau_it++ ) + { + if( (*tau_it) == &pTau ) continue; + //loop over core tracks + for (unsigned int j = 0; j < (*tau_it)->nTracks(); ++j) + { + if ((*track_it) == (*tau_it)->track(j)) + { + ATH_MSG_WARNING("Found a track that is identical with a track already associated to another tau. Will not add this track to more than one tau candidate"); + alreadyUsed = true; + } + } + } + + //if this track has already been used by another tau, don't associate it to this new one + if (alreadyUsed) track_it = tauTracks.erase(track_it); + else ++track_it; + } + + + // associated track to tau candidate and calculate charge + float charge = 0; + for (unsigned int i = 0; i < tauTracks.size(); ++i) { + const xAOD::TrackParticle* trackParticle = tauTracks.at(i); + + ATH_MSG_VERBOSE(name() << " adding core track nr: " << i + << " eta " << trackParticle->eta() + << " phi " << trackParticle->phi() + ); + charge += trackParticle->charge(); + ElementLink<xAOD::TrackParticleContainer> linkToTrackParticle; + linkToTrackParticle.toContainedElement(*trackParticleCont, trackParticle); + pTau.addTrackLink(linkToTrackParticle); + ATH_MSG_VERBOSE(name() << " added core track nr: " << i + << " eta " << pTau.track(i)->eta() + << " phi " << pTau.track(i)->phi() + ); + } + // set the charge, which is defined by the core tau tracks only + pTau.setCharge(charge); + + /// FIXME hide the logic to create element links inside xAODTau + /// was + // for (unsigned int i = 0; i < wideTracks.size(); ++i) + // details->addSeedCalo_wideTrk(trackParticleCont, wideTracks.at(i)); + for (unsigned int i = 0; i < wideTracks.size(); ++i) { + const xAOD::TrackParticle* trackParticle = wideTracks.at(i); + + ATH_MSG_VERBOSE(name() << " adding wide track nr: " << i + << " eta " << trackParticle->eta() + << " phi " << trackParticle->phi() + ); + ElementLink<xAOD::TrackParticleContainer> linkToTrackParticle; + linkToTrackParticle.toContainedElement(*trackParticleCont, trackParticle); + pTau.addWideTrackLink(linkToTrackParticle); + ATH_MSG_VERBOSE(name() << " added wide track nr: " << i + << " eta " << pTau.wideTrack(i)->eta() + << " phi " << pTau.wideTrack(i)->phi() + ); + } + + /// was + // for (unsigned int i = 0; i < otherTracks.size(); ++i) + // details->addOtherTrk(trackParticleCont, otherTracks.at(i)); + for (unsigned int i = 0; i < otherTracks.size(); ++i) { + const xAOD::TrackParticle* trackParticle = otherTracks.at(i); + + ATH_MSG_VERBOSE(name() << " adding other track nr: " << i + << " eta " << trackParticle->eta() + << " phi " << trackParticle->phi() + ); + ElementLink<xAOD::TrackParticleContainer> linkToTrackParticle; + linkToTrackParticle.toContainedElement(*trackParticleCont, trackParticle); + pTau.addOtherTrackLink(linkToTrackParticle); + ATH_MSG_VERBOSE(name() << " added other track nr: " << i + << " eta " << pTau.otherTrack(i)->eta() + << " phi " << pTau.otherTrack(i)->phi() + ); + } + + + ATH_MSG_DEBUG("numTrack: " << "/" << pTau.nTracks()); + ATH_MSG_DEBUG("charge: " << "/" << pTau.charge()); + + // extrapolate core tracks to calorimeter surface + // store information only in ExtraDetailsContainer + + if(!m_bypassExtrapolator) + { + sc = extrapolateToCaloSurface(pTau); + if (sc.isFailure() && !sc.isRecoverable()) { + ATH_MSG_ERROR("couldn't extrapolate tracks to calo surface"); + return StatusCode::FAILURE; + } + } + + return StatusCode::SUCCESS; +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +TauTrackFinder::TauTrackType TauTrackFinder::tauTrackType( const xAOD::TauJet& pTau, + const xAOD::TrackParticle& trackParticle, + const xAOD::Vertex* primaryVertex) +{ + //ATH_MSG_VERBOSE("tau axis:" << pTau.hlv().perp()<< " " << pTau.hlv().eta() << " " << pTau.hlv().phi() << " " << pTau.hlv().e() ); + double dR = Tau1P3PKineUtils::deltaR(pTau.eta(),pTau.phi(),trackParticle.eta(),trackParticle.phi()); + + if (dR > m_maxJetDr_wide) return NotTauTrack; + + bool goodTrack = true; + if(!m_bypassSelector) + goodTrack = m_trackSelectorTool_tau->decision(trackParticle, primaryVertex); + + if (goodTrack) { + if (dR > m_maxJetDr_tau) + return TauTrackWide; + else + return TauTrackCore; + } else + return TauTrackOther; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +void TauTrackFinder::getTauTracksFromPV( const xAOD::TauJet& pTau, + const xAOD::TrackParticleContainer& trackParticleCont, + const xAOD::Vertex* primaryVertex, + std::vector<const xAOD::TrackParticle*> &tauTracks, + std::vector<const xAOD::TrackParticle*> &wideTracks, + std::vector<const xAOD::TrackParticle*> &otherTracks) +{ + for (xAOD::TrackParticleContainer::const_iterator tpcItr = trackParticleCont.begin(); tpcItr != trackParticleCont.end(); ++tpcItr) { + const xAOD::TrackParticle *trackParticle = *tpcItr; + + TauTrackType type = tauTrackType(pTau, *trackParticle, primaryVertex); + + if (type == TauTrackCore) + tauTracks.push_back(trackParticle); + else if (type == TauTrackWide) + wideTracks.push_back(trackParticle); + else if (type == TauTrackOther) + otherTracks.push_back(trackParticle); + + } + std::sort(tauTracks.begin(), tauTracks.end(), TrackSort()); + std::sort(wideTracks.begin(), wideTracks.end(), TrackSort()); + std::sort(otherTracks.begin(), otherTracks.end(), TrackSort()); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +StatusCode TauTrackFinder::extrapolateToCaloSurface(xAOD::TauJet& pTau) { + + //apparently unused: const int numOfsampEM = 4; + + Trk::TrackParametersIdHelper parsIdHelper; + + for (unsigned int itr = 0; itr < 10 && itr < pTau.nTracks(); ++itr) { + + const xAOD::TrackParticle *orgTrack = pTau.track(itr); + + if( !orgTrack ) continue; + + // get the extrapolation into the calo + const Trk::CaloExtension* caloExtension = 0; + if( !m_caloExtensionTool->caloExtension(*orgTrack,caloExtension) || caloExtension->caloLayerIntersections().empty() ) continue; + + // loop over calo layers + for( auto cur = caloExtension->caloLayerIntersections().begin(); cur != caloExtension->caloLayerIntersections().end() ; ++cur ){ + + // only use entry layer + if( !parsIdHelper.isEntryToVolume((*cur)->cIdentifier()) ) continue; + + CaloSampling::CaloSample sample = parsIdHelper.caloSample((*cur)->cIdentifier()); + + if( sample == CaloSampling::EME1 || sample == CaloSampling::EMB1 ){ + pTau.setTrackEtaStrip( itr, (*cur)->position().eta() ); + pTau.setTrackPhiStrip( itr, (*cur)->position().phi() ); + break; + } + } + // //--------------------------------------------------------------------- + // // Extrapolate to all layers + // //--------------------------------------------------------------------- + // const DataVector< const Trk::TrackParameters >* pTrk = m_trackToCalo->getParametersInCalo(*orgTrack, Trk::pion, Trk::alongMomentum); //FIXME + + // //--------------------------------------------------------------------- + // // Calculate eta, phi impact point at calorimeter layers EM 0,1,2,3 + // //--------------------------------------------------------------------- + // double eta_extrapol[4]; + // double phi_extrapol[4]; + + // for (int i = 0; i < numOfsampEM; ++i) { + // eta_extrapol[i] = -11111.; + // phi_extrapol[i] = -11111.; + // } + + // // XXX commenting this out as long as it's not clear whether these variables will be stored in xAOD::TauJet + // // if (pTrk && (*pTrk)[IExtrapolateToCaloTool::PreSampler]) { + // // eta_extrapol[0] = (*pTrk)[IExtrapolateToCaloTool::PreSampler]->position().eta(); + // // phi_extrapol[0] = (*pTrk)[IExtrapolateToCaloTool::PreSampler]->position().phi(); + // // } + + // if (pTrk && (*pTrk)[IExtrapolateToCaloTool::Strips]) { + // eta_extrapol[1] = (*pTrk)[IExtrapolateToCaloTool::Strips]->position().eta(); + // phi_extrapol[1] = (*pTrk)[IExtrapolateToCaloTool::Strips]->position().phi(); + + // if (msgLvl(MSG::VERBOSE)) + // { //only if desired msg level is requested + // ATH_MSG_VERBOSE(name() << " extrapolation in strip layer : " + // << " track nr " << itr + // << " impact point eta " << eta_extrapol[1] + // << " impact point phi " << phi_extrapol[1] + // ); + // } + + // pTau.setTrackEtaStrip( itr, (*pTrk)[IExtrapolateToCaloTool::Strips]->position().eta() ); + // pTau.setTrackPhiStrip( itr, (*pTrk)[IExtrapolateToCaloTool::Strips]->position().phi() ); + + // if (msgLvl(MSG::VERBOSE)) + // { //only if desired msg level is requested + // ATH_MSG_VERBOSE(name() << " extrapolation in strip layer stored in tau : " + // << " track nr " << itr + // << " impact point eta " << pTau.trackEtaStrip(itr) + // << " impact point phi " << pTau.trackPhiStrip(itr) + // ); + // } + + // } + + // XXX commenting this out as long as it's not clear whether these variables will be stored in xAOD::TauJet + // if (pTrk && (*pTrk)[IExtrapolateToCaloTool::Middle]) { + // eta_extrapol[2] = (*pTrk)[IExtrapolateToCaloTool::Middle]->position().eta(); + // phi_extrapol[2] = (*pTrk)[IExtrapolateToCaloTool::Middle]->position().phi(); + // } + + // if (pTrk && (*pTrk)[IExtrapolateToCaloTool::Back]) { + // eta_extrapol[3] = (*pTrk)[IExtrapolateToCaloTool::Back]->position().eta(); + // phi_extrapol[3] = (*pTrk)[IExtrapolateToCaloTool::Back]->position().phi(); + // } + + + // for (int i = 0; i < numOfsampEM; ++i) { + // pExtraDetails->etaLooseTrkCaloSamp()[itr][i] = eta_extrapol[i]; + // pExtraDetails->phiLooseTrkCaloSamp()[itr][i] = phi_extrapol[i]; + // } + + // // in the past this was filled by tau1P3PTrackMatchCalo + // for (int i = 0; i < numOfsampEM; ++i) { + // pExtraDetails->etaTrkCaloSamp()[itr][i] = eta_extrapol[i]; + // pExtraDetails->phiTrkCaloSamp()[itr][i] = phi_extrapol[i]; + // } + + //if (pTrk) delete pTrk; + + // XXX commenting this out as long as it's not clear whether these variables will be stored in xAOD::TauJet + // if (msgLvl(MSG::VERBOSE)) { //only if desired msg level is requested + // for (int i = 0; i < numOfsampEM; ++i) { + // ATH_MSG_VERBOSE(name() << " extrapolation for loose trk in samp : " << i + // << " track nr " << itr + // << " impact point eta " << pExtraDetails->etaLooseTrkCaloSamp()[itr][i] + // << " impact point phi " << pExtraDetails->phiLooseTrkCaloSamp()[itr][i] + // ); + // ATH_MSG_VERBOSE(name() << " extrapolation in samp : " << i + // << " track nr " << itr + // << " impact point eta " << pExtraDetails->etaTrkCaloSamp()[itr][i] + // << " impact point phi " << pExtraDetails->phiTrkCaloSamp()[itr][i] + // ); + // } + // } + + } + + return StatusCode::SUCCESS; + +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +void TauTrackFinder::removeOffsideTracksWrtLeadTrk(std::vector<const Rec::TrackParticle*> &tauTracks, + std::vector<const Rec::TrackParticle*> &wideTracks, + std::vector<const Rec::TrackParticle*> &otherTracks, + const Trk::RecVertex* tauOrigin, + double maxDeltaZ0) +{ + float MAX=1e5; + this->resetDeltaZ0Cache(); + + // need at least one core track to have a leading trk to compare with + if (tauTracks.size()<1) return; + + //check if position is available for origin + /** FIXME: This causes compilation error after eigen migration + if (tauOrigin) + if (!tauOrigin->position()) + tauOrigin = 0; + */ + + // get lead trk parameters + const Rec::TrackParticle *leadTrack = tauTracks.at(0); + float z0_leadTrk = getZ0(leadTrack, tauOrigin); + + if (z0_leadTrk > MAX-1) return; // bad lead trk -> do nothing + + ATH_MSG_VERBOSE("before z0 cut: #coreTracks=" << tauTracks.size() << ", #wideTracks=" << wideTracks.size() << ", #otherTracks=" << otherTracks.size()); + + std::vector<const Rec::TrackParticle*>::iterator itr; + + // check core tracks + // skip leading track, because it is the reference + itr = tauTracks.begin()+1; + while (itr!=tauTracks.end()) { + float z0 = getZ0(*itr, tauOrigin); + float deltaZ0=z0 - z0_leadTrk; + + ATH_MSG_VERBOSE("core Trks: deltaZ0= " << deltaZ0); + m_vDeltaZ0coreTrks.push_back(deltaZ0); + + if ( fabs(deltaZ0) < maxDeltaZ0 ) {++itr;} + else { + if (m_storeInOtherTrks) otherTracks.push_back(*itr); + itr = tauTracks.erase(itr); //remove from core track collection + } + } + + // check wide tracks + itr = wideTracks.begin(); + while (itr!=wideTracks.end()) { + float z0 = getZ0(*itr, tauOrigin); + float deltaZ0=z0 - z0_leadTrk; + + ATH_MSG_VERBOSE("wide Trks: deltaZ0= " << deltaZ0); + m_vDeltaZ0wideTrks.push_back(deltaZ0); + + if ( fabs(deltaZ0) < maxDeltaZ0 ) { ++itr; } + else { + if (m_storeInOtherTrks) otherTracks.push_back(*itr); + itr = wideTracks.erase(itr); //remove from wide track collection + } + } + + ATH_MSG_VERBOSE("after z0 cut: #coreTracks=" << tauTracks.size() << ", #wideTracks=" << wideTracks.size() << ", #otherTracks=" << otherTracks.size()); + + // sort again + std::sort(tauTracks.begin(), tauTracks.end(), TrackSort()); + std::sort(wideTracks.begin(), wideTracks.end(), TrackSort()); + std::sort(otherTracks.begin(), otherTracks.end(), TrackSort()); +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +void TauTrackFinder::removeOffsideTracksWrtLeadTrk(std::vector<const xAOD::TrackParticle*> &tauTracks, + std::vector<const xAOD::TrackParticle*> &wideTracks, + std::vector<const xAOD::TrackParticle*> &otherTracks, + const xAOD::Vertex* tauOrigin, + double maxDeltaZ0) +{ + float MAX=1e5; + this->resetDeltaZ0Cache(); + + // need at least one core track to have a leading trk to compare with + if (tauTracks.size()<1) return; + + //check if position is available for origin + /** FIXME: This causes compilation error after eigen migration + if (tauOrigin) + if (!tauOrigin->position()) + tauOrigin = 0; + */ + + // get lead trk parameters + const xAOD::TrackParticle *leadTrack = tauTracks.at(0); + float z0_leadTrk = getZ0(leadTrack, tauOrigin); + + if (z0_leadTrk > MAX-1) return; // bad lead trk -> do nothing + + ATH_MSG_VERBOSE("before z0 cut: #coreTracks=" << tauTracks.size() << ", #wideTracks=" << wideTracks.size() << ", #otherTracks=" << otherTracks.size()); + + std::vector<const xAOD::TrackParticle*>::iterator itr; + + // check core tracks + // skip leading track, because it is the reference + itr = tauTracks.begin()+1; + while (itr!=tauTracks.end()) { + float z0 = getZ0(*itr, tauOrigin); + float deltaZ0=z0 - z0_leadTrk; + + ATH_MSG_VERBOSE("core Trks: deltaZ0= " << deltaZ0); + m_vDeltaZ0coreTrks.push_back(deltaZ0); + + if ( fabs(deltaZ0) < maxDeltaZ0 ) {++itr;} + else { + if (m_storeInOtherTrks) otherTracks.push_back(*itr); + itr = tauTracks.erase(itr); //remove from core track collection + } + } + + // check wide tracks + itr = wideTracks.begin(); + while (itr!=wideTracks.end()) { + float z0 = getZ0(*itr, tauOrigin); + float deltaZ0=z0 - z0_leadTrk; + + ATH_MSG_VERBOSE("wide Trks: deltaZ0= " << deltaZ0); + m_vDeltaZ0wideTrks.push_back(deltaZ0); + + if ( fabs(deltaZ0) < maxDeltaZ0 ) { ++itr; } + else { + if (m_storeInOtherTrks) otherTracks.push_back(*itr); + itr = wideTracks.erase(itr); //remove from wide track collection + } + } + + ATH_MSG_VERBOSE("after z0 cut: #coreTracks=" << tauTracks.size() << ", #wideTracks=" << wideTracks.size() << ", #otherTracks=" << otherTracks.size()); + + // sort again + std::sort(tauTracks.begin(), tauTracks.end(), TrackSort()); + std::sort(wideTracks.begin(), wideTracks.end(), TrackSort()); + std::sort(otherTracks.begin(), otherTracks.end(), TrackSort()); +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +float TauTrackFinder::getZ0(const Rec::TrackParticle* track, const Trk::RecVertex* vertex) +{ + float MAX=1e5; + + if (!track) return MAX; + if (!track->measuredPerigee()->covariance()) { + ATH_MSG_WARNING("Bad track; can't find perigee at vertex."); + return MAX; + } + + const Trk::Perigee* perigee = 0; + if (vertex) perigee = m_trackToVertexTool->perigeeAtVertex(*track, vertex->position()); + else perigee = m_trackToVertexTool->perigeeAtVertex(*track); //will use beamspot or 0,0,0 instead + + if (!perigee) { + ATH_MSG_WARNING("Bad track; can't find perigee at vertex."); + return MAX; + } + + float z0 = perigee->parameters()[Trk::z0]; + + delete perigee; //cleanup necessary to prevent mem leak + + return z0; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +float TauTrackFinder::getZ0(const xAOD::TrackParticle* track, const xAOD::Vertex* vertex) +{ + float MAX=1e5; + + if (!track) return MAX; + + const Trk::Perigee* perigee = 0; + if (vertex) perigee = m_trackToVertexTool->perigeeAtVertex(*track, vertex->position()); + else perigee = m_trackToVertexTool->perigeeAtVertex(*track); //will use beamspot or 0,0,0 instead + + if (!perigee) { + ATH_MSG_WARNING("Bad track; can't find perigee at vertex."); + return MAX; + } + + float z0 = perigee->parameters()[Trk::z0]; + + delete perigee; //cleanup necessary to prevent mem leak + + return z0; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +void TauTrackFinder::getDeltaZ0Values(std::vector<float>& vDeltaZ0coreTrks, std::vector<float>& vDeltaZ0wideTrks) +{ + vDeltaZ0coreTrks.clear(); + vDeltaZ0coreTrks = m_vDeltaZ0coreTrks; + + vDeltaZ0wideTrks.clear(); + vDeltaZ0wideTrks = m_vDeltaZ0wideTrks; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +void TauTrackFinder::resetDeltaZ0Cache() +{ + m_vDeltaZ0coreTrks.clear(); + m_vDeltaZ0wideTrks.clear(); +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// Helpers +template <class T> +bool TauTrackFinder::openContainer(T* &container, std::string containerName, bool printFATAL) { + StatusCode sc = evtStore()->retrieve(container, containerName); + if (sc.isFailure() || !container) { + if (printFATAL) ATH_MSG_FATAL("Container (" << containerName << ") not found in StoreGate"); + return 0; + } + return container; +} + +template <class T> +bool TauTrackFinder::retrieveTool(T & tool) { + if (tool.retrieve().isFailure()) { + ATH_MSG_FATAL("Failed to retrieve tool " << tool); + return false; + } else { + ATH_MSG_VERBOSE("Retrieved tool " << tool); + } + return true; +} diff --git a/Reconstruction/tauRecTools/src/TauTrackFinder.h b/Reconstruction/tauRecTools/src/TauTrackFinder.h new file mode 100644 index 0000000000000000000000000000000000000000..e6ad1425b930618c48a9a95dcd3db9e372015347 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauTrackFinder.h @@ -0,0 +1,154 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUTRACKFINDER_H +#define TAUREC_TAUTRACKFINDER_H + +#include "tauRecTools/TauRecToolBase.h" +#include "GaudiKernel/ToolHandle.h" +#include "ITrackToVertex/ITrackToVertex.h" + +#include "xAODTracking/Vertex.h" +#include "xAODTracking/TrackParticle.h" +#include "xAODTracking/TrackParticleContainer.h" + +#include "VxVertex/RecVertex.h" + +namespace Trk { + class ITrackSelectorTool; + class IParticleCaloExtensionTool; +} + +///////////////////////////////////////////////////////////////////////////// + +/** + * @brief Associate tracks to the tau candidate. + * + * The tracks have to pass dedicated quality criteria and have to + * match to a primary vertex consistent with the tau origin. + * + * @author KG Tan <Kong.Guan.Tan@cern.ch> + * @author Felix Friedrich + */ + +class TauTrackFinder : virtual public TauRecToolBase { +public: + //------------------------------------------------------------- + //! Constructor and Destructor + //------------------------------------------------------------- + TauTrackFinder(const std::string& name); + ASG_TOOL_CLASS2(TauTrackFinder, TauRecToolBase, ITauToolBase); + ~TauTrackFinder(); + + //------------------------------------------------------------- + //! Enumerator defining type of tau track + //------------------------------------------------------------- + enum TauTrackType + { + TauTrackCore = 0, + TauTrackWide = 1, + TauTrackOther = 2, + NotTauTrack = 3 + }; + + //------------------------------------------------------------- + //! Algorithm functions + //------------------------------------------------------------- + virtual StatusCode initialize(); + virtual StatusCode eventInitialize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode eventFinalize(); + virtual StatusCode finalize(); + + virtual void print() const { } + + //------------------------------------------------------------- + //! Extrapolate track eta and phi to the calorimeter middle surface + //------------------------------------------------------------- + StatusCode extrapolateToCaloSurface(xAOD::TauJet& pTau); + + TauTrackType tauTrackType( const xAOD::TauJet& tauJet, + const xAOD::TrackParticle& trackParticle, + const xAOD::Vertex* primaryVertex); + + void getTauTracksFromPV( const xAOD::TauJet& tauJet, + const xAOD::TrackParticleContainer& trackParticleCont, + const xAOD::Vertex* primaryVertex, + std::vector<const xAOD::TrackParticle*> &tauTracks, + std::vector<const xAOD::TrackParticle*> &wideTracks, + std::vector<const xAOD::TrackParticle*> &otherTracks); + + // old style AOD version + void removeOffsideTracksWrtLeadTrk(std::vector<const Rec::TrackParticle*> &tauTracks, + std::vector<const Rec::TrackParticle*> &wideTracks, + std::vector<const Rec::TrackParticle*> &otherTracks, + const Trk::RecVertex* tauOrigin, + double maxDeltaZ0); + + // new xAOD version + void removeOffsideTracksWrtLeadTrk(std::vector<const xAOD::TrackParticle*> &tauTracks, + std::vector<const xAOD::TrackParticle*> &wideTracks, + std::vector<const xAOD::TrackParticle*> &otherTracks, + const xAOD::Vertex* tauOrigin, + double maxDeltaZ0); + + void getDeltaZ0Values(std::vector<float>& vDeltaZ0coreTrks, std::vector<float>& vDeltaZ0wideTrks); + void resetDeltaZ0Cache(); + +private: + //------------------------------------------------------------- + //! Some internally used functions + //------------------------------------------------------------- + float getZ0(const Rec::TrackParticle* track, const Trk::RecVertex* vertex); //AOD version + float getZ0(const xAOD::TrackParticle* track, const xAOD::Vertex* vertex); //xAOD version + +private: + //------------------------------------------------------------- + //! Storegate names of input containers and output containers + //------------------------------------------------------------- + std::string m_inputTauJetContainerName; + std::string m_inputTrackParticleContainerName; + std::string m_inputPrimaryVertexContainerName; + + //------------------------------------------------------------- + //! tools + //------------------------------------------------------------- + ToolHandle< Trk::IParticleCaloExtensionTool > m_caloExtensionTool; + ToolHandle<Trk::ITrackSelectorTool> m_trackSelectorTool_tau; + ToolHandle<Reco::ITrackToVertex> m_trackToVertexTool; + + //------------------------------------------------------------- + //! Input parameters for algorithm + //------------------------------------------------------------- + double m_maxJetDr_tau; + double m_maxJetDr_wide; + + //------------------------------------------------------------- + // z0 cuts + //------------------------------------------------------------- + float m_z0maxDelta; + bool m_applyZ0cut; + bool m_storeInOtherTrks; + std::vector<float> m_vDeltaZ0coreTrks; + std::vector<float> m_vDeltaZ0wideTrks; + + //------------------------------------------------------------- + // Bypass TrackSelectorTool / Extrapolation + //------------------------------------------------------------- + + bool m_bypassSelector; + bool m_bypassExtrapolator; + + //------------------------------------------------------------- + //! Convenience functions to handle storegate objects + //------------------------------------------------------------- + template <class T> + bool openContainer(T* &container, std::string containerName, bool printFATAL=false); + + template <class T> + bool retrieveTool(T &tool); + +}; + +#endif diff --git a/Reconstruction/tauRecTools/src/TauVertexFinder.cxx b/Reconstruction/tauRecTools/src/TauVertexFinder.cxx new file mode 100644 index 0000000000000000000000000000000000000000..237f302cb852466868c14d4f53ba906add79bfc3 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauVertexFinder.cxx @@ -0,0 +1,211 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TauVertexFinder.h" + +#include "VxVertex/RecVertex.h" +#include "VxVertex/VxCandidate.h" + +#include "xAODTracking/VertexContainer.h" +#include "xAODTracking/Vertex.h" + +#include "xAODTau/TauJetContainer.h" +#include "xAODTau/TauJetAuxContainer.h" +#include "xAODTau/TauJet.h" + +TauVertexFinder::TauVertexFinder(const std::string& name ) : +TauRecToolBase(name), +m_printMissingContainerINFO(true), +m_maxJVF(-100.), +m_assocTracksName(""), +m_trackVertexAssocName("") +{ + declareProperty("UseTJVA", m_useTJVA=true); + declareProperty("PrimaryVertexContainer", m_inputPrimaryVertexContainerName = "PrimaryVertices"); + declareProperty("AssociatedTracks",m_assocTracksName); + declareProperty("TrackVertexAssociation",m_trackVertexAssocName); +} + +TauVertexFinder::~TauVertexFinder() { +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +StatusCode TauVertexFinder::initialize() { + if (m_useTJVA) ATH_MSG_INFO("using TJVA to determine tau vertex"); + return StatusCode::SUCCESS; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +StatusCode TauVertexFinder::finalize() { + return StatusCode::SUCCESS; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +StatusCode TauVertexFinder::eventInitialize() { + return StatusCode::SUCCESS; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +StatusCode TauVertexFinder::eventFinalize() { + return StatusCode::SUCCESS; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +StatusCode TauVertexFinder::execute(xAOD::TauJet& pTau) { + + // get the primary vertex container from StoreGate + //do it here because of tau trigger + const xAOD::VertexContainer* vxContainer = 0; + const xAOD::Vertex* primaryVertex = 0; + + StatusCode sc; + //for tau trigger + sc = tauEventData()->getObject("VxPrimaryCandidate", vxContainer); + + if (sc.isFailure() || !vxContainer) { //not in trigger mode or no vxContainer was set by trigger + ATH_MSG_DEBUG("no VxPrimaryCandidateContainer for trigger -> try standard way"); + if (!openContainer(vxContainer, m_inputPrimaryVertexContainerName)) { + if (m_printMissingContainerINFO) { + ATH_MSG_INFO(m_inputPrimaryVertexContainerName << " container not found --> skip TauVertexFinder (no further info)"); + m_printMissingContainerINFO=false; + } + return StatusCode::SUCCESS; + } + + // find default PrimaryVertex (needed if TJVA is switched off or fails) + // see: https://twiki.cern.ch/twiki/bin/viewauth/AtlasProtected/VertexReselectionOnAOD + // code adapted from + // https://svnweb.cern.ch/trac/atlasoff/browser/Tracking/TrkEvent/VxVertex/trunk/VxVertex/PrimaryVertexSelector.h + if (vxContainer->size()>0) { + // simple loop through and get the primary vertex + xAOD::VertexContainer::const_iterator vxIter = vxContainer->begin(); + xAOD::VertexContainer::const_iterator vxIterEnd = vxContainer->end(); + for ( size_t ivtx = 0; vxIter != vxIterEnd; ++vxIter, ++ivtx ){ + // the first and only primary vertex candidate is picked + if ( (*vxIter)->vertexType() == xAOD::VxType::PriVtx){ + primaryVertex = (*vxIter); + break; + } + } + } + } + else { // trigger mode + // find default PrimaryVertex (highest sum pt^2) + if (vxContainer->size()>0) primaryVertex = (*vxContainer)[0]; + } + + ATH_MSG_VERBOSE("size of VxPrimaryContainer is: " << vxContainer->size() ); + + // associate vertex to tau + if (primaryVertex) pTau.setVertex(vxContainer, primaryVertex); + + //stop here if TJVA is disabled or vertex container is empty + if (!m_useTJVA || vxContainer->size()==0) return StatusCode::SUCCESS; + + // try to find new PV with TJVA + ATH_MSG_DEBUG("TJVA enabled -> try to find new PV for the tau candidate"); + + ElementLink<xAOD::VertexContainer> newPrimaryVertexLink = getPV_TJVA(pTau, *vxContainer ); + if (newPrimaryVertexLink.isValid()) { + // set new primary vertex + // will overwrite default one which was set above + pTau.setVertexLink(newPrimaryVertexLink); + // save highest JVF value + pTau.setDetail(xAOD::TauJetParameters::TauJetVtxFraction,static_cast<float>(m_maxJVF)); + ATH_MSG_DEBUG("TJVA vertex found and set"); + } + else { + ATH_MSG_DEBUG("couldn't find new PV for TJVA"); + } + + return StatusCode::SUCCESS; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +ElementLink<xAOD::VertexContainer> TauVertexFinder::getPV_TJVA(const xAOD::TauJet& pTau, const xAOD::VertexContainer& vertices) +{ + const xAOD::Jet* pJetSeed = (*pTau.jetLink()); + + // the implementation follows closely the example given in modifyJet(...) in https://svnweb.cern.ch/trac/atlasoff/browser/Reconstruction/Jet/JetMomentTools/trunk/Root/JetVertexFractionTool.cxx#15 + + // Get the tracks associated to the jet + std::vector<const xAOD::TrackParticle*> assocTracks; + if (! pJetSeed->getAssociatedObjects(m_assocTracksName, assocTracks)) { + ATH_MSG_ERROR("Could not retrieve the AssociatedObjects named \""<< m_assocTracksName <<"\" from jet"); + return ElementLink<xAOD::VertexContainer>(); + } + + // Get the TVA object + const jet::TrackVertexAssociation* tva = NULL; + if (evtStore()->retrieve(tva,m_trackVertexAssocName).isFailure()) { + ATH_MSG_ERROR("Could not retrieve the TrackVertexAssociation from evtStore: " << m_trackVertexAssocName); + return ElementLink<xAOD::VertexContainer>(); + } + + // Calculate Jet Vertex Fraction + std::vector<float> jvf; + jvf.resize(vertices.size()); + for (size_t iVertex = 0; iVertex < vertices.size(); ++iVertex) { + jvf.at(iVertex) = getJetVertexFraction(vertices.at(iVertex),assocTracks,tva); + } + + // Get the highest JVF vertex and store maxJVF for later use + // Note: the official JetMomentTools/JetVertexFractionTool doesn't provide any possibility to access the JVF value, but just the vertex. + m_maxJVF=-100.; + size_t maxIndex = 0; + for (size_t iVertex = 0; iVertex < jvf.size(); ++iVertex) { + if (jvf.at(iVertex) > m_maxJVF) { + m_maxJVF = jvf.at(iVertex); + maxIndex = iVertex; + } + } + + // Set the highest JVF vertex + ElementLink<xAOD::VertexContainer> vtxlink = ElementLink<xAOD::VertexContainer>(vertices,vertices.at(maxIndex)->index()); + + return vtxlink; +} + +// reimplementation of JetVertexFractionTool::getJetVertexFraction(const xAOD::Vertex* vertex, const std::vector<const xAOD::TrackParticle*>& tracks, const jet::TrackVertexAssociation* tva) const +// avoid to call this specific tool only for this easy purpose +// see https://svnweb.cern.ch/trac/atlasoff/browser/Reconstruction/Jet/JetMomentTools/trunk/Root/JetVertexFractionTool.cxx +float TauVertexFinder::getJetVertexFraction(const xAOD::Vertex* vertex, const std::vector<const xAOD::TrackParticle*>& tracks, const jet::TrackVertexAssociation* tva) const +{ + float sumTrackPV = 0; + float sumTrackAll = 0; + for (size_t iTrack = 0; iTrack < tracks.size(); ++iTrack) + { + const xAOD::TrackParticle* track = tracks.at(iTrack); + const xAOD::Vertex* ptvtx = tva->associatedVertex(track); + if (ptvtx != nullptr) { // C++11 feature + if (ptvtx->index() == vertex->index()) sumTrackPV += track->pt(); + } + sumTrackAll += track->pt(); + + } + return sumTrackAll!=0 ? sumTrackPV/sumTrackAll : 0; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// Helpers +template <class T> +bool TauVertexFinder::openContainer(T* &container, std::string containerName, bool printFATAL) { + StatusCode sc = evtStore()->retrieve(container, containerName); + if (sc.isFailure() || !container) { + if (printFATAL) ATH_MSG_FATAL("Container (" << containerName << ") not found in StoreGate"); + return 0; + } + return container; +} + +template <class T> +bool TauVertexFinder::retrieveTool(T & tool) { + if (tool.retrieve().isFailure()) { + ATH_MSG_FATAL("Failed to retrieve tool " << tool); + return false; + } else { + ATH_MSG_VERBOSE("Retrieved tool " << tool); + } + return true; +} diff --git a/Reconstruction/tauRecTools/src/TauVertexFinder.h b/Reconstruction/tauRecTools/src/TauVertexFinder.h new file mode 100644 index 0000000000000000000000000000000000000000..de30101ac0ea1b522a52a58993f13f7d5c819f75 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauVertexFinder.h @@ -0,0 +1,74 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUVERTEXFINDER_H +#define TAUREC_TAUVERTEXFINDER_H + +#include "tauRecTools/TauRecToolBase.h" +#include "GaudiKernel/ToolHandle.h" +#include "xAODTracking/VertexContainer.h" +#include "JetEDM/TrackVertexAssociation.h" + +///////////////////////////////////////////////////////////////////////////// + +/** + * @brief Associate a vertex (origin) to the tau candidate. + * + * The vertex has to be consistent with the origin of tau jet seed. + * The vertex is determined in the following order: TJVA -> first PV in vertex container -> 0 + * Attention: all downstream tau variables will be calculated to the vertex set here! + * + * @author KG Tan <Kong.Guan.Tan@cern.ch> + * @author Felix Friedrich <Felix.Friedrich@cern.ch> + */ + +class TauVertexFinder : virtual public TauRecToolBase { +public: + //------------------------------------------------------------- + //! Constructor and Destructor + //------------------------------------------------------------- + TauVertexFinder(const std::string& name); + ASG_TOOL_CLASS2(TauVertexFinder, TauRecToolBase, ITauToolBase); + ~TauVertexFinder(); + + //------------------------------------------------------------- + //! Algorithm functions + //------------------------------------------------------------- + virtual StatusCode initialize(); + virtual StatusCode eventInitialize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode eventFinalize(); + virtual StatusCode finalize(); + + virtual void cleanup(xAOD::TauJet* ) { } + virtual void print() const { } + + ElementLink<xAOD::VertexContainer> getPV_TJVA(const xAOD::TauJet& tauJet, const xAOD::VertexContainer& vertices); + +private: + float getJetVertexFraction(const xAOD::Vertex* vertex, const std::vector<const xAOD::TrackParticle*>& tracks, const jet::TrackVertexAssociation* tva) const; + + //------------------------------------------------------------- + //! Convenience functions to handle storegate objects + //------------------------------------------------------------- + template <class T> + bool openContainer(T* &container, std::string containerName, bool printFATAL=false); + + template <class T> + bool retrieveTool(T &tool); + +private: + bool m_printMissingContainerINFO; + float m_maxJVF; + + //------------------------------------------------------------- + //! Configureables + //------------------------------------------------------------- + bool m_useTJVA; + std::string m_inputPrimaryVertexContainerName; + std::string m_assocTracksName; + std::string m_trackVertexAssocName; +}; + +#endif // not TAUREC_TAUVERTEXFINDER_H diff --git a/Reconstruction/tauRecTools/src/TauVertexVariables.cxx b/Reconstruction/tauRecTools/src/TauVertexVariables.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ec30ed28c283d34821737f6a3f612dcd3ac5c633 --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauVertexVariables.cxx @@ -0,0 +1,339 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +#include "Particle/TrackParticle.h" +#include "Particle/TrackParticleContainer.h" +#include "TrkParameters/TrackParameters.h" + +#include "xAODTracking/TrackParticleContainer.h" + +#include "TrkVertexFitterInterfaces/ITrackToVertexIPEstimator.h" +#include "TrkVertexFitterInterfaces/IVertexFitter.h" +#include "TrkVertexFitterInterfaces/IVertexSeedFinder.h" +#include "TrkVertexFitters/AdaptiveVertexFitter.h" +#include "TrkVxEdmCnv/IVxCandidateXAODVertex.h" +#include "TrkLinks/LinkToXAODTrackParticle.h" + +#include "tauRecTools/TauEventData.h" +#include "TauVertexVariables.h" + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- + +TauVertexVariables::TauVertexVariables(const std::string &name ) : + TauRecToolBase(name), + m_primaryVertexKey("PrimaryVertices"), + m_useOldSeedFinderAPI(false), + m_fitTool("Trk::AdaptiveVertexFitter"), + m_SeedFinder("Trk::CrossDistancesSeedFinder"), + m_xaodConverter("Trk::VxCandidateXAODVertex"), + m_pSecVtxContainer(0), + m_pSecVtxAuxContainer(0){ + declareProperty("PrimaryVertexKey", m_primaryVertexKey); + declareProperty("TrackParticleContainer", m_inputTrackParticleContainerName = "InDetTrackParticles"); + declareProperty("TrackToVertexIPEstimator", m_trackToVertexIPEstimator); + declareProperty("VertexFitter", m_fitTool); + declareProperty("SeedFinder", m_SeedFinder); + declareProperty("XAODConverter",m_xaodConverter); + declareProperty("useOldSeedFinderAPI",m_useOldSeedFinderAPI); + declareProperty("runOnAOD", m_AODmode);//AODS are input file +} + +//----------------------------------------------------------------------------- +// Destructor +//----------------------------------------------------------------------------- + +TauVertexVariables::~TauVertexVariables() { +} + + +//----------------------------------------------------------------------------- +// Initializer +//----------------------------------------------------------------------------- + +StatusCode TauVertexVariables::initialize() { + CHECK( m_trackToVertexIPEstimator.retrieve() ); + CHECK( m_fitTool.retrieve() ); + CHECK( m_SeedFinder.retrieve() ); + if (m_useOldSeedFinderAPI) CHECK( m_xaodConverter.retrieve() ); + + if (m_useOldSeedFinderAPI) { + ATH_MSG_INFO("using AOD-style API of the AdaptiveVertexFitter"); + } + else { + ATH_MSG_INFO("using new xAOD-style API of the AdaptiveVertexFitter"); + } + + return StatusCode::SUCCESS; +} + +StatusCode TauVertexVariables::eventInitialize() { + + bool inTrigger = tauEventData()->inTrigger(); + + // Only store the vertex containers if we are offline? + if(!inTrigger) + { + // Secondary Vertex Container for tau decay vertex + if(!m_AODmode){ + m_pSecVtxContainer = new xAOD::VertexContainer(); + m_pSecVtxAuxContainer = new xAOD::VertexAuxContainer(); + m_pSecVtxContainer->setStore( m_pSecVtxAuxContainer ); + + CHECK( evtStore()->record( m_pSecVtxContainer, "TauSecondaryVertices" ) ); + CHECK( evtStore()->record( m_pSecVtxAuxContainer, "TauSecondaryVerticesAux." ) ); + } + else { + CHECK( evtStore()->retrieve( m_pSecVtxContainer, "TauSecondaryVertices") ); + CHECK( evtStore()->retrieve( m_pSecVtxAuxContainer, "TauSecondaryVerticesAux.") ); + } + } + + return StatusCode::SUCCESS; + +} + + + +//----------------------------------------------------------------------------- +// Finalizer +//----------------------------------------------------------------------------- +StatusCode TauVertexVariables::finalize() { + return StatusCode::SUCCESS; +} + + +//----------------------------------------------------------------------------- +// Execution +//----------------------------------------------------------------------------- +StatusCode TauVertexVariables::execute(xAOD::TauJet& pTau) { + + ATH_MSG_DEBUG("executing TauVertexVariables"); + + // for tau trigger + bool inTrigger = tauEventData()->inTrigger(); + if (inTrigger) ATH_MSG_DEBUG("We're in the Trigger"); + + // impact parameter variables for standard tracks + if (pTau.nTracks() > 0) { + + const Trk::ImpactParametersAndSigma* myIPandSigma(0); + const xAOD::Vertex* vxcand = nullptr; + + if (inTrigger) { + + StatusCode scBeam = StatusCode::FAILURE; + + if (tauEventData()->hasObject("Beamspot")) scBeam = tauEventData()->getObject("Beamspot", vxcand); + + if(scBeam){ + myIPandSigma = m_trackToVertexIPEstimator->estimate(pTau.track(0), vxcand); + } else { + ATH_MSG_DEBUG("No Beamspot object in tau candidate"); + } + + } else if (pTau.vertexLink()) { + + vxcand = *(pTau.vertexLink()) ; + + //check if vertex has a valid type (skip if vertex has type NoVtx) + if (vxcand->vertexType() > 0){ + myIPandSigma = m_trackToVertexIPEstimator->estimate(pTau.track(0), vxcand); + } + + } + + if (myIPandSigma != 0) { + pTau.setDetail(xAOD::TauJetParameters::ipSigLeadTrk, (float)( myIPandSigma->IPd0 / myIPandSigma->sigmad0 )); + pTau.setDetail(xAOD::TauJetParameters::ipZ0SinThetaSigLeadTrk, (float)( myIPandSigma->IPz0SinTheta / myIPandSigma->sigmaz0SinTheta )); + } else { + ATH_MSG_DEBUG("trackToVertexIPestimator failed for a standard track!"); + pTau.setDetail(xAOD::TauJetParameters::ipSigLeadTrk, (float)(-999.)); + pTau.setDetail(xAOD::TauJetParameters::ipZ0SinThetaSigLeadTrk, (float)(-999.)); + } + + delete myIPandSigma; + + } else { + + ATH_MSG_DEBUG("Tau has no tracks"); + + } + + + float ipSigLeadTrk; + float ipZ0SinThetaSigLeadTrk; + + if (pTau.detail(xAOD::TauJetParameters::ipSigLeadTrk, ipSigLeadTrk)) + ATH_MSG_VERBOSE("IP significance lead track " << ipSigLeadTrk); + if (pTau.detail(xAOD::TauJetParameters::ipZ0SinThetaSigLeadTrk, ipZ0SinThetaSigLeadTrk)) + ATH_MSG_VERBOSE("IP Z0 significance lead track " << ipZ0SinThetaSigLeadTrk); + + //try to find secondary vertex + //look for secondary vertex if more than 1 track + pTau.setDetail(xAOD::TauJetParameters::trFlightPathSig, (float)(-1111.)); + if (pTau.nTracks() < 2) { + return StatusCode::SUCCESS; + } + + const xAOD::VertexContainer* vxContainer = 0; + StatusCode sc=StatusCode::SUCCESS; + if (sc.isSuccess() && inTrigger) sc = tauEventData()->getObject("VxPrimaryCandidate", vxContainer); + // retrieve vertex container, exit if not found + else sc = evtStore()->retrieve(vxContainer, m_primaryVertexKey); + + if (sc.isFailure() || !vxContainer) { + ATH_MSG_WARNING("No vertex container found. Skipping secondary vertex fitting."); + return StatusCode::SUCCESS; + } + + const xAOD::TrackParticleContainer* trackParticleCont = 0; + if (inTrigger) sc = tauEventData()->getObject( "TrackContainer", trackParticleCont ); + // retrieve track particle container, exit if not found + else sc = evtStore()->retrieve(trackParticleCont, m_inputTrackParticleContainerName); + if (sc.isFailure() || !trackParticleCont) { + ATH_MSG_WARNING("No track particle container found. Skipping secondary vertex fitting."); + return StatusCode::SUCCESS; + } + + // get xAOD TrackParticles and Trk::Tracks + std::vector<const xAOD::TrackParticle*> xaodTracks; + std::vector<const Trk::Track*> origTracks; + for (unsigned i = 0; i < pTau.nTracks(); ++i) { + xaodTracks.push_back(pTau.track(i)); + ATH_MSG_VERBOSE("xAOD::TrackParticle " <<i<<": "<< pTau.track(i)->pt() << " " << pTau.track(i)->eta() << " " << pTau.track(i)->phi()); + if (pTau.track(i)->track()) { + origTracks.push_back(pTau.track(i)->track()); + + // for debugging + /* + ATH_MSG_DEBUG("Trk::Track " <<i<<": "<< (*pTau.track(i)->track())->pt() << " " << (*pTau.track(i)->track())->eta() << " " << (*pTau.track(i)->track())->phi()); + const Trk::TrackParameters * tmpMeasPer = (*pTau.track(i)->track())->perigeeParameters(); + const AmgSymMatrix(5)* cov = tmpMeasPer->covariance(); + ATH_MSG_DEBUG(" TrackParameters: pT="<< tmpMeasPer->pT() << ", eta=" << tmpMeasPer->eta() << ", x=" << tmpMeasPer->position().x() << ", y="<< tmpMeasPer->position().y() <<", z="<< tmpMeasPer->position().z()); + ATH_MSG_DEBUG(" covariance ="<< *cov); + */ + // for debugging + } + else { + ATH_MSG_WARNING("no Trk::Track for xAOD::TrackParticle"); + } + } + + // get the starting point for the fit using Trk::Tracks + Trk::Vertex* seedPoint = new Trk::Vertex(m_SeedFinder->findSeed(origTracks)); + ATH_MSG_VERBOSE("seedPoint x/y/perp=" << seedPoint->position().x() << " "<< seedPoint->position().y() << " "<< seedPoint->position().perp()); + if (!seedPoint) { + ATH_MSG_WARNING("no seedPoint: Can not calculate secondary vertex!"); + return StatusCode::SUCCESS; + } + + // fitting the vertex itself + xAOD::Vertex* xAODvertex(0); + if (!m_useOldSeedFinderAPI) { // use new xAOD API of VertexFitter + xAODvertex = m_fitTool->fit(xaodTracks, *seedPoint); + if (xAODvertex && !inTrigger) { + ATH_MSG_VERBOSE("using new xAOD API: Secondary Vertex found and recorded! x="<<xAODvertex->position().x()<< ", y="<<xAODvertex->position().y()<<", perp="<<xAODvertex->position().perp()); + m_pSecVtxContainer->push_back(xAODvertex); + } + } + else { // use standard AOD-style API of VertexFitter + Trk::VxCandidate* tmpVxCandidate = m_fitTool->fit(origTracks, *seedPoint); + if (tmpVxCandidate) { + ATH_MSG_VERBOSE("using old AOD API:Secondary Vertex found and recorded! x="<<tmpVxCandidate->recVertex().position().x()<< ", y="<<tmpVxCandidate->recVertex().position().y()<<", perp="<<tmpVxCandidate->recVertex().position().perp()); + + //****************************************************************** + // convert VxCandidate to xAOD::Vertex + //****************************************************************** + + // assigning the input xAOD tracks to the fitted vertex + // this means: after that procedure the Trk::VxCandidate knows already the links to the xAOD tracks (which have to be identical with the Trk:Tracks used in the VertexFitter!) + // this is needed for the converting, otherwise the new xAODVertex don't have the track links + if(tmpVxCandidate->vxTrackAtVertex() != 0 && tmpVxCandidate->vxTrackAtVertex()->size() !=0) { + for(unsigned int i = 0; i <xaodTracks.size(); ++i) { + Trk::LinkToXAODTrackParticle * linkTT = new Trk::LinkToXAODTrackParticle; + linkTT->setElement(xaodTracks[i]); + linkTT->setStorableObject(*trackParticleCont); + // vxtrackatvertex takes ownership! + (*(tmpVxCandidate->vxTrackAtVertex()))[i]->setOrigTrack(linkTT); + } + } + + xAODvertex = new xAOD::Vertex(); + if (!inTrigger) m_pSecVtxContainer->push_back(xAODvertex); + // perform the final converting now + if( m_xaodConverter->createXAODVertex(*tmpVxCandidate,xAODvertex).isFailure() ) { + ATH_MSG_ERROR("Failed to create xAODVertex for VxCandidate. Don't set any secondary vertex for tau!"); + return StatusCode::SUCCESS; + } + delete tmpVxCandidate; + } + } + delete seedPoint; + + if (!xAODvertex) { + ATH_MSG_WARNING("no secondary vertex found!"); + return StatusCode::SUCCESS; + } + + // get the transverse flight path significance + float trFlightPS = trFlightPathSig(pTau, *xAODvertex); + pTau.setDetail(xAOD::TauJetParameters::trFlightPathSig, (float)(trFlightPS)); + ATH_MSG_VERBOSE("transverse flight path significance="<<trFlightPS); + + // Note, we only attach the 2nd vertex if at offline, otherwise, break the trigger persistency + if (!inTrigger) { + pTau.setSecondaryVertex(m_pSecVtxContainer, xAODvertex); // set the link to the vertex + } + else { + delete xAODvertex; // delete the vertex when in trigger mode, because we can not save it + } + + return StatusCode::SUCCESS; +} + +//------------------------------------------------------------------------- +// calculate the transverse flight path significance +//------------------------------------------------------------------------- +double TauVertexVariables::trFlightPathSig(const xAOD::TauJet& pTau, const xAOD::Vertex& secVertex) { + + const xAOD::Vertex* pVertex = 0; + if (pTau.vertexLink()) pVertex = *pTau.vertexLink(); + if (!pVertex) { + ATH_MSG_WARNING("No primary vertex information for calculation of transverse flight path significance"); + return -11111.; + } + + double fpx = secVertex.position().x() - pVertex->position().x(); + double fpy = secVertex.position().y() - pVertex->position().y(); + double fpt = (secVertex.position() - pVertex->position()).perp(); + + if (fpt == 0) { + ATH_MSG_WARNING("delta pt of (secVtx - priVtx) is 0!"); + return -11111.; + } + + double sigma_fpt2 = (fpx * fpx * secVertex.covariancePosition()(Trk::x, Trk::x) + + fpx * fpy * secVertex.covariancePosition()(Trk::x, Trk::y) + + fpy * fpx * secVertex.covariancePosition()(Trk::y, Trk::x) + + fpy * fpy * secVertex.covariancePosition()(Trk::y, Trk::y)) / (fpt * fpt); + + if (sigma_fpt2 <= 0) { + ATH_MSG_WARNING("sigma delta pt of (secVtx - priVtx) is 0!"); + return -11111.; + } + + double sigma_fpt = sqrt(sigma_fpt2); + double sign = 0; + + if (fpx * pTau.p4().Px() + fpy * pTau.p4().Py() > 0.) sign = 1.; + else sign = -1.; + + //ATH_MSG_INFO(sign << " " <<fpt << " " << sigma_fpt << " " << sign * fpt / sigma_fpt); + return sign * fpt / sigma_fpt; +} + diff --git a/Reconstruction/tauRecTools/src/TauVertexVariables.h b/Reconstruction/tauRecTools/src/TauVertexVariables.h new file mode 100644 index 0000000000000000000000000000000000000000..54789149c51d708049c60494798fe73b1cfb182c --- /dev/null +++ b/Reconstruction/tauRecTools/src/TauVertexVariables.h @@ -0,0 +1,67 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUVERTEXVARIABLES_H +#define TAUREC_TAUVERTEXVARIABLES_H + +#include "xAODTracking/VertexContainer.h" +#include "xAODTracking/VertexAuxContainer.h" +#include "tauRecTools/TauRecToolBase.h" +#include "GaudiKernel/ToolHandle.h" + +// forwards +class TauEventData; +namespace Trk { + class ITrackToVertexIPEstimator; + class IVertexFitter; + class IVertexSeedFinder; + class IVxCandidateXAODVertex; +} + +/** + * + * @brief Class for calculating vertex variables. + * + * @authors Stan Lai, Felix Friedrich + */ + +class TauVertexVariables : virtual public TauRecToolBase { +public: + //----------------------------------------------------------------- + // Constructor and destructor + //----------------------------------------------------------------- + TauVertexVariables(const std::string& name); + ASG_TOOL_CLASS2(TauVertexVariables, TauRecToolBase, ITauToolBase); + ~TauVertexVariables(); + + virtual StatusCode initialize(); + virtual StatusCode execute(xAOD::TauJet&); + virtual StatusCode eventInitialize(); + virtual StatusCode finalize(); + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + + //------------------------------------------------------------- + //! determines the transverse flight path significance from + //! the primary vertex and the secondary vertex of tau candidate + //------------------------------------------------------------- + double trFlightPathSig(const xAOD::TauJet& pTau, const xAOD::Vertex& secVertex); + +private: + std::string m_primaryVertexKey; + std::string m_inputTrackParticleContainerName; + bool m_useOldSeedFinderAPI; + bool m_AODmode; + ToolHandle< Trk::ITrackToVertexIPEstimator > m_trackToVertexIPEstimator; + ToolHandle< Trk::IVertexFitter > m_fitTool; //!< Pointer to the base class of the fit algtools + ToolHandle< Trk::IVertexSeedFinder > m_SeedFinder; + ToolHandle< Trk::IVxCandidateXAODVertex > m_xaodConverter; // necessary to convert VxCandidate to xAOD::Vertex in case old API is used + + xAOD::VertexContainer* m_pSecVtxContainer; + xAOD::VertexAuxContainer* m_pSecVtxAuxContainer; +}; + +#endif /* TAUREC_TAUVERTEXVARIABLES_H */ + diff --git a/Reconstruction/tauRecTools/src/components/tauRecTools_entries.cxx b/Reconstruction/tauRecTools/src/components/tauRecTools_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..905298fe21a84add140340d726ddce784cc7660e --- /dev/null +++ b/Reconstruction/tauRecTools/src/components/tauRecTools_entries.cxx @@ -0,0 +1,62 @@ +#include "../JetSeedBuilder.h" +#include "../LockTauContainers.h" +#include "../TauAxisSetter.h" +#include "../TauCalibrateEM.h" +#include "tauRecTools/TauCalibrateLC.h" +#include "tauRecTools/TauIDPileupCorrection.h" +#include "../TauCellVariables.h" +#include "../TauTrackFinder.h" +#include "../TauVertexFinder.h" +#include "../TauElectronVetoVariables.h" +#include "tauRecTools/TauCommonCalcVars.h" +#include "../TauShotFinder.h" +#include "../TauPi0ClusterCreator.h" +#include "../TauPi0CreateROI.h" +#include "../TauPi0ClusterScaler.h" +#include "../TauPi0ScoreCalculator.h" +#include "../TauPi0Selector.h" +#include "../TauSubstructureVariables.h" +#include "../TauConversionFinder.h" +#include "../PhotonConversionPID.h" +#include "../PhotonConversionVertex.h" +#include "../TauConversionTagger.h" +#include "../TauVertexVariables.h" +#include "../tauCalibrateWeightTool.h" //for trigger +#include "tauRecTools/TauTrackFilter.h" +#include "tauRecTools/TauGenericPi0Cone.h" +#include "../TauTestDump.h" +#include "tauRecTools/TauProcessorTool.h" +#include "tauRecTools/TauBuilderTool.h" + + +#include "GaudiKernel/DeclareFactoryEntries.h" + +DECLARE_TOOL_FACTORY( JetSeedBuilder ) +DECLARE_TOOL_FACTORY( LockTauContainers ) +DECLARE_TOOL_FACTORY( TauAxisSetter ) +DECLARE_TOOL_FACTORY( TauCalibrateEM ) +DECLARE_TOOL_FACTORY( TauCalibrateLC ) +DECLARE_TOOL_FACTORY( TauIDPileupCorrection ) +DECLARE_TOOL_FACTORY( TauCellVariables ) +DECLARE_TOOL_FACTORY( TauTrackFinder ) +DECLARE_TOOL_FACTORY( TauVertexFinder ) +DECLARE_TOOL_FACTORY( TauElectronVetoVariables ) +DECLARE_TOOL_FACTORY( TauCommonCalcVars ) +DECLARE_TOOL_FACTORY( TauShotFinder ) +DECLARE_TOOL_FACTORY( TauPi0ClusterCreator ) +DECLARE_TOOL_FACTORY( TauPi0CreateROI ) +DECLARE_TOOL_FACTORY( TauPi0ClusterScaler ) +DECLARE_TOOL_FACTORY( TauPi0ScoreCalculator ) +DECLARE_TOOL_FACTORY( TauPi0Selector ) +DECLARE_TOOL_FACTORY( TauSubstructureVariables ) +DECLARE_TOOL_FACTORY( PhotonConversionPID ) +DECLARE_TOOL_FACTORY( PhotonConversionVertex ) +DECLARE_TOOL_FACTORY( TauConversionFinder ) +DECLARE_TOOL_FACTORY( TauConversionTagger ) +DECLARE_TOOL_FACTORY( TauVertexVariables ) +DECLARE_TOOL_FACTORY( tauCalibrateWeightTool ) +DECLARE_TOOL_FACTORY( TauTrackFilter ) +DECLARE_TOOL_FACTORY( TauGenericPi0Cone ) +DECLARE_TOOL_FACTORY( TauTestDump ) +DECLARE_TOOL_FACTORY( TauProcessorTool ) +DECLARE_TOOL_FACTORY( TauBuilderTool ) diff --git a/Reconstruction/tauRecTools/src/components/tauRecTools_load.cxx b/Reconstruction/tauRecTools/src/components/tauRecTools_load.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6b1c2188830c28bd0ce8c55d51143773b065ebdd --- /dev/null +++ b/Reconstruction/tauRecTools/src/components/tauRecTools_load.cxx @@ -0,0 +1,4 @@ +#include "GaudiKernel/LoadFactoryEntries.h" + +LOAD_FACTORY_ENTRIES(tauRecTools) + diff --git a/Reconstruction/tauRecTools/src/tauCalibrateWeightTool.cxx b/Reconstruction/tauRecTools/src/tauCalibrateWeightTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d0fb365cadef91089c65782ace0d850fa2e868ab --- /dev/null +++ b/Reconstruction/tauRecTools/src/tauCalibrateWeightTool.cxx @@ -0,0 +1,391 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/******************************************************************** +(depreciated!) + +NAME: tauCalibrateWeightTool.cxx +PACKAGE: offline/Reconstruction/tauRec + +AUTHORS: M.Heldmann +CREATED: March 22, 2005 +MODIFIED: July 15, 2005 ( Include pT dependent correction ) +23/10/2006 - (AK) fixing some compilation warnings (unused parameter) +18/04/2007 - (AK) fixing some compilation warnings (unused parameter) +29/06/2007 - (SL) fixing some compilation warnings +13/12/2008 - (AK) change to extrapolation of TP instead of Track+code cleaning +16/03/2010 - (AK) use the cell id instead of the pointer +17/03/2010 - (AK) change to P4Helpers +14/12/2011 - (FF) change to use tau axis and numTrack (not seedCalo_) + ********************************************************************/ +#include "tauRecTools/TauEventData.h" +#include "tauEvent/TauCommonDetails.h" +#include "CaloEvent/CaloCluster.h" +#include "CaloEvent/CaloCell.h" +#include "AtlasDetDescr/AtlasDetectorID.h" +#include "CaloIdentifier/CaloID.h" +#include "CaloGeoHelpers/CaloSampling.h" + +#include "CLHEP/Units/SystemOfUnits.h" + +// INCLUDE GAUDI HEADER FILES: +#include "GaudiKernel/Property.h" +#include "AIDA/IHistogram1D.h" + +#include <algorithm> +#include <math.h> + +#include "FourMomUtils/P4Helpers.h" +#include "FourMom/P4EEtaPhiM.h" + +#include "CaloInterface/IHadronicCalibrationTool.h" +#include "TF1.h" + +#include "tauCalibrateWeightTool.h" +/********************************************************************/ + +tauCalibrateWeightTool::tauCalibrateWeightTool(const std::string& name) : + TauRecToolBase(name), + m_calibrateType( tauCalibrateWeightTool::calCells ), + m_caloWeightTool(this), + m_cellWeightTool("CellWeightTool2004"), + m_applyCellWeightEM(true), + m_applyCellWeightHad(true), + m_applyPtEtaCorrFactors(true), + m_validCaloWeightTool(true), + m_doEtaInterpolation(false), + m_cellCone(0.4) +{ + declareProperty( "calibrateType", m_calibrateType ); + // Calibration Tool + declareProperty("CellWeightTool",m_cellWeightTool); + declareProperty("ApplyCellWeightEM", m_applyCellWeightEM); + declareProperty("ApplyCellWeightHad", m_applyCellWeightHad); + declareProperty("ApplyPtEtaCorrFactors", m_applyPtEtaCorrFactors); + declareProperty("pTNumberOfBins", m_nptbins ); + declareProperty("etaNumberOfBins", m_netabins ); + + declareProperty("pTPoints",m_ptpoints=std::vector<float>(10,0)); + declareProperty("etaPoints",m_etapoints=std::vector<float>(10,0)); + declareProperty("pTetaCorrectionsNtr1",m_ptetacorrectionsntr1=std::vector<float>(100,0)); + declareProperty("pTetaCorrectionsNtr23",m_ptetacorrectionsntr23=std::vector<float>(100,0)); + + declareProperty("FudgeFactor",m_fudge=1); + declareProperty("DoEtaInterpolation", m_doEtaInterpolation); + declareProperty("CellCone",m_cellCone); + declareProperty("CaloWeightTool",m_caloWeightTool); +} + +tauCalibrateWeightTool::~tauCalibrateWeightTool() +{ +} + +StatusCode tauCalibrateWeightTool::initialize() +{ + StatusCode sc; + ATH_MSG_INFO( "Calibrating using fitted weights. " ); + + // retrieve all helpers from det store + sc = detStore()->retrieve(m_emid); + if (sc.isFailure()) { + ATH_MSG_ERROR( "Unable to retrieve LArEM_ID helper from DetectorStore" ); + return sc; + } + + sc = detStore()->retrieve(m_tileid); + if (sc.isFailure()) { + ATH_MSG_ERROR( "Unable to retrieve TileID helper from DetectorStore" ); + return sc; + } + + // Tool service + IToolSvc* myToolSvc; + sc = service("ToolSvc",myToolSvc); + if ( sc.isFailure() ) { + ATH_MSG_FATAL( "Tool Service not found" ); + return StatusCode::FAILURE; + } + + // Fetch cell weight tool + sc = m_caloWeightTool.retrieve(); + if ( sc.isFailure() ) { + ATH_MSG_ERROR( "Cannot find tool named <" << m_cellWeightTool << ">" ); + m_validCaloWeightTool = false; + + return StatusCode::FAILURE; + } + else { + if( m_caloWeightTool != 0 ) { + ATH_MSG_INFO( "Will use the CaloWeightTool named: " << m_cellWeightTool ); + m_validCaloWeightTool = true; + } + } + + if ( (int)m_ptpoints.size() != m_nptbins || (int)m_etapoints.size() != m_netabins ) { + ATH_MSG_FATAL( "wrong number of points for interpolation" ); + return StatusCode::FAILURE; + } + + for ( int i = 0; i < m_nptbins - 1; ++i ) { + if ( m_ptpoints[i] >= m_ptpoints[i+1]) { + ATH_MSG_FATAL( "Correction factor coordinates must be ordered in Pt and unique" ); + return StatusCode::FAILURE; + } + } + m_ptpoints.push_back(0); //makes the boundary conditions easyer to handle + + for ( int i = 0; i < m_netabins - 1; ++i ) { + if ( m_etapoints[i] >= m_etapoints[i+1]) { + ATH_MSG_FATAL( "Correction factor coordinates must be ordered in eta and unique" ); + return StatusCode::FAILURE; + } + } + m_etapoints.push_back(0); + + if ( (int)m_ptetacorrectionsntr1.size() != (m_nptbins * m_netabins) ) { + ATH_MSG_FATAL( "Wrong number of correction factors for 1 Track" ); + return StatusCode::FAILURE; + } + + if ( (int)m_ptetacorrectionsntr23.size() != (m_nptbins * m_netabins) ) { + ATH_MSG_FATAL( "Wrong number of correction factors for 2 and 3 Tracks" ); + return StatusCode::FAILURE; + } + + return StatusCode::SUCCESS; +} + +/********************************************************************/ +StatusCode tauCalibrateWeightTool::execute(xAOD::TauJet&) +{ + /* + * FF: March 2014 + * This Tool is not migrated yet to xAOD. Unclear if still needed. Only client was TauTrigger. + * FF will investigate. + * + * + Analysis :: TauJet *tau = data->tau; + Analysis :: TauCommonDetails *details = dynamic_cast<Analysis :: TauCommonDetails *>(data->details); + + // Detector identifiers + AtlasDetectorID AtlasID; + + // Variables for sums + double sumEM = 0; + double sumE = 0; + double sumAccb3 = 0; + double sumHad = 0; + double sumTile1 = 0; + + double sumScint = 0; + double sumGap = 0; + + double dR; + + // loop over all cells of the tau (placed there by the tauSeedBuilder) + typedef NavigationToken<CaloCell,NavigationDefaults::DefaultWeight,CaloCellIDFcn> token_t; + token_t nt; + + pTau.fillToken( nt ); + + token_t::const_iterator nt_iter = nt.begin(); + token_t::const_iterator nt_end = nt.end(); + + const CaloCell *cell; + + double etaSeed = pTau.eta(); //FF details->seedCalo_eta(); + double phiSeed = pTau.phi(); //FF details->seedCalo_phi(); + + P4EEtaPhiM P4Seed( 1., etaSeed, phiSeed, 0. ); + + for ( ; nt_iter != nt_end; nt_iter++ ) { + cell = (*nt_iter); + + // Cell ET and index for ET range + // This is made symmetric around zero so that noise (not yet included) + // does not produce a shift. + double cellET = cell->et(); + + CaloSampling::CaloSample calo = cell->caloDDE()->getSampling(); + + // Use cells that are in DR < m_cellCone of eta,phi of jet: + dR = P4Helpers::deltaR( P4Seed, cell->eta(), cell->phi() ); + + if ( dR < m_cellCone ) { + double calWeight = 1.; + + // Check which kind of calib tools have been selected + // and Get calibration weight + + if (m_validCaloWeightTool) calWeight = m_caloWeightTool->wtCell( cell ); + + sumE += cell->e(); + + switch ( calo ) { + case CaloSampling::PreSamplerB: + case CaloSampling::PreSamplerE: + case CaloSampling::EMB1: + case CaloSampling::EME1: + case CaloSampling::EMB2: + case CaloSampling::EME2: + sumEM += (m_applyCellWeightEM ? calWeight*cellET : cellET); + break; + case CaloSampling::EMB3: + sumAccb3 += cellET; + + case CaloSampling::EME3: + // Only include first two EM layers in EM sum; add third to HAD + // Keep track of ACCB3 for cryostat correction below + sumHad += (m_applyCellWeightHad ? calWeight*cellET : cellET); + break; + + case CaloSampling::TileBar0: + sumTile1 += cellET; + + case CaloSampling::TileBar1: + case CaloSampling::TileBar2: + sumHad += (m_applyCellWeightHad ? calWeight*cellET : cellET); + break; + case CaloSampling::TileExt0: + case CaloSampling::TileExt1: + case CaloSampling::TileExt2: + sumHad += (m_applyCellWeightHad ? calWeight*cellET : cellET); + break; + case CaloSampling::TileGap1: + // scintillator ? + // Gap Scintillator is included in Gap + // Hence do NOT add it separately + // MH I don't know what's it like now .... but I guess its seperated + sumScint += cellET; + case CaloSampling::TileGap2: + case CaloSampling::TileGap3: + sumHad += (m_applyCellWeightHad ? calWeight*cellET : cellET); + sumGap += cellET; + break; + case CaloSampling::HEC0: + case CaloSampling::HEC1: + case CaloSampling::HEC2: + case CaloSampling::HEC3: + sumHad += (m_applyCellWeightHad ? calWeight*cellET : cellET); + break; + case CaloSampling::FCAL0: + case CaloSampling::FCAL1: + case CaloSampling::FCAL2: + case CaloSampling::MINIFCAL0: + case CaloSampling::MINIFCAL1: + case CaloSampling::MINIFCAL2: + case CaloSampling::MINIFCAL3: + case CaloSampling::Unknown: + break; + } + } // end dR cut + else + { + ATH_MSG_VERBOSE( "cell with energy " << cell->e() << " outside of cell cone" ); + } + + } // end cell loop + + // Cryostat correction uses geometric mean of last layer of EM and + // first layer of tile: + + if(sumAccb3<0.) sumAccb3=0.; + if(sumTile1<0.) sumTile1=0.; + + double wtCryo = 1.; + + if (m_validCaloWeightTool) wtCryo = m_caloWeightTool->wtCryo(); + double sumCryo = (m_applyCellWeightHad ? wtCryo*sqrt(sumAccb3*sumTile1) : sqrt(sumAccb3*sumTile1)); + + // Weight fudge factor. The H1 weights are taken to be independent of + // eta. This factor is applied to the hadronic energy to produce a + // more uniform response. + + details->setSeedCalo_etEMCalib(sumEM); + details->setSeedCalo_etHadCalib((sumHad+sumCryo)); + + double et = details->seedCalo_etEMCalib()+details->seedCalo_etHadCalib(); + double eta = fabs( etaSeed ); + double corr = 1; + + if (m_applyPtEtaCorrFactors) { + + ATH_MSG_VERBOSE( "energy: " << details->seedCalo_etEMCalib() << " " <<details->seedCalo_etHadCalib() << " " << sumEM <<" "<<sumHad<<" "<<sumCryo ); + + int lowpt_idx = 0; + int loweta_idx = 0; + + double lowpt_frac = 0; + double loweta_frac = 0; + + while ( lowpt_idx < m_nptbins-1 && et > m_ptpoints[lowpt_idx+1] ) + lowpt_idx++; + + lowpt_frac = ( m_ptpoints[lowpt_idx+1] - et ) / ( m_ptpoints[lowpt_idx+1] - m_ptpoints[lowpt_idx] ); // will be >1 if et is out of bounds + + if ( lowpt_frac > 1 ) + lowpt_frac = 1; + if( lowpt_frac < 0 ) { //should never happen, only if ptNumberOfBins is set wrong (which is checked now) + ATH_MSG_ERROR( "FIXME: lowpt_frac < 0 !!" ); + } + + while ( loweta_idx < m_netabins-1 && eta > m_etapoints[loweta_idx+1] ) + loweta_idx++; + + if(m_doEtaInterpolation) + loweta_frac = ( m_etapoints[loweta_idx+1] - eta ) / ( m_etapoints[loweta_idx+1] - m_etapoints[loweta_idx] ); // will be >1 if eta is out of bounds, + else + loweta_frac = 1; + + if ( loweta_frac > 1) + loweta_frac = 1; + if( loweta_frac < 0 ) { //should never happen, only if etaNumberOfBins is set wrong + ATH_MSG_ERROR( "FIXME: loweta_frac < 0 !!" ); + } + + double coeff_matrix[2][2] = { {0, 0}, {0, 0} }; + + //FF changed from seeddCalo_numTrack to numTrack + if ( pTau.numTrack() <= 1 ) { + coeff_matrix[0][0] = m_ptetacorrectionsntr1[lowpt_idx*m_netabins+loweta_idx]; + if( lowpt_idx < m_nptbins-1 ) + coeff_matrix[1][0] = m_ptetacorrectionsntr1[(lowpt_idx+1)*m_netabins+loweta_idx]; + if( loweta_idx < m_netabins-1 ) + coeff_matrix[0][1] = m_ptetacorrectionsntr1[lowpt_idx*m_netabins+(loweta_idx+1)]; + if( lowpt_idx < m_nptbins-1 && loweta_idx < m_netabins-1 ) + coeff_matrix[1][1] = m_ptetacorrectionsntr1[(lowpt_idx+1)*m_netabins+(loweta_idx+1)]; + } else { + coeff_matrix[0][0] = m_ptetacorrectionsntr23[lowpt_idx*m_netabins+loweta_idx]; + if( lowpt_idx < m_nptbins-1 ) + coeff_matrix[1][0] = m_ptetacorrectionsntr23[(lowpt_idx+1)*m_netabins+loweta_idx]; + if( loweta_idx < m_netabins-1 ) + coeff_matrix[0][1] = m_ptetacorrectionsntr23[lowpt_idx*m_netabins+(loweta_idx+1)]; + if( lowpt_idx < m_nptbins-1 && loweta_idx < m_netabins-1 ) + coeff_matrix[1][1] = m_ptetacorrectionsntr23[(lowpt_idx+1)*m_netabins+(loweta_idx+1)]; + } + + corr = ( coeff_matrix[0][0] * lowpt_frac * loweta_frac ) + ( coeff_matrix[1][0] * (1-lowpt_frac) * loweta_frac ); + corr += ( coeff_matrix[0][1] * lowpt_frac * (1-loweta_frac) ) + ( coeff_matrix[1][1] * (1-lowpt_frac) * (1-loweta_frac) ); + + } // end if (m_applyPtEtaCorrFactors) + + ATH_MSG_VERBOSE( "corrected energy: " << et << "*" << corr << "=" << et*corr ); + + + //pTau.setE( et*cosh( details->seedCalo_eta() )*corr*m_fudge ); + */ + + //return StatusCode::SUCCESS; + // print error so that everybody knows this tool isn't working in case it is called. + ATH_MSG_ERROR( "This Tool is not yet migrated to xAOD!" ); + return StatusCode::SUCCESS; +} + +//----------------------------------------------------------------------------- +// Finalize +//----------------------------------------------------------------------------- +StatusCode tauCalibrateWeightTool :: finalize() +{ + return StatusCode :: SUCCESS; +} diff --git a/Reconstruction/tauRecTools/src/tauCalibrateWeightTool.h b/Reconstruction/tauRecTools/src/tauCalibrateWeightTool.h new file mode 100644 index 0000000000000000000000000000000000000000..2300acfe756992b9990a1a7bd58072877425d212 --- /dev/null +++ b/Reconstruction/tauRecTools/src/tauCalibrateWeightTool.h @@ -0,0 +1,82 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUCALIBRATEWEIGHTTOOL_H +#define TAUREC_TAUCALIBRATEWEIGHTTOOL_H +/******************************************************************** +(depreciated!) + +NAME: tauCalibrateWeightTool.h +PACKAGE: offline/Reconstruction/tauRec +AUTHORS: M.Heldmann +CREATED: March 15, 2005 + +See comments in tauCalibrateWeightTool.cxx. + +13/12/2008 - (AK) change to extrapolation of TP instead of Track+code cleaning + ********************************************************************/ + +#include "tauRecTools/TauRecToolBase.h" +#include "GaudiKernel/ToolHandle.h" + + +class TauEventData; +class LArEM_ID; +class TileID; +//namespace AIDA { +//class IHistogram1D; +//} +class IHadronicCalibrationTool; + +//------------------------------------------------------------- +//! Class for applying H1-weighting on calorimeter cells and fudge factor for tau energy +//------------------------------------------------------------- +class tauCalibrateWeightTool : virtual public TauRecToolBase +{ + public: + enum calibrateType { calCells = 0, calJets, calTracks, calCluster, calTopocluster }; + + tauCalibrateWeightTool(const std::string& name); + ASG_TOOL_CLASS2(tauCalibrateWeightTool, TauRecToolBase, ITauToolBase); + ~tauCalibrateWeightTool(); + + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + + // Accessor methods: + + private: + int m_calibrateType; + ToolHandle<IHadronicCalibrationTool> m_caloWeightTool; + + const LArEM_ID* m_emid; + const TileID* m_tileid; + + std::string m_cellWeightTool; + std::vector<float> m_poly; + + bool m_applyCellWeightEM; + bool m_applyCellWeightHad; + bool m_applyPtEtaCorrFactors; + bool m_validCaloWeightTool; + bool m_doEtaInterpolation; + + float m_fudge; + double m_cellCone; + + int m_nptbins; + int m_netabins; + + std::vector<float> m_ptpoints; + std::vector<float> m_etapoints; + std::vector<float> m_ptetacorrectionsntr1; + std::vector<float> m_ptetacorrectionsntr23; +}; + +#endif diff --git a/Reconstruction/tauRecTools/tauRecTools/ITauToolBase.h b/Reconstruction/tauRecTools/tauRecTools/ITauToolBase.h new file mode 100644 index 0000000000000000000000000000000000000000..cb5e5645f233f2efea5f2048b278d641973895c6 --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/ITauToolBase.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ITOOLBASE_TAU_H +#define ITOOLBASE_TAU_H + +#include "AsgTools/IAsgTool.h" +#include "tauRecTools/TauEventData.h" + +/** + * @brief The base class for all tau tools. + * + * @author Lukasz Janyst + * @author Justin Griffiths + * Thanks to Lianyou Shan, Lorenz Hauswald + */ + +class ITauToolBase : virtual public asg::IAsgTool +{ + public: + + ASG_TOOL_INTERFACE(ITauToolBase) + + virtual ~ITauToolBase() {} + + //----------------------------------------------------------------- + //! Tool initializer + //----------------------------------------------------------------- + virtual StatusCode initialize() = 0; + + //----------------------------------------------------------------- + //! Event initializer - called at the beginning of each event + //----------------------------------------------------------------- + virtual StatusCode eventInitialize() = 0; + + //----------------------------------------------------------------- + //! Execute - called for each tau candidate + //----------------------------------------------------------------- + virtual StatusCode execute(xAOD::TauJet& pTau) = 0; + + //----------------------------------------------------------------- + //! Event finalizer - called at the end of each event + //----------------------------------------------------------------- + virtual StatusCode eventFinalize() = 0; + + //----------------------------------------------------------------- + //! Finalizer + //----------------------------------------------------------------- + virtual StatusCode finalize() = 0; + + virtual void setTauEventData(TauEventData* data) = 0; + +}; + +#endif // TOOLBASE_TAU_H diff --git a/Reconstruction/tauRecTools/tauRecTools/ITauToolExecBase.h b/Reconstruction/tauRecTools/tauRecTools/ITauToolExecBase.h new file mode 100644 index 0000000000000000000000000000000000000000..ef03c83ef5c3f853bdfa32d5603ae6325fe05406 --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/ITauToolExecBase.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ITAUTOOLEXECBASE_TAU_H +#define ITAUTOOLEXECBASE_TAU_H + +#include <string> + +#include "AsgTools/AsgTool.h" + +/** + * @brief The base class for all tau tools that act as algorithms. + * + * @author Justin Griffiths + */ + + +class ITauToolExecBase : virtual public asg::IAsgTool +{ + public: + + virtual ~ITauToolExecBase() {} + + //----------------------------------------------------------------- + //! Tool initializer + //----------------------------------------------------------------- + virtual StatusCode initialize() = 0; + + //----------------------------------------------------------------- + //! Execute - called for each tau candidate + //----------------------------------------------------------------- + virtual StatusCode execute() = 0; + + //----------------------------------------------------------------- + //! Finalizer + //----------------------------------------------------------------- + virtual StatusCode finalize() = 0; + +}; + +#endif // ITAUTOOLEXECBASE_TAU_H diff --git a/Reconstruction/tauRecTools/tauRecTools/KineUtils.h b/Reconstruction/tauRecTools/tauRecTools/KineUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..28d5e0bf25734cf82cbdb1f5d5c1e94bc585fd6f --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/KineUtils.h @@ -0,0 +1,70 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_KINEUTILS_H +#define TAUREC_KINEUTILS_H + + +#include <string> +#include "TVector2.h" + +//static const double kPI = 3.1415927; +//static const double k2PI = 2*3.1415927; + +//! +//! @class Tau1P3PKineUtils +//! @brief Provides methods for simple kinematical calculations +//! +//! Provides methods for simple kinematical calculations: absolute value +//! of difference in pseudorapidity, in phi position, half-opening angle +//! in ( eta, phi ) space +//! + +class Tau1P3PKineUtils +{ + public: + //! + //! Calculates absolute value for difference in eta position + //! + //! @param x eta position of object 1 + //! @param y eta position of object 2 + //! + static double deltaEta(double eta1, double eta2) { return std::fabs( eta1 - eta2);} + + //! + //! Calculates absolute value for difference in phi position, + //! corrected for 2pi symmetry + //! + //! @param x phi position of object 1 + //! @param y phi position of object 2 + //! + + /* + static double deltaPhi(double phi1, double phi2) + { + + double dphi = std :: fabs( phi1 - phi2 ); + if( dphi > kPI ) dphi -= k2PI; + return std :: fabs( dphi ); + } + */ + static double deltaPhi(double phi1, double phi2) + { + return TVector2::Phi_mpi_pi(phi1-phi2); + } + + //! + //! Calculates half-opening angle in (eta,phi) space + //! + //! @param x detphi of two objects + //! @param y deteta of two objects + //! + static double deltaR(double de,double dp) { return std::sqrt(de*de+dp*dp); } + static double deltaR(double eta1, double phi1, double eta2, double phi2) { + return std::sqrt(deltaEta(eta1,eta2)*deltaEta(eta1,eta2)+deltaPhi(phi1,phi2)*deltaPhi(phi1,phi2)); + } + +}; + +#endif diff --git a/Reconstruction/tauRecTools/tauRecTools/TauBuilderTool.h b/Reconstruction/tauRecTools/tauRecTools/TauBuilderTool.h new file mode 100644 index 0000000000000000000000000000000000000000..c8776c84da2aafdcbefc7d47903980906cbdb2b9 --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/TauBuilderTool.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUBUILDERTOOL_H +#define TAUREC_TAUBUILDERTOOL_H + +#include "tauRecTools/TauRecToolBase.h" +#include "tauRecTools/ITauToolExecBase.h" +#include "AsgTools/ToolHandleArray.h" + +/** + * @brief Implementation of tauRec/TauBuilder as a tool. + * + * @author Justin Griffiths + * @authors (tauRec/TauBuilder.h) Srini Rajagopalan, Michael Heldmann, Lukasz Janyst, Anna Kaczmarska, Felix Friedrich + * + */ + +class TauBuilderTool : public asg::AsgTool, virtual public ITauToolExecBase { + public: + + ASG_TOOL_CLASS1( TauBuilderTool, ITauToolExecBase ) + + TauBuilderTool(const std::string& type); + ~TauBuilderTool(); + + virtual StatusCode initialize(); + virtual StatusCode execute(); + virtual StatusCode finalize(); + + private: + std :: string m_tauContainerName; //!< tau output container + std :: string m_tauAuxContainerName; //!< tau output aux store container + std::string m_seedContainerName; //!< seed input container + double m_maxEta; //!< only build taus with eta_seed < m_maxeta + double m_minPt; //!< only build taus with pt_seed > m_minpt + + /** switch to create tau containers, + * if false tau containers will be updated only + */ + bool m_doCreateTauContainers; + ToolHandleArray<ITauToolBase> m_tools; + TauEventData m_data; + + public: + +}; + +#endif //TAUREC_TAUBUILDERTOOL_H diff --git a/Reconstruction/tauRecTools/tauRecTools/TauCalibrateLC.h b/Reconstruction/tauRecTools/tauRecTools/TauCalibrateLC.h new file mode 100644 index 0000000000000000000000000000000000000000..44e29116bdc215428062817e07917aca551edd76 --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/TauCalibrateLC.h @@ -0,0 +1,63 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUCALIBRATELC_H +#define TAUREC_TAUCALIBRATELC_H + +#include "tauRecTools/TauRecToolBase.h" + +class TH1; +class TF1; + +/** + * @brief Implementation of tau energy scale (TES) with eta and pile-up correction. + * + * The energy and eta (direction) correction are done separatly and steered by flags. + * + * @author Margar Simonyan + * @author Felix Friedrich + * + */ + +class TauCalibrateLC : virtual public TauRecToolBase { +public: + + ASG_TOOL_CLASS2( TauCalibrateLC, TauRecToolBase, ITauToolBase ) + + TauCalibrateLC(const std::string& type); + ~TauCalibrateLC(); + + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + + +private: + std::string tauContainerKey; + std::string vertexContainerKey; + std::string calibrationFile; //!< energy calibration file + + static const int nProngBins = 2; + + const TF1 * calibFunc[nProngBins][10]; //maximum 10 eta bins; might not be used on the whole + const TH1 * slopeNPVHist[nProngBins]; + const TH1 * etaBinHist; + const TH1 * etaCorrectionHist; + + unsigned int m_minNTrackAtVertex; + int m_nEtaBins; + double m_averageNPV; + + bool m_doEnergyCorr; //!< switch for energy correction + bool m_doAxisCorr; //!< switch for eta correction + bool m_printMissingContainerINFO; + + double m_clusterCone; //obsolete +}; + +#endif diff --git a/Reconstruction/tauRecTools/tauRecTools/TauCommonCalcVars.h b/Reconstruction/tauRecTools/tauRecTools/TauCommonCalcVars.h new file mode 100644 index 0000000000000000000000000000000000000000..8dad05a149cf104e497c3ac6c43f9c5944d283d1 --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/TauCommonCalcVars.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUCOMMONCALCVARS_H +#define TAUREC_TAUCOMMONCALCVARS_H + +#include "tauRecTools/TauRecToolBase.h" + + +/** + * @brief Calculate variables which rely on tracks and precalculated cell/cluster information. + * + * All variables here can be recalculated using AODs. + * + * @author Stan Lai + * @author Felix Friedrich + */ + +class TauCommonCalcVars : virtual public TauRecToolBase { +public: + //----------------------------------------------------------------- + // Constructor and destructor + //----------------------------------------------------------------- + TauCommonCalcVars(const std::string& name); + ASG_TOOL_CLASS2(TauCommonCalcVars, TauRecToolBase, ITauToolBase) + ~TauCommonCalcVars(); + + virtual StatusCode initialize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode finalize(); + + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + +}; + +#endif // TAUREC_TAUCOMMONCALCVARS_H diff --git a/Reconstruction/tauRecTools/tauRecTools/TauEventData.h b/Reconstruction/tauRecTools/tauRecTools/TauEventData.h new file mode 100644 index 0000000000000000000000000000000000000000..1778c99d6a16c387a4b69fbaafc968108f65e5ff --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/TauEventData.h @@ -0,0 +1,128 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_EVENT_DATA_H +#define TAUREC_EVENT_DATA_H +//----------------------------------------------------------------------------- +// file: TauEventData.h was TauCandidateData.h +// package: Reconstruction/tauEvent +// authors: Lukasz Janyst +// date: 2007-02-13 +// +// MODIFICATIONS +// 2008-04-22 nicom: moved setObject()/getObject() to TauEventData +// +//----------------------------------------------------------------------------- + +#include <string> +#include <map> +#include <boost/any.hpp> + +#include "xAODTau/TauJetContainer.h" +#include "xAODTau/TauJetAuxContainer.h" +#include "AsgTools/StatusCode.h" + +/** + * @brief The tau candidate object. + * + * Holds all containers and information needed for the tau reconstruction process. + * + * @authors Lukasz Janyst + */ + +class TauEventData +{ +public: + //----------------------------------------------------------------- + //! Associate some object to a key - this is meant to be used by + //! TrigTauRec to pass container pointers to tauRec tools + //----------------------------------------------------------------- + template <typename P> + void setObject( std :: string key, P ptr ); + + //----------------------------------------------------------------- + //! Check if something has been associated with given key + //----------------------------------------------------------------- + bool hasObject( std :: string key ) const; + + //----------------------------------------------------------------- + //! Get the pointer associated with given key, if types don't + //! match boost :: bad_any_cast exception is thrown + //----------------------------------------------------------------- + template <typename P> + StatusCode getObject( std :: string key, P &ptr ); + + xAOD::TauJetContainer* xAODTauContainer=0; + xAOD::TauJetAuxContainer *tauAuxContainer=0; + /* //think about changing this to IParticle */ + /* const xAOD::Jet *seed=0; */ + const xAOD::JetContainer *seedContainer=0; + unsigned int detailsNum; + + std :: map<std :: string, boost :: any> m_ptrMap; + + void clear(); + + inline void setInTrigger(bool v=true); + inline bool inTrigger(); + + private: + //don't clear this infomation + bool m_inTrigger = false; + +}; + +//------------------------------------------------------------------------- +// Set pointer +//------------------------------------------------------------------------- + template <typename P> +inline void TauEventData :: setObject( std :: string key, P ptr ) +{ + m_ptrMap[key] = ptr; +} + +//------------------------------------------------------------------------- +// Get pointer +//------------------------------------------------------------------------- + template <typename P> +inline StatusCode TauEventData :: getObject( std :: string key, P &ptr ) +{ + std :: map< std :: string, boost :: any> :: iterator p_it; + p_it = m_ptrMap.find( key ); + if( p_it == m_ptrMap.end() ) + return StatusCode :: FAILURE; + + ptr = boost :: any_cast<P>( (*p_it).second ); + return StatusCode :: SUCCESS; +} + +//------------------------------------------------------------------------- +// Test if any pointer has been associated with given key +//------------------------------------------------------------------------- +inline bool TauEventData :: hasObject( std :: string key ) const +{ + return m_ptrMap.find( key ) != m_ptrMap.end(); +} + +//------------------------------------------------------------------------- +// reset all information, nothing is deleted assuming pointers +// owned by storegate +//------------------------------------------------------------------------- +inline void TauEventData :: clear(){ + xAODTauContainer=0; + tauAuxContainer=0; + seedContainer=0; + detailsNum=0; + m_ptrMap.clear(); +} + +inline void TauEventData :: setInTrigger(bool v){ + m_inTrigger=v; +} + +inline bool TauEventData :: inTrigger(){ + return m_inTrigger; +} + +#endif // TAU_CANDIDATE_DATA diff --git a/Reconstruction/tauRecTools/tauRecTools/TauGenericPi0Cone.h b/Reconstruction/tauRecTools/tauRecTools/TauGenericPi0Cone.h new file mode 100644 index 0000000000000000000000000000000000000000..43b9c0db64d4272c3fd7e1e774f3bac69fb8669b --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/TauGenericPi0Cone.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauGenericPi0Cone.h +// package: Reconstruction/tauRec +// authors: Robert Clarke, Blake Burghgrave +// date: 2014-01-04 +// +// +//----------------------------------------------------------------------------- + +#ifndef TAUREC_TAUGENERICPI0CONE_H +#define TAUREC_TAUGENERICPI0CONE_H + +#include "tauRecTools/TauRecToolBase.h" + +class TauGenericPi0Cone : virtual public TauRecToolBase { +public: + //------------------------------------------------------------- + //! Constructor + //------------------------------------------------------------- + TauGenericPi0Cone(const std::string& name); + ASG_TOOL_CLASS2(TauGenericPi0Cone, TauRecToolBase, ITauToolBase) + + //------------------------------------------------------------- + //! Destructor + //------------------------------------------------------------- + ~TauGenericPi0Cone(); + + virtual StatusCode initialize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode finalize(); + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + +private: + + float m_pi0conedr; + +}; + +#endif diff --git a/Reconstruction/tauRecTools/tauRecTools/TauIDPileupCorrection.h b/Reconstruction/tauRecTools/tauRecTools/TauIDPileupCorrection.h new file mode 100644 index 0000000000000000000000000000000000000000..1e5996ff8e289edffbfe8cea751afc2b39fbfd93 --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/TauIDPileupCorrection.h @@ -0,0 +1,74 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUIDPILEUPCORRECTION_H +#define TAUREC_TAUIDPILEUPCORRECTION_H + +#include "tauRecTools/TauRecToolBase.h" +#include "xAODTau/TauDefs.h" + +class TH1; +class TF1; + +/** + * @brief Implementation of tool to correct tau ID variables for pile-up in a generic way + * + * Input comes from 2 ROOT files with TF1 functions containing the mean variable value + * as a function of the chosen pile-up estimator (Nvtx offline, mu online) + * + * The correspondence between the ROOT File curve names and the TauParameters is handled + * via a small structure defined in initialize + * + * @author M. Beckingham + * @author P.O. DeViveiros + * @author M. Janus + * + */ + +class TauIDPileupCorrection : virtual public TauRecToolBase { +public: + + TauIDPileupCorrection(const std::string& name) ; + ASG_TOOL_CLASS2(TauIDPileupCorrection, TauRecToolBase, ITauToolBase) + ~TauIDPileupCorrection(); + + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + + virtual void print() const { } + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + virtual void cleanup(xAOD::TauJet* ) { } + + +private: + std::string m_tauContainerKey; + std::string m_vertexContainerKey; + std::string m_file1P; //!< energy calibration file + std::string m_file3P; //!< energy calibration file + + std::map<std::string, TF1> m_calibFunctions1P; + std::map<std::string, TF1> m_calibFunctions3P; + + struct TauConversion { + std::string detailName; + xAOD::TauJetParameters::Detail detailUncorr; + xAOD::TauJetParameters::Detail detailCorr; + + TauConversion(std::string name, xAOD::TauJetParameters::Detail detail1, xAOD::TauJetParameters::Detail detail2) + : detailName(name), detailUncorr(detail1), detailCorr(detail2) + { } + }; + + std::vector<TauConversion> m_conversion; + + double m_averageEstimator; + unsigned int m_minNTrackAtVertex; + bool m_printMissingContainerINFO; + bool m_useMu; + +}; + +#endif diff --git a/Reconstruction/tauRecTools/tauRecTools/TauProcessorTool.h b/Reconstruction/tauRecTools/tauRecTools/TauProcessorTool.h new file mode 100644 index 0000000000000000000000000000000000000000..01593ccea63bd2af8f483ec71877591fdb9a7d61 --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/TauProcessorTool.h @@ -0,0 +1,93 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TAUPROCESSORTOOL_H +#define TAUREC_TAUPROCESSORTOOL_H + +#include "tauRecTools/TauRecToolBase.h" +#include "tauRecTools/ITauToolExecBase.h" +#include "AsgTools/ToolHandleArray.h" + +/** + * @brief Implementation of tauRec/TauProcessor as a tool. + * + * @author Justin Griffiths + * + */ + +class TauProcessorTool : public asg::AsgTool, virtual public ITauToolExecBase { + public: + + ASG_TOOL_CLASS1( TauProcessorTool, ITauToolExecBase ) + + TauProcessorTool(const std::string& type); + ~TauProcessorTool(); + + virtual StatusCode initialize(); + virtual StatusCode execute(); + virtual StatusCode finalize(); + + private: + std :: string m_tauContainerName; + std :: string m_tauAuxContainerName; + bool m_AODmode; + bool m_deep_copy_chargedPFOContainer; + bool m_deep_copy_hadronicPFOContainer; + bool m_deep_copy_neutralPFOContainer; + bool m_deep_copy_SecVtxContainer; + TauEventData m_data; + ToolHandleArray<ITauToolBase> m_tools; + + public: + //------------------------------------------------------------------------- + // make a deep copy of conatiner a + // xAOD::TauJetContainer *cont(0); + // xAOD::TauJetAuxContainer* contAux(0); + // xAOD::TauJet* tau(0); + // ATH_CHECK( ITauToolBase::deepCopy( cont, contAux, tau, "TauJets", "TauJetsAux.") ); + // tau is only used to infer type of object in T... + //------------------------------------------------------------------------- + template<class T, class U, class V> + StatusCode deepCopy(T*& containerOut, U*& containerStoreOut, const V* dummyContainerType, + const std::string& containername, std::string containerNameAux=""); + + +}; + +template<class T, class U, class V> + StatusCode TauProcessorTool::deepCopy(T*& container, U*& containerStore, const V* /*dummyContainerElementType*/, + const std::string& containerName, std::string containerNameAux){ + if(containerNameAux=="") { + containerNameAux=containerName; + containerNameAux+="Aux."; + } + + const T* constContainer(0); + const U* constAuxContainer(0); + + ATH_CHECK( evtStore()->retrieve(constContainer, containerName) ); + ATH_CHECK( evtStore()->retrieve(constAuxContainer, containerNameAux) ); + if(container==0 && containerStore==0){ + container = new T(); + containerStore = new U(); + container->setStore(containerStore); + } + else{ + ATH_MSG_FATAL("Proviced non-null containters, not initializing please provide null containers: "); + return StatusCode::FAILURE; + } + for( const V* v : *constContainer ){ + V* newV = new V(); + container->push_back(newV); + *newV = *v; + } + + ATH_CHECK( evtStore()->overwrite(container, containerName, true, false) ); + ATH_CHECK( evtStore()->overwrite(containerStore, containerNameAux, true, false) ); + + return StatusCode::SUCCESS; +} + + +#endif //TAUREC_TAUPROCESSORTOOL_H diff --git a/Reconstruction/tauRecTools/tauRecTools/TauRecToolBase.h b/Reconstruction/tauRecTools/tauRecTools/TauRecToolBase.h new file mode 100644 index 0000000000000000000000000000000000000000..3b0a6deb15f12c025a8f8bc9587e819ccf315e4c --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/TauRecToolBase.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAURECTOOLBASE_H +#define TAURECTOOLBASE_H +/** + * @brief The base class for all tau tools. + * + * @author Lukasz Janyst + * @author Justin Griffiths + * Thanks to Lianyou Shan, Lorenz Hauswald + */ + +#include <string> + +#include "tauRecTools/TauEventData.h" +#include "tauRecTools/ITauToolBase.h" +#include "AsgTools/AsgTool.h" + +extern TauEventData defaultTauEventData; + +class TauRecToolBase : public asg::AsgTool, virtual public ITauToolBase { + public: + + ASG_TOOL_INTERFACE(TauRecToolBase) + ASG_TOOL_CLASS1( TauRecToolBase, ITauToolBase ) + + TauRecToolBase(const std::string& name); + virtual ~TauRecToolBase() {} + + //----------------------------------------------------------------- + //! Tool initializer + //----------------------------------------------------------------- + virtual StatusCode initialize(); + + //----------------------------------------------------------------- + //! Event initializer - called at the beginning of each event + //----------------------------------------------------------------- + virtual StatusCode eventInitialize(); + + //----------------------------------------------------------------- + //! Execute - called for each tau candidate + //----------------------------------------------------------------- + virtual StatusCode execute(xAOD::TauJet& pTau); + + //----------------------------------------------------------------- + //! Event finalizer - called at the end of each event + //----------------------------------------------------------------- + virtual StatusCode eventFinalize(); + + //----------------------------------------------------------------- + //! Finalizer + //----------------------------------------------------------------- + virtual StatusCode finalize(); + + std::string find_file(const std::string& fname) const; + + void setTauEventData(TauEventData* data); + TauEventData* tauEventData(); + + + + protected: + TauEventData* m_data = 0; + +}; + +inline TauEventData* TauRecToolBase::tauEventData() { + return m_data; +} + +#endif //TAURECTOOLBASE_H diff --git a/Reconstruction/tauRecTools/tauRecTools/TauTrackFilter.h b/Reconstruction/tauRecTools/tauRecTools/TauTrackFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..0489bb13348af91d084d9a019aa110256ff52129 --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/TauTrackFilter.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauTrackFilter.h +// package: Reconstruction/tauRec +// authors: Robert Clarke, Blake Burghgrave +// date: 2014-01-04 +// +// +//----------------------------------------------------------------------------- + +#ifndef TAUREC_TAUTRACKFILTER_H +#define TAUREC_TAUTRACKFILTER_H + +#include "tauRecTools/TauRecToolBase.h" + +class TauTrackFilter : virtual public TauRecToolBase { +public: + //------------------------------------------------------------- + //! Constructor + //------------------------------------------------------------- + TauTrackFilter(const std::string& name); + ASG_TOOL_CLASS2(TauTrackFilter, TauRecToolBase, ITauToolBase) + + //------------------------------------------------------------- + //! Destructor + //------------------------------------------------------------- + ~TauTrackFilter(); + + virtual StatusCode initialize(); + virtual StatusCode execute(xAOD::TauJet& pTau); + virtual StatusCode finalize(); + virtual StatusCode eventInitialize() { return StatusCode::SUCCESS; } + virtual StatusCode eventFinalize() { return StatusCode::SUCCESS; } + + virtual void print() const { } + +private: + + std::string m_trackContainerName; + std::vector<bool> m_TrkPass; + int m_nProng; + int m_flag; + //TODO some of this probably need to be public to be useful... + +}; + +#endif diff --git a/Reconstruction/tauRecTools/tauRecTools/TauTrackFilterUtils.h b/Reconstruction/tauRecTools/tauRecTools/TauTrackFilterUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..443f965f46cd9f53e9f8b1d01344793507c35ff3 --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/TauTrackFilterUtils.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------------- +// file: TauTrackFilterUtils.h +// package: Reconstruction/tauRec +// authors: Robert Clarke, Blake Burghgrave +// date: 2014-01-13 +// +// +//----------------------------------------------------------------------------- + +#ifndef TAUREC_TAUTRACKFILTERUTILS_H +#define TAUREC_TAUTRACKFILTERUTILS_H + +#include "TF1.h" +#include "TLorentzVector.h" +#include <vector> +#include <iostream> +#include <string> + +namespace TauTrackFilterUtils { + + struct TrackInfo{ + TLorentzVector p4; + int charge; + int index; + }; + + struct TrackPair{ + float angle; + float mass; + int charge; + }; + + bool pass3prong(std::vector<TauTrackFilterUtils::TrackInfo> combination,TLorentzVector tau); + bool pass2prong(std::vector<TauTrackFilterUtils::TrackInfo> pair,TLorentzVector tau); + bool pass1prong(TLorentzVector track,TLorentzVector tau); + float ComputePi0Cone(int recProngs,TLorentzVector tau); + float ComputeAngle(float p, float eta, float a[9][4], int npar, int npol, char eqn[] = (char*)"[0]*exp([1]*x)+[2]+[3]/(x*x)"); + float Compute1dim(float p, float a[10], int npar, char eqn[]); + +} + +#endif diff --git a/Reconstruction/tauRecTools/tauRecTools/TrackSort.h b/Reconstruction/tauRecTools/tauRecTools/TrackSort.h new file mode 100644 index 0000000000000000000000000000000000000000..4fa2290d6dd0d614bd0576dd6ff4df7b7df05260 --- /dev/null +++ b/Reconstruction/tauRecTools/tauRecTools/TrackSort.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TAUREC_TRACKSORT_H +#define TAUREC_TRACKSORT_H + +#ifdef ASGTOOL_ATHENA +#include "Particle/TrackParticle.h" +#include "Particle/TrackParticleContainer.h" +#endif +#include "AthLinks/ElementLink.h" +#include "xAODTracking/TrackParticle.h" + +/** + * @brief Helper method to sort tracks + * + * Usage: + * sort(track_begin, track_end, tauTrackSort); + * We want pt0 > pt1 > ..., so the test on ptInvVert is < . + * + */ + +class TrackSort { + + public: + TrackSort(){ }; + +#ifdef ASGTOOL_ATHENA + bool operator() (const ElementLink<Rec::TrackParticleContainer>& t1, const ElementLink<Rec::TrackParticleContainer> &t2) const + { + return fabs( (*t1)->pt() ) > fabs( (*t2)->pt() ); + }; + + bool operator() ( const Rec::TrackParticle *t1, const Rec::TrackParticle *t2 ) const + { + return fabs( t1->pt() ) > fabs( t2->pt() ); + }; +#endif + + bool operator() ( const xAOD::TrackParticle *t1, const xAOD::TrackParticle *t2 ) const + { + return fabs( t1->pt() ) > fabs( t2->pt() ); + }; + +}; + +#endif